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