From: krw Date: Sun, 1 Oct 2023 15:58:11 +0000 (+0000) Subject: Add sysctl hw.ucomnames to list 'fixed' paths to USB serial X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=36bb8c29181ecb600c921487fecd40f16c75f9fe;p=openbsd Add sysctl hw.ucomnames to list 'fixed' paths to USB serial ports. Suggested by deraadt@, USB route idea from kettenis@. Feedback from anton@, man page improvements from deraadt@, jmc@, schwarze@. ok deraadt@ kettenis@ --- diff --git a/lib/libc/sys/sysctl.2 b/lib/libc/sys/sysctl.2 index 4f78c121ae2..17ecf7e85f2 100644 --- a/lib/libc/sys/sysctl.2 +++ b/lib/libc/sys/sysctl.2 @@ -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 diff --git a/sys/dev/usb/ucom.c b/sys/dev/usb/ucom.c index 02ce1534fff..5cfd5d9613b 100644 --- a/sys/dev/usb/ucom.c +++ b/sys/dev/usb/ucom.c @@ -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 #include #include +#include #include @@ -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) diff --git a/sys/dev/usb/ucomvar.h b/sys/dev/usb/ucomvar.h index 0877c2f0d94..700c7230466 100644 --- a/sys/dev/usb/ucomvar.h +++ b/sys/dev/usb/ucomvar.h @@ -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 *); diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index 4e8502d0a86..134b7b077f9 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -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) diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 030a6a5cdb6..1692e28d8ee 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -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); diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 07d9a6f9e80..827eb00fb29 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -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 +#include + #include #include #include @@ -116,6 +118,7 @@ #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)); diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 9060932667d..e695f1d95cd 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -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 }, \ } /*