diff options
author | hselasky <hselasky@FreeBSD.org> | 2010-10-27 17:38:05 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2010-10-27 17:38:05 +0000 |
commit | 37e36d28fc56fffa91de881e7e6b4c1aca45fc0c (patch) | |
tree | 4299a00a332e6c0147de5063dd625a377ca73151 /sys/dev/usb | |
parent | d3a1fbe16a8cdea57e3c9f83e2ce71936e4de376 (diff) | |
download | FreeBSD-src-37e36d28fc56fffa91de881e7e6b4c1aca45fc0c.zip FreeBSD-src-37e36d28fc56fffa91de881e7e6b4c1aca45fc0c.tar.gz |
Add support for setting per-interface PnP information.
Submitted by: Nick Hibma
Approved by: thompsa (mentor)
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/usb_device.c | 50 | ||||
-rw-r--r-- | sys/dev/usb/usb_hub.c | 6 | ||||
-rw-r--r-- | sys/dev/usb/usbdi.h | 3 |
3 files changed, 53 insertions, 6 deletions
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index 8887fc1..495bd82 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -88,7 +88,7 @@ static void usb_init_endpoint(struct usb_device *, uint8_t, struct usb_endpoint *); static void usb_unconfigure(struct usb_device *, uint8_t); static void usb_detach_device_sub(struct usb_device *, device_t *, - uint8_t); + char **, uint8_t); static uint8_t usb_probe_and_attach_sub(struct usb_device *, struct usb_attach_arg *); static void usb_init_attach_arg(struct usb_device *, @@ -1035,9 +1035,10 @@ usb_reset_iface_endpoints(struct usb_device *udev, uint8_t iface_index) *------------------------------------------------------------------------*/ static void usb_detach_device_sub(struct usb_device *udev, device_t *ppdev, - uint8_t flag) + char **ppnpinfo, uint8_t flag) { device_t dev; + char *pnpinfo; int err; dev = *ppdev; @@ -1069,11 +1070,17 @@ usb_detach_device_sub(struct usb_device *udev, device_t *ppdev, goto error; } } + + pnpinfo = *ppnpinfo; + if (pnpinfo != NULL) { + *ppnpinfo = NULL; + free(pnpinfo, M_USBDEV); + } return; error: /* Detach is not allowed to fail in the USB world */ - panic("A USB driver would not detach\n"); + panic("usb_detach_device_sub: A USB driver would not detach\n"); } /*------------------------------------------------------------------------* @@ -1122,7 +1129,8 @@ usb_detach_device(struct usb_device *udev, uint8_t iface_index, /* looks like the end of the USB interfaces */ break; } - usb_detach_device_sub(udev, &iface->subdev, flag); + usb_detach_device_sub(udev, &iface->subdev, + &iface->pnpinfo, flag); } } @@ -2714,3 +2722,37 @@ usbd_enum_is_locked(struct usb_device *udev) { return (sx_xlocked(&udev->enum_sx)); } + +/* + * The following function is used to set the per-interface specific + * plug and play information. The string referred to by the pnpinfo + * argument can safely be freed after calling this function. The + * pnpinfo of an interface will be reset at device detach or when + * passing a NULL argument to this function. This function + * returns zero on success, else a USB_ERR_XXX failure code. + */ + +usb_error_t +usbd_set_pnpinfo(struct usb_device *udev, uint8_t iface_index, const char *pnpinfo) +{ + struct usb_interface *iface; + + iface = usbd_get_iface(udev, iface_index); + if (iface == NULL) + return (USB_ERR_INVAL); + + if (iface->pnpinfo != NULL) { + free(iface->pnpinfo, M_USBDEV); + iface->pnpinfo = NULL; + } + + if (pnpinfo == NULL || pnpinfo[0] == 0) + return (0); /* success */ + + iface->pnpinfo = strdup(pnpinfo, M_USBDEV); + if (iface->pnpinfo == NULL) + return (USB_ERR_NOMEM); + + return (0); /* success */ +} + diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index afeadaa..b2870a3 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -1330,7 +1330,7 @@ uhub_child_pnpinfo_string(device_t parent, device_t child, "devclass=0x%02x devsubclass=0x%02x " "sernum=\"%s\" " "release=0x%04x " - "intclass=0x%02x intsubclass=0x%02x", + "intclass=0x%02x intsubclass=0x%02x" "%s%s", UGETW(res.udev->ddesc.idVendor), UGETW(res.udev->ddesc.idProduct), res.udev->ddesc.bDeviceClass, @@ -1338,7 +1338,9 @@ uhub_child_pnpinfo_string(device_t parent, device_t child, usb_get_serial(res.udev), UGETW(res.udev->ddesc.bcdDevice), iface->idesc->bInterfaceClass, - iface->idesc->bInterfaceSubClass); + iface->idesc->bInterfaceSubClass, + iface->pnpinfo ? " " : "", + iface->pnpinfo ? iface->pnpinfo : ""); } else { if (buflen) { buf[0] = '\0'; diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 1c2d412..6d4a911 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -171,6 +171,7 @@ struct usb_interface { struct usb_host_interface *cur_altsetting; struct usb_device *linux_udev; void *bsd_priv_sc; /* device specific information */ + char *pnpinfo; /* additional PnP-info for this interface */ uint8_t num_altsetting; /* number of alternate settings */ uint8_t bsd_iface_index; }; @@ -444,6 +445,8 @@ enum usb_hc_mode usbd_get_mode(struct usb_device *udev); enum usb_dev_speed usbd_get_speed(struct usb_device *udev); void device_set_usb_desc(device_t dev); void usb_pause_mtx(struct mtx *mtx, int _ticks); +usb_error_t usbd_set_pnpinfo(struct usb_device *udev, + uint8_t iface_index, const char *pnpinfo); const struct usb_device_id *usbd_lookup_id_by_info( const struct usb_device_id *id, usb_size_t sizeof_id, |