diff options
Diffstat (limited to 'sys/dev/usb/usb_device.c')
-rw-r--r-- | sys/dev/usb/usb_device.c | 85 |
1 files changed, 40 insertions, 45 deletions
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index a9aab53..fdc734c 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -460,13 +460,8 @@ usb_unconfigure(struct usb_device *udev, uint8_t flag) { 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); @@ -529,13 +524,8 @@ usbd_set_config_index(struct usb_device *udev, uint8_t index) 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); @@ -888,13 +878,9 @@ usbd_set_alt_interface_index(struct usb_device *udev, 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; @@ -931,7 +917,6 @@ usbd_set_alt_interface_index(struct usb_device *udev, done: if (do_unlock) usbd_enum_unlock(udev); - return (err); } @@ -1310,13 +1295,8 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index) 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 */ @@ -1403,7 +1383,6 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index) done: if (do_unlock) usbd_enum_unlock(udev); - return (0); } @@ -1532,6 +1511,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, 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", @@ -1750,7 +1730,11 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, * 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 || @@ -1775,7 +1759,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, mask = usb_lang_mask; /* align length correctly */ - scratch_ptr[0] &= ~1; + scratch_ptr[0] &= ~1U; /* fix compiler warning */ langid = 0; @@ -1796,6 +1780,9 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, 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 */ @@ -2295,9 +2282,13 @@ usbd_set_device_strings(struct usb_device *udev) 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); @@ -2352,6 +2343,9 @@ usbd_set_device_strings(struct usb_device *udev) snprintf(temp_ptr, temp_size, "product 0x%04x", product_id); udev->product = strdup(temp_ptr, M_USB); } + + if (do_unlock) + usbd_enum_unlock(udev); } /* @@ -2664,11 +2658,17 @@ usbd_device_attached(struct usb_device *udev) 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); /* @@ -2677,6 +2677,7 @@ usbd_enum_lock(struct usb_device *udev) * locked multiple times. */ mtx_lock(&Giant); + return (1); } /* The following function unlocks enumerating the given USB device. */ @@ -2783,13 +2784,8 @@ usbd_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep, usb_error_t error; 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 (udev->bus->methods->set_endpoint_mode != NULL) { error = (udev->bus->methods->set_endpoint_mode) ( @@ -2805,7 +2801,6 @@ usbd_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep, if (do_unlock) usbd_enum_unlock(udev); - return (error); } |