Add sysctl hw.ucomnames to list 'fixed' paths to USB serial
authorkrw <krw@openbsd.org>
Sun, 1 Oct 2023 15:58:11 +0000 (15:58 +0000)
committerkrw <krw@openbsd.org>
Sun, 1 Oct 2023 15:58:11 +0000 (15:58 +0000)
ports.

Suggested by deraadt@, USB route idea from kettenis@. Feedback
from anton@, man page improvements from deraadt@, jmc@,
schwarze@.

ok deraadt@ kettenis@

lib/libc/sys/sysctl.2
sys/dev/usb/ucom.c
sys/dev/usb/ucomvar.h
sys/dev/usb/usb_subr.c
sys/dev/usb/usbdi.h
sys/kern/kern_sysctl.c
sys/sys/sysctl.h

index 4f78c12..17ecf7e 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: sysctl.2,v 1.52 2023/05/16 21:13:19 jmc Exp $
+.\"    $OpenBSD: sysctl.2,v 1.53 2023/10/01 15:58:11 krw Exp $
 .\"
 .\" Copyright (c) 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -27,7 +27,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: May 16 2023 $
+.Dd $Mdocdate: October 1 2023 $
 .Dt SYSCTL 2
 .Os
 .Sh NAME
@@ -296,6 +296,7 @@ privileges may change the value.
 .It Dv HW_SENSORS Ta "node" Ta "not applicable"
 .It Dv HW_SETPERF Ta "integer" Ta "yes"
 .It Dv HW_SMT Ta "integer" Ta "yes"
+.It DV HW_UCOMNAMES Ta "string" Ta "no"
 .It Dv HW_USERMEM Ta "integer" Ta "no"
 .It Dv HW_USERMEM64 Ta "int64_t" Ta "no"
 .It Dv HW_UUID Ta "string" Ta "no"
@@ -396,6 +397,20 @@ is set to
 If set to 1, enable simultaneous multithreading (SMT) on CPUs that
 support it.
 Disabled by default.
+.It Dv HW_UCOMNAMES Pq Va hw.ucomnames
+A comma-separated list of currently attached
+.Xr ucom 4
+devices in the following format:
+.Pp
+.Sm off
+.D1 Sy ucom Ar N : Sy usb Ar bus.route.interface
+.Sm on
+.Pp
+The
+.Ar route
+consists of five hexadecimal digits and identifies the port
+containing the
+.Ar interface .
 .It Dv HW_USERMEM
 The amount of available non-kernel memory in bytes.
 This variable is deprecated; use
