From 4dde0c3698231546fc2827d1ba38731bdec8cce6 Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Wed, 15 Mar 2017 01:43:04 +0100 Subject: [PATCH] gattlib.h: Introduced gattlib_notification_(start|stop) --- bluez/gattlib_read_write.c | 26 ++++++++++++++ dbus/gattlib.c | 73 ++++++++++++++++++++++++++++++++++++-- gattlib_common.c | 10 ++++++ include/gattlib.h | 6 ++++ 4 files changed, 113 insertions(+), 2 deletions(-) diff --git a/bluez/gattlib_read_write.c b/bluez/gattlib_read_write.c index 3854908..62318f4 100644 --- a/bluez/gattlib_read_write.c +++ b/bluez/gattlib_read_write.c @@ -197,3 +197,29 @@ int gattlib_write_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, void return gattlib_write_char_by_handle(connection, handle, buffer, sizeof(buffer)); } + +int gattlib_notification_start(gatt_connection_t* connection, const uuid_t* uuid) { + uint16_t handle; + uint16_t enable_notification = 0x0001; + + int ret = get_handle_from_uuid(connection, uuid, &handle); + if (ret) { + return -1; + } + + // Enable Status Notification + return gattlib_write_char_by_handle(connection, handle + 1, &enable_notification, sizeof(enable_notification)); +} + +int gattlib_notification_stop(gatt_connection_t* connection, const uuid_t* uuid) { + uint16_t handle; + uint16_t enable_notification = 0x0000; + + int ret = get_handle_from_uuid(connection, uuid, &handle); + if (ret) { + return -1; + } + + // Enable Status Notification + return gattlib_write_char_by_handle(connection, handle + 1, &enable_notification, sizeof(enable_notification)); +} diff --git a/dbus/gattlib.c b/dbus/gattlib.c index ad580a8..76c6b39 100644 --- a/dbus/gattlib.c +++ b/dbus/gattlib.c @@ -848,8 +848,77 @@ int gattlib_write_char_by_handle(gatt_connection_t* connection, uint16_t handle, return -1; } -void gattlib_register_notification(gatt_connection_t* connection, gattlib_event_handler_t notification_handler, void* user_data) { +gboolean on_handle_characteristic_property_change( + OrgBluezGattCharacteristic1 *object, + GVariant *arg_changed_properties, + const gchar *const *arg_invalidated_properties, + gpointer user_data) +{ + gatt_connection_t* connection = user_data; + + if (connection->notification_handler) { + // Retrieve 'Value' from 'arg_changed_properties' + if (g_variant_n_children (arg_changed_properties) > 0) { + GVariantIter *iter; + const gchar *key; + GVariant *value; + + g_variant_get (arg_changed_properties, "a{sv}", &iter); + while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) { + if (strcmp(key, "Value") == 0) { + uuid_t uuid; + size_t data_length; + const uint8_t* data = g_variant_get_fixed_array(value, &data_length, sizeof(guchar)); + + gattlib_string_to_uuid( + org_bluez_gatt_characteristic1_get_uuid(object), + MAX_LEN_UUID_STR + 1, + &uuid); + + connection->notification_handler(&uuid, data, data_length, user_data); + break; + } + } + } + } + return TRUE; } -void gattlib_register_indication(gatt_connection_t* connection, gattlib_event_handler_t indication_handler, void* user_data) { +int gattlib_notification_start(gatt_connection_t* connection, const uuid_t* uuid) { + OrgBluezGattCharacteristic1 *characteristic = get_characteristic_from_uuid(uuid); + if (characteristic == NULL) { + return -1; + } + + // Register a handle for notification + g_signal_connect(characteristic, + "g-properties-changed", + G_CALLBACK (on_handle_characteristic_property_change), + connection); + + GError *error = NULL; + org_bluez_gatt_characteristic1_call_start_notify_sync(characteristic, NULL, &error); + + if (error) { + return 1; + } else { + return 0; + } +} + +int gattlib_notification_stop(gatt_connection_t* connection, const uuid_t* uuid) { + OrgBluezGattCharacteristic1 *characteristic = get_characteristic_from_uuid(uuid); + if (characteristic == NULL) { + return -1; + } + + GError *error = NULL; + org_bluez_gatt_characteristic1_call_stop_notify_sync( + characteristic, NULL, &error); + + if (error) { + return 1; + } else { + return 0; + } } diff --git a/gattlib_common.c b/gattlib_common.c index 0b38bb8..363191a 100644 --- a/gattlib_common.c +++ b/gattlib_common.c @@ -1,5 +1,15 @@ #include "gattlib_internal.h" +void gattlib_register_notification(gatt_connection_t* connection, gattlib_event_handler_t notification_handler, void* user_data) { + connection->notification_handler = notification_handler; + connection->notification_user_data = user_data; +} + +void gattlib_register_indication(gatt_connection_t* connection, gattlib_event_handler_t indication_handler, void* user_data) { + connection->indication_handler = indication_handler; + connection->indication_user_data = user_data; +} + void bt_uuid_to_uuid(bt_uuid_t* bt_uuid, uuid_t* uuid) { memcpy(&uuid->value, &bt_uuid->value, sizeof(uuid->value)); if (bt_uuid->type == BT_UUID16) { diff --git a/include/gattlib.h b/include/gattlib.h index 76cb698..bcb09a9 100644 --- a/include/gattlib.h +++ b/include/gattlib.h @@ -140,6 +140,12 @@ int gattlib_read_char_by_uuid_async(gatt_connection_t* connection, uuid_t* uuid, int gattlib_write_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, void* buffer, size_t buffer_len); int gattlib_write_char_by_handle(gatt_connection_t* connection, uint16_t handle, void* buffer, size_t buffer_len); +/* + * @param uuid UUID of the characteristic that will trigger the notification + */ +int gattlib_notification_start(gatt_connection_t* connection, const uuid_t* uuid); +int gattlib_notification_stop(gatt_connection_t* connection, const uuid_t* uuid); + void gattlib_register_notification(gatt_connection_t* connection, gattlib_event_handler_t notification_handler, void* user_data); void gattlib_register_indication(gatt_connection_t* connection, gattlib_event_handler_t indication_handler, void* user_data);