2 Linux USB HID gadget driver
6 The HID Gadget driver provides emulation of USB Human Interface
7 Devices (HID). The basic HID handling is done in the kernel,
8 and HID reports can be sent/received through I/O on the
9 /dev/hidgX character devices.
11 For more details about HID, see the developer page on
12 http://www.usb.org/developers/hidpage/
16 g_hid is a platform driver, so to use it you need to add
17 struct platform_device(s) to your platform code defining the
18 HID function descriptors you want to use - E.G. something
21 #include <linux/platform_device.h>
22 #include <linux/usb/g_hid.h>
24 /* hid descriptor for a keyboard */
25 static struct hidg_func_descriptor my_hid_data = {
26 .subclass = 0, /* No subclass */
27 .protocol = 1, /* Keyboard */
29 .report_desc_length = 63,
31 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
32 0x09, 0x06, /* USAGE (Keyboard) */
33 0xa1, 0x01, /* COLLECTION (Application) */
34 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
35 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */
36 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */
37 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
38 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
39 0x75, 0x01, /* REPORT_SIZE (1) */
40 0x95, 0x08, /* REPORT_COUNT (8) */
41 0x81, 0x02, /* INPUT (Data,Var,Abs) */
42 0x95, 0x01, /* REPORT_COUNT (1) */
43 0x75, 0x08, /* REPORT_SIZE (8) */
44 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
45 0x95, 0x05, /* REPORT_COUNT (5) */
46 0x75, 0x01, /* REPORT_SIZE (1) */
47 0x05, 0x08, /* USAGE_PAGE (LEDs) */
48 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
49 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
50 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
51 0x95, 0x01, /* REPORT_COUNT (1) */
52 0x75, 0x03, /* REPORT_SIZE (3) */
53 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
54 0x95, 0x06, /* REPORT_COUNT (6) */
55 0x75, 0x08, /* REPORT_SIZE (8) */
56 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
57 0x25, 0x65, /* LOGICAL_MAXIMUM (101) */
58 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
59 0x19, 0x00, /* USAGE_MINIMUM (Reserved) */
60 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */
61 0x81, 0x00, /* INPUT (Data,Ary,Abs) */
62 0xc0 /* END_COLLECTION */
66 static struct platform_device my_hid = {
71 .dev.platform_data = &my_hid_data,
74 You can add as many HID functions as you want, only limited by
75 the amount of interrupt endpoints your gadget driver supports.
77 Configuration with configfs
79 Instead of adding fake platform devices and drivers in order to pass
80 some data to the kernel, if HID is a part of a gadget composed with
81 configfs the hidg_func_descriptor.report_desc is passed to the kernel
82 by writing the appropriate stream of bytes to a configfs attribute.
84 Send and receive HID reports
86 HID reports can be sent/received using read/write on the
87 /dev/hidgX character devices. See below for an example program
90 hid_gadget_test is a small interactive program to test the HID
91 gadget driver. To use, point it at a hidg device and set the
92 device type (keyboard / mouse / joystick) - E.G.:
94 # hid_gadget_test /dev/hidg0 keyboard
96 You are now in the prompt of hid_gadget_test. You can type any
97 combination of options and values. Available options and
98 values are listed at program start. In keyboard mode you can
99 send up to six values.
101 For example type: g i s t r --left-shift
103 Hit return and the corresponding report will be sent by the
106 Another interesting example is the caps lock test. Type
107 --caps-lock and hit return. A report is then sent by the
108 gadget and you should receive the host answer, corresponding
109 to the caps lock LED status.
116 # hid_gadget_test /dev/hidg1 mouse
118 You can test the mouse emulation. Values are two signed numbers.
123 /* hid_gadget_test */
142 static struct options kmod[] = {
143 {.opt = "--left-ctrl", .val = 0x01},
144 {.opt = "--right-ctrl", .val = 0x10},
145 {.opt = "--left-shift", .val = 0x02},
146 {.opt = "--right-shift", .val = 0x20},
147 {.opt = "--left-alt", .val = 0x04},
148 {.opt = "--right-alt", .val = 0x40},
149 {.opt = "--left-meta", .val = 0x08},
150 {.opt = "--right-meta", .val = 0x80},
154 static struct options kval[] = {
155 {.opt = "--return", .val = 0x28},
156 {.opt = "--esc", .val = 0x29},
157 {.opt = "--bckspc", .val = 0x2a},
158 {.opt = "--tab", .val = 0x2b},
159 {.opt = "--spacebar", .val = 0x2c},
160 {.opt = "--caps-lock", .val = 0x39},
161 {.opt = "--f1", .val = 0x3a},
162 {.opt = "--f2", .val = 0x3b},
163 {.opt = "--f3", .val = 0x3c},
164 {.opt = "--f4", .val = 0x3d},
165 {.opt = "--f5", .val = 0x3e},
166 {.opt = "--f6", .val = 0x3f},
167 {.opt = "--f7", .val = 0x40},
168 {.opt = "--f8", .val = 0x41},
169 {.opt = "--f9", .val = 0x42},
170 {.opt = "--f10", .val = 0x43},
171 {.opt = "--f11", .val = 0x44},
172 {.opt = "--f12", .val = 0x45},
173 {.opt = "--insert", .val = 0x49},
174 {.opt = "--home", .val = 0x4a},
175 {.opt = "--pageup", .val = 0x4b},
176 {.opt = "--del", .val = 0x4c},
177 {.opt = "--end", .val = 0x4d},
178 {.opt = "--pagedown", .val = 0x4e},
179 {.opt = "--right", .val = 0x4f},
180 {.opt = "--left", .val = 0x50},
181 {.opt = "--down", .val = 0x51},
182 {.opt = "--kp-enter", .val = 0x58},
183 {.opt = "--up", .val = 0x52},
184 {.opt = "--num-lock", .val = 0x53},
188 int keyboard_fill_report(char report[8], char buf[BUF_LEN], int *hold)
190 char *tok = strtok(buf, " ");
194 for (; tok != NULL; tok = strtok(NULL, " ")) {
196 if (strcmp(tok, "--quit") == 0)
199 if (strcmp(tok, "--hold") == 0) {
205 for (i = 0; kval[i].opt != NULL; i++)
206 if (strcmp(tok, kval[i].opt) == 0) {
207 report[2 + key++] = kval[i].val;
210 if (kval[i].opt != NULL)
215 if (islower(tok[0])) {
216 report[2 + key++] = (tok[0] - ('a' - 0x04));
220 for (i = 0; kmod[i].opt != NULL; i++)
221 if (strcmp(tok, kmod[i].opt) == 0) {
222 report[0] = report[0] | kmod[i].val;
225 if (kmod[i].opt != NULL)
229 fprintf(stderr, "unknown option: %s\n", tok);
234 static struct options mmod[] = {
235 {.opt = "--b1", .val = 0x01},
236 {.opt = "--b2", .val = 0x02},
237 {.opt = "--b3", .val = 0x04},
241 int mouse_fill_report(char report[8], char buf[BUF_LEN], int *hold)
243 char *tok = strtok(buf, " ");
246 for (; tok != NULL; tok = strtok(NULL, " ")) {
248 if (strcmp(tok, "--quit") == 0)
251 if (strcmp(tok, "--hold") == 0) {
256 for (i = 0; mmod[i].opt != NULL; i++)
257 if (strcmp(tok, mmod[i].opt) == 0) {
258 report[0] = report[0] | mmod[i].val;
261 if (mmod[i].opt != NULL)
264 if (!(tok[0] == '-' && tok[1] == '-') && mvt < 2) {
266 report[1 + mvt++] = (char)strtol(tok, NULL, 0);
268 fprintf(stderr, "Bad value:'%s'\n", tok);
269 report[1 + mvt--] = 0;
274 fprintf(stderr, "unknown option: %s\n", tok);
279 static struct options jmod[] = {
280 {.opt = "--b1", .val = 0x10},
281 {.opt = "--b2", .val = 0x20},
282 {.opt = "--b3", .val = 0x40},
283 {.opt = "--b4", .val = 0x80},
284 {.opt = "--hat1", .val = 0x00},
285 {.opt = "--hat2", .val = 0x01},
286 {.opt = "--hat3", .val = 0x02},
287 {.opt = "--hat4", .val = 0x03},
288 {.opt = "--hatneutral", .val = 0x04},
292 int joystick_fill_report(char report[8], char buf[BUF_LEN], int *hold)
294 char *tok = strtok(buf, " ");
300 /* set default hat position: neutral */
303 for (; tok != NULL; tok = strtok(NULL, " ")) {
305 if (strcmp(tok, "--quit") == 0)
308 for (i = 0; jmod[i].opt != NULL; i++)
309 if (strcmp(tok, jmod[i].opt) == 0) {
310 report[3] = (report[3] & 0xF0) | jmod[i].val;
313 if (jmod[i].opt != NULL)
316 if (!(tok[0] == '-' && tok[1] == '-') && mvt < 3) {
318 report[mvt++] = (char)strtol(tok, NULL, 0);
320 fprintf(stderr, "Bad value:'%s'\n", tok);
326 fprintf(stderr, "unknown option: %s\n", tok);
331 void print_options(char c)
336 printf(" keyboard options:\n"
338 for (i = 0; kmod[i].opt != NULL; i++)
339 printf("\t\t%s\n", kmod[i].opt);
340 printf("\n keyboard values:\n"
342 for (i = 0; kval[i].opt != NULL; i++)
343 printf("\t\t%-8s%s", kval[i].opt, i % 2 ? "\n" : "");
345 } else if (c == 'm') {
346 printf(" mouse options:\n"
348 for (i = 0; mmod[i].opt != NULL; i++)
349 printf("\t\t%s\n", mmod[i].opt);
350 printf("\n mouse values:\n"
351 " Two signed numbers\n"
352 "--quit to close\n");
354 printf(" joystick options:\n");
355 for (i = 0; jmod[i].opt != NULL; i++)
356 printf("\t\t%s\n", jmod[i].opt);
357 printf("\n joystick values:\n"
358 " three signed numbers\n"
359 "--quit to close\n");
363 int main(int argc, const char *argv[])
365 const char *filename = NULL;
376 fprintf(stderr, "Usage: %s devname mouse|keyboard|joystick\n",
381 if (argv[2][0] != 'k' && argv[2][0] != 'm' && argv[2][0] != 'j')
386 if ((fd = open(filename, O_RDWR, 0666)) == -1) {
391 print_options(argv[2][0]);
396 FD_SET(STDIN_FILENO, &rfds);
399 retval = select(fd + 1, &rfds, NULL, NULL, NULL);
400 if (retval == -1 && errno == EINTR)
407 if (FD_ISSET(fd, &rfds)) {
408 cmd_len = read(fd, buf, BUF_LEN - 1);
409 printf("recv report:");
410 for (i = 0; i < cmd_len; i++)
411 printf(" %02x", buf[i]);
415 if (FD_ISSET(STDIN_FILENO, &rfds)) {
416 memset(report, 0x0, sizeof(report));
417 cmd_len = read(STDIN_FILENO, buf, BUF_LEN - 1);
422 buf[cmd_len - 1] = '\0';
425 memset(report, 0x0, sizeof(report));
426 if (argv[2][0] == 'k')
427 to_send = keyboard_fill_report(report, buf, &hold);
428 else if (argv[2][0] == 'm')
429 to_send = mouse_fill_report(report, buf, &hold);
431 to_send = joystick_fill_report(report, buf, &hold);
436 if (write(fd, report, to_send) != to_send) {
441 memset(report, 0x0, sizeof(report));
442 if (write(fd, report, to_send) != to_send) {