index 02ce153..5cfd5d9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ucom.c,v 1.75 2023/09/21 00:05:36 krw Exp $ */
+/*     $OpenBSD: ucom.c,v 1.76 2023/10/01 15:58:11 krw Exp $ */
 /*     $NetBSD: ucom.c,v 1.49 2003/01/01 00:10:25 thorpej Exp $        */
 
 /*
@@ -44,6 +44,7 @@
 #include <sys/fcntl.h>
 #include <sys/vnode.h>
 #include <sys/device.h>
+#include <sys/malloc.h>
 
 #include <dev/usb/usb.h>
 
@@ -153,6 +154,9 @@ const struct cfattach ucom_ca = {
        ucom_detach,
 };
 
+static int ucom_change;
+struct rwlock sysctl_ucomlock = RWLOCK_INITIALIZER("sysctlulk");
+
 void
 ucom_lock(struct ucom_softc *sc)
 {
@@ -201,6 +205,7 @@ ucom_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_tty = tp;
        sc->sc_cua = 0;
 
+       ucom_change = 1;
        rw_init(&sc->sc_lock, "ucomlk");
 }
 
@@ -273,6 +278,7 @@ ucom_detach(struct device *self, int flags)
                sc->sc_tty = NULL;
        }
 
+       ucom_change = 1;
        return (0);
 }
 
@@ -1223,7 +1229,53 @@ ucom_cleanup(struct ucom_softc *sc)
        }
 }
 
-#endif /* NUCOM > 0 */
+/*
+ * Update ucom names for export by sysctl.
+ */
+char *
+sysctl_ucominit(void)
+{
+       static char *ucoms = NULL;
+       static size_t ucomslen = 0;
+       char name[34];  /* sizeof(dv_xname) + strlen(":usb000.00000.000,") */
+       struct ucom_softc *sc;
+       int rslt;
+       unsigned int unit;
+       uint32_t route;
+       uint8_t bus, ifaceidx;
+
+       KERNEL_ASSERT_LOCKED();
+
+       if (rw_enter(&sysctl_ucomlock, RW_WRITE|RW_INTR) != 0)
+               return NULL;
+
+       if (ucoms == NULL || ucom_change) {
+               free(ucoms, M_SYSCTL, ucomslen);
+               ucomslen = ucom_cd.cd_ndevs * sizeof(name);
+               ucoms = malloc(ucomslen, M_SYSCTL, M_WAITOK | M_ZERO);
+               for (unit = 0; unit < ucom_cd.cd_ndevs; unit++) {
+                       sc = ucom_cd.cd_devs[unit];
+                       if (sc == NULL || sc->sc_iface == NULL)
+                               continue;
+                       if (usbd_get_location(sc->sc_uparent, sc->sc_iface,
+                           &bus, &route, &ifaceidx) == -1)
+                               continue;
+                       rslt = snprintf(name, sizeof(name), "%s:usb%u.%05x.%u,",
+                           sc->sc_dev.dv_xname, bus, route, ifaceidx);
+                       if (rslt < sizeof(name) && (strlen(ucoms) + rslt) < ucomslen)
+                               strlcat(ucoms, name, ucomslen);
+               }
+       }
+
+       /* Remove trailing ','. */
+       if (strlen(ucoms))
+               ucoms[strlen(ucoms) - 1] = '\0';
+
+       rw_exit_write(&sysctl_ucomlock);
+
+       return ucoms;
+}
+#endif /* NUCOM > 0 */
 
 int
 ucomprint(void *aux, const char *pnp)
index 0877c2f..700c723 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ucomvar.h,v 1.19 2022/04/09 20:07:44 naddy Exp $ */
+/*     $OpenBSD: ucomvar.h,v 1.20 2023/10/01 15:58:11 krw Exp $ */
 /*     $NetBSD: ucomvar.h,v 1.10 2001/12/31 12:15:21 augustss Exp $    */
 
 /*
@@ -99,5 +99,7 @@ struct ucom_attach_args {
 
 int ucomsubmatch(struct device *, void *, void *);
 
+char *sysctl_ucominit(void);
+
 int ucomprint(void *aux, const char *pnp);
 void ucom_status_change(struct ucom_softc *);
index 4e8502d..134b7b0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usb_subr.c,v 1.159 2023/09/11 08:41:27 mvs Exp $ */
+/*     $OpenBSD: usb_subr.c,v 1.160 2023/10/01 15:58:11 krw Exp $ */
 /*     $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $  */
 /*     $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $   */
 
@@ -1330,6 +1330,59 @@ usbd_fill_deviceinfo(struct usbd_device *dev, struct usb_device_info *di)
                    sizeof(di->udi_serial));
 }
 
+int
+usbd_get_routestring(struct usbd_device *dev, uint32_t *route)
+{
+       struct usbd_device *hub;
+       uint32_t r;
+       uint8_t port;
+
+       /*
+        * Calculate the Route String.  Assume that there is no hub with
+        * more than 15 ports and that they all have a depth < 6.  See
+        * section 8.9 of USB 3.1 Specification for more details.
+        */
+       r = dev->powersrc ? dev->powersrc->portno : 0;
+       for (hub = dev->myhub; hub && hub->depth; hub = hub->myhub) {
+               port = hub->powersrc ? hub->powersrc->portno : 0;
+               if (port > 15)
+                       return -1;
+               r <<= 4;
+               r |= port;
+       }
+
+       *route = r;
+       return 0;
+}
+
+int
+usbd_get_location(struct usbd_device *dev, struct usbd_interface *iface,
+    uint8_t *bus, uint32_t *route, uint8_t *ifaceidx)
+{
+       int i;
+       uint32_t r;
+
+       if (dev == NULL || usbd_is_dying(dev) ||
+           dev->cdesc == NULL ||
+           dev->cdesc->bNumInterfaces == 0 ||
+           dev->bus == NULL ||
+           dev->bus->usbctl == NULL ||
+           dev->myhub == NULL ||
+           dev->powersrc == NULL)
+               return -1;
+
+       for(i = 0; i < dev->cdesc->bNumInterfaces; i++) {
+               if (iface == &dev->ifaces[i]) {
+                       *bus = dev->bus->usbctl->dv_unit;
+                       *route = (usbd_get_routestring(dev, &r)) ? 0 : r;
+                       *ifaceidx = i;
+                       return 0;
+               }
+       }
+
+       return -1;
+}
+
 /* Retrieve a complete descriptor for a certain device and index. */
 usb_config_descriptor_t *
 usbd_get_cdesc(struct usbd_device *dev, int index, u_int *lenp)
