1 /****************************************************************************** 2 * 3 * Copyright (C) 2016 The Android Open Source Project 4 * Copyright (C) 2002-2012 Broadcom Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 ******************************************************************************/ 19 20 /****************************************************************************** 21 * 22 * this file contains the connection interface functions 23 * 24 ******************************************************************************/ 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 30 #include "bt_types.h" 31 32 #include "l2c_api.h" 33 #include "l2cdefs.h" 34 35 #include "btm_api.h" 36 #include "btm_int.h" 37 #include "btu.h" 38 39 #include "hiddefs.h" 40 41 #include "bt_utils.h" 42 #include "hidd_api.h" 43 #include "hidd_int.h" 44 45 #include "osi/include/osi.h" 46 47 static void hidd_l2cif_connect_ind(BD_ADDR bd_addr, uint16_t cid, uint16_t psm, 48 uint8_t id); 49 static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result); 50 static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO* p_cfg); 51 static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO* p_cfg); 52 static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed); 53 static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result); 54 static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR* p_msg); 55 static void hidd_l2cif_cong_ind(uint16_t cid, bool congested); 56 57 static const tL2CAP_APPL_INFO dev_reg_info = {hidd_l2cif_connect_ind, 58 hidd_l2cif_connect_cfm, 59 NULL, 60 hidd_l2cif_config_ind, 61 hidd_l2cif_config_cfm, 62 hidd_l2cif_disconnect_ind, 63 hidd_l2cif_disconnect_cfm, 64 NULL, 65 hidd_l2cif_data_ind, 66 hidd_l2cif_cong_ind, 67 NULL}; 68 69 /******************************************************************************* 70 * 71 * Function hidd_check_config_done 72 * 73 * Description Checks if connection is configured and callback can be fired 74 * 75 * Returns void 76 * 77 ******************************************************************************/ 78 static void hidd_check_config_done() { 79 tHID_CONN* p_hcon; 80 81 p_hcon = &hd_cb.device.conn; 82 83 if (((p_hcon->conn_flags & HID_CONN_FLAGS_ALL_CONFIGURED) == 84 HID_CONN_FLAGS_ALL_CONFIGURED) && 85 (p_hcon->conn_state == HID_CONN_STATE_CONFIG)) { 86 p_hcon->conn_state = HID_CONN_STATE_CONNECTED; 87 88 hd_cb.device.state = HIDD_DEV_CONNECTED; 89 90 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_OPEN, 0, NULL); 91 92 // send outstanding data on intr 93 if (hd_cb.pending_data) { 94 L2CA_DataWrite(p_hcon->intr_cid, hd_cb.pending_data); 95 hd_cb.pending_data = NULL; 96 } 97 } 98 } 99 100 /******************************************************************************* 101 * 102 * Function hidh_sec_check_complete_term 103 * 104 * Description HID security check complete callback function. 105 * 106 * Returns Send L2CA_ConnectRsp OK if secutiry check succeed; otherwise 107 * send security block L2C connection response. 108 * 109 ******************************************************************************/ 110 static void hidd_sec_check_complete(UNUSED_ATTR BD_ADDR bd_addr, 111 UNUSED_ATTR tBT_TRANSPORT transport, 112 void* p_ref_data, uint8_t res) { 113 tHID_DEV_DEV_CTB* p_dev = (tHID_DEV_DEV_CTB*)p_ref_data; 114 115 if (res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY) { 116 p_dev->conn.disc_reason = HID_SUCCESS; 117 p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_INTR; 118 119 L2CA_ConnectRsp(p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid, 120 L2CAP_CONN_OK, L2CAP_CONN_OK); 121 L2CA_ConfigReq(p_dev->conn.ctrl_cid, &hd_cb.l2cap_cfg); 122 } else if (res != BTM_SUCCESS) { 123 HIDD_TRACE_WARNING("%s: connection rejected by security", __func__); 124 125 p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED; 126 p_dev->conn.conn_state = HID_CONN_STATE_UNUSED; 127 L2CA_ConnectRsp(p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid, 128 L2CAP_CONN_SECURITY_BLOCK, L2CAP_CONN_OK); 129 return; 130 } 131 } 132 133 /******************************************************************************* 134 * 135 * Function hidd_sec_check_complete_orig 136 * 137 * Description HID security check complete callback function (device 138 *originated) 139 * 140 * Returns void 141 * 142 ******************************************************************************/ 143 void hidd_sec_check_complete_orig(UNUSED_ATTR BD_ADDR bd_addr, 144 UNUSED_ATTR tBT_TRANSPORT transport, 145 void* p_ref_data, uint8_t res) { 146 tHID_DEV_DEV_CTB* p_dev = (tHID_DEV_DEV_CTB*)p_ref_data; 147 148 if (p_dev->conn.conn_state != HID_CONN_STATE_SECURITY) { 149 HIDD_TRACE_WARNING("%s: invalid state (%02x)", __func__, 150 p_dev->conn.conn_state); 151 return; 152 } 153 154 if (res == BTM_SUCCESS) { 155 HIDD_TRACE_EVENT("%s: security ok", __func__); 156 p_dev->conn.disc_reason = HID_SUCCESS; 157 158 p_dev->conn.conn_state = HID_CONN_STATE_CONFIG; 159 L2CA_ConfigReq(p_dev->conn.ctrl_cid, &hd_cb.l2cap_cfg); 160 } else { 161 HIDD_TRACE_WARNING("%s: security check failed (%02x)", __func__, res); 162 p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED; 163 hidd_conn_disconnect(); 164 } 165 } 166 167 /******************************************************************************* 168 * 169 * Function hidd_l2cif_connect_ind 170 * 171 * Description Handles incoming L2CAP connection (we act as server) 172 * 173 * Returns void 174 * 175 ******************************************************************************/ 176 static void hidd_l2cif_connect_ind(BD_ADDR bd_addr, uint16_t cid, uint16_t psm, 177 uint8_t id) { 178 tHID_CONN* p_hcon; 179 tHID_DEV_DEV_CTB* p_dev; 180 bool accept = TRUE; // accept by default 181 182 HIDD_TRACE_EVENT("%s: psm=%04x cid=%04x id=%02x", __func__, psm, cid, id); 183 184 p_dev = &hd_cb.device; 185 186 if (!hd_cb.allow_incoming) { 187 HIDD_TRACE_WARNING("%s: incoming connections not allowed, rejecting", 188 __func__); 189 L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0); 190 return; 191 } 192 193 if (p_dev->in_use && memcmp(bd_addr, p_dev->addr, sizeof(BD_ADDR))) { 194 HIDD_TRACE_WARNING( 195 "%s: incoming connections from different device, rejecting", __func__); 196 L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0); 197 return; 198 } else if (!p_dev->in_use) { 199 p_dev->in_use = TRUE; 200 memcpy(p_dev->addr, bd_addr, sizeof(BD_ADDR)); 201 p_dev->state = HIDD_DEV_NO_CONN; 202 } 203 204 p_hcon = &hd_cb.device.conn; 205 206 switch (psm) { 207 case HID_PSM_INTERRUPT: 208 if (p_hcon->ctrl_cid == 0) { 209 accept = FALSE; 210 HIDD_TRACE_WARNING("%s: incoming INTR without CTRL, rejecting", 211 __func__); 212 } 213 214 if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) { 215 accept = FALSE; 216 HIDD_TRACE_WARNING("%s: incoming INTR in invalid state (%d), rejecting", 217 __func__, p_hcon->conn_state); 218 } 219 220 break; 221 222 case HID_PSM_CONTROL: 223 if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) { 224 accept = FALSE; 225 HIDD_TRACE_WARNING("%s: incoming CTRL in invalid state (%d), rejecting", 226 __func__, p_hcon->conn_state); 227 } 228 229 break; 230 231 default: 232 accept = FALSE; 233 HIDD_TRACE_ERROR("%s: received invalid PSM, rejecting", __func__); 234 break; 235 } 236 237 if (!accept) { 238 L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0); 239 return; 240 } 241 242 // for CTRL we need to go through security and we reply in callback from there 243 if (psm == HID_PSM_CONTROL) { 244 p_hcon->conn_flags = 0; 245 p_hcon->ctrl_cid = cid; 246 p_hcon->ctrl_id = id; 247 p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; 248 249 p_hcon->conn_state = HID_CONN_STATE_SECURITY; 250 if (btm_sec_mx_access_request(p_dev->addr, HID_PSM_CONTROL, FALSE, 251 BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN, 252 &hidd_sec_check_complete, 253 p_dev) == BTM_CMD_STARTED) { 254 L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK); 255 } 256 257 return; 258 } 259 260 // for INTR we go directly to config state 261 p_hcon->conn_state = HID_CONN_STATE_CONFIG; 262 p_hcon->intr_cid = cid; 263 264 L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_OK, L2CAP_CONN_OK); 265 L2CA_ConfigReq(cid, &hd_cb.l2cap_intr_cfg); 266 } 267 268 /******************************************************************************* 269 * 270 * Function hidd_l2cif_connect_cfm 271 * 272 * Description Handles L2CAP connection response (we act as client) 273 * 274 * Returns void 275 * 276 ******************************************************************************/ 277 static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result) { 278 tHID_DEV_DEV_CTB* p_dev = &hd_cb.device; 279 tHID_CONN* p_hcon = &hd_cb.device.conn; 280 281 HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result); 282 283 if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) { 284 HIDD_TRACE_WARNING("%s: unknown cid", __func__); 285 return; 286 } 287 288 if (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) || 289 ((cid == p_hcon->ctrl_cid) && 290 (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL)) || 291 ((cid == p_hcon->intr_cid) && 292 (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR))) { 293 HIDD_TRACE_WARNING("%s: unexpected", __func__); 294 return; 295 } 296 297 if (result != L2CAP_CONN_OK) { 298 HIDD_TRACE_WARNING("%s: connection failed, now disconnect", __func__); 299 300 if (cid == p_hcon->ctrl_cid) 301 p_hcon->ctrl_cid = 0; 302 else 303 p_hcon->intr_cid = 0; 304 305 hidd_conn_disconnect(); 306 307 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, 308 HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL); 309 return; 310 } 311 312 /* CTRL connect conf */ 313 if (cid == p_hcon->ctrl_cid) { 314 p_hcon->conn_state = HID_CONN_STATE_SECURITY; 315 p_hcon->disc_reason = 316 HID_L2CAP_CONN_FAIL; /* in case disconnected before sec completed */ 317 318 btm_sec_mx_access_request(p_dev->addr, HID_PSM_CONTROL, TRUE, 319 BTM_SEC_PROTO_HID, HIDD_SEC_CHN, 320 &hidd_sec_check_complete_orig, p_dev); 321 } else { 322 p_hcon->conn_state = HID_CONN_STATE_CONFIG; 323 L2CA_ConfigReq(cid, &hd_cb.l2cap_intr_cfg); 324 } 325 326 return; 327 } 328 329 /******************************************************************************* 330 * 331 * Function hidd_l2cif_config_ind 332 * 333 * Description Handles incoming L2CAP configuration request 334 * 335 * Returns void 336 * 337 ******************************************************************************/ 338 static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) { 339 tHID_CONN* p_hcon; 340 341 HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid); 342 343 p_hcon = &hd_cb.device.conn; 344 345 if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) { 346 HIDD_TRACE_WARNING("%s: unknown cid", __func__); 347 return; 348 } 349 350 if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_DEV_MTU_SIZE)) 351 p_hcon->rem_mtu_size = HID_DEV_MTU_SIZE; 352 else 353 p_hcon->rem_mtu_size = p_cfg->mtu; 354 355 // accept without changes 356 p_cfg->flush_to_present = FALSE; 357 p_cfg->mtu_present = FALSE; 358 p_cfg->result = L2CAP_CFG_OK; 359 360 if (cid == p_hcon->intr_cid && hd_cb.use_in_qos && !p_cfg->qos_present) { 361 p_cfg->qos_present = TRUE; 362 memcpy(&p_cfg->qos, &hd_cb.in_qos, sizeof(FLOW_SPEC)); 363 } 364 365 L2CA_ConfigRsp(cid, p_cfg); 366 367 // update flags 368 if (cid == p_hcon->ctrl_cid) { 369 p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE; 370 371 if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && 372 (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) { 373 p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; 374 if ((p_hcon->intr_cid = 375 L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) { 376 hidd_conn_disconnect(); 377 p_hcon->conn_state = HID_CONN_STATE_UNUSED; 378 379 HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR", 380 __func__); 381 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, 382 HID_ERR_L2CAP_FAILED, NULL); 383 return; 384 } else { 385 p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR; 386 } 387 } 388 } else { 389 p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_INTR_CFG_DONE; 390 } 391 392 hidd_check_config_done(); 393 } 394 395 /******************************************************************************* 396 * 397 * Function hidd_l2cif_config_cfm 398 * 399 * Description Handles incoming L2CAP configuration response 400 * 401 * Returns void 402 * 403 ******************************************************************************/ 404 static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) { 405 tHID_CONN* p_hcon; 406 uint32_t reason; 407 408 HIDD_TRACE_EVENT("%s: cid=%04x pcfg->result=%d", __func__, cid, 409 p_cfg->result); 410 411 p_hcon = &hd_cb.device.conn; 412 413 if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) { 414 HIDD_TRACE_WARNING("%s: unknown cid", __func__); 415 return; 416 } 417 418 if (p_hcon->intr_cid == cid && 419 p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS && p_cfg->qos_present) { 420 tL2CAP_CFG_INFO new_qos; 421 422 // QoS parameters not accepted for intr, try again with host proposal 423 424 memcpy(&new_qos, &hd_cb.l2cap_intr_cfg, sizeof(new_qos)); 425 memcpy(&new_qos.qos, &p_cfg->qos, sizeof(FLOW_SPEC)); 426 new_qos.qos_present = TRUE; 427 428 HIDD_TRACE_WARNING("%s: config failed, retry", __func__); 429 430 L2CA_ConfigReq(cid, &new_qos); 431 return; 432 } else if (p_hcon->intr_cid == cid && 433 p_cfg->result == L2CAP_CFG_UNKNOWN_OPTIONS) { 434 // QoS not understood by remote device, try configuring without QoS 435 436 HIDD_TRACE_WARNING("%s: config failed, retry without QoS", __func__); 437 438 L2CA_ConfigReq(cid, &hd_cb.l2cap_cfg); 439 return; 440 } else if (p_cfg->result != L2CAP_CFG_OK) { 441 HIDD_TRACE_WARNING("%s: config failed, disconnecting", __func__); 442 443 hidd_conn_disconnect(); 444 reason = HID_L2CAP_CFG_FAIL | (uint32_t)p_cfg->result; 445 446 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, reason, NULL); 447 return; 448 } 449 450 // update flags 451 if (cid == p_hcon->ctrl_cid) { 452 p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE; 453 454 if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && 455 (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) { 456 p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; 457 if ((p_hcon->intr_cid = 458 L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) { 459 hidd_conn_disconnect(); 460 p_hcon->conn_state = HID_CONN_STATE_UNUSED; 461 462 HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR", 463 __func__); 464 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, 465 HID_ERR_L2CAP_FAILED, NULL); 466 return; 467 } else { 468 p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR; 469 } 470 } 471 } else { 472 p_hcon->conn_flags |= HID_CONN_FLAGS_MY_INTR_CFG_DONE; 473 } 474 475 hidd_check_config_done(); 476 } 477 478 /******************************************************************************* 479 * 480 * Function hidd_l2cif_disconnect_ind 481 * 482 * Description Handler incoming L2CAP disconnection request 483 * 484 * Returns void 485 * 486 ******************************************************************************/ 487 static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed) { 488 tHID_CONN* p_hcon; 489 490 HIDD_TRACE_EVENT("%s: cid=%04x ack_needed=%d", __func__, cid, ack_needed); 491 492 p_hcon = &hd_cb.device.conn; 493 494 if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || 495 (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) { 496 HIDD_TRACE_WARNING("%s: unknown cid", __func__); 497 return; 498 } 499 500 if (ack_needed) L2CA_DisconnectRsp(cid); 501 502 p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING; 503 504 if (cid == p_hcon->ctrl_cid) 505 p_hcon->ctrl_cid = 0; 506 else 507 p_hcon->intr_cid = 0; 508 509 if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) { 510 HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__); 511 512 // clean any outstanding data on intr 513 if (hd_cb.pending_data) { 514 osi_free(hd_cb.pending_data); 515 hd_cb.pending_data = NULL; 516 } 517 518 hd_cb.device.state = HIDD_DEV_NO_CONN; 519 p_hcon->conn_state = HID_CONN_STATE_UNUSED; 520 521 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, p_hcon->disc_reason, 522 NULL); 523 } 524 } 525 526 /******************************************************************************* 527 * 528 * Function hidd_l2cif_disconnect_cfm 529 * 530 * Description Handles L2CAP disconection response 531 * 532 * Returns void 533 * 534 ******************************************************************************/ 535 static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result) { 536 tHID_CONN* p_hcon; 537 538 HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result); 539 540 p_hcon = &hd_cb.device.conn; 541 542 if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || 543 (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) { 544 HIDD_TRACE_WARNING("%s: unknown cid", __func__); 545 return; 546 } 547 548 if (cid == p_hcon->ctrl_cid) { 549 p_hcon->ctrl_cid = 0; 550 } else { 551 p_hcon->intr_cid = 0; 552 553 // now disconnect CTRL 554 L2CA_DisconnectReq(p_hcon->ctrl_cid); 555 } 556 557 if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) { 558 HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__); 559 560 hd_cb.device.state = HIDD_DEV_NO_CONN; 561 p_hcon->conn_state = HID_CONN_STATE_UNUSED; 562 563 if (hd_cb.pending_vc_unplug) { 564 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_VC_UNPLUG, 565 p_hcon->disc_reason, NULL); 566 hd_cb.pending_vc_unplug = FALSE; 567 } else { 568 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, 569 p_hcon->disc_reason, NULL); 570 } 571 } 572 } 573 574 /******************************************************************************* 575 * 576 * Function hidd_l2cif_cong_ind 577 * 578 * Description Handles L2CAP congestion status event 579 * 580 * Returns void 581 * 582 ******************************************************************************/ 583 static void hidd_l2cif_cong_ind(uint16_t cid, bool congested) { 584 tHID_CONN* p_hcon; 585 586 HIDD_TRACE_EVENT("%s: cid=%04x congested=%d", __func__, cid, congested); 587 588 p_hcon = &hd_cb.device.conn; 589 590 if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || 591 (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) { 592 HIDD_TRACE_WARNING("%s: unknown cid", __func__); 593 return; 594 } 595 596 if (congested) { 597 p_hcon->conn_flags |= HID_CONN_FLAGS_CONGESTED; 598 } else { 599 p_hcon->conn_flags &= ~HID_CONN_FLAGS_CONGESTED; 600 } 601 } 602 603 /******************************************************************************* 604 * 605 * Function hidd_l2cif_data_ind 606 * 607 * Description Handler incoming data on L2CAP channel 608 * 609 * Returns void 610 * 611 ******************************************************************************/ 612 static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR* p_msg) { 613 tHID_CONN* p_hcon; 614 uint8_t* p_data = (uint8_t*)(p_msg + 1) + p_msg->offset; 615 uint8_t msg_type, param; 616 bool err = FALSE; 617 618 HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid); 619 620 p_hcon = &hd_cb.device.conn; 621 622 if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || 623 (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) { 624 HIDD_TRACE_WARNING("%s: unknown cid", __func__); 625 osi_free(p_msg); 626 return; 627 } 628 629 msg_type = HID_GET_TRANS_FROM_HDR(*p_data); 630 param = HID_GET_PARAM_FROM_HDR(*p_data); 631 632 if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) { 633 // skip HID header 634 p_msg->offset++; 635 p_msg->len--; 636 637 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_INTR_DATA, 0, p_msg); 638 return; 639 } 640 641 switch (msg_type) { 642 case HID_TRANS_GET_REPORT: 643 // at this stage we don't know if Report Id shall be included in request 644 // so we pass complete packet in callback and let other code analyze this 645 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_GET_REPORT, 646 !!(param & HID_PAR_GET_REP_BUFSIZE_FOLLOWS), p_msg); 647 break; 648 649 case HID_TRANS_SET_REPORT: 650 // as above 651 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_REPORT, 0, p_msg); 652 break; 653 654 case HID_TRANS_GET_IDLE: 655 hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, 656 HID_PAR_REP_TYPE_OTHER, hd_cb.device.idle_time, 0, 657 NULL); 658 osi_free(p_msg); 659 break; 660 661 case HID_TRANS_SET_IDLE: 662 if (p_msg->len != 2) { 663 HIDD_TRACE_ERROR("%s: invalid len (%d) set idle request received", 664 __func__, p_msg->len); 665 err = TRUE; 666 } else { 667 hd_cb.device.idle_time = p_data[1]; 668 HIDD_TRACE_DEBUG("%s: idle_time = %d", __func__, 669 hd_cb.device.idle_time); 670 if (hd_cb.device.idle_time) { 671 HIDD_TRACE_WARNING( 672 "%s: idle_time of %d ms not supported by HID Device", __func__, 673 (hd_cb.device.idle_time * 4)); 674 err = TRUE; 675 } 676 } 677 if (!err) { 678 hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, 679 HID_PAR_HANDSHAKE_RSP_SUCCESS, 0, 0, NULL); 680 } else { 681 hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, 682 HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM, 0, 0, 683 NULL); 684 } 685 osi_free(p_msg); 686 break; 687 688 case HID_TRANS_GET_PROTOCOL: 689 hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, 690 HID_PAR_REP_TYPE_OTHER, !hd_cb.device.boot_mode, 0, 691 NULL); 692 osi_free(p_msg); 693 break; 694 695 case HID_TRANS_SET_PROTOCOL: 696 hd_cb.device.boot_mode = !(param & HID_PAR_PROTOCOL_MASK); 697 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_PROTOCOL, 698 param & HID_PAR_PROTOCOL_MASK, NULL); 699 hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_SUCCESS, 700 0, 0, NULL); 701 osi_free(p_msg); 702 break; 703 704 case HID_TRANS_CONTROL: 705 switch (param) { 706 case HID_PAR_CONTROL_SUSPEND: 707 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SUSPEND, 0, NULL); 708 break; 709 710 case HID_PAR_CONTROL_EXIT_SUSPEND: 711 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_EXIT_SUSPEND, 0, 712 NULL); 713 break; 714 715 case HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG: 716 hidd_conn_disconnect(); 717 718 // set flag so we can notify properly when disconnected 719 hd_cb.pending_vc_unplug = TRUE; 720 break; 721 } 722 723 osi_free(p_msg); 724 break; 725 726 case HID_TRANS_DATA: 727 default: 728 HIDD_TRACE_WARNING("%s: got unsupported msg (%d)", __func__, msg_type); 729 hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, 730 HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ, 0, 0, 731 NULL); 732 osi_free(p_msg); 733 break; 734 } 735 } 736 737 /******************************************************************************* 738 * 739 * Function hidd_conn_reg 740 * 741 * Description Registers L2CAP channels 742 * 743 * Returns void 744 * 745 ******************************************************************************/ 746 tHID_STATUS hidd_conn_reg(void) { 747 HIDD_TRACE_API("%s", __func__); 748 749 memset(&hd_cb.l2cap_cfg, 0, sizeof(tL2CAP_CFG_INFO)); 750 751 hd_cb.l2cap_cfg.mtu_present = TRUE; 752 hd_cb.l2cap_cfg.mtu = HID_DEV_MTU_SIZE; 753 hd_cb.l2cap_cfg.flush_to_present = TRUE; 754 hd_cb.l2cap_cfg.flush_to = HID_DEV_FLUSH_TO; 755 756 memset(&hd_cb.l2cap_intr_cfg, 0, sizeof(tL2CAP_CFG_INFO)); 757 hd_cb.l2cap_intr_cfg.mtu_present = TRUE; 758 hd_cb.l2cap_intr_cfg.mtu = HID_DEV_MTU_SIZE; 759 hd_cb.l2cap_intr_cfg.flush_to_present = TRUE; 760 hd_cb.l2cap_intr_cfg.flush_to = HID_DEV_FLUSH_TO; 761 762 if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&dev_reg_info)) { 763 HIDD_TRACE_ERROR("HID Control (device) registration failed"); 764 return (HID_ERR_L2CAP_FAILED); 765 } 766 767 if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&dev_reg_info)) { 768 L2CA_Deregister(HID_PSM_CONTROL); 769 HIDD_TRACE_ERROR("HID Interrupt (device) registration failed"); 770 return (HID_ERR_L2CAP_FAILED); 771 } 772 773 return (HID_SUCCESS); 774 } 775 776 /******************************************************************************* 777 * 778 * Function hidd_conn_dereg 779 * 780 * Description Deregisters L2CAP channels 781 * 782 * Returns void 783 * 784 ******************************************************************************/ 785 void hidd_conn_dereg(void) { 786 HIDD_TRACE_API("%s", __func__); 787 788 L2CA_Deregister(HID_PSM_CONTROL); 789 L2CA_Deregister(HID_PSM_INTERRUPT); 790 } 791 792 /******************************************************************************* 793 * 794 * Function hidd_conn_initiate 795 * 796 * Description Initiates HID connection to plugged device 797 * 798 * Returns HID_SUCCESS 799 * 800 ******************************************************************************/ 801 tHID_STATUS hidd_conn_initiate(void) { 802 tHID_DEV_DEV_CTB* p_dev = &hd_cb.device; 803 804 HIDD_TRACE_API("%s", __func__); 805 806 if (!p_dev->in_use) { 807 HIDD_TRACE_WARNING("%s: no virtual cable established", __func__); 808 return (HID_ERR_NOT_REGISTERED); 809 } 810 811 if (p_dev->conn.conn_state != HID_CONN_STATE_UNUSED) { 812 HIDD_TRACE_WARNING("%s: connection already in progress", __func__); 813 return (HID_ERR_CONN_IN_PROCESS); 814 } 815 816 p_dev->conn.ctrl_cid = 0; 817 p_dev->conn.intr_cid = 0; 818 p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL; 819 820 p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG; 821 822 BTM_SetOutService(p_dev->addr, BTM_SEC_SERVICE_HIDD_SEC_CTRL, HIDD_SEC_CHN); 823 824 /* Check if L2CAP started the connection process */ 825 if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) == 826 0) { 827 HIDD_TRACE_WARNING("%s: could not start L2CAP connection", __func__); 828 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, 829 NULL); 830 } else { 831 p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_CTRL; 832 } 833 834 return (HID_SUCCESS); 835 } 836 837 /******************************************************************************* 838 * 839 * Function hidd_conn_disconnect 840 * 841 * Description Disconnects existing HID connection 842 * 843 * Returns HID_SUCCESS 844 * 845 ******************************************************************************/ 846 tHID_STATUS hidd_conn_disconnect(void) { 847 tHID_CONN* p_hcon; 848 849 HIDD_TRACE_API("%s", __func__); 850 851 // clean any outstanding data on intr 852 if (hd_cb.pending_data) { 853 osi_free(hd_cb.pending_data); 854 hd_cb.pending_data = NULL; 855 } 856 857 p_hcon = &hd_cb.device.conn; 858 859 if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) { 860 p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING; 861 862 /* Set l2cap idle timeout to 0 (so ACL link is disconnected 863 * immediately after last channel is closed) */ 864 L2CA_SetIdleTimeoutByBdAddr(hd_cb.device.addr, 0, BT_TRANSPORT_BR_EDR); 865 866 if (p_hcon->intr_cid) { 867 L2CA_DisconnectReq(p_hcon->intr_cid); 868 } else if (p_hcon->ctrl_cid) { 869 L2CA_DisconnectReq(p_hcon->ctrl_cid); 870 } 871 } else { 872 HIDD_TRACE_WARNING("%s: already disconnected", __func__); 873 p_hcon->conn_state = HID_CONN_STATE_UNUSED; 874 } 875 876 return (HID_SUCCESS); 877 } 878 879 /******************************************************************************* 880 * 881 * Function hidd_conn_send_data 882 * 883 * Description Sends data to host 884 * 885 * Returns tHID_STATUS 886 * 887 ******************************************************************************/ 888 tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, 889 uint8_t param, uint8_t data, uint16_t len, 890 uint8_t* p_data) { 891 tHID_CONN* p_hcon; 892 BT_HDR* p_buf; 893 uint8_t* p_out; 894 uint16_t cid; 895 uint16_t buf_size; 896 897 HIDD_TRACE_VERBOSE("%s: channel(%d), msg_type(%d), len(%d)", __func__, 898 channel, msg_type, len); 899 900 p_hcon = &hd_cb.device.conn; 901 902 if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) { 903 return HID_ERR_CONGESTED; 904 } 905 906 switch (msg_type) { 907 case HID_TRANS_HANDSHAKE: 908 case HID_TRANS_CONTROL: 909 cid = p_hcon->ctrl_cid; 910 buf_size = HID_CONTROL_BUF_SIZE; 911 break; 912 case HID_TRANS_DATA: 913 if (channel == HID_CHANNEL_CTRL) { 914 cid = p_hcon->ctrl_cid; 915 buf_size = HID_CONTROL_BUF_SIZE; 916 } else { 917 cid = p_hcon->intr_cid; 918 buf_size = HID_INTERRUPT_BUF_SIZE; 919 } 920 break; 921 default: 922 return (HID_ERR_INVALID_PARAM); 923 } 924 925 p_buf = (BT_HDR*)osi_malloc(buf_size); 926 if (p_buf == NULL) return (HID_ERR_NO_RESOURCES); 927 928 p_buf->offset = L2CAP_MIN_OFFSET; 929 930 p_out = (uint8_t*)(p_buf + 1) + p_buf->offset; 931 932 *p_out = HID_BUILD_HDR(msg_type, param); 933 p_out++; 934 935 p_buf->len = 1; // start with header only 936 937 // add report id prefix only if non-zero (which is reserved) 938 if (msg_type == HID_TRANS_DATA && (data || param == HID_PAR_REP_TYPE_OTHER)) { 939 *p_out = data; // report_id 940 p_out++; 941 p_buf->len++; 942 } 943 944 if (len > 0 && p_data != NULL) { 945 memcpy(p_out, p_data, len); 946 p_buf->len += len; 947 } 948 949 // check if connected 950 if (hd_cb.device.state != HIDD_DEV_CONNECTED) { 951 // for DATA on intr we hold transfer and try to reconnect 952 if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) { 953 // drop previous data, we do not queue it for now 954 if (hd_cb.pending_data) { 955 osi_free(hd_cb.pending_data); 956 } 957 958 hd_cb.pending_data = p_buf; 959 960 if (hd_cb.device.conn.conn_state == HID_CONN_STATE_UNUSED) { 961 hidd_conn_initiate(); 962 } 963 964 return HID_SUCCESS; 965 } 966 967 return HID_ERR_NO_CONNECTION; 968 } 969 970 #ifdef REPORT_TRANSFER_TIMESTAMP 971 if (report_transfer) { 972 HIDD_TRACE_ERROR("%s: report sent", __func__); 973 } 974 #endif 975 HIDD_TRACE_VERBOSE("%s: report sent", __func__); 976 977 if (!L2CA_DataWrite(cid, p_buf)) return (HID_ERR_CONGESTED); 978 979 return (HID_SUCCESS); 980 } 981