1 /****************************************************************************** 2 * 3 * Copyright (C) 2009-2012 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 /****************************************************************************** 20 * 21 * This is the API implementation file for the Multi-Channel Adaptation 22 * Protocol (MCAP). 23 * 24 ******************************************************************************/ 25 #include <string.h> 26 27 #include "bt_target.h" 28 #include "btm_api.h" 29 #include "btm_int.h" 30 #include "mca_api.h" 31 #include "mca_defs.h" 32 #include "mca_int.h" 33 34 #include "wcassert.h" 35 #include "btu.h" 36 37 38 /******************************************************************************* 39 ** 40 ** Function mca_process_timeout 41 ** 42 ** Description This function is called by BTU when an MCA timer 43 ** expires. 44 ** 45 ** This function is for use internal to the stack only. 46 ** 47 ** Returns void 48 ** 49 *******************************************************************************/ 50 void mca_process_timeout(TIMER_LIST_ENT *p_tle) 51 { 52 if(p_tle->event == BTU_TTYPE_MCA_CCB_RSP) 53 { 54 p_tle->event = 0; 55 mca_ccb_event ((tMCA_CCB *) p_tle->param, MCA_CCB_RSP_TOUT_EVT, NULL); 56 } 57 } 58 59 /******************************************************************************* 60 ** 61 ** Function MCA_Init 62 ** 63 ** Description Initialize MCAP main control block. 64 ** This function is called at stack start up. 65 ** 66 ** Returns void 67 ** 68 *******************************************************************************/ 69 void MCA_Init(void) 70 { 71 memset(&mca_cb, 0, sizeof(tMCA_CB)); 72 73 #if defined(MCA_INITIAL_TRACE_LEVEL) 74 mca_cb.trace_level = MCA_INITIAL_TRACE_LEVEL; 75 #else 76 mca_cb.trace_level = BT_TRACE_LEVEL_NONE; 77 #endif 78 } 79 80 /******************************************************************************* 81 ** 82 ** Function MCA_SetTraceLevel 83 ** 84 ** Description This function sets the debug trace level for MCA. 85 ** If 0xff is passed, the current trace level is returned. 86 ** 87 ** Input Parameters: 88 ** level: The level to set the MCA tracing to: 89 ** 0xff-returns the current setting. 90 ** 0-turns off tracing. 91 ** >= 1-Errors. 92 ** >= 2-Warnings. 93 ** >= 3-APIs. 94 ** >= 4-Events. 95 ** >= 5-Debug. 96 ** 97 ** Returns The new trace level or current trace level if 98 ** the input parameter is 0xff. 99 ** 100 *******************************************************************************/ 101 UINT8 MCA_SetTraceLevel (UINT8 level) 102 { 103 if (level != 0xFF) 104 mca_cb.trace_level = level; 105 106 return (mca_cb.trace_level); 107 } 108 109 /******************************************************************************* 110 ** 111 ** Function MCA_Register 112 ** 113 ** Description This function registers an MCAP implementation. 114 ** It is assumed that the control channel PSM and data channel 115 ** PSM are not used by any other instances of the stack. 116 ** If the given p_reg->ctrl_psm is 0, this handle is INT only. 117 ** 118 ** Returns 0, if failed. Otherwise, the MCA handle. 119 ** 120 *******************************************************************************/ 121 tMCA_HANDLE MCA_Register(tMCA_REG *p_reg, tMCA_CTRL_CBACK *p_cback) 122 { 123 tMCA_RCB *p_rcb; 124 tMCA_HANDLE handle = 0; 125 tL2CAP_APPL_INFO l2c_cacp_appl; 126 tL2CAP_APPL_INFO l2c_dacp_appl; 127 128 WC_ASSERT(p_reg != NULL ); 129 WC_ASSERT(p_cback != NULL ); 130 131 MCA_TRACE_API ("MCA_Register: ctrl_psm:0x%x, data_psm:0x%x", p_reg->ctrl_psm, p_reg->data_psm); 132 133 if ( (p_rcb = mca_rcb_alloc (p_reg)) != NULL) 134 { 135 if (p_reg->ctrl_psm) 136 { 137 if (L2C_INVALID_PSM(p_reg->ctrl_psm) || L2C_INVALID_PSM(p_reg->data_psm)) 138 { 139 MCA_TRACE_ERROR ("INVALID_PSM"); 140 return 0; 141 } 142 143 l2c_cacp_appl = *(tL2CAP_APPL_INFO *)&mca_l2c_int_appl; 144 l2c_cacp_appl.pL2CA_ConnectCfm_Cb = NULL; 145 l2c_dacp_appl = *(tL2CAP_APPL_INFO *)&l2c_cacp_appl; 146 l2c_cacp_appl.pL2CA_ConnectInd_Cb = mca_l2c_cconn_ind_cback; 147 l2c_dacp_appl.pL2CA_ConnectInd_Cb = mca_l2c_dconn_ind_cback; 148 if (L2CA_Register(p_reg->ctrl_psm, (tL2CAP_APPL_INFO *) &l2c_cacp_appl) && 149 L2CA_Register(p_reg->data_psm, (tL2CAP_APPL_INFO *) &l2c_dacp_appl)) 150 { 151 /* set security level */ 152 BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_MCAP_CTRL, p_reg->sec_mask, 153 p_reg->ctrl_psm, BTM_SEC_PROTO_MCA, MCA_CTRL_TCID); 154 155 /* in theory, we do not need this one for data_psm 156 * If we don't, L2CAP rejects with security block (3), 157 * which is different reject code from what MCAP spec suggests. 158 * we set this one, so mca_l2c_dconn_ind_cback can reject /w no resources (4) */ 159 BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_MCAP_DATA, p_reg->sec_mask, 160 p_reg->data_psm, BTM_SEC_PROTO_MCA, MCA_CTRL_TCID); 161 } 162 else 163 { 164 MCA_TRACE_ERROR ("Failed to register to L2CAP"); 165 return 0; 166 } 167 } 168 else 169 p_rcb->reg.data_psm = 0; 170 handle = mca_rcb_to_handle (p_rcb); 171 p_rcb->p_cback = p_cback; 172 p_rcb->reg.rsp_tout = p_reg->rsp_tout; 173 } 174 return handle; 175 } 176 177 178 /******************************************************************************* 179 ** 180 ** Function MCA_Deregister 181 ** 182 ** Description This function is called to deregister an MCAP implementation. 183 ** Before this function can be called, all control and data 184 ** channels must be removed with MCA_DisconnectReq and MCA_CloseReq. 185 ** 186 ** Returns void 187 ** 188 *******************************************************************************/ 189 void MCA_Deregister(tMCA_HANDLE handle) 190 { 191 tMCA_RCB *p_rcb = mca_rcb_by_handle(handle); 192 193 MCA_TRACE_API ("MCA_Deregister: %d", handle); 194 if (p_rcb && p_rcb->reg.ctrl_psm) 195 { 196 L2CA_Deregister(p_rcb->reg.ctrl_psm); 197 L2CA_Deregister(p_rcb->reg.data_psm); 198 btm_sec_clr_service_by_psm (p_rcb->reg.ctrl_psm); 199 btm_sec_clr_service_by_psm (p_rcb->reg.data_psm); 200 } 201 mca_rcb_dealloc(handle); 202 } 203 204 205 /******************************************************************************* 206 ** 207 ** Function MCA_CreateDep 208 ** 209 ** Description Create a data endpoint. If the MDEP is created successfully, 210 ** the MDEP ID is returned in *p_dep. After a data endpoint is 211 ** created, an application can initiate a connection between this 212 ** endpoint and an endpoint on a peer device. 213 ** 214 ** Returns MCA_SUCCESS if successful, otherwise error. 215 ** 216 *******************************************************************************/ 217 tMCA_RESULT MCA_CreateDep(tMCA_HANDLE handle, tMCA_DEP *p_dep, tMCA_CS *p_cs) 218 { 219 tMCA_RESULT result = MCA_BAD_HANDLE; 220 int i; 221 tMCA_RCB *p_rcb = mca_rcb_by_handle(handle); 222 tMCA_CS *p_depcs; 223 224 WC_ASSERT(p_dep != NULL ); 225 WC_ASSERT(p_cs != NULL ); 226 WC_ASSERT(p_cs->p_data_cback != NULL ); 227 228 MCA_TRACE_API ("MCA_CreateDep: %d", handle); 229 if (p_rcb) 230 { 231 if (p_cs->max_mdl > MCA_NUM_MDLS) 232 { 233 MCA_TRACE_ERROR ("max_mdl: %d is too big", p_cs->max_mdl ); 234 result = MCA_BAD_PARAMS; 235 } 236 else 237 { 238 p_depcs = p_rcb->dep; 239 if (p_cs->type == MCA_TDEP_ECHO) 240 { 241 if (p_depcs->p_data_cback) 242 { 243 MCA_TRACE_ERROR ("Already has ECHO MDEP"); 244 return MCA_NO_RESOURCES; 245 } 246 memcpy (p_depcs, p_cs, sizeof (tMCA_CS)); 247 *p_dep = 0; 248 result = MCA_SUCCESS; 249 } 250 else 251 { 252 result = MCA_NO_RESOURCES; 253 /* non-echo MDEP starts from 1 */ 254 p_depcs++; 255 for (i=1; i<MCA_NUM_DEPS; i++, p_depcs++) 256 { 257 if (p_depcs->p_data_cback == NULL) 258 { 259 memcpy (p_depcs, p_cs, sizeof (tMCA_CS)); 260 /* internally use type as the mdep id */ 261 p_depcs->type = i; 262 *p_dep = i; 263 result = MCA_SUCCESS; 264 break; 265 } 266 } 267 } 268 } 269 } 270 return result; 271 } 272 273 274 /******************************************************************************* 275 ** 276 ** Function MCA_DeleteDep 277 ** 278 ** Description Delete a data endpoint. This function is called when 279 ** the implementation is no longer using a data endpoint. 280 ** If this function is called when the endpoint is connected 281 ** the connection is closed and the data endpoint 282 ** is removed. 283 ** 284 ** Returns MCA_SUCCESS if successful, otherwise error. 285 ** 286 *******************************************************************************/ 287 tMCA_RESULT MCA_DeleteDep(tMCA_HANDLE handle, tMCA_DEP dep) 288 { 289 tMCA_RESULT result = MCA_BAD_HANDLE; 290 tMCA_RCB *p_rcb = mca_rcb_by_handle(handle); 291 tMCA_DCB *p_dcb; 292 int i, max; 293 tMCA_CS *p_depcs; 294 295 MCA_TRACE_API ("MCA_DeleteDep: %d dep:%d", handle, dep); 296 if (p_rcb) 297 { 298 if (dep < MCA_NUM_DEPS && p_rcb->dep[dep].p_data_cback) 299 { 300 result = MCA_SUCCESS; 301 p_rcb->dep[dep].p_data_cback = NULL; 302 p_depcs = &(p_rcb->dep[dep]); 303 i = handle - 1; 304 max = MCA_NUM_MDLS*MCA_NUM_LINKS; 305 p_dcb = &mca_cb.dcb[i*max]; 306 /* make sure no MDL exists for this MDEP */ 307 for (i=0; i<max; i++, p_dcb++) 308 { 309 if (p_dcb->state && p_dcb->p_cs == p_depcs) 310 { 311 mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL); 312 } 313 } 314 } 315 } 316 return result; 317 } 318 319 /******************************************************************************* 320 ** 321 ** Function MCA_ConnectReq 322 ** 323 ** Description This function initiates an MCAP control channel connection 324 ** to the peer device. When the connection is completed, an 325 ** MCA_CONNECT_IND_EVT is reported to the application via its 326 ** control callback function. 327 ** This control channel is identified by the tMCA_CL. 328 ** If the connection attempt fails, an MCA_DISCONNECT_IND_EVT is 329 ** reported. The security mask parameter overrides the outgoing 330 ** security mask set in MCA_Register(). 331 ** 332 ** Returns MCA_SUCCESS if successful, otherwise error. 333 ** 334 *******************************************************************************/ 335 tMCA_RESULT MCA_ConnectReq(tMCA_HANDLE handle, BD_ADDR bd_addr, 336 UINT16 ctrl_psm, UINT16 sec_mask) 337 { 338 tMCA_RESULT result = MCA_BAD_HANDLE; 339 tMCA_CCB *p_ccb; 340 tMCA_TC_TBL *p_tbl; 341 342 MCA_TRACE_API ("MCA_ConnectReq: %d psm:0x%x", handle, ctrl_psm); 343 if ((p_ccb = mca_ccb_by_bd(handle, bd_addr)) == NULL) 344 p_ccb = mca_ccb_alloc(handle, bd_addr); 345 else 346 { 347 MCA_TRACE_ERROR ("control channel already exists"); 348 return MCA_BUSY; 349 } 350 351 if (p_ccb) 352 { 353 p_ccb->ctrl_vpsm = L2CA_Register (ctrl_psm, (tL2CAP_APPL_INFO *)&mca_l2c_int_appl); 354 result = MCA_NO_RESOURCES; 355 if (p_ccb->ctrl_vpsm) 356 { 357 BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_MCAP_CTRL, sec_mask, 358 p_ccb->ctrl_vpsm, BTM_SEC_PROTO_MCA, MCA_CTRL_TCID); 359 p_ccb->lcid = mca_l2c_open_req(bd_addr, p_ccb->ctrl_vpsm, NULL); 360 if (p_ccb->lcid) 361 { 362 p_tbl = mca_tc_tbl_calloc(p_ccb); 363 if (p_tbl) 364 { 365 p_tbl->state = MCA_TC_ST_CONN; 366 p_ccb->sec_mask = sec_mask; 367 result = MCA_SUCCESS; 368 } 369 } 370 } 371 if (result != MCA_SUCCESS) 372 mca_ccb_dealloc (p_ccb, NULL); 373 } 374 return result; 375 } 376 377 378 /******************************************************************************* 379 ** 380 ** Function MCA_DisconnectReq 381 ** 382 ** Description This function disconnect an MCAP control channel 383 ** to the peer device. 384 ** If associated data channel exists, they are disconnected. 385 ** When the MCL is disconnected an MCA_DISCONNECT_IND_EVT is 386 ** reported to the application via its control callback function. 387 ** 388 ** Returns MCA_SUCCESS if successful, otherwise error. 389 ** 390 *******************************************************************************/ 391 tMCA_RESULT MCA_DisconnectReq(tMCA_CL mcl) 392 { 393 tMCA_RESULT result = MCA_BAD_HANDLE; 394 tMCA_CCB *p_ccb = mca_ccb_by_hdl(mcl); 395 396 MCA_TRACE_API ("MCA_DisconnectReq: %d ", mcl); 397 if (p_ccb) 398 { 399 result = MCA_SUCCESS; 400 mca_ccb_event (p_ccb, MCA_CCB_API_DISCONNECT_EVT, NULL); 401 } 402 return result; 403 } 404 405 406 /******************************************************************************* 407 ** 408 ** Function MCA_CreateMdl 409 ** 410 ** Description This function sends a CREATE_MDL request to the peer device. 411 ** When the response is received, a MCA_CREATE_CFM_EVT is reported 412 ** with the given MDL ID. 413 ** If the response is successful, a data channel is open 414 ** with the given p_chnl_cfg 415 ** If p_chnl_cfg is NULL, the data channel is not initiated until 416 ** MCA_DataChnlCfg is called to provide the p_chnl_cfg. 417 ** When the data channel is open successfully, a MCA_OPEN_CFM_EVT 418 ** is reported. This data channel is identified as tMCA_DL. 419 ** 420 ** Returns MCA_SUCCESS if successful, otherwise error. 421 ** 422 *******************************************************************************/ 423 tMCA_RESULT MCA_CreateMdl(tMCA_CL mcl, tMCA_DEP dep, UINT16 data_psm, 424 UINT16 mdl_id, UINT8 peer_dep_id, 425 UINT8 cfg, const tMCA_CHNL_CFG *p_chnl_cfg) 426 { 427 tMCA_RESULT result = MCA_BAD_HANDLE; 428 tMCA_CCB *p_ccb = mca_ccb_by_hdl(mcl); 429 tMCA_CCB_MSG *p_evt_data; 430 tMCA_DCB *p_dcb; 431 432 MCA_TRACE_API ("MCA_CreateMdl: %d dep=%d mdl_id=%d peer_dep_id=%d", mcl, dep, mdl_id, peer_dep_id); 433 if (p_ccb) 434 { 435 if (p_ccb->p_tx_req || p_ccb->p_rx_msg || p_ccb->cong) 436 { 437 MCA_TRACE_ERROR ("pending req"); 438 return MCA_BUSY; 439 } 440 441 if ((peer_dep_id > MCA_MAX_MDEP_ID) || (!MCA_IS_VALID_MDL_ID(mdl_id))) 442 { 443 MCA_TRACE_ERROR ("bad peer dep id:%d or bad mdl id: %d ", peer_dep_id, mdl_id); 444 return MCA_BAD_PARAMS; 445 } 446 447 if (mca_ccb_uses_mdl_id(p_ccb, mdl_id)) 448 { 449 MCA_TRACE_ERROR ("mdl id: %d is used in the control link", mdl_id); 450 return MCA_BAD_MDL_ID; 451 } 452 453 p_dcb = mca_dcb_alloc(p_ccb, dep); 454 result = MCA_NO_RESOURCES; 455 if (p_dcb) 456 { 457 /* save the info required by dcb connection */ 458 p_dcb->p_chnl_cfg = p_chnl_cfg; 459 p_dcb->mdl_id = mdl_id; 460 p_evt_data = (tMCA_CCB_MSG *)GKI_getbuf (sizeof(tMCA_CCB_MSG)); 461 if (p_evt_data) 462 { 463 if (!p_ccb->data_vpsm) 464 p_ccb->data_vpsm = L2CA_Register (data_psm, (tL2CAP_APPL_INFO *)&mca_l2c_int_appl); 465 if (p_ccb->data_vpsm) 466 { 467 p_evt_data->dcb_idx = mca_dcb_to_hdl (p_dcb); 468 p_evt_data->mdep_id = peer_dep_id; 469 p_evt_data->mdl_id = mdl_id; 470 p_evt_data->param = cfg; 471 p_evt_data->op_code = MCA_OP_MDL_CREATE_REQ; 472 p_evt_data->hdr.event = MCA_CCB_API_REQ_EVT; 473 p_evt_data->hdr.layer_specific = FALSE; 474 mca_ccb_event(p_ccb, MCA_CCB_API_REQ_EVT, (tMCA_CCB_EVT *)p_evt_data); 475 return MCA_SUCCESS; 476 } 477 else 478 GKI_freebuf (p_evt_data); 479 } 480 mca_dcb_dealloc(p_dcb, NULL); 481 } 482 } 483 return result; 484 } 485 486 487 /******************************************************************************* 488 ** 489 ** Function MCA_CreateMdlRsp 490 ** 491 ** Description This function sends a CREATE_MDL response to the peer device 492 ** in response to a received MCA_CREATE_IND_EVT. 493 ** If the rsp_code is successful, a data channel is open 494 ** with the given p_chnl_cfg 495 ** When the data channel is open successfully, a MCA_OPEN_IND_EVT 496 ** is reported. This data channel is identified as tMCA_DL. 497 ** 498 ** Returns MCA_SUCCESS if successful, otherwise error. 499 ** 500 *******************************************************************************/ 501 tMCA_RESULT MCA_CreateMdlRsp(tMCA_CL mcl, tMCA_DEP dep, 502 UINT16 mdl_id, UINT8 cfg, UINT8 rsp_code, 503 const tMCA_CHNL_CFG *p_chnl_cfg) 504 { 505 tMCA_RESULT result = MCA_BAD_HANDLE; 506 tMCA_CCB *p_ccb = mca_ccb_by_hdl(mcl); 507 tMCA_CCB_MSG evt_data; 508 tMCA_DCB *p_dcb; 509 510 MCA_TRACE_API ("MCA_CreateMdlRsp: %d dep=%d mdl_id=%d cfg=%d rsp_code=%d", mcl, dep, mdl_id, cfg, rsp_code); 511 WC_ASSERT(p_chnl_cfg != NULL ); 512 if (p_ccb) 513 { 514 if (p_ccb->cong) 515 { 516 MCA_TRACE_ERROR ("congested"); 517 return MCA_BUSY; 518 } 519 if (p_ccb->p_rx_msg && (p_ccb->p_rx_msg->mdep_id == dep ) 520 && (p_ccb->p_rx_msg->mdl_id == mdl_id) && (p_ccb->p_rx_msg->op_code == MCA_OP_MDL_CREATE_REQ)) 521 { 522 result = MCA_SUCCESS; 523 evt_data.dcb_idx = 0; 524 if (rsp_code == MCA_RSP_SUCCESS) 525 { 526 p_dcb = mca_dcb_alloc(p_ccb, dep); 527 if (p_dcb) 528 { 529 evt_data.dcb_idx = mca_dcb_to_hdl(p_dcb); 530 p_dcb->p_chnl_cfg = p_chnl_cfg; 531 p_dcb->mdl_id = mdl_id; 532 } 533 else 534 { 535 rsp_code = MCA_RSP_MDEP_BUSY; 536 result = MCA_NO_RESOURCES; 537 } 538 } 539 540 if (result == MCA_SUCCESS) 541 { 542 evt_data.mdl_id = mdl_id; 543 evt_data.param = cfg; 544 evt_data.rsp_code = rsp_code; 545 evt_data.op_code = MCA_OP_MDL_CREATE_RSP; 546 mca_ccb_event(p_ccb, MCA_CCB_API_RSP_EVT, (tMCA_CCB_EVT *)&evt_data); 547 } 548 } 549 else 550 { 551 MCA_TRACE_ERROR ("The given MCL is not expecting a MCA_CreateMdlRsp with the given parameters" ); 552 result = MCA_BAD_PARAMS; 553 } 554 } 555 return result; 556 } 557 558 /******************************************************************************* 559 ** 560 ** Function MCA_CloseReq 561 ** 562 ** Description Close a data channel. When the channel is closed, an 563 ** MCA_CLOSE_CFM_EVT is sent to the application via the 564 ** control callback function for this handle. 565 ** 566 ** Returns MCA_SUCCESS if successful, otherwise error. 567 ** 568 *******************************************************************************/ 569 tMCA_RESULT MCA_CloseReq(tMCA_DL mdl) 570 { 571 tMCA_RESULT result = MCA_BAD_HANDLE; 572 tMCA_DCB *p_dcb = mca_dcb_by_hdl(mdl); 573 574 MCA_TRACE_API ("MCA_CloseReq: %d ", mdl); 575 if (p_dcb) 576 { 577 result = MCA_SUCCESS; 578 mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL); 579 } 580 return result; 581 } 582 583 584 /******************************************************************************* 585 ** 586 ** Function MCA_ReconnectMdl 587 ** 588 ** Description This function sends a RECONNECT_MDL request to the peer device. 589 ** When the response is received, a MCA_RECONNECT_CFM_EVT is reported. 590 ** If p_chnl_cfg is NULL, the data channel is not initiated until 591 ** MCA_DataChnlCfg is called to provide the p_chnl_cfg. 592 ** If the response is successful, a data channel is open. 593 ** When the data channel is open successfully, a MCA_OPEN_CFM_EVT 594 ** is reported. 595 ** 596 ** Returns MCA_SUCCESS if successful, otherwise error. 597 ** 598 *******************************************************************************/ 599 tMCA_RESULT MCA_ReconnectMdl(tMCA_CL mcl, tMCA_DEP dep, UINT16 data_psm, 600 UINT16 mdl_id, const tMCA_CHNL_CFG *p_chnl_cfg) 601 { 602 tMCA_RESULT result = MCA_BAD_HANDLE; 603 tMCA_CCB *p_ccb = mca_ccb_by_hdl(mcl); 604 tMCA_CCB_MSG *p_evt_data; 605 tMCA_DCB *p_dcb; 606 607 MCA_TRACE_API ("MCA_ReconnectMdl: %d ", mcl); 608 WC_ASSERT(p_chnl_cfg != NULL ); 609 if (p_ccb) 610 { 611 if (p_ccb->p_tx_req || p_ccb->p_rx_msg || p_ccb->cong) 612 { 613 MCA_TRACE_ERROR ("pending req"); 614 return MCA_BUSY; 615 } 616 617 if (!MCA_IS_VALID_MDL_ID(mdl_id)) 618 { 619 MCA_TRACE_ERROR ("bad mdl id: %d ", mdl_id); 620 return MCA_BAD_PARAMS; 621 } 622 623 if (mca_ccb_uses_mdl_id(p_ccb, mdl_id)) 624 { 625 MCA_TRACE_ERROR ("mdl id: %d is used in the control link", mdl_id); 626 return MCA_BAD_MDL_ID; 627 } 628 629 p_dcb = mca_dcb_alloc(p_ccb, dep); 630 result = MCA_NO_RESOURCES; 631 if (p_dcb) 632 { 633 p_dcb->p_chnl_cfg = p_chnl_cfg; 634 p_dcb->mdl_id = mdl_id; 635 p_evt_data = (tMCA_CCB_MSG *)GKI_getbuf (sizeof(tMCA_CCB_MSG)); 636 if (p_evt_data) 637 { 638 if (!p_ccb->data_vpsm) 639 p_ccb->data_vpsm = L2CA_Register (data_psm, (tL2CAP_APPL_INFO *)&mca_l2c_int_appl); 640 p_evt_data->dcb_idx = mca_dcb_to_hdl(p_dcb); 641 p_evt_data->mdl_id = mdl_id; 642 p_evt_data->op_code = MCA_OP_MDL_RECONNECT_REQ; 643 p_evt_data->hdr.event = MCA_CCB_API_REQ_EVT; 644 mca_ccb_event(p_ccb, MCA_CCB_API_REQ_EVT, (tMCA_CCB_EVT *)p_evt_data); 645 return MCA_SUCCESS; 646 } 647 mca_dcb_dealloc(p_dcb, NULL); 648 } 649 } 650 return result; 651 } 652 653 654 /******************************************************************************* 655 ** 656 ** Function MCA_ReconnectMdlRsp 657 ** 658 ** Description This function sends a RECONNECT_MDL response to the peer device 659 ** in response to a MCA_RECONNECT_IND_EVT event. 660 ** If the response is successful, a data channel is open. 661 ** When the data channel is open successfully, a MCA_OPEN_IND_EVT 662 ** is reported. 663 ** 664 ** Returns MCA_SUCCESS if successful, otherwise error. 665 ** 666 *******************************************************************************/ 667 tMCA_RESULT MCA_ReconnectMdlRsp(tMCA_CL mcl, tMCA_DEP dep, 668 UINT16 mdl_id, UINT8 rsp_code, 669 const tMCA_CHNL_CFG *p_chnl_cfg) 670 { 671 tMCA_RESULT result = MCA_BAD_HANDLE; 672 tMCA_CCB *p_ccb = mca_ccb_by_hdl(mcl); 673 tMCA_CCB_MSG evt_data; 674 tMCA_DCB *p_dcb; 675 676 MCA_TRACE_API ("MCA_ReconnectMdlRsp: %d ", mcl); 677 WC_ASSERT(p_chnl_cfg != NULL ); 678 if (p_ccb) 679 { 680 if (p_ccb->cong) 681 { 682 MCA_TRACE_ERROR ("congested"); 683 return MCA_BUSY; 684 } 685 if (p_ccb->p_rx_msg && (p_ccb->p_rx_msg->mdl_id == mdl_id) && 686 (p_ccb->p_rx_msg->op_code == MCA_OP_MDL_RECONNECT_REQ)) 687 { 688 result = MCA_SUCCESS; 689 evt_data.dcb_idx = 0; 690 if (rsp_code == MCA_RSP_SUCCESS) 691 { 692 p_dcb = mca_dcb_alloc(p_ccb, dep); 693 if (p_dcb) 694 { 695 evt_data.dcb_idx = mca_dcb_to_hdl(p_dcb); 696 p_dcb->p_chnl_cfg = p_chnl_cfg; 697 p_dcb->mdl_id = mdl_id; 698 } 699 else 700 { 701 MCA_TRACE_ERROR ("Out of MDL for this MDEP"); 702 rsp_code = MCA_RSP_MDEP_BUSY; 703 result = MCA_NO_RESOURCES; 704 } 705 } 706 707 evt_data.mdl_id = mdl_id; 708 evt_data.rsp_code = rsp_code; 709 evt_data.op_code = MCA_OP_MDL_RECONNECT_RSP; 710 mca_ccb_event(p_ccb, MCA_CCB_API_RSP_EVT, (tMCA_CCB_EVT *)&evt_data); 711 } 712 else 713 { 714 MCA_TRACE_ERROR ("The given MCL is not expecting a MCA_ReconnectMdlRsp with the given parameters" ); 715 result = MCA_BAD_PARAMS; 716 } 717 } 718 return result; 719 } 720 721 722 /******************************************************************************* 723 ** 724 ** Function MCA_DataChnlCfg 725 ** 726 ** Description This function initiates a data channel connection toward the 727 ** connected peer device. 728 ** When the data channel is open successfully, a MCA_OPEN_CFM_EVT 729 ** is reported. This data channel is identified as tMCA_DL. 730 ** 731 ** Returns MCA_SUCCESS if successful, otherwise error. 732 ** 733 *******************************************************************************/ 734 tMCA_RESULT MCA_DataChnlCfg(tMCA_CL mcl, const tMCA_CHNL_CFG *p_chnl_cfg) 735 { 736 tMCA_RESULT result = MCA_BAD_HANDLE; 737 tMCA_CCB *p_ccb = mca_ccb_by_hdl(mcl); 738 tMCA_DCB *p_dcb; 739 tMCA_TC_TBL *p_tbl; 740 741 MCA_TRACE_API ("MCA_DataChnlCfg: %d ", mcl); 742 WC_ASSERT(p_chnl_cfg != NULL ); 743 if (p_ccb) 744 { 745 result = MCA_NO_RESOURCES; 746 if ((p_ccb->p_tx_req == NULL) || (p_ccb->status != MCA_CCB_STAT_PENDING) || 747 ((p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx)) == NULL)) 748 { 749 MCA_TRACE_ERROR ("The given MCL is not expecting this API:%d", p_ccb->status); 750 return result; 751 } 752 753 p_dcb->p_chnl_cfg = p_chnl_cfg; 754 BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_MCAP_DATA, p_ccb->sec_mask, 755 p_ccb->data_vpsm, BTM_SEC_PROTO_MCA, p_ccb->p_tx_req->dcb_idx); 756 p_dcb->lcid = mca_l2c_open_req(p_ccb->peer_addr, p_ccb->data_vpsm, p_dcb->p_chnl_cfg); 757 if (p_dcb->lcid) 758 { 759 p_tbl = mca_tc_tbl_dalloc(p_dcb); 760 if (p_tbl) 761 { 762 p_tbl->state = MCA_TC_ST_CONN; 763 result = MCA_SUCCESS; 764 } 765 } 766 } 767 return result; 768 } 769 770 771 /******************************************************************************* 772 ** 773 ** Function MCA_Abort 774 ** 775 ** Description This function sends a ABORT_MDL request to the peer device. 776 ** When the response is received, a MCA_ABORT_CFM_EVT is reported. 777 ** 778 ** Returns MCA_SUCCESS if successful, otherwise error. 779 ** 780 *******************************************************************************/ 781 tMCA_RESULT MCA_Abort(tMCA_CL mcl) 782 { 783 tMCA_RESULT result = MCA_BAD_HANDLE; 784 tMCA_CCB *p_ccb = mca_ccb_by_hdl(mcl); 785 tMCA_CCB_MSG *p_evt_data; 786 tMCA_DCB *p_dcb; 787 788 MCA_TRACE_API ("MCA_Abort: %d", mcl); 789 if (p_ccb) 790 { 791 result = MCA_NO_RESOURCES; 792 /* verify that we are waiting for data channel to come up with the given mdl */ 793 if ((p_ccb->p_tx_req == NULL) || (p_ccb->status != MCA_CCB_STAT_PENDING) || 794 ((p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx)) == NULL)) 795 { 796 MCA_TRACE_ERROR ("The given MCL is not expecting this API:%d", p_ccb->status); 797 return result; 798 } 799 800 if (p_ccb->cong) 801 { 802 MCA_TRACE_ERROR ("congested"); 803 return MCA_BUSY; 804 } 805 806 result = MCA_NO_RESOURCES; 807 p_evt_data = (tMCA_CCB_MSG *)GKI_getbuf (sizeof(tMCA_CCB_MSG)); 808 if (p_evt_data) 809 { 810 result = MCA_SUCCESS; 811 p_evt_data->op_code = MCA_OP_MDL_ABORT_REQ; 812 p_evt_data->hdr.event = MCA_CCB_API_REQ_EVT; 813 mca_ccb_event(p_ccb, MCA_CCB_API_REQ_EVT, (tMCA_CCB_EVT *)p_evt_data); 814 } 815 816 } 817 return result; 818 } 819 820 821 /******************************************************************************* 822 ** 823 ** Function MCA_Delete 824 ** 825 ** Description This function sends a DELETE_MDL request to the peer device. 826 ** When the response is received, a MCA_DELETE_CFM_EVT is reported. 827 ** 828 ** Returns MCA_SUCCESS if successful, otherwise error. 829 ** 830 *******************************************************************************/ 831 tMCA_RESULT MCA_Delete(tMCA_CL mcl, UINT16 mdl_id) 832 { 833 tMCA_RESULT result = MCA_BAD_HANDLE; 834 tMCA_CCB *p_ccb = mca_ccb_by_hdl(mcl); 835 tMCA_CCB_MSG *p_evt_data; 836 837 MCA_TRACE_API ("MCA_Delete: %d ", mcl); 838 if (p_ccb) 839 { 840 if (p_ccb->cong) 841 { 842 MCA_TRACE_ERROR ("congested"); 843 return MCA_BUSY; 844 } 845 if (!MCA_IS_VALID_MDL_ID(mdl_id) && (mdl_id != MCA_ALL_MDL_ID)) 846 { 847 MCA_TRACE_ERROR ("bad mdl id: %d ", mdl_id); 848 return MCA_BAD_PARAMS; 849 } 850 p_evt_data = (tMCA_CCB_MSG *)GKI_getbuf (sizeof(tMCA_CCB_MSG)); 851 if (p_evt_data) 852 { 853 result = MCA_SUCCESS; 854 p_evt_data->mdl_id = mdl_id; 855 p_evt_data->op_code = MCA_OP_MDL_DELETE_REQ; 856 p_evt_data->hdr.event = MCA_CCB_API_REQ_EVT; 857 mca_ccb_event(p_ccb, MCA_CCB_API_REQ_EVT, (tMCA_CCB_EVT *)p_evt_data); 858 } 859 else 860 result = MCA_NO_RESOURCES; 861 } 862 return result; 863 } 864 865 /******************************************************************************* 866 ** 867 ** Function MCA_WriteReq 868 ** 869 ** Description Send a data packet to the peer device. 870 ** 871 ** The application passes the packet using the BT_HDR structure. 872 ** The offset field must be equal to or greater than L2CAP_MIN_OFFSET. 873 ** This allows enough space in the buffer for the L2CAP header. 874 ** 875 ** The memory pointed to by p_pkt must be a GKI buffer 876 ** allocated by the application. This buffer will be freed 877 ** by the protocol stack; the application must not free 878 ** this buffer. 879 ** 880 ** Returns MCA_SUCCESS if successful, otherwise error. 881 ** 882 *******************************************************************************/ 883 tMCA_RESULT MCA_WriteReq(tMCA_DL mdl, BT_HDR *p_pkt) 884 { 885 tMCA_RESULT result = MCA_BAD_HANDLE; 886 tMCA_DCB *p_dcb = mca_dcb_by_hdl(mdl); 887 tMCA_DCB_EVT evt_data; 888 889 MCA_TRACE_API ("MCA_WriteReq: %d ", mdl); 890 if (p_dcb) 891 { 892 if (p_dcb->cong) 893 { 894 result = MCA_BUSY; 895 } 896 else 897 { 898 evt_data.p_pkt = p_pkt; 899 result = MCA_SUCCESS; 900 mca_dcb_event(p_dcb, MCA_DCB_API_WRITE_EVT, &evt_data); 901 } 902 } 903 return result; 904 } 905 906 /******************************************************************************* 907 ** 908 ** Function MCA_GetL2CapChannel 909 ** 910 ** Description Get the L2CAP CID used by the given data channel handle. 911 ** 912 ** Returns L2CAP channel ID if successful, otherwise 0. 913 ** 914 *******************************************************************************/ 915 UINT16 MCA_GetL2CapChannel (tMCA_DL mdl) 916 { 917 UINT16 lcid = 0; 918 tMCA_DCB *p_dcb = mca_dcb_by_hdl(mdl); 919 920 MCA_TRACE_API ("MCA_GetL2CapChannel: %d ", mdl); 921 if (p_dcb) 922 lcid = p_dcb->lcid; 923 return lcid; 924 } 925 926