Ejemplo n.º 1
0
/*******************************************************************************
**
** 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);
    }
}
Ejemplo n.º 2
0
/*******************************************************************************
**
** Function         avdt_sec_check_complete_orig
**
** Description      The function called when Security Manager finishes
**                  verification of the service side connection
**
** Returns          void
**
*******************************************************************************/
static void avdt_sec_check_complete_orig (BD_ADDR bd_addr, tBT_TRANSPORT trasnport,
        void *p_ref_data, UINT8 res)
{
    tAVDT_CCB       *p_ccb = NULL;
    tL2CAP_CFG_INFO cfg;
    tAVDT_TC_TBL    *p_tbl;
    UNUSED(p_ref_data);

    AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d\n", res);
    if (bd_addr) {
        p_ccb = avdt_ccb_by_bd(bd_addr);
    }
    p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_INT);
    if (p_tbl == NULL) {
        return;
    }

    if ( res == BTM_SUCCESS ) {
        /* 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(p_tbl->lcid, &cfg);
    } else {
        L2CA_DisconnectReq (p_tbl->lcid);
        avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
    }
}
/*******************************************************************************
**
** Function         mca_sec_check_complete_term
**
** Description      The function called when Security Manager finishes
**                  verification of the service side connection
**
** Returns          void
**
*******************************************************************************/
static void mca_sec_check_complete_term (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
{
    tMCA_TC_TBL     *p_tbl = (tMCA_TC_TBL *)p_ref_data;
    tL2CAP_CFG_INFO cfg;
    tL2CAP_ERTM_INFO ertm_info;

    MCA_TRACE_DEBUG1("mca_sec_check_complete_term res: %d", res);

    if ( res == BTM_SUCCESS )
    {
        MCA_TRACE_DEBUG2 ("lcid:x%x id:x%x", p_tbl->lcid, p_tbl->id);
        /* 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;
        /* Send response to the L2CAP layer. */
        L2CA_ErtmConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK, L2CAP_CONN_OK, &ertm_info);

        /* transition to configuration 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);
    }
    else
    {
        L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_SECURITY_BLOCK, L2CAP_CONN_OK);
        mca_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
    }
}
Ejemplo n.º 4
0
/*******************************************************************************
**
** Function         hidh_sec_check_complete_term
**
** Description      HID security check complete callback function.
**
** Returns          Send L2CA_ConnectRsp OK if secutiry check succeed; otherwise
**                  send security block L2C connection response.
**
*******************************************************************************/
void hidh_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res)
{
    tHID_HOST_DEV_CTB *p_dev= (tHID_HOST_DEV_CTB *) p_ref_data;
    UNUSED(bd_addr);
    UNUSED (transport);

    if( res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY )
    {
        p_dev->conn.disc_reason = HID_SUCCESS;  /* Authentication passed. Reset disc_reason (from HID_ERR_AUTH_FAILED) */

        p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_INTR;

        /* Send response to the L2CAP layer. */
        L2CA_ConnectRsp (p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid, L2CAP_CONN_OK, L2CAP_CONN_OK);

        /* Send a Configuration Request. */
        L2CA_ConfigReq (p_dev->conn.ctrl_cid, &hh_cb.l2cap_cfg);

    }
    /* security check fail */
    else if (res != BTM_SUCCESS)
    {
        p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED;      /* Save reason for disconnecting */
        p_dev->conn.conn_state = HID_CONN_STATE_UNUSED;
        L2CA_ConnectRsp (p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid, L2CAP_CONN_SECURITY_BLOCK, L2CAP_CONN_OK);
    }
}
/*******************************************************************************
**
** 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         sdp_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 sdp_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id)
{
#if SDP_SERVER_ENABLED == TRUE
    tCONN_CB    *p_ccb;

    /* Allocate a new CCB. Return if none available. */
    if ((p_ccb = sdpu_allocate_ccb()) == NULL)
        return;

    /* Transition to the next appropriate state, waiting for config setup. */
    p_ccb->con_state = SDP_STATE_CFG_SETUP;

    /* Save the BD Address and Channel ID. */
    memcpy (&p_ccb->device_address[0], bd_addr, sizeof (BD_ADDR));
    p_ccb->connection_id = l2cap_cid;

    /* Send response to the L2CAP layer. */
    L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK);
    {
        tL2CAP_CFG_INFO cfg = sdp_cb.l2cap_my_cfg;

        if (cfg.fcr_present)
        {
            SDP_TRACE_DEBUG6("sdp_connect_ind:  mode %u, txwinsz %u, max_trans %u, rtrans_tout %u, mon_tout %u, mps %u",
                             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.mode = L2CAP_FCR_BASIC_MODE;
            cfg.fcr_present = FALSE;
            L2CA_ConfigReq (l2cap_cid, &cfg);
        }
    }

    SDP_TRACE_EVENT1 ("SDP - Rcvd L2CAP conn ind, sent config req, CID 0x%x", p_ccb->connection_id);
#else   /* No server */
    /* Reject the connection */
    L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_PSM, 0);
#endif
}
/*******************************************************************************
**
** Function         mca_l2c_dconn_ind_cback
**
** Description      This is the L2CAP connect indication callback function.
**
**
** Returns          void
**
*******************************************************************************/
void mca_l2c_dconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
{
    tMCA_HANDLE handle = mca_handle_by_dpsm(psm);
    tMCA_CCB    *p_ccb;
    tMCA_DCB       *p_dcb;
    tMCA_TC_TBL    *p_tbl = NULL;
    UINT16          result;
    tL2CAP_CFG_INFO cfg;
    tL2CAP_ERTM_INFO *p_ertm_info = NULL, ertm_info;
    const tMCA_CHNL_CFG   *p_chnl_cfg;

    MCA_TRACE_EVENT2 ("mca_l2c_dconn_ind_cback: lcid:x%x psm:x%x ", lcid, psm);

    if (((p_ccb = mca_ccb_by_bd(handle, bd_addr)) != NULL) && /* find the CCB */
        (p_ccb->status == MCA_CCB_STAT_PENDING) &&  /* this CCB is expecting a MDL */
        (p_ccb->p_tx_req && (p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx)) != NULL))
    {
        /* found the associated dcb in listening mode */
        /* proceed with connection */
        p_dcb->lcid     = lcid;
        p_tbl           = mca_tc_tbl_dalloc(p_dcb);
        p_tbl->id       = id;
        p_tbl->cfg_flags= MCA_L2C_CFG_CONN_ACP;
        p_chnl_cfg = p_dcb->p_chnl_cfg;
        /* assume that control channel has verified the security requirement */
        /* Set the FCR options: control channel mandates ERTM */
        ertm_info.preferred_mode    = p_chnl_cfg->fcr_opt.mode;
        ertm_info.allowed_modes     = (1 << p_chnl_cfg->fcr_opt.mode);
        ertm_info.user_rx_pool_id   = p_chnl_cfg->user_rx_pool_id;
        ertm_info.user_tx_pool_id   = p_chnl_cfg->user_tx_pool_id;
        ertm_info.fcr_rx_pool_id    = p_chnl_cfg->fcr_rx_pool_id;
        ertm_info.fcr_tx_pool_id    = p_chnl_cfg->fcr_tx_pool_id;
        p_ertm_info = &ertm_info;
        result = L2CAP_CONN_OK;
    }
    else
    {
        /* else we're not listening for traffic channel; reject
         * (this error code is specified by MCAP spec) */
        result = L2CAP_CONN_NO_RESOURCES;
    }

    /* Send L2CAP connect rsp */
    L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, result, p_ertm_info);

    /* if result ok, proceed with connection */
    if (result == L2CAP_CONN_OK)
    {
        /* transition to configuration state */
        p_tbl->state = MCA_TC_ST_CFG;

        /* Send L2CAP config req */
        mca_set_cfg_by_tbl (&cfg, p_tbl);
        L2CA_ConfigReq(lcid, &cfg);
    }
}
Ejemplo n.º 8
0
/*******************************************************************************
**
** Function         avct_l2c_connect_ind_cback
**
** Description      This is the L2CAP connect indication callback function.
**
**
** Returns          void
**
*******************************************************************************/
void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
{
    tAVCT_LCB       *p_lcb;
    UINT16          result = L2CAP_CONN_OK;
    tL2CAP_CFG_INFO cfg;
    UNUSED(psm);

    /* do we already have a channel for this peer? */
    if ((p_lcb = avct_lcb_by_bd(bd_addr)) == NULL) {
        /* no, allocate lcb */
        if ((p_lcb = avct_lcb_alloc(bd_addr)) == NULL) {
            /* no ccb available, reject L2CAP connection */
            result = L2CAP_CONN_NO_RESOURCES;
        }
    }
    /* else we already have a channel for this peer */
    else {
        if (!avct_l2c_is_passive (p_lcb) || (p_lcb->ch_state == AVCT_CH_OPEN)) {
            /* this LCB included CT role - reject */
            result = L2CAP_CONN_NO_RESOURCES;
        } else {
            /* TG role only - accept the connection from CT. move the channel ID to the conflict list */
            p_lcb->conflict_lcid = p_lcb->ch_lcid;
            AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback conflict_lcid:0x%x", p_lcb->conflict_lcid);
        }
    }

    if (p_lcb) {
        AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback: 0x%x, res: %d, ch_state: %d",
                         lcid, result, p_lcb->ch_state);
    }
    /* Send L2CAP connect rsp */
    L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);

    /* if result ok, proceed with connection */
    if (result == L2CAP_CONN_OK) {
        /* store LCID */
        p_lcb->ch_lcid = lcid;

        /* transition to configuration state */
        p_lcb->ch_state = AVCT_CH_CFG;

        /* Send L2CAP config req */
        memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
        cfg.mtu_present = TRUE;
        cfg.mtu = avct_cb.mtu;
        L2CA_ConfigReq(lcid, &cfg);
        AVCT_TRACE_DEBUG("avct_l2c snd Cfg Req");
    }

