Bluetooth GATT Service Exported Functions

group BT_GATT_SERVICE_Exported_Functions

Functions

bool gatt_svc_add(T_SERVER_ID *p_out_service_id, uint8_t *p_database, uint16_t length, const T_FUN_GATT_EXT_SERVICE_CBS *p_srv_ext_cbs, P_FUN_GATT_EXT_SEND_DATA_CB p_srv_ext_send_data_cb)

Register specific service.

Example usage

//case 1
bool bass_add_service(uint8_t brs_num)
{
    T_SERVER_ID service_id;
    uint16_t attr_tbl_size = sizeof(bass_attr_tbl);

    attr_tbl_size -= (BASS_BRS_CHAR_MAX_NUM - brs_num) * 3 * sizeof(T_ATTRIB_APPL);

    if (false == gatt_svc_add(&service_id,
                                 (uint8_t *)bass_attr_tbl,
                                 attr_tbl_size,
                                 &bass_cbs, bass_send_data_cb))
    {
        PROTOCOL_PRINT_ERROR0("bass_add_service: failed");
        return false;
    }
    p_bass->service_id = service_id;

    return true;
}
void bass_send_data_cb(T_EXT_SEND_DATA_RESULT result)
{
    PROTOCOL_PRINT_INFO6("bass_send_data_cb: credits %d, conn_handle 0x%x, cid 0x%x, service_id %d, attr_idx %d, cause 0x%x",
                         result.credits, result.conn_handle, result.cid,
                         result.service_id, result.attrib_idx, result.cause);
}

//case 2
bool bass_add_service(uint8_t brs_num)
{
    T_SERVER_ID service_id;
    uint16_t attr_tbl_size = sizeof(bass_attr_tbl);

    attr_tbl_size -= (BASS_BRS_CHAR_MAX_NUM - brs_num) * 3 * sizeof(T_ATTRIB_APPL);

    if (false == gatt_svc_add(&service_id,
                                 (uint8_t *)bass_attr_tbl,
                                 attr_tbl_size,
                                 &bass_cbs, NULL))
    {
        PROTOCOL_PRINT_ERROR0("bass_add_service: failed");
        return false;
    }
    p_bass->service_id = service_id;

    return true;
}

Note

Add specific service information to gatt_svc_table struct, will be registered to GATT later.

Parameters:
  • p_out_service_id -- [in] Service ID of specific service.

  • p_database -- [in] Database pointer of specific service.

  • length -- [in] Length of Database of specific service. T_FUN_GATT_EXT_SERVICE_CBS.

  • p_srv_ext_cbs -- [in] Service callback functions of specific service. P_FUN_GATT_EXT_SEND_DATA_CB.

  • p_srv_ext_send_data_cb -- [in] Callback functions for service to handle the result of send notification or indication.

Return values:
  • true -- Add service success.

  • false -- Add service failed.

Returns:

Operation result.

uint8_t gatt_svc_get_num(void)

Get the service table number registered by gatt_svc_add.

Added Since 2.12.0.0:
Returns:

Registered service table number.

bool gatt_svc_read_confirm(uint16_t conn_handle, uint16_t cid, T_SERVER_ID service_id, uint16_t attrib_index, uint8_t *p_data, uint16_t data_len, uint16_t total_len, T_APP_RESULT cause)

Confirm from the application when receiving a read request from the client.

Example usage

