Commit 08a98b89df39d25a1260f390c19be4649dfd303d

Authored by Adrian Cox
Committed by Marek Vasut
1 parent ea42777567

usb: Fix USB keyboard polling via control endpoint

USB keyboard polling failed for some keyboards on PowerPC 5020.
This was caused by requesting only 4 bytes of data from keyboards that
produce an 8 byte HID report.

Signed-off-by: Adrian Cox <adrian@humboldt.co.uk>
Signed-off-by: Wolfgang Denk <wd@denx.de>
Cc: Marek Vasut <marex@denx.de>

Showing 1 changed file with 25 additions and 11 deletions Side-by-side Diff

... ... @@ -91,6 +91,12 @@
91 91 #define USB_KBD_LEDMASK \
92 92 (USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK)
93 93  
  94 +/*
  95 + * USB Keyboard reports are 8 bytes in boot protocol.
  96 + * Appendix B of HID Device Class Definition 1.11
  97 + */
  98 +#define USB_KBD_BOOT_REPORT_SIZE 8
  99 +
94 100 struct usb_kbd_pdata {
95 101 uint32_t repeat_delay;
96 102  
... ... @@ -99,7 +105,7 @@
99 105 uint8_t usb_kbd_buffer[USB_KBD_BUFFER_LEN];
100 106  
101 107 uint8_t *new;
102   - uint8_t old[8];
  108 + uint8_t old[USB_KBD_BOOT_REPORT_SIZE];
103 109  
104 110 uint8_t flags;
105 111 };
... ... @@ -131,7 +137,8 @@
131 137 /* Submit a interrupt transfer request */
132 138 maxp = usb_maxpacket(usb_kbd_dev, pipe);
133 139 usb_submit_int_msg(usb_kbd_dev, pipe, data->new,
134   - maxp > 8 ? 8 : maxp, ep->bInterval);
  140 + min(maxp, USB_KBD_BOOT_REPORT_SIZE),
  141 + ep->bInterval);
135 142 }
136 143  
137 144 /* Puts character in the queue and sets up the in and out pointer. */
138 145  
... ... @@ -266,8 +273,11 @@
266 273 old = data->old;
267 274 }
268 275  
269   - if ((old[i] > 3) && (memscan(new + 2, old[i], 6) == new + 8))
  276 + if ((old[i] > 3) &&
  277 + (memscan(new + 2, old[i], USB_KBD_BOOT_REPORT_SIZE - 2) ==
  278 + new + USB_KBD_BOOT_REPORT_SIZE)) {
270 279 res |= usb_kbd_translate(data, old[i], data->new[0], up);
  280 + }
271 281  
272 282 return res;
273 283 }
... ... @@ -285,7 +295,7 @@
285 295 else if ((data->new[0] == LEFT_CNTR) || (data->new[0] == RIGHT_CNTR))
286 296 data->flags |= USB_KBD_CTRL;
287 297  
288   - for (i = 2; i < 8; i++) {
  298 + for (i = 2; i < USB_KBD_BOOT_REPORT_SIZE; i++) {
289 299 res |= usb_kbd_service_key(dev, i, 0);
290 300 res |= usb_kbd_service_key(dev, i, 1);
291 301 }
... ... @@ -297,7 +307,7 @@
297 307 if (res == 1)
298 308 usb_kbd_setled(dev);
299 309  
300   - memcpy(data->old, data->new, 8);
  310 + memcpy(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE);
301 311  
302 312 return 1;
303 313 }
... ... @@ -305,7 +315,8 @@
305 315 /* Keyboard interrupt handler */
306 316 static int usb_kbd_irq(struct usb_device *dev)
307 317 {
308   - if ((dev->irq_status != 0) || (dev->irq_act_len != 8)) {
  318 + if ((dev->irq_status != 0) ||
  319 + (dev->irq_act_len != USB_KBD_BOOT_REPORT_SIZE)) {
309 320 debug("USB KBD: Error %lX, len %d\n",
310 321 dev->irq_status, dev->irq_act_len);
311 322 return 1;
... ... @@ -333,7 +344,8 @@
333 344 /* Submit a interrupt transfer request */
334 345 maxp = usb_maxpacket(dev, pipe);
335 346 usb_submit_int_msg(dev, pipe, &data->new[0],
336   - maxp > 8 ? 8 : maxp, ep->bInterval);
  347 + min(maxp, USB_KBD_BOOT_REPORT_SIZE),
  348 + ep->bInterval);
337 349  
338 350 usb_kbd_irq_worker(dev);
339 351 #elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP)
... ... @@ -341,8 +353,8 @@
341 353 struct usb_kbd_pdata *data = dev->privptr;
342 354 iface = &dev->config.if_desc[0];
343 355 usb_get_report(dev, iface->desc.bInterfaceNumber,
344   - 1, 0, data->new, sizeof(data->new));
345   - if (memcmp(data->old, data->new, sizeof(data->new)))
  356 + 1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE);
  357 + if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE))
346 358 usb_kbd_irq_worker(dev);
347 359 #endif
348 360 }
... ... @@ -441,7 +453,8 @@
441 453 memset(data, 0, sizeof(struct usb_kbd_pdata));
442 454  
443 455 /* allocate input buffer aligned and sized to USB DMA alignment */
444   - data->new = memalign(USB_DMA_MINALIGN, roundup(8, USB_DMA_MINALIGN));
  456 + data->new = memalign(USB_DMA_MINALIGN,
  457 + roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN));
445 458  
446 459 /* Insert private data into USB device structure */
447 460 dev->privptr = data;
... ... @@ -459,7 +472,8 @@
459 472 usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0);
460 473  
461 474 debug("USB KBD: enable interrupt pipe...\n");
462   - if (usb_submit_int_msg(dev, pipe, data->new, maxp > 8 ? 8 : maxp,
  475 + if (usb_submit_int_msg(dev, pipe, data->new,
  476 + min(maxp, USB_KBD_BOOT_REPORT_SIZE),
463 477 ep->bInterval) < 0) {
464 478 printf("Failed to get keyboard state from device %04x:%04x\n",
465 479 dev->descriptor.idVendor, dev->descriptor.idProduct);