/******************************************************************************* ** ** Function sdp_data_ind ** ** Description This function is called when data is received from L2CAP. ** if we are the originator of the connection, we are the SDP ** client, and the received message is queued up for the client. ** ** If we are the destination of the connection, we are the SDP ** server, so the message is passed to the server processing ** function. ** ** Returns void ** *******************************************************************************/ static void sdp_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg) { tCONN_CB *p_ccb; /* Find CCB based on CID */ if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) != NULL) { if (p_ccb->con_state == SDP_STATE_CONNECTED) { if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) sdp_disc_server_rsp (p_ccb, p_msg); else sdp_server_handle_client_req (p_ccb, p_msg); } else { SDP_TRACE_WARNING2 ("SDP - Ignored L2CAP data while in state: %d, CID: 0x%x", p_ccb->con_state, l2cap_cid); } } else { SDP_TRACE_WARNING1 ("SDP - Rcvd L2CAP data, unknown CID: 0x%x", l2cap_cid); } GKI_freebuf (p_msg); }
/******************************************************************************* ** ** Function sdp_disconnect_ind ** ** Description This function handles a disconnect event from L2CAP. If ** requested to, we ack the disconnect before dropping the CCB ** ** Returns void ** *******************************************************************************/ static void sdp_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed) { tCONN_CB *p_ccb; /* Find CCB based on CID */ if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) { SDP_TRACE_WARNING1 ("SDP - Rcvd L2CAP disc, unknown CID: 0x%x", l2cap_cid); return; } if (ack_needed) L2CA_DisconnectRsp (l2cap_cid); SDP_TRACE_EVENT1 ("SDP - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid); #if SDP_CLIENT_ENABLED == TRUE /* Tell the user if he has a callback */ if (p_ccb->p_cb) (*p_ccb->p_cb) ((UINT16) ((p_ccb->con_state == SDP_STATE_CONNECTED) ? SDP_SUCCESS : SDP_CONN_FAILED)); else if (p_ccb->p_cb2) (*p_ccb->p_cb2) ((UINT16) ((p_ccb->con_state == SDP_STATE_CONNECTED) ? SDP_SUCCESS : SDP_CONN_FAILED), p_ccb->user_data); #endif sdpu_release_ccb (p_ccb); }
/******************************************************************************* ** ** Function sdp_connect_cfm ** ** Description This function handles the connect confirm events ** from L2CAP. This is the case when we are acting as a ** client and have sent a connect request. ** ** Returns void ** *******************************************************************************/ static void sdp_connect_cfm (UINT16 l2cap_cid, UINT16 result) { tCONN_CB *p_ccb; tL2CAP_CFG_INFO cfg; /* Find CCB based on CID */ if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) { SDP_TRACE_WARNING ("SDP - Rcvd conn cnf for unknown CID 0x%x\n", l2cap_cid); return; } /* If the connection response contains success status, then */ /* Transition to the next state and startup the timer. */ if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == SDP_STATE_CONN_SETUP)) { p_ccb->con_state = SDP_STATE_CFG_SETUP; cfg = sdp_cb.l2cap_my_cfg; if (cfg.fcr_present) { SDP_TRACE_DEBUG("sdp_connect_cfm: mode %u, txwinsz %u, max_trans %u, rtrans_tout %u, mon_tout %u, mps %u\n", cfg.fcr.mode, cfg.fcr.tx_win_sz, cfg.fcr.max_transmit, cfg.fcr.rtrans_tout, cfg.fcr.mon_tout, cfg.fcr.mps); } if ((!L2CA_ConfigReq (l2cap_cid, &cfg)) && cfg.fcr_present && cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) { /* FCR not desired; try again in basic mode */ cfg.fcr_present = FALSE; cfg.fcr.mode = L2CAP_FCR_BASIC_MODE; L2CA_ConfigReq (l2cap_cid, &cfg); } SDP_TRACE_EVENT ("SDP - got conn cnf, sent cfg req, CID: 0x%x\n", p_ccb->connection_id); } else { SDP_TRACE_WARNING ("SDP - Rcvd conn cnf with error: 0x%x CID 0x%x\n", result, p_ccb->connection_id); /* Tell the user if he has a callback */ if (p_ccb->p_cb || p_ccb->p_cb2) { UINT16 err = -1; if ((result == HCI_ERR_HOST_REJECT_SECURITY) || (result == HCI_ERR_AUTH_FAILURE) || (result == HCI_ERR_PAIRING_NOT_ALLOWED) || (result == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) || (result == HCI_ERR_KEY_MISSING)) { err = SDP_SECURITY_ERR; } else if (result == HCI_ERR_HOST_REJECT_DEVICE) { err = SDP_CONN_REJECTED; } else { err = SDP_CONN_FAILED; } if (p_ccb->p_cb) { (*p_ccb->p_cb)(err); } else if (p_ccb->p_cb2) { (*p_ccb->p_cb2)(err, p_ccb->user_data); } } sdpu_release_ccb (p_ccb); } }
/******************************************************************************* ** ** Function sdp_config_cfm ** ** Description This function processes the L2CAP configuration confirmation ** event. ** ** Returns void ** *******************************************************************************/ static void sdp_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) { tCONN_CB *p_ccb; SDP_TRACE_EVENT2 ("SDP - Rcvd cfg cfm, CID: 0x%x Result: %d", l2cap_cid, p_cfg->result); /* Find CCB based on CID */ if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) { SDP_TRACE_WARNING1 ("SDP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid); return; } /* For now, always accept configuration from the other side */ if (p_cfg->result == L2CAP_CFG_OK) { p_ccb->con_flags |= SDP_FLAGS_MY_CFG_DONE; if (p_ccb->con_flags & SDP_FLAGS_HIS_CFG_DONE) { p_ccb->con_state = SDP_STATE_CONNECTED; if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) sdp_disc_connected (p_ccb); else /* Start inactivity timer */ btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT); } } else { /* If peer has rejected FCR and suggested basic then try basic */ if (p_cfg->fcr_present) { tL2CAP_CFG_INFO cfg = sdp_cb.l2cap_my_cfg; cfg.fcr_present = FALSE; L2CA_ConfigReq (l2cap_cid, &cfg); /* Remain in configure state */ return; } #if SDP_CLIENT_ENABLED == TRUE sdp_disconnect(p_ccb, SDP_CFG_FAILED); #endif } }
/******************************************************************************* ** ** Function sdp_disconnect_cfm ** ** Description This function handles a disconnect confirm event from L2CAP. ** ** Returns void ** *******************************************************************************/ static void sdp_disconnect_cfm (UINT16 l2cap_cid, UINT16 result) { tCONN_CB *p_ccb; /* Find CCB based on CID */ if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) { SDP_TRACE_WARNING1 ("SDP - Rcvd L2CAP disc cfm, unknown CID: 0x%x", l2cap_cid); return; } SDP_TRACE_EVENT1 ("SDP - Rcvd L2CAP disc cfm, CID: 0x%x", l2cap_cid); /* Tell the user if he has a callback */ if (p_ccb->p_cb) (*p_ccb->p_cb) (p_ccb->disconnect_reason); else if (p_ccb->p_cb2) (*p_ccb->p_cb2) (p_ccb->disconnect_reason, p_ccb->user_data); sdpu_release_ccb (p_ccb); }
/******************************************************************************* ** ** Function sdp_config_ind ** ** Description This function processes the L2CAP configuration indication ** event. ** ** Returns void ** *******************************************************************************/ static void sdp_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) { tCONN_CB *p_ccb; /* Find CCB based on CID */ if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) { SDP_TRACE_WARNING1 ("SDP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid); return; } /* Remember the remote MTU size */ if (!p_cfg->mtu_present) { /* use min(L2CAP_DEFAULT_MTU,SDP_MTU_SIZE) for GKI buffer size reasons */ p_ccb->rem_mtu_size = (L2CAP_DEFAULT_MTU > SDP_MTU_SIZE)?SDP_MTU_SIZE:L2CAP_DEFAULT_MTU; } else { if (p_cfg->mtu > SDP_MTU_SIZE) p_ccb->rem_mtu_size = SDP_MTU_SIZE; else p_ccb->rem_mtu_size = p_cfg->mtu; } /* For now, always accept configuration from the other side */ p_cfg->flush_to_present = FALSE; p_cfg->mtu_present = FALSE; p_cfg->result = L2CAP_CFG_OK; /* Check peer config request against our rfcomm configuration */ if (p_cfg->fcr_present) { /* Reject the window size if it is bigger than we want it to be */ if (p_cfg->fcr.mode != L2CAP_FCR_BASIC_MODE) { if (sdp_cb.l2cap_my_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE && p_cfg->fcr.tx_win_sz > sdp_cb.l2cap_my_cfg.fcr.tx_win_sz) { p_cfg->fcr.tx_win_sz = sdp_cb.l2cap_my_cfg.fcr.tx_win_sz; p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS; SDP_TRACE_DEBUG0("sdp_config_ind(CONFIG) -> Please try again with SMALLER TX WINDOW"); } /* Reject if locally we want basic and they don't */ if (sdp_cb.l2cap_my_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) { /* Ask for a new setup */ p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE; p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS; SDP_TRACE_DEBUG0("sdp_config_ind(CONFIG) -> Please try again with BASIC mode"); } /* Remain in configure state and give the peer our desired configuration */ if (p_cfg->result != L2CAP_CFG_OK) { SDP_TRACE_WARNING1 ("SDP - Rcvd cfg ind, Unacceptable Parameters sent cfg cfm, CID: 0x%x", l2cap_cid); L2CA_ConfigRsp (l2cap_cid, p_cfg); return; } } else /* We agree with peer's request */ p_cfg->fcr_present = FALSE; } L2CA_ConfigRsp (l2cap_cid, p_cfg); SDP_TRACE_EVENT1 ("SDP - Rcvd cfg ind, sent cfg cfm, CID: 0x%x", l2cap_cid); p_ccb->con_flags |= SDP_FLAGS_HIS_CFG_DONE; if (p_ccb->con_flags & SDP_FLAGS_MY_CFG_DONE) { p_ccb->con_state = SDP_STATE_CONNECTED; if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) sdp_disc_connected (p_ccb); else /* Start inactivity timer */ btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT); } }