linxu hid hilicon实现鼠标键盘功能

参考https://www.cnblogs.com/sky-heaven/p/9265161.html 

1.linux内核配置 

Menuconfig->Device Drviers->USB Support <> Support for Host-side USB
[ ] USB verbose debug messages
[] USB announce new devices
*** Miscellaneous USB options ***
...... <*> USB Gadget Support --->

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

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

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

5.完成以上步骤,先保存退出。 ##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);
}

linux4.9需要加载的驱动为        libcomposite.ko

                                                  usb_f_hid.ko

                                                  g_hid.ko

6.上层测试代码

#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;
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值