esp_hid_common.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. // Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <string.h>
  14. #include "esp_log.h"
  15. #include "esp_err.h"
  16. #include "esp_hid_common.h"
  17. #if (CONFIG_GATTS_ENABLE || CONFIG_GATTC_ENABLE)
  18. #include "esp_gatt_defs.h"
  19. #endif
  20. static const char *TAG = "hid_parser";
  21. typedef struct {
  22. uint16_t appearance;
  23. uint8_t usage_mask;
  24. uint8_t reports_len;
  25. esp_hid_report_item_t reports[64];
  26. } temp_hid_report_map_t;
  27. typedef struct {
  28. uint8_t cmd;
  29. uint8_t len;
  30. union {
  31. uint32_t value;
  32. uint8_t data[4];
  33. };
  34. } hid_report_cmd_t;
  35. typedef struct {
  36. uint16_t usage_page;
  37. uint16_t usage;
  38. uint16_t inner_usage_page;
  39. uint16_t inner_usage;
  40. uint8_t report_id;
  41. uint16_t input_len;
  42. uint16_t output_len;
  43. uint16_t feature_len;
  44. } hid_report_params_t;
  45. typedef enum {
  46. PARSE_WAIT_USAGE_PAGE, PARSE_WAIT_USAGE, PARSE_WAIT_COLLECTION_APPLICATION, PARSE_WAIT_END_COLLECTION
  47. } s_parse_step_t;
  48. static s_parse_step_t s_parse_step = PARSE_WAIT_USAGE_PAGE;
  49. static uint8_t s_collection_depth = 0;
  50. static hid_report_params_t s_report_params = {0,};
  51. static uint16_t s_report_size = 0;
  52. static uint16_t s_report_count = 0;
  53. static bool s_new_map = false;
  54. static temp_hid_report_map_t *s_temp_hid_report_map;
  55. static int add_report(temp_hid_report_map_t *map, esp_hid_report_item_t *item)
  56. {
  57. if (map->reports_len >= 64) {
  58. ESP_LOGE(TAG, "reports overflow");
  59. return -1;
  60. }
  61. memcpy(&(map->reports[map->reports_len]), item, sizeof(esp_hid_report_item_t));
  62. map->reports_len++;
  63. return 0;
  64. }
  65. static int handle_report(hid_report_params_t *report, bool first)
  66. {
  67. if (s_temp_hid_report_map == NULL) {
  68. s_temp_hid_report_map = (temp_hid_report_map_t *)calloc(1, sizeof(temp_hid_report_map_t));
  69. if (s_temp_hid_report_map == NULL) {
  70. ESP_LOGE(TAG, "malloc failed");
  71. return -1;
  72. }
  73. }
  74. temp_hid_report_map_t *map = s_temp_hid_report_map;
  75. if (first) {
  76. memset(map, 0, sizeof(temp_hid_report_map_t));
  77. }
  78. if (report->usage_page == HID_USAGE_PAGE_GENERIC_DESKTOP && report->usage == HID_USAGE_KEYBOARD) {
  79. //Keyboard
  80. map->usage_mask |= ESP_HID_USAGE_KEYBOARD;
  81. if (report->input_len > 0) {
  82. esp_hid_report_item_t item = {
  83. .usage = ESP_HID_USAGE_KEYBOARD,
  84. .report_id = report->report_id,
  85. .report_type = ESP_HID_REPORT_TYPE_INPUT,
  86. .protocol_mode = ESP_HID_PROTOCOL_MODE_REPORT,
  87. .value_len = report->input_len / 8,
  88. };
  89. if (add_report(map, &item) != 0) {
  90. return -1;
  91. }
  92. item.protocol_mode = ESP_HID_PROTOCOL_MODE_BOOT;
  93. item.value_len = 8;
  94. if (add_report(map, &item) != 0) {
  95. return -1;
  96. }
  97. }
  98. if (report->output_len > 0) {
  99. esp_hid_report_item_t item = {
  100. .usage = ESP_HID_USAGE_KEYBOARD,
  101. .report_id = report->report_id,
  102. .report_type = ESP_HID_REPORT_TYPE_OUTPUT,
  103. .protocol_mode = ESP_HID_PROTOCOL_MODE_REPORT,
  104. .value_len = report->output_len / 8,
  105. };
  106. if (add_report(map, &item) != 0) {
  107. return -1;
  108. }
  109. item.protocol_mode = ESP_HID_PROTOCOL_MODE_BOOT;
  110. item.value_len = 1;
  111. if (add_report(map, &item) != 0) {
  112. return -1;
  113. }
  114. }
  115. } else if (report->usage_page == HID_USAGE_PAGE_GENERIC_DESKTOP && report->usage == HID_USAGE_MOUSE) {
  116. //Mouse
  117. map->usage_mask |= ESP_HID_USAGE_MOUSE;
  118. if (report->input_len > 0) {
  119. esp_hid_report_item_t item = {
  120. .usage = ESP_HID_USAGE_MOUSE,
  121. .report_id = report->report_id,
  122. .report_type = ESP_HID_REPORT_TYPE_INPUT,
  123. .protocol_mode = ESP_HID_PROTOCOL_MODE_REPORT,
  124. .value_len = report->input_len / 8,
  125. };
  126. if (add_report(map, &item) != 0) {
  127. return -1;
  128. }
  129. item.protocol_mode = ESP_HID_PROTOCOL_MODE_BOOT;
  130. item.value_len = 3;
  131. if (add_report(map, &item) != 0) {
  132. return -1;
  133. }
  134. }
  135. } else {
  136. esp_hid_usage_t cusage = ESP_HID_USAGE_GENERIC;
  137. if (report->usage_page == HID_USAGE_PAGE_GENERIC_DESKTOP) {
  138. if (report->usage == HID_USAGE_JOYSTICK) {
  139. //Joystick
  140. map->usage_mask |= ESP_HID_USAGE_JOYSTICK;
  141. cusage = ESP_HID_USAGE_JOYSTICK;
  142. } else if (report->usage == HID_USAGE_GAMEPAD) {
  143. //Gamepad
  144. map->usage_mask |= ESP_HID_USAGE_GAMEPAD;
  145. cusage = ESP_HID_USAGE_GAMEPAD;
  146. }
  147. } else if (report->usage_page == HID_USAGE_PAGE_CONSUMER_DEVICE && report->usage == HID_USAGE_CONSUMER_CONTROL) {
  148. //Consumer Control
  149. map->usage_mask |= ESP_HID_USAGE_CCONTROL;
  150. cusage = ESP_HID_USAGE_CCONTROL;
  151. } else if (report->usage_page >= 0xFF) {
  152. //Vendor
  153. map->usage_mask |= ESP_HID_USAGE_VENDOR;
  154. cusage = ESP_HID_USAGE_VENDOR;
  155. }
  156. //Generic
  157. esp_hid_report_item_t item = {
  158. .usage = cusage,
  159. .report_id = report->report_id,
  160. .report_type = ESP_HID_REPORT_TYPE_INPUT,
  161. .protocol_mode = ESP_HID_PROTOCOL_MODE_REPORT,
  162. .value_len = report->input_len / 8,
  163. };
  164. if (report->input_len > 0) {
  165. if (add_report(map, &item) != 0) {
  166. return -1;
  167. }
  168. }
  169. if (report->output_len > 0) {
  170. item.report_type = ESP_HID_REPORT_TYPE_OUTPUT;
  171. item.value_len = report->output_len / 8;
  172. if (add_report(map, &item) != 0) {
  173. return -1;
  174. }
  175. }
  176. if (report->feature_len > 0) {
  177. item.report_type = ESP_HID_REPORT_TYPE_FEATURE;
  178. item.value_len = report->feature_len / 8;
  179. if (add_report(map, &item) != 0) {
  180. return -1;
  181. }
  182. }
  183. }
  184. return 0;
  185. }
  186. static int parse_cmd(const uint8_t *data, size_t len, size_t index, hid_report_cmd_t **out)
  187. {
  188. if (index == len) {
  189. return 0;
  190. }
  191. hid_report_cmd_t *cmd = (hid_report_cmd_t *)malloc(sizeof(hid_report_cmd_t));
  192. if (cmd == NULL) {
  193. return -1;
  194. }
  195. const uint8_t *dp = data + index;
  196. cmd->cmd = *dp & 0xFC;
  197. cmd->len = *dp & 0x03;
  198. cmd->value = 0;
  199. if (cmd->len == 3) {
  200. cmd->len = 4;
  201. }
  202. if ((len - index - 1) < cmd->len) {
  203. ESP_LOGE(TAG, "not enough bytes! cmd: 0x%02x, len: %u, index: %u", cmd->cmd, cmd->len, index);
  204. free(cmd);
  205. return -1;
  206. }
  207. memcpy(cmd->data, dp + 1, cmd->len);
  208. *out = cmd;
  209. return cmd->len + 1;
  210. }
  211. static int handle_cmd(hid_report_cmd_t *cmd)
  212. {
  213. switch (s_parse_step) {
  214. case PARSE_WAIT_USAGE_PAGE: {
  215. if (cmd->cmd != HID_RM_USAGE_PAGE) {
  216. ESP_LOGE(TAG, "expected USAGE_PAGE, but got 0x%02x", cmd->cmd);
  217. return -1;
  218. }
  219. s_report_size = 0;
  220. s_report_count = 0;
  221. memset(&s_report_params, 0, sizeof(hid_report_params_t));
  222. s_report_params.usage_page = cmd->value;
  223. s_parse_step = PARSE_WAIT_USAGE;
  224. break;
  225. }
  226. case PARSE_WAIT_USAGE: {
  227. if (cmd->cmd != HID_RM_USAGE) {
  228. ESP_LOGE(TAG, "expected USAGE, but got 0x%02x", cmd->cmd);
  229. s_parse_step = PARSE_WAIT_USAGE_PAGE;
  230. return -1;
  231. }
  232. s_report_params.usage = cmd->value;
  233. s_parse_step = PARSE_WAIT_COLLECTION_APPLICATION;
  234. break;
  235. }
  236. case PARSE_WAIT_COLLECTION_APPLICATION: {
  237. if (cmd->cmd != HID_RM_COLLECTION) {
  238. ESP_LOGE(TAG, "expected COLLECTION, but got 0x%02x", cmd->cmd);
  239. s_parse_step = PARSE_WAIT_USAGE_PAGE;
  240. return -1;
  241. }
  242. if (cmd->value != 1) {
  243. ESP_LOGE(TAG, "expected APPLICATION, but got 0x%02x", cmd->value);
  244. s_parse_step = PARSE_WAIT_USAGE_PAGE;
  245. return -1;
  246. }
  247. s_report_params.report_id = 0;
  248. s_collection_depth = 1;
  249. s_parse_step = PARSE_WAIT_END_COLLECTION;
  250. break;
  251. }
  252. case PARSE_WAIT_END_COLLECTION: {
  253. if (cmd->cmd == HID_RM_REPORT_ID) {
  254. if (s_report_params.report_id && s_report_params.report_id != cmd->value) {
  255. //report id changed mid collection
  256. if (s_report_params.input_len & 0x7) {
  257. ESP_LOGE(TAG, "ERROR: INPUT report does not amount to full bytes! %d (%d)", s_report_params.input_len, s_report_params.input_len & 0x7);
  258. } else if (s_report_params.output_len & 0x7) {
  259. ESP_LOGE(TAG, "ERROR: OUTPUT report does not amount to full bytes! %d (%d)", s_report_params.output_len, s_report_params.output_len & 0x7);
  260. } else if (s_report_params.feature_len & 0x7) {
  261. ESP_LOGE(TAG, "ERROR: FEATURE report does not amount to full bytes! %d (%d)", s_report_params.feature_len, s_report_params.feature_len & 0x7);
  262. } else {
  263. //SUCCESS!!!
  264. int res = handle_report(&s_report_params, s_new_map);
  265. if (res != 0) {
  266. s_parse_step = PARSE_WAIT_USAGE_PAGE;
  267. return -1;
  268. }
  269. s_new_map = false;
  270. s_report_params.input_len = 0;
  271. s_report_params.output_len = 0;
  272. s_report_params.feature_len = 0;
  273. s_report_params.usage = s_report_params.inner_usage;
  274. s_report_params.usage_page = s_report_params.inner_usage_page;
  275. }
  276. }
  277. s_report_params.report_id = cmd->value;
  278. } else if (cmd->cmd == HID_RM_USAGE_PAGE) {
  279. s_report_params.inner_usage_page = cmd->value;
  280. } else if (cmd->cmd == HID_RM_USAGE) {
  281. s_report_params.inner_usage = cmd->value;
  282. } else if (cmd->cmd == HID_RM_REPORT_SIZE) {
  283. s_report_size = cmd->value;
  284. } else if (cmd->cmd == HID_RM_REPORT_COUNT) {
  285. s_report_count = cmd->value;
  286. } else if (cmd->cmd == HID_RM_INPUT) {
  287. s_report_params.input_len += (s_report_size * s_report_count);
  288. } else if (cmd->cmd == HID_RM_OUTPUT) {
  289. s_report_params.output_len += (s_report_size * s_report_count);
  290. } else if (cmd->cmd == HID_RM_FEATURE) {
  291. s_report_params.feature_len += (s_report_size * s_report_count);
  292. } else if (cmd->cmd == HID_RM_COLLECTION) {
  293. s_collection_depth += 1;
  294. } else if (cmd->cmd == HID_RM_END_COLLECTION) {
  295. s_collection_depth -= 1;
  296. if (s_collection_depth == 0) {
  297. if (s_report_params.input_len & 0x7) {
  298. ESP_LOGE(TAG, "ERROR: INPUT report does not amount to full bytes! %d (%d)", s_report_params.input_len, s_report_params.input_len & 0x7);
  299. } else if (s_report_params.output_len & 0x7) {
  300. ESP_LOGE(TAG, "ERROR: OUTPUT report does not amount to full bytes! %d (%d)", s_report_params.output_len, s_report_params.output_len & 0x7);
  301. } else if (s_report_params.feature_len & 0x7) {
  302. ESP_LOGE(TAG, "ERROR: FEATURE report does not amount to full bytes! %d (%d)", s_report_params.feature_len, s_report_params.feature_len & 0x7);
  303. } else {
  304. //SUCCESS!!!
  305. int res = handle_report(&s_report_params, s_new_map);
  306. if (res != 0) {
  307. s_parse_step = PARSE_WAIT_USAGE_PAGE;
  308. return -1;
  309. }
  310. s_new_map = false;
  311. }
  312. s_parse_step = PARSE_WAIT_USAGE_PAGE;
  313. }
  314. }
  315. break;
  316. }
  317. default:
  318. s_parse_step = PARSE_WAIT_USAGE_PAGE;
  319. break;
  320. }
  321. return 0;
  322. }
  323. esp_hid_report_map_t *esp_hid_parse_report_map(const uint8_t *hid_rm, size_t hid_rm_len)
  324. {
  325. size_t index = 0;
  326. int res;
  327. s_new_map = true;
  328. while (index < hid_rm_len) {
  329. hid_report_cmd_t *cmd;
  330. res = parse_cmd(hid_rm, hid_rm_len, index, &cmd);
  331. if (res < 0) {
  332. ESP_LOGE(TAG, "Failed parsing the descriptor at index: %u", index);
  333. return NULL;
  334. }
  335. index += res;
  336. res = handle_cmd(cmd);
  337. free(cmd);
  338. if (res != 0) {
  339. return NULL;
  340. }
  341. }
  342. esp_hid_report_map_t *out = (esp_hid_report_map_t *)calloc(1, sizeof(esp_hid_report_map_t));
  343. if (out == NULL) {
  344. ESP_LOGE(TAG, "hid_report_map malloc failed");
  345. free(s_temp_hid_report_map);
  346. s_temp_hid_report_map = NULL;
  347. return NULL;
  348. }
  349. temp_hid_report_map_t *map = s_temp_hid_report_map;
  350. esp_hid_report_item_t *reports = (esp_hid_report_item_t *)calloc(1, map->reports_len * sizeof(esp_hid_report_item_t));
  351. if (reports == NULL) {
  352. ESP_LOGE(TAG, "hid_report_items malloc failed! %u maps", map->reports_len);
  353. free(out);
  354. free(s_temp_hid_report_map);
  355. s_temp_hid_report_map = NULL;
  356. return NULL;
  357. }
  358. if (map->usage_mask & ESP_HID_USAGE_KEYBOARD) {
  359. out->usage = ESP_HID_USAGE_KEYBOARD;
  360. out->appearance = ESP_HID_APPEARANCE_KEYBOARD;
  361. } else if (map->usage_mask & ESP_HID_USAGE_MOUSE) {
  362. out->usage = ESP_HID_USAGE_MOUSE;
  363. out->appearance = ESP_HID_APPEARANCE_MOUSE;
  364. } else if (map->usage_mask & ESP_HID_USAGE_JOYSTICK) {
  365. out->usage = ESP_HID_USAGE_JOYSTICK;
  366. out->appearance = ESP_HID_APPEARANCE_JOYSTICK;
  367. } else if (map->usage_mask & ESP_HID_USAGE_GAMEPAD) {
  368. out->usage = ESP_HID_USAGE_GAMEPAD;
  369. out->appearance = ESP_HID_APPEARANCE_GAMEPAD;
  370. } else if (map->usage_mask & ESP_HID_USAGE_CCONTROL) {
  371. out->usage = ESP_HID_USAGE_CCONTROL;
  372. out->appearance = ESP_HID_APPEARANCE_KEYBOARD;
  373. } else {
  374. out->usage = ESP_HID_USAGE_GENERIC;
  375. out->appearance = ESP_HID_APPEARANCE_GENERIC;
  376. }
  377. out->reports_len = map->reports_len;
  378. memcpy(reports, map->reports, map->reports_len * sizeof(esp_hid_report_item_t));
  379. out->reports = reports;
  380. free(s_temp_hid_report_map);
  381. s_temp_hid_report_map = NULL;
  382. return out;
  383. }
  384. void esp_hid_free_report_map(esp_hid_report_map_t *map)
  385. {
  386. if (map != NULL){
  387. free(map->reports);
  388. free(map);
  389. }
  390. }
  391. esp_hid_usage_t esp_hid_usage_from_appearance(uint16_t appearance)
  392. {
  393. return ESP_HID_USAGE_GENERIC;
  394. }
  395. esp_hid_usage_t esp_hid_usage_from_cod(uint32_t cod)
  396. {
  397. return ESP_HID_USAGE_GENERIC;
  398. }
  399. static const char *s_unknown_str = "UNKNOWN";
  400. static const char *s_hid_protocol_names[] = {"BOOT", "REPORT"};
  401. static const char *s_hid_report_type_names[] = {"NULL", "INPUT", "OUTPUT", "FEATURE"};
  402. static const char *s_hid_cod_major_names[] = {"MISC", "COMPUTER", "PHONE", "LAN_NAP", "AV", "PERIPHERAL", "IMAGING", "WEARABLE", "TOY", "HEALTH"};
  403. static const char *s_hid_cod_minor_names[7] = {"GENERIC", "JOYSTICK", "GAMEPAD", "REMOTE", "SENSOR", "TABLET", "CARD_READER"};
  404. const char *esp_hid_usage_str(esp_hid_usage_t usage)
  405. {
  406. switch (usage) {
  407. case ESP_HID_USAGE_GENERIC: return "GENERIC";
  408. case ESP_HID_USAGE_KEYBOARD: return "KEYBOARD";
  409. case ESP_HID_USAGE_MOUSE: return "MOUSE";
  410. case ESP_HID_USAGE_JOYSTICK: return "JOYSTICK";
  411. case ESP_HID_USAGE_GAMEPAD: return "GAMEPAD";
  412. case ESP_HID_USAGE_CCONTROL: return "CCONTROL";
  413. case ESP_HID_USAGE_VENDOR: return "VENDOR";
  414. default: break;
  415. }
  416. return s_unknown_str;
  417. }
  418. const char *esp_hid_protocol_mode_str(uint8_t protocol)
  419. {
  420. if (protocol >= (sizeof(s_hid_protocol_names)/sizeof(s_hid_protocol_names[0]))) {
  421. return s_unknown_str;
  422. }
  423. return s_hid_protocol_names[protocol];
  424. }
  425. const char *esp_hid_report_type_str(uint8_t report_type)
  426. {
  427. if (report_type >= (sizeof(s_hid_report_type_names)/sizeof(s_hid_report_type_names[0]))) {
  428. return s_unknown_str;
  429. }
  430. return s_hid_report_type_names[report_type];
  431. }
  432. const char *esp_hid_cod_major_str(uint8_t cod_major)
  433. {
  434. if (cod_major >= (sizeof(s_hid_cod_major_names)/sizeof(s_hid_cod_major_names[0]))) {
  435. return s_unknown_str;
  436. }
  437. return s_hid_cod_major_names[cod_major];
  438. }
  439. void esp_hid_cod_minor_print(uint8_t cod_min, FILE *fp)
  440. {
  441. if (cod_min & ESP_HID_COD_MIN_KEYBOARD) {
  442. fputs("KEYBOARD", fp);
  443. }
  444. if (cod_min & ESP_HID_COD_MIN_MOUSE) {
  445. if (cod_min & ESP_HID_COD_MIN_KEYBOARD) {
  446. fputs("+", fp);
  447. }
  448. fputs("MOUSE", fp);
  449. }
  450. if (cod_min & 0xF0) {
  451. if (cod_min & 0x0F) {
  452. fputs("+", fp);
  453. } else {
  454. return;
  455. }
  456. }
  457. cod_min &= 0x0F;
  458. if (cod_min < ESP_HID_COD_MIN_MAX) {
  459. fprintf(fp, "%s", s_hid_cod_minor_names[cod_min]);
  460. }
  461. }
  462. const char *esp_hid_disconnect_reason_str(esp_hid_transport_t transport, int reason)
  463. {
  464. if (transport == ESP_HID_TRANSPORT_BLE) {
  465. #if (CONFIG_GATTS_ENABLE || CONFIG_GATTC_ENABLE)
  466. switch ((esp_gatt_conn_reason_t)reason) {
  467. case ESP_GATT_CONN_L2C_FAILURE: return "L2C_FAILURE";
  468. case ESP_GATT_CONN_TIMEOUT: return "TIMEOUT";
  469. case ESP_GATT_CONN_TERMINATE_PEER_USER: return "TERMINATE_PEER_USER";
  470. case ESP_GATT_CONN_TERMINATE_LOCAL_HOST: return "TERMINATE_LOCAL_HOST";
  471. case ESP_GATT_CONN_LMP_TIMEOUT: return "LMP_TIMEOUT";
  472. case ESP_GATT_CONN_FAIL_ESTABLISH: return "FAIL_ESTABLISH";
  473. case ESP_GATT_CONN_CONN_CANCEL: return "CONN_CANCEL";
  474. case ESP_GATT_CONN_NONE: return "NONE";
  475. default: break;
  476. }
  477. #endif /* CONFIG_GATTS_ENABLE || CONFIG_GATTC_ENABLE */
  478. }
  479. return s_unknown_str;
  480. }