T_APP_RESULT bass_attr_read_cb(uint16_t conn_handle, uint16_t cid, T_SERVER_ID service_id,
                               uint16_t attrib_index,
                               uint16_t offset, uint16_t *p_length, uint8_t **pp_value)
{
    T_APP_RESULT cause = APP_RESULT_SUCCESS;
    uint8_t *p_data = NULL;
    uint16_t len;
    uint8_t source_id = bass_get_source_id(attrib_index, false);
    PROTOCOL_PRINT_INFO2("bass_attr_read_cb: attrib_index %d, offset %x", attrib_index, offset);
    if (source_id == BASS_INVALID_SOURCE_ID)
    {
        return APP_RESULT_ATTR_NOT_FOUND;
    }

    if (bass_brs_gen_char_data(source_id,
                               &p_data,
                               &len))
    {
        if (offset > len)
        {
            cause = APP_RESULT_INVALID_OFFSET;
        }
        else
        {
            if (gatt_svc_read_confirm(conn_handle, cid, p_bass->service_id,
                                         attrib_index,
                                         p_data + offset,
                                         len - offset, len, APP_RESULT_SUCCESS))
            {
                cause = APP_RESULT_PENDING;
            }
        }
        if (p_data)
        {
            ble_audio_mem_free(p_data);
        }
    }
    return (cause);
}

Note

When using this API, the cause shall be set to APP_RESULT_PENDING in the attr_read_cb.

Parameters:
  • conn_handle -- [in] Connection handle of the ACL link.

  • cid -- [in] Local CID assigned by Bluetooth Host.

  • service_id -- [in] Service ID.

  • attrib_index -- [in] Attribute index of the attribute to read confirm from the application.

  • p_data -- [in] Pointer to the read value.

  • data_len -- [in] The length of the read data.

  • total_len -- [in] The total length of the data to read.

  • cause -- [in] Cause for read confirm. T_APP_RESULT.

Return values:
  • true -- Confirm from APP OK.

  • false -- Confirm from APP failed.

Returns:

Operation result.

bool gatt_svc_write_confirm(uint16_t conn_handle, uint16_t cid, T_SERVER_ID service_id, uint16_t attrib_index, T_APP_RESULT cause)

Confirm from the application when receiving a write request from the client.

Added Since 2.13.1.0:
Example usage
T_USER_CMD_PARSE_RESULT cmd_writeconf(T_USER_CMD_PARSED_VALUE *p_parse_value)
{
    uint8_t conn_id = p_parse_value->dw_param[0];
    uint16_t cid = p_parse_value->dw_param[1];
    T_SERVER_ID service_id = p_parse_value->dw_param[2];
    uint16_t attrib_index = p_parse_value->dw_param[3];

    if (!gatt_svc_write_confirm(conn_id, cid, service_id, attrib_index,
                                   APP_RESULT_SUCCESS))
    {
        return (RESULT_ERR);
    }

    return (RESULT_SUCESS);
}

Note

If the process of writing the attribute value does not end immediately, the specific service will call gatt_svc_write_confirm, and the cause shall be set to APP_RESULT_PENDING in the attr_write_cb.

Parameters:
  • conn_handle -- [in] Connection handle of the ACL link.

  • cid -- [in] Local CID assigned by Bluetooth Host.

  • service_id -- [in] Service ID.

  • attrib_index -- [in] Attribute index of the attribute to write confirm from the application.

  • cause -- [in] Write request APP handle result, APP_RESULT_SUCCESS or others.

Return values:
  • true -- Confirm from APP OK.

  • false -- Confirm from APP failed.

Returns:

Operation result.

bool gatt_svc_send_data(uint16_t conn_handle, uint16_t cid, T_SERVER_ID service_id, uint16_t attrib_index, uint8_t *p_data, uint16_t data_len, T_GATT_PDU_TYPE type)

Send notification or indication to peer device.

Example usage

