Browse Source

新增usb hid report解析器 (#58)

* new: usb hid parser
login 2 years ago
parent
commit
39f11c5b4b

+ 2 - 1
.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": ""

+ 1 - 0
kernel/common/compiler_attributes.h

@@ -1,4 +1,5 @@
 #pragma once
+#include <common/stddef.h>
 
 // 当函数的返回值未被使用时,编译器抛出警告信息
 #define __must_check __attribute__((__warn_unused_result__))

+ 97 - 0
kernel/common/hid.h

@@ -0,0 +1,97 @@
+#pragma once
+#include <common/stddef.h>
+
+#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);

+ 1 - 1
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 "$@"

+ 19 - 0
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)
+

+ 526 - 0
kernel/driver/hid/hidparse.c

@@ -0,0 +1,526 @@
+#include "internal.h"
+#include <common/compiler.h>
+#include <common/glib.h>
+#include <common/hid.h>
+#include <common/printk.h>
+#include <common/string.h>
+#include <debug/bug.h>
+
+/*
+    参考文档: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;
+}

+ 1580 - 0
kernel/driver/hid/hidstrings.c

@@ -0,0 +1,1580 @@
+#include <common/hid.h>
+
+// 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",
+};

+ 37 - 0
kernel/driver/hid/internal.h

@@ -0,0 +1,37 @@
+#pragma once
+#include <common/hid.h>
+
+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];

+ 15 - 0
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)
+

+ 25 - 7
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驱动程序
  *

+ 264 - 93
kernel/driver/usb/xhci/xhci.c

@@ -1,14 +1,15 @@
 #include "xhci.h"
 #include "internal.h"
+#include <common/hid.h>
 #include <common/kprint.h>
-#include <debug/bug.h>
 #include <common/spinlock.h>
-#include <mm/mm.h>
-#include <mm/slab.h>
-#include <debug/traceback/traceback.h>
 #include <common/time.h>
-#include <exception/irq.h>
+#include <debug/bug.h>
+#include <debug/traceback/traceback.h>
 #include <driver/interrupt/apic/apic.h>
+#include <exception/irq.h>
+#include <mm/mm.h>
+#include <mm/slab.h>
 
 // 由于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);
-
-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,
+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,
 };
 
 /**
@@ -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);
+        struct usb_interface_desc *ptr = (struct usb_interface_desc *)(in_buf + pos);
+        if (ptr->type != USB_DT_INTERFACE)
+        {
+            pos += ptr->len;
+            continue;
+        }
+
+        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;
     }
-    // 返回结果
-    *if_desc = ptr;
 
-    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;
+    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);
 }