/******************************************************************************* ** ** Function sdp_conn_originate ** ** Description This function is called from the API to originate a ** connection. ** ** Returns void ** *******************************************************************************/ tCONN_CB *sdp_conn_originate (UINT8 *p_bd_addr) { tCONN_CB *p_ccb; UINT16 cid; /* Allocate a new CCB. Return if none available. */ if ((p_ccb = sdpu_allocate_ccb()) == NULL) { SDP_TRACE_WARNING ("SDP - no spare CCB for orig\n"); return (NULL); } SDP_TRACE_EVENT ("SDP - Originate started\n"); /* We are the originator of this connection */ p_ccb->con_flags |= SDP_FLAGS_IS_ORIG; /* Save the BD Address and Channel ID. */ memcpy (&p_ccb->device_address[0], p_bd_addr, sizeof (BD_ADDR)); /* Transition to the next appropriate state, waiting for connection confirm. */ p_ccb->con_state = SDP_STATE_CONN_SETUP; cid = L2CA_ConnectReq (SDP_PSM, p_bd_addr); /* Check if L2CAP started the connection process */ if (cid != 0) { p_ccb->connection_id = cid; return (p_ccb); } else { SDP_TRACE_WARNING ("SDP - Originate failed\n"); sdpu_release_ccb (p_ccb); return (NULL); } }
/******************************************************************************* ** ** 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 rfc_mx_sm_state_idle ** ** Description This function handles events when the multiplexer is in ** IDLE state. This state exists when connection is being ** initially established. ** ** Returns void ** *******************************************************************************/ void rfc_mx_sm_state_idle (tRFC_MCB *p_mcb, UINT16 event, void *p_data) { RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_idle - evt:%d", event); switch (event) { case RFC_MX_EVENT_START_REQ: /* Initialize L2CAP MTU */ p_mcb->peer_l2cap_mtu = L2CAP_DEFAULT_MTU - RFCOMM_MIN_OFFSET - 1; 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); p_mcb->state = RFC_MX_STATE_WAIT_CONN_CNF; return; case RFC_MX_EVENT_START_RSP: case RFC_MX_EVENT_CONN_CNF: case RFC_MX_EVENT_CONF_IND: case RFC_MX_EVENT_CONF_CNF: RFCOMM_TRACE_ERROR2 ("Mx error state %d event %d", p_mcb->state, event); return; case RFC_MX_EVENT_CONN_IND: rfc_timer_start (p_mcb, RFCOMM_CONN_TIMEOUT); L2CA_ConnectRsp (p_mcb->bd_addr, *((UINT8 *)p_data), p_mcb->lcid, L2CAP_CONN_OK, 0); rfc_mx_send_config_req (p_mcb); p_mcb->state = RFC_MX_STATE_CONFIGURE; return; case RFC_EVENT_SABME: break; case RFC_EVENT_UA: case RFC_EVENT_DM: return; case RFC_EVENT_DISC: rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, TRUE); return; case RFC_EVENT_UIH: rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, FALSE); return; } RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); }
static UINT16 L2cap_Connect(UINT16 psm, bt_bdaddr_t *bd_addr) { BTIF_TRACE_DEBUG("L2cap_Connect:: %0x %0x %0x %0x %0x %0x", bd_addr->address[0],bd_addr->address[1], bd_addr->address[2],bd_addr->address[3],bd_addr->address[4],bd_addr->address[5]); if (0 == (g_lcid = L2CA_ConnectReq (psm, bd_addr->address))) { BTIF_TRACE_DEBUG("Error:: L2CA_ConnectReq failed for psm %d", psm); } return g_lcid; }
/******************************************************************************* ** ** Function hidh_sec_check_complete_orig ** ** Description This function checks to see if security procedures are being ** carried out or not.. ** ** Returns void ** *******************************************************************************/ void hidh_sec_check_complete_orig (BD_ADDR bd_addr, void *p_ref_data, UINT8 res) { tHID_HOST_DEV_CTB *p_dev = (tHID_HOST_DEV_CTB *) p_ref_data; UINT8 dhandle; #if (HID_HOST_MAX_CONN_RETRY > 0) UINT32 cb_res = HID_ERR_AUTH_FAILED; #endif UINT32 reason; dhandle = ((UINT32)p_dev - (UINT32)&(hh_cb.devices[0]))/ sizeof(tHID_HOST_DEV_CTB); if( res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY ) { HIDH_TRACE_EVENT0 ("HID-Host Originator security pass."); p_dev->conn.disc_reason = HID_SUCCESS; /* Authentication passed. Reset disc_reason (from HID_ERR_AUTH_FAILED) */ /* Check if L2CAP started the connection process for interrupt channel */ if ((p_dev->conn.intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0) { HIDH_TRACE_WARNING0 ("HID-Host INTR Originate failed"); reason = HID_L2CAP_REQ_FAIL ; hidh_conn_disconnect (dhandle); hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ; return; } else { /* Transition to the next appropriate state, waiting for connection confirm on control channel. */ p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_INTR; } } if( res != BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY ) { #if (HID_HOST_MAX_CONN_RETRY > 0) if( res == BTM_DEVICE_TIMEOUT ) { if( p_dev->conn_tries <= HID_HOST_MAX_CONN_RETRY ) { hidh_conn_retry (dhandle); return; } else cb_res = HID_L2CAP_CONN_FAIL | HCI_ERR_PAGE_TIMEOUT ; } #endif p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED; /* Save reason for disconnecting */ hidh_conn_disconnect(dhandle); } }
/******************************************************************************* ** ** Function sdp_conn_originate ** ** Description This function is called from the API to originate a ** connection. ** ** Returns void ** *******************************************************************************/ tCONN_CB* sdp_conn_originate (UINT8 *p_bd_addr) { tCONN_CB *p_ccb; UINT16 cid; /* Allocate a new CCB. Return if none available. */ if ((p_ccb = sdpu_allocate_ccb()) == NULL) { SDP_TRACE_WARNING0 ("SDP - no spare CCB for orig"); return (NULL); } SDP_TRACE_EVENT0 ("SDP - Originate started"); /* We are the originator of this connection */ p_ccb->con_flags |= SDP_FLAGS_IS_ORIG; /* Save the BD Address and Channel ID. */ memcpy (&p_ccb->device_address[0], p_bd_addr, sizeof (BD_ADDR)); /* Transition to the next appropriate state, waiting for connection confirm. */ p_ccb->con_state = SDP_STATE_CONN_SETUP; // btla-specific ++ #ifndef ANDROID_APP_INCLUDED /* Skip for Android: Do not need to set out_service for sdp, since sdp does not use sec. Prevents over-writing service_rec of a connection already in progress */ BTM_SetOutService(p_bd_addr, BTM_SEC_SERVICE_SDP_SERVER, 0); #endif // btla-specific -- cid = L2CA_ConnectReq (SDP_PSM, p_bd_addr); /* Check if L2CAP started the connection process */ if (cid != 0) { p_ccb->connection_id = cid; return (p_ccb); } else { SDP_TRACE_WARNING0 ("SDP - Originate failed"); sdpu_release_ccb (p_ccb); return (NULL); } }
/******************************************************************************* ** ** Function gatt_connect ** ** Description This function is called to initiate a connection to a peer device. ** ** Parameter rem_bda: remote device address to connect to. ** ** Returns TRUE if connection is started, otherwise return FALSE. ** *******************************************************************************/ BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb, tBT_TRANSPORT transport) { BOOLEAN gatt_ret = FALSE; if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN) gatt_set_ch_state(p_tcb, GATT_CH_CONN); if (transport == BT_TRANSPORT_LE) { p_tcb->att_lcid = L2CAP_ATT_CID; gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda); } else { if ((p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda)) != 0) gatt_ret = TRUE; } return gatt_ret; }
/******************************************************************************* ** ** Function gatt_connect ** ** Description This function is called to initiate a connection to a peer device. ** ** Parameter rem_bda: remote device address to connect to. ** ** Returns TRUE if connection is started, otherwise return FALSE. ** *******************************************************************************/ BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb) { BOOLEAN gatt_ret = FALSE; if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN) gatt_set_ch_state(p_tcb, GATT_CH_CONN); /* select the physical link for GATT connection */ if (BTM_UseLeLink(rem_bda)) { p_tcb->att_lcid = L2CAP_ATT_CID; gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda); } else { if ((p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda)) != 0) gatt_ret = TRUE; } return gatt_ret; }
/******************************************************************************* ** ** Function gatt_connect ** ** Description This function is called to initiate a connection to a peer device. ** ** Parameter rem_bda: remote device address to connect to. ** ** Returns TRUE if connection is started, otherwise return FALSE. ** *******************************************************************************/ BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb) { BOOLEAN gatt_ret = TRUE; tBT_DEVICE_TYPE dev_type; tBLE_ADDR_TYPE addr_type; BTM_ReadDevInfo(rem_bda, &dev_type, &addr_type); gatt_set_ch_state(p_tcb, GATT_CH_CONN); if (dev_type == BT_DEVICE_TYPE_BLE) { p_tcb->att_lcid = L2CAP_ATT_CID; gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda); } else { if ((p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda)) == 0) gatt_ret = FALSE; } return gatt_ret; }
/******************************************************************************* ** ** Function hidh_l2cif_config_cfm ** ** Description This function processes the L2CAP configuration confirmation ** event. ** ** Returns void ** *******************************************************************************/ static void hidh_l2cif_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) { UINT8 dhandle; tHID_CONN *p_hcon = NULL; UINT32 reason; HIDH_TRACE_EVENT ("HID-Host Rcvd cfg cfm, CID: 0x%x Result: %d", l2cap_cid, p_cfg->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 cfg ind, unknown CID: 0x%x", l2cap_cid); return; } /* If configuration failed, disconnect the channel(s) */ if (p_cfg->result != L2CAP_CFG_OK) { hidh_conn_disconnect (dhandle); reason = HID_L2CAP_CFG_FAIL | (UINT32) p_cfg->result ; HIDH_TRACE_WARNING ("HID-Host: l2cap config ind failed, reason = %d", reason); hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ; return; } if (l2cap_cid == p_hcon->ctrl_cid) { p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE; if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) { /* Connect interrupt channel */ p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */ if ((p_hcon->intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0) { HIDH_TRACE_WARNING ("HID-Host INTR Originate failed"); reason = HID_L2CAP_REQ_FAIL ; p_hcon->conn_state = HID_CONN_STATE_UNUSED; hidh_conn_disconnect (dhandle); HIDH_TRACE_WARNING ("HID-Host: l2cap config ind failed 2, reason = %d", reason); hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ; return; } else { /* Transition to the next appropriate state, waiting for connection confirm on interrupt channel. */ p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR; } } } else p_hcon->conn_flags |= HID_CONN_FLAGS_MY_INTR_CFG_DONE; /* If all configuration is complete, change state and tell management we are up */ if (((p_hcon->conn_flags & HID_CONN_FLAGS_ALL_CONFIGURED) == HID_CONN_FLAGS_ALL_CONFIGURED) && (p_hcon->conn_state == HID_CONN_STATE_CONFIG)) { p_hcon->conn_state = HID_CONN_STATE_CONNECTED; /* Reset disconnect reason to success, as connection successful */ p_hcon->disc_reason = HID_SUCCESS; hh_cb.devices[dhandle].state = HID_DEV_CONNECTED; hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_OPEN, 0, NULL ) ; } }
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 } }
/******************************************************************************* ** ** 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); }
/******************************************************************************* ** ** 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_config_ind ** ** Description This function processes the L2CAP configuration indication ** event. ** ** Returns void ** *******************************************************************************/ static void hidh_l2cif_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) { UINT8 dhandle; tHID_CONN *p_hcon = NULL; UINT32 reason; /* 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 cfg ind, unknown CID: 0x%x", l2cap_cid); return; } HIDH_TRACE_EVENT ("HID-Host Rcvd cfg ind, sent cfg cfm, CID: 0x%x", l2cap_cid); /* Remember the remote MTU size */ if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_HOST_MTU)) p_hcon->rem_mtu_size = HID_HOST_MTU; else p_hcon->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; L2CA_ConfigRsp (l2cap_cid, p_cfg); if (l2cap_cid == p_hcon->ctrl_cid) { p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE; if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) { /* Connect interrupt channel */ p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */ if ((p_hcon->intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0) { HIDH_TRACE_WARNING ("HID-Host INTR Originate failed"); reason = HID_L2CAP_REQ_FAIL ; p_hcon->conn_state = HID_CONN_STATE_UNUSED; hidh_conn_disconnect (dhandle); hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ; return; } else { /* Transition to the next appropriate state, waiting for connection confirm on interrupt channel. */ p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR; } } } else p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_INTR_CFG_DONE; /* If all configuration is complete, change state and tell management we are up */ if (((p_hcon->conn_flags & HID_CONN_FLAGS_ALL_CONFIGURED) == HID_CONN_FLAGS_ALL_CONFIGURED) && (p_hcon->conn_state == HID_CONN_STATE_CONFIG)) { p_hcon->conn_state = HID_CONN_STATE_CONNECTED; /* Reset disconnect reason to success, as connection successful */ p_hcon->disc_reason = HID_SUCCESS; hh_cb.devices[dhandle].state = HID_DEV_CONNECTED; hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_OPEN, 0, NULL ) ; } }