struct usbi_hotplug_callback *hotplug_cb, *next_cb;
struct usbi_hotplug_message *msg;
struct libusb_device *dev, *next_dev;
- int devices_released;
/* check for hotplug support */
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG))
}
/* free all discovered devices. due to parent references loop until no devices are freed. */
- do {
- devices_released = 0;
- for_each_device_safe(ctx, dev, next_dev) {
- /* remove the device from the usb_devs list only if there are no
- * references held, otherwise leave it on the list so that a
- * warning message will be shown */
- if (usbi_atomic_load(&dev->refcnt) == 1) {
- ++devices_released;
- list_del(&dev->list);
- }
- libusb_unref_device(dev);
+ for_each_device_safe(ctx, dev, next_dev) {
+ /* remove the device from the usb_devs list only if there are no
+ * references held, otherwise leave it on the list so that a
+ * warning message will be shown */
+ if (usbi_atomic_load(&dev->refcnt) == 1) {
+ list_del(&dev->list);
+ }
+ if (dev->parent_dev && usbi_atomic_load(&dev->parent_dev->refcnt) == 1) {
+ /* the parent was before this device in the list and will be released.
+ remove it from the list. this is safe as parent_dev can not be
+ equal to next_dev. */
+ assert (dev->parent_dev != next_dev);
+ list_del(&dev->parent_dev->list);
}
- } while (devices_released > 0);
+ libusb_unref_device(dev);
+ }
usbi_mutex_destroy(&ctx->hotplug_cbs_lock);
}