diff --git a/drivers/libhid.h b/drivers/libhid.h index d422002b6a..23e34a1389 100644 --- a/drivers/libhid.h +++ b/drivers/libhid.h @@ -42,12 +42,14 @@ typedef char HIDDeviceMatcher_t; typedef usb_dev_handle hid_dev_handle_t; typedef shut_communication_subdriver_t communication_subdriver_t; + #define HID_DEV_HANDLE_CLOSED (hid_dev_handle_t)(-1) #else #include "nut_libusb.h" /* includes usb-common.h */ typedef USBDevice_t HIDDevice_t; typedef USBDeviceMatcher_t HIDDeviceMatcher_t; typedef usb_dev_handle * hid_dev_handle_t; typedef usb_communication_subdriver_t communication_subdriver_t; + #define HID_DEV_HANDLE_CLOSED (hid_dev_handle_t)(NULL) #endif /* use explicit booleans */ diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 4723f3a1e3..de22c48d89 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.42" +#define USB_DRIVER_VERSION "0.43" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { @@ -46,6 +46,7 @@ upsdrv_info_t comm_upsdrv_info = { }; #define MAX_REPORT_SIZE 0x1800 +#define MAX_RETRY 3 static void libusb_close(usb_dev_handle *udev); @@ -166,9 +167,7 @@ static int libusb_open(usb_dev_handle **udevp, USBDevice_t *hd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen) ) { -#ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP int retries; -#endif usb_ctrl_charbufsize rdlen1, rdlen2; /* report descriptor length, method 1+2 */ USBDeviceMatcher_t *m; struct usb_device *dev; @@ -239,26 +238,44 @@ static int libusb_open(usb_dev_handle **udevp, 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 = xstrdup(string); + retries = MAX_RETRY; + while (retries > 0) { + ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, + string, sizeof(string)); + if (ret > 0) { + curDevice->Vendor = xstrdup(string); + break; + } + retries--; + upsdebugx(1, "%s get iManufacturer failed, retrying...", __func__); } } if (dev->descriptor.iProduct) { - ret = usb_get_string_simple(udev, dev->descriptor.iProduct, - string, sizeof(string)); - if (ret > 0) { - curDevice->Product = xstrdup(string); + retries = MAX_RETRY; + while (retries > 0) { + ret = usb_get_string_simple(udev, dev->descriptor.iProduct, + string, sizeof(string)); + if (ret > 0) { + curDevice->Product = xstrdup(string); + break; + } + retries--; + upsdebugx(1, "%s get iProduct failed, retrying...", __func__); } } if (dev->descriptor.iSerialNumber) { - ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, - string, sizeof(string)); - if (ret > 0) { - curDevice->Serial = xstrdup(string); + retries = MAX_RETRY; + while (retries > 0) { + ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, + string, sizeof(string)); + if (ret > 0) { + curDevice->Serial = xstrdup(string); + break; + } + retries--; + upsdebugx(1, "%s get iSerialNumber failed, retrying...", __func__); } } @@ -307,7 +324,7 @@ static int libusb_open(usb_dev_handle **udevp, /* this method requires at least libusb 0.1.8: * it force device claiming by unbinding * attached driver... From libhid */ - retries = 3; + retries = MAX_RETRY; while (usb_claim_interface(udev, usb_subdriver.hid_rep_index) < 0) { upsdebugx(2, "failed to claim USB device: %s", diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 44d8dc96d5..d9dc2d67e4 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.42" +#define USB_DRIVER_VERSION "0.43" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { @@ -45,6 +45,7 @@ upsdrv_info_t comm_upsdrv_info = { }; #define MAX_REPORT_SIZE 0x1800 +#define MAX_RETRY 3 static void nut_libusb_close(libusb_device_handle *udev); @@ -138,9 +139,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, USBDevice_t *hd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen) ) { -#if (defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER) || (defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP) int retries; -#endif /* libusb-1.0 usb_ctrl_charbufsize is uint16_t and we * want the rdlen vars signed - so taking a wider type */ int32_t rdlen1, rdlen2; /* report descriptor length, method 1+2 */ @@ -227,38 +226,56 @@ static int nut_libusb_open(libusb_device_handle **udevp, curDevice->bcdDevice = dev_desc.bcdDevice; if (dev_desc.iManufacturer) { - ret = libusb_get_string_descriptor_ascii(udev, dev_desc.iManufacturer, - (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"); + retries = MAX_RETRY; + while (retries > 0) { + ret = libusb_get_string_descriptor_ascii(udev, dev_desc.iManufacturer, + (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"); + } + break; } + retries--; + upsdebugx(1, "%s get iManufacturer failed, retrying...", __func__); } } if (dev_desc.iProduct) { - ret = libusb_get_string_descriptor_ascii(udev, dev_desc.iProduct, - (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"); + retries = MAX_RETRY; + while (retries > 0) { + ret = libusb_get_string_descriptor_ascii(udev, dev_desc.iProduct, + (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"); + } + break; } + retries--; + upsdebugx(1, "%s get iProduct failed, retrying...", __func__); } } if (dev_desc.iSerialNumber) { - ret = libusb_get_string_descriptor_ascii(udev, dev_desc.iSerialNumber, - (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"); + retries = MAX_RETRY; + while (retries > 0) { + ret = libusb_get_string_descriptor_ascii(udev, dev_desc.iSerialNumber, + (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"); + } + break; } + retries--; + upsdebugx(1, "%s get iSerialNumber failed, retrying...", __func__); } } @@ -343,7 +360,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, #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; + retries = MAX_RETRY; 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)); diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 7ac92a6018..999651864b 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1,7 +1,7 @@ /* usbhid-ups.c - Driver for USB and serial (MGE SHUT) HID UPS units * * Copyright (C) - * 2003-2012 Arnaud Quette + * 2003-2022 Arnaud Quette * 2005 John Stamp * 2005-2006 Peter Selinger * 2007-2009 Arjen de Korte @@ -28,7 +28,7 @@ */ #define DRIVER_NAME "Generic HID driver" -#define DRIVER_VERSION "0.45" +#define DRIVER_VERSION "0.46" #include "main.h" #include "libhid.h" @@ -147,7 +147,7 @@ bool_t use_interrupt_pipe = TRUE; bool_t use_interrupt_pipe = FALSE; #endif static time_t lastpoll; /* Timestamp the last polling */ -hid_dev_handle_t udev; +hid_dev_handle_t udev = HID_DEV_HANDLE_CLOSED; /* support functions */ static hid_info_t *find_nut_info(const char *varname); @@ -1544,6 +1544,10 @@ static int reconnect_ups(void) upsdebugx(4, "= device has been disconnected, try to reconnect ="); upsdebugx(4, "=================================================="); + /* Try to close the previous handle */ + if (udev) + comm_driver->close(udev); + ret = comm_driver->open(&udev, &curDevice, subdriver_matcher, NULL); if (ret > 0) {