Skip to content

Commit aba6f43

Browse files
committed
drivers/libusb{0,1}.c, NEWS.adoc: if the tried "rdlen" did not succeed, fall back to the other value we had in mind [#3136]
In libusb1.c also fix printout of rdlen variables from %d to %PRIi32 Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
1 parent 774960e commit aba6f43

File tree

3 files changed

+166
-110
lines changed

3 files changed

+166
-110
lines changed

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: 73 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,82 @@ 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+
/*goto next_device;*/
668+
}
656669

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);
670+
/* Note: rdlen is safe to cast to unsigned below,
671+
* since the <0 case was ruled out above */
672+
/* res = usb_get_descriptor(udev, USB_DT_REPORT, hid_desc_index, bigbuf, rdlen); */
673+
res = usb_control_msg(udev,
674+
USB_ENDPOINT_IN + 1,
675+
USB_REQ_GET_DESCRIPTOR,
676+
(USB_DT_REPORT << 8) + usb_subdriver.hid_desc_index,
677+
usb_subdriver.hid_rep_index,
678+
rdbuf, rdlen, USB_TIMEOUT);
666679

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

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

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

0 commit comments

Comments
 (0)