summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoão Paulo Rechi Vita <jprvita@gmail.com>2013-12-05 17:44:08 -0300
committerJoão Paulo Rechi Vita <jprvita@gmail.com>2014-01-14 16:33:21 -0300
commite04be1f6e3b4f0f443a411122e7928ef1eea3ad0 (patch)
treeb52672192d70c331934b952c0baab5940d45dfd7
parent14ce36a1de9391d4424c751685f8addf29e635dd (diff)
lib: Create API to enable and disable the BLE features
The same call initializes the GATT profile, gets the GATT client interface and powers on the adapter (and symmetrically powers off the adapter and do the necessary clean-ups).
-rw-r--r--lib/ble.c120
-rw-r--r--lib/ble.h26
2 files changed, 134 insertions, 12 deletions
diff --git a/lib/ble.c b/lib/ble.c
index 9893ea7..a58b0a5 100644
--- a/lib/ble.c
+++ b/lib/ble.c
@@ -25,6 +25,8 @@
#include <unistd.h>
#include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <hardware/bt_gatt_client.h>
#include <hardware/hardware.h>
#include "ble.h"
@@ -35,12 +37,98 @@ static struct libdata {
uint8_t btiface_initialized;
const bt_interface_t *btiface;
+ const btgatt_interface_t *gattiface;
+ int client;
+
+ uint8_t adapter_state;
} data;
+/* 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) {
+ data.client = client_if;
+ if (data.cbs.enable_cb)
+ data.cbs.enable_cb();
+ } else
+ data.client = 0;
+}
+
+/* GATT client interface callbacks */
+static const btgatt_client_callbacks_t gattccbs = {
+ register_client_cb,
+ NULL, /* scan_result_cb */
+ NULL, /* connect_cb */
+ NULL, /* disconnect_cb */
+ NULL, /* search_complete_cb */
+ NULL, /* search_result_cb */
+ NULL, /* get_characteristic_cb */
+ NULL, /* get_descriptor_cb */
+ NULL, /* get_included_service_cb */
+ NULL, /* register_for_notification_cb */
+ NULL, /* notify_cb */
+ NULL, /* read_characteristic_cb */
+ NULL, /* write_characteristic_cb */
+ NULL, /* read_descriptor_cb */
+ NULL, /* write_descriptor_cb */
+ NULL, /* execute_write_cb */
+ NULL, /* read_remote_rssi_cb */
+};
+
+/* GATT interface callbacks */
+static const btgatt_callbacks_t gattcbs = {
+ sizeof(btgatt_callbacks_t),
+ &gattccbs,
+ NULL /* btgatt_server_callbacks_t */
+};
+
+/* Called every time the adapter state changes */
+static void adapter_state_changed_cb(bt_state_t state) {
+ /* Arbitrary UUID used to identify this application with the GATT profile */
+ bt_uuid_t app_uuid = { .uu = { 0x1b, 0x1c, 0xb9, 0x2e, 0x0d, 0x2e, 0x4c,
+ 0x45, 0xbb, 0xb8, 0xf4, 0x1b, 0x46, 0x39,
+ 0x23, 0x36 } };
+
+ data.adapter_state = state == BT_STATE_ON ? 1 : 0;
+ if (data.cbs.adapter_state_cb)
+ data.cbs.adapter_state_cb(data.adapter_state);
+
+ if (data.adapter_state) {
+ bt_status_t s = data.gattiface->client->register_client(&app_uuid);
+ if (s != BT_STATUS_SUCCESS)
+ data.btiface->disable();
+ } else
+ /* Cleanup the Bluetooth interface */
+ data.btiface->cleanup();
+}
+
+/* This callback is called when the stack finishes initialization / shutdown */
+static void thread_event_cb(bt_cb_thread_evt event) {
+ bt_status_t s;
+
+ if (event == DISASSOCIATE_JVM) {
+ data.btiface_initialized = 0;
+ return;
+ }
+
+ data.btiface_initialized = 1;
+
+ data.gattiface = data.btiface->get_profile_interface(BT_PROFILE_GATT_ID);
+ if (data.gattiface != NULL) {
+ s = data.gattiface->init(&gattcbs);
+ if (s != BT_STATUS_SUCCESS)
+ data.gattiface = NULL;
+ }
+
+ /* Enable the adapter */
+ s = data.btiface->enable();
+ if (s != BT_STATUS_SUCCESS)
+ data.btiface->cleanup();
+}
+
/* Bluetooth interface callbacks */
static bt_callbacks_t btcbs = {
sizeof(bt_callbacks_t),
- NULL, /* adapter_state_change_cb */
+ adapter_state_changed_cb,
NULL, /* adapter_properties_cb */
NULL, /* remote_device_properties_callback */
NULL, /* device_found_cb */
@@ -49,12 +137,12 @@ static bt_callbacks_t btcbs = {
NULL, /* ssp_request_cb */
NULL, /* bond_state_changed_cb */
NULL, /* acl_state_changed_callback */
- NULL, /* thread_event_cb */
+ thread_event_cb,
NULL, /* dut_mode_recv_callback */
NULL, /* le_test_mode_callback */
};
-int ble_init(ble_cbs_t cbs) {
+int ble_enable(ble_cbs_t cbs) {
int status;
bt_status_t s;
hw_module_t *module;
@@ -90,9 +178,25 @@ int ble_init(ble_cbs_t cbs) {
return 0;
}
-void ble_shutdown() {
- /* Cleanup the Bluetooth interface */
- data.btiface->cleanup();
- while (data.btiface_initialized)
- usleep(10000);
+int ble_disable() {
+ bt_status_t s;
+
+ if (!data.adapter_state)
+ return -1;
+
+ if (!data.btiface)
+ return -1;
+
+ if (!data.client)
+ return -1;
+
+ s = data.gattiface->client->unregister_client(data.client);
+ if (s != BT_STATUS_SUCCESS)
+ return -s;
+
+ s = data.btiface->disable();
+ if (s != BT_STATUS_SUCCESS)
+ return -s;
+
+ return 0;
}
diff --git a/lib/ble.h b/lib/ble.h
index b60bc82..c4e4edd 100644
--- a/lib/ble.h
+++ b/lib/ble.h
@@ -42,23 +42,41 @@
*/
/**
+ * Type that represents a callback function to inform that BLE is enabled and
+ * available to be used.
+ */
+typedef void (*ble_enable_cb_t)(void);
+
+/**
+ * Type that represents a callback function to inform an adapter state change.
+ *
+ * @param state The new state of the adapter: 0 disabled, 1 enabled.
+ */
+typedef void (*ble_adapter_state_cb_t)(uint8_t state);
+
+/**
* 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_cbs_t;
/**
- * Initialize the stack and necessary interfaces.
+ * Initialize the BLE stack and necessary interfaces and power on the adapter.
*
* @param cbs List of callbacks for BLE operations.
*
* @return 0 on success.
* @return Negative value on failure.
*/
-int ble_init(ble_cbs_t cbs);
+int ble_enable(ble_cbs_t cbs);
/**
- * Shutdown the stack and do the necessary cleanups.
+ * Power off the adapter, cleanup the BLE features and shutdown the stack.
+ *
+ * @return 0 on success.
+ * @return Negative value on failure.
*/
-void ble_shutdown();
+int ble_disable();
#endif