mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-09-02 16:44:59 +00:00

While supporting GET_REPORT is a mandatory request per the HID specification the current implementation of the GET_REPORT request responds to the USB Host with an empty reply of the request length. However, some USB Hosts will request the contents of feature reports via the GET_REPORT request. In addition, some proprietary HID 'protocols' will expect different data, for the same report ID, to be to become available in the feature report by sending a preceding SET_REPORT to the USB Device that defines what data is to be presented when that feature report is subsequently retrieved via GET_REPORT (with a very fast < 5ms turn around between the SET_REPORT and the GET_REPORT). There are two other patch sets already submitted for adding GET_REPORT support. The first [1] allows for pre-priming a list of reports via IOCTLs which then allows the USB Host to perform the request, with no further userspace interaction possible during the GET_REPORT request. And another [2] which allows for a single report to be setup by userspace via IOCTL, which will be fetched and returned by the kernel for subsequent GET_REPORT requests by the USB Host, also with no further userspace interaction possible. This patch, while loosely based on both the patch sets, differs by allowing the option for userspace to respond to each GET_REPORT request by setting up a poll to notify userspace that a new GET_REPORT request has arrived. To support this, two extra IOCTLs are supplied. The first of which is used to retrieve the report ID of the GET_REPORT request (in the case of having non-zero report IDs in the HID descriptor). The second IOCTL allows for storing report responses in a list for responding to requests. The report responses are stored in a list (it will be either added if it does not exist or updated if it exists already). A flag (userspace_req) can be set to whether subsequent requests notify userspace or not. Basic operation when a GET_REPORT request arrives from USB Host: - If the report ID exists in the list and it is set for immediate return (i.e. userspace_req == false) then response is sent immediately, userspace is not notified - The report ID does not exist, or exists but is set to notify userspace (i.e. userspace_req == true) then notify userspace via poll: - If userspace responds, and either adds or update the response in the list and respond to the host with the contents - If userspace does not respond within the fixed timeout (2500ms) but the report has been set prevously, then send 'old' report contents - If userspace does not respond within the fixed timeout (2500ms) and the report does not exist in the list then send an empty report Note that userspace could 'prime' the report list at any other time. While this patch allows for flexibility in how the system responds to requests, and therefore the HID 'protocols' that could be supported, a drawback is the time it takes to service the requests and therefore the maximum throughput that would be achievable. The USB HID Specification v1.11 itself states that GET_REPORT is not intended for periodic data polling, so this limitation is not severe. Testing on an iMX8M Nano Ultra Lite with a heavy multi-core CPU loading showed that userspace can typically respond to the GET_REPORT request within 1200ms - which is well within the 5000ms most operating systems seem to allow, and within the 2500ms set by this patch. [1] https://lore.kernel.org/all/20220805070507.123151-2-sunil@amarulasolutions.com/ [2] https://lore.kernel.org/all/20220726005824.2817646-1-vi@endrift.com/ Signed-off-by: David Sands <david.sands@biamp.com> Signed-off-by: Chris Wulff <chris.wulff@biamp.com> Link: https://lore.kernel.org/r/20240817142850.1311460-2-crwulff@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
90 lines
2.8 KiB
C
90 lines
2.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
/*
|
|
* Filesystem based user-mode API to USB Gadget controller hardware
|
|
*
|
|
* Other than ep0 operations, most things are done by read() and write()
|
|
* on endpoint files found in one directory. They are configured by
|
|
* writing descriptors, and then may be used for normal stream style
|
|
* i/o requests. When ep0 is configured, the device can enumerate;
|
|
* when it's closed, the device disconnects from usb. Operations on
|
|
* ep0 require ioctl() operations.
|
|
*
|
|
* Configuration and device descriptors get written to /dev/gadget/$CHIP,
|
|
* which may then be used to read usb_gadgetfs_event structs. The driver
|
|
* may activate endpoints as it handles SET_CONFIGURATION setup events,
|
|
* or earlier; writing endpoint descriptors to /dev/gadget/$ENDPOINT
|
|
* then performing data transfers by reading or writing.
|
|
*/
|
|
|
|
#ifndef __LINUX_USB_GADGETFS_H
|
|
#define __LINUX_USB_GADGETFS_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/ioctl.h>
|
|
|
|
#include <linux/usb/ch9.h>
|
|
|
|
/*
|
|
* Events are delivered on the ep0 file descriptor, when the user mode driver
|
|
* reads from this file descriptor after writing the descriptors. Don't
|
|
* stop polling this descriptor.
|
|
*/
|
|
|
|
enum usb_gadgetfs_event_type {
|
|
GADGETFS_NOP = 0,
|
|
|
|
GADGETFS_CONNECT,
|
|
GADGETFS_DISCONNECT,
|
|
GADGETFS_SETUP,
|
|
GADGETFS_SUSPEND,
|
|
/* and likely more ! */
|
|
};
|
|
|
|
/* NOTE: this structure must stay the same size and layout on
|
|
* both 32-bit and 64-bit kernels.
|
|
*/
|
|
struct usb_gadgetfs_event {
|
|
union {
|
|
/* NOP, DISCONNECT, SUSPEND: nothing
|
|
* ... some hardware can't report disconnection
|
|
*/
|
|
|
|
/* CONNECT: just the speed */
|
|
enum usb_device_speed speed;
|
|
|
|
/* SETUP: packet; DATA phase i/o precedes next event
|
|
*(setup.bmRequestType & USB_DIR_IN) flags direction
|
|
* ... includes SET_CONFIGURATION, SET_INTERFACE
|
|
*/
|
|
struct usb_ctrlrequest setup;
|
|
} u;
|
|
enum usb_gadgetfs_event_type type;
|
|
};
|
|
|
|
|
|
/* The 'g' code is also used by printer and hid gadget ioctl requests.
|
|
* Don't add any colliding codes to either driver, and keep
|
|
* them in unique ranges (size 0x20 for now).
|
|
*/
|
|
|
|
/* endpoint ioctls */
|
|
|
|
/* IN transfers may be reported to the gadget driver as complete
|
|
* when the fifo is loaded, before the host reads the data;
|
|
* OUT transfers may be reported to the host's "client" driver as
|
|
* complete when they're sitting in the FIFO unread.
|
|
* THIS returns how many bytes are "unclaimed" in the endpoint fifo
|
|
* (needed for precise fault handling, when the hardware allows it)
|
|
*/
|
|
#define GADGETFS_FIFO_STATUS _IO('g', 1)
|
|
|
|
/* discards any unclaimed data in the fifo. */
|
|
#define GADGETFS_FIFO_FLUSH _IO('g', 2)
|
|
|
|
/* resets endpoint halt+toggle; used to implement set_interface.
|
|
* some hardware (like pxa2xx) can't support this.
|
|
*/
|
|
#define GADGETFS_CLEAR_HALT _IO('g', 3)
|
|
|
|
#endif /* __LINUX_USB_GADGETFS_H */
|