diff options
author | Marcus Glocker <mglocker@cvs.openbsd.org> | 2013-04-08 10:34:21 +0000 |
---|---|---|
committer | Marcus Glocker <mglocker@cvs.openbsd.org> | 2013-04-08 10:34:21 +0000 |
commit | ddec2027d9edb59dff664ea02c5ecabd791c2981 (patch) | |
tree | 84034339ca710df9359bf58209f3dd920f811e73 /sys/dev/usb | |
parent | 5285fafd3b88f9e11cb286d9449e37ec35fee719 (diff) |
Add new ioctl's USB_DEVICE_GET_CDESC and USB_DEVICE_GET_FDESC to usb(4).
Those are the equivalents for ugen(4)'s USB_GET_CONFIG_DESC and
USB_GET_FULL_DESC.
Help and OK mpi@, jmc@
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/usb.c | 120 | ||||
-rw-r--r-- | sys/dev/usb/usb.h | 19 | ||||
-rw-r--r-- | sys/dev/usb/usbdi.h | 4 |
3 files changed, 140 insertions, 3 deletions
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index 2a5e45c41d6..07566b0c598 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usb.c,v 1.84 2013/03/28 03:58:03 tedu Exp $ */ +/* $OpenBSD: usb.c,v 1.85 2013/04/08 10:34:20 mglocker Exp $ */ /* $NetBSD: usb.c,v 1.77 2003/01/01 00:10:26 thorpej Exp $ */ /* @@ -499,6 +499,57 @@ usbd_fill_di_task(void *arg) usbd_fill_deviceinfo(dev, di, 1); } +void +usbd_fill_udc_task(void *arg) +{ + struct usb_device_cdesc *udc = (struct usb_device_cdesc *)arg; + struct usb_softc *sc; + usbd_device_handle dev; + int addr = udc->udc_addr; + usb_config_descriptor_t *cdesc; + + /* check that the bus and device are still present */ + if (udc->udc_bus >= usb_cd.cd_ndevs) + return; + sc = usb_cd.cd_devs[udc->udc_bus]; + if (sc == NULL) + return; + dev = sc->sc_bus->devices[udc->udc_addr]; + if (dev == NULL) + return; + + cdesc = usbd_get_cdesc(sc->sc_bus->devices[addr], + udc->udc_config_index, 0); + if (cdesc == NULL) + return; + udc->udc_desc = *cdesc; + free(cdesc, M_TEMP); +} + +void +usbd_fill_udf_task(void *arg) +{ + struct usb_device_fdesc *udf = (struct usb_device_fdesc *)arg; + struct usb_softc *sc; + usbd_device_handle dev; + int addr = udf->udf_addr; + usb_config_descriptor_t *cdesc; + + /* check that the bus and device are still present */ + if (udf->udf_bus >= usb_cd.cd_ndevs) + return; + sc = usb_cd.cd_devs[udf->udf_bus]; + if (sc == NULL) + return; + dev = sc->sc_bus->devices[udf->udf_addr]; + if (dev == NULL) + return; + + cdesc = usbd_get_cdesc(sc->sc_bus->devices[addr], + udf->udf_config_index, &udf->udf_size); + udf->udf_data = (char *)cdesc; +} + int usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, struct proc *p) { @@ -628,6 +679,73 @@ usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, struct proc *p) *(struct usb_device_stats *)data = sc->sc_bus->stats; break; + case USB_DEVICE_GET_CDESC: + { + struct usb_device_cdesc *udc = (struct usb_device_cdesc *)data; + int addr = udc->udc_addr; + struct usb_task udc_task; + + if (addr < 1 || addr >= USB_MAX_DEVICES) + return (EINVAL); + if (sc->sc_bus->devices[addr] == NULL) + return (ENXIO); + + udc->udc_bus = unit; + + udc->udc_desc.bLength = 0; + usb_init_task(&udc_task, usbd_fill_udc_task, udc, + USB_TASK_TYPE_GENERIC); + usb_add_task(sc->sc_bus->root_hub, &udc_task); + usb_wait_task(sc->sc_bus->root_hub, &udc_task); + if (udc->udc_desc.bLength == 0) + return (EINVAL); + break; + } + + case USB_DEVICE_GET_FDESC: + { + struct usb_device_fdesc *udf = (struct usb_device_fdesc *)data; + int addr = udf->udf_addr; + struct usb_task udf_task; + struct usb_device_fdesc save_udf; + usb_config_descriptor_t *cdesc; + struct iovec iov; + struct uio uio; + int len, error; + + if (addr < 1 || addr >= USB_MAX_DEVICES) + return (EINVAL); + if (sc->sc_bus->devices[addr] == NULL) + return (ENXIO); + + udf->udf_bus = unit; + + save_udf = *udf; + usb_init_task(&udf_task, usbd_fill_udf_task, udf, + USB_TASK_TYPE_GENERIC); + usb_add_task(sc->sc_bus->root_hub, &udf_task); + usb_wait_task(sc->sc_bus->root_hub, &udf_task); + len = udf->udf_size; + cdesc = (usb_config_descriptor_t *)udf->udf_data; + *udf = save_udf; + if (cdesc == NULL) + return (EINVAL); + if (len > udf->udf_size) + len = udf->udf_size; + iov.iov_base = (caddr_t)udf->udf_data; + iov.iov_len = len; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_resid = len; + uio.uio_offset = 0; + uio.uio_segflg = UIO_USERSPACE; + uio.uio_rw = UIO_READ; + uio.uio_procp = p; + error = uiomove((void *)cdesc, len, &uio); + free(cdesc, M_TEMP); + return (error); + } + default: return (EINVAL); } diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h index bf71960edf7..a889553c302 100644 --- a/sys/dev/usb/usb.h +++ b/sys/dev/usb/usb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usb.h,v 1.42 2013/03/16 09:58:40 mpi Exp $ */ +/* $OpenBSD: usb.h,v 1.43 2013/04/08 10:34:20 mglocker Exp $ */ /* $NetBSD: usb.h,v 1.69 2002/09/22 23:20:50 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb.h,v 1.14 1999/11/17 22:33:46 n_hibma Exp $ */ @@ -560,6 +560,13 @@ struct usb_config_desc { usb_config_descriptor_t ucd_desc; }; +struct usb_device_cdesc { + u_int8_t udc_bus; + u_int8_t udc_addr; /* device address */ + int udc_config_index; + usb_config_descriptor_t udc_desc; +}; + struct usb_interface_desc { int uid_config_index; int uid_interface_index; @@ -581,6 +588,14 @@ struct usb_full_desc { u_char *ufd_data; }; +struct usb_device_fdesc { + u_int8_t udf_bus; + u_int8_t udf_addr; /* device address */ + int udf_config_index; + u_int udf_size; + u_char *udf_data; +}; + struct usb_string_desc { int usd_string_index; int usd_language_id; @@ -637,6 +652,8 @@ struct usb_device_stats { #define USB_DISCOVER _IO ('U', 3) #define USB_DEVICEINFO _IOWR('U', 4, struct usb_device_info) #define USB_DEVICESTATS _IOR ('U', 5, struct usb_device_stats) +#define USB_DEVICE_GET_CDESC _IOWR('U', 6, struct usb_device_cdesc) +#define USB_DEVICE_GET_FDESC _IOWR('U', 7, struct usb_device_fdesc) /* Generic HID device */ #define USB_GET_REPORT_DESC _IOR ('U', 21, struct usb_ctl_report_desc) diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 0440d55370d..913ec2868be 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdi.h,v 1.43 2013/04/01 19:49:53 mglocker Exp $ */ +/* $OpenBSD: usbdi.h,v 1.44 2013/04/08 10:34:20 mglocker 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 $ */ @@ -140,6 +140,8 @@ int usbd_get_no_alts(usb_config_descriptor_t *, int); usbd_status usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface); void usbd_fill_deviceinfo(usbd_device_handle, struct usb_device_info *, int); void usbd_fill_di_task(void *); +void usbd_fill_udc_task(void *); +void usbd_fill_udf_task(void *); usb_config_descriptor_t *usbd_get_cdesc(usbd_device_handle, int, int *); int usbd_get_interface_altindex(usbd_interface_handle iface); |