DM816X 实现 USB HID Gadget 鼠标键盘功能【转】
转自:https://my.oschina.net/renyongke/blog/410695
开发环境: 平台: DM8168 内核 :linux 2.6.32 RDK:DVRRDK_04.00.00.03 USB口:DM8168有两个USB口可供选择,因为特殊原因我选择的是USB1,请根据实际需要选择USB口 ,下面的配置会稍微有些不同。
##1配置内核 依据参照http://processors.wiki.ti.com/index.php/DM81xx_AM38XX_USB_User_Guide#Introduction http://processors.wiki.ti.com/index.php/Usbgeneralpage#One_port_as_host_and_other_port_as_Gadget_.28for_DM81XX.29。 摘录如下:
- Select host and gadget support
Menuconfig->Device Drviers->USB Support <> Support for Host-side USB
[ ] USB verbose debug messages
[] USB announce new devices
*** Miscellaneous USB options ***
......
<*> USB Gadget Support --->
- Select USB OTG support (for TI816X)
Menuconfig->Device Drviers->USB Support
<> Inventra Highspeed Dual Role Controller (TI, ADI, ...)
*** Platform Glue Layer ***
< > TUSB6010
< > OMAP2430 and onwards
< > AM35x
<> TI81XX
TI816X usb connector's ID pin control (from software setting) --->
Force TI816X USB0 to (Host mode) --->
Force TI816X USB1 to (Host mode) --->
Driver Mode (Both host and peripheral: USB OTG (On The Go) Device) --->
[ ] Disable DMA (always use PIO)
[*] Enable debugging messages
- Select Gadget device controller and gadget driver as modules
Menuconfig->Device Drviers->USB Support
<> USB Gadget Support --->
--- USB Gadget Support
[ ] Debugging messages (DEVELOPMENT) (NEW)
[ ] Debugging information files (DEVELOPMENT) (NEW)
[ ] Debugging information files in debugfs (DEVELOPMENT) (NEW)
(2) Maximum VBUS Power usage (2-500 mA) (NEW)
USB Peripheral Controller (Inventra HDRC USB Peripheral (TI, ADI, ...)) --->
<M> USB Gadget Drivers
<M> Gadget Zero (DEVELOPMENT)
[ ] HNP Test Device (NEW)
< > Audio Gadget (EXPERIMENTAL) (NEW)
<M> Ethernet Gadget (with CDC Ethernet support)
[] RNDIS support (NEW)
[ ] Ethernet Emulation Model (EEM) support (NEW)
< > Gadget Filesystem (EXPERIMENTAL) (NEW)
< > Function Filesystem (EXPERIMENTAL) (NEW)
<M> File-backed Storage Gadget
[*] File-backed Storage Gadget testing version
- Unselect the OTG Targeted Peripherals list
Menuconfig->Device Drviers->USB Support
<> Support for Host-side USB
....
[] USB runtime power management (autosuspend) and wakeup
-*- OTG support
[ ] Rely on OTG Targeted Peripherals List
[ ] Disable external hubs
完成以上步骤,先保存退出。
##2设备注册
为了实现设备被识别,需加入设备注册。修改hid.c 路径: DVRRDK_04.00.00.03/ti_tools/linux_lsp/kernel/linux-dvr-rdk/drivers/usb/gadget。
由于鼠标键盘为常见USB设备,设备描述符很好得到,如果是要自定义hid设备请参照usb协议.pdf(网络上很容易找到)。
修改如下
#include <linux/usb/g_hid.h>
/* hid descriptor for a keyboard */
static struct hidg_func_descriptor pcdm8168_keyboard_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 */
}
};
/*hid descriptor for a mouse*/
static struct hidg_func_descriptor pcdm8168_mouse_data = {
.subclass = 0, /*NO SubClass*/
.protocol = 2, /*Mouse*/
.report_length = 4,
.report_desc_length = 52,
.report_desc={
0x05,0x01, /*Usage Page (Generic Desktop Controls)*/
0x09,0x02, /*Usage (Mouse)*/
0xa1,0x01, /*Collction (Application)*/
0x09,0x01, /*Usage (pointer)*/
0xa1,0x00, /*Collction (Physical)*/
0x05,0x09, /*Usage Page (Button)*/
0x19,0x01, /*Usage Minimum(1)*/
0x29,0x03, /*Usage Maximum(3) */
0x15,0x00, /*Logical Minimum(1)*/
0x25,0x01, /*Logical Maximum(1)*/
0x95,0x03, /*Report Count(5) */
0x75,0x01, /*Report Size(1)*/
0x81,0x02, /*Input(Data,Variable,Absolute,BitFiled)*/
0x95,0x01, /*Report Count(1)*/
0x75,0x05, /*Report Size(5) */
0x81,0x01, /*Input(Constant,Array,Absolute,BitFiled) */
0x05,0x01, /*Usage Page (Generic Desktop Controls)*/
0x09,0x30, /*Usage(x)*/
0x09,0x31, /*Usage(y)*/
0x09,0x38, /*Usage(Wheel)*/
0x15,0x81, /*Logical Minimum(-127)*/
0x25,0x7f, /*Logical Maximum(127)*/
0x75,0x08, /*Report Size(8)*/
0x95,0x02, /*Report Count(2) */
0x81,0x06, /*Input(Data,Variable,Relative,BitFiled)*/
0xc0, /*End Collection*/
0xc0 /*End Collection*/
}
};
static struct platform_device pcdm8168_hid_keyboard = {
.name = "hidg",
.id = 0,
.num_resources = 0,
.resource = 0,
.dev.platform_data = &pcdm8168_keyboard_data,
};
static struct platform_device pcdm8168_hid_mouse = {
.name = "hidg",
.id = 1,
.num_resources = 0,
.resource = 0,
.dev.platform_data = &pcdm8168_mouse_data,
};
static int __init hidg_init(void)
{
int status;
status = platform_device_register(&pcdm8168_hid_keyboard);
if (status < 0)
{
printk("platform_driver hid keyboard:*****wrong\n");
platform_device_unregister(&pcdm8168_hid_keyboard);
return status;
}
status = platform_device_register(&pcdm8168_hid_mouse);
if (status < 0)
{
printk("platform_driver hid mouse:*****wrong\n");
platform_device_unregister(&pcdm8168_hid_mouse);
return status;
}
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;
}
static void __exit hidg_cleanup(void)
{
platform_driver_unregister(&hidg_plat_driver);
platform_device_unregister(&pcdm8168_hid_keyboard);
platform_device_unregister(&pcdm8168_hid_mouse);
usb_composite_unregister(&hidg_driver);
}
##3编译 继续完成内核配置的后续操作 1)Build uImage and usb gadget modules
Build the kernel image and the two usb gadget as modules (like g_ether.ko, g_file_storage.ko, g_mass_storage.ko or g_zero.ko ..etc).
编译内核 以及 上方修改的代码 ,根据自己的开发环境编译 我的是 make lsp ##4测试
通过USB线把8168板子和PC机 连接接起来。 1)Insert the two gadget modules
Load the kernel image and Make sure above setup is done before insert the modules. Insert the gadget modules for usb0 port.
insmod <module>.ko (eg: #insert g_ether.ko) Insert the gadget
module for usb1 port.
insmod <module>.ko (eg: #insert g_file_storage.kofile=<filepath> stall=0 buflen=65536)
8168上电,进入工作目录,make init 和 make load(个人需要) 由于我所用板子使用的是USB1,没有使用USB0,但是由于8168的特性,USB0也必须进行配置, 我的配置如下: insmod g_ether.ko insmod g_hid.ko
这时打开PC的设别管理器会发现,8168已经被识别成鼠标和键盘。 为了测试其功能是否正常需要写一小测试程序, 如下:
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.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;
}
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( " --quit to close\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");
}
}
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\n",
argv[0]);
return 1;
}
if(argv[2][0] != 'k' && argv[2][0] != 'm')
{
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);
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;
}
需要交叉编译器进行编译,我使用的是arm-none-linux-gnueabi-gcc-4.3.3
编译完成后,把生成的执行文件cp到设备中分别执行 ./pcdm8168_hid /dev/hidg0 k和./pcdm8168_hid /dev/hidg1 m 根据提示进行操作即可。
声明:上文是参考http://www.oschina.net/question/1174645_135969完成的,思路和代码大体是按其思路,只有修改了个别设备描述符
DM816X 实现 USB HID Gadget 鼠标键盘功能【转】的更多相关文章
- USB HID复合设备实例—键盘+鼠标
实现这种USB HID复合设备有两种方法,在<USB HID协议入门>一节已经讲到其中一种方法,说一个USB HID设备可以包含多种功能的报告描述符合集,这样可以实现复合设备,如带鼠标功能 ...
- 使用Gadget 做usb鼠标键盘设备
使用Gadget 做usb鼠标键盘设备 感谢TI社区提供的好帮助啊!http://e2e.ti.com/support/arm/sitara_arm/f/791/p/571771/2103409?pi ...
- 玩转X-CTR100 l USB功能-HOST鼠标键盘
更多塔克创新资讯欢迎登陆[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] X-CTR100控制器具有MicroUSB接口,支持SLAVE和HOST两 ...
- usb的hid鼠标键盘报告描述符(五)
title: usb的hid鼠标键盘报告描述符 tags: linux date: 2018/12/20/ 18:05:08 toc: true --- usb的hid鼠标键盘报告描述符 https: ...
- linux 读取 USB HID鼠标坐标和点击 在 LCD上显示
首先要,编译内核时启用了 USB HID 设备.启用了 鼠标 . 在开发板上插入usb 时会有如下提示. 可以看到,多了一个 mouse0 和 eventX 打出来的是我的 联想鼠标. 1, 在 终端 ...
- Qt移植对USB鼠标键盘、触摸屏的支持
.USB键盘 经过一番搜索,发现对Qt键盘的支持主要关系到两个方面: 1. 键盘类型确定: 4.7以前的Qt版本,如果是PS2圆孔键盘,Qt编译时需加上选项:-qt-kbd-vr41xx(未测试):如 ...
- USB HID介绍【转】
本文转载自:http://blog.csdn.net/leo_wonty/article/details/6721214 HID是一种USB通信协议,无需安装驱动就能进行交互,在学习HID之前,先来复 ...
- USB HID 协议入门
转载请注明来源:cuixiaolei的技术博客 USB HID设备类的应用场合 USB HID类是USB设备的一个标准设备类,包括的设备非常多.HID类设备定义它属于人机交互操作的设备,用于控制计算机 ...
- USB HID介绍
HID是一种USB通信协议,无需安装驱动就能进行交互,在学习HID之前,先来复习一下USB协议的相关内容. USB设备描述符-概述 当插入USB设备后,主机会向设备请求各种描述符来识别设备.那什么是设 ...
随机推荐
- Docker打DB2 9.7镜像采坑相关
概况:以centos:7.2.1511镜像为基础镜像,使用docker commit方式进行构建 步骤: 运行centos7.2.1511镜像(以特权模式运行,后续内核参数修改必需参数) dock ...
- c++ 读写功能
课程作业三 git链接: Operations 感想 这次代码修改的地方主要有,加入了文件读写.读出功能,以及分离函数写到了头文件里. 但是也有很多不足的地方,首先本来想要 ...
- ElasticSearch 2 (30) - 信息聚合系列之条形图
ElasticSearch 2 (30) - 信息聚合系列之条形图 摘要 版本 elasticsearch版本: elasticsearch-2.x 内容 聚合还有一个令人激动的特性就是能够十分容易地 ...
- Alpha 冲刺一
团队成员 051601135 岳冠宇 051604103 陈思孝 031602629 刘意晗 031602248 郑智文 031602234 王淇 会议照片 项目燃尽图 项目进展 界面(简陋) 登录界 ...
- [转帖] 一文看懂:"边缘计算"究竟是什么?为何潜力无限?
一文看懂:"边缘计算"究竟是什么?为何潜力无限? 转载cnbeta 云计算 雾计算 边缘计算... 知名创投调研机构CB Insights撰文详述了边缘计算的发展和应用前景 ...
- IntelliJ IDEA2017 修改缓存文件的路径
IDEA的缓存文件夹.IntelliJIdea2017.1,存放着IDEA的破解密码,各个项目的缓存,默认是在C盘的用户目录下,目前有1.5G大小.现在想要把它从C盘移出. 在IDEA的安装路径下中, ...
- 【题解】 Test 买水的ACX(套路)
题目描述: ACX在××信竞组学会信息竞赛,但是他的同学都很巨,于是要他去买水,结果来到某个买水的商店(奇奇怪怪的商店). 一天,ACX买了 N 个容量可以认为是无限大的瓶子,初始时每个瓶子里有 1 ...
- 【贪心策略】USACO 越野跑
问题 H: 越野跑[贪心策略] [题面] 为了能在下一次跑步比赛中有好的发挥,贝茜在一条山路上开始了她的训练.贝茜希望能在每次训练中跑得尽可能远,不过她也知道农场中的一条规定:奶牛独自进山的时间不得超 ...
- 【转】树莓派Raspberry Pi - 还原已经装过系统的TF卡
想给树莓派换个系统的话,需要先把已经装过系统的TF卡进行还原,这里使用最简单粗暴无脑的方法: 1,下载安装Win32 Disk Imager(一般已经装过一次系统后,这个东西都有) 2,下载boots ...
- 错误日志收集sentry的安装与简单使用
通过官方文档https://docs.sentry.io/可以得知,安装服务有两种方式,一种是使用Python,这种方式个人感觉比较麻烦.于是选择了第二种方式:使用docker. 我是在Windows ...