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