[PATCH v2 10/25] docs/zh_CN: Add gadget_hid.rst translation
#UpdatedFrom:macrofun <baikefan@leap-io-kernel.com>
Date:
Message-ID:<24670a5803653b6532541f4fe02ecb06f7efec5a.1763897036.git.baikefan@leap-io-kernel.com>
Patch:v2 · 10/25
Language:zh_CN
Patch-ID:80f03758cae4aca899c313a7b407497cba86fce1
Files:
Documentation/translations/zh_CN/usb/gadget_hid.rstLinks:lore message ↗ · raw mail ↗
Patch content 1 changed file
Translate .../usb/gadget_hid.rst into Chinese. Update the translation through commit ffeb1e9e897b("USB: Replace HTTP links with HTTPS ones") Signed-off-by: macrofun <baikefan@leap-io-kernel.com>--- .../translations/zh_CN/usb/gadget_hid.rst | 462 ++++++++++++++++++ 1 file changed, 462 insertions(+) create mode 100644 Documentation/translations/zh_CN/usb/gadget_hid.rst diff --git a/Documentation/translations/zh_CN/usb/gadget_hid.rst b/Documentation/translations/zh_CN/usb/gadget_hid.rstnew file mode 100644index 000000000000..3c1fa8ed3979--- /dev/null+++ b/Documentation/translations/zh_CN/usb/gadget_hid.rst@@ -0,0 +1,462 @@+.. SPDX-License-Identifier: GPL-2.0+.. include:: ../disclaimer-zh_CN.rst++:Original: Documentation/usb/gadget_hid.rst+:翻译:++ 白钶凡 Kefan Bai <baikefan@leap-io-kernel.com>++:校译:++++===========================+Linux USB HID gadget驱动+===========================++简介+====+HID Gadget驱动提供USB人机接口设备(HID)的模拟实现。+基础的HID处理由内核完成,+HID报告可以通过对 /dev/hidgX 字符设备进行I/O来发送/接收。++关于HID的更多细节请参考开发者页面:+https://www.usb.org/developers/hidpage/++配置+====+g_hid是一个 platform driver,因此要使用它,+你需要在平台代码中添加 struct platform_device,+定义你想要使用的HID功能描述符 —— 例如如下代码:::++ #include <linux/platform_device.h>+ #include <linux/usb/g_hid.h>++ /* hid descriptor for a keyboard */+ static struct hidg_func_descriptor my_hid_data = {+ .subclass = 0, /* 无子类 */+ .protocol = 1, /* 键盘 */+ .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 my_hid = {+ .name = "hidg",+ .id = 0,+ .num_resources = 0,+ .resource = 0,+ .dev.platform_data = &my_hid_data,+ };++你可以添加任意数量的HID功能,+唯一的限制是gadget驱动所支持的中断端点数量。++使用configfs进行配置+======================++与其通过添加虚拟的platform device和driver来向内核传递数据,不如这样做:+如果HID是由configfs组成的gadget的一部分,+hidg_func_descriptor.report_desc可以直接通过+向configfs属性写入相应的字节流来传递给内核。++发送和接收HID报告+====================++HID报告可以通过对/dev/hidgX字符设备执行+read/write来发送或接收。下面是一个示例程序展示如何实现。++hid_gadget_test是一个用于测试HID gadget驱动的小型交互程序。+使用方式是指定一个hidg设备并设置设备类型(keyboard / mouse / joystick)+—— 例如::++ # hid_gadget_test /dev/hidg0 keyboard++现在你进入了hid_gadget_test的提示界面。+你可以输入任意组合的选项和值。+可用的选项和值会在程序启动时列出。+在键盘模式下,你最多可以发送六个值。++例如输入: g i s t r --left-shift++按回车后,会由HID gadget发送对应的报告。++另一个有趣的例子是大小写锁定(caps lock)测试。+输入--caps-lock 然后回车,gadget 会发送一个报告,+并且你将收到主机端的回应,对应于 caps lock LED 的状态::++ --caps-lock+ recv report:2++使用以下命令::++ # hid_gadget_test /dev/hidg1 mouse++你可以测试鼠标模拟。数值是两个有符号数。+++示例代码::++ /* 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 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;+ }++ 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);+ else+ to_send = joystick_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;+ }-- 2.52.0