diff options
author | Vadim Mikhailov <mvp@users.noreply.github.com> | 2020-01-05 13:39:40 -0800 |
---|---|---|
committer | Vadim Mikhailov <mvp@users.noreply.github.com> | 2020-01-05 13:43:14 -0800 |
commit | 4aae44ced03980802c5fdadcea16d1bc2f8c0bdb (patch) | |
tree | ac81797e12b2a0c27c161072b0bd4ed61ad209f8 /uhubctl.c | |
parent | 9857849c0e7e5984b568a9225271b819b368ab1a (diff) |
Add support for Raspberry Pi 4
Hack to support Raspberry Pi 4:
* Override ganged power switching reported by USB2 hub as per-port. This is not necessarily true,
but is consistent with per-port power switching returned by dual USB3 root hub.
Proper fix is for Raspberry Pi 4 USB firmware to return consistent descriptor information.
* When root USB3 hub is detected on RPi4 without ContainerID, it is assumed to have
ContainerID of dual USB2 hub, so USB2/3 duality is still working as expected.
Proper fix would be for USB3 root hub to report correct ContainerID.
Diffstat (limited to 'uhubctl.c')
-rw-r--r-- | uhubctl.c | 71 |
1 files changed, 45 insertions, 26 deletions
@@ -408,9 +408,54 @@ static int get_hub_info(struct libusb_device *dev, struct hub_info *info) strcat(info->location, s); } + /* Get container_id: */ + bzero(info->container_id, sizeof(info->container_id)); + struct libusb_bos_descriptor *bos; + rc = libusb_get_bos_descriptor(devh, &bos); + if (rc == 0) { + int cap; +#ifdef __FreeBSD__ + for (cap=0; cap < bos->bNumDeviceCapabilities; cap++) { +#else + for (cap=0; cap < bos->bNumDeviceCaps; cap++) { +#endif + if (bos->dev_capability[cap]->bDevCapabilityType == LIBUSB_BT_CONTAINER_ID) { + struct libusb_container_id_descriptor *container_id; + rc = libusb_get_container_id_descriptor(NULL, bos->dev_capability[cap], &container_id); + if (rc == 0) { + int i; + for (i=0; i<16; i++) { + sprintf(info->container_id+i*2, "%02x", container_id->ContainerID[i]); + } + info->container_id[i*2] = 0; + libusb_free_container_id_descriptor(container_id); + } + } + } + libusb_free_bos_descriptor(bos); + + /* Raspberry Pi 4 hack for USB3 root hub: */ + if (strlen(info->container_id)==0 && + strcasecmp(info->vendor, "1d6b:0003")==0 && + info->level==1 && + info->nports==4 && + bcd_usb==USB_SS_BCD) + { + strcpy(info->container_id, "5cf3ee30d5074925b001802d79434c30"); + } + } + info->ppps = 0; /* Logical Power Switching Mode */ int lpsm = uhd->wHubCharacteristics[0] & HUB_CHAR_LPSM; + if (lpsm == HUB_CHAR_COMMON_LPSM && info->nports == 1) { + /* For 1 port hubs, ganged power switching is the same as per-port: */ + lpsm = HUB_CHAR_INDV_PORT_LPSM; + } + /* Raspberry Pi 4 reports inconsistent descriptors, override: */ + if (lpsm == HUB_CHAR_COMMON_LPSM && strcasecmp(info->vendor, "2109:3431")==0) { + lpsm = HUB_CHAR_INDV_PORT_LPSM; + } /* Over-Current Protection Mode */ int ocpm = uhd->wHubCharacteristics[0] & HUB_CHAR_OCPM; /* LPSM must be supported per-port, and OCPM per port or ganged */ @@ -423,32 +468,6 @@ static int get_hub_info(struct libusb_device *dev, struct hub_info *info) } else { rc = len; } - /* Get container_id: */ - bzero(info->container_id, sizeof(info->container_id)); - struct libusb_bos_descriptor *bos; - rc = libusb_get_bos_descriptor(devh, &bos); - if (rc == 0) { - int cap; -#ifdef __FreeBSD__ - for (cap=0; cap < bos->bNumDeviceCapabilities; cap++) { -#else - for (cap=0; cap < bos->bNumDeviceCaps; cap++) { -#endif - if (bos->dev_capability[cap]->bDevCapabilityType == LIBUSB_BT_CONTAINER_ID) { - struct libusb_container_id_descriptor *container_id; - rc = libusb_get_container_id_descriptor(NULL, bos->dev_capability[cap], &container_id); - if (rc == 0) { - int i; - for (i=0; i<16; i++) { - sprintf(info->container_id+i*2, "%02x", container_id->ContainerID[i]); - } - info->container_id[i*2] = 0; - libusb_free_container_id_descriptor(container_id); - } - } - } - libusb_free_bos_descriptor(bos); - } libusb_close(devh); } return rc; |