summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoão Paulo Rechi Vita <jprvita@gmail.com>2013-12-16 20:09:23 -0300
committerJoão Paulo Rechi Vita <jprvita@gmail.com>2014-01-15 15:03:51 -0300
commit96fbdc6e8a10df6b2399a5f5428592a04f469ac3 (patch)
treea64134842c9eef627ca9719a9468d6d689c1275c
parent47ba774aa2c8848a090e42578f6981782a4f1c68 (diff)
lib: Create API for GATT service discovery
-rw-r--r--lib/ble.c80
-rw-r--r--lib/ble.h40
2 files changed, 118 insertions, 2 deletions
diff --git a/lib/ble.c b/lib/ble.c
index d859cc4..8a46283 100644
--- a/lib/ble.c
+++ b/lib/ble.c
@@ -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;
}
}
diff --git a/lib/ble.h b/lib/ble.h
index 6f75801..738e89d 100644
--- a/lib/ble.h
+++ b/lib/ble.h
@@ -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