Message ID | 20140406111746.25D3538099A@gemini.denx.de |
---|---|
State | Accepted |
Delegated to: | Marek Vasut |
Headers | show |
> From: "Wolfgang Denk" <wd@denx.de> > I agree that the code is wrong and needs fixing. data->new is an > uint8_t pointer, so taking the size of the pointer is obviously > wrong. But what you fix here is not the only place where > sizeof(data->new) is used, so this patch fixes part of the problem at > best. I can't find any other instances of sizeof in usb_kbd.c. Is this a broader problem in the USB stack? > Can you please try out if the following extended version f the patch > works and fixes your problem? You will note that I removed all > occurrences of this magic number 8 by replacing it with > USB_KBD_PDATA_SIZE so the could should also be easier to read. I've tested your extended patch, and it does fix the problem for me. I agree that adding USB_KBD_PDATA_SIZE does improve readability. Thanks and regards, Adrian Cox
Dear Adrian, In message <3392231.3254.1396864604431.JavaMail.adrian@Gurnard> you wrote: > > > From: "Wolfgang Denk" <wd@denx.de> > > > I agree that the code is wrong and needs fixing. data->new is an > > uint8_t pointer, so taking the size of the pointer is obviously > > wrong. But what you fix here is not the only place where > > sizeof(data->new) is used, so this patch fixes part of the problem at > > best. > > I can't find any other instances of sizeof in usb_kbd.c. Yes, you are right. I did not see that your patch fixes both occurrences of sizeof(data->new). > Is this a broader problem in the USB stack? I haven't looked at the other code, so I cannot comment on that. > > Can you please try out if the following extended version f the patch > > works and fixes your problem? You will note that I removed all > > occurrences of this magic number 8 by replacing it with > > USB_KBD_PDATA_SIZE so the could should also be easier to read. > > I've tested your extended patch, and it does fix the problem for me. I agree that adding USB_KBD_PDATA_SIZE > does improve readability. Thanks for testing. Marek, can you then please use my version of the patch instead of the original one? Thanks. Best regards, Wolfgang Denk
On Sunday, April 06, 2014 at 01:17:46 PM, Wolfgang Denk wrote: [...] > @@ -131,7 +133,9 @@ void usb_kbd_generic_poll(void) > /* Submit a interrupt transfer request */ > maxp = usb_maxpacket(usb_kbd_dev, pipe); > usb_submit_int_msg(usb_kbd_dev, pipe, data->new, > - maxp > 8 ? 8 : maxp, ep->bInterval); > + maxp > USB_KBD_PDATA_SIZE ? > + USB_KBD_PDATA_SIZE : maxp, > + ep->bInterval); Can we use min(8, USB_KBD_PDATA_SIZE) here instead of this multi-line monster call please ? Also, this USB_KBD_PDATA_SIZE should instead be called "USB_KBD_LS_REPORT_SIZE" according to USB HID spec v1.11 section 5.6 : 5.6 Reports Using USB terminology, a device may send or receive a transaction every USB frame (1 millisecond). A transaction may be made up of multiple packets (token, data, handshake) but is limited in size to 8 bytes for low-speed devices and 64 bytes for high-speed devices. A transfer is one or more transactions creating a set of data that is meaningful to the device—for example, Input, Output, and Feature reports. In this document, a transfer is synonymous with a report. What worries me a bit is that 64-byte high-speed report, but I never saw a device that would generate those. This section 5.6 is also the only place that mentions the high-speed HID device report size limit. [...] > @@ -333,7 +340,9 @@ static inline void usb_kbd_poll_for_event(struct > usb_device *dev) /* Submit a interrupt transfer request */ > maxp = usb_maxpacket(dev, pipe); > usb_submit_int_msg(dev, pipe, &data->new[0], > - maxp > 8 ? 8 : maxp, ep->bInterval); > + maxp > USB_KBD_PDATA_SIZE ? > + USB_KBD_PDATA_SIZE : maxp, min(USB_KBD_LS_REPORT_SIZE, maxp) would be nice. > + ep->bInterval); > > usb_kbd_irq_worker(dev); > #elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) [...] > @@ -459,7 +469,9 @@ static int usb_kbd_probe(struct usb_device *dev, > unsigned int ifnum) usb_set_idle(dev, iface->desc.bInterfaceNumber, > REPEAT_RATE, 0); > > debug("USB KBD: enable interrupt pipe...\n"); > - if (usb_submit_int_msg(dev, pipe, data->new, maxp > 8 ? 8 : maxp, > + if (usb_submit_int_msg(dev, pipe, data->new, > + maxp > USB_KBD_PDATA_SIZE ? > + USB_KBD_PDATA_SIZE : maxp, Here as well. Other than that, I don't see a problem. Thank you!
> From: "Marek Vasut" <marex@denx.de> > Also, this USB_KBD_PDATA_SIZE should instead be called > "USB_KBD_LS_REPORT_SIZE" > [...] > What worries me a bit is that 64-byte high-speed report, but I never > saw a > device that would generate those. This section 5.6 is also the only > place that > mentions the high-speed HID device report size limit. How about renaming to USB_KBD_BOOT_REPORT_SIZE? We know that the keyboard report will be 8 bytes because we explicitly set the keyboard into boot protocol (Appendix B of HID 1.11: "The report may not exceed 8 bytes in length."). Regards, Adrian Cox
On Thursday, April 10, 2014 at 10:49:56 AM, Adrian Cox wrote: > > From: "Marek Vasut" <marex@denx.de> > > > > Also, this USB_KBD_PDATA_SIZE should instead be called > > "USB_KBD_LS_REPORT_SIZE" > > [...] > > What worries me a bit is that 64-byte high-speed report, but I never > > saw a > > device that would generate those. This section 5.6 is also the only > > place that > > mentions the high-speed HID device report size limit. > > How about renaming to USB_KBD_BOOT_REPORT_SIZE? We know that the keyboard > report will be 8 bytes because we explicitly set the keyboard into boot > protocol (Appendix B of HID 1.11: "The report may not exceed 8 bytes in > length."). Good point, thanks. A comment in the code about where this number '8' comes from would be nice. Best regards, Marek Vasut
Dear Marek, In message <201404101012.42527.marex@denx.de> you wrote: > On Sunday, April 06, 2014 at 01:17:46 PM, Wolfgang Denk wrote: > [...] > > > @@ -131,7 +133,9 @@ void usb_kbd_generic_poll(void) > > /* Submit a interrupt transfer request */ > > maxp = usb_maxpacket(usb_kbd_dev, pipe); > > usb_submit_int_msg(usb_kbd_dev, pipe, data->new, > > - maxp > 8 ? 8 : maxp, ep->bInterval); > > + maxp > USB_KBD_PDATA_SIZE ? > > + USB_KBD_PDATA_SIZE : maxp, > > + ep->bInterval); > > Can we use min(8, USB_KBD_PDATA_SIZE) here instead of this multi-line monster > call please ? Agreed. > Also, this USB_KBD_PDATA_SIZE should instead be called "USB_KBD_LS_REPORT_S> IZE" > according to USB HID spec v1.11 section 5.6 : Fine with me. > What worries me a bit is that 64-byte high-speed report, but I never saw a > device that would generate those. This section 5.6 is also the only place that > mentions the high-speed HID device report size limit. I'm not an USB expert; I cannot comment on this. > Other than that, I don't see a problem. So how should we proceed? Shall I prepare an updated patch - or Adrian, will you do that? Best regards, Wolfgang Denk
On Thursday, April 10, 2014 at 12:15:30 PM, Wolfgang Denk wrote: > Dear Marek, > > In message <201404101012.42527.marex@denx.de> you wrote: > > On Sunday, April 06, 2014 at 01:17:46 PM, Wolfgang Denk wrote: > > [...] > > > > > @@ -131,7 +133,9 @@ void usb_kbd_generic_poll(void) > > > > > > /* Submit a interrupt transfer request */ > > > maxp = usb_maxpacket(usb_kbd_dev, pipe); > > > usb_submit_int_msg(usb_kbd_dev, pipe, data->new, > > > > > > - maxp > 8 ? 8 : maxp, ep->bInterval); > > > + maxp > USB_KBD_PDATA_SIZE ? > > > + USB_KBD_PDATA_SIZE : maxp, > > > + ep->bInterval); > > > > Can we use min(8, USB_KBD_PDATA_SIZE) here instead of this multi-line > > monster call please ? > > Agreed. > > > Also, this USB_KBD_PDATA_SIZE should instead be called > > "USB_KBD_LS_REPORT_S> IZE" > > > according to USB HID spec v1.11 section 5.6 : > Fine with me. > > > What worries me a bit is that 64-byte high-speed report, but I never saw > > a device that would generate those. This section 5.6 is also the only > > place that mentions the high-speed HID device report size limit. > > I'm not an USB expert; I cannot comment on this. > > > Other than that, I don't see a problem. > > So how should we proceed? Shall I prepare an updated patch - or > Adrian, will you do that? Adrian, can you please take all the discussion here and roll out a new patch please ? Best regards, Marek Vasut
diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 1ad67ca..c6692c5 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -91,6 +91,8 @@ static const unsigned char usb_kbd_arrow[] = { #define USB_KBD_LEDMASK \ (USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK) +#define USB_KBD_PDATA_SIZE 8 + struct usb_kbd_pdata { uint32_t repeat_delay; @@ -99,7 +101,7 @@ struct usb_kbd_pdata { uint8_t usb_kbd_buffer[USB_KBD_BUFFER_LEN]; uint8_t *new; - uint8_t old[8]; + uint8_t old[USB_KBD_PDATA_SIZE]; uint8_t flags; }; @@ -131,7 +133,9 @@ void usb_kbd_generic_poll(void) /* Submit a interrupt transfer request */ maxp = usb_maxpacket(usb_kbd_dev, pipe); usb_submit_int_msg(usb_kbd_dev, pipe, data->new, - maxp > 8 ? 8 : maxp, ep->bInterval); + maxp > USB_KBD_PDATA_SIZE ? + USB_KBD_PDATA_SIZE : maxp, + ep->bInterval); } /* Puts character in the queue and sets up the in and out pointer. */ @@ -266,8 +270,10 @@ static uint32_t usb_kbd_service_key(struct usb_device *dev, int i, int up) old = data->old; } - if ((old[i] > 3) && (memscan(new + 2, old[i], 6) == new + 8)) + if ((old[i] > 3) && + (memscan(new + 2, old[i], 6) == new + USB_KBD_PDATA_SIZE)) { res |= usb_kbd_translate(data, old[i], data->new[0], up); + } return res; } @@ -285,7 +291,7 @@ static int usb_kbd_irq_worker(struct usb_device *dev) else if ((data->new[0] == LEFT_CNTR) || (data->new[0] == RIGHT_CNTR)) data->flags |= USB_KBD_CTRL; - for (i = 2; i < 8; i++) { + for (i = 2; i < USB_KBD_PDATA_SIZE; i++) { res |= usb_kbd_service_key(dev, i, 0); res |= usb_kbd_service_key(dev, i, 1); } @@ -297,7 +303,7 @@ static int usb_kbd_irq_worker(struct usb_device *dev) if (res == 1) usb_kbd_setled(dev); - memcpy(data->old, data->new, 8); + memcpy(data->old, data->new, USB_KBD_PDATA_SIZE); return 1; } @@ -305,7 +311,8 @@ static int usb_kbd_irq_worker(struct usb_device *dev) /* Keyboard interrupt handler */ static int usb_kbd_irq(struct usb_device *dev) { - if ((dev->irq_status != 0) || (dev->irq_act_len != 8)) { + if ((dev->irq_status != 0) || + (dev->irq_act_len != USB_KBD_PDATA_SIZE)) { debug("USB KBD: Error %lX, len %d\n", dev->irq_status, dev->irq_act_len); return 1; @@ -333,7 +340,9 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev) /* Submit a interrupt transfer request */ maxp = usb_maxpacket(dev, pipe); usb_submit_int_msg(dev, pipe, &data->new[0], - maxp > 8 ? 8 : maxp, ep->bInterval); + maxp > USB_KBD_PDATA_SIZE ? + USB_KBD_PDATA_SIZE : maxp, + ep->bInterval); usb_kbd_irq_worker(dev); #elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) @@ -341,8 +350,8 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev) struct usb_kbd_pdata *data = dev->privptr; iface = &dev->config.if_desc[0]; usb_get_report(dev, iface->desc.bInterfaceNumber, - 1, 0, data->new, sizeof(data->new)); - if (memcmp(data->old, data->new, sizeof(data->new))) + 1, 0, data->new, USB_KBD_PDATA_SIZE); + if (memcmp(data->old, data->new, USB_KBD_PDATA_SIZE)) usb_kbd_irq_worker(dev); #endif } @@ -441,7 +450,8 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) 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(8, USB_DMA_MINALIGN)); + data->new = memalign(USB_DMA_MINALIGN, + roundup(USB_KBD_PDATA_SIZE, USB_DMA_MINALIGN)); /* Insert private data into USB device structure */ dev->privptr = data; @@ -459,7 +469,9 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0); debug("USB KBD: enable interrupt pipe...\n"); - if (usb_submit_int_msg(dev, pipe, data->new, maxp > 8 ? 8 : maxp, + if (usb_submit_int_msg(dev, pipe, data->new, + maxp > USB_KBD_PDATA_SIZE ? + USB_KBD_PDATA_SIZE : maxp, ep->bInterval) < 0) { printf("Failed to get keyboard state from device %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct);