Index: sys/dev/usb/serial/u3g.c =================================================================== --- sys/dev/usb/serial/u3g.c +++ sys/dev/usb/serial/u3g.c @@ -991,8 +991,8 @@ } sc->sc_numports = nports; - error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, - sc->sc_numports, sc, &u3g_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, sc->sc_ucom, + sc->sc_numports, sc, &u3g_callback, &sc->sc_mtx, uaa->device); if (error) { DPRINTF("ucom_attach failed\n"); goto detach; Index: sys/dev/usb/serial/uark.c =================================================================== --- sys/dev/usb/serial/uark.c +++ sys/dev/usb/serial/uark.c @@ -225,8 +225,8 @@ usbd_xfer_set_stall(sc->sc_xfer[UARK_BULK_DT_RD]); mtx_unlock(&sc->sc_mtx); - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &uark_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &uark_callback, &sc->sc_mtx, uaa->device); if (error) { DPRINTF("ucom_attach failed\n"); goto detach; Index: sys/dev/usb/serial/ubsa.c =================================================================== --- sys/dev/usb/serial/ubsa.c +++ sys/dev/usb/serial/ubsa.c @@ -324,8 +324,8 @@ usbd_xfer_set_stall(sc->sc_xfer[UBSA_BULK_DT_RD]); mtx_unlock(&sc->sc_mtx); - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &ubsa_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &ubsa_callback, &sc->sc_mtx, uaa->device); if (error) { DPRINTF("ucom_attach failed\n"); goto detach; Index: sys/dev/usb/serial/ubser.c =================================================================== --- sys/dev/usb/serial/ubser.c +++ sys/dev/usb/serial/ubser.c @@ -285,8 +285,8 @@ sc->sc_ucom[n].sc_portno = n; } - error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, - sc->sc_numser, sc, &ubser_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, sc->sc_ucom, + sc->sc_numser, sc, &ubser_callback, &sc->sc_mtx, uaa->device); if (error) { goto detach; } Index: sys/dev/usb/serial/uchcom.c =================================================================== --- sys/dev/usb/serial/uchcom.c +++ sys/dev/usb/serial/uchcom.c @@ -354,8 +354,8 @@ usbd_xfer_set_stall(sc->sc_xfer[UCHCOM_BULK_DT_RD]); mtx_unlock(&sc->sc_mtx); - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &uchcom_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &uchcom_callback, &sc->sc_mtx, uaa->device); if (error) { goto detach; } Index: sys/dev/usb/serial/ucycom.c =================================================================== --- sys/dev/usb/serial/ucycom.c +++ sys/dev/usb/serial/ucycom.c @@ -272,8 +272,8 @@ "transfers failed\n"); goto detach; } - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &ucycom_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &ucycom_callback, &sc->sc_mtx, uaa->device); if (error) { goto detach; } Index: sys/dev/usb/serial/ufoma.c =================================================================== --- sys/dev/usb/serial/ufoma.c +++ sys/dev/usb/serial/ufoma.c @@ -445,8 +445,8 @@ usbd_xfer_set_stall(sc->sc_bulk_xfer[UFOMA_BULK_ENDPT_READ]); mtx_unlock(&sc->sc_mtx); - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &ufoma_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &ufoma_callback, &sc->sc_mtx, uaa->device); if (error) { DPRINTF("ucom_attach failed\n"); goto detach; Index: sys/dev/usb/serial/uftdi.c =================================================================== --- sys/dev/usb/serial/uftdi.c +++ sys/dev/usb/serial/uftdi.c @@ -1129,8 +1129,8 @@ /* Indicate tx bits in sc_lsr can be used to determine busy vs idle. */ ucom_use_lsr_txbits(&sc->sc_ucom); - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &uftdi_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &uftdi_callback, &sc->sc_mtx, uaa->device); if (error) { goto detach; } Index: sys/dev/usb/serial/ugensa.c =================================================================== --- sys/dev/usb/serial/ugensa.c +++ sys/dev/usb/serial/ugensa.c @@ -251,8 +251,8 @@ } device_printf(dev, "Found %d serial ports.\n", sc->sc_nports); - error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_nports, sc, - &ugensa_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_nports, sc, + &ugensa_callback, &sc->sc_mtx, uaa->device); if (error) { DPRINTF("ucom attach failed\n"); Index: sys/dev/usb/serial/uipaq.c =================================================================== --- sys/dev/usb/serial/uipaq.c +++ sys/dev/usb/serial/uipaq.c @@ -1162,8 +1162,8 @@ usbd_xfer_set_stall(sc->sc_xfer[UIPAQ_BULK_DT_RD]); mtx_unlock(&sc->sc_mtx); - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &uipaq_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &uipaq_callback, &sc->sc_mtx, uaa->device); if (error) { goto detach; } Index: sys/dev/usb/serial/umcs.c =================================================================== --- sys/dev/usb/serial/umcs.c +++ sys/dev/usb/serial/umcs.c @@ -387,8 +387,8 @@ } mtx_unlock(&sc->sc_mtx); - error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_numports, sc, - &umcs7840_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_numports, sc, + &umcs7840_callback, &sc->sc_mtx, uaa->device); if (error) goto detach; Index: sys/dev/usb/serial/umct.c =================================================================== --- sys/dev/usb/serial/umct.c +++ sys/dev/usb/serial/umct.c @@ -303,8 +303,8 @@ sc->sc_obufsize = 16; } } - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &umct_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &umct_callback, &sc->sc_mtx, uaa->device); if (error) { goto detach; } Index: sys/dev/usb/serial/umodem.c =================================================================== --- sys/dev/usb/serial/umodem.c +++ sys/dev/usb/serial/umodem.c @@ -459,8 +459,8 @@ ucom_set_usb_mode(&sc->sc_super_ucom, uaa->usb_mode); - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &umodem_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &umodem_callback, &sc->sc_mtx, uaa->device); if (error) { device_printf(dev, "Can't attach com\n"); goto detach; Index: sys/dev/usb/serial/umoscom.c =================================================================== --- sys/dev/usb/serial/umoscom.c +++ sys/dev/usb/serial/umoscom.c @@ -337,8 +337,8 @@ usbd_xfer_set_stall(sc->sc_xfer[UMOSCOM_BULK_DT_RD]); mtx_unlock(&sc->sc_mtx); - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &umoscom_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &umoscom_callback, &sc->sc_mtx, uaa->device); if (error) { goto detach; } Index: sys/dev/usb/serial/uplcom.c =================================================================== --- sys/dev/usb/serial/uplcom.c +++ sys/dev/usb/serial/uplcom.c @@ -484,8 +484,8 @@ } } - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &uplcom_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &uplcom_callback, &sc->sc_mtx, uaa->device); if (error) { goto detach; } Index: sys/dev/usb/serial/usb_serial.h =================================================================== --- sys/dev/usb/serial/usb_serial.h +++ sys/dev/usb/serial/usb_serial.h @@ -211,6 +211,10 @@ int ucom_attach(struct ucom_super_softc *, struct ucom_softc *, int, void *, const struct ucom_callback *callback, struct mtx *); +int ucom_attach_usb(struct ucom_super_softc *, + struct ucom_softc *, int, void *, + const struct ucom_callback *callback, struct mtx *, + struct usb_device *); void ucom_detach(struct ucom_super_softc *, struct ucom_softc *); void ucom_set_pnpinfo_usb(struct ucom_super_softc *, device_t); void ucom_set_usb_mode(struct ucom_super_softc *, enum usb_hc_mode); Index: sys/dev/usb/serial/usb_serial.c =================================================================== --- sys/dev/usb/serial/usb_serial.c +++ sys/dev/usb/serial/usb_serial.c @@ -92,6 +92,7 @@ #include #include #include +#include #include @@ -111,6 +112,12 @@ &ucom_device_mode_console, 0, "set to 1 to mark terminals as consoles when in device mode"); +static int ucom_location_as_unit; + +SYSCTL_INT(_hw_usb_ucom, OID_AUTO, location_as_unit, CTLFLAG_RDTUN, + &ucom_location_as_unit, 0, + "set to 1 to use device location as device unit"); + #ifdef USB_DEBUG static int ucom_debug = 0; @@ -248,7 +255,7 @@ { /* sanity checks */ if (unit < 0 || unit >= UCOM_UNIT_MAX || ucom_unrhdr == NULL) { - DPRINTF("cannot free unit number\n"); + DPRINTF("cannot free unit %d\n", unit); return; } DPRINTF("unit %d is freed\n", unit); @@ -267,6 +274,16 @@ int subunits, void *parent, const struct ucom_callback *callback, struct mtx *mtx) { + + return (ucom_attach_usb(ssc, sc, subunits, parent, callback, mtx, NULL)); +} + +int +ucom_attach_usb(struct ucom_super_softc *ssc, struct ucom_softc *sc, + int subunits, void *parent, + const struct ucom_callback *callback, struct mtx *mtx, + struct usb_device *udev) +{ int subunit; int error = 0; @@ -278,7 +295,16 @@ } /* allocate a uniq unit number */ - ssc->sc_unit = ucom_unit_alloc(); + if (ucom_location_as_unit == 0 || udev == NULL) { + ssc->sc_unit = ucom_unit_alloc(); + } else { + ssc->sc_unit = usb_compute_uniq_location(udev) + UCOM_UNIT_MAX; + + /* add fallback code just in case */ + if (ssc->sc_unit < UCOM_UNIT_MAX) + ssc->sc_unit = ucom_unit_alloc(); + DPRINTF("unit %d by location\n", location); + } if (ssc->sc_unit == -1) return (ENOMEM); Index: sys/dev/usb/serial/uslcom.c =================================================================== --- sys/dev/usb/serial/uslcom.c +++ sys/dev/usb/serial/uslcom.c @@ -447,8 +447,8 @@ sc->sc_partnum = uslcom_get_partnum(sc); - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &uslcom_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &uslcom_callback, &sc->sc_mtx, uaa->device); if (error) { goto detach; } Index: sys/dev/usb/serial/uvisor.c =================================================================== --- sys/dev/usb/serial/uvisor.c +++ sys/dev/usb/serial/uvisor.c @@ -348,8 +348,8 @@ goto detach; } - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &uvisor_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &uvisor_callback, &sc->sc_mtx, uaa->device); if (error) { DPRINTF("ucom_attach failed\n"); goto detach; Index: sys/dev/usb/serial/uvscom.c =================================================================== --- sys/dev/usb/serial/uvscom.c +++ sys/dev/usb/serial/uvscom.c @@ -322,8 +322,8 @@ usbd_xfer_set_stall(sc->sc_xfer[UVSCOM_BULK_DT_RD]); mtx_unlock(&sc->sc_mtx); - error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, - &uvscom_callback, &sc->sc_mtx); + error = ucom_attach_usb(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, + &uvscom_callback, &sc->sc_mtx, uaa->device); if (error) { goto detach; } Index: sys/dev/usb/usb_util.h =================================================================== --- sys/dev/usb/usb_util.h +++ sys/dev/usb/usb_util.h @@ -32,5 +32,6 @@ uint8_t usb_make_str_desc(void *ptr, uint16_t max_len, const char *s); void usb_printbcd(char *p, uint16_t p_len, uint16_t bcd); void usb_trim_spaces(char *p); +int usb_compute_uniq_location(const struct usb_device *); #endif /* _USB_UTIL_H_ */ Index: sys/dev/usb/usb_util.c =================================================================== --- sys/dev/usb/usb_util.c +++ sys/dev/usb/usb_util.c @@ -61,6 +61,8 @@ #include #include + +#include #endif /* USB_GLOBAL_INCLUDE_FILE */ /*------------------------------------------------------------------------* @@ -223,3 +225,45 @@ } return (totlen); } + +/*------------------------------------------------------------------------* + * Compute uniq location value for the given USB device + * + * This function returns a uniq integer value for the given USB + * device, based on the location of the USB device. This function + * returns -1 if the location doesn't fit into an integer. + *------------------------------------------------------------------------*/ +int +usb_compute_uniq_location(const struct usb_device *udev) +{ + int64_t retval; + int unit; + + retval = 0; + + unit = device_get_unit(udev->bus->bdev); + + /* range check */ + if (unit < 0 || unit >= 128) + return (-1); + + for (; udev != NULL; udev = udev->parent_hub) { + if (udev->hub == NULL) + continue; + retval *= udev->hub->nports; + retval += udev->port_no - 1; + + /* check for overflow */ + if ((int)retval != retval) + return (-1); + } + + retval *= 128; + retval += unit; + + /* check for overflow */ + if ((int)retval != retval) + return (-1); + + return (retval); +}