index 030a6a5..1692e28 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdi.h,v 1.72 2022/02/16 06:23:42 anton Exp $ */
+/*     $OpenBSD: usbdi.h,v 1.73 2023/10/01 15:58:12 krw Exp $ */
 /*     $NetBSD: usbdi.h,v 1.62 2002/07/11 21:14:35 augustss Exp $      */
 /*     $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.18 1999/11/17 22:33:49 n_hibma Exp $      */
 
@@ -130,6 +130,9 @@ usb_device_descriptor_t *usbd_get_device_descriptor(struct usbd_device *dev);
 usbd_status usbd_set_interface(struct usbd_interface *, int);
 int usbd_get_no_alts(usb_config_descriptor_t *, int);
 void usbd_fill_deviceinfo(struct usbd_device *, struct usb_device_info *);
+int usbd_get_routestring(struct usbd_device *, uint32_t *);
+int usbd_get_location(struct usbd_device *, struct usbd_interface *, uint8_t *,
+    uint32_t *, uint8_t *);
 usb_config_descriptor_t *usbd_get_cdesc(struct usbd_device *, int, u_int *);
 int usbd_get_interface_altindex(struct usbd_interface *iface);
 
index 07d9a6f..827eb00 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_sysctl.c,v 1.419 2023/09/16 09:33:27 mpi Exp $   */
+/*     $OpenBSD: kern_sysctl.c,v 1.420 2023/10/01 15:58:12 krw Exp $   */
 /*     $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $     */
 
 /*-
@@ -86,6 +86,8 @@
 
 #include <dev/cons.h>
 
+#include <dev/usb/ucomvar.h>
+
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
 #include "audio.h"
 #include "dt.h"
 #include "pf.h"
+#include "ucom.h"
 #include "video.h"
 
 extern struct forkstat forkstat;
@@ -768,6 +771,14 @@ hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
        case HW_ALLOWPOWERDOWN:
                return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
                    &allowpowerdown));
+#if NUCOM > 0
+       case HW_UCOMNAMES: {
+               const char *str = sysctl_ucominit();
+               if (str == NULL)
+                       return EINVAL;
+               return (sysctl_rdstring(oldp, oldlenp, newp, str));
+       }
+#endif /* NUCOM > 0 */
 #ifdef __HAVE_CPU_TOPOLOGY
        case HW_SMT:
                return (sysctl_hwsmt(oldp, oldlenp, newp, newlen));
index 9060932..e695f1d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sysctl.h,v 1.234 2023/07/04 11:14:00 jsg Exp $        */
+/*     $OpenBSD: sysctl.h,v 1.235 2023/10/01 15:58:12 krw Exp $        */
 /*     $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $  */
 
 /*
@@ -949,6 +949,7 @@ struct kinfo_file {
 #define        HW_NCPUONLINE           25      /* int: number of cpus being used */
 #define        HW_POWER                26      /* int: machine has wall-power */
 #define        HW_BATTERY              27      /* node: battery */
+#define        HW_UCOMNAMES            28      /* strings: ucom names */
 #define        HW_MAXID                30      /* number of valid hw ids */
 
 #define        CTL_HW_NAMES { \
@@ -980,6 +981,7 @@ struct kinfo_file {
        { "ncpuonline", CTLTYPE_INT }, \
        { "power", CTLTYPE_INT }, \
        { "battery", CTLTYPE_NODE }, \
+       { "ucomnames", CTLTYPE_STRING }, \
 }
 
 /*