Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 428e3582 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

Add new HAL method get_gatt_db

Currently getting GATT database from HAL requires multiple calls
and iterating over each element. This is long, unnecessary
complicated process, error prone process. This patch adds new
method, get_gatt_db that can be used to grab whole GATT database
for remote device just in one call.

Change-Id: Ib5d88fbc28d09d5c191e7c0152ca61d6a34f7a81
parent 73f865ef
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -546,6 +546,23 @@ tBTA_GATT_STATUS BTA_GATTC_GetNextIncludedService(UINT16 conn_id,
    return status;
}

/*******************************************************************************
**
** Function         BTA_GATTC_GetGattDb
**
** Description      This function is called to get the GATT database.
**
** Parameters       conn_id: connection ID which identify the server.
**                  db: output parameter which will contain the GATT database copy.
**                      Caller is responsible for freeing it.
**                  count: number of elements in database.
**
*******************************************************************************/
void  BTA_GATTC_GetGattDb(UINT16 conn_id, btgatt_db_element_t **db, int *count)
{
    bta_gattc_get_gatt_db(conn_id, db, count);
}

/*******************************************************************************
**
** Function         BTA_GATTC_ReadCharacteristic
+159 −0
Original line number Diff line number Diff line
@@ -1499,6 +1499,165 @@ tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
    return status;
}

/*******************************************************************************
**
** Function         bta_gattc_fill_gatt_db_el
**
** Description      fill a btgatt_db_element_t value
**
** Returns          None.
**
*******************************************************************************/
void bta_gattc_fill_gatt_db_el(btgatt_db_element_t *p_attr,
                               bt_gatt_db_attribute_type_t type,
                               UINT16 att_handle,
                               UINT16 s_handle, UINT16 e_handle,
                               UINT8 id, tBT_UUID uuid, UINT8 prop)
{
    p_attr->type             = type;
    p_attr->attribute_handle = att_handle;
    p_attr->start_handle     = s_handle;
    p_attr->end_handle       = e_handle;
    p_attr->id               = id;
    p_attr->properties       = prop;
    bta_to_btif_uuid(&p_attr->uuid, &uuid);
}

/*******************************************************************************
**
** Function         bta_gattc_get_gatt_db_impl
**
** Description      copy the server GATT database into db parameter.
**
** Parameters       p_srvc_cb: server.
**                  db: output parameter which will contain GATT database copy.
**                      Caller is responsible for freeing it.
**                  count: output parameter which will contain number of
**                  elements in database.
**
** Returns          None.
**
*******************************************************************************/
static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV *p_srvc_cb,
                                       btgatt_db_element_t **db,
                                       int *count)
{
    tBTA_GATTC_CACHE_ATTR   *p_attr;
    tBT_UUID                uuid;

    APPL_TRACE_DEBUG(LOG_TAG, "%s", __func__);

    tBTA_GATTC_CACHE        *p_cur_srvc = p_srvc_cb->p_srvc_cache;
    int db_size = 0;
    while (p_cur_srvc)
    {
        db_size++;
        for(p_attr = p_cur_srvc->p_attr; p_attr; p_attr = p_attr->p_next)
            db_size++;
        p_cur_srvc = p_cur_srvc->p_next;
    }

    void* buffer = osi_malloc(db_size * sizeof(btgatt_db_element_t));
    btgatt_db_element_t *curr_db_attr = buffer;

    p_cur_srvc = p_srvc_cb->p_srvc_cache;
    while (p_cur_srvc)
    {
        bta_gattc_fill_gatt_db_el(curr_db_attr,
                                  p_cur_srvc->service_uuid.is_primary ?
                                      BTGATT_DB_PRIMARY_SERVICE :
                                      BTGATT_DB_SECONDARY_SERVICE,
                                  0 /* att_handle */,
                                  p_cur_srvc->s_handle,
                                  p_cur_srvc->e_handle,
                                  p_cur_srvc->service_uuid.id.inst_id,
                                  p_cur_srvc->service_uuid.id.uuid,
                                  0 /* prop */);
        curr_db_attr++;

        for (p_attr = p_cur_srvc->p_attr; p_attr; p_attr = p_attr->p_next)
        {
            if ((uuid.len = p_attr->uuid_len) == LEN_UUID_16)
                uuid.uu.uuid16 = p_attr->p_uuid->uuid16;
            else
                memcpy(uuid.uu.uuid128, p_attr->p_uuid->uuid128, LEN_UUID_128);

            bt_gatt_db_attribute_type_t type;
            switch (p_attr->attr_type)
            {
                case BTA_GATTC_ATTR_TYPE_CHAR:
                    type = BTGATT_DB_CHARACTERISTIC;
                    break;

                case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
                    type = BTGATT_DB_DESCRIPTOR;
                    break;

                case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
                    type = BTGATT_DB_INCLUDED_SERVICE;
                    break;

                default:
                    LOG_ERROR(LOG_TAG, "%s unknown gatt db attribute type: %d",
                              __func__, p_attr->attr_type);
            }

            bta_gattc_fill_gatt_db_el(curr_db_attr,
                                      type,
                                      p_attr->attr_handle,
                                      0 /* s_handle */,
                                      0 /* e_handle */,
                                      p_attr->inst_id,
                                      uuid,
                                      p_attr->property);
            curr_db_attr++;
        }
        p_cur_srvc = p_cur_srvc->p_next;
    }

    *db = buffer;
    *count = db_size;
}

