/******************************************************************************* ** ** Function rfc_port_sm_state_closed ** ** Description This function handles events when the port is in ** CLOSED state. This state exists when port is ** being initially established. ** ** Returns void ** *******************************************************************************/ void rfc_port_sm_state_closed (tPORT *p_port, UINT16 event, void *p_data) { switch (event) { case RFC_EVENT_OPEN: p_port->rfc.state = RFC_STATE_ORIG_WAIT_SEC_CHECK; btm_sec_mx_access_request (p_port->rfc.p_mcb->bd_addr, BT_PSM_RFCOMM, TRUE, BTM_SEC_PROTO_RFCOMM, (UINT32)(p_port->dlci / 2), &rfc_sec_check_complete, p_port); return; case RFC_EVENT_CLOSE: break; case RFC_EVENT_CLEAR: return; case RFC_EVENT_DATA: GKI_freebuf (p_data); break; case RFC_EVENT_SABME: /* make sure the multiplexer disconnect timer is not running (reconnect case) */ rfc_timer_stop(p_port->rfc.p_mcb ); /* Open will be continued after security checks are passed */ p_port->rfc.state = RFC_STATE_TERM_WAIT_SEC_CHECK; btm_sec_mx_access_request (p_port->rfc.p_mcb->bd_addr, BT_PSM_RFCOMM, FALSE, BTM_SEC_PROTO_RFCOMM, (UINT32)(p_port->dlci / 2), &rfc_sec_check_complete, p_port); return; case RFC_EVENT_UA: return; case RFC_EVENT_DM: rfc_port_closed (p_port); return; case RFC_EVENT_UIH: GKI_freebuf (p_data); rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, FALSE); return; case RFC_EVENT_DISC: rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, FALSE); return; case RFC_EVENT_TIMEOUT: Port_TimeOutCloseMux( p_port->rfc.p_mcb ) ; RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event); return; } RFCOMM_TRACE_WARNING ("Port state closed Event ignored %d", event); return; }
/******************************************************************************* ** ** Function gap_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 gap_connect_cfm (UINT16 l2cap_cid, UINT16 result) { tGAP_CCB *p_ccb; /* Find CCB based on CID */ if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) return; /* initiate security process, if needed */ if ( (p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0) { btm_sec_mx_access_request (p_ccb->rem_dev_address, p_ccb->psm, TRUE, 0, 0, &gap_sec_check_complete, p_ccb); } /* 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 == GAP_CCB_STATE_CONN_SETUP)) { p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP; /* Send a Configuration Request. */ L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg); } else { /* Tell the user if he has a callback */ if (p_ccb->p_callback) (*p_ccb->p_callback) (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED); gap_release_ccb (p_ccb); } }
/******************************************************************************* ** ** Function mca_l2c_connect_cfm_cback ** ** Description This is the L2CAP connect confirm callback function. ** ** ** Returns void ** *******************************************************************************/ void mca_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result) { tMCA_TC_TBL *p_tbl; tL2CAP_CFG_INFO cfg; tMCA_CCB *p_ccb; MCA_TRACE_DEBUG2("mca_l2c_connect_cfm_cback lcid: x%x, result: %d", lcid, result); /* look up info for this channel */ if ((p_tbl = mca_tc_tbl_by_lcid(lcid)) != NULL) { MCA_TRACE_DEBUG2("p_tbl state: %d, tcid: %d", p_tbl->state, p_tbl->tcid); /* if in correct state */ if (p_tbl->state == MCA_TC_ST_CONN) { /* if result successful */ if (result == L2CAP_CONN_OK) { if (p_tbl->tcid != 0) { /* set channel state */ p_tbl->state = MCA_TC_ST_CFG; /* Send L2CAP config req */ mca_set_cfg_by_tbl (&cfg, p_tbl); L2CA_ConfigReq(lcid, &cfg); } else { p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx); if (p_ccb == NULL) { result = L2CAP_CONN_NO_RESOURCES; } else { /* set channel state */ p_tbl->state = MCA_TC_ST_SEC_INT; p_tbl->lcid = lcid; p_tbl->cfg_flags= MCA_L2C_CFG_CONN_INT; /* Check the security */ btm_sec_mx_access_request (p_ccb->peer_addr, p_ccb->ctrl_vpsm, TRUE, BTM_SEC_PROTO_MCA, p_tbl->tcid, &mca_sec_check_complete_orig, p_tbl); } } } /* failure; notify adaption that channel closed */ if (result != L2CAP_CONN_OK) { p_tbl->cfg_flags |= MCA_L2C_CFG_DISCN_INT; mca_tc_close_ind(p_tbl, result); } } } }
/******************************************************************************* ** ** Function avdt_l2c_connect_cfm_cback ** ** Description This is the L2CAP connect confirm callback function. ** ** ** Returns void ** *******************************************************************************/ void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result) { tAVDT_TC_TBL *p_tbl; tL2CAP_CFG_INFO cfg; tAVDT_CCB *p_ccb; AVDT_TRACE_DEBUG("avdt_l2c_connect_cfm_cback lcid: %d, result: %d\n", lcid, result); /* look up info for this channel */ if ((p_tbl = avdt_ad_tc_tbl_by_lcid(lcid)) != NULL) { /* if in correct state */ if (p_tbl->state == AVDT_AD_ST_CONN) { /* if result successful */ if (result == L2CAP_CONN_OK) { if (p_tbl->tcid != AVDT_CHAN_SIG) { /* 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(lcid, &cfg); } else { p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); if (p_ccb == NULL) { result = L2CAP_CONN_NO_RESOURCES; } else { /* set channel state */ p_tbl->state = AVDT_AD_ST_SEC_INT; p_tbl->lcid = lcid; p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT; /* Check the security */ btm_sec_mx_access_request (p_ccb->peer_addr, AVDT_PSM, TRUE, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG, &avdt_sec_check_complete_orig, NULL); } } } /* failure; notify adaption that channel closed */ if (result != L2CAP_CONN_OK) { avdt_ad_tc_close_ind(p_tbl, result); } } } }
/******************************************************************************* ** ** Function mca_l2c_cconn_ind_cback ** ** Description This is the L2CAP connect indication callback function. ** ** Returns void ** *******************************************************************************/ void mca_l2c_cconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id) { tMCA_HANDLE handle = mca_handle_by_cpsm(psm); tMCA_CCB *p_ccb; tMCA_TC_TBL *p_tbl = NULL; UINT16 result = L2CAP_CONN_NO_RESOURCES; tBTM_STATUS rc; tL2CAP_ERTM_INFO ertm_info, *p_ertm_info = NULL; tL2CAP_CFG_INFO cfg; MCA_TRACE_EVENT3 ("mca_l2c_cconn_ind_cback: lcid:x%x psm:x%x id:x%x", lcid, psm, id); /* do we already have a control channel for this peer? */ if ((p_ccb = mca_ccb_by_bd(handle, bd_addr)) == NULL) { /* no, allocate ccb */ if ((p_ccb = mca_ccb_alloc(handle, bd_addr)) != NULL) { /* allocate and set up entry */ p_ccb->lcid = lcid; p_tbl = mca_tc_tbl_calloc(p_ccb); p_tbl->id = id; p_tbl->cfg_flags= MCA_L2C_CFG_CONN_ACP; /* proceed with connection */ /* Check the security */ rc = btm_sec_mx_access_request (bd_addr, psm, FALSE, BTM_SEC_PROTO_MCA, 0, &mca_sec_check_complete_term, p_tbl); if (rc == BTM_CMD_STARTED) { /* Set the FCR options: control channel mandates ERTM */ ertm_info.preferred_mode = mca_l2c_fcr_opts_def.mode; ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM; ertm_info.user_rx_pool_id = MCA_USER_RX_POOL_ID; ertm_info.user_tx_pool_id = MCA_USER_TX_POOL_ID; ertm_info.fcr_rx_pool_id = MCA_FCR_RX_POOL_ID; ertm_info.fcr_tx_pool_id = MCA_FCR_TX_POOL_ID; p_ertm_info = &ertm_info; result = L2CAP_CONN_PENDING; } else result = L2CAP_CONN_OK; } /* deal with simultaneous control channel connect case */ } /* else reject their connection */ if (!p_tbl || (p_tbl->state != MCA_TC_ST_CFG)) { /* Send L2CAP connect rsp */ L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, L2CAP_CONN_OK, p_ertm_info); /* if result ok, proceed with connection and send L2CAP config req */ if (result == L2CAP_CONN_OK) { /* 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); } } }
/******************************************************************************* ** ** 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); } }
/******************************************************************************* ** ** Function hidh_l2cif_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 hidh_l2cif_connect_cfm (UINT16 l2cap_cid, UINT16 result) { UINT8 dhandle; tHID_CONN *p_hcon = NULL; UINT32 reason; tHID_HOST_DEV_CTB *p_dev = NULL; /* Find CCB based on CID, and verify we are in a state to accept this message */ if( (dhandle = find_conn_by_cid(l2cap_cid)) < HID_HOST_MAX_DEVICES ) { p_dev = &hh_cb.devices[dhandle]; p_hcon = &hh_cb.devices[dhandle].conn; } if ((p_hcon == NULL) || (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG)) || ((l2cap_cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL)) || ((l2cap_cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) && (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING))) { HIDH_TRACE_WARNING ("HID-Host Rcvd unexpected conn cnf, CID 0x%x ", l2cap_cid); return; } if (result != L2CAP_CONN_OK) { if (l2cap_cid == p_hcon->ctrl_cid) p_hcon->ctrl_cid = 0; else p_hcon->intr_cid = 0; hidh_conn_disconnect(dhandle); #if (HID_HOST_MAX_CONN_RETRY > 0) if( (hh_cb.devices[dhandle].conn_tries <= HID_HOST_MAX_CONN_RETRY) && (result == HCI_ERR_CONNECTION_TOUT || result == HCI_ERR_UNSPECIFIED || result == HCI_ERR_PAGE_TIMEOUT) ) { hidh_conn_retry(dhandle); } else #endif { reason = HID_L2CAP_CONN_FAIL | (UINT32) result ; HIDH_TRACE_WARNING ("HID-Host: l2cap connect failed, reason = %d", reason); hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ; } return; } /* receive Control Channel connect confirmation */ if (l2cap_cid == p_hcon->ctrl_cid) { /* check security requirement */ p_hcon->conn_state = HID_CONN_STATE_SECURITY; p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* In case disconnection occurs before security is completed, then set CLOSE_EVT reason code to "connection failure" */ if (!interop_addr_match(INTEROP_DISABLE_AUTH_FOR_HID_POINTING, (bt_bdaddr_t *)p_dev->addr)) { btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL, TRUE, BTM_SEC_PROTO_HID, (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN, &hidh_sec_check_complete_orig, p_dev); } else { /* device is blacklisted, don't perform authentication */ hidh_sec_check_complete_orig(p_dev->addr, BT_TRANSPORT_BR_EDR, p_dev, BTM_SUCCESS); } } else { p_hcon->conn_state = HID_CONN_STATE_CONFIG; /* Send a Configuration Request. */ L2CA_ConfigReq (l2cap_cid, &hh_cb.l2cap_cfg); HIDH_TRACE_EVENT ("HID-Host got Interrupt conn cnf, sent cfg req, CID: 0x%x", l2cap_cid); } return; }
/******************************************************************************* ** ** Function hidh_l2cif_connect_ind ** ** Description This function handles an inbound connection indication ** from L2CAP. This is the case where we are acting as a ** server. ** ** Returns void ** *******************************************************************************/ static void hidh_l2cif_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id) { tHID_CONN *p_hcon; BOOLEAN bAccept = TRUE; UINT8 i = HID_HOST_MAX_DEVICES; tHID_HOST_DEV_CTB *p_dev; HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP conn ind, PSM: 0x%04x CID 0x%x", psm, l2cap_cid); /* always add incoming connection device into HID database by default */ if (HID_HostAddDev(bd_addr, HID_SEC_REQUIRED, &i) != HID_SUCCESS) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_SECURITY_BLOCK, 0); return; } p_hcon = &hh_cb.devices[i].conn; p_dev = &hh_cb.devices[i]; /* Stop the retry timer if active */ #if (HID_HOST_MAX_CONN_RETRY > 0) #if (HID_HOST_REPAGE_WIN > 0) HIDH_TRACE_DEBUG ("HID-Host stopping retry timer as l2cap is connected from remote side"); p_dev->conn_tries = HID_HOST_MAX_CONN_RETRY+1; btu_stop_timer(&(p_dev->conn.timer_entry)); #endif #endif /* Check we are in the correct state for this */ if (psm == HID_PSM_INTERRUPT) { if (p_hcon->ctrl_cid == 0) { HIDH_TRACE_WARNING ("HID-Host Rcvd INTR L2CAP conn ind, but no CTL channel"); bAccept = FALSE; } if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) { HIDH_TRACE_WARNING ("HID-Host Rcvd INTR L2CAP conn ind, wrong state: %d", p_hcon->conn_state); bAccept = FALSE; } } else /* CTRL channel */ { #if defined(HID_HOST_ACPT_NEW_CONN) && (HID_HOST_ACPT_NEW_CONN == TRUE) p_hcon->ctrl_cid = p_hcon->intr_cid = 0; p_hcon->conn_state = HID_CONN_STATE_UNUSED; #else if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) { HIDH_TRACE_WARNING ("HID-Host - Rcvd CTL L2CAP conn ind, wrong state: %d", p_hcon->conn_state); bAccept = FALSE; } #endif } if (!bAccept) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_RESOURCES, 0); return; } if (psm == HID_PSM_CONTROL) { p_hcon->conn_flags = 0; p_hcon->ctrl_cid = l2cap_cid; p_hcon->ctrl_id = l2cap_id; p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* In case disconnection occurs before security is completed, then set CLOSE_EVT reason code to 'connection failure' */ p_hcon->conn_state = HID_CONN_STATE_SECURITY; if (!interop_addr_match(INTEROP_DISABLE_AUTH_FOR_HID_POINTING, (bt_bdaddr_t*)p_dev->addr)) { if(btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL, FALSE, BTM_SEC_PROTO_HID, (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN, &hidh_sec_check_complete_term, p_dev) == BTM_CMD_STARTED) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK); } } else { /* device is blacklisted, don't perform authentication */ L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK); hidh_sec_check_complete_term(p_dev->addr, BT_TRANSPORT_BR_EDR, p_dev, BTM_SUCCESS); } return; } /* Transition to the next appropriate state, configuration */ p_hcon->conn_state = HID_CONN_STATE_CONFIG; p_hcon->intr_cid = l2cap_cid; /* Send response to the L2CAP layer. */ L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK); /* Send a Configuration Request. */ L2CA_ConfigReq (l2cap_cid, &hh_cb.l2cap_cfg); HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP conn ind, sent config req, PSM: 0x%04x CID 0x%x", psm, l2cap_cid); }
/******************************************************************************* ** ** Function BNEP_Connect ** ** Description This function creates a BNEP connection to a remote ** device. ** ** Parameters: p_rem_addr - BD_ADDR of the peer ** src_uuid - source uuid for the connection ** dst_uuid - destination uuid for the connection ** p_handle - pointer to return the handle for the connection ** ** Returns BNEP_SUCCESS if connection started ** BNEP_NO_RESOURCES if no resources ** *******************************************************************************/ tBNEP_RESULT BNEP_Connect (BD_ADDR p_rem_bda, tBT_UUID *src_uuid, tBT_UUID *dst_uuid, UINT16 *p_handle) { UINT16 cid; tBNEP_CONN *p_bcb = bnepu_find_bcb_by_bd_addr (p_rem_bda); BNEP_TRACE_API ("BNEP_Connect() BDA: %02x-%02x-%02x-%02x-%02x-%02x", p_rem_bda[0], p_rem_bda[1], p_rem_bda[2], p_rem_bda[3], p_rem_bda[4], p_rem_bda[5]); if (!bnep_cb.profile_registered) return BNEP_WRONG_STATE; /* Both source and destination UUID lengths should be same */ if (src_uuid->len != dst_uuid->len) return BNEP_CONN_FAILED_UUID_SIZE; #if (!defined (BNEP_SUPPORTS_ALL_UUID_LENGTHS) || BNEP_SUPPORTS_ALL_UUID_LENGTHS == FALSE) if (src_uuid->len != 2) return BNEP_CONN_FAILED_UUID_SIZE; #endif if (!p_bcb) { if ((p_bcb = bnepu_allocate_bcb (p_rem_bda)) == NULL) return (BNEP_NO_RESOURCES); } else if (p_bcb->con_state != BNEP_STATE_CONNECTED) return BNEP_WRONG_STATE; else { /* Backup current UUID values to restore if role change fails */ memcpy ((UINT8 *)&(p_bcb->prv_src_uuid), (UINT8 *)&(p_bcb->src_uuid), sizeof (tBT_UUID)); memcpy ((UINT8 *)&(p_bcb->prv_dst_uuid), (UINT8 *)&(p_bcb->dst_uuid), sizeof (tBT_UUID)); } /* We are the originator of this connection */ p_bcb->con_flags |= BNEP_FLAGS_IS_ORIG; memcpy ((UINT8 *)&(p_bcb->src_uuid), (UINT8 *)src_uuid, sizeof (tBT_UUID)); memcpy ((UINT8 *)&(p_bcb->dst_uuid), (UINT8 *)dst_uuid, sizeof (tBT_UUID)); if (p_bcb->con_state == BNEP_STATE_CONNECTED) { /* Transition to the next appropriate state, waiting for connection confirm. */ p_bcb->con_state = BNEP_STATE_SEC_CHECKING; BNEP_TRACE_API ("BNEP initiating security procedures for src uuid 0x%x", p_bcb->src_uuid.uu.uuid16); #if (defined (BNEP_DO_AUTH_FOR_ROLE_SWITCH) && BNEP_DO_AUTH_FOR_ROLE_SWITCH == TRUE) btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, TRUE, BTM_SEC_PROTO_BNEP, bnep_get_uuid32(src_uuid), &bnep_sec_check_complete, p_bcb); #else bnep_sec_check_complete (p_bcb->rem_bda, p_bcb, BTM_SUCCESS); #endif } else { /* Transition to the next appropriate state, waiting for connection confirm. */ p_bcb->con_state = BNEP_STATE_CONN_START; if ((cid = L2CA_ConnectReq (BT_PSM_BNEP, p_bcb->rem_bda)) != 0) { p_bcb->l2cap_cid = cid; } else { BNEP_TRACE_ERROR ("BNEP - Originate failed"); if (bnep_cb.p_conn_state_cb) (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE); bnepu_release_bcb (p_bcb); return BNEP_CONN_FAILED; } /* Start timer waiting for connect */ btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT); } *p_handle = p_bcb->handle; return (BNEP_SUCCESS); }
/******************************************************************************* ** ** Function hidh_l2cif_connect_ind ** ** Description This function handles an inbound connection indication ** from L2CAP. This is the case where we are acting as a ** server. ** ** Returns void ** *******************************************************************************/ static void hidh_l2cif_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id) { tHID_CONN *p_hcon; BOOLEAN bAccept = TRUE; UINT8 i = HID_HOST_MAX_DEVICES; tHID_HOST_DEV_CTB *p_dev; HIDH_TRACE_EVENT2 ("HID-Host Rcvd L2CAP conn ind, PSM: 0x%04x CID 0x%x", psm, l2cap_cid); /* always add incoming connection device into HID database by default */ if (HID_HostAddDev(bd_addr, HID_SEC_REQUIRED, &i) != HID_SUCCESS) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_SECURITY_BLOCK, 0); return; } p_hcon = &hh_cb.devices[i].conn; p_dev = &hh_cb.devices[i]; /* Check we are in the correct state for this */ if (psm == HID_PSM_INTERRUPT) { if (p_hcon->ctrl_cid == 0) { HIDH_TRACE_WARNING0 ("HID-Host Rcvd INTR L2CAP conn ind, but no CTL channel"); bAccept = FALSE; } if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) { HIDH_TRACE_WARNING1 ("HID-Host Rcvd INTR L2CAP conn ind, wrong state: %d", p_hcon->conn_state); bAccept = FALSE; } } else /* CTRL channel */ { #if defined(HID_HOST_ACPT_NEW_CONN) && (HID_HOST_ACPT_NEW_CONN == TRUE) p_hcon->ctrl_cid = p_hcon->intr_cid = 0; p_hcon->conn_state = HID_CONN_STATE_UNUSED; #else if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) { HIDH_TRACE_WARNING1 ("HID-Host - Rcvd CTL L2CAP conn ind, wrong state: %d", p_hcon->conn_state); bAccept = FALSE; } #endif } if (!bAccept) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_RESOURCES, 0); return; } if (psm == HID_PSM_CONTROL) { p_hcon->conn_flags = 0; p_hcon->ctrl_cid = l2cap_cid; p_hcon->ctrl_id = l2cap_id; p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* In case disconnection occurs before security is completed, then set CLOSE_EVT reason code to 'connection failure' */ p_hcon->conn_state = HID_CONN_STATE_SECURITY; if(btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL, FALSE, BTM_SEC_PROTO_HID, (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN, &hidh_sec_check_complete_term, p_dev) == BTM_CMD_STARTED) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK); } return; } /* Transition to the next appropriate state, configuration */ p_hcon->conn_state = HID_CONN_STATE_CONFIG; p_hcon->intr_cid = l2cap_cid; /* Send response to the L2CAP layer. */ L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK); /* Send a Configuration Request. */ L2CA_ConfigReq (l2cap_cid, &hh_cb.l2cap_cfg); HIDH_TRACE_EVENT2 ("HID-Host Rcvd L2CAP conn ind, sent config req, PSM: 0x%04x CID 0x%x", psm, l2cap_cid); }