@@ -190,7 +190,7 @@ struct hub_info {
190
190
int bcd_usb ;
191
191
int super_speed ; /* 1 if super speed hub, and 0 otherwise */
192
192
int nports ;
193
- int ppps ;
193
+ int lpsm ; /* logical power switching mode */
194
194
int actionable ; /* true if this hub is subject to action */
195
195
char container_id [33 ]; /* container ID as hex string */
196
196
char vendor [16 ];
@@ -218,6 +218,7 @@ static int opt_repeat = 1;
218
218
static int opt_wait = 20 ; /* wait before repeating in ms */
219
219
static int opt_exact = 0 ; /* exact location match - disable USB3 duality handling */
220
220
static int opt_reset = 0 ; /* reset hub after operation(s) */
221
+ static int opt_force = 0 ; /* force operation even on unsupported hubs */
221
222
222
223
static const struct option long_options [] = {
223
224
{ "location" , required_argument , NULL , 'l' },
@@ -229,6 +230,7 @@ static const struct option long_options[] = {
229
230
{ "repeat" , required_argument , NULL , 'r' },
230
231
{ "wait" , required_argument , NULL , 'w' },
231
232
{ "exact" , no_argument , NULL , 'e' },
233
+ { "force" , no_argument , NULL , 'f' },
232
234
{ "reset" , no_argument , NULL , 'R' },
233
235
{ "version" , no_argument , NULL , 'v' },
234
236
{ "help" , no_argument , NULL , 'h' },
@@ -252,6 +254,7 @@ static int print_usage()
252
254
"--delay, -d - delay for cycle action [%g sec].\n"
253
255
"--repeat, -r - repeat power off count [%d] (some devices need it to turn off).\n"
254
256
"--exact, -e - exact location (no USB3 duality handling).\n"
257
+ "--force, -f - force operation even on unsupported hubs.\n"
255
258
"--reset, -R - reset hub after each power-on action, causing all devices to reassociate.\n"
256
259
"--wait, -w - wait before repeat power off [%d ms].\n"
257
260
"--version, -v - print program version.\n"
@@ -447,7 +450,6 @@ static int get_hub_info(struct libusb_device *dev, struct hub_info *info)
447
450
}
448
451
}
449
452
450
- info -> ppps = 0 ;
451
453
/* Logical Power Switching Mode */
452
454
int lpsm = uhd -> wHubCharacteristics [0 ] & HUB_CHAR_LPSM ;
453
455
if (lpsm == HUB_CHAR_COMMON_LPSM && info -> nports == 1 ) {
@@ -458,15 +460,8 @@ static int get_hub_info(struct libusb_device *dev, struct hub_info *info)
458
460
if (lpsm == HUB_CHAR_COMMON_LPSM && strcasecmp (info -> vendor , "2109:3431" )== 0 ) {
459
461
lpsm = HUB_CHAR_INDV_PORT_LPSM ;
460
462
}
461
- /* Over-Current Protection Mode */
462
- int ocpm = uhd -> wHubCharacteristics [0 ] & HUB_CHAR_OCPM ;
463
- /* LPSM must be supported per-port, and OCPM per port or ganged */
464
- if ((lpsm == HUB_CHAR_INDV_PORT_LPSM ) &&
465
- (ocpm == HUB_CHAR_INDV_PORT_OCPM ||
466
- ocpm == HUB_CHAR_COMMON_OCPM ))
467
- {
468
- info -> ppps = 1 ;
469
- }
463
+ info -> lpsm = lpsm ;
464
+ rc = 0 ;
470
465
} else {
471
466
rc = len ;
472
467
}
@@ -524,7 +519,7 @@ static int get_device_description(struct libusb_device * dev, struct descriptor_
524
519
int rc ;
525
520
int id_vendor = 0 ;
526
521
int id_product = 0 ;
527
- char ports [64 ] = "" ;
522
+ char hub_specific [64 ] = "" ;
528
523
struct libusb_device_descriptor desc ;
529
524
struct libusb_device_handle * devh = NULL ;
530
525
rc = libusb_get_device_descriptor (dev , & desc );
@@ -554,8 +549,16 @@ static int get_device_description(struct libusb_device * dev, struct descriptor_
554
549
struct hub_info info ;
555
550
rc = get_hub_info (dev , & info );
556
551
if (rc == 0 ) {
557
- snprintf (ports , sizeof (ports ), ", USB %x.%02x, %d ports" ,
558
- info .bcd_usb >> 8 , info .bcd_usb & 0xFF , info .nports );
552
+ const char * lpsm_type ;
553
+ if (info .lpsm == HUB_CHAR_INDV_PORT_LPSM ) {
554
+ lpsm_type = "ppps" ;
555
+ } else if (info .lpsm == HUB_CHAR_COMMON_LPSM ) {
556
+ lpsm_type = "ganged" ;
557
+ } else {
558
+ lpsm_type = "nops" ;
559
+ }
560
+ snprintf (hub_specific , sizeof (hub_specific ), ", USB %x.%02x, %d ports, %s" ,
561
+ info .bcd_usb >> 8 , info .bcd_usb & 0xFF , info .nports , lpsm_type );
559
562
}
560
563
}
561
564
libusb_close (devh );
@@ -566,7 +569,7 @@ static int get_device_description(struct libusb_device * dev, struct descriptor_
566
569
ds -> vendor [0 ] ? " " : "" , ds -> vendor ,
567
570
ds -> product [0 ] ? " " : "" , ds -> product ,
568
571
ds -> serial [0 ] ? " " : "" , ds -> serial ,
569
- ports
572
+ hub_specific
570
573
);
571
574
return 0 ;
572
575
}
@@ -700,9 +703,10 @@ static int usb_find_hubs()
700
703
rc = get_hub_info (dev , & info );
701
704
if (rc ) {
702
705
perm_ok = 0 ; /* USB permission issue? */
706
+ continue ;
703
707
}
704
708
get_device_description (dev , & info .ds );
705
- if (info .ppps ) { /* PPPS is supported */
709
+ if (info .lpsm == HUB_CHAR_INDV_PORT_LPSM || opt_force ) {
706
710
if (hub_count < MAX_HUBS ) {
707
711
info .actionable = 1 ;
708
712
if (strlen (opt_location ) > 0 ) {
@@ -836,6 +840,14 @@ static int usb_find_hubs()
836
840
hub_phys_count ++ ;
837
841
}
838
842
}
843
+ #ifdef __gnu_linux__
844
+ if (perm_ok == 0 && geteuid () != 0 ) {
845
+ fprintf (stderr ,
846
+ "There were permission problems while accessing USB.\n"
847
+ "Follow https://git.io/JIB2Z for a fix!\n"
848
+ );
849
+ }
850
+ #endif
839
851
if (perm_ok == 0 && hub_phys_count == 0 ) {
840
852
return LIBUSB_ERROR_ACCESS ;
841
853
}
@@ -850,7 +862,7 @@ int main(int argc, char *argv[])
850
862
int option_index = 0 ;
851
863
852
864
for (;;) {
853
- c = getopt_long (argc , argv , "l:L:n:a:p:d:r:w:hveR " ,
865
+ c = getopt_long (argc , argv , "l:L:n:a:p:d:r:w:hvefR " ,
854
866
long_options , & option_index );
855
867
if (c == -1 )
856
868
break ; /* no more options left */
@@ -898,6 +910,9 @@ int main(int argc, char *argv[])
898
910
case 'r' :
899
911
opt_repeat = atoi (optarg );
900
912
break ;
913
+ case 'f' :
914
+ opt_force = 1 ;
915
+ break ;
901
916
case 'e' :
902
917
opt_exact = 1 ;
903
918
break ;
@@ -956,18 +971,6 @@ int main(int argc, char *argv[])
956
971
strlen (opt_location ) ? " at location " : "" ,
957
972
opt_location
958
973
);
959
- #ifdef __gnu_linux__
960
- if (rc < 0 && geteuid () != 0 ) {
961
- fprintf (stderr ,
962
- "There were permission problems while accessing USB.\n"
963
- "To fix this, run this tool as root using 'sudo uhubctl',\n"
964
- "or add one or more udev rules like below\n"
965
- "to file '/etc/udev/rules.d/52-usb.rules':\n"
966
- "SUBSYSTEM==\"usb\", ATTR{idVendor}==\"2001\", MODE=\"0666\"\n"
967
- "then run 'sudo udevadm trigger --attr-match=subsystem=usb'\n"
968
- );
969
- }
970
- #endif
971
974
rc = 1 ;
972
975
goto cleanup ;
973
976
}
0 commit comments