Adding Marek as USB maintainer. Otherwise this non-patch-email may get
lost when sent to the mailing list only.

Soeren

On 25.02.20 18:45, Stefan wrote:
> Hello!
>
> I own a D-Link DBT-120 Bluetooth Adapter, which has a CSR firmware running in 
> a so called “HID proxy mode”. This firmware pretends to be a USB keyboard 
> (and mouse) and thus allows to use a Bluetooth keyboard in U-Boot.
>
> Unfortunately it acts as a low-speed device and there seems to be some well 
> known troubles about low-speed USB keyboards. There is a FAQ entry for 
> openSUSE about this: 
> https://en.opensuse.org/HCL:Raspberry_Pi3#I_cannot_use_keyboard_in_U-Boot_and_Grub_but_it_works_in_Linux
>
> I spend some effort to solve this issue. There are three tiny changes to get 
> my Bluetooth keyboard working reliably as a low-speed USB keyboard.
>
> Sometimes the Bluetooth adapter needs a bit longer to power on and send its 
> descriptor. As I use a Raspberry Pi 3b, I modified include/configs/rpi.h to 
> add "usb_pgood_delay=100\0" to the CONFIG_EXTRA_ENV_SETTINGS define. However 
> this is actually not a necessary change, even without it, most of the time 
> there is no issue.
>
> Then the Bluetooth adapter needs one millisecond delay before accepting a new 
> address, to avoid the error “USB device not accepting new address”. This is 
> in common/usb.c at line 1047:
>
> https://github.com/u-boot/u-boot/blob/master/common/usb.c#L1047
>
>       dev->devnum = addr;
>       mdelay(1);
>       err = usb_set_address(dev); /* set address */
>
> And finally, assuming the use of CONFIG_SYS_USB_EVENT_POLL=y (which is the 
> default), in common/usb_kbd.c at line 520 this first interrupt IN message 
> must not be send:
>
> https://github.com/u-boot/u-boot/blob/master/common/usb_kbd.c#L520
>
>       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;
>       }
>
> Due to the #if stuff around, its a bit ugly. I solved it simply by modifying 
> the if-statement in line 520:
>
>       if (0) {
>
> With these two fixes my keyboard is working reliably. There is no need to 
> press a key upfront and no error message any longer, as described for 
> openSUSE. A chain-loaded GRUB-EFI is always usable now. I’m pretty sure that 
> these changes will solve the issues for other low-speed USB keyboards as well.
>
>
> However, with that first interrupt IN message still sent, it seemed to me 
> that there was a NYET loop in chunk_msg() in drivers/usb/host/dwc.c once 
> complete_split got set. I guessed that “done += actual_len;” happens to often 
> and possibly to early for an unfinished split transaction. With the recent 
> fix 9dcab2c4d2cb50ab1864c818b82a72393c160236 introducing the nonblock 
> argument, a split transfer gets restarted at a higher level, once there were 
> to many NYET responses. But for this first interrupt IN message this nonblock 
> argument is set to false, and in _submit_int_msg() we run into the timeout.
>
> If I understand it correctly, once a NYET message is received, it may take up 
> to a millisecond before a response from a low-speed device is received (one 
> low-speed frame). And a high-speed host has a frame length of 125 ms. That 
> means that it can take up to 8 high-speed frames before a response from a 
> low-speed device is received. Bit chunk_msg() returns already after > 4 
> high-speed frames. I would expect to wait at least 8 frames.
>
> The check after that first interrupt IN message got added by 
> 5da2dc9789abecb1b018beb0c93f4c38c2985bc6 to workaround non-working keyboards. 
> My suggested change will kind of revert that workaround. So there is some 
> trade-off.
>
>
> Stefan

Reply via email to