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*******************************************************************************/ 50void 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*******************************************************************************/ 69void 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*******************************************************************************/ 101UINT8 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*******************************************************************************/ 121tMCA_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_API2 ("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_ERROR0 ("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_ERROR0 ("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*******************************************************************************/ 189void MCA_Deregister(tMCA_HANDLE handle) 190{ 191 tMCA_RCB *p_rcb = mca_rcb_by_handle(handle); 192 193 MCA_TRACE_API1 ("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*******************************************************************************/ 217tMCA_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_API1 ("MCA_CreateDep: %d", handle); 229 if (p_rcb) 230 { 231 if (p_cs->max_mdl > MCA_NUM_MDLS) 232 { 233 MCA_TRACE_ERROR1 ("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_ERROR0 ("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*******************************************************************************/ 287tMCA_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_API2 ("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*******************************************************************************/ 335tMCA_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_API2 ("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_ERROR0 ("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*******************************************************************************/ 391tMCA_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_API1 ("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*******************************************************************************/ 423tMCA_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_API4 ("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_ERROR0 ("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_ERROR2 ("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_ERROR1 ("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*******************************************************************************/ 501tMCA_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_API5 ("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_ERROR0 ("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_ERROR0 ("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*******************************************************************************/ 569tMCA_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_API1 ("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*******************************************************************************/ 599tMCA_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_API1 ("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_ERROR0 ("pending req"); 614 return MCA_BUSY; 615 } 616 617 if (!MCA_IS_VALID_MDL_ID(mdl_id)) 618 { 619 MCA_TRACE_ERROR1 ("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_ERROR1 ("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*******************************************************************************/ 667tMCA_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_API1 ("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_ERROR0 ("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_ERROR0 ("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_ERROR0 ("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*******************************************************************************/ 734tMCA_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_API1 ("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_ERROR1 ("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*******************************************************************************/ 781tMCA_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_API1 ("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_ERROR1 ("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_ERROR0 ("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*******************************************************************************/ 831tMCA_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_API1 ("MCA_Delete: %d ", mcl); 838 if (p_ccb) 839 { 840 if (p_ccb->cong) 841 { 842 MCA_TRACE_ERROR0 ("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_ERROR1 ("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*******************************************************************************/ 883tMCA_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_API1 ("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*******************************************************************************/ 915UINT16 MCA_GetL2CapChannel (tMCA_DL mdl) 916{ 917 UINT16 lcid = 0; 918 tMCA_DCB *p_dcb = mca_dcb_by_hdl(mdl); 919 920 MCA_TRACE_API1 ("MCA_GetL2CapChannel: %d ", mdl); 921 if (p_dcb) 922 lcid = p_dcb->lcid; 923 return lcid; 924} 925 926