asm-generic/atomic.h: allow SMP peeps to leverage this
[linux-2.6/kvm.git] / Documentation / usb / gadget_hid.txt
blob12696c2e43fb1391b52b09d4ca405cfd1d7bce9d
2                      Linux USB HID gadget driver
4 Introduction
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/
14 Configuration
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
19         like:
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 */
28         .report_length          = 8,
29         .report_desc_length     = 63,
30         .report_desc            = {
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                         */
63         }
66 static struct platform_device my_hid = {
67         .name                   = "hidg",
68         .id                     = 0,
69         .num_resources          = 0,
70         .resource               = 0,
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 Send and receive HID reports
79         HID reports can be sent/received using read/write on the
80         /dev/hidgX character devices. See below for an example program
81         to do this.
83         hid_gadget_test is a small interactive program to test the HID
84         gadget driver. To use, point it at a hidg device and set the
85         device type (keyboard / mouse / joystick) - E.G.:
87                 # hid_gadget_test /dev/hidg0 keyboard
89         You are now in the prompt of hid_gadget_test. You can type any
90         combination of options and values. Available options and
91         values are listed at program start. In keyboard mode you can
92         send up to six values.
94         For example type: g i s t r --left-shift
96         Hit return and the corresponding report will be sent by the
97         HID gadget.
99         Another interesting example is the caps lock test. Type
100         --caps-lock and hit return. A report is then sent by the
101         gadget and you should receive the host answer, corresponding
102         to the caps lock LED status.
104                 --caps-lock
105                 recv report:2
107         With this command:
109                 # hid_gadget_test /dev/hidg1 mouse
111         You can test the mouse emulation. Values are two signed numbers.
114 Sample code
116 /* hid_gadget_test */
118 #include <pthread.h>
119 #include <string.h>
120 #include <stdio.h>
121 #include <ctype.h>
122 #include <fcntl.h>
123 #include <errno.h>
124 #include <stdio.h>
125 #include <stdlib.h>
126 #include <unistd.h>
128 #define BUF_LEN 512
130 struct options {
131         const char    *opt;
132         unsigned char val;
135 static struct options kmod[] = {
136         {.opt = "--left-ctrl",          .val = 0x01},
137         {.opt = "--right-ctrl",         .val = 0x10},
138         {.opt = "--left-shift",         .val = 0x02},
139         {.opt = "--right-shift",        .val = 0x20},
140         {.opt = "--left-alt",           .val = 0x04},
141         {.opt = "--right-alt",          .val = 0x40},
142         {.opt = "--left-meta",          .val = 0x08},
143         {.opt = "--right-meta",         .val = 0x80},
144         {.opt = NULL}
147 static struct options kval[] = {
148         {.opt = "--return",     .val = 0x28},
149         {.opt = "--esc",        .val = 0x29},
150         {.opt = "--bckspc",     .val = 0x2a},
151         {.opt = "--tab",        .val = 0x2b},
152         {.opt = "--spacebar",   .val = 0x2c},
153         {.opt = "--caps-lock",  .val = 0x39},
154         {.opt = "--f1",         .val = 0x3a},
155         {.opt = "--f2",         .val = 0x3b},
156         {.opt = "--f3",         .val = 0x3c},
157         {.opt = "--f4",         .val = 0x3d},
158         {.opt = "--f5",         .val = 0x3e},
159         {.opt = "--f6",         .val = 0x3f},
160         {.opt = "--f7",         .val = 0x40},
161         {.opt = "--f8",         .val = 0x41},
162         {.opt = "--f9",         .val = 0x42},
163         {.opt = "--f10",        .val = 0x43},
164         {.opt = "--f11",        .val = 0x44},
165         {.opt = "--f12",        .val = 0x45},
166         {.opt = "--insert",     .val = 0x49},
167         {.opt = "--home",       .val = 0x4a},
168         {.opt = "--pageup",     .val = 0x4b},
169         {.opt = "--del",        .val = 0x4c},
170         {.opt = "--end",        .val = 0x4d},
171         {.opt = "--pagedown",   .val = 0x4e},
172         {.opt = "--right",      .val = 0x4f},
173         {.opt = "--left",       .val = 0x50},
174         {.opt = "--down",       .val = 0x51},
175         {.opt = "--kp-enter",   .val = 0x58},
176         {.opt = "--up",         .val = 0x52},
177         {.opt = "--num-lock",   .val = 0x53},
178         {.opt = NULL}
181 int keyboard_fill_report(char report[8], char buf[BUF_LEN], int *hold)
183         char *tok = strtok(buf, " ");
184         int key = 0;
185         int i = 0;
187         for (; tok != NULL; tok = strtok(NULL, " ")) {
189                 if (strcmp(tok, "--quit") == 0)
190                         return -1;
192                 if (strcmp(tok, "--hold") == 0) {
193                         *hold = 1;
194                         continue;
195                 }
197                 if (key < 6) {
198                         for (i = 0; kval[i].opt != NULL; i++)
199                                 if (strcmp(tok, kval[i].opt) == 0) {
200                                         report[2 + key++] = kval[i].val;
201                                         break;
202                                 }
203                         if (kval[i].opt != NULL)
204                                 continue;
205                 }
207                 if (key < 6)
208                         if (islower(tok[0])) {
209                                 report[2 + key++] = (tok[0] - ('a' - 0x04));
210                                 continue;
211                         }
213                 for (i = 0; kmod[i].opt != NULL; i++)
214                         if (strcmp(tok, kmod[i].opt) == 0) {
215                                 report[0] = report[0] | kmod[i].val;
216                                 break;
217                         }
218                 if (kmod[i].opt != NULL)
219                         continue;
221                 if (key < 6)
222                         fprintf(stderr, "unknown option: %s\n", tok);
223         }
224         return 8;
227 static struct options mmod[] = {
228         {.opt = "--b1", .val = 0x01},
229         {.opt = "--b2", .val = 0x02},
230         {.opt = "--b3", .val = 0x04},
231         {.opt = NULL}
234 int mouse_fill_report(char report[8], char buf[BUF_LEN], int *hold)
236         char *tok = strtok(buf, " ");
237         int mvt = 0;
238         int i = 0;
239         for (; tok != NULL; tok = strtok(NULL, " ")) {
241                 if (strcmp(tok, "--quit") == 0)
242                         return -1;
244                 if (strcmp(tok, "--hold") == 0) {
245                         *hold = 1;
246                         continue;
247                 }
249                 for (i = 0; mmod[i].opt != NULL; i++)
250                         if (strcmp(tok, mmod[i].opt) == 0) {
251                                 report[0] = report[0] | mmod[i].val;
252                                 break;
253                         }
254                 if (mmod[i].opt != NULL)
255                         continue;
257                 if (!(tok[0] == '-' && tok[1] == '-') && mvt < 2) {
258                         errno = 0;
259                         report[1 + mvt++] = (char)strtol(tok, NULL, 0);
260                         if (errno != 0) {
261                                 fprintf(stderr, "Bad value:'%s'\n", tok);
262                                 report[1 + mvt--] = 0;
263                         }
264                         continue;
265                 }
267                 fprintf(stderr, "unknown option: %s\n", tok);
268         }
269         return 3;
272 static struct options jmod[] = {
273         {.opt = "--b1",         .val = 0x10},
274         {.opt = "--b2",         .val = 0x20},
275         {.opt = "--b3",         .val = 0x40},
276         {.opt = "--b4",         .val = 0x80},
277         {.opt = "--hat1",       .val = 0x00},
278         {.opt = "--hat2",       .val = 0x01},
279         {.opt = "--hat3",       .val = 0x02},
280         {.opt = "--hat4",       .val = 0x03},
281         {.opt = "--hatneutral", .val = 0x04},
282         {.opt = NULL}
285 int joystick_fill_report(char report[8], char buf[BUF_LEN], int *hold)
287         char *tok = strtok(buf, " ");
288         int mvt = 0;
289         int i = 0;
291         *hold = 1;
293         /* set default hat position: neutral */
294         report[3] = 0x04;
296         for (; tok != NULL; tok = strtok(NULL, " ")) {
298                 if (strcmp(tok, "--quit") == 0)
299                         return -1;
301                 for (i = 0; jmod[i].opt != NULL; i++)
302                         if (strcmp(tok, jmod[i].opt) == 0) {
303                                 report[3] = (report[3] & 0xF0) | jmod[i].val;
304                                 break;
305                         }
306                 if (jmod[i].opt != NULL)
307                         continue;
309                 if (!(tok[0] == '-' && tok[1] == '-') && mvt < 3) {
310                         errno = 0;
311                         report[mvt++] = (char)strtol(tok, NULL, 0);
312                         if (errno != 0) {
313                                 fprintf(stderr, "Bad value:'%s'\n", tok);
314                                 report[mvt--] = 0;
315                         }
316                         continue;
317                 }
319                 fprintf(stderr, "unknown option: %s\n", tok);
320         }
321         return 4;
324 void print_options(char c)
326         int i = 0;
328         if (c == 'k') {
329                 printf("        keyboard options:\n"
330                        "                --hold\n");
331                 for (i = 0; kmod[i].opt != NULL; i++)
332                         printf("\t\t%s\n", kmod[i].opt);
333                 printf("\n      keyboard values:\n"
334                        "                [a-z] or\n");
335                 for (i = 0; kval[i].opt != NULL; i++)
336                         printf("\t\t%-8s%s", kval[i].opt, i % 2 ? "\n" : "");
337                 printf("\n");
338         } else if (c == 'm') {
339                 printf("        mouse options:\n"
340                        "                --hold\n");
341                 for (i = 0; mmod[i].opt != NULL; i++)
342                         printf("\t\t%s\n", mmod[i].opt);
343                 printf("\n      mouse values:\n"
344                        "                Two signed numbers\n"
345                        "--quit to close\n");
346         } else {
347                 printf("        joystick options:\n");
348                 for (i = 0; jmod[i].opt != NULL; i++)
349                         printf("\t\t%s\n", jmod[i].opt);
350                 printf("\n      joystick values:\n"
351                        "                three signed numbers\n"
352                        "--quit to close\n");
353         }
356 int main(int argc, const char *argv[])
358         const char *filename = NULL;
359         int fd = 0;
360         char buf[BUF_LEN];
361         int cmd_len;
362         char report[8];
363         int to_send = 8;
364         int hold = 0;
365         fd_set rfds;
366         int retval, i;
368         if (argc < 3) {
369                 fprintf(stderr, "Usage: %s devname mouse|keyboard|joystick\n",
370                         argv[0]);
371                 return 1;
372         }
374         if (argv[2][0] != 'k' && argv[2][0] != 'm' && argv[2][0] != 'j')
375           return 2;
377         filename = argv[1];
379         if ((fd = open(filename, O_RDWR, 0666)) == -1) {
380                 perror(filename);
381                 return 3;
382         }
384         print_options(argv[2][0]);
386         while (42) {
388                 FD_ZERO(&rfds);
389                 FD_SET(STDIN_FILENO, &rfds);
390                 FD_SET(fd, &rfds);
392                 retval = select(fd + 1, &rfds, NULL, NULL, NULL);
393                 if (retval == -1 && errno == EINTR)
394                         continue;
395                 if (retval < 0) {
396                         perror("select()");
397                         return 4;
398                 }
400                 if (FD_ISSET(fd, &rfds)) {
401                         cmd_len = read(fd, buf, BUF_LEN - 1);
402                         printf("recv report:");
403                         for (i = 0; i < cmd_len; i++)
404                                 printf(" %02x", buf[i]);
405                         printf("\n");
406                 }
408                 if (FD_ISSET(STDIN_FILENO, &rfds)) {
409                         memset(report, 0x0, sizeof(report));
410                         cmd_len = read(STDIN_FILENO, buf, BUF_LEN - 1);
412                         if (cmd_len == 0)
413                                 break;
415                         buf[cmd_len - 1] = '\0';
416                         hold = 0;
418                         memset(report, 0x0, sizeof(report));
419                         if (argv[2][0] == 'k')
420                                 to_send = keyboard_fill_report(report, buf, &hold);
421                         else if (argv[2][0] == 'm')
422                                 to_send = mouse_fill_report(report, buf, &hold);
423                         else
424                                 to_send = joystick_fill_report(report, buf, &hold);
426                         if (to_send == -1)
427                                 break;
429                         if (write(fd, report, to_send) != to_send) {
430                                 perror(filename);
431                                 return 5;
432                         }
433                         if (!hold) {
434                                 memset(report, 0x0, sizeof(report));
435                                 if (write(fd, report, to_send) != to_send) {
436                                         perror(filename);
437                                         return 6;
438                                 }
439                         }
440                 }
441         }
443         close(fd);
444         return 0;