summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libusb20/libusb20_compat01.c75
-rw-r--r--lib/libusb20/libusb20_ugen20.c41
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);
}
OpenPOWER on IntegriCloud