esp_hidh.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 "sys/queue.h"
  14. #include "esp_hidh_private.h"
  15. #include "bt_hidh.h"
  16. #include "ble_hidh.h"
  17. #include <string.h>
  18. #include <stdbool.h>
  19. #include "esp_event_base.h"
  20. ESP_EVENT_DEFINE_BASE(ESP_HIDH_EVENTS);
  21. static const char *TAG = "ESP_HIDH";
  22. static esp_hidh_dev_head_t s_esp_hidh_devices;
  23. static xSemaphoreHandle s_esp_hidh_devices_semaphore = NULL;
  24. static inline void lock_devices(void)
  25. {
  26. if (s_esp_hidh_devices_semaphore != NULL) {
  27. xSemaphoreTake(s_esp_hidh_devices_semaphore, portMAX_DELAY);
  28. }
  29. }
  30. static inline void unlock_devices(void)
  31. {
  32. if (s_esp_hidh_devices_semaphore != NULL) {
  33. xSemaphoreGive(s_esp_hidh_devices_semaphore);
  34. }
  35. }
  36. static bool esp_hidh_dev_exists(esp_hidh_dev_t *dev)
  37. {
  38. if (dev == NULL) {
  39. return false;
  40. }
  41. esp_hidh_dev_t * d = NULL;
  42. lock_devices();
  43. TAILQ_FOREACH(d, &s_esp_hidh_devices, devices) {
  44. if (d == dev) {
  45. unlock_devices();
  46. return true;
  47. }
  48. }
  49. unlock_devices();
  50. return false;
  51. }
  52. /*
  53. * Public Functions
  54. * */
  55. esp_err_t esp_hidh_init(const esp_hidh_config_t *config)
  56. {
  57. esp_err_t err = ESP_FAIL;
  58. if (config == NULL) {
  59. ESP_LOGE(TAG, "Config is NULL");
  60. return err;
  61. }
  62. if (s_esp_hidh_devices_semaphore != NULL) {
  63. ESP_LOGE(TAG, "Already initialized");
  64. return err;
  65. }
  66. s_esp_hidh_devices_semaphore = xSemaphoreCreateBinary();
  67. if (s_esp_hidh_devices_semaphore == NULL) {
  68. ESP_LOGE(TAG, "xSemaphoreCreateMutex failed!");
  69. return err;
  70. }
  71. err = ESP_OK;
  72. #if CONFIG_BT_HID_HOST_ENABLED
  73. if (err == ESP_OK) {
  74. err = esp_bt_hidh_init(config);
  75. }
  76. #endif /* CONFIG_BT_HID_HOST_ENABLED */
  77. #if CONFIG_GATTC_ENABLE
  78. if (err == ESP_OK) {
  79. err = esp_ble_hidh_init(config);
  80. }
  81. #endif /* CONFIG_GATTC_ENABLE */
  82. if (err == ESP_OK) {
  83. TAILQ_INIT(&s_esp_hidh_devices);
  84. unlock_devices();
  85. } else {
  86. vSemaphoreDelete(s_esp_hidh_devices_semaphore);
  87. s_esp_hidh_devices_semaphore = NULL;
  88. }
  89. return err;
  90. }
  91. esp_err_t esp_hidh_deinit(void)
  92. {
  93. esp_err_t err = ESP_FAIL;
  94. if (s_esp_hidh_devices_semaphore == NULL) {
  95. ESP_LOGE(TAG, "Already uninitialized");
  96. return err;
  97. }
  98. if (!TAILQ_EMPTY(&s_esp_hidh_devices)) {
  99. ESP_LOGE(TAG, "Please disconnect all devices first!");
  100. return err;
  101. }
  102. err = ESP_OK;
  103. #if CONFIG_BT_HID_HOST_ENABLED
  104. if (err == ESP_OK) {
  105. err = esp_bt_hidh_deinit();
  106. }
  107. #endif /* CONFIG_BT_HID_HOST_ENABLED */
  108. #if CONFIG_GATTC_ENABLE
  109. if (err == ESP_OK) {
  110. err = esp_ble_hidh_deinit();
  111. }
  112. #endif /* CONFIG_GATTC_ENABLE */
  113. if (err == ESP_OK) {
  114. TAILQ_INIT(&s_esp_hidh_devices);
  115. vSemaphoreDelete(s_esp_hidh_devices_semaphore);
  116. s_esp_hidh_devices_semaphore = NULL;
  117. }
  118. return err;
  119. }
  120. #if CONFIG_BLUEDROID_ENABLED
  121. esp_hidh_dev_t *esp_hidh_dev_open(esp_bd_addr_t bda, esp_hid_transport_t transport, uint8_t remote_addr_type)
  122. {
  123. if (esp_hidh_dev_get_by_bda(bda) != NULL) {
  124. ESP_LOGE(TAG, "Already Connected");
  125. return NULL;
  126. }
  127. esp_hidh_dev_t *dev = NULL;
  128. #if CONFIG_GATTC_ENABLE
  129. if (transport == ESP_HID_TRANSPORT_BLE) {
  130. dev = esp_ble_hidh_dev_open(bda, (esp_ble_addr_type_t)remote_addr_type);
  131. }
  132. #endif /* CONFIG_GATTC_ENABLE */
  133. #if CONFIG_BT_HID_HOST_ENABLED
  134. if (transport == ESP_HID_TRANSPORT_BT) {
  135. dev = esp_bt_hidh_dev_open(bda);
  136. }
  137. #endif /* CONFIG_BT_HID_HOST_ENABLED */
  138. return dev;
  139. }
  140. #endif /* CONFIG_BLUEDROID_ENABLED */
  141. esp_err_t esp_hidh_dev_close(esp_hidh_dev_t *dev)
  142. {
  143. if (!esp_hidh_dev_exists(dev)) {
  144. return ESP_FAIL;
  145. }
  146. return dev->close(dev);
  147. }
  148. void esp_hidh_dev_dump(esp_hidh_dev_t *dev, FILE *fp)
  149. {
  150. if (!esp_hidh_dev_exists(dev)) {
  151. return;
  152. }
  153. dev->dump(dev, fp);
  154. }
  155. esp_err_t esp_hidh_dev_output_set(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, uint8_t *value, size_t value_len)
  156. {
  157. if (!esp_hidh_dev_exists(dev)) {
  158. return ESP_FAIL;
  159. }
  160. return dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_OUTPUT, value, value_len);
  161. }
  162. esp_err_t esp_hidh_dev_feature_set(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, uint8_t *value, size_t value_len)
  163. {
  164. if (!esp_hidh_dev_exists(dev)) {
  165. return ESP_FAIL;
  166. }
  167. return dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, value, value_len);
  168. }
  169. esp_err_t esp_hidh_dev_feature_get(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, size_t max_length, uint8_t *value, size_t *value_len)
  170. {
  171. if (!esp_hidh_dev_exists(dev)) {
  172. return ESP_FAIL;
  173. }
  174. return dev->report_read(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, max_length, value, value_len);
  175. }
  176. const uint8_t *esp_hidh_dev_bda_get(esp_hidh_dev_t *dev)
  177. {
  178. #if CONFIG_BLUEDROID_ENABLED
  179. if (esp_hidh_dev_exists(dev)) {
  180. return dev->bda;
  181. }
  182. #endif /* CONFIG_BLUEDROID_ENABLED */
  183. return NULL;
  184. }
  185. esp_hid_transport_t esp_hidh_dev_transport_get(esp_hidh_dev_t *dev)
  186. {
  187. if (!esp_hidh_dev_exists(dev)) {
  188. return ESP_HID_TRANSPORT_MAX;
  189. }
  190. return dev->transport;
  191. }
  192. const esp_hid_device_config_t *esp_hidh_dev_config_get(esp_hidh_dev_t *dev)
  193. {
  194. if (!esp_hidh_dev_exists(dev)) {
  195. return NULL;
  196. }
  197. return &dev->config;
  198. }
  199. const char *esp_hidh_dev_name_get(esp_hidh_dev_t *dev)
  200. {
  201. if (!esp_hidh_dev_exists(dev)) {
  202. return NULL;
  203. }
  204. return dev->config.device_name ? dev->config.device_name : "";
  205. }
  206. const char *esp_hidh_dev_manufacturer_get(esp_hidh_dev_t *dev)
  207. {
  208. if (!esp_hidh_dev_exists(dev)) {
  209. return NULL;
  210. }
  211. return dev->config.manufacturer_name ? dev->config.manufacturer_name : "";
  212. }
  213. const char *esp_hidh_dev_serial_get(esp_hidh_dev_t *dev)
  214. {
  215. if (!esp_hidh_dev_exists(dev)) {
  216. return NULL;
  217. }
  218. return dev->config.serial_number ? dev->config.serial_number : "";
  219. }
  220. uint16_t esp_hidh_dev_vendor_id_get(esp_hidh_dev_t *dev)
  221. {
  222. if (!esp_hidh_dev_exists(dev)) {
  223. return 0;
  224. }
  225. return dev->config.vendor_id;
  226. }
  227. uint16_t esp_hidh_dev_product_id_get(esp_hidh_dev_t *dev)
  228. {
  229. if (!esp_hidh_dev_exists(dev)) {
  230. return 0;
  231. }
  232. return dev->config.product_id;
  233. }
  234. uint16_t esp_hidh_dev_version_get(esp_hidh_dev_t *dev)
  235. {
  236. if (!esp_hidh_dev_exists(dev)) {
  237. return 0;
  238. }
  239. return dev->config.version;
  240. }
  241. esp_hid_usage_t esp_hidh_dev_usage_get(esp_hidh_dev_t *dev)
  242. {
  243. if (!esp_hidh_dev_exists(dev)) {
  244. return ESP_HID_USAGE_GENERIC;
  245. }
  246. return dev->usage;
  247. }
  248. esp_err_t esp_hidh_dev_reports_get(esp_hidh_dev_t *dev, size_t *num_reports, esp_hid_report_item_t **reports)
  249. {
  250. if (!esp_hidh_dev_exists(dev)) {
  251. return ESP_FAIL;
  252. }
  253. esp_hid_report_item_t *r = (esp_hid_report_item_t *)malloc(sizeof(esp_hid_report_item_t) * dev->reports_len);
  254. if (r == NULL) {
  255. return ESP_FAIL;
  256. }
  257. esp_hidh_dev_report_t *dr = dev->reports;
  258. for (uint8_t i = 0; i < dev->reports_len; i++) {
  259. if (dr == NULL) {
  260. //error
  261. free(r);
  262. return ESP_FAIL;
  263. }
  264. r[i].map_index = dr->map_index;
  265. r[i].protocol_mode = dr->protocol_mode;
  266. r[i].usage = dr->usage;
  267. r[i].report_id = dr->report_id;
  268. r[i].report_type = dr->report_type;
  269. r[i].value_len = dr->value_len;
  270. dr = dr->next;
  271. }
  272. *reports = r;
  273. *num_reports = dev->reports_len;
  274. return ESP_OK;
  275. }
  276. esp_err_t esp_hidh_dev_report_maps_get(esp_hidh_dev_t *dev, size_t *num_maps, esp_hid_raw_report_map_t **maps)
  277. {
  278. if (!esp_hidh_dev_exists(dev)) {
  279. return ESP_FAIL;
  280. }
  281. *num_maps = dev->config.report_maps_len;
  282. *maps = dev->config.report_maps;
  283. return ESP_OK;
  284. }
  285. /*
  286. * Private Functions
  287. * */
  288. esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t *dev, uint16_t handle)
  289. {
  290. esp_hidh_dev_report_t *r = dev->reports;
  291. while (r) {
  292. if (r->handle == handle) {
  293. return r;
  294. }
  295. r = r->next;
  296. }
  297. return NULL;
  298. }
  299. esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_and_type(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type)
  300. {
  301. esp_hidh_dev_report_t *r = dev->reports;
  302. while (r) {
  303. if (r->map_index == map_index && r->report_id == report_id && r->report_type == report_type && r->protocol_mode == ESP_HID_PROTOCOL_MODE_REPORT) {
  304. return r;
  305. }
  306. r = r->next;
  307. }
  308. return NULL;
  309. }
  310. esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_id_and_proto(esp_hidh_dev_t *dev, size_t report_id, int protocol_mode)
  311. {
  312. esp_hidh_dev_report_t *r = dev->reports;
  313. while (r) {
  314. if (r->report_id == report_id && (r->report_type & 1) && r->protocol_mode == protocol_mode) {
  315. return r;
  316. }
  317. r = r->next;
  318. }
  319. return NULL;
  320. }
  321. static void esp_hidh_dev_resources_free(esp_hidh_dev_t *dev)
  322. {
  323. if (dev->semaphore) {
  324. vSemaphoreDelete(dev->semaphore);
  325. }
  326. free((void *)dev->config.device_name);
  327. free((void *)dev->config.manufacturer_name);
  328. free((void *)dev->config.serial_number);
  329. for (uint8_t d = 0; d < dev->config.report_maps_len; d++) {
  330. free((void *)dev->config.report_maps[d].data);
  331. }
  332. free((void *)dev->config.report_maps);
  333. esp_hidh_dev_report_t *r;
  334. while (dev->reports) {
  335. r = dev->reports;
  336. dev->reports = dev->reports->next;
  337. free(r);
  338. }
  339. free(dev);
  340. }
  341. esp_hidh_dev_t *esp_hidh_dev_malloc()
  342. {
  343. esp_hidh_dev_t *dev = (esp_hidh_dev_t *)calloc(1, sizeof(esp_hidh_dev_t));
  344. if (dev == NULL) {
  345. ESP_LOGE(TAG, "malloc esp_hidh_dev_t failed");
  346. return NULL;
  347. }
  348. dev->semaphore = xSemaphoreCreateBinary();
  349. if (dev->semaphore == NULL) {
  350. ESP_LOGE(TAG, "malloc semaphore failed");
  351. esp_hidh_dev_resources_free(dev);
  352. return NULL;
  353. }
  354. lock_devices();
  355. TAILQ_INSERT_TAIL(&s_esp_hidh_devices, dev, devices);
  356. unlock_devices();
  357. return dev;
  358. }
  359. esp_err_t esp_hidh_dev_free(esp_hidh_dev_t *dev)
  360. {
  361. esp_err_t ret = ESP_FAIL;
  362. if (dev == NULL) {
  363. return ret;
  364. }
  365. esp_hidh_dev_t *d = NULL;
  366. esp_hidh_dev_t *next = NULL;
  367. lock_devices();
  368. TAILQ_FOREACH_SAFE(d, &s_esp_hidh_devices, devices, next) {
  369. if (d == dev) {
  370. TAILQ_REMOVE(&s_esp_hidh_devices, d, devices);
  371. esp_hidh_dev_resources_free(d);
  372. ret = ESP_OK;
  373. break;
  374. }
  375. }
  376. unlock_devices();
  377. if (ret != ESP_OK) {
  378. ESP_LOGW(TAG, "device not found");
  379. } else {
  380. ESP_LOGD(TAG, "device removed");
  381. }
  382. return ret;
  383. }
  384. #if CONFIG_BLUEDROID_ENABLED
  385. esp_hidh_dev_t *esp_hidh_dev_get_by_bda(esp_bd_addr_t bda)
  386. {
  387. esp_hidh_dev_t * d = NULL;
  388. lock_devices();
  389. TAILQ_FOREACH(d, &s_esp_hidh_devices, devices) {
  390. if (memcmp(bda, d->bda, sizeof(esp_bd_addr_t)) == 0) {
  391. unlock_devices();
  392. return d;
  393. }
  394. }
  395. unlock_devices();
  396. return NULL;
  397. }
  398. esp_hidh_dev_t *esp_hidh_dev_get_by_handle(int handle)
  399. {
  400. #if CONFIG_BT_HID_HOST_ENABLED
  401. esp_hidh_dev_t * d = NULL;
  402. lock_devices();
  403. TAILQ_FOREACH(d, &s_esp_hidh_devices, devices) {
  404. if (d->transport == ESP_HID_TRANSPORT_BT && d->bt.handle == handle) {
  405. unlock_devices();
  406. return d;
  407. }
  408. }
  409. unlock_devices();
  410. #endif /* CONFIG_BT_HID_HOST_ENABLED */
  411. return NULL;
  412. }
  413. esp_hidh_dev_t *esp_hidh_dev_get_by_conn_id(uint16_t conn_id)
  414. {
  415. #if CONFIG_GATTC_ENABLE
  416. esp_hidh_dev_t * d = NULL;
  417. lock_devices();
  418. TAILQ_FOREACH(d, &s_esp_hidh_devices, devices) {
  419. if (d->transport == ESP_HID_TRANSPORT_BLE && d->ble.conn_id == conn_id) {
  420. unlock_devices();
  421. return d;
  422. }
  423. }
  424. unlock_devices();
  425. #endif /* CONFIG_GATTC_ENABLE */
  426. return NULL;
  427. }
  428. #endif /* CONFIG_BLUEDROID_ENABLED */