@@ -505,7 +505,7 @@ static int print_port_status(struct hub_info * hub, int portmask)
505
505
if (port_status & USB_PORT_STAT_SUSPEND ) printf (" suspend" );
506
506
}
507
507
} else {
508
- if (port_status == USB_SS_PORT_LS_SS_DISABLED ) {
508
+ if (!( port_status & USB_SS_PORT_STAT_POWER ) ) {
509
509
printf (" off" );
510
510
} else {
511
511
int link_state = port_status & USB_PORT_STAT_LINK_STATE ;
@@ -591,54 +591,69 @@ static int usb_find_hubs()
591
591
}
592
592
}
593
593
}
594
+ if (!opt_exact ) {
595
+ /* Handle USB2/3 duality: */
596
+ for (i = 0 ; i < hub_count ; i ++ ) {
597
+ /* Check only actionable hubs: */
598
+ if (hubs [i ].actionable != 1 )
599
+ continue ;
600
+ int match = -1 ;
601
+ for (j = 0 ; j < hub_count ; j ++ ) {
602
+ if (i == j )
603
+ continue ;
604
+
605
+ /* Find hub which is USB2/3 dual to the hub above.
606
+ * This is quite reliable and predictable on Linux
607
+ * but not on Mac, where we may match wrong hub :(
608
+ * It will work reliably on Mac if there is
609
+ * only one compatible USB3 hub is connected.
610
+ * Unfortunately, libusb does not provide any way
611
+ * to detect USB2/3 dual hubs.
612
+ * TODO: discover better way to find dual hub.
613
+ */
614
+
615
+ /* Hub and its dual must be different types: one USB2, another USB3: */
616
+ if ((hubs [i ].bcd_usb < USB_SS_BCD ) ==
617
+ (hubs [j ].bcd_usb < USB_SS_BCD ))
618
+ continue ;
619
+
620
+ /* But they must have the same vendor: */
621
+ if (strncasecmp (hubs [i ].vendor , hubs [j ].vendor , 4 ))
622
+ continue ;
623
+
624
+ /* And the same number of ports: */
625
+ if (hubs [i ].nports != hubs [j ].nports )
626
+ continue ;
627
+
628
+ /* Provisionally we choose this one as dual: */
629
+ if (match < 0 && !hubs [j ].actionable )
630
+ match = j ;
631
+
632
+ /* But if there is exact port path match,
633
+ * we prefer it (true for Linux but not Mac):
634
+ */
635
+ char * p1 = strchr (hubs [i ].location , '-' );
636
+ char * p2 = strchr (hubs [j ].location , '-' );
637
+ if (p1 && p2 && strcasecmp (p1 , p2 )== 0 ) {
638
+ match = j ;
639
+ break ;
640
+ }
641
+ }
642
+ if (match >= 0 ) {
643
+ if (!hubs [match ].actionable ) {
644
+ /* Use 2 to signify that this is derived dual device */
645
+ hubs [match ].actionable = 2 ;
646
+ }
647
+ }
648
+ }
649
+ }
594
650
hub_phys_count = 0 ;
595
651
for (i = 0 ; i < hub_count ; i ++ ) {
596
- /* Check only actionable USB3 hubs: */
597
652
if (!hubs [i ].actionable )
598
653
continue ;
599
654
if (hubs [i ].bcd_usb < USB_SS_BCD || opt_exact ) {
600
655
hub_phys_count ++ ;
601
656
}
602
- if (opt_exact )
603
- continue ;
604
- int match = -1 ;
605
- for (j = 0 ; j < hub_count ; j ++ ) {
606
- if (i == j )
607
- continue ;
608
-
609
- /* Find hub which is USB2/3 dual to the hub above.
610
- * This is quite reliable and predictable on Linux
611
- * but not on Mac, where we may match wrong hub :(
612
- * It will work reliably on Mac if there is
613
- * only one compatible USB3 hub is connected.
614
- * TODO: discover better way to find dual hub.
615
- */
616
-
617
- /* Hub and its dual must be different types: one USB2, another USB3: */
618
- if ((hubs [i ].bcd_usb < USB_SS_BCD ) ==
619
- (hubs [j ].bcd_usb < USB_SS_BCD ))
620
- continue ;
621
-
622
- /* But they must have the same vendor: */
623
- if (strncasecmp (hubs [i ].vendor , hubs [j ].vendor , 4 ))
624
- continue ;
625
-
626
- /* Provisionally we choose this one as dual: */
627
- if (match < 0 && !hubs [j ].actionable )
628
- match = j ;
629
-
630
- /* But if there is exact port path match,
631
- * we prefer it (true for Linux but not Mac):
632
- */
633
- char * p1 = strchr (hubs [i ].location , '-' );
634
- char * p2 = strchr (hubs [j ].location , '-' );
635
- if (p1 && p2 && strcasecmp (p1 , p2 )== 0 ) {
636
- match = j ;
637
- break ;
638
- }
639
- }
640
- if (match >= 0 )
641
- hubs [match ].actionable = 1 ;
642
657
}
643
658
if (perm_ok == 0 && hub_phys_count == 0 ) {
644
659
return LIBUSB_ERROR_ACCESS ;
0 commit comments