• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-2013 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #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("%s ---> Deregister Report ID: %d", __func__, 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("%s <--- Register Boot Report ID: %d", __func__, 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("%s ---> Deregister Boot Report ID: %d", __func__, 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("%s <--- Register Report ID: %d", __func__, 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_deregister_input_notif
846 **
847 ** Description      Deregister all notifications
848 **
849 *******************************************************************************/
bta_hh_le_deregister_input_notif(tBTA_HH_DEV_CB * p_dev_cb)850 void bta_hh_le_deregister_input_notif(tBTA_HH_DEV_CB *p_dev_cb)
851 {
852     tBTA_HH_LE_RPT  *p_rpt = &p_dev_cb->hid_srvc.report[0];
853 
854     for (UINT8 i = 0; i < BTA_HH_LE_RPT_MAX; i++, p_rpt++)
855     {
856         if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
857         {
858             if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
859                 p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
860             {
861                 APPL_TRACE_DEBUG("%s ---> Deregister Report ID: %d", __func__, p_rpt->rpt_id);
862                 BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
863                                                     p_rpt->char_inst_id);
864             }
865             else if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
866                 p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
867                 p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
868             {
869                 APPL_TRACE_DEBUG("%s ---> Deregister Boot Report ID: %d", __func__, p_rpt->rpt_id);
870                 BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
871                                                     p_rpt->char_inst_id);
872             }
873         }
874     }
875 }
876 
877 
878 /*******************************************************************************
879 **
880 ** Function         bta_hh_le_open_cmpl
881 **
882 ** Description      HID over GATT connection sucessfully opened
883 **
884 *******************************************************************************/
bta_hh_le_open_cmpl(tBTA_HH_DEV_CB * p_cb)885 void bta_hh_le_open_cmpl(tBTA_HH_DEV_CB *p_cb)
886 {
887     if ( p_cb->disc_active == BTA_HH_LE_DISC_NONE)
888     {
889 #if BTA_HH_DEBUG
890         bta_hh_le_hid_report_dbg(p_cb);
891 #endif
892         bta_hh_le_register_input_notif(p_cb, p_cb->mode, TRUE);
893         bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
894 
895 #if (BTA_HH_LE_RECONN == TRUE)
896         if (p_cb->status == BTA_HH_OK)
897         {
898             bta_hh_le_add_dev_bg_conn(p_cb, TRUE);
899         }
900 #endif
901     }
902 }
903 
904 /*******************************************************************************
905 **
906 ** Function         bta_hh_le_write_char_clt_cfg
907 **
908 ** Description      Utility function to find and write client configuration of
909 **                  a characteristic
910 **
911 *******************************************************************************/
bta_hh_le_write_char_clt_cfg(tBTA_HH_DEV_CB * p_cb,UINT8 char_handle,UINT16 clt_cfg_value)912 BOOLEAN bta_hh_le_write_char_clt_cfg(tBTA_HH_DEV_CB *p_cb,
913                                      UINT8 char_handle,
914                                      UINT16 clt_cfg_value)
915 {
916     UINT8                      buf[2], *pp = buf;
917 
918     tBTA_GATTC_DESCRIPTOR *p_desc = find_descriptor_by_short_uuid(p_cb->conn_id,
919                                        char_handle, GATT_UUID_CHAR_CLIENT_CONFIG);
920     if (!p_desc)
921         return FALSE;
922 
923     UINT16_TO_STREAM(pp, clt_cfg_value);
924     gatt_queue_write_op(GATT_WRITE_DESC, p_cb->conn_id,
925                         p_desc->handle, 2, buf, BTA_GATTC_TYPE_WRITE);
926     return TRUE;
927 }
928 
929 /*******************************************************************************
930 **
931 ** Function         bta_hh_le_write_rpt_clt_cfg
932 **
933 ** Description      write client configuration. This is only for input report
934 **                  enable all input notification upon connection open.
935 **
936 *******************************************************************************/
bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB * p_cb,UINT8 srvc_inst_id)937 BOOLEAN bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst_id)
938 {
939     UINT8           i;
940     tBTA_HH_LE_RPT  *p_rpt = &p_cb->hid_srvc.report[p_cb->clt_cfg_idx];
941 
942     for (i = p_cb->clt_cfg_idx; i < BTA_HH_LE_RPT_MAX && p_rpt->in_use; i ++, p_rpt ++)
943     {
944         /* enable notification for all input report, regardless mode */
945         if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
946         {
947             if (bta_hh_le_write_char_clt_cfg(p_cb,
948                                              p_rpt->char_inst_id,
949                                              BTA_GATT_CLT_CONFIG_NOTIFICATION))
950             {
951                 p_cb->clt_cfg_idx = i;
952                 return TRUE;
953             }
954         }
955     }
956     p_cb->clt_cfg_idx = 0;
957 
958     /* client configuration is completed, send open callback */
959     if (p_cb->state == BTA_HH_W4_CONN_ST)
960     {
961         p_cb->disc_active &= ~BTA_HH_LE_DISC_HIDS;
962 
963         bta_hh_le_open_cmpl(p_cb);
964     }
965     return FALSE;
966 }
967 
968 /*******************************************************************************
969 **
970 ** Function         bta_hh_le_set_protocol_mode
971 **
972 ** Description      Set remote device protocol mode.
973 **
974 *******************************************************************************/
bta_hh_le_set_protocol_mode(tBTA_HH_DEV_CB * p_cb,tBTA_HH_PROTO_MODE mode)975 BOOLEAN bta_hh_le_set_protocol_mode(tBTA_HH_DEV_CB *p_cb, tBTA_HH_PROTO_MODE mode)
976 {
977     tBTA_HH_CBDATA      cback_data;
978     BOOLEAN             exec = FALSE;
979 
980     APPL_TRACE_DEBUG("%s attempt mode: %s", __func__,
981                      (mode == BTA_HH_PROTO_RPT_MODE)? "Report": "Boot");
982 
983     cback_data.handle  = p_cb->hid_handle;
984     /* boot mode is not supported in the remote device */
985     if (p_cb->hid_srvc.proto_mode_handle == 0)
986     {
987         p_cb->mode  = BTA_HH_PROTO_RPT_MODE;
988 
989         if (mode == BTA_HH_PROTO_BOOT_MODE)
990         {
991             APPL_TRACE_ERROR("Set Boot Mode failed!! No PROTO_MODE Char!");
992             cback_data.status = BTA_HH_ERR;
993         }
994         else
995         {
996             /* if set to report mode, need to de-register all input report notification */
997             bta_hh_le_register_input_notif(p_cb, p_cb->mode, FALSE);
998             cback_data.status = BTA_HH_OK;
999         }
1000         if (p_cb->state == BTA_HH_W4_CONN_ST)
1001         {
1002             p_cb->status = (cback_data.status == BTA_HH_OK)? BTA_HH_OK: BTA_HH_ERR_PROTO;
1003         }
1004         else
1005             (* bta_hh_cb.p_cback)(BTA_HH_SET_PROTO_EVT, (tBTA_HH *)&cback_data);
1006     } else if (p_cb->mode != mode) {
1007         p_cb->mode = mode;
1008         mode = (mode == BTA_HH_PROTO_BOOT_MODE)? BTA_HH_LE_PROTO_BOOT_MODE : BTA_HH_LE_PROTO_REPORT_MODE;
1009 
1010         gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle, 1,
1011                             &mode, BTA_GATTC_TYPE_WRITE_NO_RSP);
1012         exec        = TRUE;
1013     }
1014 
1015     return exec;
1016 }
1017 
1018 /*******************************************************************************
1019 **
1020 ** Function         bta_hh_le_get_protocol_mode
1021 **
1022 ** Description      Get remote device protocol mode.
1023 **
1024 *******************************************************************************/
bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB * p_cb)1025 void bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB *p_cb)
1026 {
1027     tBTA_HH_HSDATA    hs_data;
1028     p_cb->w4_evt = BTA_HH_GET_PROTO_EVT;
1029 
1030     if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.proto_mode_handle != 0) {
1031         gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle);
1032         return;
1033     }
1034 
1035     /* no service support protocol_mode, by default report mode */
1036     hs_data.status  = BTA_HH_OK;
1037     hs_data.handle  = p_cb->hid_handle;
1038     hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
1039     p_cb->w4_evt = 0;
1040     (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
1041 }
1042 
1043 /*******************************************************************************
1044 **
1045 ** Function         bta_hh_le_dis_cback
1046 **
1047 ** Description      DIS read complete callback
1048 **
1049 ** Parameters:
1050 **
1051 *******************************************************************************/
bta_hh_le_dis_cback(BD_ADDR addr,tDIS_VALUE * p_dis_value)1052 void bta_hh_le_dis_cback(BD_ADDR addr, tDIS_VALUE *p_dis_value)
1053 {
1054     tBTA_HH_DEV_CB *p_cb = bta_hh_le_find_dev_cb_by_bda(addr);
1055 
1056 
1057     if (p_cb == NULL || p_dis_value == NULL)
1058     {
1059         APPL_TRACE_ERROR("received unexpected/error DIS callback");
1060         return;
1061     }
1062 
1063     p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
1064     /* plug in the PnP info for this device */
1065     if (p_dis_value->attr_mask & DIS_ATTR_PNP_ID_BIT)
1066     {
1067 #if BTA_HH_DEBUG == TRUE
1068         APPL_TRACE_DEBUG("Plug in PnP info: product_id = %02x, vendor_id = %04x, version = %04x",
1069                 p_dis_value->pnp_id.product_id,
1070                 p_dis_value->pnp_id.vendor_id,
1071                 p_dis_value->pnp_id.product_version);
1072 #endif
1073         p_cb->dscp_info.product_id = p_dis_value->pnp_id.product_id;
1074         p_cb->dscp_info.vendor_id  = p_dis_value->pnp_id.vendor_id;
1075         p_cb->dscp_info.version    = p_dis_value->pnp_id.product_version;
1076     }
1077     bta_hh_le_open_cmpl(p_cb);
1078 }
1079 
1080 /*******************************************************************************
1081 **
1082 ** Function         bta_hh_le_pri_service_discovery
1083 **
1084 ** Description      Initialize GATT discovery on the remote LE HID device by opening
1085 **                  a GATT connection first.
1086 **
1087 ** Parameters:
1088 **
1089 *******************************************************************************/
bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB * p_cb)1090 void bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB *p_cb)
1091 {
1092     tBT_UUID        pri_srvc;
1093 
1094     bta_hh_le_co_reset_rpt_cache(p_cb->addr, p_cb->app_id);
1095 
1096     p_cb->disc_active |= (BTA_HH_LE_DISC_HIDS|BTA_HH_LE_DISC_DIS);
1097 
1098     /* read DIS info */
1099     if (!DIS_ReadDISInfo(p_cb->addr, bta_hh_le_dis_cback, DIS_ATTR_PNP_ID_BIT))
1100     {
1101         APPL_TRACE_ERROR("read DIS failed");
1102         p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
1103     }
1104 
1105     /* in parallel */
1106     /* start primary service discovery for HID service */
1107     pri_srvc.len        = LEN_UUID_16;
1108     pri_srvc.uu.uuid16  = UUID_SERVCLASS_LE_HID;
1109     BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
1110     return;
1111 }
1112 
1113 /*******************************************************************************
1114 **
1115 ** Function         bta_hh_le_encrypt_cback
1116 **
1117 ** Description      link encryption complete callback for bond verification.
1118 **
1119 ** Returns          None
1120 **
1121 *******************************************************************************/
bta_hh_le_encrypt_cback(BD_ADDR bd_addr,tBTA_GATT_TRANSPORT transport,void * p_ref_data,tBTM_STATUS result)1122 void bta_hh_le_encrypt_cback(BD_ADDR bd_addr, tBTA_GATT_TRANSPORT transport,
1123                                     void *p_ref_data, tBTM_STATUS result)
1124 {
1125     UINT8   idx = bta_hh_find_cb(bd_addr);
1126     tBTA_HH_DEV_CB *p_dev_cb;
1127     UNUSED(p_ref_data);
1128     UNUSED (transport);
1129 
1130     if (idx != BTA_HH_IDX_INVALID)
1131         p_dev_cb = &bta_hh_cb.kdev[idx];
1132     else
1133     {
1134         APPL_TRACE_ERROR("unexpected encryption callback, ignore");
1135         return;
1136     }
1137     p_dev_cb->status = (result == BTM_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR_SEC;
1138     p_dev_cb->reason = result;
1139 
1140     bta_hh_sm_execute(p_dev_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1141 }
1142 
1143 /*******************************************************************************
1144 **
1145 ** Function         bta_hh_security_cmpl
1146 **
1147 ** Description      Security check completed, start the service discovery
1148 **                  if no cache available, otherwise report connection open completed
1149 **
1150 ** Parameters:
1151 **
1152 *******************************************************************************/
bta_hh_security_cmpl(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_buf)1153 void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1154 {
1155     UNUSED(p_buf);
1156 
1157     APPL_TRACE_DEBUG("%s", __func__);
1158     if (p_cb->status == BTA_HH_OK)
1159     {
1160         if (!p_cb->hid_srvc.in_use)
1161         {
1162             APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load");
1163 
1164             /* start loading the cache if not in stack */
1165             //TODO(jpawlowski): cache storage is broken, fix it
1166             // tBTA_HH_RPT_CACHE_ENTRY     *p_rpt_cache;
1167             // UINT8                       num_rpt = 0;
1168             // if ((p_rpt_cache = bta_hh_le_co_cache_load(p_cb->addr, &num_rpt, p_cb->app_id)) != NULL)
1169             // {
1170             //     bta_hh_process_cache_rpt(p_cb, p_rpt_cache, num_rpt);
1171             // }
1172         }
1173         /*  discovery has been done for HID service */
1174         if (p_cb->app_id != 0 && p_cb->hid_srvc.in_use)
1175         {
1176             APPL_TRACE_DEBUG("%s: discovery has been done for HID service", __func__);
1177             /* configure protocol mode */
1178             if (bta_hh_le_set_protocol_mode(p_cb, p_cb->mode) == FALSE)
1179             {
1180                 bta_hh_le_open_cmpl(p_cb);
1181             }
1182         }
1183         /* start primary service discovery for HID service */
1184         else
1185         {
1186             APPL_TRACE_DEBUG("%s: Starting service discovery", __func__);
1187             bta_hh_le_pri_service_discovery(p_cb);
1188         }
1189     }
1190     else
1191     {
1192         APPL_TRACE_ERROR("%s() - encryption failed; status=0x%04x, reason=0x%04x",
1193                 __FUNCTION__, p_cb->status, p_cb->reason);
1194         if (!(p_cb->status == BTA_HH_ERR_SEC && p_cb->reason == BTM_ERR_PROCESSING))
1195             bta_hh_le_api_disc_act(p_cb);
1196     }
1197 }
1198 
1199 /*******************************************************************************
1200 **
1201 ** Function         bta_hh_le_notify_enc_cmpl
1202 **
1203 ** Description      process GATT encryption complete event
1204 **
1205 ** Returns
1206 **
1207 *******************************************************************************/
bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_buf)1208 void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1209 {
1210     if (p_cb == NULL || p_cb->security_pending == FALSE ||
1211         p_buf == NULL || p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if)
1212     {
1213         return;
1214     }
1215 
1216     p_cb->security_pending = FALSE;
1217     bta_hh_start_security(p_cb, NULL);
1218 }
1219 
1220 /*******************************************************************************
1221 **
1222 ** Function         bta_hh_clear_service_cache
1223 **
1224 ** Description      clear the service cache
1225 **
1226 ** Parameters:
1227 **
1228 *******************************************************************************/
bta_hh_clear_service_cache(tBTA_HH_DEV_CB * p_cb)1229 void bta_hh_clear_service_cache(tBTA_HH_DEV_CB *p_cb)
1230 {
1231     tBTA_HH_LE_HID_SRVC     *p_hid_srvc = &p_cb->hid_srvc;
1232 
1233     p_cb->app_id = 0;
1234     p_cb->dscp_info.descriptor.dsc_list = NULL;
1235 
1236     osi_free_and_reset((void **)&p_hid_srvc->rpt_map);
1237     memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC));
1238 }
1239 
1240 /*******************************************************************************
1241 **
1242 ** Function         bta_hh_start_security
1243 **
1244 ** Description      start the security check of the established connection
1245 **
1246 ** Parameters:
1247 **
1248 *******************************************************************************/
bta_hh_start_security(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_buf)1249 void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1250 {
1251     UINT8           sec_flag=0;
1252     tBTM_SEC_DEV_REC  *p_dev_rec;
1253     UNUSED(p_buf);
1254 
1255     p_dev_rec = btm_find_dev(p_cb->addr);
1256     if (p_dev_rec)
1257     {
1258         if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
1259             p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
1260         {
1261             /* if security collision happened, wait for encryption done */
1262             p_cb->security_pending = TRUE;
1263             return;
1264         }
1265     }
1266 
1267     /* verify bond */
1268     BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
1269 
1270     /* if link has been encrypted */
1271     if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
1272     {
1273         bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1274     }
1275     /* if bonded and link not encrypted */
1276     else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
1277     {
1278         sec_flag = BTM_BLE_SEC_ENCRYPT;
1279         p_cb->status = BTA_HH_ERR_AUTH_FAILED;
1280         BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, NULL, sec_flag);
1281     }
1282     /* unbonded device, report security error here */
1283     else if (p_cb->sec_mask != BTA_SEC_NONE)
1284     {
1285         sec_flag = BTM_BLE_SEC_ENCRYPT_NO_MITM;
1286         p_cb->status = BTA_HH_ERR_AUTH_FAILED;
1287         bta_hh_clear_service_cache(p_cb);
1288         BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, NULL, sec_flag);
1289     }
1290     /* otherwise let it go through */
1291     else
1292     {
1293         bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1294     }
1295 
1296 
1297 }
1298 
1299 /*******************************************************************************
1300 **
1301 ** Function         bta_hh_gatt_open
1302 **
1303 ** Description      process GATT open event.
1304 **
1305 ** Parameters:
1306 **
1307 *******************************************************************************/
bta_hh_gatt_open(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_buf)1308 void bta_hh_gatt_open(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1309 {
1310     tBTA_GATTC_OPEN *p_data = &p_buf->le_open;
1311     UINT8           *p2;
1312     tHID_STATUS     status = BTA_HH_ERR;
1313 
1314     /* if received invalid callback data , ignore it */
1315     if (p_cb == NULL || p_data == NULL)
1316         return;
1317 
1318     p2 = p_data->remote_bda;
1319 
1320     APPL_TRACE_DEBUG("bta_hh_gatt_open BTA_GATTC_OPEN_EVT bda= [%08x%04x] status =%d",
1321                       ((p2[0])<<24)+((p2[1])<<16)+((p2[2])<<8)+(p2[3]),
1322                       ((p2[4])<<8)+ p2[5],p_data->status);
1323 
1324     if (p_data->status == BTA_GATT_OK)
1325     {
1326         p_cb->is_le_device  = TRUE;
1327         p_cb->in_use    = TRUE;
1328         p_cb->conn_id   = p_data->conn_id;
1329         p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
1330 
1331         bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
1332 
1333         gatt_op_queue_clean(p_cb->conn_id);
1334 
1335 #if BTA_HH_DEBUG == TRUE
1336         APPL_TRACE_DEBUG("hid_handle = %2x conn_id = %04x cb_index = %d", p_cb->hid_handle, p_cb->conn_id, p_cb->index);
1337 #endif
1338 
1339         bta_hh_sm_execute(p_cb, BTA_HH_START_ENC_EVT, NULL);
1340 
1341     }
1342     else /* open failure */
1343     {
1344         bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
1345     }
1346 
1347 }
1348 
1349 /*******************************************************************************
1350 **
1351 ** Function         bta_hh_le_close
1352 **
1353 ** Description      This function process the GATT close event and post it as a
1354 **                  BTA HH internal event
1355 **
1356 ** Parameters:
1357 **
1358 *******************************************************************************/
bta_hh_le_close(tBTA_GATTC_CLOSE * p_data)1359 void bta_hh_le_close(tBTA_GATTC_CLOSE * p_data)
1360 {
1361     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->remote_bda);
1362     UINT16  sm_event = BTA_HH_GATT_CLOSE_EVT;
1363 
1364     if (p_dev_cb != NULL) {
1365         tBTA_HH_LE_CLOSE *p_buf =
1366             (tBTA_HH_LE_CLOSE *)osi_malloc(sizeof(tBTA_HH_LE_CLOSE));
1367         p_buf->hdr.event = sm_event;
1368         p_buf->hdr.layer_specific = (UINT16)p_dev_cb->hid_handle;
1369         p_buf->conn_id = p_data->conn_id;
1370         p_buf->reason = p_data->reason;
1371 
1372         p_dev_cb->conn_id = BTA_GATT_INVALID_CONN_ID;
1373         p_dev_cb->security_pending = FALSE;
1374         bta_sys_sendmsg(p_buf);
1375     }
1376 }
1377 
1378 /*******************************************************************************
1379 **
1380 ** Function         bta_hh_le_gatt_disc_cmpl
1381 **
1382 ** Description      Check to see if the remote device is a LE only device
1383 **
1384 ** Parameters:
1385 **
1386 *******************************************************************************/
bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB * p_cb,tBTA_HH_STATUS status)1387 void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status)
1388 {
1389     APPL_TRACE_DEBUG("bta_hh_le_gatt_disc_cmpl ");
1390 
1391     /* if open sucessful or protocol mode not desired, keep the connection open but inform app */
1392     if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO)
1393     {
1394         /* assign a special APP ID temp, since device type unknown */
1395         p_cb->app_id = BTA_HH_APP_ID_LE;
1396 
1397         /* set report notification configuration */
1398         p_cb->clt_cfg_idx = 0;
1399         bta_hh_le_write_rpt_clt_cfg(p_cb, p_cb->hid_srvc.srvc_inst_id);
1400     }
1401     else /* error, close the GATT connection */
1402     {
1403         /* close GATT connection if it's on */
1404         bta_hh_le_api_disc_act(p_cb);
1405     }
1406 }
1407 
process_included(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_SERVICE * service)1408 void process_included(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_SERVICE *service) {
1409     if (!service->included_svc || list_is_empty(service->included_svc)) {
1410         APPL_TRACE_ERROR("%s: Remote device does not have battery level", __func__);
1411         return;
1412     }
1413 
1414     for (list_node_t *isn = list_begin(service->included_svc);
1415          isn != list_end(service->included_svc); isn = list_next(isn)) {
1416         tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
1417         tBTA_GATTC_SERVICE *incl_svc = p_isvc->included_service;
1418         if (incl_svc->uuid.uu.uuid16 == UUID_SERVCLASS_BATTERY &&
1419             incl_svc->uuid.len == LEN_UUID_16) {
1420 
1421             /* read include service UUID */
1422             p_dev_cb->hid_srvc.incl_srvc_inst = incl_svc->handle;
1423 
1424             for (list_node_t *cn = list_begin(incl_svc->characteristics);
1425                  cn != list_end(incl_svc->characteristics); cn = list_next(cn)) {
1426                 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1427                 if (p_char->uuid.uu.uuid16 == GATT_UUID_BATTERY_LEVEL &&
1428                     p_char->uuid.len == LEN_UUID_16) {
1429 
1430                     if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
1431                                                           incl_svc->s_handle,
1432                                                           GATT_UUID_BATTERY_LEVEL,
1433                                                           p_char->handle) == NULL)
1434                         APPL_TRACE_ERROR("Add battery report entry failed !!!");
1435 
1436                     gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle);
1437                     return;
1438                 }
1439             }
1440         }
1441     }
1442 
1443     APPL_TRACE_ERROR("%s: Remote device does not have battery level", __func__);
1444 }
1445 
1446 /*******************************************************************************
1447 **
1448 ** Function         bta_hh_le_search_hid_chars
1449 **
1450 ** Description      This function discover all characteristics a service and
1451 **                  all descriptors available.
1452 **
1453 ** Parameters:
1454 **
1455 *******************************************************************************/
bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_SERVICE * service)1456 static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_SERVICE *service)
1457 {
1458     tBTA_HH_LE_RPT *p_rpt;
1459 
1460     for (list_node_t *cn = list_begin(service->characteristics);
1461          cn != list_end(service->characteristics); cn = list_next(cn)) {
1462         tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1463 
1464         if(p_char->uuid.len != LEN_UUID_16)
1465             continue;
1466 
1467         LOG_DEBUG(LOG_TAG, "%s: %s 0x%04d", __func__, bta_hh_uuid_to_str(p_char->uuid.uu.uuid16),
1468                   p_char->uuid.uu.uuid16);
1469 
1470         switch (p_char->uuid.uu.uuid16)
1471         {
1472         case GATT_UUID_HID_CONTROL_POINT:
1473             p_dev_cb->hid_srvc.control_point_handle = p_char->handle;
1474             break;
1475         case GATT_UUID_HID_INFORMATION:
1476         case GATT_UUID_HID_REPORT_MAP:
1477             /* read the char value */
1478             gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle);
1479 
1480             bta_hh_le_read_char_dscrpt(p_dev_cb, p_char->handle,
1481                                    GATT_UUID_EXT_RPT_REF_DESCR);
1482             break;
1483 
1484         case GATT_UUID_HID_REPORT:
1485             p_rpt = bta_hh_le_find_alloc_report_entry(p_dev_cb,
1486                                               p_dev_cb->hid_srvc.srvc_inst_id,
1487                                               GATT_UUID_HID_REPORT,
1488                                               p_char->handle);
1489             if (p_rpt == NULL) {
1490                 APPL_TRACE_ERROR("%s: Add report entry failed !!!", __func__);
1491                 break;
1492             }
1493 
1494             if (p_rpt->rpt_type != BTA_HH_RPTT_INPUT)
1495                 break;
1496 
1497             bta_hh_le_read_char_dscrpt(p_dev_cb, p_char->handle, GATT_UUID_RPT_REF_DESCR);
1498             break;
1499 
1500         /* found boot mode report types */
1501         case GATT_UUID_HID_BT_KB_OUTPUT:
1502         case GATT_UUID_HID_BT_MOUSE_INPUT:
1503         case GATT_UUID_HID_BT_KB_INPUT:
1504             if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
1505                                       service->handle,
1506                                       p_char->uuid.uu.uuid16,
1507                                       p_char->handle) == NULL)
1508                 APPL_TRACE_ERROR("%s: Add report entry failed !!!", __func__);
1509 
1510             break;
1511 
1512         default:
1513             APPL_TRACE_DEBUG("%s: not processing %s 0x%04d", __func__,
1514                              bta_hh_uuid_to_str(p_char->uuid.uu.uuid16),
1515                              p_char->uuid.uu.uuid16);
1516         }
1517     }
1518 
1519     /* Make sure PROTO_MODE is processed as last */
1520     for (list_node_t *cn = list_begin(service->characteristics);
1521          cn != list_end(service->characteristics); cn = list_next(cn)) {
1522         tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1523 
1524         if(p_char->uuid.len != LEN_UUID_16 &&
1525            p_char->uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE) {
1526             p_dev_cb->hid_srvc.proto_mode_handle = p_char->handle;
1527             bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
1528             break;
1529         }
1530     }
1531 }
1532 
1533 /*******************************************************************************
1534 **
1535 ** Function         bta_hh_le_srvc_search_cmpl
1536 **
1537 ** Description      This function process the GATT service search complete.
1538 **
1539 ** Parameters:
1540 **
1541 *******************************************************************************/
bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL * p_data)1542 void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL *p_data)
1543 {
1544     tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
1545 
1546     /* service search exception or no HID service is supported on remote */
1547     if (p_dev_cb == NULL)
1548         return;
1549 
1550     if(p_data->status != BTA_GATT_OK)
1551     {
1552         p_dev_cb->status = BTA_HH_ERR_SDP;
1553         /* close the connection and report service discovery complete with error */
1554         bta_hh_le_api_disc_act(p_dev_cb);
1555         return;
1556     }
1557 
1558     const list_t *services = BTA_GATTC_GetServices(p_data->conn_id);
1559 
1560     bool have_hid = false;
1561     for (list_node_t *sn = list_begin(services);
1562          sn != list_end(services); sn = list_next(sn)) {
1563         tBTA_GATTC_SERVICE *service = list_node(sn);
1564 
1565         if (service->uuid.uu.uuid16 == UUID_SERVCLASS_LE_HID &&
1566             service->is_primary && !have_hid) {
1567             have_hid = true;
1568 
1569             /* found HID primamry service */
1570             p_dev_cb->hid_srvc.in_use = TRUE;
1571             p_dev_cb->hid_srvc.srvc_inst_id = service->handle;
1572             p_dev_cb->hid_srvc.proto_mode_handle = 0;
1573             p_dev_cb->hid_srvc.control_point_handle = 0;
1574 
1575             process_included(p_dev_cb, service);
1576             bta_hh_le_search_hid_chars(p_dev_cb, service);
1577 
1578             APPL_TRACE_DEBUG("%s: have HID service inst_id= %d", __func__, p_dev_cb->hid_srvc.srvc_inst_id);
1579         } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_SCAN_PARAM) {
1580             p_dev_cb->scan_refresh_char_handle = 0;
1581 
1582             for (list_node_t *cn = list_begin(service->characteristics);
1583                  cn != list_end(service->characteristics); cn = list_next(cn)) {
1584                 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1585                 if (p_char->uuid.len == LEN_UUID_16 &&
1586                     p_char->uuid.uu.uuid16 == GATT_UUID_SCAN_REFRESH) {
1587 
1588                     p_dev_cb->scan_refresh_char_handle = p_char->handle;
1589 
1590                     if (p_char->properties & BTA_GATT_CHAR_PROP_BIT_NOTIFY)
1591                         p_dev_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT;
1592                     else
1593                         p_dev_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE;
1594 
1595                     break;
1596                 }
1597             }
1598         } else if (service->uuid.uu.uuid16 == UUID_SERVCLASS_GAP_SERVER) {
1599             //TODO(jpawlowski): this should be done by GAP profile, remove when GAP is fixed.
1600             for (list_node_t *cn = list_begin(service->characteristics);
1601                  cn != list_end(service->characteristics); cn = list_next(cn)) {
1602                 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1603                 if (p_char->uuid.len == LEN_UUID_16 &&
1604                     p_char->uuid.uu.uuid16 == GATT_UUID_GAP_PREF_CONN_PARAM) {
1605 
1606                     /* read the char value */
1607                     gatt_queue_read_op(GATT_READ_CHAR, p_dev_cb->conn_id, p_char->handle);
1608 
1609                     break;
1610                 }
1611             }
1612         }
1613     }
1614 
1615     bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status);
1616 }
1617 
1618 /*******************************************************************************
1619 **
1620 ** Function         bta_hh_read_battery_level_cmpl
1621 **
1622 ** Description      This function process the battery level read
1623 **
1624 ** Parameters:
1625 **
1626 *******************************************************************************/
bta_hh_read_battery_level_cmpl(UINT8 status,tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_READ * p_data)1627 void bta_hh_read_battery_level_cmpl(UINT8 status, tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1628 {
1629     UNUSED(status);
1630     UNUSED(p_data);
1631     p_dev_cb->hid_srvc.expl_incl_srvc = TRUE;
1632 }
1633 
1634 
1635 /*******************************************************************************
1636 **
1637 ** Function         bta_hh_le_save_rpt_map
1638 **
1639 ** Description      save the report map into the control block.
1640 **
1641 ** Parameters:
1642 **
1643 *******************************************************************************/
bta_hh_le_save_rpt_map(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_READ * p_data)1644 void bta_hh_le_save_rpt_map(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1645 {
1646     tBTA_HH_LE_HID_SRVC *p_srvc = &p_dev_cb->hid_srvc;
1647 
1648     osi_free_and_reset((void **)&p_srvc->rpt_map);
1649 
1650     if (p_data->p_value->len > 0)
1651         p_srvc->rpt_map = (UINT8 *)osi_malloc(p_data->p_value->len);
1652 
1653     if (p_srvc->rpt_map != NULL)
1654     {
1655         UINT8 *pp = p_data->p_value->p_value;
1656         STREAM_TO_ARRAY(p_srvc->rpt_map, pp, p_data->p_value->len);
1657         p_srvc->descriptor.dl_len = p_data->p_value->len;
1658         p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc.rpt_map;
1659     }
1660 }
1661 
1662 /*******************************************************************************
1663 **
1664 ** Function         bta_hh_le_proc_get_rpt_cmpl
1665 **
1666 ** Description      Process the Read report complete, send GET_REPORT_EVT to application
1667 **                  with the report data.
1668 **
1669 ** Parameters:
1670 **
1671 *******************************************************************************/
bta_hh_le_proc_get_rpt_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_READ * p_data)1672 void bta_hh_le_proc_get_rpt_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1673 {
1674     BT_HDR              *p_buf = NULL;
1675     tBTA_HH_LE_RPT      *p_rpt;
1676     tBTA_HH_HSDATA      hs_data;
1677     UINT8               *pp ;
1678 
1679     if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT)
1680     {
1681         APPL_TRACE_ERROR("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt);
1682         return;
1683     }
1684 
1685     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
1686                                                                           p_data->handle);
1687 
1688     memset(&hs_data, 0, sizeof(hs_data));
1689     hs_data.status  = BTA_HH_ERR;
1690     hs_data.handle  = p_dev_cb->hid_handle;
1691 
1692     if (p_data->status == BTA_GATT_OK)
1693     {
1694         p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1695                                             p_char->service->handle,
1696                                             p_char->uuid.uu.uuid16,
1697                                             p_char->handle);
1698 
1699         if (p_rpt != NULL && p_data->p_value != NULL) {
1700             p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR) + p_data->p_value->len + 1);
1701             /* pack data send to app */
1702             hs_data.status  = BTA_HH_OK;
1703             p_buf->len = p_data->p_value->len + 1;
1704             p_buf->layer_specific = 0;
1705             p_buf->offset = 0;
1706 
1707             /* attach report ID as the first byte of the report before sending it to USB HID driver */
1708             pp = (UINT8*)(p_buf + 1);
1709             UINT8_TO_STREAM(pp, p_rpt->rpt_id);
1710             memcpy(pp, p_data->p_value->p_value, p_data->p_value->len);
1711 
1712             hs_data.rsp_data.p_rpt_data =p_buf;
1713         }
1714     }
1715 
1716     p_dev_cb->w4_evt = 0;
1717     (* bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH *)&hs_data);
1718 
1719     osi_free_and_reset((void **)&p_buf);
1720 }
1721 
1722 /*******************************************************************************
1723 **
1724 ** Function         bta_hh_le_proc_read_proto_mode
1725 **
1726 ** Description      Process the Read protocol mode, send GET_PROTO_EVT to application
1727 **                  with the protocol mode.
1728 **
1729 *******************************************************************************/
bta_hh_le_proc_read_proto_mode(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATTC_READ * p_data)1730 void bta_hh_le_proc_read_proto_mode(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1731 {
1732     tBTA_HH_HSDATA      hs_data;
1733 
1734     hs_data.status  = BTA_HH_ERR;
1735     hs_data.handle  = p_dev_cb->hid_handle;
1736     hs_data.rsp_data.proto_mode = p_dev_cb->mode;
1737 
1738     if (p_data->status == BTA_GATT_OK && p_data->p_value)
1739     {
1740         hs_data.status  = BTA_HH_OK;
1741         /* match up BTE/BTA report/boot mode def*/
1742         hs_data.rsp_data.proto_mode = *(p_data->p_value->p_value);
1743         /* LE repot mode is the opposite value of BR/EDR report mode, flip it here */
1744         if (hs_data.rsp_data.proto_mode == 0)
1745             hs_data.rsp_data.proto_mode = BTA_HH_PROTO_BOOT_MODE;
1746         else
1747             hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
1748 
1749         p_dev_cb->mode = hs_data.rsp_data.proto_mode;
1750     }
1751 #if BTA_HH_DEBUG
1752     APPL_TRACE_DEBUG("LE GET_PROTOCOL Mode = [%s]",
1753                         (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot");
1754 #endif
1755 
1756     p_dev_cb->w4_evt = 0;
1757     (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
1758 
1759 }
1760 
1761 /*******************************************************************************
1762 **
1763 ** Function         bta_hh_w4_le_read_char_cmpl
1764 **
1765 ** Description      process the GATT read complete in W4_CONN state.
1766 **
1767 ** Parameters:
1768 **
1769 *******************************************************************************/
bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)1770 void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1771 {
1772     tBTA_GATTC_READ     * p_data = (tBTA_GATTC_READ *)p_buf;
1773     UINT8               *pp ;
1774 
1775     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
1776                                                                           p_data->handle);
1777     UINT16 char_uuid = p_char->uuid.uu.uuid16;
1778 
1779     if (char_uuid == GATT_UUID_BATTERY_LEVEL)
1780     {
1781         bta_hh_read_battery_level_cmpl(p_data->status, p_dev_cb, p_data);
1782     }
1783     else if (char_uuid == GATT_UUID_GAP_PREF_CONN_PARAM)
1784     {
1785         //TODO(jpawlowski): this should be done by GAP profile, remove when GAP is fixed.
1786         UINT8 *pp = p_data->p_value->p_value;
1787         UINT16 min, max, latency, tout;
1788         STREAM_TO_UINT16 (min, pp);
1789         STREAM_TO_UINT16 (max, pp);
1790         STREAM_TO_UINT16 (latency, pp);
1791         STREAM_TO_UINT16 (tout, pp);
1792 
1793         // Make sure both min, and max are bigger than 11.25ms, lower values can introduce
1794         // audio issues if A2DP is also active.
1795         if (min < BTM_BLE_CONN_INT_MIN_LIMIT)
1796             min = BTM_BLE_CONN_INT_MIN_LIMIT;
1797         if (max < BTM_BLE_CONN_INT_MIN_LIMIT)
1798             max = BTM_BLE_CONN_INT_MIN_LIMIT;
1799 
1800         if (tout < BTM_BLE_CONN_TIMEOUT_MIN_DEF)
1801             tout = BTM_BLE_CONN_TIMEOUT_MIN_DEF;
1802 
1803         BTM_BleSetPrefConnParams (p_dev_cb->addr, min, max, latency, tout);
1804         L2CA_UpdateBleConnParams(p_dev_cb->addr, min, max, latency, tout);
1805     }
1806     else
1807     {
1808         if (p_data->status == BTA_GATT_OK && p_data->p_value)
1809         {
1810             pp = p_data->p_value->p_value;
1811 
1812             switch (char_uuid)
1813             {
1814            /* save device information */
1815             case GATT_UUID_HID_INFORMATION:
1816                 STREAM_TO_UINT16(p_dev_cb->dscp_info.version, pp);
1817                 STREAM_TO_UINT8(p_dev_cb->dscp_info.ctry_code, pp);
1818                 STREAM_TO_UINT8(p_dev_cb->dscp_info.flag, pp);
1819                 break;
1820 
1821             case GATT_UUID_HID_REPORT_MAP:
1822                 bta_hh_le_save_rpt_map(p_dev_cb, p_data);
1823                 return;
1824 
1825             default:
1826 #if BTA_HH_DEBUG == TRUE
1827                 APPL_TRACE_ERROR("Unexpected read %s(0x%04x)",
1828                                 bta_hh_uuid_to_str(char_uuid), char_uuid);
1829 #endif
1830                 break;
1831             }
1832         }
1833         else
1834         {
1835 #if BTA_HH_DEBUG == TRUE
1836             APPL_TRACE_ERROR("read uuid %s[0x%04x] error: %d", bta_hh_uuid_to_str(char_uuid),
1837                              char_uuid, p_data->status);
1838 #else
1839             APPL_TRACE_ERROR("read uuid [0x%04x] error: %d", char_uuid, p_data->status);
1840 #endif
1841         }
1842     }
1843 
1844 }
1845 
1846 /*******************************************************************************
1847 **
1848 ** Function         bta_hh_le_read_char_cmpl
1849 **
1850 ** Description      a characteristic value is received.
1851 **
1852 ** Parameters:
1853 **
1854 *******************************************************************************/
bta_hh_le_read_char_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)1855 void bta_hh_le_read_char_cmpl (tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1856 {
1857     tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
1858 
1859     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
1860                                                                           p_data->handle);
1861     UINT16 char_uuid = p_char->uuid.uu.uuid16;
1862 
1863     switch (char_uuid)
1864     {
1865     /* GET_REPORT */
1866     case GATT_UUID_HID_REPORT:
1867     case GATT_UUID_HID_BT_KB_INPUT:
1868     case GATT_UUID_HID_BT_KB_OUTPUT:
1869     case GATT_UUID_HID_BT_MOUSE_INPUT:
1870     case GATT_UUID_BATTERY_LEVEL: /* read battery level */
1871         bta_hh_le_proc_get_rpt_cmpl(p_dev_cb, p_data);
1872         break;
1873 
1874     case GATT_UUID_HID_PROTO_MODE:
1875         bta_hh_le_proc_read_proto_mode(p_dev_cb, p_data);
1876         break;
1877 
1878     default:
1879         APPL_TRACE_ERROR("Unexpected Read UUID: 0x%04x", char_uuid);
1880         break;
1881     }
1882 
1883 }
1884 
1885 /*******************************************************************************
1886 **
1887 ** Function         bta_hh_le_read_descr_cmpl
1888 **
1889 ** Description      read characteristic descriptor is completed in CONN st.
1890 **
1891 ** Parameters:
1892 **
1893 *******************************************************************************/
bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)1894 void bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1895 {
1896     tBTA_HH_LE_RPT  *p_rpt;
1897     tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
1898     UINT8   *pp;
1899 
1900     const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(p_data->conn_id, p_data->handle);
1901 
1902     /* if a report client configuration */
1903     if (p_desc->uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
1904     {
1905         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1906                                                  p_desc->characteristic->service->handle,
1907                                                  p_desc->characteristic->uuid.uu.uuid16,
1908                                                  p_desc->characteristic->handle)) != NULL)
1909         {
1910             pp = p_data->p_value->p_value;
1911             STREAM_TO_UINT16(p_rpt->client_cfg_value, pp);
1912 
1913             APPL_TRACE_DEBUG("Read Client Configuration: 0x%04x", p_rpt->client_cfg_value);
1914         }
1915     }
1916 }
1917 
1918 /*******************************************************************************
1919 **
1920 ** Function         bta_hh_w4_le_read_descr_cmpl
1921 **
1922 ** Description      read characteristic descriptor is completed in W4_CONN st.
1923 **
1924 ** Parameters:
1925 **
1926 *******************************************************************************/
bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)1927 void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1928 {
1929     tBTA_HH_LE_RPT  *p_rpt;
1930     tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
1931     UINT16 char_uuid16;
1932 
1933     if (p_data == NULL)
1934         return;
1935 
1936     const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(p_data->conn_id, p_data->handle);
1937 
1938     if (p_desc == NULL) {
1939         APPL_TRACE_ERROR("%s: p_descr is NULL %d", __func__, p_data->handle);
1940         return;
1941     }
1942 
1943     char_uuid16 = p_desc->characteristic->uuid.uu.uuid16;
1944 
1945 #if BTA_HH_DEBUG == TRUE
1946     APPL_TRACE_DEBUG("bta_hh_w4_le_read_descr_cmpl uuid: %s(0x%04x)",
1947                         bta_hh_uuid_to_str(p_desc->uuid.uu.uuid16),
1948                         p_desc->uuid.uu.uuid16);
1949 #endif
1950     switch (char_uuid16)
1951     {
1952     case GATT_UUID_HID_REPORT:
1953         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1954                                             p_desc->characteristic->service->handle,
1955                                             GATT_UUID_HID_REPORT,
1956                                             p_desc->characteristic->handle)))
1957             bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
1958         break;
1959 
1960     case GATT_UUID_HID_REPORT_MAP:
1961         bta_hh_le_save_ext_rpt_ref(p_dev_cb, p_data);
1962         break;
1963 
1964     case GATT_UUID_BATTERY_LEVEL:
1965         if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1966                                             p_desc->characteristic->service->handle,
1967                                             GATT_UUID_BATTERY_LEVEL,
1968                                             p_desc->characteristic->handle)))
1969             bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
1970 
1971         break;
1972 
1973     default:
1974         APPL_TRACE_ERROR("unknown descriptor read complete for uuid: 0x%04x", char_uuid16);
1975         break;
1976     }
1977 }
1978 
1979 /*******************************************************************************
1980 **
1981 ** Function         bta_hh_w4_le_write_cmpl
1982 **
1983 ** Description      Write charactersitic complete event at W4_CONN st.
1984 **
1985 ** Parameters:
1986 **
1987 *******************************************************************************/
bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)1988 void bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1989 {
1990     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
1991 
1992     if (p_data == NULL)
1993         return;
1994 
1995     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
1996                                                                           p_data->handle);
1997 
1998     if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE)
1999     {
2000         p_dev_cb->status = (p_data->status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
2001 
2002         if ((p_dev_cb->disc_active & BTA_HH_LE_DISC_HIDS) == 0)
2003             bta_hh_le_open_cmpl(p_dev_cb);
2004     }
2005 }
2006 
2007 /*******************************************************************************
2008 **
2009 ** Function         bta_hh_le_write_cmpl
2010 **
2011 ** Description      Write charactersitic complete event at CONN st.
2012 **
2013 ** Parameters:
2014 **
2015 *******************************************************************************/
bta_hh_le_write_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)2016 void bta_hh_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2017 {
2018     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
2019     tBTA_HH_CBDATA      cback_data ;
2020     UINT16              cb_evt = p_dev_cb->w4_evt;
2021 
2022     if (p_data == NULL  || cb_evt == 0)
2023         return;
2024 
2025     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
2026                                                                           p_data->handle);
2027 
2028 #if BTA_HH_DEBUG
2029     APPL_TRACE_DEBUG("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt);
2030 #endif
2031     switch (p_char->uuid.uu.uuid16)
2032     {
2033     /* Set protocol finished */
2034     case GATT_UUID_HID_PROTO_MODE:
2035         cback_data.handle  = p_dev_cb->hid_handle;
2036         if (p_data->status == BTA_GATT_OK)
2037         {
2038             bta_hh_le_register_input_notif(p_dev_cb, p_dev_cb->mode, FALSE);
2039             cback_data.status = BTA_HH_OK;
2040         }
2041         else
2042             cback_data.status =  BTA_HH_ERR;
2043         p_dev_cb->w4_evt = 0;
2044         (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
2045         break;
2046 
2047     /* Set Report finished */
2048     case GATT_UUID_HID_REPORT:
2049     case GATT_UUID_HID_BT_KB_INPUT:
2050     case GATT_UUID_HID_BT_MOUSE_INPUT:
2051     case GATT_UUID_HID_BT_KB_OUTPUT:
2052         cback_data.handle  = p_dev_cb->hid_handle;
2053         cback_data.status = (p_data->status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
2054         p_dev_cb->w4_evt = 0;
2055         (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
2056         break;
2057 
2058     case GATT_UUID_SCAN_INT_WINDOW:
2059         bta_hh_le_register_scpp_notif(p_dev_cb, p_data->status);
2060         break;
2061 
2062     default:
2063         break;
2064     }
2065 
2066 }
2067 
2068 /*******************************************************************************
2069 **
2070 ** Function         bta_hh_le_write_char_descr_cmpl
2071 **
2072 ** Description      Write charactersitic descriptor complete event
2073 **
2074 ** Parameters:
2075 **
2076 *******************************************************************************/
bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)2077 void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2078 {
2079     tBTA_GATTC_WRITE    *p_data = (tBTA_GATTC_WRITE *)p_buf;
2080     UINT8   srvc_inst_id, hid_inst_id;
2081 
2082     const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(p_dev_cb->conn_id,
2083                                                                        p_data->handle);
2084 
2085     UINT16 desc_uuid = p_desc->uuid.uu.uuid16;
2086     UINT16 char_uuid = p_desc->characteristic->uuid.uu.uuid16;
2087     /* only write client configuration possible */
2088     if (desc_uuid == GATT_UUID_CHAR_CLIENT_CONFIG)
2089     {
2090         srvc_inst_id = p_desc->characteristic->service->handle;
2091         hid_inst_id = srvc_inst_id;
2092         switch (char_uuid)
2093         {
2094         case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
2095             hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_dev_cb, srvc_inst_id);
2096             /* fall through */
2097         case GATT_UUID_HID_BT_KB_INPUT:
2098         case GATT_UUID_HID_BT_MOUSE_INPUT:
2099         case GATT_UUID_HID_REPORT:
2100             if (p_data->status == BTA_GATT_OK)
2101                 p_dev_cb->hid_srvc.report[p_dev_cb->clt_cfg_idx].client_cfg_value =
2102                         BTA_GATT_CLT_CONFIG_NOTIFICATION;
2103             p_dev_cb->clt_cfg_idx ++;
2104             bta_hh_le_write_rpt_clt_cfg(p_dev_cb, hid_inst_id);
2105 
2106             break;
2107 
2108         case GATT_UUID_SCAN_REFRESH:
2109             bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, p_data->status);
2110             break;
2111 
2112         default:
2113             APPL_TRACE_ERROR("Unknown char ID clt cfg: 0x%04x", char_uuid);
2114         }
2115     }
2116     else
2117     {
2118 #if BTA_HH_DEBUG == TRUE
2119         APPL_TRACE_ERROR("Unexpected write to %s(0x%04x)",
2120                          bta_hh_uuid_to_str(desc_uuid), desc_uuid);
2121 #else
2122         APPL_TRACE_ERROR("Unexpected write to (0x%04x)", desc_uuid);
2123 #endif
2124     }
2125 
2126 }
2127 
2128 /*******************************************************************************
2129 **
2130 ** Function         bta_hh_le_input_rpt_notify
2131 **
2132 ** Description      process the notificaton event, most likely for input report.
2133 **
2134 ** Parameters:
2135 **
2136 *******************************************************************************/
bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY * p_data)2137 void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data)
2138 {
2139     tBTA_HH_DEV_CB       *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
2140     UINT8           app_id;
2141     UINT8           *p_buf;
2142     tBTA_HH_LE_RPT  *p_rpt;
2143 
2144     if (p_dev_cb == NULL)
2145     {
2146         APPL_TRACE_ERROR("notification received from Unknown device");
2147         return;
2148     }
2149 
2150     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
2151                                                                           p_data->handle);
2152 
2153     app_id= p_dev_cb->app_id;
2154 
2155     p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
2156                                         p_dev_cb->hid_srvc.srvc_inst_id,
2157                                         p_char->uuid.uu.uuid16,
2158                                         p_char->handle);
2159     if (p_rpt == NULL)
2160     {
2161         APPL_TRACE_ERROR("notification received for Unknown Report");
2162         return;
2163     }
2164 
2165     if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_BT_MOUSE_INPUT)
2166         app_id = BTA_HH_APP_ID_MI;
2167     else if (p_char->uuid.uu.uuid16 == GATT_UUID_HID_BT_KB_INPUT)
2168         app_id = BTA_HH_APP_ID_KB;
2169 
2170     APPL_TRACE_DEBUG("Notification received on report ID: %d", p_rpt->rpt_id);
2171 
2172     /* need to append report ID to the head of data */
2173     if (p_rpt->rpt_id != 0)
2174     {
2175         p_buf = (UINT8 *)osi_malloc(p_data->len + 1);
2176 
2177         p_buf[0] = p_rpt->rpt_id;
2178         memcpy(&p_buf[1], p_data->value, p_data->len);
2179         ++p_data->len;
2180     } else {
2181         p_buf = p_data->value;
2182     }
2183 
2184     bta_hh_co_data((UINT8)p_dev_cb->hid_handle,
2185                     p_buf,
2186                     p_data->len,
2187                     p_dev_cb->mode,
2188                     0 , /* no sub class*/
2189                     p_dev_cb->dscp_info.ctry_code,
2190                     p_dev_cb->addr,
2191                     app_id);
2192 
2193     if (p_buf != p_data->value)
2194         osi_free(p_buf);
2195 }
2196 
2197 /*******************************************************************************
2198 **
2199 ** Function         bta_hh_gatt_open_fail
2200 **
2201 ** Description      action function to process the open fail
2202 **
2203 ** Returns          void
2204 **
2205 *******************************************************************************/
bta_hh_le_open_fail(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_data)2206 void bta_hh_le_open_fail(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
2207 {
2208     tBTA_HH_CONN            conn_dat ;
2209 
2210     /* open failure in the middle of service discovery, clear all services */
2211     if (p_cb->disc_active & BTA_HH_LE_DISC_HIDS)
2212     {
2213         bta_hh_clear_service_cache(p_cb);
2214     }
2215 
2216     p_cb->disc_active = BTA_HH_LE_DISC_NONE;
2217     /* Failure in opening connection or GATT discovery failure */
2218     conn_dat.handle = p_cb->hid_handle;
2219     memcpy(conn_dat.bda, p_cb->addr, BD_ADDR_LEN);
2220     conn_dat.le_hid = TRUE;
2221     conn_dat.scps_supported = p_cb->scps_supported;
2222 
2223     if (p_cb->status == BTA_HH_OK)
2224         conn_dat.status = (p_data->le_close.reason == BTA_GATT_CONN_UNKNOWN) ? p_cb->status : BTA_HH_ERR;
2225     else
2226         conn_dat.status = p_cb->status;
2227 
2228     /* Report OPEN fail event */
2229     (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
2230 
2231 }
2232 
2233 /*******************************************************************************
2234 **
2235 ** Function         bta_hh_gatt_close
2236 **
2237 ** Description      action function to process the GATT close int he state machine.
2238 **
2239 ** Returns          void
2240 **
2241 *******************************************************************************/
bta_hh_gatt_close(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_data)2242 void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
2243 {
2244     tBTA_HH_CBDATA          disc_dat = {BTA_HH_OK, 0};
2245 
2246     /* deregister all notification */
2247     bta_hh_le_deregister_input_notif(p_cb);
2248     /* finaliza device driver */
2249     bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
2250     /* update total conn number */
2251     bta_hh_cb.cnt_num --;
2252 
2253     disc_dat.handle = p_cb->hid_handle;
2254     disc_dat.status = p_cb->status;
2255 
2256     (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
2257 
2258     /* if no connection is active and HH disable is signaled, disable service */
2259     if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
2260     {
2261         bta_hh_disc_cmpl();
2262     }
2263     else
2264     {
2265 #if (BTA_HH_LE_RECONN == TRUE)
2266     if (p_data->le_close.reason == BTA_GATT_CONN_TIMEOUT)
2267     {
2268         bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
2269     }
2270 #endif
2271     }
2272 
2273     return;
2274 
2275 }
2276 
2277 /*******************************************************************************
2278 **
2279 ** Function         bta_hh_le_api_disc_act
2280 **
2281 ** Description      initaite a Close API to a remote HID device
2282 **
2283 ** Returns          void
2284 **
2285 *******************************************************************************/
bta_hh_le_api_disc_act(tBTA_HH_DEV_CB * p_cb)2286 void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb)
2287 {
2288     if (p_cb->conn_id != BTA_GATT_INVALID_CONN_ID)
2289     {
2290         gatt_op_queue_clean(p_cb->conn_id);
2291         BTA_GATTC_Close(p_cb->conn_id);
2292         /* remove device from background connection if intended to disconnect,
2293            do not allow reconnection */
2294         bta_hh_le_remove_dev_bg_conn(p_cb);
2295     }
2296 }
2297 
2298 /*******************************************************************************
2299 **
2300 ** Function         bta_hh_le_get_rpt
2301 **
2302 ** Description      GET_REPORT on a LE HID Report
2303 **
2304 ** Returns          void
2305 **
2306 *******************************************************************************/
bta_hh_le_get_rpt(tBTA_HH_DEV_CB * p_cb,tBTA_HH_RPT_TYPE r_type,UINT8 rpt_id)2307 void bta_hh_le_get_rpt(tBTA_HH_DEV_CB *p_cb, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
2308 {
2309     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);
2310 
2311     if (p_rpt == NULL) {
2312         APPL_TRACE_ERROR("%s: no matching report", __func__);
2313         return;
2314     }
2315 
2316     p_cb->w4_evt = BTA_HH_GET_RPT_EVT;
2317     gatt_queue_read_op(GATT_READ_CHAR, p_cb->conn_id, p_rpt->char_inst_id);
2318 }
2319 
2320 /*******************************************************************************
2321 **
2322 ** Function         bta_hh_le_write_rpt
2323 **
2324 ** Description      SET_REPORT/or DATA output on a LE HID Report
2325 **
2326 ** Returns          void
2327 **
2328 *******************************************************************************/
bta_hh_le_write_rpt(tBTA_HH_DEV_CB * p_cb,tBTA_HH_RPT_TYPE r_type,BT_HDR * p_buf,UINT16 w4_evt)2329 void bta_hh_le_write_rpt(tBTA_HH_DEV_CB *p_cb,
2330                          tBTA_HH_RPT_TYPE r_type,
2331                          BT_HDR *p_buf, UINT16 w4_evt )
2332 {
2333     tBTA_HH_LE_RPT  *p_rpt;
2334     UINT8   *p_value, rpt_id;
2335 
2336     if (p_buf == NULL || p_buf->len == 0)
2337     {
2338         APPL_TRACE_ERROR("bta_hh_le_write_rpt: Illegal data");
2339         return;
2340     }
2341 
2342     /* strip report ID from the data */
2343     p_value = (UINT8 *)(p_buf + 1) + p_buf->offset;
2344     STREAM_TO_UINT8(rpt_id, p_value);
2345     p_buf->len -= 1;
2346 
2347     p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode, r_type, rpt_id);
2348 
2349     if (p_rpt == NULL) {
2350         APPL_TRACE_ERROR("%s: no matching report", __func__);
2351         osi_free(p_buf);
2352         return;
2353     }
2354 
2355     p_cb->w4_evt = w4_evt;
2356 
2357     const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_cb->conn_id,
2358                                                                           p_rpt->char_inst_id);
2359 
2360     tBTA_GATTC_WRITE_TYPE write_type = BTA_GATTC_TYPE_WRITE;
2361     if (p_char && (p_char->properties & BTA_GATT_CHAR_PROP_BIT_WRITE_NR))
2362         write_type = BTA_GATTC_TYPE_WRITE_NO_RSP;
2363 
2364     gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_rpt->char_inst_id,
2365                         p_buf->len, p_value, write_type);
2366 }
2367 
2368 /*******************************************************************************
2369 **
2370 ** Function         bta_hh_le_suspend
2371 **
2372 ** Description      send LE suspend or exit suspend mode to remote device.
2373 **
2374 ** Returns          void
2375 **
2376 *******************************************************************************/
bta_hh_le_suspend(tBTA_HH_DEV_CB * p_cb,tBTA_HH_TRANS_CTRL_TYPE ctrl_type)2377 void bta_hh_le_suspend(tBTA_HH_DEV_CB *p_cb, tBTA_HH_TRANS_CTRL_TYPE ctrl_type)
2378 {
2379     ctrl_type -= BTA_HH_CTRL_SUSPEND;
2380 
2381     gatt_queue_write_op(GATT_WRITE_CHAR, p_cb->conn_id, p_cb->hid_srvc.control_point_handle, 1,
2382                         &ctrl_type, BTA_GATTC_TYPE_WRITE_NO_RSP);
2383 }
2384 
2385 /*******************************************************************************
2386 **
2387 ** Function         bta_hh_le_write_dev_act
2388 **
2389 ** Description      Write LE device action. can be SET/GET/DATA transaction.
2390 **
2391 ** Returns          void
2392 **
2393 *******************************************************************************/
bta_hh_le_write_dev_act(tBTA_HH_DEV_CB * p_cb,tBTA_HH_DATA * p_data)2394 void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
2395 {
2396     switch(p_data->api_sndcmd.t_type)
2397     {
2398         case HID_TRANS_SET_PROTOCOL:
2399             p_cb->w4_evt = BTA_HH_SET_PROTO_EVT;
2400             bta_hh_le_set_protocol_mode(p_cb, p_data->api_sndcmd.param);
2401             break;
2402 
2403         case HID_TRANS_GET_PROTOCOL:
2404             bta_hh_le_get_protocol_mode(p_cb);
2405             break;
2406 
2407         case HID_TRANS_GET_REPORT:
2408             bta_hh_le_get_rpt(p_cb,
2409                               p_data->api_sndcmd.param,
2410                               p_data->api_sndcmd.rpt_id);
2411             break;
2412 
2413         case HID_TRANS_SET_REPORT:
2414             bta_hh_le_write_rpt(p_cb,
2415                                 p_data->api_sndcmd.param,
2416                                 p_data->api_sndcmd.p_data,
2417                                 BTA_HH_SET_RPT_EVT);
2418             break;
2419 
2420         case HID_TRANS_DATA:  /* output report */
2421 
2422             bta_hh_le_write_rpt(p_cb,
2423                                 p_data->api_sndcmd.param,
2424                                 p_data->api_sndcmd.p_data,
2425                                 BTA_HH_DATA_EVT);
2426             break;
2427 
2428         case HID_TRANS_CONTROL:
2429             /* no handshake event will be generated */
2430             /* if VC_UNPLUG is issued, set flag */
2431             if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND ||
2432                 p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
2433             {
2434                 bta_hh_le_suspend(p_cb, p_data->api_sndcmd.param);
2435             }
2436             break;
2437 
2438         default:
2439             APPL_TRACE_ERROR("%s unsupported transaction for BLE HID device: %d",
2440                 __func__, p_data->api_sndcmd.t_type);
2441             break;
2442     }
2443 }
2444 
2445 /*******************************************************************************
2446 **
2447 ** Function         bta_hh_le_get_dscp_act
2448 **
2449 ** Description      Send ReportDescriptor to application for all HID services.
2450 **
2451 ** Returns          void
2452 **
2453 *******************************************************************************/
bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB * p_cb)2454 void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb)
2455 {
2456     if (p_cb->hid_srvc.in_use)
2457     {
2458         p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc.descriptor.dl_len;
2459         p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc.descriptor.dsc_list;
2460 
2461         (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
2462     }
2463 }
2464 
2465 /*******************************************************************************
2466 **
2467 ** Function         bta_hh_le_add_dev_bg_conn
2468 **
2469 ** Description      Remove a LE HID device from back ground connection procedure.
2470 **
2471 ** Returns          void
2472 **
2473 *******************************************************************************/
bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB * p_cb,BOOLEAN check_bond)2474 static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond)
2475 {
2476     UINT8           sec_flag=0;
2477     BOOLEAN         to_add = TRUE;
2478 
2479     if (check_bond)
2480     {
2481         /* start reconnection if remote is a bonded device */
2482         /* verify bond */
2483         BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
2484 
2485         if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0)
2486             to_add = FALSE;
2487     }
2488 
2489     if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/
2490         !p_cb->in_bg_conn && to_add)
2491     {
2492         /* add device into BG connection to accept remote initiated connection */
2493         BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE);
2494         p_cb->in_bg_conn = TRUE;
2495 
2496         BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL);
2497     }
2498     return;
2499 }
2500 
2501 /*******************************************************************************
2502 **
2503 ** Function         bta_hh_le_add_device
2504 **
2505 ** Description      Add a LE HID device as a known device, and also add the address
2506 **                  into back ground connection WL for incoming connection.
2507 **
2508 ** Returns          void
2509 **
2510 *******************************************************************************/
bta_hh_le_add_device(tBTA_HH_DEV_CB * p_cb,tBTA_HH_MAINT_DEV * p_dev_info)2511 UINT8 bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info)
2512 {
2513     p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
2514     bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
2515 
2516     /* update DI information */
2517     bta_hh_update_di_info(p_cb,
2518                           p_dev_info->dscp_info.vendor_id,
2519                           p_dev_info->dscp_info.product_id,
2520                           p_dev_info->dscp_info.version,
2521                           p_dev_info->dscp_info.flag);
2522 
2523     /* add to BTA device list */
2524     bta_hh_add_device_to_list(p_cb, p_cb->hid_handle,
2525                               p_dev_info->attr_mask,
2526                               &p_dev_info->dscp_info.descriptor,
2527                               p_dev_info->sub_class,
2528                               p_dev_info->dscp_info.ssr_max_latency,
2529                               p_dev_info->dscp_info.ssr_min_tout,
2530                               p_dev_info->app_id);
2531 
2532     bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
2533 
2534     return p_cb->hid_handle;
2535 }
2536 
2537 /*******************************************************************************
2538 **
2539 ** Function         bta_hh_le_remove_dev_bg_conn
2540 **
2541 ** Description      Remove a LE HID device from back ground connection procedure.
2542 **
2543 ** Returns          void
2544 **
2545 *******************************************************************************/
bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB * p_dev_cb)2546 void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB *p_dev_cb)
2547 {
2548     if (p_dev_cb->in_bg_conn)
2549     {
2550         p_dev_cb->in_bg_conn = FALSE;
2551 
2552         BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, FALSE);
2553     }
2554 }
2555 
2556 /*******************************************************************************
2557 **
2558 ** Function         bta_hh_le_update_scpp
2559 **
2560 ** Description      action function to update the scan parameters on remote HID
2561 **                  device
2562 **
2563 ** Parameters:
2564 **
2565 *******************************************************************************/
bta_hh_le_update_scpp(tBTA_HH_DEV_CB * p_dev_cb,tBTA_HH_DATA * p_buf)2566 void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2567 {
2568     UINT8   value[4], *p = value;
2569     tBTA_HH_CBDATA      cback_data;
2570 
2571     if (!p_dev_cb->is_le_device ||
2572         p_dev_cb->mode != BTA_HH_PROTO_RPT_MODE ||
2573         p_dev_cb->scps_supported == FALSE) {
2574         APPL_TRACE_ERROR("Can not set ScPP scan paramter as boot host, or remote does not support ScPP ");
2575 
2576         cback_data.handle = p_dev_cb->hid_handle;
2577         cback_data.status = BTA_HH_ERR;
2578         (* bta_hh_cb.p_cback)(BTA_HH_UPDATE_SCPP_EVT, (tBTA_HH *)&cback_data);
2579 
2580         return;
2581     }
2582 
2583     p_dev_cb->w4_evt = BTA_HH_UPDATE_SCPP_EVT;
2584 
2585     UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_int);
2586     UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_win);
2587 
2588     gatt_queue_write_op(GATT_WRITE_CHAR, p_dev_cb->conn_id, p_dev_cb->scan_refresh_char_handle, 2,
2589                         value, BTA_GATTC_TYPE_WRITE_NO_RSP);
2590 }
2591 
2592 /*******************************************************************************
2593 **
2594 ** Function         bta_hh_gattc_callback
2595 **
2596 ** Description      This is GATT client callback function used in BTA HH.
2597 **
2598 ** Parameters:
2599 **
2600 *******************************************************************************/
bta_hh_gattc_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)2601 static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
2602 {
2603     tBTA_HH_DEV_CB *p_dev_cb;
2604     UINT16          evt;
2605 #if BTA_HH_DEBUG
2606     APPL_TRACE_DEBUG("bta_hh_gattc_callback event = %d", event);
2607 #endif
2608     if (p_data == NULL)
2609         return;
2610 
2611     switch (event)
2612     {
2613         case BTA_GATTC_REG_EVT: /* 0 */
2614             bta_hh_le_register_cmpl(&p_data->reg_oper);
2615             break;
2616 
2617         case BTA_GATTC_DEREG_EVT: /* 1 */
2618             bta_hh_cleanup_disable(p_data->reg_oper.status);
2619             break;
2620 
2621         case BTA_GATTC_OPEN_EVT: /* 2 */
2622             p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda);
2623             if (p_dev_cb) {
2624                 bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
2625             }
2626             break;
2627 
2628         case BTA_GATTC_READ_CHAR_EVT: /* 3 */
2629         case BTA_GATTC_READ_DESCR_EVT: /* 8 */
2630             mark_as_not_executing(p_data->read.conn_id);
2631             gatt_execute_next_op(p_data->read.conn_id);
2632             p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->read.conn_id);
2633             if (event == BTA_GATTC_READ_CHAR_EVT)
2634                 evt = BTA_HH_GATT_READ_CHAR_CMPL_EVT;
2635             else
2636                 evt = BTA_HH_GATT_READ_DESCR_CMPL_EVT;
2637 
2638             bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->read);
2639             break;
2640 
2641         case BTA_GATTC_WRITE_DESCR_EVT: /* 9 */
2642         case BTA_GATTC_WRITE_CHAR_EVT: /* 4 */
2643             mark_as_not_executing(p_data->write.conn_id);
2644             gatt_execute_next_op(p_data->write.conn_id);
2645             p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->write.conn_id);
2646             if (event == BTA_GATTC_WRITE_CHAR_EVT)
2647                 evt = BTA_HH_GATT_WRITE_CHAR_CMPL_EVT;
2648             else
2649                 evt = BTA_HH_GATT_WRITE_DESCR_CMPL_EVT;
2650 
2651             bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->write);
2652             break;
2653 
2654         case BTA_GATTC_CLOSE_EVT: /* 5 */
2655             bta_hh_le_close(&p_data->close);
2656             break;
2657 
2658         case BTA_GATTC_SEARCH_CMPL_EVT: /* 6 */
2659             bta_hh_le_srvc_search_cmpl(&p_data->search_cmpl);
2660             break;
2661 
2662         case BTA_GATTC_NOTIF_EVT: /* 10 */
2663             bta_hh_le_input_rpt_notify(&p_data->notify);
2664             break;
2665 
2666         case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */
2667             p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda);
2668             if (p_dev_cb) {
2669                 bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_ENC_CMPL_EVT,
2670                               (tBTA_HH_DATA *)&p_data->enc_cmpl);
2671             }
2672             break;
2673 
2674         default:
2675             break;
2676     }
2677 }
2678 
2679 /*******************************************************************************
2680 **
2681 ** Function         bta_hh_le_hid_read_rpt_clt_cfg
2682 **
2683 ** Description      a test command to read report descriptor client configuration
2684 **
2685 ** Returns          void
2686 **
2687 *******************************************************************************/
bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr,UINT8 rpt_id)2688 void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id)
2689 {
2690     tBTA_HH_DEV_CB *p_cb = NULL;
2691     tBTA_HH_LE_RPT *p_rpt ;
2692     UINT8           index = BTA_HH_IDX_INVALID;
2693 
2694     index = bta_hh_find_cb(bd_addr);
2695     if ((index = bta_hh_find_cb(bd_addr))== BTA_HH_IDX_INVALID)
2696     {
2697         APPL_TRACE_ERROR("unknown device");
2698         return;
2699     }
2700 
2701     p_cb = &bta_hh_cb.kdev[index];
2702 
2703     p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode, BTA_HH_RPTT_INPUT, rpt_id);
2704 
2705     if (p_rpt == NULL)
2706     {
2707         APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report");
2708         return;
2709     }
2710 
2711     bta_hh_le_read_char_dscrpt(p_cb, p_rpt->char_inst_id, GATT_UUID_CHAR_CLIENT_CONFIG);
2712     return;
2713 }
2714 
2715 /*******************************************************************************
2716 **
2717 ** Function         bta_hh_le_register_scpp_notif
2718 **
2719 ** Description      register scan parameter refresh notitication complete
2720 **
2721 **
2722 ** Parameters:
2723 **
2724 *******************************************************************************/
bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATT_STATUS status)2725 static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
2726 {
2727     UINT8               sec_flag=0;
2728 
2729     /* if write scan parameter sucessful */
2730     /* if bonded and notification is not enabled, configure the client configuration */
2731     if (status == BTA_GATT_OK &&
2732         (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_SPT) != 0 &&
2733         (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_ENB) == 0)
2734     {
2735         BTM_GetSecurityFlagsByTransport(p_dev_cb->addr, &sec_flag, BT_TRANSPORT_LE);
2736         if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN))
2737         {
2738             if (bta_hh_le_write_char_clt_cfg (p_dev_cb, p_dev_cb->scan_refresh_char_handle,
2739                                               BTA_GATT_CLT_CONFIG_NOTIFICATION))
2740             {
2741                 BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, p_dev_cb->addr,
2742                                                    p_dev_cb->scan_refresh_char_handle);
2743                 return;
2744             }
2745         }
2746     }
2747     bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, status);
2748 }
2749 
2750 /*******************************************************************************
2751 **
2752 ** Function         bta_hh_le_register_scpp_notif_cmpl
2753 **
2754 ** Description      action function to register scan parameter refresh notitication
2755 **
2756 ** Parameters:
2757 **
2758 *******************************************************************************/
bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB * p_dev_cb,tBTA_GATT_STATUS status)2759 static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
2760 {
2761     tBTA_HH_CBDATA      cback_data ;
2762     UINT16              cb_evt = p_dev_cb->w4_evt;
2763 
2764     if (status == BTA_GATT_OK)
2765         p_dev_cb->scps_notify = (BTA_HH_LE_SCPS_NOTIFY_ENB | BTA_HH_LE_SCPS_NOTIFY_SPT);
2766 
2767     cback_data.handle = p_dev_cb->hid_handle;
2768     cback_data.status = (status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
2769     p_dev_cb->w4_evt = 0;
2770     (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
2771 }
2772 
2773 /*******************************************************************************
2774 **
2775 ** Function         bta_hh_process_cache_rpt
2776 **
2777 ** Description      Process the cached reports
2778 **
2779 ** Parameters:
2780 **
2781 *******************************************************************************/
2782 //TODO(jpawlowski): uncomment when fixed
2783 // static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb,
2784 //                                       tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache,
2785 //                                       UINT8 num_rpt)
2786 // {
2787 //     UINT8                       i = 0;
2788 //     tBTA_HH_LE_RPT              *p_rpt;
2789 
2790 //     if (num_rpt != 0)  /* no cache is found */
2791 //     {
2792 //         p_cb->hid_srvc.in_use = TRUE;
2793 
2794 //         /* set the descriptor info */
2795 //         p_cb->hid_srvc.descriptor.dl_len =
2796 //                 p_cb->dscp_info.descriptor.dl_len;
2797 //         p_cb->hid_srvc.descriptor.dsc_list =
2798 //                     p_cb->dscp_info.descriptor.dsc_list;
2799 
2800 //         for (; i <num_rpt; i ++, p_rpt_cache ++)
2801 //         {
2802 //             if ((p_rpt = bta_hh_le_find_alloc_report_entry (p_cb,
2803 //                                                p_rpt_cache->srvc_inst_id,
2804 //                                                p_rpt_cache->rpt_uuid,
2805 //                                                p_rpt_cache->char_inst_id,
2806 //                                                p_rpt_cache->prop))  == NULL)
2807 //             {
2808 //                 APPL_TRACE_ERROR("bta_hh_process_cache_rpt: allocation report entry failure");
2809 //                 break;
2810 //             }
2811 //             else
2812 //             {
2813 //                 p_rpt->rpt_type =  p_rpt_cache->rpt_type;
2814 //                 p_rpt->rpt_id   =  p_rpt_cache->rpt_id;
2815 
2816 //                 if(p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
2817 //                     p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT ||
2818 //                     (p_rpt->uuid == GATT_UUID_HID_REPORT && p_rpt->rpt_type == BTA_HH_RPTT_INPUT))
2819 //                 {
2820 //                     p_rpt->client_cfg_value = BTA_GATT_CLT_CONFIG_NOTIFICATION;
2821 //                 }
2822 //             }
2823 //         }
2824 //     }
2825 // }
2826 
2827 #endif
2828 
2829 
2830 
2831 
2832