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