Hello, with pain I found out that libusb_exit() must be called in ftdi_deinit(), as ftdi_free() can't be run on a static struct ftdi_context. So find appended a corrected patch, or more exact two patches, the first doing the libusb_exit() and the second libusb_free_device_list() (fixing one more path than the original).
It's hard to get things right the first time -- Uwe Bonnes [email protected] Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt --------- Tel. 06151 162516 -------- Fax. 06151 164321 ---------- >From 2b6e88b88dee09e43f2e20815be494d31a876353 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes <[email protected]> Date: Mon, 7 Jun 2010 20:41:03 +0200 Subject: libusb_init() needs libusb_exit() to avoid leak --- src/ftdi.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/src/ftdi.c b/src/ftdi.c index 7b4b987..69e5068 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -185,6 +185,7 @@ void ftdi_deinit(struct ftdi_context *ftdi) free(ftdi->readbuffer); ftdi->readbuffer = NULL; } + libusb_exit(NULL); } /** -- 1.6.4.2 >From 2863d71e145d07db58cfb67e1cdc3579344e8c44 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes <[email protected]> Date: Mon, 7 Jun 2010 20:44:40 +0200 Subject: libbusb_get_device_list() needs libusb_free_device_list() to avoid leaks --- src/ftdi.c | 41 +++++++++++++++++++++++++++-------------- 1 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/ftdi.c b/src/ftdi.c index 69e5068..cde1c76 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -41,6 +41,12 @@ return code; \ } while(0); +#define ftdi_error_return_free_device_list(code, str, devs) do { \ + libusb_free_device_list(devs,1); \ + ftdi->error_str = str; \ + return code; \ + } while(0); + /** Internal function to close usb device pointer. @@ -251,13 +257,13 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devli struct libusb_device_descriptor desc; if (libusb_get_device_descriptor(dev, &desc) < 0) - ftdi_error_return(-6, "libusb_get_device_descriptor() failed"); + ftdi_error_return_free_device_list(-6, "libusb_get_device_descriptor() failed", devs); if (desc.idVendor == vendor && desc.idProduct == product) { *curdev = (struct ftdi_device_list*)malloc(sizeof(struct ftdi_device_list)); if (!*curdev) - ftdi_error_return(-3, "out of memory"); + ftdi_error_return_free_device_list(-3, "out of memory", devs); (*curdev)->next = NULL; (*curdev)->dev = dev; @@ -266,7 +272,7 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devli count++; } } - + libusb_free_device_list(devs,1); return count; } @@ -626,30 +632,31 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product, if (libusb_init(NULL) < 0) ftdi_error_return(-11, "libusb_init() failed"); - if (libusb_get_device_list(NULL, &devs) < 0) - ftdi_error_return(-12, "libusb_get_device_list() failed"); - if (ftdi == NULL) ftdi_error_return(-11, "ftdi context invalid"); + if (libusb_get_device_list(NULL, &devs) < 0) + ftdi_error_return(-12, "libusb_get_device_list() failed"); + while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; + int res; if (libusb_get_device_descriptor(dev, &desc) < 0) - ftdi_error_return(-13, "libusb_get_device_descriptor() failed"); + ftdi_error_return_free_device_list(-13, "libusb_get_device_descriptor() failed", devs); if (desc.idVendor == vendor && desc.idProduct == product) { if (libusb_open(dev, &ftdi->usb_dev) < 0) - ftdi_error_return(-4, "usb_open() failed"); + ftdi_error_return_free_device_list(-4, "usb_open() failed", devs); if (description != NULL) { if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, desc.iProduct, (unsigned char *)string, sizeof(string)) < 0) { libusb_close (ftdi->usb_dev); - ftdi_error_return(-8, "unable to fetch product description"); + ftdi_error_return_free_device_list(-8, "unable to fetch product description", devs); } if (strncmp(string, description, sizeof(string)) != 0) { @@ -662,7 +669,7 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product, if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, desc.iSerialNumber, (unsigned char *)string, sizeof(string)) < 0) { ftdi_usb_close_internal (ftdi); - ftdi_error_return(-9, "unable to fetch serial number"); + ftdi_error_return_free_device_list(-9, "unable to fetch serial number", devs); } if (strncmp(string, serial, sizeof(string)) != 0) { @@ -679,12 +686,14 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product, continue; } - return ftdi_usb_open_dev(ftdi, dev); + res = ftdi_usb_open_dev(ftdi, dev); + libusb_free_device_list(devs, 1); + return res; } } // device not found - ftdi_error_return(-3, "device not found"); + ftdi_error_return_free_device_list(-3, "device not found", devs); } /** @@ -743,11 +752,15 @@ int ftdi_usb_open_string(struct ftdi_context *ftdi, const char* description) { if (bus_number == libusb_get_bus_number (dev) && device_address == libusb_get_device_address (dev)) - return ftdi_usb_open_dev(ftdi, dev); + { + int res = ftdi_usb_open_dev(ftdi, dev); + libusb_free_device_list(devs, 1); + return res; + } } // device not found - ftdi_error_return(-3, "device not found"); + ftdi_error_return_free_device_list(-3, "device not found", devs); } else if (description[0] == 'i' || description[0] == 's') { -- 1.6.4.2 -- libftdi - see http://www.intra2net.com/en/developer/libftdi for details. To unsubscribe send a mail to [email protected]
