diff options
Diffstat (limited to 'common/usb_kbd.c')
-rw-r--r-- | common/usb_kbd.c | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 4cbc9acb738..820f591fc5b 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -24,6 +24,18 @@ #include <usb.h> /* + * USB vendor and product IDs used for quirks. + */ +#define USB_VENDOR_ID_APPLE 0x05ac +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 0x029a +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f + +#define USB_VENDOR_ID_KEYCHRON 0x3434 + +#define USB_HID_QUIRK_POLL_NO_REPORT_IDLE BIT(0) + +/* * If overwrite_console returns 1, the stdin, stderr and stdout * are switched to the serial port, else the settings in the * environment are used @@ -106,6 +118,8 @@ struct usb_kbd_pdata { unsigned long last_report; struct int_queue *intq; + uint32_t ifnum; + uint32_t repeat_delay; uint32_t usb_in_pointer; @@ -150,8 +164,8 @@ static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c) */ static void usb_kbd_setled(struct usb_device *dev) { - struct usb_interface *iface = &dev->config.if_desc[0]; struct usb_kbd_pdata *data = dev->privptr; + struct usb_interface *iface = &dev->config.if_desc[data->ifnum]; ALLOC_ALIGN_BUFFER(uint32_t, leds, 1, USB_DMA_MINALIGN); *leds = data->flags & USB_KBD_LEDMASK; @@ -365,7 +379,7 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev) #if defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) struct usb_interface *iface; struct usb_kbd_pdata *data = dev->privptr; - iface = &dev->config.if_desc[0]; + iface = &dev->config.if_desc[data->ifnum]; usb_get_report(dev, iface->desc.bInterfaceNumber, 1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE); if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) { @@ -464,6 +478,7 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) struct usb_interface *iface; struct usb_endpoint_descriptor *ep; struct usb_kbd_pdata *data; + unsigned int quirks = 0; int epNum; if (dev->descriptor.bNumConfigurations != 1) @@ -496,6 +511,15 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) debug("USB KBD: found interrupt EP: 0x%x\n", ep->bEndpointAddress); + switch (dev->descriptor.idVendor) { + case USB_VENDOR_ID_APPLE: + case USB_VENDOR_ID_KEYCHRON: + quirks |= USB_HID_QUIRK_POLL_NO_REPORT_IDLE; + break; + default: + break; + } + data = malloc(sizeof(struct usb_kbd_pdata)); if (!data) { printf("USB KBD: Error allocating private data\n"); @@ -509,6 +533,8 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) data->new = memalign(USB_DMA_MINALIGN, roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN)); + data->ifnum = ifnum; + /* Insert private data into USB device structure */ dev->privptr = data; @@ -534,6 +560,14 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0); #endif + /* + * Apple and Keychron keyboards do not report the device state. Reports + * are only returned during key presses. + */ + if (quirks & USB_HID_QUIRK_POLL_NO_REPORT_IDLE) { + debug("USB KBD: quirk: skip testing device state\n"); + return 1; + } debug("USB KBD: enable interrupt pipe...\n"); #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE data->intq = create_int_queue(dev, data->intpipe, 1, @@ -561,10 +595,17 @@ static int probe_usb_keyboard(struct usb_device *dev) { char *stdinname; struct stdio_dev usb_kbd_dev; + unsigned int ifnum; + unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES, + (unsigned int)dev->config.no_of_if); int error; /* Try probing the keyboard */ - if (usb_kbd_probe_dev(dev, 0) != 1) + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + if (usb_kbd_probe_dev(dev, ifnum) == 1) + break; + } + if (ifnum >= max_ifnum) return -ENOENT; /* Register the keyboard */ @@ -731,6 +772,18 @@ static const struct usb_device_id kbd_id_table[] = { .bInterfaceSubClass = USB_SUB_HID_BOOT, .bInterfaceProtocol = USB_PROT_HID_KEYBOARD, }, + { + USB_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021), + }, + { + USB_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), + }, + { + USB_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021), + }, { } /* Terminating entry */ }; |