mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
usb: gadget: add raw-gadget interface
USB Raw Gadget is a kernel module that provides a userspace interface for the USB Gadget subsystem. Essentially it allows to emulate USB devices from userspace. Enabled with CONFIG_USB_RAW_GADGET. Raw Gadget is currently a strictly debugging feature and shouldn't be used in production. Raw Gadget is similar to GadgetFS, but provides a more low-level and direct access to the USB Gadget layer for the userspace. The key differences are: 1. Every USB request is passed to the userspace to get a response, while GadgetFS responds to some USB requests internally based on the provided descriptors. However note, that the UDC driver might respond to some requests on its own and never forward them to the Gadget layer. 2. GadgetFS performs some sanity checks on the provided USB descriptors, while Raw Gadget allows you to provide arbitrary data as responses to USB requests. 3. Raw Gadget provides a way to select a UDC device/driver to bind to, while GadgetFS currently binds to the first available UDC. 4. Raw Gadget uses predictable endpoint names (handles) across different UDCs (as long as UDCs have enough endpoints of each required transfer type). 5. Raw Gadget has ioctl-based interface instead of a filesystem-based one. Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Signed-off-by: Felipe Balbi <balbi@kernel.org>
This commit is contained in:
parent
1a0808cb9e
commit
f2c2e71764
@ -22,6 +22,7 @@ USB support
|
||||
misc_usbsevseg
|
||||
mtouchusb
|
||||
ohci
|
||||
raw-gadget
|
||||
usbip_protocol
|
||||
usbmon
|
||||
usb-serial
|
||||
|
61
Documentation/usb/raw-gadget.rst
Normal file
61
Documentation/usb/raw-gadget.rst
Normal file
@ -0,0 +1,61 @@
|
||||
==============
|
||||
USB Raw Gadget
|
||||
==============
|
||||
|
||||
USB Raw Gadget is a kernel module that provides a userspace interface for
|
||||
the USB Gadget subsystem. Essentially it allows to emulate USB devices
|
||||
from userspace. Enabled with CONFIG_USB_RAW_GADGET. Raw Gadget is
|
||||
currently a strictly debugging feature and shouldn't be used in
|
||||
production, use GadgetFS instead.
|
||||
|
||||
Comparison to GadgetFS
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Raw Gadget is similar to GadgetFS, but provides a more low-level and
|
||||
direct access to the USB Gadget layer for the userspace. The key
|
||||
differences are:
|
||||
|
||||
1. Every USB request is passed to the userspace to get a response, while
|
||||
GadgetFS responds to some USB requests internally based on the provided
|
||||
descriptors. However note, that the UDC driver might respond to some
|
||||
requests on its own and never forward them to the Gadget layer.
|
||||
|
||||
2. GadgetFS performs some sanity checks on the provided USB descriptors,
|
||||
while Raw Gadget allows you to provide arbitrary data as responses to
|
||||
USB requests.
|
||||
|
||||
3. Raw Gadget provides a way to select a UDC device/driver to bind to,
|
||||
while GadgetFS currently binds to the first available UDC.
|
||||
|
||||
4. Raw Gadget uses predictable endpoint names (handles) across different
|
||||
UDCs (as long as UDCs have enough endpoints of each required transfer
|
||||
type).
|
||||
|
||||
5. Raw Gadget has ioctl-based interface instead of a filesystem-based one.
|
||||
|
||||
Userspace interface
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To create a Raw Gadget instance open /dev/raw-gadget. Multiple raw-gadget
|
||||
instances (bound to different UDCs) can be used at the same time. The
|
||||
interaction with the opened file happens through the ioctl() calls, see
|
||||
comments in include/uapi/linux/usb/raw_gadget.h for details.
|
||||
|
||||
The typical usage of Raw Gadget looks like:
|
||||
|
||||
1. Open Raw Gadget instance via /dev/raw-gadget.
|
||||
2. Initialize the instance via USB_RAW_IOCTL_INIT.
|
||||
3. Launch the instance with USB_RAW_IOCTL_RUN.
|
||||
4. In a loop issue USB_RAW_IOCTL_EVENT_FETCH calls to receive events from
|
||||
Raw Gadget and react to those depending on what kind of USB device
|
||||
needs to be emulated.
|
||||
|
||||
Potential future improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Implement ioctl's for setting/clearing halt status on endpoints.
|
||||
|
||||
- Reporting more events (suspend, resume, etc.) through
|
||||
USB_RAW_IOCTL_EVENT_FETCH.
|
||||
|
||||
- Support O_NONBLOCK I/O.
|
@ -516,4 +516,15 @@ config USB_G_WEBCAM
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_webcam".
|
||||
|
||||
config USB_RAW_GADGET
|
||||
tristate "USB Raw Gadget"
|
||||
help
|
||||
USB Raw Gadget is a kernel module that provides a userspace interface
|
||||
for the USB Gadget subsystem. Essentially it allows to emulate USB
|
||||
devices from userspace. See Documentation/usb/raw-gadget.rst for
|
||||
details.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "raw_gadget".
|
||||
|
||||
endchoice
|
||||
|
@ -43,3 +43,4 @@ obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o
|
||||
obj-$(CONFIG_USB_G_NCM) += g_ncm.o
|
||||
obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o
|
||||
obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o
|
||||
obj-$(CONFIG_USB_RAW_GADGET) += raw_gadget.o
|
||||
|
1078
drivers/usb/gadget/legacy/raw_gadget.c
Normal file
1078
drivers/usb/gadget/legacy/raw_gadget.c
Normal file
File diff suppressed because it is too large
Load Diff
167
include/uapi/linux/usb/raw_gadget.h
Normal file
167
include/uapi/linux/usb/raw_gadget.h
Normal file
@ -0,0 +1,167 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* USB Raw Gadget driver.
|
||||
*
|
||||
* See Documentation/usb/raw-gadget.rst for more details.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI__LINUX_USB_RAW_GADGET_H
|
||||
#define _UAPI__LINUX_USB_RAW_GADGET_H
|
||||
|
||||
#include <asm/ioctl.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
|
||||
/* Maximum length of driver_name/device_name in the usb_raw_init struct. */
|
||||
#define UDC_NAME_LENGTH_MAX 128
|
||||
|
||||
/*
|
||||
* struct usb_raw_init - argument for USB_RAW_IOCTL_INIT ioctl.
|
||||
* @speed: The speed of the emulated USB device, takes the same values as
|
||||
* the usb_device_speed enum: USB_SPEED_FULL, USB_SPEED_HIGH, etc.
|
||||
* @driver_name: The name of the UDC driver.
|
||||
* @device_name: The name of a UDC instance.
|
||||
*
|
||||
* The last two fields identify a UDC the gadget driver should bind to.
|
||||
* For example, Dummy UDC has "dummy_udc" as its driver_name and "dummy_udc.N"
|
||||
* as its device_name, where N in the index of the Dummy UDC instance.
|
||||
* At the same time the dwc2 driver that is used on Raspberry Pi Zero, has
|
||||
* "20980000.usb" as both driver_name and device_name.
|
||||
*/
|
||||
struct usb_raw_init {
|
||||
__u8 driver_name[UDC_NAME_LENGTH_MAX];
|
||||
__u8 device_name[UDC_NAME_LENGTH_MAX];
|
||||
__u8 speed;
|
||||
};
|
||||
|
||||
/* The type of event fetched with the USB_RAW_IOCTL_EVENT_FETCH ioctl. */
|
||||
enum usb_raw_event_type {
|
||||
USB_RAW_EVENT_INVALID = 0,
|
||||
|
||||
/* This event is queued when the driver has bound to a UDC. */
|
||||
USB_RAW_EVENT_CONNECT = 1,
|
||||
|
||||
/* This event is queued when a new control request arrived to ep0. */
|
||||
USB_RAW_EVENT_CONTROL = 2,
|
||||
|
||||
/* The list might grow in the future. */
|
||||
};
|
||||
|
||||
/*
|
||||
* struct usb_raw_event - argument for USB_RAW_IOCTL_EVENT_FETCH ioctl.
|
||||
* @type: The type of the fetched event.
|
||||
* @length: Length of the data buffer. Updated by the driver and set to the
|
||||
* actual length of the fetched event data.
|
||||
* @data: A buffer to store the fetched event data.
|
||||
*
|
||||
* Currently the fetched data buffer is empty for USB_RAW_EVENT_CONNECT,
|
||||
* and contains struct usb_ctrlrequest for USB_RAW_EVENT_CONTROL.
|
||||
*/
|
||||
struct usb_raw_event {
|
||||
__u32 type;
|
||||
__u32 length;
|
||||
__u8 data[0];
|
||||
};
|
||||
|
||||
#define USB_RAW_IO_FLAGS_ZERO 0x0001
|
||||
#define USB_RAW_IO_FLAGS_MASK 0x0001
|
||||
|
||||
static int usb_raw_io_flags_valid(__u16 flags)
|
||||
{
|
||||
return (flags & ~USB_RAW_IO_FLAGS_MASK) == 0;
|
||||
}
|
||||
|
||||
static int usb_raw_io_flags_zero(__u16 flags)
|
||||
{
|
||||
return (flags & USB_RAW_IO_FLAGS_ZERO);
|
||||
}
|
||||
|
||||
/*
|
||||
* struct usb_raw_ep_io - argument for USB_RAW_IOCTL_EP0/EP_WRITE/READ ioctls.
|
||||
* @ep: Endpoint handle as returned by USB_RAW_IOCTL_EP_ENABLE for
|
||||
* USB_RAW_IOCTL_EP_WRITE/READ. Ignored for USB_RAW_IOCTL_EP0_WRITE/READ.
|
||||
* @flags: When USB_RAW_IO_FLAGS_ZERO is specified, the zero flag is set on
|
||||
* the submitted USB request, see include/linux/usb/gadget.h for details.
|
||||
* @length: Length of data.
|
||||
* @data: Data to send for USB_RAW_IOCTL_EP0/EP_WRITE. Buffer to store received
|
||||
* data for USB_RAW_IOCTL_EP0/EP_READ.
|
||||
*/
|
||||
struct usb_raw_ep_io {
|
||||
__u16 ep;
|
||||
__u16 flags;
|
||||
__u32 length;
|
||||
__u8 data[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Initializes a Raw Gadget instance.
|
||||
* Accepts a pointer to the usb_raw_init struct as an argument.
|
||||
* Returns 0 on success or negative error code on failure.
|
||||
*/
|
||||
#define USB_RAW_IOCTL_INIT _IOW('U', 0, struct usb_raw_init)
|
||||
|
||||
/*
|
||||
* Instructs Raw Gadget to bind to a UDC and start emulating a USB device.
|
||||
* Returns 0 on success or negative error code on failure.
|
||||
*/
|
||||
#define USB_RAW_IOCTL_RUN _IO('U', 1)
|
||||
|
||||
/*
|
||||
* A blocking ioctl that waits for an event and returns fetched event data to
|
||||
* the user.
|
||||
* Accepts a pointer to the usb_raw_event struct.
|
||||
* Returns 0 on success or negative error code on failure.
|
||||
*/
|
||||
#define USB_RAW_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_raw_event)
|
||||
|
||||
/*
|
||||
* Queues an IN (OUT for READ) urb as a response to the last control request
|
||||
* received on endpoint 0, provided that was an IN (OUT for READ) request and
|
||||
* waits until the urb is completed. Copies received data to user for READ.
|
||||
* Accepts a pointer to the usb_raw_ep_io struct as an argument.
|
||||
* Returns length of trasferred data on success or negative error code on
|
||||
* failure.
|
||||
*/
|
||||
#define USB_RAW_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_raw_ep_io)
|
||||
#define USB_RAW_IOCTL_EP0_READ _IOWR('U', 4, struct usb_raw_ep_io)
|
||||
|
||||
/*
|
||||
* Finds an endpoint that supports the transfer type specified in the
|
||||
* descriptor and enables it.
|
||||
* Accepts a pointer to the usb_endpoint_descriptor struct as an argument.
|
||||
* Returns enabled endpoint handle on success or negative error code on failure.
|
||||
*/
|
||||
#define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor)
|
||||
|
||||
/* Disables specified endpoint.
|
||||
* Accepts endpoint handle as an argument.
|
||||
* Returns 0 on success or negative error code on failure.
|
||||
*/
|
||||
#define USB_RAW_IOCTL_EP_DISABLE _IOW('U', 6, __u32)
|
||||
|
||||
/*
|
||||
* Queues an IN (OUT for READ) urb as a response to the last control request
|
||||
* received on endpoint usb_raw_ep_io.ep, provided that was an IN (OUT for READ)
|
||||
* request and waits until the urb is completed. Copies received data to user
|
||||
* for READ.
|
||||
* Accepts a pointer to the usb_raw_ep_io struct as an argument.
|
||||
* Returns length of trasferred data on success or negative error code on
|
||||
* failure.
|
||||
*/
|
||||
#define USB_RAW_IOCTL_EP_WRITE _IOW('U', 7, struct usb_raw_ep_io)
|
||||
#define USB_RAW_IOCTL_EP_READ _IOWR('U', 8, struct usb_raw_ep_io)
|
||||
|
||||
/*
|
||||
* Switches the gadget into the configured state.
|
||||
* Returns 0 on success or negative error code on failure.
|
||||
*/
|
||||
#define USB_RAW_IOCTL_CONFIGURE _IO('U', 9)
|
||||
|
||||
/*
|
||||
* Constrains UDC VBUS power usage.
|
||||
* Accepts current limit in 2 mA units as an argument.
|
||||
* Returns 0 on success or negative error code on failure.
|
||||
*/
|
||||
#define USB_RAW_IOCTL_VBUS_DRAW _IOW('U', 10, __u32)
|
||||
|
||||
#endif /* _UAPI__LINUX_USB_RAW_GADGET_H */
|
Loading…
Reference in New Issue
Block a user