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