From 39f11c5b4b5f9249123d564e2347a6b7815b05cd Mon Sep 17 00:00:00 2001 From: login Date: Fri, 14 Oct 2022 18:45:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Eusb=20hid=20report=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=99=A8=20(#58)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * new: usb hid parser --- .vscode/settings.json | 3 +- kernel/common/compiler_attributes.h | 1 + kernel/common/hid.h | 97 ++ kernel/driver/Makefile | 2 +- kernel/driver/hid/Makefile | 19 + kernel/driver/hid/hidparse.c | 526 +++++++++ kernel/driver/hid/hidstrings.c | 1580 +++++++++++++++++++++++++++ kernel/driver/hid/internal.h | 37 + kernel/driver/hid/usbhid/Makefile | 15 + kernel/driver/usb/usb.h | 32 +- kernel/driver/usb/xhci/xhci.c | 357 ++++-- 11 files changed, 2567 insertions(+), 102 deletions(-) create mode 100644 kernel/common/hid.h create mode 100644 kernel/driver/hid/Makefile create mode 100644 kernel/driver/hid/hidparse.c create mode 100644 kernel/driver/hid/hidstrings.c create mode 100644 kernel/driver/hid/internal.h create mode 100644 kernel/driver/hid/usbhid/Makefile diff --git a/.vscode/settings.json b/.vscode/settings.json index c4e42aef..f840a4b2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -145,7 +145,8 @@ "kthread.h": "c", "lockref.h": "c", "compiler_attributes.h": "c", - "timer.h": "c" + "timer.h": "c", + "hid.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "" diff --git a/kernel/common/compiler_attributes.h b/kernel/common/compiler_attributes.h index b77cae26..12278be6 100644 --- a/kernel/common/compiler_attributes.h +++ b/kernel/common/compiler_attributes.h @@ -1,4 +1,5 @@ #pragma once +#include // 当函数的返回值未被使用时,编译器抛出警告信息 #define __must_check __attribute__((__warn_unused_result__)) diff --git a/kernel/common/hid.h b/kernel/common/hid.h new file mode 100644 index 00000000..a215de3a --- /dev/null +++ b/kernel/common/hid.h @@ -0,0 +1,97 @@ +#pragma once +#include + +#define __HID_USAGE_TABLE_SIZE 64 // usage stack的大小 +#define HID_MAX_REPORT 300 // 最大允许的hid report数目(包括feature、input、output) +#define HID_MAX_PATH_SIZE 16 // maximum depth for path + +/** + * @brief 描述hid path中的一个节点 + * + */ +struct hid_node_t +{ + int u_page; + int usage; +}; + +/** + * @brief 描述一条hid path + * + */ +struct hid_path_t +{ + int size; // 路径中的节点数目 + struct hid_node_t node[HID_MAX_PATH_SIZE]; +}; + +/** + * @brief Describe a HID Data with its location in report + * + */ +struct hid_data_t +{ + int value; // hid对象的值 + struct hid_path_t path; // hid path + + int report_count; // count of reports for this usage type + int offset; // offset of data in report + int size; // size of data in bits + + uint8_t report_id; // report id(from incoming report) + uint8_t type; // 数据类型:FEATURE / INPUT / OUTPUT + uint8_t attribute; // report field attribute. (2 = (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)) + // (6 = (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)) + int8_t unit_exp; // unit exponent; + + uint32_t unit; // HID unit + + int logical_min; // Logical min + int logical_max; // Logical max + int phys_min; // Physical min + int phys_max; // Physical max +}; + +/** + * @brief hid解析器 + * + */ +struct hid_parser +{ + const uint8_t *report_desc; // 指向report descriptor的指针 + int report_desc_size; // report descriptor的大小(字节) + int pos; // report_desc中,当前正在处理的位置 + uint8_t item; // 暂存当前的item + uint32_t value; // 暂存当前的值 + + struct hid_data_t data; // 存储当前的环境 + + int offset_table[HID_MAX_REPORT][3]; // 存储 hid report的ID、type、offset + int report_count; // hid report的数量 + int count; // local items的计数 + + uint32_t u_page; + struct hid_node_t usage_table[__HID_USAGE_TABLE_SIZE]; // Usage stack + int usage_size; // usage的数量 + int usage_min; + int usage_max; + + int cnt_objects; // report descriptor中的对象数目 + int cnt_report // report desc中的report数目 +}; + + +struct hid_usage_types_string +{ + int value; + const char *string; +}; + +struct hid_usage_pages_string +{ + int value; + struct hid_usage_types_string * types; + const char * string; +}; + +int hid_parse_report(const void *report_data, const int len); diff --git a/kernel/driver/Makefile b/kernel/driver/Makefile index bbd51c12..3b84c7ef 100644 --- a/kernel/driver/Makefile +++ b/kernel/driver/Makefile @@ -1,7 +1,7 @@ CFLAGS += -I . -kernel_driver_subdirs:=video interrupt usb pci uart acpi disk keyboard mouse multiboot2 timers tty +kernel_driver_subdirs:=video interrupt usb pci uart acpi disk keyboard mouse multiboot2 timers tty hid ECHO: @echo "$@" diff --git a/kernel/driver/hid/Makefile b/kernel/driver/hid/Makefile new file mode 100644 index 00000000..63f6e33f --- /dev/null +++ b/kernel/driver/hid/Makefile @@ -0,0 +1,19 @@ + +CFLAGS += -I . + +kernel_driver_hid_subdirs:= usbhid + +kernel_driver_hid_objs:= $(shell find ./*.c) + +ECHO: + @echo "$@" + +$(kernel_driver_hid_subdirs): ECHO + $(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" PIC="$(PIC)" + +$(kernel_driver_hid_objs): ECHO + gcc $(CFLAGS) -c $@ -o $@.o + +all: $(kernel_driver_hid_objs) $(kernel_driver_hid_subdirs) + @echo $(kernel_driver_hid_objs) + diff --git a/kernel/driver/hid/hidparse.c b/kernel/driver/hid/hidparse.c new file mode 100644 index 00000000..c882f47a --- /dev/null +++ b/kernel/driver/hid/hidparse.c @@ -0,0 +1,526 @@ +#include "internal.h" +#include +#include +#include +#include +#include +#include + +/* + 参考文档:https://www.usb.org/document-library/device-class-definition-hid-111 + 本文件参考了FYSOS: https://github.com/fysnet/FYSOS.git + */ + +static bool HID_PARSE_OUTPUT = true; // 是否输出解析信息 +static char __tmp_usage_page_str[128] = {0}; + +static void hid_reset_parser(struct hid_parser *parser); + +static const char *hid_get_usage_page_str(const int u_page); +static const char *hid_get_usage_type_str(const int page, const int type); +static const char *hid_get_collection_str(const int value); +static int *__get_report_offset(struct hid_parser *parser, const uint8_t report_id, const uint8_t report_type); +static __always_inline const struct hid_usage_pages_string *hid_get_usage_page(const int u_page); + +static __always_inline const struct hid_usage_types_string *hid_get_usage_type( + const struct hid_usage_pages_string *upage, const int type); + +// hid item的低2位为size +#define HID_SIZE_MASK 0x3 +// 高6bit为item内容 +#define HID_ITEM_MASK 0xFC +#define HID_ITEM_UPAGE 0x04 // usage page +#define HID_ITEM_USAGE 0x08 // local item +#define HID_ITEM_LOG_MIN 0x14 +#define HID_ITEM_USAGE_MIN 0x18 // local item +#define HID_ITEM_LOG_MAX 0x24 +#define HID_ITEM_USAGE_MAX 0x28 // local item +#define HID_ITEM_PHY_MIN 0x34 +#define HID_ITEM_PHY_MAX 0x44 +#define HID_ITEM_UNIT_EXP 0x54 +#define HID_ITEM_UNIT 0x64 +#define HID_ITEM_REP_SIZE 0x74 +#define HID_ITEM_STRING 0x78 // local item? +#define HID_ITEM_REP_ID 0x84 +#define HID_ITEM_REP_COUNT 0x94 + +// 这部分请参考hid_1_11.pdf Section 6.2.2.4 + +#define HID_ITEM_COLLECTION 0xA0 +#define HID_ITEM_END_COLLECTION 0xC0 +#define HID_ITEM_FEATURE 0xB0 +#define HID_ITEM_INPUT 0x80 +#define HID_ITEM_OUTPUT 0x90 + +static char __spaces_buf[33]; +char *__spaces(uint8_t cnt) +{ + static char __space_overflow_str[] = "**"; + if (cnt > 32) + { + return &__space_overflow_str; + } + + memset(__spaces_buf, ' ', 32); + __spaces_buf[cnt] = '\0'; + return __spaces_buf; +} + +static __always_inline uint32_t __format_value(uint32_t value, uint8_t size) +{ + switch (size) + { + case 1: + value = (uint32_t)(uint8_t)value; + break; + case 2: + value = (uint32_t)(uint16_t)value; + break; + } + return value; +} + +/** + * @brief 重置parser + * + * @param parser 解析器 + * @return int 状态码 + */ +static void hid_reset_parser(struct hid_parser *parser) +{ + memset(parser, 0, sizeof(struct hid_parser)); + parser->data.report_id = 1; // we must give it a non-zero value or the parser doesn't work +} + +/** + * @brief 从usage_stack中弹出第一个元素 + * + * @param parser 解析器 + * @return __always_inline + */ +static __always_inline void __pop_usage_stack(struct hid_parser *parser) +{ + if (parser->usage_size > 0) + { + for (int js = 0; js < parser->usage_size - 1; ++js) + memmove(&parser->usage_table[js], &parser->usage_table[js + 1], sizeof(struct hid_node_t)); + + --parser->usage_size; + } +} + +/** + * @brief 解析hid report,并获取下一个数据到data字段中 + * + * @param parser 解析器 + * @param data 返回的数据 + * @return true 解析成功 + * @return false 解析失败 + */ +static bool hid_parse(struct hid_parser *parser, struct hid_data_t *data) +{ + bool found = false; + static uint8_t space_cnt = 0; + static bool did_collection = false; + static int item_size[4] = {0, 1, 2, 4}; + + // 循环解析 + while (!found && (parser->pos < parser->report_desc_size)) + { + // 当前parse过程还没有解析到report + if (parser->count == 0) + { + // 打印当前 report_data 的值 + if (HID_PARSE_OUTPUT) + printk("\n %02X ", parser->report_desc[parser->pos]); + // 获取到report size + parser->item = parser->report_desc[parser->pos++]; + parser->value = 0; + // 拷贝report的数据 + memcpy(&parser->value, &parser->report_desc[parser->pos], item_size[parser->item & HID_SIZE_MASK]); + + if (HID_PARSE_OUTPUT) + { + for (int i = 0; i < 4; ++i) + { + if (i < item_size[parser->item & HID_SIZE_MASK]) + printk("%02X ", parser->report_desc[parser->pos + i]); + else + printk(" "); + } + } + // 将指针指向下一个item + parser->pos += item_size[parser->item & HID_SIZE_MASK]; + } + + switch (parser->item & HID_ITEM_MASK) + { + case HID_ITEM_UPAGE: + // 拷贝upage + parser->u_page = (int)parser->value; + if (HID_PARSE_OUTPUT) + printk("%sUsage Page (%s)", __spaces(space_cnt), hid_get_usage_page_str(parser->u_page)); + // 拷贝到 usage table。由于这是一个USAGE entry,因此不增加usage_size(以便后面覆盖它) + parser->usage_table[parser->usage_size].u_page = parser->u_page; + parser->usage_table[parser->usage_size].usage = 0xff; + break; + case HID_ITEM_USAGE: + // 拷贝upage到usage table中 + if ((parser->item & HID_SIZE_MASK) > 2) // item大小为32字节 + parser->usage_table[parser->usage_size].u_page = (int)(parser->value >> 16); + else + parser->usage_table[parser->usage_size].u_page = parser->u_page; + + if (HID_PARSE_OUTPUT) + printk("%sUsage (%s)", __spaces(space_cnt), + hid_get_usage_type_str(parser->u_page, parser->value & 0xffff)); + ++parser->usage_size; + break; + case HID_ITEM_USAGE_MIN: + // todo: 设置usage min + if (HID_PARSE_OUTPUT) + printk("%sUsage min (%i=%s)", __spaces(space_cnt), parser->value, + hid_get_usage_type_str(parser->u_page, parser->value)); + break; + case HID_ITEM_USAGE_MAX: + // todo: 设置usage max + if (HID_PARSE_OUTPUT) + printk("%sUsage max (%i=%s)", __spaces(space_cnt), parser->value, + hid_get_usage_type_str(parser->u_page, parser->value)); + break; + case HID_ITEM_COLLECTION: + // 从usage table中取出第一个u_page和usage,并且将他们存储在parser->data.path + parser->data.path.node[parser->data.path.size].u_page = parser->usage_table[0].u_page; + parser->data.path.node[parser->data.path.size].usage = parser->usage_table[0].usage; + ++parser->data.path.size; + + // 由于上面取出了元素,因此将队列往前移动1个位置 + __pop_usage_stack(parser); + + // 获取index(如果有的话)??? + if (parser->value >= 0x80) + { + kdebug("parser->value > 0x80"); + parser->data.path.node[parser->data.path.size].u_page = 0xff; + parser->data.path.node[parser->data.path.size].usage = parser->value & 0x7f; + ++parser->data.path.size; + } + if (HID_PARSE_OUTPUT) + { + printk("%sCollection (%s)", __spaces(space_cnt), hid_get_collection_str(parser->value)); + space_cnt += 2; + } + break; + case HID_ITEM_END_COLLECTION: + --parser->data.path.size; // 为什么要--????? + // 删除多余的(未识别的)node + if (parser->data.path.node[parser->data.path.size].u_page == 0xff) + --parser->data.path.size; + if (HID_PARSE_OUTPUT) + { + if (space_cnt >= 2) + space_cnt -= 2; + printk("%sEnd Collection", __spaces(space_cnt)); + } + break; + case HID_ITEM_FEATURE: + case HID_ITEM_INPUT: + case HID_ITEM_OUTPUT: + // 找到了一个对象 + found = true; + + // 增加对象计数器 + ++parser->cnt_objects; + + // 更新local items的计数 + if (parser->count == 0) + parser->count = parser->report_count; + + // 从usage_table获取u_page和usage,将他们存储到parser.data.path + parser->data.path.node[parser->data.path.size].u_page = parser->usage_table[0].u_page; + parser->data.path.node[parser->data.path.size].usage = parser->usage_table[0].usage; + ++parser->data.path.size; + + // 从usage table中弹出刚刚那个node + __pop_usage_stack(parser); + + // 拷贝数据到data + parser->data.type = (uint8_t)(parser->item & HID_ITEM_MASK); + parser->data.attribute = (uint8_t)parser->value; + int *offset_ptr = + __get_report_offset(parser, parser->data.report_id, (uint8_t)(parser->item & HID_ITEM_MASK)); + + if (unlikely(offset_ptr == NULL)) + { + BUG_ON(1); + return false; + } + parser->data.offset = *offset_ptr; + + // 获取pData中的对象 + memcpy(data, &parser->data, sizeof(struct hid_data_t)); + + // 增加report offset + *offset_ptr = (*offset_ptr) + parser->data.size; + + // 从path中删除最后一个节点(刚刚弹出的这个节点) + --parser->data.path.size; + + // 减少local items计数 + if (parser->count > 0) + --parser->count; + + if (!did_collection) + { + if (HID_PARSE_OUTPUT) + { + if ((parser->item & HID_ITEM_MASK) == HID_ITEM_FEATURE) + printk("%sFeature ", __spaces(space_cnt)); + else if ((parser->item & HID_ITEM_MASK) == HID_ITEM_INPUT) + printk("%sInput ", __spaces(space_cnt)); + else if ((parser->item & HID_ITEM_MASK) == HID_ITEM_OUTPUT) + printk("%sOutut ", __spaces(space_cnt)); + + printk("(%s,%s,%s" /* ",%s,%s,%s,%s" */ ")", !(parser->value & (1 << 0)) ? "Data" : "Constant", + !(parser->value & (1 << 1)) ? "Array" : "Variable", + !(parser->value & (1 << 2)) ? "Absolute" : "Relative" /*, + !(parser->value & (1<<3)) ? "No Wrap" : "Wrap", + !(parser->value & (1<<4)) ? "Linear" : "Non Linear", + !(parser->value & (1<<5)) ? "Preferred State" : "No Preferred", + !(parser->value & (1<<6)) ? "No Null" : "Null State", + //!(parser->value & (1<<8)) ? "Bit Fueld" : "Buffered Bytes" + */ + ); + } + + did_collection = true; + } + break; + case HID_ITEM_REP_ID: // 当前item表示report id + parser->data.report_id = (uint8_t)parser->value; + if (HID_PARSE_OUTPUT) + printk("%sReport ID: %i", __spaces(space_cnt), parser->data.report_id); + break; + case HID_ITEM_REP_SIZE: // 当前item表示report size + parser->data.size = parser->value; + if (HID_PARSE_OUTPUT) + printk("%sReport size (%i)", __spaces(space_cnt), parser->data.size); + break; + case HID_ITEM_REP_COUNT: + parser->report_count = parser->value; + if (HID_PARSE_OUTPUT) + printk("%sReport count (%i)", __spaces(space_cnt), parser->report_count); + break; + case HID_ITEM_UNIT_EXP: + parser->data.unit_exp = (int8_t)parser->value; + if (parser->data.unit_exp > 7) + parser->data.unit_exp |= 0xf0; + if (HID_PARSE_OUTPUT) + printk("%sUnit Exp (%i)", __spaces(space_cnt), parser->data.unit_exp); + break; + case HID_ITEM_UNIT: + parser->data.unit = parser->value; + if (HID_PARSE_OUTPUT) + printk("%sUnit (%i)", __spaces(space_cnt), parser->data.unit); + break; + case HID_ITEM_LOG_MIN: // logical min + parser->data.logical_min = __format_value(parser->value, item_size[parser->item & HID_SIZE_MASK]); + if (HID_PARSE_OUTPUT) + printk("%sLogical Min (%i)", __spaces(space_cnt), parser->data.logical_min); + break; + case HID_ITEM_LOG_MAX: + parser->data.logical_max = __format_value(parser->value, item_size[parser->item & HID_SIZE_MASK]); + if (HID_PARSE_OUTPUT) + printk("%sLogical Max (%i)", __spaces(space_cnt), parser->data.logical_max); + break; + case HID_ITEM_PHY_MIN: + parser->data.phys_min = __format_value(parser->value, item_size[parser->item & HID_SIZE_MASK]); + if (HID_PARSE_OUTPUT) + printk("%Physical Min (%i)", __spaces(space_cnt), parser->data.phys_min); + break; + case HID_ITEM_PHY_MAX: + parser->data.phys_max = __format_value(parser->value, item_size[parser->item & HID_SIZE_MASK]); + if (HID_PARSE_OUTPUT) + printk("%Physical Max (%i)", __spaces(space_cnt), parser->data.phys_max); + break; + default: + printk("\n Found unknown item %#02X\n", parser->item & HID_ITEM_MASK); + return false; + } + } + return found; +} + +/** + * @brief 解析hid report的数据 + * + * @param report_data 从usb hid设备获取到hid report + * @param len report_data的大小(字节) + * @return int错误码 + */ +int hid_parse_report(const void *report_data, const int len) +{ + struct hid_parser parser = {0}; + struct hid_data_t data; + + hid_reset_parser(&parser); + parser.report_desc = (const uint8_t *)report_data; + parser.report_desc_size = len; + + while (hid_parse(&parser, &data)) + ; + return 0; +} + +/** + * @brief 根据usage page的id获取usage page string结构体.当u_page不属于任何已知的id时,返回NULL + * + * @param u_page usage page id + * @return const struct hid_usage_pages_string * usage page string结构体 + */ +static __always_inline const struct hid_usage_pages_string *hid_get_usage_page(const int u_page) +{ + int i = 0; + while ((hid_usage_page_strings[i].value < u_page) && (hid_usage_page_strings[i].value < 0xffff)) + ++i; + if ((hid_usage_page_strings[i].value != u_page) || (hid_usage_page_strings[i].value == 0xffff)) + return NULL; + else + return &hid_usage_page_strings[i]; +} + +/** + * @brief 从指定的upage获取指定类型的usage type结构体。当不存在时,返回NULL + * + * @param upage 指定的upage + * @param type usage的类型 + * @return const struct hid_usage_types_string * 目标usage type结构体。 + */ +static __always_inline const struct hid_usage_types_string *hid_get_usage_type( + const struct hid_usage_pages_string *upage, const int type) +{ + if (unlikely(upage == NULL || upage->types == NULL)) + { + BUG_ON(1); + return NULL; + } + struct hid_usage_types_string *types = upage->types; + int i = 0; + while ((types[i].value < type) && (types[i].value != 0xffff)) + ++i; + + if ((types[i].value != type) || (types[i].value == 0xffff)) + return NULL; + + return &types[i]; +} + +/** + * @brief 获取usage page的名称 + * + * @param u_page usage page的id + * @return const char* usage page的字符串 + */ +static const char *hid_get_usage_page_str(const int u_page) +{ + + const struct hid_usage_pages_string *upage = hid_get_usage_page(u_page); + if (unlikely(upage == NULL)) + { + sprintk(__tmp_usage_page_str, "Unknown Usage Page: %#04x", u_page); + return __tmp_usage_page_str; + } + return upage->string; +} + +/** + * @brief 打印usage page的指定类型的usage + * + * @param page usage page id + * @param type usage的类型 + * @return const char* + */ +static const char *hid_get_usage_type_str(const int page, const int type) +{ + const struct hid_usage_pages_string *upage = hid_get_usage_page(page); + if (unlikely(upage == NULL)) + { + sprintk(__tmp_usage_page_str, "Unknown Usage Page: %#04x", page); + return __tmp_usage_page_str; + } + + // button press, ordinal, or UTC + if (page == 0x0009) + { + sprintk(__tmp_usage_page_str, "Button number %i", type); + return __tmp_usage_page_str; + } + else if (page == 0x000a) + { + sprintk(__tmp_usage_page_str, "Ordinal %i", type); + return __tmp_usage_page_str; + } + else if (page == 0x0010) + { + sprintk(__tmp_usage_page_str, "UTC %#04X", type); + return __tmp_usage_page_str; + } + + const struct hid_usage_types_string *usage_type = hid_get_usage_type(upage, type); + if (unlikely(usage_type == NULL)) + { + sprintk(__tmp_usage_page_str, "Usage Page %s, with Unknown Type: %#04X", upage->string, type); + return __tmp_usage_page_str; + } + + return usage_type->string; +} + +/** + * @brief 输出colection字符串 + * + * @param value collection的值 + * @return const char* + */ +static const char *hid_get_collection_str(const int value) +{ + if (value <= 0x06) + return hid_collection_str[value]; + else if (value <= 0x7f) + return "Reserved"; + else if (value <= 0xff) + return "Vendor-defined"; + else + return "Error in get_collection_str(): value > 0xff"; +} + +/** + * @brief 从parser的offset table中,根据report_id和report_type,获取表中指向offset字段的指针 + * + * @param parser 解析器 + * @param report_id report_id + * @param report_type report类型 + * @return int* 指向offset字段的指针 + */ +static int *__get_report_offset(struct hid_parser *parser, const uint8_t report_id, const uint8_t report_type) +{ + int pos = 0; + // 尝试从已有的report中获取 + while ((pos < HID_MAX_REPORT) && (parser->offset_table[pos][0] != 0)) // 当offset的id不为0时 + { + if ((parser->offset_table[pos][0] == report_id) && (parser->offset_table[pos][1] == report_type)) + return &parser->offset_table[2]; + ++pos; + } + // 在offset table中占用一个新的表项来存储这个report的offset + if (pos < HID_MAX_REPORT) + { + ++parser->cnt_report; + parser->offset_table[pos][0] = report_id; + parser->offset_table[pos][1] = report_type; + parser->offset_table[pos][2] = 0; + return &parser->offset_table[pos][2]; + } + // 当offset table满了,且未找到结果的时候,返回NULL + return NULL; +} \ No newline at end of file diff --git a/kernel/driver/hid/hidstrings.c b/kernel/driver/hid/hidstrings.c new file mode 100644 index 00000000..eb938b8a --- /dev/null +++ b/kernel/driver/hid/hidstrings.c @@ -0,0 +1,1580 @@ +#include + +// Generic Desktop Devices +struct hid_usage_types_string hid_usage_type001[] = { + {0x0000, "Undefined"}, + {0x0001, "Pointer"}, + {0x0002, "Mouse"}, + {0x0003, "Reserved"}, + {0x0004, "Joystick"}, + {0x0005, "Game Pad"}, + {0x0006, "Keyboard"}, + {0x0007, "Keypad"}, + {0x0008, "Multi-axis Controller"}, + {0x0009, "Tablet PC System Controls"}, + {0x0030, "X"}, + {0x0031, "Y"}, + {0x0032, "Z"}, + {0x0033, "Rx"}, + {0x0034, "Ry"}, + {0x0035, "Rz"}, + {0x0036, "Slider"}, + {0x0037, "Dial"}, + {0x0038, "Wheel"}, + {0x0039, "Hat Switch"}, + {0x003A, "Counted Buffer"}, + {0x003B, "Byte Count"}, + {0x003C, "Motion Wake-up"}, + {0x003D, "Start"}, + {0x003E, "Select"}, + {0x003F, "Reserved"}, + {0x0040, "Vx"}, + {0x0041, "Vy"}, + {0x0042, "Vz"}, + {0x0043, "Vbrx"}, + {0x0044, "Vbry"}, + {0x0045, "Vbrz"}, + {0x0046, "Vno"}, + {0x0047, "Feature Notification"}, + {0x0048, "Resolution Mutliplier"}, + {0x0080, "System Control"}, + {0x0081, "System Power Down"}, + {0x0082, "System Sleep"}, + {0x0083, "System Wake-up"}, + {0x0084, "System Context Menu"}, + {0x0085, "System Main Menu"}, + {0x0086, "System App Menu"}, + {0x0087, "System Menu Help"}, + {0x0088, "System Menu Exit"}, + {0x0089, "System Menu Select"}, + {0x008A, "System Menu Right"}, + {0x008B, "System Menu Left"}, + {0x008C, "System Menu Up"}, + {0x008D, "System Menu Down"}, + {0x008E, "System Cold Restart "}, + {0x008F, "System Warm Restart"}, + {0x0090, "D-Pan Up"}, + {0x0091, "D-Pan Down"}, + {0x0092, "D-Pan Right"}, + {0x0093, "D-Pan Left"}, + {0x00A0, "System Dock"}, + {0x00A1, "System unDock"}, + {0x00A2, "System Setup"}, + {0x00A3, "System Break"}, + {0x00A4, "System Debugger Break"}, + {0x00A5, "Application Break"}, + {0x00A6, "Application Debugger Break"}, + {0x00A7, "System Speaker Mute"}, + {0x00A8, "System Hibernate"}, + {0x00B0, "System Display Invert"}, + {0x00B1, "System Display Internal"}, + {0x00B2, "System Display External"}, + {0x00B3, "System Display Both"}, + {0x00B4, "System Display Dual"}, + {0x00B5, "System Display Toggle Int/Ext"}, + {0x00B6, "System Display Swap Prim/Sec"}, + {0x00B7, "System Display Display Auto Scale"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type002[] = { + {0x0000, "Undefined"}, + {0x0001, "Flight Simulation Device"}, + {0x0002, "Automobile Simulation Device"}, + {0x0003, "Tank Simulation Device"}, + {0x0004, "Spaceship Simulation Device"}, + {0x0005, "Submarine Simulation Device"}, + {0x0006, "Sailing Simulation Device"}, + {0x0007, "Motorcycle Simulation Device"}, + {0x0008, "Sports Simulation Device"}, + {0x0009, "Airplane Simulation Device"}, + {0x000A, "Helicopter Simulation Device"}, + {0x000B, "Magic Carpet Simulation Device"}, + {0x000C, "Bicycle"}, + {0x0020, "Flight Control Stick"}, + {0x0021, "Flight Stick"}, + {0x0022, "Cyclic Control"}, + {0x0023, "Cyclic Trim"}, + {0x0024, "Flight Yoke"}, + {0x0025, "Track Control"}, + {0x0026, "Driving Control"}, + {0x00B0, "Aileron"}, + {0x00B1, "Aileron Trim"}, + {0x00B2, "Anti-Torque Control"}, + {0x00B3, "Auto-pilot Enable"}, + {0x00B4, "Chaff Release"}, + {0x00B5, "Collective Control"}, + {0x00B6, "Dive Brake"}, + {0x00B7, "Electronic Counter Measures"}, + {0x00B8, "Elevator"}, + {0x00B9, "Elevator Trim"}, + {0x00BA, "Rudder"}, + {0x00BB, "Throttle"}, + {0x00BC, "Flight Communication"}, + {0x00BD, "Flare Release"}, + {0x00BE, "Landing Gear"}, + {0x00BF, "Toe Brake"}, + {0x00C0, "Trigger"}, + {0x00C1, "Weapons Arm"}, + {0x00C2, "Weapons Select"}, + {0x00C3, "Wing Flaps"}, + {0x00C4, "Accelerator"}, + {0x00C5, "Brake"}, + {0x00C6, "Clutch"}, + {0x00C7, "Shifter"}, + {0x00C8, "Steering"}, + {0x00C9, "Turret Direction"}, + {0x00CA, "Barrel Elevation"}, + {0x00CB, "Dive Plane"}, + {0x00CC, "Ballast"}, + {0x00CD, "Bicycle Crank"}, + {0x00CE, "Handle Bars"}, + {0x00CF, "Front Brake"}, + {0x00D0, "Rear Brake"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type003[] = { + {0x0000, "Unidentified"}, + {0x0001, "Belt"}, + {0x0002, "Body Suit"}, + {0x0003, "Flexor"}, + {0x0004, "Glove"}, + {0x0005, "Head Tracker"}, + {0x0006, "Head Mounted Display"}, + {0x0007, "Hand Tracker"}, + {0x0008, "Oculometer"}, + {0x0009, "Vest"}, + {0x000A, "Animatronic Device"}, + {0x0020, "Stereo Enable"}, + {0x0021, "Display Enable"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type004[] = { + {0x0000, "Unidentified"}, + {0x0001, "Baseball Bat"}, + {0x0002, "Golf Club"}, + {0x0003, "Rowing Machine"}, + {0x0004, "Treadmill"}, + {0x0030, "Oar"}, + {0x0031, "Slope"}, + {0x0032, "Rate"}, + {0x0033, "Stick Speed"}, + {0x0034, "Stick Face Angle"}, + {0x0035, "Stick Heel/Toe"}, + {0x0036, "Stick Follow Through"}, + {0x0037, "Stick Tempo"}, + {0x0038, "Stick Type"}, + {0x0039, "Stick Height"}, + {0x0050, "Putter"}, + {0x0051, "1 Iron"}, + {0x0052, "2 Iron"}, + {0x0053, "3 Iron"}, + {0x0054, "4 Iron"}, + {0x0055, "5 Iron"}, + {0x0056, "6 Iron"}, + {0x0057, "7 Iron"}, + {0x0058, "8 Iron"}, + {0x0059, "9 Iron"}, + {0x005A, "10 Iron"}, + {0x005B, "11 Iron"}, + {0x005C, "Sand Wedge"}, + {0x005D, "Loft Wedge"}, + {0x005E, "Power Wedge"}, + {0x005F, "1 Wood"}, + {0x0060, "3 Wood"}, + {0x0061, "5 Wood"}, + {0x0062, "7 Wood"}, + {0x0063, "9 Wood"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type005[] = { + {0x0000, "Undefined"}, + {0x0001, "3D Game Controller"}, + {0x0002, "Pinball Device"}, + {0x0003, "Gun Device"}, + {0x0020, "Point of View"}, + {0x0021, "Turn Right/Left"}, + {0x0022, "Pitch Right/Left"}, + {0x0023, "Roll Forward/Backward"}, + {0x0024, "Move Right/Left"}, + {0x0025, "Move Forward/Backward"}, + {0x0026, "Move Up/Down"}, + {0x0027, "Lean Right/Left"}, + {0x0028, "Lean Forward/Backward"}, + {0x0029, "Height of POV"}, + {0x002A, "Flipper"}, + {0x002B, "Secondary Flipper"}, + {0x002C, "Bump"}, + {0x002D, "New Game"}, + {0x002E, "Shoot Ball"}, + {0x002F, "Player"}, + {0x0030, "Gun Bolt"}, + {0x0031, "Gun Clip"}, + {0x0032, "Gun Selector"}, + {0x0033, "Gun Single Shot"}, + {0x0034, "Gun Burst"}, + {0x0035, "Gun Automatic"}, + {0x0036, "Gun Safety"}, + {0x0037, "Gamepad Fire/Jump"}, + {0x0039, "Gamepad Trigger"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type006[] = { + {0x0000, "Unidentified"}, + {0x0020, " Battery Strength"}, + {0x0021, " Wireless Channel"}, + {0x0022, " Wireless ID"}, + {0x0023, " Discover Wireless Control"}, + {0x0024, " Security Code Character Entered"}, + {0x0025, " Security Code Character Erased"}, + {0x0026, " Security Code Cleared"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type007[] = { + {0x0000, "Reserved (no event indicated)"}, + {0x0001, "Keyboard ErrorRollOver"}, + {0x0002, "Keyboard POSTFail"}, + {0x0003, "Keyboard ErrorUndefined"}, + {0x0004, "Keyboard a and A"}, + {0x0005, "Keyboard b and B"}, + {0x0006, "Keyboard c and C"}, + {0x0007, "Keyboard d and D"}, + {0x0008, "Keyboard e and E"}, + {0x0009, "Keyboard f and F"}, + {0x000A, "Keyboard g and G"}, + {0x000B, "Keyboard h and H"}, + {0x000C, "Keyboard i and I"}, + {0x000D, "Keyboard j and J"}, + {0x000E, "Keyboard k and K"}, + {0x000F, "Keyboard l and L"}, + {0x0010, "Keyboard m and M"}, + {0x0011, "Keyboard n and N"}, + {0x0012, "Keyboard o and O"}, + {0x0013, "Keyboard p and P"}, + {0x0014, "Keyboard q and Q"}, + {0x0015, "Keyboard r and R"}, + {0x0016, "Keyboard s and S"}, + {0x0017, "Keyboard t and T"}, + {0x0018, "Keyboard u and U"}, + {0x0019, "Keyboard v and V"}, + {0x001A, "Keyboard w and W"}, + {0x001B, "Keyboard x and X"}, + {0x001C, "Keyboard y and Y"}, + {0x001D, "Keyboard z and Z"}, + {0x001E, "Keyboard 1 and !"}, + {0x001F, "Keyboard 2 and @"}, + {0x0020, "Keyboard 3 and #"}, + {0x0021, "Keyboard 4 and $"}, + {0x0022, "Keyboard 5 and %"}, + {0x0023, "Keyboard 6 and ^"}, + {0x0024, "Keyboard 7 and &"}, + {0x0025, "Keyboard 8 and *"}, + {0x0026, "Keyboard 9 and ("}, + {0x0027, "Keyboard 0 and )"}, + {0x0028, "Keyboard Return (ENTER)"}, + {0x0029, "Keyboard ESCAPE"}, + {0x002A, "Keyboard DELETE (Backspace)"}, + {0x002B, "Keyboard Tab"}, + {0x002C, "Keyboard Spacebar"}, + {0x002D, "Keyboard - and (underscore)"}, + {0x002E, "Keyboard = and +"}, + {0x002F, "Keyboard [ and {"}, + {0x0030, "Keyboard ] and }"}, + {0x0031, "Keyboard \\ and |"}, + {0x0032, "Keyboard Non-US # and ~"}, + {0x0033, "Keyboard ; and :"}, + {0x0034, "Keyboard ' and \""}, + {0x0035, "Keyboard Grave Accent and Tilde"}, + {0x0036, "Keyboard, and <"}, + {0x0037, "Keyboard . and >"}, + {0x0038, "Keyboard / and ?"}, + {0x0039, "Keyboard Caps Lock"}, + {0x003A, "Keyboard F1"}, + {0x003B, "Keyboard F2"}, + {0x003C, "Keyboard F3"}, + {0x003D, "Keyboard F4"}, + {0x003E, "Keyboard F5"}, + {0x003F, "Keyboard F6"}, + {0x0040, "Keyboard F7"}, + {0x0041, "Keyboard F8"}, + {0x0042, "Keyboard F9"}, + {0x0043, "Keyboard F10"}, + {0x0044, "Keyboard F11"}, + {0x0045, "Keyboard F12"}, + {0x0046, "Keyboard PrintScreen"}, + {0x0047, "Keyboard Scroll Lock"}, + {0x0048, "Keyboard Pause"}, + {0x0049, "Keyboard Insert"}, + {0x004A, "Keyboard Home"}, + {0x004B, "Keyboard PageUp"}, + {0x004C, "Keyboard Delete Forward"}, + {0x004D, "Keyboard End"}, + {0x004E, "Keyboard PageDown"}, + {0x004F, "Keyboard RightArrow"}, + {0x0050, "Keyboard LeftArrow"}, + {0x0051, "Keyboard DownArrow"}, + {0x0052, "Keyboard UpArrow"}, + {0x0053, "Keypad Num Lock and Clear"}, + {0x0054, "Keypad /"}, + {0x0055, "Keypad *"}, + {0x0056, "Keypad -"}, + {0x0057, "Keypad +"}, + {0x0058, "Keypad ENTER"}, + {0x0059, "Keypad 1 and End"}, + {0x005A, "Keypad 2 and Down Arrow"}, + {0x005B, "Keypad 3 and PageDn"}, + {0x005C, "Keypad 4 and Left Arrow"}, + {0x005D, "Keypad 5"}, + {0x005E, "Keypad 6 and Right Arrow"}, + {0x005F, "Keypad 7 and Home"}, + {0x0060, "Keypad 8 and Up Arrow"}, + {0x0061, "Keypad 9 and PageUp"}, + {0x0062, "Keypad 0 and Insert"}, + {0x0063, "Keypad . and Delete"}, + {0x0064, "Keyboard Non-US \\ and |"}, + {0x0065, "Keyboard Application"}, + {0x0066, "Keyboard Power"}, + {0x0067, "Keypad ="}, + {0x0068, "Keyboard F13"}, + {0x0069, "Keyboard F14"}, + {0x006A, "Keyboard F15"}, + {0x006B, "Keyboard F16"}, + {0x006C, "Keyboard F17"}, + {0x006D, "Keyboard F18"}, + {0x006E, "Keyboard F19"}, + {0x006F, "Keyboard F20"}, + {0x0070, "Keyboard F21"}, + {0x0071, "Keyboard F22"}, + {0x0072, "Keyboard F23"}, + {0x0073, "Keyboard F24"}, + {0x0074, "Keyboard Execute"}, + {0x0075, "Keyboard Help"}, + {0x0076, "Keyboard Menu"}, + {0x0077, "Keyboard Select"}, + {0x0078, "Keyboard Stop"}, + {0x0079, "Keyboard Again"}, + {0x007A, "Keyboard Undo"}, + {0x007B, "Keyboard Cut"}, + {0x007C, "Keyboard Copy"}, + {0x007D, "Keyboard Paste"}, + {0x007E, "Keyboard Find"}, + {0x007F, "Keyboard Mute"}, + {0x0080, "Keyboard Volume Up"}, + {0x0081, "Keyboard Volume Down"}, + {0x0082, "Keyboard Locking Caps Lock"}, + {0x0083, "Keyboard Locking Num Lock"}, + {0x0084, "Keyboard Locking Scroll Lock"}, + {0x0085, "Keypad Comma"}, + {0x0086, "Keypad Equal Sign"}, + {0x0087, "Keyboard International1"}, + {0x0088, "Keyboard International2"}, + {0x0089, "Keyboard International3"}, + {0x008A, "Keyboard International4"}, + {0x008B, "Keyboard International5"}, + {0x008C, "Keyboard International6"}, + {0x008D, "Keyboard International7"}, + {0x008E, "Keyboard International8"}, + {0x008F, "Keyboard International9"}, + {0x0090, "Keyboard LANG1"}, + {0x0091, "Keyboard LANG2"}, + {0x0092, "Keyboard LANG3"}, + {0x0093, "Keyboard LANG4"}, + {0x0094, "Keyboard LANG5"}, + {0x0095, "Keyboard LANG6"}, + {0x0096, "Keyboard LANG7"}, + {0x0097, "Keyboard LANG8"}, + {0x0098, "Keyboard LANG9"}, + {0x0099, "Keyboard Alternate Erase"}, + {0x009A, "Keyboard SysReq/Attention"}, + {0x009B, "Keyboard Cancel"}, + {0x009C, "Keyboard Clear"}, + {0x009D, "Keyboard Prior"}, + {0x009E, "Keyboard Return"}, + {0x009F, "Keyboard Separator"}, + {0x00A0, "Keyboard Out"}, + {0x00A1, "Keyboard Oper"}, + {0x00A2, "Keyboard Clear/Again"}, + {0x00A3, "Keyboard CrSel/Props"}, + {0x00A4, "Keyboard ExSel"}, + {0x00E0, "Keyboard LeftControl"}, + {0x00E1, "Keyboard LeftShift"}, + {0x00E2, "Keyboard LeftAlt"}, + {0x00E3, "Keyboard Left GUI"}, + {0x00E4, "Keyboard RightControl"}, + {0x00E5, "Keyboard RightShift"}, + {0x00E6, "Keyboard RightAlt"}, + {0x00E7, "Keyboard Right GUI"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type008[] = { + {0x0000, "Undefined"}, + {0x0001, "Num Lock"}, + {0x0002, "Caps Lock"}, + {0x0003, "Scroll Lock"}, + {0x0004, "Compose"}, + {0x0005, "Kana"}, + {0x0006, "Power"}, + {0x0007, "Shift"}, + {0x0008, "Do Not Disturb"}, + {0x0009, "Mute"}, + {0x000A, "Tone Enable"}, + {0x000B, "High Cut Filter"}, + {0x000C, "Low Cut Filter"}, + {0x000D, "Equalizer Enable"}, + {0x000E, "Sound Field On"}, + {0x000F, "Surround Field On"}, + {0x0010, "Repeat"}, + {0x0011, "Stereo"}, + {0x0012, "Sampling Rate Detect"}, + {0x0013, "Spinning"}, + {0x0014, "CAV"}, + {0x0015, "CLV"}, + {0x0016, "Recording Format Detect"}, + {0x0017, "Off-Hook"}, + {0x0018, "Ring"}, + {0x0019, "Message Waiting"}, + {0x001A, "Data Mode"}, + {0x001B, "Battery Operation"}, + {0x001C, "Battery OK"}, + {0x001D, "Battery Low"}, + {0x001E, "Speaker"}, + {0x001F, "Head Set"}, + {0x0020, "Hold"}, + {0x0021, "Microphone"}, + {0x0022, "Coverage"}, + {0x0023, "Night Mode"}, + {0x0024, "Send Calls"}, + {0x0025, "Call Pickup"}, + {0x0026, "Conference"}, + {0x0027, "Stand-by"}, + {0x0028, "Camera On"}, + {0x0029, "Camera Off"}, + {0x002A, "On-Line"}, + {0x002B, "Off-Line"}, + {0x002C, "Busy"}, + {0x002D, "Ready"}, + {0x002E, "Paper-Out"}, + {0x002F, "Paper-Jam"}, + {0x0030, "Remote"}, + {0x0031, "Forward"}, + {0x0032, "Reverse"}, + {0x0033, "Stop"}, + {0x0034, "Rewind"}, + {0x0035, "Fast Forward"}, + {0x0036, "Play"}, + {0x0037, "Pause"}, + {0x0038, "Record"}, + {0x0039, "Error"}, + {0x003A, "Usage Selected Indicator"}, + {0x003B, "Usage In Use Indicator"}, + {0x003C, "Usage Multi Mode Indicator"}, + {0x003D, "Indicator On"}, + {0x003E, "Indicator Flash"}, + {0x003F, "Indicator Slow Blink"}, + {0x0040, "Indicator Fast Blink"}, + {0x0041, "Indicator Off"}, + {0x0042, "Flash On Time"}, + {0x0043, "Slow Blink On Time"}, + {0x0044, "Slow Blink Off Time"}, + {0x0045, "Fast Blink On Time"}, + {0x0046, "Fast Blink Off Time"}, + {0x0047, "Usage Indicator Color"}, + {0x0048, "Red"}, + {0x0049, "Green"}, + {0x004A, "Amber"}, + {0x004B, "Generic Indicator"}, + {0x004C, "System Suspend"}, + {0x004D, "External Power Connected"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type00B[] = { + {0x0000, "Unassigned"}, + {0x0001, "Phone"}, + {0x0002, "Answering Machine"}, + {0x0003, "Message Controls"}, + {0x0004, "Handset"}, + {0x0005, "Headset"}, + {0x0006, "Telephony Key Pad"}, + {0x0007, "Programmable Button"}, + {0x0020, "Hook Switch"}, + {0x0021, "Flash"}, + {0x0022, "Feature"}, + {0x0023, "Hold"}, + {0x0024, "Redial"}, + {0x0025, "Transfer"}, + {0x0026, "Drop"}, + {0x0027, "Park"}, + {0x0028, "Forward Calls"}, + {0x0029, "Alternate Function"}, + {0x002A, "Line"}, + {0x002B, "Speaker Phone"}, + {0x002C, "Conference"}, + {0x002D, "Ring Enable"}, + {0x002E, "Ring Select"}, + {0x002F, "Phone Mute"}, + {0x0030, "Caller ID"}, + {0x0050, "Speed Dial"}, + {0x0051, "Store Number"}, + {0x0052, "Recall Number"}, + {0x0053, "Phone Directory"}, + {0x0070, "Voice Mail"}, + {0x0071, "Screen Calls"}, + {0x0072, "Do Not Disturb"}, + {0x0073, "Message"}, + {0x0074, "Answer On/Off"}, + {0x0090, "Inside Dial Tone"}, + {0x0091, "Outside Dial Tone"}, + {0x0092, "Inside Ring Tone"}, + {0x0093, "Outside Ring Tone"}, + {0x0094, "Priority Ring Tone"}, + {0x0095, "Inside Ringback"}, + {0x0096, "Priority Ringback"}, + {0x0097, "Line Busy Tone"}, + {0x0098, "Reorder Tone"}, + {0x0099, "Call Waiting Tone"}, + {0x009A, "Confirmation Tone 1"}, + {0x009B, "Confirmation Tone 2"}, + {0x009C, "Tones Off"}, + {0x00B0, "Phone Key 0"}, + {0x00B1, "Phone Key 1"}, + {0x00B2, "Phone Key 2"}, + {0x00B3, "Phone Key 3"}, + {0x00B4, "Phone Key 4"}, + {0x00B5, "Phone Key 5"}, + {0x00B6, "Phone Key 6"}, + {0x00B7, "Phone Key 7"}, + {0x00B8, "Phone Key 8"}, + {0x00B9, "Phone Key 9"}, + {0x00BA, "Phone Key Star"}, + {0x00BB, "Phone Key Pound"}, + {0x00BC, "Phone Key A"}, + {0x00BD, "Phone Key B"}, + {0x00BE, "Phone Key C"}, + {0x00BF, "Phone Key D"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type00C[] = { + {0x0000, "Undefined"}, + {0x0001, "Consumer Control"}, + {0x0002, "Numeric Key Pad"}, + {0x0003, "Programmable Buttons"}, + {0x0004, "Microphone"}, + {0x0005, "Headphone"}, + {0x0006, "Graphic Equalizer"}, + {0x0020, "+10"}, + {0x0021, "+100"}, + {0x0022, "AM/PM"}, + {0x0030, "Power"}, + {0x0031, "Reset"}, + {0x0032, "Sleep"}, + {0x0033, "Sleep After"}, + {0x0034, "Sleep Mode"}, + {0x0035, "Illumination"}, + {0x0036, "Function Buttons"}, + {0x0040, "Menu"}, + {0x0041, "Menu Pick"}, + {0x0042, "Menu Up"}, + {0x0043, "Menu Down"}, + {0x0044, "Menu Left"}, + {0x0045, "Menu Right"}, + {0x0046, "Menu Esc"}, + {0x0047, "Menu Value Increase"}, + {0x0048, "Menu Value Decrease"}, + {0x0060, "Data On Screen"}, + {0x0061, "Closed Caption"}, + {0x0062, "Closed Caption Select"}, + {0x0063, "VCR/TV"}, + {0x0064, "Broadcast Mode"}, + {0x0065, "Snap shot"}, + {0x0066, "Still"}, + {0x0080, "Selection"}, + {0x0081, "Assign Selection"}, + {0x0082, "Mode Setup"}, + {0x0083, "Recal Last"}, + {0x0084, "Enter Channel"}, + {0x0085, "Order Movie"}, + {0x0086, "Channel"}, + {0x0087, "Media Selection"}, + {0x0088, "Media Select Computer"}, + {0x0089, "Media Select TV"}, + {0x008A, "Media Select WWW"}, + {0x008B, "Media Select DVD"}, + {0x008C, "Media Select Telephone"}, + {0x008D, "Media Select Program Guide"}, + {0x008E, "Media Select Video Phone"}, + {0x008F, "Media Select Games"}, + {0x0090, "Media Select Messages"}, + {0x0091, "Media Select CD"}, + {0x0092, "Media Select VCR"}, + {0x0093, "Media Select Tuner"}, + {0x0094, "Quit"}, + {0x0095, "Help"}, + {0x0096, "Media Select Tape"}, + {0x0097, "Media Select Cable"}, + {0x0098, "Media Select Satelite"}, + {0x0099, "Media Select Security"}, + {0x009A, "Media Select Home"}, + {0x009B, "Media Select Call"}, + {0x009C, "Channel Increment"}, + {0x009E, "Channel Decrement"}, + {0x009D, "Media Select SAP"}, + {0x009F, "Reserved"}, + {0x00A0, "VCR Plus"}, + {0x00A1, "Once"}, + {0x00A2, "Daily"}, + {0x00A3, "Weekly"}, + {0x00A4, "Monthly"}, + {0x00B0, "Play"}, + {0x00B1, "Pause"}, + {0x00B2, "Record"}, + {0x00B3, "Fast Foward"}, + {0x00B4, "Rewind"}, + {0x00B5, "Scan Next Track"}, + {0x00B6, "Scan Previous Track"}, + {0x00B7, "Stop"}, + {0x00B8, "Eject"}, + {0x00B9, "Random Play"}, + {0x00BA, "Select Disc"}, + {0x00BB, "Enter Disk"}, + {0x00BC, "Repeat"}, + {0x00BD, "Tracking"}, + {0x00BE, "Track Normal"}, + {0x00BF, "Slow Tracking"}, + {0x00C0, "Frame Forward"}, + {0x00C1, "Frame Back"}, + {0x00C2, "Mark"}, + {0x00C3, "Clear Mark"}, + {0x00C4, "Repeat from Mark"}, + {0x00C5, "Return to Mark"}, + {0x00C6, "Search Mark Forward"}, + {0x00C7, "Search Mark Backwards"}, + {0x00C8, "Counter Reset"}, + {0x00C9, "Show Counter"}, + {0x00CA, "Tracking Increment"}, + {0x00CB, "Tracking Decrement"}, + {0x00CC, "Stop/Eject"}, + {0x00CD, "Play/Pause"}, + {0x00CE, "Play/Skip"}, + {0x00E0, "Volume"}, + {0x00E1, "Balance"}, + {0x00E2, "Mute"}, + {0x00E3, "Bass"}, + {0x00E4, "Treble"}, + {0x00E5, "Bass Boost"}, + {0x00E6, "Surround Mode"}, + {0x00E7, "Loudness"}, + {0x00E8, "MPX"}, + {0x00E9, "Volume Increment"}, + {0x00EA, "Volume Decrement"}, + {0x00F0, "Speed Select"}, + {0x00F1, "Playback Speed"}, + {0x00F2, "Standard Play"}, + {0x00F3, "Long Play"}, + {0x00F4, "Extended Play"}, + {0x00F5, "Slow"}, + {0x0100, "Fan Enable"}, + {0x0101, "Fan Speed"}, + {0x0102, "Light Enable"}, + {0x0103, "Light Illumination Level"}, + {0x0104, "Climate Control Enable"}, + {0x0105, "Room Temperature"}, + {0x0106, "Security Enable"}, + {0x0107, "Fire Alarm"}, + {0x0108, "Police Alarm"}, + {0x0109, "Proximity"}, + {0x010A, "Motion"}, + {0x010B, "Duress Alarm"}, + {0x010C, "Holdup Alarm"}, + {0x010D, "Medical Alarm"}, + {0x0150, "Balance Right"}, + {0x0151, "Balance Left"}, + {0x0152, "Bass Increment"}, + {0x0153, "Bass Decrement"}, + {0x0154, "Treble Increment"}, + {0x0155, "Trebel Decrement"}, + {0x0160, "Speaker System"}, + {0x0161, "Channel Left"}, + {0x0162, "Channel Right"}, + {0x0163, "Channel Center"}, + {0x0164, "Channel Front"}, + {0x0165, "Channel Center Front"}, + {0x0166, "Channel Side"}, + {0x0167, "Channel Surround"}, + {0x0168, "Channel Low Freq Enhancement"}, + {0x0169, "Channel Top"}, + {0x016A, "Channel Unknown"}, + {0x0170, "Sub-channel"}, + {0x0171, "Sub-channel Increment"}, + {0x0172, "Sub-channel Decrement"}, + {0x0173, "Alternate Audio Increment"}, + {0x0174, "Alternate Audio Decrement"}, + {0x0180, "Application Launch"}, + {0x0180, "App Launch: Config Tool"}, + {0x0181, "App Launch: Launch Button Config"}, + {0x0182, "App Launch: Programmable Button"}, + {0x0183, "App Launch: Consumer Control"}, + {0x0184, "App Launch: Word Processor"}, + {0x0185, "App Launch: Text Editor"}, + {0x0186, "App Launch: Spread Sheet"}, + {0x0187, "App Launch: Graphics Editor"}, + {0x0188, "App Launch: Presentation App"}, + {0x0189, "App Launch: Database App"}, + {0x018A, "App Launch: Email Reader"}, + {0x018B, "App Launch: News Reader"}, + {0x018C, "App Launch: Voice Mail"}, + {0x018D, "App Launch: Contacts/Address Book"}, + {0x018E, "App Launch: Calendar/Schedule Book"}, + {0x018F, "App Launch: Task/Project Manager"}, + {0x0190, "App Launch: Log/Journal/Time card"}, + {0x0191, "App Launch: Checkbook/Finance"}, + {0x0192, "App Launch: Calculator"}, + {0x0193, "App Launch: A/V Capture/Playback"}, + {0x0194, "App Launch: Local Machine Browser"}, + {0x0195, "App Launch: LAN/WAN Browser"}, + {0x0196, "App Launch: Internet Browser"}, + {0x0197, "App Launch: Remote Networking"}, + {0x0198, "App Launch: Network Conference"}, + {0x0199, "App Launch: Network Chat"}, + {0x019A, "App Launch: Telephone Dialer"}, + {0x019B, "App Launch: Logon"}, + {0x019C, "App Launch: Logoff"}, + {0x019D, "App Launch: Logon/Logoff"}, + {0x019E, "App Launch: Term Lock/Screensaver"}, + {0x019F, "App Launch: Control Panel"}, + {0x01A0, "App Launch: Command Line"}, + {0x01A1, "App Launch: Process Task Manager"}, + {0x01A2, "App Launch: Select Task/App"}, + {0x01A3, "App Launch: Next Task/App"}, + {0x01A4, "App Launch: Prev Task/App"}, + {0x01A5, "App Launch: Premptive Halt"}, + {0x01A6, "App Launch: Integrated Help Center"}, + {0x01A7, "App Launch: Documents"}, + {0x01A8, "App Launch: Thesarus"}, + {0x01A9, "App Launch: Dictionary"}, + {0x01AA, "App Launch: Desktop"}, + {0x01AB, "App Launch: Spell Check"}, + {0x01AC, "App Launch: Grammer Check"}, + {0x01AD, "App Launch: Wireless Status"}, + {0x01AE, "App Launch: Keyboard Layout"}, + {0x01AF, "App Launch: Virus Protect"}, + {0x01B0, "App Launch: Encryption"}, + {0x01B1, "App Launch: Screen Saver"}, + {0x01B2, "App Launch: Alarms"}, + {0x01B3, "App Launch: Clock"}, + {0x01B4, "App Launch: File Browser"}, + {0x01B5, "App Launch: Power Status"}, + {0x01B6, "App Launch: Image Browser"}, + {0x01B7, "App Launch: Audio Browser"}, + {0x01B8, "App Launch: Movie Browser"}, + {0x01B9, "App Launch: Digital Rights Manager"}, + {0x01BA, "App Launch: Digital Wallet"}, + {0x01BB, "App Launch: Reserved"}, + {0x01BC, "App Launch: Instant Messaging"}, + {0x01BD, "App Launch: OEM Tools"}, + {0x01BE, "App Launch: OEM Help"}, + {0x01BF, "App Launch: Online Community"}, + {0x01C0, "App Launch: Entertainment Content Browser"}, + {0x01C1, "App Launch: Online Shopping Browser"}, + {0x01C2, "App Launch: SmartCard Info"}, + {0x01C3, "App Launch: Market Monitor"}, + {0x01C4, "App Launch: Customized News"}, + {0x01C5, "App Launch: Online Activity Browser"}, + {0x01C6, "App Launch: Research/Search Browser"}, + {0x01C7, "App Launch: Audio Player"}, + {0x0200, "GUI Controls"}, + {0x0201, "GUI: New"}, + {0x0202, "GUI: Open"}, + {0x0203, "GUI: Close"}, + {0x0204, "GUI: Exit"}, + {0x0205, "GUI: Maximize"}, + {0x0206, "GUI: Minimize"}, + {0x0207, "GUI: Save"}, + {0x0208, "GUI: Print"}, + {0x0209, "GUI: Properties"}, + {0x021A, "GUI: Undo"}, + {0x021B, "GUI: Copy"}, + {0x021C, "GUI: Cut"}, + {0x021D, "GUI: Paste"}, + {0x021E, "GUI: Select All"}, + {0x021F, "GUI: Find"}, + {0x0220, "GUI: Find/Replace"}, + {0x0221, "GUI: Search"}, + {0x0222, "GUI: Goto"}, + {0x0223, "GUI: Home"}, + {0x0224, "GUI: Back"}, + {0x0225, "GUI: Foward"}, + {0x0226, "GUI: Stop"}, + {0x0227, "GUI: Refresh"}, + {0x0228, "GUI: Prev Link"}, + {0x0229, "GUI: Next Link"}, + {0x022A, "GUI: Bookmarks"}, + {0x022B, "GUI: History"}, + {0x022C, "GUI: Subscriptions"}, + {0x022D, "GUI: Zoom In"}, + {0x022E, "GUI: Zoom Out"}, + {0x022F, "GUI: Zoom"}, + {0x0230, "GUI: Full Screen"}, + {0x0231, "GUI: Normal View"}, + {0x0232, "GUI: View Toggle"}, + {0x0233, "GUI: Scroll Up"}, + {0x0234, "GUI: Scroll Down"}, + {0x0235, "GUI: Scroll"}, + {0x0236, "GUI: Pan Left"}, + {0x0237, "GUI: Pan Right"}, + {0x0238, "GUI: Pan"}, + {0x0239, "GUI: New Window"}, + {0x023A, "GUI: Tile Horz"}, + {0x023B, "GUI: Tile Vert"}, + {0x023C, "GUI: Format"}, + {0x023D, "GUI: Edit"}, + {0x023E, "GUI: Bold"}, + {0x023F, "GUI: Italics"}, + {0x0240, "GUI: Underline"}, + {0x0241, "GUI: StrikeThrough"}, + {0x0242, "GUI: SubScript"}, + {0x0243, "GUI: SuperScript"}, + {0x0244, "GUI: All Caps"}, + {0x0245, "GUI: Rotate"}, + {0x0246, "GUI: Resize"}, + {0x0247, "GUI: Flip Horz"}, + {0x0248, "GUI: Flip Vert"}, + {0x0249, "GUI: Mirror Horz"}, + {0x024A, "GUI: Mirror Vert"}, + {0x024B, "GUI: Font Select"}, + {0x024C, "GUI: Font Color"}, + {0x024D, "GUI: Font Size"}, + {0x024E, "GUI: Justify Left"}, + {0x024F, "GUI: Justify Center H"}, + {0x0250, "GUI: Justify Right"}, + {0x0251, "GUI: Justify Block H"}, + {0x0252, "GUI: Justify Top"}, + {0x0253, "GUI: Justify Center V"}, + {0x0254, "GUI: Justify Bottom"}, + {0x0255, "GUI: Justify Block V"}, + {0x0256, "GUI: Indent Decrease"}, + {0x0257, "GUI: Indent Increase"}, + {0x0258, "GUI: Numbered List"}, + {0x0259, "GUI: Restart Numbering"}, + {0x025A, "GUI: Bulleted List"}, + {0x025B, "GUI: Promote"}, + {0x025C, "GUI: Demote"}, + {0x025D, "GUI: Yes"}, + {0x025E, "GUI: No"}, + {0x025F, "GUI: Cancel"}, + {0x0260, "GUI: Catalog"}, + {0x0261, "GUI: Buy/Checkout"}, + {0x0262, "GUI: Add to Cart"}, + {0x0263, "GUI: Expand"}, + {0x0264, "GUI: Expand All"}, + {0x0265, "GUI: Collapse"}, + {0x0266, "GUI: Collapse All"}, + {0x0267, "GUI: Print Preview"}, + {0x0268, "GUI: Paste Special"}, + {0x0269, "GUI: Insert Mode"}, + {0x026A, "GUI: Delete"}, + {0x026B, "GUI: Lock"}, + {0x026C, "GUI: Unlock"}, + {0x026D, "GUI: Protect"}, + {0x026E, "GUI: Unprotect"}, + {0x026F, "GUI: Attache Comment"}, + {0x0270, "GUI: Delete Comment"}, + {0x0271, "GUI: View Comment"}, + {0x0272, "GUI: Select Word"}, + {0x0273, "GUI: Select Sentence"}, + {0x0274, "GUI: Select Paragraph"}, + {0x0275, "GUI: Select Column"}, + {0x0276, "GUI: Select Row"}, + {0x0277, "GUI: Select Table"}, + {0x0278, "GUI: Select Object"}, + {0x0279, "GUI: Redo/Repeat"}, + {0x027A, "GUI: Sort"}, + {0x027B, "GUI: Sort Ascending"}, + {0x027C, "GUI: Sort Descending"}, + {0x027D, "GUI: Filter"}, + {0x027E, "GUI: Set Clock"}, + {0x027F, "GUI: View Clock"}, + {0x0280, "GUI: Select Time Zone"}, + {0x0281, "GUI: Edit Time Zone"}, + {0x0282, "GUI: Set Alarm"}, + {0x0283, "GUI: Clear Alarm"}, + {0x0284, "GUI: Snooze Alarm"}, + {0x0285, "GUI: Reset Alarm"}, + {0x0286, "GUI: Synchronize"}, + {0x0287, "GUI: Send/Receive"}, + {0x0288, "GUI: Send To"}, + {0x0289, "GUI: Reply"}, + {0x028A, "GUI: Reply All"}, + {0x028B, "GUI: Forward Message"}, + {0x028C, "GUI: Send"}, + {0x028D, "GUI: Attach File"}, + {0x028E, "GUI: Upload"}, + {0x028F, "GUI: Download"}, + {0x0290, "GUI: Set Boards"}, + {0x0291, "GUI: Insert Row"}, + {0x0292, "GUI: Insert Column"}, + {0x0293, "GUI: insert File"}, + {0x0294, "GUI: Insert Picture"}, + {0x0295, "GUI: Insert Object"}, + {0x0296, "GUI: Insert Symbol"}, + {0x0297, "GUI: Save and Close"}, + {0x0298, "GUI: Rename"}, + {0x0299, "GUI: Merge"}, + {0x029A, "GUI: Split"}, + {0x029B, "GUI: Distribute Horz"}, + {0x029C, "GUI: Distribute Vert"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type00D[] = { + {0x0000, "Undefined"}, + {0x0001, "Digitizer"}, + {0x0002, "Pen"}, + {0x0003, "Light Pen"}, + {0x0004, "Touch Screen"}, + {0x0005, "Touch Pad"}, + {0x0006, "White Board"}, + {0x0007, "Coordinate Measuring Machine"}, + {0x0008, "3-D Digitizer"}, + {0x0009, "Stereo Plotter"}, + {0x000A, "Articulated Arm"}, + {0x000B, "Armature"}, + {0x000C, "Multiple Point Digitizer"}, + {0x000D, "Free Space Wand"}, + {0x0020, "Stylus"}, + {0x0021, "Puck"}, + {0x0022, "Finger"}, + {0x0030, "Tip Pressure"}, + {0x0031, "Barrel Pressure"}, + {0x0032, "In Range"}, + {0x0033, "Touch"}, + {0x0034, "Untouch"}, + {0x0035, "Tap"}, + {0x0036, "Quality"}, + {0x0037, "Data Valid"}, + {0x0038, "Transducer Index"}, + {0x0039, "Tablet Function Keys"}, + {0x003A, "Program Change Keys"}, + {0x003B, "Battery Strength"}, + {0x003C, "Invert"}, + {0x003D, "X Tilt"}, + {0x003E, "Y Tilt"}, + {0x003F, "Azimuth"}, + {0x0040, "Altitude"}, + {0x0041, "Twist"}, + {0x0042, "Tip Switch"}, + {0x0043, "Secondary Tip Switch"}, + {0x0044, "Barrel Switch"}, + {0x0045, "Eraser"}, + {0x0046, "Tablet Pick"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type00F[] = { + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type014[] = { + {0x0000, "Undefined"}, + {0x0001, "Alphanumeric Display"}, + {0x0020, "Display Attributes Report"}, + {0x0021, "ASCII Character Set"}, + {0x0022, "Data Read Back"}, + {0x0023, "Font Read Back"}, + {0x0024, "Display Control Report"}, + {0x0025, "Clear Display"}, + {0x0026, "Display Enable"}, + {0x0027, "Screen Saver Delay"}, + {0x0028, "Screen Saver Enable"}, + {0x0029, "Vertical Scroll"}, + {0x002A, "Horizontal Scroll"}, + {0x002B, "Character Report"}, + {0x002C, "Display Data"}, + {0x002D, "Display Status"}, + {0x002E, "Stat Not Ready"}, + {0x002F, "Stat Ready"}, + {0x0030, "Err Not a loadable character"}, + {0x0031, "Err Font data cannot be read"}, + {0x0032, "Cursor Position Report"}, + {0x0033, "Row"}, + {0x0034, "Column"}, + {0x0035, "Rows"}, + {0x0036, "Columns"}, + {0x0037, "Cursor Pixel Positioning"}, + {0x0038, "Cursor Mode"}, + {0x0039, "Cursor Enable"}, + {0x003A, "Cursor Blink"}, + {0x003B, "Font Report"}, + {0x003C, "Font Data"}, + {0x003D, "Character Width"}, + {0x003E, "Character Height"}, + {0x003F, "Character Spacing Horizontal"}, + {0x0040, "Character Spacing Vertical"}, + {0x0041, "Unicode Character Set"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type040[] = { + {0x0000, "Undefined"}, + {0x0001, "Medical Ultrasound"}, + {0x0020, "VCR/Acquisition"}, + {0x0021, "Freeze/Thaw"}, + {0x0022, "Clip Store"}, + {0x0023, "Update"}, + {0x0024, "Next"}, + {0x0025, "Save"}, + {0x0026, "Print"}, + {0x0027, "Microphone Enable"}, + {0x0040, "Cine"}, + {0x0041, "Transmit Power"}, + {0x0042, "Volume"}, + {0x0043, "Focus"}, + {0x0044, "Depth"}, + {0x0060, "Soft Step - Primary"}, + {0x0061, "Soft Step - Secondary"}, + {0x0070, "Depth Gain Compensation"}, + {0x0080, "Zoom Select"}, + {0x0081, "Zoom Adjust"}, + {0x0082, "Spectral Doppler Mode Select"}, + {0x0083, "Spectral Doppler Adjust"}, + {0x0084, "Color Doppler Mode Select"}, + {0x0085, "Color Doppler Adjust"}, + {0x0086, "Motion Mode Select"}, + {0x0087, "Motion Mode Adjust"}, + {0x0088, "2-D Mode Select"}, + {0x0089, "2-D Mode Adjust"}, + {0x00A0, "Soft Control Select"}, + {0x00A1, "Soft Control Adjust"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type080[] = { + {0x0000, "Undefined"}, + {0x0001, "Monitor Control"}, + {0x0002, "EDID Information"}, + {0x0003, "VDIF Information"}, + {0x0004, "VESA Version"}, + {0x0005, "On Screen Display"}, + {0x0006, "Auto Size Center"}, + {0x0007, "Polarity Horz Synch"}, + {0x0008, "Polarity Vert Synch"}, + {0x0009, "Sync Type"}, + {0x000A, "Screen Position"}, + {0x000B, "Horizontal Frequency"}, + {0x000C, "Vertical Frequency"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type082[] = { + {0x0010, "Brightness"}, + {0x0012, "Contrast"}, + {0x0016, "Video Gain Red"}, + {0x0018, "Video Gain Green"}, + {0x001A, "Video Gain Blue"}, + {0x001C, "Focus"}, + {0x0020, "Horizontal Position"}, + {0x0022, "Horizontal Size"}, + {0x0024, "Horizontal Pincushion"}, + {0x0026, "Horizontal Pincushion Balance"}, + {0x0028, "Horizontal Misconvergence"}, + {0x002A, "Horizontal Linearity"}, + {0x002C, "Horizontal Linearity Balance"}, + {0x0030, "Vertical Position"}, + {0x0032, "Vertical Size"}, + {0x0034, "Vertical Pincushion"}, + {0x0036, "Vertical Pincushion Balance"}, + {0x0038, "Vertical Misconvergence"}, + {0x003A, "Vertical Linearity"}, + {0x003C, "Vertical Linearity Balance"}, + {0x0040, "Parallelogram Distortion"}, + {0x0042, "Trapezoidal Distortion"}, + {0x0044, "Tilt"}, + {0x0046, "Top Corner Distortion Control"}, + {0x0048, "Top Corner Distortion Balance"}, + {0x004A, "Bottom Corner Distortion Control"}, + {0x004C, "Bottom Corner Distortion Balance"}, + {0x0056, "Moir Horizontal"}, + {0x0058, "Moir Vertical"}, + {0x005E, "Input Level Select"}, + {0x0060, "Input Source Select"}, + {0x0062, "Stereo Mode"}, + {0x006C, "Video Black Level Red"}, + {0x006E, "Video Black Level Green"}, + {0x0070, "Video Black Level Blue"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type083[] = { + {0x0000, "Undefined"}, + {0x0001, "Settings"}, + {0x0002, "Degauss"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type084[] = { + {0x0000, "Undefined"}, + {0x0001, "iName"}, + {0x0002, "PresentStatus"}, + {0x0003, "ChangedStatus"}, + {0x0004, "UPS"}, + {0x0005, "PowerSupply"}, + {0x0010, "BatterySystem"}, + {0x0011, "BatterySystemID"}, + {0x0012, "Battery"}, + {0x0013, "BatteryID"}, + {0x0014, "Charger"}, + {0x0015, "ChargerID"}, + {0x0016, "PowerConverter"}, + {0x0017, "PowerConverterID"}, + {0x0018, "OutletSystem"}, + {0x0019, "OutletSystemID"}, + {0x001A, "Input"}, + {0x001B, "InputID"}, + {0x001C, "Output"}, + {0x001D, "OutputID"}, + {0x001E, "Flow"}, + {0x001F, "FlowID"}, + {0x0020, "Outlet"}, + {0x0021, "OutletID"}, + {0x0022, "Gang"}, + {0x0023, "GangID"}, + {0x0024, "Sink"}, + {0x0025, "SinkID"}, + {0x0030, "Voltage"}, + {0x0031, "Current"}, + {0x0032, "Frequency"}, + {0x0033, "ApparentPower"}, + {0x0034, "ActivePower"}, + {0x0035, "PercentLoad"}, + {0x0036, "Temperature"}, + {0x0037, "Humidity"}, + {0x0040, "ConfigVoltage"}, + {0x0041, "ConfigCurrent"}, + {0x0042, "ConfigFrequency"}, + {0x0043, "ConfigApparentPower"}, + {0x0044, "ConfigActivePower"}, + {0x0045, "ConfigPercentLoad"}, + {0x0046, "ConfigTemperature"}, + {0x0047, "ConfigHumidity"}, + {0x0050, "SwitchOnControl"}, + {0x0051, "SwitchOffControl"}, + {0x0052, "ToggleControl"}, + {0x0053, "LowVoltageTransfer"}, + {0x0054, "HighVoltageTransfer"}, + {0x0055, "DelayBeforeReboot"}, + {0x0056, "DelayBeforeStartup"}, + {0x0057, "DelayBeforeShutdown"}, + {0x0058, "Test"}, + {0x0059, "Vendorspecificcommand"}, + {0x0060, "Present"}, + {0x0061, "Good"}, + {0x0062, "InternalFailure"}, + {0x0063, "VoltageOutOfRange"}, + {0x0064, "FrequencyOutOfRange"}, + {0x0065, "Overload"}, + {0x0066, "OverCharged"}, + {0x0067, "OverTemperature"}, + {0x0068, "ShutdownRequested"}, + {0x0069, "ShutdownImminent"}, + {0x006A, "VendorSpecificAnswerValid"}, + {0x006B, "SwitchOn/Off"}, + {0x006C, "Switcheble"}, + {0x006D, "Used"}, + {0x006E, "Boost"}, + {0x006F, "Buck"}, + {0x0070, "Initialized"}, + {0x0071, "Tested"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type085[] = { + {0x0000, "Undefined"}, + {0x0001, "SMBBatteryMode"}, + {0x0002, "SMBBatteryStatus"}, + {0x0003, "SMBAlarmWarning"}, + {0x0004, "SMBChargerMode"}, + {0x0005, "SMBChargerStatus"}, + {0x0006, "SMBChargerSpecInfo"}, + {0x0007, "SMBSelectorState"}, + {0x0008, "SMBSelectorPreset"}, + {0x0009, "SMBSelectorInfo"}, + {0x0010, "OptionalMfgFunction1"}, + {0x0011, "OptionalMfgFunction2"}, + {0x0012, "OptionalMfgFunction3"}, + {0x0013, "OptionalMfgFunction4"}, + {0x0014, "OptionalMfgFunction5"}, + {0x0015, "ConnectionToSMBus"}, + {0x0016, "OutputConnection"}, + {0x0017, "ChargerConnection"}, + {0x0018, "BatteryInsertion"}, + {0x0019, "Usenext"}, + {0x001A, "OKToUse"}, + {0x0028, "ManufacturerAccess"}, + {0x0029, "RemainingCapacityLimit"}, + {0x002A, "RemainingTimeLimit"}, + {0x002B, "AtRate"}, + {0x002C, "CapacityMode"}, + {0x002D, "BroadcastToCharger"}, + {0x002E, "PrimaryBattery"}, + {0x002F, "ChargeController"}, + {0x0040, "TerminateCharge"}, + {0x0041, "TermminateDischarge"}, + {0x0042, "BelowRemainingCapacityLimit"}, + {0x0043, "RemainingTimeLimitExpired"}, + {0x0044, "Charging"}, + {0x0045, "Discharging"}, + {0x0046, "FullyCharged"}, + {0x0047, "FullyDischarged"}, + {0x0048, "ConditionningFlag"}, + {0x0049, "AtRateOK"}, + {0x004A, "SMBErrorCode"}, + {0x004B, "NeedReplacement"}, + {0x0060, "AtRateTimeToFull"}, + {0x0061, "AtRateTimeToEmpty"}, + {0x0062, "AverageCurrent"}, + {0x0063, "Maxerror"}, + {0x0064, "RelativeStateOfCharge"}, + {0x0065, "AbsoluteStateOfCharge"}, + {0x0066, "RemainingCapacity"}, + {0x0067, "FullChargeCapacity"}, + {0x0068, "RunTimeToEmpty"}, + {0x0069, "AverageTimeToEmpty"}, + {0x006A, "AverageTimeToFull"}, + {0x006B, "CycleCount"}, + {0x0080, "BattPackModelLevel"}, + {0x0081, "InternalChargeController"}, + {0x0082, "PrimaryBatterySupport"}, + {0x0083, "DesignCapacity"}, + {0x0084, "SpecificationInfo"}, + {0x0085, "ManufacturerDate"}, + {0x0086, "SerialNumber"}, + {0x0087, "iManufacturerName"}, + {0x0088, "iDevicename"}, + {0x0089, "iDeviceChemistery"}, + {0x008A, "iManufacturerData"}, + {0x008B, "Rechargeable"}, + {0x008C, "WarningCapacityLimit"}, + {0x008D, "CapacityGranularity1"}, + {0x008E, "CapacityGranularity2"}, + {0x00C0, "InhibitCharge"}, + {0x00C1, "EnablePolling"}, + {0x00C2, "ResetToZero"}, + {0x00D0, "ACPresent"}, + {0x00D1, "BatteryPresent"}, + {0x00D2, "PowerFail"}, + {0x00D3, "AlarmInhibited"}, + {0x00D4, "ThermistorUnderRange"}, + {0x00D5, "ThermistorHot"}, + {0x00D6, "ThermistorCold"}, + {0x00D7, "ThermistorOverRange"}, + {0x00D8, "VoltageOutOfRange"}, + {0x00D9, "CurrentOutOfRange"}, + {0x00DA, "CurrentNotRegulated"}, + {0x00DB, "VoltageNotRegulated"}, + {0x00DC, "MasterMode"}, + {0x00DD, "ChargerBattery/HostControlled"}, + {0x00F0, "ChargerSpecInfo"}, + {0x00F1, "ChargerSpecRef"}, + {0x00F2, "Level2"}, + {0x00F3, "Level3"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type086[] = { + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type087[] = { + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type08C[] = { + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type08D[] = { + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type08E[] = { + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type08F[] = { + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type090[] = { + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_type091[] = { + + {0xFFFF, ""}, +}; + +/* +struct S_USAGE_TYPES_STR usage_typeF1F2[] = { + { 0x0000, "?????0000" }, + { 0x0001, "?????1111" }, + + { 0xFFFF, "" } +}; +*/ + +struct hid_usage_types_string hid_usage_typeFF00[] = { + {0x00E9, "Base Up"}, + {0x00EA, "Base Down"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_typeFF84[] = { + {0x0000, "Undefined"}, + {0x0001, "iName"}, + {0x0002, "PresentStatus"}, + {0x0003, "ChangedStatus"}, + {0x0004, "UPS"}, + {0x0005, "PowerSupply"}, + {0x0010, "BatterySystem"}, + {0x0011, "BatterySystemID"}, + {0x0012, "Battery"}, + {0x0013, "BatteryID"}, + {0x0014, "Charger"}, + {0x0015, "ChargerID"}, + {0x0016, "PowerConverter"}, + {0x0017, "PowerConverterID"}, + {0x0018, "OutletSystem"}, + {0x0019, "OutletSystemID"}, + {0x001A, "Input"}, + {0x001B, "InputID"}, + {0x001C, "Output"}, + {0x001D, "OutputID"}, + {0x001E, "Flow"}, + {0x001F, "FlowID"}, + {0x0020, "Outlet"}, + {0x0021, "OutletID"}, + {0x0022, "Gang"}, + {0x0023, "GangID"}, + {0x0024, "Sink"}, + {0x0025, "SinkID"}, + {0x0030, "Voltage"}, + {0x0031, "Current"}, + {0x0032, "Frequency"}, + {0x0033, "ApparentPower"}, + {0x0034, "ActivePower"}, + {0x0035, "PercentLoad"}, + {0x0036, "Temperature"}, + {0x0037, "Humidity"}, + {0x0040, "ConfigVoltage"}, + {0x0041, "ConfigCurrent"}, + {0x0042, "ConfigFrequency"}, + {0x0043, "ConfigApparentPower"}, + {0x0044, "ConfigActivePower"}, + {0x0045, "ConfigPercentLoad"}, + {0x0046, "ConfigTemperature"}, + {0x0047, "ConfigHumidity"}, + {0x0050, "SwitchOnControl"}, + {0x0051, "SwitchOffControl"}, + {0x0052, "ToggleControl"}, + {0x0053, "LowVoltageTransfer"}, + {0x0054, "HighVoltageTransfer"}, + {0x0055, "DelayBeforeReboot"}, + {0x0056, "DelayBeforeStartup"}, + {0x0057, "DelayBeforeShutdown"}, + {0x0058, "Test"}, + {0x0059, "Vendorspecificcommand"}, + {0x0060, "Present"}, + {0x0061, "Good"}, + {0x0062, "InternalFailure"}, + {0x0063, "VoltageOutOfRange"}, + {0x0064, "FrequencyOutOfRange"}, + {0x0065, "Overload"}, + {0x0066, "OverCharged"}, + {0x0067, "OverTemperature"}, + {0x0068, "ShutdownRequested"}, + {0x0069, "ShutdownImminent"}, + {0x006A, "VendorSpecificAnswerValid"}, + {0x006B, "SwitchOn/Off"}, + {0x006C, "Switcheble"}, + {0x006D, "Used"}, + {0x006E, "Boost"}, + {0x006F, "Buck"}, + {0x0070, "Initialized"}, + {0x0071, "Tested"}, + + {0xFFFF, ""}, +}; + +struct hid_usage_types_string hid_usage_typeFF85[] = { + {0x0000, "Undefined"}, + {0x0001, "SMBBatteryMode"}, + {0x0002, "SMBBatteryStatus"}, + {0x0003, "SMBAlarmWarning"}, + {0x0004, "SMBChargerMode"}, + {0x0005, "SMBChargerStatus"}, + {0x0006, "SMBChargerSpecInfo"}, + {0x0007, "SMBSelectorState"}, + {0x0008, "SMBSelectorPreset"}, + {0x0009, "SMBSelectorInfo"}, + {0x0010, "OptionalMfgFunction1"}, + {0x0011, "OptionalMfgFunction2"}, + {0x0012, "OptionalMfgFunction3"}, + {0x0013, "OptionalMfgFunction4"}, + {0x0014, "OptionalMfgFunction5"}, + {0x0015, "ConnectionToSMBus"}, + {0x0016, "OutputConnection"}, + {0x0017, "ChargerConnection"}, + {0x0018, "BatteryInsertion"}, + {0x0019, "Usenext"}, + {0x001A, "OKToUse"}, + {0x0028, "ManufacturerAccess"}, + {0x0029, "RemainingCapacityLimit"}, + {0x002A, "RemainingTimeLimit"}, + {0x002B, "AtRate"}, + {0x002C, "CapacityMode"}, + {0x002D, "BroadcastToCharger"}, + {0x002E, "PrimaryBattery"}, + {0x002F, "ChargeController"}, + {0x0040, "TerminateCharge"}, + {0x0041, "TermminateDischarge"}, + {0x0042, "BelowRemainingCapacityLimit"}, + {0x0043, "RemainingTimeLimitExpired"}, + {0x0044, "Charging"}, + {0x0045, "Discharging"}, + {0x0046, "FullyCharged"}, + {0x0047, "FullyDischarged"}, + {0x0048, "ConditionningFlag"}, + {0x0049, "AtRateOK"}, + {0x004A, "SMBErrorCode"}, + {0x004B, "NeedReplacement"}, + {0x0060, "AtRateTimeToFull"}, + {0x0061, "AtRateTimeToEmpty"}, + {0x0062, "AverageCurrent"}, + {0x0063, "Maxerror"}, + {0x0064, "RelativeStateOfCharge"}, + {0x0065, "AbsoluteStateOfCharge"}, + {0x0066, "RemainingCapacity"}, + {0x0067, "FullChargeCapacity"}, + {0x0068, "RunTimeToEmpty"}, + {0x0069, "AverageTimeToEmpty"}, + {0x006A, "AverageTimeToFull"}, + {0x006B, "CycleCount"}, + {0x0080, "BattPackModelLevel"}, + {0x0081, "InternalChargeController"}, + {0x0082, "PrimaryBatterySupport"}, + {0x0083, "DesignCapacity"}, + {0x0084, "SpecificationInfo"}, + {0x0085, "ManufacturerDate"}, + {0x0086, "SerialNumber"}, + {0x0087, "iManufacturerName"}, + {0x0088, "iDevicename"}, + {0x0089, "iDeviceChemistery"}, + {0x008A, "iManufacturerData"}, + {0x008B, "Rechargeable"}, + {0x008C, "WarningCapacityLimit"}, + {0x008D, "CapacityGranularity1"}, + {0x008E, "CapacityGranularity2"}, + {0x00C0, "InhibitCharge"}, + {0x00C1, "EnablePolling"}, + {0x00C2, "ResetToZero"}, + {0x00D0, "ACPresent"}, + {0x00D1, "BatteryPresent"}, + {0x00D2, "PowerFail"}, + {0x00D3, "AlarmInhibited"}, + {0x00D4, "ThermistorUnderRange"}, + {0x00D5, "ThermistorHot"}, + {0x00D6, "ThermistorCold"}, + {0x00D7, "ThermistorOverRange"}, + {0x00D8, "VoltageOutOfRange"}, + {0x00D9, "CurrentOutOfRange"}, + {0x00DA, "CurrentNotRegulated"}, + {0x00DB, "VoltageNotRegulated"}, + {0x00DC, "MasterMode"}, + {0x00DD, "ChargerBattery/HostControlled"}, + {0x00F0, "ChargerSpecInfo"}, + {0x00F1, "ChargerSpecRef"}, + {0x00F2, "Level2"}, + {0x00F3, "Level3"}, + + {0xFFFF, ""}, +}; + +// Usage Pages +struct hid_usage_pages_string hid_usage_page_strings[] = { + {0x0000, NULL, "Undefined"}, + {0x0001, hid_usage_type001, "Generic Desktop"}, + {0x0002, hid_usage_type002, "Simulation"}, + {0x0003, hid_usage_type003, "Virtual Reality"}, + {0x0004, hid_usage_type004, "Sport"}, + {0x0005, hid_usage_type005, "Game"}, + {0x0006, hid_usage_type006, "Generic Device"}, + {0x0007, hid_usage_type007, "Keyboard/Keypad"}, + {0x0008, hid_usage_type008, "LEDs"}, + {0x0009, NULL, "Button"}, + {0x000A, NULL, "Ordinal"}, + {0x000B, hid_usage_type00B, "Telephony"}, + {0x000C, hid_usage_type00C, "Consumer"}, + {0x000D, hid_usage_type00D, "Digitizer"}, + {0x000F, hid_usage_type00F, "PID Page"}, + {0x0010, NULL, "Unicode"}, + {0x0014, hid_usage_type014, "Alphanumeric Display"}, + {0x0040, hid_usage_type040, "Meidcal Insturments"}, + {0x0080, hid_usage_type080, "Monitor Pages"}, + {0x0081, NULL, "Monitor Pages"}, + {0x0082, hid_usage_type082, "Monitor Pages"}, + {0x0083, hid_usage_type083, "Monitor Pages"}, + {0x0084, hid_usage_type084, "Power Pages"}, + {0x0085, hid_usage_type085, "Power Pages"}, + {0x0086, hid_usage_type086, "Power Pages"}, + {0x0087, hid_usage_type087, "Power Pages"}, + {0x008C, hid_usage_type08C, "Barcode Scanner"}, + {0x008D, hid_usage_type08D, "Scale"}, + {0x008E, hid_usage_type08E, "Magnetic Stripe Reading (MSR) Devices"}, + {0x008F, hid_usage_type08F, "Reserved Point of Sale"}, + {0x0090, hid_usage_type090, "Camera Control"}, + {0x0091, hid_usage_type091, "Arcade"}, + //{ 0xF1F2, hid_usage_typeF1F2, "??????" }, // unknown: I have a MOSART Semi Wireless Mouse that uses this Upage + {0xFF00, hid_usage_typeFF00, "MS Non-Standard"}, + {0xFF84, hid_usage_typeFF84, "APC Non-Standard"}, + {0xFF85, hid_usage_typeFF85, "APC Non-Standard"}, + + {0xFFFF, NULL, ""}, +}; + +char hid_collection_str[][64] = { + "Physical", "Application", "Logical", "Report", "Named Array", "Usage Switch", "Usage Modifier", +}; \ No newline at end of file diff --git a/kernel/driver/hid/internal.h b/kernel/driver/hid/internal.h new file mode 100644 index 00000000..3da9db43 --- /dev/null +++ b/kernel/driver/hid/internal.h @@ -0,0 +1,37 @@ +#pragma once +#include + +extern struct hid_usage_types_string hid_usage_type001[]; +extern struct hid_usage_types_string hid_usage_type002[]; +extern struct hid_usage_types_string hid_usage_type003[]; +extern struct hid_usage_types_string hid_usage_type004[]; +extern struct hid_usage_types_string hid_usage_type005[]; +extern struct hid_usage_types_string hid_usage_type006[]; +extern struct hid_usage_types_string hid_usage_type007[]; +extern struct hid_usage_types_string hid_usage_type008[]; +extern struct hid_usage_types_string hid_usage_type00B[]; +extern struct hid_usage_types_string hid_usage_type00C[]; +extern struct hid_usage_types_string hid_usage_type00D[]; +extern struct hid_usage_types_string hid_usage_type00F[]; +extern struct hid_usage_types_string hid_usage_type014[]; +extern struct hid_usage_types_string hid_usage_type040[]; +extern struct hid_usage_types_string hid_usage_type080[]; +extern struct hid_usage_types_string hid_usage_type082[]; +extern struct hid_usage_types_string hid_usage_type083[]; +extern struct hid_usage_types_string hid_usage_type084[]; +extern struct hid_usage_types_string hid_usage_type085[]; +extern struct hid_usage_types_string hid_usage_type086[]; +extern struct hid_usage_types_string hid_usage_type087[]; +extern struct hid_usage_types_string hid_usage_type08C[]; +extern struct hid_usage_types_string hid_usage_type08D[]; +extern struct hid_usage_types_string hid_usage_type08E[]; +extern struct hid_usage_types_string hid_usage_type08F[]; +extern struct hid_usage_types_string hid_usage_type090[]; +extern struct hid_usage_types_string hid_usage_type091[]; +extern struct hid_usage_types_string hid_usage_typeFF00[]; +extern struct hid_usage_types_string hid_usage_typeFF84[]; +extern struct hid_usage_types_string hid_usage_typeFF85[]; + +extern struct hid_usage_pages_string hid_usage_page_strings[]; + +extern char hid_collection_str[][64]; \ No newline at end of file diff --git a/kernel/driver/hid/usbhid/Makefile b/kernel/driver/hid/usbhid/Makefile new file mode 100644 index 00000000..39103944 --- /dev/null +++ b/kernel/driver/hid/usbhid/Makefile @@ -0,0 +1,15 @@ + +CFLAGS += -I . + + +kernel_driver_usbhid_objs:= $(shell find ./*.c) + +ECHO: + @echo "$@" + +$(kernel_driver_usbhid_objs): ECHO + gcc $(CFLAGS) -c $@ -o $@.o + +all: $(kernel_driver_hid_objs) $(kernel_driver_hid_subdirs) + @echo $(kernel_driver_hid_objs) + diff --git a/kernel/driver/usb/usb.h b/kernel/driver/usb/usb.h index fa521902..c2298342 100644 --- a/kernel/driver/usb/usb.h +++ b/kernel/driver/usb/usb.h @@ -105,7 +105,8 @@ struct usb_interface_desc uint8_t num_endpoints; // 当前interface的端点数量 uint8_t interface_class; // Class code uint8_t interface_sub_class; // Sub class code - uint8_t interface_protocol; // 协议 These codes are qualified by the value of thebInterfaceClass and the bInterfaceSubClass fields. + uint8_t interface_protocol; // 协议 These codes are qualified by the value of thebInterfaceClass and the + // bInterfaceSubClass fields. uint8_t index; // index of String Descriptor describing this interface } __attribute__((packed)); @@ -162,6 +163,7 @@ struct usb_request_packet_t #define USB_REQ_TYPE_GET_REQUEST (__USB_REQ_TYPE_D2H | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_DEVICE) #define USB_REQ_TYPE_SET_REQUEST (__USB_REQ_TYPE_H2D | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_DEVICE) +#define USB_REQ_TYPE_GET_INTERFACE_REQUEST (__USB_REQ_TYPE_D2H | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_INTERFACE) #define USB_REQ_TYPE_SET_INTERFACE (__USB_REQ_TYPE_H2D | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_INTERFACE) #define USB_REQ_TYPE_SET_CLASS_INTERFACE (__USB_REQ_TYPE_H2D | __USB_REQ_TYPE_CLASS | __USB_REQ_TYPE_INTERFACE) @@ -244,12 +246,12 @@ enum * @brief 该宏定义用于声明usb请求包,并初始化其中的各个字段 * */ -#define DECLARE_USB_PACKET(pak_name, _trans_req_type, _trans_request, _trans_value, _trans_index, _transfer_length) \ - struct usb_request_packet_t pak_name = {0}; \ - pak_name.request_type = (_trans_req_type); \ - pak_name.request = (_trans_request); \ - pak_name.value = (_trans_value); \ - pak_name.index = (_trans_index); \ +#define DECLARE_USB_PACKET(pak_name, _trans_req_type, _trans_request, _trans_value, _trans_index, _transfer_length) \ + struct usb_request_packet_t pak_name = {0}; \ + pak_name.request_type = (_trans_req_type); \ + pak_name.request = (_trans_request); \ + pak_name.value = (_trans_value); \ + pak_name.index = (_trans_index); \ pak_name.length = (_transfer_length); /* @@ -283,6 +285,22 @@ enum USB_CLASS_VENDOR_SPEC = 0XFF, }; +/** + * @brief usb hid descriptor的结构体 + * + */ +struct usb_hid_desc +{ + uint8_t len; + uint8_t type; // USB_DT_HID + uint16_t bcdHID; // 标识HIDClass规范版本的数字表达式。 + + uint8_t country_code; + uint8_t descriptors_num; // the number of class descriptors + uint8_t desc_type; // Constant name identifying type of class descriptor + uint16_t report_desc_len; // Report descriptor的大小 +}; + /** * @brief 初始化usb驱动程序 * diff --git a/kernel/driver/usb/xhci/xhci.c b/kernel/driver/usb/xhci/xhci.c index f9f0c929..308d1bff 100644 --- a/kernel/driver/usb/xhci/xhci.c +++ b/kernel/driver/usb/xhci/xhci.c @@ -1,14 +1,15 @@ #include "xhci.h" #include "internal.h" +#include #include -#include #include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include // 由于xhci寄存器读取需要对齐,因此禁用GCC优化选项 #pragma GCC optimize("O0") @@ -30,7 +31,8 @@ static int xhci_hc_reset(int id); static int xhci_hc_stop_legacy(int id); static int xhci_hc_start_sched(int id); static int xhci_hc_stop_sched(int id); -static uint32_t xhci_hc_get_protocol_offset(int id, uint32_t list_off, const int version, uint32_t *offset, uint32_t *count, uint16_t *protocol_flag); +static uint32_t xhci_hc_get_protocol_offset(int id, uint32_t list_off, const int version, uint32_t *offset, + uint32_t *count, uint16_t *protocol_flag); static int xhci_hc_pair_ports(int id); static uint64_t xhci_create_ring(int trbs); static uint64_t xhci_create_event_ring(int trbs, uint64_t *ret_ring_addr); @@ -40,30 +42,43 @@ static int xhci_hc_start_ports(int id); static int xhci_send_command(int id, struct xhci_TRB_t *trb, const bool do_ring); static uint64_t xhci_initialize_slot(const int id, const int port, const int speed, const int max_packet); -static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const int port_id, const int ep_num, const int max_packet, const int max_burst, const int type, const int direction, const int speed, const int ep_interval); +static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const int port_id, const int ep_num, + const int max_packet, const int max_burst, const int type, const int direction, + const int speed, const int ep_interval); static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int slot_id, const bool block); -static int xhci_control_in(const int id, struct usb_request_packet_t *packet, void *target, const int port_id, const int max_packet); -static int xhci_control_out(const int id, struct usb_request_packet_t *packet, void *target, const int slot_id, const int max_packet); -static int xhci_setup_stage(struct xhci_ep_info_t *ep, const struct usb_request_packet_t *packet, const uint8_t direction); -static int xhci_data_stage(struct xhci_ep_info_t *ep, uint64_t buf_vaddr, uint8_t trb_type, const uint32_t size, uint8_t direction, const int max_packet, const uint64_t status_vaddr); +static int xhci_control_in(const int id, struct usb_request_packet_t *packet, void *target, const int port_id, + const int max_packet); +static int xhci_control_out(const int id, struct usb_request_packet_t *packet, void *target, const int slot_id, + const int max_packet); +static int xhci_setup_stage(struct xhci_ep_info_t *ep, const struct usb_request_packet_t *packet, + const uint8_t direction); +static int xhci_data_stage(struct xhci_ep_info_t *ep, uint64_t buf_vaddr, uint8_t trb_type, const uint32_t size, + uint8_t direction, const int max_packet, const uint64_t status_vaddr); static int xhci_status_stage(struct xhci_ep_info_t *ep, uint8_t direction, uint64_t status_buf_vaddr); static int xhci_wait_for_interrupt(const int id, uint64_t status_vaddr); -static inline int xhci_get_desc(const int id, const int port_id, void *target, const uint16_t desc_type, const uint8_t desc_index, const uint16_t lang_id, const uint16_t length); +static inline int xhci_get_desc(const int id, const int port_id, void *target, const uint16_t desc_type, + const uint8_t desc_index, const uint16_t lang_id, const uint16_t length); static int xhci_get_config_desc(const int id, const int port_id, struct usb_config_desc *conf_desc); -static inline int xhci_get_config_desc_full(const int id, const int port_id, const struct usb_config_desc *conf_desc, void *target); +static inline int xhci_get_config_desc_full(const int id, const int port_id, const struct usb_config_desc *conf_desc, + void *target); static int xhci_get_interface_desc(const void *in_buf, const uint8_t if_num, struct usb_interface_desc **if_desc); -static inline int xhci_get_endpoint_desc(const struct usb_interface_desc *if_desc, const uint8_t ep_num, struct usb_endpoint_desc **ep_desc); +static inline int xhci_get_endpoint_desc(const struct usb_interface_desc *if_desc, const uint8_t ep_num, + struct usb_endpoint_desc **ep_desc); static int xhci_get_descriptor(const int id, const int port_id, struct usb_device_desc *dev_desc); static int xhci_configure_port(const int id, const int port_id); -static int xhci_configure_endpoint(const int id, const int port_id, const uint8_t ep_num, const uint8_t ep_type, struct usb_endpoint_desc *ep_desc); +static int xhci_configure_endpoint(const int id, const int port_id, const uint8_t ep_num, const uint8_t ep_type, + struct usb_endpoint_desc *ep_desc); +static int xhci_get_hid_report(int id, int port_id, int interface_number, void *ret_hid_report, + uint32_t hid_report_len); +static int xhci_get_hid_descriptor(int id, int port_id, const void *full_conf, int interface_number, + struct usb_hid_desc **ret_hid_desc); -hardware_intr_controller xhci_hc_intr_controller = - { - .enable = xhci_hc_irq_enable, - .disable = xhci_hc_irq_disable, - .install = xhci_hc_irq_install, - .uninstall = xhci_hc_irq_uninstall, - .ack = apic_local_apic_edge_ack, +hardware_intr_controller xhci_hc_intr_controller = { + .enable = xhci_hc_irq_enable, + .disable = xhci_hc_irq_disable, + .install = xhci_hc_irq_install, + .uninstall = xhci_hc_irq_uninstall, + .ack = apic_local_apic_edge_ack, }; /** @@ -207,7 +222,8 @@ static __always_inline void __xhci_write_trb(struct xhci_ep_info_t *ep_info, str */ static __always_inline uint64_t xhci_get_device_context_vaddr(const int id, const int port_id) { - return (uint64_t)phys_2_virt(__read8b(xhci_hc[id].dcbaap_vaddr + (xhci_hc[id].ports[port_id].slot_id * sizeof(uint64_t)))); + return (uint64_t)phys_2_virt( + __read8b(xhci_hc[id].dcbaap_vaddr + (xhci_hc[id].ports[port_id].slot_id * sizeof(uint64_t)))); } /** @@ -294,11 +310,13 @@ static int xhci_hc_stop_legacy(int id) { io_mfence(); // 接管控制权 - xhci_write_cap_reg32(id, current_offset, xhci_read_cap_reg32(id, current_offset) | XHCI_XECP_LEGACY_OS_OWNED); + xhci_write_cap_reg32(id, current_offset, + xhci_read_cap_reg32(id, current_offset) | XHCI_XECP_LEGACY_OS_OWNED); io_mfence(); // 等待响应完成 int timeout = XHCI_XECP_LEGACY_TIMEOUT; - while ((xhci_read_cap_reg32(id, current_offset) & XHCI_XECP_LEGACY_OWNING_MASK) != XHCI_XECP_LEGACY_OS_OWNED) + while ((xhci_read_cap_reg32(id, current_offset) & XHCI_XECP_LEGACY_OWNING_MASK) != + XHCI_XECP_LEGACY_OS_OWNED) { io_mfence(); usleep(1000); @@ -361,7 +379,8 @@ static int xhci_hc_stop_sched(int id) * @param protocol_flag 返回的与协议相关的flag * @return uint32_t 下一个列表项的偏移量 */ -static uint32_t xhci_hc_get_protocol_offset(int id, uint32_t list_off, const int version, uint32_t *offset, uint32_t *count, uint16_t *protocol_flag) +static uint32_t xhci_hc_get_protocol_offset(int id, uint32_t list_off, const int version, uint32_t *offset, + uint32_t *count, uint16_t *protocol_flag) { if (count) *count = 0; @@ -467,7 +486,8 @@ static int xhci_hc_pair_ports(int id) continue; io_mfence(); if ((xhci_hc[id].ports[i].offset == xhci_hc[id].ports[j].offset) && - ((xhci_hc[id].ports[i].flags & XHCI_PROTOCOL_INFO) != (xhci_hc[id].ports[j].flags & XHCI_PROTOCOL_INFO))) + ((xhci_hc[id].ports[i].flags & XHCI_PROTOCOL_INFO) != + (xhci_hc[id].ports[j].flags & XHCI_PROTOCOL_INFO))) { xhci_hc[id].ports[i].paired_port_num = j; xhci_hc[id].ports[i].flags |= XHCI_PROTOCOL_HAS_PAIR; @@ -482,11 +502,11 @@ static int xhci_hc_pair_ports(int id) for (int i = 0; i < xhci_hc[id].port_num; ++i) { io_mfence(); - if (XHCI_PORT_IS_USB3(id, i) || - (XHCI_PORT_IS_USB2(id, i) && (!XHCI_PORT_HAS_PAIR(id, i)))) + if (XHCI_PORT_IS_USB3(id, i) || (XHCI_PORT_IS_USB2(id, i) && (!XHCI_PORT_HAS_PAIR(id, i)))) xhci_hc[id].ports[i].flags |= XHCI_PROTOCOL_ACTIVE; } - kinfo("Found %d ports on root hub, usb2 ports:%d, usb3 ports:%d", xhci_hc[id].port_num, xhci_hc[id].port_num_u2, xhci_hc[id].port_num_u3); + kinfo("Found %d ports on root hub, usb2 ports:%d, usb3 ports:%d", xhci_hc[id].port_num, xhci_hc[id].port_num_u2, + xhci_hc[id].port_num_u3); /* // 打印配对结果 @@ -494,8 +514,9 @@ static int xhci_hc_pair_ports(int id) { if (XHCI_PORT_IS_USB3(id, i)) { - kdebug("USB3 port %d, offset=%d, pair with usb2 port %d, current port is %s", i, xhci_hc[id].ports[i].offset, - xhci_hc[id].ports[i].paired_port_num, XHCI_PORT_IS_ACTIVE(id, i) ? "active" : "inactive"); + kdebug("USB3 port %d, offset=%d, pair with usb2 port %d, current port is %s", i, + xhci_hc[id].ports[i].offset, xhci_hc[id].ports[i].paired_port_num, XHCI_PORT_IS_ACTIVE(id, i) ? "active" : + "inactive"); } else if (XHCI_PORT_IS_USB2(id, i) && (!XHCI_PORT_HAS_PAIR(id, i))) // 单独的2.0接口 { @@ -721,8 +742,10 @@ void xhci_hc_irq_handler(uint64_t irq_num, uint64_t cid, struct pt_regs *regs) switch (event_trb_ptr->TRB_type) { case TRB_TYPE_TRANS_EVENT: // 当前 event trb是 transfer event TRB - // If SPD was encountered in this TD, comp_code will be SPD, else it should be SUCCESS (specs 4.10.1.1) - __write4b((uint64_t)phys_2_virt(event_trb.param), (event_trb.status | XHCI_IRQ_DONE)); // return code + bytes *not* transferred + // If SPD was encountered in this TD, comp_code will be SPD, else it should be SUCCESS + // (specs 4.10.1.1) + __write4b((uint64_t)phys_2_virt(event_trb.param), + (event_trb.status | XHCI_IRQ_DONE)); // return code + bytes *not* transferred break; default: @@ -871,14 +894,15 @@ static uint64_t xhci_initialize_slot(const int id, const int port, const int spe uint64_t device_context_vaddr = (uint64_t)kzalloc(xhci_hc[id].context_size * 32, 0); // kdebug("slot id=%d, device_context_vaddr=%#018lx, port=%d", slot_id, device_context_vaddr, port); // 写到数组中 - __write8b(xhci_hc[id].dcbaap_vaddr + (xhci_hc[id].ports[port].slot_id * sizeof(uint64_t)), virt_2_phys(device_context_vaddr)); + __write8b(xhci_hc[id].dcbaap_vaddr + (xhci_hc[id].ports[port].slot_id * sizeof(uint64_t)), + virt_2_phys(device_context_vaddr)); struct xhci_slot_context_t slot_ctx = {0}; slot_ctx.entries = 1; slot_ctx.speed = speed; slot_ctx.route_string = 0; slot_ctx.rh_port_num = port + 1; // 由于xhci控制器是1-base的,因此把驱动程序中存储的端口号加1,才是真实的端口号 - slot_ctx.max_exit_latency = 0; // 稍后会计算这个值 - slot_ctx.int_target = 0; // 当前全部使用第0个interrupter + slot_ctx.max_exit_latency = 0; // 稍后会计算这个值 + slot_ctx.int_target = 0; // 当前全部使用第0个interrupter slot_ctx.slot_state = XHCI_SLOT_STATE_DISABLED_OR_ENABLED; slot_ctx.device_address = 0; @@ -904,7 +928,9 @@ static uint64_t xhci_initialize_slot(const int id, const int port, const int spe * @param speed 传输速度 * @param ep_interval 端点的连续请求间隔 */ -static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const int port_id, const int ep_num, const int max_packet, const int max_burst, const int type, const int direction, const int speed, const int ep_interval) +static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const int port_id, const int ep_num, + const int max_packet, const int max_burst, const int type, const int direction, + const int speed, const int ep_interval) { // 由于目前只实现获取设备的描述符,因此暂时只支持control ep if (type != USB_EP_CONTROL && type != USB_EP_INTERRUPT) @@ -917,10 +943,12 @@ static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const in ep_ctx.tr_dequeue_ptr = virt_2_phys(xhci_hc[id].ports[port_id].ep_info[ep_num].ep_ring_vbase); xhci_ep_set_dequeue_cycle_state(&ep_ctx, XHCI_TRB_CYCLE_ON); - xhci_hc[id].ports[port_id].ep_info[ep_num].current_ep_ring_vaddr = xhci_hc[id].ports[port_id].ep_info[ep_num].ep_ring_vbase; + xhci_hc[id].ports[port_id].ep_info[ep_num].current_ep_ring_vaddr = + xhci_hc[id].ports[port_id].ep_info[ep_num].ep_ring_vbase; xhci_hc[id].ports[port_id].ep_info[ep_num].current_ep_ring_cycle = xhci_ep_get_dequeue_cycle_state(&ep_ctx); // kdebug("ep_ctx.tr_dequeue_ptr = %#018lx", ep_ctx.tr_dequeue_ptr); - // kdebug("xhci_hc[id].control_ep_info.current_ep_ring_cycle = %d", xhci_hc[id].control_ep_info.current_ep_ring_cycle); + // kdebug("xhci_hc[id].control_ep_info.current_ep_ring_cycle = %d", + // xhci_hc[id].control_ep_info.current_ep_ring_cycle); kdebug("max_packet=%d, max_burst=%d", max_packet, max_burst); switch (type) { @@ -1032,7 +1060,8 @@ failed:; * @param direction 传输的方向 * @return int 产生的TRB数量 */ -static int xhci_setup_stage(struct xhci_ep_info_t *ep, const struct usb_request_packet_t *packet, const uint8_t direction) +static int xhci_setup_stage(struct xhci_ep_info_t *ep, const struct usb_request_packet_t *packet, + const uint8_t direction) { // kdebug("ep->current_ep_ring_cycle=%d", ep->current_ep_ring_cycle); struct xhci_TRB_setup_stage_t trb = {0}; @@ -1066,7 +1095,8 @@ static int xhci_setup_stage(struct xhci_ep_info_t *ep, const struct usb_request_ * @param status_vaddr event data TRB的缓冲区(4字节,且地址按照16字节对齐) * @return int 产生的TRB数量 */ -static int xhci_data_stage(struct xhci_ep_info_t *ep, uint64_t buf_vaddr, uint8_t trb_type, const uint32_t size, uint8_t direction, const int max_packet, const uint64_t status_vaddr) +static int xhci_data_stage(struct xhci_ep_info_t *ep, uint64_t buf_vaddr, uint8_t trb_type, const uint32_t size, + uint8_t direction, const int max_packet, const uint64_t status_vaddr) { if (size == 0) return 0; @@ -1204,10 +1234,12 @@ static int xhci_wait_for_interrupt(const int id, uint64_t status_vaddr) * @param max_packet 最大数据包大小 * @return int 读取到的数据的大小 */ -static int xhci_control_in(const int id, struct usb_request_packet_t *packet, void *target, const int port_id, const int max_packet) +static int xhci_control_in(const int id, struct usb_request_packet_t *packet, void *target, const int port_id, + const int max_packet) { - uint64_t status_buf_vaddr = (uint64_t)kzalloc(16, 0); // 本来是要申请4bytes的buffer的,但是因为xhci控制器需要16bytes对齐,因此申请16bytes + uint64_t status_buf_vaddr = + (uint64_t)kzalloc(16, 0); // 本来是要申请4bytes的buffer的,但是因为xhci控制器需要16bytes对齐,因此申请16bytes uint64_t data_buf_vaddr = 0; int retval = 0; @@ -1216,7 +1248,8 @@ static int xhci_control_in(const int id, struct usb_request_packet_t *packet, vo if (packet->length) { data_buf_vaddr = (uint64_t)kzalloc(packet->length, 0); - xhci_data_stage(&xhci_hc[id].ports[port_id].ep_info[XHCI_EP_CONTROL], data_buf_vaddr, TRB_TYPE_DATA_STAGE, packet->length, XHCI_DIR_IN_BIT, max_packet, status_buf_vaddr); + xhci_data_stage(&xhci_hc[id].ports[port_id].ep_info[XHCI_EP_CONTROL], data_buf_vaddr, TRB_TYPE_DATA_STAGE, + packet->length, XHCI_DIR_IN_BIT, max_packet, status_buf_vaddr); } /* @@ -1275,7 +1308,8 @@ done:; * @param max_packet 最大数据包大小 * @return int 读取到的数据的大小 */ -static int xhci_control_out(const int id, struct usb_request_packet_t *packet, void *target, const int port_id, const int max_packet) +static int xhci_control_out(const int id, struct usb_request_packet_t *packet, void *target, const int port_id, + const int max_packet) { uint64_t status_buf_vaddr = (uint64_t)kzalloc(16, 0); uint64_t data_buf_vaddr = 0; @@ -1287,7 +1321,8 @@ static int xhci_control_out(const int id, struct usb_request_packet_t *packet, v if (packet->length) { data_buf_vaddr = (uint64_t)kzalloc(packet->length, 0); - xhci_data_stage(&xhci_hc[id].ports[port_id].ep_info[XHCI_EP_CONTROL], data_buf_vaddr, TRB_TYPE_DATA_STAGE, packet->length, XHCI_DIR_OUT_BIT, max_packet, status_buf_vaddr); + xhci_data_stage(&xhci_hc[id].ports[port_id].ep_info[XHCI_EP_CONTROL], data_buf_vaddr, TRB_TYPE_DATA_STAGE, + packet->length, XHCI_DIR_OUT_BIT, max_packet, status_buf_vaddr); } #ifndef __QEMU_EMULATION__ @@ -1338,7 +1373,8 @@ done:; * @param length 要传输的数据长度 * @return int 错误码 */ -static inline int xhci_get_desc(const int id, const int port_id, void *target, const uint16_t desc_type, const uint8_t desc_index, const uint16_t lang_id, const uint16_t length) +static inline int xhci_get_desc(const int id, const int port_id, void *target, const uint16_t desc_type, + const uint8_t desc_index, const uint16_t lang_id, const uint16_t length) { struct usb_device_desc *dev_desc = xhci_hc[id].ports[port_id].dev_desc; int count; @@ -1347,7 +1383,13 @@ static inline int xhci_get_desc(const int id, const int port_id, void *target, c // 设备端口没有对应的描述符 if (unlikely(dev_desc == NULL)) return -EINVAL; - DECLARE_USB_PACKET(ctrl_in_packet, USB_REQ_TYPE_GET_REQUEST, USB_REQ_GET_DESCRIPTOR, (desc_type << 8) | desc_index, lang_id, length); + + uint8_t req_type = USB_REQ_TYPE_GET_REQUEST; + if (desc_type == USB_DT_HID_REPORT) + req_type = USB_REQ_TYPE_GET_INTERFACE_REQUEST; + + DECLARE_USB_PACKET(ctrl_in_packet, req_type, USB_REQ_GET_DESCRIPTOR, (desc_type << 8) | desc_index, lang_id, + length); count = xhci_control_in(id, &ctrl_in_packet, target, port_id, dev_desc->max_packet_size); if (unlikely(count == 0)) return -EAGAIN; @@ -1364,9 +1406,9 @@ static inline int xhci_set_configuration(const int id, const int port_id, const if (unlikely(dev_desc == NULL)) return -EINVAL; DECLARE_USB_PACKET(ctrl_out_packet, USB_REQ_TYPE_SET_REQUEST, USB_REQ_SET_CONFIGURATION, conf_value & 0xff, 0, 0); - kdebug("set conf: to control out"); + // kdebug("set conf: to control out"); count = xhci_control_out(id, &ctrl_out_packet, NULL, port_id, dev_desc->max_packet_size); - kdebug("set conf: count=%d", count); + // kdebug("set conf: count=%d", count); return 0; } @@ -1387,7 +1429,10 @@ static int xhci_get_config_desc(const int id, const int port_id, struct usb_conf int retval = xhci_get_desc(id, port_id, conf_desc, USB_DT_CONFIG, 0, 0, 9); if (unlikely(retval != 0)) return retval; - kdebug("port %d got conf ok. type=%d, len=%d, total_len=%d, num_interfaces=%d, max_power=%dmA", port_id, conf_desc->type, conf_desc->len, conf_desc->total_len, conf_desc->num_interfaces, (xhci_get_port_speed(id, port_id) == XHCI_PORT_SPEED_SUPER) ? (conf_desc->max_power * 8) : (conf_desc->max_power * 2)); + kdebug("port %d got conf ok. type=%d, len=%d, total_len=%d, num_interfaces=%d, max_power=%dmA", port_id, + conf_desc->type, conf_desc->len, conf_desc->total_len, conf_desc->num_interfaces, + (xhci_get_port_speed(id, port_id) == XHCI_PORT_SPEED_SUPER) ? (conf_desc->max_power * 8) + : (conf_desc->max_power * 2)); return 0; } @@ -1400,7 +1445,8 @@ static int xhci_get_config_desc(const int id, const int port_id, struct usb_conf * @param target 最终结果要拷贝到的地址 * @return int 错误码 */ -static inline int xhci_get_config_desc_full(const int id, const int port_id, const struct usb_config_desc *conf_desc, void *target) +static inline int xhci_get_config_desc_full(const int id, const int port_id, const struct usb_config_desc *conf_desc, + void *target) { if (unlikely(conf_desc == NULL || target == NULL)) return -EINVAL; @@ -1420,20 +1466,31 @@ static int xhci_get_interface_desc(const void *in_buf, const uint8_t if_num, str { if (unlikely(if_desc == NULL || in_buf == NULL)) return -EINVAL; - kdebug("to get interface."); // 判断接口index是否合理 if (if_num >= ((struct usb_config_desc *)in_buf)->num_interfaces) return -EINVAL; - struct usb_interface_desc *ptr = (struct usb_interface_desc *)(in_buf + sizeof(struct usb_config_desc)); - for (int i = 0; i < if_num; ++i) + uint32_t total_len = ((struct usb_config_desc *)in_buf)->total_len; + uint32_t pos = 0; + while (pos < total_len) { - ptr = (struct usb_interface_desc *)(((uint64_t)ptr) + sizeof(struct usb_interface_desc) + sizeof(struct usb_endpoint_desc) * ptr->num_endpoints); - } - // 返回结果 - *if_desc = ptr; + struct usb_interface_desc *ptr = (struct usb_interface_desc *)(in_buf + pos); + if (ptr->type != USB_DT_INTERFACE) + { + pos += ptr->len; + continue; + } - kdebug("get interface desc ok. interface_number=%d, num_endpoints=%d, class=%d, subclass=%d", ptr->interface_number, ptr->num_endpoints, ptr->interface_class, ptr->interface_sub_class); - return 0; + if (ptr->interface_number == if_num) // 找到目标interface desc + { + kdebug("get interface desc ok. interface_number=%d, num_endpoints=%d, class=%d, subclass=%d", + ptr->interface_number, ptr->num_endpoints, ptr->interface_class, ptr->interface_sub_class); + *if_desc = ptr; + return 0; + } + pos += ptr->len; + } + + return -EINVAL; } /** @@ -1444,14 +1501,16 @@ static int xhci_get_interface_desc(const void *in_buf, const uint8_t if_num, str * @param ep_desc 返回的指向端点描述符的指针 * @return int 错误码 */ -static inline int xhci_get_endpoint_desc(const struct usb_interface_desc *if_desc, const uint8_t ep_num, struct usb_endpoint_desc **ep_desc) +static inline int xhci_get_endpoint_desc(const struct usb_interface_desc *if_desc, const uint8_t ep_num, + struct usb_endpoint_desc **ep_desc) { if (unlikely(if_desc == NULL || ep_desc == NULL)) return -EINVAL; BUG_ON(ep_num >= if_desc->num_endpoints); *ep_desc = (struct usb_endpoint_desc *)((uint64_t)(if_desc + 1) + ep_num * sizeof(struct usb_endpoint_desc)); - kdebug("get endpoint desc: ep_addr=%d, max_packet=%d, attr=%#06x, interval=%d", (*ep_desc)->endpoint_addr, (*ep_desc)->max_packet, (*ep_desc)->attributes, (*ep_desc)->interval); + kdebug("get endpoint desc: ep_addr=%d, max_packet=%d, attr=%#06x, interval=%d", (*ep_desc)->endpoint_addr, + (*ep_desc)->max_packet, (*ep_desc)->attributes, (*ep_desc)->interval); return 0; } @@ -1552,11 +1611,11 @@ static int xhci_get_descriptor(const int id, const int port_id, struct usb_devic " product index: %i\n" " serial index: %i\n" " number of configs: %i\n", - port_id, dev_desc->len, dev_desc->type, dev_desc->usb_version >> 8, dev_desc->usb_version & 0xFF, dev_desc->_class, dev_desc->subclass, - dev_desc->protocol, dev_desc->max_packet_size, dev_desc->vendor_id, dev_desc->product_id, - (dev_desc->device_rel & 0xF000) >> 12, (dev_desc->device_rel & 0x0F00) >> 8, - (dev_desc->device_rel & 0x00F0) >> 4, (dev_desc->device_rel & 0x000F) >> 0, - dev_desc->manufacturer_index, dev_desc->procuct_index, dev_desc->serial_index, dev_desc->config); + port_id, dev_desc->len, dev_desc->type, dev_desc->usb_version >> 8, dev_desc->usb_version & 0xFF, + dev_desc->_class, dev_desc->subclass, dev_desc->protocol, dev_desc->max_packet_size, dev_desc->vendor_id, + dev_desc->product_id, (dev_desc->device_rel & 0xF000) >> 12, (dev_desc->device_rel & 0x0F00) >> 8, + (dev_desc->device_rel & 0x00F0) >> 4, (dev_desc->device_rel & 0x000F) >> 0, dev_desc->manufacturer_index, + dev_desc->procuct_index, dev_desc->serial_index, dev_desc->config); return 0; } @@ -1605,8 +1664,9 @@ static int xhci_hc_start_ports(int id) // kdebug("initializing usb2: %d", i); // reset该端口 // kdebug("to reset port %d, rflags=%#018lx", i, get_rflags()); - if (likely(xhci_reset_port(id, i) == 0)) // 如果端口reset成功,就获取它的描述符 - // 否则,reset函数会把它给设置为未激活,并且标志配对的usb2端口是激活的 + if (likely(xhci_reset_port(id, i) == + 0)) // 如果端口reset成功,就获取它的描述符 + // 否则,reset函数会把它给设置为未激活,并且标志配对的usb2端口是激活的 { // kdebug("reset port %d ok", id); @@ -1657,7 +1717,8 @@ static int xhci_hid_set_idle(const int id, const int port_id, struct usb_interfa * @param ep_desc 端点描述符 * @return int 错误码 */ -static int xhci_configure_endpoint(const int id, const int port_id, const uint8_t ep_num, const uint8_t ep_type, struct usb_endpoint_desc *ep_desc) +static int xhci_configure_endpoint(const int id, const int port_id, const uint8_t ep_num, const uint8_t ep_type, + struct usb_endpoint_desc *ep_desc) { int retval = 0; @@ -1672,7 +1733,7 @@ static int xhci_configure_endpoint(const int id, const int port_id, const uint8_ // 创建输入上下文缓冲区 uint64_t input_ctx_buffer = (uint64_t)kzalloc(xhci_hc[id].context_size * 33, 0); // 置位对应的add bit - __write4b(input_ctx_buffer + 4, (1 << ep_num)|1); + __write4b(input_ctx_buffer + 4, (1 << ep_num) | 1); __write4b(input_ctx_buffer + 0x1c, 1); // 拷贝slot上下文 @@ -1736,38 +1797,83 @@ static int xhci_configure_port(const int id, const int port_id) void *full_conf = NULL; struct usb_interface_desc *if_desc = NULL; struct usb_endpoint_desc *ep_desc = NULL; + int retval = 0; + // hint: 暂时只考虑对键盘的初始化 // 获取完整的config { struct usb_config_desc conf_desc = {0}; - xhci_get_config_desc(id, port_id, &conf_desc); + retval = xhci_get_config_desc(id, port_id, &conf_desc); + if (unlikely(retval != 0)) + return retval; + full_conf = kzalloc(conf_desc.total_len, 0); - xhci_get_config_desc_full(id, port_id, &conf_desc, full_conf); + if (unlikely(full_conf == NULL)) + return -ENOMEM; + + retval = xhci_get_config_desc_full(id, port_id, &conf_desc, full_conf); + if (unlikely(retval != 0)) + goto failed; } - xhci_get_interface_desc(full_conf, 0, &if_desc); + retval = xhci_get_interface_desc(full_conf, 0, &if_desc); + if (unlikely(retval != 0)) + goto failed; + if (if_desc->interface_class == USB_CLASS_HID) { // 由于暂时只支持键盘,因此把键盘的驱动也写在这里 // todo: 分离usb键盘驱动 - xhci_get_endpoint_desc(if_desc, 0, &ep_desc); - + retval = xhci_get_endpoint_desc(if_desc, 0, &ep_desc); + if (unlikely(retval != 0)) + goto failed; // kdebug("to set conf, val=%#010lx", ((struct usb_config_desc *)full_conf)->value); - xhci_set_configuration(id, port_id, ((struct usb_config_desc *)full_conf)->value); + retval = xhci_set_configuration(id, port_id, ((struct usb_config_desc *)full_conf)->value); + if (unlikely(retval != 0)) + goto failed; // kdebug("set conf ok"); - // todo: configure endpoint - xhci_configure_endpoint(id, port_id, ep_desc->endpoint_addr, USB_EP_INTERRUPT, ep_desc); - - xhci_hid_set_idle(id, port_id, if_desc); - - // 获取report desc - // todo: parse hid report + // configure endpoint + retval = xhci_configure_endpoint(id, port_id, ep_desc->endpoint_addr, USB_EP_INTERRUPT, ep_desc); + if (unlikely(retval != 0)) + goto failed; + retval = xhci_hid_set_idle(id, port_id, if_desc); + if (unlikely(retval != 0)) + goto failed; + + struct usb_hid_desc *hid_desc = NULL; + uint32_t hid_desc_len = 0; + // 获取hid desc + retval = xhci_get_hid_descriptor(id, port_id, full_conf, if_desc->interface_number, &hid_desc); + if (unlikely(retval != 0)) + goto failed; + + // 获取hid report + void *hid_report_data = kzalloc(hid_desc->report_desc_len, 0); + if (unlikely(hid_report_data == NULL)) + goto failed; + retval = + xhci_get_hid_report(id, port_id, if_desc->interface_number, hid_report_data, hid_desc->report_desc_len); + if (unlikely(retval != 0)) + { + kfree(hid_report_data); + goto failed; + } + + kdebug("to parse hid report"); + // todo: parse hid report + hid_parse_report(hid_report_data, hid_desc->report_desc_len); + kdebug("parse hid report done"); + kfree(hid_report_data); } + goto out; +failed:; + kerror("failed at xhci_configure_port, retval=%d", retval); +out:; kfree(full_conf); - return 0; + return retval; } /** * @brief 初始化xhci主机控制器的中断控制 @@ -1796,7 +1902,8 @@ static int xhci_hc_init_intr(int id) if (unlikely((int64_t)(retval) == -ENOMEM)) return -ENOMEM; xhci_hc[id].event_ring_table_vaddr = retval; - xhci_hc[id].current_event_ring_vaddr = xhci_hc[id].event_ring_vaddr; // 设置驱动程序要读取的下一个event ring trb的地址 + xhci_hc[id].current_event_ring_vaddr = + xhci_hc[id].event_ring_vaddr; // 设置驱动程序要读取的下一个event ring trb的地址 retval = 0; xhci_hc[id].current_event_ring_cycle = 1; @@ -1809,7 +1916,9 @@ static int xhci_hc_init_intr(int id) io_mfence(); xhci_write_intr_reg32(id, 0, XHCI_IR_TABLE_SIZE, 1); // 当前只有1个segment io_mfence(); - xhci_write_intr_reg64(id, 0, XHCI_IR_DEQUEUE, virt_2_phys(xhci_hc[id].current_event_ring_vaddr) | (1 << 3)); // 写入dequeue寄存器,并清除busy位(写1就会清除) + xhci_write_intr_reg64(id, 0, XHCI_IR_DEQUEUE, + virt_2_phys(xhci_hc[id].current_event_ring_vaddr) | + (1 << 3)); // 写入dequeue寄存器,并清除busy位(写1就会清除) io_mfence(); xhci_write_intr_reg64(id, 0, XHCI_IR_TABLE_ADDR, virt_2_phys(xhci_hc[id].event_ring_table_vaddr)); // 写入table地址 io_mfence(); @@ -1894,6 +2003,62 @@ static int xhci_send_command(int id, struct xhci_TRB_t *trb, const bool do_ring) return 0; } +/** + * @brief 获取接口的hid descriptor + * + * @param id 主机控制器号 + * @param port_id 端口号 + * @param full_conf 完整的cofig缓冲区 + * @param interface_number 接口号 + * @param ret_hid_desc 返回的指向hid描述符的指针 + * @return int 错误码 + */ +static int xhci_get_hid_descriptor(int id, int port_id, const void *full_conf, int interface_number, + struct usb_hid_desc **ret_hid_desc) +{ + if (unlikely(ret_hid_desc == NULL || full_conf == NULL)) + return -EINVAL; + kdebug("to get hid_descriptor."); + // 判断接口index是否合理 + if (interface_number >= ((struct usb_config_desc *)full_conf)->num_interfaces) + return -EINVAL; + uint32_t total_len = ((struct usb_config_desc *)full_conf)->total_len; + uint32_t pos = 0; + while (pos < total_len) + { + struct usb_hid_desc *ptr = (struct usb_hid_desc *)(full_conf + pos); + if (ptr->type != USB_DT_HID) + { + pos += ptr->len; + continue; + } + // 找到目标hid描述符 + *ret_hid_desc = ptr; + kdebug("Found hid descriptor for port:%d, if:%d, report_desc_len=%d", port_id, interface_number, + ptr->report_desc_len); + return 0; + } + + return -EINVAL; +} + +/** + * @brief 发送get_hid_descriptor请求,将hid + * + * @param id 主机控制器号 + * @param port_id 端口号 + * @param interface_number 接口号 + * @param ret_hid_report hid report要拷贝到的地址 + * @param hid_report_len hid report的长度 + * @return int 错误码 + */ +static int xhci_get_hid_report(int id, int port_id, int interface_number, void *ret_hid_report, uint32_t hid_report_len) +{ + int retval = xhci_get_desc(id, port_id, ret_hid_report, USB_DT_HID_REPORT, 0, interface_number, hid_report_len); + if (unlikely(retval != 0)) + kerror("xhci_get_hid_report failed: host_controller:%d, port:%d, interface %d", id, port_id, interface_number); + return retval; +} /** * @brief 初始化xhci控制器 * @@ -1909,7 +2074,10 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr) } spin_lock(&xhci_controller_init_lock); - kinfo("Initializing xhci host controller: bus=%#02x, device=%#02x, func=%#02x, VendorID=%#04x, irq_line=%d, irq_pin=%d", dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, dev_hdr->header.Vendor_ID, dev_hdr->Interrupt_Line, dev_hdr->Interrupt_PIN); + kinfo("Initializing xhci host controller: bus=%#02x, device=%#02x, func=%#02x, VendorID=%#04x, irq_line=%d, " + "irq_pin=%d", + dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, dev_hdr->header.Vendor_ID, + dev_hdr->Interrupt_Line, dev_hdr->Interrupt_PIN); io_mfence(); int cid = xhci_hc_find_available_id(); if (cid < 0) @@ -1930,7 +2098,8 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr) } io_mfence(); // 为当前控制器映射寄存器地址空间 - xhci_hc[cid].vbase = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + XHCI_MAPPING_OFFSET + 65536 * xhci_hc[cid].controller_id; + xhci_hc[cid].vbase = + SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + XHCI_MAPPING_OFFSET + 65536 * xhci_hc[cid].controller_id; // kdebug("dev_hdr->BAR0 & (~0xf)=%#018lx", dev_hdr->BAR0 & (~0xf)); mm_map_phys_addr(xhci_hc[cid].vbase, dev_hdr->BAR0 & (~0xf), 65536, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, true); io_mfence(); @@ -1975,7 +2144,8 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr) } // if it is a Panther Point device, make sure sockets are xHCI controlled. if (((pci_read_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0) & 0xffff) == 0x8086) && - (((pci_read_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0) >> 16) & 0xffff) == 0x1E31) && + (((pci_read_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0) >> 16) & 0xffff) == + 0x1E31) && ((pci_read_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 8) & 0xff) == 4)) { kdebug("Is a Panther Point device"); @@ -2082,6 +2252,7 @@ failed:; memset((void *)&xhci_hc[cid], 0, sizeof(struct xhci_host_controller_t)); failed_exceed_max:; - kerror("Failed to initialize controller: bus=%d, dev=%d, func=%d", dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func); + kerror("Failed to initialize controller: bus=%d, dev=%d, func=%d", dev_hdr->header.bus, dev_hdr->header.device, + dev_hdr->header.func); spin_unlock(&xhci_controller_init_lock); } \ No newline at end of file