linux/Documentation/usb/gadget_hid.txt
<<
>>
Prefs
   1
   2                     Linux USB HID gadget driver
   3
   4Introduction
   5
   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.
  10
  11        For more details about HID, see the developer page on
  12        http://www.usb.org/developers/hidpage/
  13
  14Configuration
  15
  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:
  20
  21#include <linux/platform_device.h>
  22#include <linux/usb/g_hid.h>
  23
  24/* hid descriptor for a keyboard */
  25static 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        }
  64};
  65
  66static 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,
  72};
  73
  74        You can add as many HID functions as you want, only limited by
  75        the amount of interrupt endpoints your gadget driver supports.
  76
  77Send and receive HID reports
  78
  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.
  82
  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.:
  86
  87                # hid_gadget_test /dev/hidg0 keyboard
  88
  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.
  93
  94        For example type: g i s t r --left-shift
  95
  96        Hit return and the corresponding report will be sent by the
  97        HID gadget.
  98
  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.
 103
 104                --caps-lock
 105                recv report:2
 106
 107        With this command:
 108
 109                # hid_gadget_test /dev/hidg1 mouse
 110
 111        You can test the mouse emulation. Values are two signed numbers.
 112
 113
 114Sample code
 115
 116/* hid_gadget_test */
 117
 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>
 127
 128#define BUF_LEN 512
 129
 130struct options {
 131        const char    *opt;
 132        unsigned char val;
 133};
 134
 135static 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}
 145};
 146
 147static 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}
 179};
 180
 181int keyboard_fill_report(char report[8], char buf[BUF_LEN], int *hold)
 182{
 183        char *tok = strtok(buf, " ");
 184        int key = 0;
 185        int i = 0;
 186
 187        for (; tok != NULL; tok = strtok(NULL, " ")) {
 188
 189                if (strcmp(tok, "--quit") == 0)
 190                        return -1;
 191
 192                if (strcmp(tok, "--hold") == 0) {
 193                        *hold = 1;
 194                        continue;
 195                }
 196
 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                }
 206
 207                if (key < 6)
 208                        if (islower(tok[0])) {
 209                                report[2 + key++] = (tok[0] - ('a' - 0x04));
 210                                continue;
 211                        }
 212
 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;
 220
 221                if (key < 6)
 222                        fprintf(stderr, "unknown option: %s\n", tok);
 223        }
 224        return 8;
 225}
 226
 227static struct options mmod[] = {
 228        {.opt = "--b1", .val = 0x01},
 229        {.opt = "--b2", .val = 0x02},
 230        {.opt = "--b3", .val = 0x04},
 231        {.opt = NULL}
 232};
 233
 234int mouse_fill_report(char report[8], char buf[BUF_LEN], int *hold)
 235{
 236        char *tok = strtok(buf, " ");
 237        int mvt = 0;
 238        int i = 0;
 239        for (; tok != NULL; tok = strtok(NULL, " ")) {
 240
 241                if (strcmp(tok, "--quit") == 0)
 242                        return -1;
 243
 244                if (strcmp(tok, "--hold") == 0) {
 245                        *hold = 1;
 246                        continue;
 247                }
 248
 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;
 256
 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                }
 266
 267                fprintf(stderr, "unknown option: %s\n", tok);
 268        }
 269        return 3;
 270}
 271
 272static struct options jmod[] = {
 273        {.opt = "--b1",         .val = 0x10},
 274        {.opt = "--850ame="L26812entation/    if (key < 6)
 156        {.opt = "--f7",         .val = 0x40},
 157        {.opt --right-meta",         .val = 0x80},
 273   /a>       -right-meta",         .val = 0x80},
 273   /a>        {.opt = "--b1", .val = 0x01},
 273   /a>        {.opt = "--b2", .val = 0x02},
 273   /a>        "--num-lock",   .val = 0x53},
 230        {.opt = "--b3", .val = 0x04},
 231        {.opt = NULL}
 133};
 134
 234int 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;
 240
 245                        *hold = 1;
 212
 osi     fneutralame="L116"> 116/* hid_gadget_test */
                        *hold = 1;
  95
 239        for (; tok != NULL; tok = strtok(NULL, " ")) {
 127
 241                if (strcmp(tok, "--quit") == 0)
 242                        return -1;
 240
                for (i = 0; mmod[i].opt != NULL; i++)
 24j                    if (strcmp(tok, mmod[i].opt) == 0) {
 202                                break;
 231        {.opt = NULL}
           for (i = 0; mmod[i].opt != NULL; i++)
 264                        continue;
 108
 257                if (!(tok[0] == '-' && tok[1]3    if (strcmp(tok, mmod[i].opt) == 0) {
 258                        errno = 0;
                                fprintf(stderr, "Bad value:'%s'\n", tok);
                        report[1 + mvt--] = 0;
 231        {.opt = NULL}
 264                        continue;
 231        {.opt = NULL}
 108
 267                fprintf(stderr, "unknown option: %s\n", tok);
 231        {.opt = NULL}
 2                         *hold = 1;
 231        {.opt = NULL}
 243
 235{
 238        int i = 0;
 127
 235{
 235{
 213                for (i = 0; kmod[i].opt != NULL; i++)
:(stderr,5" class="line" name="L235"> 235{
 198                        for (i = 0; kval[i].opt != NULL; i++)
 235{
 1e" name:(stderr,5" class="line" name="L235"> 235{
 249                for (i = 0; mmod[i].opt != NULL; i++)
 1"L92">:(stderr,5" class="line" name="L235"> 235{
 235{
 235{
                for (i = 0; mmod[i].opt != NULL; i++)
:(stderr,5" class="line" name="L235"> 235{
 235{
 223        }
 223        }
  95
 235{
 238        int i = 0;
 238        int i = 0;
 238        int i = 0;
 234 238        int i = 0;
 224        return 8;
 24 name="L238"> 238        int i = 0;
 238        int i = 0;
 238        int i = 0;
 127
 267 Usage fprintf devhid.n11"> |lues are|     dev(stderr,  if (strcmp(tok, mmod[i].opt) == 0) {
 22                        return -1;
 223        }
 243
!0] == &k39;-&39; &&amargv[2]57">!0] == &m39;-&39; &&amargv[2]57">!0] == &j39;-+" class="line" name="L243"> 243
 22                        return -1;
 266
 238        int i = 0;
 108
 or(filehid.t;unknown option: %s\n", tok);
 2" name="L269"> 269        return 3;
 223        }
 243
  95
 127
 191
 2= EINTR#43" class="line" name="L243"> 243
 194                        continue;
 or(tderr,/elect()tderr,t;unknown option: %s\n", tok);
 2                         *hold = 1;
 223        }
 223        }
 23fill_re - 1t;unknown option: %s\n", tok);
 234:tderr,t;unknown option: %s\n", tok);
 20name="Lr (; toprint02xtderr, &use_i"t;unknown option: %s\n", tok);
 223        }
 127
 23fill_re - 1t;unknown option: %s\n", tok);
 191
                                break;
 134
 24 name="L238"> 238        int i = 0;
 127
[0] == &k39;-&#+] = (tok[0] - ('a' - 0x04));
 21to_sendne"class="line" name="L1s= 234, "> 236p;&ar rep++] = (tok[0] - ('a' - 0x04));
[0] == &m39;-&#+] = (tok[0] - ('a' - 0x04));
 21to_sendne"class="line" name=s= 234, "> 236p;&ar rep++] = (tok[0] - ('a' - 0x04));
 20to_sendne"     dev="line" name=s= 234, "> 236p;&ar rep++] = (tok[0] - ('a' - 0x04));
  95
  95
                                break;
 108
 or(filehid.t;unknown option: %s\n", tok);
 25;unknown option: %s\n", tok);
 223        }
 or(filehid.t;unknown option: %s\n", tok);
 26;unknown option: %s\n", tok);
 223        }
 223        }
 223        }
 223        }
 212
 238        int i = 0;
 225}

The original LXR software by the " class="http://sourceforge.net/projects/lxr">LXR community="L2, this exn">i" naml vers="L by " class="mailto:lxr@adgux.no">lxr@adgux.no="L2.
lxr.adgux.no kindly hosted by " class="http://www.redplin-adgpro.no">Redplin Ldgpro AS="L2, provider of Ldguxss="lulting ane e"erme="Ls services since" id5.