esp_hid_device_main.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <inttypes.h>
  10. #include "freertos/FreeRTOS.h"
  11. #include "freertos/task.h"
  12. #include "freertos/event_groups.h"
  13. #include "esp_system.h"
  14. #include "esp_wifi.h"
  15. #include "esp_event.h"
  16. #include "esp_log.h"
  17. #include "nvs_flash.h"
  18. #include "esp_bt.h"
  19. #include "esp_bt_defs.h"
  20. #if CONFIG_BT_BLE_ENABLED
  21. #include "esp_gap_ble_api.h"
  22. #include "esp_gatts_api.h"
  23. #include "esp_gatt_defs.h"
  24. #endif
  25. #include "esp_bt_main.h"
  26. #include "esp_bt_device.h"
  27. #include "esp_hidd.h"
  28. #include "esp_hid_gap.h"
  29. static const char *TAG = "HID_DEV_DEMO";
  30. typedef struct
  31. {
  32. TaskHandle_t task_hdl;
  33. esp_hidd_dev_t *hid_dev;
  34. uint8_t protocol_mode;
  35. uint8_t *buffer;
  36. } local_param_t;
  37. #if CONFIG_BT_BLE_ENABLED
  38. static local_param_t s_ble_hid_param = {0};
  39. const unsigned char mediaReportMap[] = {
  40. 0x05, 0x0C, // Usage Page (Consumer)
  41. 0x09, 0x01, // Usage (Consumer Control)
  42. 0xA1, 0x01, // Collection (Application)
  43. 0x85, 0x03, // Report ID (3)
  44. 0x09, 0x02, // Usage (Numeric Key Pad)
  45. 0xA1, 0x02, // Collection (Logical)
  46. 0x05, 0x09, // Usage Page (Button)
  47. 0x19, 0x01, // Usage Minimum (0x01)
  48. 0x29, 0x0A, // Usage Maximum (0x0A)
  49. 0x15, 0x01, // Logical Minimum (1)
  50. 0x25, 0x0A, // Logical Maximum (10)
  51. 0x75, 0x04, // Report Size (4)
  52. 0x95, 0x01, // Report Count (1)
  53. 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
  54. 0xC0, // End Collection
  55. 0x05, 0x0C, // Usage Page (Consumer)
  56. 0x09, 0x86, // Usage (Channel)
  57. 0x15, 0xFF, // Logical Minimum (-1)
  58. 0x25, 0x01, // Logical Maximum (1)
  59. 0x75, 0x02, // Report Size (2)
  60. 0x95, 0x01, // Report Count (1)
  61. 0x81, 0x46, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,Null State)
  62. 0x09, 0xE9, // Usage (Volume Increment)
  63. 0x09, 0xEA, // Usage (Volume Decrement)
  64. 0x15, 0x00, // Logical Minimum (0)
  65. 0x75, 0x01, // Report Size (1)
  66. 0x95, 0x02, // Report Count (2)
  67. 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
  68. 0x09, 0xE2, // Usage (Mute)
  69. 0x09, 0x30, // Usage (Power)
  70. 0x09, 0x83, // Usage (Recall Last)
  71. 0x09, 0x81, // Usage (Assign Selection)
  72. 0x09, 0xB0, // Usage (Play)
  73. 0x09, 0xB1, // Usage (Pause)
  74. 0x09, 0xB2, // Usage (Record)
  75. 0x09, 0xB3, // Usage (Fast Forward)
  76. 0x09, 0xB4, // Usage (Rewind)
  77. 0x09, 0xB5, // Usage (Scan Next Track)
  78. 0x09, 0xB6, // Usage (Scan Previous Track)
  79. 0x09, 0xB7, // Usage (Stop)
  80. 0x15, 0x01, // Logical Minimum (1)
  81. 0x25, 0x0C, // Logical Maximum (12)
  82. 0x75, 0x04, // Report Size (4)
  83. 0x95, 0x01, // Report Count (1)
  84. 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
  85. 0x09, 0x80, // Usage (Selection)
  86. 0xA1, 0x02, // Collection (Logical)
  87. 0x05, 0x09, // Usage Page (Button)
  88. 0x19, 0x01, // Usage Minimum (0x01)
  89. 0x29, 0x03, // Usage Maximum (0x03)
  90. 0x15, 0x01, // Logical Minimum (1)
  91. 0x25, 0x03, // Logical Maximum (3)
  92. 0x75, 0x02, // Report Size (2)
  93. 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
  94. 0xC0, // End Collection
  95. 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
  96. 0xC0, // End Collection
  97. };
  98. static esp_hid_raw_report_map_t ble_report_maps[] = {
  99. {
  100. .data = mediaReportMap,
  101. .len = sizeof(mediaReportMap)
  102. }
  103. };
  104. static esp_hid_device_config_t ble_hid_config = {
  105. .vendor_id = 0x16C0,
  106. .product_id = 0x05DF,
  107. .version = 0x0100,
  108. .device_name = "ESP BLE HID2",
  109. .manufacturer_name = "Espressif",
  110. .serial_number = "1234567890",
  111. .report_maps = ble_report_maps,
  112. .report_maps_len = 1
  113. };
  114. #define HID_CC_RPT_MUTE 1
  115. #define HID_CC_RPT_POWER 2
  116. #define HID_CC_RPT_LAST 3
  117. #define HID_CC_RPT_ASSIGN_SEL 4
  118. #define HID_CC_RPT_PLAY 5
  119. #define HID_CC_RPT_PAUSE 6
  120. #define HID_CC_RPT_RECORD 7
  121. #define HID_CC_RPT_FAST_FWD 8
  122. #define HID_CC_RPT_REWIND 9
  123. #define HID_CC_RPT_SCAN_NEXT_TRK 10
  124. #define HID_CC_RPT_SCAN_PREV_TRK 11
  125. #define HID_CC_RPT_STOP 12
  126. #define HID_CC_RPT_CHANNEL_UP 0x10
  127. #define HID_CC_RPT_CHANNEL_DOWN 0x30
  128. #define HID_CC_RPT_VOLUME_UP 0x40
  129. #define HID_CC_RPT_VOLUME_DOWN 0x80
  130. // HID Consumer Control report bitmasks
  131. #define HID_CC_RPT_NUMERIC_BITS 0xF0
  132. #define HID_CC_RPT_CHANNEL_BITS 0xCF
  133. #define HID_CC_RPT_VOLUME_BITS 0x3F
  134. #define HID_CC_RPT_BUTTON_BITS 0xF0
  135. #define HID_CC_RPT_SELECTION_BITS 0xCF
  136. // Macros for the HID Consumer Control 2-byte report
  137. #define HID_CC_RPT_SET_NUMERIC(s, x) (s)[0] &= HID_CC_RPT_NUMERIC_BITS; (s)[0] = (x)
  138. #define HID_CC_RPT_SET_CHANNEL(s, x) (s)[0] &= HID_CC_RPT_CHANNEL_BITS; (s)[0] |= ((x) & 0x03) << 4
  139. #define HID_CC_RPT_SET_VOLUME_UP(s) (s)[0] &= HID_CC_RPT_VOLUME_BITS; (s)[0] |= 0x40
  140. #define HID_CC_RPT_SET_VOLUME_DOWN(s) (s)[0] &= HID_CC_RPT_VOLUME_BITS; (s)[0] |= 0x80
  141. #define HID_CC_RPT_SET_BUTTON(s, x) (s)[1] &= HID_CC_RPT_BUTTON_BITS; (s)[1] |= (x)
  142. #define HID_CC_RPT_SET_SELECTION(s, x) (s)[1] &= HID_CC_RPT_SELECTION_BITS; (s)[1] |= ((x) & 0x03) << 4
  143. // HID Consumer Usage IDs (subset of the codes available in the USB HID Usage Tables spec)
  144. #define HID_CONSUMER_POWER 48 // Power
  145. #define HID_CONSUMER_RESET 49 // Reset
  146. #define HID_CONSUMER_SLEEP 50 // Sleep
  147. #define HID_CONSUMER_MENU 64 // Menu
  148. #define HID_CONSUMER_SELECTION 128 // Selection
  149. #define HID_CONSUMER_ASSIGN_SEL 129 // Assign Selection
  150. #define HID_CONSUMER_MODE_STEP 130 // Mode Step
  151. #define HID_CONSUMER_RECALL_LAST 131 // Recall Last
  152. #define HID_CONSUMER_QUIT 148 // Quit
  153. #define HID_CONSUMER_HELP 149 // Help
  154. #define HID_CONSUMER_CHANNEL_UP 156 // Channel Increment
  155. #define HID_CONSUMER_CHANNEL_DOWN 157 // Channel Decrement
  156. #define HID_CONSUMER_PLAY 176 // Play
  157. #define HID_CONSUMER_PAUSE 177 // Pause
  158. #define HID_CONSUMER_RECORD 178 // Record
  159. #define HID_CONSUMER_FAST_FORWARD 179 // Fast Forward
  160. #define HID_CONSUMER_REWIND 180 // Rewind
  161. #define HID_CONSUMER_SCAN_NEXT_TRK 181 // Scan Next Track
  162. #define HID_CONSUMER_SCAN_PREV_TRK 182 // Scan Previous Track
  163. #define HID_CONSUMER_STOP 183 // Stop
  164. #define HID_CONSUMER_EJECT 184 // Eject
  165. #define HID_CONSUMER_RANDOM_PLAY 185 // Random Play
  166. #define HID_CONSUMER_SELECT_DISC 186 // Select Disk
  167. #define HID_CONSUMER_ENTER_DISC 187 // Enter Disc
  168. #define HID_CONSUMER_REPEAT 188 // Repeat
  169. #define HID_CONSUMER_STOP_EJECT 204 // Stop/Eject
  170. #define HID_CONSUMER_PLAY_PAUSE 205 // Play/Pause
  171. #define HID_CONSUMER_PLAY_SKIP 206 // Play/Skip
  172. #define HID_CONSUMER_VOLUME 224 // Volume
  173. #define HID_CONSUMER_BALANCE 225 // Balance
  174. #define HID_CONSUMER_MUTE 226 // Mute
  175. #define HID_CONSUMER_BASS 227 // Bass
  176. #define HID_CONSUMER_VOLUME_UP 233 // Volume Increment
  177. #define HID_CONSUMER_VOLUME_DOWN 234 // Volume Decrement
  178. #define HID_RPT_ID_CC_IN 3 // Consumer Control input report ID
  179. #define HID_CC_IN_RPT_LEN 2 // Consumer Control input report Len
  180. void esp_hidd_send_consumer_value(uint8_t key_cmd, bool key_pressed)
  181. {
  182. uint8_t buffer[HID_CC_IN_RPT_LEN] = {0, 0};
  183. if (key_pressed) {
  184. switch (key_cmd) {
  185. case HID_CONSUMER_CHANNEL_UP:
  186. HID_CC_RPT_SET_CHANNEL(buffer, HID_CC_RPT_CHANNEL_UP);
  187. break;
  188. case HID_CONSUMER_CHANNEL_DOWN:
  189. HID_CC_RPT_SET_CHANNEL(buffer, HID_CC_RPT_CHANNEL_DOWN);
  190. break;
  191. case HID_CONSUMER_VOLUME_UP:
  192. HID_CC_RPT_SET_VOLUME_UP(buffer);
  193. break;
  194. case HID_CONSUMER_VOLUME_DOWN:
  195. HID_CC_RPT_SET_VOLUME_DOWN(buffer);
  196. break;
  197. case HID_CONSUMER_MUTE:
  198. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_MUTE);
  199. break;
  200. case HID_CONSUMER_POWER:
  201. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_POWER);
  202. break;
  203. case HID_CONSUMER_RECALL_LAST:
  204. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_LAST);
  205. break;
  206. case HID_CONSUMER_ASSIGN_SEL:
  207. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_ASSIGN_SEL);
  208. break;
  209. case HID_CONSUMER_PLAY:
  210. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_PLAY);
  211. break;
  212. case HID_CONSUMER_PAUSE:
  213. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_PAUSE);
  214. break;
  215. case HID_CONSUMER_RECORD:
  216. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_RECORD);
  217. break;
  218. case HID_CONSUMER_FAST_FORWARD:
  219. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_FAST_FWD);
  220. break;
  221. case HID_CONSUMER_REWIND:
  222. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_REWIND);
  223. break;
  224. case HID_CONSUMER_SCAN_NEXT_TRK:
  225. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_SCAN_NEXT_TRK);
  226. break;
  227. case HID_CONSUMER_SCAN_PREV_TRK:
  228. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_SCAN_PREV_TRK);
  229. break;
  230. case HID_CONSUMER_STOP:
  231. HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_STOP);
  232. break;
  233. default:
  234. break;
  235. }
  236. }
  237. esp_hidd_dev_input_set(s_ble_hid_param.hid_dev, 0, HID_RPT_ID_CC_IN, buffer, HID_CC_IN_RPT_LEN);
  238. return;
  239. }
  240. void ble_hid_demo_task(void *pvParameters)
  241. {
  242. static bool send_volum_up = false;
  243. while (1) {
  244. ESP_LOGI(TAG, "Send the volume");
  245. if (send_volum_up) {
  246. esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_UP, true);
  247. vTaskDelay(100 / portTICK_PERIOD_MS);
  248. esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_UP, false);
  249. } else {
  250. esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_DOWN, true);
  251. vTaskDelay(100 / portTICK_PERIOD_MS);
  252. esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_DOWN, false);
  253. }
  254. send_volum_up = !send_volum_up;
  255. vTaskDelay(2000 / portTICK_PERIOD_MS);
  256. }
  257. }
  258. void ble_hid_task_start_up(void)
  259. {
  260. if (s_ble_hid_param.task_hdl) {
  261. // Task already exists
  262. return;
  263. }
  264. xTaskCreate(ble_hid_demo_task, "ble_hid_demo_task", 2 * 1024, NULL, configMAX_PRIORITIES - 3,
  265. &s_ble_hid_param.task_hdl);
  266. }
  267. void ble_hid_task_shut_down(void)
  268. {
  269. if (s_ble_hid_param.task_hdl) {
  270. vTaskDelete(s_ble_hid_param.task_hdl);
  271. s_ble_hid_param.task_hdl = NULL;
  272. }
  273. }
  274. static void ble_hidd_event_callback(void *handler_args, esp_event_base_t base, int32_t id, void *event_data)
  275. {
  276. esp_hidd_event_t event = (esp_hidd_event_t)id;
  277. esp_hidd_event_data_t *param = (esp_hidd_event_data_t *)event_data;
  278. static const char *TAG = "HID_DEV_BLE";
  279. switch (event) {
  280. case ESP_HIDD_START_EVENT: {
  281. ESP_LOGI(TAG, "START");
  282. esp_hid_ble_gap_adv_start();
  283. break;
  284. }
  285. case ESP_HIDD_CONNECT_EVENT: {
  286. ESP_LOGI(TAG, "CONNECT");
  287. break;
  288. }
  289. case ESP_HIDD_PROTOCOL_MODE_EVENT: {
  290. ESP_LOGI(TAG, "PROTOCOL MODE[%u]: %s", param->protocol_mode.map_index, param->protocol_mode.protocol_mode ? "REPORT" : "BOOT");
  291. break;
  292. }
  293. case ESP_HIDD_CONTROL_EVENT: {
  294. ESP_LOGI(TAG, "CONTROL[%u]: %sSUSPEND", param->control.map_index, param->control.control ? "EXIT_" : "");
  295. if (param->control.control)
  296. {
  297. // exit suspend
  298. ble_hid_task_start_up();
  299. } else {
  300. // suspend
  301. ble_hid_task_shut_down();
  302. }
  303. break;
  304. }
  305. case ESP_HIDD_OUTPUT_EVENT: {
  306. ESP_LOGI(TAG, "OUTPUT[%u]: %8s ID: %2u, Len: %d, Data:", param->output.map_index, esp_hid_usage_str(param->output.usage), param->output.report_id, param->output.length);
  307. ESP_LOG_BUFFER_HEX(TAG, param->output.data, param->output.length);
  308. break;
  309. }
  310. case ESP_HIDD_FEATURE_EVENT: {
  311. ESP_LOGI(TAG, "FEATURE[%u]: %8s ID: %2u, Len: %d, Data:", param->feature.map_index, esp_hid_usage_str(param->feature.usage), param->feature.report_id, param->feature.length);
  312. ESP_LOG_BUFFER_HEX(TAG, param->feature.data, param->feature.length);
  313. break;
  314. }
  315. case ESP_HIDD_DISCONNECT_EVENT: {
  316. ESP_LOGI(TAG, "DISCONNECT: %s", esp_hid_disconnect_reason_str(esp_hidd_dev_transport_get(param->disconnect.dev), param->disconnect.reason));
  317. ble_hid_task_shut_down();
  318. esp_hid_ble_gap_adv_start();
  319. break;
  320. }
  321. case ESP_HIDD_STOP_EVENT: {
  322. ESP_LOGI(TAG, "STOP");
  323. break;
  324. }
  325. default:
  326. break;
  327. }
  328. return;
  329. }
  330. #endif
  331. #if CONFIG_BT_HID_DEVICE_ENABLED
  332. static local_param_t s_bt_hid_param = {0};
  333. const unsigned char mouseReportMap[] = {
  334. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  335. 0x09, 0x02, // USAGE (Mouse)
  336. 0xa1, 0x01, // COLLECTION (Application)
  337. 0x09, 0x01, // USAGE (Pointer)
  338. 0xa1, 0x00, // COLLECTION (Physical)
  339. 0x05, 0x09, // USAGE_PAGE (Button)
  340. 0x19, 0x01, // USAGE_MINIMUM (Button 1)
  341. 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
  342. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  343. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  344. 0x95, 0x03, // REPORT_COUNT (3)
  345. 0x75, 0x01, // REPORT_SIZE (1)
  346. 0x81, 0x02, // INPUT (Data,Var,Abs)
  347. 0x95, 0x01, // REPORT_COUNT (1)
  348. 0x75, 0x05, // REPORT_SIZE (5)
  349. 0x81, 0x03, // INPUT (Cnst,Var,Abs)
  350. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  351. 0x09, 0x30, // USAGE (X)
  352. 0x09, 0x31, // USAGE (Y)
  353. 0x09, 0x38, // USAGE (Wheel)
  354. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  355. 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
  356. 0x75, 0x08, // REPORT_SIZE (8)
  357. 0x95, 0x03, // REPORT_COUNT (3)
  358. 0x81, 0x06, // INPUT (Data,Var,Rel)
  359. 0xc0, // END_COLLECTION
  360. 0xc0 // END_COLLECTION
  361. };
  362. static esp_hid_raw_report_map_t bt_report_maps[] = {
  363. {
  364. .data = mouseReportMap,
  365. .len = sizeof(mouseReportMap)
  366. },
  367. };
  368. static esp_hid_device_config_t bt_hid_config = {
  369. .vendor_id = 0x16C0,
  370. .product_id = 0x05DF,
  371. .version = 0x0100,
  372. .device_name = "ESP BT HID1",
  373. .manufacturer_name = "Espressif",
  374. .serial_number = "1234567890",
  375. .report_maps = bt_report_maps,
  376. .report_maps_len = 1
  377. };
  378. // send the buttons, change in x, and change in y
  379. void send_mouse(uint8_t buttons, char dx, char dy, char wheel)
  380. {
  381. static uint8_t buffer[4] = {0};
  382. buffer[0] = buttons;
  383. buffer[1] = dx;
  384. buffer[2] = dy;
  385. buffer[3] = wheel;
  386. esp_hidd_dev_input_set(s_bt_hid_param.hid_dev, 0, 0, buffer, 4);
  387. }
  388. void bt_hid_demo_task(void *pvParameters)
  389. {
  390. static const char* help_string = "########################################################################\n"\
  391. "BT hid mouse demo usage:\n"\
  392. "You can input these value to simulate mouse: 'q', 'w', 'e', 'a', 's', 'd', 'h'\n"\
  393. "q -- click the left key\n"\
  394. "w -- move up\n"\
  395. "e -- click the right key\n"\
  396. "a -- move left\n"\
  397. "s -- move down\n"\
  398. "d -- move right\n"\
  399. "h -- show the help\n"\
  400. "########################################################################\n";
  401. printf("%s\n", help_string);
  402. char c;
  403. while (1) {
  404. c = fgetc(stdin);
  405. switch (c) {
  406. case 'q':
  407. send_mouse(1, 0, 0, 0);
  408. break;
  409. case 'w':
  410. send_mouse(0, 0, -10, 0);
  411. break;
  412. case 'e':
  413. send_mouse(2, 0, 0, 0);
  414. break;
  415. case 'a':
  416. send_mouse(0, -10, 0, 0);
  417. break;
  418. case 's':
  419. send_mouse(0, 0, 10, 0);
  420. break;
  421. case 'd':
  422. send_mouse(0, 10, 0, 0);
  423. break;
  424. case 'h':
  425. printf("%s\n", help_string);
  426. break;
  427. default:
  428. break;
  429. }
  430. vTaskDelay(10 / portTICK_PERIOD_MS);
  431. }
  432. }
  433. void bt_hid_task_start_up(void)
  434. {
  435. xTaskCreate(bt_hid_demo_task, "bt_hid_demo_task", 2 * 1024, NULL, configMAX_PRIORITIES - 3, &s_bt_hid_param.task_hdl);
  436. return;
  437. }
  438. void bt_hid_task_shut_down(void)
  439. {
  440. if (s_bt_hid_param.task_hdl) {
  441. vTaskDelete(s_bt_hid_param.task_hdl);
  442. s_bt_hid_param.task_hdl = NULL;
  443. }
  444. }
  445. static void bt_hidd_event_callback(void *handler_args, esp_event_base_t base, int32_t id, void *event_data)
  446. {
  447. esp_hidd_event_t event = (esp_hidd_event_t)id;
  448. esp_hidd_event_data_t *param = (esp_hidd_event_data_t *)event_data;
  449. static const char *TAG = "HID_DEV_BT";
  450. switch (event) {
  451. case ESP_HIDD_START_EVENT: {
  452. if (param->start.status == ESP_OK) {
  453. ESP_LOGI(TAG, "START OK");
  454. ESP_LOGI(TAG, "Setting to connectable, discoverable");
  455. esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
  456. } else {
  457. ESP_LOGE(TAG, "START failed!");
  458. }
  459. break;
  460. }
  461. case ESP_HIDD_CONNECT_EVENT: {
  462. if (param->connect.status == ESP_OK) {
  463. ESP_LOGI(TAG, "CONNECT OK");
  464. ESP_LOGI(TAG, "Setting to non-connectable, non-discoverable");
  465. esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
  466. bt_hid_task_start_up();
  467. } else {
  468. ESP_LOGE(TAG, "CONNECT failed!");
  469. }
  470. break;
  471. }
  472. case ESP_HIDD_PROTOCOL_MODE_EVENT: {
  473. ESP_LOGI(TAG, "PROTOCOL MODE[%u]: %s", param->protocol_mode.map_index, param->protocol_mode.protocol_mode ? "REPORT" : "BOOT");
  474. break;
  475. }
  476. case ESP_HIDD_OUTPUT_EVENT: {
  477. ESP_LOGI(TAG, "OUTPUT[%u]: %8s ID: %2u, Len: %d, Data:", param->output.map_index, esp_hid_usage_str(param->output.usage), param->output.report_id, param->output.length);
  478. ESP_LOG_BUFFER_HEX(TAG, param->output.data, param->output.length);
  479. break;
  480. }
  481. case ESP_HIDD_FEATURE_EVENT: {
  482. ESP_LOGI(TAG, "FEATURE[%u]: %8s ID: %2u, Len: %d, Data:", param->feature.map_index, esp_hid_usage_str(param->feature.usage), param->feature.report_id, param->feature.length);
  483. ESP_LOG_BUFFER_HEX(TAG, param->feature.data, param->feature.length);
  484. break;
  485. }
  486. case ESP_HIDD_DISCONNECT_EVENT: {
  487. if (param->disconnect.status == ESP_OK) {
  488. ESP_LOGI(TAG, "DISCONNECT OK");
  489. bt_hid_task_shut_down();
  490. ESP_LOGI(TAG, "Setting to connectable, discoverable again");
  491. esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
  492. } else {
  493. ESP_LOGE(TAG, "DISCONNECT failed!");
  494. }
  495. break;
  496. }
  497. case ESP_HIDD_STOP_EVENT: {
  498. ESP_LOGI(TAG, "STOP");
  499. break;
  500. }
  501. default:
  502. break;
  503. }
  504. return;
  505. }
  506. #endif
  507. void app_main(void)
  508. {
  509. esp_err_t ret;
  510. #if HID_DEV_MODE == HIDD_IDLE_MODE
  511. ESP_LOGE(TAG, "Please turn on BT HID device or BLE!");
  512. return;
  513. #endif
  514. ret = nvs_flash_init();
  515. if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  516. ESP_ERROR_CHECK(nvs_flash_erase());
  517. ret = nvs_flash_init();
  518. }
  519. ESP_ERROR_CHECK( ret );
  520. ESP_LOGI(TAG, "setting hid gap, mode:%d", HID_DEV_MODE);
  521. ret = esp_hid_gap_init(HID_DEV_MODE);
  522. ESP_ERROR_CHECK( ret );
  523. #if CONFIG_BT_BLE_ENABLED
  524. ret = esp_hid_ble_gap_adv_init(ESP_HID_APPEARANCE_GENERIC, ble_hid_config.device_name);
  525. ESP_ERROR_CHECK( ret );
  526. if ((ret = esp_ble_gatts_register_callback(esp_hidd_gatts_event_handler)) != ESP_OK) {
  527. ESP_LOGE(TAG, "GATTS register callback failed: %d", ret);
  528. return;
  529. }
  530. ESP_LOGI(TAG, "setting ble device");
  531. ESP_ERROR_CHECK(
  532. esp_hidd_dev_init(&ble_hid_config, ESP_HID_TRANSPORT_BLE, ble_hidd_event_callback, &s_ble_hid_param.hid_dev));
  533. #endif
  534. #if CONFIG_BT_HID_DEVICE_ENABLED
  535. ESP_LOGI(TAG, "setting device name");
  536. esp_bt_dev_set_device_name(bt_hid_config.device_name);
  537. ESP_LOGI(TAG, "setting cod major, peripheral");
  538. esp_bt_cod_t cod;
  539. cod.major = ESP_BT_COD_MAJOR_DEV_PERIPHERAL;
  540. esp_bt_gap_set_cod(cod, ESP_BT_SET_COD_MAJOR_MINOR);
  541. vTaskDelay(1000 / portTICK_PERIOD_MS);
  542. ESP_LOGI(TAG, "setting bt device");
  543. ESP_ERROR_CHECK(
  544. esp_hidd_dev_init(&bt_hid_config, ESP_HID_TRANSPORT_BT, bt_hidd_event_callback, &s_bt_hid_param.hid_dev));
  545. #endif
  546. }