Beispiel #1
0
/*******************************************************************************
**
** Function         gatt_update_app_use_link_flag
**
** Description      Update the application use link flag and optional to check the acl link
**                  if the link is up then set the idle time out accordingly
**
** Returns          void.
**
*******************************************************************************/
void gatt_update_app_use_link_flag (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link)
{
    GATT_TRACE_DEBUG2("gatt_update_app_use_link_flag  is_add=%d chk_link=%d",
                      is_add, check_acl_link);

    gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add);

    if (check_acl_link &&
        p_tcb &&
        (BTM_GetHCIConnHandle(p_tcb->peer_bda) != GATT_INVALID_ACL_HANDLE))
    {
        if (is_add)
        {
            GATT_TRACE_DEBUG0("GATT disables link idle timer");
            /* acl link is connected disable the idle timeout */
            GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT);
        }
        else
        {
            if (!gatt_num_apps_hold_link(p_tcb))
            {
                /* acl link is connected but no application needs to use the link
                   so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */
                GATT_TRACE_DEBUG1("GATT starts link idle timer =%d sec", GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
                GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
            }

        }
    }
}
Beispiel #2
0
/*******************************************************************************
**
** Function         srvc_eng_init
**
** Description      Initializa the GATT Service engine.
**
*******************************************************************************/
tGATT_STATUS srvc_eng_init (void)
{
    tBT_UUID          app_uuid = {LEN_UUID_16, {UUID_SERVCLASS_DEVICE_INFO}};

    if (srvc_eng_cb.enabled)
    {
        GATT_TRACE_ERROR0("DIS already initalized");
    }
    else
    {
        memset(&srvc_eng_cb, 0, sizeof(tDIS_CB));

        /* Create a GATT profile service */
        srvc_eng_cb.gatt_if = GATT_Register(&app_uuid, &srvc_gatt_cback);
        GATT_StartIf(srvc_eng_cb.gatt_if);

        GATT_TRACE_DEBUG1 ("Srvc_Init:  gatt_if=%d  ", srvc_eng_cb.gatt_if);

        srvc_eng_cb.enabled = TRUE;
//#if DIS_INCLUDED == TRUE
        dis_cb.dis_read_uuid_idx = 0xff;
//#endif
    }
    return GATT_SUCCESS;
}
/*******************************************************************************
**
** Function         gatt_chk_srv_chg
**
** Description      Check sending service chnaged Indication is required or not
**                  if required then send the Indication
**
** Returns          void
**
*******************************************************************************/
void gatt_chk_srv_chg(tGATTS_SRV_CHG *p_srv_chg_clt)
{
    GATT_TRACE_DEBUG1("gatt_chk_srv_chg srv_changed=%d", p_srv_chg_clt->srv_changed );

    if (p_srv_chg_clt->srv_changed)
    {
        gatt_send_srv_chg_ind(p_srv_chg_clt->bda);
    }
}
Beispiel #4
0
/*******************************************************************************
**
** Function         gatt_get_ch_state
**
** Description      This function get the ch_state in tcb
**
** Returns          none
**
*******************************************************************************/
tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB *p_tcb)
{
    tGATT_CH_STATE ch_state = GATT_CH_CLOSE;
    if (p_tcb)
    {
        GATT_TRACE_DEBUG1 ("gatt_get_ch_state: ch_state=%d", p_tcb->ch_state);
        ch_state = p_tcb->ch_state;
    }
    return ch_state;
}
Beispiel #5
0
/*******************************************************************************
**
** Function         gatt_le_data_ind
**
** Description      This function is called when data is received from L2CAP.
**                  if we are the originator of the connection, we are the ATT
**                  client, and the received message is queued up for the client.
**
**                  If we are the destination of the connection, we are the ATT
**                  server, so the message is passed to the server processing
**                  function.
**
** Returns          void
**
*******************************************************************************/
void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf)
{
    GATT_TRACE_DEBUG0("gatt_data_process");
    UINT8   *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
    UINT8   op_code, pseudo_op_code;
    UINT16  msg_len;


    if (p_buf->len > 0)
    {
        msg_len = p_buf->len - 1;
        STREAM_TO_UINT8(op_code, p);
        GATT_TRACE_DEBUG1("op_code = %d", op_code);

        /* remove the two MSBs associated with sign write and write cmd */
        pseudo_op_code = op_code & (~GATT_WRITE_CMD_MASK);

        if (pseudo_op_code < GATT_OP_CODE_MAX)
        {
            if (op_code == GATT_SIGN_CMD_WRITE)
            {
                GATT_TRACE_DEBUG0("op_code == GATT_SIGN_CMD_WRITE");
                gatt_verify_signature(p_tcb, p_buf);
                return;
            }
            else
            {
                /* message from client */
                if ((op_code % 2) == 0)
                {
                    GATT_TRACE_DEBUG0("gatt_server_handle_client_req");
                    gatt_server_handle_client_req (p_tcb, op_code, msg_len, p);
                }
                else
                {
                    GATT_TRACE_DEBUG0("gatt_client_handle_server_rsp");
                    gatt_client_handle_server_rsp (p_tcb, op_code, msg_len, p);
                }
            }
        }
        else
        {
            GATT_TRACE_ERROR1 ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x", op_code);
        }
    }
    else
    {
        GATT_TRACE_ERROR0 ("invalid data length, ignore");
    }

    GKI_freebuf (p_buf);
}
/*******************************************************************************
**
** Function         gatt_send_prepare_write
**
** Description      Send prepare write.
**
** Returns          void.
**
*******************************************************************************/
void gatt_send_prepare_write(tGATT_TCB  *p_tcb, tGATT_CLCB *p_clcb)
{
    tGATT_VALUE  *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
    UINT16  to_send, offset;
    UINT8   rt = GATT_SUCCESS;
    UINT8   type = p_clcb->op_subtype;

    GATT_TRACE_DEBUG1("gatt_send_prepare_write type=0x%x", type );
    to_send = p_attr->len - p_attr->offset;

    if (to_send > (p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE)) /* 2 = UINT16 offset bytes  */
        to_send = p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE;

    p_clcb->s_handle = p_attr->handle;

    offset = p_attr->offset;
    if (type == GATT_WRITE_PREPARE)
    {
        offset += p_clcb->start_offset;
    }

    GATT_TRACE_DEBUG2("offset =0x%x len=%d", offset, to_send );

    rt = gatt_send_write_msg(p_tcb,
                             p_clcb->clcb_idx,
                             GATT_REQ_PREPARE_WRITE,
                             p_attr->handle,
                             to_send,                           /* length */
                             offset,                            /* used as offset */
                             p_attr->value + p_attr->offset);   /* data */

    /* remember the write long attribute length */
    p_clcb->counter = to_send;

    if (rt != GATT_SUCCESS )
    {
        gatt_end_operation(p_clcb, rt, NULL);
    }
}
Beispiel #7
0
/*******************************************************************************
**
** Function         gatt_init_srv_chg
**
** Description      This function is used to initialize the service changed
**                  attribute value
**
** Returns          void
**
*******************************************************************************/
void gatt_init_srv_chg (void)
{
    tGATTS_SRV_CHG_REQ req;
    tGATTS_SRV_CHG_RSP rsp;
    BOOLEAN status;
    UINT8 num_clients,i;
    tGATTS_SRV_CHG  srv_chg_clt;

    GATT_TRACE_DEBUG0("gatt_init_srv_chg");
    if (gatt_cb.cb_info.p_srv_chg_callback)
    {
        status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_NUM_CLENTS, NULL, &rsp);

        if (status && rsp.num_clients)
        {
            GATT_TRACE_DEBUG1("gatt_init_srv_chg num_srv_chg_clt_clients=%d", rsp.num_clients);
            num_clients = rsp.num_clients;
            i = 1; /* use one based index */
            while ((i <= num_clients) && status)
            {
                req.client_read_index = i;
                if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)))
                {
                    memcpy(&srv_chg_clt, &rsp.srv_chg ,sizeof(tGATTS_SRV_CHG));
                    if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL)
                    {
                        GATT_TRACE_ERROR0("Unable to add a service change client");
                        status = FALSE;
                    }
                }
                i++;
            }
        }
    }
    else
    {
        GATT_TRACE_DEBUG0("gatt_init_srv_chg callback not registered yet");
    }
}
/*******************************************************************************
**
** Function         gatt_act_read
**
** Description      GATT read operation.
**
** Returns          void.
**
*******************************************************************************/
void gatt_act_read (tGATT_CLCB *p_clcb, UINT16 offset)
{
    tGATT_TCB  *p_tcb = p_clcb->p_tcb;
    UINT8   rt = GATT_INTERNAL_ERROR;
    tGATT_CL_MSG  msg;
    UINT8        op_code = 0;

    memset (&msg, 0, sizeof(tGATT_CL_MSG));

    switch (p_clcb->op_subtype)
    {
        case GATT_READ_CHAR_VALUE:
        case GATT_READ_BY_TYPE:
            op_code = GATT_REQ_READ_BY_TYPE;
            msg.browse.s_handle = p_clcb->s_handle;
            msg.browse.e_handle = p_clcb->e_handle;
            if (p_clcb->op_subtype == GATT_READ_BY_TYPE)
                memcpy(&msg.browse.uuid, &p_clcb->uuid, sizeof(tBT_UUID));
            else
            {
                msg.browse.uuid.len = LEN_UUID_16;
                msg.browse.uuid.uu.uuid16 = GATT_UUID_CHAR_DECLARE;
            }
            break;

        case GATT_READ_CHAR_VALUE_HDL:
        case GATT_READ_BY_HANDLE:
            if (!p_clcb->counter)
            {
                op_code = GATT_REQ_READ;
                msg.handle = p_clcb->s_handle;
            }
            else
            {
                if (!p_clcb->first_read_blob_after_read)
                    p_clcb->first_read_blob_after_read = TRUE;
                else
                    p_clcb->first_read_blob_after_read = FALSE;

                GATT_TRACE_DEBUG1("gatt_act_read first_read_blob_after_read=%d",
                                  p_clcb->first_read_blob_after_read);
                op_code = GATT_REQ_READ_BLOB;
                msg.read_blob.offset = offset;
                msg.read_blob.handle = p_clcb->s_handle;
            }
            p_clcb->op_subtype &= ~ 0x80;
            break;

        case GATT_READ_PARTIAL:
            op_code = GATT_REQ_READ_BLOB;
            msg.read_blob.handle = p_clcb->s_handle;
            msg.read_blob.offset = offset;
            break;

        case GATT_READ_MULTIPLE:
            op_code = GATT_REQ_READ_MULTI;
            memcpy (&msg.read_multi, p_clcb->p_attr_buf, sizeof(tGATT_READ_MULTI));
            break;

        case GATT_READ_INC_SRV_UUID128:
            op_code = GATT_REQ_READ;
            msg.handle = p_clcb->s_handle;
            p_clcb->op_subtype &= ~ 0x90;
            break;

        default:
            GATT_TRACE_ERROR1("Unknown read type: %d", p_clcb->op_subtype);
            break;
    }

    if ( op_code == 0 ||
         (rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, op_code, &msg)) != GATT_SUCCESS)
    {
        gatt_end_operation(p_clcb, rt, NULL);
    }
}
Beispiel #9
0
/*******************************************************************************
**
** Function         gatt_le_connect_cback
**
** Description      This callback function is called by L2CAP to indicate that
**                  the ATT fixed channel for LE is
**                      connected (conn = TRUE)/disconnected (conn = FALSE).
**
*******************************************************************************/
static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason)
{

    tGATT_TCB       *p_tcb = gatt_find_tcb_by_addr(bd_addr);

    BOOLEAN                 check_srv_chg = FALSE;
    tGATTS_SRV_CHG          *p_srv_chg_clt=NULL;
    BOOLEAN                 is_bg_conn = FALSE;


    GATT_TRACE_DEBUG3 ("GATT   ATT protocol channel with BDA: %08x%04x is %s",
                       (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
                       (bd_addr[4]<<8)+bd_addr[5], (connected) ? "connected" : "disconnected");


    if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr)) != NULL)
    {
        check_srv_chg = TRUE;
    }
    else
    {
        if (btm_sec_is_a_bonded_dev(bd_addr))
            gatt_add_a_bonded_dev_for_srv_chg(bd_addr);
    }

    if (connected)
    {
        GATT_TRACE_DEBUG1("connected is TRUE reason=%d",reason );
        /* BR/EDR lik, ignore this callback */
        if (reason == 0)
            return;

        /* do we have a channel initiating a connection? */
        if (p_tcb)
        {
            if (check_srv_chg)
                gatt_chk_srv_chg (p_srv_chg_clt);
            /* we are initiating connection */
            if ( gatt_get_ch_state(p_tcb) == GATT_CH_CONN)
            {
                /* send callback */
                gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
                p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;

                gatt_send_conn_cback(FALSE, p_tcb);
            }
            else /* there was an exisiting link, ignore the callback */
            {
                GATT_TRACE_ERROR0("connection already up, ignore it");
                return;
            }
        }
        /* this is incoming connection or background connection callback */
        else
        {
            if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) != NULL)
            {
                p_tcb->att_lcid = L2CAP_ATT_CID;

                gatt_set_ch_state(p_tcb, GATT_CH_OPEN);

                p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
                if (L2CA_GetBleConnRole(p_tcb->peer_bda)== HCI_ROLE_MASTER)
                {
                    is_bg_conn = TRUE;
                }
                gatt_send_conn_cback (is_bg_conn, p_tcb);
                if (check_srv_chg)
                {
                    gatt_chk_srv_chg (p_srv_chg_clt);
                }
            }
            else
            {
                GATT_TRACE_ERROR0("CCB max out, no rsources");
            }
        }
    }
    else
    {
        gatt_cleanup_upon_disc(bd_addr, reason);
        GATT_TRACE_DEBUG0 ("ATT disconnected");
    }
}