diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libusb20/libusb20_compat01.c | 75 | ||||
-rw-r--r-- | lib/libusb20/libusb20_ugen20.c | 41 |
2 files changed, 70 insertions, 46 deletions
diff --git a/lib/libusb20/libusb20_compat01.c b/lib/libusb20/libusb20_compat01.c index b63c5e9..3700c7f 100644 --- a/lib/libusb20/libusb20_compat01.c +++ b/lib/libusb20/libusb20_compat01.c @@ -177,19 +177,42 @@ usb_open(struct usb_device *dev) if (err) return (NULL); + /* + * Dequeue USB device from backend queue so that it does not get + * freed when the backend is re-scanned: + */ + libusb20_be_dequeue_device(usb_backend, dev->dev); + return (dev->dev); } int -usb_close(usb_dev_handle * dev) +usb_close(usb_dev_handle * udev) { + struct usb_device *dev; int err; - err = libusb20_dev_close((void *)dev); + err = libusb20_dev_close((void *)udev); if (err) return (-1); + if (usb_backend != NULL) { + /* + * Enqueue USB device to backend queue so that it gets freed + * when the backend is re-scanned: + */ + libusb20_be_enqueue_device(usb_backend, (void *)udev); + } else { + /* + * The backend is gone. Free device data so that we + * don't start leaking memory! + */ + dev = usb_device(udev); + libusb20_dev_free((void *)udev); + LIST_DEL(usb_global_bus.devices, dev); + free(dev); + } return (0); } @@ -697,7 +720,8 @@ usb_set_configuration(usb_dev_handle * udev, int bConfigurationValue) /* "bConfigurationValue" not found */ return (-1); } - if ((dev->config + i)->bConfigurationValue == bConfigurationValue) { + if ((dev->config + i)->bConfigurationValue == + bConfigurationValue) { break; } } @@ -821,36 +845,28 @@ usb_find_devices(void) struct libusb20_device *pdev; struct usb_device *udev; struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; - struct libusb20_backend *pold; int err; /* cleanup after last device search */ - - pold = usb_backend; - - pdev = NULL; - while ((pdev = libusb20_be_device_foreach(pold, pdev))) { - if (!pdev->is_opened) { - /* - * if the device has not been opened we free the - * device data - */ - udev = pdev->priv01Data; - libusb20_be_dequeue_device(pold, pdev); - libusb20_dev_free(pdev); - if (udev != NULL) { - LIST_DEL(usb_global_bus.devices, udev); - free(udev); - } - pdev = NULL; /* restart search */ + /* close all opened devices, if any */ + + while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { + udev = pdev->priv01Data; + libusb20_be_dequeue_device(usb_backend, pdev); + libusb20_dev_free(pdev); + if (udev != NULL) { + LIST_DEL(usb_global_bus.devices, udev); + free(udev); } } - /* do a new backend device search */ + /* free old USB backend, if any */ + + libusb20_be_free(usb_backend); + /* do a new backend device search */ usb_backend = libusb20_be_alloc_default(); if (usb_backend == NULL) { - usb_backend = pold; /* restore */ return (-1); } /* iterate all devices */ @@ -904,17 +920,6 @@ usb_find_devices(void) LIST_ADD(usb_global_bus.devices, udev); } - /* move old devices over to the new USB backend */ - - while ((pdev = libusb20_be_device_foreach(pold, pdev))) { - libusb20_be_dequeue_device(pold, pdev); - libusb20_be_enqueue_device(usb_backend, pdev); - } - - /* free old backend, if any */ - - libusb20_be_free(pold); - return (0); /* success */ } diff --git a/lib/libusb20/libusb20_ugen20.c b/lib/libusb20/libusb20_ugen20.c index 0ef5562..3646a59 100644 --- a/lib/libusb20/libusb20_ugen20.c +++ b/lib/libusb20/libusb20_ugen20.c @@ -307,10 +307,27 @@ ugen20_init_backend(struct libusb20_backend *pbe) return (0); /* success */ } +static void +ugen20_tr_release(struct libusb20_device *pdev) +{ + struct usb2_fs_uninit fs_uninit; + + if (pdev->nTransfer == 0) { + return; + } + /* release all pending USB transfers */ + if (pdev->privBeData != NULL) { + memset(&fs_uninit, 0, sizeof(fs_uninit)); + if (ioctl(pdev->file, USB_FS_UNINIT, &fs_uninit)) { + /* ignore any errors of this kind */ + } + } + return; +} + static int ugen20_tr_renew(struct libusb20_device *pdev) { - struct usb2_fs_uninit fs_uninit; struct usb2_fs_init fs_init; struct usb2_fs_endpoint *pfse; int error; @@ -325,12 +342,7 @@ ugen20_tr_renew(struct libusb20_device *pdev) } size = nMaxTransfer * sizeof(*pfse); - if (pdev->privBeData != NULL) { - memset(&fs_uninit, 0, sizeof(fs_uninit)); - if (ioctl(pdev->file, USB_FS_UNINIT, &fs_uninit)) { - /* ignore any errors of this kind */ - } - } else { + if (pdev->privBeData == NULL) { pfse = malloc(size); if (pfse == NULL) { error = LIBUSB20_ERROR_NO_MEM; @@ -338,7 +350,6 @@ ugen20_tr_renew(struct libusb20_device *pdev) } pdev->privBeData = pfse; } - /* reset endpoint data */ memset(pdev->privBeData, 0, size); @@ -421,12 +432,11 @@ static int ugen20_close_device(struct libusb20_device *pdev) { struct usb2_fs_uninit fs_uninit; - int error = 0; if (pdev->privBeData) { memset(&fs_uninit, 0, sizeof(fs_uninit)); if (ioctl(pdev->file, USB_FS_UNINIT, &fs_uninit)) { - error = LIBUSB20_ERROR_OTHER; + /* ignore this error */ } free(pdev->privBeData); } @@ -436,7 +446,7 @@ ugen20_close_device(struct libusb20_device *pdev) close(pdev->file_ctrl); pdev->file = -1; pdev->file_ctrl = -1; - return (error); + return (0); /* success */ } static void @@ -509,6 +519,9 @@ ugen20_set_config_index(struct libusb20_device *pdev, uint8_t cfg_index) { int temp = cfg_index; + /* release all active USB transfers */ + ugen20_tr_release(pdev); + if (ioctl(pdev->file_ctrl, USB_SET_CONFIG, &temp)) { return (LIBUSB20_ERROR_OTHER); } @@ -548,6 +561,9 @@ ugen20_set_alt_index(struct libusb20_device *pdev, alt_iface.uai_interface_index = iface_index; alt_iface.uai_alt_index = alt_index; + /* release all active USB transfers */ + ugen20_tr_release(pdev); + if (ioctl(pdev->file_ctrl, USB_SET_ALTINTERFACE, &alt_iface)) { return (LIBUSB20_ERROR_OTHER); } @@ -559,6 +575,9 @@ ugen20_reset_device(struct libusb20_device *pdev) { int temp = 0; + /* release all active USB transfers */ + ugen20_tr_release(pdev); + if (ioctl(pdev->file_ctrl, USB_DEVICEENUMERATE, &temp)) { return (LIBUSB20_ERROR_OTHER); } |