做设计哪个网站可以接单不死鸟分享友情链接
说明
在rv1106平台上内核版本5.10上通过usb口接入电脑,被电脑识别成鼠标和键盘,模拟成键盘鼠标设备
一:修改内核配置
1:增加hid gadget,这里直接编进内核了,进入到内核源码树,make ARCH=arm menuconfig
Device Drivers--->USB support--->(*)USB Gadget Support--->USB Gadget precomposed configurations--->HID Gadget(*)
2:usb host修改为usb device
CONFIG_USB_DWC3=m
CONFIG_USB_DWC3_GADGET=y
二:修改设备树
usb修改为从机模式
/**********USB**********/
&usbdrd_dwc3 {
status = "okay";
dr_mode="peripheral";//"host";//dr_mode = "peripheral";
};
三:修改hid源码增加键鼠描述符及设备注册
/home/hfzuo/rock/luckfox-pico/sysdrv/source/kernel/drivers/usb/gadget/legacy/hid.c
/* hid descriptor for a keyboard */static struct hidg_func_descriptor pcduino_keyboard_date = {.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 */}};static struct platform_device pcduino_hid_keyboard = {.name = "hidg",.id = 0,.num_resources = 0,.resource = 0,.dev.platform_data = &pcduino_keyboard_date,};/* hid descriptor for a mouse */static struct hidg_func_descriptor pcduino_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, 0x05, //Usage Maximum(5)0x15, 0x00, //Logical Minimum(1)0x25, 0x01, //Logical Maximum(1)0x95, 0x05, //Report Count(5)0x75, 0x01, //Report Size(1)0x81, 0x02, //Input(Data,Variable,Absolute,BitField)0x95, 0x01, //Report Count(1)0x75, 0x03, //Report Size(3)0x81, 0x01, //Input(Constant,Array,Absolute,BitField)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, 0x03, //Report Count(3)0x81, 0x06, //Input(Data,Variable,Relative,BitField)0xc0, //End Collection0xc0 //End Collection}};static struct platform_device pcduino_hid_mouse = {.name = "hidg",.id = 1,.num_resources = 0,.resource = 0,.dev.platform_data = &pcduino_mouse_data,};static int __init hidg_init(void)
{int status;status = platform_device_register(&pcduino_hid_keyboard);if (status < 0) {printk("hid keyboard reg failed\n");platform_device_unregister(&pcduino_hid_keyboard);return status;}status = platform_device_register(&pcduino_hid_mouse);if (status < 0) {printk("hid mouse reg failed\n");platform_device_unregister(&pcduino_hid_mouse);return status;} status = platform_driver_probe(&hidg_plat_driver,hidg_plat_driver_probe);if (status < 0)return status;status = usb_composite_probe(&hidg_driver);if (status < 0)platform_driver_unregister(&hidg_plat_driver);return status;
}
module_init(hidg_init);static void __exit hidg_cleanup(void)
{platform_device_unregister(&pcduino_hid_keyboard);platform_device_unregister(&pcduino_hid_mouse);usb_composite_unregister(&hidg_driver);platform_driver_unregister(&hidg_plat_driver);
}
四:加载驱动
insmod dwc3.ko insmod dwc3-of-simple.ko,如果没问题就应该造 /sys/class/udc 下能找到udc
五:应用代码测试,模拟键鼠想电脑发送数据
/* hid_gadget_test */#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 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;
}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);elseto_send = joystick_fill_report(report, buf, &hold);if (to_send == -1)break;for(i=0;i<to_send;i++){printf("data[%d]=%x\r\n",i,report[i]);}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;
}
./gadget_hid /dev/hidg1 k 终端按提示输入 a b 即可看到键盘有输入a b
./gadget_hid /dev/hidg2 j -b3 -10 100 即可看到鼠标移动
五:键鼠数据分析
鼠标发送给 PC 的数据每次 4 个字节
BYTE1 BYTE2 BYTE3 BYTE4
定义分别是:
BYTE1 –
|–bit7: 1 表示 Y 坐标的变化量超出-256 ~ 255 的范围,0 表示没有溢出
|–bit6: 1 表示 X 坐标的变化量超出-256 ~ 255 的范围,0 表示没有溢出
|–bit5: Y 坐标变化的符号位,1 表示负数,即鼠标向下移动
|–bit4: X 坐标变化的符号位,1 表示负数,即鼠标向左移动
|–bit3: 恒为 1
|–bit2: 1 表示中键按下
|–bit1: 1 表示右键按下
|–bit0: 1 表示左键按下
BYTE2 — X 坐标变化量,与 byte 的 bit4 组成 9 位符号数,负数表示向左移,正数表右移。用补码表示变化量
BYTE3 — Y 坐标变化量,与 byte 的 bit5 组成 9 位符号数,负数表示向下移,正数表上移。用补码表示变化量
BYTE4 — 滚轮变化。
由于手上没有 USB 鼠标,对 BYTE1 的 4-7 位没有测试,对于 BYTE2 BYTE3 做个测试,BYTE1 的 4-7 全为 0 的时候,BYTE2 BYTE3 的正负表示鼠标移动方向
键盘发送给 PC 的数据每次 8 个字节
BYTE1 BYTE2 BYTE3 BYTE4 BYTE5 BYTE6 BYTE7 BYTE8
定义分别是:
BYTE1 –
|–bit0: Left Control 是否按下,按下为 1
|–bit1: Left Shift 是否按下,按下为 1
|–bit2: Left Alt 是否按下,按下为 1
|–bit3: Left GUI 是否按下,按下为 1
|–bit4: Right Control 是否按下,按下为 1
|–bit5: Right Shift 是否按下,按下为 1
|–bit6: Right Alt 是否按下,按下为 1
|–bit7: Right GUI 是否按下,按下为 1
BYTE2 — 暂不清楚,有的地方说是保留位
BYTE3–BYTE8 — 这六个为普通按键
键盘经过测试。
例如:键盘发送一帧数据 02 00 0×04 0×05 00 00 00 00
表示同时按下了 Left Shift + ‘a’+‘b’三个键
附件里面是 usb 协议中文版,喜欢折腾的可以看看。USB1.1 协议中文版