Merge tag 'trace-v5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux...
[linux-2.6-block.git] / Documentation / usb / gadget_hid.rst
CommitLineData
d80b5005
MCC
1===========================
2Linux USB HID gadget driver
3===========================
71adf118
FC
4
5Introduction
d80b5005 6============
71adf118 7
d80b5005
MCC
8The HID Gadget driver provides emulation of USB Human Interface
9Devices (HID). The basic HID handling is done in the kernel,
10and HID reports can be sent/received through I/O on the
11/dev/hidgX character devices.
71adf118 12
d80b5005
MCC
13For more details about HID, see the developer page on
14http://www.usb.org/developers/hidpage/
71adf118
FC
15
16Configuration
d80b5005 17=============
71adf118 18
d80b5005
MCC
19g_hid is a platform driver, so to use it you need to add
20struct platform_device(s) to your platform code defining the
21HID function descriptors you want to use - E.G. something
22like::
71adf118 23
d80b5005
MCC
24 #include <linux/platform_device.h>
25 #include <linux/usb/g_hid.h>
71adf118 26
d80b5005
MCC
27 /* hid descriptor for a keyboard */
28 static struct hidg_func_descriptor my_hid_data = {
71adf118
FC
29 .subclass = 0, /* No subclass */
30 .protocol = 1, /* Keyboard */
31 .report_length = 8,
32 .report_desc_length = 63,
33 .report_desc = {
34 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
35 0x09, 0x06, /* USAGE (Keyboard) */
36 0xa1, 0x01, /* COLLECTION (Application) */
37 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
38 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */
39 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */
40 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
41 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
42 0x75, 0x01, /* REPORT_SIZE (1) */
43 0x95, 0x08, /* REPORT_COUNT (8) */
44 0x81, 0x02, /* INPUT (Data,Var,Abs) */
45 0x95, 0x01, /* REPORT_COUNT (1) */
46 0x75, 0x08, /* REPORT_SIZE (8) */
47 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
48 0x95, 0x05, /* REPORT_COUNT (5) */
49 0x75, 0x01, /* REPORT_SIZE (1) */
50 0x05, 0x08, /* USAGE_PAGE (LEDs) */
51 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
52 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
53 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
54 0x95, 0x01, /* REPORT_COUNT (1) */
55 0x75, 0x03, /* REPORT_SIZE (3) */
56 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
57 0x95, 0x06, /* REPORT_COUNT (6) */
58 0x75, 0x08, /* REPORT_SIZE (8) */
59 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
60 0x25, 0x65, /* LOGICAL_MAXIMUM (101) */
61 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
62 0x19, 0x00, /* USAGE_MINIMUM (Reserved) */
63 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */
64 0x81, 0x00, /* INPUT (Data,Ary,Abs) */
65 0xc0 /* END_COLLECTION */
66 }
d80b5005 67 };
71adf118 68
d80b5005 69 static struct platform_device my_hid = {
71adf118
FC
70 .name = "hidg",
71 .id = 0,
72 .num_resources = 0,
73 .resource = 0,
74 .dev.platform_data = &my_hid_data,
d80b5005 75 };
71adf118 76
d80b5005
MCC
77You can add as many HID functions as you want, only limited by
78the amount of interrupt endpoints your gadget driver supports.
71adf118 79
21a9476a 80Configuration with configfs
d80b5005 81===========================
21a9476a 82
d80b5005
MCC
83Instead of adding fake platform devices and drivers in order to pass
84some data to the kernel, if HID is a part of a gadget composed with
85configfs the hidg_func_descriptor.report_desc is passed to the kernel
86by writing the appropriate stream of bytes to a configfs attribute.
21a9476a 87
71adf118 88Send and receive HID reports
d80b5005 89============================
71adf118 90
d80b5005
MCC
91HID reports can be sent/received using read/write on the
92/dev/hidgX character devices. See below for an example program
93to do this.
71adf118 94
d80b5005
MCC
95hid_gadget_test is a small interactive program to test the HID
96gadget driver. To use, point it at a hidg device and set the
97device type (keyboard / mouse / joystick) - E.G.::
71adf118 98
d80b5005 99 # hid_gadget_test /dev/hidg0 keyboard
71adf118 100
d80b5005
MCC
101You are now in the prompt of hid_gadget_test. You can type any
102combination of options and values. Available options and
103values are listed at program start. In keyboard mode you can
104send up to six values.
71adf118 105
d80b5005 106For example type: g i s t r --left-shift
71adf118 107
d80b5005
MCC
108Hit return and the corresponding report will be sent by the
109HID gadget.
71adf118 110
d80b5005
MCC
111Another interesting example is the caps lock test. Type
112--caps-lock and hit return. A report is then sent by the
113gadget and you should receive the host answer, corresponding
114to the caps lock LED status::
71adf118 115
d80b5005
MCC
116 --caps-lock
117 recv report:2
71adf118 118
d80b5005 119With this command::
71adf118 120
d80b5005 121 # hid_gadget_test /dev/hidg1 mouse
71adf118 122
d80b5005 123You can test the mouse emulation. Values are two signed numbers.
71adf118
FC
124
125
d80b5005 126Sample code::
71adf118 127
d80b5005 128 /* hid_gadget_test */
71adf118 129
d80b5005
MCC
130 #include <pthread.h>
131 #include <string.h>
132 #include <stdio.h>
133 #include <ctype.h>
134 #include <fcntl.h>
135 #include <errno.h>
136 #include <stdio.h>
137 #include <stdlib.h>
138 #include <unistd.h>
71adf118 139
d80b5005 140 #define BUF_LEN 512
71adf118 141
d80b5005 142 struct options {
71adf118
FC
143 const char *opt;
144 unsigned char val;
d80b5005 145 };
71adf118 146
d80b5005 147 static struct options kmod[] = {
71adf118
FC
148 {.opt = "--left-ctrl", .val = 0x01},
149 {.opt = "--right-ctrl", .val = 0x10},
150 {.opt = "--left-shift", .val = 0x02},
151 {.opt = "--right-shift", .val = 0x20},
152 {.opt = "--left-alt", .val = 0x04},
153 {.opt = "--right-alt", .val = 0x40},
154 {.opt = "--left-meta", .val = 0x08},
155 {.opt = "--right-meta", .val = 0x80},
156 {.opt = NULL}
d80b5005 157 };
71adf118 158
d80b5005 159 static struct options kval[] = {
71adf118
FC
160 {.opt = "--return", .val = 0x28},
161 {.opt = "--esc", .val = 0x29},
162 {.opt = "--bckspc", .val = 0x2a},
163 {.opt = "--tab", .val = 0x2b},
164 {.opt = "--spacebar", .val = 0x2c},
165 {.opt = "--caps-lock", .val = 0x39},
166 {.opt = "--f1", .val = 0x3a},
167 {.opt = "--f2", .val = 0x3b},
168 {.opt = "--f3", .val = 0x3c},
169 {.opt = "--f4", .val = 0x3d},
170 {.opt = "--f5", .val = 0x3e},
171 {.opt = "--f6", .val = 0x3f},
172 {.opt = "--f7", .val = 0x40},
173 {.opt = "--f8", .val = 0x41},
174 {.opt = "--f9", .val = 0x42},
175 {.opt = "--f10", .val = 0x43},
176 {.opt = "--f11", .val = 0x44},
177 {.opt = "--f12", .val = 0x45},
178 {.opt = "--insert", .val = 0x49},
179 {.opt = "--home", .val = 0x4a},
180 {.opt = "--pageup", .val = 0x4b},
181 {.opt = "--del", .val = 0x4c},
182 {.opt = "--end", .val = 0x4d},
183 {.opt = "--pagedown", .val = 0x4e},
184 {.opt = "--right", .val = 0x4f},
185 {.opt = "--left", .val = 0x50},
186 {.opt = "--down", .val = 0x51},
187 {.opt = "--kp-enter", .val = 0x58},
188 {.opt = "--up", .val = 0x52},
189 {.opt = "--num-lock", .val = 0x53},
190 {.opt = NULL}
d80b5005 191 };
71adf118 192
d80b5005
MCC
193 int keyboard_fill_report(char report[8], char buf[BUF_LEN], int *hold)
194 {
71adf118
FC
195 char *tok = strtok(buf, " ");
196 int key = 0;
197 int i = 0;
198
199 for (; tok != NULL; tok = strtok(NULL, " ")) {
200
201 if (strcmp(tok, "--quit") == 0)
202 return -1;
203
204 if (strcmp(tok, "--hold") == 0) {
205 *hold = 1;
206 continue;
207 }
208
209 if (key < 6) {
210 for (i = 0; kval[i].opt != NULL; i++)
211 if (strcmp(tok, kval[i].opt) == 0) {
212 report[2 + key++] = kval[i].val;
213 break;
214 }
215 if (kval[i].opt != NULL)
216 continue;
217 }
218
219 if (key < 6)
220 if (islower(tok[0])) {
221 report[2 + key++] = (tok[0] - ('a' - 0x04));
222 continue;
223 }
224
225 for (i = 0; kmod[i].opt != NULL; i++)
226 if (strcmp(tok, kmod[i].opt) == 0) {
227 report[0] = report[0] | kmod[i].val;
228 break;
229 }
230 if (kmod[i].opt != NULL)
231 continue;
232
233 if (key < 6)
234 fprintf(stderr, "unknown option: %s\n", tok);
235 }
236 return 8;
d80b5005 237 }
71adf118 238
d80b5005 239 static struct options mmod[] = {
71adf118
FC
240 {.opt = "--b1", .val = 0x01},
241 {.opt = "--b2", .val = 0x02},
242 {.opt = "--b3", .val = 0x04},
243 {.opt = NULL}
d80b5005 244 };
71adf118 245
d80b5005
MCC
246 int mouse_fill_report(char report[8], char buf[BUF_LEN], int *hold)
247 {
71adf118
FC
248 char *tok = strtok(buf, " ");
249 int mvt = 0;
250 int i = 0;
251 for (; tok != NULL; tok = strtok(NULL, " ")) {
252
253 if (strcmp(tok, "--quit") == 0)
254 return -1;
255
256 if (strcmp(tok, "--hold") == 0) {
257 *hold = 1;
258 continue;
259 }
260
261 for (i = 0; mmod[i].opt != NULL; i++)
262 if (strcmp(tok, mmod[i].opt) == 0) {
263 report[0] = report[0] | mmod[i].val;
264 break;
265 }
266 if (mmod[i].opt != NULL)
267 continue;
268
269 if (!(tok[0] == '-' && tok[1] == '-') && mvt < 2) {
270 errno = 0;
271 report[1 + mvt++] = (char)strtol(tok, NULL, 0);
272 if (errno != 0) {
273 fprintf(stderr, "Bad value:'%s'\n", tok);
274 report[1 + mvt--] = 0;
275 }
276 continue;
277 }
278
279 fprintf(stderr, "unknown option: %s\n", tok);
280 }
281 return 3;
d80b5005 282 }
71adf118 283
d80b5005 284 static struct options jmod[] = {
71adf118
FC
285 {.opt = "--b1", .val = 0x10},
286 {.opt = "--b2", .val = 0x20},
287 {.opt = "--b3", .val = 0x40},
288 {.opt = "--b4", .val = 0x80},
289 {.opt = "--hat1", .val = 0x00},
290 {.opt = "--hat2", .val = 0x01},
291 {.opt = "--hat3", .val = 0x02},
292 {.opt = "--hat4", .val = 0x03},
293 {.opt = "--hatneutral", .val = 0x04},
294 {.opt = NULL}
d80b5005 295 };
71adf118 296
d80b5005
MCC
297 int joystick_fill_report(char report[8], char buf[BUF_LEN], int *hold)
298 {
71adf118
FC
299 char *tok = strtok(buf, " ");
300 int mvt = 0;
301 int i = 0;
302
303 *hold = 1;
304
305 /* set default hat position: neutral */
306 report[3] = 0x04;
307
308 for (; tok != NULL; tok = strtok(NULL, " ")) {
309
310 if (strcmp(tok, "--quit") == 0)
311 return -1;
312
313 for (i = 0; jmod[i].opt != NULL; i++)
314 if (strcmp(tok, jmod[i].opt) == 0) {
315 report[3] = (report[3] & 0xF0) | jmod[i].val;
316 break;
317 }
318 if (jmod[i].opt != NULL)
319 continue;
320
321 if (!(tok[0] == '-' && tok[1] == '-') && mvt < 3) {
322 errno = 0;
323 report[mvt++] = (char)strtol(tok, NULL, 0);
324 if (errno != 0) {
325 fprintf(stderr, "Bad value:'%s'\n", tok);
326 report[mvt--] = 0;
327 }
328 continue;
329 }
330
331 fprintf(stderr, "unknown option: %s\n", tok);
332 }
333 return 4;
d80b5005 334 }
71adf118 335
d80b5005
MCC
336 void print_options(char c)
337 {
71adf118
FC
338 int i = 0;
339
340 if (c == 'k') {
341 printf(" keyboard options:\n"
342 " --hold\n");
343 for (i = 0; kmod[i].opt != NULL; i++)
344 printf("\t\t%s\n", kmod[i].opt);
345 printf("\n keyboard values:\n"
346 " [a-z] or\n");
347 for (i = 0; kval[i].opt != NULL; i++)
348 printf("\t\t%-8s%s", kval[i].opt, i % 2 ? "\n" : "");
349 printf("\n");
350 } else if (c == 'm') {
351 printf(" mouse options:\n"
352 " --hold\n");
353 for (i = 0; mmod[i].opt != NULL; i++)
354 printf("\t\t%s\n", mmod[i].opt);
355 printf("\n mouse values:\n"
356 " Two signed numbers\n"
357 "--quit to close\n");
358 } else {
359 printf(" joystick options:\n");
360 for (i = 0; jmod[i].opt != NULL; i++)
361 printf("\t\t%s\n", jmod[i].opt);
362 printf("\n joystick values:\n"
363 " three signed numbers\n"
364 "--quit to close\n");
365 }
d80b5005 366 }
71adf118 367
d80b5005
MCC
368 int main(int argc, const char *argv[])
369 {
71adf118
FC
370 const char *filename = NULL;
371 int fd = 0;
372 char buf[BUF_LEN];
373 int cmd_len;
374 char report[8];
375 int to_send = 8;
376 int hold = 0;
377 fd_set rfds;
378 int retval, i;
379
380 if (argc < 3) {
381 fprintf(stderr, "Usage: %s devname mouse|keyboard|joystick\n",
382 argv[0]);
383 return 1;
384 }
385
386 if (argv[2][0] != 'k' && argv[2][0] != 'm' && argv[2][0] != 'j')
387 return 2;
388
389 filename = argv[1];
390
391 if ((fd = open(filename, O_RDWR, 0666)) == -1) {
392 perror(filename);
393 return 3;
394 }
395
396 print_options(argv[2][0]);
397
398 while (42) {
399
400 FD_ZERO(&rfds);
401 FD_SET(STDIN_FILENO, &rfds);
402 FD_SET(fd, &rfds);
403
404 retval = select(fd + 1, &rfds, NULL, NULL, NULL);
405 if (retval == -1 && errno == EINTR)
406 continue;
407 if (retval < 0) {
408 perror("select()");
409 return 4;
410 }
411
412 if (FD_ISSET(fd, &rfds)) {
413 cmd_len = read(fd, buf, BUF_LEN - 1);
414 printf("recv report:");
415 for (i = 0; i < cmd_len; i++)
416 printf(" %02x", buf[i]);
417 printf("\n");
418 }
419
420 if (FD_ISSET(STDIN_FILENO, &rfds)) {
421 memset(report, 0x0, sizeof(report));
422 cmd_len = read(STDIN_FILENO, buf, BUF_LEN - 1);
423
424 if (cmd_len == 0)
425 break;
426
427 buf[cmd_len - 1] = '\0';
428 hold = 0;
429
430 memset(report, 0x0, sizeof(report));
431 if (argv[2][0] == 'k')
432 to_send = keyboard_fill_report(report, buf, &hold);
433 else if (argv[2][0] == 'm')
434 to_send = mouse_fill_report(report, buf, &hold);
435 else
436 to_send = joystick_fill_report(report, buf, &hold);
437
438 if (to_send == -1)
439 break;
440
441 if (write(fd, report, to_send) != to_send) {
442 perror(filename);
443 return 5;
444 }
445 if (!hold) {
446 memset(report, 0x0, sizeof(report));
447 if (write(fd, report, to_send) != to_send) {
448 perror(filename);
449 return 6;
450 }
451 }
452 }
453 }
454
455 close(fd);
456 return 0;
d80b5005 457 }