hidparse.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. #include "internal.h"
  2. #include <common/compiler.h>
  3. #include <common/glib.h>
  4. #include <common/hid.h>
  5. #include <common/printk.h>
  6. #include <common/string.h>
  7. #include <debug/bug.h>
  8. /*
  9. 参考文档:https://www.usb.org/document-library/device-class-definition-hid-111
  10. 本文件参考了FYSOS: https://github.com/fysnet/FYSOS.git
  11. */
  12. static bool HID_PARSE_OUTPUT = true; // 是否输出解析信息
  13. static char __tmp_usage_page_str[128] = {0};
  14. static void hid_reset_parser(struct hid_parser *parser);
  15. static const char *hid_get_usage_page_str(const int u_page);
  16. static const char *hid_get_usage_type_str(const int page, const int type);
  17. static const char *hid_get_collection_str(const int value);
  18. static int *__get_report_offset(struct hid_parser *parser, const uint8_t report_id, const uint8_t report_type);
  19. static __always_inline const struct hid_usage_pages_string *hid_get_usage_page(const int u_page);
  20. static __always_inline const struct hid_usage_types_string *hid_get_usage_type(
  21. const struct hid_usage_pages_string *upage, const int type);
  22. // hid item的低2位为size
  23. #define HID_SIZE_MASK 0x3
  24. // 高6bit为item内容
  25. #define HID_ITEM_MASK 0xFC
  26. #define HID_ITEM_UPAGE 0x04 // usage page
  27. #define HID_ITEM_USAGE 0x08 // local item
  28. #define HID_ITEM_LOG_MIN 0x14
  29. #define HID_ITEM_USAGE_MIN 0x18 // local item
  30. #define HID_ITEM_LOG_MAX 0x24
  31. #define HID_ITEM_USAGE_MAX 0x28 // local item
  32. #define HID_ITEM_PHY_MIN 0x34
  33. #define HID_ITEM_PHY_MAX 0x44
  34. #define HID_ITEM_UNIT_EXP 0x54
  35. #define HID_ITEM_UNIT 0x64
  36. #define HID_ITEM_REP_SIZE 0x74
  37. #define HID_ITEM_STRING 0x78 // local item?
  38. #define HID_ITEM_REP_ID 0x84
  39. #define HID_ITEM_REP_COUNT 0x94
  40. static char __spaces_buf[33];
  41. char *__spaces(uint8_t cnt)
  42. {
  43. static char __space_overflow_str[] = "**";
  44. if (cnt > 32)
  45. {
  46. return __space_overflow_str;
  47. }
  48. memset(__spaces_buf, ' ', 32);
  49. __spaces_buf[cnt] = '\0';
  50. return __spaces_buf;
  51. }
  52. static __always_inline uint32_t __format_value(uint32_t value, uint8_t size)
  53. {
  54. switch (size)
  55. {
  56. case 1:
  57. value = (uint32_t)(uint8_t)value;
  58. break;
  59. case 2:
  60. value = (uint32_t)(uint16_t)value;
  61. break;
  62. }
  63. return value;
  64. }
  65. /**
  66. * @brief 重置parser
  67. *
  68. * @param parser 解析器
  69. * @return int 状态码
  70. */
  71. static void hid_reset_parser(struct hid_parser *parser)
  72. {
  73. memset(parser, 0, sizeof(struct hid_parser));
  74. parser->data.report_id = 1; // we must give it a non-zero value or the parser doesn't work
  75. }
  76. /**
  77. * @brief 从usage_stack中弹出第一个元素
  78. *
  79. * @param parser 解析器
  80. * @return __always_inline
  81. */
  82. static __always_inline void __pop_usage_stack(struct hid_parser *parser)
  83. {
  84. if (parser->usage_size > 0)
  85. {
  86. for (int js = 0; js < parser->usage_size - 1; ++js)
  87. c_memmove(&parser->usage_table[js], &parser->usage_table[js + 1], sizeof(struct hid_node_t));
  88. --parser->usage_size;
  89. }
  90. }
  91. /**
  92. * @brief 解析hid report,并获取下一个数据到data字段中
  93. * todo:(不知道为什么,在qemu上面,发现键盘的usage都是0xff)
  94. *
  95. * @param parser 解析器
  96. * @param data 返回的数据
  97. * @return true 解析成功
  98. * @return false 解析失败
  99. */
  100. static bool hid_parse(struct hid_parser *parser, struct hid_data_t *data)
  101. {
  102. bool found = false;
  103. static uint8_t space_cnt = 0;
  104. static bool did_collection = false;
  105. static int item_size[4] = {0, 1, 2, 4};
  106. // 循环解析
  107. while (!found && (parser->pos < parser->report_desc_size))
  108. {
  109. // 当前parse过程还没有解析到report
  110. if (parser->count == 0)
  111. {
  112. // 打印当前 report_data 的值
  113. if (HID_PARSE_OUTPUT)
  114. printk("\n %02X ", parser->report_desc[parser->pos]);
  115. // 获取到report size
  116. parser->item = parser->report_desc[parser->pos++];
  117. parser->value = 0;
  118. // 拷贝report的数据
  119. memcpy(&parser->value, &parser->report_desc[parser->pos], item_size[parser->item & HID_SIZE_MASK]);
  120. if (HID_PARSE_OUTPUT)
  121. {
  122. for (int i = 0; i < 4; ++i)
  123. {
  124. if (i < item_size[parser->item & HID_SIZE_MASK])
  125. printk("%02X ", parser->report_desc[parser->pos + i]);
  126. else
  127. printk(" ");
  128. }
  129. }
  130. // 将指针指向下一个item
  131. parser->pos += item_size[parser->item & HID_SIZE_MASK];
  132. }
  133. switch (parser->item & HID_ITEM_MASK)
  134. {
  135. case HID_ITEM_UPAGE:
  136. // 拷贝upage
  137. parser->u_page = (int)parser->value;
  138. if (HID_PARSE_OUTPUT)
  139. printk("%sUsage Page (%s)", __spaces(space_cnt), hid_get_usage_page_str(parser->u_page));
  140. // 拷贝到 usage table。由于这是一个USAGE entry,因此不增加usage_size(以便后面覆盖它)
  141. parser->usage_table[parser->usage_size].u_page = parser->u_page;
  142. parser->usage_table[parser->usage_size].usage = 0xff;
  143. break;
  144. case HID_ITEM_USAGE:
  145. // 拷贝upage到usage table中
  146. if ((parser->item & HID_SIZE_MASK) > 2) // item大小为32字节
  147. parser->usage_table[parser->usage_size].u_page = (int)(parser->value >> 16);
  148. else
  149. parser->usage_table[parser->usage_size].u_page = parser->u_page;
  150. if (HID_PARSE_OUTPUT)
  151. printk("%sUsage (%s)", __spaces(space_cnt),
  152. hid_get_usage_type_str(parser->u_page, parser->value & 0xffff));
  153. ++parser->usage_size;
  154. break;
  155. case HID_ITEM_USAGE_MIN:
  156. // todo: 设置usage min
  157. if (HID_PARSE_OUTPUT)
  158. printk("%sUsage min (%i=%s)", __spaces(space_cnt), parser->value,
  159. hid_get_usage_type_str(parser->u_page, parser->value));
  160. break;
  161. case HID_ITEM_USAGE_MAX:
  162. // todo: 设置usage max
  163. if (HID_PARSE_OUTPUT)
  164. printk("%sUsage max (%i=%s)", __spaces(space_cnt), parser->value,
  165. hid_get_usage_type_str(parser->u_page, parser->value));
  166. break;
  167. case HID_ITEM_COLLECTION:
  168. // 从usage table中取出第一个u_page和usage,并且将他们存储在parser->data.path
  169. parser->data.path.node[parser->data.path.size].u_page = parser->usage_table[0].u_page;
  170. parser->data.path.node[parser->data.path.size].usage = parser->usage_table[0].usage;
  171. ++parser->data.path.size;
  172. // 由于上面取出了元素,因此将队列往前移动1个位置
  173. __pop_usage_stack(parser);
  174. // 获取index(如果有的话)???
  175. if (parser->value >= 0x80)
  176. {
  177. kdebug("parser->value > 0x80");
  178. parser->data.path.node[parser->data.path.size].u_page = 0xff;
  179. parser->data.path.node[parser->data.path.size].usage = parser->value & 0x7f;
  180. ++parser->data.path.size;
  181. }
  182. if (HID_PARSE_OUTPUT)
  183. {
  184. printk("%sCollection (%s)", __spaces(space_cnt), hid_get_collection_str(parser->value));
  185. space_cnt += 2;
  186. }
  187. break;
  188. case HID_ITEM_END_COLLECTION:
  189. --parser->data.path.size; // 为什么要--?????
  190. // 删除多余的(未识别的)node
  191. if (parser->data.path.node[parser->data.path.size].u_page == 0xff)
  192. --parser->data.path.size;
  193. if (HID_PARSE_OUTPUT)
  194. {
  195. if (space_cnt >= 2)
  196. space_cnt -= 2;
  197. printk("%sEnd Collection", __spaces(space_cnt));
  198. }
  199. break;
  200. case HID_ITEM_FEATURE:
  201. case HID_ITEM_INPUT:
  202. case HID_ITEM_OUTPUT:
  203. // 找到了一个对象
  204. found = true;
  205. // 增加对象计数器
  206. ++parser->cnt_objects;
  207. // 更新local items的计数
  208. if (parser->count == 0)
  209. parser->count = parser->report_count;
  210. // 从usage_table获取u_page和usage,将他们存储到parser.data.path
  211. parser->data.path.node[parser->data.path.size].u_page = parser->usage_table[0].u_page;
  212. parser->data.path.node[parser->data.path.size].usage = parser->usage_table[0].usage;
  213. ++parser->data.path.size;
  214. // 从usage table中弹出刚刚那个node
  215. __pop_usage_stack(parser);
  216. // 拷贝数据到data
  217. parser->data.type = (uint8_t)(parser->item & HID_ITEM_MASK);
  218. parser->data.attribute = (uint8_t)parser->value;
  219. int *offset_ptr =
  220. __get_report_offset(parser, parser->data.report_id, (uint8_t)(parser->item & HID_ITEM_MASK));
  221. if (unlikely(offset_ptr == NULL))
  222. {
  223. BUG_ON(1);
  224. return false;
  225. }
  226. parser->data.offset = *offset_ptr;
  227. // 获取pData中的对象
  228. memcpy(data, &parser->data, sizeof(struct hid_data_t));
  229. // 增加report offset
  230. *offset_ptr = (*offset_ptr) + parser->data.size;
  231. // 从path中删除最后一个节点(刚刚弹出的这个节点)
  232. --parser->data.path.size;
  233. // 减少local items计数
  234. if (parser->count > 0)
  235. --parser->count;
  236. if (!did_collection)
  237. {
  238. if (HID_PARSE_OUTPUT)
  239. {
  240. if ((parser->item & HID_ITEM_MASK) == HID_ITEM_FEATURE)
  241. printk("%sFeature ", __spaces(space_cnt));
  242. else if ((parser->item & HID_ITEM_MASK) == HID_ITEM_INPUT)
  243. printk("%sInput ", __spaces(space_cnt));
  244. else if ((parser->item & HID_ITEM_MASK) == HID_ITEM_OUTPUT)
  245. printk("%sOutut ", __spaces(space_cnt));
  246. printk("(%s,%s,%s" /* ",%s,%s,%s,%s" */ ")", !(parser->value & (1 << 0)) ? "Data" : "Constant",
  247. !(parser->value & (1 << 1)) ? "Array" : "Variable",
  248. !(parser->value & (1 << 2)) ? "Absolute" : "Relative" /*,
  249. !(parser->value & (1<<3)) ? "No Wrap" : "Wrap",
  250. !(parser->value & (1<<4)) ? "Linear" : "Non Linear",
  251. !(parser->value & (1<<5)) ? "Preferred State" : "No Preferred",
  252. !(parser->value & (1<<6)) ? "No Null" : "Null State",
  253. //!(parser->value & (1<<8)) ? "Bit Fueld" : "Buffered Bytes"
  254. */
  255. );
  256. }
  257. did_collection = true;
  258. }
  259. break;
  260. case HID_ITEM_REP_ID: // 当前item表示report id
  261. parser->data.report_id = (uint8_t)parser->value;
  262. if (HID_PARSE_OUTPUT)
  263. printk("%sReport ID: %i", __spaces(space_cnt), parser->data.report_id);
  264. break;
  265. case HID_ITEM_REP_SIZE: // 当前item表示report size
  266. parser->data.size = parser->value;
  267. if (HID_PARSE_OUTPUT)
  268. printk("%sReport size (%i)", __spaces(space_cnt), parser->data.size);
  269. break;
  270. case HID_ITEM_REP_COUNT:
  271. parser->report_count = parser->value;
  272. if (HID_PARSE_OUTPUT)
  273. printk("%sReport count (%i)", __spaces(space_cnt), parser->report_count);
  274. break;
  275. case HID_ITEM_UNIT_EXP:
  276. parser->data.unit_exp = (int8_t)parser->value;
  277. if (parser->data.unit_exp > 7)
  278. parser->data.unit_exp |= 0xf0;
  279. if (HID_PARSE_OUTPUT)
  280. printk("%sUnit Exp (%i)", __spaces(space_cnt), parser->data.unit_exp);
  281. break;
  282. case HID_ITEM_UNIT:
  283. parser->data.unit = parser->value;
  284. if (HID_PARSE_OUTPUT)
  285. printk("%sUnit (%i)", __spaces(space_cnt), parser->data.unit);
  286. break;
  287. case HID_ITEM_LOG_MIN: // logical min
  288. parser->data.logical_min = __format_value(parser->value, item_size[parser->item & HID_SIZE_MASK]);
  289. if (HID_PARSE_OUTPUT)
  290. printk("%sLogical Min (%i)", __spaces(space_cnt), parser->data.logical_min);
  291. break;
  292. case HID_ITEM_LOG_MAX:
  293. parser->data.logical_max = __format_value(parser->value, item_size[parser->item & HID_SIZE_MASK]);
  294. if (HID_PARSE_OUTPUT)
  295. printk("%sLogical Max (%i)", __spaces(space_cnt), parser->data.logical_max);
  296. break;
  297. case HID_ITEM_PHY_MIN:
  298. parser->data.phys_min = __format_value(parser->value, item_size[parser->item & HID_SIZE_MASK]);
  299. if (HID_PARSE_OUTPUT)
  300. printk("%Physical Min (%i)", __spaces(space_cnt), parser->data.phys_min);
  301. break;
  302. case HID_ITEM_PHY_MAX:
  303. parser->data.phys_max = __format_value(parser->value, item_size[parser->item & HID_SIZE_MASK]);
  304. if (HID_PARSE_OUTPUT)
  305. printk("%Physical Max (%i)", __spaces(space_cnt), parser->data.phys_max);
  306. break;
  307. default:
  308. printk("\n Found unknown item %#02X\n", parser->item & HID_ITEM_MASK);
  309. return found;
  310. }
  311. }
  312. return found;
  313. }
  314. /**
  315. * @brief 解析hid report的数据
  316. *
  317. * @param report_data 从usb hid设备获取到hid report
  318. * @param len report_data的大小(字节)
  319. * @return int错误码
  320. */
  321. int hid_parse_report(const void *report_data, const int len)
  322. {
  323. struct hid_parser parser = {0};
  324. struct hid_data_t data;
  325. hid_reset_parser(&parser);
  326. parser.report_desc = (const uint8_t *)report_data;
  327. parser.report_desc_size = len;
  328. while (hid_parse(&parser, &data))
  329. ;
  330. return 0;
  331. }
  332. /**
  333. * @brief 根据usage page的id获取usage page string结构体.当u_page不属于任何已知的id时,返回NULL
  334. *
  335. * @param u_page usage page id
  336. * @return const struct hid_usage_pages_string * usage page string结构体
  337. */
  338. static __always_inline const struct hid_usage_pages_string *hid_get_usage_page(const int u_page)
  339. {
  340. int i = 0;
  341. while ((hid_usage_page_strings[i].value < u_page) && (hid_usage_page_strings[i].value < 0xffff))
  342. ++i;
  343. if ((hid_usage_page_strings[i].value != u_page) || (hid_usage_page_strings[i].value == 0xffff))
  344. return NULL;
  345. else
  346. return &hid_usage_page_strings[i];
  347. }
  348. /**
  349. * @brief 从指定的upage获取指定类型的usage type结构体。当不存在时,返回NULL
  350. *
  351. * @param upage 指定的upage
  352. * @param type usage的类型
  353. * @return const struct hid_usage_types_string * 目标usage type结构体。
  354. */
  355. static __always_inline const struct hid_usage_types_string *hid_get_usage_type(
  356. const struct hid_usage_pages_string *upage, const int type)
  357. {
  358. if (unlikely(upage == NULL || upage->types == NULL))
  359. {
  360. BUG_ON(1);
  361. return NULL;
  362. }
  363. struct hid_usage_types_string *types = upage->types;
  364. int i = 0;
  365. while ((types[i].value < type) && (types[i].value != 0xffff))
  366. ++i;
  367. if ((types[i].value != type) || (types[i].value == 0xffff))
  368. return NULL;
  369. return &types[i];
  370. }
  371. /**
  372. * @brief 获取usage page的名称
  373. *
  374. * @param u_page usage page的id
  375. * @return const char* usage page的字符串
  376. */
  377. static const char *hid_get_usage_page_str(const int u_page)
  378. {
  379. const struct hid_usage_pages_string *upage = hid_get_usage_page(u_page);
  380. if (unlikely(upage == NULL))
  381. {
  382. sprintk(__tmp_usage_page_str, "Unknown Usage Page: %#04x", u_page);
  383. return __tmp_usage_page_str;
  384. }
  385. return upage->string;
  386. }
  387. /**
  388. * @brief 打印usage page的指定类型的usage
  389. *
  390. * @param page usage page id
  391. * @param type usage的类型
  392. * @return const char*
  393. */
  394. static const char *hid_get_usage_type_str(const int page, const int type)
  395. {
  396. const struct hid_usage_pages_string *upage = hid_get_usage_page(page);
  397. if (unlikely(upage == NULL))
  398. {
  399. sprintk(__tmp_usage_page_str, "Unknown Usage Page: %#04x", page);
  400. return __tmp_usage_page_str;
  401. }
  402. // button press, ordinal, or UTC
  403. if (page == 0x0009)
  404. {
  405. sprintk(__tmp_usage_page_str, "Button number %i", type);
  406. return __tmp_usage_page_str;
  407. }
  408. else if (page == 0x000a)
  409. {
  410. sprintk(__tmp_usage_page_str, "Ordinal %i", type);
  411. return __tmp_usage_page_str;
  412. }
  413. else if (page == 0x0010)
  414. {
  415. sprintk(__tmp_usage_page_str, "UTC %#04X", type);
  416. return __tmp_usage_page_str;
  417. }
  418. const struct hid_usage_types_string *usage_type = hid_get_usage_type(upage, type);
  419. if (unlikely(usage_type == NULL))
  420. {
  421. sprintk(__tmp_usage_page_str, "Usage Page %s, with Unknown Type: %#04X", upage->string, type);
  422. return __tmp_usage_page_str;
  423. }
  424. return usage_type->string;
  425. }
  426. /**
  427. * @brief 输出colection字符串
  428. *
  429. * @param value collection的值
  430. * @return const char*
  431. */
  432. static const char *hid_get_collection_str(const int value)
  433. {
  434. if (value <= 0x06)
  435. return hid_collection_str[value];
  436. else if (value <= 0x7f)
  437. return "Reserved";
  438. else if (value <= 0xff)
  439. return "Vendor-defined";
  440. else
  441. return "Error in get_collection_str(): value > 0xff";
  442. }
  443. /**
  444. * @brief 从parser的offset table中,根据report_id和report_type,获取表中指向offset字段的指针
  445. *
  446. * @param parser 解析器
  447. * @param report_id report_id
  448. * @param report_type report类型
  449. * @return int* 指向offset字段的指针
  450. */
  451. static int *__get_report_offset(struct hid_parser *parser, const uint8_t report_id, const uint8_t report_type)
  452. {
  453. int pos = 0;
  454. // 尝试从已有的report中获取
  455. while ((pos < HID_MAX_REPORT) && (parser->offset_table[pos][0] != 0)) // 当offset的id不为0时
  456. {
  457. if ((parser->offset_table[pos][0] == report_id) && (parser->offset_table[pos][1] == report_type))
  458. return &parser->offset_table[pos][2];
  459. ++pos;
  460. }
  461. // 在offset table中占用一个新的表项来存储这个report的offset
  462. if (pos < HID_MAX_REPORT)
  463. {
  464. ++parser->cnt_report;
  465. parser->offset_table[pos][0] = report_id;
  466. parser->offset_table[pos][1] = report_type;
  467. parser->offset_table[pos][2] = 0;
  468. return &parser->offset_table[pos][2];
  469. }
  470. // 当offset table满了,且未找到结果的时候,返回NULL
  471. return NULL;
  472. }
  473. static __always_inline bool __find_object(struct hid_parser *parser, struct hid_data_t *data)
  474. {
  475. kdebug("target_type=%d report_id=%d, offset=%d, size=%d", data->type, data->report_id, data->offset, data->size);
  476. struct hid_data_t found_data = {0};
  477. while (hid_parse(parser, &found_data))
  478. {
  479. kdebug("size=%d, type=%d, report_id=%d, u_page=%d, usage=%d", found_data.size, found_data.type,
  480. found_data.report_id, found_data.path.node[0].u_page, found_data.path.node[0].usage);
  481. // 按照路径完整匹配data
  482. if ((data->path.size > 0) && (found_data.type == data->type) &&
  483. (memcmp(found_data.path.node, data->path.node, data->path.size * sizeof(struct hid_node_t)) == 0))
  484. {
  485. goto found;
  486. }
  487. // 通过report id以及offset匹配成功
  488. else if ((found_data.report_id == data->report_id) && (found_data.type == data->type) &&
  489. (found_data.offset == data->offset))
  490. {
  491. goto found;
  492. }
  493. }
  494. return false;
  495. found:;
  496. memcpy(data, &found_data, sizeof(struct hid_data_t));
  497. data->report_count = parser->report_count;
  498. return true;
  499. }
  500. /**
  501. * @brief 在hid report中寻找参数data给定的节点数据,并将结果写入到data中
  502. *
  503. * @param hid_report hid report 数据
  504. * @param report_size report_data的大小(字节)
  505. * @param data 要寻找的节点数据。
  506. * @return true 找到指定的节点
  507. * @return false 未找到指定的节点
  508. */
  509. bool hid_parse_find_object(const void *hid_report, const int report_size, struct hid_data_t *data)
  510. {
  511. struct hid_parser parser = {0};
  512. hid_reset_parser(&parser);
  513. parser.report_desc = hid_report;
  514. parser.report_desc_size = report_size;
  515. // HID_PARSE_OUTPUT = false;
  516. printk("\nFinding Coordinate value:");
  517. if (__find_object(&parser, data))
  518. {
  519. printk(" size: %i (in bits)\n"
  520. " offset: %i (in bits)\n"
  521. " min: %i\n"
  522. " max: %i\n"
  523. " attrib: 0x%02X (input, output, or feature, etc.)\n",
  524. data->size, data->offset, data->logical_min, data->logical_max, data->attribute);
  525. return true;
  526. }
  527. else
  528. {
  529. printk(" Did not find Coordinate value.\n");
  530. return false;
  531. }
  532. }