gattlib: Introduce 'gattlib_register_on_disconnect()'

pull/95/head
Olivier Martin 2019-05-03 09:47:58 +02:00
parent bcac05a811
commit 98ac9e5d2b
3 changed files with 42 additions and 10 deletions

View File

@ -220,7 +220,8 @@ gboolean on_handle_device_property_change(
const gchar *const *arg_invalidated_properties, const gchar *const *arg_invalidated_properties,
gpointer user_data) gpointer user_data)
{ {
GMainLoop *loop = user_data; gatt_connection_t* connection = user_data;
gattlib_context_t* conn_context = connection->context;
// Retrieve 'Value' from 'arg_changed_properties' // Retrieve 'Value' from 'arg_changed_properties'
if (g_variant_n_children (arg_changed_properties) > 0) { if (g_variant_n_children (arg_changed_properties) > 0) {
@ -231,8 +232,16 @@ gboolean on_handle_device_property_change(
g_variant_get (arg_changed_properties, "a{sv}", &iter); g_variant_get (arg_changed_properties, "a{sv}", &iter);
while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) { while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
if (strcmp(key, "UUIDs") == 0) { if (strcmp(key, "UUIDs") == 0) {
g_main_loop_quit(loop); // When UUIDs properties appear, we are connected to the device
g_main_loop_quit(conn_context->connection_loop);
break; break;
} else if (strcmp(key, "Connected") == 0) {
if (!g_variant_get_boolean(value)) {
// Disconnection case
if (connection->disconnection_handler) {
connection->disconnection_handler(connection->disconnection_user_data);
}
}
} }
} }
} }
@ -316,17 +325,19 @@ gatt_connection_t *gattlib_connect(const char *src, const char *dst,
// Wait for the property 'UUIDs' to be changed. We assume 'org.bluez.GattService1 // Wait for the property 'UUIDs' to be changed. We assume 'org.bluez.GattService1
// and 'org.bluez.GattCharacteristic1' to be advertised at that moment. // and 'org.bluez.GattCharacteristic1' to be advertised at that moment.
GMainLoop *loop = g_main_loop_new(NULL, 0); conn_context->connection_loop = g_main_loop_new(NULL, 0);
// Register a handle for notification // Register a handle for notification
g_signal_connect(device, g_signal_connect(device,
"g-properties-changed", "g-properties-changed",
G_CALLBACK (on_handle_device_property_change), G_CALLBACK (on_handle_device_property_change),
loop); connection);
g_timeout_add_seconds (CONNECT_TIMEOUT, stop_scan_func, loop); g_timeout_add_seconds (CONNECT_TIMEOUT, stop_scan_func, conn_context->connection_loop);
g_main_loop_run(loop); g_main_loop_run(conn_context->connection_loop);
g_main_loop_unref(loop); g_main_loop_unref(conn_context->connection_loop);
// Set the attribute to NULL even if not required
conn_context->connection_loop = NULL;
return connection; return connection;
@ -364,6 +375,11 @@ int gattlib_disconnect(gatt_connection_t* connection) {
return 0; return 0;
} }
void gattlib_register_on_disconnect(gatt_connection_t *connection, gattlib_disconnection_handler_t handler, void* user_data) {
connection->disconnection_handler = handler;
connection->disconnection_user_data = user_data;
}
// Bluez was using org.bluez.Device1.GattServices until 5.37 to expose the list of available GATT Services // Bluez was using org.bluez.Device1.GattServices until 5.37 to expose the list of available GATT Services
#if BLUEZ_VERSION < BLUEZ_VERSIONS(5, 38) #if BLUEZ_VERSION < BLUEZ_VERSIONS(5, 38)
int gattlib_discover_primary(gatt_connection_t* connection, gattlib_primary_service_t** services, int* services_count) { int gattlib_discover_primary(gatt_connection_t* connection, gattlib_primary_service_t** services, int* services_count) {

View File

@ -41,6 +41,10 @@
typedef struct { typedef struct {
char* device_object_path; char* device_object_path;
OrgBluezDevice1* device; OrgBluezDevice1* device;
// This attribute is only used during the connection stage. By placing the attribute here, we can pass
// `gatt_connection_t` to
GMainLoop *connection_loop;
} gattlib_context_t; } gattlib_context_t;
#endif #endif

View File

@ -69,6 +69,14 @@ typedef struct _GAttrib GAttrib;
typedef void (*gattlib_event_handler_t)(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data); typedef void (*gattlib_event_handler_t)(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data);
/**
* @brief Handler called on disconnection
*
* @param connection Connection that is disconnecting
* @param user_data Data defined when calling `gattlib_register_on_disconnect()`
*/
typedef void (*gattlib_disconnection_handler_t)(void* user_data);
typedef struct _gatt_connection_t { typedef struct _gatt_connection_t {
void* context; void* context;
@ -77,17 +85,19 @@ typedef struct _gatt_connection_t {
gattlib_event_handler_t indication_handler; gattlib_event_handler_t indication_handler;
void* indication_user_data; void* indication_user_data;
gattlib_disconnection_handler_t disconnection_handler;
void* disconnection_user_data;
} gatt_connection_t; } gatt_connection_t;
typedef void (*gattlib_discovered_device_t)(const char* addr, const char* name); typedef void (*gattlib_discovered_device_t)(const char* addr, const char* name);
typedef void (*gatt_connect_cb_t)(gatt_connection_t* connection, void* user_data); typedef void (*gatt_connect_cb_t)(gatt_connection_t* connection, void* user_data);
typedef void* (*gatt_read_cb_t)(const void* buffer, size_t buffer_len); typedef void* (*gatt_read_cb_t)(const void* buffer, size_t buffer_len);
/** /**
* Open Bluetooth adapter * @brief Open Bluetooth adapter
* *
* @adapter_name With value NULL, the default adapter will be selected. * @param adapter_name With value NULL, the default adapter will be selected.
*/ */
int gattlib_adapter_open(const char* adapter_name, void** adapter); int gattlib_adapter_open(const char* adapter_name, void** adapter);
int gattlib_adapter_scan_enable(void* adapter, gattlib_discovered_device_t discovered_device_cb, int timeout); int gattlib_adapter_scan_enable(void* adapter, gattlib_discovered_device_t discovered_device_cb, int timeout);
@ -111,6 +121,8 @@ gatt_connection_t *gattlib_connect_async(const char *src, const char *dst,
int gattlib_disconnect(gatt_connection_t* connection); int gattlib_disconnect(gatt_connection_t* connection);
void gattlib_register_on_disconnect(gatt_connection_t *connection, gattlib_disconnection_handler_t handler, void* user_data);
typedef struct { typedef struct {
uint16_t attr_handle_start; uint16_t attr_handle_start;
uint16_t attr_handle_end; uint16_t attr_handle_end;