RFC: Populating shared/gatt-client from storage.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all,

In the case where bluez is bonded with a remote device we don't want
to always perform service discovery, but instead to cache the
attribute data permanently and just use that on reconnections.
Currently shared/gatt-client automatically discovers all services when
created (via bt_gatt_client_new) so we need to add support to populate
a shared/gatt-client based on cached data in storage, since a
bt_gatt_client instance acts as our in-memory attribute cache for the
client role.

I initially thought about storing everything in INI format and loading
things directly from a file, via some function like
bt_gatt_client_new_from_storage. The biggest problem with this
approach is parsing the INI format; since we don't want to pull in any
external dependencies into shared/gatt (e.g. glib) we would possibly
have to write our own key-value file parser for shared/ which seems
like overkill. We could possibly invent some simpler blob format for
shared/gatt-client but people brought to my attention on IRC that we
may want to leave the exact storage format to the upper-layer, e.g.
desktop and android versions of bluetoothd may want to use different
formats for their attribute cache that's consistent with the platform.

So I decided to go with something generic instead. We would basically
add functions to manually populate a gatt-client and mark the client
as ready only after it's services have been populated. So we would
have these API changes:

1. A new argument to bt_gatt_client_new, to tell it not to perform
discovery. Something like "bool discover_services".

    /* Don't perform discovery */
    bt_gatt_client_new(att, mtu, false);

This would basically just leave the structure in "init" state and not
become ready.

2. We would then add a new structure to populate a gatt-client.

    struct bt_gatt_populate { .. };  /* Probably something with a better name */

    bool bt_gatt_populate_start(struct bt_gatt_populate *, struct
bt_gatt_client *);
    bool bt_gatt_populate_add_service(....)
    bool bt_gatt_populate_add_characteristic(...)
    bool bt_gatt_populate_add_descriptor(....)
    bool bt_gatt_populate_add_include(....)
    bool bt_gatt_populate_cancel(...)
    bool bt_gatt_populate_commit(struct bt_gatt_populate *);

The start function would tell gatt-client that it's being populated so
it would prevent this from being called twice. All of the _add_*
functions would create a temporary tree owned by the populate
structure, using the same internal structures defined in
shared/gatt-client.c. Calling bt_gatt_populate_commit would then pass
the ownership of the services to the bt_gatt_client, and
bt_gatt_client would perform the MTU exchange, subscribe to
notifications from the "Service Changed" characteristic if one exists,
mark itself as ready and invoke the ready handler.

If the upper-layer wants to store the current contents of gatt-client,
they can do so by iterating through its services and caching them to a
file directly. This way, shared/gatt-client would remain agnostic to
any storage format.

Comments requested.
Arman
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux