ble_hid_service.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #include "include.h"
  2. #include "utils_hid_usage.h"
  3. #include "ble_hid_service.h"
  4. #define TRACE_EN 1
  5. #if TRACE_EN
  6. #define TRACE(...) my_printf("[BLE] ");my_printf(__VA_ARGS__)
  7. #define TRACE_R(...) my_print_r(__VA_ARGS__)
  8. #else // !TRACE_EN
  9. #define TRACE(...)
  10. #define TRACE_R(...)
  11. #endif // TRACE_EN
  12. #define BLE_HID_HANDLE_MAP ATT_CHARACTERISTIC_2a4b_01_VALUE_HANDLE
  13. #define BLE_HID_HANDLE_CTRL_POINT ATT_CHARACTERISTIC_2a4c_01_VALUE_HANDLE
  14. #define BLE_HID_HANDLE_REP_CONSUMER ATT_CHARACTERISTIC_2a4d_01_VALUE_HANDLE
  15. #define BLE_HID_HANDLE_REP_CONSUMER_CCC ATT_CHARACTERISTIC_2a4d_01_CLIENT_CONFIGURATION_HANDLE
  16. #define BLE_HID_HANDLE_REP_KEYBOARD ATT_CHARACTERISTIC_2a4d_02_VALUE_HANDLE
  17. #define BLE_HID_HANDLE_REP_KEYBOARD_CCC ATT_CHARACTERISTIC_2a4d_02_CLIENT_CONFIGURATION_HANDLE
  18. #define BLE_HID_HANDLE_REP_LED ATT_CHARACTERISTIC_2a4d_03_VALUE_HANDLE
  19. //#define BLE_HID_HANDLE_REP_MOUSE ATT_CHARACTERISTIC_2a4d_04_VALUE_HANDLE
  20. //#define BLE_HID_HANDLE_REP_MOUSE_CCC ATT_CHARACTERISTIC_2a4d_04_CLIENT_CONFIGURATION_HANDLE
  21. static att_service_handler_t hid_service;
  22. static uint16_t hid_report_client_config_consumer;
  23. static uint16_t hid_report_client_config_keyboard;
  24. static uint16_t hid_report_client_config_mouse;
  25. static uint16_t hid_connect_handle;
  26. static struct {
  27. bool ready;
  28. hid_rep_info_t data;
  29. } ble_hid_state AT(.ble_buf.hid.comm);
  30. #if 0
  31. static u8 report_map[] = {
  32. HID_REP_MAP_CONSUMER(1),
  33. HID_REP_MAP_KEYBOARD(2),
  34. HID_REP_MAP_MOUSE(3),
  35. #if 0
  36. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  37. 0x09, 0x02, // USAGE (Mouse)
  38. 0xA1, 0x01, // COLLECTION (Application)
  39. 0x85, 0x01, // Report Id (1)
  40. 0x09, 0x01, // USAGE (Pointer)
  41. 0xA1, 0x00, // COLLECTION (Physical)
  42. 0x05, 0x09, // USAGE_PAGE (Button)
  43. 0x19, 0x01, // USAGE_MINIMUM (Button 1)
  44. 0x29, 0x05, // USAGE_MAXIMUM (Button 5)
  45. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  46. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  47. 0x75, 0x01, // REPORT_SIZE (1)
  48. 0x95, 0x05, // REPORT_COUNT (5)
  49. 0x81, 0x02, // INPUT (Data,Var,Abs)
  50. 0x75, 0x03, // REPORT_SIZE (3)
  51. 0x95, 0x01, // REPORT_COUNT (1)
  52. 0x81, 0x03, // INPUT (Cnst,Var,Abs)
  53. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  54. 0x09, 0x38, // USAGE (Wheel)
  55. 0x09, 0x30, // USAGE (X)
  56. 0x09, 0x31, // USAGE (Y)
  57. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  58. 0x25, 0x7F, // LOGICAL_MAXIMUM (127)
  59. 0x75, 0x08, // REPORT_SIZE (8)
  60. 0x95, 0x03, // REPORT_COUNT (3)
  61. 0x81, 0x06, // INPUT (Data,Var,Rel)
  62. 0xC0, // END_COLLECTION
  63. 0xC0, // END_COLLECTION
  64. #endif
  65. };
  66. #endif // 0
  67. static void hid_service_event_packet_handle(uint8_t event_type, uint8_t *param, uint16_t size)
  68. {
  69. switch(event_type){
  70. case BLE_EVT_CONNECT:{
  71. memcpy(&hid_connect_handle, &param[7], 2);
  72. TRACE("Connected - con_handle: 0x%04x\n", hid_connect_handle);
  73. ble_hid_state.ready = true;
  74. } break;
  75. case BLE_EVT_DISCONNECT:{
  76. uint16_t con_handle;
  77. memcpy(&con_handle, &param[0], 2);
  78. TRACE("Disconnected - con_handle: 0x%04x\n", con_handle);
  79. if (con_handle == hid_connect_handle) {
  80. hid_connect_handle = 0;
  81. // TODO: The CCCD value shall be persistent across connections for bonded devices.
  82. hid_report_client_config_consumer = CCCD_DFT;
  83. hid_report_client_config_keyboard = CCCD_DFT;
  84. hid_report_client_config_mouse = CCCD_DFT;
  85. }
  86. ble_hid_state.ready = false;
  87. } break;
  88. default:
  89. break;
  90. }
  91. }
  92. static uint16_t hid_service_read_callback(uint16_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size)
  93. {
  94. u8 data_len = 0;
  95. //u8 hid_report_map_len = sizeof(report_map);
  96. switch (attribute_handle) {
  97. #if 0
  98. case BLE_HID_HANDLE_MAP:
  99. if (buffer) {
  100. data_len = (buffer_size < (hid_report_map_len - offset))? buffer_size: (hid_report_map_len - offset);
  101. memcpy(buffer, report_map + offset, data_len);
  102. TRACE("Read Request - handle: 0x%04x len: %d data:\n", attribute_handle, buffer_size);
  103. TRACE_R(buffer, buffer_size);
  104. } else {
  105. data_len = hid_report_map_len;
  106. }
  107. break;
  108. case BLE_HID_HANDLE_REP_CONSUMER_CCC:
  109. if (buffer) {
  110. TRACE("Read CCC Consumer - val: 0x%04x\n", hid_report_client_config_consumer);
  111. data_len = 2;
  112. memcpy(buffer, (u8 *)&hid_report_client_config_consumer, 2);
  113. } else {
  114. data_len = 2;
  115. }
  116. break;
  117. case BLE_HID_HANDLE_REP_KEYBOARD_CCC:
  118. if (buffer) {
  119. TRACE("Read CCC Keyboard - val: 0x%04x\n", hid_report_client_config_keyboard);
  120. data_len = 2;
  121. memcpy(buffer, (u8 *)&hid_report_client_config_keyboard, 2);
  122. } else {
  123. data_len = 2;
  124. }
  125. break;
  126. case BLE_HID_HANDLE_REP_MOUSE_CCC:
  127. if (buffer) {
  128. TRACE("Read CCC Mouse - val: 0x%04x\n", hid_report_client_config_mouse);
  129. data_len = 2;
  130. memcpy(buffer, (u8 *)&hid_report_client_config_mouse, 2);
  131. } else {
  132. data_len = 2;
  133. }
  134. break;
  135. case BLE_HID_HANDLE_REP_CONSUMER:
  136. case BLE_HID_HANDLE_REP_KEYBOARD:
  137. case BLE_HID_HANDLE_REP_MOUSE:
  138. if (buffer) {
  139. /* Response default value that all zere */
  140. hid_rep_info_t hid_rep_info;
  141. memset(&hid_rep_info, 0x00, sizeof(hid_rep_info));
  142. data_len = sizeof(hid_rep_info.pdu);
  143. TRACE("Read Val - handle: 0x%04x val[%d]: ", attribute_handle, data_len);
  144. TRACE_R(&hid_rep_info.pdu, data_len);
  145. } else {
  146. hid_rep_info_t hid_rep_info;
  147. data_len = sizeof(hid_rep_info.pdu);
  148. }
  149. break;
  150. #endif // 0
  151. default:
  152. TRACE("No process read - handle: 0x%04x\n", attribute_handle);
  153. break;
  154. }
  155. return data_len;
  156. }
  157. static int hid_service_write_callback(uint16_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)
  158. {
  159. switch (attribute_handle) {
  160. case BLE_HID_HANDLE_CTRL_POINT:
  161. /* 0: suspend 1: exit suspend, maybe not used because some central will disc when sleep */
  162. TRACE("Write Suspend status - val: 0x%02x\n", buffer[0]);
  163. break;
  164. case BLE_HID_HANDLE_REP_CONSUMER_CCC:
  165. hid_report_client_config_consumer = GET_LE16(buffer);
  166. TRACE("Write CCC Consumer - val: 0x%04x\n", hid_report_client_config_consumer);
  167. break;
  168. case BLE_HID_HANDLE_REP_KEYBOARD_CCC:
  169. hid_report_client_config_keyboard = GET_LE16(buffer);
  170. TRACE("Write CCC Keyboard - val: 0x%04x\n", hid_report_client_config_keyboard);
  171. break;
  172. //case BLE_HID_HANDLE_REP_MOUSE_CCC:
  173. // hid_report_client_config_mouse = GET_LE16(buffer);
  174. // TRACE("Write CCC Mouse - val: 0x%04x\n", hid_report_client_config_mouse);
  175. // break;
  176. case BLE_HID_HANDLE_REP_LED:
  177. break;
  178. default:
  179. TRACE("No process write - handle: 0x%04x\n", attribute_handle);
  180. break;
  181. }
  182. return ATT_ERR_NO_ERR;
  183. }
  184. int ble_hid_mouse_report(hid_rep_info_t *param)
  185. {
  186. //uint16_t handle;
  187. int ret = -1;
  188. //if (param->report_id == HID_REP_ID_CONSUMER) {
  189. // handle = BLE_HID_HANDLE_REP_CONSUMER;
  190. //} else if (param->report_id == HID_REP_ID_KEYBOARD) {
  191. // handle = BLE_HID_HANDLE_REP_KEYBOARD;
  192. //} else if (param->report_id == HID_REP_ID_MOUSE) {
  193. // handle = BLE_HID_HANDLE_REP_MOUSE;
  194. //} else {
  195. // return ret;
  196. //}
  197. // TRACE("Report - handle: 0x%04x data[%d]: ", handle, sizeof(param->pdu));
  198. // TRACE_R(&param->pdu, sizeof(param->pdu));
  199. /* Some Central-Device do not subscribe again after being connected back. Do not determine the client config here */
  200. // TODO: The CCCD value shall be persistent across connections for bonded devices.
  201. lowpwr_pwroff_delay_reset();
  202. lowpwr_sleep_delay_reset();
  203. /*Prevent acl buffer is full before connection really success when report mouse data*/
  204. //if (!hid_report_client_config_mouse && (handle == BLE_HID_HANDLE_REP_MOUSE)) {
  205. // return ret;
  206. //}
  207. /*Prevent acl buffer is full before connection really success*/
  208. //if (!txpkt_is_full(&ble_tx)) {
  209. // ret = ble_notify_for_handle(hid_connect_handle, handle, (u8 *)&param->pdu, sizeof(param->pdu));
  210. //}
  211. return ret;
  212. }
  213. void ble_hid_service_init(void)
  214. {
  215. printf("%s\n", __func__);
  216. hid_service.start_handle = ATT_SERVICE_1812_START_HANDLE;
  217. hid_service.end_handle = ATT_SERVICE_1812_END_HANDLE;
  218. hid_service.read_callback = &hid_service_read_callback;
  219. hid_service.write_callback = &hid_service_write_callback;
  220. hid_service.event_handler = &hid_service_event_packet_handle;
  221. att_server_register_service_handler(&hid_service);
  222. hid_report_client_config_consumer = CCCD_DFT;
  223. hid_report_client_config_keyboard = CCCD_DFT;
  224. hid_report_client_config_mouse = CCCD_DFT;
  225. memset(&ble_hid_state, 0x00, sizeof(ble_hid_state));
  226. }
  227. void ble_hid_service_proc(void)
  228. {
  229. if (hid_connect_handle) {
  230. if (ble_hid_state.ready) {
  231. } else {
  232. /* Retry */
  233. ble_hid_state.ready = (0 == ble_hid_mouse_report(&ble_hid_state.data));
  234. }
  235. }
  236. }
  237. void ble_hid_set_mouse_cccd()
  238. {
  239. hid_report_client_config_mouse = 1;
  240. }