示例#1
0
文件: hidh_conn.c 项目: morrey/bt_bcm
/*******************************************************************************
**
** 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_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);
    }
}
static BOOLEAN L2cap_ConnectRsp(BD_ADDR p_bd_addr, UINT8 id, UINT16 lcid,
                                        UINT16 result, UINT16 status)
{
    if (!L2CA_ConnectRsp (p_bd_addr, id, lcid, result, status)) {
        BTIF_TRACE_DEBUG("L2CA_ConnectRsp:: error ");
        return  BT_STATUS_FAIL;
    }
    return BT_STATUS_SUCCESS;
}
示例#4
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);
    }
}
/*******************************************************************************
**
** 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
}
示例#6
0
文件: avct_l2c.c 项目: tve/esp-idf
/*******************************************************************************
**
** 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
}
示例#7
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);
}
示例#8
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);
    }
}
/*******************************************************************************
**
** Function         RFCOMM_ConnectInd
**
** Description      This is a callback function called by L2CAP when
**                  L2CA_ConnectInd received.  Allocate multiplexer control block
**                  and dispatch the event to it.
**
*******************************************************************************/
void RFCOMM_ConnectInd (BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
{
    tRFC_MCB *p_mcb = rfc_alloc_multiplexer_channel(bd_addr, FALSE);
    UNUSED(psm);

    if ((p_mcb)&&(p_mcb->state != RFC_MX_STATE_IDLE))
    {
        /* if this is collision case */
        if ((p_mcb->is_initiator)&&(p_mcb->state == RFC_MX_STATE_WAIT_CONN_CNF))
        {
            p_mcb->pending_lcid = lcid;
            p_mcb->pending_id   = id;

            /* wait random timeout (2 - 12) to resolve collision */
            /* if peer gives up then local device rejects incoming connection and continues as initiator */
            /* if timeout, local device disconnects outgoing connection and continues as acceptor */
            RFCOMM_TRACE_DEBUG ("RFCOMM_ConnectInd start timer for collision, initiator's LCID(0x%x), acceptor's LCID(0x%x)",
                                  p_mcb->lcid, p_mcb->pending_lcid);

            rfc_timer_start(p_mcb, (UINT16)(GKI_get_tick_count()%10 + 2));
            return;
        }
        else
        {
            /* we cannot accept connection request from peer at this state */
            /* don't update lcid */
            p_mcb = NULL;
        }
    }
    else
    {
        /* store mcb even if null */
        rfc_save_lcid_mcb (p_mcb, lcid);
    }

    if (p_mcb == NULL)
    {
        L2CA_ConnectRsp (bd_addr, id, lcid, L2CAP_CONN_NO_RESOURCES, 0);
        return;
    }
    p_mcb->lcid     = lcid;

    rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_CONN_IND, &id);
}
示例#10
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);
    }
}
/*******************************************************************************
**
** Function         RFCOMM_ConnectCnf
**
** Description      This is a callback function called by L2CAP when
**                  L2CA_ConnectCnf received.  Save L2CAP handle and dispatch
**                  event to the FSM.
**
*******************************************************************************/
void RFCOMM_ConnectCnf (UINT16 lcid, UINT16 result)
{
    tRFC_MCB *p_mcb = rfc_find_lcid_mcb (lcid);

    if (!p_mcb)
    {
        RFCOMM_TRACE_ERROR ("RFCOMM_ConnectCnf LCID:0x%x", lcid);
        return;
    }

    if (p_mcb->pending_lcid)
    {
        /* if peer rejects our connect request but peer's connect request is pending */
        if (result != L2CAP_CONN_OK )
        {
            UINT16 i;
            UINT8  idx;

            RFCOMM_TRACE_DEBUG ("RFCOMM_ConnectCnf retry as acceptor on pending LCID(0x%x)", p_mcb->pending_lcid);

            /* remove mcb from mapping table */
            rfc_save_lcid_mcb (NULL, p_mcb->lcid);

            p_mcb->lcid         = p_mcb->pending_lcid;
            p_mcb->is_initiator = FALSE;
            p_mcb->state        = RFC_MX_STATE_IDLE;

            /* store mcb into mapping table */
            rfc_save_lcid_mcb (p_mcb, p_mcb->lcid);

            /* update direction bit */
            for (i = 0; i < RFCOMM_MAX_DLCI; i += 2)
            {
                if ((idx = p_mcb->port_inx[i]) != 0)
                {
                    p_mcb->port_inx[i] = 0;
                    p_mcb->port_inx[i+1] = idx;
                    rfc_cb.port.port[idx - 1].dlci += 1;
                    RFCOMM_TRACE_DEBUG ("RFCOMM MX - DLCI:%d -> %d", i, rfc_cb.port.port[idx - 1].dlci);
                }
            }

            rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_CONN_IND, &(p_mcb->pending_id));
            return;
        }
        else
        {
            RFCOMM_TRACE_DEBUG ("RFCOMM_ConnectCnf peer gave up pending LCID(0x%x)", p_mcb->pending_lcid);

            /* Peer gave up his connection request, make sure cleaning up L2CAP channel */
            L2CA_ConnectRsp (p_mcb->bd_addr, p_mcb->pending_id, p_mcb->pending_lcid, L2CAP_CONN_NO_RESOURCES, 0);

            p_mcb->pending_lcid = 0;
        }
    }

    /* Save LCID to be used in all consecutive calls to L2CAP */
    p_mcb->lcid         = lcid;

    rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_CONN_CNF, &result);
}
示例#12
0
文件: hidh_conn.c 项目: morrey/bt_bcm
/*******************************************************************************
**
** Function         hidh_l2cif_connect_ind
**
** Description      This function handles an inbound connection indication
**                  from L2CAP. This is the case where we are acting as a
**                  server.
**
** Returns          void
**
*******************************************************************************/
static void hidh_l2cif_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id)
{
    tHID_CONN    *p_hcon;
    BOOLEAN      bAccept = TRUE;
    UINT8        i = HID_HOST_MAX_DEVICES;
    tHID_HOST_DEV_CTB *p_dev;

    HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP conn ind, PSM: 0x%04x  CID 0x%x", psm, l2cap_cid);

    /* always add incoming connection device into HID database by default */
    if (HID_HostAddDev(bd_addr, HID_SEC_REQUIRED, &i) != HID_SUCCESS)
    {
        L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_SECURITY_BLOCK, 0);
        return;
    }

    p_hcon = &hh_cb.devices[i].conn;
    p_dev  = &hh_cb.devices[i];

    /* Stop the retry timer if active */
