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