diff --git a/drivers/bcmxcp_usb.c b/drivers/bcmxcp_usb.c index 0558ee568a..fc894f4890 100644 --- a/drivers/bcmxcp_usb.c +++ b/drivers/bcmxcp_usb.c @@ -11,7 +11,7 @@ #include #define SUBDRIVER_NAME "USB communication subdriver" -#define SUBDRIVER_VERSION "0.23" +#define SUBDRIVER_VERSION "0.26" /* communication driver description structure */ upsdrv_info_t comm_upsdrv_info = { @@ -358,6 +358,11 @@ void upsdrv_cleanup(void) { upslogx(LOG_ERR, "CLOSING\n"); nutusb_close(upsdev, "USB"); + free(curDevice.Vendor); + free(curDevice.Product); + free(curDevice.Serial); + free(curDevice.Bus); + free(curDevice.Device); } void upsdrv_reconnect(void) @@ -414,7 +419,11 @@ static usb_dev_handle *open_powerware_usb(void) curDevice.VendorID = dev_desc.idVendor; curDevice.ProductID = dev_desc.idProduct; bus = libusb_get_bus_number(device); - curDevice.Bus = (char *)xmalloc(4); + curDevice.Bus = (char *)malloc(4); + if (curDevice.Bus == NULL) { + libusb_free_device_list(devlist, 1); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } sprintf(curDevice.Bus, "%03d", bus); /* FIXME: we should also retrieve @@ -426,9 +435,11 @@ static usb_dev_handle *open_powerware_usb(void) if (is_usb_device_supported(pw_usb_device_table, &curDevice) == SUPPORTED) { libusb_open(device, &udev); + libusb_free_device_list(devlist, 1); return udev; } } + libusb_free_device_list(devlist, 1); #else /* not WITH_LIBUSB_1_0 */ struct usb_bus *busses = usb_get_busses(); struct usb_bus *bus; @@ -445,7 +456,7 @@ static usb_dev_handle *open_powerware_usb(void) curDevice.VendorID = dev->descriptor.idVendor; curDevice.ProductID = dev->descriptor.idProduct; - curDevice.Bus = strdup(bus->dirname); + curDevice.Bus = xstrdup(bus->dirname); /* FIXME: we should also retrieve * dev->descriptor.iManufacturer diff --git a/drivers/libhid.c b/drivers/libhid.c index fe434269ff..0002fb222d 100644 --- a/drivers/libhid.c +++ b/drivers/libhid.c @@ -681,7 +681,7 @@ int HIDGetEvents(hid_dev_handle_t udev, HIDData_t **event, int eventsize) buflen = comm_driver->get_interrupt( udev, (usb_ctrl_charbuf)buf, (usb_ctrl_charbufsize)r, - 250); + 750); if (buflen <= 0) { return buflen; /* propagate "error" or "no event" code */ diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 65cc5752dc..c7e9a4c025 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -34,7 +34,7 @@ #include "nut_libusb.h" #define USB_DRIVER_NAME "USB communication driver (libusb 0.1)" -#define USB_DRIVER_VERSION "0.34" +#define USB_DRIVER_VERSION "0.35" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { @@ -200,6 +200,8 @@ static int libusb_open(usb_dev_handle **udevp, for (bus = usb_busses; bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { + /* int if_claimed = 0; */ + upsdebugx(2, "Checking device (%04X/%04X) (%s/%s)", dev->descriptor.idVendor, dev->descriptor.idProduct, bus->dirname, dev->filename); @@ -232,15 +234,15 @@ static int libusb_open(usb_dev_handle **udevp, curDevice->VendorID = dev->descriptor.idVendor; curDevice->ProductID = dev->descriptor.idProduct; - curDevice->Bus = strdup(bus->dirname); - curDevice->Device = strdup(dev->filename); + curDevice->Bus = xstrdup(bus->dirname); + curDevice->Device = xstrdup(dev->filename); curDevice->bcdDevice = dev->descriptor.bcdDevice; if (dev->descriptor.iManufacturer) { ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, string, sizeof(string)); if (ret > 0) { - curDevice->Vendor = strdup(string); + curDevice->Vendor = xstrdup(string); } } @@ -248,7 +250,7 @@ static int libusb_open(usb_dev_handle **udevp, ret = usb_get_string_simple(udev, dev->descriptor.iProduct, string, sizeof(string)); if (ret > 0) { - curDevice->Product = strdup(string); + curDevice->Product = xstrdup(string); } } @@ -256,7 +258,7 @@ static int libusb_open(usb_dev_handle **udevp, ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, string, sizeof(string)); if (ret > 0) { - curDevice->Serial = strdup(string); + curDevice->Serial = xstrdup(string); } } @@ -339,6 +341,7 @@ static int libusb_open(usb_dev_handle **udevp, usb_strerror()); } #endif + /* if_claimed = 1; */ nut_usb_set_altinterface(udev); @@ -490,6 +493,11 @@ static int libusb_open(usb_dev_handle **udevp, return rdlen; next_device: + /* usb_release_interface() sometimes blocks + * and goes into uninterruptible sleep. + * So don't do it. */ + /* if (if_claimed) + usb_release_interface(udev, 0); */ usb_close(udev); } } diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 81fd7c9912..67408b9ac4 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -33,7 +33,7 @@ #include "nut_stdint.h" #define USB_DRIVER_NAME "USB communication driver (libusb 1.0)" -#define USB_DRIVER_VERSION "0.02" +#define USB_DRIVER_VERSION "0.9" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { @@ -53,6 +53,8 @@ static void nut_libusb_close(libusb_device_handle *udev); */ void nut_usb_addvars(void) { + const struct libusb_version *v = libusb_get_version(); + /* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */ addvar(VAR_VALUE, "vendor", "Regular expression to match UPS Manufacturer string"); addvar(VAR_VALUE, "product", "Regular expression to match UPS Product string"); @@ -66,9 +68,9 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "usb_set_altinterface", "Force redundant call to usb_set_altinterface() (value=bAlternateSetting; default=0)"); #ifdef LIBUSB_API_VERSION - dstate_setinfo("driver.version.usb", "libusb-1.0 (API: 0x%x)", LIBUSB_API_VERSION); + dstate_setinfo("driver.version.usb", "libusb-%u.%u.%u (API: 0x%x)", v->major, v->minor, v->micro, LIBUSB_API_VERSION); #else /* no LIBUSB_API_VERSION */ - dstate_setinfo("driver.version.usb", "libusb-1.0"); + dstate_setinfo("driver.version.usb", "libusb-%u.%u.%u", v->major, v->minor, v->micro); #endif /* LIBUSB_API_VERSION */ } @@ -106,18 +108,18 @@ static int nut_usb_set_altinterface(libusb_device_handle *udev) } } /* set default interface */ - upsdebugx(2, "%s: calling libusb_set_interface_alt_setting(udev, 0, %d)", - __func__, altinterface); - ret = libusb_set_interface_alt_setting(udev, 0, altinterface); + upsdebugx(2, "%s: calling libusb_set_interface_alt_setting(udev, %d, %d)", + __func__, usb_subdriver.hid_rep_index, altinterface); + ret = libusb_set_interface_alt_setting(udev, usb_subdriver.hid_rep_index, altinterface); if(ret != 0) { - upslogx(LOG_WARNING, "%s: libusb_set_interface_alt_setting(udev, 0, %d) returned %d (%s)", - __func__, altinterface, ret, libusb_strerror((enum libusb_error)ret) ); + upslogx(LOG_WARNING, "%s: libusb_set_interface_alt_setting(udev, %d, %d) returned %d (%s)", + __func__, usb_subdriver.hid_rep_index, altinterface, ret, libusb_strerror((enum libusb_error)ret) ); } upslogx(LOG_NOTICE, "%s: libusb_set_interface_alt_setting() should not be necessary - " "please email the nut-upsdev list with information about your UPS.", __func__); } else { - upsdebugx(3, "%s: skipped libusb_set_interface_alt_setting(udev, 0, 0)", - __func__); + upsdebugx(3, "%s: skipped libusb_set_interface_alt_setting(udev, %d, 0)", + __func__, usb_subdriver.hid_rep_index); } return ret; } @@ -143,6 +145,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, USBDeviceMatcher_t *m; libusb_device **devlist; ssize_t devcount = 0; + size_t devnum; struct libusb_device_descriptor dev_desc; struct libusb_config_descriptor *conf_desc = NULL; const struct libusb_interface_descriptor *if_desc; @@ -166,16 +169,22 @@ static int nut_libusb_open(libusb_device_handle **udevp, #ifndef __linux__ /* SUN_LIBUSB (confirmed to work on Solaris and FreeBSD) */ /* Causes a double free corruption in linux if device is detached! */ - nut_libusb_close(*udevp); + /* nut_libusb_close(*udevp); */ + if (*udevp) + libusb_close(*udevp); #endif devcount = libusb_get_device_list(NULL, &devlist); - for (i = 0; i < devcount; i++) { + /* devcount may be < 0, loop will get skipped; + * its SSIZE_MAX < SIZE_MAX for devnum */ + for (devnum = 0; (ssize_t)devnum < devcount; devnum++) { + /* int if_claimed = 0; */ + libusb_device *device = devlist[devnum]; - libusb_device *device = devlist[i]; libusb_get_device_descriptor(device, &dev_desc); - upsdebugx(2, "Checking device (%04X/%04X)", + upsdebugx(2, "Checking device %zu of %zu (%04X/%04X)", + devnum + 1, devcount, dev_desc.idVendor, dev_desc.idProduct); /* supported vendors are now checked by the supplied matcher */ @@ -205,7 +214,11 @@ static int nut_libusb_open(libusb_device_handle **udevp, memset(curDevice, '\0', sizeof(*curDevice)); bus = libusb_get_bus_number(device); - curDevice->Bus = (char *)xmalloc(4); + curDevice->Bus = (char *)malloc(4); + if (curDevice->Bus == NULL) { + libusb_free_device_list(devlist, 1); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } sprintf(curDevice->Bus, "%03d", bus); curDevice->VendorID = dev_desc.idVendor; curDevice->ProductID = dev_desc.idProduct; @@ -216,6 +229,10 @@ static int nut_libusb_open(libusb_device_handle **udevp, (unsigned char*)string, sizeof(string)); if (ret > 0) { curDevice->Vendor = strdup(string); + if (curDevice->Vendor == NULL) { + libusb_free_device_list(devlist, 1); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -224,6 +241,10 @@ static int nut_libusb_open(libusb_device_handle **udevp, (unsigned char*)string, sizeof(string)); if (ret > 0) { curDevice->Product = strdup(string); + if (curDevice->Product == NULL) { + libusb_free_device_list(devlist, 1); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -232,6 +253,10 @@ static int nut_libusb_open(libusb_device_handle **udevp, (unsigned char*)string, sizeof(string)); if (ret > 0) { curDevice->Serial = strdup(string); + if (curDevice->Serial == NULL) { + libusb_free_device_list(devlist, 1); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -256,6 +281,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "Device does not match - skipping"); goto next_device; } else if (ret==-1) { + libusb_free_device_list(devlist, 1); fatal_with_errno(EXIT_FAILURE, "matcher"); #ifndef HAVE___ATTRIBUTE__NORETURN # if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) @@ -286,33 +312,49 @@ static int nut_libusb_open(libusb_device_handle **udevp, /* Now we have matched the device we wanted. Claim it. */ -#ifdef HAVE_LIBUSB_SET_AUTO_DETACH_KERNEL_DRIVER - /* First, try the auto-detach kernel driver method - * This function is not available on FreeBSD 10.1-10.3 */ - if ((ret = libusb_set_auto_detach_kernel_driver (udev, 1)) < 0) - upsdebugx(2, "failed to auto detach kernel driver from USB device: %s", - libusb_strerror((enum libusb_error)ret)); - else - upsdebugx(2, "auto detached kernel driver from USB device"); +#if defined(HAVE_LIBUSB_KERNEL_DRIVER_ACTIVE) && defined(HAVE_LIBUSB_SET_AUTO_DETACH_KERNEL_DRIVER) + /* Due to the way FreeBSD implements libusb_set_auto_detach_kernel_driver(), + * check to see if the kernel driver is active before setting + * the auto-detach flag. Otherwise, libusb_claim_interface() + * with the auto-detach flag only works if the driver is + * running as root. + * + * Is the kernel driver active? Consider the unimplemented + * return code to be equivalent to inactive here. + */ + if((ret = libusb_kernel_driver_active(udev, usb_subdriver.hid_rep_index)) == 1) { + upsdebugx(3, "libusb_kernel_driver_active() returned 1 (driver active)"); + /* Try the auto-detach kernel driver method. + * This function is not available on FreeBSD 10.1-10.3 */ + if ((ret = libusb_set_auto_detach_kernel_driver (udev, 1)) != LIBUSB_SUCCESS) { + upsdebugx(1, "failed to set kernel driver auto-detach " + "driver flag for USB device: %s", + libusb_strerror((enum libusb_error)ret)); + } else { + upsdebugx(2, "successfully set kernel driver auto-detach flag"); + } + } else { + upsdebugx(3, "libusb_kernel_driver_active() returned %d", ret); + } #endif #if (defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER) || (defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP) /* Then, try the explicit detach method. * This function is available on FreeBSD 10.1-10.3 */ retries = 3; - while ((ret = libusb_claim_interface(udev, usb_subdriver.hid_rep_index)) < 0) { + while ((ret = libusb_claim_interface(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { upsdebugx(2, "failed to claim USB device: %s", libusb_strerror((enum libusb_error)ret)); # ifdef HAVE_LIBUSB_DETACH_KERNEL_DRIVER - if ((ret = libusb_detach_kernel_driver(udev, usb_subdriver.hid_rep_index)) < 0) { + if ((ret = libusb_detach_kernel_driver(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { # else /* if defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP) */ - if ((ret = libusb_detach_kernel_driver_np(udev, usb_subdriver.hid_rep_index)) < 0) { + if ((ret = libusb_detach_kernel_driver_np(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS) { # endif if (ret == LIBUSB_ERROR_NOT_FOUND) upsdebugx(2, "Kernel driver already detached"); else - upsdebugx(2, "failed to detach kernel driver from USB device: %s", + upsdebugx(1, "failed to detach kernel driver from USB device: %s", libusb_strerror((enum libusb_error)ret)); } else { upsdebugx(2, "detached kernel driver from USB device..."); @@ -322,6 +364,8 @@ static int nut_libusb_open(libusb_device_handle **udevp, continue; } + libusb_free_config_descriptor(conf_desc); + libusb_free_device_list(devlist, 1); fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]@%d/%d: %s", curDevice->VendorID, curDevice->ProductID, @@ -330,7 +374,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, libusb_strerror((enum libusb_error)ret)); } #else - if ((ret = libusb_claim_interface(udev, usb_subdriver.hid_rep_index)) < 0 ) { + if ((ret = libusb_claim_interface(udev, usb_subdriver.hid_rep_index)) != LIBUSB_SUCCESS ) { + libusb_free_config_descriptor(conf_desc); + libusb_free_device_list(devlist, 1); fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]@%d/%d: %s", curDevice->VendorID, curDevice->ProductID, @@ -339,11 +385,15 @@ static int nut_libusb_open(libusb_device_handle **udevp, libusb_strerror((enum libusb_error)ret)); } #endif - upsdebugx(2, "Claimed interface 0 successfully"); + /* if_claimed = 1; */ + upsdebugx(2, "Claimed interface %d successfully", + usb_subdriver.hid_rep_index); nut_usb_set_altinterface(udev); if (!callback) { + libusb_free_config_descriptor(conf_desc); + libusb_free_device_list(devlist, 1); return 1; } @@ -504,14 +554,20 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "Report descriptor retrieved (Reportlen = %d)", rdlen); upsdebugx(2, "Found HID device"); fflush(stdout); + libusb_free_device_list(devlist, 1); return rdlen; next_device: + /* usb_release_interface() sometimes blocks and goes + into uninterruptible sleep. So don't do it. */ + /* if (if_claimed) + libusb_release_interface(udev, usb_subdriver.hid_rep_index); */ libusb_close(udev); } *udevp = NULL; + libusb_free_device_list(devlist, 1); upsdebugx(2, "libusb1: No appropriate HID device found"); fflush(stdout); @@ -791,7 +847,7 @@ static void nut_libusb_close(libusb_device_handle *udev) /* usb_release_interface() sometimes blocks and goes * into uninterruptible sleep. So don't do it. */ - /* libusb_release_interface(udev, 0); */ + /* libusb_release_interface(udev, usb_subdriver.hid_rep_index); */ libusb_close(udev); libusb_exit(NULL); } diff --git a/drivers/nutdrv_atcl_usb.c b/drivers/nutdrv_atcl_usb.c index 3851cce8d2..a7da0cd56c 100644 --- a/drivers/nutdrv_atcl_usb.c +++ b/drivers/nutdrv_atcl_usb.c @@ -28,7 +28,7 @@ /* driver version */ #define DRIVER_NAME "'ATCL FOR UPS' USB driver" -#define DRIVER_VERSION "1.11" +#define DRIVER_VERSION "1.15" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -271,7 +271,9 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #ifndef __linux__ /* SUN_LIBUSB (confirmed to work on Solaris and FreeBSD) */ /* Causes a double free corruption in linux if device is detached! */ - usb_device_close(*handlep); + /* usb_device_close(*handlep); */ + if (*handlep) + usb_close(*handlep); #endif #if WITH_LIBUSB_1_0 @@ -338,7 +340,11 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev device->VendorID = dev_desc.idVendor; device->ProductID = dev_desc.idProduct; bus = libusb_get_bus_number(dev); - device->Bus = (char *)xmalloc(4); + device->Bus = (char *)malloc(4); + if (device->Bus == NULL) { + libusb_free_device_list(devlist, 1); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } sprintf(device->Bus, "%03d", bus); iManufacturer = dev_desc.iManufacturer; iProduct = dev_desc.iProduct; @@ -346,7 +352,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #else /* => WITH_LIBUSB_0_1 */ device->VendorID = dev->descriptor.idVendor; device->ProductID = dev->descriptor.idProduct; - device->Bus = strdup(bus->dirname); + device->Bus = xstrdup(bus->dirname); iManufacturer = dev->descriptor.iManufacturer; iProduct = dev->descriptor.iProduct; iSerialNumber = dev->descriptor.iSerialNumber; @@ -358,6 +364,12 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev (usb_ctrl_charbuf)buf, sizeof(buf)); if (ret > 0) { device->Vendor = strdup(buf); + if (device->Vendor == NULL) { +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -367,6 +379,12 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev (usb_ctrl_charbuf)buf, sizeof(buf)); if (ret > 0) { device->Product = strdup(buf); + if (device->Product == NULL) { +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -376,6 +394,12 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev (usb_ctrl_charbuf)buf, sizeof(buf)); if (ret > 0) { device->Serial = strdup(buf); + if (device->Serial == NULL) { +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -394,6 +418,9 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev upsdebugx(4, "Device does not match - skipping"); goto next_device; case -1: +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ fatal_with_errno(EXIT_FAILURE, "matcher"); #ifndef HAVE___ATTRIBUTE__NORETURN # if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) @@ -425,6 +452,9 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev ret = callback(handle, device); if (ret >= 0) { upsdebugx(3, "USB device [%04x:%04x] opened", device->VendorID, device->ProductID); +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ return ret; } @@ -462,6 +492,9 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #endif /* HAVE_USB_DETACH_KERNEL_DRIVER_NP or HAVE_LIBUSB_DETACH_KERNEL_DRIVER or HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP */ } +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ fatalx(EXIT_FAILURE, "USB device [%04x:%04x] matches, but driver callback failed: %s", device->VendorID, device->ProductID, @@ -475,6 +508,9 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } *handlep = NULL; +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ upsdebugx(3, "No matching USB device found"); return -1; diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index ba145a6cc0..e8a6e7b7ca 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -593,8 +593,8 @@ static int sgs_command(const char *cmd, char *buf, size_t buflen) (usb_ctrl_charbuf)tmp, 8, 1000); /* No error!!! */ - /* TODO: Macro code */ - if (ret == -110) + /* if (ret == -110) */ + if (ret == ERROR_TIMEOUT) break; /* Any errors here mean that we are unable to read a reply @@ -656,9 +656,9 @@ static int phoenix_command(const char *cmd, char *buf, size_t buflen) * data (e.g. it times out). */ switch (ret) { - case -EPIPE: /* Broken pipe */ + case ERROR_PIPE: /* Broken pipe */ usb_clear_halt(udev, 0x81); - case -ETIMEDOUT: /* Connection timed out */ + case ERROR_TIMEOUT: /* Connection timed out */ break; } @@ -754,7 +754,7 @@ static int ippon_command(const char *cmd, char *buf, size_t buflen) if (ret <= 0) { upsdebugx(3, "send: %s (%d)", - (ret != -ETIMEDOUT) ? nut_usb_strerror(ret) : "Connection timed out", + (ret != ERROR_TIMEOUT) ? nut_usb_strerror(ret) : "Connection timed out", ret); return ret; } @@ -773,7 +773,7 @@ static int ippon_command(const char *cmd, char *buf, size_t buflen) * to the UPS) */ if (ret <= 0) { upsdebugx(3, "read: %s (%d)", - (ret != -ETIMEDOUT) ? nut_usb_strerror(ret) : "Connection timed out", + (ret != ERROR_TIMEOUT) ? nut_usb_strerror(ret) : "Connection timed out", ret); return ret; } @@ -2897,7 +2897,7 @@ static ssize_t qx_command(const char *cmd, char *buf, size_t buflen) switch (ret) { - case -EBUSY: /* Device or resource busy */ + case ERROR_BUSY: /* Device or resource busy */ fatal_with_errno(EXIT_FAILURE, "Got disconnected by another driver"); #ifndef HAVE___ATTRIBUTE__NORETURN # if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) @@ -2910,6 +2910,7 @@ static ssize_t qx_command(const char *cmd, char *buf, size_t buflen) # endif #endif + #if WITH_LIBUSB_0_1 /* limit to libusb 0.1 implementation */ case -EPERM: /* Operation not permitted */ fatal_with_errno(EXIT_FAILURE, "Permissions problem"); #ifndef HAVE___ATTRIBUTE__NORETURN @@ -2922,35 +2923,38 @@ static ssize_t qx_command(const char *cmd, char *buf, size_t buflen) # pragma GCC diagnostic pop # endif #endif + #endif /* WITH_LIBUSB_0_1 */ - case -EPIPE: /* Broken pipe */ + case ERROR_PIPE: /* Broken pipe */ if (usb_clear_halt(udev, 0x81) == 0) { upsdebugx(1, "Stall condition cleared"); break; } -#ifdef ETIME +#if ETIME && WITH_LIBUSB_0_1 /* limit to libusb 0.1 implementation */ goto fallthrough_case_ETIME; case -ETIME: /* Timer expired */ fallthrough_case_ETIME: -#endif /* ETIME */ +#endif /* ETIME && WITH_LIBUSB_0_1 */ if (usb_reset(udev) == 0) { upsdebugx(1, "Device reset handled"); } goto fallthrough_case_reconnect; - case -ENODEV: /* No such device */ - case -EACCES: /* Permission denied */ - case -EIO: /* I/O error */ + case ERROR_NO_DEVICE: /* No such device */ + case ERROR_ACCESS: /* Permission denied */ + case ERROR_IO: /* I/O error */ +#if WITH_LIBUSB_0_1 /* limit to libusb 0.1 implementation */ case -ENXIO: /* No such device or address */ - case -ENOENT: /* No such file or directory */ +#endif /* WITH_LIBUSB_0_1 */ + case ERROR_NOT_FOUND: /* No such file or directory */ fallthrough_case_reconnect: /* Uh oh, got to reconnect! */ usb->close(udev); udev = NULL; break; - case -ETIMEDOUT: /* Connection timed out */ - case -EOVERFLOW: /* Value too large for defined data type */ -#ifdef EPROTO + case ERROR_TIMEOUT: /* Connection timed out */ + case ERROR_OVERFLOW: /* Value too large for defined data type */ +#if EPROTO && WITH_LIBUSB_0_1 /* limit to libusb 0.1 implementation */ case -EPROTO: /* Protocol error */ #endif default: diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index 6e2fee9cc8..99af7913b5 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -29,7 +29,7 @@ /* driver version */ #define DRIVER_NAME "Richcomm dry-contact to USB driver" -#define DRIVER_VERSION "0.05" +#define DRIVER_VERSION "0.09" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -318,7 +318,9 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #ifndef __linux__ /* SUN_LIBUSB (confirmed to work on Solaris and FreeBSD) */ /* Causes a double free corruption in linux if device is detached! */ - usb_device_close(*handlep); + /* usb_device_close(*handlep); */ + if (*handlep) + usb_close(*handlep); #endif #if WITH_LIBUSB_1_0 @@ -385,7 +387,11 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev device->VendorID = dev_desc.idVendor; device->ProductID = dev_desc.idProduct; bus = libusb_get_bus_number(dev); - device->Bus = (char *)xmalloc(4); + device->Bus = (char *)malloc(4); + if (device->Bus == NULL) { + libusb_free_device_list(devlist, 1); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } sprintf(device->Bus, "%03d", bus); iManufacturer = dev_desc.iManufacturer; iProduct = dev_desc.iProduct; @@ -393,7 +399,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #else /* => WITH_LIBUSB_0_1 */ device->VendorID = dev->descriptor.idVendor; device->ProductID = dev->descriptor.idProduct; - device->Bus = strdup(bus->dirname); + device->Bus = xstrdup(bus->dirname); iManufacturer = dev->descriptor.iManufacturer; iProduct = dev->descriptor.iProduct; iSerialNumber = dev->descriptor.iSerialNumber; @@ -405,6 +411,12 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev (usb_ctrl_charbuf)buf, sizeof(buf)); if (ret > 0) { device->Vendor = strdup(buf); + if (device->Vendor == NULL) { +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -414,6 +426,12 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev (usb_ctrl_charbuf)buf, sizeof(buf)); if (ret > 0) { device->Product = strdup(buf); + if (device->Product == NULL) { +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -423,6 +441,12 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev (usb_ctrl_charbuf)buf, sizeof(buf)); if (ret > 0) { device->Serial = strdup(buf); + if (device->Serial == NULL) { +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -441,6 +465,9 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev upsdebugx(4, "Device does not match - skipping"); goto next_device; case -1: +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ fatal_with_errno(EXIT_FAILURE, "matcher"); #ifndef HAVE___ATTRIBUTE__NORETURN # if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) @@ -460,7 +487,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #ifdef HAVE_LIBUSB_SET_AUTO_DETACH_KERNEL_DRIVER /* First, try the auto-detach kernel driver method * This function is not available on FreeBSD 10.1-10.3 */ - if ((ret = libusb_set_auto_detach_kernel_driver (udev, 1)) < 0) + if ((ret = libusb_set_auto_detach_kernel_driver(handle, 1)) < 0) upsdebugx(2, "failed to auto detach kernel driver from USB device: %s", nut_usb_strerror((enum libusb_error)ret)); @@ -474,6 +501,9 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev if (ret >= 0) { upsdebugx(4, "USB device [%04x:%04x] opened", device->VendorID, device->ProductID); +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ return ret; } #if WITH_LIBUSB_0_1 && (defined HAVE_USB_DETACH_KERNEL_DRIVER_NP) @@ -489,7 +519,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } #else # ifdef HAVE_LIBUSB_DETACH_KERNEL_DRIVER - if ((ret = libusb_detach_kernel_driver(udev, 0)) < 0) { + if ((ret = libusb_detach_kernel_driver(handle, 0)) < 0) { upsdebugx(4, "failed to detach kernel driver from USB device: %s", nut_usb_strerror(ret)); @@ -510,6 +540,9 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev #endif /* HAVE_USB_DETACH_KERNEL_DRIVER_NP or HAVE_LIBUSB_DETACH_KERNEL_DRIVER or HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP */ } +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ fatalx(EXIT_FAILURE, "USB device [%04x:%04x] matches, but driver callback failed: %s", device->VendorID, device->ProductID, nut_usb_strerror(ret)); @@ -522,6 +555,9 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } *handlep = NULL; +#if WITH_LIBUSB_1_0 + libusb_free_device_list(devlist, 1); +#endif /* WITH_LIBUSB_1_0 */ upsdebugx(4, "No matching USB device found"); return -1; diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 8d494dd8b4..28195da8af 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -34,7 +34,7 @@ #include "riello.h" #define DRIVER_NAME "Riello USB driver" -#define DRIVER_VERSION "0.04" +#define DRIVER_VERSION "0.05" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -168,6 +168,7 @@ static int Get_USB_Packet(uint8_t *buffer) char inBuf[10]; int err, ep; size_t size; + /*int errno;*/ /* note: this function stop until some byte(s) is not arrived */ size = 8; @@ -387,9 +388,9 @@ static int riello_command(uint8_t *cmd, uint8_t *buf, uint16_t length, uint16_t upsdebugx(1, "Device reset handled"); } goto fallthrough_case_reconnect; - case ERROR_NO_DEVICE: /* No such device */ - case ERROR_ACCESS: /* Permission denied */ - case ERROR_IO: /* I/O error */ + case ERROR_NO_DEVICE: /* No such device */ + case ERROR_ACCESS: /* Permission denied */ + case ERROR_IO: /* I/O error */ #if WITH_LIBUSB_0_1 /* limit to libusb 0.1 implementation */ case -ENXIO: /* No such device or address */ #endif diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 267ff3bd10..ab67664498 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -136,7 +136,7 @@ #include "usb-common.h" #define DRIVER_NAME "Tripp Lite OMNIVS / SMARTPRO driver" -#define DRIVER_VERSION "0.30" +#define DRIVER_VERSION "0.31" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -1638,4 +1638,9 @@ void upsdrv_cleanup(void) comm_driver->close(udev); USBFreeExactMatcher(reopen_matcher); USBFreeRegexMatcher(regex_matcher); + free(curDevice.Vendor); + free(curDevice.Product); + free(curDevice.Serial); + free(curDevice.Bus); + free(curDevice.Device); } diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index f8564b5d24..e96103ea55 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -568,6 +568,7 @@ int instcmd(const char *cmdname, const char *extradata) /* Retrieve and check netvar & item_path */ hidups_item = find_nut_info(cmdname); + upsdebugx(3, "%s: using Path '%s'", __func__, hidups_item->hidpath); /* Check for fallback if not found */ if (hidups_item == NULL) { diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 3f760081e3..557bbd0917 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -51,6 +51,7 @@ static int (*nut_usb_get_string_simple)(libusb_device_handle *dev, int index, static void (*nut_usb_exit)(libusb_context *ctx); static char * (*nut_usb_strerror)(enum libusb_error errcode); static ssize_t (*nut_usb_get_device_list)(libusb_context *ctx, libusb_device ***list); + static void (*nut_usb_free_device_list)(libusb_device **list, int unref_devices); static uint8_t (*nut_usb_get_bus_number)(libusb_device *dev); static int (*nut_usb_get_device_descriptor)(libusb_device *dev, struct libusb_device_descriptor *desc); @@ -128,6 +129,11 @@ int nutscan_load_usb_library(const char *libname_path) goto err; } + *(void **) (&nut_usb_free_device_list) = lt_dlsym(dl_handle, "libusb_free_device_list"); + if ((dl_error = lt_dlerror()) != NULL) { + goto err; + } + *(void **) (&nut_usb_get_bus_number) = lt_dlsym(dl_handle, "libusb_get_bus_number"); if ((dl_error = lt_dlerror()) != NULL) { goto err; @@ -137,6 +143,12 @@ int nutscan_load_usb_library(const char *libname_path) if ((dl_error = lt_dlerror()) != NULL) { goto err; } + + *(void **) (&nut_usb_get_string_simple) = lt_dlsym(dl_handle, + "libusb_get_string_descriptor_ascii"); + if ((dl_error = lt_dlerror()) != NULL) { + goto err; + } #else /* for libusb 0.1 */ *(void **) (&nut_usb_find_busses) = lt_dlsym(dl_handle, "usb_find_busses"); if ((dl_error = lt_dlerror()) != NULL) { @@ -152,13 +164,13 @@ int nutscan_load_usb_library(const char *libname_path) if ((dl_error = lt_dlerror()) != NULL) { goto err; } -#endif /* WITH_LIBUSB_1_0 */ *(void **) (&nut_usb_get_string_simple) = lt_dlsym(dl_handle, "usb_get_string_simple"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } +#endif /* WITH_LIBUSB_1_0 */ return 1; @@ -203,7 +215,7 @@ nutscan_device_t * nutscan_scan_usb() libusb_device *dev; libusb_device **devlist; uint8_t bus; -#else +#else /* => WITH_LIBUSB_0_1 */ struct usb_device *dev; struct usb_bus *bus; #endif /* WITH_LIBUSB_1_0 */ @@ -223,7 +235,7 @@ nutscan_device_t * nutscan_scan_usb() (*nut_usb_exit)(NULL); fatal_with_errno(EXIT_FAILURE, "Failed to init libusb 1.0"); } -#else +#else /* => WITH_LIBUSB_0_1 */ (*nut_usb_init)(); (*nut_usb_find_busses)(); (*nut_usb_find_devices)(); @@ -235,8 +247,10 @@ nutscan_device_t * nutscan_scan_usb() int i; devcount = (*nut_usb_get_device_list)(NULL, &devlist); - if (devcount <= 0) + if (devcount <= 0) { + (*nut_usb_exit)(NULL); fatal_with_errno(EXIT_FAILURE, "No USB device found"); + } for (i = 0; i < devcount; i++) { @@ -250,9 +264,14 @@ nutscan_device_t * nutscan_scan_usb() iProduct = dev_desc.iProduct; iSerialNumber = dev_desc.iSerialNumber; bus = (*nut_usb_get_bus_number)(dev); - busname = (char *)xmalloc(4); + busname = (char *)malloc(4); + if (busname == NULL) { + (*nut_usb_free_device_list)(devlist, 1); + (*nut_usb_exit)(NULL); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } snprintf(busname, 4, "%03d", bus); -#else +#else /* => WITH_LIBUSB_0_1 */ for (bus = (*nut_usb_busses); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { @@ -277,7 +296,7 @@ nutscan_device_t * nutscan_scan_usb() (*nut_usb_strerror)(ret)); continue; } -#else +#else /* => WITH_LIBUSB_0_1 */ udev = (*nut_usb_open)(dev); if (!udev) { fprintf(stderr, "Failed to open device, \ @@ -293,6 +312,15 @@ nutscan_device_t * nutscan_scan_usb() iSerialNumber, string, sizeof(string)); if (ret > 0) { serialnumber = strdup(str_rtrim(string, ' ')); + if (serialnumber == NULL) { + (*nut_usb_close)(udev); +#if WITH_LIBUSB_1_0 + free(busname); + (*nut_usb_free_device_list)(devlist, 1); + (*nut_usb_exit)(NULL); +#endif /* WITH_LIBUSB_1_0 */ + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -302,6 +330,16 @@ nutscan_device_t * nutscan_scan_usb() iProduct, string, sizeof(string)); if (ret > 0) { device_name = strdup(str_rtrim(string, ' ')); + if (device_name == NULL) { + free(serialnumber); + (*nut_usb_close)(udev); +#if WITH_LIBUSB_1_0 + free(busname); + (*nut_usb_free_device_list)(devlist, 1); + (*nut_usb_exit)(NULL); +#endif /* WITH_LIBUSB_1_0 */ + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -311,6 +349,17 @@ nutscan_device_t * nutscan_scan_usb() iManufacturer, string, sizeof(string)); if (ret > 0) { vendor_name = strdup(str_rtrim(string, ' ')); + if (vendor_name == NULL) { + free(serialnumber); + free(device_name); + (*nut_usb_close)(udev); +#if WITH_LIBUSB_1_0 + free(busname); + (*nut_usb_free_device_list)(devlist, 1); + (*nut_usb_exit)(NULL); +#endif /* WITH_LIBUSB_1_0 */ + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } } } @@ -322,6 +371,12 @@ nutscan_device_t * nutscan_scan_usb() free(serialnumber); free(device_name); free(vendor_name); + (*nut_usb_close)(udev); +#if WITH_LIBUSB_1_0 + free(busname); + (*nut_usb_free_device_list)(devlist, 1); + (*nut_usb_exit)(NULL); +#endif /* WITH_LIBUSB_1_0 */ return NULL; } @@ -379,12 +434,14 @@ nutscan_device_t * nutscan_scan_usb() } #if WITH_LIBUSB_0_1 } -#endif + } +#else /* not WITH_LIBUSB_0_1 */ + free(busname); } -#if WITH_LIBUSB_1_0 + (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); -#endif +#endif /* WITH_LIBUSB_0_1 */ return nutscan_rewind_device(current_nut_dev); }