esp_hid_device_main.c 22 KB

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