ble_hidd.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  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 <stdbool.h>
  15. #include "ble_hidd.h"
  16. #if CONFIG_GATTS_ENABLE
  17. #include "esp_hidd_private.h"
  18. #include "esp_log.h"
  19. #include "esp_bt.h"
  20. #include "esp_bt_main.h"
  21. #include "esp_bt_defs.h"
  22. #include "esp_gatts_api.h"
  23. #include "esp_gatt_defs.h"
  24. #include "esp_gap_ble_api.h"
  25. static const char *TAG = "BLE_HIDD";
  26. /// Maximal length of Report Char. Value
  27. #define HIDD_LE_REPORT_MAX_LEN (255)
  28. /// Maximal length of Report Map Char. Value
  29. #define HIDD_LE_REPORT_MAP_MAX_LEN (512)
  30. /// Length of Boot Report Char. Value Maximal Length
  31. #define HIDD_LE_BOOT_REPORT_MAX_LEN (8)
  32. /*
  33. * UUIDs
  34. * */
  35. //the uuid definition
  36. static const uint16_t s_primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
  37. static const uint16_t s_include_service_uuid = ESP_GATT_UUID_INCLUDE_SERVICE;
  38. static const uint16_t s_character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
  39. static const uint16_t s_character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
  40. //the property definition
  41. static const uint8_t s_char_prop_read = ESP_GATT_CHAR_PROP_BIT_READ;
  42. //static const uint8_t s_char_prop_write = ESP_GATT_CHAR_PROP_BIT_WRITE;
  43. static const uint8_t s_char_prop_write_nr = ESP_GATT_CHAR_PROP_BIT_WRITE_NR;
  44. static const uint8_t s_char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY;
  45. static const uint8_t s_char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_READ;
  46. static const uint8_t s_char_prop_read_write_nr = ESP_GATT_CHAR_PROP_BIT_WRITE_NR | ESP_GATT_CHAR_PROP_BIT_READ;
  47. //static const uint8_t s_char_prop_read_write_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_NOTIFY;
  48. // Service UUIDs
  49. static const uint16_t s_bat_svc = ESP_GATT_UUID_BATTERY_SERVICE_SVC;
  50. static const uint16_t s_device_info_svc = ESP_GATT_UUID_DEVICE_INFO_SVC;
  51. static const uint16_t s_hid_le_svc = ESP_GATT_UUID_HID_SVC;
  52. // Battery UUIDs
  53. static const uint16_t s_bat_level_uuid = ESP_GATT_UUID_BATTERY_LEVEL;
  54. static const uint16_t s_bat_char_pres_format_uuid = ESP_GATT_UUID_CHAR_PRESENT_FORMAT;
  55. // Device Info UUIDs
  56. static const uint16_t s_device_info_pnp_id_uuid = ESP_GATT_UUID_PNP_ID;
  57. static const uint16_t s_device_info_manufacturer_uuid = ESP_GATT_UUID_MANU_NAME;
  58. static const uint16_t s_device_info_serial_num_uuid = ESP_GATT_UUID_SERIAL_NUMBER_STR;
  59. // HID General UUIDs
  60. static const uint16_t s_hid_report_map_uuid = ESP_GATT_UUID_HID_REPORT_MAP;
  61. static const uint16_t s_hid_report_map_ext_desc_uuid = ESP_GATT_UUID_EXT_RPT_REF_DESCR;
  62. static const uint16_t s_hid_info_char_uuid = ESP_GATT_UUID_HID_INFORMATION;
  63. static const uint16_t s_hid_control_point_uuid = ESP_GATT_UUID_HID_CONTROL_POINT;
  64. static const uint16_t s_hid_proto_mode_uuid = ESP_GATT_UUID_HID_PROTO_MODE;
  65. // HID Report UUIDs
  66. static const uint16_t s_hid_report_ref_descr_uuid = ESP_GATT_UUID_RPT_REF_DESCR;
  67. static const uint16_t s_hid_report_uuid = ESP_GATT_UUID_HID_REPORT;
  68. // HID BOOT UUIDs
  69. static const uint16_t s_hid_boot_kb_input_uuid = ESP_GATT_UUID_HID_BT_KB_INPUT;
  70. static const uint16_t s_hid_boot_kb_output_uuid = ESP_GATT_UUID_HID_BT_KB_OUTPUT;
  71. static const uint16_t s_hid_boot_mouse_input_uuid = ESP_GATT_UUID_HID_BT_MOUSE_INPUT;
  72. // Battery Service Attributes Indexes
  73. enum {
  74. BAS_IDX_SVC,
  75. BAS_IDX_BATT_LVL_CHAR,
  76. BAS_IDX_BATT_LVL_VAL,
  77. BAS_IDX_BATT_LVL_CCC,
  78. BAS_IDX_BATT_LVL_PRES_FMT,
  79. BAS_IDX_NB,
  80. };
  81. // HID Service Attributes Indexes
  82. enum {
  83. HIDD_LE_IDX_SVC,
  84. // Included Service
  85. HIDD_LE_IDX_INCL_SVC,
  86. // HID Information
  87. HIDD_LE_IDX_HID_INFO_CHAR,
  88. HIDD_LE_IDX_HID_INFO_VAL,
  89. // HID Control Point
  90. HIDD_LE_IDX_HID_CTNL_PT_CHAR,
  91. HIDD_LE_IDX_HID_CTNL_PT_VAL,
  92. // Protocol Mode
  93. HIDD_LE_IDX_PROTO_MODE_CHAR,
  94. HIDD_LE_IDX_PROTO_MODE_VAL,
  95. // Report Map
  96. HIDD_LE_IDX_REPORT_MAP_CHAR,
  97. HIDD_LE_IDX_REPORT_MAP_VAL,
  98. HIDD_LE_IDX_REPORT_MAP_EXT_REP_REF,
  99. HIDD_LE_IDX_NB,
  100. };
  101. /* Client Characteristic Configuration value structure */
  102. typedef union {
  103. struct {
  104. uint16_t notify_enable: 1;
  105. uint16_t indicate_enable: 1;
  106. uint16_t reserved: 14;
  107. };
  108. uint16_t value;
  109. } hidd_le_ccc_value_t;
  110. typedef struct {
  111. uint8_t map_index; //the index of the report map
  112. uint8_t report_id; //the id of the report
  113. uint8_t report_type; //input, output or feature
  114. uint8_t protocol_mode; //boot or report
  115. esp_hid_usage_t usage; //generic, keyboard, mouse, joystick or gamepad
  116. uint16_t value_len; //maximum len of value by report map
  117. //used by gatts
  118. uint8_t index; //index of the value in the gatts attr db
  119. uint16_t handle; //obtained once all attributes are registered
  120. uint16_t ccc_handle; //obtained once all attributes are registered
  121. hidd_le_ccc_value_t ccc; //notifications and/or indications enabled
  122. } hidd_le_report_item_t;
  123. typedef struct {
  124. esp_gatt_if_t gatt_if;
  125. uint16_t handle;
  126. } hidd_le_service_t;
  127. typedef struct {
  128. esp_hid_raw_report_map_t reports_map;
  129. uint8_t reports_len;
  130. hidd_le_report_item_t *reports;
  131. hidd_le_service_t hid_svc;
  132. uint16_t hid_control_handle;
  133. uint16_t hid_protocol_handle;
  134. } hidd_dev_map_t;
  135. struct esp_ble_hidd_dev_s {
  136. esp_hidd_dev_t *dev;
  137. xSemaphoreHandle sem;
  138. esp_event_loop_handle_t event_loop_handle;
  139. esp_hid_device_config_t config;
  140. uint16_t appearance;
  141. bool connected;
  142. uint16_t conn_id;
  143. esp_bd_addr_t remote_bda;
  144. hidd_le_ccc_value_t bat_ccc;
  145. uint8_t bat_level; // 0 - 100 - battery percentage
  146. uint8_t control; // 0x00 suspend, 0x01 suspend off
  147. uint8_t protocol; // 0x00 boot, 0x01 report
  148. hidd_le_service_t bat_svc;
  149. hidd_le_service_t info_svc;
  150. esp_gatts_incl_svc_desc_t hid_incl_svc;
  151. uint16_t bat_level_handle;
  152. uint16_t bat_ccc_handle;
  153. uint8_t pnp[7];
  154. hidd_dev_map_t *devices;
  155. uint8_t devices_len;
  156. };
  157. typedef struct esp_ble_hidd_dev_s esp_ble_hidd_dev_t;
  158. // HID Information characteristic value
  159. static const uint8_t hidInfo[4] = {
  160. 0x11, 0x01, // bcdHID (USB HID version)
  161. 0x00, // bCountryCode
  162. ESP_HID_FLAGS_REMOTE_WAKE | ESP_HID_FLAGS_NORMALLY_CONNECTABLE // Flags
  163. };
  164. #define WAIT_CB(d) xSemaphoreTake(d->sem, portMAX_DELAY)
  165. #define SEND_CB(d) xSemaphoreGive(d->sem)
  166. static const char *gatts_evt_names[25] = { "REG", "READ", "WRITE", "EXEC_WRITE", "MTU", "CONF", "UNREG", "CREATE", "ADD_INCL_SRVC", "ADD_CHAR", "ADD_CHAR_DESCR", "DELETE", "START", "STOP", "CONNECT", "DISCONNECT", "OPEN", "CANCEL_OPEN", "CLOSE", "LISTEN", "CONGEST", "RESPONSE", "CREAT_ATTR_TAB", "SET_ATTR_VAL", "SEND_SERVICE_CHANGE"};
  167. static const char *gatts_evt_str(uint8_t event)
  168. {
  169. if (event >= (sizeof(gatts_evt_names)/sizeof(*gatts_evt_names))) {
  170. return "UNKNOWN";
  171. }
  172. return gatts_evt_names[event];
  173. }
  174. static void add_db_record(esp_gatts_attr_db_t *db, size_t index, uint8_t *uuid, uint8_t perm, uint16_t max_length, uint16_t length, uint8_t *value)
  175. {
  176. db[index].attr_control.auto_rsp = ESP_GATT_AUTO_RSP;
  177. db[index].att_desc.uuid_length = ESP_UUID_LEN_16;
  178. db[index].att_desc.uuid_p = uuid;
  179. db[index].att_desc.perm = perm;
  180. db[index].att_desc.max_length = max_length;
  181. db[index].att_desc.length = length;
  182. db[index].att_desc.value = value;
  183. }
  184. static esp_gatts_attr_db_t *_last_db = NULL;
  185. static esp_err_t create_bat_db(esp_ble_hidd_dev_t *dev)
  186. {
  187. _last_db = (esp_gatts_attr_db_t *)malloc(sizeof(esp_gatts_attr_db_t) * BAS_IDX_NB);
  188. if (!_last_db) {
  189. ESP_LOGE(TAG, "Malloc bat_db failed");
  190. return ESP_FAIL;
  191. }
  192. add_db_record(_last_db, BAS_IDX_SVC, (uint8_t *)&s_primary_service_uuid, ESP_GATT_PERM_READ, 2, 2, (uint8_t *)&s_bat_svc);
  193. add_db_record(_last_db, BAS_IDX_BATT_LVL_CHAR, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read_notify);
  194. add_db_record(_last_db, BAS_IDX_BATT_LVL_VAL, (uint8_t *)&s_bat_level_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&dev->bat_level);
  195. add_db_record(_last_db, BAS_IDX_BATT_LVL_CCC, (uint8_t *)&s_character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, 2, 0, NULL);
  196. add_db_record(_last_db, BAS_IDX_BATT_LVL_PRES_FMT, (uint8_t *)&s_bat_char_pres_format_uuid, ESP_GATT_PERM_READ, 7, 0, NULL);
  197. esp_err_t err = esp_ble_gatts_create_attr_tab(_last_db, dev->bat_svc.gatt_if, BAS_IDX_NB, 0);
  198. return err;
  199. }
  200. static esp_err_t create_info_db(esp_ble_hidd_dev_t *dev)
  201. {
  202. _last_db = (esp_gatts_attr_db_t *)malloc(sizeof(esp_gatts_attr_db_t) * 7);
  203. if (!_last_db) {
  204. ESP_LOGE(TAG, "Malloc info_db failed");
  205. return ESP_FAIL;
  206. }
  207. size_t index = 0;
  208. add_db_record(_last_db, index++, (uint8_t *)&s_primary_service_uuid, ESP_GATT_PERM_READ, 2, 2, (uint8_t *)&s_device_info_svc);
  209. if (dev->config.product_id || dev->config.vendor_id || dev->config.version) {
  210. uint8_t pnp_val[7] = {
  211. 0x02, //0x1=BT, 0x2=USB
  212. dev->config.vendor_id & 0xFF, (dev->config.vendor_id >> 8) & 0xFF, //VID
  213. dev->config.product_id & 0xFF, (dev->config.product_id >> 8) & 0xFF, //PID
  214. dev->config.version & 0xFF, (dev->config.version >> 8) & 0xFF //VERSION
  215. };
  216. memcpy(dev->pnp, pnp_val, 7);
  217. add_db_record(_last_db, index++, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read);
  218. add_db_record(_last_db, index++, (uint8_t *)&s_device_info_pnp_id_uuid, ESP_GATT_PERM_READ, 7, 7, (uint8_t *)dev->pnp);
  219. }
  220. if (dev->config.manufacturer_name && dev->config.manufacturer_name[0]) {
  221. size_t name_len = strlen(dev->config.manufacturer_name);
  222. add_db_record(_last_db, index++, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read);
  223. add_db_record(_last_db, index++, (uint8_t *)&s_device_info_manufacturer_uuid, ESP_GATT_PERM_READ, name_len, name_len, (uint8_t *)dev->config.manufacturer_name);
  224. }
  225. if (dev->config.serial_number && dev->config.serial_number[0]) {
  226. size_t name_len = strlen(dev->config.serial_number);
  227. add_db_record(_last_db, index++, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read);
  228. add_db_record(_last_db, index++, (uint8_t *)&s_device_info_serial_num_uuid, ESP_GATT_PERM_READ, name_len, name_len, (uint8_t *)dev->config.serial_number);
  229. }
  230. esp_err_t err = esp_ble_gatts_create_attr_tab(_last_db, dev->info_svc.gatt_if, index, 0);
  231. return err;
  232. }
  233. static esp_err_t create_hid_db(esp_ble_hidd_dev_t *dev, int device_index)
  234. {
  235. size_t report_attr_len = 0;
  236. for (uint8_t i = 0; i < dev->devices[device_index].reports_len; i++) {
  237. if (dev->devices[device_index].reports[i].report_type == ESP_HID_REPORT_TYPE_INPUT) {
  238. report_attr_len += 3;
  239. } else {
  240. report_attr_len += 2;
  241. }
  242. if (dev->devices[device_index].reports[i].protocol_mode == ESP_HID_PROTOCOL_MODE_REPORT) {
  243. report_attr_len += 1;
  244. }
  245. }
  246. _last_db = (esp_gatts_attr_db_t *)malloc(sizeof(esp_gatts_attr_db_t) * (HIDD_LE_IDX_NB + report_attr_len + (dev->devices_len * 3)));
  247. if (!_last_db) {
  248. ESP_LOGE(TAG, "Malloc hid_db failed");
  249. return ESP_FAIL;
  250. }
  251. add_db_record(_last_db, HIDD_LE_IDX_SVC, (uint8_t *)&s_primary_service_uuid, ESP_GATT_PERM_READ_ENCRYPTED, 2, 2, (uint8_t *)&s_hid_le_svc);
  252. add_db_record(_last_db, HIDD_LE_IDX_INCL_SVC, (uint8_t *)&s_include_service_uuid, ESP_GATT_PERM_READ, sizeof(esp_gatts_incl_svc_desc_t), sizeof(esp_gatts_incl_svc_desc_t), (uint8_t *)&dev->hid_incl_svc);
  253. add_db_record(_last_db, HIDD_LE_IDX_HID_INFO_CHAR, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read);
  254. add_db_record(_last_db, HIDD_LE_IDX_HID_INFO_VAL, (uint8_t *)&s_hid_info_char_uuid, ESP_GATT_PERM_READ, 4, 4, (uint8_t *)hidInfo);
  255. add_db_record(_last_db, HIDD_LE_IDX_HID_CTNL_PT_CHAR, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_write_nr);
  256. add_db_record(_last_db, HIDD_LE_IDX_HID_CTNL_PT_VAL, (uint8_t *)&s_hid_control_point_uuid, ESP_GATT_PERM_READ, 1, 0, NULL);
  257. add_db_record(_last_db, HIDD_LE_IDX_PROTO_MODE_CHAR, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read_write_nr);
  258. add_db_record(_last_db, HIDD_LE_IDX_PROTO_MODE_VAL, (uint8_t *)&s_hid_proto_mode_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, 1, 1, (uint8_t *)&dev->protocol);
  259. add_db_record(_last_db, HIDD_LE_IDX_REPORT_MAP_CHAR, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read);
  260. add_db_record(_last_db, HIDD_LE_IDX_REPORT_MAP_VAL, (uint8_t *)&s_hid_report_map_uuid, ESP_GATT_PERM_READ, HIDD_LE_REPORT_MAP_MAX_LEN, dev->devices[device_index].reports_map.len, (uint8_t *)dev->devices[device_index].reports_map.data);
  261. add_db_record(_last_db, HIDD_LE_IDX_REPORT_MAP_EXT_REP_REF, (uint8_t *)&s_hid_report_map_ext_desc_uuid, ESP_GATT_PERM_READ, 2, 2, (uint8_t *)&s_bat_level_uuid);
  262. size_t index = HIDD_LE_IDX_NB;
  263. for (uint8_t i = 0; i < dev->devices[device_index].reports_len; i++) {
  264. hidd_le_report_item_t *report = &dev->devices[device_index].reports[i];
  265. if (report->protocol_mode == ESP_HID_PROTOCOL_MODE_REPORT) {
  266. if (report->report_type == ESP_HID_REPORT_TYPE_INPUT) {
  267. //Input Report
  268. add_db_record(_last_db, index++, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read_notify);
  269. report->index = index;
  270. add_db_record(_last_db, index++, (uint8_t *)&s_hid_report_uuid, ESP_GATT_PERM_READ, report->value_len, 0, NULL);
  271. add_db_record(_last_db, index++, (uint8_t *)&s_character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, 2, 0, NULL);
  272. } else {
  273. //Output or Feature Report
  274. add_db_record(_last_db, index++, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read_write);
  275. report->index = index;
  276. add_db_record(_last_db, index++, (uint8_t *)&s_hid_report_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, report->value_len, 0, NULL);
  277. }
  278. add_db_record(_last_db, index++, (uint8_t *)&s_hid_report_ref_descr_uuid, ESP_GATT_PERM_READ, 2, 2, (uint8_t *)&report->report_id);
  279. } else {
  280. if (report->report_type == ESP_HID_REPORT_TYPE_INPUT) {
  281. add_db_record(_last_db, index++, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read_notify);
  282. report->index = index;
  283. if (report->usage == ESP_HID_USAGE_KEYBOARD) { //Boot Keyboard Input
  284. add_db_record(_last_db, index++, (uint8_t *)&s_hid_boot_kb_input_uuid, ESP_GATT_PERM_READ, HIDD_LE_BOOT_REPORT_MAX_LEN, 0, NULL);
  285. } else { //Boot Mouse Input
  286. add_db_record(_last_db, index++, (uint8_t *)&s_hid_boot_mouse_input_uuid, ESP_GATT_PERM_READ, HIDD_LE_BOOT_REPORT_MAX_LEN, 0, NULL);
  287. }
  288. add_db_record(_last_db, index++, (uint8_t *)&s_character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, 2, 0, NULL);
  289. } else { //Boot Keyboard Output
  290. add_db_record(_last_db, index++, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read_write);
  291. report->index = index;
  292. add_db_record(_last_db, index++, (uint8_t *)&s_hid_boot_kb_output_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, HIDD_LE_BOOT_REPORT_MAX_LEN, 0, NULL);
  293. }
  294. }
  295. }
  296. esp_err_t err = esp_ble_gatts_create_attr_tab(_last_db, dev->devices[device_index].hid_svc.gatt_if, index, device_index);
  297. return err;
  298. }
  299. static void link_report_handles(hidd_dev_map_t *dev, uint16_t *handles)
  300. {
  301. hidd_le_report_item_t *rpt = NULL;
  302. for (uint8_t i = 0; i < dev->reports_len; i++) {
  303. rpt = &dev->reports[i];
  304. rpt->handle = handles[rpt->index];
  305. if (rpt->report_type == ESP_HID_REPORT_TYPE_INPUT) {
  306. rpt->ccc_handle = handles[rpt->index + 1];
  307. }
  308. }
  309. }
  310. static hidd_le_report_item_t *get_report_by_handle(esp_ble_hidd_dev_t *dev, uint16_t handle)
  311. {
  312. hidd_le_report_item_t *rpt = NULL;
  313. for (uint8_t d = 0; d < dev->devices_len; d++) {
  314. for (uint8_t i = 0; i < dev->devices[d].reports_len; i++) {
  315. rpt = &dev->devices[d].reports[i];
  316. if (rpt->handle == handle || rpt->ccc_handle == handle) {
  317. return rpt;
  318. }
  319. }
  320. }
  321. return NULL;
  322. }
  323. static hidd_le_report_item_t *get_report_by_id_and_type(esp_ble_hidd_dev_t *dev, uint8_t id, uint8_t type)
  324. {
  325. hidd_le_report_item_t *rpt = NULL;
  326. for (uint8_t d = 0; d < dev->devices_len; d++) {
  327. for (uint8_t i = 0; i < dev->devices[d].reports_len; i++) {
  328. rpt = &dev->devices[d].reports[i];
  329. if (rpt->report_id == id && rpt->report_type == type && rpt->protocol_mode == ESP_HID_PROTOCOL_MODE_REPORT) {
  330. return rpt;
  331. }
  332. }
  333. }
  334. return NULL;
  335. }
  336. static void bat_event_handler(esp_ble_hidd_dev_t *dev, esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
  337. {
  338. switch (event) {
  339. case ESP_GATTS_REG_EVT:
  340. ESP_LOGV(TAG, "Battery REG App ID: 0x%x", param->reg.app_id);
  341. break;
  342. case ESP_GATTS_CREAT_ATTR_TAB_EVT:
  343. dev->bat_svc.handle = param->add_attr_tab.handles[BAS_IDX_SVC];
  344. dev->bat_level_handle = param->add_attr_tab.handles[BAS_IDX_BATT_LVL_VAL];//so we notify of the change
  345. dev->bat_ccc_handle = param->add_attr_tab.handles[BAS_IDX_BATT_LVL_CCC];//so we know if we can send notify
  346. ESP_LOGV(TAG, "Battery CREAT_ATTR_TAB service handle = %d", dev->bat_svc.handle);
  347. dev->hid_incl_svc.start_hdl = dev->bat_svc.handle;
  348. dev->hid_incl_svc.end_hdl = dev->bat_svc.handle + BAS_IDX_NB - 1;
  349. esp_ble_gatts_start_service(dev->bat_svc.handle);
  350. // Add the info service next, because it's shared between all device maps
  351. create_info_db(dev);
  352. break;
  353. case ESP_GATTS_READ_EVT:
  354. if (param->read.handle == dev->bat_level_handle) {
  355. ESP_LOGD(TAG, "Battery READ %d", dev->bat_level);
  356. }
  357. break;
  358. case ESP_GATTS_WRITE_EVT: {
  359. if (param->write.handle == dev->bat_ccc_handle) {
  360. dev->bat_ccc.value = param->write.value[0];
  361. ESP_LOGV(TAG, "Battery CCC: Notify: %s, Indicate: %s", dev->bat_ccc.notify_enable ? "On" : "Off", dev->bat_ccc.indicate_enable ? "On" : "Off");
  362. }
  363. break;
  364. }
  365. case ESP_GATTS_SET_ATTR_VAL_EVT: {
  366. if (param->set_attr_val.attr_handle == dev->bat_level_handle) {
  367. ESP_LOGD(TAG, "Battery SET %d, status: 0x%02x", dev->bat_level, param->set_attr_val.status);
  368. }
  369. break;
  370. }
  371. default:
  372. ESP_LOGV(TAG, "Battery %s", gatts_evt_str(event));
  373. break;
  374. }
  375. }
  376. static void info_event_handler(esp_ble_hidd_dev_t *dev, esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
  377. {
  378. switch (event) {
  379. case ESP_GATTS_REG_EVT:
  380. ESP_LOGV(TAG, "Dev Info REG App ID: 0x%x", param->reg.app_id);
  381. break;
  382. case ESP_GATTS_CREAT_ATTR_TAB_EVT:
  383. dev->info_svc.handle = param->add_attr_tab.handles[0];
  384. ESP_LOGV(TAG, "Dev Info service handle = %d", dev->info_svc.handle);
  385. esp_ble_gatts_start_service(dev->info_svc.handle);
  386. create_hid_db(dev, 0);
  387. break;
  388. default:
  389. ESP_LOGV(TAG, "Dev Info %s", gatts_evt_str(event));
  390. break;
  391. }
  392. }
  393. static void hid_event_handler(esp_ble_hidd_dev_t *dev, int device_index, esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
  394. {
  395. switch (event) {
  396. case ESP_GATTS_REG_EVT: {
  397. ESP_LOGV(TAG, "HID REG[%d] App ID: 0x%x", device_index, param->reg.app_id);
  398. // is this the last report map app?
  399. if (device_index == (dev->devices_len - 1)) {
  400. // we should add the battery service first, because the hid service should include the battery service.
  401. create_bat_db(dev);
  402. }
  403. break;
  404. }
  405. case ESP_GATTS_CREAT_ATTR_TAB_EVT: {
  406. dev->devices[device_index].hid_svc.handle = param->add_attr_tab.handles[HIDD_LE_IDX_SVC];
  407. dev->devices[device_index].hid_control_handle = param->add_attr_tab.handles[HIDD_LE_IDX_HID_CTNL_PT_VAL];
  408. dev->devices[device_index].hid_protocol_handle = param->add_attr_tab.handles[HIDD_LE_IDX_PROTO_MODE_VAL];
  409. ESP_LOGV(TAG, "HID CREAT_ATTR_TAB[%u] service handle = %d", device_index, dev->devices[device_index].hid_svc.handle);
  410. link_report_handles(&dev->devices[device_index], param->add_attr_tab.handles);
  411. esp_ble_gatts_start_service(dev->devices[device_index].hid_svc.handle);
  412. if ((device_index + 1) < dev->devices_len) {
  413. create_hid_db(dev, device_index + 1);//add next device
  414. }
  415. break;
  416. }
  417. case ESP_GATTS_START_EVT: {
  418. ESP_LOGD(TAG, "HID START[%d] status: 0x%02x", device_index, param->start.status);
  419. if (device_index == (dev->devices_len - 1)) {
  420. esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_START_EVENT, NULL, 0, portMAX_DELAY);
  421. }
  422. break;
  423. }
  424. case ESP_GATTS_CONNECT_EVT: {
  425. ESP_LOGD(TAG, "HID CONNECT[%d] conn_id = %x", device_index, param->connect.conn_id);
  426. if (!dev->connected && device_index == (dev->devices_len - 1)) {
  427. dev->connected = true;
  428. dev->conn_id = param->connect.conn_id;
  429. memcpy(dev->remote_bda, param->connect.remote_bda, ESP_BD_ADDR_LEN);
  430. esp_ble_set_encryption(param->connect.remote_bda, ESP_BLE_SEC_ENCRYPT_NO_MITM);
  431. esp_hidd_event_data_t cb_param = {
  432. .connect.dev = dev->dev,
  433. };
  434. esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_CONNECT_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
  435. }
  436. break;
  437. }
  438. case ESP_GATTS_DISCONNECT_EVT: {
  439. ESP_LOGD(TAG, "HID DISCONNECT[%d] 0x%x", device_index, param->disconnect.reason);
  440. if (dev->connected) {
  441. dev->connected = false;
  442. esp_hidd_event_data_t cb_param = {0};
  443. cb_param.disconnect.dev = dev->dev;
  444. cb_param.disconnect.reason = param->disconnect.reason;
  445. esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_DISCONNECT_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
  446. }
  447. break;
  448. }
  449. case ESP_GATTS_READ_EVT: {
  450. hidd_le_report_item_t *map = get_report_by_handle(dev, param->read.handle);
  451. if (map && map->handle == param->read.handle) {
  452. ESP_LOGV(TAG, "HID READ[%d] %8s %7s %6s id: %d, need_resp: %d", device_index, esp_hid_usage_str(map->usage), esp_hid_report_type_str(map->report_type), esp_hid_protocol_mode_str(map->protocol_mode), map->report_id, param->read.need_rsp);
  453. }
  454. break;
  455. }
  456. case ESP_GATTS_WRITE_EVT: {
  457. if (param->write.handle == dev->devices[device_index].hid_control_handle) {
  458. dev->control = param->write.value[0];
  459. esp_hidd_event_data_t cb_param = {0};
  460. cb_param.control.dev = dev->dev;
  461. cb_param.control.control = dev->control;
  462. cb_param.control.map_index = device_index;
  463. esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_CONTROL_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
  464. } else if (param->write.handle == dev->devices[device_index].hid_protocol_handle) {
  465. dev->protocol = param->write.value[0];
  466. esp_hidd_event_data_t cb_param = {};
  467. cb_param.protocol_mode.dev = dev->dev;
  468. cb_param.protocol_mode.protocol_mode = dev->protocol;
  469. cb_param.protocol_mode.map_index = device_index;
  470. esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_PROTOCOL_MODE_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
  471. } else {
  472. hidd_le_report_item_t *map = get_report_by_handle(dev, param->write.handle);
  473. if (map) {
  474. if (param->write.handle == map->ccc_handle) {
  475. map->ccc.value = param->write.value[0];
  476. ESP_LOGV(TAG, "HID CCC[%d] %8s %7s %6s id: %d, Notify: %s, Indicate: %s", device_index, esp_hid_usage_str(map->usage), esp_hid_report_type_str(map->report_type), esp_hid_protocol_mode_str(map->protocol_mode), map->report_id, map->ccc.notify_enable ? "On" : "Off", map->ccc.indicate_enable ? "On" : "Off");
  477. } else {
  478. ESP_LOGV(TAG, "HID WRITE %8s %7s %6s id: %d, len: %d", esp_hid_usage_str(map->usage), esp_hid_report_type_str(map->report_type), esp_hid_protocol_mode_str(map->protocol_mode), map->report_id, param->write.len);
  479. esp_hidd_event_data_t cb_param = {0};
  480. if (map->report_type == ESP_HID_REPORT_TYPE_OUTPUT) {
  481. cb_param.output.dev = dev->dev;
  482. cb_param.output.report_id = map->report_id;
  483. cb_param.output.usage = map->usage;
  484. cb_param.output.length = param->write.len;
  485. cb_param.output.data = param->write.value;
  486. cb_param.output.map_index = device_index;
  487. esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_OUTPUT_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
  488. } else {
  489. cb_param.feature.dev = dev->dev;
  490. cb_param.feature.report_id = map->report_id;
  491. cb_param.feature.usage = map->usage;
  492. cb_param.feature.length = param->write.len;
  493. cb_param.feature.data = param->write.value;
  494. cb_param.feature.map_index = device_index;
  495. esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
  496. }
  497. }
  498. }
  499. }
  500. break;
  501. }
  502. case ESP_GATTS_SET_ATTR_VAL_EVT: {
  503. hidd_le_report_item_t *map = get_report_by_handle(dev, param->set_attr_val.attr_handle);
  504. if (map && map->handle == param->set_attr_val.attr_handle) {
  505. ESP_LOGV(TAG, "HID SET[%d] %8s %7s %6s id: %d, status: 0x%02x", device_index, esp_hid_usage_str(map->usage), esp_hid_report_type_str(map->report_type), esp_hid_protocol_mode_str(map->protocol_mode), map->report_id, param->set_attr_val.status);
  506. }
  507. SEND_CB(dev);
  508. break;
  509. }
  510. case ESP_GATTS_CONF_EVT: {
  511. ESP_LOGV(TAG, "HID CONF[%d] status: 0x%02x, len: %d", device_index, param->conf.status, param->conf.len);
  512. SEND_CB(dev);
  513. break;
  514. }
  515. case ESP_GATTS_MTU_EVT:
  516. ESP_LOGV(TAG, "HID[%d] MTU = %d", device_index, param->mtu.mtu);
  517. break;
  518. default:
  519. ESP_LOGV(TAG, "HID[%d] %s", device_index, gatts_evt_str(event));
  520. break;
  521. }
  522. }
  523. static int get_device_map_index_by_gatts_if (esp_ble_hidd_dev_t *dev, esp_gatt_if_t gatts_if)
  524. {
  525. for (uint8_t d = 0; d < dev->devices_len; d++) {
  526. if (dev->devices[d].hid_svc.gatt_if && gatts_if == dev->devices[d].hid_svc.gatt_if) {
  527. return d;
  528. }
  529. }
  530. return -1;
  531. }
  532. static esp_err_t ble_hid_start_gatts(esp_ble_hidd_dev_t *dev)
  533. {
  534. esp_err_t ret;
  535. if ((ret = esp_ble_gatts_app_register(ESP_GATT_UUID_BATTERY_SERVICE_SVC)) != ESP_OK) {
  536. ESP_LOGE(TAG, "GATTS register battery service failed: %d", ret);
  537. return ret;
  538. }
  539. if ((ret = esp_ble_gatts_app_register(ESP_GATT_UUID_DEVICE_INFO_SVC)) != ESP_OK) {
  540. ESP_LOGE(TAG, "GATTS register device info service failed: %d", ret);
  541. return ret;
  542. }
  543. for (uint8_t i = 0; i < dev->devices_len; i++) {
  544. if ((ret = esp_ble_gatts_app_register(ESP_GATT_UUID_HID_SVC + i)) != ESP_OK) {
  545. ESP_LOGE(TAG, "GATTS register HID[%u] service failed: %d", i, ret);
  546. return ret;
  547. }
  548. }
  549. return ret;
  550. }
  551. static esp_err_t ble_hid_stop_gatts(esp_ble_hidd_dev_t *dev)
  552. {
  553. esp_err_t ret = ESP_OK;
  554. for (uint8_t d = 0; d < dev->devices_len; d++) {
  555. esp_ble_gatts_stop_service(dev->devices[d].hid_svc.handle);
  556. esp_ble_gatts_delete_service(dev->devices[d].hid_svc.handle);
  557. esp_ble_gatts_app_unregister(dev->devices[d].hid_svc.gatt_if);
  558. }
  559. esp_ble_gatts_stop_service(dev->info_svc.handle);
  560. esp_ble_gatts_delete_service(dev->info_svc.handle);
  561. esp_ble_gatts_app_unregister(dev->info_svc.gatt_if);
  562. esp_ble_gatts_stop_service(dev->bat_svc.handle);
  563. esp_ble_gatts_delete_service(dev->bat_svc.handle);
  564. esp_ble_gatts_app_unregister(dev->bat_svc.gatt_if);
  565. return ret;
  566. }
  567. static esp_err_t ble_hid_init_config(esp_ble_hidd_dev_t *dev, const esp_hid_device_config_t *config)
  568. {
  569. memset((uint8_t *)(&dev->config), 0, sizeof(esp_hid_device_config_t));
  570. dev->config.vendor_id = config->vendor_id;
  571. dev->config.product_id = config->product_id;
  572. dev->config.version = config->version;
  573. if (config->device_name != NULL) {
  574. dev->config.device_name = strdup(config->device_name);
  575. }
  576. if (config->manufacturer_name != NULL) {
  577. dev->config.manufacturer_name = strdup(config->manufacturer_name);
  578. }
  579. if (config->serial_number != NULL) {
  580. dev->config.serial_number = strdup(config->serial_number);
  581. }
  582. dev->appearance = ESP_HID_APPEARANCE_GENERIC;
  583. if (config->report_maps_len) {
  584. dev->devices = (hidd_dev_map_t *)malloc(config->report_maps_len * sizeof(hidd_dev_map_t));
  585. if (dev->devices == NULL) {
  586. ESP_LOGE(TAG, "devices malloc(%d) failed", config->report_maps_len);
  587. return ESP_FAIL;
  588. }
  589. memset(dev->devices, 0, config->report_maps_len * sizeof(hidd_dev_map_t));
  590. dev->devices_len = config->report_maps_len;
  591. for (uint8_t d = 0; d < dev->devices_len; d++) {
  592. //raw report map
  593. uint8_t *map = (uint8_t *)malloc(config->report_maps[d].len);
  594. if (map == NULL) {
  595. ESP_LOGE(TAG, "report map malloc(%d) failed", config->report_maps[d].len);
  596. return ESP_FAIL;
  597. }
  598. memcpy(map, config->report_maps[d].data, config->report_maps[d].len);
  599. dev->devices[d].reports_map.data = (const uint8_t *)map;
  600. dev->devices[d].reports_map.len = config->report_maps[d].len;
  601. esp_hid_report_map_t *rmap = esp_hid_parse_report_map(config->report_maps[d].data, config->report_maps[d].len);
  602. if (rmap == NULL) {
  603. ESP_LOGE(TAG, "hid_parse_report_map[%d](%d) failed", d, config->report_maps[d].len);
  604. return ESP_FAIL;
  605. }
  606. dev->appearance = rmap->appearance;
  607. dev->devices[d].reports_len = rmap->reports_len;
  608. dev->devices[d].reports = (hidd_le_report_item_t *)malloc(rmap->reports_len * sizeof(hidd_le_report_item_t));
  609. if (dev->devices[d].reports == NULL) {
  610. ESP_LOGE(TAG, "reports malloc(%d) failed", rmap->reports_len * sizeof(hidd_le_report_item_t));
  611. free(rmap);
  612. return ESP_FAIL;
  613. }
  614. for (uint8_t r = 0; r < rmap->reports_len; r++) {
  615. dev->devices[d].reports[r].map_index = d;
  616. dev->devices[d].reports[r].report_id = rmap->reports[r].report_id;
  617. dev->devices[d].reports[r].protocol_mode = rmap->reports[r].protocol_mode;
  618. dev->devices[d].reports[r].report_type = rmap->reports[r].report_type;
  619. dev->devices[d].reports[r].usage = rmap->reports[r].usage;
  620. dev->devices[d].reports[r].value_len = rmap->reports[r].value_len;
  621. }
  622. free(rmap->reports);
  623. free(rmap);
  624. }
  625. }
  626. return ESP_OK;
  627. }
  628. static esp_err_t ble_hid_free_config(esp_ble_hidd_dev_t *dev)
  629. {
  630. for (uint8_t d = 0; d < dev->devices_len; d++) {
  631. free((void *)dev->devices[d].reports);
  632. free((void *)dev->devices[d].reports_map.data);
  633. }
  634. free((void *)dev->devices);
  635. free((void *)dev->config.device_name);
  636. free((void *)dev->config.manufacturer_name);
  637. free((void *)dev->config.serial_number);
  638. if (dev->sem != NULL) {
  639. vSemaphoreDelete(dev->sem);
  640. }
  641. if (dev->event_loop_handle != NULL) {
  642. esp_event_loop_delete(dev->event_loop_handle);
  643. }
  644. return ESP_OK;
  645. }
  646. /*
  647. * PUBLIC FUNCTIONS
  648. * */
  649. // there can be only one BLE HID device
  650. static esp_ble_hidd_dev_t *s_dev = NULL;
  651. void esp_hidd_gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
  652. {
  653. if (!s_dev) {
  654. return;
  655. }
  656. if (event == ESP_GATTS_REG_EVT) {
  657. if (param->reg.status != ESP_GATT_OK) {
  658. ESP_LOGE(TAG, "Reg app failed, app_id %04x, status %d", param->reg.app_id, param->reg.status);
  659. return;
  660. } else {
  661. if (param->reg.app_id == ESP_GATT_UUID_DEVICE_INFO_SVC) {
  662. s_dev->info_svc.gatt_if = gatts_if;
  663. } else if (param->reg.app_id == ESP_GATT_UUID_BATTERY_SERVICE_SVC) {
  664. s_dev->bat_svc.gatt_if = gatts_if;
  665. } else if (param->reg.app_id >= ESP_GATT_UUID_HID_SVC && param->reg.app_id < (ESP_GATT_UUID_HID_SVC + s_dev->devices_len)) {
  666. ESP_LOGV(TAG, "HID SVC[%u] IF: %d", param->reg.app_id - ESP_GATT_UUID_HID_SVC, gatts_if);
  667. s_dev->devices[param->reg.app_id - ESP_GATT_UUID_HID_SVC].hid_svc.gatt_if = gatts_if;
  668. } else {
  669. ESP_LOGE(TAG, "Unknown Application, app_id %04x", param->reg.app_id);
  670. return;
  671. }
  672. }
  673. } else if (event == ESP_GATTS_CREAT_ATTR_TAB_EVT) {
  674. free(_last_db);
  675. _last_db = NULL;
  676. }
  677. if (s_dev->bat_svc.gatt_if && gatts_if == s_dev->bat_svc.gatt_if) {
  678. bat_event_handler(s_dev, event, gatts_if, param);
  679. } else if (s_dev->info_svc.gatt_if && gatts_if == s_dev->info_svc.gatt_if) {
  680. info_event_handler(s_dev, event, gatts_if, param);
  681. } else {
  682. int devi = get_device_map_index_by_gatts_if (s_dev, gatts_if);
  683. if (devi >= 0) {
  684. hid_event_handler(s_dev, devi, event, gatts_if, param);
  685. } else {
  686. ESP_LOGE(TAG, "Unknown gatts_if %u", gatts_if);
  687. }
  688. return;
  689. }
  690. }
  691. static esp_err_t esp_ble_hidd_dev_deinit(void *devp)
  692. {
  693. esp_ble_hidd_dev_t *dev = (esp_ble_hidd_dev_t *)devp;
  694. if (!s_dev) {
  695. ESP_LOGE(TAG, "HID device profile already uninitialized");
  696. return ESP_OK;
  697. }
  698. if (s_dev != dev) {
  699. ESP_LOGE(TAG, "Wrong HID device provided");
  700. return ESP_FAIL;
  701. }
  702. s_dev = NULL;
  703. ble_hid_stop_gatts(dev);
  704. esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_STOP_EVENT, NULL, 0, portMAX_DELAY);
  705. ble_hid_free_config(dev);
  706. free(dev);
  707. return ESP_OK;
  708. }
  709. static bool esp_ble_hidd_dev_connected(void *devp)
  710. {
  711. esp_ble_hidd_dev_t *dev = (esp_ble_hidd_dev_t *)devp;
  712. return (dev != NULL && s_dev == dev && dev->connected);
  713. }
  714. static esp_err_t esp_ble_hidd_dev_battery_set(void *devp, uint8_t level)
  715. {
  716. esp_err_t ret;
  717. esp_ble_hidd_dev_t *dev = (esp_ble_hidd_dev_t *)devp;
  718. if (!dev || s_dev != dev) {
  719. return ESP_FAIL;
  720. }
  721. dev->bat_level = level;
  722. if (!dev->connected || dev->bat_ccc.value == 0) {
  723. //if we are not yet connected, that is not an error
  724. return ESP_OK;
  725. }
  726. ret = esp_ble_gatts_send_indicate(dev->bat_svc.gatt_if, dev->conn_id, dev->bat_level_handle, 1, &dev->bat_level, dev->bat_ccc.indicate_enable);
  727. if (ret) {
  728. ESP_LOGE(TAG, "esp_ble_gatts_send_indicate failed: %d", ret);
  729. return ESP_FAIL;
  730. }
  731. WAIT_CB(dev);
  732. return ESP_OK;
  733. }
  734. static esp_err_t esp_ble_hidd_dev_input_set(void *devp, size_t index, size_t id, uint8_t *data, size_t length)
  735. {
  736. hidd_le_report_item_t *p_rpt;
  737. esp_ble_hidd_dev_t *dev = (esp_ble_hidd_dev_t *)devp;
  738. if (!dev || s_dev != dev) {
  739. return ESP_FAIL;
  740. }
  741. if (!dev->connected) {
  742. ESP_LOGE(TAG, "Device Not Connected: %d", index);
  743. return ESP_FAIL;
  744. }
  745. if ((p_rpt = get_report_by_id_and_type(dev, id, ESP_HID_REPORT_TYPE_INPUT)) != NULL && p_rpt->ccc.value) {
  746. esp_err_t err = esp_ble_gatts_send_indicate(dev->devices[index].hid_svc.gatt_if, dev->conn_id, p_rpt->handle, length, data, p_rpt->ccc.indicate_enable);
  747. if (err != ESP_OK) {
  748. ESP_LOGE(TAG, "Send Input Indicate Failed: %d", err);
  749. return ESP_FAIL;
  750. }
  751. WAIT_CB(dev);
  752. } else {
  753. ESP_LOGE(TAG, "Indicate Not Enabled: %d", 0);
  754. return ESP_FAIL;
  755. }
  756. return ESP_OK;
  757. }
  758. static esp_err_t esp_ble_hidd_dev_feature_set(void *devp, size_t index, size_t id, uint8_t *data, size_t length)
  759. {
  760. esp_err_t ret;
  761. esp_ble_hidd_dev_t *dev = (esp_ble_hidd_dev_t *)devp;
  762. if (!dev || s_dev != dev) {
  763. return ESP_FAIL;
  764. }
  765. hidd_le_report_item_t *p_rpt;
  766. if ((p_rpt = get_report_by_id_and_type(dev, id, ESP_HID_REPORT_TYPE_FEATURE)) != NULL) {
  767. ret = esp_ble_gatts_set_attr_value(p_rpt->handle, length, data);
  768. if (ret) {
  769. ESP_LOGE(TAG, "esp_ble_gatts_set_attr_value failed: %d", ret);
  770. return ESP_FAIL;
  771. }
  772. WAIT_CB(dev);
  773. if (dev->connected && p_rpt->ccc.value) {
  774. ret = esp_ble_gatts_send_indicate(dev->devices[index].hid_svc.gatt_if, dev->conn_id, p_rpt->handle, length, data, p_rpt->ccc.indicate_enable);
  775. if (ret != ESP_OK) {
  776. ESP_LOGE(TAG, "Send Feature Indicate Failed: %d", ret);
  777. return ESP_FAIL;
  778. }
  779. WAIT_CB(dev);
  780. }
  781. } else {
  782. ESP_LOGE(TAG, "FEATURE %d not found", id);
  783. return ESP_FAIL;
  784. }
  785. return ESP_OK;
  786. }
  787. static esp_err_t esp_ble_hidd_dev_event_handler_register(void *devp, esp_event_handler_t callback, esp_hidd_event_t event)
  788. {
  789. esp_ble_hidd_dev_t *dev = (esp_ble_hidd_dev_t *)devp;
  790. if (!dev || s_dev != dev) {
  791. return ESP_FAIL;
  792. }
  793. return esp_event_handler_register_with(dev->event_loop_handle, ESP_HIDD_EVENTS, event, callback, dev->dev);
  794. }
  795. static esp_err_t esp_ble_hidd_dev_event_handler_unregister(void *devp, esp_event_handler_t callback, esp_hidd_event_t event)
  796. {
  797. esp_ble_hidd_dev_t *dev = (esp_ble_hidd_dev_t *)devp;
  798. if (!dev || s_dev != dev) {
  799. return ESP_FAIL;
  800. }
  801. return esp_event_handler_unregister_with(dev->event_loop_handle, ESP_HIDD_EVENTS, event, callback);
  802. }
  803. static void ble_hidd_dev_free(void)
  804. {
  805. ble_hid_free_config(s_dev);
  806. free(s_dev);
  807. s_dev = NULL;
  808. }
  809. esp_err_t esp_ble_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_config_t *config, esp_event_handler_t callback)
  810. {
  811. esp_err_t ret;
  812. if (s_dev) {
  813. ESP_LOGE(TAG, "HID device profile already initialized");
  814. return ESP_FAIL;
  815. }
  816. s_dev = (esp_ble_hidd_dev_t *)calloc(1, sizeof(esp_ble_hidd_dev_t));
  817. if (s_dev == NULL) {
  818. ESP_LOGE(TAG, "HID device could not be allocated");
  819. return ESP_FAIL;
  820. }
  821. // Reset the hid device target environment
  822. s_dev->bat_level = 100;
  823. s_dev->bat_ccc.value = 0;
  824. s_dev->control = ESP_HID_CONTROL_EXIT_SUSPEND;
  825. s_dev->protocol = ESP_HID_PROTOCOL_MODE_REPORT;
  826. s_dev->event_loop_handle = NULL;
  827. s_dev->dev = dev_p;
  828. s_dev->sem = xSemaphoreCreateBinary();
  829. if (s_dev->sem == NULL) {
  830. ESP_LOGE(TAG, "HID device semaphore could not be allocated");
  831. ble_hidd_dev_free();
  832. return ESP_FAIL;
  833. }
  834. esp_event_loop_args_t event_task_args = {
  835. .queue_size = 5,
  836. .task_name = "ble_hidd_events",
  837. .task_priority = uxTaskPriorityGet(NULL),
  838. .task_stack_size = 2048,
  839. .task_core_id = tskNO_AFFINITY
  840. };
  841. ret = esp_event_loop_create(&event_task_args, &s_dev->event_loop_handle);
  842. if (ret != ESP_OK) {
  843. ESP_LOGE(TAG, "HID device event loop could not be created");
  844. ble_hidd_dev_free();
  845. return ret;
  846. }
  847. ret = ble_hid_init_config(s_dev, config);
  848. if (ret != ESP_OK) {
  849. ble_hidd_dev_free();
  850. return ret;
  851. }
  852. dev_p->dev = s_dev;
  853. dev_p->connected = esp_ble_hidd_dev_connected;
  854. dev_p->deinit = esp_ble_hidd_dev_deinit;
  855. dev_p->battery_set = esp_ble_hidd_dev_battery_set;
  856. dev_p->input_set = esp_ble_hidd_dev_input_set;
  857. dev_p->feature_set = esp_ble_hidd_dev_feature_set;
  858. dev_p->event_handler_register = esp_ble_hidd_dev_event_handler_register;
  859. dev_p->event_handler_unregister = esp_ble_hidd_dev_event_handler_unregister;
  860. if (callback != NULL) {
  861. ret = esp_ble_hidd_dev_event_handler_register(s_dev, callback, ESP_EVENT_ANY_ID);
  862. if (ret != ESP_OK) {
  863. ble_hidd_dev_free();
  864. return ret;
  865. }
  866. }
  867. ret = ble_hid_start_gatts(s_dev);
  868. if (ret != ESP_OK) {
  869. ble_hidd_dev_free();
  870. return ret;
  871. }
  872. return ret;
  873. }
  874. #endif /* CONFIG_GATTS_ENABLE */