USB gadget hid

2023-10-06 20:00
文章标签 usb hid gadget

本文主要是介绍USB gadget hid,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

摘要
主要实现让dm8168被识别成鼠标和键盘,以达到可以远程控制和dm8168相连的pc

开发环境: 平台: 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#Introductionhttp://processors.wiki.ti.com/index.php/Usbgeneralpage#Oneport_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 --->

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

完成以上步骤,先保存退出。

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 512struct 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 根据提示进行操作即可。

这篇关于USB gadget hid的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/153896

相关文章

Usb Audio Device Descriptor(10) Hid Device

对于 Standard Interface Descriptor, 当 bInterfaceClass=0x03时,即为HID设备。Standard Interface Descriptor如下 struct usb_standard_interface_descriptor{U8 bLength; /*Size of this descriptor in bytes*/U8 bDescrip

Android rk3399 UAC(USB Audio)开发笔记

一、UAC有1.0和2.0,因Windows对2.0支持不好,我使用的是UAC1.0驱动 内核配置:CONFIG_USB_CONFIGFS_F_UAC1          ---这个宏配置无需物理codec,使用虚拟 alsa codec  驱动路径:"kernel\drivers\usb\gadget\function\f_uac1.c" 内核配置:CONFIG_USB_CONFIGFS_

多款式随身WiFi如何挑选,USB随身WiFi、无线电池随身WiFi、充电宝随身WiFi哪个好?优缺点分析!

市面上的随身WiFi款式多样琳琅满目,最具代表性的就是USB插电款、无线款和充电宝款。今天就来用一篇文章分析一下这三种款式的优缺点。 USB插电款 优点:便宜,无需充电,在有电源的地方可以随时随地插电使用,比如中兴的USB随身WiFi。 缺点:无电源的情况下,无法带出门使用,部分品牌考虑到这个问题,会配备一个充电仓,这个充电仓相对来说就有点累赘了。网速上也不太稳定,波动比较大。

基于FPGA的开源项目:FOC/SHA/USB/JPEG等

文章目录 [1. USB 1.1控制器](https://github.com/WangXuan95/FPGA-USB-Device)[2. FOC控制算法](https://github.com/WangXuan95/FPGA-FOC)[3. BSV高级硬件描述语言入门指南](https://github.com/WangXuan95/BSV_Tutorial_cn)[4. 基于XDMA的

关于小米手机USB传输稍大点的文件老中断的问题解决方法!

关于小米手机USB传输稍大点的文件老中断的问题解决方法! 这是一个很痛苦的事情,当你传输大文件的时候,传输到一半就会莫名其妙的中断,拔插数据线很多次以后,好不容易没准可以成功传输一次。 后来使用了360的手机助手,从调试模式传输文件,虽然不会中断,但是慢的要死。 最后我看到手机插上后手机提示 有3种模式:仅限充电 传输文件(MTP) 传输照片(PTP)。当然我们选择传输文件是没戏了,会中

VirtualBox安装VirtualBox Extension Pack,支持USB No USB devices connected after upgrade

安装步骤及出现问题解决No USB devices connected after upgrade: 一、本要主机ubuntu14.04,安装virtualbox,支持usb设置步骤: 1.安装VirtualBox. 可以从https://www.virtualbox.org官方站点下载或者从软件中心。 2.在VirtualBox里安装Windows; 3.为USB2.0,你需要

QT Android开发之Android端usb调试模式设置与问题解决

一.QT android开发android端usb调试模式设置 QT android开发环境搭建完成后,android设备需要打开usb调试模式才能正常连接,下面以小米ipad为例进行设置(其他手机和ipad设置方法类似) 常见问题: 本文会介绍相关问题的解决方法。 二.小

【电子通识】无法识别USB设备怎么就和USB线序有关系

最近在做一个和USB通信有关的工装,有点类似于HUB但又有点不同。Type-C和USB-A两种输入选择,然后再选择输出8个通道中的一个。         在焊接调试时,首先先验证一路。因为USB-A公头转USB-A公头的线有点难找,所以找到一根USB线缆,中间剪掉一半直接焊在USBA焊盘上方便调试。         根据标准的USB接口线颜色的定义,一般为红(VCC)

将RK3588平台的TMC等USB function驱动挪出内核源码树

背景 前一段时间定位一个上位机通过USB-TMC连接下位机(基于RK3588平台)时界面发生卡顿的问题,发现USB-TMC驱动代码是放在内核源码树里跟内核一起编译的,觉着这样既不便于更换TMC 驱动版本(每次修改代码都要重编内核),也不便于将TMC驱动代码单独放到SVN管理(RK的build系统有16GB之巨,全部提交到SVN服务器吃不消),于是考虑将其挪到源码树外。 想参照自己之前在zynq

Linux内核源码-USB驱动分析

基础层次详解 通用串行总线(USB)主要用于连接主机和外部设备(协调主机和设备之间的通讯),USB 设备不能主动向主机发送数据。USB 总线采用拓扑(树形),主机侧和设备侧的 USB 控制器(Host 和 UDC),每个总线只要一个主机控制器。 主机侧的 USB 节点为根节点,所有子节点都连接在根节点集线器(Root hub)上,根节点有 USB 主机控制器(USB Host Controll