bool bass_send_brs_notify(T_BLE_AUDIO_LINK *p_link, T_BASS_BRS_DB *p_db)
{
    uint8_t *p_data = NULL;
    uint16_t len = 0;
    uint16_t attrib_idx;
    bool ret = true;

    attrib_idx = BASS_CHAR_BRS_INDEX + 3 * (p_db->brs_data.source_id - 1);
    if (bass_brs_gen_char_data(p_db->brs_data.source_id, &p_data,  &len))
    {
        if (len > p_link->mtu_size - 3)
        {
            len = p_link->mtu_size - 3;
        }
        if (gatt_svc_send_data(p_link->conn_handle, L2C_FIXED_CID_ATT, p_bass->service_id, attrib_idx,
                                  p_data, len,
                                  GATT_PDU_TYPE_NOTIFICATION) == false)
        {
            ret = false;
        }
    }
    if (p_data)
    {
        ble_audio_mem_free(p_data);
    }
    return ret;
}
Parameters:
  • conn_handle -- [in] Connection handle of the ACL link.

  • cid -- [in] Local CID assigned by Bluetooth Host.

  • service_id -- [in] Service ID.

  • attrib_index -- [in] Attribute index of characteristic.

  • p_data -- [in] Pointer to data to be sent.

  • data_len -- [in] Length of value to be sent, range: 0~(mtu_size - 3). uint16_t mtu_size is acquired by le_get_conn_param(GAP_PARAM_CONN_MTU_SIZE, &mtu_size, conn_id).

  • type -- [in] GATT PDU type.

Return values:
  • true -- Success.

  • false -- Failed.

Returns:

Data sent result.

bool gatt_svc_init(uint16_t mode, uint8_t svc_num)

Initialize the GATT Service mode and service number.

Example usage

//case 1: The parameter svc_num is 0.
void app_ble_service_init(void)
{
    uint8_t server_num = 1;
    server_register_app_cb(app_ble_service_general_srv_cb);
    server_init(server_num);
    gatt_svc_init(GATT_SVC_USE_NORMAL_SERVER, 0);
}

//case 2: The parameter svc_num is not 0.
void app_ble_service_init(void)
{
    uint8_t server_num = 1;
    gatt_svc_init(GATT_SVC_USE_NORMAL_SERVER, server_num);
}
Parameters:
Return values:
  • true -- Success.

  • false -- Failed.

Returns:

The result of initializing the GATT Service mode.

void gatt_svc_cfg_pending_num(T_GATT_SVC_PENDING_NUM num)

Set the Maximum pending packets in the Bluetooth GATT service module.

Experimental Added Since 2.14.0.0:
Example usage
void test(void)
{
    gatt_svc_init(GATT_SVC_USE_NORMAL_SERVER, server_num);

    T_GATT_SVC_PENDING_NUM num;
    num.notify_num = 20;
    num.ind_num = 10;
    gatt_svc_cfg_pending_num(num);
}
Parameters:

num -- [in] Pending packet number T_GATT_SVC_PENDING_NUM. The default number for notification is 10. The default number for indication is 5.

void gatt_svc_register_general_cb(P_FUNC_GATT_SVC_GENERAL_CB svc_cb)

Register GATT service general callback function.

Experimental Added Since 2.14.0.0:
Example usage
void app_ble_service_init(void)
{
    gatt_svc_init(GATT_SVC_USE_NORMAL_SERVER, 1);
    gatt_svc_register_general_cb(app_gatt_svc_general_cb);
}

void app_gatt_svc_general_cb(uint8_t type, void *p_data)
{
    if (type == GATT_SVC_EVENT_REG_RESULT)
    {
        T_GATT_SVC_REG_RESULT *p_result = (T_GATT_SVC_REG_RESULT *)p_data;

        APP_PRINT_INFO1("GATT_SVC_EVENT_REG_RESULT: result 0x%x", p_result->result);
    }
    else if (type == GATT_SVC_EVENT_REG_AFTER_INIT_RESULT)
    {
        T_GATT_SVC_REG_AFTER_INIT_RESULT *p_result = (T_GATT_SVC_REG_AFTER_INIT_RESULT *)p_data;
        APP_PRINT_INFO2("GATT_SVC_EVENT_REG_AFTER_INIT_RESULT: service_id %d, cause 0x%x",
                        p_result->service_id, p_result->cause);
    }
}
Parameters:

svc_cb -- [in] GATT Service general callback function: P_FUNC_GATT_SVC_GENERAL_CB.

