예제 #1
0
파일: bta_hh_act.c 프로젝트: morrey/bt_bcm
/*******************************************************************************
**
** Function         bta_hh_start_sdp
**
** Description      Start SDP service search, and obtain necessary SDP records.
**                  Only one SDP service search request is allowed at the same
**                  time. For every BTA_HhOpen API call, do SDP first unless SDP
**                  has been done previously.
**
** Returns          void
**
*******************************************************************************/
void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
{
    tBTA_HH_STATUS          status = BTA_HH_ERR_SDP;
    UINT8                   hdl;

    p_cb->sec_mask  = p_data->api_conn.sec_mask;
    p_cb->mode      = p_data->api_conn.mode;
    bta_hh_cb.p_cur = p_cb;

#if (BTA_HH_LE_INCLUDED == TRUE)
    if (bta_hh_is_le_device(p_cb, p_data->api_conn.bd_addr))
    {
        bta_hh_le_open_conn(p_cb, p_data->api_conn.bd_addr);
        return;
    }
#endif

    /* if previously virtually cabled device, skip SDP */
    if (p_cb->app_id)
    {
        status = BTA_HH_OK;
#if BTA_HH_DEBUG
        APPL_TRACE_DEBUG("bta_hh_start_sdp:: skip SDP for known devices");
#endif
        if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
        {
            if (HID_HostAddDev (p_cb->addr, p_cb->attr_mask, &hdl) \
                == HID_SUCCESS)
            {
                /* update device CB with newly register device handle */
                bta_hh_add_device_to_list(p_cb,  hdl, p_cb->attr_mask, NULL,
                                          p_cb->sub_class,
                                          p_cb->dscp_info.ssr_max_latency,
                                          p_cb->dscp_info.ssr_min_tout,
                                          p_cb->app_id);
                /* update cb_index[] map */
                bta_hh_cb.cb_index[hdl] = p_cb->index;
            }
            else
                status = BTA_HH_ERR_NO_RES;
        }
        bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);

        return;
    }
    /* GetSDPRecord. at one time only one SDP precedure can be active */
    else if (!bta_hh_cb.p_disc_db)
    {
        bta_hh_cb.p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(p_bta_hh_cfg->sdp_db_size);

        if (bta_hh_cb.p_disc_db == NULL)
        {
            status = BTA_HH_ERR_NO_RES;
        }
        else
        {
            bta_hh_cb.p_cur = p_cb;
            /* do DI discovery first */
            if (SDP_DiDiscover(p_data->api_conn.bd_addr,
                                         bta_hh_cb.p_disc_db,
                                         p_bta_hh_cfg->sdp_db_size,
                                         bta_hh_di_sdp_cback) != SDP_SUCCESS)
            {
#if BTA_HH_DEBUG
                APPL_TRACE_DEBUG ("bta_hh_start_sdp:  SDP_DiDiscover failed: \
                    Status 0x%2X",status);
#endif
                status = BTA_HH_ERR_SDP;
                utl_freebuf((void **)&bta_hh_cb.p_disc_db);
            }
            else
예제 #2
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);
}
예제 #3
0
파일: bta_hh_act.c 프로젝트: morrey/bt_bcm
/*******************************************************************************
**
** Function         bta_hh_sdp_cback
**
** Description      SDP callback function.
**
** Returns          void
**
*******************************************************************************/
static void bta_hh_sdp_cback(UINT16 result, UINT16 attr_mask,
                                  tHID_DEV_SDP_INFO *sdp_rec )
{
    tBTA_HH_DEV_CB     *p_cb = bta_hh_cb.p_cur;
    UINT8              hdl = 0;
    tBTA_HH_STATUS    status = BTA_HH_ERR_SDP;

    /* make sure sdp succeeded and hh has not been disabled */
    if ((result == SDP_SUCCESS) && (p_cb != NULL))
    {
        /* security is required for the connection, add attr_mask bit*/
        if (p_cb->sec_mask)
            attr_mask |= HID_SEC_REQUIRED;

#if BTA_HH_DEBUG
        APPL_TRACE_EVENT("bta_hh_sdp_cback: p_cb: %d result 0x%02x, \
                            attr_mask 0x%02x, handle %x", \
                            p_cb, result, attr_mask,p_cb->hid_handle);
#endif

        /* check to see type of device is supported , and should not been added before */
        if (bta_hh_tod_spt(p_cb, sdp_rec->sub_class))
        {
            /* if not added before */
            if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
            {
                /*  add device/update attr_mask information */
                if(HID_HostAddDev (p_cb->addr, attr_mask, &hdl) == HID_SUCCESS)
                {
                    status = BTA_HH_OK;
                    /* update cb_index[] map */
                    bta_hh_cb.cb_index[hdl] = p_cb->index;
                }
                else
                {
                    p_cb->app_id = 0;
                }
            }
            else
            {
                hdl = p_cb->hid_handle;
            }
            /* else : incoming connection after SDP should update the SDP information as well */

            if (p_cb->app_id != 0)
            {
                /* update cb information with attr_mask, dscp_info etc. */
                bta_hh_add_device_to_list(p_cb,  hdl, attr_mask,
                                            &sdp_rec->dscp_info,
                                            sdp_rec->sub_class,
                                            sdp_rec->ssr_max_latency,
                                            sdp_rec->ssr_min_tout,
                                            p_cb->app_id);

                p_cb->dscp_info.ctry_code = sdp_rec->ctry_code;

                status = BTA_HH_OK;
            }

        }
        else /* type of device is not supported */
            status = BTA_HH_ERR_TOD_UNSPT;
    }

    /* free disc_db when SDP is completed */
    utl_freebuf((void **)&bta_hh_cb.p_disc_db);

    /* send SDP_CMPL_EVT into state machine */
    bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);

    return;
}
/*******************************************************************************
**
** 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);
}