1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-2013 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #include "bta/bta_api.h"
20 #include "bta_hh_int.h"
21 
22 #if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
23 
24 #include "bta/bta_api.h"
25 #include <string.h>
26 #include "stack/btm_api.h"
27 #include "stack/btm_ble_api.h"
28 #include "bta/bta_hh_co.h"
29 #include "bta/bta_gatt_api.h"
30 #include "srvc_api.h"
31 #include "btm_int.h"
32 #include "bta/utl.h"
33 
34 #define LOG_TAG "bt_bta_hh"
35 // #include "osi/include/log.h"
36 
37 #ifndef BTA_HH_LE_RECONN
38 #define BTA_HH_LE_RECONN    TRUE
39 #endif
40 
41 #define BTA_HH_APP_ID_LE            0xff
42 
43 #define BTA_HH_LE_RPT_TYPE_VALID(x)     ((x) <= BTA_LE_HID_RPT_FEATURE && (x)>=BTA_LE_HID_RPT_INPUT)
44 
45 #define BTA_HH_LE_RPT_INST_ID_MAP(s,c)  (UINT8)(((s)<<4)|(c))
46 #define BTA_HH_LE_RPT_GET_SRVC_INST_ID(x)  (UINT8)(x  >> 4)
47 #define BTA_HH_LE_RPT_GET_RPT_INST_ID(x)  (UINT8)(x & 0x0f)
48 
49 
50 #define BTA_HH_LE_PROTO_BOOT_MODE      0x00
51 #define BTA_HH_LE_PROTO_REPORT_MODE      0x01
52 
53 #define BTA_HH_SCPP_INST_DEF            0
54 
55 #define BTA_HH_LE_DISC_CHAR_NUM     8
56 static const UINT16 bta_hh_le_disc_char_uuid[BTA_HH_LE_DISC_CHAR_NUM] = {
57     GATT_UUID_HID_INFORMATION,
58     GATT_UUID_HID_REPORT_MAP,
59     GATT_UUID_HID_CONTROL_POINT,
60     GATT_UUID_HID_REPORT,
61     GATT_UUID_HID_BT_KB_INPUT,
62     GATT_UUID_HID_BT_KB_OUTPUT,
63     GATT_UUID_HID_BT_MOUSE_INPUT,
64     GATT_UUID_HID_PROTO_MODE        /* always make sure this is the last attribute to discover */
65 };
66 
67 #define BTA_LE_HID_RTP_UUID_MAX     5
68 static const UINT16 bta_hh_uuid_to_rtp_type[BTA_LE_HID_RTP_UUID_MAX][2] = {
69     {GATT_UUID_HID_REPORT,       BTA_HH_RPTT_INPUT},
70     {GATT_UUID_HID_BT_KB_INPUT,  BTA_HH_RPTT_INPUT},
71     {GATT_UUID_HID_BT_KB_OUTPUT, BTA_HH_RPTT_OUTPUT},
72     {GATT_UUID_HID_BT_MOUSE_INPUT, BTA_HH_RPTT_INPUT},
73     {GATT_UUID_BATTERY_LEVEL,      BTA_HH_RPTT_INPUT}
74 };
75 
76 
77 static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
78 static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb);
79 static void bta_hh_le_search_hid_included(tBTA_HH_DEV_CB *p_dev_cb);
80 static void bta_hh_le_search_scps(tBTA_HH_DEV_CB *p_cb);
81 static void bta_hh_le_search_scps_chars(tBTA_HH_DEV_CB *p_cb);
82 static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status);
83 static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status);
84 static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond);
85 static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
86                                       tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
87                                       UINT8 num_rpt);
88 
89 #define BTA_HH_LE_SRVC_DEF      0
90 
91 #if BTA_HH_DEBUG == TRUE
92 static const char *bta_hh_le_rpt_name[4] = {
93     "UNKNOWN",
94     "INPUT",
95     "OUTPUT",
96     "FEATURE"
97 };
98 
99 /*******************************************************************************
100 **
101 ** Function         bta_hh_le_hid_report_dbg
102 **
103 ** Description      debug function to print out all HID report available on remote
104 **                  device.
105 **
106 ** Returns          void
107 **
108 *******************************************************************************/
bta_hh_le_hid_report_dbg(tBTA_HH_DEV_CB * p_cb)109 static void bta_hh_le_hid_report_dbg(tBTA_HH_DEV_CB *p_cb)
110 {
111     UINT8 i , j;
112     tBTA_HH_LE_RPT  *p_rpt;
113     char   *rpt_name;
114 
115     APPL_TRACE_DEBUG("HID Report DB");
116     for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++) {
117         if (p_cb->hid_srvc[i].in_use) {
118             p_rpt = &p_cb->hid_srvc[i].report[0];
119 
120             APPL_TRACE_DEBUG("\t HID service inst: %d", i);
121 
122             for (j = 0; j < BTA_HH_LE_RPT_MAX; j ++, p_rpt++) {
123                 rpt_name = "Unknown";
124                 if (p_rpt->in_use) {
125                     if (p_rpt->uuid == GATT_UUID_HID_REPORT) {
126                         rpt_name = "Report";
127                     }
128                     if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT) {
129                         rpt_name = "Boot KB Input";
130                     }
131                     if (p_rpt->uuid == GATT_UUID_HID_BT_KB_OUTPUT) {
132                         rpt_name = "Boot KB Output";
133                     }
134                     if (p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) {
135                         rpt_name = "Boot MI Input";
136                     }
137 
138 
139                     APPL_TRACE_DEBUG("\t\t [%s- 0x%04x] [Type: %s], [ReportID: %d] [inst_id: %d]  [Clt_cfg: %d]",
140                                      rpt_name,
141                                      p_rpt->uuid ,
142                                      ((p_rpt->rpt_type < 4) ? bta_hh_le_rpt_name[p_rpt->rpt_type] : "UNKNOWN"),
143                                      p_rpt->rpt_id,
144                                      p_rpt->inst_id,
145                                      p_rpt->client_cfg_value);
146                 } else {
147                     break;
148                 }
149             }
150         } else {
151             break;
152         }
153     }
154 }
155 
156 /*******************************************************************************
157 **
158 ** Function         bta_hh_uuid_to_str
159 **
160 ** Description
161 **
162 ** Returns          void
163 **
164 *******************************************************************************/
bta_hh_uuid_to_str(UINT16 uuid)165 static char *bta_hh_uuid_to_str(UINT16 uuid)
166 {
167     switch (uuid) {
168     case GATT_UUID_HID_INFORMATION:
169         return "GATT_UUID_HID_INFORMATION";
170     case GATT_UUID_HID_REPORT_MAP:
171         return "GATT_UUID_HID_REPORT_MAP";
172     case GATT_UUID_HID_CONTROL_POINT:
173         return "GATT_UUID_HID_CONTROL_POINT";
174     case GATT_UUID_HID_REPORT:
175         return "GATT_UUID_HID_REPORT";
176     case GATT_UUID_HID_PROTO_MODE:
177         return "GATT_UUID_HID_PROTO_MODE";
178     case GATT_UUID_HID_BT_KB_INPUT:
179         return "GATT_UUID_HID_BT_KB_INPUT";
180     case GATT_UUID_HID_BT_KB_OUTPUT:
181         return "GATT_UUID_HID_BT_KB_OUTPUT";
182     case GATT_UUID_HID_BT_MOUSE_INPUT:
183         return "GATT_UUID_HID_BT_MOUSE_INPUT";
184     case GATT_UUID_CHAR_CLIENT_CONFIG:
185         return "GATT_UUID_CHAR_CLIENT_CONFIG";
186     case GATT_UUID_EXT_RPT_REF_DESCR:
187         return "GATT_UUID_EXT_RPT_REF_DESCR";
188     case GATT_UUID_RPT_REF_DESCR:
189         return "GATT_UUID_RPT_REF_DESCR";
190     default:
191         return "Unknown UUID";
192     }
193 }
194 
195 #endif
196 /*******************************************************************************
197 **
198 ** Function         bta_hh_le_enable
199 **
200 ** Description      initialize LE HID related functionality
201 **
202 **
203 ** Returns          void
204 **
205 *******************************************************************************/
bta_hh_le_enable(void)206 void bta_hh_le_enable(void)
207 {
208     char       app_name[LEN_UUID_128 + 1];
209     tBT_UUID    app_uuid = {LEN_UUID_128, {0}};
210     UINT8       xx;
211 
212     bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
213 
214     for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++) {
215         bta_hh_cb.le_cb_index[xx]       = BTA_HH_IDX_INVALID;
216     }
217 
218     memset (app_name, 0, LEN_UUID_128 + 1);
219     strncpy(app_name, "BTA HH OVER LE", LEN_UUID_128);
220 
221     memcpy((void *)app_uuid.uu.uuid128, (void *)app_name, LEN_UUID_128);
222 
223     BTA_GATTC_AppRegister(&app_uuid, bta_hh_gattc_callback);
224 
225     return;
226 }
227 
228 /*******************************************************************************
229 **
230 ** Function         bta_hh_le_register_cmpl
231 **
232 ** Description      BTA HH register with BTA GATTC completed
233 **
234 ** Parameters:
235 **
236 *******************************************************************************/
bta_hh_le_register_cmpl(tBTA_GATTC_REG * p_reg)237 void bta_hh_le_register_cmpl(tBTA_GATTC_REG *p_reg)
238 {
239     tBTA_HH_STATUS      status = BTA_HH_ERR;
240 
241     if (p_reg->status == BTA_GATT_OK) {
242         bta_hh_cb.gatt_if = p_reg->client_if;
243         status = BTA_HH_OK;
244     } else {
245         bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
246     }
247 
248     /* signal BTA call back event */
249     (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
250 }
251 
252 /*******************************************************************************
253 **
254 ** Function         bta_hh_le_is_hh_gatt_if
255 **
256 ** Description      Check to see if client_if is BTA HH LE GATT interface
257 **
258 **
259 ** Returns          whether it is HH GATT IF
260 **
261 *******************************************************************************/
bta_hh_le_is_hh_gatt_if(tBTA_GATTC_IF client_if)262 BOOLEAN bta_hh_le_is_hh_gatt_if(tBTA_GATTC_IF client_if)
263 {
264     return (bta_hh_cb.gatt_if == client_if);
265 }
266 
267 /*******************************************************************************
268 **
269 ** Function         bta_hh_le_deregister
270 **
271 ** Description      De-register BTA HH from BTA GATTC
272 **
273 **
274 ** Returns          void
275 **
276 *******************************************************************************/
bta_hh_le_deregister(void)277 void bta_hh_le_deregister(void)
278 {
279     BTA_GATTC_AppDeregister(bta_hh_cb.gatt_if);
280 }
281 
282 /*******************************************************************************
283 **
284 ** Function         bta_hh_is_le_device
285 **
286 ** Description      Check to see if the remote device is a LE only device
287 **
288 ** Parameters:
289 **
290 *******************************************************************************/
bta_hh_is_le_device(tBTA_HH_DEV_CB * p_cb,BD_ADDR remote_bda)291 BOOLEAN bta_hh_is_le_device(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda)
292 {
293     p_cb->is_le_device = BTM_UseLeLink (remote_bda);
294 
295     return p_cb->is_le_device;
296 }
297 
298 /*******************************************************************************
299 **
300 ** Function         bta_hh_le_add_hid_srvc_entry
301 **
302 ** Description      Add a HID service entry in the HID device control block
303 **
304 ** Parameters:
305 **
306 *******************************************************************************/
bta_hh_le_add_hid_srvc_entry(tBTA_HH_DEV_CB * p_dev_cb,UINT8 idx)307 BOOLEAN bta_hh_le_add_hid_srvc_entry(tBTA_HH_DEV_CB *p_dev_cb, UINT8 idx)
308 {
309     BOOLEAN added = FALSE;
310 
311     if (idx < BTA_HH_LE_HID_SRVC_MAX) {
312         p_dev_cb->hid_srvc[idx].in_use = TRUE;
313         added = TRUE;
314     } else {
315         APPL_TRACE_ERROR("DB full,max HID service entry!");
316     }
317     return added;
318 }
319 
320 /*******************************************************************************
321 **
322 ** Function         bta_hh_le_open_conn
323 **
324 ** Description      open a GATT connection first.
325 **
326 ** Parameters:
327 **
328 *******************************************************************************/
bta_hh_le_open_conn(tBTA_HH_DEV_CB * p_cb,BD_ADDR remote_bda)329 void bta_hh_le_open_conn(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda)
330 {
331     /* update cb_index[] map */
332     p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
333     memcpy(p_cb->addr, remote_bda, BD_ADDR_LEN);
334     bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
335     p_cb->in_use = TRUE;
336 
337     BTA_GATTC_Enh_Open(bta_hh_cb.gatt_if, remote_bda, BLE_ADDR_UNKNOWN_TYPE, TRUE,
338             BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, 0, NULL, NULL, NULL);
339 }
340 
341 /*******************************************************************************
342 **
343 ** Function         bta_hh_le_fill_16bits_gatt_id
344 **
345 ** Description      Utility function to fill a GATT ID structure
346 **
347 *******************************************************************************/
bta_hh_le_fill_16bits_gatt_id(UINT8 inst_id,UINT16 uuid,tBTA_GATT_ID * p_output)348 void bta_hh_le_fill_16bits_gatt_id(UINT8 inst_id, UINT16 uuid,  tBTA_GATT_ID *p_output)
349 {
350     p_output->inst_id        = inst_id;
351     p_output->uuid.len       = LEN_UUID_16;
352     p_output->uuid.uu.uuid16 = uuid;
353 }
354 
355 /*******************************************************************************
356 **
357 ** Function         bta_hh_le_fill_16bits_srvc_id
358 **
359 ** Description      Utility function to fill a service ID structure with a 16 bits
360 **                  service UUID.
361 **
362 *******************************************************************************/
bta_hh_le_fill_16bits_srvc_id(BOOLEAN is_pri,UINT8 inst_id,UINT16 srvc_uuid,tBTA_GATT_SRVC_ID * p_output)363 void bta_hh_le_fill_16bits_srvc_id(BOOLEAN is_pri, UINT8 inst_id, UINT16 srvc_uuid,
364                                    tBTA_GATT_SRVC_ID *p_output)
365 {
366     memset((void *)p_output, 0, sizeof(tBTA_GATT_SRVC_ID));
367     p_output->is_primary        = is_pri;
368     bta_hh_le_fill_16bits_gatt_id(inst_id, srvc_uuid, &p_output->id);
369 
370 }
371 
372 /*******************************************************************************
373 **
374 ** Function         bta_hh_le_fill_16bits_char_id
375 **
376 ** Description      Utility function to fill a char ID structure with a 16 bits
377 **                  char UUID.
378 **
379 *******************************************************************************/
bta_hh_le_fill_16bits_char_id(UINT8 inst_id,UINT16 char_uuid,tBTA_GATT_ID * p_output)380 void bta_hh_le_fill_16bits_char_id(UINT8 inst_id, UINT16 char_uuid,
381                                    tBTA_GATT_ID *p_output)
382 {
383     memset((void *)p_output, 0, sizeof(tBTA_GATT_ID));
384     bta_hh_le_fill_16bits_gatt_id(inst_id, char_uuid, p_output);
385 }
386 
387 /*******************************************************************************
388 **
389 ** Function         bta_hh_le_find_dev_cb_by_conn_id
390 **
391 ** Description      Utility function find a device control block by connection ID.
392 **
393 *******************************************************************************/
bta_hh_le_find_dev_cb_by_conn_id(UINT16 conn_id)394 tBTA_HH_DEV_CB *bta_hh_le_find_dev_cb_by_conn_id(UINT16 conn_id)
395 {
396     UINT8   i;
397     tBTA_HH_DEV_CB *p_dev_cb = &bta_hh_cb.kdev[0];
398 
399     for (i = 0; i < BTA_HH_MAX_DEVICE; i ++, p_dev_cb ++) {
400         if (p_dev_cb->in_use  && p_dev_cb->conn_id == conn_id) {
401             return p_dev_cb;
402         }
403     }
404     return NULL;
405 }
406 
407 /*******************************************************************************
408 **
409 ** Function         bta_hh_le_find_dev_cb_by_bda
410 **
411 ** Description      Utility function find a device control block by BD address.
412 **
413 *******************************************************************************/
bta_hh_le_find_dev_cb_by_bda(BD_ADDR bda)414 tBTA_HH_DEV_CB *bta_hh_le_find_dev_cb_by_bda(BD_ADDR bda)
415 {
416     UINT8   i;
417     tBTA_HH_DEV_CB *p_dev_cb = &bta_hh_cb.kdev[0];
418 
419     for (i = 0; i < BTA_HH_MAX_DEVICE; i ++, p_dev_cb ++) {
420         if (p_dev_cb->in_use  &&
421                 memcmp(p_dev_cb->addr, bda, BD_ADDR_LEN) == 0) {
422             return p_dev_cb;
423         }
424     }
425     return NULL;
426 }
427 
428 /*******************************************************************************
429 **
430 ** Function         bta_hh_le_find_service_inst_by_battery_inst_id
431 **
432 ** Description      find HID service instance ID by battery service instance ID
433 **
434 *******************************************************************************/
bta_hh_le_find_service_inst_by_battery_inst_id(tBTA_HH_DEV_CB * p_cb,UINT8 ba_inst_id)435 UINT8 bta_hh_le_find_service_inst_by_battery_inst_id(tBTA_HH_DEV_CB *p_cb, UINT8 ba_inst_id)
436 {
437     UINT8   i;
438 
439     for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++) {
440         if (p_cb->hid_srvc[i].in_use &&
441                 p_cb->hid_srvc[i].incl_srvc_inst == ba_inst_id) {
442             return i;
443         }
444     }
445     return BTA_HH_IDX_INVALID;
446 }
447 
448 /*******************************************************************************
449 **
450 ** Function         bta_hh_le_find_report_entry
451 **
452 ** Description      find the report entry by service instance and report UUID and
453 **                  instance ID
454 **
455 *******************************************************************************/
bta_hh_le_find_report_entry(tBTA_HH_DEV_CB * p_cb,UINT8 srvc_inst_id,UINT16 rpt_uuid,UINT8 char_inst_id)456 tBTA_HH_LE_RPT *bta_hh_le_find_report_entry(tBTA_HH_DEV_CB *p_cb,
457         UINT8  srvc_inst_id,  /* service instance ID */
458         UINT16 rpt_uuid,
459         UINT8  char_inst_id)
460 {
461     UINT8   i;
462     UINT8   hid_inst_id = srvc_inst_id;
463     tBTA_HH_LE_RPT *p_rpt;
464 
465     if (rpt_uuid == GATT_UUID_BATTERY_LEVEL) {
466         hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_cb, srvc_inst_id);
467 
468         if (hid_inst_id == BTA_HH_IDX_INVALID) {
469             return NULL;
470         }
471     }
472 
473     p_rpt = &p_cb->hid_srvc[hid_inst_id].report[0];
474 
475     for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++) {
476         if (p_rpt->uuid == rpt_uuid &&
477                 p_rpt->inst_id == BTA_HH_LE_RPT_INST_ID_MAP(srvc_inst_id, char_inst_id)) {
478 
479             return p_rpt;
480         }
481     }
482     return NULL;
483 
484 }
485 
486 /*******************************************************************************
487 **
488 ** Function         bta_hh_le_find_rpt_by_idtype
489 **
490 ** Description      find a report entry by report ID and protocol mode
491 **
492 ** Returns          void
493 **
494 *******************************************************************************/
bta_hh_le_find_rpt_by_idtype(tBTA_HH_LE_RPT * p_head,UINT8 mode,tBTA_HH_RPT_TYPE r_type,UINT8 rpt_id)495 tBTA_HH_LE_RPT *bta_hh_le_find_rpt_by_idtype(tBTA_HH_LE_RPT *p_head, UINT8 mode,
496         tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
497 {
498     tBTA_HH_LE_RPT *p_rpt = p_head;
499     UINT8   i;
500 
501 #if BTA_HH_DEBUG == TRUE
502     APPL_TRACE_DEBUG("bta_hh_le_find_rpt_by_idtype: r_type: %d rpt_id: %d", r_type, rpt_id);
503 #endif
504 
505     for (i = 0 ; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt++) {
506         if (p_rpt->in_use && p_rpt->rpt_id == rpt_id && r_type == p_rpt->rpt_type) {
507             /* return battery report w/o condition */
508             if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL) {
509                 return p_rpt;
510             }
511 
512             if (mode == BTA_HH_PROTO_RPT_MODE && p_rpt->uuid == GATT_UUID_HID_REPORT) {
513                 return p_rpt;
514             }
515 
516             if ( mode == BTA_HH_PROTO_BOOT_MODE &&
517                     (p_rpt->uuid >= GATT_UUID_HID_BT_KB_INPUT && p_rpt->uuid <= GATT_UUID_HID_BT_MOUSE_INPUT)) {
518                 return p_rpt;
519             }
520         }
521     }
522     return NULL;
523 }
524 
525 /*******************************************************************************
526 **
527 ** Function         bta_hh_le_find_alloc_report_entry
528 **
529 ** Description      find or allocate a report entry in the HID service report list.
530 **
531 *******************************************************************************/
bta_hh_le_find_alloc_report_entry(tBTA_HH_DEV_CB * p_cb,UINT8 srvc_inst_id,UINT16 rpt_uuid,UINT8 inst_id,UINT8 prop)532 tBTA_HH_LE_RPT *bta_hh_le_find_alloc_report_entry(tBTA_HH_DEV_CB *p_cb,
533         UINT8 srvc_inst_id,
534         UINT16 rpt_uuid,
535         UINT8  inst_id,
536         UINT8  prop)
537 {
538     UINT8   i, hid_inst_id = srvc_inst_id;
539     tBTA_HH_LE_RPT *p_rpt;
540 
541     if (rpt_uuid == GATT_UUID_BATTERY_LEVEL) {
542         hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_cb, srvc_inst_id);
543 
544         if (hid_inst_id == BTA_HH_IDX_INVALID) {
545             return NULL;
546         }
547     }
548     p_rpt = &p_cb->hid_srvc[hid_inst_id].report[0];
549 
550     for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++) {
551         if (!p_rpt->in_use ||
552                 (p_rpt->uuid == rpt_uuid &&
553                  p_rpt->inst_id == BTA_HH_LE_RPT_INST_ID_MAP(srvc_inst_id, inst_id))) {
554             if (!p_rpt->in_use) {
555                 p_rpt->in_use   = TRUE;
556                 p_rpt->index    = i;
557                 p_rpt->inst_id  = BTA_HH_LE_RPT_INST_ID_MAP(srvc_inst_id, inst_id);
558                 p_rpt->prop     = prop;
559                 p_rpt->uuid     = rpt_uuid;
560 
561                 /* assign report type */
562                 for (i = 0; i < BTA_LE_HID_RTP_UUID_MAX; i ++) {
563                     if (bta_hh_uuid_to_rtp_type[i][0] == rpt_uuid) {
564                         p_rpt->rpt_type = (tBTA_HH_RPT_TYPE)bta_hh_uuid_to_rtp_type[i][1];
565 
566                         if (rpt_uuid == GATT_UUID_HID_BT_KB_INPUT || rpt_uuid == GATT_UUID_HID_BT_KB_OUTPUT) {
567                             p_rpt->rpt_id = BTA_HH_KEYBD_RPT_ID;
568                         }
569 
570                         if (rpt_uuid == GATT_UUID_HID_BT_MOUSE_INPUT) {
571                             p_rpt->rpt_id = BTA_HH_MOUSE_RPT_ID;
572                         }
573 
574                         break;
575                     }
576                 }
577             }
578             return p_rpt;
579         }
580     }
581     return NULL;
582 }
583 
584 /*******************************************************************************
585 **
586 ** Function         bta_hh_le_read_char_dscrpt
587 **
588 ** Description      read characteristic descriptor
589 **
590 *******************************************************************************/
bta_hh_le_read_char_dscrpt(tBTA_HH_DEV_CB * p_cb,UINT16 srvc_uuid,UINT8 srvc_inst_id,UINT16 char_uuid,UINT8 char_inst_id,UINT16 char_descp_uuid)591 tBTA_HH_STATUS bta_hh_le_read_char_dscrpt(tBTA_HH_DEV_CB *p_cb, UINT16 srvc_uuid, UINT8 srvc_inst_id,
592         UINT16 char_uuid, UINT8 char_inst_id, UINT16 char_descp_uuid)
593 {
594     tBTA_GATTC_CHAR_ID  char_id;
595     tBT_UUID        descr_uuid;
596     tBTA_GATTC_CHAR_DESCR_ID    descr_id;
597     tBTA_HH_STATUS  status = BTA_HH_ERR;
598 
599     bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst_id, srvc_uuid, &char_id.srvc_id);
600     bta_hh_le_fill_16bits_char_id(char_inst_id, char_uuid, &char_id.char_id);
601 
602     descr_uuid.len       = LEN_UUID_16;
603     descr_uuid.uu.uuid16 = char_descp_uuid;
604 
605     /* find the report reference descriptor */
606     if (BTA_GATTC_GetFirstCharDescr(p_cb->conn_id,
607                                     &char_id,
608                                     &descr_uuid,
609                                     &descr_id) == BTA_GATT_OK) {
610         BTA_GATTC_ReadCharDescr(p_cb->conn_id,
611                                 &descr_id,
612                                 BTA_GATT_AUTH_REQ_NONE);
613 
614         status = BTA_HH_OK;
615     } else {
616 #if BTA_HH_DEBUG == TRUE
617         APPL_TRACE_WARNING("%s No descriptor exists: %s(0x%04x)", __func__,
618                  bta_hh_uuid_to_str(char_descp_uuid), char_descp_uuid);
619 #endif
620     }
621     return status;
622 }
623 
624 /*******************************************************************************
625 **
626 ** Function         bta_hh_le_read_rpt_ref_descr
627 **
628 ** Description      read report reference descriptors in service discovery process
629 **
630 *******************************************************************************/
bta_hh_le_read_rpt_ref_descr(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_LE_RPT * p_rpt)631 void bta_hh_le_read_rpt_ref_descr(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_LE_RPT *p_rpt)
632 {
633     BOOLEAN started = FALSE;
634     UINT16  srvc_uuid, char_uuid;
635 
636     while (p_rpt != NULL) {
637         if (!p_rpt->in_use) {
638             break;
639         }
640 
641         if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) {
642             /* is battery report */
643             if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL) {
644 #if BTA_HH_DEBUG == TRUE
645                 APPL_TRACE_DEBUG("read battery level report reference descriptor");
646 #endif
647                 srvc_uuid = UUID_SERVCLASS_BATTERY;
648                 char_uuid = GATT_UUID_BATTERY_LEVEL;
649             } else {
650 #if BTA_HH_DEBUG == TRUE
651                 APPL_TRACE_DEBUG("read HID report reference descriptor");
652 #endif
653                 srvc_uuid = UUID_SERVCLASS_LE_HID;
654                 char_uuid = GATT_UUID_HID_REPORT;
655             }
656 
657             if (bta_hh_le_read_char_dscrpt(p_dev_cb,
658                                            srvc_uuid,
659                                            BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt->inst_id),
660                                            char_uuid,
661                                            BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt->inst_id),
662                                            GATT_UUID_RPT_REF_DESCR)
663                     == BTA_HH_OK) {
664                 started = TRUE;
665                 break;
666             }
667         }
668 
669         if (p_rpt->index == BTA_HH_LE_RPT_MAX - 1) {
670             break;
671         }
672 
673         p_rpt ++;
674     }
675 
676 
677     /* if no report reference descriptor */
678     if (!started) {
679         /* explore next char */
680         bta_hh_le_search_hid_chars(p_dev_cb);
681     }
682 }
683 
684 /*******************************************************************************
685 **
686 ** Function         bta_hh_le_save_rpt_ref
687 **
688 ** Description      save report reference information and move to next one.
689 **
690 ** Parameters:
691 **
692 *******************************************************************************/
bta_hh_le_save_rpt_ref(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_LE_RPT * p_rpt,tBTA_GATTC_READ * p_data)693 void bta_hh_le_save_rpt_ref(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_LE_RPT  *p_rpt,
694                             tBTA_GATTC_READ *p_data)
695 {
696     UINT8                       *pp;
697     tBTA_HH_RPT_CACHE_ENTRY     rpt_entry;
698 
699     /* if the length of the descriptor value is right, parse it */
700     if (p_data->status == BTA_GATT_OK &&
701             p_data->p_value && p_data->p_value->unformat.len == 2) {
702         pp = p_data->p_value->unformat.p_value;
703 
704         STREAM_TO_UINT8(p_rpt->rpt_id, pp);
705         STREAM_TO_UINT8(p_rpt->rpt_type, pp);
706 
707         if (p_rpt->rpt_type > BTA_HH_RPTT_FEATURE) { /* invalid report type */
708             p_rpt->rpt_type = BTA_HH_RPTT_RESRV;
709         }
710 
711 #if BTA_HH_DEBUG == TRUE
712         APPL_TRACE_DEBUG("report ID: %d", p_rpt->rpt_id);
713 #endif
714         rpt_entry.rpt_id    = p_rpt->rpt_id;
715         rpt_entry.rpt_type  = p_rpt->rpt_type;
716         rpt_entry.rpt_uuid  = p_rpt->uuid;
717         rpt_entry.prop      = p_rpt->prop;
718         rpt_entry.inst_id   = p_rpt->inst_id;
719 
720         bta_hh_le_co_rpt_info(p_dev_cb->addr,
721                               &rpt_entry,
722                               p_dev_cb->app_id);
723     } else if (p_data->status == BTA_GATT_INSUF_AUTHENTICATION) {
724         /* close connection right away */
725         p_dev_cb->status = BTA_HH_ERR_AUTH_FAILED;
726         /* close the connection and report service discovery complete with error */
727         bta_hh_le_api_disc_act(p_dev_cb);
728         return;
729     }
730 
731     if (p_rpt->index < BTA_HH_LE_RPT_MAX - 1) {
732         p_rpt ++;
733     } else {
734         p_rpt = NULL;
735     }
736 
737     /* read next report reference descriptor  */
738     bta_hh_le_read_rpt_ref_descr(p_dev_cb, p_rpt);
739 
740 }
741 
742 /*******************************************************************************
743 **
744 ** Function         bta_hh_le_save_rpt_ref
745 **
746 ** Description      save report reference information and move to next one.
747 **
748 ** Parameters:
749 **
750 *******************************************************************************/
bta_hh_le_save_ext_rpt_ref(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_READ * p_data)751 void bta_hh_le_save_ext_rpt_ref(tBTA_HH_DEV_CB *p_dev_cb,
752                                 tBTA_GATTC_READ *p_data)
753 {
754     UINT8 *pp;
755 
756     /* if the length of the descriptor value is right, parse it
757       assume it's a 16 bits UUID */
758     if (p_data->status == BTA_GATT_OK &&
759             p_data->p_value && p_data->p_value->unformat.len == 2) {
760         pp = p_data->p_value->unformat.p_value;
761         STREAM_TO_UINT16(p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].ext_rpt_ref, pp);
762 
763 #if BTA_HH_DEBUG == TRUE
764         APPL_TRACE_DEBUG("External Report Reference UUID 0x%04x",
765                          p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].ext_rpt_ref);
766 #endif
767     }
768     bta_hh_le_search_hid_chars(p_dev_cb);
769 
770 }
771 
772 /*******************************************************************************
773 **
774 ** Function         bta_hh_le_register_input_notif
775 **
776 ** Description      Register for all notifications for the report applicable
777 **                  for the protocol mode.
778 **
779 ** Parameters:
780 **
781 *******************************************************************************/
bta_hh_le_register_input_notif(tBTA_HH_DEV_CB * p_dev_cb,UINT8 srvc_inst,UINT8 proto_mode,BOOLEAN register_ba)782 void bta_hh_le_register_input_notif(tBTA_HH_DEV_CB *p_dev_cb, UINT8 srvc_inst,
783                                     UINT8 proto_mode, BOOLEAN register_ba)
784 {
785     tBTA_HH_LE_RPT  *p_rpt = &p_dev_cb->hid_srvc[srvc_inst].report[0];
786     tBTA_GATTC_CHAR_ID  char_id;
787     UINT8   i;
788     UINT16  srvc_uuid;
789 
790 #if BTA_HH_DEBUG == TRUE
791     APPL_TRACE_DEBUG("bta_hh_le_register_input_notif mode: %d", proto_mode);
792 #endif
793 
794     for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++) {
795         if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) {
796             if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL) {
797                 srvc_uuid = UUID_SERVCLASS_BATTERY;
798             } else {
799                 srvc_uuid = UUID_SERVCLASS_LE_HID;
800             }
801 
802             bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt->inst_id), srvc_uuid, &char_id.srvc_id);
803             bta_hh_le_fill_16bits_char_id(BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt->inst_id), p_rpt->uuid, &char_id.char_id);
804 
805             if (register_ba && p_rpt->uuid == GATT_UUID_BATTERY_LEVEL) {
806                 BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
807                                                    p_dev_cb->addr,
808                                                    &char_id);
809             }
810             /* boot mode, deregister report input notification */
811             else if (proto_mode == BTA_HH_PROTO_BOOT_MODE) {
812                 if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
813                         p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION) {
814                     APPL_TRACE_DEBUG("---> Deregister Report ID: %d", p_rpt->rpt_id);
815                     BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if,
816                                                          p_dev_cb->addr,
817                                                          &char_id);
818                 }
819                 /* register boot reports notification */
820                 else if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
821                          p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) {
822                     APPL_TRACE_DEBUG("<--- Register Boot Report ID: %d", p_rpt->rpt_id);
823                     BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
824                                                        p_dev_cb->addr,
825                                                        &char_id);
826                 }
827             } else if (proto_mode == BTA_HH_PROTO_RPT_MODE) {
828                 if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
829                         p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
830                         p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION) {
831 
832                     APPL_TRACE_DEBUG("---> Deregister Boot Report ID: %d", p_rpt->rpt_id);
833                     BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if,
834                                                          p_dev_cb->addr,
835                                                          &char_id);
836                 } else if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
837                            p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION) {
838                     APPL_TRACE_DEBUG("<--- Register Report ID: %d", p_rpt->rpt_id);
839                     BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
840                                                        p_dev_cb->addr,
841                                                        &char_id);
842                 }
843             }
844             /*
845             else unknown protocol mode */
846         }
847     }
848 }
849 
850 /*******************************************************************************
851 **
852 ** Function         bta_hh_le_open_cmpl
853 **
854 ** Description      HID over GATT connection successfully opened
855 **
856 *******************************************************************************/
bta_hh_le_open_cmpl(tBTA_HH_DEV_CB * p_cb)857 void bta_hh_le_open_cmpl(tBTA_HH_DEV_CB *p_cb)
858 {
859     if ( p_cb->disc_active == BTA_HH_LE_DISC_NONE) {
860 #if BTA_HH_DEBUG
861         bta_hh_le_hid_report_dbg(p_cb);
862 #endif
863         bta_hh_le_register_input_notif(p_cb, 0, p_cb->mode, TRUE);
864         bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
865 
866 #if (BTA_HH_LE_RECONN == TRUE)
867         if (p_cb->status == BTA_HH_OK) {
868             bta_hh_le_add_dev_bg_conn(p_cb, TRUE);
869         }
870 #endif
871     }
872 }
873 
874 /*******************************************************************************
875 **
876 ** Function         bta_hh_le_write_char_clt_cfg
877 **
878 ** Description      Utility function to find and write client configuration of
879 **                  a characteristic
880 **
881 *******************************************************************************/
bta_hh_le_write_char_clt_cfg(tBTA_HH_DEV_CB * p_cb,UINT8 srvc_inst_id,UINT16 srvc_uuid16,UINT8 char_inst_id,UINT16 char_uuid16,UINT16 clt_cfg_value)882 BOOLEAN bta_hh_le_write_char_clt_cfg(tBTA_HH_DEV_CB *p_cb,
883                                      UINT8 srvc_inst_id, UINT16 srvc_uuid16,
884                                      UINT8 char_inst_id, UINT16 char_uuid16,
885                                      UINT16 clt_cfg_value)
886 {
887     tBTA_GATTC_CHAR_ID          char_id;
888     tBT_UUID                    descr_cond;
889     tBTA_GATTC_CHAR_DESCR_ID    descr_id;
890     tBTA_GATT_UNFMT             value;
891     UINT8                      buf[2], *pp = buf;
892 
893     bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst_id, srvc_uuid16, &char_id.srvc_id);
894     bta_hh_le_fill_16bits_char_id(char_inst_id, char_uuid16, &char_id.char_id);
895 
896     descr_cond.len       = LEN_UUID_16;
897     descr_cond.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG;
898 
899     value.len = 2;
900     value.p_value = buf;
901 
902     UINT16_TO_STREAM(pp, clt_cfg_value);
903 
904     if (BTA_GATTC_GetFirstCharDescr(p_cb->conn_id,
905                                     &char_id,
906                                     &descr_cond,
907                                     &descr_id) == BTA_GATT_OK) {
908         BTA_GATTC_WriteCharDescr(p_cb->conn_id,
909                                  &descr_id,
910                                  BTA_GATTC_TYPE_WRITE,
911                                  &value,
912                                  BTA_GATT_AUTH_REQ_NONE);
913 
914         return TRUE;
915     }
916     return FALSE;
917 }
918 
919 /*******************************************************************************
920 **
921 ** Function         bta_hh_le_write_rpt_clt_cfg
922 **
923 ** Description      write client configuration. This is only for input report
924 **                  enable all input notification upon connection open.
925 **
926 *******************************************************************************/
bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB * p_cb,UINT8 srvc_inst_id)927 BOOLEAN bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst_id)
928 {
929     UINT8           i;
930     tBTA_HH_LE_RPT  *p_rpt = &p_cb->hid_srvc[srvc_inst_id].report[p_cb->clt_cfg_idx];
931     UINT16          srvc_uuid;
932 
933     for (i = p_cb->clt_cfg_idx; i < BTA_HH_LE_RPT_MAX && p_rpt->in_use; i ++, p_rpt ++) {
934         /* enable notification for all input report, regardless mode */
935         if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
936 
937         {
938             if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL) {
939                 srvc_uuid = UUID_SERVCLASS_BATTERY;
940             } else {
941                 srvc_uuid = UUID_SERVCLASS_LE_HID;
942             }
943 
944             if (bta_hh_le_write_char_clt_cfg(p_cb,
945                                              BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt->inst_id),
946                                              srvc_uuid,
947                                              BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt->inst_id),
948                                              p_rpt->uuid,
949                                              BTA_GATT_CLT_CONFIG_NOTIFICATION)) {
950                 p_cb->clt_cfg_idx = i;
951                 return TRUE;
952             }
953         }
954 
955     }
956     p_cb->clt_cfg_idx = 0;
957 
958     /* client configuration is completed, send open callback */
959     if (p_cb->state == BTA_HH_W4_CONN_ST) {
960         p_cb->disc_active &= ~BTA_HH_LE_DISC_HIDS;
961 
962         /* discover scan parameter profile is act as report host */
963         bta_hh_le_search_scps(p_cb);
964     }
965     return FALSE;
966 }
967 
968 /*******************************************************************************
969 **
970 ** Function         bta_hh_le_set_protocol_mode
971 **
972 ** Description      Set remote device protocol mode.
973 **
974 *******************************************************************************/
bta_hh_le_set_protocol_mode(tBTA_HH_DEV_CB * p_cb,tBTA_HH_PROTO_MODE mode)975 BOOLEAN bta_hh_le_set_protocol_mode(tBTA_HH_DEV_CB *p_cb, tBTA_HH_PROTO_MODE mode)
976 {
977     tBTA_GATTC_CHAR_ID  char_id;
978     tBTA_HH_CBDATA      cback_data ;
979     BOOLEAN             exec = FALSE;
980 
981     APPL_TRACE_DEBUG("bta_hh_le_set_protocol_mode attempt mode: %s",
982                      (mode == BTA_HH_PROTO_RPT_MODE) ? "Report" : "Boot");
983 
984     cback_data.handle  = p_cb->hid_handle;
985     /* boot mode is not supported in the remote device */
986     if ((p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].option_char & BTA_HH_LE_PROTO_MODE_BIT) == 0) {
987         p_cb->mode  = BTA_HH_PROTO_RPT_MODE;
988 
989         if (mode == BTA_HH_PROTO_BOOT_MODE) {
990             APPL_TRACE_ERROR("Set Boot Mode failed!! No PROTO_MODE Char!");
991             cback_data.status = BTA_HH_ERR;
992         } else {
993             /* if set to report mode, need to de-register all input report notification */
994             bta_hh_le_register_input_notif(p_cb, 0, p_cb->mode, FALSE);
995             cback_data.status = BTA_HH_OK;
996         }
997         if (p_cb->state == BTA_HH_W4_CONN_ST) {
998             p_cb->status = (cback_data.status == BTA_HH_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
999         } else {
1000             (* bta_hh_cb.p_cback)(BTA_HH_SET_PROTO_EVT, (tBTA_HH *)&cback_data);
1001         }
1002     } else if (p_cb->mode != mode) {
1003         bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
1004         bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_PROTO_MODE, &char_id.char_id);
1005 
1006         p_cb->mode = mode;
1007         mode = (mode == BTA_HH_PROTO_BOOT_MODE) ? BTA_HH_LE_PROTO_BOOT_MODE : BTA_HH_LE_PROTO_REPORT_MODE;
1008 
1009         BTA_GATTC_WriteCharValue(p_cb->conn_id,
1010                                  &char_id,
1011                                  BTA_GATTC_TYPE_WRITE_NO_RSP,
1012                                  1,
1013                                  &mode,
1014                                  BTA_GATT_AUTH_REQ_NONE);
1015         exec        = TRUE;
1016     }
1017 
1018     return exec;
1019 }
1020 
1021 /*******************************************************************************
1022 **
1023 ** Function         bta_hh_le_get_protocol_mode
1024 **
1025 ** Description      Get remote device protocol mode.
1026 **
1027 *******************************************************************************/
bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB * p_cb)1028 void bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB *p_cb)
1029 {
1030     tBTA_GATTC_CHAR_ID  char_id;
1031     tBTA_HH_HSDATA    hs_data;
1032     UINT8 i;
1033 
1034     p_cb->w4_evt = BTA_HH_GET_PROTO_EVT;
1035 
1036     for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++) {
1037         if (p_cb->hid_srvc[i].in_use &&
1038                 p_cb->hid_srvc[i].option_char & BTA_HH_LE_PROTO_MODE_BIT) {
1039             bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
1040             bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_PROTO_MODE, &char_id.char_id);
1041 
1042             BTA_GATTC_ReadCharacteristic(p_cb->conn_id,
1043                                          &char_id,
1044                                          BTA_GATT_AUTH_REQ_NONE);
1045             break;
1046         }
1047     }
1048     /* no service support protocol_mode, by default report mode */
1049     if (i == BTA_HH_LE_HID_SRVC_MAX) {
1050         hs_data.status  = BTA_HH_OK;
1051         hs_data.handle  = p_cb->hid_handle;
1052         hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
1053         p_cb->w4_evt = 0;
1054         (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
1055     }
1056 
1057 }
1058 
1059 /*******************************************************************************
1060 **
1061 ** Function         bta_hh_le_expl_rpt
1062 **
1063 ** Description      explore all report characteristic
1064 **
1065 *******************************************************************************/
bta_hh_le_expl_rpt(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_CHAR_ID * p_char_id,tBT_UUID * p_char_cond,tBTA_GATT_CHAR_PROP prop)1066 void bta_hh_le_expl_rpt(tBTA_HH_DEV_CB *p_dev_cb,
1067                         tBTA_GATTC_CHAR_ID *p_char_id,
1068                         tBT_UUID *p_char_cond,
1069                         tBTA_GATT_CHAR_PROP prop)
1070 {
1071     tBTA_GATTC_CHAR_ID  char_result;
1072 
1073     do {
1074         if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
1075                                               p_dev_cb->cur_srvc_index,
1076                                               GATT_UUID_HID_REPORT,
1077                                               p_char_id->char_id.inst_id,
1078                                               prop) == NULL) {
1079             APPL_TRACE_ERROR("Add report entry failed !!!");
1080             break;
1081         }
1082 
1083         APPL_TRACE_DEBUG("Find more REPORT");
1084 
1085         if (BTA_GATTC_GetNextChar(p_dev_cb->conn_id,
1086                                   p_char_id,
1087                                   p_char_cond,
1088                                   &char_result,
1089                                   &prop) != BTA_GATT_OK) {
1090             break;
1091         }
1092 
1093         p_char_id = &char_result;
1094     } while (1);
1095 
1096     APPL_TRACE_API("%s all BLE reports searched", __func__);
1097     bta_hh_le_read_rpt_ref_descr(p_dev_cb,
1098                                  &p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].report[0]);
1099 
1100 
1101     return ;
1102 }
1103 
1104 /*******************************************************************************
1105 **
1106 ** Function         bta_hh_le_expl_boot_rpt
1107 **
1108 ** Description      explore boot report
1109 **
1110 *******************************************************************************/
bta_hh_le_expl_boot_rpt(tBTA_HH_DEV_CB * p_dev_cb,UINT16 char_uuid,tBTA_GATT_CHAR_PROP prop)1111 void bta_hh_le_expl_boot_rpt(tBTA_HH_DEV_CB *p_dev_cb, UINT16 char_uuid,
1112                              tBTA_GATT_CHAR_PROP prop)
1113 {
1114     if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
1115                                           p_dev_cb->cur_srvc_index,
1116                                           char_uuid,
1117                                           0,
1118                                           prop) == NULL)
1119 
1120     {
1121         APPL_TRACE_ERROR("Add report entry failed !!!");
1122     }
1123 
1124     return;
1125 }
1126 
1127 /*******************************************************************************
1128 **
1129 ** Function         bta_hh_le_dis_cback
1130 **
1131 ** Description      DIS read complete callback
1132 **
1133 ** Parameters:
1134 **
1135 *******************************************************************************/
bta_hh_le_dis_cback(BD_ADDR addr,tDIS_VALUE * p_dis_value)1136 void bta_hh_le_dis_cback(BD_ADDR addr, tDIS_VALUE *p_dis_value)
1137 {
1138     tBTA_HH_DEV_CB *p_cb = bta_hh_le_find_dev_cb_by_bda(addr);
1139 
1140 
1141     if (p_cb == NULL || p_dis_value == NULL) {
1142         APPL_TRACE_ERROR("received unexpected/error DIS callback");
1143         return;
1144     }
1145 
1146     p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
1147     /* plug in the PnP info for this device */
1148     if (p_dis_value->attr_mask & DIS_ATTR_PNP_ID_BIT) {
1149 #if BTA_HH_DEBUG == TRUE
1150         APPL_TRACE_DEBUG("Plug in PnP info: product_id = %02x, vendor_id = %04x, version = %04x",
1151                          p_dis_value->pnp_id.product_id,
1152                          p_dis_value->pnp_id.vendor_id,
1153                          p_dis_value->pnp_id.product_version);
1154 #endif
1155         p_cb->dscp_info.product_id = p_dis_value->pnp_id.product_id;
1156         p_cb->dscp_info.vendor_id  = p_dis_value->pnp_id.vendor_id;
1157         p_cb->dscp_info.version    = p_dis_value->pnp_id.product_version;
1158     }
1159     bta_hh_le_open_cmpl(p_cb);
1160 }
1161 
1162 /*******************************************************************************
1163 **
1164 ** Function         bta_hh_le_pri_service_discovery
1165 **
1166 ** Description      Initialize GATT discovery on the remote LE HID device by opening
1167 **                  a GATT connection first.
1168 **
1169 ** Parameters:
1170 **
1171 *******************************************************************************/
bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB * p_cb)1172 void bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB *p_cb)
1173 {
1174     tBT_UUID        pri_srvc;
1175 
1176     bta_hh_le_co_reset_rpt_cache(p_cb->addr, p_cb->app_id);
1177 
1178     p_cb->disc_active |= (BTA_HH_LE_DISC_HIDS | BTA_HH_LE_DISC_DIS);
1179 
1180     /* read DIS info */
1181     if (!DIS_ReadDISInfo(p_cb->addr, bta_hh_le_dis_cback, DIS_ATTR_PNP_ID_BIT)) {
1182         APPL_TRACE_ERROR("read DIS failed");
1183         p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
1184     }
1185 
1186     /* in parallel */
1187     /* start primary service discovery for HID service */
1188     pri_srvc.len        = LEN_UUID_16;
1189     pri_srvc.uu.uuid16  = UUID_SERVCLASS_LE_HID;
1190     BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
1191     return;
1192 }
1193 
1194 /*******************************************************************************
1195 **
1196 ** Function         bta_hh_le_encrypt_cback
1197 **
1198 ** Description      link encryption complete callback for bond verification.
1199 **
1200 ** Returns          None
1201 **
1202 *******************************************************************************/
bta_hh_le_encrypt_cback(BD_ADDR bd_addr,tBTA_GATT_TRANSPORT transport,void * p_ref_data,tBTM_STATUS result)1203 void bta_hh_le_encrypt_cback(BD_ADDR bd_addr, tBTA_GATT_TRANSPORT transport,
1204                              void *p_ref_data, tBTM_STATUS result)
1205 {
1206     UINT8   idx = bta_hh_find_cb(bd_addr);
1207     tBTA_HH_DEV_CB *p_dev_cb;
1208     UNUSED(p_ref_data);
1209     UNUSED (transport);
1210 
1211     if (idx != BTA_HH_IDX_INVALID) {
1212         p_dev_cb = &bta_hh_cb.kdev[idx];
1213     } else {
1214         APPL_TRACE_ERROR("unexpected encryption callback, ignore");
1215         return;
1216     }
1217     p_dev_cb->status = (result == BTM_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR_SEC;
1218     p_dev_cb->reason = result;
1219 
1220     bta_hh_sm_execute(p_dev_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1221 }
1222 
1223 /*******************************************************************************
1224 **
1225 ** Function         bta_hh_security_cmpl
1226 **
1227 ** Description      Security check completed, start the service discovery
1228 **                  if no cache available, otherwise report connection open completed
1229 **
1230 ** Parameters:
1231 **
1232 *******************************************************************************/
bta_hh_security_cmpl(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_buf)1233 void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1234 {
1235     tBTA_HH_RPT_CACHE_ENTRY     *p_rpt_cache;
1236     UINT8                       num_rpt = 0;
1237     UNUSED(p_buf);
1238 
1239     if (p_cb->status == BTA_HH_OK) {
1240         APPL_TRACE_DEBUG("bta_hh_security_cmpl OK");
1241         if (!p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use) {
1242             APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load");
1243             /* start loading the cache if not in stack */
1244             if ((p_rpt_cache = bta_hh_le_co_cache_load(p_cb->addr, &num_rpt, p_cb->app_id)) != NULL) {
1245                 bta_hh_process_cache_rpt(p_cb, p_rpt_cache, num_rpt);
1246             }
1247         }
1248         /*  discovery has been done for HID service */
1249         if (p_cb->app_id != 0 && p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use) {
1250             /* configure protocol mode */
1251             if (bta_hh_le_set_protocol_mode(p_cb, p_cb->mode) == FALSE) {
1252                 APPL_TRACE_ERROR("bta_hh_security_cmpl");
1253                 bta_hh_le_open_cmpl(p_cb);
1254             }
1255         }
1256         /* start primary service discovery for HID service */
1257         else {
1258             bta_hh_le_pri_service_discovery(p_cb);
1259         }
1260     } else {
1261         APPL_TRACE_ERROR("%s() - encryption failed; status=0x%04x, reason=0x%04x",
1262                          __FUNCTION__, p_cb->status, p_cb->reason);
1263         if (!(p_cb->status == BTA_HH_ERR_SEC && p_cb->reason == BTM_ERR_PROCESSING)) {
1264             bta_hh_le_api_disc_act(p_cb);
1265         }
1266     }
1267 }
1268 
1269 /*******************************************************************************
1270 **
1271 ** Function         bta_hh_le_notify_enc_cmpl
1272 **
1273 ** Description      process GATT encryption complete event
1274 **
1275 ** Returns
1276 **
1277 *******************************************************************************/
bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_buf)1278 void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1279 {
1280     if (p_cb == NULL || p_cb->security_pending == FALSE ||
1281             p_buf == NULL || p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if) {
1282         return;
1283     }
1284 
1285     p_cb->security_pending = FALSE;
1286     bta_hh_start_security(p_cb, NULL);
1287 }
1288 
1289 /*******************************************************************************
1290 **
1291 ** Function         bta_hh_clear_service_cache
1292 **
1293 ** Description      clear the service cache
1294 **
1295 ** Parameters:
1296 **
1297 *******************************************************************************/
bta_hh_clear_service_cache(tBTA_HH_DEV_CB * p_cb)1298 void bta_hh_clear_service_cache(tBTA_HH_DEV_CB *p_cb)
1299 {
1300     UINT8 i;
1301     tBTA_HH_LE_HID_SRVC     *p_hid_srvc = &p_cb->hid_srvc[0];
1302 
1303     p_cb->app_id = 0;
1304     p_cb->total_srvc = 0;
1305     p_cb->dscp_info.descriptor.dsc_list = NULL;
1306 
1307     for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++, p_hid_srvc ++) {
1308         utl_freebuf((void **)&p_hid_srvc->rpt_map);
1309         memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC));
1310     }
1311 }
1312 
1313 /*******************************************************************************
1314 **
1315 ** Function         bta_hh_start_security
1316 **
1317 ** Description      start the security check of the established connection
1318 **
1319 ** Parameters:
1320 **
1321 *******************************************************************************/
bta_hh_start_security(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_buf)1322 void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1323 {
1324     UINT8           sec_flag = 0;
1325     tBTM_SEC_DEV_REC  *p_dev_rec;
1326     UNUSED(p_buf);
1327 
1328     p_dev_rec = btm_find_dev(p_cb->addr);
1329     if (p_dev_rec) {
1330         if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
1331                 p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING) {
1332             /* if security collision happened, wait for encryption done */
1333             p_cb->security_pending = TRUE;
1334             return;
1335         }
1336     }
1337 
1338     /* verify bond */
1339     BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
1340 
1341     /* if link has been encrypted */
1342     if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) {
1343         bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1344     }
1345     /* if bonded and link not encrypted */
1346     else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) {
1347         sec_flag = BTM_BLE_SEC_ENCRYPT;
1348         p_cb->status = BTA_HH_ERR_AUTH_FAILED;
1349         BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, &sec_flag);
1350     }
1351     /* unbonded device, report security error here */
1352     else if (p_cb->sec_mask != BTA_SEC_NONE) {
1353         sec_flag = BTM_BLE_SEC_ENCRYPT_NO_MITM;
1354         p_cb->status = BTA_HH_ERR_AUTH_FAILED;
1355         bta_hh_clear_service_cache(p_cb);
1356         BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, &sec_flag);
1357     }
1358     /* otherwise let it go through */
1359     else {
1360         bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1361     }
1362 
1363 
1364 }
1365 
1366 /*******************************************************************************
1367 **
1368 ** Function         bta_hh_gatt_open
1369 **
1370 ** Description      process GATT open event.
1371 **
1372 ** Parameters:
1373 **
1374 *******************************************************************************/
bta_hh_gatt_open(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_buf)1375 void bta_hh_gatt_open(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1376 {
1377     tBTA_GATTC_OPEN *p_data = &p_buf->le_open;
1378     UINT8           *p2;
1379     tHID_STATUS     status = BTA_HH_ERR;
1380 
1381     /* if received invalid callback data , ignore it */
1382     if (p_cb == NULL || p_data == NULL) {
1383         return;
1384     }
1385 
1386     p2 = p_data->remote_bda;
1387 
1388     APPL_TRACE_DEBUG("bta_hh_gatt_open BTA_GATTC_OPEN_EVT bda= [%08x%04x] status =%d",
1389                      ((p2[0]) << 24) + ((p2[1]) << 16) + ((p2[2]) << 8) + (p2[3]),
1390                      ((p2[4]) << 8) + p2[5], p_data->status);
1391 
1392     if (p_data->status == BTA_GATT_OK) {
1393         p_cb->is_le_device  = TRUE;
1394         p_cb->in_use    = TRUE;
1395         p_cb->conn_id   = p_data->conn_id;
1396         p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
1397 
1398         bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
1399 
1400 #if BTA_HH_DEBUG == TRUE
1401         APPL_TRACE_DEBUG("hid_handle = %2x conn_id = %04x cb_index = %d", p_cb->hid_handle, p_cb->conn_id, p_cb->index);
1402 #endif
1403 
1404         bta_hh_sm_execute(p_cb, BTA_HH_START_ENC_EVT, NULL);
1405 
1406     } else { /* open failure */
1407         bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
1408     }
1409 
1410 }
1411 
1412 /*******************************************************************************
1413 **
1414 ** Function         bta_hh_le_close
1415 **
1416 ** Description      This function process the GATT close event and post it as a
1417 **                  BTA HH internal event
1418 **
1419 ** Parameters:
1420 **
1421 *******************************************************************************/
bta_hh_le_close(tBTA_GATTC_CLOSE * p_data)1422 void bta_hh_le_close(tBTA_GATTC_CLOSE *p_data)
1423 {
1424     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->remote_bda);
1425     tBTA_HH_LE_CLOSE    *p_buf = NULL;
1426     UINT16  sm_event = BTA_HH_GATT_CLOSE_EVT;
1427 
1428     if (p_dev_cb != NULL &&
1429             (p_buf = (tBTA_HH_LE_CLOSE *)osi_malloc(sizeof(tBTA_HH_LE_CLOSE))) != NULL) {
1430         p_buf->hdr.event            = sm_event;
1431         p_buf->hdr.layer_specific   = (UINT16)p_dev_cb->hid_handle;
1432         p_buf->conn_id              = p_data->conn_id;
1433         p_buf->reason               = p_data->reason;
1434 
1435         p_dev_cb->conn_id           = BTA_GATT_INVALID_CONN_ID;
1436         p_dev_cb->security_pending  = FALSE;
1437         bta_sys_sendmsg(p_buf);
1438     }
1439 }
1440 
1441 /*******************************************************************************
1442 **
1443 ** Function         bta_hh_le_search_result
1444 **
1445 ** Description      This function process the GATT service search result.
1446 **
1447 ** Parameters:
1448 **
1449 *******************************************************************************/
bta_hh_le_search_result(tBTA_GATTC_SRVC_RES * p_srvc_result)1450 void bta_hh_le_search_result(tBTA_GATTC_SRVC_RES *p_srvc_result)
1451 {
1452     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_srvc_result->conn_id);
1453 
1454     if (p_dev_cb != NULL) {
1455         switch (p_srvc_result->service_uuid.id.uuid.uu.uuid16) {
1456         case UUID_SERVCLASS_LE_HID:
1457             if (p_srvc_result->service_uuid.is_primary) {
1458                 /* found HID primamry service */
1459                 /* TODO: proceed to find battery and device info */
1460                 if (bta_hh_le_add_hid_srvc_entry(p_dev_cb, p_dev_cb->total_srvc)) {
1461                     p_dev_cb->total_srvc ++;
1462                 }
1463                 APPL_TRACE_DEBUG("num of hid service: %d", p_dev_cb->total_srvc);
1464             }
1465             break;
1466 
1467         case UUID_SERVCLASS_SCAN_PARAM : /* scan parameter service */
1468             bta_hh_le_search_scps_chars(p_dev_cb);
1469             break;
1470         }
1471 
1472     }
1473 
1474 }
1475 
1476 
1477 /*******************************************************************************
1478 **
1479 ** Function         bta_hh_le_gatt_disc_cmpl
1480 **
1481 ** Description      Check to see if the remote device is a LE only device
1482 **
1483 ** Parameters:
1484 **
1485 *******************************************************************************/
bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB * p_cb,tBTA_HH_STATUS status)1486 void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status)
1487 {
1488     APPL_TRACE_DEBUG("bta_hh_le_gatt_disc_cmpl ");
1489 
1490     /* if open successful or protocol mode not desired, keep the connection open but inform app */
1491     if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO) {
1492         /* assign a special APP ID temp, since device type unknown */
1493         p_cb->app_id = BTA_HH_APP_ID_LE;
1494 
1495         /* set report notification configuration */
1496         p_cb->clt_cfg_idx = 0;
1497         bta_hh_le_write_rpt_clt_cfg(p_cb, BTA_HH_LE_SRVC_DEF);
1498     } else { /* error, close the GATT connection */
1499         /* close GATT connection if it's on */
1500         bta_hh_le_api_disc_act(p_cb);
1501     }
1502 }
1503 
1504 /*******************************************************************************
1505 **
1506 ** Function         bta_hh_le_srvc_expl_srvc
1507 **
1508 ** Description      This function discover the next available HID service.
1509 **
1510 ** Parameters:
1511 **
1512 *******************************************************************************/
bta_hh_le_srvc_expl_srvc(tBTA_HH_DEV_CB * p_dev_cb)1513 void bta_hh_le_srvc_expl_srvc(tBTA_HH_DEV_CB *p_dev_cb)
1514 {
1515 #if BTA_HH_DEBUG == TRUE
1516     APPL_TRACE_DEBUG("bta_hh_le_srvc_expl_srvc cur_srvc_index = %d in_use = %d",
1517                      p_dev_cb->cur_srvc_index,
1518                      p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].in_use);
1519 #endif
1520 
1521     if (p_dev_cb->cur_srvc_index < BTA_HH_LE_HID_SRVC_MAX &&
1522             p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].in_use) {
1523         if (!p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc)
1524             /* explore included service first */
1525         {
1526             bta_hh_le_search_hid_included(p_dev_cb);
1527         } else {
1528             /* explore characterisc */
1529             p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx = 0;
1530             bta_hh_le_search_hid_chars(p_dev_cb);
1531         }
1532     } else { /* all service discvery finished */
1533         bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status);
1534     }
1535 }
1536 
1537 /*******************************************************************************
1538 **
1539 ** Function         bta_hh_le_srvc_search_cmpl
1540 **
1541 ** Description      This function process the GATT service search complete.
1542 **
1543 ** Parameters:
1544 **
1545 *******************************************************************************/
bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL * p_data)1546 void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL *p_data)
1547 {
1548     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
1549 
1550     /* service search exception or no HID service is supported on remote */
1551     if (p_dev_cb == NULL) {
1552         return;
1553     }
1554 
1555     if (p_data->status != BTA_GATT_OK || p_dev_cb->total_srvc == 0) {
1556         p_dev_cb->status = BTA_HH_ERR_SDP;
1557         /* close the connection and report service discovery complete with error */
1558         bta_hh_le_api_disc_act(p_dev_cb);
1559     }
1560     /* GATT service discovery successfully finished */
1561     else {
1562         if (p_dev_cb->disc_active  & BTA_HH_LE_DISC_SCPS) {
1563             p_dev_cb->disc_active  &= ~BTA_HH_LE_DISC_SCPS;
1564             bta_hh_le_open_cmpl(p_dev_cb);
1565         } else { /* discover HID service */
1566             p_dev_cb->cur_srvc_index = 0;
1567             bta_hh_le_srvc_expl_srvc(p_dev_cb);
1568         }
1569     }
1570 }
1571 
1572 /*******************************************************************************
1573 **
1574 ** Function         bta_hh_le_search_hid_included
1575 **
1576 ** Description      This function search the included service within the HID service.
1577 **
1578 ** Parameters:
1579 **
1580 *******************************************************************************/
bta_hh_le_search_hid_included(tBTA_HH_DEV_CB * p_dev_cb)1581 static void bta_hh_le_search_hid_included(tBTA_HH_DEV_CB *p_dev_cb)
1582 {
1583     tBT_UUID    srvc_cond, char_cond;
1584     tBTA_GATTC_INCL_SVC_ID  inc_srvc_result;
1585     tBTA_GATT_SRVC_ID srvc_id;
1586     tBTA_GATTC_CHAR_ID  char_result;
1587     tBTA_GATT_CHAR_PROP prop = 0;
1588 
1589     bta_hh_le_fill_16bits_srvc_id(TRUE, p_dev_cb->cur_srvc_index, UUID_SERVCLASS_LE_HID, &srvc_id);
1590 
1591     srvc_cond.len = LEN_UUID_16;
1592     srvc_cond.uu.uuid16 = UUID_SERVCLASS_BATTERY;
1593 
1594     if (BTA_GATTC_GetFirstIncludedService(p_dev_cb->conn_id,
1595                                           &srvc_id,
1596                                           &srvc_cond,
1597                                           &inc_srvc_result) == BTA_GATT_OK) {
1598         /* read include service UUID */
1599         p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].incl_srvc_inst = inc_srvc_result.incl_svc_id.id.inst_id;
1600 
1601         char_cond.len = LEN_UUID_16;
1602         char_cond.uu.uuid16 = GATT_UUID_BATTERY_LEVEL;
1603 
1604         /* find the battery characteristic */
1605         if (BTA_GATTC_GetFirstChar( p_dev_cb->conn_id,
1606                                     &inc_srvc_result.incl_svc_id,
1607                                     &char_cond,
1608                                     &char_result,
1609                                     &prop) == BTA_GATT_OK) {
1610 
1611             if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
1612                                                   char_result.srvc_id.id.inst_id,
1613                                                   GATT_UUID_BATTERY_LEVEL,
1614                                                   char_result.char_id.inst_id,
1615                                                   prop) == NULL) {
1616                 APPL_TRACE_ERROR("Add battery report entry failed !!!")
1617             }
1618 
1619             /* read the battery characteristic */
1620             BTA_GATTC_ReadCharacteristic(p_dev_cb->conn_id,
1621                                          &char_result,
1622                                          BTA_GATT_AUTH_REQ_NONE);
1623 
1624             return;
1625 
1626         } else {
1627             APPL_TRACE_ERROR("Remote device does not have battery level");
1628         }
1629     }
1630 
1631     p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE;
1632 
1633     bta_hh_le_srvc_expl_srvc(p_dev_cb);
1634 
1635 }
1636 
1637 /*******************************************************************************
1638 **
1639 ** Function         bta_hh_read_battery_level_cmpl
1640 **
1641 ** Description      This function process the battery level read
1642 **
1643 ** Parameters:
1644 **
1645 *******************************************************************************/
bta_hh_read_battery_level_cmpl(UINT8 status,tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_READ * p_data)1646 void bta_hh_read_battery_level_cmpl(UINT8 status, tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1647 {
1648     UNUSED(status);
1649     UNUSED(p_data);
1650 
1651     p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE;
1652     bta_hh_le_srvc_expl_srvc(p_dev_cb);
1653 }
1654 /*******************************************************************************
1655 **
1656 ** Function         bta_hh_le_search_hid_chars
1657 **
1658 ** Description      This function discover all characteristics a service and
1659 **                  all descriptors available.
1660 **
1661 ** Parameters:
1662 **
1663 *******************************************************************************/
bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB * p_dev_cb)1664 static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb)
1665 {
1666     tBT_UUID    char_cond;
1667     tBTA_GATTC_CHAR_ID  char_result;
1668     tBTA_GATT_CHAR_PROP prop;
1669     BOOLEAN     next = TRUE;
1670     UINT16      char_uuid = 0;
1671     tBTA_GATT_SRVC_ID srvc_id;
1672 
1673     if (p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx == BTA_HH_LE_DISC_CHAR_NUM ||
1674             (p_dev_cb->status != BTA_HH_OK && p_dev_cb->status != BTA_HH_ERR_PROTO)) {
1675         p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx = 0;
1676         /* explore next service */
1677         p_dev_cb->cur_srvc_index ++;
1678         bta_hh_le_srvc_expl_srvc(p_dev_cb);
1679         return;
1680     }
1681 
1682     p_dev_cb->hid_srvc[ p_dev_cb->cur_srvc_index].cur_expl_char_idx ++;
1683     char_uuid = bta_hh_le_disc_char_uuid[p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx - 1];
1684 
1685     char_cond.len = LEN_UUID_16;
1686     char_cond.uu.uuid16 = char_uuid;
1687 
1688     bta_hh_le_fill_16bits_srvc_id(TRUE, p_dev_cb->cur_srvc_index, UUID_SERVCLASS_LE_HID, &srvc_id);
1689 
1690 #if BTA_HH_DEBUG == TRUE
1691     APPL_TRACE_DEBUG("bta_hh_le_search_hid_chars: looking for %s(0x%04x)",
1692                      bta_hh_uuid_to_str(char_uuid), char_uuid);
1693 #endif
1694 
1695     if (BTA_GATTC_GetFirstChar( p_dev_cb->conn_id,
1696                                 &srvc_id,
1697                                 &char_cond,
1698                                 &char_result,
1699                                 &prop) == BTA_GATT_OK) {
1700         switch (char_uuid) {
1701         case GATT_UUID_HID_CONTROL_POINT:
1702             p_dev_cb->hid_srvc[char_result.srvc_id.id.inst_id].option_char |= BTA_HH_LE_CP_BIT;
1703             next = TRUE;
1704             break;
1705         case GATT_UUID_HID_INFORMATION:
1706         case GATT_UUID_HID_REPORT_MAP:
1707             /* read the char value */
1708             BTA_GATTC_ReadCharacteristic(p_dev_cb->conn_id,
1709                                          &char_result,
1710                                          BTA_GATT_AUTH_REQ_NONE);
1711             next = FALSE;
1712             break;
1713 
1714         case GATT_UUID_HID_PROTO_MODE:
1715             p_dev_cb->hid_srvc[char_result.srvc_id.id.inst_id].option_char |= BTA_HH_LE_PROTO_MODE_BIT;
1716             next = !bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
1717             break;
1718 
1719         case GATT_UUID_HID_REPORT:
1720             bta_hh_le_expl_rpt(p_dev_cb, &char_result, &char_cond, prop);
1721             next = FALSE;
1722             break;
1723 
1724         /* found boot mode report types */
1725         case GATT_UUID_HID_BT_KB_OUTPUT:
1726         case GATT_UUID_HID_BT_MOUSE_INPUT:
1727         case GATT_UUID_HID_BT_KB_INPUT:
1728             bta_hh_le_expl_boot_rpt(p_dev_cb, char_uuid, prop);
1729             break;
1730         }
1731     } else {
1732         if (char_uuid == GATT_UUID_HID_PROTO_MODE) {
1733             next = !bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
1734         }
1735 
1736     }
1737 
1738     if (next == TRUE) {
1739         bta_hh_le_search_hid_chars(p_dev_cb);
1740     }
1741 }
1742 
1743 /*******************************************************************************
1744 **
1745 ** Function         bta_hh_le_save_rpt_map
1746 **
1747 ** Description      save the report map into the control block.
1748 **
1749 ** Parameters:
1750 **
1751 *******************************************************************************/
bta_hh_le_save_rpt_map(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_READ * p_data)1752 void bta_hh_le_save_rpt_map(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1753 {
1754     UINT8           *pp ;
1755     tBTA_HH_LE_HID_SRVC *p_srvc = &p_dev_cb->hid_srvc[p_data->srvc_id.id.inst_id];
1756 
1757     pp = p_data->p_value->unformat.p_value;
1758 
1759     /* save report descriptor */
1760     if (p_srvc->rpt_map != NULL) {
1761         osi_free((void *)p_srvc->rpt_map);
1762     }
1763 
1764     if (p_data->p_value->unformat.len > 0) {
1765         p_srvc->rpt_map = (UINT8 *)osi_malloc(p_data->p_value->unformat.len);
1766     }
1767 
1768     if (p_srvc->rpt_map != NULL) {
1769         STREAM_TO_ARRAY(p_srvc->rpt_map, pp, p_data->p_value->unformat.len);
1770         p_srvc->descriptor.dl_len = p_data->p_value->unformat.len;
1771         p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc[p_data->srvc_id.id.inst_id].rpt_map;
1772     }
1773 
1774     if (bta_hh_le_read_char_dscrpt(p_dev_cb,
1775                                    UUID_SERVCLASS_LE_HID,
1776                                    p_data->srvc_id.id.inst_id,
1777                                    GATT_UUID_HID_REPORT_MAP,
1778                                    p_data->char_id.inst_id,
1779                                    GATT_UUID_EXT_RPT_REF_DESCR) != BTA_HH_OK) {
1780         bta_hh_le_search_hid_chars(p_dev_cb);
1781     }
1782 }
1783 
1784 /*******************************************************************************
1785 **
1786 ** Function         bta_hh_le_proc_get_rpt_cmpl
1787 **
1788 ** Description      Process the Read report complete, send GET_REPORT_EVT to application
1789 **                  with the report data.
1790 **
1791 ** Parameters:
1792 **
1793 *******************************************************************************/
bta_hh_le_proc_get_rpt_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_READ * p_data)1794 void bta_hh_le_proc_get_rpt_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1795 {
1796     BT_HDR              *p_buf = NULL;
1797     tBTA_HH_LE_RPT      *p_rpt;
1798     tBTA_HH_HSDATA      hs_data;
1799     UINT8               *pp ;
1800 
1801     if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT) {
1802         APPL_TRACE_ERROR("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt);
1803         return;
1804     }
1805 
1806     memset(&hs_data, 0, sizeof(hs_data));
1807     hs_data.status  = BTA_HH_ERR;
1808     hs_data.handle  = p_dev_cb->hid_handle;
1809 
1810     if (p_data->status == BTA_GATT_OK) {
1811         p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1812                                             p_data->srvc_id.id.inst_id,//BTA_HH_LE_SRVC_DEF,
1813                                             p_data->char_id.uuid.uu.uuid16,
1814                                             p_data->char_id.inst_id);
1815 
1816         if (p_rpt != NULL &&
1817                 p_data->p_value != NULL &&
1818                 (p_buf = (BT_HDR *)osi_malloc((UINT16)(sizeof(BT_HDR) + p_data->p_value->unformat.len + 1))) != NULL) {
1819             /* pack data send to app */
1820             hs_data.status  = BTA_HH_OK;
1821             p_buf->len = p_data->p_value->unformat.len + 1;
1822             p_buf->layer_specific = 0;
1823             p_buf->offset = 0;
1824 
1825             /* attach report ID as the first byte of the report before sending it to USB HID driver */
1826             pp = (UINT8 *)(p_buf + 1);
1827             UINT8_TO_STREAM(pp, p_rpt->rpt_id);
1828             memcpy(pp, p_data->p_value->unformat.p_value, p_data->p_value->unformat.len);
1829 
1830             hs_data.rsp_data.p_rpt_data = p_buf;
1831         }
1832     }
1833 
1834     p_dev_cb->w4_evt = 0;
1835     (* bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH *)&hs_data);
1836 
1837     utl_freebuf((void **)&p_buf);
1838 }
1839 
1840 /*******************************************************************************
1841 **
1842 ** Function         bta_hh_le_proc_read_proto_mode
1843 **
1844 ** Description      Process the Read protocol mode, send GET_PROTO_EVT to application
1845 **                  with the protocol mode.
1846 **
1847 *******************************************************************************/
bta_hh_le_proc_read_proto_mode(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_READ * p_data)1848 void bta_hh_le_proc_read_proto_mode(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1849 {
1850     tBTA_HH_HSDATA      hs_data;
1851 
1852     hs_data.status  = BTA_HH_ERR;
1853     hs_data.handle  = p_dev_cb->hid_handle;
1854     hs_data.rsp_data.proto_mode = p_dev_cb->mode;
1855 
1856     if (p_data->status == BTA_GATT_OK && p_data->p_value) {
1857         hs_data.status  = BTA_HH_OK;
1858         /* match up BTE/BTA report/boot mode def*/
1859         hs_data.rsp_data.proto_mode = *(p_data->p_value->unformat.p_value);
1860         /* LE repot mode is the opposite value of BR/EDR report mode, flip it here */
1861         if (hs_data.rsp_data.proto_mode == 0) {
1862             hs_data.rsp_data.proto_mode = BTA_HH_PROTO_BOOT_MODE;
1863         } else {
1864             hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
1865         }
1866 
1867         p_dev_cb->mode = hs_data.rsp_data.proto_mode;
1868     }
1869 #if BTA_HH_DEBUG
1870     APPL_TRACE_DEBUG("LE GET_PROTOCOL Mode = [%s]",
1871                      (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE) ? "Report" : "Boot");
1872 #endif
1873 
1874     p_dev_cb->w4_evt = 0;
1875     (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
1876 
1877 }
1878 
1879 /*******************************************************************************
1880 **
1881 ** Function         bta_hh_w4_le_read_char_cmpl
1882 **
1883 ** Description      process the GATT read complete in W4_CONN state.
1884 **
1885 ** Parameters:
1886 **
1887 *******************************************************************************/
bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)1888 void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1889 {
1890     tBTA_GATTC_READ      *p_data = (tBTA_GATTC_READ *)p_buf;
1891     UINT8               *pp ;
1892 
1893     if (p_data->char_id.uuid.uu.uuid16 == GATT_UUID_BATTERY_LEVEL) {
1894         bta_hh_read_battery_level_cmpl(p_data->status, p_dev_cb, p_data);
1895     } else {
1896         if (p_data->status == BTA_GATT_OK && p_data->p_value) {
1897             pp = p_data->p_value->unformat.p_value;
1898 
1899             switch (p_data->char_id.uuid.uu.uuid16) {
1900             /* save device information */
1901             case GATT_UUID_HID_INFORMATION:
1902                 STREAM_TO_UINT16(p_dev_cb->dscp_info.version, pp);
1903                 STREAM_TO_UINT8(p_dev_cb->dscp_info.ctry_code, pp);
1904                 STREAM_TO_UINT8(p_dev_cb->dscp_info.flag, pp);
1905                 break;
1906 
1907             case GATT_UUID_HID_REPORT_MAP:
1908                 bta_hh_le_save_rpt_map(p_dev_cb, p_data);
1909                 return;
1910 
1911             default:
1912 #if BTA_HH_DEBUG == TRUE
1913                 APPL_TRACE_ERROR("Unexpected read %s(0x%04x)",
1914                                  bta_hh_uuid_to_str(p_data->char_id.uuid.uu.uuid16),
1915                                  p_data->char_id.uuid.uu.uuid16);
1916 #endif
1917                 break;
1918             }
1919         } else {
1920 #if BTA_HH_DEBUG == TRUE
1921             APPL_TRACE_ERROR("read uuid %s[0x%04x] error: %d",
1922                              bta_hh_uuid_to_str(p_data->char_id.uuid.uu.uuid16),
1923                              p_data->char_id.uuid.uu.uuid16,
1924                              p_data->status);
1925 #else
1926             APPL_TRACE_ERROR("read uuid [0x%04x] error: %d", p_data->char_id.uuid.uu.uuid16, p_data->status);
1927 #endif
1928         }
1929         bta_hh_le_search_hid_chars(p_dev_cb);
1930     }
1931 
1932 }
1933 
1934 /*******************************************************************************
1935 **
1936 ** Function         bta_hh_le_read_char_cmpl
1937 **
1938 ** Description      a characteristic value is received.
1939 **
1940 ** Parameters:
1941 **
1942 *******************************************************************************/
bta_hh_le_read_char_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)1943 void bta_hh_le_read_char_cmpl (tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1944 {
1945     tBTA_GATTC_READ *p_data = (tBTA_GATTC_READ *)p_buf;
1946 
1947     switch (p_data->char_id.uuid.uu.uuid16) {
1948     /* GET_REPORT */
1949     case GATT_UUID_HID_REPORT:
1950     case GATT_UUID_HID_BT_KB_INPUT:
1951     case GATT_UUID_HID_BT_KB_OUTPUT:
1952     case GATT_UUID_HID_BT_MOUSE_INPUT:
1953     case GATT_UUID_BATTERY_LEVEL: /* read battery level */
1954         bta_hh_le_proc_get_rpt_cmpl(p_dev_cb, p_data);
1955         break;
1956 
1957     case GATT_UUID_HID_PROTO_MODE:
1958         bta_hh_le_proc_read_proto_mode(p_dev_cb, p_data);
1959         break;
1960 
1961     default:
1962         APPL_TRACE_ERROR("Unexpected Read UUID: 0x%04x", p_data->char_id.uuid.uu.uuid16);
1963         break;
1964     }
1965 
1966 }
1967 
1968 /*******************************************************************************
1969 **
1970 ** Function         bta_hh_le_read_descr_cmpl
1971 **
1972 ** Description      read characteristic descriptor is completed in CONN st.
1973 **
1974 ** Parameters:
1975 **
1976 *******************************************************************************/
bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)1977 void bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1978 {
1979     tBTA_HH_LE_RPT  *p_rpt;
1980     tBTA_GATTC_READ *p_data = (tBTA_GATTC_READ *)p_buf;
1981     UINT8   *pp;
1982 
1983     /* if a report client configuration */
1984     if (p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG) {
1985         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1986                      BTA_HH_LE_SRVC_DEF,
1987                      p_data->char_id.uuid.uu.uuid16,
1988                      p_data->char_id.inst_id)) != NULL) {
1989             pp = p_data->p_value->unformat.p_value;
1990             STREAM_TO_UINT16(p_rpt->client_cfg_value, pp);
1991 
1992             APPL_TRACE_DEBUG("Read Client Configuration: 0x%04x", p_rpt->client_cfg_value);
1993         }
1994     }
1995 }
1996 
1997 /*******************************************************************************
1998 **
1999 ** Function         bta_hh_le_read_battery_level_descr_cmpl
2000 **
2001 ** Description      Process report reference descriptor for battery level is completed
2002 **
2003 ** Parameters:
2004 **
2005 *******************************************************************************/
bta_hh_le_read_battery_level_descr_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_READ * p_data)2006 void bta_hh_le_read_battery_level_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
2007 {
2008     tBTA_HH_LE_RPT  *p_rpt;
2009     UINT16 descr_uuid = p_data->descr_type.uuid.uu.uuid16;
2010 
2011     /* read report reference descriptor for battery level is completed */
2012     if (descr_uuid == GATT_UUID_RPT_REF_DESCR) {
2013         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
2014                      p_data->srvc_id.id.inst_id,
2015                      GATT_UUID_BATTERY_LEVEL,
2016                      p_data->char_id.inst_id)) == NULL) {
2017             bta_hh_le_search_hid_chars(p_dev_cb);
2018         } else {
2019             bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
2020         }
2021     }
2022 }
2023 
2024 /*******************************************************************************
2025 **
2026 ** Function         bta_hh_w4_le_read_descr_cmpl
2027 **
2028 ** Description      read characteristic descriptor is completed in W4_CONN st.
2029 **
2030 ** Parameters:
2031 **
2032 *******************************************************************************/
bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)2033 void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2034 {
2035     tBTA_HH_LE_RPT  *p_rpt;
2036     tBTA_GATTC_READ *p_data = (tBTA_GATTC_READ *)p_buf;
2037     UINT16 char_uuid16;
2038 
2039     if (p_data == NULL) {
2040         return;
2041     }
2042 
2043     char_uuid16 = p_data->char_id.uuid.uu.uuid16;
2044 
2045 #if BTA_HH_DEBUG == TRUE
2046     APPL_TRACE_DEBUG("bta_hh_w4_le_read_descr_cmpl uuid: %s(0x%04x)",
2047                      bta_hh_uuid_to_str(p_data->descr_type.uuid.uu.uuid16),
2048                      p_data->descr_type.uuid.uu.uuid16);
2049 #endif
2050     switch (char_uuid16) {
2051     case GATT_UUID_HID_REPORT:
2052         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
2053                      p_data->srvc_id.id.inst_id,
2054                      GATT_UUID_HID_REPORT,
2055                      p_data->char_id.inst_id)) == NULL) {
2056             bta_hh_le_search_hid_chars(p_dev_cb);
2057         } else {
2058             bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
2059         }
2060         break;
2061 
2062     case GATT_UUID_HID_REPORT_MAP:
2063         bta_hh_le_save_ext_rpt_ref(p_dev_cb, p_data);
2064         break;
2065 
2066     case GATT_UUID_BATTERY_LEVEL:
2067         bta_hh_le_read_battery_level_descr_cmpl(p_dev_cb, p_data);
2068         break;
2069 
2070     default:
2071         APPL_TRACE_ERROR("unknown descriptor read complete for uuid: 0x%04x", char_uuid16);
2072         break;
2073     }
2074 }
2075 
2076 /*******************************************************************************
2077 **
2078 ** Function         bta_hh_w4_le_write_cmpl
2079 **
2080 ** Description      Write characteristic complete event at W4_CONN st.
2081 **
2082 ** Parameters:
2083 **
2084 *******************************************************************************/
bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)2085 void bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2086 {
2087     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
2088 
2089     if (p_data == NULL) {
2090         return;
2091     }
2092 
2093     if (p_data->char_id.uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE) {
2094         p_dev_cb->status = (p_data->status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
2095 
2096         if ((p_dev_cb->disc_active & BTA_HH_LE_DISC_HIDS) != 0) {
2097             bta_hh_le_search_hid_chars(p_dev_cb);
2098         } else {
2099             bta_hh_le_open_cmpl(p_dev_cb);
2100         }
2101     }
2102 }
2103 
2104 /*******************************************************************************
2105 **
2106 ** Function         bta_hh_le_write_cmpl
2107 **
2108 ** Description      Write characteristic complete event at CONN st.
2109 **
2110 ** Parameters:
2111 **
2112 *******************************************************************************/
bta_hh_le_write_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)2113 void bta_hh_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2114 {
2115     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
2116     tBTA_HH_CBDATA      cback_data ;
2117     UINT16              cb_evt = p_dev_cb->w4_evt;
2118 
2119     if (p_data == NULL  || cb_evt == 0) {
2120         return;
2121     }
2122 
2123 #if BTA_HH_DEBUG
2124     APPL_TRACE_DEBUG("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt);
2125 #endif
2126     switch (p_data->char_id.uuid.uu.uuid16) {
2127     /* Set protocol finished */
2128     case GATT_UUID_HID_PROTO_MODE:
2129         cback_data.handle  = p_dev_cb->hid_handle;
2130         if (p_data->status == BTA_GATT_OK) {
2131             bta_hh_le_register_input_notif(p_dev_cb, p_data->srvc_id.id.inst_id, p_dev_cb->mode, FALSE);
2132             cback_data.status = BTA_HH_OK;
2133         } else {
2134             cback_data.status =  BTA_HH_ERR;
2135         }
2136         p_dev_cb->w4_evt = 0;
2137         (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
2138         break;
2139 
2140     /* Set Report finished */
2141     case GATT_UUID_HID_REPORT:
2142     case GATT_UUID_HID_BT_KB_INPUT:
2143     case GATT_UUID_HID_BT_MOUSE_INPUT:
2144     case GATT_UUID_HID_BT_KB_OUTPUT:
2145         cback_data.handle  = p_dev_cb->hid_handle;
2146         cback_data.status = (p_data->status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR;
2147         p_dev_cb->w4_evt = 0;
2148         (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
2149         break;
2150 
2151     case GATT_UUID_SCAN_INT_WINDOW:
2152         bta_hh_le_register_scpp_notif(p_dev_cb, p_data->status);
2153         break;
2154 
2155 
2156     default:
2157         break;
2158     }
2159 
2160 }
2161 
2162 /*******************************************************************************
2163 **
2164 ** Function         bta_hh_le_write_char_descr_cmpl
2165 **
2166 ** Description      Write characteristic descriptor complete event
2167 **
2168 ** Parameters:
2169 **
2170 *******************************************************************************/
bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)2171 void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2172 {
2173     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
2174     UINT8   srvc_inst_id, hid_inst_id;
2175 
2176     /* only write client configuration possible */
2177     if (p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG) {
2178         srvc_inst_id = p_data->srvc_id.id.inst_id;
2179         hid_inst_id = srvc_inst_id;
2180         switch (p_data->char_id.uuid.uu.uuid16) {
2181         case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
2182             hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_dev_cb, srvc_inst_id);
2183         /* fall through */
2184         case GATT_UUID_HID_BT_KB_INPUT:
2185         case GATT_UUID_HID_BT_MOUSE_INPUT:
2186         case GATT_UUID_HID_REPORT:
2187             if (p_data->status == BTA_GATT_OK) {
2188                 p_dev_cb->hid_srvc[hid_inst_id].report[p_dev_cb->clt_cfg_idx].client_cfg_value =
2189                     BTA_GATT_CLT_CONFIG_NOTIFICATION;
2190             }
2191             p_dev_cb->clt_cfg_idx ++;
2192             bta_hh_le_write_rpt_clt_cfg(p_dev_cb, hid_inst_id);
2193 
2194             break;
2195 
2196         case GATT_UUID_SCAN_REFRESH:
2197             bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, p_data->status);
2198             break;
2199 
2200         default:
2201             APPL_TRACE_ERROR("Unknown char ID clt cfg: 0x%04x", p_data->char_id.uuid.uu.uuid16);
2202         }
2203     } else {
2204 #if BTA_HH_DEBUG == TRUE
2205         APPL_TRACE_ERROR("Unexpected write to %s(0x%04x)",
2206                          bta_hh_uuid_to_str(p_data->descr_type.uuid.uu.uuid16),
2207                          p_data->descr_type.uuid.uu.uuid16);
2208 #else
2209         APPL_TRACE_ERROR("Unexpected write to (0x%04x)",
2210                          p_data->descr_type.uuid.uu.uuid16);
2211 #endif
2212     }
2213 
2214 }
2215 
2216 /*******************************************************************************
2217 **
2218 ** Function         bta_hh_le_input_rpt_notify
2219 **
2220 ** Description      process the notification event, most likely for input report.
2221 **
2222 ** Parameters:
2223 **
2224 *******************************************************************************/
bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY * p_data)2225 void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data)
2226 {
2227     tBTA_HH_DEV_CB       *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
2228     UINT8           app_id;
2229     UINT8           *p_buf;
2230     tBTA_HH_LE_RPT  *p_rpt;
2231 
2232     if (p_dev_cb == NULL) {
2233         APPL_TRACE_ERROR("notification received from Unknown device");
2234         return;
2235     }
2236     app_id = p_dev_cb->app_id;
2237 
2238     p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
2239                                         BTA_HH_LE_SRVC_DEF,
2240                                         p_data->char_id.char_id.uuid.uu.uuid16,
2241                                         p_data->char_id.char_id.inst_id);
2242     if (p_rpt == NULL) {
2243         APPL_TRACE_ERROR("notification received for Unknown Report");
2244         return;
2245     }
2246 
2247     if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_MOUSE_INPUT) {
2248         app_id = BTA_HH_APP_ID_MI;
2249     } else if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_KB_INPUT) {
2250         app_id = BTA_HH_APP_ID_KB;
2251     }
2252 
2253     APPL_TRACE_DEBUG("Notification received on report ID: %d", p_rpt->rpt_id);
2254 
2255     /* need to append report ID to the head of data */
2256     if (p_rpt->rpt_id != 0) {
2257         if ((p_buf = (UINT8 *)osi_malloc((UINT16)(p_data->len + 1))) == NULL) {
2258             APPL_TRACE_ERROR("No resources to send report data");
2259             return;
2260         }
2261 
2262         p_buf[0] = p_rpt->rpt_id;
2263         memcpy(&p_buf[1], p_data->value, p_data->len);
2264         ++p_data->len;
2265     } else {
2266         p_buf = p_data->value;
2267     }
2268 
2269     bta_hh_co_data((UINT8)p_dev_cb->hid_handle,
2270                    p_buf,
2271                    p_data->len,
2272                    p_dev_cb->mode,
2273                    0 , /* no sub class*/
2274                    p_dev_cb->dscp_info.ctry_code,
2275                    p_dev_cb->addr,
2276                    app_id);
2277 
2278     if (p_buf != p_data->value) {
2279         osi_free(p_buf);
2280     }
2281 }
2282 
2283 /*******************************************************************************
2284 **
2285 ** Function         bta_hh_gatt_open_fail
2286 **
2287 ** Description      action function to process the open fail
2288 **
2289 ** Returns          void
2290 **
2291 *******************************************************************************/
bta_hh_le_open_fail(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_data)2292 void bta_hh_le_open_fail(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
2293 {
2294     tBTA_HH_CONN            conn_dat ;
2295 
2296     /* open failure in the middle of service discovery, clear all services */
2297     if (p_cb->disc_active & BTA_HH_LE_DISC_HIDS) {
2298         bta_hh_clear_service_cache(p_cb);
2299     }
2300 
2301     p_cb->disc_active = BTA_HH_LE_DISC_NONE;
2302     /* Failure in opening connection or GATT discovery failure */
2303     conn_dat.handle = p_cb->hid_handle;
2304     memcpy(conn_dat.bda, p_cb->addr, BD_ADDR_LEN);
2305     conn_dat.le_hid = TRUE;
2306     conn_dat.scps_supported = p_cb->scps_supported;
2307 
2308     if (p_cb->status == BTA_HH_OK) {
2309         conn_dat.status = (p_data->le_close.reason == BTA_GATT_CONN_UNKNOWN) ? p_cb->status : BTA_HH_ERR;
2310     } else {
2311         conn_dat.status = p_cb->status;
2312     }
2313 
2314     /* Report OPEN fail event */
2315     (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
2316 
2317 }
2318 
2319 /*******************************************************************************
2320 **
2321 ** Function         bta_hh_gatt_close
2322 **
2323 ** Description      action function to process the GATT close int he state machine.
2324 **
2325 ** Returns          void
2326 **
2327 *******************************************************************************/
bta_hh_gatt_close(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_data)2328 void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
2329 {
2330     tBTA_HH_CBDATA          disc_dat = {BTA_HH_OK, 0};
2331 
2332     /* finaliza device driver */
2333     bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
2334     /* update total conn number */
2335     bta_hh_cb.cnt_num --;
2336 
2337     disc_dat.handle = p_cb->hid_handle;
2338     disc_dat.status = p_cb->status;
2339 
2340     (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
2341 
2342     /* if no connection is active and HH disable is signaled, disable service */
2343     if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable) {
2344         bta_hh_disc_cmpl();
2345     } else {
2346 #if (BTA_HH_LE_RECONN == TRUE)
2347         if (p_data->le_close.reason == BTA_GATT_CONN_TIMEOUT) {
2348             bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
2349         }
2350 #endif
2351     }
2352 
2353     return;
2354 
2355 }
2356 
2357 /*******************************************************************************
2358 **
2359 ** Function         bta_hh_le_api_disc_act
2360 **
2361 ** Description      initiate a Close API to a remote HID device
2362 **
2363 ** Returns          void
2364 **
2365 *******************************************************************************/
bta_hh_le_api_disc_act(tBTA_HH_DEV_CB * p_cb)2366 void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb)
2367 {
2368     if (p_cb->conn_id != BTA_GATT_INVALID_CONN_ID) {
2369         BTA_GATTC_Close(p_cb->conn_id);
2370         /* remove device from background connection if intended to disconnect,
2371            do not allow reconnection */
2372         bta_hh_le_remove_dev_bg_conn(p_cb);
2373     }
2374 }
2375 
2376 /*******************************************************************************
2377 **
2378 ** Function         bta_hh_le_get_rpt
2379 **
2380 ** Description      GET_REPORT on a LE HID Report
2381 **
2382 ** Returns          void
2383 **
2384 *******************************************************************************/
bta_hh_le_get_rpt(tBTA_HH_DEV_CB * p_cb,UINT8 srvc_inst,tBTA_HH_RPT_TYPE r_type,UINT8 rpt_id)2385 void bta_hh_le_get_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
2386 {
2387     tBTA_HH_LE_RPT  *p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[srvc_inst].report, p_cb->mode, r_type, rpt_id);
2388     tBTA_GATTC_CHAR_ID  char_id;
2389     UINT16  srvc_uuid = UUID_SERVCLASS_LE_HID;
2390 
2391     if (p_rpt == NULL) {
2392         APPL_TRACE_ERROR("bta_hh_le_get_rpt: no matching report");
2393         return;
2394     }
2395     if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL) {
2396         srvc_uuid = UUID_SERVCLASS_BATTERY;
2397     }
2398 
2399     p_cb->w4_evt = BTA_HH_GET_RPT_EVT;
2400 
2401     bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst, srvc_uuid, &char_id.srvc_id);
2402     bta_hh_le_fill_16bits_char_id(p_rpt->inst_id, p_rpt->uuid, &char_id.char_id);
2403 
2404     BTA_GATTC_ReadCharacteristic(p_cb->conn_id,
2405                                  &char_id,
2406                                  BTA_GATT_AUTH_REQ_NONE);
2407 }
2408 
2409 /*******************************************************************************
2410 **
2411 ** Function         bta_hh_le_write_rpt
2412 **
2413 ** Description      SET_REPORT/or DATA output on a LE HID Report
2414 **
2415 ** Returns          void
2416 **
2417 *******************************************************************************/
bta_hh_le_write_rpt(tBTA_HH_DEV_CB * p_cb,UINT8 srvc_inst,tBTA_GATTC_WRITE_TYPE write_type,tBTA_HH_RPT_TYPE r_type,BT_HDR * p_buf,UINT16 w4_evt)2418 void bta_hh_le_write_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst,
2419                          tBTA_GATTC_WRITE_TYPE   write_type,
2420                          tBTA_HH_RPT_TYPE r_type,
2421                          BT_HDR *p_buf, UINT16 w4_evt )
2422 {
2423     tBTA_HH_LE_RPT  *p_rpt;
2424     tBTA_GATTC_CHAR_ID  char_id;
2425     UINT8   *p_value, rpt_id;
2426 
2427     if (p_buf == NULL || p_buf->len == 0) {
2428         APPL_TRACE_ERROR("bta_hh_le_write_rpt: Illegal data");
2429         return;
2430     }
2431 
2432     /* strip report ID from the data */
2433     p_value = (UINT8 *)(p_buf + 1) + p_buf->offset;
2434     STREAM_TO_UINT8(rpt_id, p_value);
2435     p_buf->len -= 1;
2436 
2437     p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[srvc_inst].report, p_cb->mode, r_type, rpt_id);
2438 
2439     if (p_rpt == NULL) {
2440         APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report");
2441         osi_free(p_buf);
2442         return;
2443     }
2444 
2445     APPL_TRACE_ERROR("bta_hh_le_write_rpt: ReportID: 0x%02x Data Len: %d", rpt_id, p_buf->len);
2446 
2447     p_cb->w4_evt = w4_evt;
2448 
2449     bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
2450     bta_hh_le_fill_16bits_char_id(p_rpt->inst_id, p_rpt->uuid, &char_id.char_id);
2451 
2452     BTA_GATTC_WriteCharValue(p_cb->conn_id,
2453                              &char_id,
2454                              write_type, /* default to use write request */
2455                              p_buf->len,
2456                              p_value,
2457                              BTA_GATT_AUTH_REQ_NONE);
2458 
2459 }
2460 
2461 /*******************************************************************************
2462 **
2463 ** Function         bta_hh_le_suspend
2464 **
2465 ** Description      send LE suspend or exit suspend mode to remote device.
2466 **
2467 ** Returns          void
2468 **
2469 *******************************************************************************/
bta_hh_le_suspend(tBTA_HH_DEV_CB * p_cb,tBTA_HH_TRANS_CTRL_TYPE ctrl_type)2470 void bta_hh_le_suspend(tBTA_HH_DEV_CB *p_cb, tBTA_HH_TRANS_CTRL_TYPE ctrl_type)
2471 {
2472     UINT8 i;
2473     tBTA_GATTC_CHAR_ID  char_id;
2474 
2475     ctrl_type -= BTA_HH_CTRL_SUSPEND;
2476 
2477     for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++) {
2478         bta_hh_le_fill_16bits_srvc_id(TRUE, i, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
2479         bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_CONTROL_POINT, &char_id.char_id);
2480 
2481         BTA_GATTC_WriteCharValue(p_cb->conn_id,
2482                                  &char_id,
2483                                  BTA_GATTC_TYPE_WRITE_NO_RSP, /* default to use write request */
2484                                  1,
2485                                  &ctrl_type,
2486                                  BTA_GATT_AUTH_REQ_NONE);
2487     }
2488 }
2489 
2490 /*******************************************************************************
2491 **
2492 ** Function         bta_hh_le_write_dev_act
2493 **
2494 ** Description      Write LE device action. can be SET/GET/DATA transaction.
2495 **
2496 ** Returns          void
2497 **
2498 *******************************************************************************/
bta_hh_le_write_dev_act(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_data)2499 void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
2500 {
2501     switch (p_data->api_sndcmd.t_type) {
2502     case HID_TRANS_SET_PROTOCOL:
2503         p_cb->w4_evt = BTA_HH_SET_PROTO_EVT;
2504         bta_hh_le_set_protocol_mode(p_cb, p_data->api_sndcmd.param);
2505         break;
2506 
2507     case HID_TRANS_GET_PROTOCOL:
2508         bta_hh_le_get_protocol_mode(p_cb);
2509         break;
2510 
2511     case HID_TRANS_GET_REPORT:
2512         bta_hh_le_get_rpt(p_cb,
2513                           BTA_HH_LE_SRVC_DEF,
2514                           p_data->api_sndcmd.param,
2515                           p_data->api_sndcmd.rpt_id);
2516         break;
2517 
2518     case HID_TRANS_SET_REPORT:
2519         bta_hh_le_write_rpt(p_cb,
2520                             BTA_HH_LE_SRVC_DEF,
2521                             BTA_GATTC_TYPE_WRITE,
2522                             p_data->api_sndcmd.param,
2523                             p_data->api_sndcmd.p_data,
2524                             BTA_HH_SET_RPT_EVT);
2525         break;
2526 
2527     case HID_TRANS_DATA:  /* output report */
2528 
2529         bta_hh_le_write_rpt(p_cb,
2530                             BTA_HH_LE_SRVC_DEF,
2531                             BTA_GATTC_TYPE_WRITE_NO_RSP,
2532                             p_data->api_sndcmd.param,
2533                             p_data->api_sndcmd.p_data,
2534                             BTA_HH_DATA_EVT);
2535         break;
2536 
2537     case HID_TRANS_CONTROL:
2538         /* no handshake event will be generated */
2539         /* if VC_UNPLUG is issued, set flag */
2540         if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND ||
2541                 p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND) {
2542             bta_hh_le_suspend(p_cb, p_data->api_sndcmd.param);
2543         }
2544         break;
2545 
2546     default:
2547         APPL_TRACE_ERROR("%s unsupported transaction for BLE HID device: %d",
2548                          __func__, p_data->api_sndcmd.t_type);
2549         break;
2550     }
2551 }
2552 
2553 /*******************************************************************************
2554 **
2555 ** Function         bta_hh_le_get_dscp_act
2556 **
2557 ** Description      Send ReportDescriptor to application for all HID services.
2558 **
2559 ** Returns          void
2560 **
2561 *******************************************************************************/
bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB * p_cb)2562 void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb)
2563 {
2564     UINT8 i;
2565 
2566     for (i = 0 ; i < BTA_HH_LE_HID_SRVC_MAX; i ++) {
2567         if (p_cb->hid_srvc[i].in_use) {
2568             p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc[i].descriptor.dl_len;
2569             p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc[i].descriptor.dsc_list;
2570 
2571             (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
2572         } else {
2573             break;
2574         }
2575     }
2576 }
2577 
2578 /*******************************************************************************
2579 **
2580 ** Function         bta_hh_le_add_dev_bg_conn
2581 **
2582 ** Description      Remove a LE HID device from background connection procedure.
2583 **
2584 ** Returns          void
2585 **
2586 *******************************************************************************/
bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB * p_cb,BOOLEAN check_bond)2587 static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond)
2588 {
2589     UINT8           sec_flag = 0;
2590     BOOLEAN         to_add = TRUE;
2591 
2592     if (check_bond) {
2593         /* start reconnection if remote is a bonded device */
2594         /* verify bond */
2595         BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
2596 
2597         if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0) {
2598             to_add = FALSE;
2599         }
2600     }
2601 
2602     if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/
2603         !p_cb->in_bg_conn && to_add) {
2604         /* add device into BG connection to accept remote initiated connection */
2605         BTA_GATTC_Enh_Open(bta_hh_cb.gatt_if, p_cb->addr, BLE_ADDR_UNKNOWN_TYPE, FALSE,
2606                 BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, 0, NULL, NULL);
2607         p_cb->in_bg_conn = TRUE;
2608 
2609         BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL);
2610     }
2611     return;
2612 }
2613 
2614 /*******************************************************************************
2615 **
2616 ** Function         bta_hh_le_add_device
2617 **
2618 ** Description      Add a LE HID device as a known device, and also add the address
2619 **                  into background connection WL for incoming connection.
2620 **
2621 ** Returns          void
2622 **
2623 *******************************************************************************/
bta_hh_le_add_device(tBTA_HH_DEV_CB * p_cb,tBTA_HH_MAINT_DEV * p_dev_info)2624 UINT8 bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info)
2625 {
2626     p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
2627     bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
2628 
2629     /* update DI information */
2630     bta_hh_update_di_info(p_cb,
2631                           p_dev_info->dscp_info.vendor_id,
2632                           p_dev_info->dscp_info.product_id,
2633                           p_dev_info->dscp_info.version,
2634                           p_dev_info->dscp_info.flag);
2635 
2636     /* add to BTA device list */
2637     bta_hh_add_device_to_list(p_cb, p_cb->hid_handle,
2638                               p_dev_info->attr_mask,
2639                               &p_dev_info->dscp_info.descriptor,
2640                               p_dev_info->sub_class,
2641                               p_dev_info->dscp_info.ssr_max_latency,
2642                               p_dev_info->dscp_info.ssr_min_tout,
2643                               p_dev_info->app_id);
2644 
2645     bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
2646 
2647     return p_cb->hid_handle;
2648 }
2649 
2650 /*******************************************************************************
2651 **
2652 ** Function         bta_hh_le_remove_dev_bg_conn
2653 **
2654 ** Description      Remove a LE HID device from background connection procedure.
2655 **
2656 ** Returns          void
2657 **
2658 *******************************************************************************/
bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB * p_dev_cb)2659 void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB *p_dev_cb)
2660 {
2661     if (p_dev_cb->in_bg_conn) {
2662         p_dev_cb->in_bg_conn = FALSE;
2663 
2664         BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, FALSE);
2665     }
2666 }
2667 
2668 /*******************************************************************************
2669 **
2670 ** Function         bta_hh_le_update_scpp
2671 **
2672 ** Description      action function to update the scan parameters on remote HID
2673 **                  device
2674 **
2675 ** Parameters:
2676 **
2677 *******************************************************************************/
bta_hh_le_update_scpp(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)2678 void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2679 {
2680     tBTA_GATTC_CHAR_ID  char_id;
2681     UINT8   value[4], *p = value;
2682     tBTA_HH_CBDATA      cback_data ;
2683 
2684     if (!p_dev_cb->is_le_device ||
2685             p_dev_cb->mode != BTA_HH_PROTO_RPT_MODE ||
2686             p_dev_cb->scps_supported == FALSE) {
2687         APPL_TRACE_ERROR("Can not set ScPP scan parameter as boot host, or remote does not support ScPP ");
2688 
2689         cback_data.handle = p_dev_cb->hid_handle;
2690         cback_data.status = BTA_HH_ERR;
2691         (* bta_hh_cb.p_cback)(BTA_HH_UPDATE_SCPP_EVT, (tBTA_HH *)&cback_data);
2692 
2693         return;
2694     }
2695 
2696     p_dev_cb->w4_evt = BTA_HH_UPDATE_SCPP_EVT;
2697 
2698     UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_int);
2699     UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_win);
2700 
2701     bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_SCPP_INST_DEF, UUID_SERVCLASS_SCAN_PARAM, &char_id.srvc_id);
2702     bta_hh_le_fill_16bits_char_id(BTA_HH_SCPP_INST_DEF, GATT_UUID_SCAN_INT_WINDOW, &char_id.char_id);
2703 
2704     BTA_GATTC_WriteCharValue(p_dev_cb->conn_id,
2705                              &char_id,
2706                              BTA_GATTC_TYPE_WRITE_NO_RSP,
2707                              2,
2708                              value,
2709                              BTA_GATT_AUTH_REQ_NONE);
2710 
2711 }
2712 
2713 /*******************************************************************************
2714 **
2715 ** Function         bta_hh_gattc_callback
2716 **
2717 ** Description      This is GATT client callback function used in BTA HH.
2718 **
2719 ** Parameters:
2720 **
2721 *******************************************************************************/
bta_hh_gattc_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)2722 static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
2723 {
2724     tBTA_HH_DEV_CB *p_dev_cb;
2725     UINT16          evt;
2726 #if BTA_HH_DEBUG
2727     APPL_TRACE_DEBUG("bta_hh_gattc_callback event = %d", event);
2728 #endif
2729     if (p_data == NULL) {
2730         return;
2731     }
2732 
2733     switch (event) {
2734     case BTA_GATTC_REG_EVT: /* 0 */
2735         bta_hh_le_register_cmpl(&p_data->reg_oper);
2736         break;
2737 
2738     case BTA_GATTC_DEREG_EVT: /* 1 */
2739         bta_hh_cleanup_disable(p_data->reg_oper.status);
2740         break;
2741 
2742     case BTA_GATTC_OPEN_EVT: /* 2 */
2743         p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda);
2744         if (p_dev_cb) {
2745             bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
2746         }
2747         break;
2748 
2749     case BTA_GATTC_READ_CHAR_EVT: /* 3 */
2750     case BTA_GATTC_READ_DESCR_EVT: /* 8 */
2751         p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->read.conn_id);
2752         if (event == BTA_GATTC_READ_CHAR_EVT) {
2753             evt = BTA_HH_GATT_READ_CHAR_CMPL_EVT;
2754         } else {
2755             evt = BTA_HH_GATT_READ_DESCR_CMPL_EVT;
2756         }
2757 
2758         bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->read);
2759         break;
2760 
2761     case BTA_GATTC_WRITE_DESCR_EVT: /* 9 */
2762     case BTA_GATTC_WRITE_CHAR_EVT: /* 4 */
2763         p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->write.conn_id);
2764         if (event == BTA_GATTC_WRITE_CHAR_EVT) {
2765             evt = BTA_HH_GATT_WRITE_CHAR_CMPL_EVT;
2766         } else {
2767             evt = BTA_HH_GATT_WRITE_DESCR_CMPL_EVT;
2768         }
2769 
2770         bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->write);
2771         break;
2772 
2773     case BTA_GATTC_CLOSE_EVT: /* 5 */
2774         bta_hh_le_close(&p_data->close);
2775         break;
2776 
2777     case BTA_GATTC_SEARCH_CMPL_EVT: /* 6 */
2778         bta_hh_le_srvc_search_cmpl(&p_data->search_cmpl);
2779         break;
2780 
2781     case BTA_GATTC_SEARCH_RES_EVT: /* 7 */
2782         bta_hh_le_search_result(&p_data->srvc_res);
2783         break;
2784 
2785 
2786 
2787     case BTA_GATTC_NOTIF_EVT: /* 10 */
2788         bta_hh_le_input_rpt_notify(&p_data->notify);
2789         break;
2790 
2791     case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */
2792         p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda);
2793         if (p_dev_cb) {
2794             bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_ENC_CMPL_EVT,
2795                               (tBTA_HH_DATA *)&p_data->enc_cmpl);
2796         }
2797         break;
2798 
2799     default:
2800         break;
2801     }
2802 }
2803 
2804 /*******************************************************************************
2805 **
2806 ** Function         bta_hh_le_hid_read_rpt_clt_cfg
2807 **
2808 ** Description      a test command to read report descriptor client configuration
2809 **
2810 ** Returns          void
2811 **
2812 *******************************************************************************/
bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr,UINT8 rpt_id)2813 void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id)
2814 {
2815     tBTA_HH_DEV_CB *p_cb = NULL;
2816     tBTA_HH_LE_RPT *p_rpt ;
2817     UINT8           index = BTA_HH_IDX_INVALID;
2818 
2819     index = bta_hh_find_cb(bd_addr);
2820     if ((index = bta_hh_find_cb(bd_addr)) == BTA_HH_IDX_INVALID) {
2821         APPL_TRACE_ERROR("unknown device");
2822         return;
2823     }
2824 
2825     p_cb = &bta_hh_cb.kdev[index];
2826 
2827     p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].report, p_cb->mode, BTA_HH_RPTT_INPUT, rpt_id);
2828 
2829     if (p_rpt == NULL) {
2830         APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report");
2831         return;
2832     }
2833 
2834     bta_hh_le_read_char_dscrpt(p_cb,
2835                                UUID_SERVCLASS_LE_HID,
2836                                BTA_HH_LE_SRVC_DEF,
2837                                p_rpt->uuid,
2838                                p_rpt->inst_id,
2839                                GATT_UUID_CHAR_CLIENT_CONFIG);
2840 
2841 
2842 
2843     return;
2844 }
2845 
2846 /*******************************************************************************
2847 **
2848 ** Function         bta_hh_le_search_scps
2849 **
2850 ** Description      discovery scan parameter service if act as report host, otherwise
2851 **                  finish LE connection.
2852 **
2853 ** Parameters:
2854 **
2855 *******************************************************************************/
bta_hh_le_search_scps(tBTA_HH_DEV_CB * p_cb)2856 static void bta_hh_le_search_scps(tBTA_HH_DEV_CB *p_cb)
2857 {
2858     tBT_UUID        pri_srvc;
2859 
2860     if ( p_cb->mode == BTA_HH_PROTO_RPT_MODE) {
2861         p_cb->disc_active  |= BTA_HH_LE_DISC_SCPS;
2862         /* start  service discovery for Scan Parameter service */
2863         pri_srvc.len        = LEN_UUID_16;
2864         pri_srvc.uu.uuid16  = UUID_SERVCLASS_SCAN_PARAM;
2865 
2866         BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
2867     } else {
2868         bta_hh_le_open_cmpl(p_cb);
2869     }
2870 }
2871 
2872 /*******************************************************************************
2873 **
2874 ** Function         bta_hh_le_search_scps_chars
2875 **
2876 ** Description      find ScPS optional characteristics scan refresh
2877 **
2878 ** Parameters:
2879 **
2880 *******************************************************************************/
bta_hh_le_search_scps_chars(tBTA_HH_DEV_CB * p_cb)2881 static void bta_hh_le_search_scps_chars(tBTA_HH_DEV_CB *p_cb)
2882 {
2883     tBTA_GATT_SRVC_ID   srvc_id;
2884     tBT_UUID            char_cond;
2885     tBTA_GATTC_CHAR_ID  char_result;
2886     tBTA_GATT_CHAR_PROP prop;
2887 
2888     p_cb->scps_supported = TRUE;
2889     bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_SCAN_PARAM, &srvc_id);
2890 
2891     char_cond.len   = LEN_UUID_16;
2892     char_cond.uu.uuid16 = GATT_UUID_SCAN_REFRESH;
2893 
2894     /* look for scan refresh */
2895     if (BTA_GATTC_GetFirstChar( p_cb->conn_id,
2896                                 &srvc_id,
2897                                 &char_cond,
2898                                 &char_result,
2899                                 &prop) == BTA_GATT_OK) {
2900         if (prop & BTA_GATT_CHAR_PROP_BIT_NOTIFY) {
2901             p_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT;
2902         } else {
2903             p_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE;
2904         }
2905 
2906     }
2907 }
2908 
2909 /*******************************************************************************
2910 **
2911 ** Function         bta_hh_le_register_scpp_notif
2912 **
2913 ** Description      register scan parameter refresh notification complete
2914 **
2915 **
2916 ** Parameters:
2917 **
2918 *******************************************************************************/
bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATT_STATUS status)2919 static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
2920 {
2921     UINT8               sec_flag = 0;
2922     tBTA_GATTC_CHAR_ID  char_id;
2923 
2924     /* if write scan parameter successful */
2925     /* if bonded and notification is not enabled, configure the client configuration */
2926     if (status == BTA_GATT_OK &&
2927             (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_SPT) != 0 &&
2928             (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_ENB) == 0) {
2929         BTM_GetSecurityFlagsByTransport(p_dev_cb->addr, &sec_flag, BT_TRANSPORT_LE);
2930         if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)) {
2931             if (bta_hh_le_write_char_clt_cfg (p_dev_cb,
2932                                               BTA_HH_SCPP_INST_DEF,
2933                                               UUID_SERVCLASS_SCAN_PARAM,
2934                                               BTA_HH_SCPP_INST_DEF,
2935                                               GATT_UUID_SCAN_REFRESH,
2936                                               BTA_GATT_CLT_CONFIG_NOTIFICATION)) {
2937                 bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_SCPP_INST_DEF, UUID_SERVCLASS_SCAN_PARAM, &char_id.srvc_id);
2938                 bta_hh_le_fill_16bits_char_id(BTA_HH_SCPP_INST_DEF, GATT_UUID_SCAN_REFRESH, &char_id.char_id);
2939 
2940                 BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
2941                                                    p_dev_cb->addr,
2942                                                    &char_id);
2943                 return;
2944             }
2945         }
2946     }
2947     bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, status);
2948 }
2949 
2950 /*******************************************************************************
2951 **
2952 ** Function         bta_hh_le_register_scpp_notif_cmpl
2953 **
2954 ** Description      action function to register scan parameter refresh notification
2955 **
2956 ** Parameters:
2957 **
2958 *******************************************************************************/
bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATT_STATUS status)2959 static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
2960 {
2961     tBTA_HH_CBDATA      cback_data ;
2962     UINT16              cb_evt = p_dev_cb->w4_evt;
2963 
2964     if (status == BTA_GATT_OK) {
2965         p_dev_cb->scps_notify = (BTA_HH_LE_SCPS_NOTIFY_ENB | BTA_HH_LE_SCPS_NOTIFY_SPT);
2966     }
2967 
2968     cback_data.handle  = p_dev_cb->hid_handle;
2969     cback_data.status = (status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR;
2970     p_dev_cb->w4_evt = 0;
2971     (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
2972 
2973 
2974 }
2975 
2976 /*******************************************************************************
2977 **
2978 ** Function         bta_hh_process_cache_rpt
2979 **
2980 ** Description      Process the cached reports
2981 **
2982 ** Parameters:
2983 **
2984 *******************************************************************************/
bta_hh_process_cache_rpt(tBTA_HH_DEV_CB * p_cb,tBTA_HH_RPT_CACHE_ENTRY * p_rpt_cache,UINT8 num_rpt)2985 static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
2986                                       tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
2987                                       UINT8 num_rpt)
2988 {
2989     UINT8                       i = 0;
2990     tBTA_HH_LE_RPT              *p_rpt;
2991 
2992     if (num_rpt != 0) { /* no cache is found */
2993         p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].in_use = TRUE;
2994 
2995         /* set the descriptor info */
2996         p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].descriptor.dl_len =
2997             p_cb->dscp_info.descriptor.dl_len;
2998         p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].descriptor.dsc_list =
2999             p_cb->dscp_info.descriptor.dsc_list;
3000 
3001         for (; i < num_rpt; i ++, p_rpt_cache ++) {
3002             if ((p_rpt = bta_hh_le_find_alloc_report_entry (p_cb,
3003                          BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id),
3004                          p_rpt_cache->rpt_uuid,
3005                          BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt_cache->inst_id),
3006                          p_rpt_cache->prop))  == NULL) {
3007                 APPL_TRACE_ERROR("bta_hh_process_cache_rpt: allocation report entry failure");
3008                 break;
3009             } else {
3010                 p_rpt->rpt_type =  p_rpt_cache->rpt_type;
3011                 p_rpt->rpt_id   =  p_rpt_cache->rpt_id;
3012 
3013                 if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
3014                         p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT ||
3015                         (p_rpt->uuid == GATT_UUID_HID_REPORT && p_rpt->rpt_type == BTA_HH_RPTT_INPUT)) {
3016                     p_rpt->client_cfg_value = BTA_GATT_CLT_CONFIG_NOTIFICATION;
3017                 }
3018             }
3019         }
3020     }
3021 }
3022 
3023 #endif
3024