@@ -227,6 +227,9 @@ static int opt_nodesc = 0; /* skip querying device description */
227227static int opt_nosysfs = 0 ; /* don't use the Linux sysfs port disable interface, even if available */
228228#endif
229229
230+ /* For Raspberry Pi detection and workarounds: */
231+ static int is_rpi_4b = 0 ;
232+ static int is_rpi_5 = 0 ;
230233
231234static const char short_options [] =
232235 "l:L:n:a:p:d:r:w:s:hvefRN"
@@ -361,6 +364,46 @@ static int ports2bitmap(char* const portlist)
361364 return ports ;
362365}
363366
367+ /*
368+ * Get model of the computer we are currently running on.
369+ * On success return 0 and fill model string (null terminated).
370+ * If model is not known or error occurred returns -1.
371+ *
372+ * Currently this can only return successfully on Linux,
373+ * but in the future we may need it on other operating systems too.
374+ */
375+
376+ static int get_computer_model (char * model , int len )
377+ {
378+ int fd = open ("/sys/firmware/devicetree/base/model" , O_RDONLY );
379+ if (fd < 0 ) {
380+ return fd ;
381+ }
382+ int bytes_read = read (fd , model , len - 1 );
383+ close (fd );
384+ if (bytes_read < 0 ) {
385+ return -1 ;
386+ }
387+ model [bytes_read ] = 0 ;
388+ return 0 ;
389+ }
390+
391+ /*
392+ * Check if we are running on given computer model using substring match.
393+ * Returns 1 if yes and 0 otherwise.
394+ */
395+
396+ static int check_computer_model (char * target )
397+ {
398+ char model [256 ] = "" ;
399+ if (get_computer_model (model , sizeof (model )) == 0 ) {
400+ if (strstr (model , target ) != NULL ) {
401+ return 1 ;
402+ }
403+ }
404+ return 0 ;
405+ }
406+
364407
365408/*
366409 * Compatibility wrapper around libusb_get_port_numbers()
@@ -466,7 +509,8 @@ static int get_hub_info(struct libusb_device *dev, struct hub_info *info)
466509 libusb_free_bos_descriptor (bos );
467510
468511 /* Raspberry Pi 4B hack for USB3 root hub: */
469- if (strlen (info -> container_id )== 0 &&
512+ if (is_rpi_4b &&
513+ strlen (info -> container_id )== 0 &&
470514 strcasecmp (info -> vendor , "1d6b:0003" )== 0 &&
471515 info -> pn_len == 0 &&
472516 info -> nports == 4 &&
@@ -483,32 +527,28 @@ static int get_hub_info(struct libusb_device *dev, struct hub_info *info)
483527 lpsm = HUB_CHAR_INDV_PORT_LPSM ;
484528 }
485529 /* Raspberry Pi 4B reports inconsistent descriptors, override: */
486- if (lpsm == HUB_CHAR_COMMON_LPSM && strcasecmp (info -> vendor , "2109:3431" )== 0 ) {
530+ if (is_rpi_4b && lpsm == HUB_CHAR_COMMON_LPSM && strcasecmp (info -> vendor , "2109:3431" )== 0 ) {
487531 lpsm = HUB_CHAR_INDV_PORT_LPSM ;
488532 }
489533 info -> lpsm = lpsm ;
490534
491535 /* Raspberry Pi 5 hack */
492-
493- /* TODO: make this hack more reliable by querying Raspberry Pi model */
494-
495- if (strlen (info -> container_id )== 0 &&
536+ if (is_rpi_5 &&
537+ strlen (info -> container_id )== 0 &&
496538 info -> lpsm == HUB_CHAR_INDV_PORT_LPSM &&
497539 info -> pn_len == 0 )
498540 {
499541 /* USB2 */
500542 if (strcasecmp (info -> vendor , "1d6b:0002" )== 0 &&
501543 info -> nports == 2 &&
502- !info -> super_speed &&
503- (info -> bus == 1 || info -> bus == 3 ))
544+ !info -> super_speed )
504545 {
505546 strcpy (info -> container_id , "Raspberry Pi 5 Fake Container Id" );
506547 }
507548 /* USB3 */
508549 if (strcasecmp (info -> vendor , "1d6b:0003" )== 0 &&
509550 info -> nports == 1 &&
510- info -> super_speed &&
511- (info -> bus == 2 || info -> bus == 4 ))
551+ info -> super_speed )
512552 {
513553 strcpy (info -> container_id , "Raspberry Pi 5 Fake Container Id" );
514554 }
@@ -1004,7 +1044,7 @@ static int usb_find_hubs(void)
10041044 }
10051045
10061046 /* Raspberry Pi 4B hack (USB2 hub is one level deeper than USB3): */
1007- if (l1 + s1 == l2 + s2 && l1 >= s2 && memcmp (p1 + s2 , p2 + s1 , l1 - s2 )== 0 ) {
1047+ if (is_rpi_4b && l1 + s1 == l2 + s2 && l1 >= s2 && memcmp (p1 + s2 , p2 + s1 , l1 - s2 )== 0 ) {
10081048 if (best_score < 3 ) {
10091049 best_score = 3 ;
10101050 best_match = j ;
@@ -1180,6 +1220,9 @@ int main(int argc, char *argv[])
11801220 goto cleanup ;
11811221 }
11821222
1223+ is_rpi_4b = check_computer_model ("Raspberry Pi 4 Model B" );
1224+ is_rpi_5 = check_computer_model ("Raspberry Pi 5" );
1225+
11831226 rc = usb_find_hubs ();
11841227 if (rc <= 0 ) {
11851228 fprintf (stderr ,
0 commit comments