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