Re: [PATCH] usb: gadget: f_hid: optional SETUP/SET_REPORT mode

From: Maxim Devaev
Date: Fri Aug 13 2021 - 16:22:21 EST


Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
> In other words, a device does not need to have an interrupt-OUT
> endpoint, but if it does have one then the host must use it.

You're right. Although the actual behavior of the hosts is not different
from what I wrote - they really just ignore out endpoint.
I will eventually fix this in the patch description.

> > However, this raises several problems.
> >
> > (1) Some host OS drivers without OUT Endpoint support can't receive
>
> Can't _transmit_ output reports. This is understandable, since such
> hosts aren't compliant with the standard.

Thank you, this is a typo. With the replacement of the word, the meaning
is fixed. They really don't work. Hosts do not use OUT endpoint
and transmit reports.

> > reports at all. In the case of the keyboard, it becomes impossible
> > to get the status of the LEDs from the host OS.
> >
> > (2) Some BIOSes and UEFIs not only don't support the OUT Endpoint,
> > they cannot work with HID with this configuration at all.
>
> What configuration, exactly? Do you mean that they can't work with
> HID interfaces that include an interrupt-OUT endpoint?

Yep. They see OUT endpoint and refuse to use the device in various ways,
for example, they don't continue the initialization process after receiving
the descriptor. The failure behavior may differ, but it always leads to
a refuse or to the fact that the device simply does not poll IN endpoint.

> > For example, absolutely all Apple UEFIs in all Macs can't handle
> > the OUT Endpoint in accordance with the HID standard so it makes
> > impossible to enter the Boot Menu using the hotkey at boot.
>
> These hosts simply give up when they see an HID interface with an
> interrupt-OUT endpoint? They don't just ignore it and continue on?

Exactly. Hosts will either stop the initialization process when they receive
a handle with an OUT endpoint, or they will not be able to work in any other way.

While investigating the problem with Apple, I realized that their UEFI
is presumably iterated over endpoints and simply does not break the loop
when an IN endpoint is detected. They reach OUT endpoint (which follows IN),
see that it is not IN endpoint, repeat the last initialization ops three times
(SET_IDLE, etc.) and refuse to work with our keyboard. If I change the order
of the endpoints in the descriptor and do OUT first and then IN, then everything
will work in the case of Apple, but this is obviously a violation of the standard,
since it explicitly describes the order of IN and then the optional OUT.

And it only helps with Apple. So the correct solution was to make SETUP/SET_REPORT
because this satisfies all devices. For the order of the endpoints, see 7.2 of HID 1.11:

> The HID class uses the standard request Get_Descriptor as described in the USB
> Specification ... That is, the order shall be:
> Configuration descriptor
> Interface descriptor (specifying HID Class)
> HID descriptor (associated with above Interface)
> Endpoint descriptor (for HID Interrupt In Endpoint)
> Optional Endpoint descriptor (for HID Interrupt Out Endpoint)

> Why not always allow f_hid to receive reports over ep0? The HID
> standard doesn't forbid this.

Previously, this was the case, but then this functionality was removed
for two reasons: using OUT endpoint takes up a USB channel less than SETUP
and allows you to transfer more data from HID gadget, and also allows you
to organize a queue. The queue could have been organized without this change,
but the first point is more significant. I found the correspondence
so that you can read the history of the issue, link below.

That change was not a problem as long as f_hid was mainly used for the keyboard
at the OS level. Now I am making an open source KVM-over-IP based on this
and the compatibility hell have risen to full height.

> Missing the SHA value of the commit.

99c515005857ff7d6cd5c2ba272ccab5dc0ea648

Also the descussion: https://www.spinics.net/lists/linux-usb/msg65494.html

Sorry, I couldn't find this on lore.kernel.org. Maybe I didn't search well,
or this correspondence is too old, 2012.