[Midnightbsd-cvs] src [6566] trunk/sys/dev/usb: Update USB stack
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sat Dec 28 10:27:54 EST 2013
Revision: 6566
http://svnweb.midnightbsd.org/src/?rev=6566
Author: laffer1
Date: 2013-12-28 10:27:54 -0500 (Sat, 28 Dec 2013)
Log Message:
-----------
Update USB stack
Obtained from: FreeBSD 9.2
Modified Paths:
--------------
trunk/sys/dev/usb/usb.h
trunk/sys/dev/usb/usb_bus.h
trunk/sys/dev/usb/usb_controller.h
trunk/sys/dev/usb/usb_debug.c
trunk/sys/dev/usb/usb_debug.h
trunk/sys/dev/usb/usb_dev.c
trunk/sys/dev/usb/usb_dev.h
trunk/sys/dev/usb/usb_device.c
trunk/sys/dev/usb/usb_device.h
trunk/sys/dev/usb/usb_generic.c
trunk/sys/dev/usb/usb_handle_request.c
trunk/sys/dev/usb/usb_hid.c
trunk/sys/dev/usb/usb_hub.c
trunk/sys/dev/usb/usb_ioctl.h
trunk/sys/dev/usb/usb_msctest.c
trunk/sys/dev/usb/usb_process.c
trunk/sys/dev/usb/usb_process.h
trunk/sys/dev/usb/usb_request.c
trunk/sys/dev/usb/usb_transfer.c
trunk/sys/dev/usb/usb_util.c
trunk/sys/dev/usb/usbdi.h
trunk/sys/dev/usb/usbhid.h
Modified: trunk/sys/dev/usb/usb.h
===================================================================
--- trunk/sys/dev/usb/usb.h 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb.h 2013-12-28 15:27:54 UTC (rev 6566)
@@ -93,31 +93,29 @@
#define USB_POWER_MODE_SUSPEND 3 /* force suspend */
#define USB_POWER_MODE_RESUME 4 /* force resume */
-#if 0
/* These are the values from the USB specification. */
-#define USB_PORT_RESET_DELAY 10 /* ms */
-#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */
-#define USB_PORT_RESET_RECOVERY 10 /* ms */
-#define USB_PORT_POWERUP_DELAY 100 /* ms */
-#define USB_PORT_RESUME_DELAY 20 /* ms */
-#define USB_SET_ADDRESS_SETTLE 2 /* ms */
-#define USB_RESUME_DELAY (20*5) /* ms */
-#define USB_RESUME_WAIT 10 /* ms */
-#define USB_RESUME_RECOVERY 10 /* ms */
-#define USB_EXTRA_POWER_UP_TIME 0 /* ms */
-#else
+#define USB_PORT_RESET_DELAY_SPEC 10 /* ms */
+#define USB_PORT_ROOT_RESET_DELAY_SPEC 50 /* ms */
+#define USB_PORT_RESET_RECOVERY_SPEC 10 /* ms */
+#define USB_PORT_POWERUP_DELAY_SPEC 100 /* ms */
+#define USB_PORT_RESUME_DELAY_SPEC 20 /* ms */
+#define USB_SET_ADDRESS_SETTLE_SPEC 2 /* ms */
+#define USB_RESUME_DELAY_SPEC (20*5) /* ms */
+#define USB_RESUME_WAIT_SPEC 10 /* ms */
+#define USB_RESUME_RECOVERY_SPEC 10 /* ms */
+#define USB_EXTRA_POWER_UP_TIME_SPEC 0 /* ms */
+
/* Allow for marginal and non-conforming devices. */
-#define USB_PORT_RESET_DELAY 50 /* ms */
-#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */
-#define USB_PORT_RESET_RECOVERY 250 /* ms */
-#define USB_PORT_POWERUP_DELAY 300 /* ms */
-#define USB_PORT_RESUME_DELAY (20*2) /* ms */
-#define USB_SET_ADDRESS_SETTLE 10 /* ms */
-#define USB_RESUME_DELAY (50*5) /* ms */
-#define USB_RESUME_WAIT 50 /* ms */
-#define USB_RESUME_RECOVERY 50 /* ms */
-#define USB_EXTRA_POWER_UP_TIME 20 /* ms */
-#endif
+#define USB_PORT_RESET_DELAY 50 /* ms */
+#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */
+#define USB_PORT_RESET_RECOVERY 250 /* ms */
+#define USB_PORT_POWERUP_DELAY 300 /* ms */
+#define USB_PORT_RESUME_DELAY (20*2) /* ms */
+#define USB_SET_ADDRESS_SETTLE 10 /* ms */
+#define USB_RESUME_DELAY (50*5) /* ms */
+#define USB_RESUME_WAIT 50 /* ms */
+#define USB_RESUME_RECOVERY 50 /* ms */
+#define USB_EXTRA_POWER_UP_TIME 20 /* ms */
#define USB_MIN_POWER 100 /* mA */
#define USB_MAX_POWER 500 /* mA */
Modified: trunk/sys/dev/usb/usb_bus.h
===================================================================
--- trunk/sys/dev/usb/usb_bus.h 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_bus.h 2013-12-28 15:27:54 UTC (rev 6566)
@@ -103,16 +103,6 @@
uint8_t devices_max; /* maximum number of USB devices */
uint8_t do_probe; /* set if USB should be re-probed */
uint8_t no_explore; /* don't explore USB ports */
-
- /*
- * The scratch area can only be used inside the explore thread
- * belonging to the give serial bus.
- */
- union {
- struct usb_hw_ep_scratch hw_ep_scratch[1];
- struct usb_temp_setup temp_setup[1];
- uint8_t data[255];
- } scratch[1];
};
#endif /* _USB_BUS_H_ */
Modified: trunk/sys/dev/usb/usb_controller.h
===================================================================
--- trunk/sys/dev/usb/usb_controller.h 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_controller.h 2013-12-28 15:27:54 UTC (rev 6566)
@@ -40,7 +40,6 @@
struct usb_setup_params;
struct usb_hw_ep_profile;
struct usb_fs_isoc_schedule;
-struct usb_config_descriptor;
struct usb_endpoint_descriptor;
/* typedefs */
@@ -181,50 +180,6 @@
uint8_t support_out:1; /* OUT-token is supported */
};
-/*
- * The following structure is used when trying to allocate hardware
- * endpoints for an USB configuration in USB device side mode.
- */
-struct usb_hw_ep_scratch_sub {
- const struct usb_hw_ep_profile *pf;
- uint16_t max_frame_size;
- uint8_t hw_endpoint_out;
- uint8_t hw_endpoint_in;
- uint8_t needs_ep_type;
- uint8_t needs_in:1;
- uint8_t needs_out:1;
-};
-
-/*
- * The following structure is used when trying to allocate hardware
- * endpoints for an USB configuration in USB device side mode.
- */
-struct usb_hw_ep_scratch {
- struct usb_hw_ep_scratch_sub ep[USB_EP_MAX];
- struct usb_hw_ep_scratch_sub *ep_max;
- struct usb_config_descriptor *cd;
- struct usb_device *udev;
- struct usb_bus_methods *methods;
- uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16];
- uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16];
-};
-
-/*
- * The following structure is used when generating USB descriptors
- * from USB templates.
- */
-struct usb_temp_setup {
- void *buf;
- usb_size_t size;
- enum usb_dev_speed usb_speed;
- uint8_t self_powered;
- uint8_t bNumEndpoints;
- uint8_t bInterfaceNumber;
- uint8_t bAlternateSetting;
- uint8_t bConfigurationValue;
- usb_error_t err;
-};
-
/* prototypes */
void usb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb);
Modified: trunk/sys/dev/usb/usb_debug.c
===================================================================
--- trunk/sys/dev/usb/usb_debug.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_debug.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -63,11 +63,59 @@
int usb_debug = 0;
SYSCTL_NODE(_hw, OID_AUTO, usb, CTLFLAG_RW, 0, "USB debugging");
-SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&usb_debug, 0, "Debug level");
-
TUNABLE_INT("hw.usb.debug", &usb_debug);
+#ifdef USB_DEBUG
+/*
+ * Sysctls to modify timings/delays
+ */
+static SYSCTL_NODE(_hw_usb, OID_AUTO, timings, CTLFLAG_RW, 0, "Timings");
+static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS);
+
+TUNABLE_INT("hw.usb.timings.port_reset_delay", (int *)&usb_port_reset_delay);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_port_reset_delay, sizeof(usb_port_reset_delay),
+ usb_timings_sysctl_handler, "IU", "Port Reset Delay");
+TUNABLE_INT("hw.usb.timings.port_root_reset_delay", (int *)&usb_port_root_reset_delay);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_root_reset_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_port_root_reset_delay, sizeof(usb_port_root_reset_delay),
+ usb_timings_sysctl_handler, "IU", "Root Port Reset Delay");
+TUNABLE_INT("hw.usb.timings.port_reset_recovery", (int *)&usb_port_reset_recovery);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_recovery, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_port_reset_recovery, sizeof(usb_port_reset_recovery),
+ usb_timings_sysctl_handler, "IU", "Port Reset Recovery");
+TUNABLE_INT("hw.usb.timings.port_powerup_delay", (int *)&usb_port_powerup_delay);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_powerup_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_port_powerup_delay, sizeof(usb_port_powerup_delay),
+ usb_timings_sysctl_handler, "IU", "Port PowerUp Delay");
+TUNABLE_INT("hw.usb.timings.port_resume_delay", (int *)&usb_port_resume_delay);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_resume_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_port_resume_delay, sizeof(usb_port_resume_delay),
+ usb_timings_sysctl_handler, "IU", "Port Resume Delay");
+TUNABLE_INT("hw.usb.timings.set_address_settle", (int *)&usb_set_address_settle);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, set_address_settle, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_set_address_settle, sizeof(usb_set_address_settle),
+ usb_timings_sysctl_handler, "IU", "Set Address Settle");
+TUNABLE_INT("hw.usb.timings.resume_delay", (int *)&usb_resume_delay);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_resume_delay, sizeof(usb_resume_delay),
+ usb_timings_sysctl_handler, "IU", "Resume Delay");
+TUNABLE_INT("hw.usb.timings.resume_wait", (int *)&usb_resume_wait);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_wait, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_resume_wait, sizeof(usb_resume_wait),
+ usb_timings_sysctl_handler, "IU", "Resume Wait");
+TUNABLE_INT("hw.usb.timings.resume_recovery", (int *)&usb_resume_recovery);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_recovery, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_resume_recovery, sizeof(usb_resume_recovery),
+ usb_timings_sysctl_handler, "IU", "Resume Recovery");
+TUNABLE_INT("hw.usb.timings.extra_power_up_time", (int *)&usb_extra_power_up_time);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, extra_power_up_time, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_extra_power_up_time, sizeof(usb_extra_power_up_time),
+ usb_timings_sysctl_handler, "IU", "Extra PowerUp Time");
+#endif
+
/*------------------------------------------------------------------------*
* usb_dump_iface
*
@@ -174,3 +222,87 @@
xfer->endpoint->edesc->bEndpointAddress,
xfer->endpoint->edesc->bmAttributes);
}
+
+#ifdef USB_DEBUG
+unsigned int usb_port_reset_delay = USB_PORT_RESET_DELAY;
+unsigned int usb_port_root_reset_delay = USB_PORT_ROOT_RESET_DELAY;
+unsigned int usb_port_reset_recovery = USB_PORT_RESET_RECOVERY;
+unsigned int usb_port_powerup_delay = USB_PORT_POWERUP_DELAY;
+unsigned int usb_port_resume_delay = USB_PORT_RESUME_DELAY;
+unsigned int usb_set_address_settle = USB_SET_ADDRESS_SETTLE;
+unsigned int usb_resume_delay = USB_RESUME_DELAY;
+unsigned int usb_resume_wait = USB_RESUME_WAIT;
+unsigned int usb_resume_recovery = USB_RESUME_RECOVERY;
+unsigned int usb_extra_power_up_time = USB_EXTRA_POWER_UP_TIME;
+
+/*------------------------------------------------------------------------*
+ * usb_timings_sysctl_handler
+ *
+ * This function updates timings variables, adjusting them where necessary.
+ *------------------------------------------------------------------------*/
+static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+ int error = 0;
+ unsigned int val;
+
+ /*
+ * Attempt to get a coherent snapshot by making a copy of the data.
+ */
+ if (arg1)
+ val = *(unsigned int *)arg1;
+ else
+ val = arg2;
+ error = SYSCTL_OUT(req, &val, sizeof(int));
+ if (error || !req->newptr)
+ return (error);
+
+ if (!arg1)
+ return EPERM;
+
+ error = SYSCTL_IN(req, &val, sizeof(unsigned int));
+ if (error)
+ return (error);
+
+ /*
+ * Now make sure the values are decent, and certainly no lower than
+ * what the USB spec prescribes.
+ */
+ unsigned int *p = (unsigned int *)arg1;
+ if (p == &usb_port_reset_delay) {
+ if (val < USB_PORT_RESET_DELAY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_port_root_reset_delay) {
+ if (val < USB_PORT_ROOT_RESET_DELAY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_port_reset_recovery) {
+ if (val < USB_PORT_RESET_RECOVERY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_port_powerup_delay) {
+ if (val < USB_PORT_POWERUP_DELAY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_port_resume_delay) {
+ if (val < USB_PORT_RESUME_DELAY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_set_address_settle) {
+ if (val < USB_SET_ADDRESS_SETTLE_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_resume_delay) {
+ if (val < USB_RESUME_DELAY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_resume_wait) {
+ if (val < USB_RESUME_WAIT_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_resume_recovery) {
+ if (val < USB_RESUME_RECOVERY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_extra_power_up_time) {
+ if (val < USB_EXTRA_POWER_UP_TIME_SPEC)
+ return (EINVAL);
+ } else {
+ /* noop */
+ }
+
+ *p = val;
+ return 0;
+}
+#endif
Modified: trunk/sys/dev/usb/usb_debug.h
===================================================================
--- trunk/sys/dev/usb/usb_debug.h 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_debug.h 2013-12-28 15:27:54 UTC (rev 6566)
@@ -59,4 +59,28 @@
void usb_dump_endpoint(struct usb_endpoint *ep);
void usb_dump_xfer(struct usb_xfer *xfer);
+#ifdef USB_DEBUG
+extern unsigned int usb_port_reset_delay;
+extern unsigned int usb_port_root_reset_delay;
+extern unsigned int usb_port_reset_recovery;
+extern unsigned int usb_port_powerup_delay;
+extern unsigned int usb_port_resume_delay;
+extern unsigned int usb_set_address_settle;
+extern unsigned int usb_resume_delay;
+extern unsigned int usb_resume_wait;
+extern unsigned int usb_resume_recovery;
+extern unsigned int usb_extra_power_up_time;
+#else
+#define usb_port_reset_delay USB_PORT_RESET_DELAY
+#define usb_port_root_reset_delay USB_PORT_ROOT_RESET_DELAY
+#define usb_port_reset_recovery USB_PORT_RESET_RECOVERY
+#define usb_port_powerup_delay USB_PORT_POWERUP_DELAY
+#define usb_port_resume_delay USB_PORT_RESUME_DELAY
+#define usb_set_address_settle USB_SET_ADDRESS_SETTLE
+#define usb_resume_delay USB_RESUME_DELAY
+#define usb_resume_wait USB_RESUME_WAIT
+#define usb_resume_recovery USB_RESUME_RECOVERY
+#define usb_extra_power_up_time USB_EXTRA_POWER_UP_TIME
+#endif
+
#endif /* _USB_DEBUG_H_ */
Modified: trunk/sys/dev/usb/usb_dev.c
===================================================================
--- trunk/sys/dev/usb/usb_dev.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_dev.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -81,10 +81,9 @@
#ifdef USB_DEBUG
static int usb_fifo_debug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, dev, CTLFLAG_RW, 0, "USB device");
-SYSCTL_INT(_hw_usb_dev, OID_AUTO, debug, CTLFLAG_RW,
+static SYSCTL_NODE(_hw_usb, OID_AUTO, dev, CTLFLAG_RW, 0, "USB device");
+SYSCTL_INT(_hw_usb_dev, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&usb_fifo_debug, 0, "Debug Level");
-
TUNABLE_INT("hw.usb.dev.debug", &usb_fifo_debug);
#endif
@@ -215,10 +214,10 @@
mtx_unlock(&usb_ref_lock);
/*
- * We need to grab the sx-lock before grabbing the
- * FIFO refs to avoid deadlock at detach!
+ * We need to grab the enumeration SX-lock before
+ * grabbing the FIFO refs to avoid deadlock at detach!
*/
- usbd_enum_lock(cpd->udev);
+ crd->do_unlock = usbd_enum_lock(cpd->udev);
mtx_lock(&usb_ref_lock);
@@ -279,9 +278,10 @@
return (0);
error:
- if (crd->is_uref) {
+ if (crd->do_unlock)
usbd_enum_unlock(cpd->udev);
+ if (crd->is_uref) {
if (--(cpd->udev->refcount) == 0) {
cv_signal(&cpd->udev->ref_cv);
}
@@ -333,7 +333,7 @@
DPRINTFN(2, "cpd=%p is_uref=%d\n", cpd, crd->is_uref);
- if (crd->is_uref)
+ if (crd->do_unlock)
usbd_enum_unlock(cpd->udev);
mtx_lock(&usb_ref_lock);
Modified: trunk/sys/dev/usb/usb_dev.h
===================================================================
--- trunk/sys/dev/usb/usb_dev.h 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_dev.h 2013-12-28 15:27:54 UTC (rev 6566)
@@ -82,6 +82,7 @@
uint8_t is_write; /* location has write access */
uint8_t is_uref; /* USB refcount decr. needed */
uint8_t is_usbfs; /* USB-FS is active */
+ uint8_t do_unlock; /* USB enum unlock needed */
};
struct usb_fs_privdata {
Modified: trunk/sys/dev/usb/usb_device.c
===================================================================
--- trunk/sys/dev/usb/usb_device.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_device.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -111,7 +111,7 @@
int usb_template = 0;
TUNABLE_INT("hw.usb.usb_template", &usb_template);
-SYSCTL_INT(_hw_usb, OID_AUTO, template, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb, OID_AUTO, template, CTLFLAG_RW | CTLFLAG_TUN,
&usb_template, 0, "Selected USB device side template");
/* English is default language */
@@ -120,11 +120,11 @@
static int usb_lang_mask = 0x00FF;
TUNABLE_INT("hw.usb.usb_lang_id", &usb_lang_id);
-SYSCTL_INT(_hw_usb, OID_AUTO, usb_lang_id, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb, OID_AUTO, usb_lang_id, CTLFLAG_RW | CTLFLAG_TUN,
&usb_lang_id, 0, "Preferred USB language ID");
TUNABLE_INT("hw.usb.usb_lang_mask", &usb_lang_mask);
-SYSCTL_INT(_hw_usb, OID_AUTO, usb_lang_mask, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb, OID_AUTO, usb_lang_mask, CTLFLAG_RW | CTLFLAG_TUN,
&usb_lang_mask, 0, "Preferred USB language mask");
static const char* statestr[USB_STATE_MAX] = {
@@ -443,13 +443,8 @@
{
uint8_t do_unlock;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
/* detach all interface drivers */
usb_detach_device(udev, USB_IFACE_INDEX_ANY, flag);
@@ -512,13 +507,8 @@
DPRINTFN(6, "udev=%p index=%d\n", udev, index);
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
usb_unconfigure(udev, 0);
@@ -871,13 +861,9 @@
usb_error_t err;
uint8_t do_unlock;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
+
if (iface == NULL) {
err = USB_ERR_INVAL;
goto done;
@@ -914,7 +900,6 @@
done:
if (do_unlock)
usbd_enum_unlock(udev);
-
return (err);
}
@@ -1285,13 +1270,8 @@
DPRINTF("udev == NULL\n");
return (USB_ERR_INVAL);
}
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
if (udev->curr_config_index == USB_UNCONFIG_INDEX) {
/* do nothing - no configuration has been set */
@@ -1378,7 +1358,6 @@
done:
if (do_unlock)
usbd_enum_unlock(udev);
-
return (0);
}
@@ -1507,6 +1486,7 @@
uint8_t config_index;
uint8_t config_quirk;
uint8_t set_config_failed;
+ uint8_t do_unlock;
DPRINTF("parent_dev=%p, bus=%p, parent_hub=%p, depth=%u, "
"port_index=%u, port_no=%u, speed=%u, usb_mode=%u\n",
@@ -1541,9 +1521,6 @@
return (NULL);
}
/* initialise our SX-lock */
- sx_init_flags(&udev->ctrl_sx, "USB device SX lock", SX_DUPOK);
-
- /* initialise our SX-lock */
sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK);
sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS);
@@ -1725,8 +1702,12 @@
* device descriptor. If no strings are present there we
* simply disable all USB strings.
*/
- scratch_ptr = udev->bus->scratch[0].data;
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
+
+ scratch_ptr = udev->scratch.data;
+
if (udev->ddesc.iManufacturer ||
udev->ddesc.iProduct ||
udev->ddesc.iSerialNumber) {
@@ -1750,7 +1731,7 @@
mask = usb_lang_mask;
/* align length correctly */
- scratch_ptr[0] &= ~1;
+ scratch_ptr[0] &= ~1U;
/* fix compiler warning */
langid = 0;
@@ -1771,6 +1752,9 @@
udev->langid = langid;
}
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
/* assume 100mA bus powered for now. Changed when configured. */
udev->power = USB_MIN_POWER;
/* fetch the vendor and product strings from the device */
@@ -2107,7 +2091,6 @@
&udev->cs_msg[0], &udev->cs_msg[1]);
USB_BUS_UNLOCK(udev->bus);
- sx_destroy(&udev->ctrl_sx);
sx_destroy(&udev->enum_sx);
sx_destroy(&udev->sr_sx);
@@ -2270,10 +2253,14 @@
size_t temp_size;
uint16_t vendor_id;
uint16_t product_id;
+ uint8_t do_unlock;
- temp_ptr = (char *)udev->bus->scratch[0].data;
- temp_size = sizeof(udev->bus->scratch[0].data);
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
+ temp_ptr = (char *)udev->scratch.data;
+ temp_size = sizeof(udev->scratch.data);
+
vendor_id = UGETW(udd->idVendor);
product_id = UGETW(udd->idProduct);
@@ -2327,6 +2314,9 @@
snprintf(temp_ptr, temp_size, "product 0x%04x", product_id);
udev->product = strdup(temp_ptr, M_USB);
}
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
}
/*
@@ -2639,11 +2629,17 @@
return (udev->state > USB_STATE_DETACHED);
}
-/* The following function locks enumerating the given USB device. */
-
-void
+/*
+ * The following function locks enumerating the given USB device. If
+ * the lock is already grabbed this function returns zero. Else a
+ * non-zero value is returned.
+ */
+uint8_t
usbd_enum_lock(struct usb_device *udev)
{
+ if (sx_xlocked(&udev->enum_sx))
+ return (0);
+
sx_xlock(&udev->enum_sx);
sx_xlock(&udev->sr_sx);
/*
@@ -2652,6 +2648,7 @@
* locked multiple times.
*/
mtx_lock(&Giant);
+ return (1);
}
/* The following function unlocks enumerating the given USB device. */
Modified: trunk/sys/dev/usb/usb_device.h
===================================================================
--- trunk/sys/dev/usb/usb_device.h 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_device.h 2013-12-28 15:27:54 UTC (rev 6566)
@@ -27,9 +27,18 @@
#ifndef _USB_DEVICE_H_
#define _USB_DEVICE_H_
-struct usb_symlink; /* UGEN */
+#ifndef USB_GLOBAL_INCLUDE_FILE
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_transfer.h>
+#endif
+
+struct usb_bus_methods;
+struct usb_config_descriptor;
struct usb_device; /* linux compat */
struct usb_fs_privdata;
+struct usb_hw_ep_profile;
+struct usb_symlink; /* UGEN */
#define USB_CTRL_XFER_MAX 2
@@ -108,6 +117,64 @@
};
/*
+ * The following structure is used when trying to allocate hardware
+ * endpoints for an USB configuration in USB device side mode.
+ */
+struct usb_hw_ep_scratch_sub {
+ const struct usb_hw_ep_profile *pf;
+ uint16_t max_frame_size;
+ uint8_t hw_endpoint_out;
+ uint8_t hw_endpoint_in;
+ uint8_t needs_ep_type;
+ uint8_t needs_in:1;
+ uint8_t needs_out:1;
+};
+
+/*
+ * The following structure is used when trying to allocate hardware
+ * endpoints for an USB configuration in USB device side mode.
+ */
+struct usb_hw_ep_scratch {
+ struct usb_hw_ep_scratch_sub ep[USB_EP_MAX];
+ struct usb_hw_ep_scratch_sub *ep_max;
+ struct usb_config_descriptor *cd;
+ struct usb_device *udev;
+ struct usb_bus_methods *methods;
+ uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16];
+ uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16];
+};
+
+/*
+ * The following structure is used when generating USB descriptors
+ * from USB templates.
+ */
+struct usb_temp_setup {
+ void *buf;
+ usb_size_t size;
+ enum usb_dev_speed usb_speed;
+ uint8_t self_powered;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bConfigurationValue;
+ usb_error_t err;
+};
+
+/*
+ * The scratch area for USB devices. Access to this structure is
+ * protected by the enumeration SX lock.
+ */
+union usb_device_scratch {
+ struct usb_hw_ep_scratch hw_ep_scratch[1];
+ struct usb_temp_setup temp_setup[1];
+ struct {
+ struct usb_xfer dummy;
+ struct usb_setup_params parm;
+ } xfer_setup[1];
+ uint8_t data[255];
+};
+
+/*
* The following structure defines an USB device. There exists one of
* these structures for every USB device.
*/
@@ -114,7 +181,6 @@
struct usb_device {
struct usb_clear_stall_msg cs_msg[2]; /* generic clear stall
* messages */
- struct sx ctrl_sx;
struct sx enum_sx;
struct sx sr_sx;
struct mtx device_mtx;
@@ -191,6 +257,8 @@
#endif
uint32_t clear_stall_errors; /* number of clear-stall failures */
+
+ union usb_device_scratch scratch;
};
/* globals */
@@ -227,7 +295,7 @@
void usb_set_device_state(struct usb_device *, enum usb_dev_state);
enum usb_dev_state usb_get_device_state(struct usb_device *);
-void usbd_enum_lock(struct usb_device *);
+uint8_t usbd_enum_lock(struct usb_device *);
void usbd_enum_unlock(struct usb_device *);
void usbd_sr_lock(struct usb_device *);
void usbd_sr_unlock(struct usb_device *);
Modified: trunk/sys/dev/usb/usb_generic.c
===================================================================
--- trunk/sys/dev/usb/usb_generic.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_generic.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -126,10 +126,9 @@
#ifdef USB_DEBUG
static int ugen_debug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW, 0, "USB generic");
-SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RW, &ugen_debug,
+static SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW, 0, "USB generic");
+SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &ugen_debug,
0, "Debug level");
-
TUNABLE_INT("hw.usb.ugen.debug", &ugen_debug);
#endif
@@ -714,13 +713,20 @@
return (error);
}
+/*
+ * This function is called having the enumeration SX locked which
+ * protects the scratch area used.
+ */
static int
ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
{
- void *ptr = f->udev->bus->scratch[0].data;
- uint16_t size = sizeof(f->udev->bus->scratch[0].data);
+ void *ptr;
+ uint16_t size;
int error;
+ ptr = f->udev->scratch.data;
+ size = sizeof(f->udev->scratch.data);
+
if (usbd_req_get_string_desc(f->udev, NULL, ptr,
size, ugd->ugd_lang_id, ugd->ugd_string_index)) {
error = EINVAL;
@@ -1825,6 +1831,17 @@
}
static int
+ugen_get_power_usage(struct usb_fifo *f)
+{
+ struct usb_device *udev = f->udev;
+
+ if (udev == NULL)
+ return (0);
+
+ return (udev->power);
+}
+
+static int
ugen_do_port_feature(struct usb_fifo *f, uint8_t port_no,
uint8_t set, uint16_t feature)
{
@@ -2186,6 +2203,10 @@
*u.pint = ugen_get_power_mode(f);
break;
+ case USB_GET_POWER_USAGE:
+ *u.pint = ugen_get_power_usage(f);
+ break;
+
case USB_SET_PORT_ENABLE:
error = ugen_do_port_feature(f,
*u.pint, 1, UHF_PORT_ENABLE);
Modified: trunk/sys/dev/usb/usb_handle_request.c
===================================================================
--- trunk/sys/dev/usb/usb_handle_request.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_handle_request.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -145,6 +145,7 @@
{
struct usb_device *udev = xfer->xroot->udev;
usb_error_t err = 0;
+ uint8_t do_unlock;
/*
* We need to protect against other threads doing probe and
@@ -152,7 +153,8 @@
*/
USB_XFER_UNLOCK(xfer);
- usbd_enum_lock(udev);
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
if (conf_no == USB_UNCONFIG_NO) {
conf_no = USB_UNCONFIG_INDEX;
@@ -175,7 +177,8 @@
goto done;
}
done:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (err);
}
@@ -187,13 +190,8 @@
uint8_t do_unlock;
usb_error_t err = 0;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc))
err = USB_ERR_INVAL;
@@ -222,6 +220,7 @@
int error;
uint8_t iface_index;
uint8_t temp_state;
+ uint8_t do_unlock;
if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
iface_index = req.wIndex[0]; /* unicast */
@@ -235,7 +234,8 @@
*/
USB_XFER_UNLOCK(xfer);
- usbd_enum_lock(udev);
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
error = ENXIO;
@@ -351,17 +351,20 @@
goto tr_stalled;
}
tr_valid:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (0);
tr_short:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (USB_ERR_SHORT_XFER);
tr_stalled:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (USB_ERR_STALLED);
}
Modified: trunk/sys/dev/usb/usb_hid.c
===================================================================
--- trunk/sys/dev/usb/usb_hid.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_hid.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -845,3 +845,79 @@
}
return (USB_ERR_NORMAL_COMPLETION);
}
+
+/*------------------------------------------------------------------------*
+ * hid_is_mouse
+ *
+ * This function will decide if a USB descriptor belongs to a USB mouse.
+ *
+ * Return values:
+ * Zero: Not a USB mouse.
+ * Else: Is a USB mouse.
+ *------------------------------------------------------------------------*/
+int
+hid_is_mouse(const void *d_ptr, uint16_t d_len)
+{
+ struct hid_data *hd;
+ struct hid_item hi;
+ int mdepth;
+ int found;
+
+ hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
+ if (hd == NULL)
+ return (0);
+
+ mdepth = 0;
+ found = 0;
+
+ while (hid_get_item(hd, &hi)) {
+ switch (hi.kind) {
+ case hid_collection:
+ if (mdepth != 0)
+ mdepth++;
+ else if (hi.collection == 1 &&
+ hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
+ mdepth++;
+ break;
+ case hid_endcollection:
+ if (mdepth != 0)
+ mdepth--;
+ break;
+ case hid_input:
+ if (mdepth == 0)
+ break;
+ if (hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
+ (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
+ found++;
+ if (hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
+ (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
+ found++;
+ break;
+ default:
+ break;
+ }
+ }
+ hid_end_parse(hd);
+ return (found);
+}
+
+/*------------------------------------------------------------------------*
+ * hid_is_keyboard
+ *
+ * This function will decide if a USB descriptor belongs to a USB keyboard.
+ *
+ * Return values:
+ * Zero: Not a USB keyboard.
+ * Else: Is a USB keyboard.
+ *------------------------------------------------------------------------*/
+int
+hid_is_keyboard(const void *d_ptr, uint16_t d_len)
+{
+ if (hid_is_collection(d_ptr, d_len,
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
+ return (1);
+ return (0);
+}
Modified: trunk/sys/dev/usb/usb_hub.c
===================================================================
--- trunk/sys/dev/usb/usb_hub.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_hub.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -76,10 +76,9 @@
#ifdef USB_DEBUG
static int uhub_debug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB HUB");
-SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW, &uhub_debug, 0,
+static SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB HUB");
+SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &uhub_debug, 0,
"Debug level");
-
TUNABLE_INT("hw.usb.uhub.debug", &uhub_debug);
#endif
@@ -241,7 +240,9 @@
/* check if device should be re-enumerated */
if (child->flags.usb_mode == USB_MODE_HOST) {
- usbd_enum_lock(child);
+ uint8_t do_unlock;
+
+ do_unlock = usbd_enum_lock(child);
if (child->re_enumerate_wait) {
err = usbd_set_config_index(child,
USB_UNCONFIG_INDEX);
@@ -260,7 +261,8 @@
child->re_enumerate_wait = 0;
err = 0;
}
- usbd_enum_unlock(child);
+ if (do_unlock)
+ usbd_enum_unlock(child);
}
/* check if probe and attach should be done */
@@ -415,7 +417,7 @@
/* wait for maximum device power up time */
usb_pause_mtx(NULL,
- USB_MS_TO_TICKS(USB_PORT_POWERUP_DELAY));
+ USB_MS_TO_TICKS(usb_port_powerup_delay));
/* reset port, which implies enabling it */
@@ -711,6 +713,7 @@
usb_error_t err;
uint8_t portno;
uint8_t x;
+ uint8_t do_unlock;
hub = udev->hub;
sc = hub->hubsoftc;
@@ -732,7 +735,7 @@
* Make sure we don't race against user-space applications
* like LibUSB:
*/
- usbd_enum_lock(udev);
+ do_unlock = usbd_enum_lock(udev);
for (x = 0; x != hub->nports; x++) {
up = hub->ports + x;
@@ -812,7 +815,8 @@
up->restartcnt = 0;
}
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
/* initial status checked */
sc->sc_flags |= UHUB_FLAG_DID_EXPLORE;
@@ -979,7 +983,7 @@
/* get power delay */
pwrdly = ((hubdesc20.bPwrOn2PwrGood * UHD_PWRON_FACTOR) +
- USB_EXTRA_POWER_UP_TIME);
+ usb_extra_power_up_time);
/* get complete HUB descriptor */
if (nports >= 8) {
@@ -1024,7 +1028,7 @@
/* get power delay */
pwrdly = ((hubdesc30.bPwrOn2PwrGood * UHD_PWRON_FACTOR) +
- USB_EXTRA_POWER_UP_TIME);
+ usb_extra_power_up_time);
/* get complete HUB descriptor */
if (nports >= 8) {
@@ -1053,7 +1057,7 @@
/* default number of ports */
nports = 1;
/* default power delay */
- pwrdly = ((10 * UHD_PWRON_FACTOR) + USB_EXTRA_POWER_UP_TIME);
+ pwrdly = ((10 * UHD_PWRON_FACTOR) + usb_extra_power_up_time);
break;
}
if (nports == 0) {
@@ -2261,7 +2265,7 @@
}
/* resume settle time */
- usb_pause_mtx(NULL, USB_MS_TO_TICKS(USB_PORT_RESUME_DELAY));
+ usb_pause_mtx(NULL, USB_MS_TO_TICKS(usb_port_resume_delay));
if (bus->methods->device_resume != NULL) {
/* resume USB device on the USB controller */
@@ -2414,7 +2418,7 @@
NULL, udev->port_no, UHF_PORT_SUSPEND);
/* resume settle time */
- usb_pause_mtx(NULL, USB_MS_TO_TICKS(USB_PORT_RESUME_DELAY));
+ usb_pause_mtx(NULL, USB_MS_TO_TICKS(usb_port_resume_delay));
}
DPRINTF("Suspend was cancelled!\n");
return;
Modified: trunk/sys/dev/usb/usb_ioctl.h
===================================================================
--- trunk/sys/dev/usb/usb_ioctl.h 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_ioctl.h 2013-12-28 15:27:54 UTC (rev 6566)
@@ -270,7 +270,8 @@
#define USB_IFACE_DRIVER_DETACH _IOW ('U', 125, int)
#define USB_GET_PLUGTIME _IOR ('U', 126, uint32_t)
#define USB_READ_DIR _IOW ('U', 127, struct usb_read_dir)
-/* 128 - 135 unused */
+/* 128 - 134 unused */
+#define USB_GET_POWER_USAGE _IOR ('U', 135, int)
#define USB_SET_TX_FORCE_SHORT _IOW ('U', 136, int)
#define USB_SET_TX_TIMEOUT _IOW ('U', 137, int)
#define USB_GET_TX_FRAME_SIZE _IOR ('U', 138, int)
Modified: trunk/sys/dev/usb/usb_msctest.c
===================================================================
--- trunk/sys/dev/usb/usb_msctest.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_msctest.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -103,6 +103,8 @@
0x00, 0x00, 0x00, 0x00 };
static uint8_t scsi_request_sense[] = { 0x03, 0x00, 0x00, 0x00, 0x12, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_read_capacity[] = { 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
#define BULK_SIZE 64 /* dummy */
#define ERR_CSW_FAILED -1
@@ -499,13 +501,8 @@
usb_error_t err;
uint8_t do_unlock;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
/*
* Make sure any driver which is hooked up to this interface,
@@ -652,7 +649,7 @@
}
is_no_direct = 1;
- for (timeout = 4; timeout; timeout--) {
+ for (timeout = 4; timeout != 0; timeout--) {
err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
USB_MS_HZ);
@@ -662,8 +659,11 @@
if (sid_type == 0x00)
is_no_direct = 0;
break;
- } else if (err != ERR_CSW_FAILED)
- break; /* non retryable error */
+ } else if (err != ERR_CSW_FAILED) {
+ DPRINTF("Device is not responding "
+ "properly to SCSI INQUIRY command.\n");
+ goto error; /* non retryable error */
+ }
usb_pause_mtx(NULL, hz);
}
@@ -681,7 +681,9 @@
if (err != ERR_CSW_FAILED)
goto error;
}
+ timeout = 1;
+retry_sync_cache:
err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
&scsi_sync_cache, sizeof(scsi_sync_cache),
USB_MS_HZ);
@@ -694,6 +696,42 @@
DPRINTF("Device doesn't handle synchronize cache\n");
usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+
+ } else {
+
+ /*
+ * Certain Kingston memory sticks fail the first
+ * read capacity after a synchronize cache command
+ * has been issued. Disable the synchronize cache
+ * command for such devices.
+ */
+
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
+ &scsi_read_capacity, sizeof(scsi_read_capacity),
+ USB_MS_HZ);
+
+ if (err != 0) {
+ if (err != ERR_CSW_FAILED)
+ goto error;
+
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
+ &scsi_read_capacity, sizeof(scsi_read_capacity),
+ USB_MS_HZ);
+
+ if (err == 0) {
+ if (timeout--)
+ goto retry_sync_cache;
+
+ DPRINTF("Device most likely doesn't "
+ "handle synchronize cache\n");
+
+ usbd_add_dynamic_quirk(udev,
+ UQ_MSC_NO_SYNC_CACHE);
+ } else {
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ }
+ }
}
/* clear sense status of any failed commands on the device */
Modified: trunk/sys/dev/usb/usb_process.c
===================================================================
--- trunk/sys/dev/usb/usb_process.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_process.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -81,10 +81,9 @@
#ifdef USB_DEBUG
static int usb_proc_debug;
-SYSCTL_NODE(_hw_usb, OID_AUTO, proc, CTLFLAG_RW, 0, "USB process");
-SYSCTL_INT(_hw_usb_proc, OID_AUTO, debug, CTLFLAG_RW, &usb_proc_debug, 0,
+static SYSCTL_NODE(_hw_usb, OID_AUTO, proc, CTLFLAG_RW, 0, "USB process");
+SYSCTL_INT(_hw_usb_proc, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &usb_proc_debug, 0,
"Debug level");
-
TUNABLE_INT("hw.usb.proc.debug", &usb_proc_debug);
#endif
Modified: trunk/sys/dev/usb/usb_process.h
===================================================================
--- trunk/sys/dev/usb/usb_process.h 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_process.h 2013-12-28 15:27:54 UTC (rev 6566)
@@ -42,6 +42,7 @@
/* structure prototypes */
struct usb_proc_msg;
+struct usb_device;
/*
* The following structure defines the USB process.
@@ -79,4 +80,9 @@
void *usb_proc_msignal(struct usb_process *up, void *pm0, void *pm1);
void usb_proc_rewakeup(struct usb_process *up);
+void usb_proc_explore_mwait(struct usb_device *, void *, void *);
+void *usb_proc_explore_msignal(struct usb_device *, void *, void *);
+void usb_proc_explore_lock(struct usb_device *);
+void usb_proc_explore_unlock(struct usb_device *);
+
#endif /* _USB_PROCESS_H_ */
Modified: trunk/sys/dev/usb/usb_request.c
===================================================================
--- trunk/sys/dev/usb/usb_request.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_request.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -73,14 +73,6 @@
&usb_no_cs_fail, 0, "USB clear stall failures are ignored, if set");
#ifdef USB_DEBUG
-static int usb_pr_poll_delay = USB_PORT_RESET_DELAY;
-static int usb_pr_recovery_delay = USB_PORT_RESET_RECOVERY;
-
-SYSCTL_INT(_hw_usb, OID_AUTO, pr_poll_delay, CTLFLAG_RW,
- &usb_pr_poll_delay, 0, "USB port reset poll delay in ms");
-SYSCTL_INT(_hw_usb, OID_AUTO, pr_recovery_delay, CTLFLAG_RW,
- &usb_pr_recovery_delay, 0, "USB port reset recovery delay in ms");
-
#ifdef USB_REQ_DEBUG
/* The following structures are used in connection to fault injection. */
struct usb_ctrl_debug {
@@ -87,7 +79,7 @@
int bus_index; /* target bus */
int dev_index; /* target address */
int ds_fail; /* fail data stage */
- int ss_fail; /* fail data stage */
+ int ss_fail; /* fail status stage */
int ds_delay; /* data stage delay in ms */
int ss_delay; /* status stage delay in ms */
int bmRequestType_value;
@@ -390,9 +382,8 @@
* than 30 seconds is treated like a 30 second timeout. This USB stack
* does not allow control requests without a timeout.
*
- * NOTE: This function is thread safe. All calls to
- * "usbd_do_request_flags" will be serialised by the use of an
- * internal "sx_lock".
+ * NOTE: This function is thread safe. All calls to "usbd_do_request_flags"
+ * will be serialized by the use of the USB device enumeration lock.
*
* Returns:
* 0: Success
@@ -416,7 +407,7 @@
uint16_t length;
uint16_t temp;
uint16_t acttemp;
- uint8_t enum_locked;
+ uint8_t do_unlock;
if (timeout < 50) {
/* timeout is too small */
@@ -428,8 +419,6 @@
}
length = UGETW(req->wLength);
- enum_locked = usbd_enum_is_locked(udev);
-
DPRINTFN(5, "udev=%p bmRequestType=0x%02x bRequest=0x%02x "
"wValue=0x%02x%02x wIndex=0x%02x%02x wLength=0x%02x%02x\n",
udev, req->bmRequestType, req->bRequest,
@@ -460,17 +449,16 @@
}
/*
- * We need to allow suspend and resume at this point, else the
- * control transfer will timeout if the device is suspended!
+ * Grab the USB device enumeration SX-lock serialization is
+ * achieved when multiple threads are involved:
*/
- if (enum_locked)
- usbd_sr_unlock(udev);
+ do_unlock = usbd_enum_lock(udev);
/*
- * Grab the default sx-lock so that serialisation
- * is achieved when multiple threads are involved:
+ * We need to allow suspend and resume at this point, else the
+ * control transfer will timeout if the device is suspended!
*/
- sx_xlock(&udev->ctrl_sx);
+ usbd_sr_unlock(udev);
hr_func = usbd_get_hr_func(udev);
@@ -714,10 +702,10 @@
USB_XFER_UNLOCK(xfer);
done:
- sx_xunlock(&udev->ctrl_sx);
+ usbd_sr_lock(udev);
- if (enum_locked)
- usbd_sr_lock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
if ((mtx != NULL) && (mtx != &Giant))
mtx_lock(mtx);
@@ -788,12 +776,6 @@
uint16_t status;
uint16_t change;
-#ifdef USB_DEBUG
- uint16_t pr_poll_delay;
- uint16_t pr_recovery_delay;
-
-#endif
-
DPRINTF("\n");
/* clear any leftover port reset changes first */
@@ -808,29 +790,12 @@
if (err)
goto done;
#ifdef USB_DEBUG
- /* range check input parameters */
- pr_poll_delay = usb_pr_poll_delay;
- if (pr_poll_delay < 1) {
- pr_poll_delay = 1;
- } else if (pr_poll_delay > 1000) {
- pr_poll_delay = 1000;
- }
- pr_recovery_delay = usb_pr_recovery_delay;
- if (pr_recovery_delay > 1000) {
- pr_recovery_delay = 1000;
- }
#endif
n = 0;
while (1) {
-#ifdef USB_DEBUG
/* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_poll_delay));
- n += pr_poll_delay;
-#else
- /* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(USB_PORT_RESET_DELAY));
- n += USB_PORT_RESET_DELAY;
-#endif
+ usb_pause_mtx(mtx, USB_MS_TO_TICKS(usb_port_reset_delay));
+ n += usb_port_reset_delay;
err = usbd_req_get_port_status(udev, mtx, &ps, port);
if (err)
goto done;
@@ -872,13 +837,8 @@
err = USB_ERR_TIMEOUT;
goto done;
}
-#ifdef USB_DEBUG
/* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_recovery_delay));
-#else
- /* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(USB_PORT_RESET_RECOVERY));
-#endif
+ usb_pause_mtx(mtx, USB_MS_TO_TICKS(usb_port_reset_recovery));
done:
DPRINTFN(2, "port %d reset returning error=%s\n",
@@ -909,12 +869,6 @@
uint16_t status;
uint16_t change;
-#ifdef USB_DEBUG
- uint16_t pr_poll_delay;
- uint16_t pr_recovery_delay;
-
-#endif
-
DPRINTF("\n");
err = usbd_req_get_port_status(udev, mtx, &ps, port);
@@ -944,30 +898,11 @@
if (err)
goto done;
-#ifdef USB_DEBUG
- /* range check input parameters */
- pr_poll_delay = usb_pr_poll_delay;
- if (pr_poll_delay < 1) {
- pr_poll_delay = 1;
- } else if (pr_poll_delay > 1000) {
- pr_poll_delay = 1000;
- }
- pr_recovery_delay = usb_pr_recovery_delay;
- if (pr_recovery_delay > 1000) {
- pr_recovery_delay = 1000;
- }
-#endif
n = 0;
while (1) {
-#ifdef USB_DEBUG
/* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_poll_delay));
- n += pr_poll_delay;
-#else
- /* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(USB_PORT_RESET_DELAY));
- n += USB_PORT_RESET_DELAY;
-#endif
+ usb_pause_mtx(mtx, USB_MS_TO_TICKS(usb_port_reset_delay));
+ n += usb_port_reset_delay;
err = usbd_req_get_port_status(udev, mtx, &ps, port);
if (err)
goto done;
@@ -1001,13 +936,8 @@
err = USB_ERR_TIMEOUT;
goto done;
}
-#ifdef USB_DEBUG
/* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_recovery_delay));
-#else
- /* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(USB_PORT_RESET_RECOVERY));
-#endif
+ usb_pause_mtx(mtx, USB_MS_TO_TICKS(usb_port_reset_recovery));
done:
DPRINTFN(2, "port %d warm reset returning error=%s\n",
@@ -1566,7 +1496,7 @@
done:
/* allow device time to set new address */
usb_pause_mtx(mtx,
- USB_MS_TO_TICKS(USB_SET_ADDRESS_SETTLE));
+ USB_MS_TO_TICKS(usb_set_address_settle));
return (err);
}
Modified: trunk/sys/dev/usb/usb_transfer.c
===================================================================
--- trunk/sys/dev/usb/usb_transfer.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_transfer.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -22,7 +22,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- */
+ */
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -810,21 +810,18 @@
const struct usb_config *setup_start, uint16_t n_setup,
void *priv_sc, struct mtx *xfer_mtx)
{
- struct usb_xfer dummy;
- struct usb_setup_params parm;
const struct usb_config *setup_end = setup_start + n_setup;
const struct usb_config *setup;
+ struct usb_setup_params *parm;
struct usb_endpoint *ep;
struct usb_xfer_root *info;
struct usb_xfer *xfer;
void *buf = NULL;
+ usb_error_t error = 0;
uint16_t n;
uint16_t refcount;
+ uint8_t do_unlock;
- parm.err = 0;
- refcount = 0;
- info = NULL;
-
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
"usbd_transfer_setup can sleep!");
@@ -842,31 +839,40 @@
DPRINTFN(6, "using global lock\n");
xfer_mtx = &Giant;
}
- /* sanity checks */
+
+ /* more sanity checks */
+
for (setup = setup_start, n = 0;
setup != setup_end; setup++, n++) {
if (setup->bufsize == (usb_frlength_t)-1) {
- parm.err = USB_ERR_BAD_BUFSIZE;
+ error = USB_ERR_BAD_BUFSIZE;
DPRINTF("invalid bufsize\n");
}
if (setup->callback == NULL) {
- parm.err = USB_ERR_NO_CALLBACK;
+ error = USB_ERR_NO_CALLBACK;
DPRINTF("no callback\n");
}
ppxfer[n] = NULL;
}
- if (parm.err) {
- goto done;
- }
- memset(&parm, 0, sizeof(parm));
+ if (error)
+ return (error);
- parm.udev = udev;
- parm.speed = usbd_get_speed(udev);
- parm.hc_max_packet_count = 1;
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
- if (parm.speed >= USB_SPEED_MAX) {
- parm.err = USB_ERR_INVAL;
+ refcount = 0;
+ info = NULL;
+
+ parm = &udev->scratch.xfer_setup[0].parm;
+ memset(parm, 0, sizeof(*parm));
+
+ parm->udev = udev;
+ parm->speed = usbd_get_speed(udev);
+ parm->hc_max_packet_count = 1;
+
+ if (parm->speed >= USB_SPEED_MAX) {
+ parm->err = USB_ERR_INVAL;
goto done;
}
/* setup all transfers */
@@ -881,14 +887,14 @@
info = USB_ADD_BYTES(buf, 0);
info->memory_base = buf;
- info->memory_size = parm.size[0];
+ info->memory_size = parm->size[0];
#if USB_HAVE_BUSDMA
- info->dma_page_cache_start = USB_ADD_BYTES(buf, parm.size[4]);
- info->dma_page_cache_end = USB_ADD_BYTES(buf, parm.size[5]);
+ info->dma_page_cache_start = USB_ADD_BYTES(buf, parm->size[4]);
+ info->dma_page_cache_end = USB_ADD_BYTES(buf, parm->size[5]);
#endif
- info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm.size[5]);
- info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm.size[2]);
+ info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm->size[5]);
+ info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm->size[2]);
cv_init(&info->cv_drain, "WDRAIN");
@@ -895,8 +901,8 @@
info->xfer_mtx = xfer_mtx;
#if USB_HAVE_BUSDMA
usb_dma_tag_setup(&info->dma_parent_tag,
- parm.dma_tag_p, udev->bus->dma_parent_tag[0].tag,
- xfer_mtx, &usb_bdma_done_event, 32, parm.dma_tag_max);
+ parm->dma_tag_p, udev->bus->dma_parent_tag[0].tag,
+ xfer_mtx, &usb_bdma_done_event, 32, parm->dma_tag_max);
#endif
info->bus = udev->bus;
@@ -931,9 +937,9 @@
}
/* reset sizes */
- parm.size[0] = 0;
- parm.buf = buf;
- parm.size[0] += sizeof(info[0]);
+ parm->size[0] = 0;
+ parm->buf = buf;
+ parm->size[0] += sizeof(info[0]);
for (setup = setup_start, n = 0;
setup != setup_end; setup++, n++) {
@@ -952,15 +958,15 @@
if ((setup->usb_mode != USB_MODE_DUAL) &&
(setup->usb_mode != udev->flags.usb_mode))
continue;
- parm.err = USB_ERR_NO_PIPE;
+ parm->err = USB_ERR_NO_PIPE;
goto done;
}
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store current setup pointer */
- parm.curr_setup = setup;
+ parm->curr_setup = setup;
if (buf) {
/*
@@ -967,7 +973,7 @@
* Common initialization of the
* "usb_xfer" structure.
*/
- xfer = USB_ADD_BYTES(buf, parm.size[0]);
+ xfer = USB_ADD_BYTES(buf, parm->size[0]);
xfer->address = udev->address;
xfer->priv_sc = priv_sc;
xfer->xroot = info;
@@ -982,8 +988,8 @@
* before we have allocated any
* memory:
*/
- xfer = &dummy;
- memset(&dummy, 0, sizeof(dummy));
+ xfer = &udev->scratch.xfer_setup[0].dummy;
+ memset(xfer, 0, sizeof(*xfer));
refcount++;
}
@@ -990,18 +996,18 @@
/* set transfer endpoint pointer */
xfer->endpoint = ep;
- parm.size[0] += sizeof(xfer[0]);
- parm.methods = xfer->endpoint->methods;
- parm.curr_xfer = xfer;
+ parm->size[0] += sizeof(xfer[0]);
+ parm->methods = xfer->endpoint->methods;
+ parm->curr_xfer = xfer;
/*
* Call the Host or Device controller transfer
* setup routine:
*/
- (udev->bus->methods->xfer_setup) (&parm);
+ (udev->bus->methods->xfer_setup) (parm);
/* check for error */
- if (parm.err)
+ if (parm->err)
goto done;
if (buf) {
@@ -1016,7 +1022,7 @@
*/
USB_BUS_LOCK(info->bus);
if (xfer->endpoint->refcount_alloc >= USB_EP_REF_MAX)
- parm.err = USB_ERR_INVAL;
+ parm->err = USB_ERR_INVAL;
xfer->endpoint->refcount_alloc++;
@@ -1039,22 +1045,22 @@
}
/* check for error */
- if (parm.err)
+ if (parm->err)
goto done;
}
- if (buf || parm.err) {
+ if (buf != NULL || parm->err != 0)
goto done;
- }
- if (refcount == 0) {
- /* no transfers - nothing to do ! */
+
+ /* if no transfers, nothing to do */
+ if (refcount == 0)
goto done;
- }
+
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store offset temporarily */
- parm.size[1] = parm.size[0];
+ parm->size[1] = parm->size[0];
/*
* The number of DMA tags required depends on
@@ -1062,72 +1068,72 @@
* for maximum number of DMA tags per endpoint
* is two.
*/
- parm.dma_tag_max += 2 * MIN(n_setup, USB_EP_MAX);
+ parm->dma_tag_max += 2 * MIN(n_setup, USB_EP_MAX);
/*
* DMA tags for QH, TD, Data and more.
*/
- parm.dma_tag_max += 8;
+ parm->dma_tag_max += 8;
- parm.dma_tag_p += parm.dma_tag_max;
+ parm->dma_tag_p += parm->dma_tag_max;
- parm.size[0] += ((uint8_t *)parm.dma_tag_p) -
+ parm->size[0] += ((uint8_t *)parm->dma_tag_p) -
((uint8_t *)0);
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store offset temporarily */
- parm.size[3] = parm.size[0];
+ parm->size[3] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.dma_page_ptr) -
+ parm->size[0] += ((uint8_t *)parm->dma_page_ptr) -
((uint8_t *)0);
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store offset temporarily */
- parm.size[4] = parm.size[0];
+ parm->size[4] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.dma_page_cache_ptr) -
+ parm->size[0] += ((uint8_t *)parm->dma_page_cache_ptr) -
((uint8_t *)0);
/* store end offset temporarily */
- parm.size[5] = parm.size[0];
+ parm->size[5] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.xfer_page_cache_ptr) -
+ parm->size[0] += ((uint8_t *)parm->xfer_page_cache_ptr) -
((uint8_t *)0);
/* store end offset temporarily */
- parm.size[2] = parm.size[0];
+ parm->size[2] = parm->size[0];
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
- parm.size[6] = parm.size[0];
+ parm->size[6] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.xfer_length_ptr) -
+ parm->size[0] += ((uint8_t *)parm->xfer_length_ptr) -
((uint8_t *)0);
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* allocate zeroed memory */
- buf = malloc(parm.size[0], M_USB, M_WAITOK | M_ZERO);
+ buf = malloc(parm->size[0], M_USB, M_WAITOK | M_ZERO);
if (buf == NULL) {
- parm.err = USB_ERR_NOMEM;
+ parm->err = USB_ERR_NOMEM;
DPRINTFN(0, "cannot allocate memory block for "
"configuration (%d bytes)\n",
- parm.size[0]);
+ parm->size[0]);
goto done;
}
- parm.dma_tag_p = USB_ADD_BYTES(buf, parm.size[1]);
- parm.dma_page_ptr = USB_ADD_BYTES(buf, parm.size[3]);
- parm.dma_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[4]);
- parm.xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[5]);
- parm.xfer_length_ptr = USB_ADD_BYTES(buf, parm.size[6]);
+ parm->dma_tag_p = USB_ADD_BYTES(buf, parm->size[1]);
+ parm->dma_page_ptr = USB_ADD_BYTES(buf, parm->size[3]);
+ parm->dma_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[4]);
+ parm->xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[5]);
+ parm->xfer_length_ptr = USB_ADD_BYTES(buf, parm->size[6]);
}
done:
@@ -1143,10 +1149,17 @@
usbd_transfer_unsetup_sub(info, 0);
}
}
- if (parm.err) {
+
+ /* check if any errors happened */
+ if (parm->err)
usbd_transfer_unsetup(ppxfer, n_setup);
- }
- return (parm.err);
+
+ error = parm->err;
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
+ return (error);
}
/*------------------------------------------------------------------------*
@@ -1923,6 +1936,17 @@
return (&xfer->frbuffers[frindex]);
}
+void *
+usbd_xfer_get_frame_buffer(struct usb_xfer *xfer, usb_frcount_t frindex)
+{
+ struct usb_page_search page_info;
+
+ KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
+
+ usbd_get_page(&xfer->frbuffers[frindex], 0, &page_info);
+ return (page_info.buffer);
+}
+
/*------------------------------------------------------------------------*
* usbd_xfer_get_fps_shift
*
Modified: trunk/sys/dev/usb/usb_util.c
===================================================================
--- trunk/sys/dev/usb/usb_util.c 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usb_util.c 2013-12-28 15:27:54 UTC (rev 6566)
@@ -71,6 +71,7 @@
struct usb_interface *iface;
char *temp_p;
usb_error_t err;
+ uint8_t do_unlock;
if (dev == NULL) {
/* should not happen */
@@ -92,19 +93,26 @@
err = 0;
}
- temp_p = (char *)udev->bus->scratch[0].data;
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
- if (!err) {
+ temp_p = (char *)udev->scratch.data;
+
+ if (err == 0) {
/* try to get the interface string ! */
- err = usbd_req_get_string_any
- (udev, NULL, temp_p,
- sizeof(udev->bus->scratch), iface->idesc->iInterface);
+ err = usbd_req_get_string_any(udev, NULL, temp_p,
+ sizeof(udev->scratch.data),
+ iface->idesc->iInterface);
}
- if (err) {
+ if (err != 0) {
/* use default description */
usb_devinfo(udev, temp_p,
- sizeof(udev->bus->scratch));
+ sizeof(udev->scratch.data));
}
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
device_set_desc_copy(dev, temp_p);
device_printf(dev, "<%s> on %s\n", temp_p,
device_get_nameunit(udev->bus->bdev));
Modified: trunk/sys/dev/usb/usbdi.h
===================================================================
--- trunk/sys/dev/usb/usbdi.h 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usbdi.h 2013-12-28 15:27:54 UTC (rev 6566)
@@ -522,6 +522,7 @@
int *aframes, int *nframes);
struct usb_page_cache *usbd_xfer_get_frame(struct usb_xfer *xfer,
usb_frcount_t frindex);
+void *usbd_xfer_get_frame_buffer(struct usb_xfer *, usb_frcount_t);
void *usbd_xfer_softc(struct usb_xfer *xfer);
void *usbd_xfer_get_priv(struct usb_xfer *xfer);
void usbd_xfer_set_priv(struct usb_xfer *xfer, void *);
Modified: trunk/sys/dev/usb/usbhid.h
===================================================================
--- trunk/sys/dev/usb/usbhid.h 2013-12-28 15:25:37 UTC (rev 6565)
+++ trunk/sys/dev/usb/usbhid.h 2013-12-28 15:27:54 UTC (rev 6566)
@@ -242,5 +242,7 @@
usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
void **descp, uint16_t *sizep, struct malloc_type *mem,
uint8_t iface_index);
+int hid_is_mouse(const void *d_ptr, uint16_t d_len);
+int hid_is_keyboard(const void *d_ptr, uint16_t d_len);
#endif /* _KERNEL */
#endif /* _USB_HID_H_ */
More information about the Midnightbsd-cvs
mailing list