aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb2/core/usb2_request.c
diff options
context:
space:
mode:
authorAlfred Perlstein <alfred@FreeBSD.org>2009-01-04 00:12:01 +0000
committerAlfred Perlstein <alfred@FreeBSD.org>2009-01-04 00:12:01 +0000
commitd5474fd85f6d8044976511534faa78061d078efe (patch)
tree6a212d791777cd056f5b3466272b0be92152182e /sys/dev/usb2/core/usb2_request.c
parent17c98d6dabbf9ca3b4b2ad4d9bfca987fb74276c (diff)
downloadsrc-d5474fd85f6d8044976511534faa78061d078efe.tar.gz
src-d5474fd85f6d8044976511534faa78061d078efe.zip
Sync with usb4bsd:
src/lib/libusb20/libusb20_desc.c Make "libusb20_desc_foreach()" more readable. src/sys/dev/usb2/controller/*.[ch] src/sys/dev/usb2/core/*.[ch] Implement support for USB power save for all HC's. Implement support for Big-endian EHCI. Move Huawei quirks back into "u3g" driver. Improve device enumeration. src/sys/dev/usb2/ethernet/*[ch] Patches for supporting new AXE Gigabit chipset. src/sys/dev/usb2/serial/*[ch] Fix IOCTL return code. src/sys/dev/usb2/wlan/*[ch] Sync with old USB stack. Submitted by: hps
Notes
Notes: svn path=/head/; revision=186730
Diffstat (limited to 'sys/dev/usb2/core/usb2_request.c')
-rw-r--r--sys/dev/usb2/core/usb2_request.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/sys/dev/usb2/core/usb2_request.c b/sys/dev/usb2/core/usb2_request.c
index 030a022c615a..b1eb81fa9b10 100644
--- a/sys/dev/usb2/core/usb2_request.c
+++ b/sys/dev/usb2/core/usb2_request.c
@@ -611,7 +611,8 @@ usb2_req_get_desc(struct usb2_device *udev, struct mtx *mtx, void *desc,
}
USETW(req.wLength, min_len);
- err = usb2_do_request(udev, mtx, &req, desc);
+ err = usb2_do_request_flags(udev, mtx, &req,
+ desc, 0, NULL, 1000);
if (err) {
if (!retries) {
@@ -1326,6 +1327,7 @@ usb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx)
struct usb2_device *parent_hub;
usb2_error_t err;
uint8_t old_addr;
+ uint8_t do_retry = 1;
if (udev->flags.usb2_mode != USB_MODE_HOST) {
return (USB_ERR_INVAL);
@@ -1335,6 +1337,7 @@ usb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx)
if (parent_hub == NULL) {
return (USB_ERR_INVAL);
}
+retry:
err = usb2_req_reset_port(parent_hub, mtx, udev->port_no);
if (err) {
DPRINTFN(0, "addr=%d, port reset failed\n", old_addr);
@@ -1355,9 +1358,8 @@ usb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx)
err = usb2_req_set_address(udev, mtx, old_addr);
if (err) {
/* XXX ignore any errors! */
- DPRINTFN(0, "addr=%d, set address failed\n",
+ DPRINTFN(0, "addr=%d, set address failed! (ignored)\n",
old_addr);
- err = 0;
}
/* restore device address */
udev->address = old_addr;
@@ -1381,7 +1383,57 @@ usb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx)
goto done;
}
done:
+ if (err && do_retry) {
+ /* give the USB firmware some time to load */
+ usb2_pause_mtx(mtx, 500);
+ /* no more retries after this retry */
+ do_retry = 0;
+ /* try again */
+ goto retry;
+ }
/* restore address */
udev->address = old_addr;
return (err);
}
+
+/*------------------------------------------------------------------------*
+ * usb2_req_clear_device_feature
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+usb2_error_t
+usb2_req_clear_device_feature(struct usb2_device *udev, struct mtx *mtx,
+ uint16_t sel)
+{
+ struct usb2_device_request req;
+
+ req.bmRequestType = UT_WRITE_DEVICE;
+ req.bRequest = UR_CLEAR_FEATURE;
+ USETW(req.wValue, sel);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, 0);
+ return (usb2_do_request(udev, mtx, &req, 0));
+}
+
+/*------------------------------------------------------------------------*
+ * usb2_req_set_device_feature
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+usb2_error_t
+usb2_req_set_device_feature(struct usb2_device *udev, struct mtx *mtx,
+ uint16_t sel)
+{
+ struct usb2_device_request req;
+
+ req.bmRequestType = UT_WRITE_DEVICE;
+ req.bRequest = UR_SET_FEATURE;
+ USETW(req.wValue, sel);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, 0);
+ return (usb2_do_request(udev, mtx, &req, 0));
+}