/******************************************************************************* ** ** Function hidh_conn_disconnect ** ** Description This function disconnects a connection. ** ** Returns TRUE if disconnect started, FALSE if already disconnected ** *******************************************************************************/ tHID_STATUS hidh_conn_disconnect (UINT8 dhandle) { tHID_CONN *p_hcon = &hh_cb.devices[dhandle].conn; HIDH_TRACE_EVENT ("HID-Host disconnect"); if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) { p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING; /* Set l2cap idle timeout to 0 (so ACL link is disconnected * immediately after last channel is closed) */ L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0, BT_TRANSPORT_BR_EDR); /* Disconnect both interrupt and control channels */ if (p_hcon->intr_cid) L2CA_DisconnectReq (p_hcon->intr_cid); else if (p_hcon->ctrl_cid) L2CA_DisconnectReq (p_hcon->ctrl_cid); } else { p_hcon->conn_state = HID_CONN_STATE_UNUSED; } return (HID_SUCCESS); }
/******************************************************************************* ** ** Function avct_l2c_config_cfm_cback ** ** Description This is the L2CAP config confirm callback function. ** ** ** Returns void ** *******************************************************************************/ void avct_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) { tAVCT_LCB *p_lcb; /* look up lcb for this channel */ if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) { AVCT_TRACE_DEBUG("avct_l2c_config_cfm_cback: 0x%x, ch_state: %d, res: %d", lcid, p_lcb->ch_state, p_cfg->result); /* if in correct state */ if (p_lcb->ch_state == AVCT_CH_CFG) { /* if result successful */ if (p_cfg->result == L2CAP_CFG_OK) { /* update flags */ p_lcb->ch_flags |= AVCT_L2C_CFG_CFM_DONE; /* if configuration complete */ if (p_lcb->ch_flags & AVCT_L2C_CFG_IND_DONE) { p_lcb->ch_state = AVCT_CH_OPEN; avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL); } } /* else failure */ else { AVCT_TRACE_DEBUG("ERROR avct_l2c_config_cfm_cback L2CA_DisconnectReq %d ", p_lcb->ch_state); /* store result value */ p_lcb->ch_result = p_cfg->result; /* Send L2CAP disconnect req */ L2CA_DisconnectReq(lcid); } } AVCT_TRACE_DEBUG("ch_state cfc: %d ", p_lcb->ch_state); } }
/******************************************************************************* ** ** Function mca_ccb_do_disconn ** ** Description This function closes a control channel. ** ** Returns void. ** *******************************************************************************/ void mca_ccb_do_disconn (tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data) { UNUSED(p_data); mca_dcb_close_by_mdl_id (p_ccb, MCA_ALL_MDL_ID); L2CA_DisconnectReq(p_ccb->lcid); }
/******************************************************************************* ** ** Function rfc_mx_conf_cnf ** ** Description This function handles L2CA_ConfigCnf message from the ** L2CAP. If result is not success tell upper layer that ** start has not been accepted. If initiator send SABME ** on DLCI 0. T1 is still running. ** *******************************************************************************/ static void rfc_mx_conf_cnf (tRFC_MCB *p_mcb, tL2CAP_CFG_INFO *p_cfg) { RFCOMM_TRACE_EVENT2 ("rfc_mx_conf_cnf p_cfg:%08x res:%d ", p_cfg, (p_cfg) ? p_cfg->result : 0); if (p_cfg->result != L2CAP_CFG_OK) { if (p_mcb->is_initiator) { PORT_StartCnf (p_mcb, p_cfg->result); L2CA_DisconnectReq (p_mcb->lcid); } rfc_release_multiplexer_channel (p_mcb); return; } p_mcb->local_cfg_sent = TRUE; if ((p_mcb->state == RFC_MX_STATE_CONFIGURE) && p_mcb->peer_cfg_rcvd) { if (p_mcb->is_initiator) { p_mcb->state = RFC_MX_STATE_SABME_WAIT_UA; rfc_send_sabme (p_mcb, RFCOMM_MX_DLCI); rfc_timer_start (p_mcb, RFC_T1_TIMEOUT); } else { p_mcb->state = RFC_MX_STATE_WAIT_SABME; rfc_timer_start (p_mcb, RFC_T2_TIMEOUT); } } }
/******************************************************************************* ** ** Function rfc_mx_sm_state_connected ** ** Description This function handles events when the multiplexer is ** in the CONNECTED state ** ** Returns void ** *******************************************************************************/ void rfc_mx_sm_state_connected (tRFC_MCB *p_mcb, UINT16 event, void *p_data) { RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_connected - evt:%d", event); switch (event) { case RFC_EVENT_TIMEOUT: case RFC_MX_EVENT_CLOSE_REQ: rfc_timer_start (p_mcb, RFC_DISC_TIMEOUT); p_mcb->state = RFC_MX_STATE_DISC_WAIT_UA; rfc_send_disc (p_mcb, RFCOMM_MX_DLCI); return; case RFC_MX_EVENT_DISC_IND: p_mcb->state = RFC_MX_STATE_IDLE; PORT_CloseInd (p_mcb); return; case RFC_EVENT_DISC: /* Reply with UA. If initiator bring down L2CAP connection */ /* If server wait for some time if client decide to reinitiate channel */ rfc_send_ua (p_mcb, RFCOMM_MX_DLCI); if (p_mcb->is_initiator) { L2CA_DisconnectReq (p_mcb->lcid); } /* notify all ports that connection is gone */ PORT_CloseInd (p_mcb); return; } RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); }
/******************************************************************************* ** ** Function rfc_mx_sm_state_configure ** ** Description This function handles events when the multiplexer in the ** configuration state. ** ** Returns void ** *******************************************************************************/ void rfc_mx_sm_state_configure (tRFC_MCB *p_mcb, UINT16 event, void *p_data) { RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_configure - evt:%d", event); switch (event) { case RFC_MX_EVENT_START_REQ: case RFC_MX_EVENT_CONN_CNF: RFCOMM_TRACE_ERROR2 ("Mx error state %d event %d", p_mcb->state, event); return; case RFC_MX_EVENT_CONF_IND: rfc_mx_conf_ind (p_mcb, (tL2CAP_CFG_INFO *)p_data); return; case RFC_MX_EVENT_CONF_CNF: rfc_mx_conf_cnf (p_mcb, (tL2CAP_CFG_INFO *)p_data); return; case RFC_MX_EVENT_DISC_IND: p_mcb->state = RFC_MX_STATE_IDLE; PORT_CloseInd (p_mcb); return; case RFC_EVENT_TIMEOUT: p_mcb->state = RFC_MX_STATE_IDLE; L2CA_DisconnectReq (p_mcb->lcid); PORT_StartCnf (p_mcb, RFCOMM_ERROR); return; } RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); }
/******************************************************************************* ** ** Function avdt_sec_check_complete_orig ** ** Description The function called when Security Manager finishes ** verification of the service side connection ** ** Returns void ** *******************************************************************************/ static void avdt_sec_check_complete_orig (BD_ADDR bd_addr, tBT_TRANSPORT trasnport, void *p_ref_data, UINT8 res) { tAVDT_CCB *p_ccb = NULL; tL2CAP_CFG_INFO cfg; tAVDT_TC_TBL *p_tbl; UNUSED(p_ref_data); AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d\n", res); if (bd_addr) { p_ccb = avdt_ccb_by_bd(bd_addr); } p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_INT); if (p_tbl == NULL) { return; } if ( res == BTM_SUCCESS ) { /* set channel 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(p_tbl->lcid, &cfg); } else { L2CA_DisconnectReq (p_tbl->lcid); avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK); } }
/******************************************************************************* ** ** Function mca_l2c_config_cfm_cback ** ** Description This is the L2CAP config confirm callback function. ** ** ** Returns void ** *******************************************************************************/ void mca_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) { tMCA_TC_TBL *p_tbl; /* look up info for this channel */ if ((p_tbl = mca_tc_tbl_by_lcid(lcid)) != NULL) { /* if in correct state */ if (p_tbl->state == MCA_TC_ST_CFG) { /* if result successful */ if (p_cfg->result == L2CAP_CONN_OK) { /* update cfg_flags */ p_tbl->cfg_flags |= MCA_L2C_CFG_CFM_DONE; /* if configuration complete */ if (p_tbl->cfg_flags & MCA_L2C_CFG_IND_DONE) { mca_tc_open_ind(p_tbl); } } /* else failure */ else { /* Send L2CAP disconnect req */ L2CA_DisconnectReq(lcid); } } } }
// add by stanley : 2006-0719 void L2CA_TesterDisconnect(U8 cid) { L2capDisconnectRequest parms; if(cid == 0x00) parms.cid = L2CAPTS(cid); else parms.cid = cid; bt_trace(TRACE_GROUP_1,L2CAP_TESTER_DISCONN_REQ); L2CA_DisconnectReq(&parms); }
/******************************************************************************* ** ** Function rfc_mx_sm_state_wait_sabme ** ** Description This function handles events when the multiplexer is ** waiting for SABME on the acceptor side after configuration ** ** Returns void ** *******************************************************************************/ void rfc_mx_sm_state_wait_sabme (tRFC_MCB *p_mcb, UINT16 event, void *p_data) { RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_wait_sabme - evt:%d", event); switch (event) { case RFC_MX_EVENT_DISC_IND: p_mcb->state = RFC_MX_STATE_IDLE; PORT_CloseInd (p_mcb); return; case RFC_EVENT_SABME: /* if we gave up outgoing connection request */ if (p_mcb->pending_lcid) { p_mcb->pending_lcid = 0; rfc_send_ua (p_mcb, RFCOMM_MX_DLCI); rfc_timer_stop (p_mcb); p_mcb->state = RFC_MX_STATE_CONNECTED; p_mcb->peer_ready = TRUE; /* MX channel collision has been resolved, continue to open ports */ PORT_StartCnf (p_mcb, RFCOMM_SUCCESS); } else { rfc_timer_stop (p_mcb); PORT_StartInd (p_mcb); } return; case RFC_MX_EVENT_START_RSP: if (*((UINT16 *)p_data) != RFCOMM_SUCCESS) rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, TRUE); else { rfc_send_ua (p_mcb, RFCOMM_MX_DLCI); p_mcb->state = RFC_MX_STATE_CONNECTED; p_mcb->peer_ready = TRUE; } return; case RFC_MX_EVENT_CONF_IND: /* workaround: we don't support reconfig */ case RFC_MX_EVENT_CONF_CNF: /* workaround: we don't support reconfig */ case RFC_EVENT_TIMEOUT: p_mcb->state = RFC_MX_STATE_IDLE; L2CA_DisconnectReq (p_mcb->lcid); PORT_CloseInd (p_mcb); return; } RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); }
/******************************************************************************* ** ** 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); } }
/******************************************************************************* ** ** Function rfc_mx_sm_sabme_wait_ua ** ** Description This function handles events when the multiplexer sent ** SABME and is waiting for UA reply. ** ** Returns void ** *******************************************************************************/ void rfc_mx_sm_sabme_wait_ua (tRFC_MCB *p_mcb, UINT16 event, void *p_data) { RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_sabme_wait_ua - evt:%d", event); switch (event) { case RFC_MX_EVENT_START_REQ: case RFC_MX_EVENT_CONN_CNF: RFCOMM_TRACE_ERROR2 ("Mx error state %d event %d", p_mcb->state, event); return; /* workaround: we don't support reconfig */ /* commented out until we support reconfig case RFC_MX_EVENT_CONF_IND: rfc_mx_conf_ind (p_mcb, (tL2CAP_CFG_INFO *)p_data); return; case RFC_MX_EVENT_CONF_CNF: rfc_mx_conf_cnf (p_mcb, (tL2CAP_CFG_INFO *)p_data); return; */ case RFC_MX_EVENT_DISC_IND: p_mcb->state = RFC_MX_STATE_IDLE; PORT_CloseInd (p_mcb); return; case RFC_EVENT_UA: rfc_timer_stop (p_mcb); p_mcb->state = RFC_MX_STATE_CONNECTED; p_mcb->peer_ready = TRUE; PORT_StartCnf (p_mcb, RFCOMM_SUCCESS); return; case RFC_EVENT_DM: rfc_timer_stop (p_mcb); /* Case falls through */ case RFC_MX_EVENT_CONF_IND: /* workaround: we don't support reconfig */ case RFC_MX_EVENT_CONF_CNF: /* workaround: we don't support reconfig */ case RFC_EVENT_TIMEOUT: p_mcb->state = RFC_MX_STATE_IDLE; L2CA_DisconnectReq (p_mcb->lcid); PORT_StartCnf (p_mcb, RFCOMM_ERROR); return; } RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); }
/******************************************************************************* ** ** Function hidh_conn_disconnect ** ** Description This function disconnects a connection. ** ** Returns TRUE if disconnect started, FALSE if already disconnected ** *******************************************************************************/ tHID_STATUS hidh_conn_disconnect (UINT8 dhandle) { tHID_CONN *p_hcon = &hh_cb.devices[dhandle].conn; HIDH_TRACE_EVENT0 ("HID-Host disconnect"); if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) { p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING; /* Disconnect both interrupt and control channels */ if (p_hcon->intr_cid) L2CA_DisconnectReq (p_hcon->intr_cid); if (p_hcon->ctrl_cid) L2CA_DisconnectReq (p_hcon->ctrl_cid); } else { p_hcon->conn_state = HID_CONN_STATE_UNUSED; } return (HID_SUCCESS); }
/******************************************************************************* ** ** Function sdp_conn_timeout ** ** Description This function processes a timeout. Currently, we simply send ** a disconnect request to L2CAP. ** ** Returns void ** *******************************************************************************/ void sdp_conn_timeout (tCONN_CB*p_ccb) { SDP_TRACE_EVENT2 ("SDP - CCB timeout in state: %d CID: 0x%x", p_ccb->con_state, p_ccb->connection_id); L2CA_DisconnectReq (p_ccb->connection_id); #if SDP_CLIENT_ENABLED == TRUE /* Tell the user if he has a callback */ if (p_ccb->p_cb) (*p_ccb->p_cb) (SDP_CONN_FAILED); else if (p_ccb->p_cb2) (*p_ccb->p_cb2) (SDP_CONN_FAILED, p_ccb->user_data); #endif sdpu_release_ccb (p_ccb); }
/******************************************************************************* ** ** Function gatt_l2cif_config_cfm_cback ** ** Description This is the L2CAP config confirm callback function. ** ** ** Returns void ** *******************************************************************************/ void gatt_l2cif_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) { tGATT_TCB *p_tcb; tGATTS_SRV_CHG *p_srv_chg_clt=NULL; /* look up clcb for this channel */ if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) { /* if in correct state */ if ( gatt_get_ch_state(p_tcb) == GATT_CH_CFG) { /* if result successful */ if (p_cfg->result == L2CAP_CFG_OK) { /* update flags */ p_tcb->ch_flags |= GATT_L2C_CFG_CFM_DONE; /* if configuration complete */ if (p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE) { gatt_set_ch_state(p_tcb, GATT_CH_OPEN); if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL) { gatt_chk_srv_chg(p_srv_chg_clt); } else { if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda)) gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda); } /* send callback */ gatt_send_conn_cback(p_tcb); } } /* else failure */ else { /* Send L2CAP disconnect req */ L2CA_DisconnectReq(lcid); } } } }
/******************************************************************************* ** ** Function avct_l2c_connect_cfm_cback ** ** Description This is the L2CAP connect confirm callback function. ** ** ** Returns void ** *******************************************************************************/ void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result) { tAVCT_LCB *p_lcb; tL2CAP_CFG_INFO cfg; /* look up lcb for this channel */ if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) { AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback lcid:0x%x result: %d ch_state: %d, conflict_lcid:0x%x", lcid, result, p_lcb->ch_state, p_lcb->conflict_lcid); /* if in correct state */ if (p_lcb->ch_state == AVCT_CH_CONN) { /* if result successful */ if (result == L2CAP_CONN_OK) { /* set channel state */ p_lcb->ch_state = AVCT_CH_CFG; /* Send L2CAP config req */ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); cfg.mtu_present = TRUE; cfg.mtu = avct_cb.mtu; L2CA_ConfigReq(lcid, &cfg); AVCT_TRACE_DEBUG("avct_l2c snd Cfg Req"); } /* else failure */ else { AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback conflict_lcid:0x%x", p_lcb->conflict_lcid); if (p_lcb->conflict_lcid == lcid) { p_lcb->conflict_lcid = 0; } else { avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result); } } } else if (p_lcb->conflict_lcid == lcid) { /* we must be in AVCT_CH_CFG state for the ch_lcid channel */ AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback ch_state: %d, conflict_lcid:0x%x", p_lcb->ch_state, p_lcb->conflict_lcid); if (result == L2CAP_CONN_OK) { /* just in case the peer also accepts our connection - Send L2CAP disconnect req */ L2CA_DisconnectReq(lcid); } p_lcb->conflict_lcid = 0; } AVCT_TRACE_DEBUG("ch_state cnc: %d ", p_lcb->ch_state); } }
/******************************************************************************* ** ** Function gatt_l2c_connect_cfm_cback ** ** Description This is the L2CAP connect confirm callback function. ** ** ** Returns void ** *******************************************************************************/ static void gatt_l2cif_connect_cfm_cback(UINT16 lcid, UINT16 result) { tGATT_TCB *p_tcb; tL2CAP_CFG_INFO cfg; /* look up clcb for this channel */ if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) { GATT_TRACE_DEBUG("gatt_l2c_connect_cfm_cback result: %d ch_state: %d, lcid:0x%x", result, gatt_get_ch_state(p_tcb), p_tcb->att_lcid); /* if in correct state */ if (gatt_get_ch_state(p_tcb) == GATT_CH_CONN) { /* if result successful */ if (result == L2CAP_CONN_OK) { /* set channel state */ gatt_set_ch_state(p_tcb, GATT_CH_CFG); /* Send L2CAP config req */ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); cfg.mtu_present = TRUE; cfg.mtu = GATT_MAX_MTU_SIZE; L2CA_ConfigReq(lcid, &cfg); } /* else initiating connection failure */ else { gatt_cleanup_upon_disc(p_tcb->peer_bda, result, GATT_TRANSPORT_BR_EDR); } } else /* wrong state, disconnect it */ { if (result == L2CAP_CONN_OK) { /* just in case the peer also accepts our connection - Send L2CAP disconnect req */ L2CA_DisconnectReq(lcid); } } } }
/******************************************************************************* ** ** Function mca_sec_check_complete_orig ** ** Description The function called when Security Manager finishes ** verification of the service side connection ** ** Returns void ** *******************************************************************************/ static void mca_sec_check_complete_orig (BD_ADDR bd_addr, void *p_ref_data, UINT8 res) { tMCA_TC_TBL *p_tbl = (tMCA_TC_TBL *)p_ref_data; tL2CAP_CFG_INFO cfg; MCA_TRACE_DEBUG1("mca_sec_check_complete_orig res: %d", res); if ( res == BTM_SUCCESS ) { /* set channel state */ p_tbl->state = MCA_TC_ST_CFG; /* Send L2CAP config req */ mca_set_cfg_by_tbl (&cfg, p_tbl); L2CA_ConfigReq(p_tbl->lcid, &cfg); } else { L2CA_DisconnectReq (p_tbl->lcid); mca_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK); } }
/******************************************************************************* ** ** Function gatt_disconnect ** ** Description This function is called to disconnect to an ATT device. ** ** Parameter rem_bda: remote device address to disconnect from. ** ** Returns TRUE: if connection found and to be disconnected; otherwise ** return FALSE. ** *******************************************************************************/ BOOLEAN gatt_disconnect (BD_ADDR rem_bda) { tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(rem_bda); BOOLEAN ret = FALSE; tGATT_CH_STATE ch_state; GATT_TRACE_DEBUG0 ("gatt_disconnect "); if (p_tcb != NULL) { ret = TRUE; if ( (ch_state = gatt_get_ch_state(p_tcb)) != GATT_CH_CLOSING ) { if (p_tcb->att_lcid == L2CAP_ATT_CID) { if (ch_state == GATT_CH_OPEN) { /* only LCB exist between remote device and local */ ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, rem_bda); } else { gatt_set_ch_state(p_tcb, GATT_CH_CLOSING); ret = L2CA_CancelBleConnectReq (rem_bda); } } else { ret = L2CA_DisconnectReq(p_tcb->att_lcid); } } else { GATT_TRACE_DEBUG0 ("gatt_disconnect already in closing state"); } } return ret; }
/******************************************************************************* ** ** Function hidh_l2cif_disconnect_cfm ** ** Description This function handles a disconnect confirm event from L2CAP. ** ** Returns void ** *******************************************************************************/ static void hidh_l2cif_disconnect_cfm (UINT16 l2cap_cid, UINT16 result) { UINT8 dhandle; tHID_CONN *p_hcon = NULL; UNUSED(result); /* Find CCB based on CID */ if( (dhandle = find_conn_by_cid(l2cap_cid)) < HID_HOST_MAX_DEVICES ) p_hcon = &hh_cb.devices[dhandle].conn; if (p_hcon == NULL) { HIDH_TRACE_WARNING ("HID-Host Rcvd L2CAP disc cfm, unknown CID: 0x%x", l2cap_cid); return; } HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP disc cfm, CID: 0x%x", l2cap_cid); if (l2cap_cid == p_hcon->ctrl_cid) p_hcon->ctrl_cid = 0; else { p_hcon->intr_cid = 0; if (p_hcon->ctrl_cid) { HIDH_TRACE_EVENT ("HID-Host Initiating L2CAP Ctrl disconnection"); L2CA_DisconnectReq (p_hcon->ctrl_cid); } } if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) { hh_cb.devices[dhandle].state = HID_DEV_NO_CONN; p_hcon->conn_state = HID_CONN_STATE_UNUSED; HIDH_TRACE_EVENT ("HID-Host: disconnect cfm, reason = %d", p_hcon->disc_reason); hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, p_hcon->disc_reason, NULL ) ; } }
/******************************************************************************* ** ** Function avdt_ad_close_req ** ** Description This function is called by a CCB or SCB to close a ** transport channel. The function looks up the LCID for the ** channel and calls L2CA_DisconnectReq(). ** ** ** Returns Nothing. ** *******************************************************************************/ void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb) { UINT8 tcid; tAVDT_TC_TBL *p_tbl; p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb); AVDT_TRACE_DEBUG("avdt_ad_close_req state: %d\n", p_tbl->state); switch (p_tbl->state) { case AVDT_AD_ST_UNUSED: /* probably for reporting */ break; case AVDT_AD_ST_ACP: /* if we're listening on this channel, send ourselves a close ind */ avdt_ad_tc_close_ind(p_tbl, 0); break; default: /* get tcid from type, scb */ tcid = avdt_ad_type_to_tcid(type, p_scb); /* call l2cap disconnect req */ L2CA_DisconnectReq(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid); } }
static BOOLEAN L2cap_DisconnectReq (UINT16 cid) { BTIF_TRACE_DEBUG("L2cap_DisconnectReq:: cid=%d", cid); return L2CA_DisconnectReq(cid); }
/******************************************************************************* ** ** Function rfc_mx_sm_state_wait_conn_cnf ** ** Description This function handles events when the multiplexer is ** waiting for Connection Confirm from L2CAP. ** ** Returns void ** *******************************************************************************/ void rfc_mx_sm_state_wait_conn_cnf (tRFC_MCB *p_mcb, UINT16 event, void *p_data) { RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_wait_conn_cnf - evt:%d", event); switch (event) { case RFC_MX_EVENT_START_REQ: RFCOMM_TRACE_ERROR2 ("Mx error state %d event %d", p_mcb->state, event); return; /* There is some new timing so that Config Ind comes before security is completed so we are still waiting fo the confirmation. */ case RFC_MX_EVENT_CONF_IND: rfc_mx_conf_ind (p_mcb, (tL2CAP_CFG_INFO *)p_data); return; case RFC_MX_EVENT_CONN_CNF: if (*((UINT16 *)p_data) != L2CAP_SUCCESS) { p_mcb->state = RFC_MX_STATE_IDLE; PORT_StartCnf (p_mcb, *((UINT16 *)p_data)); return; } p_mcb->state = RFC_MX_STATE_CONFIGURE; rfc_mx_send_config_req (p_mcb); return; case RFC_MX_EVENT_DISC_IND: p_mcb->state = RFC_MX_STATE_IDLE; PORT_CloseInd (p_mcb); return; case RFC_EVENT_TIMEOUT: p_mcb->state = RFC_MX_STATE_IDLE; L2CA_DisconnectReq (p_mcb->lcid); /* we gave up outgoing connection request then try peer's request */ if (p_mcb->pending_lcid) { UINT16 i; UINT8 idx; RFCOMM_TRACE_DEBUG2 ("RFCOMM MX retry as acceptor in collision case - evt:%d in state:%d", event, p_mcb->state); rfc_save_lcid_mcb (NULL, p_mcb->lcid); p_mcb->lcid = p_mcb->pending_lcid; rfc_save_lcid_mcb (p_mcb, p_mcb->lcid); p_mcb->is_initiator = FALSE; /* update direction bit */ for (i = 0; i < RFCOMM_MAX_DLCI; i += 2) { if ((idx = p_mcb->port_inx[i]) != 0) { p_mcb->port_inx[i] = 0; p_mcb->port_inx[i+1] = idx; rfc_cb.port.port[idx - 1].dlci += 1; RFCOMM_TRACE_DEBUG2 ("RFCOMM MX - DLCI:%d -> %d", i, rfc_cb.port.port[idx - 1].dlci); } } rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_CONN_IND, &(p_mcb->pending_id)); } else { PORT_CloseInd (p_mcb); } return; } RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); }
/******************************************************************************* ** ** Function sdp_disconnect ** ** Description This function disconnects a connection. ** ** Returns void ** *******************************************************************************/ void sdp_disconnect (tCONN_CB*p_ccb, UINT16 reason) { #if (defined(SDP_BROWSE_PLUS) && SDP_BROWSE_PLUS == TRUE) /* If we are browsing for multiple UUIDs ... */ if ((p_ccb->con_state == SDP_STATE_CONNECTED) && (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) && ((reason == SDP_SUCCESS) || (reason == SDP_NO_RECS_MATCH))) { /* If the browse found something, do no more searching */ if ((p_ccb->cur_uuid_idx == 0) && (p_ccb->p_db->p_first_rec)) p_ccb->cur_uuid_idx = p_ccb->p_db->num_uuid_filters; while (++p_ccb->cur_uuid_idx < p_ccb->p_db->num_uuid_filters) { /* Check we have not already found the UUID (maybe through browse) */ if ((p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].len == 2) && (SDP_FindServiceInDb (p_ccb->p_db, p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].uu.uuid16, NULL))) continue; if ((p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].len > 2) && (SDP_FindServiceUUIDInDb (p_ccb->p_db, &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx], NULL))) continue; p_ccb->cur_handle = 0; SDP_TRACE_EVENT1 ("SDP - looking for for more, CID: 0x%x", p_ccb->connection_id); sdp_disc_connected (p_ccb); return; } } if ((reason == SDP_NO_RECS_MATCH) && (p_ccb->p_db->p_first_rec)) reason = SDP_SUCCESS; #endif SDP_TRACE_EVENT1 ("SDP - disconnect CID: 0x%x", p_ccb->connection_id); /* Check if we have a connection ID */ if (p_ccb->connection_id != 0) { L2CA_DisconnectReq (p_ccb->connection_id); p_ccb->disconnect_reason = reason; } /* If at setup state, we may not get callback ind from L2CAP */ /* Call user callback immediately */ if (p_ccb->con_state == SDP_STATE_CONN_SETUP) { /* Tell the user if he has a callback */ if (p_ccb->p_cb) (*p_ccb->p_cb) (reason); else if (p_ccb->p_cb2) (*p_ccb->p_cb2) (reason, p_ccb->user_data); sdpu_release_ccb (p_ccb); } }
/******************************************************************************* ** ** Function rfc_mx_sm_state_disc_wait_ua ** ** Description This function handles events when the multiplexer sent ** DISC and is waiting for UA reply. ** ** Returns void ** *******************************************************************************/ void rfc_mx_sm_state_disc_wait_ua (tRFC_MCB *p_mcb, UINT16 event, void *p_data) { BT_HDR *p_buf; RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_disc_wait_ua - evt:%d", event); switch (event) { case RFC_EVENT_UA: case RFC_EVENT_DM: case RFC_EVENT_TIMEOUT: L2CA_DisconnectReq (p_mcb->lcid); if (p_mcb->restart_required) { /* Start Request was received while disconnecting. Execute it again */ if ((p_mcb->lcid = L2CA_ConnectReq (BT_PSM_RFCOMM, p_mcb->bd_addr)) == 0) { PORT_StartCnf (p_mcb, RFCOMM_ERROR); return; } /* Save entry for quicker access to mcb based on the LCID */ rfc_save_lcid_mcb (p_mcb, p_mcb->lcid); /* clean up before reuse it */ while ((p_buf = (BT_HDR *)GKI_dequeue(&p_mcb->cmd_q)) != NULL) GKI_freebuf(p_buf); rfc_timer_start (p_mcb, RFC_MCB_INIT_INACT_TIMER); p_mcb->is_initiator = TRUE; p_mcb->restart_required = FALSE; p_mcb->local_cfg_sent = FALSE; p_mcb->peer_cfg_rcvd = FALSE; p_mcb->state = RFC_MX_STATE_WAIT_CONN_CNF; return; } rfc_release_multiplexer_channel (p_mcb); return; case RFC_EVENT_DISC: rfc_send_ua (p_mcb, RFCOMM_MX_DLCI); return; case RFC_EVENT_UIH: GKI_freebuf (p_data); rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, FALSE); return; case RFC_MX_EVENT_START_REQ: p_mcb->restart_required = TRUE; return; case RFC_MX_EVENT_DISC_IND: p_mcb->state = RFC_MX_STATE_IDLE; PORT_CloseInd (p_mcb); return; case RFC_MX_EVENT_CLOSE_REQ: return; case RFC_MX_EVENT_QOS_VIOLATION_IND: break; } RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); }
void l2captester_handler(ilm_struct *ilm_ptr) { char *string; bt_test_cmd_struct *test_msg; if (ilm_ptr->msg_id == MSG_ID_BT_TEST_CMD_REQ) { test_msg = ((bt_test_cmd_struct *)ilm_ptr->local_para_ptr); string = (char *)test_msg->string; if(strncmp(string, "init",4)==0) { l2capTesterInit(); } else if(strncmp(string, "senddata",8)==0) { L2capSendData(); } else if(strncmp(string, "conn",4)==0) { U8 bd_addr[6]; L2capConnectRequest parms; memset(bd_addr, 0, 6); if(!l2capTester_get_bdaddr_from_string(bd_addr, string+4)) { return; } memcpy((U8 *)parms.bd_addr, (U8 *)bd_addr, 6); L2CA_ConnectReq(&parms); } else if(strncmp(string, "disconn",7)==0) { L2capDisconnectRequest parms; parms.cid = L2CAPTS(cid); L2CA_DisconnectReq(&parms); } else if(strncmp(string, "info",4)==0) { L2capInfoRequest parms; U8 bd_addr[6]; memset(bd_addr, 0, 6); if(!l2capTester_get_bdaddr_from_string(bd_addr, string+4)) { return; } memcpy((U8 *)parms.bd_addr, (U8 *)bd_addr, 6); parms.info_type = 0x0002; L2CA_InfoReq(&parms); } else if(strncmp(string, "echo",4)==0) { L2capEchoRequest parms; U8 bd_addr[6]; memset(bd_addr, 0, 6); if(!l2capTester_get_bdaddr_from_string(bd_addr, string+4)) { return; } memcpy((U8 *)parms.bd_addr, (U8 *)bd_addr, 6); L2CA_EchoReq(&parms); } else if(strncmp(string, "encry",5)==0) { bt_bm_write_authentication_mode_req_struct ptr; ptr.mode = BTBM_AUTHENTICATION_ENABLE_LEVEL3_ENCRYPT_ON; BTBMGapSetAuthenticationMode(TRUE, &ptr); } #if L2CAP_NUM_GROUPS > 0 else if(strncmp(string, "groupreq",8)==0) { L2capGroupAddr parms; U8 bd_addr[6]; bt_trace(TRACE_GROUP_1,GROUP_ADD_REQUEST); memset(bd_addr, 0, 6); if(!l2capTester_get_bdaddr_from_string(bd_addr, string+8)) { return; } memcpy((U8 *)parms.bd_addr, (U8 *)bd_addr, 6); L2CA_AddGroup(&parms); } else if(strncmp(string, "grouprem",8)==0) { L2capGroupAddr parms; U8 bd_addr[6]; bt_trace(TRACE_GROUP_1,GROUP_REMOVE_REQUEST); memset(bd_addr, 0, 6); if(!l2capTester_get_bdaddr_from_string(bd_addr, string+8)) { return; } memcpy((U8 *)parms.bd_addr, (U8 *)bd_addr, 6); L2CA_RemoveGroup(&parms); } else if(strncmp(string, "sendgroupdata",13)==0) { bt_trace(TRACE_GROUP_1,SEND_GROUP_DATA); L2CA_GroupDataReq(); } else if(strncmp(string, "sendunidata",11)==0) { bt_trace(TRACE_GROUP_1,SEND_GROUP_DATA); L2CA_UniCastDataReq(); } else if(strncmp(string, "setencry", 8)==0) { Report(("set encryption on")); BTBMGapSetEncryptionOn(); } #endif } }