/*******************************************************************************
**
** Function         bta_gattc_get_gatt_db
**
** Description      copy the server GATT database into db parameter.
**
** Parameters       conn_id: connection ID which identify the server.
**                  db: output parameter which will contain GATT database copy.
**                      Caller is responsible for freeing it.
**                  count: number of elements in database.
**
** Returns          None.
**
*******************************************************************************/
void bta_gattc_get_gatt_db(UINT16 conn_id, btgatt_db_element_t **db, int *count)
{
    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;

    LOG_DEBUG(LOG_TAG, "%s", __func__);
    if (p_clcb == NULL) {
        APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
        return;
    }

    if (p_clcb->state != BTA_GATTC_CONN_ST) {
        APPL_TRACE_ERROR("server cache not available, CLCB state = %d",
                         p_clcb->state);
        return;
    }

    if (!p_clcb->p_srcb || p_clcb->p_srcb->p_srvc_list || /* no active discovery */
        !p_clcb->p_srcb->p_srvc_cache) {
        APPL_TRACE_ERROR("No server cache available");
    }

    bta_gattc_get_gatt_db_impl(p_clcb->p_srcb, db, count);
}

/*******************************************************************************
**
** Function         bta_gattc_rebuild_cache
+1 −0
Original line number Diff line number Diff line
@@ -540,6 +540,7 @@ extern void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid);
extern tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id, UINT8 query_type, tBTA_GATT_SRVC_ID *p_srvc_id,
                                              tBTA_GATT_ID *p_start_rec,tBT_UUID *p_uuid_cond,
                                              tBTA_GATT_ID *p_output, void *p_param);
extern void bta_gattc_get_gatt_db(UINT16 conn_id, btgatt_db_element_t **db, int *count);
extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index);
extern BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id);
+14 −0
Original line number Diff line number Diff line
@@ -882,6 +882,20 @@ extern tBTA_GATT_STATUS BTA_GATTC_GetNextIncludedService(UINT16 conn_id,
                                                          tBT_UUID             *p_uuid_cond,
                                                          tBTA_GATTC_INCL_SVC_ID *p_result);

/*******************************************************************************
**
** Function         BTA_GATTC_GetGattDb
**
** Description      This function is called to get gatt db.
**
** Parameters       conn_id: connection ID which identify the server.
**                  db: output parameter which will contain gatt db copy.
**                      Caller is responsible for freeing it.
**                  count: number of elements in db.
**
*******************************************************************************/
extern void BTA_GATTC_GetGattDb(UINT16 conn_id, btgatt_db_element_t **db, int *count);

/*******************************************************************************
**
** Function         BTA_GATTC_ReadCharacteristic
+27 −2
Original line number Diff line number Diff line
@@ -107,7 +107,8 @@ typedef enum {
    BTIF_GATTC_CONFIG_STORAGE_PARAMS,
    BTIF_GATTC_ENABLE_BATCH_SCAN,
    BTIF_GATTC_READ_BATCH_SCAN_REPORTS,
    BTIF_GATTC_DISABLE_BATCH_SCAN
    BTIF_GATTC_DISABLE_BATCH_SCAN,
    BTIF_GATTC_GET_GATT_DB
} btif_gattc_event_t;

#define BTIF_GATT_MAX_OBSERVED_DEV 40
@@ -1369,6 +1370,18 @@ static void btgattc_handle_event(uint16_t event, char* p_param)
            break;
        }

        case BTIF_GATTC_GET_GATT_DB:
        {
            btgatt_db_element_t *db = NULL;
            int count = 0;
            BTA_GATTC_GetGattDb(p_cb->conn_id, &db, &count);

            HAL_CBACK(bt_gatt_callbacks, client->get_gatt_db_cb,
                p_cb->conn_id, db, count);
            osi_free(db);
            break;
        }

        case BTIF_GATTC_READ_CHAR:
            btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
            btif_to_bta_gatt_id(&in_char_id.char_id, &p_cb->char_id);
@@ -1958,6 +1971,17 @@ static bt_status_t btif_gattc_get_included_service(int conn_id, btgatt_srvc_id_t
                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}

static bt_status_t btif_gattc_get_gatt_db(int conn_id)
{
    CHECK_BTGATT_INIT();
    btif_gattc_cb_t btif_cb;
    btif_cb.conn_id = (uint16_t) conn_id;

    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_GATT_DB,
                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}


static bt_status_t btif_gattc_read_char(int conn_id, btgatt_srvc_id_t* srvc_id,
                                        btgatt_gatt_id_t* char_id, int auth_req )
{
@@ -2386,7 +2410,8 @@ const btgatt_client_interface_t btgattClientInterface = {
    btif_gattc_enb_batch_scan,
    btif_gattc_dis_batch_scan,
    btif_gattc_read_batch_scan_reports,
    btif_gattc_test_command
    btif_gattc_test_command,
    btif_gattc_get_gatt_db
};

#endif