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