Add pnpinfo and location information to uhub. We also keep track of
the subdevices of uhub better now to accomplish this. Submitted by: Bernd Walter
This commit is contained in:
parent
37b4e4f471
commit
1c91aaf9ab
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=131305
@ -93,6 +93,8 @@ Static void uhub_intr(usbd_xfer_handle, usbd_private_handle,usbd_status);
|
||||
#if defined(__FreeBSD__)
|
||||
Static bus_driver_added_t uhub_driver_added;
|
||||
Static bus_child_detached_t uhub_child_detached;
|
||||
int uhub_child_location_str(device_t, device_t, char*, size_t);
|
||||
int uhub_child_pnpinfo_str(device_t, device_t, char*, size_t);
|
||||
#endif
|
||||
|
||||
|
||||
@ -112,6 +114,8 @@ CFATTACH_DECL(uhub_uhub, sizeof(struct uhub_softc),
|
||||
USB_DECLARE_DRIVER_INIT(uhub,
|
||||
DEVMETHOD(bus_driver_added, uhub_driver_added),
|
||||
DEVMETHOD(bus_child_detached, uhub_child_detached),
|
||||
DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
|
||||
DEVMETHOD(bus_child_location_str, uhub_child_location_str),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown)
|
||||
@ -123,6 +127,8 @@ devclass_t uhubroot_devclass;
|
||||
Static device_method_t uhubroot_methods[] = {
|
||||
DEVMETHOD(device_probe, uhub_match),
|
||||
DEVMETHOD(device_attach, uhub_attach),
|
||||
DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
|
||||
DEVMETHOD(bus_child_location_str, uhub_child_location_str),
|
||||
|
||||
/* detach is not allowed for a root hub */
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
@ -576,6 +582,107 @@ USB_DETACH(uhub)
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
int
|
||||
uhub_child_location_str(device_t cbdev, device_t child, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
struct uhub_softc *sc = device_get_softc(cbdev);
|
||||
usbd_device_handle devhub = sc->sc_hub;
|
||||
usbd_device_handle dev;
|
||||
int nports;
|
||||
int port;
|
||||
int i;
|
||||
|
||||
nports = devhub->hub->hubdesc.bNbrPorts;
|
||||
for (port = 0; port < nports; port++) {
|
||||
dev = devhub->hub->ports[port].device;
|
||||
if (dev && dev->subdevs) {
|
||||
for (i = 0; dev->subdevs[i]; i++) {
|
||||
if (dev->subdevs[i] == child) {
|
||||
goto found_dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DPRINTFN(0,("uhub_child_location_str: device not on hub\n"));
|
||||
buf[0] = '\0';
|
||||
return (0);
|
||||
|
||||
found_dev:
|
||||
if (dev->ifacenums == NULL) {
|
||||
snprintf(buf, buflen, "port=%i", port);
|
||||
} else {
|
||||
snprintf(buf, buflen, "port=%i interface=%i",
|
||||
port, dev->ifacenums[i]);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
uhub_child_pnpinfo_str(device_t cbdev, device_t child, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
struct uhub_softc *sc = device_get_softc(cbdev);
|
||||
usbd_device_handle devhub = sc->sc_hub;
|
||||
usbd_device_handle dev;
|
||||
usb_string_descriptor_t us;
|
||||
struct usbd_interface *iface;
|
||||
char serial[128];
|
||||
int nports;
|
||||
int port;
|
||||
int i, j, size;
|
||||
int err;
|
||||
|
||||
nports = devhub->hub->hubdesc.bNbrPorts;
|
||||
for (port = 0; port < nports; port++) {
|
||||
dev = devhub->hub->ports[port].device;
|
||||
if (dev && dev->subdevs) {
|
||||
for (i = 0; dev->subdevs[i]; i++) {
|
||||
if (dev->subdevs[i] == child) {
|
||||
goto found_dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DPRINTFN(0,("uhub_child_pnpinfo_str: device not on hub\n"));
|
||||
buf[0] = '\0';
|
||||
return (0);
|
||||
|
||||
found_dev:
|
||||
j = 0;
|
||||
if (dev->ddesc.iSerialNumber != 0) {
|
||||
err = usbd_get_string_desc(dev, dev->ddesc.iSerialNumber, 0,
|
||||
&us, &size);
|
||||
if (err == 0) {
|
||||
do {
|
||||
serial[j] = UGETW(us.bString[j]);
|
||||
j++;
|
||||
} while (j < ((us.bLength - 2) / 2));
|
||||
}
|
||||
}
|
||||
serial[j] = '\0';
|
||||
if (dev->ifacenums == NULL) {
|
||||
snprintf(buf, buflen, "vendor=0x%04x product=0x%04x "
|
||||
"devclass=0x%02x devsubclass=0x%02x "
|
||||
"sernum=\"%s\"",
|
||||
UGETW(dev->ddesc.idVendor), UGETW(dev->ddesc.idProduct),
|
||||
dev->ddesc.bDeviceClass, dev->ddesc.bDeviceSubClass,
|
||||
serial);
|
||||
} else {
|
||||
iface = &dev->ifaces[dev->ifacenums[i]];
|
||||
snprintf(buf, buflen, "vendor=0x%04x product=0x%04x "
|
||||
"devclass=0x%02x devsubclass=0x%02x "
|
||||
"sernum=\"%s\" "
|
||||
"intclass=0x%02x intsubclass=0x%02x",
|
||||
UGETW(dev->ddesc.idVendor), UGETW(dev->ddesc.idProduct),
|
||||
dev->ddesc.bDeviceClass, dev->ddesc.bDeviceSubClass,
|
||||
serial,
|
||||
iface->idesc->bInterfaceClass,
|
||||
iface->idesc->bInterfaceSubClass);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Called when a device has been detached from it */
|
||||
Static void
|
||||
uhub_child_detached(device_t self, device_t child)
|
||||
|
@ -849,6 +849,7 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
|
||||
int found, i, confi, nifaces;
|
||||
usbd_status err;
|
||||
device_ptr_t dv;
|
||||
device_ptr_t *tmpdv;
|
||||
usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
@ -880,14 +881,20 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
|
||||
|
||||
/* First try with device specific drivers. */
|
||||
DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
|
||||
|
||||
dev->ifacenums = NULL;
|
||||
dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
|
||||
if (dev->subdevs == NULL)
|
||||
return (USBD_NOMEM);
|
||||
dev->subdevs[0] = bdev;
|
||||
dev->subdevs[1] = 0;
|
||||
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
|
||||
if (dv) {
|
||||
dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
|
||||
if (dev->subdevs == NULL)
|
||||
return (USBD_NOMEM);
|
||||
dev->subdevs[0] = dv;
|
||||
dev->subdevs[1] = 0;
|
||||
return (USBD_NORMAL_COMPLETION);
|
||||
} else {
|
||||
tmpdv = dev->subdevs;
|
||||
dev->subdevs = NULL;
|
||||
free(tmpdv, M_USB);
|
||||
}
|
||||
|
||||
DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
|
||||
@ -927,6 +934,15 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
|
||||
#endif
|
||||
return (USBD_NOMEM);
|
||||
}
|
||||
dev->ifacenums = malloc((nifaces) * sizeof(*dev->ifacenums),
|
||||
M_USB,M_NOWAIT);
|
||||
if (dev->ifacenums == NULL) {
|
||||
free(tmpdv, M_USB);
|
||||
#if defined(__FreeBSD__)
|
||||
device_delete_child(parent, bdev);
|
||||
#endif
|
||||
return (USBD_NOMEM);
|
||||
}
|
||||
|
||||
found = 0;
|
||||
for (i = 0; i < nifaces; i++) {
|
||||
@ -934,12 +950,14 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
|
||||
continue; /* interface already claimed */
|
||||
uaa.iface = ifaces[i];
|
||||
uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
|
||||
dev->subdevs[found] = bdev;
|
||||
dev->subdevs[found + 1] = 0;
|
||||
dev->ifacenums[found] = i;
|
||||
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
|
||||
usbd_submatch);
|
||||
if (dv != NULL) {
|
||||
dev->subdevs[found++] = dv;
|
||||
dev->subdevs[found] = 0;
|
||||
ifaces[i] = 0; /* consumed */
|
||||
found++;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
/* create another child for the next iface */
|
||||
@ -952,6 +970,8 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
|
||||
device_set_ivars(bdev, &uaa);
|
||||
device_quiet(bdev);
|
||||
#endif
|
||||
} else {
|
||||
dev->subdevs[found] = 0;
|
||||
}
|
||||
}
|
||||
if (found != 0) {
|
||||
@ -961,8 +981,11 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
|
||||
#endif
|
||||
return (USBD_NORMAL_COMPLETION);
|
||||
}
|
||||
free(dev->subdevs, M_USB);
|
||||
dev->subdevs = 0;
|
||||
tmpdv = dev->subdevs;
|
||||
dev->subdevs = NULL;
|
||||
free(tmpdv, M_USB);
|
||||
free(dev->ifacenums, M_USB);
|
||||
dev->ifacenums = NULL;
|
||||
}
|
||||
/* No interfaces were attached in any of the configurations. */
|
||||
|
||||
@ -976,14 +999,18 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
|
||||
uaa.usegeneric = 1;
|
||||
uaa.configno = UHUB_UNK_CONFIGURATION;
|
||||
uaa.ifaceno = UHUB_UNK_INTERFACE;
|
||||
dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
|
||||
if (dev->subdevs == 0)
|
||||
return (USBD_NOMEM);
|
||||
dev->subdevs[0] = bdev;
|
||||
dev->subdevs[1] = 0;
|
||||
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
|
||||
if (dv != NULL) {
|
||||
dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
|
||||
if (dev->subdevs == 0)
|
||||
return (USBD_NOMEM);
|
||||
dev->subdevs[0] = dv;
|
||||
dev->subdevs[1] = 0;
|
||||
return (USBD_NORMAL_COMPLETION);
|
||||
} else {
|
||||
tmpdv = dev->subdevs;
|
||||
dev->subdevs = 0;
|
||||
free(tmpdv, M_USB);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1370,6 +1397,8 @@ usb_free_device(usbd_device_handle dev)
|
||||
free(dev->cdesc, M_USB);
|
||||
if (dev->subdevs != NULL)
|
||||
free(dev->subdevs, M_USB);
|
||||
if (dev->ifacenums != NULL)
|
||||
free(dev->ifacenums, M_USB);
|
||||
free(dev, M_USB);
|
||||
}
|
||||
|
||||
|
@ -150,6 +150,7 @@ struct usbd_device {
|
||||
const struct usbd_quirks *quirks; /* device quirks, always set */
|
||||
struct usbd_hub *hub; /* only if this is a hub */
|
||||
device_ptr_t *subdevs; /* sub-devices, 0 terminated */
|
||||
uint8_t *ifacenums; /* sub-device interfacenumbers */
|
||||
};
|
||||
|
||||
struct usbd_interface {
|
||||
|
Loading…
Reference in New Issue
Block a user