Skip to content

Commit cf61981

Browse files
authored
Merge 3516f7c into e175edd
2 parents e175edd + 3516f7c commit cf61981

3 files changed

Lines changed: 159 additions & 110 deletions

File tree

NEWS.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ https://github.com/networkupstools/nut/milestone/12
4949
stable name as a default implementation). Drivers united by `main.c`
5050
framework introduced a `upsdrv_tweak_prognames()` hook method to let
5151
them manipulate the array of `prognames[]` aliases. [PR #3101]
52+
* `libusb0` and `libusb1` integrations now try both "Resource Descriptor
53+
Length" values they could identify on some devices: sometimes the first
54+
(or otherwise preferred) option may be not the correct one, so try the
55+
other too. [issue #3136]
5256

5357
- `asem`, `bestfortress`, `bestuferrups`, `bicker_ser`, `everups`, `metasys`,
5458
`masterguard`, `mge-utalk`, `oneac`, `phoenixcontact_modbus`, `pijuice`,

drivers/libusb0.c

Lines changed: 70 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
#endif /* WIN32 */
3939

4040
#define USB_DRIVER_NAME "USB communication driver (libusb 0.1)"
41-
#define USB_DRIVER_VERSION "0.50"
41+
#define USB_DRIVER_VERSION "0.51"
4242

4343
/* driver description structure */
4444
upsdrv_info_t comm_upsdrv_info = {
@@ -219,7 +219,7 @@ static int nut_libusb_open(usb_dev_handle **udevp,
219219
#ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP
220220
int retries;
221221
#endif
222-
usb_ctrl_charbufsize rdlen1, rdlen2; /* report descriptor length, method 1+2 */
222+
usb_ctrl_charbufsize rdlen1, rdlen2, rdlens[2]; /* report descriptor length, method 1+2, then an array to iterate them (if both) in chosen order */
223223
USBDeviceMatcher_t *m;
224224
struct usb_device *dev;
225225
struct usb_bus *bus;
@@ -231,13 +231,14 @@ static int nut_libusb_open(usb_dev_handle **udevp,
231231
usb_ctrl_char *p;
232232
char string[256];
233233
int i;
234+
size_t j;
234235
int count_open_EACCESS = 0;
235236
int count_open_errors = 0;
236237
int count_open_attempts = 0;
237238

238239
/* report descriptor */
239240
usb_ctrl_char rdbuf[MAX_REPORT_SIZE];
240-
usb_ctrl_charbufsize rdlen;
241+
usb_ctrl_charbufsize rdlen = -1;
241242

242243
struct usb_bus *busses;
243244

@@ -625,13 +626,15 @@ static int nut_libusb_open(usb_dev_handle **udevp,
625626
the maximum of the two values instead. */
626627
if ((curDevice->VendorID == 0x463) && (curDevice->bcdDevice == 0x0202)) {
627628
upsdebugx(1, "Eaton device v2.02. Using full report descriptor");
628-
rdlen = rdlen1;
629+
rdlens[0] = rdlen1;
630+
rdlens[1] = rdlen2;
629631
}
630632
else {
631-
rdlen = rdlen2 >= 0 ? rdlen2 : rdlen1;
633+
rdlens[0] = rdlen2 >= 0 ? rdlen2 : rdlen1;
634+
rdlens[1] = rdlen2 >= 0 ? rdlen1 : rdlen2;
632635
}
633636

634-
if (rdlen < 0) {
637+
if (rdlen1 < 0 && rdlen2 < 0) {
635638
upsdebugx(2, "Unable to retrieve any HID descriptor");
636639
goto next_device;
637640
}
@@ -640,61 +643,79 @@ static int nut_libusb_open(usb_dev_handle **udevp,
640643
"(Reportlen = %" PRI_NUT_USB_CTRL_CHARBUFSIZE
641644
" vs. %" PRI_NUT_USB_CTRL_CHARBUFSIZE ")",
642645
rdlen1, rdlen2);
646+
} else {
647+
if (rdlen1 == rdlen2) {
648+
rdlens[1] = -1;
649+
}
643650
}
644651

645-
upsdebugx(2,
646-
"HID descriptor length %" PRI_NUT_USB_CTRL_CHARBUFSIZE,
647-
rdlen);
652+
for (j = 0; j < sizeof(rdlens); j++) {
653+
rdlen = rdlens[j];
654+
if (rdlen < 0)
655+
continue;
648656

649-
if ((uintmax_t)rdlen > sizeof(rdbuf)) {
650657
upsdebugx(2,
651-
"HID descriptor too long %" PRI_NUT_USB_CTRL_CHARBUFSIZE
652-
" (max %" PRIuSIZE ")",
653-
rdlen, sizeof(rdbuf));
654-
goto next_device;
655-
}
658+
"Trying HID descriptor length %" PRI_NUT_USB_CTRL_CHARBUFSIZE,
659+
rdlen);
660+
661+
if ((uintmax_t)rdlen > sizeof(rdbuf)) {
662+
upsdebugx(2,
663+
"HID descriptor too long %" PRI_NUT_USB_CTRL_CHARBUFSIZE
664+
" (max %" PRIuSIZE ")",
665+
rdlen, sizeof(rdbuf));
666+
continue;
667+
}
656668

657-
/* Note: rdlen is safe to cast to unsigned below,
658-
* since the <0 case was ruled out above */
659-
/* res = usb_get_descriptor(udev, USB_DT_REPORT, hid_desc_index, bigbuf, rdlen); */
660-
res = usb_control_msg(udev,
661-
USB_ENDPOINT_IN + 1,
662-
USB_REQ_GET_DESCRIPTOR,
663-
(USB_DT_REPORT << 8) + usb_subdriver.hid_desc_index,
664-
usb_subdriver.hid_rep_index,
665-
rdbuf, rdlen, USB_TIMEOUT);
669+
/* Note: rdlen is safe to cast to unsigned below,
670+
* since the <0 case was ruled out above */
671+
/* res = usb_get_descriptor(udev, USB_DT_REPORT, hid_desc_index, bigbuf, rdlen); */
672+
res = usb_control_msg(udev,
673+
USB_ENDPOINT_IN + 1,
674+
USB_REQ_GET_DESCRIPTOR,
675+
(USB_DT_REPORT << 8) + usb_subdriver.hid_desc_index,
676+
usb_subdriver.hid_rep_index,
677+
rdbuf, rdlen, USB_TIMEOUT);
666678

667-
if (res < 0)
668-
{
669-
upsdebug_with_errno(2, "Unable to get Report descriptor");
670-
goto next_device;
671-
}
679+
if (res < 0)
680+
{
681+
upsdebug_with_errno(2, "Unable to get Report descriptor");
682+
continue;
683+
}
672684

673-
if (res < rdlen)
674-
{
685+
if (res < rdlen)
686+
{
675687
#ifndef WIN32
676-
upsdebugx(2, "Warning: report descriptor too short "
677-
"(expected %" PRI_NUT_USB_CTRL_CHARBUFSIZE
678-
", got %d)", rdlen, res);
688+
upsdebugx(2, "Warning: report descriptor too short "
689+
"(expected %" PRI_NUT_USB_CTRL_CHARBUFSIZE
690+
", got %d)", rdlen, res);
679691
#else /* WIN32 */
680-
/* https://github.com/networkupstools/nut/issues/1690#issuecomment-1455206002 */
681-
upsdebugx(0, "Warning: report descriptor too short "
682-
"(expected %" PRI_NUT_USB_CTRL_CHARBUFSIZE
683-
", got %d)", rdlen, res);
684-
upsdebugx(0, "Please check your Windows Device Manager: "
685-
"perhaps the UPS was recognized by default OS\n"
686-
"driver such as HID UPS Battery (hidbatt.sys, "
687-
"hidusb.sys or similar). It could have been\n"
688-
"\"restored\" by Windows Update. You can try "
689-
"https://zadig.akeo.ie/ to handle it with\n"
690-
"either WinUSB, libusb0.sys or libusbK.sys.");
692+
/* https://github.com/networkupstools/nut/issues/1690#issuecomment-1455206002 */
693+
upsdebugx(0, "Warning: report descriptor too short "
694+
"(expected %" PRI_NUT_USB_CTRL_CHARBUFSIZE
695+
", got %d)", rdlen, res);
696+
upsdebugx(0, "Please check your Windows Device Manager: "
697+
"perhaps the UPS was recognized by default OS\n"
698+
"driver such as HID UPS Battery (hidbatt.sys, "
699+
"hidusb.sys or similar). It could have been\n"
700+
"\"restored\" by Windows Update. You can try "
701+
"https://zadig.akeo.ie/ to handle it with\n"
702+
"either WinUSB, libusb0.sys or libusbK.sys.");
691703
#endif /* WIN32 */
692-
rdlen = res; /* correct rdlen if necessary */
704+
rdlen = res; /* correct rdlen if necessary */
705+
}
706+
707+
res = callback(udev, curDevice, rdbuf, rdlen);
708+
if (res < 1) {
709+
upsdebugx(2, "Caller doesn't like this device (or rdlen is wrong)");
710+
continue;
711+
}
712+
713+
/* We found it... or at least something that did not complain */
714+
break;
693715
}
694716

695-
res = callback(udev, curDevice, rdbuf, rdlen);
696-
if (res < 1) {
697-
upsdebugx(2, "Caller doesn't like this device");
717+
if (j >= sizeof(rdlens)) {
718+
/* Ended the loop without success */
698719
goto next_device;
699720
}
700721

0 commit comments

Comments
 (0)