
If the USB transfer fails or otherwise returns no data, don't process the (non-existent) reponse data and generate keypresses from it. Doing so makes each successful transaction appear to be a new keypress, which results in ridiculously fast key repeat rates.
FIXME: This breaks USB keyboard on at least NVIDIA Tegra Seaboard, hence why this is an RFC.
I wonder if submit_int_msg() is expected to keep executing until a successful transfer is made? That would likely explain why the existing lack of error handling has no negative effect on non-DWC2 platforms.
Signed-off-by: Stephen Warren swarren@wwwdotorg.org --- With all these commits applied, both my USB keyboards (one LS Lenovo and one FS Dell) work correctly when there is no USB hub between the SoC and the keyboard; I still need split transactions to be implemented for hubs to work.
Tested with this series on top of u-boot-usb/topic/dwc2 plus a patch to enable USB keyboard in include/configs/rpi-common.h (see my github):
Model A, model A+: * USB SD card reader * Both keyboards Early model B, model B, model B+, RPi 2: * USB SD card reader * Both keyboards * Built-in Ethernet Compute module: * USB SD card reader For some reason, the keyboards don't work on the CM. I don't believe it has a USB hub, so I don't know why this is. Perhaps a USB power issue? --- common/usb_kbd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/common/usb_kbd.c b/common/usb_kbd.c index ecc3085cc081..532551af7a6b 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -313,10 +313,10 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev) struct usb_kbd_pdata *data = dev->privptr;
/* Submit a interrupt transfer request */ - usb_submit_int_msg(dev, data->intpipe, &data->new[0], data->intpktsize, + int ret = usb_submit_int_msg(dev, data->intpipe, &data->new[0], data->intpktsize, data->intinterval); - - usb_kbd_irq_worker(dev); + if ((!ret) && dev->act_len) + usb_kbd_irq_worker(dev); #elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) struct usb_interface *iface; struct usb_kbd_pdata *data = dev->privptr;