#if (HID_HOST_MAX_CONN_RETRY > 0)
#if (HID_HOST_REPAGE_WIN > 0)
    HIDH_TRACE_DEBUG ("HID-Host stopping retry timer as l2cap is connected from remote side");
    p_dev->conn_tries = HID_HOST_MAX_CONN_RETRY+1;
    btu_stop_timer(&(p_dev->conn.timer_entry));
#endif
#endif

    /* Check we are in the correct state for this */
    if (psm == HID_PSM_INTERRUPT)
    {
        if (p_hcon->ctrl_cid == 0)
        {
            HIDH_TRACE_WARNING ("HID-Host Rcvd INTR L2CAP conn ind, but no CTL channel");
            bAccept = FALSE;
        }
        if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)
        {
            HIDH_TRACE_WARNING ("HID-Host Rcvd INTR L2CAP conn ind, wrong state: %d",
                                 p_hcon->conn_state);
            bAccept = FALSE;
        }
    }
    else /* CTRL channel */
    {
#if defined(HID_HOST_ACPT_NEW_CONN) && (HID_HOST_ACPT_NEW_CONN == TRUE)
        p_hcon->ctrl_cid = p_hcon->intr_cid = 0;
        p_hcon->conn_state = HID_CONN_STATE_UNUSED;
#else
        if (p_hcon->conn_state != HID_CONN_STATE_UNUSED)
        {
            HIDH_TRACE_WARNING ("HID-Host - Rcvd CTL L2CAP conn ind, wrong state: %d",
                                 p_hcon->conn_state);
            bAccept = FALSE;
        }
#endif
    }

    if (!bAccept)
    {
        L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_RESOURCES, 0);
        return;
    }

    if (psm == HID_PSM_CONTROL)
    {
        p_hcon->conn_flags = 0;
        p_hcon->ctrl_cid   = l2cap_cid;
        p_hcon->ctrl_id    = l2cap_id;
        p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;  /* In case disconnection occurs before security is completed, then set CLOSE_EVT reason code to 'connection failure' */

        p_hcon->conn_state = HID_CONN_STATE_SECURITY;
        if (!interop_addr_match(INTEROP_DISABLE_AUTH_FOR_HID_POINTING, (bt_bdaddr_t*)p_dev->addr))
        {
            if(btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL,
                FALSE, BTM_SEC_PROTO_HID,
                (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN,
                &hidh_sec_check_complete_term, p_dev) == BTM_CMD_STARTED)
            {
                L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK);
            }
        }
        else
        {
            /* device is blacklisted, don't perform authentication */
            L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK);
            hidh_sec_check_complete_term(p_dev->addr, BT_TRANSPORT_BR_EDR,
                p_dev, BTM_SUCCESS);
        }

        return;
    }

    /* Transition to the next appropriate state, configuration */
    p_hcon->conn_state = HID_CONN_STATE_CONFIG;
    p_hcon->intr_cid   = l2cap_cid;

    /* Send response to the L2CAP layer. */
    L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK);

    /* Send a Configuration Request. */
    L2CA_ConfigReq (l2cap_cid, &hh_cb.l2cap_cfg);

    HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP conn ind, sent config req, PSM: 0x%04x  CID 0x%x",
                       psm, l2cap_cid);
}
/*******************************************************************************
**
** Function         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);
}