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