Attribute Caching

I am trying to implement Attribute caching as described in Vol 3, part G, section 2.5.2 of the Bluetooth Core Spec.

  • Reading the GATT Database Hash seems to work:
    • The bt_gatt_read returns zero
    • The callback function returns a zero “err” parameter
  • However:
    • the callback also returns a “length” of 3 (I would expect a 1 (if the return is a “field”) or a 16 (if the return is an array of bytes))
    • the bytes are not what I would expect – they don’t match my reference db hash.
    • an Ellisys trace does not show the Read by UUID ATT Transaction I would expect
  • I expect I am not configuring the bt_gatt_read_params correctly - here's the relevant code snippet:

// Callback for GATT DB Hash read

static uint8_t unicast_client_read_func_cb(struct bt_conn *conn, uint8_t err,

                                                                                struct bt_gatt_read_params *read, const void *data,

                                                                                uint16_t length)

{

                LOG_INF("TEC - unicast_client_read_func_cb: conn %p err %u read %p data 0x%032x length 0x%02x\n",

                                (void *)conn, err, (void *)read, data, length);

                for (int i = 0; i < 32; i++) {

                                LOG_INF("TEC - unicast_client_read_func_cb: data[%0d] = 0x%02x", i, ((uint8_t *)data)[i]);

                }              

                return BT_GATT_ITER_STOP;

}

 

int unicast_client_gatt_db_hash_read(struct bt_conn *conn)

{

                LOG_INF("TEC - unicast_client_gatt_db_hash_read: conn %p\n", (void *)conn);

                int ret;

                struct stream_index idx;

                static struct bt_gatt_read_params read_params;

                struct bt_gatt_read_params* read_params_ptr = &read_params;

                ret = device_index_get(conn, &idx);

                LOG_INF("TEC - device_index_get ret %d idx %d,%d,%d\n", ret, idx.lvl1, idx.lvl2, idx.lvl3);

                if (ret) {

                                return ret;

                }

                (*read_params_ptr).func = unicast_client_read_func_cb;

                (*read_params_ptr).by_uuid.uuid = BT_UUID_GATT_DB_HASH_VAL; // GATT DB Hash UUID

                (*read_params_ptr).by_uuid.start_handle = 0x0001;

                (*read_params_ptr).by_uuid.end_handle = 0xffff;

                (*read_params_ptr).handle_count = 0;

                ret = bt_gatt_read(conn, read_params_ptr);

                if (ret) {

                                LOG_WRN("Failed to read gatt db hash: %d", ret);

                                return ret;

                }

                return 0;

}

  • Hi,

    Interesting. 

    First memset the read_prams_ptr before use as a good practice.

    Are you sure that you are setting the uuid correct here?
    (*read_params_ptr).by_uuid.uuid = BT_UUID_GATT_DB_HASH_VAL; 

    Shouldn't this be set to BT_UUID_GATT_DB_HASH?

    Also guard your callback when data == NULL when you return BT_GATT_ITER_STOP else you keep on looping on the GATT iterations even though you see no data.

  • Excellent! Step 1 achieved.  The key was the uuid itself - using BT_UUID_GATT_DB_HASH solved my immediate problem.  I'll work with my FW expert on code cleanup - implementing your other suggestions - now that we've got read by uuid working.  I'm sure we'll have more questions as we continue to implement Attribute caching.

    Thanks for your prompt and accurate response!

    Tom

Related