示例#1
0
/*******************************************************************************
**
** Function         bta_hh_api_disable
**
** Description      Perform necessary operations to disable HID host.
**
**
** Returns          void
**
*******************************************************************************/
void bta_hh_api_disable(void)
{
    UINT8 xx;

    /* service is not enabled */
    if (bta_hh_cb.p_cback == NULL)
        return;

    /* no live connection, signal DISC_CMPL_EVT directly */
    if (!bta_hh_cb.cnt_num)
    {
        bta_hh_disc_cmpl();
    }
    else /* otherwise, disconnect all live connections */
    {
        bta_hh_cb.w4_disable = TRUE;

        for(xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
        {
            /* send API_CLOSE event to every connected device */
            if ( bta_hh_cb.kdev[xx].state == BTA_HH_CONN_ST )
            {
                /* disconnect all connected devices */
                bta_hh_sm_execute(&bta_hh_cb.kdev[xx],
                                BTA_HH_API_CLOSE_EVT,
                                NULL);
            }
        }
    }

    return;
}
示例#2
0
/*******************************************************************************
**
** Function         bta_hh_hdl_event
**
** Description      HID host main event handling function.
**
**
** Returns          void
**
*******************************************************************************/
BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
{
    UINT8           index = BTA_HH_IDX_INVALID;
    tBTA_HH_DEV_CB *p_cb = NULL;

    switch (p_msg->event) {
    case BTA_HH_API_ENABLE_EVT:
        bta_hh_api_enable((tBTA_HH_DATA *) p_msg);
        break;

    case BTA_HH_API_DISABLE_EVT:
        bta_hh_api_disable();
        break;

    case BTA_HH_DISC_CMPL_EVT:          /* disable complete */
        bta_hh_disc_cmpl();
        break;

    default:
        /* all events processed in state machine need to find corresponding
            CB before proceed */
        if (p_msg->event == BTA_HH_API_OPEN_EVT) {
            index = bta_hh_find_cb(((tBTA_HH_API_CONN *)p_msg)->bd_addr);
        } else if (p_msg->event == BTA_HH_API_MAINT_DEV_EVT) {
            /* if add device */
            if (((tBTA_HH_MAINT_DEV *)p_msg)->sub_event == BTA_HH_ADD_DEV_EVT) {
                index = bta_hh_find_cb(((tBTA_HH_MAINT_DEV *)p_msg)->bda);
            } else { /* else remove device by handle */
                index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
// btla-specific ++
                /* If BT disable is done while the HID device is connected and Link_Key uses unauthenticated combination
                  * then we can get into a situation where remove_bonding is called with the index set to 0 (without getting
                  * cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the index and make it MAX_KNOWN.
                  * So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we
                  * force the index to be IDX_INVALID
                  */
                if ((index != BTA_HH_IDX_INVALID) &&
                        (bta_hh_cb.kdev[index].in_use == FALSE)) {
                    index = BTA_HH_IDX_INVALID;
                }
// btla-specific --
            }
        } else if (p_msg->event == BTA_HH_INT_OPEN_EVT) {
            index = bta_hh_find_cb(((tBTA_HH_CBACK_DATA *)p_msg)->addr);
        } else {
            index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
        }

        if (index != BTA_HH_IDX_INVALID) {
            p_cb = &bta_hh_cb.kdev[index];
        }

#if BTA_HH_DEBUG
        APPL_TRACE_DEBUG("bta_hh_hdl_event:: handle = %d dev_cb[%d] ", p_msg->layer_specific, index);
#endif
        bta_hh_sm_execute(p_cb, p_msg->event, (tBTA_HH_DATA *) p_msg);
    }
    return (TRUE);
}
示例#3
0
/*******************************************************************************
**
** Function         bta_hh_di_sdp_cback
**
** Description      SDP DI callback function.
**
** Returns          void
**
*******************************************************************************/
static void bta_hh_di_sdp_cback(UINT16 result)
{
    tBTA_HH_DEV_CB     *p_cb = bta_hh_cb.p_cur;
    tBTA_HH_STATUS         status = BTA_HH_ERR_SDP;
    tSDP_DI_GET_RECORD  di_rec;
    tHID_STATUS ret;
#if BTA_HH_DEBUG
    APPL_TRACE_EVENT("bta_hh_di_sdp_cback: p_cb: %d result 0x%02x", p_cb, result);
#endif

    /* if DI record does not exist on remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be
         * set to 0xffff and we will allow the connection to go through. Spec mandates that DI
         * record be set, but many HID devices do not set this. So for IOP purposes, we allow the
         * connection to go through and update the DI record to invalid DI entry.*/
    if (((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH)) && (p_cb != NULL))
    {
        if(result == SDP_SUCCESS && SDP_GetNumDiRecords(bta_hh_cb.p_disc_db) != 0)
        {
            /* always update information with primary DI record */
            if (SDP_GetDiRecord(1, &di_rec, bta_hh_cb.p_disc_db) == SDP_SUCCESS)
            {
                bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version, 0);
            }

        }
        else /* no DI recrod available */
        {
            bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0);
        }

        if ((ret = HID_HostGetSDPRecord(p_cb->addr,
                                 bta_hh_cb.p_disc_db,
                                 p_bta_hh_cfg->sdp_db_size,
                                 bta_hh_sdp_cback)) == HID_SUCCESS)
        {
            status = BTA_HH_OK;
        }
        else
        {
#if BTA_HH_DEBUG
            APPL_TRACE_DEBUG ("bta_hh_di_sdp_cback:  HID_HostGetSDPRecord failed: Status 0x%2x",
                               ret);
#endif
        }
    }


    if (status != BTA_HH_OK)
    {
        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;

}
示例#4
0
/*******************************************************************************
**
** 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
示例#5
0
/*******************************************************************************
**
** 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;
}