Add USB hub quirk to support AMI virtual keyboard (issue #523) (#535)

* Add USB hub quirk to support AMI virtual keyboard (issue #523)

From testing it appears that the AMI virtual devices do not work
correctly if you disable one port on the virtual hub then reuse the
USB address for a device connected to another port on that hub. So
add a quirk to detect the virtual hub from its vendor/product ID
and leave all ports on that hub active when performing the scan for
USB keyboards. This will permanently reserve a bit more memory, but
not significantly so.

* Replace hard-coded USB vendor ID with macro definition.
This commit is contained in:
martinwhitaker
2025-08-16 22:20:40 +02:00
committed by GitHub
parent f19066d258
commit 2a58a7cb53
3 changed files with 26 additions and 1 deletions
+4
View File
@@ -87,6 +87,10 @@
#define HUB_PORT_LOW_SPEED 0x00000200
#define HUB_PORT_HIGH_SPEED 0x00000400
// Vendor IDs
#define USB_VID_AMERICAN_MEGATRENDS 0x046b
// Data structures.
typedef struct __attribute__((packed)) {
+12
View File
@@ -150,6 +150,7 @@ static bool build_hub_info(const usb_hcd_t *hcd, const usb_hub_t *parent, int po
hub->tt_think_time = hub_desc.characteristics & 0x0060 >> 5;
hub->power_up_delay = hub_desc.power_up_delay;
hub->hs_parent = usb_hs_parent(parent, port_num, ep0->device_speed);
hub->quirks = USB_HUB_NO_QUIRKS;
usb_endpoint_desc_t *ep1_desc = find_hub_endpoint_descriptor(hcd->ws->data_buffer, hcd->ws->data_length);
if (ep1_desc == NULL) {
@@ -167,6 +168,14 @@ static bool build_hub_info(const usb_hcd_t *hcd, const usb_hub_t *parent, int po
return true;
}
static void add_hub_quirks(const usb_device_desc_t *device, usb_hub_t *hub)
{
if ((device->vendor_id == USB_VID_AMERICAN_MEGATRENDS) && (device->product_id == 0xff01)) {
// add quirk for AMI Virtual Hub - see issue #523
hub->quirks |= USB_HUB_DONT_DISABLE_PORTS;
}
}
static bool get_hub_port_status(const usb_hcd_t *hcd, const usb_hub_t *hub, int port_num, uint32_t *port_status)
{
usb_setup_pkt_t setup_pkt;
@@ -352,6 +361,8 @@ static bool scan_hub_ports(const usb_hcd_t *hcd, const usb_hub_t *hub, int *num_
continue;
}
if (hub->quirks & USB_HUB_DONT_DISABLE_PORTS) continue;
// If we didn't find any keyboards, we can disable the port and release the slot.
build_setup_packet(&setup_pkt, USB_REQ_TO_HUB_PORT | USB_REQ_CLASS, HUB_CLR_FEATURE, HUB_PORT_ENABLE, port_num, 0);
(void)hcd->methods->setup_request(hcd, hub->ep0, &setup_pkt);
@@ -754,6 +765,7 @@ bool find_attached_usb_keyboards(const usb_hcd_t *hcd, const usb_hub_t *hub, int
if (!build_hub_info(hcd, hub, port_num, &ep0, &new_hub, &ep1)) {
return false;
}
add_hub_quirks(device, &new_hub);
if (!configure_device(hcd, &ep0, config_num)) {
return false;
}
+10 -1
View File
@@ -70,6 +70,14 @@ typedef struct __attribute__ ((packed)) {
uint8_t port_num;
} usb_parent_t;
/**
* A set of USB hub quirk identifiers.
*/
typedef enum __attribute__ ((packed)) {
USB_HUB_NO_QUIRKS = 0,
USB_HUB_DONT_DISABLE_PORTS = 1 << 0
} usb_hub_quirk_t;
/**
* A USB hub descriptor (used internally by the various HCI drivers).
*/
@@ -81,7 +89,8 @@ typedef struct __attribute__ ((packed)) {
uint8_t tt_think_time;
uint8_t power_up_delay;
usb_parent_t hs_parent;
uint16_t reserved;
uint8_t quirks;
uint8_t reserved;
} usb_hub_t;
/**