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 p_dev_cb->reason = result; 1269 1270 bta_hh_sm_execute(p_dev_cb, BTA_HH_ENC_CMPL_EVT, NULL); 1271 } 1272 1273 /******************************************************************************* 1274 ** 1275 ** Function bta_hh_security_cmpl 1276 ** 1277 ** Description Security check completed, start the service discovery 1278 ** if no cache available, otherwise report connection open completed 1279 ** 1280 ** Parameters: 1281 ** 1282 *******************************************************************************/ 1283 void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf) 1284 { 1285 tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache; 1286 UINT8 num_rpt = 0; 1287 UNUSED(p_buf); 1288 1289 if (p_cb->status == BTA_HH_OK) 1290 { 1291 APPL_TRACE_DEBUG("bta_hh_security_cmpl OK"); 1292 if (!p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use) 1293 { 1294 APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load"); 1295 /* start loading the cache if not in stack */ 1296 if ((p_rpt_cache = bta_hh_le_co_cache_load(p_cb->addr, &num_rpt, p_cb->app_id)) != NULL) 1297 { 1298 bta_hh_process_cache_rpt(p_cb, p_rpt_cache, num_rpt); 1299 } 1300 } 1301 /* discovery has been done for HID service */ 1302 if (p_cb->app_id != 0 && p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use) 1303 { 1304 /* configure protocol mode */ 1305 if (bta_hh_le_set_protocol_mode(p_cb, p_cb->mode) == FALSE) 1306 { 1307 APPL_TRACE_ERROR("bta_hh_security_cmpl"); 1308 bta_hh_le_open_cmpl(p_cb); 1309 } 1310 } 1311 /* start primary service discovery for HID service */ 1312 else 1313 { 1314 bta_hh_le_pri_service_discovery(p_cb); 1315 } 1316 } 1317 else 1318 { 1319 APPL_TRACE_ERROR("%s() - encryption failed; status=0x%04x, reason=0x%04x", 1320 __FUNCTION__, p_cb->status, p_cb->reason); 1321 if (!(p_cb->status == BTA_HH_ERR_SEC && p_cb->reason == BTM_ERR_PROCESSING)) 1322 bta_hh_le_api_disc_act(p_cb); 1323 } 1324 } 1325 1326 /******************************************************************************* 1327 ** 1328 ** Function bta_hh_le_notify_enc_cmpl 1329 ** 1330 ** Description process GATT encryption complete event 1331 ** 1332 ** Returns 1333 ** 1334 *******************************************************************************/ 1335 void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf) 1336 { 1337 if (p_cb == NULL || p_cb->security_pending == FALSE || 1338 p_buf == NULL || p_buf->le_enc_cmpl.client_if != bta_hh_cb.gatt_if) 1339 { 1340 return; 1341 } 1342 1343 p_cb->security_pending = FALSE; 1344 bta_hh_start_security(p_cb, NULL); 1345 } 1346 1347 /******************************************************************************* 1348 ** 1349 ** Function bta_hh_clear_service_cache 1350 ** 1351 ** Description clear the service cache 1352 ** 1353 ** Parameters: 1354 ** 1355 *******************************************************************************/ 1356 void bta_hh_clear_service_cache(tBTA_HH_DEV_CB *p_cb) 1357 { 1358 UINT8 i; 1359 tBTA_HH_LE_HID_SRVC *p_hid_srvc = &p_cb->hid_srvc[0]; 1360 1361 p_cb->app_id = 0; 1362 p_cb->total_srvc = 0; 1363 p_cb->dscp_info.descriptor.dsc_list = NULL; 1364 1365 for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++, p_hid_srvc ++) 1366 { 1367 utl_freebuf((void **)&p_hid_srvc->rpt_map); 1368 memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC)); 1369 } 1370 } 1371 1372 /******************************************************************************* 1373 ** 1374 ** Function bta_hh_start_security 1375 ** 1376 ** Description start the security check of the established connection 1377 ** 1378 ** Parameters: 1379 ** 1380 *******************************************************************************/ 1381 void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf) 1382 { 1383 UINT8 sec_flag=0; 1384 tBTM_SEC_DEV_REC *p_dev_rec; 1385 UNUSED(p_buf); 1386 1387 p_dev_rec = btm_find_dev(p_cb->addr); 1388 if (p_dev_rec) 1389 { 1390 if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING || 1391 p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING) 1392 { 1393 /* if security collision happened, wait for encryption done */ 1394 p_cb->security_pending = TRUE; 1395 return; 1396 } 1397 } 1398 1399 /* verify bond */ 1400 BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE); 1401 1402 /* if link has been encrypted */ 1403 if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) 1404 { 1405 bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL); 1406 } 1407 /* if bonded and link not encrypted */ 1408 else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) 1409 { 1410 sec_flag = BTM_BLE_SEC_ENCRYPT; 1411 p_cb->status = BTA_HH_ERR_AUTH_FAILED; 1412 BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, &sec_flag); 1413 } 1414 /* unbonded device, report security error here */ 1415 else if (p_cb->sec_mask != BTA_SEC_NONE) 1416 { 1417 sec_flag = BTM_BLE_SEC_ENCRYPT_NO_MITM; 1418 p_cb->status = BTA_HH_ERR_AUTH_FAILED; 1419 bta_hh_clear_service_cache(p_cb); 1420 BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_hh_le_encrypt_cback, &sec_flag); 1421 } 1422 /* otherwise let it go through */ 1423 else 1424 { 1425 bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL); 1426 } 1427 1428 1429 } 1430 1431 /******************************************************************************* 1432 ** 1433 ** Function bta_hh_gatt_open 1434 ** 1435 ** Description process GATT open event. 1436 ** 1437 ** Parameters: 1438 ** 1439 *******************************************************************************/ 1440 void bta_hh_gatt_open(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf) 1441 { 1442 tBTA_GATTC_OPEN *p_data = &p_buf->le_open; 1443 UINT8 *p2; 1444 tHID_STATUS status = BTA_HH_ERR; 1445 1446 /* if received invalid callback data , ignore it */ 1447 if (p_cb == NULL || p_data == NULL) 1448 return; 1449 1450 p2 = p_data->remote_bda; 1451 1452 APPL_TRACE_DEBUG("bta_hh_gatt_open BTA_GATTC_OPEN_EVT bda= [%08x%04x] status =%d", 1453 ((p2[0])<<24)+((p2[1])<<16)+((p2[2])<<8)+(p2[3]), 1454 ((p2[4])<<8)+ p2[5],p_data->status); 1455 1456 if (p_data->status == BTA_GATT_OK) 1457 { 1458 p_cb->is_le_device = TRUE; 1459 p_cb->in_use = TRUE; 1460 p_cb->conn_id = p_data->conn_id; 1461 p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index); 1462 1463 bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index; 1464 1465 #if BTA_HH_DEBUG == TRUE 1466 APPL_TRACE_DEBUG("hid_handle = %2x conn_id = %04x cb_index = %d", p_cb->hid_handle, p_cb->conn_id, p_cb->index); 1467 #endif 1468 1469 bta_hh_sm_execute(p_cb, BTA_HH_START_ENC_EVT, NULL); 1470 1471 } 1472 else /* open failure */ 1473 { 1474 bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status); 1475 } 1476 1477 } 1478 1479 /******************************************************************************* 1480 ** 1481 ** Function bta_hh_le_close 1482 ** 1483 ** Description This function process the GATT close event and post it as a 1484 ** BTA HH internal event 1485 ** 1486 ** Parameters: 1487 ** 1488 *******************************************************************************/ 1489 void bta_hh_le_close(tBTA_GATTC_CLOSE * p_data) 1490 { 1491 tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->remote_bda); 1492 tBTA_HH_LE_CLOSE *p_buf = NULL; 1493 UINT16 sm_event = BTA_HH_GATT_CLOSE_EVT; 1494 1495 if (p_dev_cb != NULL && 1496 (p_buf = (tBTA_HH_LE_CLOSE *)GKI_getbuf(sizeof(tBTA_HH_LE_CLOSE))) != NULL) 1497 { 1498 p_buf->hdr.event = sm_event; 1499 p_buf->hdr.layer_specific = (UINT16)p_dev_cb->hid_handle; 1500 p_buf->conn_id = p_data->conn_id; 1501 p_buf->reason = p_data->reason; 1502 1503 p_dev_cb->conn_id = BTA_GATT_INVALID_CONN_ID; 1504 p_dev_cb->security_pending = FALSE; 1505 bta_sys_sendmsg(p_buf); 1506 } 1507 } 1508 1509 /******************************************************************************* 1510 ** 1511 ** Function bta_hh_le_search_result 1512 ** 1513 ** Description This function process the GATT service search result. 1514 ** 1515 ** Parameters: 1516 ** 1517 *******************************************************************************/ 1518 void bta_hh_le_search_result(tBTA_GATTC_SRVC_RES *p_srvc_result) 1519 { 1520 tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_srvc_result->conn_id); 1521 1522 if (p_dev_cb != NULL) 1523 { 1524 switch (p_srvc_result->service_uuid.id.uuid.uu.uuid16) 1525 { 1526 case UUID_SERVCLASS_LE_HID: 1527 if (p_srvc_result->service_uuid.is_primary) 1528 { 1529 /* found HID primamry service */ 1530 /* TODO: proceed to find battery and device info */ 1531 if (bta_hh_le_add_hid_srvc_entry(p_dev_cb, p_dev_cb->total_srvc)) 1532 p_dev_cb->total_srvc ++; 1533 APPL_TRACE_DEBUG("num of hid service: %d", p_dev_cb->total_srvc); 1534 } 1535 break; 1536 1537 case UUID_SERVCLASS_SCAN_PARAM : /* scan parameter service */ 1538 bta_hh_le_search_scps_chars(p_dev_cb); 1539 break; 1540 } 1541 1542 } 1543 1544 } 1545 1546 1547 /******************************************************************************* 1548 ** 1549 ** Function bta_hh_le_gatt_disc_cmpl 1550 ** 1551 ** Description Check to see if the remote device is a LE only device 1552 ** 1553 ** Parameters: 1554 ** 1555 *******************************************************************************/ 1556 void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status) 1557 { 1558 APPL_TRACE_DEBUG("bta_hh_le_gatt_disc_cmpl "); 1559 1560 /* if open sucessful or protocol mode not desired, keep the connection open but inform app */ 1561 if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO) 1562 { 1563 /* assign a special APP ID temp, since device type unknown */ 1564 p_cb->app_id = BTA_HH_APP_ID_LE; 1565 1566 /* set report notification configuration */ 1567 p_cb->clt_cfg_idx = 0; 1568 bta_hh_le_write_rpt_clt_cfg(p_cb, BTA_HH_LE_SRVC_DEF); 1569 } 1570 else /* error, close the GATT connection */ 1571 { 1572 /* close GATT connection if it's on */ 1573 bta_hh_le_api_disc_act(p_cb); 1574 } 1575 } 1576 1577 /******************************************************************************* 1578 ** 1579 ** Function bta_hh_le_srvc_expl_srvc 1580 ** 1581 ** Description This function discover the next avaible HID service. 1582 ** 1583 ** Parameters: 1584 ** 1585 *******************************************************************************/ 1586 void bta_hh_le_srvc_expl_srvc(tBTA_HH_DEV_CB *p_dev_cb) 1587 { 1588 #if BTA_HH_DEBUG == TRUE 1589 APPL_TRACE_DEBUG("bta_hh_le_srvc_expl_srvc cur_srvc_index = %d in_use = %d", 1590 p_dev_cb->cur_srvc_index, 1591 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].in_use); 1592 #endif 1593 1594 if (p_dev_cb->cur_srvc_index < BTA_HH_LE_HID_SRVC_MAX && 1595 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].in_use) 1596 { 1597 if (!p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc) 1598 /* explore included service first */ 1599 bta_hh_le_search_hid_included(p_dev_cb); 1600 else 1601 { 1602 /* explore characterisc */ 1603 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx = 0; 1604 bta_hh_le_search_hid_chars(p_dev_cb); 1605 } 1606 } 1607 else /* all service discvery finished */ 1608 { 1609 bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status); 1610 } 1611 } 1612 1613 /******************************************************************************* 1614 ** 1615 ** Function bta_hh_le_srvc_search_cmpl 1616 ** 1617 ** Description This function process the GATT service search complete. 1618 ** 1619 ** Parameters: 1620 ** 1621 *******************************************************************************/ 1622 void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL *p_data) 1623 { 1624 tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id); 1625 1626 /* service search exception or no HID service is supported on remote */ 1627 if (p_dev_cb == NULL) 1628 return; 1629 1630 if(p_data->status != BTA_GATT_OK || p_dev_cb->total_srvc == 0) 1631 { 1632 p_dev_cb->status = BTA_HH_ERR_SDP; 1633 /* close the connection and report service discovery complete with error */ 1634 bta_hh_le_api_disc_act(p_dev_cb); 1635 } 1636 /* GATT service discovery sucessfully finished */ 1637 else 1638 { 1639 if (p_dev_cb->disc_active & BTA_HH_LE_DISC_SCPS) 1640 { 1641 p_dev_cb->disc_active &= ~BTA_HH_LE_DISC_SCPS; 1642 bta_hh_le_open_cmpl(p_dev_cb); 1643 } 1644 else /* discover HID service */ 1645 { 1646 p_dev_cb->cur_srvc_index = 0; 1647 bta_hh_le_srvc_expl_srvc(p_dev_cb); 1648 } 1649 } 1650 } 1651 1652 /******************************************************************************* 1653 ** 1654 ** Function bta_hh_le_search_hid_included 1655 ** 1656 ** Description This function search the included service within the HID service. 1657 ** 1658 ** Parameters: 1659 ** 1660 *******************************************************************************/ 1661 static void bta_hh_le_search_hid_included(tBTA_HH_DEV_CB *p_dev_cb) 1662 { 1663 tBT_UUID srvc_cond, char_cond; 1664 tBTA_GATTC_INCL_SVC_ID inc_srvc_result; 1665 tBTA_GATT_SRVC_ID srvc_id; 1666 tBTA_GATTC_CHAR_ID char_result; 1667 tBTA_GATT_CHAR_PROP prop = 0; 1668 1669 bta_hh_le_fill_16bits_srvc_id(TRUE, p_dev_cb->cur_srvc_index, UUID_SERVCLASS_LE_HID, &srvc_id); 1670 1671 srvc_cond.len = LEN_UUID_16; 1672 srvc_cond.uu.uuid16 = UUID_SERVCLASS_BATTERY; 1673 1674 if (BTA_GATTC_GetFirstIncludedService(p_dev_cb->conn_id, 1675 &srvc_id, 1676 &srvc_cond, 1677 &inc_srvc_result) == BTA_GATT_OK) 1678 { 1679 /* read include service UUID */ 1680 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].incl_srvc_inst = inc_srvc_result.incl_svc_id.id.inst_id; 1681 1682 char_cond.len = LEN_UUID_16; 1683 char_cond.uu.uuid16 = GATT_UUID_BATTERY_LEVEL; 1684 1685 /* find the battery characteristic */ 1686 if (BTA_GATTC_GetFirstChar( p_dev_cb->conn_id, 1687 &inc_srvc_result.incl_svc_id, 1688 &char_cond, 1689 &char_result, 1690 &prop) == BTA_GATT_OK) 1691 { 1692 1693 if (bta_hh_le_find_alloc_report_entry(p_dev_cb, 1694 char_result.srvc_id.id.inst_id, 1695 GATT_UUID_BATTERY_LEVEL, 1696 char_result.char_id.inst_id, 1697 prop) == NULL) 1698 { 1699 APPL_TRACE_ERROR("Add battery report entry failed !!!") 1700 } 1701 1702 /* read the battery characteristic */ 1703 BTA_GATTC_ReadCharacteristic(p_dev_cb->conn_id, 1704 &char_result, 1705 BTA_GATT_AUTH_REQ_NONE); 1706 1707 return; 1708 1709 } 1710 else 1711 { 1712 APPL_TRACE_ERROR("Remote device does not have battery level"); 1713 } 1714 } 1715 1716 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE; 1717 1718 bta_hh_le_srvc_expl_srvc(p_dev_cb); 1719 1720 } 1721 1722 /******************************************************************************* 1723 ** 1724 ** Function bta_hh_read_battery_level_cmpl 1725 ** 1726 ** Description This function process the battery level read 1727 ** 1728 ** Parameters: 1729 ** 1730 *******************************************************************************/ 1731 void bta_hh_read_battery_level_cmpl(UINT8 status, tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data) 1732 { 1733 UNUSED(status); 1734 UNUSED(p_data); 1735 1736 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE; 1737 bta_hh_le_srvc_expl_srvc(p_dev_cb); 1738 } 1739 /******************************************************************************* 1740 ** 1741 ** Function bta_hh_le_search_hid_chars 1742 ** 1743 ** Description This function discover all characteristics a service and 1744 ** all descriptors available. 1745 ** 1746 ** Parameters: 1747 ** 1748 *******************************************************************************/ 1749 static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb) 1750 { 1751 tBT_UUID char_cond; 1752 tBTA_GATTC_CHAR_ID char_result; 1753 tBTA_GATT_CHAR_PROP prop; 1754 BOOLEAN next = TRUE; 1755 UINT16 char_uuid = 0; 1756 tBTA_GATT_SRVC_ID srvc_id; 1757 1758 if (p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx == BTA_HH_LE_DISC_CHAR_NUM || 1759 (p_dev_cb->status != BTA_HH_OK && p_dev_cb->status != BTA_HH_ERR_PROTO)) 1760 { 1761 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx = 0; 1762 /* explore next service */ 1763 p_dev_cb->cur_srvc_index ++; 1764 bta_hh_le_srvc_expl_srvc(p_dev_cb); 1765 return; 1766 } 1767 1768 p_dev_cb->hid_srvc[ p_dev_cb->cur_srvc_index].cur_expl_char_idx ++; 1769 char_uuid = bta_hh_le_disc_char_uuid[p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx - 1]; 1770 1771 char_cond.len = LEN_UUID_16; 1772 char_cond.uu.uuid16 = char_uuid; 1773 1774 bta_hh_le_fill_16bits_srvc_id(TRUE, p_dev_cb->cur_srvc_index, UUID_SERVCLASS_LE_HID, &srvc_id); 1775 1776 #if BTA_HH_DEBUG == TRUE 1777 APPL_TRACE_DEBUG("bta_hh_le_search_hid_chars: looking for %s(0x%04x)", 1778 bta_hh_uuid_to_str(char_uuid), char_uuid); 1779 #endif 1780 1781 if (BTA_GATTC_GetFirstChar( p_dev_cb->conn_id, 1782 &srvc_id, 1783 &char_cond, 1784 &char_result, 1785 &prop) == BTA_GATT_OK) 1786 { 1787 switch (char_uuid) 1788 { 1789 case GATT_UUID_HID_CONTROL_POINT: 1790 p_dev_cb->hid_srvc[char_result.srvc_id.id.inst_id].option_char |= BTA_HH_LE_CP_BIT; 1791 next = TRUE; 1792 break; 1793 case GATT_UUID_HID_INFORMATION: 1794 case GATT_UUID_HID_REPORT_MAP: 1795 /* read the char value */ 1796 BTA_GATTC_ReadCharacteristic(p_dev_cb->conn_id, 1797 &char_result, 1798 BTA_GATT_AUTH_REQ_NONE); 1799 next = FALSE; 1800 break; 1801 1802 case GATT_UUID_HID_PROTO_MODE: 1803 p_dev_cb->hid_srvc[char_result.srvc_id.id.inst_id].option_char |= BTA_HH_LE_PROTO_MODE_BIT; 1804 next = !bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode); 1805 break; 1806 1807 case GATT_UUID_HID_REPORT: 1808 bta_hh_le_expl_rpt(p_dev_cb, &char_result, &char_cond, prop); 1809 next = FALSE; 1810 break; 1811 1812 /* found boot mode report types */ 1813 case GATT_UUID_HID_BT_KB_OUTPUT: 1814 case GATT_UUID_HID_BT_MOUSE_INPUT: 1815 case GATT_UUID_HID_BT_KB_INPUT: 1816 bta_hh_le_expl_boot_rpt(p_dev_cb, char_uuid, prop); 1817 break; 1818 } 1819 } 1820 else 1821 { 1822 if (char_uuid == GATT_UUID_HID_PROTO_MODE) 1823 next = !bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode); 1824 1825 } 1826 1827 if (next == TRUE) 1828 { 1829 bta_hh_le_search_hid_chars(p_dev_cb); 1830 } 1831 } 1832 1833 /******************************************************************************* 1834 ** 1835 ** Function bta_hh_le_save_rpt_map 1836 ** 1837 ** Description save the report map into the control block. 1838 ** 1839 ** Parameters: 1840 ** 1841 *******************************************************************************/ 1842 void bta_hh_le_save_rpt_map(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data) 1843 { 1844 UINT8 *pp ; 1845 tBTA_HH_LE_HID_SRVC *p_srvc = &p_dev_cb->hid_srvc[p_data->srvc_id.id.inst_id]; 1846 1847 pp = p_data->p_value->unformat.p_value; 1848 1849 /* save report descriptor */ 1850 if (p_srvc->rpt_map != NULL) 1851 GKI_freebuf((void*)p_srvc->rpt_map); 1852 1853 if (p_data->p_value->unformat.len > 0) 1854 p_srvc->rpt_map = (UINT8 *)GKI_getbuf(p_data->p_value->unformat.len); 1855 1856 if (p_srvc->rpt_map != NULL) 1857 { 1858 STREAM_TO_ARRAY(p_srvc->rpt_map, pp, p_data->p_value->unformat.len); 1859 p_srvc->descriptor.dl_len = p_data->p_value->unformat.len; 1860 p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc[p_data->srvc_id.id.inst_id].rpt_map; 1861 } 1862 1863 if (bta_hh_le_read_char_dscrpt(p_dev_cb, 1864 UUID_SERVCLASS_LE_HID, 1865 p_data->srvc_id.id.inst_id, 1866 GATT_UUID_HID_REPORT_MAP, 1867 p_data->char_id.inst_id, 1868 GATT_UUID_EXT_RPT_REF_DESCR) != BTA_HH_OK) 1869 { 1870 bta_hh_le_search_hid_chars(p_dev_cb); 1871 } 1872 } 1873 1874 /******************************************************************************* 1875 ** 1876 ** Function bta_hh_le_proc_get_rpt_cmpl 1877 ** 1878 ** Description Process the Read report complete, send GET_REPORT_EVT to application 1879 ** with the report data. 1880 ** 1881 ** Parameters: 1882 ** 1883 *******************************************************************************/ 1884 void bta_hh_le_proc_get_rpt_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data) 1885 { 1886 BT_HDR *p_buf = NULL; 1887 tBTA_HH_LE_RPT *p_rpt; 1888 tBTA_HH_HSDATA hs_data; 1889 UINT8 *pp ; 1890 1891 if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT) 1892 { 1893 APPL_TRACE_ERROR("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt); 1894 return; 1895 } 1896 1897 hs_data.status = BTA_HH_ERR; 1898 hs_data.handle = p_dev_cb->hid_handle; 1899 1900 if (p_data->status == BTA_GATT_OK) 1901 { 1902 p_rpt = bta_hh_le_find_report_entry(p_dev_cb, 1903 p_data->srvc_id.id.inst_id,//BTA_HH_LE_SRVC_DEF, 1904 p_data->char_id.uuid.uu.uuid16, 1905 p_data->char_id.inst_id); 1906 1907 if (p_rpt != NULL && 1908 p_data->p_value != NULL && 1909 (p_buf = (BT_HDR *)GKI_getbuf((UINT16)(sizeof(BT_HDR) +p_data->p_value->unformat.len + 1))) != NULL) 1910 { 1911 /* pack data send to app */ 1912 hs_data.status = BTA_HH_OK; 1913 p_buf->len = p_data->p_value->unformat.len + 1; 1914 p_buf->layer_specific = 0; 1915 p_buf->offset = 0; 1916 1917 /* attach report ID as the first byte of the report before sending it to USB HID driver */ 1918 pp = (UINT8*)(p_buf + 1); 1919 UINT8_TO_STREAM(pp, p_rpt->rpt_id); 1920 memcpy(pp, p_data->p_value->unformat.p_value, p_data->p_value->unformat.len); 1921 1922 hs_data.rsp_data.p_rpt_data =p_buf; 1923 } 1924 } 1925 1926 p_dev_cb->w4_evt = 0; 1927 (* bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH *)&hs_data); 1928 1929 utl_freebuf((void **)&p_buf); 1930 } 1931 1932 /******************************************************************************* 1933 ** 1934 ** Function bta_hh_le_proc_read_proto_mode 1935 ** 1936 ** Description Process the Read protocol mode, send GET_PROTO_EVT to application 1937 ** with the protocol mode. 1938 ** 1939 *******************************************************************************/ 1940 void bta_hh_le_proc_read_proto_mode(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data) 1941 { 1942 tBTA_HH_HSDATA hs_data; 1943 1944 hs_data.status = BTA_HH_ERR; 1945 hs_data.handle = p_dev_cb->hid_handle; 1946 hs_data.rsp_data.proto_mode = p_dev_cb->mode; 1947 1948 if (p_data->status == BTA_GATT_OK && p_data->p_value) 1949 { 1950 hs_data.status = BTA_HH_OK; 1951 /* match up BTE/BTA report/boot mode def*/ 1952 hs_data.rsp_data.proto_mode = *(p_data->p_value->unformat.p_value); 1953 /* LE repot mode is the opposite value of BR/EDR report mode, flip it here */ 1954 if (hs_data.rsp_data.proto_mode == 0) 1955 hs_data.rsp_data.proto_mode = BTA_HH_PROTO_BOOT_MODE; 1956 else 1957 hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE; 1958 1959 p_dev_cb->mode = hs_data.rsp_data.proto_mode; 1960 } 1961 #if BTA_HH_DEBUG 1962 APPL_TRACE_DEBUG("LE GET_PROTOCOL Mode = [%s]", 1963 (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot"); 1964 #endif 1965 1966 p_dev_cb->w4_evt = 0; 1967 (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data); 1968 1969 } 1970 1971 /******************************************************************************* 1972 ** 1973 ** Function bta_hh_w4_le_read_char_cmpl 1974 ** 1975 ** Description process the GATT read complete in W4_CONN state. 1976 ** 1977 ** Parameters: 1978 ** 1979 *******************************************************************************/ 1980 void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) 1981 { 1982 tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf; 1983 UINT8 *pp ; 1984 1985 if (p_data->char_id.uuid.uu.uuid16 == GATT_UUID_BATTERY_LEVEL) 1986 { 1987 bta_hh_read_battery_level_cmpl(p_data->status, p_dev_cb, p_data); 1988 } 1989 else 1990 { 1991 if (p_data->status == BTA_GATT_OK && p_data->p_value) 1992 { 1993 pp = p_data->p_value->unformat.p_value; 1994 1995 switch (p_data->char_id.uuid.uu.uuid16) 1996 { 1997 /* save device information */ 1998 case GATT_UUID_HID_INFORMATION: 1999 STREAM_TO_UINT16(p_dev_cb->dscp_info.version, pp); 2000 STREAM_TO_UINT8(p_dev_cb->dscp_info.ctry_code, pp); 2001 STREAM_TO_UINT8(p_dev_cb->dscp_info.flag, pp); 2002 break; 2003 2004 case GATT_UUID_HID_REPORT_MAP: 2005 bta_hh_le_save_rpt_map(p_dev_cb, p_data); 2006 return; 2007 2008 default: 2009 #if BTA_HH_DEBUG == TRUE 2010 APPL_TRACE_ERROR("Unexpected read %s(0x%04x)", 2011 bta_hh_uuid_to_str(p_data->char_id.uuid.uu.uuid16), 2012 p_data->char_id.uuid.uu.uuid16); 2013 #endif 2014 break; 2015 } 2016 } 2017 else 2018 { 2019 #if BTA_HH_DEBUG == TRUE 2020 APPL_TRACE_ERROR("read uuid %s[0x%04x] error: %d", 2021 bta_hh_uuid_to_str(p_data->char_id.uuid.uu.uuid16), 2022 p_data->char_id.uuid.uu.uuid16, 2023 p_data->status); 2024 #else 2025 APPL_TRACE_ERROR("read uuid [0x%04x] error: %d", p_data->char_id.uuid.uu.uuid16, p_data->status); 2026 #endif 2027 } 2028 bta_hh_le_search_hid_chars(p_dev_cb); 2029 } 2030 2031 } 2032 2033 /******************************************************************************* 2034 ** 2035 ** Function bta_hh_le_read_char_cmpl 2036 ** 2037 ** Description a characteristic value is received. 2038 ** 2039 ** Parameters: 2040 ** 2041 *******************************************************************************/ 2042 void bta_hh_le_read_char_cmpl (tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) 2043 { 2044 tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf; 2045 2046 switch (p_data->char_id.uuid.uu.uuid16) 2047 { 2048 /* GET_REPORT */ 2049 case GATT_UUID_HID_REPORT: 2050 case GATT_UUID_HID_BT_KB_INPUT: 2051 case GATT_UUID_HID_BT_KB_OUTPUT: 2052 case GATT_UUID_HID_BT_MOUSE_INPUT: 2053 case GATT_UUID_BATTERY_LEVEL: /* read battery level */ 2054 bta_hh_le_proc_get_rpt_cmpl(p_dev_cb, p_data); 2055 break; 2056 2057 case GATT_UUID_HID_PROTO_MODE: 2058 bta_hh_le_proc_read_proto_mode(p_dev_cb, p_data); 2059 break; 2060 2061 default: 2062 APPL_TRACE_ERROR("Unexpected Read UUID: 0x%04x", p_data->char_id.uuid.uu.uuid16); 2063 break; 2064 } 2065 2066 } 2067 2068 /******************************************************************************* 2069 ** 2070 ** Function bta_hh_le_read_descr_cmpl 2071 ** 2072 ** Description read characteristic descriptor is completed in CONN st. 2073 ** 2074 ** Parameters: 2075 ** 2076 *******************************************************************************/ 2077 void bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) 2078 { 2079 tBTA_HH_LE_RPT *p_rpt; 2080 tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf; 2081 UINT8 *pp; 2082 2083 /* if a report client configuration */ 2084 if (p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG) 2085 { 2086 if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb, 2087 BTA_HH_LE_SRVC_DEF, 2088 p_data->char_id.uuid.uu.uuid16, 2089 p_data->char_id.inst_id)) != NULL) 2090 { 2091 pp = p_data->p_value->unformat.p_value; 2092 STREAM_TO_UINT16(p_rpt->client_cfg_value, pp); 2093 2094 APPL_TRACE_DEBUG("Read Client Configuration: 0x%04x", p_rpt->client_cfg_value); 2095 } 2096 } 2097 } 2098 2099 /******************************************************************************* 2100 ** 2101 ** Function bta_hh_le_read_battery_level_descr_cmpl 2102 ** 2103 ** Description Process report reference descriptor for battery level is completed 2104 ** 2105 ** Parameters: 2106 ** 2107 *******************************************************************************/ 2108 void bta_hh_le_read_battery_level_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ * p_data) 2109 { 2110 tBTA_HH_LE_RPT *p_rpt; 2111 UINT16 descr_uuid = p_data->descr_type.uuid.uu.uuid16; 2112 2113 /* read report reference descriptor for battery level is completed */ 2114 if (descr_uuid == GATT_UUID_RPT_REF_DESCR) 2115 { 2116 if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb, 2117 p_data->srvc_id.id.inst_id, 2118 GATT_UUID_BATTERY_LEVEL, 2119 p_data->char_id.inst_id)) == NULL) 2120 { 2121 bta_hh_le_search_hid_chars(p_dev_cb); 2122 } 2123 else 2124 bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data); 2125 } 2126 } 2127 2128 /******************************************************************************* 2129 ** 2130 ** Function bta_hh_w4_le_read_descr_cmpl 2131 ** 2132 ** Description read characteristic descriptor is completed in W4_CONN st. 2133 ** 2134 ** Parameters: 2135 ** 2136 *******************************************************************************/ 2137 void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) 2138 { 2139 tBTA_HH_LE_RPT *p_rpt; 2140 tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf; 2141 UINT16 char_uuid16; 2142 2143 if (p_data == NULL) 2144 return; 2145 2146 char_uuid16 = p_data->char_id.uuid.uu.uuid16; 2147 2148 #if BTA_HH_DEBUG == TRUE 2149 APPL_TRACE_DEBUG("bta_hh_w4_le_read_descr_cmpl uuid: %s(0x%04x)", 2150 bta_hh_uuid_to_str(p_data->descr_type.uuid.uu.uuid16), 2151 p_data->descr_type.uuid.uu.uuid16); 2152 #endif 2153 switch (char_uuid16) 2154 { 2155 case GATT_UUID_HID_REPORT: 2156 if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb, 2157 p_data->srvc_id.id.inst_id, 2158 GATT_UUID_HID_REPORT, 2159 p_data->char_id.inst_id)) == NULL) 2160 { 2161 bta_hh_le_search_hid_chars(p_dev_cb); 2162 } 2163 else 2164 bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data); 2165 break; 2166 2167 case GATT_UUID_HID_REPORT_MAP: 2168 bta_hh_le_save_ext_rpt_ref(p_dev_cb, p_data); 2169 break; 2170 2171 case GATT_UUID_BATTERY_LEVEL: 2172 bta_hh_le_read_battery_level_descr_cmpl(p_dev_cb, p_data); 2173 break; 2174 2175 default: 2176 APPL_TRACE_ERROR("unknown descriptor read complete for uuid: 0x%04x", char_uuid16); 2177 break; 2178 } 2179 } 2180 2181 /******************************************************************************* 2182 ** 2183 ** Function bta_hh_w4_le_write_cmpl 2184 ** 2185 ** Description Write charactersitic complete event at W4_CONN st. 2186 ** 2187 ** Parameters: 2188 ** 2189 *******************************************************************************/ 2190 void bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) 2191 { 2192 tBTA_GATTC_WRITE *p_data = (tBTA_GATTC_WRITE *)p_buf; 2193 2194 if (p_data == NULL) 2195 return; 2196 2197 if (p_data->char_id.uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE) 2198 { 2199 p_dev_cb->status = (p_data->status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO; 2200 2201 if ((p_dev_cb->disc_active & BTA_HH_LE_DISC_HIDS) != 0) 2202 { 2203 bta_hh_le_search_hid_chars(p_dev_cb); 2204 } 2205 else 2206 { 2207 bta_hh_le_open_cmpl(p_dev_cb); 2208 } 2209 } 2210 } 2211 2212 /******************************************************************************* 2213 ** 2214 ** Function bta_hh_le_write_cmpl 2215 ** 2216 ** Description Write charactersitic complete event at CONN st. 2217 ** 2218 ** Parameters: 2219 ** 2220 *******************************************************************************/ 2221 void bta_hh_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) 2222 { 2223 tBTA_GATTC_WRITE *p_data = (tBTA_GATTC_WRITE *)p_buf; 2224 tBTA_HH_CBDATA cback_data ; 2225 UINT16 cb_evt = p_dev_cb->w4_evt; 2226 2227 if (p_data == NULL || cb_evt == 0) 2228 return; 2229 2230 #if BTA_HH_DEBUG 2231 APPL_TRACE_DEBUG("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt); 2232 #endif 2233 switch (p_data->char_id.uuid.uu.uuid16) 2234 { 2235 /* Set protocol finished */ 2236 case GATT_UUID_HID_PROTO_MODE: 2237 cback_data.handle = p_dev_cb->hid_handle; 2238 if (p_data->status == BTA_GATT_OK) 2239 { 2240 bta_hh_le_register_input_notif(p_dev_cb, p_data->srvc_id.id.inst_id, p_dev_cb->mode, FALSE); 2241 cback_data.status = BTA_HH_OK; 2242 } 2243 else 2244 cback_data.status = BTA_HH_ERR; 2245 p_dev_cb->w4_evt = 0; 2246 (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data); 2247 break; 2248 2249 /* Set Report finished */ 2250 case GATT_UUID_HID_REPORT: 2251 case GATT_UUID_HID_BT_KB_INPUT: 2252 case GATT_UUID_HID_BT_MOUSE_INPUT: 2253 case GATT_UUID_HID_BT_KB_OUTPUT: 2254 cback_data.handle = p_dev_cb->hid_handle; 2255 cback_data.status = (p_data->status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR; 2256 p_dev_cb->w4_evt = 0; 2257 (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data); 2258 break; 2259 2260 case GATT_UUID_SCAN_INT_WINDOW: 2261 bta_hh_le_register_scpp_notif(p_dev_cb, p_data->status); 2262 break; 2263 2264 2265 default: 2266 break; 2267 } 2268 2269 } 2270 2271 /******************************************************************************* 2272 ** 2273 ** Function bta_hh_le_write_char_descr_cmpl 2274 ** 2275 ** Description Write charactersitic descriptor complete event 2276 ** 2277 ** Parameters: 2278 ** 2279 *******************************************************************************/ 2280 void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) 2281 { 2282 tBTA_GATTC_WRITE *p_data = (tBTA_GATTC_WRITE *)p_buf; 2283 UINT8 srvc_inst_id, hid_inst_id; 2284 2285 /* only write client configuration possible */ 2286 if (p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG) 2287 { 2288 srvc_inst_id = p_data->srvc_id.id.inst_id; 2289 hid_inst_id = srvc_inst_id; 2290 switch (p_data->char_id.uuid.uu.uuid16) 2291 { 2292 case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */ 2293 hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_dev_cb, srvc_inst_id); 2294 /* fall through */ 2295 case GATT_UUID_HID_BT_KB_INPUT: 2296 case GATT_UUID_HID_BT_MOUSE_INPUT: 2297 case GATT_UUID_HID_REPORT: 2298 if (p_data->status == BTA_GATT_OK) 2299 p_dev_cb->hid_srvc[hid_inst_id].report[p_dev_cb->clt_cfg_idx].client_cfg_value = 2300 BTA_GATT_CLT_CONFIG_NOTIFICATION; 2301 p_dev_cb->clt_cfg_idx ++; 2302 bta_hh_le_write_rpt_clt_cfg(p_dev_cb, hid_inst_id); 2303 2304 break; 2305 2306 case GATT_UUID_SCAN_REFRESH: 2307 bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, p_data->status); 2308 break; 2309 2310 default: 2311 APPL_TRACE_ERROR("Unknown char ID clt cfg: 0x%04x", p_data->char_id.uuid.uu.uuid16); 2312 } 2313 } 2314 else 2315 { 2316 #if BTA_HH_DEBUG == TRUE 2317 APPL_TRACE_ERROR("Unexpected write to %s(0x%04x)", 2318 bta_hh_uuid_to_str(p_data->descr_type.uuid.uu.uuid16), 2319 p_data->descr_type.uuid.uu.uuid16); 2320 #else 2321 APPL_TRACE_ERROR("Unexpected write to (0x%04x)", p_data->descr_type.uuid.uu.uuid16); 2322 #endif 2323 } 2324 2325 } 2326 2327 /******************************************************************************* 2328 ** 2329 ** Function bta_hh_le_input_rpt_notify 2330 ** 2331 ** Description process the notificaton event, most likely for input report. 2332 ** 2333 ** Parameters: 2334 ** 2335 *******************************************************************************/ 2336 void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data) 2337 { 2338 tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id); 2339 UINT8 app_id; 2340 UINT8 *p_buf; 2341 tBTA_HH_LE_RPT *p_rpt; 2342 2343 if (p_dev_cb == NULL) 2344 { 2345 APPL_TRACE_ERROR("notification received from Unknown device"); 2346 return; 2347 } 2348 app_id= p_dev_cb->app_id; 2349 2350 p_rpt = bta_hh_le_find_report_entry(p_dev_cb, 2351 BTA_HH_LE_SRVC_DEF, 2352 p_data->char_id.char_id.uuid.uu.uuid16, 2353 p_data->char_id.char_id.inst_id); 2354 if (p_rpt == NULL) 2355 { 2356 APPL_TRACE_ERROR("notification received for Unknown Report"); 2357 return; 2358 } 2359 2360 if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_MOUSE_INPUT) 2361 app_id = BTA_HH_APP_ID_MI; 2362 else if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_KB_INPUT) 2363 app_id = BTA_HH_APP_ID_KB; 2364 2365 APPL_TRACE_DEBUG("Notification received on report ID: %d", p_rpt->rpt_id); 2366 2367 /* need to append report ID to the head of data */ 2368 if (p_rpt->rpt_id != 0) 2369 { 2370 if ((p_buf = (UINT8 *)GKI_getbuf((UINT16)(p_data->len + 1))) == NULL) 2371 { 2372 APPL_TRACE_ERROR("No resources to send report data"); 2373 return; 2374 } 2375 2376 p_buf[0] = p_rpt->rpt_id; 2377 memcpy(&p_buf[1], p_data->value, p_data->len); 2378 ++p_data->len; 2379 } else { 2380 p_buf = p_data->value; 2381 } 2382 2383 bta_hh_co_data((UINT8)p_dev_cb->hid_handle, 2384 p_buf, 2385 p_data->len, 2386 p_dev_cb->mode, 2387 0 , /* no sub class*/ 2388 p_dev_cb->dscp_info.ctry_code, 2389 p_dev_cb->addr, 2390 app_id); 2391 2392 if (p_buf != p_data->value) 2393 GKI_freebuf(p_buf); 2394 } 2395 2396 /******************************************************************************* 2397 ** 2398 ** Function bta_hh_gatt_open_fail 2399 ** 2400 ** Description action function to process the open fail 2401 ** 2402 ** Returns void 2403 ** 2404 *******************************************************************************/ 2405 void bta_hh_le_open_fail(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) 2406 { 2407 tBTA_HH_CONN conn_dat ; 2408 tBTA_HH_LE_HID_SRVC *p_hid_srvc = &p_cb->hid_srvc[0]; 2409 2410 /* open failure in the middle of service discovery, clear all services */ 2411 if (p_cb->disc_active & BTA_HH_LE_DISC_HIDS) 2412 { 2413 bta_hh_clear_service_cache(p_cb); 2414 } 2415 2416 p_cb->disc_active = BTA_HH_LE_DISC_NONE; 2417 /* Failure in opening connection or GATT discovery failure */ 2418 conn_dat.handle = p_cb->hid_handle; 2419 memcpy(conn_dat.bda, p_cb->addr, BD_ADDR_LEN); 2420 conn_dat.le_hid = TRUE; 2421 conn_dat.scps_supported = p_cb->scps_supported; 2422 2423 if (p_cb->status == BTA_HH_OK) 2424 conn_dat.status = (p_data->le_close.reason == BTA_GATT_CONN_UNKNOWN) ? p_cb->status : BTA_HH_ERR; 2425 else 2426 conn_dat.status = p_cb->status; 2427 2428 /* Report OPEN fail event */ 2429 (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat); 2430 2431 } 2432 2433 /******************************************************************************* 2434 ** 2435 ** Function bta_hh_gatt_close 2436 ** 2437 ** Description action function to process the GATT close int he state machine. 2438 ** 2439 ** Returns void 2440 ** 2441 *******************************************************************************/ 2442 void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) 2443 { 2444 tBTA_HH_CBDATA disc_dat = {BTA_HH_OK, 0}; 2445 2446 /* finaliza device driver */ 2447 bta_hh_co_close(p_cb->hid_handle, p_cb->app_id); 2448 /* update total conn number */ 2449 bta_hh_cb.cnt_num --; 2450 2451 disc_dat.handle = p_cb->hid_handle; 2452 disc_dat.status = p_cb->status; 2453 2454 (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat); 2455 2456 /* if no connection is active and HH disable is signaled, disable service */ 2457 if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable) 2458 { 2459 bta_hh_disc_cmpl(); 2460 } 2461 else 2462 { 2463 #if (BTA_HH_LE_RECONN == TRUE) 2464 if (p_data->le_close.reason == BTA_GATT_CONN_TIMEOUT) 2465 { 2466 bta_hh_le_add_dev_bg_conn(p_cb, FALSE); 2467 } 2468 #endif 2469 } 2470 2471 return; 2472 2473 } 2474 2475 /******************************************************************************* 2476 ** 2477 ** Function bta_hh_le_api_disc_act 2478 ** 2479 ** Description initaite a Close API to a remote HID device 2480 ** 2481 ** Returns void 2482 ** 2483 *******************************************************************************/ 2484 void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb) 2485 { 2486 if (p_cb->conn_id != BTA_GATT_INVALID_CONN_ID) 2487 { 2488 BTA_GATTC_Close(p_cb->conn_id); 2489 /* remove device from background connection if intended to disconnect, 2490 do not allow reconnection */ 2491 bta_hh_le_remove_dev_bg_conn(p_cb); 2492 } 2493 } 2494 2495 /******************************************************************************* 2496 ** 2497 ** Function bta_hh_le_get_rpt 2498 ** 2499 ** Description GET_REPORT on a LE HID Report 2500 ** 2501 ** Returns void 2502 ** 2503 *******************************************************************************/ 2504 void bta_hh_le_get_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id) 2505 { 2506 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); 2507 tBTA_GATTC_CHAR_ID char_id; 2508 UINT16 srvc_uuid = UUID_SERVCLASS_LE_HID; 2509 2510 if (p_rpt == NULL) 2511 { 2512 APPL_TRACE_ERROR("bta_hh_le_get_rpt: no matching report"); 2513 return; 2514 } 2515 if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL) 2516 srvc_uuid = UUID_SERVCLASS_BATTERY; 2517 2518 p_cb->w4_evt = BTA_HH_GET_RPT_EVT; 2519 2520 bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst, srvc_uuid, &char_id.srvc_id); 2521 bta_hh_le_fill_16bits_char_id(p_rpt->inst_id, p_rpt->uuid, &char_id.char_id); 2522 2523 BTA_GATTC_ReadCharacteristic(p_cb->conn_id, 2524 &char_id, 2525 BTA_GATT_AUTH_REQ_NONE); 2526 } 2527 2528 /******************************************************************************* 2529 ** 2530 ** Function bta_hh_le_write_rpt 2531 ** 2532 ** Description SET_REPORT/or DATA output on a LE HID Report 2533 ** 2534 ** Returns void 2535 ** 2536 *******************************************************************************/ 2537 void bta_hh_le_write_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst, 2538 tBTA_GATTC_WRITE_TYPE write_type, 2539 tBTA_HH_RPT_TYPE r_type, 2540 BT_HDR *p_buf, UINT16 w4_evt ) 2541 { 2542 tBTA_HH_LE_RPT *p_rpt; 2543 tBTA_GATTC_CHAR_ID char_id; 2544 UINT8 *p_value, rpt_id; 2545 2546 if (p_buf == NULL || p_buf->len == 0) 2547 { 2548 APPL_TRACE_ERROR("bta_hh_le_write_rpt: Illegal data"); 2549 return; 2550 } 2551 2552 /* strip report ID from the data */ 2553 p_value = (UINT8 *)(p_buf + 1) + p_buf->offset; 2554 STREAM_TO_UINT8(rpt_id, p_value); 2555 p_buf->len -= 1; 2556 2557 p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[srvc_inst].report, p_cb->mode, r_type, rpt_id); 2558 2559 if (p_rpt == NULL) 2560 { 2561 APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report"); 2562 return; 2563 } 2564 2565 APPL_TRACE_ERROR("bta_hh_le_write_rpt: ReportID: 0x%02x Data Len: %d", rpt_id, p_buf->len); 2566 2567 p_cb->w4_evt = w4_evt; 2568 2569 bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst, UUID_SERVCLASS_LE_HID, &char_id.srvc_id); 2570 bta_hh_le_fill_16bits_char_id(p_rpt->inst_id, p_rpt->uuid, &char_id.char_id); 2571 2572 BTA_GATTC_WriteCharValue(p_cb->conn_id, 2573 &char_id, 2574 write_type, /* default to use write request */ 2575 p_buf->len, 2576 p_value, 2577 BTA_GATT_AUTH_REQ_NONE); 2578 2579 } 2580 2581 /******************************************************************************* 2582 ** 2583 ** Function bta_hh_le_suspend 2584 ** 2585 ** Description send LE suspend or exit suspend mode to remote device. 2586 ** 2587 ** Returns void 2588 ** 2589 *******************************************************************************/ 2590 void bta_hh_le_suspend(tBTA_HH_DEV_CB *p_cb, tBTA_HH_TRANS_CTRL_TYPE ctrl_type) 2591 { 2592 UINT8 i; 2593 tBTA_GATTC_CHAR_ID char_id; 2594 2595 ctrl_type -= BTA_HH_CTRL_SUSPEND; 2596 2597 for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++) 2598 { 2599 bta_hh_le_fill_16bits_srvc_id(TRUE, i, UUID_SERVCLASS_LE_HID, &char_id.srvc_id); 2600 bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_CONTROL_POINT, &char_id.char_id); 2601 2602 BTA_GATTC_WriteCharValue(p_cb->conn_id, 2603 &char_id, 2604 BTA_GATTC_TYPE_WRITE_NO_RSP, /* default to use write request */ 2605 1, 2606 &ctrl_type, 2607 BTA_GATT_AUTH_REQ_NONE); 2608 } 2609 } 2610 2611 /******************************************************************************* 2612 ** 2613 ** Function bta_hh_le_write_dev_act 2614 ** 2615 ** Description Write LE device action. can be SET/GET/DATA transaction. 2616 ** 2617 ** Returns void 2618 ** 2619 *******************************************************************************/ 2620 void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) 2621 { 2622 switch(p_data->api_sndcmd.t_type) 2623 { 2624 case HID_TRANS_SET_PROTOCOL: 2625 p_cb->w4_evt = BTA_HH_SET_PROTO_EVT; 2626 bta_hh_le_set_protocol_mode(p_cb, p_data->api_sndcmd.param); 2627 break; 2628 2629 case HID_TRANS_GET_PROTOCOL: 2630 bta_hh_le_get_protocol_mode(p_cb); 2631 break; 2632 2633 case HID_TRANS_GET_REPORT: 2634 bta_hh_le_get_rpt(p_cb, 2635 BTA_HH_LE_SRVC_DEF, 2636 p_data->api_sndcmd.param, 2637 p_data->api_sndcmd.rpt_id); 2638 break; 2639 2640 case HID_TRANS_SET_REPORT: 2641 bta_hh_le_write_rpt(p_cb, 2642 BTA_HH_LE_SRVC_DEF, 2643 BTA_GATTC_TYPE_WRITE, 2644 p_data->api_sndcmd.param, 2645 p_data->api_sndcmd.p_data, 2646 BTA_HH_SET_RPT_EVT); 2647 break; 2648 2649 case HID_TRANS_DATA: /* output report */ 2650 2651 bta_hh_le_write_rpt(p_cb, 2652 BTA_HH_LE_SRVC_DEF, 2653 BTA_GATTC_TYPE_WRITE_NO_RSP, 2654 p_data->api_sndcmd.param, 2655 p_data->api_sndcmd.p_data, 2656 BTA_HH_DATA_EVT); 2657 break; 2658 2659 case HID_TRANS_CONTROL: 2660 /* no handshake event will be generated */ 2661 /* if VC_UNPLUG is issued, set flag */ 2662 if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND || 2663 p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND) 2664 { 2665 bta_hh_le_suspend(p_cb, p_data->api_sndcmd.param); 2666 } 2667 break; 2668 2669 default: 2670 APPL_TRACE_ERROR("unsupported trsanction for LE HID device: %d", p_data->api_sndcmd.t_type); 2671 break; 2672 } 2673 } 2674 2675 /******************************************************************************* 2676 ** 2677 ** Function bta_hh_le_get_dscp_act 2678 ** 2679 ** Description Send ReportDescriptor to application for all HID services. 2680 ** 2681 ** Returns void 2682 ** 2683 *******************************************************************************/ 2684 void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb) 2685 { 2686 UINT8 i; 2687 2688 for (i = 0 ;i < BTA_HH_LE_HID_SRVC_MAX; i ++) 2689 { 2690 if (p_cb->hid_srvc[i].in_use) 2691 { 2692 p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc[i].descriptor.dl_len; 2693 p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc[i].descriptor.dsc_list; 2694 2695 (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info); 2696 } 2697 else 2698 break; 2699 } 2700 } 2701 2702 /******************************************************************************* 2703 ** 2704 ** Function bta_hh_le_add_dev_bg_conn 2705 ** 2706 ** Description Remove a LE HID device from back ground connection procedure. 2707 ** 2708 ** Returns void 2709 ** 2710 *******************************************************************************/ 2711 static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond) 2712 { 2713 UINT8 sec_flag=0; 2714 BOOLEAN to_add = TRUE; 2715 2716 if (check_bond) 2717 { 2718 /* start reconnection if remote is a bonded device */ 2719 /* verify bond */ 2720 BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE); 2721 2722 if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0) 2723 to_add = FALSE; 2724 } 2725 2726 if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/ 2727 !p_cb->in_bg_conn && to_add) 2728 { 2729 /* add device into BG connection to accept remote initiated connection */ 2730 BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE); 2731 p_cb->in_bg_conn = TRUE; 2732 2733 BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL); 2734 } 2735 return; 2736 } 2737 2738 /******************************************************************************* 2739 ** 2740 ** Function bta_hh_le_add_device 2741 ** 2742 ** Description Add a LE HID device as a known device, and also add the address 2743 ** into back ground connection WL for incoming connection. 2744 ** 2745 ** Returns void 2746 ** 2747 *******************************************************************************/ 2748 UINT8 bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info) 2749 { 2750 p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index); 2751 bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index; 2752 2753 /* update DI information */ 2754 bta_hh_update_di_info(p_cb, 2755 p_dev_info->dscp_info.vendor_id, 2756 p_dev_info->dscp_info.product_id, 2757 p_dev_info->dscp_info.version, 2758 p_dev_info->dscp_info.flag); 2759 2760 /* add to BTA device list */ 2761 bta_hh_add_device_to_list(p_cb, p_cb->hid_handle, 2762 p_dev_info->attr_mask, 2763 &p_dev_info->dscp_info.descriptor, 2764 p_dev_info->sub_class, 2765 p_dev_info->dscp_info.ssr_max_latency, 2766 p_dev_info->dscp_info.ssr_min_tout, 2767 p_dev_info->app_id); 2768 2769 bta_hh_le_add_dev_bg_conn(p_cb, FALSE); 2770 2771 return p_cb->hid_handle; 2772 } 2773 2774 /******************************************************************************* 2775 ** 2776 ** Function bta_hh_le_remove_dev_bg_conn 2777 ** 2778 ** Description Remove a LE HID device from back ground connection procedure. 2779 ** 2780 ** Returns void 2781 ** 2782 *******************************************************************************/ 2783 void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB *p_dev_cb) 2784 { 2785 if (p_dev_cb->in_bg_conn) 2786 { 2787 p_dev_cb->in_bg_conn = FALSE; 2788 2789 BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, FALSE); 2790 } 2791 } 2792 2793 /******************************************************************************* 2794 ** 2795 ** Function bta_hh_le_update_scpp 2796 ** 2797 ** Description action function to update the scan parameters on remote HID 2798 ** device 2799 ** 2800 ** Parameters: 2801 ** 2802 *******************************************************************************/ 2803 void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) 2804 { 2805 tBTA_GATTC_CHAR_ID char_id; 2806 UINT8 value[4], *p = value; 2807 tBTA_HH_CBDATA cback_data ; 2808 2809 if (!p_dev_cb->is_le_device || 2810 p_dev_cb->mode != BTA_HH_PROTO_RPT_MODE || 2811 p_dev_cb->scps_supported == FALSE) 2812 { 2813 APPL_TRACE_ERROR("Can not set ScPP scan paramter as boot host, or remote does not support ScPP "); 2814 2815 cback_data.handle = p_dev_cb->hid_handle; 2816 cback_data.status = BTA_HH_ERR; 2817 (* bta_hh_cb.p_cback)(BTA_HH_UPDATE_SCPP_EVT, (tBTA_HH *)&cback_data); 2818 2819 return; 2820 } 2821 2822 p_dev_cb->w4_evt = BTA_HH_UPDATE_SCPP_EVT; 2823 2824 UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_int); 2825 UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_win); 2826 2827 bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_SCPP_INST_DEF, UUID_SERVCLASS_SCAN_PARAM, &char_id.srvc_id); 2828 bta_hh_le_fill_16bits_char_id(BTA_HH_SCPP_INST_DEF, GATT_UUID_SCAN_INT_WINDOW, &char_id.char_id); 2829 2830 BTA_GATTC_WriteCharValue(p_dev_cb->conn_id, 2831 &char_id, 2832 BTA_GATTC_TYPE_WRITE_NO_RSP, 2833 2, 2834 value, 2835 BTA_GATT_AUTH_REQ_NONE); 2836 2837 } 2838 2839 /******************************************************************************* 2840 ** 2841 ** Function bta_hh_gattc_callback 2842 ** 2843 ** Description This is GATT client callback function used in BTA HH. 2844 ** 2845 ** Parameters: 2846 ** 2847 *******************************************************************************/ 2848 static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) 2849 { 2850 tBTA_HH_DEV_CB *p_dev_cb; 2851 UINT16 evt; 2852 #if BTA_HH_DEBUG 2853 APPL_TRACE_DEBUG("bta_hh_gattc_callback event = %d", event); 2854 #endif 2855 if (p_data == NULL) 2856 return; 2857 2858 switch (event) 2859 { 2860 case BTA_GATTC_REG_EVT: /* 0 */ 2861 bta_hh_le_register_cmpl(&p_data->reg_oper); 2862 break; 2863 2864 case BTA_GATTC_DEREG_EVT: /* 1 */ 2865 bta_hh_cleanup_disable(p_data->reg_oper.status); 2866 break; 2867 2868 case BTA_GATTC_OPEN_EVT: /* 2 */ 2869 p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda); 2870 if (p_dev_cb) { 2871 bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open); 2872 } 2873 break; 2874 2875 case BTA_GATTC_READ_CHAR_EVT: /* 3 */ 2876 case BTA_GATTC_READ_DESCR_EVT: /* 8 */ 2877 p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->read.conn_id); 2878 if (event == BTA_GATTC_READ_CHAR_EVT) 2879 evt = BTA_HH_GATT_READ_CHAR_CMPL_EVT; 2880 else 2881 evt = BTA_HH_GATT_READ_DESCR_CMPL_EVT; 2882 2883 bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->read); 2884 break; 2885 2886 case BTA_GATTC_WRITE_DESCR_EVT: /* 9 */ 2887 case BTA_GATTC_WRITE_CHAR_EVT: /* 4 */ 2888 p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->write.conn_id); 2889 if (event == BTA_GATTC_WRITE_CHAR_EVT) 2890 evt = BTA_HH_GATT_WRITE_CHAR_CMPL_EVT; 2891 else 2892 evt = BTA_HH_GATT_WRITE_DESCR_CMPL_EVT; 2893 2894 bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->write); 2895 break; 2896 2897 case BTA_GATTC_CLOSE_EVT: /* 5 */ 2898 bta_hh_le_close(&p_data->close); 2899 break; 2900 2901 case BTA_GATTC_SEARCH_CMPL_EVT: /* 6 */ 2902 bta_hh_le_srvc_search_cmpl(&p_data->search_cmpl); 2903 break; 2904 2905 case BTA_GATTC_SEARCH_RES_EVT: /* 7 */ 2906 bta_hh_le_search_result(&p_data->srvc_res); 2907 break; 2908 2909 2910 2911 case BTA_GATTC_NOTIF_EVT: /* 10 */ 2912 bta_hh_le_input_rpt_notify(&p_data->notify); 2913 break; 2914 2915 case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */ 2916 p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda); 2917 if (p_dev_cb) { 2918 bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_ENC_CMPL_EVT, 2919 (tBTA_HH_DATA *)&p_data->enc_cmpl); 2920 } 2921 break; 2922 2923 default: 2924 break; 2925 } 2926 } 2927 2928 /******************************************************************************* 2929 ** 2930 ** Function bta_hh_le_hid_read_rpt_clt_cfg 2931 ** 2932 ** Description a test command to read report descriptor client configuration 2933 ** 2934 ** Returns void 2935 ** 2936 *******************************************************************************/ 2937 void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id) 2938 { 2939 tBTA_HH_DEV_CB *p_cb = NULL; 2940 tBTA_HH_LE_RPT *p_rpt ; 2941 UINT8 index = BTA_HH_IDX_INVALID; 2942 2943 index = bta_hh_find_cb(bd_addr); 2944 if ((index = bta_hh_find_cb(bd_addr))== BTA_HH_IDX_INVALID) 2945 { 2946 APPL_TRACE_ERROR("unknown device"); 2947 return; 2948 } 2949 2950 p_cb = &bta_hh_cb.kdev[index]; 2951 2952 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); 2953 2954 if (p_rpt == NULL) 2955 { 2956 APPL_TRACE_ERROR("bta_hh_le_write_rpt: no matching report"); 2957 return; 2958 } 2959 2960 bta_hh_le_read_char_dscrpt(p_cb, 2961 UUID_SERVCLASS_LE_HID, 2962 BTA_HH_LE_SRVC_DEF, 2963 p_rpt->uuid, 2964 p_rpt->inst_id, 2965 GATT_UUID_CHAR_CLIENT_CONFIG); 2966 2967 2968 2969 return; 2970 } 2971 2972 /******************************************************************************* 2973 ** 2974 ** Function bta_hh_le_search_scps 2975 ** 2976 ** Description discovery scan parameter service if act as report host, otherwise 2977 ** finish LE connection. 2978 ** 2979 ** Parameters: 2980 ** 2981 *******************************************************************************/ 2982 static void bta_hh_le_search_scps(tBTA_HH_DEV_CB *p_cb) 2983 { 2984 tBT_UUID pri_srvc; 2985 2986 if ( p_cb->mode == BTA_HH_PROTO_RPT_MODE) 2987 { 2988 p_cb->disc_active |= BTA_HH_LE_DISC_SCPS; 2989 /* start service discovery for Scan Parameter service */ 2990 pri_srvc.len = LEN_UUID_16; 2991 pri_srvc.uu.uuid16 = UUID_SERVCLASS_SCAN_PARAM; 2992 2993 BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc); 2994 } 2995 else 2996 bta_hh_le_open_cmpl(p_cb); 2997 } 2998 2999 /******************************************************************************* 3000 ** 3001 ** Function bta_hh_le_search_scps_chars 3002 ** 3003 ** Description find ScPS optional characteristics scan refresh 3004 ** 3005 ** Parameters: 3006 ** 3007 *******************************************************************************/ 3008 static void bta_hh_le_search_scps_chars(tBTA_HH_DEV_CB *p_cb) 3009 { 3010 tBTA_GATT_SRVC_ID srvc_id; 3011 tBT_UUID char_cond; 3012 tBTA_GATTC_CHAR_ID char_result; 3013 tBTA_GATT_CHAR_PROP prop; 3014 3015 p_cb->scps_supported = TRUE; 3016 bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_SCAN_PARAM, &srvc_id); 3017 3018 char_cond.len = LEN_UUID_16; 3019 char_cond.uu.uuid16 = GATT_UUID_SCAN_REFRESH; 3020 3021 /* look for scan refresh */ 3022 if (BTA_GATTC_GetFirstChar( p_cb->conn_id, 3023 &srvc_id, 3024 &char_cond, 3025 &char_result, 3026 &prop) == BTA_GATT_OK) 3027 { 3028 if (prop & BTA_GATT_CHAR_PROP_BIT_NOTIFY) 3029 p_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT; 3030 else 3031 p_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE; 3032 3033 } 3034 } 3035 3036 /******************************************************************************* 3037 ** 3038 ** Function bta_hh_le_register_scpp_notif 3039 ** 3040 ** Description register scan parameter refresh notitication complete 3041 ** 3042 ** 3043 ** Parameters: 3044 ** 3045 *******************************************************************************/ 3046 static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status) 3047 { 3048 UINT8 sec_flag=0; 3049 tBTA_GATTC_CHAR_ID char_id; 3050 3051 /* if write scan parameter sucessful */ 3052 /* if bonded and notification is not enabled, configure the client configuration */ 3053 if (status == BTA_GATT_OK && 3054 (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_SPT) != 0 && 3055 (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_ENB) == 0) 3056 { 3057 BTM_GetSecurityFlagsByTransport(p_dev_cb->addr, &sec_flag, BT_TRANSPORT_LE); 3058 if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)) 3059 { 3060 if (bta_hh_le_write_char_clt_cfg (p_dev_cb, 3061 BTA_HH_SCPP_INST_DEF, 3062 UUID_SERVCLASS_SCAN_PARAM, 3063 BTA_HH_SCPP_INST_DEF, 3064 GATT_UUID_SCAN_REFRESH, 3065 BTA_GATT_CLT_CONFIG_NOTIFICATION)) 3066 { 3067 bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_SCPP_INST_DEF, UUID_SERVCLASS_SCAN_PARAM, &char_id.srvc_id); 3068 bta_hh_le_fill_16bits_char_id(BTA_HH_SCPP_INST_DEF, GATT_UUID_SCAN_REFRESH, &char_id.char_id); 3069 3070 BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if, 3071 p_dev_cb->addr, 3072 &char_id); 3073 return; 3074 } 3075 } 3076 } 3077 bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, status); 3078 } 3079 3080 /******************************************************************************* 3081 ** 3082 ** Function bta_hh_le_register_scpp_notif_cmpl 3083 ** 3084 ** Description action function to register scan parameter refresh notitication 3085 ** 3086 ** Parameters: 3087 ** 3088 *******************************************************************************/ 3089 static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status) 3090 { 3091 tBTA_HH_CBDATA cback_data ; 3092 UINT16 cb_evt = p_dev_cb->w4_evt; 3093 3094 if (status == BTA_GATT_OK) 3095 p_dev_cb->scps_notify = (BTA_HH_LE_SCPS_NOTIFY_ENB | BTA_HH_LE_SCPS_NOTIFY_SPT); 3096 3097 cback_data.handle = p_dev_cb->hid_handle; 3098 cback_data.status = (status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR; 3099 p_dev_cb->w4_evt = 0; 3100 (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data); 3101 3102 3103 } 3104 3105 /******************************************************************************* 3106 ** 3107 ** Function bta_hh_process_cache_rpt 3108 ** 3109 ** Description Process the cached reports 3110 ** 3111 ** Parameters: 3112 ** 3113 *******************************************************************************/ 3114 static void bta_hh_process_cache_rpt (tBTA_HH_DEV_CB *p_cb, 3115 tBTA_HH_RPT_CACHE_ENTRY *p_rpt_cache, 3116 UINT8 num_rpt) 3117 { 3118 UINT8 i = 0; 3119 tBTA_HH_LE_RPT *p_rpt; 3120 3121 if (num_rpt != 0) /* no cache is found */ 3122 { 3123 p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].in_use = TRUE; 3124 3125 /* set the descriptor info */ 3126 p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].descriptor.dl_len = 3127 p_cb->dscp_info.descriptor.dl_len; 3128 p_cb->hid_srvc[BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id)].descriptor.dsc_list = 3129 p_cb->dscp_info.descriptor.dsc_list; 3130 3131 for (; i <num_rpt; i ++, p_rpt_cache ++) 3132 { 3133 if ((p_rpt = bta_hh_le_find_alloc_report_entry (p_cb, 3134 BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt_cache->inst_id), 3135 p_rpt_cache->rpt_uuid, 3136 BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt_cache->inst_id), 3137 p_rpt_cache->prop)) == NULL) 3138 { 3139 APPL_TRACE_ERROR("bta_hh_process_cache_rpt: allocation report entry failure"); 3140 break; 3141 } 3142 else 3143 { 3144 p_rpt->rpt_type = p_rpt_cache->rpt_type; 3145 p_rpt->rpt_id = p_rpt_cache->rpt_id; 3146 3147 if(p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT || 3148 p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT || 3149 (p_rpt->uuid == GATT_UUID_HID_REPORT && p_rpt->rpt_type == BTA_HH_RPTT_INPUT)) 3150 { 3151 p_rpt->client_cfg_value = BTA_GATT_CLT_CONFIG_NOTIFICATION; 3152 } 3153 } 3154 } 3155 } 3156 } 3157 3158 #endif 3159 3160 3161 3162 3163