diff options
author | João Paulo Rechi Vita <jprvita@gmail.com> | 2013-12-16 20:09:23 -0300 |
---|---|---|
committer | João Paulo Rechi Vita <jprvita@gmail.com> | 2014-01-15 15:03:51 -0300 |
commit | 96fbdc6e8a10df6b2399a5f5428592a04f469ac3 (patch) | |
tree | a64134842c9eef627ca9719a9468d6d689c1275c | |
parent | 47ba774aa2c8848a090e42578f6981782a4f1c68 (diff) |
lib: Create API for GATT service discovery
-rw-r--r-- | lib/ble.c | 80 | ||||
-rw-r--r-- | lib/ble.h | 40 |
2 files changed, 118 insertions, 2 deletions
@@ -37,6 +37,9 @@ struct ble_device { bt_bdaddr_t bda; int conn_id; + btgatt_srvc_id_t *srvcs; + uint8_t srvc_count; + ble_device_t *next; }; @@ -277,6 +280,76 @@ int ble_remove_bond(const uint8_t *address) { return ble_pair_internal(address, 2); } +static ble_device_t *find_device_by_conn_id(int conn_id) { + ble_device_t *dev; + + for (dev = data.devices; dev ; dev = dev->next) + if (dev->conn_id == conn_id) + break; + + return dev; +} + +static int find_service(ble_device_t *dev, btgatt_srvc_id_t *srvc_id) { + int id; + + for (id = 0; id < dev->srvc_count; id++) + if (!memcmp(&dev->srvcs[id], srvc_id, sizeof(btgatt_srvc_id_t))) + return id; + + return -1; +} + +/* Called when the service discovery finishes */ +void service_discovery_complete_cb(int conn_id, int status) { + if (data.cbs.srvc_finished_cb) + data.cbs.srvc_finished_cb(conn_id, status); +} + +/* Called for each service discovery result */ +void service_discovery_result_cb(int conn_id, btgatt_srvc_id_t *srvc_id) { + int id; + ble_device_t *dev; + + dev = find_device_by_conn_id(conn_id); + if (!dev) + return; + + id = find_service(dev, srvc_id); + if (id < 0) { + id = dev->srvc_count++; + dev->srvcs = realloc(dev->srvcs, + dev->srvc_count * sizeof(btgatt_srvc_id_t)); + memcpy(&dev->srvcs[id], srvc_id, sizeof(btgatt_srvc_id_t)); + } + + if (data.cbs.srvc_found_cb) + data.cbs.srvc_found_cb(conn_id, id, srvc_id->id.uuid.uu, + srvc_id->is_primary); +} + +int ble_gatt_discover_services(int conn_id, const uint8_t *uuid) { + bt_status_t s; + bt_uuid_t uu, *u = NULL; + + if (conn_id <= 0) + return -1; + + if (!data.gattiface) + return -1; + + if (uuid) { + memcpy(uu.uu, uuid, 16 * sizeof(uint8_t)); + u = &uu; + } + + s = data.gattiface->client->search_service(conn_id, u); + if (s != BT_STATUS_SUCCESS) + return -s; + + return 0; +} + /* Called when the client registration is finished */ static void register_client_cb(int status, int client_if, bt_uuid_t *app_uuid) { if (status == BT_STATUS_SUCCESS) { @@ -293,8 +366,8 @@ static const btgatt_client_callbacks_t gattccbs = { scan_result_cb, connect_cb, disconnect_cb, - NULL, /* search_complete_cb */ - NULL, /* search_result_cb */ + service_discovery_complete_cb, + service_discovery_result_cb, NULL, /* get_characteristic_cb */ NULL, /* get_descriptor_cb */ NULL, /* get_included_service_cb */ @@ -418,7 +491,10 @@ static void remove_all_devices() { dev = data.devices; while (dev) { next = dev->next; + + free(dev->srvcs); free(dev); + dev = next; } } @@ -106,6 +106,30 @@ typedef void (*ble_bond_state_cb_t)(const uint8_t *address, ble_bond_state_t state, int status); /** + * Type that represents a callback function to notify of a new GATT element + * (service, characteristic or descriptor) found in a BLE device. + * + * @param conn_id The identifier of the connected remote device. + * @param id ID of the service, characteristic or descriptor. + * @param uuid A pointer to a 16 element array representing each part of the + * service, characteristic or descriptor UUID. + * @param props Additional element properties. For services, whether the service + * is primary or not: 1 primary, 0 included. Always zero for other + * GATT elements. + */ +typedef void (*ble_gatt_found_cb_t)(int conn_id, int id, const uint8_t *uuid, + int props); + +/** + * Type that represents a callback function to notify that a GATT operation has + * finished. + * + * @param conn_id The identifier of the connected remote device. + * @param status The status in which the operation has finished. + */ +typedef void (*ble_gatt_finished_cb_t)(int conn_id, int status); + +/** * List of callbacks for BLE operations. */ typedef struct ble_cbs { @@ -115,6 +139,8 @@ typedef struct ble_cbs { ble_connect_cb_t connect_cb; ble_connect_cb_t disconnect_cb; ble_bond_state_cb_t bond_state_cb; + ble_gatt_found_cb_t srvc_found_cb; + ble_gatt_finished_cb_t srvc_finished_cb; } ble_cbs_t; /** @@ -219,4 +245,18 @@ int ble_cancel_pairing(const uint8_t *address); * @return -1 if failed to remove bond. */ int ble_remove_bond(const uint8_t *address); + +/** + * Discover services in a BLE device. + * + * There should be an active connection with the device. + * + * @param conn_id The identifier of the connected remote device. + * @param uuid Service UUID: if not NULL then only services with this UUID will + * be notified. + * + * @return 0 if service discovery has been successfully requested. + * @return -1 if failed to request service discovery. + */ +int ble_gatt_discover_services(int conn_id, const uint8_t *uuid); #endif |