summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoão Paulo Rechi Vita <jprvita@gmail.com>2013-12-06 19:30:27 -0300
committerJoão Paulo Rechi Vita <jprvita@gmail.com>2014-01-15 15:01:16 -0300
commitb2d6b390e2435781cee678a563b204f6d7222b24 (patch)
tree979782a10138c14041c857e63d9f7e33445806ab
parent7b2f4b2501d2b26f615d4f91b840a9cd8b0d29bd (diff)
lib: Create API to connect to BLE devices and disconnect from them
-rw-r--r--lib/ble.c129
-rw-r--r--lib/ble.h43
2 files changed, 170 insertions, 2 deletions
diff --git a/lib/ble.c b/lib/ble.c
index 960b046..5a9161b 100644
--- a/lib/ble.c
+++ b/lib/ble.c
@@ -31,6 +31,15 @@
#include "ble.h"
+/* Internal representation of a BLE device */
+typedef struct ble_device ble_device_t;
+struct ble_device {
+ bt_bdaddr_t bda;
+ int conn_id;
+
+ ble_device_t *next;
+};
+
/* Data that have to be acessable by the callbacks */
static struct libdata {
ble_cbs_t cbs;
@@ -42,6 +51,7 @@ static struct libdata {
uint8_t adapter_state;
uint8_t scan_state;
+ ble_device_t *devices;
} data;
/* Called every time an advertising report is seen */
@@ -82,6 +92,110 @@ int ble_stop_scan() {
return ble_scan(0);
}
+static ble_device_t *find_device_by_address(const uint8_t *address) {
+ ble_device_t *dev;
+
+ for (dev = data.devices; dev ; dev = dev->next)
+ if (!memcmp(dev->bda.address, address, sizeof(dev->bda.address)))
+ break;
+
+ return dev;
+}
+
+/* Called every time a device gets connected */
+static void connect_cb(int conn_id, int status, int client_if,
+ bt_bdaddr_t *bda) {
+ ble_device_t *dev;
+
+ dev = find_device_by_address(bda->address);
+ if (!dev)
+ return;
+
+ dev->conn_id = conn_id;
+
+ if (data.cbs.connect_cb)
+ data.cbs.connect_cb(bda->address, conn_id, status);
+}
+
+int ble_connect(const uint8_t *address) {
+ ble_device_t *dev;
+ bt_status_t s;
+
+ if (!data.client)
+ return -1;
+
+ if (!data.gattiface)
+ return -1;
+
+ if (!data.adapter_state)
+ return -1;
+
+ dev = find_device_by_address(address);
+ if (!dev) {
+ int i;
+
+ dev = calloc(1, sizeof(ble_device_t));
+ if (!dev)
+ return -1;
+
+ /* TODO: memcpy() */
+ for (i = 0; i < 6; i++)
+ dev->bda.address[i] = address[i];
+
+ dev->next = data.devices;
+ data.devices = dev;
+ }
+
+ s = data.gattiface->client->connect(data.client, &dev->bda, true);
+ if (s != BT_STATUS_SUCCESS)
+ return -s;
+
+ return 0;
+}
+
+/* Called every time a device gets disconnected */
+static void disconnect_cb(int conn_id, int status, int client_if,
+ bt_bdaddr_t *bda) {
+ ble_device_t *dev;
+
+ dev = find_device_by_address(bda->address);
+ if (!dev)
+ return;
+
+ dev->conn_id = 0;
+
+ if (data.cbs.disconnect_cb)
+ data.cbs.disconnect_cb(bda->address, conn_id, status);
+}
+
+int ble_disconnect(const uint8_t *address) {
+ ble_device_t *dev;
+ bt_status_t s;
+
+ if (!data.client)
+ return -1;
+
+ if (!data.gattiface)
+ return -1;
+
+ if (!data.adapter_state)
+ return -1;
+
+ if (!address)
+ return -1;
+
+ dev = find_device_by_address(address);
+ if (!dev)
+ return -1;
+
+ s = data.gattiface->client->disconnect(data.client, &dev->bda,
+ dev->conn_id);
+ 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) {
@@ -96,8 +210,8 @@ static void register_client_cb(int status, int client_if, bt_uuid_t *app_uuid) {
static const btgatt_client_callbacks_t gattccbs = {
register_client_cb,
scan_result_cb,
- NULL, /* connect_cb */
- NULL, /* disconnect_cb */
+ connect_cb,
+ disconnect_cb,
NULL, /* search_complete_cb */
NULL, /* search_result_cb */
NULL, /* get_characteristic_cb */
@@ -217,6 +331,17 @@ int ble_enable(ble_cbs_t cbs) {
return 0;
}
+static void remove_all_devices() {
+ ble_device_t *dev, *next;
+
+ dev = data.devices;
+ while (dev) {
+ next = dev->next;
+ free(dev);
+ dev = next;
+ }
+}
+
int ble_disable() {
bt_status_t s;
diff --git a/lib/ble.h b/lib/ble.h
index 481e076..8bead06 100644
--- a/lib/ble.h
+++ b/lib/ble.h
@@ -69,12 +69,29 @@ typedef void (*ble_scan_cb_t)(const uint8_t *address, int rssi,
const uint8_t *adv_data);
/**
+ * Type that represents a callback function to notify of a new connection with
+ * a BLE device or a disconnection from a device.
+ *
+ * @param address A pointer to a 6 element array representing each part of the
+ * Bluetooth address of the remote device, where the
+ * most-significant byte is on position 0 and the
+ * least-sifnificant byte is on position 5.
+ * @param conn_id An identifier of the connected remote device. If this is
+ * nonpositive it means the device is not connected.
+ * @param status The status in which the connect operation has finished.
+ */
+typedef void (*ble_connect_cb_t)(const uint8_t *address, int conn_id,
+ int status);
+
+/**
* List of callbacks for BLE operations.
*/
typedef struct ble_cbs {
ble_enable_cb_t enable_cb;
ble_adapter_state_cb_t adapter_state_cb;
ble_scan_cb_t scan_cb;
+ ble_connect_cb_t connect_cb;
+ ble_connect_cb_t disconnect_cb;
} ble_cbs_t;
/**
@@ -114,4 +131,30 @@ int ble_start_scan();
* @return -1 if failed to request scan stop.
*/
int ble_stop_scan();
+
+/**
+ * Connects to a BLE device.
+ *
+ * @param address A pointer to a 6 element array representing each part of the
+ * Bluetooth address of the remote device a connection should be
+ * requested, where the most-significant byte is on position 0
+ * and the least-sifnificant byte is on position 5.
+ *
+ * @return 0 if connection has been successfully requested.
+ * @return -1 if failed to request connection.
+ */
+int ble_connect(const uint8_t *address);
+
+/**
+ * Disconnects from a BLE device.
+ *
+ * @param address A pointer to a 6 element array representing each part of the
+ * Bluetooth address of the remote device a disconnection should
+ * be requested, where the most-significant byte is on position
+ * 0 and the least-sifnificant byte is on position 5.
+ *
+ * @return 0 if disconnection has been successfully requested.
+ * @return -1 if failed to request disconnection.
+ */
+int ble_disconnect(const uint8_t *address);
#endif