bool gatt_svc_handle_profile_data_cmpl(uint16_t conn_handle, uint16_t cid, T_SERVER_ID service_id, uint16_t attrib_idx, uint16_t credits, uint16_t cause)

Handle profile send data complete event. Used when receiving the message PROFILE_EVT_SEND_DATA_COMPLETE.

Example usage

T_APP_RESULT app_bqb_ext_profile_callback(T_SERVER_ID service_id, void *p_data)
{
    T_APP_RESULT app_result = APP_RESULT_SUCCESS;
    if (service_id == SERVICE_PROFILE_GENERAL_ID)
    {
        T_SERVER_EXT_APP_CB_DATA *p_param = (T_SERVER_EXT_APP_CB_DATA *)p_data;
        switch (p_param->eventId)
        {
        case PROFILE_EVT_SEND_DATA_COMPLETE:
            if (!gatt_svc_handle_profile_data_cmpl(p_param->event_data.send_data_result.conn_handle,
                                                      p_param->event_data.send_data_result.cid,
                                                      p_param->event_data.send_data_result.service_id,
                                                      p_param->event_data.send_data_result.attrib_idx,
                                                      p_param->event_data.send_data_result.credits,
                                                      p_param->event_data.send_data_result.cause))
            {
                APP_PRINT_ERROR0("gatt_svc_handle_profile_data_cmpl failed");
            }
            break;

        default:
            break;
        }
    }
}

Note

If the application uses the Bluetooth GATT Service module and the parameter svc_num of gatt_svc_init is 0, this function shall be called after receiving PROFILE_EVT_SEND_DATA_COMPLETE.

Parameters:
  • conn_handle -- [in] Connection handle of the ACL link.

  • cid -- [in] Local CID assigned by Bluetooth Host.

  • service_id -- [in] Service ID.

  • attrib_idx -- [in] Attribute index of characteristic.

  • credits -- [in] Credits number.

  • cause -- [in] Cause of service send data.

Return values:
  • true -- Success.

  • false -- Failed.

Returns:

The result of handling the profile send data complete event.

bool gatt_svc_service_changed_indicate(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle)

Send service changed indication.

Experimental Added Since 2.14.0.0:
Example usage
void test(void)
{
    uint16_t start_handle = 0x0001;
    uint16_t end_handle = 0xFFFF;
    bool ret = gatt_svc_service_changed_indicate(conn_handle, cid, start_handle, end_handle);
}
Parameters:
  • conn_handle -- [in] Connection handle of the ACL link.

  • cid -- [in] Local Channel Identifier assigned by Bluetooth Host.

  • start_handle -- [in] Start of Affected Attribute Handle Range.

  • end_handle -- [in] End of Affected Attribute Handle Range.

Return values:
  • true -- Sending request is successful.

  • false -- Sending request is failed.

Returns:

The result of sending operation.

T_CHAR_UUID gatt_svc_find_char_uuid_by_index(const T_ATTRIB_APPL *p_srv, uint16_t index, uint16_t attr_num)

Find service characteristic uuid by attribute index.

Example usage

T_APP_RESULT tmas_attr_read_cb(uint16_t conn_handle, uint16_t cid, T_SERVER_ID service_id,
                                      uint16_t attrib_index,
                                      uint16_t offset, uint16_t *p_length, uint8_t **pp_value)
{
    T_APP_RESULT cause = APP_RESULT_SUCCESS;

    PROTOCOL_PRINT_INFO2("tmas_attr_read_cb: attrib_index %d, offset %x", attrib_index, offset);

    T_CHAR_UUID char_uuid = gatt_svc_find_char_uuid_by_index(tmas_attr_tbl, attrib_index,
                                                             sizeof(tmas_attr_tbl) / sizeof(T_ATTRIB_APPL));
    if (char_uuid.uuid_size != UUID_16BIT_SIZE)
    {
        PROTOCOL_PRINT_ERROR1("tmas_attr_read_cb Error: attrib_index 0x%x", attrib_index);
        return APP_RESULT_ATTR_NOT_FOUND;
    }
    *p_length = 0;
    switch (char_uuid.uu.char_uuid16)
    {
    case TMAS_UUID_CHAR_ROLE:
        {
            *pp_value = (uint8_t *)&p_tmas->role;
            *p_length = 2;
        }
        break;
    default:
        cause = APP_RESULT_ATTR_NOT_FOUND;
        break;
    }

    return (cause);
}
Parameters:
  • p_srv -- [in] Pointer to service table: T_ATTRIB_APPL.

  • index -- [in] Attribute index of characteristic.

  • attr_num -- [in] Total attribute number of service.

