/******************************************************************************* ** ** Function mca_dcb_close_by_mdl_id ** ** Description This function finds the DCB for a mdl_id and ** disconnect the mdl ** ** Returns void ** *******************************************************************************/ void mca_dcb_close_by_mdl_id(tMCA_CCB*p_ccb, UINT16 mdl_id) { tMCA_DCB *p_dcb; unsigned int i; MCA_TRACE_DEBUG("mca_dcb_close_by_mdl_id mdl_id=%d", mdl_id); i = mca_ccb_to_hdl(p_ccb)-1; if( i*MCA_NUM_MDLS < MCA_NUM_DCBS) p_dcb = &mca_cb.dcb[i*MCA_NUM_MDLS]; else { MCA_TRACE_WARNING("dcb index out of range"); return; } for (i=0; i<MCA_NUM_MDLS; i++, p_dcb++) { if (p_dcb->state) { if (p_dcb->mdl_id == mdl_id) { mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL); break; } else if (mdl_id == MCA_ALL_MDL_ID) { mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL); } } } }
/******************************************************************************* ** ** Function mca_ccb_snd_req ** ** Description This function builds a request and sends it to the peer. ** ** Returns void. ** *******************************************************************************/ void mca_ccb_snd_req(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data) { tMCA_CCB_MSG *p_msg = (tMCA_CCB_MSG *)p_data; BT_HDR *p_pkt; UINT8 *p, *p_start; BOOLEAN is_abort = FALSE; tMCA_DCB *p_dcb; MCA_TRACE_DEBUG ("mca_ccb_snd_req cong=%d req=%d", p_ccb->cong, p_msg->op_code); /* check for abort request */ if ((p_ccb->status == MCA_CCB_STAT_PENDING) && (p_msg->op_code == MCA_OP_MDL_ABORT_REQ)) { p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx); /* the Abort API does not have the associated mdl_id. * Get the mdl_id in dcb to compose the request */ if (p_dcb) { p_msg->mdl_id = p_dcb->mdl_id; mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL); } mca_free_buf ((void **)&p_ccb->p_tx_req); p_ccb->status = MCA_CCB_STAT_NORM; is_abort = TRUE; } /* no pending outgoing messages or it's an abort request for a pending data channel */ if ((!p_ccb->p_tx_req) || is_abort) { p_ccb->p_tx_req = p_msg; if (!p_ccb->cong) { p_pkt = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU); if (p_pkt) { p_pkt->offset = L2CAP_MIN_OFFSET; p = p_start = (UINT8*)(p_pkt + 1) + L2CAP_MIN_OFFSET; *p++ = p_msg->op_code; UINT16_TO_BE_STREAM (p, p_msg->mdl_id); if (p_msg->op_code == MCA_OP_MDL_CREATE_REQ) { *p++ = p_msg->mdep_id; *p++ = p_msg->param; } p_msg->hdr.layer_specific = TRUE; /* mark this message as sent */ p_pkt->len = p - p_start; L2CA_DataWrite (p_ccb->lcid, p_pkt); p_ccb->timer_entry.param = (TIMER_PARAM_TYPE) p_ccb; btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_MCA_CCB_RSP, p_ccb->p_rcb->reg.rsp_tout); } } /* else the L2CAP channel is congested. keep the message to be sent later */ } else { MCA_TRACE_WARNING ("dropping api req"); GKI_freebuf (p_data); } }
/******************************************************************************* ** ** Function mca_dcb_do_disconn ** ** Description This function closes a data channel. ** ** Returns void. ** *******************************************************************************/ void mca_dcb_do_disconn (tMCA_DCB *p_dcb, tMCA_DCB_EVT *p_data) { tMCA_CLOSE close; UNUSED(p_data); if ((p_dcb->lcid == 0) || (L2CA_DisconnectReq(p_dcb->lcid) == FALSE)) { close.param = MCA_INT; close.reason = L2CAP_DISC_OK; close.lcid = 0; mca_dcb_event(p_dcb, MCA_DCB_TC_CLOSE_EVT, (tMCA_DCB_EVT *) &close); } }