diff options
author | alfred <alfred@FreeBSD.org> | 2009-07-30 00:15:50 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2009-07-30 00:15:50 +0000 |
commit | ec456e3a3b32ea50f5c8e3b3a05352e989c10967 (patch) | |
tree | ad76cd69ab61646de0aee618acfa94818090e52d /sys/dev/usb/usb_handle_request.c | |
parent | fee3a289891db0743737072e9c451512f989ceae (diff) | |
download | FreeBSD-src-ec456e3a3b32ea50f5c8e3b3a05352e989c10967.zip FreeBSD-src-ec456e3a3b32ea50f5c8e3b3a05352e989c10967.tar.gz |
USB core:
- add support for defragging of written device data.
- improve handling of alternate settings in device side mode.
- correct return value from usbd_get_no_alts() function.
- reported by: HPS
- P4 ID: 166156, 166168
- report USB device release information to devd and pnpinfo.
- reported by: MIHIRA Sanpei Yoshiro
- P4 ID: 166221
Submitted by: hps
Approved by: re
Diffstat (limited to 'sys/dev/usb/usb_handle_request.c')
-rw-r--r-- | sys/dev/usb/usb_handle_request.c | 66 |
1 files changed, 39 insertions, 27 deletions
diff --git a/sys/dev/usb/usb_handle_request.c b/sys/dev/usb/usb_handle_request.c index 23486ad..a720919 100644 --- a/sys/dev/usb/usb_handle_request.c +++ b/sys/dev/usb/usb_handle_request.c @@ -46,6 +46,7 @@ #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> +#include <dev/usb/usbdi_util.h> #include "usb_if.h" #define USB_DEBUG_VAR usb_debug @@ -181,6 +182,30 @@ done: return (err); } +static usb_error_t +usb_check_alt_setting(struct usb_device *udev, + struct usb_interface *iface, uint8_t alt_index) +{ + uint8_t do_unlock; + usb_error_t err = 0; + + /* automatic locking */ + if (sx_xlocked(udev->default_sx + 1)) { + do_unlock = 0; + } else { + do_unlock = 1; + sx_xlock(udev->default_sx + 1); + } + + if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc)) + err = USB_ERR_INVAL; + + if (do_unlock) { + sx_unlock(udev->default_sx + 1); + } + return (err); +} + /*------------------------------------------------------------------------* * usb_handle_iface_request * @@ -285,42 +310,29 @@ tr_repeat: switch (req.bRequest) { case UR_SET_INTERFACE: /* - * Handle special case. If we have parent interface - * we just reset the endpoints, because this is a - * multi interface device and re-attaching only a - * part of the device is not possible. Also if the - * alternate setting is the same like before we just - * reset the interface endoints. - */ - if ((iface_parent != NULL) || - (iface->alt_index == req.wValue[0])) { - error = usb_reset_iface_endpoints(udev, - iface_index); - if (error) { - DPRINTF("alt setting failed %s\n", - usbd_errstr(error)); - goto tr_stalled; - } - break; - } - /* - * Doing the alternate setting will detach the - * interface aswell: + * We assume that the endpoints are the same + * accross the alternate settings. + * + * Reset the endpoints, because re-attaching + * only a part of the device is not possible. */ - error = usbd_set_alt_interface_index(udev, - iface_index, req.wValue[0]); + error = usb_check_alt_setting(udev, + iface, req.wValue[0]); if (error) { - DPRINTF("alt setting failed %s\n", + DPRINTF("alt setting does not exist %s\n", usbd_errstr(error)); goto tr_stalled; } - error = usb_probe_and_attach(udev, - iface_index); + error = usb_reset_iface_endpoints(udev, iface_index); if (error) { - DPRINTF("alt setting probe failed\n"); + DPRINTF("alt setting failed %s\n", + usbd_errstr(error)); goto tr_stalled; } + /* update the current alternate setting */ + iface->alt_index = req.wValue[0]; break; + default: goto tr_stalled; } |