示例#1
0
/*******************************************************************************
**
** Function         rfc_port_sm_state_closed
**
** Description      This function handles events when the port is in
**                  CLOSED state. This state exists when port is
**                  being initially established.
**
** Returns          void
**
*******************************************************************************/
void rfc_port_sm_state_closed (tPORT *p_port, UINT16 event, void *p_data)
{
    switch (event)
    {
    case RFC_EVENT_OPEN:
        p_port->rfc.state = RFC_STATE_ORIG_WAIT_SEC_CHECK;
        btm_sec_mx_access_request (p_port->rfc.p_mcb->bd_addr, BT_PSM_RFCOMM, TRUE,
                                   BTM_SEC_PROTO_RFCOMM, (UINT32)(p_port->dlci / 2),
                                   &rfc_sec_check_complete, p_port);
        return;

    case RFC_EVENT_CLOSE:
        break;

    case RFC_EVENT_CLEAR:
        return;

    case RFC_EVENT_DATA:
        GKI_freebuf (p_data);
        break;

    case RFC_EVENT_SABME:
        /* make sure the multiplexer disconnect timer is not running (reconnect case) */
        rfc_timer_stop(p_port->rfc.p_mcb );

        /* Open will be continued after security checks are passed */
        p_port->rfc.state = RFC_STATE_TERM_WAIT_SEC_CHECK;
        btm_sec_mx_access_request (p_port->rfc.p_mcb->bd_addr, BT_PSM_RFCOMM, FALSE,
                                   BTM_SEC_PROTO_RFCOMM, (UINT32)(p_port->dlci / 2),
                                   &rfc_sec_check_complete, p_port);
        return;

    case RFC_EVENT_UA:
        return;

    case RFC_EVENT_DM:
        rfc_port_closed (p_port);
        return;

    case RFC_EVENT_UIH:
        GKI_freebuf (p_data);
        rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, FALSE);
        return;

    case RFC_EVENT_DISC:
        rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, FALSE);
        return;

    case RFC_EVENT_TIMEOUT:
        Port_TimeOutCloseMux( p_port->rfc.p_mcb ) ;
        RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event);
        return;
    }

    RFCOMM_TRACE_WARNING ("Port state closed Event ignored %d", event);
    return;
}
示例#2
0
/*******************************************************************************
**
** Function         gap_connect_cfm
**
** Description      This function handles the connect confirm events
**                  from L2CAP. This is the case when we are acting as a
**                  client and have sent a connect request.
**
** Returns          void
**
*******************************************************************************/
static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result)
{
    tGAP_CCB    *p_ccb;

    /* Find CCB based on CID */
    if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
        return;

    /* initiate security process, if needed */
    if ( (p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0)
    {
        btm_sec_mx_access_request (p_ccb->rem_dev_address, p_ccb->psm, TRUE,
                                   0, 0, &gap_sec_check_complete, p_ccb);
    }

    /* If the connection response contains success status, then */
    /* Transition to the next state and startup the timer.      */
    if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP))
    {
        p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;

        /* Send a Configuration Request. */
        L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
    }
    else
    {
        /* Tell the user if he has a callback */
        if (p_ccb->p_callback)
            (*p_ccb->p_callback) (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);

        gap_release_ccb (p_ccb);
    }
}
/*******************************************************************************
**
** Function         mca_l2c_connect_cfm_cback
**
** Description      This is the L2CAP connect confirm callback function.
**
**
** Returns          void
**
*******************************************************************************/
void mca_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
{
    tMCA_TC_TBL    *p_tbl;
    tL2CAP_CFG_INFO cfg;
    tMCA_CCB *p_ccb;

    MCA_TRACE_DEBUG2("mca_l2c_connect_cfm_cback lcid: x%x, result: %d",
                     lcid, result);
    /* look up info for this channel */
    if ((p_tbl = mca_tc_tbl_by_lcid(lcid)) != NULL)
    {
        MCA_TRACE_DEBUG2("p_tbl state: %d, tcid: %d", p_tbl->state, p_tbl->tcid);
        /* if in correct state */
        if (p_tbl->state == MCA_TC_ST_CONN)
        {
            /* if result successful */
            if (result == L2CAP_CONN_OK)
            {
                if (p_tbl->tcid != 0)
                {
                    /* set channel state */
                    p_tbl->state = MCA_TC_ST_CFG;

                    /* Send L2CAP config req */
                    mca_set_cfg_by_tbl (&cfg, p_tbl);
                    L2CA_ConfigReq(lcid, &cfg);
                }
                else
                {
                    p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx);
                    if (p_ccb == NULL)
                    {
                        result = L2CAP_CONN_NO_RESOURCES;
                    }
                    else
                    {
                        /* set channel state */
                        p_tbl->state    = MCA_TC_ST_SEC_INT;
                        p_tbl->lcid     = lcid;
                        p_tbl->cfg_flags= MCA_L2C_CFG_CONN_INT;

                        /* Check the security */
                        btm_sec_mx_access_request (p_ccb->peer_addr, p_ccb->ctrl_vpsm,
                                                   TRUE, BTM_SEC_PROTO_MCA,
                                                   p_tbl->tcid,
                                                   &mca_sec_check_complete_orig, p_tbl);
                    }
                }
            }

            /* failure; notify adaption that channel closed */
            if (result != L2CAP_CONN_OK)
            {
                p_tbl->cfg_flags |= MCA_L2C_CFG_DISCN_INT;
                mca_tc_close_ind(p_tbl, result);
            }
        }
    }
}
示例#4
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         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);
        }
    }
}
示例#6
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);
    }
}
示例#7
0
文件: hidh_conn.c 项目: morrey/bt_bcm
/*******************************************************************************
**
** 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;
}
示例#8
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);
}
示例#9
0
/*******************************************************************************
**
** Function         BNEP_Connect
**
** Description      This function creates a BNEP connection to a remote
**                  device.
**
** Parameters:      p_rem_addr  - BD_ADDR of the peer
**                  src_uuid    - source uuid for the connection
**                  dst_uuid    - destination uuid for the connection
**                  p_handle    - pointer to return the handle for the connection
**
** Returns          BNEP_SUCCESS                if connection started
**                  BNEP_NO_RESOURCES           if no resources
**
*******************************************************************************/
tBNEP_RESULT BNEP_Connect (BD_ADDR p_rem_bda,
                           tBT_UUID *src_uuid,
                           tBT_UUID *dst_uuid,
                           UINT16 *p_handle)
{
    UINT16          cid;
    tBNEP_CONN      *p_bcb = bnepu_find_bcb_by_bd_addr (p_rem_bda);

    BNEP_TRACE_API ("BNEP_Connect()  BDA: %02x-%02x-%02x-%02x-%02x-%02x",
                     p_rem_bda[0], p_rem_bda[1], p_rem_bda[2],
                     p_rem_bda[3], p_rem_bda[4], p_rem_bda[5]);

    if (!bnep_cb.profile_registered)
        return BNEP_WRONG_STATE;

    /* Both source and destination UUID lengths should be same */
    if (src_uuid->len != dst_uuid->len)
        return BNEP_CONN_FAILED_UUID_SIZE;

#if (!defined (BNEP_SUPPORTS_ALL_UUID_LENGTHS) || BNEP_SUPPORTS_ALL_UUID_LENGTHS == FALSE)
    if (src_uuid->len != 2)
        return BNEP_CONN_FAILED_UUID_SIZE;
#endif

    if (!p_bcb)
    {
        if ((p_bcb = bnepu_allocate_bcb (p_rem_bda)) == NULL)
            return (BNEP_NO_RESOURCES);
    }
    else if (p_bcb->con_state != BNEP_STATE_CONNECTED)
            return BNEP_WRONG_STATE;
    else
    {
        /* Backup current UUID values to restore if role change fails */
        memcpy ((UINT8 *)&(p_bcb->prv_src_uuid), (UINT8 *)&(p_bcb->src_uuid), sizeof (tBT_UUID));
        memcpy ((UINT8 *)&(p_bcb->prv_dst_uuid), (UINT8 *)&(p_bcb->dst_uuid), sizeof (tBT_UUID));
    }

    /* We are the originator of this connection */
    p_bcb->con_flags |= BNEP_FLAGS_IS_ORIG;

    memcpy ((UINT8 *)&(p_bcb->src_uuid), (UINT8 *)src_uuid, sizeof (tBT_UUID));
    memcpy ((UINT8 *)&(p_bcb->dst_uuid), (UINT8 *)dst_uuid, sizeof (tBT_UUID));

    if (p_bcb->con_state == BNEP_STATE_CONNECTED)
    {
        /* Transition to the next appropriate state, waiting for connection confirm. */
        p_bcb->con_state = BNEP_STATE_SEC_CHECKING;

        BNEP_TRACE_API ("BNEP initiating security procedures for src uuid 0x%x",
            p_bcb->src_uuid.uu.uuid16);

#if (defined (BNEP_DO_AUTH_FOR_ROLE_SWITCH) && BNEP_DO_AUTH_FOR_ROLE_SWITCH == TRUE)
        btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, TRUE,
                                   BTM_SEC_PROTO_BNEP,
                                   bnep_get_uuid32(src_uuid),
                                   &bnep_sec_check_complete, p_bcb);
#else
        bnep_sec_check_complete (p_bcb->rem_bda, p_bcb, BTM_SUCCESS);
#endif

    }
    else
    {
        /* Transition to the next appropriate state, waiting for connection confirm. */
        p_bcb->con_state = BNEP_STATE_CONN_START;

        if ((cid = L2CA_ConnectReq (BT_PSM_BNEP, p_bcb->rem_bda)) != 0)
        {
            p_bcb->l2cap_cid = cid;

        }
        else
        {
            BNEP_TRACE_ERROR ("BNEP - Originate failed");
            if (bnep_cb.p_conn_state_cb)
                (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
            bnepu_release_bcb (p_bcb);
            return BNEP_CONN_FAILED;
        }

        /* Start timer waiting for connect */
        btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT);
    }

    *p_handle = p_bcb->handle;
    return (BNEP_SUCCESS);
}
/*******************************************************************************
**
** Function         hidh_l2cif_connect_ind
**
** Description      This function handles an inbound connection indication
**                  from L2CAP. This is the case where we are acting as a
**                  server.
**
** Returns          void
**
*******************************************************************************/
static void hidh_l2cif_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id)
{
    tHID_CONN    *p_hcon;
    BOOLEAN      bAccept = TRUE;
    UINT8        i = HID_HOST_MAX_DEVICES;
    tHID_HOST_DEV_CTB *p_dev;

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

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

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

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

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

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

        p_hcon->conn_state = HID_CONN_STATE_SECURITY;
        if(btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL,
            FALSE, BTM_SEC_PROTO_HID,
            (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN,
            &hidh_sec_check_complete_term, p_dev) == BTM_CMD_STARTED)
        {
            L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK);
        }

        return;
    }

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

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

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

    HIDH_TRACE_EVENT2 ("HID-Host Rcvd L2CAP conn ind, sent config req, PSM: 0x%04x  CID 0x%x",
                       psm, l2cap_cid);
}