linux下usb gadget 模拟键盘

分类: LINUX

平台:Ti am3517
内核:linux 2.6.37
在内核配置中选中gadget中的HID device
修改 kernel-2.6.37/drivers/usb/gadget/hid.c  加入设备注册 

点击(此处)折叠或打开

  1. /*
  2.  * hid.-- HID Composite driver
  3.  *
  4.  * Based on multi.c
  5.  *
  6.  * Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.com>
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21.  */


  22. #include <linux/kernel.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/list.h>
  25. #include <linux/usb/g_hid.h>
  26. #define DRIVER_DESC        "HID Gadget"
  27. #define DRIVER_VERSION        "2010/03/16"

  28. /*-------------------------------------------------------------------------*/

  29. #define HIDG_VENDOR_NUM        0x0525    /* XXX NetChip */
  30. #define HIDG_PRODUCT_NUM    0xa4ac    /* Linux-USB HID gadget */

  31. /*-------------------------------------------------------------------------*/

  32. /*
  33.  * kbuild is not very cooperative with respect to linking separately
  34.  * compiled library objects into one module. So for now we won't use
  35.  * separate compilation ... ensuring init/exit sections work to shrink
  36.  * the runtime footprint, and giving us at least some parts of what
  37.  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  38.  */

  39. #include "composite.c"
  40. #include "usbstring.c"
  41. #include "config.c"
  42. #include "epautoconf.c"

  43. #include "f_hid.c"



  44. /* hid descriptor for a keyboard */
  45. static struct hidg_func_descriptor my_hid_data = {
  46.     .subclass        = 0, /* No subclass */
  47.     .protocol        = 1, /* Keyboard */
  48.     .report_length        = 8,
  49.     .report_desc_length    = 63,
  50.     .report_desc        = {
  51.         0x05, 0x01,    /* USAGE_PAGE (Generic Desktop)     */
  52.         0x09, 0x06,    /* USAGE (Keyboard) */
  53.         0xa1, 0x01,    /* COLLECTION (Application) */
  54.         0x05, 0x07,    /* USAGE_PAGE (Keyboard) */
  55.         0x19, 0xe0,    /* USAGE_MINIMUM (Keyboard LeftControl) */
  56.         0x29, 0xe7,    /* USAGE_MAXIMUM (Keyboard Right GUI) */
  57.         0x15, 0x00,    /* LOGICAL_MINIMUM (0) */
  58.         0x25, 0x01,    /* LOGICAL_MAXIMUM (1) */
  59.         0x75, 0x01,    /* REPORT_SIZE (1) */
  60.         0x95, 0x08,    /* REPORT_COUNT (8) */
  61.         0x81, 0x02,    /* INPUT (Data,Var,Abs) */
  62.         0x95, 0x01,    /* REPORT_COUNT (1) */
  63.         0x75, 0x08,    /* REPORT_SIZE (8) */
  64.         0x81, 0x03,    /* INPUT (Cnst,Var,Abs) */
  65.         0x95, 0x05,    /* REPORT_COUNT (5) */
  66.         0x75, 0x01,    /* REPORT_SIZE (1) */
  67.         0x05, 0x08,    /* USAGE_PAGE (LEDs) */
  68.         0x19, 0x01,    /* USAGE_MINIMUM (Num Lock) */
  69.         0x29, 0x05,    /* USAGE_MAXIMUM (Kana) */
  70.         0x91, 0x02,    /* OUTPUT (Data,Var,Abs) */
  71.         0x95, 0x01,    /* REPORT_COUNT (1) */
  72.         0x75, 0x03,    /* REPORT_SIZE (3) */
  73.         0x91, 0x03,    /* OUTPUT (Cnst,Var,Abs) */
  74.         0x95, 0x06,    /* REPORT_COUNT (6) */
  75.         0x75, 0x08,    /* REPORT_SIZE (8) */
  76.         0x15, 0x00,    /* LOGICAL_MINIMUM (0) */
  77.         0x25, 0x65,    /* LOGICAL_MAXIMUM (101) */
  78.         0x05, 0x07,    /* USAGE_PAGE (Keyboard) */
  79.         0x19, 0x00,    /* USAGE_MINIMUM (Reserved) */
  80.         0x29, 0x65,    /* USAGE_MAXIMUM (Keyboard Application) */
  81.         0x81, 0x00,    /* INPUT (Data,Ary,Abs) */
  82.         0xc0        /* END_COLLECTION */
  83.     }
  84. };

  85. struct hidg_func_node {
  86.     struct list_head node;
  87.     struct hidg_func_descriptor *func;
  88. };

  89. static LIST_HEAD(hidg_func_list);

  90. /*-------------------------------------------------------------------------*/

  91. static struct usb_device_descriptor device_desc = {
  92.     .bLength =        sizeof device_desc,
  93.     .bDescriptorType =    USB_DT_DEVICE,

  94.     .bcdUSB =        cpu_to_le16(0x0200),

  95.     /* .bDeviceClass =        USB_CLASS_COMM, */
  96.     /* .bDeviceSubClass =    0, */
  97.     /* .bDeviceProtocol =    0, */
  98.     .bDeviceClass =        0xEF,
  99.     .bDeviceSubClass =    2,
  100.     .bDeviceProtocol =    1,
  101.     /* .bMaxPacketSize0 = f(hardware) */

  102.     /* Vendor and product id can be overridden by module parameters. */
  103.     .idVendor =        cpu_to_le16(HIDG_VENDOR_NUM),
  104.     .idProduct =        cpu_to_le16(HIDG_PRODUCT_NUM),
  105.     /* .bcdDevice = f(hardware) */
  106.     /* .iManufacturer = DYNAMIC */
  107.     /* .iProduct = DYNAMIC */
  108.     /* NO SERIAL NUMBER */
  109.     .bNumConfigurations =    1,
  110. };

  111. static struct usb_otg_descriptor otg_descriptor = {
  112.     .bLength =        sizeof otg_descriptor,
  113.     .bDescriptorType =    USB_DT_OTG,

  114.     /* REVISIT SRP-only hardware is possible, although
  115.      * it would not be called "OTG" ...
  116.      */
  117.     .bmAttributes =        USB_OTG_SRP | USB_OTG_HNP,
  118. };

  119. static const struct usb_descriptor_header *otg_desc[] = {
  120.     (struct usb_descriptor_header *) &otg_descriptor,
  121.     NULL,
  122. };


  123. /* string IDs are assigned dynamically */

  124. #define STRING_MANUFACTURER_IDX        0
  125. #define STRING_PRODUCT_IDX        1

  126. static char manufacturer[50];

  127. static struct usb_string strings_dev[] = {
  128.     [STRING_MANUFACTURER_IDX].= manufacturer,
  129.     [STRING_PRODUCT_IDX].= DRIVER_DESC,
  130.     { } /* end of list */
  131. };

  132. static struct usb_gadget_strings stringtab_dev = {
  133.     .language    = 0x0409,    /* en-us */
  134.     .strings    = strings_dev,
  135. };

  136. static struct usb_gadget_strings *dev_strings[] = {
  137.     &stringtab_dev,
  138.     NULL,
  139. };



  140. /****************************** Configurations ******************************/

  141. static int __init do_config(struct usb_configuration *c)
  142. {
  143.     struct hidg_func_node *e;
  144.     int func = 0, status = 0;

  145.     if (gadget_is_otg(c->cdev->gadget)) {
  146.         c->descriptors = otg_desc;
  147.         c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
  148.     }

  149.     list_for_each_entry(e, &hidg_func_list, node) {
  150.         status = hidg_bind_config(c, e->func, func++);
  151.         if (status)
  152.             break;
  153.     }

  154.     return status;
  155. }

  156. static struct usb_configuration config_driver = {
  157.     .label            = "HID Gadget",
  158.     .bConfigurationValue    = 1,
  159.     /* .iConfiguration = DYNAMIC */
  160.     .bmAttributes        = USB_CONFIG_ATT_SELFPOWER,
  161. };

  162. /****************************** Gadget Bind ******************************/

  163. static int __init hid_bind(struct usb_composite_dev *cdev)
  164. {
  165.     struct usb_gadget *gadget = cdev->gadget;
  166.     struct list_head *tmp;
  167.     int status, gcnum, funcs = 0;

  168.     list_for_each(tmp, &hidg_func_list)
  169.         funcs++;

  170.     if (!funcs)
  171.         return -ENODEV;

  172.     /* set up HID */
  173.     status = ghid_setup(cdev->gadget, funcs);
  174.     if (status < 0)
  175.         return status;

  176.     gcnum = usb_gadget_controller_number(gadget);
  177.     if (gcnum >= 0)
  178.         device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
  179.     else
  180.         device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);


  181.     /* Allocate string descriptor numbers ... note that string
  182.      * contents can be overridden by the composite_dev glue.
  183.      */

  184.     /* device descriptor strings: manufacturer, product */
  185.     snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
  186.         init_utsname()->sysname, init_utsname()->release,
  187.         gadget->name);
  188.     status = usb_string_id(cdev);
  189.     if (status < 0)
  190.         return status;
  191.     strings_dev[STRING_MANUFACTURER_IDX].id = status;
  192.     device_desc.iManufacturer = status;

  193.     status = usb_string_id(cdev);
  194.     if (status < 0)
  195.         return status;
  196.     strings_dev[STRING_PRODUCT_IDX].id = status;
  197.     device_desc.iProduct = status;

  198.     /* register our configuration */
  199.     status = usb_add_config(cdev, &config_driver, do_config);
  200.     if (status < 0)
  201.         return status;

  202.     dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");

  203.     return 0;
  204. }

  205. static int __exit hid_unbind(struct usb_composite_dev *cdev)
  206. {
  207.     ghid_cleanup();
  208.     return 0;
  209. }

  210. static int __init hidg_plat_driver_probe(struct platform_device *pdev)
  211. {
  212.     struct hidg_func_descriptor *func = pdev->dev.platform_data;
  213.     struct hidg_func_node *entry;

  214.     if (!func) {
  215.         dev_err(&pdev->dev, "Platform data missing\n");
  216.         return -ENODEV;
  217.     }

  218.     entry = kzalloc(sizeof(*entry), GFP_KERNEL);
  219.     if (!entry)
  220.         return -ENOMEM;

  221.     entry->func = func;
  222.     list_add_tail(&entry->node, &hidg_func_list);

  223.     return 0;
  224. }

  225. static int __devexit hidg_plat_driver_remove(struct platform_device *pdev)
  226. {
  227.     struct hidg_func_node *e, *n;

  228.     list_for_each_entry_safe(e, n, &hidg_func_list, node) {
  229.         list_del(&e->node);
  230.         kfree(e);
  231.     }

  232.     return 0;
  233. }


  234. /****************************** Some noise ******************************/
  235. //add wds
  236. static struct platform_device my_hid = {
  237.     .name = "hidg",
  238.     .id            = 0,
  239.     .num_resources = 0,
  240.     .resource    = 0,
  241.     .dev.platform_data = &my_hid_data,
  242. };
  243. //add end

  244. static struct usb_composite_driver hidg_driver = {
  245.     .name        = "g_hid",
  246.     .dev        = &device_desc,
  247.     .strings    = dev_strings,
  248.     .unbind        = __exit_p(hid_unbind),
  249. };

  250. static struct platform_driver hidg_plat_driver = {
  251.     .remove        = __devexit_p(hidg_plat_driver_remove),
  252.     .driver        = {
  253.         .owner    = THIS_MODULE,
  254.         .name    = "hidg",
  255.     },
  256. };


  257. MODULE_DESCRIPTION(DRIVER_DESC);
  258. MODULE_AUTHOR("Fabien Chouteau, Peter Korsgaard");
  259. MODULE_LICENSE("GPL");

  260. static int __init hidg_init(void)
  261. {
  262.     int status;
  263.     //add wds
  264.     status = platform_device_register(&my_hid);
  265.     if (status < 0)
  266.     {
  267.         platform_driver_unregister(&my_hid);
  268.         return status;
  269.     }
  270.     //add end
  271.     status = platform_driver_probe(&hidg_plat_driver,
  272.                 hidg_plat_driver_probe);
  273.     if (status < 0)
  274.     {
  275.             printk("platform_driver_probe:*****wrong\n");
  276.             return status;
  277.     }
  278.     status = usb_composite_probe(&hidg_driver, hid_bind);
  279.     if (status < 0)
  280.         platform_driver_unregister(&hidg_plat_driver);

  281.     return status;
  282. }
  283. module_init(hidg_init);

  284. static void __exit hidg_cleanup(void)
  285. {
  286.     platform_device_unregister(&my_hid);
  287.     platform_driver_unregister(&hidg_plat_driver);
  288.     usb_composite_unregister(&hidg_driver);
  289. }
  290. module_exit(hidg_cleanup);

