common/usb_kbd.c
/* probes the USB device dev for keyboard type. */
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;
int epNum;
if (dev->descriptor.bNumConfigurations != 1)
return 0;
iface = &dev->config.if_desc[ifnum];
if (iface->desc.bInterfaceClass != USB_CLASS_HID)
return 0;
if (iface->desc.bInterfaceSubClass != USB_SUB_HID_BOOT)
return 0;
if (iface->desc.bInterfaceProtocol != USB_PROT_HID_KEYBOARD)
return 0;
for (epNum = 0; epNum < iface->desc.bNumEndpoints; epNum++) {
ep = &iface->ep_desc[epNum];
/* Check if endpoint is interrupt IN endpoint */
if ((ep->bmAttributes & 3) != 3)
continue;
if (ep->bEndpointAddress & 0x80)
break;
}
if (epNum == iface->desc.bNumEndpoints)
return 0;
debug("USB KBD: found interrupt EP: 0x%x\n", ep->bEndpointAddress);
data = malloc(sizeof(struct usb_kbd_pdata));
if (!data) {
printf("USB KBD: Error allocating private data\n");
return 0;
}
/* Clear private data */
memset(data, 0, sizeof(struct usb_kbd_pdata));
/* allocate input buffer aligned and sized to USB DMA alignment */
data->new = memalign(USB_DMA_MINALIGN,
roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN));
/* Insert private data into USB device structure */
dev->privptr = data;
/* Set IRQ handler */
dev->irq_handle = usb_kbd_irq;
data->intpipe = usb_rcvintpipe(dev, ep->bEndpointAddress);
data->intpktsize = min(usb_maxpacket(dev, data->intpipe),
USB_KBD_BOOT_REPORT_SIZE);
data->intinterval = ep->bInterval;
data->last_report = -1;
/* We found a USB Keyboard, install it. */
debug("USB KBD: set boot protocol\n");
usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0);
#if !defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) && \
!defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE)
debug("USB KBD: set idle interval...\n");
usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE / 4, 0);
#else
debug("USB KBD: set idle interval=0...\n");
usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0);
#endif
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,
USB_KBD_BOOT_REPORT_SIZE, data->new,
data->intinterval);
if (!data->intq) {
#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP)
if (usb_get_report(dev, iface->desc.bInterfaceNumber,
1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE) < 0) {
#else
if (usb_int_msg(dev, data->intpipe, data->new, data->intpktsize,
data->intinterval, false) < 0) {
#endif
printf("Failed to get keyboard state from device %04x:%04x\n",
dev->descriptor.idVendor, dev->descriptor.idProduct);
/* Abort, we don't want to use that non-functional keyboard. */
return 0;
}
/* Success. */
return 1;
}
It seems to fall through to this point, without discovering the keyboard.
printf("Failed to get keyboard state from device %04x:%04x\n",
dev->descriptor.idVendor, dev->descriptor.idProduct);
/* Abort, we don't want to use that non-functional keyboard. */
return 0;
I think maybe I need to try and add the idVendor
and idProduct
codes for my “noname” keyboards. But it does not appear to test based on them, but rather more direct query of the device.
Edit: The Drop ENTR is the latest keyboard to fail to be recognized. This is surprising to me.
A Leopold is correctly identified, but it too is 104 keys.