#if (BT_USE_TRACES == TRUE)
    if (p_lcb) {
        AVCT_TRACE_DEBUG("ch_state cni: %d ", p_lcb->ch_state);
    }
#endif
}
static BOOLEAN L2cap_ConfigReq(UINT16 cid, tL2CAP_CFG_INFO *p_cfg)
{
    BTIF_TRACE_DEBUG("L2cap_ConfigReq:: Invoked\n");
    if (p_cfg->fcr_present)
    {
        BTIF_TRACE_DEBUG("L2cap_ConfigReq::  mode %u, txwinsz %u, max_trans %u, rtrans_tout %u, mon_tout %u, mps %u\n",
                           p_cfg->fcr.mode, p_cfg->fcr.tx_win_sz, p_cfg->fcr.max_transmit,
                           p_cfg->fcr.rtrans_tout,p_cfg->fcr.mon_tout, p_cfg->fcr.mps);
    }
    return L2CA_ConfigReq (cid, p_cfg);
}
Ejemplo n.º 10
0
/*******************************************************************************
**
** 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         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
    }
}
Ejemplo n.º 12
0
/*******************************************************************************
**
** Function         avdt_sec_check_complete_term
**
** Description      The function called when Security Manager finishes
**                  verification of the service side connection
**
** Returns          void
**
*******************************************************************************/
static void avdt_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transport,
        void *p_ref_data, UINT8 res)
{
    tAVDT_CCB       *p_ccb = NULL;
    tL2CAP_CFG_INFO cfg;
    tAVDT_TC_TBL    *p_tbl;
    UNUSED(p_ref_data);

    AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d\n", res);
    if (!bd_addr) {
        AVDT_TRACE_WARNING("avdt_sec_check_complete_term: NULL BD_ADDR");
        return;

    }
    p_ccb = avdt_ccb_by_bd(bd_addr);

    p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_ACP);
    if (p_tbl == NULL) {
        return;
    }

    if (res == BTM_SUCCESS) {
        /* Send response to the L2CAP layer. */
        L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK, L2CAP_CONN_OK);

        /* store idx in LCID table, store LCID in routing table */
        avdt_cb.ad.lcid_tbl[p_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 = p_tbl->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(p_tbl->lcid, &cfg);
    } else {
        L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_SECURITY_BLOCK, L2CAP_CONN_OK);
        avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
    }
}
Ejemplo n.º 13
0
/*******************************************************************************
**
** Function         avct_l2c_connect_cfm_cback
**
** Description      This is the L2CAP connect confirm callback function.
**
**
** Returns          void
**
*******************************************************************************/
void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
{
    tAVCT_LCB       *p_lcb;
    tL2CAP_CFG_INFO cfg;

    /* look up lcb for this channel */
    if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) {
        AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback lcid:0x%x result: %d ch_state: %d, conflict_lcid:0x%x",
                         lcid, result, p_lcb->ch_state, p_lcb->conflict_lcid);
        /* if in correct state */
        if (p_lcb->ch_state == AVCT_CH_CONN) {
            /* if result successful */
            if (result == L2CAP_CONN_OK) {
                /* set channel state */
                p_lcb->ch_state = AVCT_CH_CFG;

                /* Send L2CAP config req */
                memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
                cfg.mtu_present = TRUE;
                cfg.mtu = avct_cb.mtu;
                L2CA_ConfigReq(lcid, &cfg);
                AVCT_TRACE_DEBUG("avct_l2c snd Cfg Req");
            }
            /* else failure */
            else {
                AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback conflict_lcid:0x%x", p_lcb->conflict_lcid);
                if (p_lcb->conflict_lcid == lcid) {
                    p_lcb->conflict_lcid = 0;
                } else {
                    avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
                }
            }
        } else if (p_lcb->conflict_lcid == lcid) {
            /* we must be in AVCT_CH_CFG state for the ch_lcid channel */
            AVCT_TRACE_DEBUG("avct_l2c_connect_cfm_cback ch_state: %d, conflict_lcid:0x%x", p_lcb->ch_state, p_lcb->conflict_lcid);
            if (result == L2CAP_CONN_OK) {
                /* just in case the peer also accepts our connection - Send L2CAP disconnect req */
                L2CA_DisconnectReq(lcid);
            }
            p_lcb->conflict_lcid = 0;
        }
        AVCT_TRACE_DEBUG("ch_state cnc: %d ", p_lcb->ch_state);
    }
}
Ejemplo n.º 14
0
/*******************************************************************************
**
** Function         gatt_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 gatt_l2cif_connect_ind_cback (BD_ADDR  bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
{
    /* do we already have a control channel for this peer? */
    UINT8       result = L2CAP_CONN_OK;
    tL2CAP_CFG_INFO cfg;
    tGATT_TCB       *p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_BR_EDR);
    UNUSED(psm);

    GATT_TRACE_ERROR("Connection indication cid = %d", lcid);
    /* new connection ? */
    if (p_tcb == NULL)
    {
        /* allocate tcb */
        if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_BR_EDR)) == NULL)
        {
            /* no tcb available, reject L2CAP connection */
            result = L2CAP_CONN_NO_RESOURCES;
        }
        else
            p_tcb->att_lcid = lcid;

    }
    else /* existing connection , reject it */
    {
        result = L2CAP_CONN_NO_RESOURCES;
    }

    /* Send L2CAP connect rsp */
    L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);

    /* if result ok, proceed with connection */
    if (result == L2CAP_CONN_OK)
    {
        /* transition to configuration state */
        gatt_set_ch_state(p_tcb, GATT_CH_CFG);

        /* Send L2CAP config req */
        memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
        cfg.mtu_present = TRUE;
        cfg.mtu = GATT_MAX_MTU_SIZE;

        L2CA_ConfigReq(lcid, &cfg);
    }
}
Ejemplo n.º 15
0
/*******************************************************************************
**
** Function         gatt_l2c_connect_cfm_cback
**
** Description      This is the L2CAP connect confirm callback function.
**
**
** Returns          void
**
*******************************************************************************/
static void gatt_l2cif_connect_cfm_cback(UINT16 lcid, UINT16 result)
{
    tGATT_TCB       *p_tcb;
    tL2CAP_CFG_INFO cfg;

    /* look up clcb for this channel */
    if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
    {
        GATT_TRACE_DEBUG("gatt_l2c_connect_cfm_cback result: %d ch_state: %d, lcid:0x%x", result, gatt_get_ch_state(p_tcb), p_tcb->att_lcid);

        /* if in correct state */
        if (gatt_get_ch_state(p_tcb) == GATT_CH_CONN)
        {
            /* if result successful */
            if (result == L2CAP_CONN_OK)
            {
                /* set channel state */
                gatt_set_ch_state(p_tcb, GATT_CH_CFG);

                /* Send L2CAP config req */
                memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
                cfg.mtu_present = TRUE;
                cfg.mtu = GATT_MAX_MTU_SIZE;
                L2CA_ConfigReq(lcid, &cfg);
            }
            /* else initiating connection failure */
            else
            {
                gatt_cleanup_upon_disc(p_tcb->peer_bda, result, GATT_TRANSPORT_BR_EDR);
            }
        }
        else /* wrong state, disconnect it */
        {
            if (result == L2CAP_CONN_OK)
            {
                /* just in case the peer also accepts our connection - Send L2CAP disconnect req */
                L2CA_DisconnectReq(lcid);
            }
        }
    }
}
Ejemplo n.º 16
0
/*******************************************************************************
**
** Function         rfc_mx_send_config_req
**
** Description      This function handles L2CA_ConnectInd message from the
**                  L2CAP.  Accept connection.
**
*******************************************************************************/
static void rfc_mx_send_config_req (tRFC_MCB *p_mcb)
{
    tL2CAP_CFG_INFO cfg;

    RFCOMM_TRACE_EVENT0 ("rfc_mx_send_config_req");

    memset (&cfg, 0, sizeof (tL2CAP_CFG_INFO));

    cfg.mtu_present      = TRUE;
    cfg.mtu              = L2CAP_MTU_SIZE;

/* Defaults set by memset
    cfg.flush_to_present = FALSE;
    cfg.qos_present      = FALSE;
    cfg.fcr_present      = FALSE;
    cfg.fcr.mode         = L2CAP_FCR_BASIC_MODE;
    cfg.fcs_present      = FALSE;
    cfg.fcs              = N/A when fcs_present is FALSE;
*/
    L2CA_ConfigReq (p_mcb->lcid, &cfg);
}
Ejemplo n.º 17
0
/*******************************************************************************
**
** 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, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res)
{
    tHID_HOST_DEV_CTB *p_dev = (tHID_HOST_DEV_CTB *) p_ref_data;
    UINT8 dhandle;
    UNUSED(bd_addr);
    UNUSED (transport);

    // TODO(armansito): This kind of math to determine a device handle is way
    // too dirty and unnecessary. Why can't |p_dev| store it's handle?
    dhandle = (PTR_TO_UINT(p_dev) - PTR_TO_UINT(&(hh_cb.devices[0])))/ sizeof(tHID_HOST_DEV_CTB);
    if( res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY )
    {
        HIDH_TRACE_EVENT ("HID-Host Originator security pass.");
        p_dev->conn.disc_reason = HID_SUCCESS;  /* Authentication passed. Reset disc_reason (from HID_ERR_AUTH_FAILED) */

        /* Transition to the next appropriate state, configuration */
        p_dev->conn.conn_state = HID_CONN_STATE_CONFIG;
        L2CA_ConfigReq (p_dev->conn.ctrl_cid, &hh_cb.l2cap_cfg);
        HIDH_TRACE_EVENT ("HID-Host Got Control conn cnf, sent cfg req, CID: 0x%x", p_dev->conn.ctrl_cid);

    }

    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;
            }
        }
#endif
        p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED;      /* Save reason for disconnecting */
        hidh_conn_disconnect(dhandle);
    }

}
/*******************************************************************************
**
** Function         mca_sec_check_complete_orig
**
** Description      The function called when Security Manager finishes
**                  verification of the service side connection
**
** Returns          void
**
*******************************************************************************/
static void mca_sec_check_complete_orig (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
{
    tMCA_TC_TBL     *p_tbl = (tMCA_TC_TBL *)p_ref_data;
    tL2CAP_CFG_INFO cfg;

    MCA_TRACE_DEBUG1("mca_sec_check_complete_orig res: %d", res);

    if ( res == BTM_SUCCESS )
    {
        /* 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);
    }
    else
    {
        L2CA_DisconnectReq (p_tbl->lcid);
        mca_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
    }
}
/*******************************************************************************
**
** 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);
}
Ejemplo n.º 20
0
/*******************************************************************************
**
** 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);
}
Ejemplo n.º 21
0
/*******************************************************************************
**
** 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         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);
        }
    }
}
Ejemplo n.º 23
0
/*******************************************************************************
**
** 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);
    }
}