测试程序 

HID_TEST.c 

点击(此处)折叠或打开

  1. #include <pthread.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <ctype.h>
  5. #include <fcntl.h>
  6. #include <errno.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10.     
  11. #define BUF_LEN 512

  12. struct options {
  13.     const char *opt;
  14.     unsigned char val;
  15. };

  16. static struct options kmod[] = {
  17.     {.opt = "--left-ctrl",        .val = 0x01},
  18.     {.opt = "--right-ctrl",        .val = 0x10},
  19.     {.opt = "--left-shift",        .val = 0x02},
  20.     {.opt = "--right-shift",    .val = 0x20},
  21.     {.opt = "--left-alt",        .val = 0x04},
  22.     {.opt = "--right-alt",        .val = 0x40},
  23.     {.opt = "--left-meta",        .val = 0x08},
  24.     {.opt = "--right-meta",        .val = 0x80},
  25.     {.opt = NULL}
  26. };
  27.     
  28. static struct options kval[] = {
  29.     {.opt = "--return",    .val = 0x28},
  30.     {.opt = "--esc",    .val = 0x29},
  31.     {.opt = "--bckspc",    .val = 0x2a},
  32.     {.opt = "--tab",    .val = 0x2b},
  33.     {.opt = "--spacebar",    .val = 0x2c},
  34.     {.opt = "--caps-lock",    .val = 0x39},
  35.     {.opt = "--f1",        .val = 0x3a},
  36.     {.opt = "--f2",        .val = 0x3b},
  37.     {.opt = "--f3",        .val = 0x3c},
  38.     {.opt = "--f4",        .val = 0x3d},
  39.     {.opt = "--f5",        .val = 0x3e},
  40.     {.opt = "--f6",        .val = 0x3f},
  41.     {.opt = "--f7",        .val = 0x40},
  42.     {.opt = "--f8",        .val = 0x41},
  43.     {.opt = "--f9",        .val = 0x42},
  44.     {.opt = "--f10",    .val = 0x43},
  45.     {.opt = "--f11",    .val = 0x44},
  46.     {.opt = "--f12",    .val = 0x45},
  47.     {.opt = "--insert",    .val = 0x49},
  48.     {.opt = "--home",    .val = 0x4a},
  49.     {.opt = "--pageup",    .val = 0x4b},
  50.     {.opt = "--del",    .val = 0x4c},
  51.     {.opt = "--end",    .val = 0x4d},
  52.     {.opt = "--pagedown",    .val = 0x4e},
  53.     {.opt = "--right",    .val = 0x4f},
  54.     {.opt = "--left",    .val = 0x50},
  55.     {.opt = "--down",    .val = 0x51},
  56.     {.opt = "--kp-enter",    .val = 0x58},
  57.     {.opt = "--up",        .val = 0x52},
  58.     {.opt = "--num-lock",    .val = 0x53},
  59.     {.opt = NULL}
  60. };
  61.     
  62. int keyboard_fill_report(char report[8], char buf[BUF_LEN], int *hold)
  63. {
  64.     char *tok = strtok(buf, " ");
  65.     int key = 0;
  66.     int i = 0;
  67.     
  68.     for (; tok != NULL; tok = strtok(NULL, " ")) {
  69.     
  70.         if (strcmp(tok, "--quit") == 0)
  71.             return -1;

  72.         if (strcmp(tok, "--hold") == 0) {
  73.             *hold = 1;
  74.             continue;
  75.         }

  76.         if (key < 6) {
  77.             for (= 0; kval[i].opt != NULL; i++)
  78.                 if (strcmp(tok, kval[i].opt) == 0) {
  79.                     report[+ key++] = kval[i].val;
  80.                     break;
  81.                 }
  82.             if (kval[i].opt != NULL)
  83.                 continue;
  84.         }

  85.         if (key < 6)
  86.             if (islower(tok[0])) {
  87.                 report[+ key++] = (tok[0] - ('a' - 0x04));
  88.                 continue;
  89.             }

  90.         for (= 0; kmod[i].opt != NULL; i++)
  91.             if (strcmp(tok, kmod[i].opt) == 0) {
  92.                 report[0] = report[0] | kmod[i].val;
  93.                 break;
  94.             }
  95.         if (kmod[i].opt != NULL)
  96.             continue;

  97.         if (key < 6)
  98.             fprintf(stderr, "unknown option: %s\n", tok);
  99.     }
  100.     return 8;
  101. }
  102. static struct options mmod[] = {
  103.     {.opt = "--b1", .val = 0x01},
  104.     {.opt = "--b2", .val = 0x02},
  105.     {.opt = "--b3", .val = 0x04},
  106.     {.opt = NULL}
  107. };

  108. int mouse_fill_report(char report[8], char buf[BUF_LEN], int *hold)
  109. {
  110.     char *tok = strtok(buf, " ");
  111.     int mvt = 0;
  112.     int i = 0;
  113.     for (; tok != NULL; tok = strtok(NULL, " ")) {

  114.         if (strcmp(tok, "--quit") == 0)
  115.             return -1;

  116.         if (strcmp(tok, "--hold") == 0) {
  117.             *hold = 1;
  118.             continue;
  119.         }

  120.         for (= 0; mmod[i].opt != NULL; i++)
  121.             if (strcmp(tok, mmod[i].opt) == 0) {
  122.                 report[0] = report[0] | mmod[i].val;
  123.                 break;
  124.             }
  125.         if (mmod[i].opt != NULL)
  126.             continue;

  127.         if (!(tok[0] == '-' && tok[1] == '-') && mvt < 2) {
  128.             errno = 0;
  129.             report[+ mvt++] = (char)strtol(tok, NULL, 0);
  130.             if (errno != 0) {
  131.                 fprintf(stderr, "Bad value:'%s'\n", tok);
  132.                 report[+ mvt--] = 0;
  133.             }
  134.             continue;
  135.         }

  136.         fprintf(stderr, "unknown option: %s\n", tok);
  137.     }
  138.     return 3;
  139. }

  140. static struct options jmod[] = {
  141.     {.opt = "--b1",        .val = 0x10},
  142.     {.opt = "--b2",        .val = 0x20},
  143.     {.opt = "--b3",        .val = 0x40},
  144.     {.opt = "--b4",        .val = 0x80},
  145.     {.opt = "--hat1",    .val = 0x00},
  146.     {.opt = "--hat2",    .val = 0x01},
  147.     {.opt = "--hat3",    .val = 0x02},
  148.     {.opt = "--hat4",    .val = 0x03},
  149.     {.opt = "--hatneutral",    .val = 0x04},
  150.     {.opt = NULL}
  151. };

  152. int joystick_fill_report(char report[8], char buf[BUF_LEN], int *hold)
  153. {
  154.     char *tok = strtok(buf, " ");
  155.     int mvt = 0;
  156.     int i = 0;
  157.     
  158.     *hold = 1;

  159.     /* set default hat position: neutral */
  160.     report[3] = 0x04;

  161.     for (; tok != NULL; tok = strtok(NULL, " ")) {
  162.         if (strcmp(tok, "--quit") == 0)
  163.             return -1;

  164.         for (= 0; jmod[i].opt != NULL; i++)
  165.             if (strcmp(tok, jmod[i].opt) == 0) {
  166.                 report[3] = (report[3] & 0xF0) | jmod[i].val;
  167.                 break;
  168.             }
  169.         if (jmod[i].opt != NULL)
  170.             continue;

  171.         if (!(tok[0] == '-' && tok[1] == '-') && mvt < 3) {
  172.             errno = 0;
  173.             report[mvt++] = (char)strtol(tok, NULL, 0);
  174.             if (errno != 0) {
  175.                 fprintf(stderr, "Bad value:'%s'\n", tok);
  176.                 report[mvt--] = 0;
  177.             }
  178.             continue;
  179.         }

  180.         fprintf(stderr, "unknown option: %s\n", tok);
  181.     }
  182.     return 4;
  183. }

  184. void print_options(char c)
  185. {
  186.     int i = 0;

  187.     if (== 'k') {
  188.         printf("    keyboard options:\n"
  189.          "        --hold\n");
  190.         for (= 0; kmod[i].opt != NULL; i++)
  191.             printf("\t\t%s\n", kmod[i].opt);
  192.         printf("\n    keyboard values:\n"
  193.          "        [a-z] or\n");
  194.         for (= 0; kval[i].opt != NULL; i++)
  195.             printf("\t\t%-8s%s", kval[i].opt, i % 2 ? "\n" : "");
  196.         printf("\n");
  197.     } else if (== 'm') {
  198.         printf("    mouse options:\n"
  199.          "        --hold\n");
  200.         for (= 0; mmod[i].opt != NULL; i++)
  201.             printf("\t\t%s\n", mmod[i].opt);
  202.         printf("\n    mouse values:\n"
  203.          "        Two signed numbers\n"
  204.          "--quit to close\n");
  205.     } else {
  206.         printf("    joystick options:\n");
  207.         for (= 0; jmod[i].opt != NULL; i++)
  208.             printf("\t\t%s\n", jmod[i].opt);
  209.         printf("\n    joystick values:\n"
  210.          "        three signed numbers\n"
  211.          "--quit to close\n");
  212.     }
  213. }

  214. int main(int argc, const char *argv[])
  215. {
  216.     const char *filename = NULL;
  217.     int fd = 0;
  218.     char buf[BUF_LEN];
  219.     int cmd_len;
  220.     char report[8];
  221.     int to_send = 8;
  222.     int hold = 0;
  223.     fd_set rfds;
  224.     int retval, i;

  225.     if (argc < 3) {
  226.         fprintf(stderr, "Usage: %s devname mouse|keyboard|joystick\n",
  227.             argv[0]);
  228.         return 1;
  229.     }

  230.     if (argv[2][0] != 'k' && argv[2][0] != 'm' && argv[2][0] != 'j')
  231.      return 2;

  232.     filename = argv[1];
  233.     if ((fd = open(filename, O_RDWR, 0666)) == -1) {
  234.         perror(filename);
  235.         return 3;
  236.     }

  237.     print_options(argv[2][0]);

  238.     while (42) {

  239.         FD_ZERO(&rfds);
  240.         FD_SET(STDIN_FILENO, &rfds);
  241.         FD_SET(fd, &rfds);

  242.         retval = select(fd + 1, &rfds, NULL, NULL, NULL);
  243.         if (retval == -&& errno == EINTR)
  244.             continue;
  245.         if (retval < 0) {
  246.             perror("select()");
  247.             return 4;
  248.         }

  249.         if (FD_ISSET(fd, &rfds)) {
  250.             cmd_len = read(fd, buf, BUF_LEN - 1);
  251.             printf("recv report:");
  252.             for (= 0; i < cmd_len; i++)
  253.                 printf(" %02x", buf[i]);
  254.             printf("\n");
  255.         }

  256.         if (FD_ISSET(STDIN_FILENO, &rfds)) {
  257.             memset(report, 0x0, sizeof(report));
  258.             cmd_len = read(STDIN_FILENO, buf, BUF_LEN - 1);

  259.             if (cmd_len == 0)
  260.                 break;

  261.             buf[cmd_len - 1] = '\0';
  262.             hold = 0;

  263.             memset(report, 0x0, sizeof(report));
  264.             if (argv[2][0] == 'k')
  265.                 to_send = keyboard_fill_report(report, buf, &hold);
  266.             else if (argv[2][0] == 'm')
  267.                 to_send = mouse_fill_report(report, buf, &hold);
  268.             else
  269.                 to_send = joystick_fill_report(report, buf, &hold);

  270.             if (to_send == -1)
  271.                 break;

  272.             if (write(fd, report, to_send) != to_send) {
  273.                 perror(filename);
  274.                 return 5;
  275.             }
  276.             if (!hold) {
  277.                 memset(report, 0x0, sizeof(report));
  278.                 if (write(fd, report, to_send) != to_send) {
  279.                     perror(filename);
  280.                     return 6;
  281.                 }
  282.             }
  283.         }
  284.     }
  285.     
  286.     close(fd);
  287.     return 0;
  288. }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux USB gadget驱动编写有如下几个步骤: 1. 确定USB gadget功能:首先需要确定所需实现的USB gadget功能,例如以USB设备的形式提供存储、网络、音频等服务。这样可以决定需要实现的USB gadget驱动类型和功能。 2. 编写USB驱动框架:基于Linux内核框架,编写USB gadget驱动的基本框架。这包括注册USB gadget驱动和常用的函数接口等。 3. 实现USB gadget子系统:根据所需的功能,实现USB gadget子系统的模块,如存储、网络或音频子系统等。这些子系统需要封装底层的USB通信协议和数据传输,供应用程序调用。 4. 配置USB gadget驱动:根据具体需求,在系统配置文件中进行必要的配置,以启用和配置USB gadget驱动。这包括配置端点、描述符和功能等。 5. 移植和编译:将驱动程序编译成内核模块,然后将其移植到目标设备上。对于嵌入式设备,可能需要修改硬件相关的代码,以适应硬件平台。 6. 测试和调试:编写测试用例,对USB gadget驱动进行测试和调试,确保其正常工作。这包括对设备和主机之间的数据传输进行验证,以及处理异常情况和错误处理。 总之,编写Linux USB gadget驱动需要明确所需实现的功能、基于内核框架编写驱动框架、实现USB gadget子系统、配置以及移植和编译。最后进行测试和调试,确保驱动程序的正常运行。通过以上步骤,可以实现各种USB设备功能的驱动。 ### 回答2: Linux USB gadget驱动是用于实现USB设备的功能的驱动程序。它使得Linux设备可以作为一个USB设备与其他主机进行通信。在编写Linux USB gadget驱动时,需要完成以下几个步骤。 首先,需要确定设备的功能和属性。USB设备可以有多种功能,如储存设备、键盘、鼠标等。根据设备的类型和规格,确定设备的操作和数据传输方式。 其次,在驱动程序中定义设备的USB描述符。USB描述符包括设备描述符、接口描述符和端点描述符等,它们是USB协议的一部分,用于描述设备的属性和功能。 然后,在驱动程序中实现设备的相关功能。根据设备的类型和规格,编写相应的功能代码。例如,如果设备是一个键盘,就需要实现按键事件的处理逻辑;如果设备是一个储存设备,就需要实现读写数据的逻辑。 最后,编译和加载驱动程序。使用Linux内核提供的工具链,将驱动程序编译为可执行文件,并将其加载到Linux内核中运行。加载驱动程序后,系统即可识别设备,并根据驱动程序中定义的功能和属性来处理设备的操作和数据传输。 总之,编写Linux USB gadget驱动需要确定设备的功能和属性、定义USB描述符、实现设备的相关功能,最后编译和加载驱动程序。通过这些步骤,我们可以在Linux系统中实现USB设备的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值