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