Linux USB gadget (g hid)

From RidgeRun Developer Wiki


In this wiki we provide the basic information required to use the Linux HID gadget driver. HID gadget is an interface provided by Linux to emulate HID USB devices, so for instance using this interface one can emulate a mouse, a keyboard or a joystick in a board, so that when this board is connected to another device, say, a laptop or cell phone (via usb OTG), it can be used as the device that emulates.

Enable Module

You will need to have the HID gadget driver enabled in order to be able to use it. In case that you are using RidgeRun's SDK, the following is the route to enable the module, make sure to choose "m" in "USB Gadget Drivers".

 Symbol: USB_G_HID [=m]                                                                                                                                           
  │ Prompt: HID Gadget                                                                                                                                             
  │   Defined at drivers/usb/gadget/Kconfig:1132                                                                                                                   
  │   Depends on: <choice>                                                                                                                                        
  │   Location:                                                                                                                                                    
  │     -> Kernel configuration                                                                                                                                    
  │       -> Device Drivers                                                                                                                                        
  │         -> USB support (USB_SUPPORT [=y])                                                                                                                      
  │           -> USB Gadget Support (USB_GADGET [=y])                                                                                                              
  │             -> USB Gadget Drivers (<choice> [=m])

Add the device to emulate

You need to add the device in the kernel gadget driver ($DEVDIR/kernel/linux-3.14.52/drivers/usb/gadget/hid.c). For this you will need the structures described below:

Emulated device descriptor

struct hidg_func_descriptor {
	unsigned char		subclass;
	unsigned char		protocol;
	unsigned short		report_length;
	unsigned short		report_desc_length;
	unsigned char		report_desc[];
};

Plataform device

struct platform_device {
	const char	*name;
	int		id;
	bool		id_auto;
	struct device	dev;
	u32		num_resources;
	struct resource	*resource;

	const struct platform_device_id	*id_entry;
	char *driver_override; /* Driver name to force a match */

	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;

	/* arch specific additions */
	struct pdev_archdata	archdata;
};

An example on how to fill these structures is provided here for emulating a keyboard. If you want to implement something different than a keyboard, your report_desc[] should look different than the keyboard's, there are some examples in the Appendix D and E of the "Device Class Definition for Human Interface Devices (HID) Version 1.11".

Basically the report descriptor is a structure that informs the host of the operations performed by the device (the board emulating the gadget). You need to define there the kind of values (buttons, positions) that your gadget will emulate, let's take a very simple pointer device to understand device descriptors:

Usage Page (Generic Desktop),
Usage (Mouse),
 Collection (Application),
 Usage (Pointer),
 Collection (Physical),
 Usage Page (Generic Desktop),
 Usage (X),
 Usage (Y),
 Logical Minimum (-127),
 Logical Maximum (127),
 Report Size (8),
 Report Count (2),
 Input (Data, Variable, Relative), ;2 position bytes (X & Y)
 End Collection,
End Collection

All the possible options available to create a report for an HID gadget are described here along with the corresponding numerical values. Each report item "Usage Page (Generic Desktop)" for instance, corresponds to the value "0x01", these values are going to be the contents of the report_desc[] array in the hidg_func_descriptor struct.

This example report descriptor defines two slots of 8 bits each, this slots could take values from -127 to 127. IN memory, the report would look like this:

x value [-127,127]
y value [-127,127]

The "Input (Data, Variable, Relative)" indicates the direction of the data flow and that is a Relative value (x and y are relative to their previous positions). I you want to accept data in the device, use "Output ()", this is useful for example in a keyboard after pressing the "Caps Lock" key to turn on the led. usb.org offers this tool to create the report descriptor more easily but it only works in windows.

Important links: http://www.usb.org/developers/hidpage/