/******************************************************************************* ** ** Function L2cap_Register ** ** Description This function is called during the task startup ** to register interface functions with L2CAP. ** *******************************************************************************/ static bt_status_t L2cap_Register (UINT16 psm, BOOLEAN ConnType, UINT16 SecLevel) { BTIF_TRACE_DEBUG("L2cap_Register :: psm=%d", psm); if (!BTM_SetSecurityLevel (ConnType, "l2test", /*BTM_SEC_SERVICE_SDP_SERVER*/ BTM_SEC_PROTO_L2CAP, SecLevel, psm, 0, 0)) { BTIF_TRACE_DEBUG("Error:: BTM_SetSecurityLevel failed"); return BT_STATUS_FAIL; } #if 1 if(4113 == psm) { if (!BTM_SetSecurityLevel (ConnType, "l2test 4113", /*BTM_SEC_SERVICE_SDP_SERVER*/ BTM_SEC_PROTO_L2CAP, SecLevel, psm, 0, 0)) { BTIF_TRACE_DEBUG("Error:: BTM_SetSecurityLevel failed"); return BT_STATUS_FAIL; } } #endif g_Psm = L2CA_Register (psm, pl2test_l2c_appl); if(0 == g_Psm) { BTIF_TRACE_DEBUG("Error:: L2CA_Register failed"); return BT_STATUS_FAIL; } return BT_STATUS_SUCCESS; }
/******************************************************************************* ** ** Function sdp_init ** ** Description This function initializes the SDP unit. ** ** Returns void ** *******************************************************************************/ void sdp_init (void) { /* Clears all structures and local SDP database (if Server is enabled) */ memset (&sdp_cb, 0, sizeof (tSDP_CB)); /* Initialize the L2CAP configuration. We only care about MTU and flush */ sdp_cb.l2cap_my_cfg.mtu_present = TRUE; sdp_cb.l2cap_my_cfg.mtu = SDP_MTU_SIZE; sdp_cb.l2cap_my_cfg.flush_to_present = TRUE; sdp_cb.l2cap_my_cfg.flush_to = SDP_FLUSH_TO; sdp_cb.max_attr_list_size = SDP_MTU_SIZE - 16; sdp_cb.max_recs_per_search = SDP_MAX_DISC_SERVER_RECS; #if SDP_SERVER_ENABLED == TRUE /* Register with Security Manager for the specific security level */ if (!BTM_SetSecurityLevel (FALSE, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER, SDP_SECURITY_LEVEL, SDP_PSM, 0, 0)) { SDP_TRACE_ERROR0 ("Security Registration Server failed"); return; } #endif #if SDP_CLIENT_ENABLED == TRUE /* Register with Security Manager for the specific security level */ if (!BTM_SetSecurityLevel (TRUE, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER, SDP_SECURITY_LEVEL, SDP_PSM, 0, 0)) { SDP_TRACE_ERROR0 ("Security Registration for Client failed"); return; } #endif #if defined(SDP_INITIAL_TRACE_LEVEL) sdp_cb.trace_level = SDP_INITIAL_TRACE_LEVEL; #else sdp_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */ #endif sdp_cb.reg_info.pL2CA_ConnectInd_Cb = sdp_connect_ind; sdp_cb.reg_info.pL2CA_ConnectCfm_Cb = sdp_connect_cfm; sdp_cb.reg_info.pL2CA_ConnectPnd_Cb = NULL; sdp_cb.reg_info.pL2CA_ConfigInd_Cb = sdp_config_ind; sdp_cb.reg_info.pL2CA_ConfigCfm_Cb = sdp_config_cfm; sdp_cb.reg_info.pL2CA_DisconnectInd_Cb = sdp_disconnect_ind; sdp_cb.reg_info.pL2CA_DisconnectCfm_Cb = sdp_disconnect_cfm; sdp_cb.reg_info.pL2CA_QoSViolationInd_Cb = NULL; sdp_cb.reg_info.pL2CA_DataInd_Cb = sdp_data_ind; sdp_cb.reg_info.pL2CA_CongestionStatus_Cb = NULL; sdp_cb.reg_info.pL2CA_TxComplete_Cb = NULL; /* Now, register with L2CAP */ if (!L2CA_Register (SDP_PSM, &sdp_cb.reg_info)) { SDP_TRACE_ERROR0 ("SDP Registration failed"); } }
/******************************************************************************* ** ** Function PAN_SetPanuSecurity ** ** Description This function is used to register PANU service security ** level with Security Manager ** ** Parameters: sec_mask - Security mask for PANU role ** p_name - Service name for PANU role ** ** Returns none ** *******************************************************************************/ static void PAN_SetPanuSecurity(UINT8 sec_mask, char *p_name) { #if (defined (PAN_SUPPORTS_ROLE_PANU) && PAN_SUPPORTS_ROLE_PANU == TRUE) if ((!BTM_SetSecurityLevel (TRUE, p_name, BTM_SEC_SERVICE_BNEP_PANU, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_PANU)) || (!BTM_SetSecurityLevel (FALSE, p_name, BTM_SEC_SERVICE_BNEP_PANU, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_PANU))) { PAN_TRACE_ERROR0 ("PAN Security Registration failed for PANU"); } #endif }
/******************************************************************************* ** ** Function gatt_init ** ** Description This function is enable the GATT profile on the device. ** It clears out the control blocks, and registers with L2CAP. ** ** Returns void ** *******************************************************************************/ void gatt_init (void) { tL2CAP_FIXED_CHNL_REG fixed_reg; GATT_TRACE_DEBUG("gatt_init()"); memset (&gatt_cb, 0, sizeof(tGATT_CB)); memset (&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG)); #if defined(GATT_INITIAL_TRACE_LEVEL) gatt_cb.trace_level = GATT_INITIAL_TRACE_LEVEL; #else gatt_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */ #endif gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE; GKI_init_q (&gatt_cb.sign_op_queue); GKI_init_q (&gatt_cb.srv_chg_clt_q); GKI_init_q (&gatt_cb.pending_new_srv_start_q); /* First, register fixed L2CAP channel for ATT over BLE */ fixed_reg.fixed_chnl_opts.mode = L2CAP_FCR_BASIC_MODE; fixed_reg.fixed_chnl_opts.max_transmit = 0xFF; fixed_reg.fixed_chnl_opts.rtrans_tout = 2000; fixed_reg.fixed_chnl_opts.mon_tout = 12000; fixed_reg.fixed_chnl_opts.mps = 670; fixed_reg.fixed_chnl_opts.tx_win_sz = 1; fixed_reg.pL2CA_FixedConn_Cb = gatt_le_connect_cback; fixed_reg.pL2CA_FixedData_Cb = gatt_le_data_ind; fixed_reg.pL2CA_FixedCong_Cb = gatt_le_cong_cback; /* congestion callback */ fixed_reg.default_idle_tout = 0xffff; /* 0xffff default idle timeout */ L2CA_RegisterFixedChannel (L2CAP_ATT_CID, &fixed_reg); /* Now, register with L2CAP for ATT PSM over BR/EDR */ if (!L2CA_Register (BT_PSM_ATT, (tL2CAP_APPL_INFO *) &dyn_info)) { GATT_TRACE_ERROR ("ATT Dynamic Registration failed"); } BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0); BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0); gatt_cb.hdl_cfg.gatt_start_hdl = GATT_GATT_START_HANDLE; gatt_cb.hdl_cfg.gap_start_hdl = GATT_GAP_START_HANDLE; gatt_cb.hdl_cfg.app_start_hdl = GATT_APP_START_HANDLE; gatt_profile_db_init(); }
/******************************************************************************* ** ** Function bta_ag_start_servers ** ** Description Setup RFCOMM servers for use by AG. ** ** ** Returns void ** *******************************************************************************/ void bta_ag_start_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services) { int i; int bta_ag_port_status; services >>= BTA_HSP_SERVICE_ID; for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) { /* if service is set in mask */ if (services & 1) { BTM_SetSecurityLevel(FALSE, "", bta_ag_sec_id[i], p_scb->serv_sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_ag_cb.profile[i].scn); bta_ag_port_status = RFCOMM_CreateConnection(bta_ag_uuid[i], bta_ag_cb.profile[i].scn, TRUE, BTA_AG_MTU, (UINT8 *) bd_addr_any, &(p_scb->serv_handle[i]), bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]); if( bta_ag_port_status == PORT_SUCCESS ) { bta_ag_setup_port(p_scb, p_scb->serv_handle[i]); } else { /* TODO: CR#137125 to handle to error properly */ APPL_TRACE_DEBUG("bta_ag_start_servers: RFCOMM_CreateConnection returned error:%d", bta_ag_port_status); } } } }
/******************************************************************************* ** ** Function avdt_ccb_set_conn ** ** Description Set CCB variables associated with AVDT_ConnectReq(). ** ** ** Returns void. ** *******************************************************************************/ void avdt_ccb_set_conn(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) { /* save callback */ p_ccb->p_conn_cback = p_data->connect.p_cback; /* set security level */ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP, p_data->connect.sec_mask, AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG); }
/******************************************************************************* ** ** Function AVDT_Register ** ** Description This is the system level registration function for the ** AVDTP protocol. This function initializes AVDTP and ** prepares the protocol stack for its use. This function ** must be called once by the system or platform using AVDTP ** before the other functions of the API an be used. ** ** ** Returns void ** *******************************************************************************/ void AVDT_Register(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback) { /* register PSM with L2CAP */ L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO *) &avdt_l2c_appl); /* set security level */ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask, AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG); BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask, AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG); /* do not use security on the media channel */ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE, AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_MEDIA); BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE, AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_MEDIA); #if AVDT_REPORTING == TRUE /* do not use security on the reporting channel */ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE, AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_REPORT); BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVDTP_NOSEC, BTM_SEC_NONE, AVDT_PSM, BTM_SEC_PROTO_AVDT, AVDT_CHAN_REPORT); #endif /* initialize AVDTP data structures */ avdt_scb_init(); avdt_ccb_init(); avdt_ad_init(); /* copy registration struct */ memcpy(&avdt_cb.rcb, p_reg, sizeof(tAVDT_REG)); avdt_cb.p_conn_cback = p_cback; }
/******************************************************************************* ** ** Function bta_ag_rfc_do_open ** ** Description Open an RFCOMM connection to the peer device. ** ** ** Returns void ** *******************************************************************************/ void bta_ag_rfc_do_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) { BTM_SetSecurityLevel(TRUE, "", bta_ag_sec_id[p_scb->conn_service], p_scb->cli_sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, p_scb->peer_scn); if (RFCOMM_CreateConnection(bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn, FALSE, BTA_AG_MTU, p_scb->peer_addr, &(p_scb->conn_handle), bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]) == PORT_SUCCESS) { bta_ag_setup_port(p_scb, p_scb->conn_handle); APPL_TRACE_DEBUG("bta_ag_rfc_do_open : conn_handle = %d", p_scb->conn_handle); } /* RFCOMM create connection failed; send ourselves RFCOMM close event */ else { bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, p_data); } }
/******************************************************************************* ** ** Function mca_ccb_snd_rsp ** ** Description This function builds a response and sends it to ** the peer. ** ** Returns void. ** *******************************************************************************/ void mca_ccb_snd_rsp(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data) { tMCA_CCB_MSG *p_msg = (tMCA_CCB_MSG *)p_data; BT_HDR *p_pkt; UINT8 *p, *p_start; BOOLEAN chk_mdl = FALSE; tMCA_DCB *p_dcb; MCA_TRACE_DEBUG ("mca_ccb_snd_rsp cong=%d req=%d", p_ccb->cong, p_msg->op_code); /* assume that API functions verified the parameters */ p_pkt = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU); if (p_pkt) { p_pkt->offset = L2CAP_MIN_OFFSET; p = p_start = (UINT8*)(p_pkt + 1) + L2CAP_MIN_OFFSET; *p++ = p_msg->op_code; *p++ = p_msg->rsp_code; UINT16_TO_BE_STREAM (p, p_msg->mdl_id); if (p_msg->op_code == MCA_OP_MDL_CREATE_RSP) { *p++ = p_msg->param; chk_mdl = TRUE; } else if (p_msg->op_code == MCA_OP_MDL_RECONNECT_RSP) chk_mdl = TRUE; if (chk_mdl && p_msg->rsp_code == MCA_RSP_SUCCESS) { p_dcb = mca_dcb_by_hdl(p_msg->dcb_idx); BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_MCAP_DATA, p_ccb->sec_mask, p_ccb->p_rcb->reg.data_psm, BTM_SEC_PROTO_MCA, p_msg->dcb_idx); p_ccb->status = MCA_CCB_STAT_PENDING; /* set p_tx_req to block API_REQ/API_RSP before DL is up */ mca_free_buf ((void **)&p_ccb->p_tx_req); p_ccb->p_tx_req = p_ccb->p_rx_msg; p_ccb->p_rx_msg = NULL; p_ccb->p_tx_req->dcb_idx = p_msg->dcb_idx; } mca_free_buf ((void **)&p_ccb->p_rx_msg); p_pkt->len = p - p_start; L2CA_DataWrite (p_ccb->lcid, p_pkt); } }
tHID_STATUS HID_HostSetSecurityLevel( char serv_name[], UINT8 sec_lvl ) { if (!BTM_SetSecurityLevel (FALSE, serv_name, BTM_SEC_SERVICE_HID_SEC_CTRL, sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HID_SEC_CHN)) { HIDH_TRACE_ERROR0 ("Security Registration 1 failed"); return (HID_ERR_NO_RESOURCES); } if (!BTM_SetSecurityLevel (TRUE, serv_name, BTM_SEC_SERVICE_HID_SEC_CTRL, sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HID_SEC_CHN)) { HIDH_TRACE_ERROR0 ("Security Registration 2 failed"); return (HID_ERR_NO_RESOURCES); } if (!BTM_SetSecurityLevel (FALSE, serv_name, BTM_SEC_SERVICE_HID_NOSEC_CTRL, BTM_SEC_NONE, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HID_NOSEC_CHN)) { HIDH_TRACE_ERROR0 ("Security Registration 3 failed"); return (HID_ERR_NO_RESOURCES); } if (!BTM_SetSecurityLevel (TRUE, serv_name, BTM_SEC_SERVICE_HID_NOSEC_CTRL, BTM_SEC_NONE, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HID_NOSEC_CHN)) { HIDH_TRACE_ERROR0 ("Security Registration 4 failed"); return (HID_ERR_NO_RESOURCES); } if (!BTM_SetSecurityLevel (TRUE, serv_name, BTM_SEC_SERVICE_HID_INTR, BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID, 0)) { HIDH_TRACE_ERROR0 ("Security Registration 5 failed"); return (HID_ERR_NO_RESOURCES); } if (!BTM_SetSecurityLevel (FALSE, serv_name, BTM_SEC_SERVICE_HID_INTR, BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID, 0)) { HIDH_TRACE_ERROR0 ("Security Registration 6 failed"); return (HID_ERR_NO_RESOURCES); } return( HID_SUCCESS ); }
/******************************************************************************* ** ** Function GAP_ConnOpen ** ** Description This function is called to open an L2CAP connection. ** ** Parameters: is_server - If TRUE, the connection is not created ** but put into a "listen" mode waiting for ** the remote side to connect. ** ** service_id - Unique service ID from ** BTM_SEC_SERVICE_FIRST_EMPTY (6) ** to BTM_SEC_MAX_SERVICE_RECORDS (32) ** ** p_rem_bda - Pointer to remote BD Address. ** If a server, and we don't care about the ** remote BD Address, then NULL should be passed. ** ** psm - the PSM used for the connection ** ** p_config - Optional pointer to configuration structure. ** If NULL, the default GAP configuration will ** be used. ** ** security - security flags ** chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC, GAP_FCR_CHAN_OPT_ERTM, ** GAP_FCR_CHAN_OPT_STREAM) ** ** p_cb - Pointer to callback function for events. ** ** Returns handle of the connection if successful, else GAP_INVALID_HANDLE ** *******************************************************************************/ UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server, BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg, tL2CAP_ERTM_INFO *ertm_info, UINT16 security, UINT8 chan_mode_mask, tGAP_CONN_CALLBACK *p_cb) { tGAP_CCB *p_ccb; UINT16 cid; GAP_TRACE_EVENT ("GAP_CONN - Open Request"); /* Allocate a new CCB. Return if none available. */ if ((p_ccb = gap_allocate_ccb()) == NULL) return (GAP_INVALID_HANDLE); /* If caller specified a BD address, save it */ if (p_rem_bda) { /* the bd addr is not BT_BD_ANY, then a bd address was specified */ if (memcmp (p_rem_bda, BT_BD_ANY, BD_ADDR_LEN)) p_ccb->rem_addr_specified = TRUE; memcpy (&p_ccb->rem_dev_address[0], p_rem_bda, BD_ADDR_LEN); } else if (!is_server) { /* remore addr is not specified and is not a server -> bad */ return (GAP_INVALID_HANDLE); } /* A client MUST have specified a bd addr to connect with */ if (!p_ccb->rem_addr_specified && !is_server) { gap_release_ccb (p_ccb); GAP_TRACE_ERROR ("GAP ERROR: Client must specify a remote BD ADDR to connect to!"); return (GAP_INVALID_HANDLE); } /* Check if configuration was specified */ if (p_cfg) p_ccb->cfg = *p_cfg; p_ccb->p_callback = p_cb; /* If originator, use a dynamic PSM */ #if AMP_INCLUDED == TRUE if (!is_server) gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = NULL; else gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind; #else if (!is_server) gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = NULL; else gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind; #endif /* Register the PSM with L2CAP */ if ((p_ccb->psm = L2CA_REGISTER (psm, &gap_cb.conn.reg_info, AMP_AUTOSWITCH_ALLOWED|AMP_USE_AMP_IF_POSSIBLE)) == 0) { GAP_TRACE_ERROR ("GAP_ConnOpen: Failure registering PSM 0x%04x", psm); gap_release_ccb (p_ccb); return (GAP_INVALID_HANDLE); } /* Register with Security Manager for the specific security level */ p_ccb->service_id = service_id; if (!BTM_SetSecurityLevel ((UINT8)!is_server, p_serv_name, p_ccb->service_id, security, p_ccb->psm, 0, 0)) { GAP_TRACE_ERROR ("GAP_CONN - Security Error"); gap_release_ccb (p_ccb); return (GAP_INVALID_HANDLE); } /* Fill in eL2CAP parameter data */ if( p_ccb->cfg.fcr_present ) { if(ertm_info == NULL) { p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode; p_ccb->ertm_info.user_rx_pool_id = GAP_DATA_POOL_ID; p_ccb->ertm_info.user_tx_pool_id = GAP_DATA_POOL_ID; p_ccb->ertm_info.fcr_rx_pool_id = L2CAP_DEFAULT_ERM_POOL_ID; p_ccb->ertm_info.fcr_tx_pool_id = L2CAP_DEFAULT_ERM_POOL_ID; } else { p_ccb->ertm_info = *ertm_info; } } /* optional FCR channel modes */ if(ertm_info != NULL) { p_ccb->ertm_info.allowed_modes = (chan_mode_mask) ? chan_mode_mask : (UINT8)L2CAP_FCR_CHAN_OPT_BASIC; } if (is_server) { p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */ p_ccb->con_state = GAP_CCB_STATE_LISTENING; return (p_ccb->gap_handle); } else { /* We are the originator of this connection */ p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG; /* Transition to the next appropriate state, waiting for connection confirm. */ p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP; /* mark security done flag, when security is not required */ if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT) ) == 0) p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; /* Check if L2CAP started the connection process */ if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info)) != 0)) { p_ccb->connection_id = cid; return (p_ccb->gap_handle); } else { gap_release_ccb (p_ccb); return (GAP_INVALID_HANDLE); } } }
/******************************************************************************* ** ** Function mca_ccb_hdl_rsp ** ** Description This function is called when a MCAP response is received from ** the peer. It calls the application callback function with ** the results. ** ** Returns void. ** *******************************************************************************/ void mca_ccb_hdl_rsp(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data) { BT_HDR *p_pkt = &p_data->hdr; UINT8 *p; tMCA_CTRL evt_data; BOOLEAN chk_mdl = FALSE; tMCA_DCB *p_dcb; tMCA_RESULT result = MCA_BAD_HANDLE; tMCA_TC_TBL *p_tbl; if (p_ccb->p_tx_req) { /* verify that the received response matches the sent request */ p = (UINT8 *)(p_pkt + 1) + p_pkt->offset; evt_data.hdr.op_code = *p++; if ((evt_data.hdr.op_code == 0) || ((p_ccb->p_tx_req->op_code + 1) == evt_data.hdr.op_code)) { evt_data.rsp.rsp_code = *p++; mca_stop_timer(p_ccb); BE_STREAM_TO_UINT16 (evt_data.hdr.mdl_id, p); if (evt_data.hdr.op_code == MCA_OP_MDL_CREATE_RSP) { evt_data.create_cfm.cfg = *p++; chk_mdl = TRUE; } else if (evt_data.hdr.op_code == MCA_OP_MDL_RECONNECT_RSP) chk_mdl = TRUE; if (chk_mdl) { p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx); if (p_dcb && evt_data.rsp.rsp_code == MCA_RSP_SUCCESS) { if (evt_data.hdr.mdl_id != p_dcb->mdl_id) { MCA_TRACE_ERROR ("peer's mdl_id=%d != our mdl_id=%d", evt_data.hdr.mdl_id, p_dcb->mdl_id); /* change the response code to be an error */ if (evt_data.rsp.rsp_code == MCA_RSP_SUCCESS) { evt_data.rsp.rsp_code = MCA_RSP_BAD_MDL; /* send Abort */ p_ccb->status = MCA_CCB_STAT_PENDING; MCA_Abort(mca_ccb_to_hdl(p_ccb)); } } else if (p_dcb->p_chnl_cfg) { /* the data channel configuration is known. Proceed with data channel initiation */ BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_MCAP_DATA, p_ccb->sec_mask, p_ccb->data_vpsm, BTM_SEC_PROTO_MCA, p_ccb->p_tx_req->dcb_idx); p_dcb->lcid = mca_l2c_open_req(p_ccb->peer_addr, p_ccb->data_vpsm, p_dcb->p_chnl_cfg); if (p_dcb->lcid) { p_tbl = mca_tc_tbl_dalloc(p_dcb); if (p_tbl) { p_tbl->state = MCA_TC_ST_CONN; p_ccb->status = MCA_CCB_STAT_PENDING; result = MCA_SUCCESS; } } } else { /* mark this MCL as pending and wait for MCA_DataChnlCfg */ p_ccb->status = MCA_CCB_STAT_PENDING; result = MCA_SUCCESS; } } if (result != MCA_SUCCESS && p_dcb) { mca_dcb_dealloc(p_dcb, NULL); } } /* end of chk_mdl */ if (p_ccb->status != MCA_CCB_STAT_PENDING) mca_free_buf ((void **)&p_ccb->p_tx_req); mca_ccb_report_event(p_ccb, evt_data.hdr.op_code, &evt_data); } /* else a bad response is received */ } else { /* not expecting any response. drop it */ MCA_TRACE_WARNING ("dropping received rsp (not expecting a response)"); } GKI_freebuf (p_data); }
/******************************************************************************* ** ** Function pan_register_with_sdp ** ** Description ** ** Returns ** *******************************************************************************/ UINT32 pan_register_with_sdp (UINT16 uuid, UINT8 sec_mask, char *p_name, char *p_desc) { UINT32 sdp_handle; UINT16 browse_list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; UINT16 security = 0; UINT8 availability; UINT32 proto_len = (UINT32)pan_proto_elem_data[1]; /* Create a record */ sdp_handle = SDP_CreateRecord (); if (sdp_handle == 0) { PAN_TRACE_ERROR0 ("PAN_SetRole - could not create SDP record"); return 0; } /* Service Class ID List */ SDP_AddServiceClassIdList (sdp_handle, 1, &uuid); /* Add protocol element sequence from the constant string */ SDP_AddAttribute (sdp_handle, ATTR_ID_PROTOCOL_DESC_LIST, DATA_ELE_SEQ_DESC_TYPE, proto_len, (UINT8 *)(pan_proto_elem_data+2)); // btla-specific ++ #if 0 availability = 0xFF; SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_AVAILABILITY, UINT_DESC_TYPE, 1, &availability); #endif // btla-specific -- /* Language base */ SDP_AddLanguageBaseAttrIDList (sdp_handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8, LANGUAGE_BASE_ID); /* Profile descriptor list */ SDP_AddProfileDescriptorList (sdp_handle, uuid, PAN_PROFILE_VERSION); /* Service Name */ SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, (UINT8) (strlen(p_name) + 1), (UINT8 *)p_name); /* Service description */ SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE, (UINT8) (strlen(p_desc) + 1), (UINT8 *)p_desc); /* Security description */ if (sec_mask) { UINT16_TO_BE_FIELD(&security, 0x0001); } SDP_AddAttribute (sdp_handle, ATTR_ID_SECURITY_DESCRIPTION, UINT_DESC_TYPE, 2, (UINT8 *)&security); #if (defined (PAN_SUPPORTS_ROLE_NAP) && PAN_SUPPORTS_ROLE_NAP == TRUE) if (uuid == UUID_SERVCLASS_NAP) { UINT16 NetAccessType = 0x0005; /* Ethernet */ UINT32 NetAccessRate = 0x0001312D0; /* 10Mb/sec */ UINT8 array[10], *p; /* Net access type. */ p = array; UINT16_TO_BE_STREAM (p, NetAccessType); SDP_AddAttribute (sdp_handle, ATTR_ID_NET_ACCESS_TYPE, UINT_DESC_TYPE, 2, array); /* Net access rate. */ p = array; UINT32_TO_BE_STREAM (p, NetAccessRate); SDP_AddAttribute (sdp_handle, ATTR_ID_MAX_NET_ACCESS_RATE, UINT_DESC_TYPE, 4, array); /* Register with Security Manager for the specific security level */ if ((!BTM_SetSecurityLevel (TRUE, p_name, BTM_SEC_SERVICE_BNEP_NAP, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_NAP)) || (!BTM_SetSecurityLevel (FALSE, p_name, BTM_SEC_SERVICE_BNEP_NAP, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_NAP))) { PAN_TRACE_ERROR0 ("PAN Security Registration failed for PANU"); } } #endif #if (defined (PAN_SUPPORTS_ROLE_GN) && PAN_SUPPORTS_ROLE_GN == TRUE) if (uuid == UUID_SERVCLASS_GN) { if ((!BTM_SetSecurityLevel (TRUE, p_name, BTM_SEC_SERVICE_BNEP_GN, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_GN)) || (!BTM_SetSecurityLevel (FALSE, p_name, BTM_SEC_SERVICE_BNEP_GN, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_GN))) { PAN_TRACE_ERROR0 ("PAN Security Registration failed for GN"); } } #endif #if (defined (PAN_SUPPORTS_ROLE_PANU) && PAN_SUPPORTS_ROLE_PANU == TRUE) if (uuid == UUID_SERVCLASS_PANU) { if ((!BTM_SetSecurityLevel (TRUE, p_name, BTM_SEC_SERVICE_BNEP_PANU, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_PANU)) || (!BTM_SetSecurityLevel (FALSE, p_name, BTM_SEC_SERVICE_BNEP_PANU, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_PANU))) { PAN_TRACE_ERROR0 ("PAN Security Registration failed for PANU"); } } #endif /* Make the service browsable */ SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse_list); return sdp_handle; }