esp_hid_device_main.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. /* This example code is in the Public Domain (or CC0 licensed, at your option.)
  2. Unless required by applicable law or agreed to in writing, this software is
  3. distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  4. CONDITIONS OF ANY KIND, either express or implied.
  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. xTaskHandle 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. }