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