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