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