文档章节

DM816X 实现 USB HID Gadget 鼠标键盘功能

喵帕斯_QAQ
 喵帕斯_QAQ
发布于 2015/05/05 10:18
字数 1992
阅读 2131
收藏 1

开发环境: 平台: 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。 摘录如下:

  1. 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 --->

  1. 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

  1. 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

  1. 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完成的,思路和代码大体是按其思路,只有修改了个别设备描述符。

© 著作权归作者所有

喵帕斯_QAQ
粉丝 0
博文 11
码字总数 5536
作品 0
海淀
程序员
私信 提问
【USB开发 】用pcDuino的otg做鼠标键盘

有人说现代社会,计算机锁住了人类的双手,为什么呢?因为基本上一个人一天上班8小时手是不断的在键盘鼠标上面工作的。我们能不能让电脑更智 能一些,例如电脑放弃人类的双手 ,更智能的工作...

pc朵拉
2013/12/04
2.1K
0
MicroPython开发板TPYBoard关于USB-HID的应用

USB-HID是Human Interface Device的缩写,属于人机交互操作的设备,如USB鼠标,USB键盘,USB游戏操纵杆,USB触摸板,USB轨迹球、电话拨号设备、VCR遥控等等设备。 TPYBoard借助micropython...

bodasisiter
2016/08/23
2.2K
2
Teensy HID攻击科普文

0x00 前言: 在2014年美国黑帽大会上,柏林SRLabs的安全研究人员JakobLell和独立安全研究人员Karsten Nohl展示了他们称为“BadUSB”(按照BadBIOS命名)的攻击方法。在认识BadUSB之前我们来先了...

wf4745
2014/10/26
0
0
Ghost Tunnel:适用于隔离网络的WiFi隐蔽传输通道

      一、前言   Ghost Tunnel是一种可适用于隔离环境下的后门传输方式,可在用户无感知情况下对目标进行控制及信息回传(不创建或依赖于任何有线、无线网络,甚至不需要外插任何硬件...

FreeBuf
2018/05/09
0
0
网友xiangyunangua写的PyNano控制键盘精彩例程

网友xiangyunangua写的PyNano控制键盘例程,非常精彩: 在第一弹里尝试了用PyNano作鼠标。 既然PyNano可以模拟鼠标,当然也可以模拟为键盘了。 利用键盘信号,我们可以做很多事情(嘿嘿),这...

shaoziyang
2016/11/27
15
0

没有更多内容

加载失败,请刷新页面

加载更多

SpringBoot系列教程JPA之新增记录使用姿势

SpringBoot系列教程JPA之新增记录使用姿势 上一篇文章介绍了如何快速的搭建一个JPA的项目环境,并给出了一个简单的演示demo,接下来我们开始业务教程,也就是我们常说的CURD,接下来进入第一...

小灰灰Blog
43分钟前
4
0
大话文本检测经典模型:Pixel-Anchor

文本检测是深度学习中一项非常重要的应用,在前面的文章中已经介绍过了很多文本检测的方法,包括CTPN(详见文章:大话文本检测经典模型CTPN)、SegLink(详见文章:大话文本检测经典模型Seg...

雪饼
46分钟前
2
0
手把手教你写一个RPC

1.1 RPC 是什么 定义:RPC(Remote Procedure Call Protocol)——远程过程调用协议 ,RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC...

我最喜欢三大框架
55分钟前
4
0
系统监控-SpringBoot四大神器之Actuator

1. 为什么要使用Actuator来监控SpringBoot项目? 首先之前博客提到过使用JDK自带的JVM监控工具、Psi-Probe Tomcat监控工具以及Javamelody,也提到了Psi-Probe的强大,但是Psi-Probe针对jar包...

秋日芒草
57分钟前
6
0
pip通过setup.py和git仓库安装package

安装setup.py配置文件中的包 进入到setup.py所在目录 pip install -e . 1 安装git仓库中的包 pip install git+git clone 仓库地址.git 1 python代码打包为whl格式 python setup.py bdist_wh...

dillonxiao
58分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部