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