hidparse.c 18 KB

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