/******************************************************************************* ** ** Function avdt_ad_open_req ** ** Description This function is called by a CCB or SCB to open a transport ** channel. This function allocates and initializes a ** transport channel table entry. The channel can be opened ** in two roles: as an initiator or acceptor. When opened ** as an initiator the function will start an L2CAP connection. ** When opened as an acceptor the function simply configures ** the table entry to listen for an incoming channel. ** ** ** Returns Nothing. ** *******************************************************************************/ void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role) { tAVDT_TC_TBL *p_tbl; UINT16 lcid; if ((p_tbl = avdt_ad_tc_tbl_alloc(p_ccb)) == NULL) { AVDT_TRACE_ERROR("avdt_ad_open_req: Cannot allocate p_tbl"); return; } p_tbl->tcid = avdt_ad_type_to_tcid(type, p_scb); AVDT_TRACE_DEBUG("avdt_ad_open_req: type: %d, role: %d, tcid:%d\n", type, role, p_tbl->tcid); if (type == AVDT_CHAN_SIG) { /* if signaling, get mtu from registration control block */ p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu; p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO; } else { /* otherwise get mtu from scb */ p_tbl->my_mtu = p_scb->cs.mtu; p_tbl->my_flush_to = p_scb->cs.flush_to; /* also set scb_hdl in rt_tbl */ avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].scb_hdl = avdt_scb_to_hdl(p_scb); AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].scb_hdl = %d\n", avdt_ccb_to_idx(p_ccb), p_tbl->tcid, avdt_scb_to_hdl(p_scb)); } /* if we're acceptor, we're done; just sit back and listen */ if (role == AVDT_ACP) { p_tbl->state = AVDT_AD_ST_ACP; } /* else we're inititator, start the L2CAP connection */ else { p_tbl->state = AVDT_AD_ST_CONN; /* call l2cap connect req */ if ((lcid = L2CA_ConnectReq(AVDT_PSM, p_ccb->peer_addr)) != 0) { /* if connect req ok, store tcid in lcid table */ avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); AVDT_TRACE_DEBUG("avdt_cb.ad.lcid_tbl[%d] = %d\n", (lcid - L2CAP_BASE_APPL_CID), avdt_ad_tc_tbl_to_idx(p_tbl)); avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid; AVDT_TRACE_DEBUG("avdt_cb.ad.rt_tbl[%d][%d].lcid = 0x%x\n", avdt_ccb_to_idx(p_ccb), p_tbl->tcid, lcid); } else { /* if connect req failed, call avdt_ad_tc_close_ind() */ avdt_ad_tc_close_ind(p_tbl, 0); } } }
/******************************************************************************* ** ** Function avdt_l2c_connect_ind_cback ** ** Description This is the L2CAP connect indication callback function. ** ** ** Returns void ** *******************************************************************************/ void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id) { tAVDT_CCB *p_ccb; tAVDT_TC_TBL *p_tbl = NULL; UINT16 result; tL2CAP_CFG_INFO cfg; tBTM_STATUS rc; UNUSED(psm); /* do we already have a control channel for this peer? */ if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL) { /* no, allocate ccb */ if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL) { /* no ccb available, reject L2CAP connection */ result = L2CAP_CONN_NO_RESOURCES; } else { /* allocate and set up entry; first channel is always signaling */ p_tbl = avdt_ad_tc_tbl_alloc(p_ccb); p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu; p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO; p_tbl->tcid = AVDT_CHAN_SIG; p_tbl->lcid = lcid; p_tbl->id = id; p_tbl->state = AVDT_AD_ST_SEC_ACP; p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_ACP; /* Check the security */ rc = btm_sec_mx_access_request (bd_addr, AVDT_PSM, FALSE, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG, &avdt_sec_check_complete_term, NULL); if (rc == BTM_CMD_STARTED) { L2CA_ConnectRsp (p_ccb->peer_addr, p_tbl->id, lcid, L2CAP_CONN_PENDING, L2CAP_CONN_OK); } return; } } /* deal with simultaneous control channel connect case */ else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_CONN)) != NULL) { /* reject their connection */ result = L2CAP_CONN_NO_RESOURCES; } /* this must be a traffic channel; are we accepting a traffic channel ** for this ccb? */ else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_MEDIA, p_ccb, AVDT_AD_ST_ACP)) != NULL) { /* yes; proceed with connection */ result = L2CAP_CONN_OK; } #if AVDT_REPORTING == TRUE /* this must be a reporting channel; are we accepting a reporting channel ** for this ccb? */ else if ((p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_REPORT, p_ccb, AVDT_AD_ST_ACP)) != NULL) { /* yes; proceed with connection */ result = L2CAP_CONN_OK; } #endif /* else we're not listening for traffic channel; reject */ else { result = L2CAP_CONN_NO_PSM; } /* Send L2CAP connect rsp */ L2CA_ConnectRsp(bd_addr, id, lcid, result, 0); /* if result ok, proceed with connection */ if (result == L2CAP_CONN_OK) { /* store idx in LCID table, store LCID in routing table */ avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid; /* transition to configuration state */ p_tbl->state = AVDT_AD_ST_CFG; /* Send L2CAP config req */ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); cfg.mtu_present = TRUE; cfg.mtu = p_tbl->my_mtu; cfg.flush_to_present = TRUE; cfg.flush_to = p_tbl->my_flush_to; L2CA_ConfigReq(lcid, &cfg); } }