1 /*
2 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3 */
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdio.h>
8 //#include <aos/osal_debug.h>
9 #include <aos/ble.h>
10 #include <yoc/hids.h>
11
12 #define TAG "HIDS"
13
14 typedef struct hids_info_t {
15 uint16_t bcdHID;
16 uint8_t countryCode;
17 uint8_t flags;
18 } hids_info_t;
19
20 typedef struct hids_report_ref_t {
21 uint8_t id;
22 uint8_t type;
23 } hids_report_ref_t;
24
25 enum {
26 HIDS_INPUT = 0x01,
27 HIDS_OUTPUT = 0x02,
28 HIDS_FEATURE = 0x03,
29 };
30
31 enum {
32 HIDS_REMOTE_WAKE = 0x01,
33 HIDS_NORMALLY_CONNECTABLE = 0x02,
34 };
35
36 static hids_info_t g_hids_info = {
37 0x0101,
38 0x00,
39 HIDS_NORMALLY_CONNECTABLE | HIDS_REMOTE_WAKE,
40 };
41
42 static hids_report_ref_t report_input_ref = {
43 0x00,
44 HIDS_INPUT,
45 };
46
47 static hids_report_ref_t report_output_ref = {
48 0x00,
49 HIDS_OUTPUT,
50 };
51
52 //static hids_report_ref_t report_feature_ref = {
53 // 0x00,
54 // HIDS_FEATURE,
55 //};
56
57 typedef struct reportdata_array {
58 uint8_t *map_array;
59 uint16_t map_len;
60 int8_t s_flag;
61 } data_report_array;
62
63 static data_report_array data_in_out[] = {
64 {NULL, 0, -1}, //REPORT_MAP
65 {NULL, 0, -1}, //REPORT_INPUT
66 {NULL, 0, -1}, //REPORT_OUTPUT
67 };
68
69 gatt_service hids_service;
70
71
72 static uint8_t *get_data_map_data(uint8_t u_type);
73 static uint16_t get_data_map_len(uint8_t u_type);
74
75 typedef struct _hids_t {
76 uint16_t conn_handle;
77 uint16_t svc_handle;
78 uint16_t input_ccc;
79 uint16_t boot_input_ccc;
80 uint8_t protocol_mode;
81 } hids_t;
82
83 hids_t g_hids = {0};
84
85
86 typedef struct _register_hids_event_ {
87 int16_t idx;
88 hids_event_cb cb;
89 } register_hids_event ;
90 register_hids_event hids_event_arr[HIDS_IDX_MAX] = {0};
91
92 //static struct bt_gatt_ccc_cfg_t ccc_data1[2] = {};
93 //static struct bt_gatt_ccc_cfg_t ccc_data2[2] = {};
94
95 gatt_attr_t hids_attrs[] = {
96 GATT_PRIMARY_SERVICE_DEFINE(UUID_HIDS),
97 /* REPORT MAP */
98 GATT_CHAR_DEFINE(UUID_HIDS_REPORT_MAP, GATT_CHRC_PROP_READ),
99 GATT_CHAR_VAL_DEFINE(UUID_HIDS_REPORT_MAP, GATT_PERM_READ),
100
101 /* REPORT INPUT */
102 GATT_CHAR_DEFINE(UUID_HIDS_REPORT, GATT_CHRC_PROP_READ | GATT_CHRC_PROP_WRITE | GATT_CHRC_PROP_NOTIFY),
103 GATT_CHAR_VAL_DEFINE(UUID_HIDS_REPORT, GATT_PERM_READ | GATT_PERM_READ_AUTHEN),
104 GATT_CHAR_DESCRIPTOR_DEFINE(UUID_HIDS_REPORT_REF, GATT_PERM_READ),
105 GATT_CHAR_CCC_DEFINE(),
106
107 /* REPORT OUTPUT */
108 GATT_CHAR_DEFINE(UUID_HIDS_REPORT, GATT_CHRC_PROP_READ | GATT_CHRC_PROP_WRITE | GATT_CHRC_PROP_WRITE_WITHOUT_RESP),
109 GATT_CHAR_VAL_DEFINE(UUID_HIDS_REPORT, GATT_PERM_READ | GATT_PERM_READ_AUTHEN | GATT_PERM_WRITE),
110 GATT_CHAR_DESCRIPTOR_DEFINE(UUID_HIDS_REPORT_REF, GATT_PERM_READ),
111 #if 0
112 /* REPORT FEATURE */
113 GATT_CHAR_DEFINE(UUID_HIDS_REPORT, GATT_CHRC_PROP_READ | GATT_CHRC_PROP_WRITE),
114 GATT_CHAR_VAL_DEFINE(UUID_HIDS_REPORT, GATT_PERM_READ | GATT_PERM_READ_ENCRYPT | GATT_PERM_WRITE | GATT_PERM_WRITE_ENCRYPT),
115 GATT_CHAR_DESCRIPTOR_DEFINE(UUID_HIDS_REPORT_REF, GATT_PERM_READ),
116 #endif
117 /* Boot Keyboard Input Report */
118 GATT_CHAR_DEFINE(UUID_HIDS_BOOT_KB_IN_REPORT, GATT_CHRC_PROP_READ | GATT_CHRC_PROP_NOTIFY),
119 GATT_CHAR_VAL_DEFINE(UUID_HIDS_BOOT_KB_IN_REPORT, GATT_PERM_READ | GATT_PERM_READ_AUTHEN | GATT_PERM_WRITE),
120 GATT_CHAR_CCC_DEFINE(),
121
122 /* Boot Keyboard Output Report */
123 GATT_CHAR_DEFINE(UUID_HIDS_BOOT_KB_OUT_REPORT, GATT_CHRC_PROP_READ | GATT_CHRC_PROP_WRITE | GATT_CHRC_PROP_WRITE_WITHOUT_RESP),
124 GATT_CHAR_VAL_DEFINE(UUID_HIDS_BOOT_KB_OUT_REPORT, GATT_PERM_READ | GATT_PERM_READ_AUTHEN | GATT_PERM_WRITE), //
125
126 /* HID Information */
127 GATT_CHAR_DEFINE(UUID_HIDS_INFO, GATT_CHRC_PROP_READ),
128 GATT_CHAR_VAL_DEFINE(UUID_HIDS_INFO, GATT_PERM_READ),
129
130 /* HID Control Point */
131 GATT_CHAR_DEFINE(UUID_HIDS_CTRL_POINT, GATT_CHRC_PROP_WRITE_WITHOUT_RESP),
132 GATT_CHAR_VAL_DEFINE(UUID_HIDS_CTRL_POINT, GATT_PERM_WRITE),
133
134 /* Protocol Mode *///low power Suspend mode ,0x00 Boot Protocol Mode 0x01 report protocol mode
135 GATT_CHAR_DEFINE(UUID_HIDS_PROTOCOL_MODE, GATT_CHRC_PROP_READ | GATT_CHRC_PROP_WRITE_WITHOUT_RESP),
136 GATT_CHAR_VAL_DEFINE(UUID_HIDS_PROTOCOL_MODE, GATT_PERM_READ | GATT_PERM_WRITE),
137 };
138
read_report(evt_data_gatt_char_read_t * e,void * data,uint16_t len)139 static void read_report(evt_data_gatt_char_read_t *e, void *data, uint16_t len)
140 {
141 e->data = data;
142 e->len = len;
143 }
144
event_char_read(ble_event_en event,void * event_data)145 static void event_char_read(ble_event_en event, void *event_data)
146 {
147 evt_data_gatt_char_read_t *e = (evt_data_gatt_char_read_t *)event_data;
148
149 if (g_hids.conn_handle == 0xFFFF || e->char_handle < g_hids.svc_handle || e->char_handle >= g_hids.svc_handle + HIDS_IDX_MAX) {
150 return;
151 }
152
153 uint16_t hids_char_idx = e->char_handle - g_hids.svc_handle;
154
155 switch (hids_char_idx) {
156 case HIDS_IDX_REPORT_MAP_VAL:
157 read_report(e, get_data_map_data(REPORT_MAP), get_data_map_len(REPORT_MAP));
158 break;
159
160 case HIDS_IDX_REPORT_INPUT_VAL:
161 read_report(e, get_data_map_data(REPORT_INPUT), get_data_map_len(REPORT_INPUT));
162 break;
163
164 case HIDS_IDX_REPORT_INPUT_REF:
165 read_report(e, &report_input_ref, sizeof(report_input_ref));
166 break;
167
168 case HIDS_IDX_REPORT_OUTPUT_VAL:
169 read_report(e, get_data_map_data(REPORT_OUTPUT), get_data_map_len(REPORT_OUTPUT));
170 break;
171
172 case HIDS_IDX_REPORT_OUTPUT_REF:
173 read_report(e, &report_output_ref, sizeof(report_output_ref));
174 break;
175
176 case HIDS_IDX_INFO_VAL:
177 read_report(e, &g_hids_info, sizeof(g_hids_info));
178 break;
179
180 case HIDS_IDX_PROTOCOL_MODE_VAL:
181 read_report(e, &g_hids.protocol_mode, 1);
182 break;
183
184 default:
185 //LOGI(TAG, "unhandle event:%x\r\n\r\n", hids_char_idx);
186 break;
187 }
188 }
189
init_hids_call_func(int32_t idx,hids_event_cb cb_event)190 int init_hids_call_func(int32_t idx, hids_event_cb cb_event)
191 {
192 if (idx < 0 || idx >= HIDS_IDX_MAX) {
193 return -1;
194 }
195
196 if (hids_event_arr[idx].cb != NULL) {
197 hids_event_arr[idx].cb = cb_event;
198 }
199
200 return 0;
201 }
202
execute_hids_call_func(int32_t idx,void * event_data)203 int execute_hids_call_func(int32_t idx, void *event_data)
204 {
205 if (idx < 0 || idx >= HIDS_IDX_MAX) {
206 return -1;
207 }
208
209 if (hids_event_arr[idx].cb != NULL) {
210 hids_event_arr[idx].cb(idx, event_data);
211 }
212
213 return 0;
214 }
215
event_char_write(ble_event_en event,void * event_data)216 static void event_char_write(ble_event_en event, void *event_data)
217 {
218 evt_data_gatt_char_write_t *e = (evt_data_gatt_char_write_t *)event_data;
219 int ires = 0;
220
221 if (g_hids.conn_handle == 0xFFFF || e->char_handle < g_hids.svc_handle || e->char_handle >= g_hids.svc_handle + HIDS_IDX_MAX) {
222 return;
223 }
224
225 uint16_t hids_char_idx = e->char_handle - g_hids.svc_handle;
226
227 switch (hids_char_idx) {
228 case HIDS_IDX_REPORT_OUTPUT_VAL:
229 ires = execute_hids_call_func(HIDS_IDX_REPORT_OUTPUT_VAL, e);
230 break;
231
232 case HIDS_IDX_BOOT_KB_INPUT_REPORT_VAL:
233 ires = execute_hids_call_func(HIDS_IDX_BOOT_KB_INPUT_REPORT_VAL, e);
234 break;
235
236 case HIDS_IDX_BOOT_KB_OUTPUT_REPORT_VAL:
237 ires = execute_hids_call_func(HIDS_IDX_BOOT_KB_OUTPUT_REPORT_VAL, e);
238 break;
239
240 case HIDS_IDX_CTRL_VAL:
241 //LOGI(TAG, "control cmd %d, %s\n", e->data[0], e->data[0] == 0x00 ? " Suspend" :
242 // "Exit Suspend");
243 ires = execute_hids_call_func(HIDS_IDX_CTRL_VAL, e);
244 break;
245
246 case HIDS_IDX_PROTOCOL_MODE_VAL:
247 g_hids.protocol_mode = e->data[0];
248 break;
249
250 default:
251 break;
252 }
253
254 if (ires != 0) {
255 //LOGI(TAG, "event_char_write execute err\r\n");
256 }
257 }
258
event_char_ccc_change(ble_event_en event,void * event_data)259 static void event_char_ccc_change(ble_event_en event, void *event_data)
260 {
261 evt_data_gatt_char_ccc_change_t *e = (evt_data_gatt_char_ccc_change_t *)event_data;
262
263 if (g_hids.conn_handle == 0xFFFF || e->char_handle < g_hids.svc_handle || e->char_handle >= g_hids.svc_handle + HIDS_IDX_MAX) {
264 return;
265 }
266
267 uint16_t hids_char_idx = e->char_handle - g_hids.svc_handle;
268
269 switch (hids_char_idx) {
270 case HIDS_IDX_REPORT_INPUT_CCC:
271 g_hids.input_ccc = e->ccc_value;
272 break;
273
274 case HIDS_IDX_BOOT_KB_INPUT_REPORT_CCC:
275 g_hids.boot_input_ccc = e->ccc_value;
276 break;
277 }
278 }
279
conn_change(ble_event_en event,void * event_data)280 static void conn_change(ble_event_en event, void *event_data)
281 {
282 evt_data_gap_conn_change_t *e = (evt_data_gap_conn_change_t *)event_data;
283
284 if (e->connected == CONNECTED) {
285 g_hids.conn_handle = e->conn_handle;
286 } else {
287 g_hids.conn_handle = 0xFFFF;
288 }
289 }
290
hids_event_callback(ble_event_en event,void * event_data)291 static int hids_event_callback(ble_event_en event, void *event_data)
292 {
293 switch (event) {
294 case EVENT_GATT_CHAR_READ:
295 event_char_read(event, event_data);
296 break;
297
298 case EVENT_GATT_CHAR_WRITE:
299 event_char_write(event, event_data);
300 break;
301
302 case EVENT_GAP_CONN_CHANGE:
303 conn_change(event, event_data);
304 break;
305
306 case EVENT_GATT_CHAR_CCC_CHANGE:
307 event_char_ccc_change(event, event_data);
308 break;
309
310 default:
311 break;
312 }
313
314 return 0;
315 }
316
317 static ble_event_cb_t ble_cb = {
318 .callback = hids_event_callback,
319 };
320
hids_init(uint8_t mode)321 hids_handle_t hids_init(uint8_t mode)
322 {
323 int ret = 0;
324
325 ret = ble_stack_event_register(&ble_cb);
326
327 if (ret) {
328 return NULL;
329 }
330
331 ret = ble_stack_gatt_registe_service(&hids_service,hids_attrs, BLE_ARRAY_NUM(hids_attrs));
332
333 if (ret < 0) {
334 return NULL;
335 }
336
337 g_hids.conn_handle = 0xFFFF;
338 g_hids.svc_handle = ret;
339 g_hids.protocol_mode = mode;
340
341 memset(hids_event_arr, 0x0, sizeof(hids_event_arr));
342 return &g_hids;
343 }
344
hids_notify_send(hids_handle_t handle,uint8_t * key_code,uint16_t us_len)345 int hids_notify_send(hids_handle_t handle, uint8_t *key_code, uint16_t us_len)
346 {
347 hids_t *hids = handle;
348
349 if (handle == NULL) {
350 return -BLE_STACK_ERR_NULL;
351 }
352
353 if (hids->protocol_mode == HIDS_REPORT_PROTOCOL_MODE && hids->input_ccc == CCC_VALUE_NOTIFY) {
354 ble_stack_gatt_notificate(hids->conn_handle, hids->svc_handle + HIDS_IDX_REPORT_INPUT_VAL, key_code, us_len);
355 }
356
357 return 0;
358 }
hids_key_send(hids_handle_t handle,uint8_t * key_code,uint16_t us_len)359 int hids_key_send(hids_handle_t handle, uint8_t *key_code, uint16_t us_len)
360 {
361 hids_t *hids = handle;
362
363 if (handle == NULL) {
364 return -BLE_STACK_ERR_NULL;
365 }
366
367 ble_stack_gatt_notificate(hids->conn_handle, hids->svc_handle + HIDS_IDX_REPORT_INPUT_VAL, key_code, us_len);
368 return 0;
369 }
370
set_data_map(uint8_t u_data[],uint16_t len,uint8_t u_type)371 int set_data_map(uint8_t u_data[], uint16_t len, uint8_t u_type)
372 {
373 if (u_type >= REPORT_MAX) {
374 return -1;
375 }
376
377 //data_in_out[u_type].map_array = (uint8_t *)malloc(sizeof(uint8_t) * len);
378
379 //if (data_in_out[u_type].map_array == NULL) {
380 // return -1;
381 //}
382
383 data_in_out[u_type].map_array = u_data;
384 data_in_out[u_type].map_len = len;
385 data_in_out[u_type].s_flag = 0;
386
387 return 0;
388 }
get_data_map_data(uint8_t u_type)389 static uint8_t *get_data_map_data(uint8_t u_type)
390 {
391 if (u_type >= REPORT_MAX) {
392 return NULL;
393 }
394
395 if (data_in_out[u_type].s_flag == -1) {
396 return NULL;
397 }
398
399 return (uint8_t *)data_in_out[u_type].map_array;
400 }
401
get_data_map_len(uint8_t u_type)402 static uint16_t get_data_map_len(uint8_t u_type)
403 {
404 if (u_type >= REPORT_MAX) {
405 return -1;
406 }
407
408 if ((data_in_out[u_type].s_flag == -1) || (data_in_out[u_type].map_len > 512)) {
409 return -1;
410 }
411
412 return data_in_out[u_type].map_len;
413 }
414
415
416
417
418
419