分类: LINUX
平台:Ti am3517
内核:linux 2.6.37
在内核配置中选中gadget中的HID device
修改 kernel-2.6.37/drivers/usb/gadget/hid.c 加入设备注册
点击(此处)折叠或打开
-
/*
-
* hid.c -- HID
Composite driver
-
*
-
* Based on multi.c
-
*
-
* Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.com>
-
*
-
* This program is free software; you can redistribute it and/or modify
-
* it under the terms of the GNU General Public License as published by
-
* the Free Software Foundation; either version 2 of the License, or
-
* (at your option) any
later version.
-
*
-
* This program is distributed in the hope that it will be useful,
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
the
-
* GNU General Public License for more details.
-
*
-
* You should have received a copy of the GNU General Public License
-
* along with this program; if not, write to the
Free Software
-
* Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307
USA
-
*/
-
-
-
#include <linux/kernel.h>
-
#include <linux/platform_device.h>
-
#include <linux/list.h>
-
#include <linux/usb/g_hid.h>
-
#define DRIVER_DESC "HID Gadget"
-
#define DRIVER_VERSION "2010/03/16"
-
-
/*-------------------------------------------------------------------------*/
-
-
#define HIDG_VENDOR_NUM 0x0525 /* XXX NetChip */
-
#define HIDG_PRODUCT_NUM 0xa4ac /* Linux-USB HID gadget */
-
-
/*-------------------------------------------------------------------------*/
-
-
/*
-
* kbuild is not very cooperative with respect to linking
separately
-
* compiled library objects into one module. So for now we
won't use
-
* separate compilation ... ensuring
init/exit sections work to shrink
-
* the runtime footprint, and giving us at least some parts of what
-
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
-
*/
-
-
#include "composite.c"
-
#include "usbstring.c"
-
#include "config.c"
-
#include "epautoconf.c"
-
-
#include "f_hid.c"
-
-
-
-
/* hid descriptor for a keyboard */
-
static struct hidg_func_descriptor my_hid_data = {
-
.subclass = 0, /* No
subclass */
-
.protocol = 1, /* Keyboard */
-
.report_length = 8,
-
.report_desc_length = 63,
-
.report_desc = {
-
0x05, 0x01, /* USAGE_PAGE (Generic
Desktop) */
-
0x09, 0x06, /* USAGE (Keyboard) */
-
0xa1, 0x01, /* COLLECTION (Application) */
-
0x05, 0x07, /* USAGE_PAGE (Keyboard) */
-
0x19, 0xe0, /* USAGE_MINIMUM (Keyboard
LeftControl) */
-
0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */
-
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
-
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
-
0x75, 0x01, /* REPORT_SIZE (1) */
-
0x95, 0x08, /* REPORT_COUNT (8) */
-
0x81, 0x02, /* INPUT (Data,Var,Abs) */
-
0x95, 0x01, /* REPORT_COUNT (1) */
-
0x75, 0x08, /* REPORT_SIZE (8) */
-
0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
-
0x95, 0x05, /* REPORT_COUNT (5) */
-
0x75, 0x01, /* REPORT_SIZE (1) */
-
0x05, 0x08, /* USAGE_PAGE (LEDs) */
-
0x19, 0x01, /* USAGE_MINIMUM (Num
Lock) */
-
0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
-
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
-
0x95, 0x01, /* REPORT_COUNT (1) */
-
0x75, 0x03, /* REPORT_SIZE (3) */
-
0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
-
0x95, 0x06, /* REPORT_COUNT (6) */
-
0x75, 0x08, /* REPORT_SIZE (8) */
-
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
-
0x25, 0x65, /* LOGICAL_MAXIMUM (101) */
-
0x05, 0x07, /* USAGE_PAGE (Keyboard) */
-
0x19, 0x00, /* USAGE_MINIMUM (Reserved) */
-
0x29, 0x65, /* USAGE_MAXIMUM (Keyboard
Application) */
-
0x81, 0x00, /* INPUT (Data,Ary,Abs) */
-
0xc0 /* END_COLLECTION */
-
}
-
};
-
-
struct hidg_func_node {
-
struct list_head node;
-
struct hidg_func_descriptor *func;
-
};
-
-
static LIST_HEAD(hidg_func_list);
-
-
/*-------------------------------------------------------------------------*/
-
-
static struct usb_device_descriptor device_desc = {
-
.bLength = sizeof device_desc,
-
.bDescriptorType = USB_DT_DEVICE,
-
-
.bcdUSB = cpu_to_le16(0x0200),
-
-
/* .bDeviceClass = USB_CLASS_COMM, */
-
/* .bDeviceSubClass = 0, */
-
/* .bDeviceProtocol = 0, */
-
.bDeviceClass = 0xEF,
-
.bDeviceSubClass = 2,
-
.bDeviceProtocol = 1,
-
/* .bMaxPacketSize0 = f(hardware) */
-
-
/* Vendor and product id can be overridden by module parameters. */
-
.idVendor = cpu_to_le16(HIDG_VENDOR_NUM),
-
.idProduct = cpu_to_le16(HIDG_PRODUCT_NUM),
-
/* .bcdDevice = f(hardware) */
-
/* .iManufacturer = DYNAMIC */
-
/* .iProduct = DYNAMIC */
-
/* NO SERIAL NUMBER */
-
.bNumConfigurations = 1,
-
};
-
-
static struct usb_otg_descriptor otg_descriptor = {
-
.bLength = sizeof otg_descriptor,
-
.bDescriptorType = USB_DT_OTG,
-
-
/* REVISIT SRP-only hardware is possible, although
-
* it would not be called "OTG" ...
-
*/
-
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-
};
-
-
static const struct usb_descriptor_header *otg_desc[] = {
-
(struct usb_descriptor_header *) &otg_descriptor,
-
NULL,
-
};
-
-
-
/* string IDs are assigned dynamically */
-
-
#define STRING_MANUFACTURER_IDX 0
-
#define STRING_PRODUCT_IDX 1
-
-
static char manufacturer[50];
-
-
static struct usb_string strings_dev[] = {
-
[STRING_MANUFACTURER_IDX].s = manufacturer,
-
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
-
{ } /* end of
list */
-
};
-
-
static struct usb_gadget_strings stringtab_dev = {
-
.language = 0x0409, /* en-us */
-
.strings = strings_dev,
-
};
-
-
static struct usb_gadget_strings *dev_strings[] = {
-
&stringtab_dev,
-
NULL,
-
};
-
-
-
-
/****************************** Configurations ******************************/
-
-
static int __init do_config(struct usb_configuration *c)
-
{
-
struct hidg_func_node *e;
-
int func = 0, status = 0;
-
-
if (gadget_is_otg(c->cdev->gadget)) {
-
c->descriptors = otg_desc;
-
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-
}
-
-
list_for_each_entry(e, &hidg_func_list, node) {
-
status = hidg_bind_config(c, e->func, func++);
-
if (status)
-
break;
-
}
-
-
return status;
-
}
-
-
static struct usb_configuration config_driver = {
-
.label = "HID Gadget",
-
.bConfigurationValue = 1,
-
/* .iConfiguration = DYNAMIC */
-
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
-
};
-
-
/****************************** Gadget
Bind ******************************/
-
-
static int __init hid_bind(struct usb_composite_dev *cdev)
-
{
-
struct usb_gadget *gadget = cdev->gadget;
-
struct list_head *tmp;
-
int status, gcnum, funcs = 0;
-
-
list_for_each(tmp, &hidg_func_list)
-
funcs++;
-
-
if (!funcs)
-
return -ENODEV;
-
-
/* set up HID */
-
status = ghid_setup(cdev->gadget, funcs);
-
if (status < 0)
-
return status;
-
-
gcnum = usb_gadget_controller_number(gadget);
-
if (gcnum >= 0)
-
device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
-
else
-
device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
-
-
-
/* Allocate string descriptor numbers ... note
that string
-
* contents can be overridden by the composite_dev glue.
-
*/
-
-
/* device descriptor strings: manufacturer, product */
-
snprintf(manufacturer, sizeof manufacturer, "%s
%s with %s",
-
init_utsname()->sysname, init_utsname()->release,
-
gadget->name);
-
status = usb_string_id(cdev);
-
if (status < 0)
-
return status;
-
strings_dev[STRING_MANUFACTURER_IDX].id = status;
-
device_desc.iManufacturer = status;
-
-
status = usb_string_id(cdev);
-
if (status < 0)
-
return status;
-
strings_dev[STRING_PRODUCT_IDX].id = status;
-
device_desc.iProduct = status;
-
-
/* register our configuration */
-
status = usb_add_config(cdev, &config_driver, do_config);
-
if (status < 0)
-
return status;
-
-
dev_info(&gadget->dev, DRIVER_DESC ",
version: " DRIVER_VERSION "\n");
-
-
return 0;
-
}
-
-
static int __exit hid_unbind(struct usb_composite_dev *cdev)
-
{
-
ghid_cleanup();
-
return 0;
-
}
-
-
static int __init hidg_plat_driver_probe(struct platform_device *pdev)
-
{
-
struct hidg_func_descriptor *func = pdev->dev.platform_data;
-
struct hidg_func_node *entry;
-
-
if (!func) {
-
dev_err(&pdev->dev, "Platform
data missing\n");
-
return -ENODEV;
-
}
-
-
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-
if (!entry)
-
return -ENOMEM;
-
-
entry->func = func;
-
list_add_tail(&entry->node, &hidg_func_list);
-
-
return 0;
-
}
-
-
static int __devexit hidg_plat_driver_remove(struct platform_device *pdev)
-
{
-
struct hidg_func_node *e, *n;
-
-
list_for_each_entry_safe(e, n, &hidg_func_list, node) {
-
list_del(&e->node);
-
kfree(e);
-
}
-
-
return 0;
-
}
-
-
-
/****************************** Some
noise ******************************/
-
//add wds
-
static struct platform_device my_hid = {
-
.name = "hidg",
-
.id = 0,
-
.num_resources = 0,
-
.resource = 0,
-
.dev.platform_data = &my_hid_data,
-
};
-
//add end
-
-
static struct usb_composite_driver hidg_driver = {
-
.name = "g_hid",
-
.dev = &device_desc,
-
.strings = dev_strings,
-
.unbind = __exit_p(hid_unbind),
-
};
-
-
static struct platform_driver hidg_plat_driver = {
-
.remove = __devexit_p(hidg_plat_driver_remove),
-
.driver = {
-
.owner = THIS_MODULE,
-
.name = "hidg",
-
},
-
};
-
-
-
MODULE_DESCRIPTION(DRIVER_DESC);
-
MODULE_AUTHOR("Fabien Chouteau, Peter Korsgaard");
-
MODULE_LICENSE("GPL");
-
-
static int __init hidg_init(void)
-
{
-
int status;
-
//add wds
-
status = platform_device_register(&my_hid);
-
if (status < 0)
-
{
-
platform_driver_unregister(&my_hid);
-
return status;
-
}
-
//add end
-
status = platform_driver_probe(&hidg_plat_driver,
-
hidg_plat_driver_probe);
-
if (status < 0)
-
{
-
printk("platform_driver_probe:*****wrong\n");
-
return status;
-
}
-
status = usb_composite_probe(&hidg_driver, hid_bind);
-
if (status < 0)
-
platform_driver_unregister(&hidg_plat_driver);
-
-
return status;
-
}
-
module_init(hidg_init);
-
-
static void __exit hidg_cleanup(void)
-
{
-
platform_device_unregister(&my_hid);
-
platform_driver_unregister(&hidg_plat_driver);
-
usb_composite_unregister(&hidg_driver);
-
}
- module_exit(hidg_cleanup);
测试程序
HID_TEST.c
点击(此处)折叠或打开
-
#include <pthread.h>
-
#include <string.h>
-
#include <stdio.h>
-
#include <ctype.h>
-
#include <fcntl.h>
-
#include <errno.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
-
#define BUF_LEN 512
-
-
struct options {
-
const char *opt;
-
unsigned char val;
-
};
-
-
static struct options kmod[] = {
-
{.opt = "--left-ctrl", .val = 0x01},
-
{.opt = "--right-ctrl", .val = 0x10},
-
{.opt = "--left-shift", .val = 0x02},
-
{.opt = "--right-shift", .val = 0x20},
-
{.opt = "--left-alt", .val = 0x04},
-
{.opt = "--right-alt", .val = 0x40},
-
{.opt = "--left-meta", .val = 0x08},
-
{.opt = "--right-meta", .val = 0x80},
-
{.opt = NULL}
-
};
-
-
static struct options kval[] = {
-
{.opt = "--return", .val = 0x28},
-
{.opt = "--esc", .val = 0x29},
-
{.opt = "--bckspc", .val = 0x2a},
-
{.opt = "--tab", .val = 0x2b},
-
{.opt = "--spacebar", .val = 0x2c},
-
{.opt = "--caps-lock", .val = 0x39},
-
{.opt = "--f1", .val = 0x3a},
-
{.opt = "--f2", .val = 0x3b},
-
{.opt = "--f3", .val = 0x3c},
-
{.opt = "--f4", .val = 0x3d},
-
{.opt = "--f5", .val = 0x3e},
-
{.opt = "--f6", .val = 0x3f},
-
{.opt = "--f7", .val = 0x40},
-
{.opt = "--f8", .val = 0x41},
-
{.opt = "--f9", .val = 0x42},
-
{.opt = "--f10", .val = 0x43},
-
{.opt = "--f11", .val = 0x44},
-
{.opt = "--f12", .val = 0x45},
-
{.opt = "--insert", .val = 0x49},
-
{.opt = "--home", .val = 0x4a},
-
{.opt = "--pageup", .val = 0x4b},
-
{.opt = "--del", .val = 0x4c},
-
{.opt = "--end", .val = 0x4d},
-
{.opt = "--pagedown", .val = 0x4e},
-
{.opt = "--right", .val = 0x4f},
-
{.opt = "--left", .val = 0x50},
-
{.opt = "--down", .val = 0x51},
-
{.opt = "--kp-enter", .val = 0x58},
-
{.opt = "--up", .val = 0x52},
-
{.opt = "--num-lock", .val = 0x53},
-
{.opt = NULL}
-
};
-
-
int keyboard_fill_report(char report[8], char
buf[BUF_LEN], int *hold)
-
{
-
char *tok = strtok(buf, "
");
-
int key = 0;
-
int i = 0;
-
-
for (; tok != NULL; tok = strtok(NULL, "
")) {
-
-
if (strcmp(tok, "--quit") == 0)
-
return -1;
-
-
if (strcmp(tok, "--hold") == 0) {
-
*hold = 1;
-
continue;
-
}
-
-
if (key < 6) {
-
for (i = 0; kval[i].opt != NULL; i++)
-
if (strcmp(tok, kval[i].opt) == 0) {
-
report[2 + key++] = kval[i].val;
-
break;
-
}
-
if (kval[i].opt != NULL)
-
continue;
-
}
-
-
if (key < 6)
-
if (islower(tok[0])) {
-
report[2 + key++] = (tok[0] - ('a' - 0x04));
-
continue;
-
}
-
-
for (i = 0; kmod[i].opt != NULL; i++)
-
if (strcmp(tok, kmod[i].opt) == 0) {
-
report[0] = report[0] | kmod[i].val;
-
break;
-
}
-
if (kmod[i].opt != NULL)
-
continue;
-
-
if (key < 6)
-
fprintf(stderr, "unknown option: %s\n", tok);
-
}
-
return 8;
-
}
-
static struct options mmod[] = {
-
{.opt = "--b1", .val = 0x01},
-
{.opt = "--b2", .val = 0x02},
-
{.opt = "--b3", .val = 0x04},
-
{.opt = NULL}
-
};
-
-
int mouse_fill_report(char report[8], char
buf[BUF_LEN], int *hold)
-
{
-
char *tok = strtok(buf, "
");
-
int mvt = 0;
-
int i = 0;
-
for (; tok != NULL; tok = strtok(NULL, "
")) {
-
-
if (strcmp(tok, "--quit") == 0)
-
return -1;
-
-
if (strcmp(tok, "--hold") == 0) {
-
*hold = 1;
-
continue;
-
}
-
-
for (i = 0; mmod[i].opt != NULL; i++)
-
if (strcmp(tok, mmod[i].opt) == 0) {
-
report[0] = report[0] | mmod[i].val;
-
break;
-
}
-
if (mmod[i].opt != NULL)
-
continue;
-
-
if (!(tok[0] == '-' && tok[1] == '-') && mvt < 2) {
-
errno = 0;
-
report[1 + mvt++] = (char)strtol(tok, NULL, 0);
-
if (errno != 0) {
-
fprintf(stderr, "Bad value:'%s'\n", tok);
-
report[1 + mvt--] = 0;
-
}
-
continue;
-
}
-
-
fprintf(stderr, "unknown option: %s\n", tok);
-
}
-
return 3;
-
}
-
-
static struct options jmod[] = {
-
{.opt = "--b1", .val = 0x10},
-
{.opt = "--b2", .val = 0x20},
-
{.opt = "--b3", .val = 0x40},
-
{.opt = "--b4", .val = 0x80},
-
{.opt = "--hat1", .val = 0x00},
-
{.opt = "--hat2", .val = 0x01},
-
{.opt = "--hat3", .val = 0x02},
-
{.opt = "--hat4", .val = 0x03},
-
{.opt = "--hatneutral", .val = 0x04},
-
{.opt = NULL}
-
};
-
-
int joystick_fill_report(char report[8], char
buf[BUF_LEN], int *hold)
-
{
-
char *tok = strtok(buf, "
");
-
int mvt = 0;
-
int i = 0;
-
-
*hold = 1;
-
-
/* set default hat position: neutral */
-
report[3] = 0x04;
-
-
for (; tok != NULL; tok = strtok(NULL, "
")) {
-
if (strcmp(tok, "--quit") == 0)
-
return -1;
-
-
for (i = 0; jmod[i].opt != NULL; i++)
-
if (strcmp(tok, jmod[i].opt) == 0) {
-
report[3] = (report[3] & 0xF0) | jmod[i].val;
-
break;
-
}
-
if (jmod[i].opt != NULL)
-
continue;
-
-
if (!(tok[0] == '-' && tok[1] == '-') && mvt < 3) {
-
errno = 0;
-
report[mvt++] = (char)strtol(tok, NULL, 0);
-
if (errno != 0) {
-
fprintf(stderr, "Bad value:'%s'\n", tok);
-
report[mvt--] = 0;
-
}
-
continue;
-
}
-
-
fprintf(stderr, "unknown option: %s\n", tok);
-
}
-
return 4;
-
}
-
-
void print_options(char c)
-
{
-
int i = 0;
-
-
if (c == 'k') {
-
printf(" keyboard options:\n"
-
" --hold\n");
-
for (i = 0; kmod[i].opt != NULL; i++)
-
printf("\t\t%s\n", kmod[i].opt);
-
printf("\n keyboard values:\n"
-
" [a-z] or\n");
-
for (i = 0; kval[i].opt != NULL; i++)
-
printf("\t\t%-8s%s", kval[i].opt, i % 2 ? "\n" : "");
-
printf("\n");
-
} else if (c == 'm') {
-
printf(" mouse options:\n"
-
" --hold\n");
-
for (i = 0; mmod[i].opt != NULL; i++)
-
printf("\t\t%s\n", mmod[i].opt);
-
printf("\n mouse values:\n"
-
" Two signed numbers\n"
-
"--quit to close\n");
-
} else {
-
printf(" joystick options:\n");
-
for (i = 0; jmod[i].opt != NULL; i++)
-
printf("\t\t%s\n", jmod[i].opt);
-
printf("\n joystick values:\n"
-
" three signed numbers\n"
-
"--quit to close\n");
-
}
-
}
-
-
int main(int argc, const char *argv[])
-
{
-
const char *filename = NULL;
-
int fd = 0;
-
char buf[BUF_LEN];
-
int cmd_len;
-
char report[8];
-
int to_send = 8;
-
int hold = 0;
-
fd_set rfds;
-
int retval, i;
-
-
if (argc < 3) {
-
fprintf(stderr, "Usage: %s devname mouse|keyboard|joystick\n",
-
argv[0]);
-
return 1;
-
}
-
-
if (argv[2][0] != 'k' && argv[2][0] != 'm' && argv[2][0] != 'j')
-
return 2;
-
-
filename = argv[1];
-
if ((fd = open(filename, O_RDWR, 0666)) == -1) {
-
perror(filename);
-
return 3;
-
}
-
-
print_options(argv[2][0]);
-
-
while (42) {
-
-
FD_ZERO(&rfds);
-
FD_SET(STDIN_FILENO, &rfds);
-
FD_SET(fd, &rfds);
-
-
retval = select(fd + 1, &rfds, NULL, NULL, NULL);
-
if (retval == -1 && errno == EINTR)
-
continue;
-
if (retval < 0) {
-
perror("select()");
-
return 4;
-
}
-
-
if (FD_ISSET(fd, &rfds)) {
-
cmd_len = read(fd, buf, BUF_LEN - 1);
-
printf("recv report:");
-
for (i = 0; i < cmd_len; i++)
-
printf(" %02x", buf[i]);
-
printf("\n");
-
}
-
-
if (FD_ISSET(STDIN_FILENO, &rfds)) {
-
memset(report, 0x0, sizeof(report));
-
cmd_len = read(STDIN_FILENO, buf, BUF_LEN - 1);
-
-
if (cmd_len == 0)
-
break;
-
-
buf[cmd_len - 1] = '\0';
-
hold = 0;
-
-
memset(report, 0x0, sizeof(report));
-
if (argv[2][0] == 'k')
-
to_send = keyboard_fill_report(report, buf, &hold);
-
else if (argv[2][0] == 'm')
-
to_send = mouse_fill_report(report, buf, &hold);
-
else
-
to_send = joystick_fill_report(report, buf, &hold);
-
-
if (to_send == -1)
-
break;
-
-
if (write(fd, report, to_send) != to_send) {
-
perror(filename);
-
return 5;
-
}
-
if (!hold) {
-
memset(report, 0x0, sizeof(report));
-
if (write(fd, report, to_send) != to_send) {
-
perror(filename);
-
return 6;
-
}
-
}
-
}
-
}
-
-
close(fd);
-
return 0;
- }