/*******************************************************************************
**
** Function         GAP_BleCancelReadPeerDevName
**
** Description      Cancel reading a peripheral's device name.
**
** Returns          TRUE if request accepted
**
*******************************************************************************/
BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda)
{
    tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);

    GAP_TRACE_EVENT ("GAP_BleCancelReadPeerDevName() - BDA: %08x%04x  cl_op_uuid: 0x%04x",
                      (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
                      (peer_bda[4]<<8)+peer_bda[5], (p_clcb == NULL)? 0 : p_clcb->cl_op_uuid);

    if (p_clcb == NULL || p_clcb->cl_op_uuid != GATT_UUID_GAP_DEVICE_NAME)
    {
        GAP_TRACE_ERROR ("Cannot cancel current op is not get dev name");
        return FALSE;
    }

    if (!p_clcb->connected)
    {
        if (!GATT_CancelConnect(gap_cb.gatt_if, peer_bda, TRUE))
        {
            GAP_TRACE_ERROR ("Cannot cancel where No connection id");
            return FALSE;
        }
    }

    gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);

    return(TRUE);
}
/*******************************************************************************
**
** Function         gap_ble_cl_read_request
**
** Description      utility function to start a read request for a GAP charactersitic
**
** Returns          TRUE if read started, else FALSE if GAP is busy
**
*******************************************************************************/
BOOLEAN gap_ble_cl_read_request(tGAP_CLCB *p_clcb, UINT16 uuid, void * p_cback)
{
    tGATT_READ_PARAM   param;

    memset(&param, 0, sizeof(tGATT_READ_PARAM));

    param.service.uuid.len       = LEN_UUID_16;
    param.service.uuid.uu.uuid16 = uuid;
    param.service.s_handle       = 1;
    param.service.e_handle       = 0xFFFF;
    param.service.auth_req       = 0;

    if (GATTC_Read(p_clcb->conn_id, GATT_READ_BY_TYPE, &param) != GATT_SUCCESS)
    {
        GAP_TRACE_ERROR ("GAP_BleReadPeerPrefConnParams: GATT_Read Failed");
        /* release the link here */
        GATT_Disconnect(p_clcb->conn_id);
        return(FALSE);
    }
    else
    {
        p_clcb->p_cback = p_cback;
        p_clcb->cl_op_uuid = uuid;
        return TRUE;
    }

}
/*******************************************************************************
**
** Function         GAP_BleReadPeerDevName
**
** Description      Start a process to read a connected peripheral's device name.
**
** Returns          TRUE if request accepted
**
*******************************************************************************/
BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback)
{
    tGAP_CLCB   *p_clcb = NULL;
    BOOLEAN  status = TRUE;

    if (p_cback == NULL)
        return(FALSE);

    if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL)
    {
        if ((p_clcb = gap_clcb_alloc(0, peer_bda)) == NULL)
        {
            GAP_TRACE_ERROR("GAP_BleReadPeerDevName max connection reached");
            return FALSE;
        }
        p_clcb->connected = FALSE;
    }

    GAP_TRACE_EVENT ("GAP_BleReadPeerDevName() - BDA: %08x%04x  cl_op_uuid: 0x%04x",
                      (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
                      (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);

    /* For now we only handle one at a time */
    if (p_clcb->cl_op_uuid != 0)
        return(FALSE);

    /* hold the link here */
    if( BTM_IsInquiryActive()|| BTM_IsRnrActive() )
    {
       status = GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE);
    }
    if(status)
    {
        if (p_clcb->connected)
        {
            return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_DEVICE_NAME, (void *)p_cback);
        }

        p_clcb->p_cback = (void *)p_cback;
        /* Mark currently active operation */
        p_clcb->cl_op_uuid = GATT_UUID_GAP_DEVICE_NAME;

    }
    return FALSE;
}
Exemplo n.º 4
0
/*******************************************************************************
**
** Function     gap_send_event
**
** Description  Send BT_EVT_TO_GAP_MSG event to BTU task
**
** Returns      None
**
*******************************************************************************/
void gap_send_event (UINT16 gap_handle)
{
    BT_HDR  *p_msg;

    if ((p_msg = (BT_HDR*)GKI_getbuf(BT_HDR_SIZE)) != NULL)
    {
        p_msg->event  = BT_EVT_TO_GAP_MSG;
        p_msg->len    = 0;
        p_msg->offset = 0;
        p_msg->layer_specific = gap_handle;

        GKI_send_msg(BTU_TASK, BTU_HCI_RCV_MBOX, p_msg);
    }
    else
    {
        GAP_TRACE_ERROR("Unable to allocate message buffer for event.");
    }
}
/*******************************************************************************
**
** Function         GAP_BleReadPeerPrefConnParams
**
** Description      Start a process to read a connected peripheral's preferred
**                  connection parameters
**
** Returns          TRUE if read started, else FALSE if GAP is busy
**
*******************************************************************************/
BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda)
{

    tGAP_CLCB   *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);

    if (p_clcb == NULL)
    {
        if ((p_clcb = gap_clcb_alloc(0, peer_bda)) == NULL)
        {
            GAP_TRACE_ERROR("GAP_BleReadPeerPrefConnParams max connection reached");
            return FALSE;
        }
        p_clcb->connected = FALSE;
    }

    GAP_TRACE_API ("GAP_BleReadPeerPrefConnParams() - BDA: %08x%04x  cl_op_uuid: 0x%04x",
                    (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
                    (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);

    /* For now we only handle one at a time */
    if (p_clcb->cl_op_uuid != 0)
        return(FALSE);

    /* hold the link here */
    if (GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
    {

        if (p_clcb->connected)
        {
            return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
        }
        /* Mark currently active operation */
        p_clcb->cl_op_uuid = GATT_UUID_GAP_PREF_CONN_PARAM;

        return(TRUE);
    }
    else
        return FALSE;
}
Exemplo n.º 6
0
/*******************************************************************************
**
** Function         GAP_ConnOpen
**
** Description      This function is called to open an L2CAP connection.
**
** Parameters:      is_server   - If TRUE, the connection is not created
**                                but put into a "listen" mode waiting for
**                                the remote side to connect.
**
**                  service_id  - Unique service ID from
**                                BTM_SEC_SERVICE_FIRST_EMPTY (6)
**                                to BTM_SEC_MAX_SERVICE_RECORDS (32)
**
**                  p_rem_bda   - Pointer to remote BD Address.
**                                If a server, and we don't care about the
**                                remote BD Address, then NULL should be passed.
**
**                  psm         - the PSM used for the connection
**
**                  p_config    - Optional pointer to configuration structure.
**                                If NULL, the default GAP configuration will
**                                be used.
**
**                  security    - security flags
**                  chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC, GAP_FCR_CHAN_OPT_ERTM,
**                                    GAP_FCR_CHAN_OPT_STREAM)
**
**                  p_cb        - Pointer to callback function for events.
**
** Returns          handle of the connection if successful, else GAP_INVALID_HANDLE
**
*******************************************************************************/
UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server,
                     BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg,
                     tL2CAP_ERTM_INFO *ertm_info, UINT16 security, UINT8 chan_mode_mask,
                     tGAP_CONN_CALLBACK *p_cb)
{
    tGAP_CCB    *p_ccb;
    UINT16       cid;

    GAP_TRACE_EVENT ("GAP_CONN - Open Request");

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

    /* If caller specified a BD address, save it */
    if (p_rem_bda)
    {
        /* the bd addr is not BT_BD_ANY, then a bd address was specified */
        if (memcmp (p_rem_bda, BT_BD_ANY, BD_ADDR_LEN))
            p_ccb->rem_addr_specified = TRUE;

        memcpy (&p_ccb->rem_dev_address[0], p_rem_bda, BD_ADDR_LEN);
    }
    else if (!is_server)
    {
        /* remore addr is not specified and is not a server -> bad */
        return (GAP_INVALID_HANDLE);
    }

    /* A client MUST have specified a bd addr to connect with */
    if (!p_ccb->rem_addr_specified && !is_server)
    {
        gap_release_ccb (p_ccb);
        GAP_TRACE_ERROR ("GAP ERROR: Client must specify a remote BD ADDR to connect to!");
        return (GAP_INVALID_HANDLE);
    }

    /* Check if configuration was specified */
    if (p_cfg)
        p_ccb->cfg = *p_cfg;

    p_ccb->p_callback     = p_cb;

    /* If originator, use a dynamic PSM */
#if AMP_INCLUDED == TRUE
    if (!is_server)
        gap_cb.conn.reg_info.pAMP_ConnectInd_Cb  = NULL;
    else
        gap_cb.conn.reg_info.pAMP_ConnectInd_Cb  = gap_connect_ind;
#else
    if (!is_server)
        gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = NULL;
    else
        gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
#endif

    /* Register the PSM with L2CAP */
    if ((p_ccb->psm = L2CA_REGISTER (psm, &gap_cb.conn.reg_info,
                    AMP_AUTOSWITCH_ALLOWED|AMP_USE_AMP_IF_POSSIBLE)) == 0)
    {
        GAP_TRACE_ERROR ("GAP_ConnOpen: Failure registering PSM 0x%04x", psm);
        gap_release_ccb (p_ccb);
        return (GAP_INVALID_HANDLE);
    }

    /* Register with Security Manager for the specific security level */
    p_ccb->service_id = service_id;
    if (!BTM_SetSecurityLevel ((UINT8)!is_server, p_serv_name,
                p_ccb->service_id, security, p_ccb->psm, 0, 0))
    {
        GAP_TRACE_ERROR ("GAP_CONN - Security Error");
        gap_release_ccb (p_ccb);
        return (GAP_INVALID_HANDLE);
    }

    /* Fill in eL2CAP parameter data */
    if( p_ccb->cfg.fcr_present )
    {
        if(ertm_info == NULL) {
            p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
            p_ccb->ertm_info.user_rx_pool_id = GAP_DATA_POOL_ID;
            p_ccb->ertm_info.user_tx_pool_id = GAP_DATA_POOL_ID;
            p_ccb->ertm_info.fcr_rx_pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
            p_ccb->ertm_info.fcr_tx_pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
        } else {
            p_ccb->ertm_info = *ertm_info;
        }
    }

    /* optional FCR channel modes */
    if(ertm_info != NULL) {
        p_ccb->ertm_info.allowed_modes =
            (chan_mode_mask) ? chan_mode_mask : (UINT8)L2CAP_FCR_CHAN_OPT_BASIC;
    }

    if (is_server)
    {
        p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */
        p_ccb->con_state = GAP_CCB_STATE_LISTENING;
        return (p_ccb->gap_handle);
    }
    else
    {
        /* We are the originator of this connection */
        p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG;

        /* Transition to the next appropriate state, waiting for connection confirm. */
        p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP;

        /* mark security done flag, when security is not required */
        if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT) ) == 0)
            p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;

        /* Check if L2CAP started the connection process */
        if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info)) != 0))
        {
            p_ccb->connection_id = cid;
            return (p_ccb->gap_handle);
        }
        else
        {
            gap_release_ccb (p_ccb);
            return (GAP_INVALID_HANDLE);
        }
    }
}
/*******************************************************************************
**
** Function         gap_ble_c_connect_cback
**
** Description      Client connection callback.
**
** Returns          void
**
*******************************************************************************/
static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
                                     BOOLEAN connected, tGATT_DISCONN_REASON reason,
                                     tGATT_TRANSPORT transport)
{
    tGAP_CLCB   *p_clcb = gap_find_clcb_by_bd_addr (bda);
    UINT16      cl_op_uuid;

    UNUSED(gatt_if);
    UNUSED(transport);

    GAP_TRACE_EVENT ("gap_ble_c_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
                      (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
                      (bda[4]<<8)+bda[5], connected, conn_id, reason);


    if (connected)
    {
        if (p_clcb == NULL)
        {
            if ((p_clcb = gap_clcb_alloc(conn_id, bda))== NULL)
            {
                GAP_TRACE_ERROR ("gap_ble_c_connect_cback: no_resource");
                return;
            }
        }
        p_clcb->conn_id = conn_id;
        p_clcb->connected = TRUE;

    }
    else
    {
        if (p_clcb != NULL)
            p_clcb->connected = FALSE;
    }

    if (p_clcb)
    {
        cl_op_uuid = p_clcb->cl_op_uuid;

        GAP_TRACE_EVENT ("cl_op_uuid=0x%04x", cl_op_uuid  );

        if (p_clcb->connected)
        {
            p_clcb->cl_op_uuid = 0;
            if (cl_op_uuid == GATT_UUID_GAP_DEVICE_NAME)
            {
                GAP_BleReadPeerDevName (bda, (tGAP_BLE_DEV_NAME_CBACK *)p_clcb->p_cback);
            }
            else if (cl_op_uuid == GATT_UUID_GAP_PREF_CONN_PARAM)
            {
                 GAP_BleReadPeerPrefConnParams(bda);
            }
        }
        /* current link disconnect */
        else
        {
            gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
            memset(p_clcb, 0, sizeof(tGAP_CLCB));
        }
    }

}