hog.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /** @file
  2. * @brief HoG Service sample
  3. */
  4. /*
  5. * Copyright (c) 2016 Intel Corporation
  6. *
  7. * SPDX-License-Identifier: Apache-2.0
  8. */
  9. #include <zephyr/types.h>
  10. #include <stddef.h>
  11. #include <string.h>
  12. #include "errno.h"
  13. #include <sys/printk.h>
  14. #include <zephyr.h>
  15. #include <acts_bluetooth/bluetooth.h>
  16. #include <acts_bluetooth/hci.h>
  17. #include <acts_bluetooth/conn.h>
  18. #include <acts_bluetooth/uuid.h>
  19. #include <acts_bluetooth/gatt.h>
  20. #include <acts_bluetooth/services/hog.h>
  21. #define LOG_LEVEL CONFIG_BT_BAS_LOG_LEVEL
  22. #include <logging/log.h>
  23. LOG_MODULE_REGISTER(hog);
  24. #define HIDAPP_REMOTE_REPORT_ID 1
  25. #define HIDAPP_VOICE_REPORT_ID 2
  26. #define HIDAPP_MOUSE_REPORT_ID 3
  27. /*! HID Report Type/ID and attribute handle map */
  28. static const struct hid_report_id_map_t hid_app_report_id_set[] = {
  29. /* type ID handle */
  30. {HID_REPORT_TYPE_INPUT, HIDAPP_REMOTE_REPORT_ID, HID_INPUT_REPORT_1_HDL}, /* Remote Input Report */
  31. #if 0 //def OLD_HOG
  32. #if CONFIG_HID_MOUSE_USAGE
  33. {HID_REPORT_TYPE_INPUT, HIDAPP_VOICE_REPORT_ID, HID_INPUT_REPORT_2_HDL}, /* Keyboard Input Report */
  34. {HID_REPORT_TYPE_OUTPUT, HIDAPP_VOICE_REPORT_ID, HID_OUTPUT_REPORT_HDL}, /* Keyboard Output Report */
  35. {HID_REPORT_TYPE_FEATURE, HIDAPP_VOICE_REPORT_ID, HID_FEATURE_REPORT_HDL}, /* Keyboard Feature Report */
  36. {HID_REPORT_TYPE_INPUT, HIDAPP_MOUSE_REPORT_ID, HID_INPUT_REPORT_3_HDL}, /* Mouse Input Report */
  37. #endif
  38. {HID_REPORT_TYPE_INPUT, HID_KEYBOARD_BOOT_ID, HID_KEYBOARD_BOOT_IN_HDL}, /* Boot Keyboard Input Report */
  39. {HID_REPORT_TYPE_OUTPUT, HID_KEYBOARD_BOOT_ID, HID_KEYBOARD_BOOT_OUT_HDL}, /* Boot Keyboard Output Report */
  40. #if CONFIG_HID_MOUSE_USAGE
  41. {HID_REPORT_TYPE_INPUT, HID_MOUSE_BOOT_ID, HID_MOUSE_BOOT_IN_HDL}, /* Boot Mouse Input Report */
  42. #endif
  43. #endif
  44. };
  45. /*! HID control block */
  46. struct hid_cb_t {
  47. const struct hid_config_t *p_config;
  48. };
  49. struct hid_cb_t hid_cb;
  50. enum {
  51. HIDS_REMOTE_WAKE = BIT(0),
  52. HIDS_NORMALLY_CONNECTABLE = BIT(1),
  53. };
  54. struct hids_info {
  55. uint16_t version; /* version number of base USB HID Specification */
  56. uint8_t code; /* country HID Device hardware is localized for. */
  57. uint8_t flags;
  58. } __packed;
  59. struct hids_report {
  60. uint8_t id; /* report id */
  61. uint8_t type; /* report type */
  62. } __packed;
  63. /* HID Info Value: HID Spec version, country code, flags */
  64. const struct hids_info hid_info_val = {
  65. .version = HID_VERSION,
  66. .code = 0x00,
  67. .flags = HIDS_REMOTE_WAKE | HIDS_NORMALLY_CONNECTABLE,
  68. };
  69. const uint8_t hid_report_map[] = {
  70. 0x05, 0x0c, /* Usage Page (Consumer Devices) */
  71. 0x09, 0x01, /* Usage (Consumer Control) */
  72. 0xa1, 0x01, /* Collection (Application) */
  73. 0x85, HIDAPP_REMOTE_REPORT_ID, /* report ID (0x01) */
  74. #if 0 //def OLD_HOG
  75. 0x19, 0x00, /* USAGE_MINIMUM (0) */
  76. 0x2a, 0x9c, 0x02, /* USAGE_MINIMUM (0x29c) */
  77. 0x15, 0x00, /* Logical Minimum (0) */
  78. 0x26, 0x9c, 0x02, /* Logical Maximum (0x29c) */
  79. 0x95, 0x01, /* Report Count (1) */
  80. 0x75, 0x10, /* Report Size (16) */
  81. 0x81, 0x00, /* Input (Data, array, Absolute) */
  82. 0x09, 0x02, /* Usage (Numeric Key Pad ) */
  83. 0xa1, 0x02, /* Collection (Application) */
  84. 0x05, 0x09, /* Usage Page (button) */
  85. 0x19, 0x01, /* Usage Minimum (1) */
  86. 0x29, 0x0a, /* Usage Maximum (10) */
  87. 0x15, 0x01, /* Logical Minimum (1) */
  88. 0x25, 0x0a, /* Logical Maximum (10) */
  89. 0x95, 0x01, /* Report Count (1) */
  90. 0x75, 0x08, /* Report Size (8) */
  91. 0x81, 0x40, /* Input (Data, Variable, Relative) */
  92. 0xc0, /* End Collection */
  93. 0xc0, /* End Collection */
  94. #else
  95. 0x15, 0x00, /* Logical Minimum (0) */
  96. 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
  97. 0x75, 0x01, /* Report Size (1) */
  98. 0x95, 0x08, /* Report Count (8) */
  99. 0x09, 0xB5,/* (Scan Next Track) */
  100. 0x09, 0xB6,/* (Scan Previous Track) */
  101. 0x09, 0xB7,/* (Stop) */
  102. 0x09, 0x30,/* (Power) */
  103. 0x09, 0xCD,/* (Play/Pause) */
  104. 0x09, 0xE2,/* (Mute) */
  105. 0x09, 0xE9,/* (Volume Increment) */
  106. 0x09, 0xEA,/* (Volume Decrement) */
  107. 0x81, 0x02,
  108. 0xc0, /* End Collection */
  109. #endif
  110. #if CONFIG_HID_MOUSE_USAGE
  111. 0x05, 0x01, /* Usage Page (Generic Desktop) */
  112. 0x09, 0x02, /* USAGE (Mouse) */
  113. 0xa1, 0x01, /* COLLECTION (Application) */
  114. 0x09, 0x01, /* USAGE (Pointer) */
  115. 0xa1, 0x00, /* COLLECTION (Physical) */
  116. 0x85, HIDAPP_MOUSE_REPORT_ID, /* report ID (HIDAPP_MOUSE_REPORT_ID) */
  117. 0x05, 0x09, /* USAGE_PAGE (Button) */
  118. 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */
  119. 0x29, 0x05, /* USAGE_MAXIMUM (Button 5) */
  120. 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
  121. 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
  122. 0x75, 0x01, /* REPORT_SIZE (1) */
  123. 0x95, 0x05, /* REPORT_COUNT (5) */
  124. 0x81, 0x02, /* Input (Data, Variable, Absolute) */
  125. 0x75, 0x03, /* REPORT_SIZE (3) */
  126. 0x95, 0x01, /* REPORT_COUNT (1) */
  127. 0x81, 0x03, /* INPUT (Const, Variable, Absolute) */
  128. 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
  129. 0x09, 0x30, /* USAGE (X) */
  130. 0x09, 0x31, /* USAGE (Y) */
  131. 0x09, 0x38, /* USAGE (wheel)*/
  132. 0x15, 0x80, /* LOGICAL_MINIMUM (-127) */
  133. 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */
  134. 0x75, 0x08, /* REPORT_SIZE (8) */
  135. 0x95, 0x03, /* REPORT_COUNT (3) */
  136. 0x81, 0x06, /* INPUT (Data, Variable, Relative) */
  137. 0xc0, /* End Collection (Physical) */
  138. 0xc0, /* End Collection (Application) */
  139. 0x06, 0x01, 0xff,
  140. 0x09, 0x01, /* Usage (Consumer Control) */
  141. 0xa1, 0x02, /* COLLECTION () */
  142. 0x85, HIDAPP_VOICE_REPORT_ID, /* report ID (HIDAPP_KEYBOARD_REPORT_ID) */
  143. 0x09, 0x14,
  144. 0x75, 0x08, /* Report Size (8) */
  145. 0x95, 0x14, /* Report Count (20) */
  146. 0x15, 0x80, /* Logical Minimum (0x80) */
  147. 0x25, 0x7f, /* Logical Minimum (0x7f) */
  148. 0x81, 0x22, /* Input () */
  149. 0x85, 0x04, /* report ID () */
  150. 0x09, 0x04, /* USAGE () */
  151. 0x75, 0x08, /* Report Size (8) */
  152. 0x95, 0x01, /* Report Count (1) */
  153. 0x91, 0x02, /* Output */
  154. 0xc0,
  155. #endif
  156. };
  157. /* HID Control Point Value */
  158. uint8_t hid_cp_val;
  159. /* HID Input Report Reference - ID, Type */
  160. const struct hids_report hid_val_irep1_id_map = {
  161. .id = 0x01,
  162. .type = HID_REPORT_TYPE_INPUT,
  163. };
  164. #if 0 //def OLD_HOG
  165. #if CONFIG_HID_MOUSE_USAGE
  166. /* HID Input Report Reference - ID, Type */
  167. const struct hids_report hid_val_irep2_id_map = {
  168. .id = 0x02,
  169. .type = HID_REPORT_TYPE_INPUT,
  170. };
  171. /* HID Input Report Reference - ID, Type */
  172. const struct hids_report hid_val_irep3_id_map = {
  173. .id = 0x03,
  174. .type = HID_REPORT_TYPE_INPUT,
  175. };
  176. #endif
  177. #endif
  178. /* HID Output Report Reference - ID, Type */
  179. const struct hids_report hid_val_orep_id_map = {
  180. .id = 0x0a,
  181. .type = HID_REPORT_TYPE_OUTPUT,
  182. };
  183. /* HID Feature Report Reference - ID, Type */
  184. const struct hids_report hid_val_frep_id_map = {
  185. .id = 0x00,
  186. .type = HID_REPORT_TYPE_FEATURE,
  187. };
  188. /* HID Protocol Mode Value */
  189. static uint8_t hid_pm_val = HID_PROTOCOL_MODE_REPORT;
  190. static const uint16_t hid_len_pm_val = sizeof(hid_pm_val);
  191. static uint8_t bt_attr_get_id(const struct bt_gatt_attr *attr);
  192. static ssize_t read_info(struct bt_conn *conn,
  193. const struct bt_gatt_attr *attr, void *buf,
  194. uint16_t len, uint16_t offset)
  195. {
  196. return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data,
  197. sizeof(struct hids_info));
  198. }
  199. static ssize_t read_report_map(struct bt_conn *conn,
  200. const struct bt_gatt_attr *attr, void *buf,
  201. uint16_t len, uint16_t offset)
  202. {
  203. return bt_gatt_attr_read(conn, attr, buf, len, offset, hid_report_map,
  204. sizeof(hid_report_map));
  205. }
  206. static ssize_t read_ext_report(struct bt_conn *conn,
  207. const struct bt_gatt_attr *attr, void *buf,
  208. uint16_t len, uint16_t offset)
  209. {
  210. uint8_t hid_ext_report[] = {((uint8_t) (BT_UUID_BAS_BATTERY_LEVEL_VAL)), ((uint8_t)((BT_UUID_BAS_BATTERY_LEVEL_VAL) >> 8))};
  211. uint16_t hid_len_ext_report = sizeof(hid_ext_report);
  212. return bt_gatt_attr_read(conn, attr, buf, len, offset, hid_ext_report,
  213. hid_len_ext_report);
  214. }
  215. static ssize_t write_ctrl_point(struct bt_conn *conn,
  216. const struct bt_gatt_attr *attr,
  217. const void *buf, uint16_t len, uint16_t offset,
  218. uint8_t flags)
  219. {
  220. if (offset + len > 1)
  221. return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
  222. return len;
  223. }
  224. static ssize_t read_report_reference(struct bt_conn *conn,
  225. const struct bt_gatt_attr *attr, void *buf,
  226. uint16_t len, uint16_t offset)
  227. {
  228. return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data,
  229. sizeof(struct hids_report));
  230. }
  231. static ssize_t read_report_value(struct bt_conn *conn,
  232. const struct bt_gatt_attr *attr, void *buf,
  233. uint16_t len, uint16_t offset)
  234. {
  235. if (offset > HID_MAX_REPORT_LEN)
  236. return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
  237. return len;
  238. }
  239. static ssize_t write_report_value(struct bt_conn *conn,
  240. const struct bt_gatt_attr *attr,
  241. const void *buf, uint16_t len, uint16_t offset,
  242. uint8_t flags)
  243. {
  244. if (offset + len > HID_MAX_REPORT_LEN)
  245. return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
  246. return len;
  247. }
  248. static void hid_ccc_changed(const struct bt_gatt_attr *attr, uint16_t value)
  249. {
  250. uint16_t handle = bt_attr_get_id(attr);
  251. hid_set_ccc_table_value(handle, value);
  252. LOG_INF("handle: %d, ccc_value : %d", handle, value);
  253. }
  254. static ssize_t read_protocol_mode(struct bt_conn *conn,
  255. const struct bt_gatt_attr *attr, void *buf,
  256. uint16_t len, uint16_t offset)
  257. {
  258. return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data,
  259. hid_len_pm_val);
  260. }
  261. static ssize_t write_protocol_mode(struct bt_conn *conn,
  262. const struct bt_gatt_attr *attr,
  263. const void *buf, uint16_t len, uint16_t offset,
  264. uint8_t flags)
  265. {
  266. if (offset + len > 1)
  267. return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
  268. return len;
  269. }
  270. /* HID Service Declaration */
  271. BT_GATT_SERVICE_DEFINE(hog_svc,
  272. BT_GATT_PRIMARY_SERVICE(BT_UUID_HIDS),
  273. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_INFO,
  274. BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT,
  275. read_info, NULL, (void *)&hid_info_val),
  276. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT_MAP,
  277. BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT,
  278. read_report_map, NULL, NULL),
  279. BT_GATT_DESCRIPTOR(BT_UUID_HIDS_EXT_REPORT, BT_GATT_PERM_READ_ENCRYPT,
  280. read_ext_report, NULL, NULL),
  281. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_CTRL_POINT,
  282. BT_GATT_CHRC_WRITE_WITHOUT_RESP,
  283. BT_GATT_PERM_WRITE_ENCRYPT,
  284. NULL, write_ctrl_point, &hid_cp_val),
  285. #if 0 //def OLD_HOG
  286. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_BOOT_KEYBOARD_IN,
  287. BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
  288. BT_GATT_PERM_READ_ENCRYPT,
  289. read_report_value, NULL, NULL),
  290. BT_GATT_CCC(hid_ccc_changed,
  291. BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
  292. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_BOOT_KEYBOARD_OUT,
  293. BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_WRITE,
  294. BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT,
  295. read_report_value, write_report_value, NULL),
  296. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_BOOT_MOUSE_IN,
  297. BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
  298. BT_GATT_PERM_READ_ENCRYPT,
  299. read_report_value, NULL, NULL),
  300. BT_GATT_CCC(hid_ccc_changed,
  301. BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
  302. #endif
  303. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
  304. BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
  305. BT_GATT_PERM_READ_ENCRYPT,
  306. read_report_value, NULL, NULL),
  307. BT_GATT_CCC(hid_ccc_changed,
  308. BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
  309. BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT,
  310. read_report_reference, NULL, (void *)&hid_val_irep1_id_map),
  311. #if 0 //def OLD_HOG
  312. #if CONFIG_HID_MOUSE_USAGE
  313. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
  314. BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
  315. BT_GATT_PERM_READ_ENCRYPT,
  316. read_report_value, NULL, NULL),
  317. BT_GATT_CCC(hid_ccc_changed,
  318. BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
  319. BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT,
  320. read_report_reference, NULL, (void *)&hid_val_irep2_id_map),
  321. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
  322. BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
  323. BT_GATT_PERM_READ_ENCRYPT,
  324. read_report_value, NULL, NULL),
  325. BT_GATT_CCC(hid_ccc_changed,
  326. BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
  327. BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT,
  328. read_report_reference, NULL, (void *)&hid_val_irep3_id_map),
  329. #endif
  330. #endif
  331. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
  332. BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_WRITE,
  333. BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT,
  334. read_report_value, write_report_value, NULL),
  335. BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT,
  336. read_report_reference, NULL, (void *)&hid_val_orep_id_map),
  337. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
  338. BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
  339. BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT,
  340. read_report_value, write_report_value, NULL),
  341. BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT,
  342. read_report_reference, NULL, (void *)&hid_val_frep_id_map),
  343. BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_PROTOCOL_MODE,
  344. BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
  345. BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT,
  346. read_protocol_mode, write_protocol_mode, &hid_pm_val),
  347. );
  348. static uint8_t bt_attr_get_id(const struct bt_gatt_attr *attr)
  349. {
  350. return attr - attr_hog_svc;
  351. }
  352. void hog_init(void)
  353. {
  354. LOG_INF("hog init");
  355. }
  356. struct hids_ccc {
  357. uint16_t handle; /* ccc handle */
  358. uint8_t value; /* ccc value */
  359. } __packed;
  360. struct hids_ccc hids_ccc_table[] = {
  361. /* handle value*/
  362. #if 0 //def OLD_HOG
  363. {HID_KEYBOARD_BOOT_IN_CH_CCC_HDL, 0},
  364. {HID_MOUSE_BOOT_IN_CH_CCC_HDL, 0},
  365. #endif
  366. {HID_INPUT_REPORT_1_CH_CCC_HDL, 0},
  367. #if 0 //def OLD_HOG
  368. #if CONFIG_HID_MOUSE_USAGE
  369. {HID_INPUT_REPORT_2_CH_CCC_HDL, 0},
  370. {HID_INPUT_REPORT_3_CH_CCC_HDL, 0},
  371. #endif
  372. #endif
  373. };
  374. void hid_set_ccc_table_value(uint16_t handle, uint8_t value)
  375. {
  376. uint8_t i = 0;
  377. for (i = 0; i < ARRAY_SIZE(hids_ccc_table); i++) {
  378. if (hids_ccc_table[i].handle == handle) {
  379. hids_ccc_table[i].value = value;
  380. break;
  381. }
  382. }
  383. }
  384. uint8_t hid_get_ccc_table_value(uint16_t handle)
  385. {
  386. uint8_t i = 0;
  387. for (i = 0; i < ARRAY_SIZE(hids_ccc_table); i++) {
  388. if (hids_ccc_table[i].handle == handle) {
  389. return hids_ccc_table[i].value;
  390. }
  391. }
  392. return 0;
  393. }
  394. uint8_t hid_ccc_is_enabled(uint16_t handle)
  395. {
  396. return (hid_get_ccc_table_value(handle) == BT_GATT_CCC_NOTIFY);
  397. }
  398. uint8_t all_hid_ccc_is_enabled(void)
  399. {
  400. uint8_t ret = true;
  401. uint8_t i = 0;
  402. for (i = 2; i < ARRAY_SIZE(hids_ccc_table); i++) {
  403. if (hids_ccc_table[i].value != BT_GATT_CCC_NOTIFY) {
  404. ret = false;
  405. break;
  406. }
  407. }
  408. return ret;
  409. }
  410. uint16_t hid_get_report_handle(uint8_t type, uint8_t id)
  411. {
  412. struct hid_report_id_map_t *p_map;
  413. uint8_t count;
  414. int8_t i;
  415. p_map = (struct hid_report_id_map_t *)hid_app_report_id_set;
  416. count = sizeof(hid_app_report_id_set)/sizeof(struct hid_report_id_map_t);
  417. for (i = 0; i < count; i++) {
  418. if (p_map[i].type == type && p_map[i].id == id)
  419. return p_map[i].handle;
  420. }
  421. return 0;
  422. }
  423. uint8_t hid_get_protocol_mode(void)
  424. {
  425. return hid_pm_val;
  426. }
  427. void hid_set_protocol_mode(uint8_t protocol_mode)
  428. {
  429. hid_pm_val = protocol_mode;
  430. }
  431. int hid_send_input_report(struct bt_conn *conn, uint8_t report_id, uint16_t len, uint8_t *p_value)
  432. {
  433. uint16_t handle = hid_get_report_handle(HID_REPORT_TYPE_INPUT, report_id);
  434. if ((handle != 0) && hid_ccc_is_enabled(handle+1))
  435. return bt_gatt_notify(conn, &attr_hog_svc[handle], p_value, len);
  436. else
  437. return -EIO;
  438. }