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 */
4444upsdrv_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