/******************************************************************************* ** ** Function port_open_continue ** ** Description This function is called after security manager completes ** required security checks. ** ** Returns void ** *******************************************************************************/ int port_open_continue (tPORT *p_port) { tRFC_MCB *p_mcb; RFCOMM_TRACE_EVENT ("port_open_continue, p_port:%p", p_port); /* Check if multiplexer channel has already been established */ if ((p_mcb = rfc_alloc_multiplexer_channel (p_port->bd_addr, TRUE)) == NULL) { RFCOMM_TRACE_WARNING ("port_open_continue no mx channel"); port_release_port (p_port); return (PORT_NO_RESOURCES); } p_port->rfc.p_mcb = p_mcb; p_mcb->port_inx[p_port->dlci] = p_port->inx; /* Connection is up and we know local and remote features, select MTU */ port_select_mtu (p_port); if (p_mcb->state == RFC_MX_STATE_CONNECTED) { RFCOMM_ParNegReq (p_mcb, p_port->dlci, p_port->mtu); } else if ((p_mcb->state == RFC_MX_STATE_IDLE) || (p_mcb->state == RFC_MX_STATE_DISC_WAIT_UA)) { /* In RFC_MX_STATE_IDLE state, MX state machine will create connection */ /* In RFC_MX_STATE_DISC_WAIT_UA state, MX state machine will recreate connection */ /* after disconnecting is completed */ RFCOMM_StartReq (p_mcb); } else { /* MX state machine ignores RFC_MX_EVENT_START_REQ in these states */ /* When it enters RFC_MX_STATE_CONNECTED, it will check any openning ports */ RFCOMM_TRACE_DEBUG ("port_open_continue: mx state(%d) mx channel is openning", p_mcb->state); } return (PORT_SUCCESS); }
/******************************************************************************* ** ** Function port_rfc_closed ** ** Description This function when RFCOMM side of port is closed ** *******************************************************************************/ void port_rfc_closed (tPORT *p_port, UINT8 res) { UINT8 old_signals; UINT32 events = 0; tRFC_MCB *p_mcb = p_port->rfc.p_mcb; if ((p_port->state == PORT_STATE_OPENING) && (p_port->is_server)) { /* The servr side has not been informed that connection is up, ignore */ RFCOMM_TRACE_EVENT ("port_rfc_closed in OPENING state ignored"); rfc_port_timer_stop (p_port); p_port->rfc.state = RFC_STATE_CLOSED; if (p_mcb) { p_mcb->port_inx[p_port->dlci] = 0; /* If there are no more ports opened on this MCB release it */ rfc_check_mcb_active (p_mcb); p_port->rfc.p_mcb = NULL; } /* Need to restore DLCI to listening state * if the server was on the initiating RFC */ p_port->dlci &= 0xfe; return; } if ((p_port->state != PORT_STATE_CLOSING) && (p_port->state != PORT_STATE_CLOSED)) { p_port->line_status |= LINE_STATUS_FAILED; old_signals = p_port->peer_ctrl.modem_signal; p_port->peer_ctrl.modem_signal &= ~(PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON); events |= port_get_signal_changes (p_port, old_signals, p_port->peer_ctrl.modem_signal); if (p_port->ev_mask & PORT_EV_CONNECT_ERR) { events |= PORT_EV_CONNECT_ERR; } } RFCOMM_TRACE_EVENT ("port_rfc_closed state:%d sending events:%x", p_port->state, events); if ((p_port->p_callback != NULL) && events) { p_port->p_callback (events, p_port->inx); } if (p_port->p_mgmt_callback) { p_port->p_mgmt_callback (res, p_port->inx); } p_port->rfc.state = RFC_STATE_CLOSED; RFCOMM_TRACE_WARNING ("%s RFCOMM connection in state %d closed: %s (res: %d)", __func__, p_port->state, PORT_GetResultString(res), res); port_release_port (p_port); }
/******************************************************************************* ** ** Function PORT_StartCnf ** ** Description This function is called from the RFCOMM layer when ** establishing of the multiplexer channel is completed. ** Continue establishing of the connection for all ports that ** are in the OPENING state ** *******************************************************************************/ void PORT_StartCnf (tRFC_MCB *p_mcb, UINT16 result) { tPORT *p_port; int i; BOOLEAN no_ports_up = TRUE; RFCOMM_TRACE_EVENT ("PORT_StartCnf result:%d", result); p_port = &rfc_cb.port.port[0]; for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) { if (p_port->rfc.p_mcb == p_mcb) { no_ports_up = FALSE; if (result == RFCOMM_SUCCESS) RFCOMM_ParNegReq (p_mcb, p_port->dlci, p_port->mtu); else { RFCOMM_TRACE_WARNING ("PORT_StartCnf failed result:%d", result); /* Warning: result is also set to 4 when l2cap connection fails due to l2cap connect cnf (no_resources) */ if( result == HCI_ERR_PAGE_TIMEOUT ) p_port->error = PORT_PAGE_TIMEOUT; else p_port->error = PORT_START_FAILED; rfc_release_multiplexer_channel (p_mcb); p_port->rfc.p_mcb = NULL; /* Send event to the application */ if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECT_ERR)) (p_port->p_callback)(PORT_EV_CONNECT_ERR, p_port->inx); if (p_port->p_mgmt_callback) p_port->p_mgmt_callback (PORT_START_FAILED, p_port->inx); port_release_port (p_port); } } } /* There can be a situation when after starting connection, user closes the */ /* port, we can catch it here to close multiplexor channel */ if (no_ports_up) { rfc_check_mcb_active (p_mcb); } }
/******************************************************************************* ** ** Function port_start_close ** ** Description This function is called in the BTU_TASK context to ** release DLC ** ** Returns void ** *******************************************************************************/ void port_start_close (tPORT *p_port) { tRFC_MCB *p_mcb = p_port->rfc.p_mcb; UINT8 old_signals; UINT32 events = 0; /* At first indicate to the user that signals on the connection were dropped */ p_port->line_status |= LINE_STATUS_FAILED; old_signals = p_port->peer_ctrl.modem_signal; p_port->peer_ctrl.modem_signal &= ~(PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON); events |= port_get_signal_changes (p_port, old_signals, p_port->peer_ctrl.modem_signal); if (p_port->ev_mask & PORT_EV_CONNECT_ERR) { events |= PORT_EV_CONNECT_ERR; } if (p_port->ev_mask & PORT_EV_ERR) { events |= PORT_EV_ERR; } if ((p_port->p_callback != NULL) && events) { p_port->p_callback (events, p_port->inx); } /* Check if RFCOMM side has been closed while the message was queued */ if ((p_mcb == NULL) || (p_port->rfc.state == RFC_STATE_CLOSED)) { /* Call management callback function before calling port_release_port() to clear tPort */ if (p_port->p_mgmt_callback) { p_port->p_mgmt_callback (PORT_CLOSED, p_port->inx); } port_release_port (p_port); } else { RFCOMM_DlcReleaseReq (p_mcb, p_port->dlci); } }