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