Returns:

The characteristic uuid. T_CHAR_UUID.

bool gatt_svc_find_char_index_by_uuid(const T_ATTRIB_APPL *p_srv, T_CHAR_UUID char_uuid, uint16_t attr_num, uint16_t *index)

Find service characteristic attribute index by uuid.

Example usage

bool ccp_send_all_notify(T_TBS_CB *p_entry, uint16_t update_cfg,
                         uint16_t uuid, uint8_t *p_data, uint16_t data_len)
{
    uint8_t i;
    uint16_t attrib_idx;

    T_CHAR_UUID char_uuid;
    char_uuid.index = 1;
    char_uuid.uuid_size = UUID_16BIT_SIZE;
    char_uuid.uu.char_uuid16 = uuid;

    if (!gatt_svc_find_char_index_by_uuid(p_entry->p_attr_tbl, char_uuid,
                                     p_entry->attr_num,
                                     &attrib_idx))
    {
        PROTOCOL_PRINT_ERROR1("[CCP]ccp_send_all_notify: find index failed, uuid 0x%x", uuid);
        return false;
    }

    for (i = 0; i < MAX_BLE_LINK_NUM; i++)
    {
        if ((ble_audio_db.le_link[i].used == true) &&
            (ble_audio_db.le_link[i].state == GAP_CONN_STATE_CONNECTED))
        {
            T_LE_SRV_CFG *p_srv = ble_srv_find_by_srv_id(ble_audio_db.le_link[i].conn_handle,
                                                         p_entry->service_id);
            if (p_srv != NULL && (p_srv->cccd_cfg[0] & update_cfg))
            {
                if (tbs_send_notify(p_entry, ble_audio_db.le_link[i].conn_handle, attrib_idx, p_data,
                                    data_len) == false)
                {
                    return false;
                }
            }
        }
    }
    return true;
}
Parameters:
  • p_srv -- [in] Pointer to service table. T_ATTRIB_APPL.

  • char_uuid -- [in] Service characteristic uuid.

  • attr_num -- [in] Total attribute number of service.

  • index -- [inout] Attribute index of characteristic.

Return values:
  • true -- Success.

  • false -- Failed.

Returns:

The result of finding service characteristic attribute index.

uint16_t gatt_svc_find_char_index_by_uuid16(const T_ATTRIB_APPL *p_srv, uint16_t char_uuid16, uint16_t attr_num)

Find service characteristic attribute index by uuid16.

Example usage

bool mics_send_mute_value_notify(uint16_t conn_handle, uint8_t *p_mute_value)
{
    uint16_t attrib_idx = gatt_svc_find_char_index_by_uuid16(p_mics->p_mics_attr_tbl,
                                                             MICS_UUID_CHAR_MUTE,
                                                             p_mics->attr_num);
    return gatt_svc_send_data(conn_handle, L2C_FIXED_CID_ATT, p_mics->service_id,
                              attrib_idx,
                              p_mute_value,
                              1, GATT_PDU_TYPE_NOTIFICATION);
}
Parameters:
  • p_srv -- [in] Pointer to service table. T_ATTRIB_APPL.

  • char_uuid16 -- [in] Characteristic uuid16.

  • attr_num -- [in] Total attribute numer of service.

Return values:

0 -- Find service characteristic attribute index failed.

Returns:

The characteristic attribute index.