在usb设备的hid path中寻找给定的节点(存在问题,以后再解决) (#67)

This commit is contained in:
login 2022-10-23 20:38:48 +08:00 committed by GitHub
parent e56c10c7b6
commit 0385e0324e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 156 additions and 21 deletions

View File

@ -5,6 +5,73 @@
#define HID_MAX_REPORT 300 // 最大允许的hid report数目包括feature、input、output
#define HID_MAX_PATH_SIZE 16 // maximum depth for path
// 这部分请参考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
/**
* @brief hid的usage page列表
* <HID Usage Tables FOR Universal Serial Bus (USB)>
* usb.org下载
*/
enum HID_USAGE_PAGE_TYPES
{
HID_USAGE_PAGE_GEN_DESKTOP = 0x1,
HID_USAGE_PAGE_SIMU_CTRL, // simulation controls
HID_USAGE_PAGE_VR_CTRL, // vr controls page
HID_USAGE_PAGE_SPORT_CTRL, // sport controls
HID_USAGE_PAGE_GAME_CTRL, // game controls
HID_USAGE_PAGE_GEN_DEVICE_CTRL, // general device controls
HID_USAGE_PAGE_KBD_KPD, // keyboard/ keypad page
HID_USAGE_PAGE_LED, // LED
HID_USAGE_PAGE_BUTTON, // button page
HID_USAGE_PAGE_ORDINAL, // ordinal page
HID_USAGE_PAGE_TEL_DEVICE, // telephony device
HID_USAGE_PAGE_CONSUMER, // consumer page
HID_USAGE_PAGE_DIGITIZER, // digitizers page
HID_USAGE_PAGE_HAPTICS, // haptics page
HID_USAGE_PAGE_PHY_INPUT_DEVICE, // physical input device page
HID_USAGE_PAGE_UNICODE = 0x10, // unicode page
HID_USAGE_PAGE_EYE_HEAD_TRACKER = 0x12, // eye and head trackers page
HID_USAGE_PAGE_AUX_DISPLAY = 0x14, // auxiliary display page
HID_USAGE_PAGE_SENSORS = 0x20, // sensors page
HID_USAGE_PAGE_MEDICAL = 0x40, // medical instruments
HID_USAGE_PAGE_BRAILLE_DISPLAY, // barille display
HID_USAGE_PAGE_LIGHTNING_ILLU = 0x59, // lighting and illumination page
HID_USAGE_PAGE_MONITOR = 0x80, // monitor page
HID_USAGE_PAGE_MONITOR_ENUMERATED, // monitor enumerated page
HID_USAGE_PAGE_VESA_VIRT_CTRL, // VESA virtual controls page
HID_USAGE_PAGE_POWER = 0x84, // power page
HID_USAGE_PAGE_BATTERY_SYSTEM, // battery system page
HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c, // barcode scanner page
HID_USAGE_PAGE_SCALES, // scales page
HID_USAGE_PAGE_MAGNET_STRIPE_READER, // magnetic stript reader page
HID_USAGE_PAGE_CAMERA_CONTROL = 0x90, // camera control page
HID_USAGE_PAGE_ARCADE, // arcade page
HID_USAGE_PAGE_GAMING_DEVICE, // gaming device page
HID_USAGE_PAGE_FIDO_ALLIANCE = 0xf1d0, // FIDO alliance page
};
/**
* @brief usage type for HID_USAGE_PAGE_GEN_DESKTOP page
*
*/
enum USAGE_TYPE_GENDESK
{
HID_USAGE_GENDESK_UNDEF = 0, // undefined
HID_USAGE_GENDESK_POINTER,
HID_USAGE_GENDESK_MOUSE,
HID_USAGE_GENDESK_KEYBOARD = 0x6,
HID_USAGE_GENDESK_POINTER_X = 0x30,
HID_USAGE_GENDESK_POINTER_Y,
HID_USAGE_GENDESK_WHEEL = 0x38,
HID_USAGE_GENDESK_NOTHING = 0xff,
};
/**
* @brief hid path中的一个节点
*
@ -79,10 +146,8 @@ struct hid_parser
int cnt_objects; // report descriptor中的对象数目
int cnt_report; // report desc中的report数目
};
struct hid_usage_types_string
{
int value;
@ -92,8 +157,10 @@ struct hid_usage_types_string
struct hid_usage_pages_string
{
int value;
struct hid_usage_types_string * types;
const char * string;
struct hid_usage_types_string *types;
const char *string;
};
int hid_parse_report(const void *report_data, const int len);
bool hid_parse_find_object(const void *hid_report, const int report_size, struct hid_data_t *data);

View File

@ -44,21 +44,13 @@ static __always_inline const struct hid_usage_types_string *hid_get_usage_type(
#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;
return __space_overflow_str;
}
memset(__spaces_buf, ' ', 32);
@ -111,6 +103,7 @@ static __always_inline void __pop_usage_stack(struct hid_parser *parser)
/**
* @brief hid reportdata字段中
* todo:(qemu上面usage都是0xff)
*
* @param parser
* @param data
@ -345,7 +338,7 @@ static bool hid_parse(struct hid_parser *parser, struct hid_data_t *data)
break;
default:
printk("\n Found unknown item %#02X\n", parser->item & HID_ITEM_MASK);
return false;
return found;
}
}
return found;
@ -509,7 +502,7 @@ static int *__get_report_offset(struct hid_parser *parser, const uint8_t 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];
return &parser->offset_table[pos][2];
++pos;
}
// 在offset table中占用一个新的表项来存储这个report的offset
@ -524,3 +517,67 @@ static int *__get_report_offset(struct hid_parser *parser, const uint8_t report_
// 当offset table满了且未找到结果的时候返回NULL
return NULL;
}
static __always_inline bool __find_object(struct hid_parser *parser, struct hid_data_t *data)
{
kdebug("target_type=%d report_id=%d, offset=%d, size=%d", data->type, data->report_id, data->offset, data->size);
struct hid_data_t found_data = {0};
while (hid_parse(parser, &found_data))
{
kdebug("size=%d, type=%d, report_id=%d, u_page=%d, usage=%d", found_data.size, found_data.type,
found_data.report_id, found_data.path.node[0].u_page, found_data.path.node[0].usage);
// 按照路径完整匹配data
if ((data->path.size > 0) && (found_data.type == data->type) &&
(memcmp(found_data.path.node, data->path.node, data->path.size * sizeof(struct hid_node_t)) == 0))
{
goto found;
}
// 通过report id以及offset匹配成功
else if ((found_data.report_id == data->report_id) && (found_data.type == data->type) &&
(found_data.offset == data->offset))
{
goto found;
}
}
return false;
found:;
memcpy(data, &found_data, sizeof(struct hid_data_t));
data->report_count = parser->report_count;
return true;
}
/**
* @brief hid report中寻找参数data给定的节点数据data中
*
* @param hid_report hid report
* @param report_size report_data的大小
* @param data
* @return true
* @return false
*/
bool hid_parse_find_object(const void *hid_report, const int report_size, struct hid_data_t *data)
{
struct hid_parser parser = {0};
hid_reset_parser(&parser);
parser.report_desc = hid_report;
parser.report_desc_size = report_size;
// HID_PARSE_OUTPUT = false;
printk("\nFinding Coordinate value:");
if (__find_object(&parser, data))
{
printk(" size: %i (in bits)\n"
" offset: %i (in bits)\n"
" min: %i\n"
" max: %i\n"
" attrib: 0x%02X (input, output, or feature, etc.)\n",
data->size, data->offset, data->logical_min, data->logical_max, data->attribute);
return true;
}
else
{
printk(" Did not find Coordinate value.\n");
return false;
}
}

View File

@ -1863,9 +1863,20 @@ static int xhci_configure_port(const int id, const int port_id)
}
kdebug("to parse hid report");
// todo: parse hid report
hid_parse_report(hid_report_data, hid_desc->report_desc_len);
// todo:这里的parse有问题详见hid_parse函数的注释
// hid_parse_report(hid_report_data, hid_desc->report_desc_len);
kdebug("parse hid report done");
// kdebug("to find object from hid path");
// struct hid_data_t data = {0};
// data.type = HID_ITEM_INPUT;
// data.path.node[0].u_page = HID_USAGE_PAGE_GEN_DESKTOP;
// data.path.node[0].usage = 0xff;
// data.path.node[2].usage = USAGE_POINTER_Y; // to get the Y Coordinate, comment X above and uncomment this
// line data.path.node[2].usage = USAGE_POINTER_WHEEL; // to get the Wheel Coordinate, comment X above and
// uncomment this line
// data.path.size = 1;
// hid_parse_find_object(hid_report_data, hid_desc->report_desc_len, &data);
kfree(hid_report_data);
}
goto out;