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