From 92d30a83d0610031da3f7e7e33adfd6c713dd427 Mon Sep 17 00:00:00 2001 From: Amit Purwar Date: Thu, 17 May 2018 19:47:51 +0530 Subject: [PATCH] gatt client adaptation feature changes bt-api bt-service OAL Change-Id: If19155c4dc6aaa6367094a02a346d949d29be183 Signed-off-by: Amit Purwar --- bt-api/CMakeLists.txt | 4 +- bt-api/bt-common.c | 23 + bt-api/bt-device.c | 20 +- bt-api/bt-event-handler.c | 318 ++- bt-api/bt-gatt-client.c | 745 +++++- bt-api/bt-request-sender.c | 62 +- bt-api/include/bt-common.h | 15 +- bt-oal/include/oal-event.h | 63 +- bt-oal/include/oal-gatt.h | 47 +- bt-oal/oal-gatt.c | 636 ++++- .../services/adapter/bt-service-core-adapter-le.c | 31 +- .../services/adapter/bt-service-core-adapter.c | 1 + .../services/bt-request-handler.c | 322 ++- bt-service-adaptation/services/bt-service-common.c | 22 + .../services/bt-service-event-receiver.c | 27 + .../services/bt-service-event-sender.c | 36 + .../services/device/bt-service-core-device.c | 330 +++ .../services/gatt/bt-service-gatt.c | 2710 +++++++++++++++++++- .../services/include/bt-service-common.h | 2 + .../services/include/bt-service-core-device.h | 7 + .../services/include/bt-service-gatt.h | 51 + include/bluetooth-api.h | 55 +- include/bluetooth-gatt-client-api.h | 188 ++ include/bt-internal-types.h | 39 +- packaging/bluetooth-frwk.spec | 2 + 25 files changed, 5615 insertions(+), 141 deletions(-) create mode 100644 include/bluetooth-gatt-client-api.h diff --git a/bt-api/CMakeLists.txt b/bt-api/CMakeLists.txt index 2025a05..9af5f98 100644 --- a/bt-api/CMakeLists.txt +++ b/bt-api/CMakeLists.txt @@ -40,7 +40,8 @@ bluetooth-telephony-api.h bluetooth-media-control.h bluetooth-scmst-api.h bluetooth-ipsp-api.h -bluetooth-gatt-server-api.h) +bluetooth-gatt-server-api.h +bluetooth-gatt-client-api.h) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(EXEC_PREFIX "\${prefix}") @@ -89,6 +90,7 @@ ENDIF("${ARCH}" STREQUAL "arm") #ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_HPS") ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_OTP") ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_DPM") +ADD_DEFINITIONS("-DTIZEN_GATT_CLIENT") FIND_PROGRAM(MARSHALTOOL NAMES glib-genmarshal) EXEC_PROGRAM("${MARSHALTOOL}" ARGS "--prefix=marshal ${CMAKE_CURRENT_SOURCE_DIR}/marshal.list --header > ${CMAKE_CURRENT_SOURCE_DIR}/include/marshal.h") diff --git a/bt-api/bt-common.c b/bt-api/bt-common.c index 40f7fd1..4b6468c 100644 --- a/bt-api/bt-common.c +++ b/bt-api/bt-common.c @@ -37,6 +37,10 @@ #include "bluetooth-gatt-server-api.h" #endif +#ifdef TIZEN_GATT_CLIENT +#include "bluetooth-gatt-client-api.h" +#endif + #include "bt-common.h" #include "bt-request-sender.h" #include "bt-event-handler.h" @@ -205,6 +209,25 @@ void _bt_avrcp_event_cb(int event, int result, void *param, user_data); } +#ifdef TIZEN_GATT_CLIENT +void _bt_gatt_client_event_cb(int event, int result, void *param, + void *callback, void *user_data) +{ + BT_DBG("__bt_gatt_client_event_cb"); + gatt_client_event_param_t bt_event = { 0, 0, NULL, NULL }; + bt_event.event = event; + bt_event.result = result; + bt_event.param_data = param; + if (callback) { + BT_DBG("GATT Client event callback is registered"); + ((gatt_client_cb_func_ptr)callback)(bt_event.event, &bt_event, + user_data); + } else { + BT_ERR("GATT Client event callback is not registered!!!"); + } +} +#endif + #ifndef GATT_DIRECT void _bt_gatt_server_event_cb(int event, int result, void *param, void *callback, void *user_data) diff --git a/bt-api/bt-device.c b/bt-api/bt-device.c index 815f8dc..fff273a 100644 --- a/bt-api/bt-device.c +++ b/bt-api/bt-device.c @@ -344,7 +344,12 @@ BT_EXPORT_API int bluetooth_is_device_connected(const bluetooth_device_address_t return result; } +#ifdef TIZEN_GATT_CLIENT +BT_EXPORT_API int bluetooth_connect_le(const bluetooth_device_address_t *device_address, + gboolean auto_connect, int client_id) +#else BT_EXPORT_API int bluetooth_connect_le(const bluetooth_device_address_t *device_address, gboolean auto_connect) +#endif { int result; bt_user_info_t *user_info; @@ -364,6 +369,10 @@ BT_EXPORT_API int bluetooth_connect_le(const bluetooth_device_address_t *device_ g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); g_array_append_vals(in_param2, &auto_connect, sizeof(gboolean)); +#ifdef TIZEN_GATT_CLIENT + g_array_append_vals(in_param3, &client_id, sizeof(int)); +#endif + user_info = _bt_get_user_data(BT_COMMON); retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); @@ -377,7 +386,12 @@ BT_EXPORT_API int bluetooth_connect_le(const bluetooth_device_address_t *device_ return result; } +#ifdef TIZEN_GATT_CLIENT +BT_EXPORT_API int bluetooth_disconnect_le(const bluetooth_device_address_t *device_address, + int client_id) +#else BT_EXPORT_API int bluetooth_disconnect_le(const bluetooth_device_address_t *device_address) +#endif { int result; bt_user_info_t *user_info; @@ -386,7 +400,7 @@ BT_EXPORT_API int bluetooth_disconnect_le(const bluetooth_device_address_t *devi BT_CHECK_ENABLED_ANY(return); if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_DISCONNECT_LE) - == BLUETOOTH_ERROR_PERMISSION_DEINED) { + == BLUETOOTH_ERROR_PERMISSION_DEINED) { BT_ERR("Don't have a privilege to use this API"); return BLUETOOTH_ERROR_PERMISSION_DEINED; } @@ -395,6 +409,10 @@ BT_EXPORT_API int bluetooth_disconnect_le(const bluetooth_device_address_t *devi BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); +#ifdef TIZEN_GATT_CLIENT + BT_INFO("Send GATT disconnect using Client Interface [%d]", client_id); + g_array_append_vals(in_param2, &client_id, sizeof(int)); +#endif user_info = _bt_get_user_data(BT_COMMON); retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); diff --git a/bt-api/bt-event-handler.c b/bt-api/bt-event-handler.c index 776a309..8a1cf2d 100644 --- a/bt-api/bt-event-handler.c +++ b/bt-api/bt-event-handler.c @@ -773,7 +773,52 @@ void __bt_device_event_filter(GDBusConnection *connection, #endif ret_if(signal_name == NULL); +#ifdef TIZEN_GATT_CLIENT + if (strcasecmp(signal_name, BT_GATT_SERVER_CONNECTED) == 0) { + const char *address = NULL; + bluetooth_device_address_t dev_address = { {0} }; + BT_DBG("BT_GATT_SERVER_CONNECTED"); + g_variant_get(parameters, "(i&s)", &result, &address); + + _bt_convert_addr_string_to_type(dev_address.addr, address); + BT_DBG("Sending Event to Framework"); + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_CONNECTED, + result, &dev_address, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_GATT_SERVER_DISCONNECTED) == 0) { + const char *address = NULL; + bluetooth_device_address_t dev_address = { {0} }; + BT_DBG("BT_GATT_SERVER_DISCONNECTED"); + g_variant_get(parameters, "(i&s)", &result, &address); + + _bt_convert_addr_string_to_type(dev_address.addr, address); + BT_DBG("Sending Event to Framework"); + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_DISCONNECTED, + result, &dev_address, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_GATT_CLIENT_CONNECTED) == 0) { + const char *address = NULL; + bluetooth_device_address_t dev_address = { {0} }; + BT_DBG("BT_GATT_CLIENT_CONNECTED"); + g_variant_get(parameters, "(i&s)", &result, &address); + _bt_convert_addr_string_to_type(dev_address.addr, address); + BT_DBG("Sending Event to Framework"); + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CLIENT_CONNECTED, + result, &dev_address, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_GATT_CLIENT_DISCONNECTED) == 0) { + const char *address = NULL; + bluetooth_device_address_t dev_address = { {0} }; + BT_DBG("BT_GATT_CLIENT_DISCONNECTED"); + g_variant_get(parameters, "(i&s)", &result, &address); + + _bt_convert_addr_string_to_type(dev_address.addr, address); + BT_DBG("Sending Event to Framework"); + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CLIENT_DISCONNECTED, + result, &dev_address, + event_info->cb, event_info->user_data); +#else if (strcasecmp(signal_name, BT_GATT_CONNECTED) == 0) { const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; @@ -796,6 +841,7 @@ void __bt_device_event_filter(GDBusConnection *connection, _bt_common_event_cb(BLUETOOTH_EVENT_GATT_DISCONNECTED, result, &dev_address, event_info->cb, event_info->user_data); +#endif } else if (strcasecmp(signal_name, BT_GATT_REQ_ATT_MTU_CHANGED) == 0) { const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; @@ -3409,6 +3455,266 @@ static void __bt_event_data_free(void *data) g_free(cb_data); } +#ifdef TIZEN_GATT_CLIENT +static void __bt_gatt_client_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + BT_DBG("GATT Client event handler Entry >>"); + + bt_event_info_t *event_info; + int result = BLUETOOTH_ERROR_NONE; + + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); + + if (strcasecmp(signal_name, BT_GATT_CHAR_VAL_CHANGED) == 0) { /* Done */ + /* Event: BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED */ + BT_INFO("GATT Client event[BT_GATT_CHAR_VAL_CHANGED]"); + bt_gatt_char_property_t char_prop; + const char *address = NULL; + GVariant *data_var = NULL; + GVariant *svc_uuid_var = NULL; + int svc_inst; + GVariant *char_uuid_var = NULL; + int svc_uuid_len = 0; + int char_uuid_len = 0; + unsigned int i; + + memset(&char_prop, 0x00, sizeof(bt_gatt_char_property_t)); + + /* Extract data from DBUS params */ + g_variant_get(parameters, "(i&sn@ayin@ayin@ay)", + &result, + &address, + &svc_uuid_len, + &svc_uuid_var, + &svc_inst, + &char_uuid_len, + &char_uuid_var, + &char_prop.prop.instance_id, + &char_prop.val_len, + &data_var); + g_strlcpy(char_prop.address, address, BT_ADDRESS_STRING_SIZE); + + BT_INFO("GATT Client Char value changed in remote Server [%s]", address); + BT_INFO("GATT Client Char Val len: [%d]", char_prop.val_len); + + /* Copy Data */ + memcpy(&char_prop.value, g_variant_get_data(data_var), char_prop.val_len); + memcpy(&char_prop.prop.uuid, g_variant_get_data(char_uuid_var), 16); + + /* DEBUG */ + for (i = 0; i < char_prop.val_len; i++) + BT_INFO("Data[%d] = [0x%x]", i, char_prop.value[i]); + + _bt_gatt_client_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED, + result, &char_prop, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_GATT_CLIENT_READ_CHAR) == 0) { /* Done */ + /* Event: BLUETOOTH_EVENT_GATT_READ_CHAR */ + BT_INFO("GATT Client event[BT_GATT_CLIENT_READ_CHAR]"); + bt_gatt_char_property_t char_prop; + const char *address = NULL; + GVariant *data_var = NULL; + GVariant *svc_uuid_var = NULL; + int svc_inst = 0; + GVariant *char_uuid_var = NULL; + int svc_uuid_len = 0; + int char_uuid_len = 0; + unsigned int i; + + memset(&char_prop, 0x00, sizeof(bt_gatt_char_property_t)); + + /* Extract data from DBUS params */ + g_variant_get(parameters, "(i&sn@ayin@ayin@ay)", + &result, + &address, + &svc_uuid_len, + &svc_uuid_var, + &svc_inst, + &char_uuid_len, + &char_uuid_var, + &char_prop.prop.instance_id, + &char_prop.val_len, + &data_var); + g_strlcpy(char_prop.address, address, BT_ADDRESS_STRING_SIZE); + + BT_INFO("GATT Client Read Callback from [%s] svc inst [%d] char val len [%d] char inst [%d]", + address, svc_inst, char_prop.val_len, char_prop.prop.instance_id); + + /* Copy Data */ + memcpy(&char_prop.value, g_variant_get_data(data_var), char_prop.val_len); + memcpy(&char_prop.prop.uuid, g_variant_get_data(char_uuid_var), 16); + + /* Copy Svc Data */ + memcpy(&char_prop.svc_prop.uuid, g_variant_get_data(svc_uuid_var), 16); + char_prop.svc_prop.instance_id = svc_inst; + + /* DEBUG */ + for (i = 0; i < char_prop.val_len; i++) + BT_INFO("Data[%d] = [0x%x]", i, char_prop.value[i]); + + + _bt_gatt_client_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR, + result, &char_prop, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_GATT_CLIENT_WRITE_CHAR) == 0) { /* Done */ + /* Event: BLUETOOTH_EVENT_GATT_WRITE_CHAR */ + BT_INFO("GATT Client event[BT_GATT_CLIENT_WRITE_CHAR]"); + bt_gatt_char_property_t char_prop; + const char *address = NULL; + GVariant *svc_uuid_var = NULL; + int svc_inst = 0; + GVariant *char_uuid_var = NULL; + int svc_uuid_len = 0; + int char_uuid_len = 0; + + memset(&char_prop, 0x00, sizeof(bt_gatt_char_property_t)); + + /* Extract data from DBUS params */ + g_variant_get(parameters, "(i&sn@ayin@ayi)", + &result, + &address, + &svc_uuid_len, + &svc_uuid_var, + &svc_inst, + &char_uuid_len, + &char_uuid_var, + &char_prop.prop.instance_id); + + g_strlcpy(char_prop.address, address, BT_ADDRESS_STRING_SIZE); + + BT_DBG("GATT Client Char Write Done in remote Server [%s]", address); + + /* Copy Data */ + memcpy(&char_prop.prop.uuid, g_variant_get_data(char_uuid_var), 16); + + /* Copy Svc Data */ + memcpy(&char_prop.svc_prop.uuid, g_variant_get_data(svc_uuid_var), 16); + char_prop.svc_prop.instance_id = svc_inst; + + _bt_gatt_client_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR, + result, &char_prop, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_GATT_CLIENT_READ_DESC) == 0) { /* Done */ + /* Event: BLUETOOTH_EVENT_GATT_READ_DESC */ + BT_INFO("GATT Client event[BT_GATT_CLIENT_READ_DESC]"); + bt_gatt_char_descriptor_property_t desc_prop; + const char *address = NULL; + GVariant *data_var = NULL; + GVariant *svc_uuid_var = NULL; + int svc_inst = 0; + GVariant *char_uuid_var = NULL; + int char_inst = 0; + GVariant *desc_uuid_var = NULL; + int svc_uuid_len = 0; + int char_uuid_len = 0; + int desc_uuid_len = 0; + unsigned int i; + + memset(&desc_prop, 0x00, sizeof(bt_gatt_char_descriptor_property_t)); + + /* Extract data from DBUS params */ + g_variant_get(parameters, "(i&sn@ayin@ayin@ayin@ay)", + &result, + &address, + &svc_uuid_len, + &svc_uuid_var, + &svc_inst, + &char_uuid_len, + &char_uuid_var, + &char_inst, + &desc_uuid_len, + &desc_uuid_var, + &desc_prop.prop.instance_id, + &desc_prop.val_len, + &data_var); + g_strlcpy(desc_prop.address, address, BT_ADDRESS_STRING_SIZE); + + BT_DBG("GATT Client Read Descriptor Callback from [%s]", address); + BT_DBG("GATT Client Descriptor Val len: [%d]", desc_prop.val_len); + + /* Copy Data */ + memcpy(&desc_prop.value, g_variant_get_data(data_var), desc_prop.val_len); + memcpy(&desc_prop.prop.uuid, g_variant_get_data(desc_uuid_var), 16); + + /* Copy Char Data */ + memcpy(&desc_prop.char_prop.uuid, g_variant_get_data(char_uuid_var), 16); + desc_prop.char_prop.instance_id = char_inst; + + /* Copy Svc Data */ + memcpy(&desc_prop.svc_prop.uuid, g_variant_get_data(svc_uuid_var), 16); + desc_prop.svc_prop.instance_id = svc_inst; + + /* DEBUG */ + for (i = 0; i < desc_prop.val_len; i++) + BT_INFO("Data[%d] = [0x%x]", i, desc_prop.value[i]); + + _bt_gatt_client_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC, + result, &desc_prop, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_GATT_CLIENT_WRITE_DESC) == 0) { /* Done */ + /* Event: BLUETOOTH_EVENT_GATT_WRITE_DESC */ + BT_INFO("GATT Client event[BT_GATT_CLIENT_WRITE_DESC]"); + bt_gatt_char_descriptor_property_t desc_prop; + const char *address = NULL; + GVariant *svc_uuid_var = NULL; + int svc_inst = 0; + GVariant *char_uuid_var = NULL; + int char_inst; + GVariant *desc_uuid_var = NULL; + int svc_uuid_len = 0; + int char_uuid_len = 0; + int desc_uuid_len = 0; + + memset(&desc_prop, 0x00, sizeof(bt_gatt_char_descriptor_property_t)); + + /* Extract data from DBUS params */ + g_variant_get(parameters, "(i&sn@ayin@ayin@ayi)", + &result, + &address, + &svc_uuid_len, + &svc_uuid_var, + &svc_inst, + &char_uuid_len, + &char_uuid_var, + &char_inst, + &desc_uuid_len, + &desc_uuid_var, + &desc_prop.prop.instance_id); + + g_strlcpy(desc_prop.address, address, BT_ADDRESS_STRING_SIZE); + + BT_INFO("GATT Client Write Descriptor Callback from [%s]", address); + BT_INFO("GATT Client Descriptor Val len: [%d]", desc_prop.val_len); + + /* Copy Data */ + memcpy(&desc_prop.prop.uuid, g_variant_get_data(desc_uuid_var), 16); + + /* Copy Char Data */ + memcpy(&desc_prop.char_prop.uuid, g_variant_get_data(char_uuid_var), 16); + desc_prop.char_prop.instance_id = char_inst; + + /* Copy Svc Data */ + memcpy(&desc_prop.svc_prop.uuid, g_variant_get_data(svc_uuid_var), 16); + desc_prop.svc_prop.instance_id = svc_inst; + + _bt_gatt_client_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC, + result, &desc_prop, + event_info->cb, event_info->user_data); + } + + BT_DBG("GATT Client event handler Exit <<"); +} + +#endif + + #ifndef GATT_DIRECT static void __bt_gatt_server_event_filter(GDBusConnection *connection, const gchar *sender_name, @@ -3425,7 +3731,9 @@ static void __bt_gatt_server_event_filter(GDBusConnection *connection, event_info = (bt_event_info_t *)user_data; ret_if(event_info == NULL); - +#ifdef TIZEN_GATT_CLIENT + if (strcasecmp(signal_name, BT_GATT_VALUE_CHANGED) == 0) { +#else if (strcasecmp(signal_name, BT_GATT_CONNECTED) == 0) { const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; @@ -3447,6 +3755,7 @@ static void __bt_gatt_server_event_filter(GDBusConnection *connection, result, &dev_address, event_info->cb, event_info->user_data); } else if (strcasecmp(signal_name, BT_GATT_VALUE_CHANGED) == 0) { +#endif BT_INFO("GATT Server event[BT_GATT_SERVER_WRITE_REQUESTED]"); const char *address = NULL; GVariant *data_var = NULL; @@ -3690,6 +3999,13 @@ int _bt_register_event(int event_type, void *event_cb, void *user_data) path = BT_GATT_SERVER_PATH; break; #endif + +#ifdef TIZEN_GATT_CLIENT + case BT_GATT_CLIENT_EVENT: + event_func = __bt_gatt_client_event_filter; + path = BT_GATT_CLIENT_PATH; + break; +#endif default: BT_ERR("Unknown event"); return BLUETOOTH_ERROR_INTERNAL; diff --git a/bt-api/bt-gatt-client.c b/bt-api/bt-gatt-client.c index 21c7298..9214c7f 100755 --- a/bt-api/bt-gatt-client.c +++ b/bt-api/bt-gatt-client.c @@ -28,6 +28,11 @@ #include "bt-internal-types.h" #include "bt-request-sender.h" +#ifdef TIZEN_GATT_CLIENT +#include "bluetooth-gatt-client-api.h" +#include +#endif + #define GATT_DEFAULT_TIMEOUT (6 * 1000) // Dependent on supervision timeout 6 sec typedef enum { @@ -42,44 +47,61 @@ static GSList *service_monitor_list = NULL; BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty) { + BT_DBG("+"); + BT_CHECK_PARAMETER(svc_pty, return); +#ifdef TIZEN_GATT_CLIENT + g_free(svc_pty->uuid); +#else g_free(svc_pty->uuid); g_free(svc_pty->handle); g_strfreev(svc_pty->include_handles.handle); g_strfreev(svc_pty->char_handle.handle); +#endif memset(svc_pty, 0, sizeof(bt_gatt_service_property_t)); + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty) { + BT_DBG("+"); + BT_CHECK_PARAMETER(char_pty, return); g_free(char_pty->uuid); g_free(char_pty->name); g_free(char_pty->description); g_free(char_pty->val); +#ifndef TIZEN_GATT_CLIENT g_free(char_pty->handle); g_strfreev(char_pty->char_desc_handle.handle); +#endif memset(char_pty, 0, sizeof(bt_gatt_char_property_t)); + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty) { + BT_DBG("+"); + BT_CHECK_PARAMETER(desc_pty, return); g_free(desc_pty->uuid); g_free(desc_pty->val); +#ifndef TIZEN_GATT_CLIENT g_free(desc_pty->handle); +#endif memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t)); + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } @@ -107,10 +129,26 @@ gboolean _bluetooth_gatt_check_service_change_watcher_address( const bluetooth_device_address_t *device_addr) { GSList *l; + char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + _bt_convert_addr_type_to_string(device_address, + (unsigned char *)device_addr->addr); for (l = service_monitor_list; l != NULL; l = l->next) { + char device_address2[BT_ADDRESS_STRING_SIZE] = { 0 }; + char secure_address2[BT_ADDRESS_STRING_SIZE] = { 0 }; bluetooth_device_address_t *addr = l->data; + _bt_convert_addr_type_to_string(device_address2, + (unsigned char *)addr->addr); + _bt_convert_addr_string_to_secure_string(secure_address, + device_address); + _bt_convert_addr_string_to_secure_string(secure_address2, + device_address2); + BT_INFO("service_monitor_list [%s] - Input [%s]", + secure_address2, secure_address); + if (!memcmp(device_addr, addr, sizeof(bluetooth_device_address_t))) return TRUE; @@ -287,7 +325,7 @@ BT_EXPORT_API int bluetooth_gatt_get_primary_services( int ret = BLUETOOTH_ERROR_INTERNAL; int idx = 0; - BT_DBG("+"); + BT_INFO("+"); BT_CHECK_PARAMETER(address, return); BT_CHECK_PARAMETER(prim_svc, return); BT_CHECK_ENABLED(return); @@ -523,6 +561,8 @@ static int __get_permission_flag(char *permission) retv_if(permission == NULL, ret); + BT_INFO("permission = %s", permission); + if (!g_strcmp0(permission, "broadcast")) ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST; else if (!g_strcmp0(permission, "read")) @@ -608,6 +648,7 @@ BT_EXPORT_API int bluetooth_gatt_get_characteristics_property( GVariantIter *char_perm_iter; GVariantIter *char_desc_iter; + BT_DBG("+"); BT_CHECK_PARAMETER(char_handle, return); BT_CHECK_PARAMETER(characteristic, return); @@ -700,6 +741,7 @@ BT_EXPORT_API int bluetooth_gatt_get_characteristics_property( g_variant_unref(result); g_object_unref(properties_proxy); + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } @@ -819,6 +861,7 @@ BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property( GByteArray *gb_array = NULL; GVariantIter *desc_value_iter; + BT_INFO("+"); BT_CHECK_PARAMETER(descriptor_handle, return); BT_CHECK_PARAMETER(descriptor, return); @@ -889,6 +932,7 @@ BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property( g_variant_unref(result); g_object_unref(properties_proxy); + BT_INFO("-"); return BLUETOOTH_ERROR_NONE; } @@ -928,6 +972,9 @@ static int __bluetooth_get_att_error_code(GError *error) case BLUETOOTH_ATT_ERROR_AUTHORIZATION: BT_ERR("Operation not Authorized"); break; + default: + BT_ERR("default ecode"); + break; } if (att_ecode >= 0x80 && att_ecode <= 0x9F) @@ -1759,3 +1806,699 @@ BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle return ret; } + +#ifdef TIZEN_GATT_CLIENT +void __bt_uuid_hex_to_string(unsigned char *uuid, char *str) +{ + uint32_t uuid0, uuid4; + uint16_t uuid1, uuid2, uuid3, uuid5; + + memcpy(&uuid0, &(uuid[0]), 4); + memcpy(&uuid1, &(uuid[4]), 2); + memcpy(&uuid2, &(uuid[6]), 2); + memcpy(&uuid3, &(uuid[8]), 2); + memcpy(&uuid4, &(uuid[10]), 4); + memcpy(&uuid5, &(uuid[14]), 2); + + snprintf((char *)str, BLUETOOTH_UUID_STRING_MAX, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", + ntohl(uuid0), ntohs(uuid1), + ntohs(uuid2), ntohs(uuid3), + ntohl(uuid4), ntohs(uuid5)); + return; +} + + +static void __bt_fill_service_handle_informations(bt_services_browse_info_t *props, + bt_gatt_handle_info_t *svcs) +{ + int count; + BT_INFO("Total services found [%d]", props->count); + + if (props->count == 0) + return; + + svcs->count = props->count; + + for (count = 0; count < props->count; count++) { + BT_INFO("UUID[%d] = [%s] instance_id [%d] Is Primary [%d]", + count, props->uuids[count], props->inst_id[count], props->primary[count]); + g_strlcpy(svcs->uuids[count], props->uuids[count], + BLUETOOTH_UUID_STRING_MAX); + svcs->inst_id[count] = props->inst_id[count]; + } +} + +static void __bt_fill_char_handle_informations(bt_char_browse_info_t *props, + bt_gatt_service_property_t *service) +{ + int count; + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + BT_INFO("Total number of characteristics found [%d]", + props->count); + + service->char_handle.count = props->count; + + /* Before filling all char handles, fill the service's UUID and instance ID */ + __bt_uuid_hex_to_string(props->svc_uuid, uuid_string); + service->uuid = g_strdup(uuid_string); + service->primary = TRUE; + + /* Now fill all the char handles [UUID and Instance ID's]*/ + for (count = 0; count < props->count; count++) { + BT_INFO("UUID[%d] = [%s] instance_id [%d] properties [%d]", + count, props->uuids[count], props->inst_id[count], props->props[count]); + + g_strlcpy(service->char_handle.uuids[count], + props->uuids[count], + BLUETOOTH_UUID_STRING_MAX); + + service->char_handle.inst_id[count] = props->inst_id[count]; + } +} + +static void __bt_fill_desc_handle_informations(bt_descriptor_browse_info_t *props, + bt_gatt_char_property_t *charc) +{ + int count; + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + BT_INFO("Total descriptor count found [%d]", props->count); + + charc->char_desc_handle.count = props->count; + + /* Before filling all desc handles, fill the charac's UUID and instance ID */ + __bt_uuid_hex_to_string(props->char_uuid, uuid_string); + charc->uuid = g_strdup(uuid_string); + + /* Now fill all the descriptor handles [UUID and Instance ID's]*/ + for (count = 0; count < props->count; count++) { + BT_INFO("UUID[%d] = [%s] instance_id [%d]", + count, props->uuids[count], props->inst_id[count]); + + g_strlcpy(charc->char_desc_handle.uuids[count], + props->uuids[count], + BLUETOOTH_UUID_STRING_MAX); + + charc->char_desc_handle.inst_id[count] = props->inst_id[count]; + } + charc->permission = props->char_props_map; + BT_INFO("Characteritic property map val [%d]", charc->permission); +} + + +BT_EXPORT_API int bluetooth_gatt_client_init( + int *client_id, + const bluetooth_device_address_t *address, + gatt_client_cb_func_ptr callback_ptr) +{ + int ret = BLUETOOTH_ERROR_NONE; + bt_event_info_t *event_info; + int *count; + + BT_CHECK_PARAMETER(client_id, return); + BT_CHECK_PARAMETER(callback_ptr, return); + BT_CHECK_ENABLED(return); + + BT_INFO("+"); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t)); + + ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_REGISTER, + in_param1, in_param2, in_param3, in_param4, &out_param); + + /* App ID -1 is invalid */ + if (ret == BLUETOOTH_ERROR_NONE) { + + *client_id = g_array_index(out_param, int, 0); + + BT_INFO("GATT Client Registered successfully: Client instance ID [%d]", *client_id); + + event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT); + + if (event_info) { + count = (int*)event_info->user_data; + + BT_INFO("Total num of GATT client instances [%d]", *count); + + /* Increement the count */ + *count += 1; + } else { + BT_INFO("No GATT Client instances found in this application: Set User data"); + count = g_malloc0(sizeof(int)); + *count = 1; + + /* Register event handler for GATT */ + _bt_register_event(BT_GATT_CLIENT_EVENT, + (void *)callback_ptr, + (void *)count); + _bt_set_user_data(BT_GATT_CLIENT, (void *)callback_ptr, NULL); + } + } else + BT_ERR("GATT Client Registration failed!! ret [%d]", ret); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + return ret; +} + + + +/* GATT Client*/ +BT_EXPORT_API int bluetooth_gatt_client_get_primary_services( + const bluetooth_device_address_t *address, /* Remote GATT Server */ + bt_gatt_handle_info_t *prim_svc) /* UUID & instance_id */ +{ + + int result = BLUETOOTH_ERROR_NONE; + bt_services_browse_info_t service_props; + + BT_DBG("+"); + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(prim_svc, return); + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, + BT_GATT_GET_PRIMARY_SERVICES, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (BLUETOOTH_ERROR_NONE != result) + goto done; + + memset(&service_props, 0x00, sizeof(bt_services_browse_info_t)); + + service_props = g_array_index( + out_param, bt_services_browse_info_t, 0); + + __bt_fill_service_handle_informations( + &service_props, prim_svc); + +done: + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + BT_DBG("result = %d", result); + return result; +} + +BT_EXPORT_API int bluetooth_gatt_client_get_service_property( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_service_property_t *service) +{ + int result = BLUETOOTH_ERROR_NONE; + bluetooth_gatt_client_svc_prop_info_t svc_prop; + bt_char_browse_info_t char_handles_info; + BT_INFO("Remote Address [%s]", address); + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(service, return); + BT_CHECK_ENABLED(return); + + /* Call to bt-service (sync) and send address and service_handle info */ + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + memset(&svc_prop, 0x00, sizeof(bluetooth_gatt_client_svc_prop_info_t)); + /* All characteristics handles are discovered */ + memset(&char_handles_info, 0x00, sizeof(bt_char_browse_info_t)); + + svc_prop.svc.instance_id = service_handle->instance_id; + memcpy(&svc_prop.svc.uuid, &service_handle->uuid, 16); + + _bt_convert_addr_string_to_type(svc_prop.device_address.addr, address); + + g_array_append_vals(in_param1, &svc_prop, sizeof(bluetooth_gatt_client_svc_prop_info_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, + BT_GATT_GET_SERVICE_PROPERTIES, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (BLUETOOTH_ERROR_NONE != result) + goto done; + + char_handles_info = g_array_index( + out_param, bt_char_browse_info_t, 0); + __bt_fill_char_handle_informations(&char_handles_info, + service); + /* TODO Get all Included Services */ + +done: + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + BT_INFO("result = %d", result); + return result; +} + +BT_EXPORT_API int bluetooth_gatt_client_get_characteristics_property( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + bt_gatt_char_property_t *char_property) +{ + int result = BLUETOOTH_ERROR_NONE; + bt_descriptor_browse_info_t desc_handles_info; + bluetooth_gatt_client_char_prop_info_t char_prop; + BT_INFO("Get Properties of characteristics from remote device [%s]", address); + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(char_property, return); + BT_CHECK_ENABLED(return); + + + /* Call to bt-service (sync) and send address service_handle info & char handle info */ + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + memset(&char_prop, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t)); + char_prop.svc.instance_id = service_handle->instance_id; + memcpy(&char_prop.svc.uuid, &service_handle->uuid, 16); + + char_prop.characteristic.instance_id = char_handle->instance_id; + memcpy(&char_prop.characteristic.uuid, &char_handle->uuid, 16); + + _bt_convert_addr_string_to_type(char_prop.device_address.addr, address); + + g_array_append_vals(in_param1, &char_prop, sizeof(bluetooth_gatt_client_char_prop_info_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, + BT_GATT_GET_CHARACTERISTIC_PROPERTIES, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_INFO("result = [%d]", result); + if (BLUETOOTH_ERROR_NONE != result) + goto done; + + /* All descriptors handles are discovered */ + memset(&desc_handles_info, 0x00, sizeof(bt_descriptor_browse_info_t)); + + desc_handles_info = g_array_index( + out_param, bt_descriptor_browse_info_t, 0); + + __bt_fill_desc_handle_informations(&desc_handles_info, + char_property); + +done: + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + BT_INFO("result = %d", result); + return result; + /* Call to bt-service (sync) and send address, service_handle & char_handle infos */ + + /* After result is fetched, extract descriptor handles (UUID's & instance_id's) */ + + /* Fill the info in *char_prop */ + + /*No: Before returning, call bluetooth_gatt_client_read_characteristic_value as + an asyn function and leave every thing else in the callback */ +} + +BT_EXPORT_API int bluetooth_gatt_client_get_char_descriptor_property( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + bt_gatt_handle_property_t *descriptor_handle, + bt_gatt_char_descriptor_property_t *desc_prop) +{ + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + BT_DBG("Remote Address [%s]", address); + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(descriptor_handle, return); + BT_CHECK_PARAMETER(desc_prop, return); + /* No Need to Call to bt-service (sync) and send address, service_handle, + char_handle & descriptor handle infos */ + /* After result is fetched, extract descriptior handles (UUID's & instance_id's) */ + /* Fill the info in *desc_prop */ + __bt_uuid_hex_to_string(descriptor_handle->uuid, uuid_string); + + /* Before filling all desc handles, fill the charac's UUID and instance ID */ + desc_prop->uuid = g_strdup(uuid_string); + + return BLUETOOTH_ERROR_NONE; + /* No: Before returning, call bluetooth_gatt_client_read_descriptor_value + as an asyn function and leave every thing else in the callback */ +} + +BT_EXPORT_API int bluetooth_gatt_client_watch_characteristics( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + int client_id, + gboolean is_notify) +{ + int result = BLUETOOTH_ERROR_NONE; + bluetooth_gatt_client_char_prop_info_t param; + BT_DBG("+"); + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(char_handle, return); + + /* ASync Function, result expected in callback from bt-service */ + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + BT_INFO("Address [%s]", address); + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t)); + + memcpy(¶m.svc.uuid, service_handle->uuid, 16); + param.svc.instance_id = service_handle->instance_id; + + memcpy(¶m.characteristic.uuid, char_handle->uuid, 16); + param.characteristic.instance_id = char_handle->instance_id; + + _bt_convert_addr_string_to_type(param.device_address.addr, address); + + g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_char_prop_info_t)); + g_array_append_vals(in_param2, &client_id, sizeof(int)); + g_array_append_vals(in_param3, &is_notify, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, + BT_GATT_WATCH_CHARACTERISTIC, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + BT_INFO("Result [%d]", result); + return result; +} + +BT_EXPORT_API int bluetooth_gatt_client_read_characteristic_value( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle) +{ + int result = BLUETOOTH_ERROR_NONE; + bt_user_info_t *user_info; + bluetooth_gatt_client_char_prop_info_t param; + BT_DBG("+"); + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(char_handle, return); + + user_info = _bt_get_user_data(BT_GATT_CLIENT); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + /* Async Function, result expected in callback from bt-service */ + /* Call to bt-service (sync) and send address service_handle info & char handle info */ + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t)); + + memcpy(¶m.svc.uuid, service_handle->uuid, 16); + param.svc.instance_id = service_handle->instance_id; + + memcpy(¶m.characteristic.uuid, char_handle->uuid, 16); + param.characteristic.instance_id = char_handle->instance_id; + + _bt_convert_addr_string_to_type(param.device_address.addr, address); + + g_array_append_vals(in_param1, ¶m, + sizeof(bluetooth_gatt_client_char_prop_info_t)); + + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC, + in_param1, in_param2, in_param3, in_param4, + user_info->cb, user_info->user_data); + + + BT_INFO("result = [%d]", result); + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + return result; +} + +BT_EXPORT_API int bluetooth_gatt_client_read_descriptor_value( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + bt_gatt_handle_property_t *descriptor_handle) +{ + int result = BLUETOOTH_ERROR_NONE; + bt_user_info_t *user_info; + bluetooth_gatt_client_desc_prop_info_t param; + BT_DBG("+"); + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(descriptor_handle, return); + + user_info = _bt_get_user_data(BT_GATT_CLIENT); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + /* Async Function, result expected in callback from bt-service */ + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t)); + + memcpy(¶m.svc.uuid, service_handle->uuid, 16); + param.svc.instance_id = service_handle->instance_id; + + memcpy(¶m.characteristic.uuid, char_handle->uuid, 16); + param.characteristic.instance_id = char_handle->instance_id; + + memcpy(¶m.descriptor.uuid, descriptor_handle->uuid, 16); + param.descriptor.instance_id = descriptor_handle->instance_id; + + _bt_convert_addr_string_to_type(param.device_address.addr, address); + + g_array_append_vals(in_param1, ¶m, + sizeof(bluetooth_gatt_client_desc_prop_info_t)); + + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_DESCRIPTOR_VALUE, + in_param1, in_param2, in_param3, in_param4, + user_info->cb, user_info->user_data); + + BT_INFO("result = [%d]", result); + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + return result; +} + +BT_EXPORT_API int bluetooth_gatt_client_write_characteristic_value_by_type( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + bluetooth_gatt_att_data_t *data, + bluetooth_gatt_write_type_e write_type) +{ + int result = BLUETOOTH_ERROR_NONE; + bt_user_info_t *user_info; + bluetooth_gatt_client_char_prop_info_t param; + BT_DBG("+"); + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(data, return); + + /* ASync Function, result expected in callback from bt-service */ + user_info = _bt_get_user_data(BT_GATT_CLIENT); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t)); + + memcpy(¶m.svc.uuid, service_handle->uuid, 16); + param.svc.instance_id = service_handle->instance_id; + + memcpy(¶m.characteristic.uuid, char_handle->uuid, 16); + param.characteristic.instance_id = char_handle->instance_id; + + _bt_convert_addr_string_to_type(param.device_address.addr, address); + + g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_char_prop_info_t)); + g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t)); + g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, + BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE, + in_param1, in_param2, in_param3, in_param4, + user_info->cb, user_info->user_data); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_gatt_client_write_descriptor_value( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + bt_gatt_handle_property_t *descriptor_handle, + bluetooth_gatt_att_data_t *data, + bluetooth_gatt_write_type_e write_type) +{ + int result = BLUETOOTH_ERROR_NONE; + bt_user_info_t *user_info; + bluetooth_gatt_client_desc_prop_info_t param; + BT_DBG("+"); + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(descriptor_handle, return); + BT_CHECK_PARAMETER(data, return); + + /* Async Function, result expected in callback from bt-service */ + user_info = _bt_get_user_data(BT_GATT_CLIENT); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t)); + + memcpy(¶m.svc.uuid, service_handle->uuid, 16); + param.svc.instance_id = service_handle->instance_id; + + memcpy(¶m.characteristic.uuid, char_handle->uuid, 16); + param.characteristic.instance_id = char_handle->instance_id; + + memcpy(¶m.descriptor.uuid, descriptor_handle->uuid, 16); + param.descriptor.instance_id = descriptor_handle->instance_id; + + _bt_convert_addr_string_to_type(param.device_address.addr, address); + + g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_desc_prop_info_t)); + g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t)); + g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, + BT_GATT_WRITE_DESCRIPTOR_VALUE, + in_param1, in_param2, in_param3, in_param4, + user_info->cb, user_info->user_data); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_gatt_client_set_service_change_watcher( + const bluetooth_device_address_t *address, gboolean enable) +{ + GSList *l; + bluetooth_device_address_t *addr = NULL; + char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + int result = BLUETOOTH_ERROR_NONE; + + BT_INFO("+"); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, &enable, sizeof(gboolean)); + + + _bt_convert_addr_string_to_secure_string(secure_address, (const char *)address->addr); + BT_INFO("Set watcher for %s with %d", secure_address, enable); + + if (enable == TRUE) { + if (_bluetooth_gatt_check_service_change_watcher_address(address) + == TRUE) { + BT_INFO("The watcher is already set"); + return BLUETOOTH_ERROR_NONE; + } + + if (service_monitor_list == NULL) { + //_bt_register_manager_subscribe_signal(TRUE); + + result = _bt_send_request(BT_BLUEZ_SERVICE, + BT_GATT_WATCH_SERVICE_CHANGED_INDICATION, + in_param1, in_param2, in_param3, in_param4, &out_param); + } + + if (result == BLUETOOTH_ERROR_NONE) { + addr = g_malloc0(sizeof(bluetooth_device_address_t)); + memcpy(addr, address, sizeof(bluetooth_device_address_t)); + + service_monitor_list = + g_slist_append(service_monitor_list, addr); + } + } else { + for (l = service_monitor_list; l != NULL; l = l->next) { + addr = l->data; + + if (!memcmp(address, addr, + sizeof(bluetooth_device_address_t))) { + service_monitor_list = + g_slist_remove(service_monitor_list, addr); + g_free(addr); + break; + } + } + + if (service_monitor_list == NULL) { + //_bt_register_manager_subscribe_signal(FALSE); + result = _bt_send_request(BT_BLUEZ_SERVICE, + BT_GATT_WATCH_SERVICE_CHANGED_INDICATION, + in_param1, in_param2, in_param3, in_param4, &out_param); + + } + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + return result; +} + +BT_EXPORT_API int bluetooth_gatt_client_deinit( + int client_id) +{ + int result; + int *count; + bt_event_info_t *event_info; + + BT_CHECK_ENABLED(return); + + BT_INFO("GATT Client Deinit Client instance ID [%d]", client_id); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &client_id, sizeof(int)); + + /* Unregistration MUST NOT FAIL */ + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_UNREGISTER, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result != BLUETOOTH_ERROR_NONE) + BT_INFO("GATT Client Unregistration failed result [%d]", result); + else + BT_INFO("GATT Client Unregistration successful"); + + /* Unregister event handler if this is the only instance */ + event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT); + + if (event_info) { + count = (int*)event_info->user_data; + + BT_INFO("Total num of GATT client instances [%d]", *count); + + if (*count == 1) { + BT_INFO("Currently only one GATT client instance, so remove it and unregister GATT client events"); + _bt_unregister_event(BT_GATT_CLIENT_EVENT); + _bt_set_user_data(BT_GATT_CLIENT, NULL, NULL); + } else + *count -= 1; + } else + BT_ERR("Impossible that client is created, but no event handler is registered!!!"); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + return result; +} + +#endif diff --git a/bt-api/bt-request-sender.c b/bt-api/bt-request-sender.c index 514cff6..ae3af3f 100644 --- a/bt-api/bt-request-sender.c +++ b/bt-api/bt-request-sender.c @@ -30,6 +30,10 @@ #include "bt-event-handler.h" #include "bluetooth-media-control.h" +#ifdef TIZEN_GATT_CLIENT +#include "bluetooth-gatt-client-api.h" +#endif + static GSList *sending_requests; static GDBusProxy *service_gproxy; @@ -225,6 +229,22 @@ static void __bt_get_event_info(int service_function, GArray *output, *param_data = &g_array_index(output, bluetooth_device_address_t, 0); break; +#ifdef TIZEN_GATT_CLIENT + case BT_CONNECT_LE: + *event_type = BT_DEVICE_EVENT; + *event = BLUETOOTH_EVENT_GATT_CLIENT_CONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_device_address_t, 0); + break; + case BT_DISCONNECT_LE: + *event_type = BT_DEVICE_EVENT; + *event = BLUETOOTH_EVENT_GATT_CLIENT_DISCONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_device_address_t, 0); + break; +#else case BT_CONNECT_LE: *event_type = BT_DEVICE_EVENT; *event = BLUETOOTH_EVENT_GATT_CONNECTED; @@ -239,6 +259,41 @@ static void __bt_get_event_info(int service_function, GArray *output, *param_data = &g_array_index(output, bluetooth_device_address_t, 0); break; +#endif +#ifdef TIZEN_GATT_CLIENT + case BT_GATT_READ_CHARACTERISTIC: + BT_INFO("BT_GATT_READ_CHARACTERISTIC"); + *event_type = BT_GATT_CLIENT_EVENT; + *event = BLUETOOTH_EVENT_GATT_READ_CHAR; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_gatt_client_char_prop_info_t, 0); + break; + case BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE: + BT_INFO("BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE"); + *event_type = BT_GATT_CLIENT_EVENT; + *event = BLUETOOTH_EVENT_GATT_WRITE_CHAR; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_gatt_client_char_prop_info_t, 0); + break; + case BT_GATT_READ_DESCRIPTOR_VALUE: + BT_INFO("BT_GATT_READ_DESCRIPTOR_VALUE"); + *event_type = BT_GATT_CLIENT_EVENT; + *event = BLUETOOTH_EVENT_GATT_READ_DESC; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_gatt_client_desc_prop_info_t, 0); + break; + case BT_GATT_WRITE_DESCRIPTOR_VALUE: + BT_INFO("BT_GATT_WRITE_DESCRIPTOR_VALUE"); + *event_type = BT_GATT_CLIENT_EVENT; + *event = BLUETOOTH_EVENT_GATT_WRITE_DESC; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_gatt_client_desc_prop_info_t, 0); + break; +#endif case BT_TDS_READ_TRANSPORT_DATA: *event_type = BT_TDS_EVENT; *event = BLUETOOTH_EVENT_TDS_TRANSPORT_DATA_RECEIVED; @@ -436,7 +491,12 @@ static void __send_request_cb(GDBusProxy *proxy, &bt_event, cb_data->user_data); } else if (event_type == BT_AVRCP_EVENT) { ((bluetooth_cb_func_ptr)cb_data->cb)(bt_event.event, - &bt_event, cb_data->user_data); + &bt_event, cb_data->user_data); +#ifdef TIZEN_GATT_CLIENT + } else if (event_type == BT_GATT_CLIENT_EVENT) { + ((gatt_client_cb_func_ptr)cb_data->cb)(bt_event.event, + (gatt_client_event_param_t*)&bt_event, cb_data->user_data); +#endif } else { BT_INFO("Not handled event type : %d", event_type); } diff --git a/bt-api/include/bt-common.h b/bt-api/include/bt-common.h index e283430..231176b 100644 --- a/bt-api/include/bt-common.h +++ b/bt-api/include/bt-common.h @@ -226,11 +226,6 @@ extern "C" { #define BT_ERROR_INVALID_FILE_DESCRIPTOR "Invalid File Descriptor" #define BT_ERROR_ACCESS_DENIED "Rejected send message" -#ifndef GATT_DIRECT -#define BT_MAX_USER_INFO 6 -#else -#define BT_MAX_USER_INFO 5 -#endif #define RFKILL_EVENT_SIZE 8 #define RFKILL_NODE "/dev/rfkill" @@ -263,6 +258,11 @@ typedef enum { #ifndef GATT_DIRECT BT_GATT_SERVER, #endif + +#ifdef TIZEN_GATT_CLIENT + BT_GATT_CLIENT, +#endif + BT_MAX_USER_INFO } bt_user_info_type_t; typedef struct { @@ -305,6 +305,11 @@ void _bt_gatt_server_event_cb(int event, int result, void *param, void *callback, void *user_data); #endif +#ifdef TIZEN_GATT_CLIENT +void _bt_gatt_client_event_cb(int event, int result, void *param, + void *callback, void *user_data); +#endif + void _bt_divide_device_class(bluetooth_device_class_t *device_class, unsigned int cod); diff --git a/bt-oal/include/oal-event.h b/bt-oal/include/oal-event.h index 4d7b030..be8c158 100644 --- a/bt-oal/include/oal-event.h +++ b/bt-oal/include/oal-event.h @@ -134,7 +134,6 @@ extern "C" { EVENT(OAL_EVENT_BLE_MULTI_ADVERTISING_DISABLE) /* NULL*/\ EVENT(OAL_EVENT_BLE_MULTI_ADVERTISING_SET_INST_DATA) /* NULL*/\ EVENT(OAL_EVENT_BLE_MULTI_ADVERTISING_UPDATE) /* NULL*/\ - EVENT(OAL_EVENT_GATTC_REGISTRATION) /* gattc Registration Confirmed */\ EVENT(OAL_EVENT_BLE_DISCOVERY_STARTED) /* NULL */\ EVENT(OAL_EVENT_BLE_DISCOVERY_STOPPED) /* NULL */\ EVENT(OAL_EVENT_BLE_REMOTE_DEVICE_FOUND) /* event_ble_scan_result_info */\ @@ -153,6 +152,26 @@ extern "C" { EVENT(OAL_EVENT_GATTS_IND_CONFIRM) /* gatts Indiction confirmation from remote client */\ EVENT(OAL_EVENT_GATTS_NOTIFICATION) /* gatts Notification from remote client */\ EVENT(OAL_EVENT_GATTS_MTU_CHANGED) /* gatts MTU changed */\ + EVENT(OAL_EVENT_GATTC_REGISTRATION) /* gattc Registration Confirmed */\ + EVENT(OAL_EVENT_GATTC_CONNECTION_COMPLETED) /* gattc connection completed */\ + EVENT(OAL_EVENT_GATTC_DISCONNECTION_COMPLETED) /* gattc disconnection */\ + EVENT(OAL_EVENT_GATTC_NOTIFICATION_REGISTERED) /* gattc notification register */\ + EVENT(OAL_EVENT_GATTC_NOTIFICATION_DEREGISTERED) /* gattc notification deregister */\ + EVENT(OAL_EVENT_GATTC_SERVICE_SEARCH_RESULT) /* gattc service search result info */\ + EVENT(OAL_EVENT_GATTC_SERVICE_SEARCH_DONE) /* gattc service search complete */\ + EVENT(OAL_EVENT_GATTC_CHARAC_SERACH_RESULT) /* gattc characteristic search result info */\ + EVENT(OAL_EVENT_GATTC_DESC_SERACH_RESULT) /* gattc descriptor search result info */\ + EVENT(OAL_EVENT_GATTC_INCL_SRVC_SERACH_RESULT) /* gattc included service search result info */\ + EVENT(OAL_EVENT_GATTC_REMOTE_RSSI) /* remote device rssi */\ + EVENT(OAL_EVENT_GATTC_NOTIFY_DATA) /* gattc notify data */\ + EVENT(OAL_EVENT_GATTC_READ_CHARAC) /* gattc read characteristics */\ + EVENT(OAL_EVENT_GATTC_WRITE_CHARAC) /* gattc write characteristics */\ + EVENT(OAL_EVENT_GATTC_READ_DESCR) /* gattc read descriptor */\ + EVENT(OAL_EVENT_GATTC_WRITE_DESCR) /* gattc write descriptor */\ + EVENT(OAL_EVENT_GATTC_MTU_EXCHANGE_COMPLETED) /* gattc mtu configure complete */\ + EVENT(OAL_EVENT_GATTC_SERVICE_CHANGED_IND) /* gattc service changed indication */\ + EVENT(OAL_EVENT_GATTC_PREPARE_WRITE) /* gattc prepare write */\ + EVENT(OAL_EVENT_GATTC_EXECUTE_WRITE) /* gattc execute write */\ EVENT(OAL_EVENT_END) /* End of event*/\ @@ -384,6 +403,48 @@ typedef struct { oal_uuid_t client_uuid; } event_gattc_register_t; +typedef struct { + oal_status_t status; + int client_if; + int conn_id; + bt_address_t address; +} event_gattc_conn_t; + +typedef struct { + oal_status_t status; + int conn_id; +} event_gattc_conn_status_t; + +typedef struct { + event_gattc_conn_status_t conn_status; + oal_gatt_srvc_id_t srvc_id; +} event_gattc_service_result_t; + +typedef struct { + int char_prop; + event_gattc_conn_status_t conn_status; + oal_gatt_id_t char_id; + oal_gatt_srvc_id_t srvc_id; +} event_gattc_characteristic_result_t; + +typedef struct { + event_gattc_conn_status_t conn_status; + oal_gatt_id_t char_id; + oal_gatt_id_t descr_id; + oal_gatt_srvc_id_t srvc_id; +} event_gattc_descriptor_result_t; + +#define BLE_READ_NOTIFY_DATA_LENGTH 600 + +typedef struct { + uint16_t value_type; + uint16_t data_len; + uint8_t data[BLE_READ_NOTIFY_DATA_LENGTH]; + event_gattc_descriptor_result_t uuid_status; +} event_gattc_read_data; + +typedef event_gattc_descriptor_result_t event_gattc_write_data; + /********* AVRCP CT role callback data structures ******************/ #define MEDIA_ATTIRBUTE_STRING_LENGTH 100 typedef struct { diff --git a/bt-oal/include/oal-gatt.h b/bt-oal/include/oal-gatt.h index 2dbc7e4..2913529 100644 --- a/bt-oal/include/oal-gatt.h +++ b/bt-oal/include/oal-gatt.h @@ -26,6 +26,19 @@ #define GATTC_READ_VALUE_TYPE_VALUE 0x0000 /* Attribute value itself */ #define GATTC_READ_VALUE_TYPE_AGG_FORMAT 0x2905 /* Characteristic Aggregate Format*/ +typedef enum { + OAL_GATT_WRITE_NO_RSP = 1, + OAL_GATT_WRITE , +} oal_gatt_write_type_t; + +typedef enum { + OAL_GATT_AUTH_REQ_NONE = 0, + OAL_GATT_AUTH_REQ_NO_MITM, /* unauthenticated encryption */ + OAL_GATT_AUTH_REQ_MITM, /* authenticated encryption */ + OAL_GATT_AUTH_REQ_SIGNED_NO_MITM, + OAL_GATT_AUTH_REQ_SIGNED_MITM, +} oal_gatt_auth_req_t; + /** GATT value type used in response to remote read requests */ typedef struct { uint8_t value[OAL_GATT_MAX_ATTR_LEN]; @@ -370,8 +383,7 @@ oal_status_t gatts_send_response(int conn_id, int trans_id, int resp_status, oal * * @see gatt_enable() */ -oal_status_t gattc_start_le_discovery(void); - +oal_status_t gattc_start_le_discovery(int client_id); /** * @brief Stop LE Device discovery * @@ -384,7 +396,7 @@ oal_status_t gattc_start_le_discovery(void); * * @see gattc_start_le_discovery() */ -oal_status_t gattc_stop_le_discovery(void); +oal_status_t gattc_stop_le_discovery(int client_id); /** * @brief Set scan parameters @@ -397,4 +409,33 @@ oal_status_t gattc_stop_le_discovery(void); */ oal_status_t gattc_set_le_scan_param(int scan_type, int itv, int win); +/** Registers a GATT client application with the stack */ +oal_status_t gattc_register(oal_uuid_t* client_uuid); + +oal_status_t gattc_deregister(int client_id); + + /** Create a connection to a remote LE or dual-mode device */ +oal_status_t gattc_connect(int client_id, bt_address_t *device_address, int isDirect); + +oal_status_t gattc_search_service(int conn_id, oal_uuid_t *service_uuid); + +oal_status_t gattc_get_characteristic(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id); + +oal_status_t gattc_get_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id, + oal_gatt_id_t *desc_id); + +oal_status_t gattc_read_characteristic(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id, + oal_gatt_auth_req_t auth_req); + +oal_status_t gattc_read_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id, + oal_gatt_id_t *desc_id, oal_gatt_auth_req_t auth_req); +oal_status_t gattc_write_characteristic(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id, oal_gatt_write_type_t write_type, + int len, oal_gatt_auth_req_t auth_req, char* data); + +oal_status_t gattc_write_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id, oal_gatt_id_t *desc_id, + oal_gatt_write_type_t write_type, int len, oal_gatt_auth_req_t auth_req, char* data); + +oal_status_t gattc_disconnect(int client_id, bt_address_t *device_address, int conn_id); + +oal_status_t gattc_conn_param_update(bt_address_t * address, int min, int max, int latency, int timeout); #endif /* OAL_GATT_H_ */ diff --git a/bt-oal/oal-gatt.c b/bt-oal/oal-gatt.c index 63ada7b..ef38eeb 100644 --- a/bt-oal/oal-gatt.c +++ b/bt-oal/oal-gatt.c @@ -80,6 +80,23 @@ } \ } while (0) +#define CHECK_CLIENT_REGISTRATION(client_id) \ + do { \ + if (client_id <= 0) { \ + BT_DBG("No client registered yet...");\ + return OAL_STATUS_INTERNAL_ERROR;\ + } \ + } while (0) + +#define CHECK_CLIENT_CONNECTION(conn_id) \ + do { \ + if (conn_id <= 0) {\ + BT_ERR("No active connection");\ + return OAL_STATUS_INTERNAL_ERROR;\ + } \ + } while (0) + + typedef enum { GATT_INS_DISABLED, GATT_INS_DATA_SETTING, @@ -179,24 +196,36 @@ static const btgatt_server_callbacks_t btgatt_server_callbacks = { /* Forward declaration for GATT client callbacks */ static void cb_gattc_register_app(int status, int clientIf, bt_uuid_t *app_uuid); static void cb_gattc_scan_result(bt_bdaddr_t* bdaddress, int rssi, uint8_t *adv_data); +static void cb_gattc_connection(int conn_id, int status, int client_if, bt_bdaddr_t* bda); +static void cb_gattc_disconnect(int conn_id, int status, int client_if, bt_bdaddr_t* bda); +static void cb_gattc_search_result(int conn_id, btgatt_srvc_id_t *srvc_id); +static void cb_gattc_search_complete(int conn_id, int status); +static void cb_gattc_get_characteristics(int conn_id, int status, btgatt_srvc_id_t *srvc_id, + btgatt_gatt_id_t *char_id, int char_prop); +static void cb_gattc_get_descriptor(int conn_id, int status, btgatt_srvc_id_t *srvc_id, + btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id); +static void cb_gattc_read_characteristic(int conn_id, int status, btgatt_read_params_t *p_data); +static void cb_gattc_read_descriptor(int conn_id, int status, btgatt_read_params_t *p_data); +static void cb_gattc_write_characteristic(int conn_id, int status, btgatt_write_params_t *p_data); +static void cb_gattc_write_descriptor(int conn_id, int status, btgatt_write_params_t *p_data); /*TODO GATT CLient callbacks will be implemented in subsequent patches */ static const btgatt_client_callbacks_t btgatt_client_callbacks = { cb_gattc_register_app, cb_gattc_scan_result, - NULL, /*cb_gattc_connection*/ - NULL, /*cb_gattc_disconnect*/ - NULL, /*cb_gattc_search_complete*/ - NULL, /*cb_gattc_search_result*/ - NULL, /*cb_gattc_get_characteristics*/ - NULL, /*cb_gattc_get_descriptor*/ + cb_gattc_connection, /*cb_gattc_connection*/ + cb_gattc_disconnect, /*cb_gattc_disconnect*/ + cb_gattc_search_complete, /*cb_gattc_search_complete*/ + cb_gattc_search_result, /*cb_gattc_search_result*/ + cb_gattc_get_characteristics, /*cb_gattc_get_characteristics*/ + cb_gattc_get_descriptor, /*cb_gattc_get_descriptor*/ NULL, /*cb_gattc_get_included_service*/ NULL, /*cb_gattc_register_for_notification*/ NULL, /*cb_gattc_notify*/ - NULL, /*cb_gattc_read_characteristic*/ - NULL, /*cb_gattc_write_characteristic*/ - NULL, /*cb_gattc_read_descriptor*/ - NULL, /*cb_gattc_write_descriptor*/ + cb_gattc_read_characteristic, /*cb_gattc_read_characteristic*/ + cb_gattc_write_characteristic, /*cb_gattc_write_characteristic*/ + cb_gattc_read_descriptor, /*cb_gattc_read_descriptor*/ + cb_gattc_write_descriptor, /*cb_gattc_write_descriptor*/ NULL, /*cb_gattc_execute_write*/ NULL, /*cb_gattc_remote_rssi*/ NULL, /*cb_gattc_configure_mtu_cmpl*/ @@ -1286,40 +1315,18 @@ static void cb_gattc_register_app(int status, int clientIf, bt_uuid_t *app_uuid) char uuid_str[BT_UUID_STRING_MAX]; event_gattc_register_t *event; + BT_INFO("+"); + /* Check if GATT client registered for Default GATT client UUID */ uuid_to_string((service_uuid_t *)app_uuid, uuid_str); - if (!strncasecmp(DEFAULT_GATT_CLIENT_UUID, - uuid_str, strlen(DEFAULT_GATT_CLIENT_UUID))) { - default_client_id = clientIf; - switch (pending_gattc_req) { - case OAL_REQ_LE_SCAN: - if (0 != status) { - default_client_id = -1; - pending_gattc_req = OAL_REQ_NONE; - BT_ERR("Default client app creation failed"); - send_event(OAL_EVENT_BLE_DISCOVERY_STOPPED, NULL, 0); - break; - } - - if (OAL_STATUS_SUCCESS != gattc_start_le_discovery()) { - BT_ERR("Error:Start LE Discovery failed"); - send_event(OAL_EVENT_BLE_DISCOVERY_STOPPED, NULL, 0); - } - break; - default: - BT_ERR("Unknown pending request: %d", pending_gattc_req); - } - - /* Return from here, no need to send GATTC_REGISTRATION event */ - return; - } + BT_INFO("UUID:%s", uuid_str); BT_INFO("BTGATT CLIENT REGISTER APP CB, status:%d, clientIf:%d", status, clientIf); event = g_new0(event_gattc_register_t, 1); event->client_if = clientIf; event->status = (status == 0 ? OAL_STATUS_SUCCESS : OAL_STATUS_INTERNAL_ERROR); memcpy(event->client_uuid.uuid, app_uuid->uu, sizeof(oal_uuid_t)); - send_event_no_trace(OAL_EVENT_GATTC_REGISTRATION, event, sizeof(event_gattc_register_t)); + send_event(OAL_EVENT_GATTC_REGISTRATION, event, sizeof(event_gattc_register_t)); } static void cb_gattc_scan_result(bt_bdaddr_t* bdaddress, int rssi, uint8_t *adv_data) @@ -1334,6 +1341,256 @@ static void cb_gattc_scan_result(bt_bdaddr_t* bdaddress, int rssi, uint8_t *adv_ sizeof(event_ble_scan_result_info), (bt_address_t *)bdaddress); } +static void cb_gattc_connection(int conn_id, int status, int client_if, bt_bdaddr_t* bda) +{ + event_gattc_conn_t *event; + BT_INFO("BTGATT CLIENT CONNECTED CB, status:[%d] client_if[%d] id[%d]", + status, client_if, conn_id); + + event = g_new0(event_gattc_conn_t, 1); + memcpy(event->address.addr, bda->address, BT_ADDRESS_BYTES_NUM); + event->client_if = client_if; + + if (BT_STATUS_SUCCESS != status) { + event->status = OAL_STATUS_INTERNAL_ERROR; + BT_ERR("gattc connection Error: %d", status); + } else { + event->conn_id = conn_id; + event->status = OAL_STATUS_SUCCESS; + } + + send_event_bda_trace(OAL_EVENT_GATTC_CONNECTION_COMPLETED, event, + sizeof(*event), (bt_address_t *)bda); +} + + +static void cb_gattc_disconnect(int conn_id, int status, int client_if, bt_bdaddr_t* bda) +{ + event_gattc_conn_t *event; + BT_INFO("BTGATT Client Disconnect Complete cb, status:[%d], client_if[%d] id[%d]", + status, client_if, conn_id); + event = g_new0(event_gattc_conn_t, 1); + event->status = convert_to_oal_status(status); + event->client_if = client_if; + event->conn_id = conn_id; + memcpy(event->address.addr, bda->address, BT_ADDRESS_BYTES_NUM); + send_event_bda_trace(OAL_EVENT_GATTC_DISCONNECTION_COMPLETED, event, + sizeof(*event), (bt_address_t *)bda); +} + +static void cb_gattc_search_result(int conn_id, btgatt_srvc_id_t *srvc_id) +{ + char uuid_str[2*BT_UUID_STRING_MAX]; + + BT_INFO("BTGATT Client Service Search Result cb, conn_id:%d", conn_id); + + uuid_to_stringname((oal_uuid_t *)&(srvc_id->id.uuid), uuid_str); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", + uuid_str, srvc_id->id.inst_id, srvc_id->is_primary ? "Primary" : "Secondary"); + + event_gattc_service_result_t *event = g_new0(event_gattc_service_result_t, 1); + event->conn_status.status = OAL_STATUS_SUCCESS; + event->conn_status.conn_id = conn_id; + memcpy(&(event->srvc_id), srvc_id, sizeof(oal_gatt_srvc_id_t)); + + send_event(OAL_EVENT_GATTC_SERVICE_SEARCH_RESULT, event, sizeof(*event)); +} + +static void cb_gattc_search_complete(int conn_id, int status) +{ + BT_INFO("BTGATT Client Service Search Complete cb, status:%d, conn_id:%d", + status, conn_id); + + event_gattc_conn_status_t *event = g_new0(event_gattc_conn_status_t, 1); + event->conn_id = conn_id; + event->status = convert_to_oal_status(status); + + send_event(OAL_EVENT_GATTC_SERVICE_SEARCH_DONE, event, sizeof(*event)); +} + + +static void cb_gattc_get_characteristics(int conn_id, int status, btgatt_srvc_id_t *srvc_id, + btgatt_gatt_id_t *char_id, int char_prop) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char str[50]; + BT_INFO("BTGATT Client Get Characteristic Callback, conn_id:%d, status:%d", conn_id, status); + uuid_to_stringname((oal_uuid_t *)&(srvc_id->id.uuid), uuid_str1); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", + uuid_str1, srvc_id->id.inst_id, srvc_id->is_primary ? "Primary" : "Secondary"); + + event_gattc_characteristic_result_t *event = g_new0(event_gattc_characteristic_result_t, 1); + event->conn_status.conn_id = conn_id; + event->conn_status.status = convert_to_oal_status(status); + memcpy(&(event->srvc_id), srvc_id, sizeof(oal_gatt_srvc_id_t)); + + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(char_id->uuid), uuid_str2); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u], Prop: [%s]", + uuid_str2, char_id->inst_id, char_prop_to_string(char_prop, str)); + event->char_prop = char_prop; + memcpy(&(event->char_id), char_id, sizeof(oal_gatt_id_t)); + } + send_event(OAL_EVENT_GATTC_CHARAC_SERACH_RESULT, event, sizeof(*event)); +} + + + +static void cb_gattc_get_descriptor(int conn_id, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char uuid_str3[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Get Descriptor Callback, conn_id:%d, status:%d", conn_id, status); + uuid_to_stringname((oal_uuid_t *)&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(char_id->uuid), uuid_str2); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", + uuid_str1, srvc_id->id.inst_id, srvc_id->is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, char_id->inst_id); + + event_gattc_descriptor_result_t *event = g_new0(event_gattc_descriptor_result_t, 1); + event->conn_status.conn_id = conn_id; + event->conn_status.status = convert_to_oal_status(status); + memcpy(&(event->srvc_id), srvc_id, sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->char_id), char_id, sizeof(oal_gatt_id_t)); + + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(descr_id->uuid), uuid_str3); + BT_INFO("Desc=> UUID: [%s], Inst_id: [%u]", uuid_str3, descr_id->inst_id); + memcpy(&(event->descr_id), descr_id, sizeof(oal_gatt_id_t)); + } + send_event(OAL_EVENT_GATTC_DESC_SERACH_RESULT, event, sizeof(*event)); +} + +static void cb_gattc_read_characteristic(int conn_id, int status, btgatt_read_params_t *p_data) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Read Charcateristic Callback, conn_id:%d, read_status:%d", conn_id, status); + + event_gattc_read_data *event = g_new0(event_gattc_read_data, 1); + event->uuid_status.conn_status.conn_id = conn_id; + event->uuid_status.conn_status.status = convert_to_oal_status(status); + event->value_type = p_data->value_type; + memcpy(&(event->uuid_status.srvc_id), &(p_data->srvc_id), sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->uuid_status.char_id), &(p_data->char_id), sizeof(oal_gatt_id_t)); + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(p_data->srvc_id.id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(p_data->char_id.uuid), uuid_str2); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", uuid_str1, + p_data->srvc_id.id.inst_id, p_data->srvc_id.is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, p_data->char_id.inst_id); + BT_INFO("Len: %u, value_type: %u", p_data->value.len, p_data->value_type); + if (p_data->value.len > 0 && event->value_type == GATTC_READ_VALUE_TYPE_VALUE) { + char *data = NULL; + data = g_malloc(3*p_data->value.len+1); + if (!data) { + BT_ERR("memory allocation failed"); + g_free(event); + return; + } + convert_hex_2_str((unsigned char *)p_data->value.value, p_data->value.len, data); + BT_INFO("Read Data: [%s]", data); + event->data_len = p_data->value.len; + memcpy(&(event->data), &(p_data->value.value), event->data_len); + g_free(data); + } + } + send_event(OAL_EVENT_GATTC_READ_CHARAC, event, sizeof(*event)); +} + +static void cb_gattc_write_characteristic(int conn_id, int status, btgatt_write_params_t *p_data) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Write Charcateristic Callback, conn_id:%d, write_status:%d", conn_id, status); + + event_gattc_write_data *event = g_new0(event_gattc_write_data, 1); + event->conn_status.conn_id = conn_id; + event->conn_status.status = convert_to_oal_status(status); + memcpy(&(event->srvc_id), &(p_data->srvc_id), sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->char_id), &(p_data->char_id), sizeof(oal_gatt_id_t)); + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(p_data->srvc_id.id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(p_data->char_id.uuid), uuid_str2); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", uuid_str1, + p_data->srvc_id.id.inst_id, p_data->srvc_id.is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, p_data->char_id.inst_id); + } + send_event(OAL_EVENT_GATTC_WRITE_CHARAC, event, sizeof(*event)); +} + +static void cb_gattc_write_descriptor(int conn_id, int status, btgatt_write_params_t *p_data) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char uuid_str3[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Write Descriptor Callback, conn_id:%d, write_status:%d", conn_id, status); + + event_gattc_write_data *event = g_new0(event_gattc_write_data, 1); + event->conn_status.conn_id = conn_id; + event->conn_status.status = convert_to_oal_status(status); + memcpy(&(event->srvc_id), &(p_data->srvc_id), sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->char_id), &(p_data->char_id), sizeof(oal_gatt_id_t)); + memcpy(&(event->descr_id), &(p_data->descr_id), sizeof(oal_gatt_id_t)); + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(p_data->srvc_id.id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(p_data->char_id.uuid), uuid_str2); + uuid_to_stringname((oal_uuid_t *)&(p_data->descr_id.uuid), uuid_str3); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", uuid_str1, + p_data->srvc_id.id.inst_id, p_data->srvc_id.is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, p_data->char_id.inst_id); + BT_INFO("Desc=> UUID: [%s], Inst_id: [%u]", uuid_str3, p_data->descr_id.inst_id); + } + send_event(OAL_EVENT_GATTC_WRITE_DESCR, event, sizeof(*event)); +} + + + +static void cb_gattc_read_descriptor(int conn_id, int status, btgatt_read_params_t *p_data) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char uuid_str3[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Read Descriptor Callback, conn_id:%d, read_status:%d", conn_id, status); + + event_gattc_read_data *event = g_new0(event_gattc_read_data, 1); + event->uuid_status.conn_status.conn_id = conn_id; + event->uuid_status.conn_status.status = convert_to_oal_status(status); + event->value_type = p_data->value_type; + memcpy(&(event->uuid_status.srvc_id), &(p_data->srvc_id), sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->uuid_status.char_id), &(p_data->char_id), sizeof(oal_gatt_id_t)); + memcpy(&(event->uuid_status.descr_id), &(p_data->descr_id), sizeof(oal_gatt_id_t)); + + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(p_data->srvc_id.id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(p_data->char_id.uuid), uuid_str2); + uuid_to_stringname((oal_uuid_t *)&(p_data->descr_id.uuid), uuid_str3); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", uuid_str1, + p_data->srvc_id.id.inst_id, p_data->srvc_id.is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, p_data->char_id.inst_id); + BT_INFO("Desc=> UUID: [%s], Inst_id: [%u]", uuid_str3, p_data->descr_id.inst_id); + BT_INFO("Len: %u, value_type: %u", p_data->value.len, p_data->value_type); + if (p_data->value.len > 0 && event->value_type == GATTC_READ_VALUE_TYPE_VALUE) { + char *data = NULL; + data = g_malloc(3*p_data->value.len+1); + if (!data) { + BT_ERR("memory allocation failed"); + g_free(event); + return; + } + convert_hex_2_str((unsigned char *)p_data->value.value, p_data->value.len, data); + BT_INFO("Read Data: [%s]", data); + event->data_len = p_data->value.len; + memcpy(&(event->data), &(p_data->value.value), event->data_len); + g_free(data); + } + } + send_event(OAL_EVENT_GATTC_READ_DESCR, event, sizeof(*event)); +} + + /* Register default gatt client to be used in LE scan etc. */ static oal_status_t __register_default_gatt_client(void) { @@ -1358,54 +1615,38 @@ static oal_status_t __register_default_gatt_client(void) return OAL_STATUS_SUCCESS; } -oal_status_t gattc_start_le_discovery(void) +oal_status_t gattc_start_le_discovery(int client_id) { - int ret; + + int ret = OAL_STATUS_SUCCESS; API_TRACE("BTGATT CLIENT SCAN START"); CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_REGISTRATION(client_id); - if (default_client_id < 0) { - if (pending_gattc_req != OAL_REQ_NONE) { - BT_ERR("Another request: %d already in progress", pending_gattc_req); - return OAL_STATUS_INTERNAL_ERROR; - } - - pending_gattc_req = OAL_REQ_LE_SCAN; - ret = __register_default_gatt_client(); - if (OAL_STATUS_SUCCESS != ret) { - BT_ERR("__register_default_gatt_client failed"); - pending_gattc_req = OAL_REQ_NONE; - return OAL_STATUS_INTERNAL_ERROR; - } - - return OAL_STATUS_SUCCESS; - } - - ret = gatt_api->client->scan(default_client_id, true); + ret = gatt_api->client->scan(client_id, 1); if (ret != BT_STATUS_SUCCESS) { BT_ERR("Error:Start LE Discovery failed: %s", status2string(ret)); return convert_to_oal_status(ret); } - send_event(OAL_EVENT_BLE_DISCOVERY_STARTED, NULL, 0); return OAL_STATUS_SUCCESS; } -oal_status_t gattc_stop_le_discovery(void) +oal_status_t gattc_stop_le_discovery(int client_id) { - int ret; + + int ret = OAL_STATUS_SUCCESS; API_TRACE("Scan is stopped"); CHECK_OAL_GATT_ENABLED(); - - ret = gatt_api->client->scan(default_client_id, false); + CHECK_CLIENT_REGISTRATION(client_id); + ret = gatt_api->client->scan(client_id, 0); if (ret != BT_STATUS_SUCCESS) { BT_ERR("Error:Stop LE Discovery failed: %s", status2string(ret)); return convert_to_oal_status(ret); - } - - send_event(OAL_EVENT_BLE_DISCOVERY_STOPPED, NULL, 0); + } else + send_event(OAL_EVENT_BLE_DISCOVERY_STOPPED, NULL, 0); return OAL_STATUS_SUCCESS; } @@ -1433,3 +1674,270 @@ oal_status_t gattc_set_le_scan_param(int scan_type, int itv, int win) return OAL_STATUS_SUCCESS; } /************************************ GATT Client ***********************************/ +oal_status_t gattc_register(oal_uuid_t* client_uuid) +{ + + char str[2*BT_UUID_STRING_MAX]; + int ret = OAL_STATUS_SUCCESS; + + CHECK_OAL_GATT_ENABLED(); + uuid_to_stringname(client_uuid, str); + API_TRACE("uuid: [%s]", str); + /* We will perform actual registration in cb_gattc_register_app callback */ + ret = gatt_api->client->register_client((bt_uuid_t *)client_uuid); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client register failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_deregister(int client_id) +{ + int ret = OAL_STATUS_SUCCESS; + + API_TRACE("GATT client deregister"); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_REGISTRATION(client_id); + + ret = gatt_api->client->unregister_client(client_id); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client deregister failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_connect(int client_id, bt_address_t *device_address, int isDirect) +{ + int ret = OAL_STATUS_SUCCESS; + bdstr_t bdstr; + + OAL_CHECK_PARAMETER(device_address, return); + API_TRACE("Client Connect: [%s]", bdt_bd2str(device_address, &bdstr)); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_REGISTRATION(client_id); + + /* Handle the actual connection in cb_gattc_connection callback */ + ret = gatt_api->client->connect(client_id, (bt_bdaddr_t *)device_address, isDirect); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client connect failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_disconnect(int client_id, bt_address_t *device_address, int conn_id) +{ + + int ret = OAL_STATUS_SUCCESS; + bdstr_t bdstr; + + OAL_CHECK_PARAMETER(device_address, return); + API_TRACE("Client Disconnect: [%s]", bdt_bd2str(device_address, &bdstr)); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_REGISTRATION(client_id); + CHECK_CLIENT_CONNECTION(conn_id); + + /* Handle actual disconnection in callback */ + ret = gatt_api->client->disconnect(client_id, (bt_bdaddr_t *) device_address, conn_id); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client disconnect failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + + +oal_status_t gattc_search_service(int conn_id, oal_uuid_t *service_uuid) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str[2*BT_UUID_STRING_MAX]; + + if (service_uuid) { + uuid_to_stringname(service_uuid, uuid_str); + API_TRACE("Client Service Search UUID: [%s]", uuid_str); + } else + API_TRACE("Client Service Search All"); + + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + ret = gatt_api->client->search_service(conn_id, (bt_uuid_t *)service_uuid); + + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client service search failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_get_characteristic(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str[2*BT_UUID_STRING_MAX]; + + OAL_CHECK_PARAMETER(srvc_id, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str); + API_TRACE("Client Get Characteristic, Service_uuid: [%s]", uuid_str); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + ret = gatt_api->client->get_characteristic(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client get characteristic failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_get_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id, + oal_gatt_id_t *char_id, oal_gatt_id_t *desc_id) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + API_TRACE("Client Get Descriptor, Service_uuid: [%s], Char_uuid: [%s]", uuid_str1, uuid_str2); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + ret = gatt_api->client->get_descriptor(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id, (btgatt_gatt_id_t *)desc_id); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client get descriptor failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_read_characteristic(int conn_id, oal_gatt_srvc_id_t *srvc_id, + oal_gatt_id_t *char_id, oal_gatt_auth_req_t auth_req) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + API_TRACE("Client Read Characteristic: Service_uuid: [%s], Char_uuid: [%s]", uuid_str1, uuid_str2); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + + ret = gatt_api->client->read_characteristic(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id, auth_req); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client read characteristic failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_read_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id, + oal_gatt_id_t *char_id, oal_gatt_id_t *desc_id, oal_gatt_auth_req_t auth_req) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char uuid_str3[2*BT_UUID_STRING_MAX]; + + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + OAL_CHECK_PARAMETER(desc_id, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + uuid_to_stringname(&(desc_id->uuid), uuid_str3); + API_TRACE("Client Read Descriptor: Service_uuid: [%s], Char_uuid: [%s], Desc_uuid: [%s]", + uuid_str1, uuid_str2, uuid_str3); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + + ret = gatt_api->client->read_descriptor(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id, (btgatt_gatt_id_t *)desc_id, auth_req); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client read descriptor failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_write_characteristic(int conn_id, oal_gatt_srvc_id_t *srvc_id, + oal_gatt_id_t *char_id, oal_gatt_write_type_t write_type, + int len, oal_gatt_auth_req_t auth_req, char* data) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + OAL_CHECK_PARAMETER(data, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + API_TRACE("Client Write Characteristic: Service_uuid: [%s], Char_uuid: [%s]", uuid_str1, uuid_str2); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + + ret = gatt_api->client->write_characteristic(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id, write_type, len, auth_req, data); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client write characteristic failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_write_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id, + oal_gatt_id_t *char_id, oal_gatt_id_t *desc_id, + oal_gatt_write_type_t write_type, int len, oal_gatt_auth_req_t auth_req, char* data) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char uuid_str3[2*BT_UUID_STRING_MAX]; + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + OAL_CHECK_PARAMETER(desc_id, return); + OAL_CHECK_PARAMETER(data, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + uuid_to_stringname(&(desc_id->uuid), uuid_str3); + API_TRACE("Client Write Descriptor: Service_uuid: [%s], Char_uuid: [%s], Desc_uuid: [%s]", + uuid_str1, uuid_str2, uuid_str3); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + + ret = gatt_api->client->write_descriptor(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id, (btgatt_gatt_id_t *)desc_id, write_type, len, auth_req, data); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client write characteristic failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_conn_param_update(bt_address_t * address, int min, int max, int latency, int timeout) +{ + int ret; + bdstr_t bdstr; + + OAL_CHECK_PARAMETER(address, return); + API_TRACE("Conn Param Update: [%s]", bdt_bd2str(address, &bdstr)); + CHECK_OAL_GATT_ENABLED(); + + BT_INFO("[%s] min[%d] max[%d] latency[%d] timeout[%d]", bdt_bd2str(address, &bdstr), min, max, latency, timeout); + ret = gatt_api->client->conn_parameter_update((bt_bdaddr_t *)address, min, max, latency, timeout); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("error: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} diff --git a/bt-service-adaptation/services/adapter/bt-service-core-adapter-le.c b/bt-service-adaptation/services/adapter/bt-service-core-adapter-le.c index 353ae2c..8084df5 100644 --- a/bt-service-adaptation/services/adapter/bt-service-core-adapter-le.c +++ b/bt-service-adaptation/services/adapter/bt-service-core-adapter-le.c @@ -85,6 +85,9 @@ typedef struct { GSList *scanner_list = NULL; static gboolean is_le_set_scan_parameter = FALSE; static gboolean is_le_scanning = FALSE; + +static int g_gatt_client_id = 0; + /******************************************* LE Scan *********************************************/ void _bt_adapter_set_le_status(bt_le_status_t status) @@ -681,6 +684,28 @@ static void __bt_le_event_handler(int event_type, gpointer event_data) __bt_le_handle_device_found(scan_result); break; } + case OAL_EVENT_GATTC_REGISTRATION: { + event_gattc_register_t *gattc_event = event_data; + char uuid_str[BLUETOOTH_UUID_STRING_MAX]; + char *default_uuid_string; + + default_uuid_string = _bt_gatt_get_default_gatt_client_uuid(); + _bt_uuid_to_string((service_uuid_t*)&(gattc_event->client_uuid), uuid_str); + BT_INFO("default UUID [%s] current registered uuid [%s]", + default_uuid_string, uuid_str); + if (g_strcmp0(uuid_str, default_uuid_string)) { + BT_INFO("This is not the default GATT client that is registered"); + + g_free(default_uuid_string); + break; + } + BT_INFO("GATT CLient instance registered is default client: ID [%d]", + gattc_event->client_if); + g_free(default_uuid_string); + + g_gatt_client_id = gattc_event->client_if; + break; + } default: break; } @@ -1478,7 +1503,8 @@ int _bt_start_le_scan(const char *sender) } BT_INFO("Start LE Full Scan"); - ret = gattc_start_le_discovery(); + ret = gattc_start_le_discovery(g_gatt_client_id); + if (OAL_STATUS_SUCCESS != ret) { BT_ERR("gattc_start_le_discovery failed"); return BLUETOOTH_ERROR_INTERNAL; @@ -1517,7 +1543,8 @@ int _bt_stop_le_scan(const char *sender) BT_INFO("Just stop LE scan"); } - ret = gattc_stop_le_discovery(); + ret = gattc_stop_le_discovery(g_gatt_client_id); + if (OAL_STATUS_SUCCESS != ret) { BT_ERR("gattc_start_le_discovery failed"); return BLUETOOTH_ERROR_INTERNAL; diff --git a/bt-service-adaptation/services/adapter/bt-service-core-adapter.c b/bt-service-adaptation/services/adapter/bt-service-core-adapter.c index 73131f7..40cd1e2 100644 --- a/bt-service-adaptation/services/adapter/bt-service-core-adapter.c +++ b/bt-service-adaptation/services/adapter/bt-service-core-adapter.c @@ -957,6 +957,7 @@ static void __bt_adapter_event_handler(int event_type, gpointer event_data) int _bt_init_profiles() { int ret; + BT_INFO("+"); /*TODO: Init bluetooth profiles */ ret = _bt_hidhost_initialize(); diff --git a/bt-service-adaptation/services/bt-request-handler.c b/bt-service-adaptation/services/bt-request-handler.c index dac152a..83085ce 100644 --- a/bt-service-adaptation/services/bt-request-handler.c +++ b/bt-service-adaptation/services/bt-request-handler.c @@ -222,6 +222,14 @@ static gboolean __bt_is_sync_function(int service_function) || service_function == BT_GATT_SERVER_DELETE_SERVICE || service_function == BT_START_LE_DISCOVERY || service_function == BT_STOP_LE_DISCOVERY +#ifdef TIZEN_GATT_CLIENT + || service_function == BT_GATT_CLIENT_REGISTER + || service_function == BT_GATT_GET_PRIMARY_SERVICES + || service_function == BT_GATT_GET_SERVICE_PROPERTIES + || service_function == BT_GATT_GET_INCLUDED_SERVICES + || service_function == BT_GATT_GET_CHARACTERISTIC_PROPERTIES + || service_function == BT_GATT_WATCH_CHARACTERISTIC +#endif || service_function == BT_AUDIO_SELECT_ROLE || service_function == BT_OBEX_SERVER_ACCEPT_CONNECTION) return TRUE; @@ -834,7 +842,7 @@ int __bt_bluez_request(int function_name, #else connected = _bt_is_device_connected(&address, service_type); #endif - BT_DBG("is_connected: %d", connected); + BT_INFO("is_connected: %d", connected); g_array_append_vals(*out_param1, &connected, sizeof(gboolean)); break; } @@ -2306,6 +2314,305 @@ int __bt_bluez_request(int function_name, } break; } +#ifdef TIZEN_GATT_CLIENT + /* Local Async */ + case BT_GATT_CLIENT_REGISTER: { + bluetooth_device_address_t address = { {0} }; + char *addr; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + + __bt_service_get_parameters(in_param1, + &address, sizeof(bluetooth_device_address_t)); + + result = _bt_register_gatt_client_instance(sender, &address); + if (BLUETOOTH_ERROR_NONE == result) { + addr = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_addr_type_to_string(addr, address.addr); + BT_INFO("GATT Client: Save Invocation data GATT CLient Register app[%s] address [%s]", sender, addr); + + /* Save the informations to invocation */ + _bt_save_invocation_context(context, result, sender, + function_name, (gpointer)addr); + } + break; + } + /* Sync */ + case BT_GATT_CLIENT_UNREGISTER: { + int client_id; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + __bt_service_get_parameters(in_param1, + &client_id, sizeof(int)); + + result = _bt_unregister_gatt_client_instance(sender, client_id); + break; + } + + /* Async: Remote Interaction */ + case BT_CONNECT_LE: { + bluetooth_device_address_t address = { {0} }; + gboolean auto_connect; + char *addr; + int client_id; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + + __bt_service_get_parameters(in_param1, + &address, sizeof(bluetooth_device_address_t)); + __bt_service_get_parameters(in_param2, + &auto_connect, sizeof(gboolean)); + __bt_service_get_parameters(in_param3, + &client_id, sizeof(int)); + + BT_INFO("GATT Client: client_id[%d]", client_id); + result = _bt_connect_le_device(&address, auto_connect, client_id); + if (BLUETOOTH_ERROR_NONE == result) { + + addr = g_malloc0(BT_ADDRESS_STRING_SIZE); + BT_INFO("GATT Client: Save Invocation data Connect LE app[%s]", sender); + + _bt_convert_addr_type_to_string(addr, address.addr); + + /* Save the informations to invocation */ + _bt_save_invocation_context(context, result, sender, + function_name, (gpointer)addr); + } else { + BT_INFO("GATT Client: gatt connect failed"); + g_array_append_vals(*out_param1, &address, + sizeof(bluetooth_device_address_t)); + } + break; + } + /* Async: Remote Interaction */ + case BT_DISCONNECT_LE: { + bluetooth_device_address_t address = { {0} }; + char *addr; + int client_id; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + + __bt_service_get_parameters(in_param1, + &address, sizeof(bluetooth_device_address_t)); + __bt_service_get_parameters(in_param2, + &client_id, sizeof(int)); + + BT_INFO("GATT Disconnect using client Interface [%d]", client_id); + result = _bt_disconnect_le_device(&address, client_id); + if (BLUETOOTH_ERROR_NONE == result) { + addr = g_malloc0(BT_ADDRESS_STRING_SIZE); + BT_INFO("GATT Client: Save Invocation data DisConnect LE app[%s]", sender); + + _bt_convert_addr_type_to_string(addr, address.addr); + + /* Save the informations to invocation */ + _bt_save_invocation_context(context, result, sender, + function_name, (gpointer)addr); + } else { + g_array_append_vals(*out_param1, &address, + sizeof(bluetooth_device_address_t)); + } + break; + } + case BT_GATT_GET_PRIMARY_SERVICES: { + char *addr; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + bluetooth_device_address_t address = { {0} }; + + __bt_service_get_parameters(in_param1, &address, + sizeof(bluetooth_device_address_t)); + + addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, address.addr); + + result = _bt_gatt_get_primary_services(addr); + if (BLUETOOTH_ERROR_NONE == result) { + BT_INFO("GATT Client: Save Remote GATT Server address addr [%s] app[%s]", + addr, sender); + _bt_save_invocation_context(context, result, sender, + function_name, (gpointer)addr); + } else + g_free(addr); + break; + } + /* Local Async */ + case BT_GATT_GET_SERVICE_PROPERTIES: { + bluetooth_gatt_client_svc_prop_info_t param; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_svc_prop_info_t)); + + __bt_service_get_parameters(in_param1, ¶m, + sizeof(bluetooth_gatt_client_svc_prop_info_t)); + + result = _bt_gatt_get_all_characteristic(¶m); + if (BLUETOOTH_ERROR_NONE == result) { + BT_INFO("GATT Client: Save Invocation data for Service props app[%s]", sender); + + /* Save the informations to invocation */ + _bt_save_invocation_context(context, result, sender, + function_name, + (gpointer)g_memdup(¶m, sizeof(bluetooth_gatt_client_svc_prop_info_t))); + } + break; + } + case BT_GATT_GET_CHARACTERISTIC_PROPERTIES: { + bluetooth_gatt_client_char_prop_info_t param; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t)); + + __bt_service_get_parameters(in_param1, ¶m, + sizeof(bluetooth_gatt_client_char_prop_info_t)); + + result = _bt_gatt_get_all_characteristic_properties(¶m); + if (BLUETOOTH_ERROR_NONE == result) { + BT_INFO("GATT Client: Save Invocation data for characteristic props app[%s]", sender); + + /* Save the informations to invocation */ + _bt_save_invocation_context(context, result, sender, + function_name, + (gpointer)g_memdup(¶m, sizeof(bluetooth_gatt_client_char_prop_info_t))); + } + break; + } + /* Async: Remote Interaction */ + case BT_GATT_READ_CHARACTERISTIC: { + bluetooth_gatt_client_char_prop_info_t param; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t)); + + __bt_service_get_parameters(in_param1, ¶m, + sizeof(bluetooth_gatt_client_char_prop_info_t)); + + result = _bt_gatt_read_characteristic_value(¶m); + if (BLUETOOTH_ERROR_NONE == result) { + BT_INFO("GATT Client: Save Invocation data for characteristic props app[%s]", sender); + + /* Save the informations to invocation */ + _bt_save_invocation_context(context, result, sender, + function_name, + (gpointer)g_memdup(¶m, sizeof(bluetooth_gatt_client_char_prop_info_t))); + } + break; + } + /* Async: Remote Interaction */ + case BT_GATT_READ_DESCRIPTOR_VALUE: { + bluetooth_gatt_client_desc_prop_info_t param; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t)); + + __bt_service_get_parameters(in_param1, ¶m, + sizeof(bluetooth_gatt_client_desc_prop_info_t)); + + result = _bt_gatt_read_descriptor_value(¶m); + if (BLUETOOTH_ERROR_NONE == result) { + BT_INFO("GATT Client: Save Invocation data for Descriptor's props app[%s]", sender); + + /* Save the informations to invocation */ + _bt_save_invocation_context(context, result, sender, + function_name, + (gpointer)g_memdup(¶m, sizeof(bluetooth_gatt_client_desc_prop_info_t))); + } + break; + } + /* Async: Remote Interaction */ + case BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE: { + bluetooth_gatt_client_char_prop_info_t param; + bluetooth_gatt_att_data_t data; + bluetooth_gatt_write_type_e write_type; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + + memset(&data, 0x00, sizeof(bluetooth_gatt_att_data_t)); + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t)); + + __bt_service_get_parameters(in_param1, ¶m, + sizeof(bluetooth_gatt_client_char_prop_info_t)); + __bt_service_get_parameters(in_param2, &data, + sizeof(bluetooth_gatt_att_data_t)); + __bt_service_get_parameters(in_param3, &write_type, + sizeof(bluetooth_gatt_write_type_e)); + + result = _bt_gatt_write_characteristic_value_by_type(¶m , &data, write_type); + if (BLUETOOTH_ERROR_NONE == result) { + BT_INFO("GATT Client: Save Invocation data for characteristic props app[%s]", sender); + + /* Save the informations to invocation */ + _bt_save_invocation_context(context, result, sender, + function_name, + (gpointer)g_memdup(¶m, sizeof(bluetooth_gatt_client_char_prop_info_t))); + } + break; + } + /* Async: Remote Interaction */ + case BT_GATT_WRITE_DESCRIPTOR_VALUE: { + bluetooth_gatt_client_desc_prop_info_t param; + bluetooth_gatt_att_data_t data; + bluetooth_gatt_write_type_e write_type; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + memset(&data, 0x00, sizeof(bluetooth_gatt_att_data_t)); + memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t)); + + __bt_service_get_parameters(in_param1, ¶m, + sizeof(bluetooth_gatt_client_desc_prop_info_t)); + __bt_service_get_parameters(in_param2, &data, + sizeof(bluetooth_gatt_att_data_t)); + __bt_service_get_parameters(in_param3, &write_type, + sizeof(bluetooth_gatt_write_type_e)); + + result = _bt_gatt_write_descriptor_value_by_type(¶m, &data, write_type); + if (BLUETOOTH_ERROR_NONE == result) { + BT_INFO("GATT Client: Save Invocation data for descriptor props app[%s]", sender); + + /* Save the informations to invocation */ + _bt_save_invocation_context(context, result, sender, + function_name, + (gpointer)g_memdup(¶m, sizeof(bluetooth_gatt_client_desc_prop_info_t))); + } + break; + } + case BT_GATT_WATCH_SERVICE_CHANGED_INDICATION: { + gboolean is_enabled; + bluetooth_device_address_t address; + + sender = (char*)g_dbus_method_invocation_get_sender(context); + + __bt_service_get_parameters(in_param1, + &address, sizeof(bluetooth_device_address_t)); + __bt_service_get_parameters(in_param2, &is_enabled, + sizeof(gboolean)); + result = _bt_gatt_watch_service_changed_indication(sender, &address, is_enabled); + BT_INFO("Service changed indication from app [%s]", sender); + + break; + } + case BT_LE_CONN_UPDATE: { + char *sender = NULL; + bluetooth_device_address_t local_address = { {0} }; + bluetooth_le_connection_param_t parameters = {0}; + + sender = (char *)g_dbus_method_invocation_get_sender(context); + + __bt_service_get_parameters(in_param1, &local_address, + sizeof(bluetooth_device_address_t)); + __bt_service_get_parameters(in_param2, ¶meters, + sizeof(bluetooth_le_connection_param_t)); + + result = _bt_le_connection_update(sender, + local_address.addr, + parameters.interval_min, + parameters.interval_max, + parameters.latency, + parameters.timeout); + break; + } +#endif case BT_START_LE_DISCOVERY: { sender = (char *)g_dbus_method_invocation_get_sender(context); result = _bt_start_le_scan(sender); @@ -3189,9 +3496,22 @@ gboolean __bt_service_check_privilege(int function_name, case BT_NETWORK_SERVER_DISCONNECT: case BT_GATT_GET_PRIMARY_SERVICES: +#ifdef TIZEN_GATT_CLIENT + case BT_GATT_GET_SERVICE_PROPERTIES: /* GATT Client */ + case BT_GATT_GET_CHARACTERISTIC_PROPERTIES: /* GATT Client */ + case BT_GATT_WATCH_SERVICE_CHANGED_INDICATION: /* GATT Client */ +#endif case BT_GATT_DISCOVER_CHARACTERISTICS: case BT_GATT_SET_PROPERTY_REQUEST: case BT_GATT_READ_CHARACTERISTIC: +#ifdef TIZEN_GATT_CLIENT + case BT_GATT_READ_DESCRIPTOR_VALUE: /* GATT Client */ + case BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE: /* GATT Client */ + case BT_GATT_WRITE_DESCRIPTOR_VALUE: /* GATT Client */ + case BT_GATT_WATCH_CHARACTERISTIC: /* GATT Client */ + case BT_GATT_CLIENT_REGISTER: /* GATT Client */ + case BT_GATT_CLIENT_UNREGISTER: /* GATT Client */ +#endif case BT_GATT_DISCOVER_CHARACTERISTICS_DESCRIPTOR: case BT_GATT_REGISTER_APPLICATION: case BT_GATT_REGISTER_SERVICE: diff --git a/bt-service-adaptation/services/bt-service-common.c b/bt-service-adaptation/services/bt-service-common.c index b27a103..d2e9ab0 100644 --- a/bt-service-adaptation/services/bt-service-common.c +++ b/bt-service-adaptation/services/bt-service-common.c @@ -1138,6 +1138,28 @@ invocation_info_t* _bt_get_request_info_data(int service_function, char *address return NULL; } +#ifdef TIZEN_GATT_CLIENT +/*amit*/ +invocation_info_t* _bt_get_request_info_data_from_function_name(int service_function) +{ + GSList *l; + invocation_info_t *req_info = NULL; + + BT_DBG("+"); + + /* Get method invocation context */ + for (l = _bt_get_invocation_list(); l != NULL; l = g_slist_next(l)) { + req_info = l->data; + if (req_info == NULL || req_info->service_function != service_function) + continue; + return req_info; + } + + BT_DBG("-"); + return NULL; +} +#endif + void _bt_set_device_values(gboolean connected, int state) { int bt_device_state = VCONFKEY_BT_DEVICE_NONE; diff --git a/bt-service-adaptation/services/bt-service-event-receiver.c b/bt-service-adaptation/services/bt-service-event-receiver.c index c464f28..bdb14fe 100644 --- a/bt-service-adaptation/services/bt-service-event-receiver.c +++ b/bt-service-adaptation/services/bt-service-event-receiver.c @@ -214,6 +214,8 @@ static gboolean __bt_handle_oal_events(gpointer data) case OAL_EVENT_RSSI_ALERT_RECEIVED: if (device_cb) device_cb(event_type, event_data); + if (adapter_gatt_cb) + adapter_gatt_cb(event_type, event_data); break; case OAL_EVENT_DEVICE_PROPERTIES: if (audio_event_cb) { @@ -330,6 +332,31 @@ static gboolean __bt_handle_oal_events(gpointer data) if (adapter_le_cb) adapter_le_cb(event_type, event_data); break; +#ifdef TIZEN_GATT_CLIENT + case OAL_EVENT_GATTC_DISCONNECTION_COMPLETED: + case OAL_EVENT_GATTC_SERVICE_SEARCH_RESULT: + case OAL_EVENT_GATTC_SERVICE_SEARCH_DONE: + case OAL_EVENT_GATTC_INCL_SRVC_SERACH_RESULT: + case OAL_EVENT_GATTC_CHARAC_SERACH_RESULT: + case OAL_EVENT_GATTC_DESC_SERACH_RESULT: + case OAL_EVENT_GATTC_READ_CHARAC: + case OAL_EVENT_GATTC_WRITE_CHARAC: + case OAL_EVENT_GATTC_READ_DESCR: + case OAL_EVENT_GATTC_WRITE_DESCR: + case OAL_EVENT_GATTC_SERVICE_CHANGED_IND: + case OAL_EVENT_GATTC_MTU_EXCHANGE_COMPLETED: + case OAL_EVENT_GATTC_REMOTE_RSSI: + case OAL_EVENT_GATTC_NOTIFICATION_REGISTERED: + case OAL_EVENT_GATTC_NOTIFICATION_DEREGISTERED: + case OAL_EVENT_GATTC_NOTIFY_DATA: + case OAL_EVENT_GATTC_CONNECTION_COMPLETED: + case OAL_EVENT_GATTC_REGISTRATION: + if (adapter_gatt_cb) + adapter_gatt_cb(event_type, event_data); + if (adapter_le_cb) + adapter_le_cb(event_type, event_data); + break; +#endif case OAL_EVENT_BLE_DISCOVERY_STARTED: case OAL_EVENT_BLE_DISCOVERY_STOPPED: case OAL_EVENT_BLE_REMOTE_DEVICE_FOUND: diff --git a/bt-service-adaptation/services/bt-service-event-sender.c b/bt-service-adaptation/services/bt-service-event-sender.c index ed22b0e..b2e97fd 100644 --- a/bt-service-adaptation/services/bt-service-event-sender.c +++ b/bt-service-adaptation/services/bt-service-event-sender.c @@ -123,6 +123,12 @@ int _bt_send_event(int event_type, int event, GVariant *param) path = BT_GATT_SERVER_PATH; break; #endif +#ifdef TIZEN_GATT_CLIENT + case BT_GATT_CLIENT_EVENT: + path = BT_GATT_CLIENT_PATH; + break; +#endif + default: BT_ERR("Unknown event"); return BLUETOOTH_ERROR_INTERNAL; @@ -437,6 +443,20 @@ int _bt_send_event(int event_type, int event, GVariant *param) case BLUETOOTH_EVENT_AVRCP_DELAY_CHANGED: signal = BT_MEDIA_DELAY_CHANGE; break; +#ifdef TIZEN_GATT_CLIENT + case BLUETOOTH_EVENT_GATT_SERVER_CONNECTED: /* GATT Server and Client */ + signal = BT_GATT_SERVER_CONNECTED; + break; + case BLUETOOTH_EVENT_GATT_SERVER_DISCONNECTED: /* GATT Client and Server */ + signal = BT_GATT_SERVER_DISCONNECTED; + break; + case BLUETOOTH_EVENT_GATT_CLIENT_CONNECTED: /* GATT Server and Client */ + signal = BT_GATT_CLIENT_CONNECTED; + break; + case BLUETOOTH_EVENT_GATT_CLIENT_DISCONNECTED: /* GATT Client and Server */ + signal = BT_GATT_CLIENT_DISCONNECTED; + break; +#else case BLUETOOTH_EVENT_GATT_CONNECTED: signal = BT_GATT_CONNECTED; BT_INFO_C("### Connected [GATT]"); @@ -445,6 +465,7 @@ int _bt_send_event(int event_type, int event, GVariant *param) signal = BT_GATT_DISCONNECTED; BT_INFO_C("### Disconnected [GATT]"); break; +#endif case BLUETOOTH_EVENT_GATT_ATT_MTU_CHANGED: signal = BT_GATT_REQ_ATT_MTU_CHANGED; break; @@ -459,6 +480,21 @@ int _bt_send_event(int event_type, int event, GVariant *param) signal = BT_GATT_SERVER_NOTIFICATION_COMPLETED; break; #endif +#ifdef TIZEN_GATT_CLIENT + case BLUETOOTH_EVENT_GATT_READ_CHAR: /* GATT Client */ + signal = BT_GATT_CLIENT_READ_CHAR; + break; + case BLUETOOTH_EVENT_GATT_WRITE_CHAR: /* GATT Client */ + signal = BT_GATT_CLIENT_WRITE_CHAR; + break; + case BLUETOOTH_EVENT_GATT_READ_DESC: /* GATT Client */ + signal = BT_GATT_CLIENT_READ_DESC; + break; + case BLUETOOTH_EVENT_GATT_WRITE_DESC: /* GATT Client */ + signal = BT_GATT_CLIENT_WRITE_DESC; + break; +#endif + case BLUETOOTH_EVENT_IPSP_INIT_STATE_CHANGED: signal = BT_IPSP_INITIALIZED; break; diff --git a/bt-service-adaptation/services/device/bt-service-core-device.c b/bt-service-adaptation/services/device/bt-service-core-device.c index 2955a8d..58b7518 100644 --- a/bt-service-adaptation/services/device/bt-service-core-device.c +++ b/bt-service-adaptation/services/device/bt-service-core-device.c @@ -46,6 +46,10 @@ #endif #include "bt-service-device-internal.h" +#ifdef TIZEN_GATT_CLIENT +#include "bt-service-gatt.h" +#endif + /* OAL headers */ #include #include @@ -120,6 +124,36 @@ static int bond_retry_count; static char *passkey_watcher; static GSList *pin_info_list = NULL; +#ifdef TIZEN_GATT_CLIENT +typedef struct { + char *address; + float interval_min; + float interval_max; + GSList *senders; +} bt_connected_le_dev_t; + +typedef struct { + char *sender; + float interval_min; + float interval_max; + guint16 latency; + guint16 time_out; + float key; +} bt_le_conn_param_t; + +static GSList *le_connected_dev_list = NULL; + +#define BT_LE_CONN_INTERVAL_MIN 7.5 /* msec */ +#define BT_LE_CONN_INTERVAL_MAX 4000 /* msec */ +#define BT_LE_CONN_SUPER_TO_MIN 100 /* msec */ +#define BT_LE_CONN_SUPER_TO_MAX 32000 /* msec */ +#define BT_LE_CONN_SLAVE_LATENCY_MAX 499 +#define BT_LE_CONN_TO_SPLIT 10 /* msec */ +#define BT_LE_CONN_INTERVAL_SPLIT 1.25 /* msec */ + +static void _bt_handle_le_connected_dev_info(const char *address, gboolean connected); +#endif + /* Forward declaration */ static void __bt_device_event_handler(int event_type, gpointer event_data); static void __bt_device_remote_device_found_callback(gpointer event_data, gboolean is_ble); @@ -1337,6 +1371,14 @@ static void __bt_device_conn_state_changed_callback(event_dev_conn_status_t *acl /* Update local cache */ _bt_update_remote_dev_property(address, DEV_PROP_CONNECTED, (void *)&conn_info); +#ifdef TIZEN_GATT_CLIENT + /*handle LE connected device info*/ + if (type) { + BT_DBG("handle LE connected device info"); + _bt_handle_le_connected_dev_info(address, connected); + } +#endif + BT_DBG("-"); } @@ -1916,6 +1958,10 @@ gboolean _bt_is_device_connected(bluetooth_device_address_t *device_address, int case BT_PROFILE_CONN_HSP: svc_id = HFP_HS_SERVICE_ID; /* Remote is HFP HF Unit */ break; +#ifdef TIZEN_GATT_CLIENT + case BT_PROFILE_CONN_GATT: + return _bt_is_remote_gatt_device_connected(device_address); /* Remote is GATT client or Server */ +#endif default: BT_DBG("Unknown svc_type: %d", svc_type); return FALSE; @@ -2100,3 +2146,287 @@ int _bt_unset_pin_code(bluetooth_device_address_t *device_address) BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } + +#ifdef TIZEN_GATT_CLIENT +static bt_connected_le_dev_t *__bt_get_le_connected_dev_info(const char *address) +{ + GSList *l = NULL; + bt_connected_le_dev_t *dev; + + if (!address) + return NULL; + + for (l = le_connected_dev_list; l; l = g_slist_next(l)) { + dev = l->data; + + if (g_strcmp0(dev->address, address) == 0) + return dev; + } + return NULL; +} + +static void __bt_le_conn_param_free(void *data) +{ + bt_le_conn_param_t *param = (bt_le_conn_param_t *)data; + + BT_DBG("%s", param->sender); + g_free(param->sender); + g_free(param); +} + +static void _bt_add_le_connected_dev_info(const char *address) +{ + bt_connected_le_dev_t *dev = NULL; + + if (!address) + return; + + dev = g_malloc0(sizeof(bt_connected_le_dev_t)); + dev->address = g_strdup(address); + + le_connected_dev_list = g_slist_append(le_connected_dev_list, dev); + + return; +} + +static void _bt_remove_le_connected_dev_info(const char *address) +{ + bt_connected_le_dev_t *dev = NULL; + + if (!address) + return; + + dev = __bt_get_le_connected_dev_info(address); + if (!dev) + return; + + g_slist_free_full(dev->senders, __bt_le_conn_param_free); + le_connected_dev_list = g_slist_remove(le_connected_dev_list, dev); + g_free(dev->address); + g_free(dev); + + return; +} + + +static void _bt_handle_le_connected_dev_info(const char *address, gboolean connected) +{ + BT_DBG("+"); + + if (connected) + _bt_add_le_connected_dev_info(address); + else + _bt_remove_le_connected_dev_info(address); +} + +static bt_le_conn_param_t *__bt_get_le_conn_param_info(bt_connected_le_dev_t *dev, const char *sender) +{ + GSList *l = NULL; + bt_le_conn_param_t *param = NULL; + + if (!dev || !sender) + return NULL; + + for (l = dev->senders; l; l = g_slist_next(l)) { + param = l->data; + if (g_strcmp0(param->sender, sender) == 0) + return param; + } + + return NULL; +} + +static gint __bt_compare_le_conn_param_key(gpointer *a, gpointer *b) +{ + bt_le_conn_param_t *parama = (bt_le_conn_param_t *)a; + bt_le_conn_param_t *paramb = (bt_le_conn_param_t *)b; + + return parama->key > paramb->key; +} + + +int _bt_add_le_conn_param_info(const char *address, const char *sender, + float interval_min, float interval_max, guint16 latency, guint16 time_out) +{ + bt_connected_le_dev_t *dev = NULL; + bt_le_conn_param_t *param = NULL; + bt_le_conn_param_t *data = NULL; + + BT_DBG("+"); + + if (!address || !sender) + return BLUETOOTH_ERROR_INVALID_PARAM; + + dev = __bt_get_le_connected_dev_info(address); + if (!dev) + return BLUETOOTH_ERROR_INTERNAL; + + param = __bt_get_le_conn_param_info(dev, sender); + + data = g_malloc0(sizeof(bt_le_conn_param_t)); + data->sender = g_strdup(sender); + data->interval_min = interval_min; + data->interval_max = interval_max; + data->latency = latency; + data->time_out = time_out; + data->key = interval_min + (interval_max - interval_min)/2; + + if (param == NULL) { + BT_DBG("Add param %s %s %f %f", address, sender, interval_min, interval_max); + dev->senders = g_slist_append(dev->senders, data); + } else { + BT_DBG("Update param %s %s %f %f", address, sender, interval_min, interval_max); + dev->senders = g_slist_remove(dev->senders, param); + g_free(param->sender); + g_free(param); + dev->senders = g_slist_append(dev->senders, data); + } + + /* Sorting. First element have the minimum interval */ + dev->senders = g_slist_sort(dev->senders, + (GCompareFunc)__bt_compare_le_conn_param_key); + + return BLUETOOTH_ERROR_NONE; +} + + +static int __bt_le_set_conn_parameter(const char *address, + float interval_min, float interval_max, + guint16 latency, guint16 time_out) +{ + bt_address_t dev_addr = { {0} }; + guint32 min, max, to; + + BT_INFO("Min interval: %f, Max interval: %f, Latency: %u, Supervision timeout: %u", + interval_min, interval_max, latency, time_out); + + min = interval_min / BT_LE_CONN_INTERVAL_SPLIT; + max = interval_max / BT_LE_CONN_INTERVAL_SPLIT; + to = time_out / BT_LE_CONN_TO_SPLIT; + + BT_INFO("updating: Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d", + min, max, latency, to); + + _bt_convert_addr_string_to_type(dev_addr.addr, address); + + return gattc_conn_param_update(&dev_addr, min, max, latency, to); +} + +int _bt_remove_le_conn_param_info(const char *address, const char *sender) +{ + bt_connected_le_dev_t *dev = NULL; + bt_le_conn_param_t *param = NULL; + + if (!address || !sender) + return BLUETOOTH_ERROR_INVALID_PARAM; + + dev = __bt_get_le_connected_dev_info(address); + if (!dev) + return BLUETOOTH_ERROR_INTERNAL; + + param = __bt_get_le_conn_param_info(dev, sender); + if (param) { + BT_DBG("Remove param %s %s ", address, sender); + dev->senders = g_slist_remove(dev->senders, param); + g_free(param->sender); + g_free(param); + } + + return BLUETOOTH_ERROR_NONE; +} + + +int _bt_le_connection_update(const char *sender, + unsigned char *device_address, + float interval_min, float interval_max, + guint16 latency, guint16 time_out) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + guint32 min_supervision_to; + bt_connected_le_dev_t *dev = NULL; + bt_le_conn_param_t *param = NULL; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(device_address, return); + + BT_INFO("Sender %s, Min interval: %f, Max interval: %f, Latency: %u, Supervision timeout: %u", + sender, interval_min, interval_max, latency, time_out); + + if (interval_min > interval_max || + interval_min < BT_LE_CONN_INTERVAL_MIN || + interval_max > BT_LE_CONN_INTERVAL_MAX) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + if (time_out < BT_LE_CONN_SUPER_TO_MIN || + time_out > BT_LE_CONN_SUPER_TO_MAX) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + if (latency > BT_LE_CONN_SLAVE_LATENCY_MAX) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + /* + * The Supervision_Timeout in milliseconds shall be larger than + * (1 + Conn_Latency) * Conn_Interval_Max * 2, + * where Conn_Interval_Max is given in milliseconds. + */ + + min_supervision_to = (1 + latency) * interval_max * 2; + if (time_out <= min_supervision_to) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + _bt_convert_addr_type_to_string(address, device_address); + BT_DBG("Remote device address: %s", address); + + _bt_add_le_conn_param_info(address, sender, interval_min, interval_max, 0, 2000); + + dev = __bt_get_le_connected_dev_info(address); + if (dev == NULL) { + BT_DBG("device not found in the list"); + ret = BLUETOOTH_ERROR_NOT_CONNECTED; + goto fail; + } + + if (g_slist_length(dev->senders) == 1) + goto update; + else { + param = dev->senders->data; + + BT_DBG("dev %f, param %f, input %f", dev->interval_min, param->interval_min, interval_min); + + if (dev->interval_min == param->interval_min && dev->interval_max == param->interval_max) { + BT_DBG("Skip due to same interval"); + return ret; + } + + interval_min = param->interval_min; + interval_max = param->interval_max; + } + +update: + ret = __bt_le_set_conn_parameter(address, interval_min, interval_max, latency, time_out); + + if (ret != OAL_STATUS_SUCCESS) { + _bt_remove_le_conn_param_info(address, sender); + BT_DBG("fail to update the LE connection parameter"); + ret = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + BT_DBG("updated LE connection parameter"); + dev->interval_min = interval_min; + dev->interval_max = interval_max; + + return BLUETOOTH_ERROR_NONE; +fail: + return ret; +} + +#endif diff --git a/bt-service-adaptation/services/gatt/bt-service-gatt.c b/bt-service-adaptation/services/gatt/bt-service-gatt.c index 88e39fd..54bb798 100644 --- a/bt-service-adaptation/services/gatt/bt-service-gatt.c +++ b/bt-service-adaptation/services/gatt/bt-service-gatt.c @@ -37,6 +37,9 @@ #include "bt-service-gatt.h" #include "bt-service-core-device.h" #include "bt-service-core-adapter-le.h" +#ifdef TIZEN_GATT_CLIENT +#include "bluetooth-gatt-client-api.h" +#endif #include #include @@ -51,12 +54,41 @@ #define BT_UUID_STRING_MAX 64 #define BT_SENDER_MAX_LENGTH 50 #define MAX_APPS_SUPPORTED 11 /* Slot 0 is not used */ + +#ifdef TIZEN_GATT_CLIENT +#define NUM_UUID 20 +#else #define NUM_UUID 10 +#endif + + #define UUID_MAX_LEN 50 #define BDADDR_ANY (&(bluetooth_device_address_t) {{0, 0, 0, 0, 0, 0} }) +#ifdef TIZEN_GATT_CLIENT +char uuid_list[NUM_UUID][BT_UUID_STRING_MAX] = {"0000b00b-0000-0000-f065-080080fa49b5", /* Used by BLEAPP */ + "0000b00b-1111-1111-0123-456789ab0cd2", /* Used by BLEAPP */ + "0000b00b-2222-1111-0123-456789ab0cd2", + "0000b00b-3333-1111-0123-456789ab0cd2", + "0000b00b-4444-1111-0123-456789ab0cd2", + "0000b00b-5555-1111-0123-456789ab0cd2", + "0000b00b-6666-1111-0123-456789ab0cd2", + "0000b00b-7777-1111-0123-456789ab0cd2", + "0000b00b-8888-1111-0123-456789ab0cd2", + "0000b00b-9999-1111-0123-456789ab0cd2", + "0000b00b-aaaa-1111-0123-456789ab0cd2", + "0000b00b-bbbb-1111-0123-456789ab0cd2", + "0000b00b-cccc-1111-0123-456789ab0cd2", + "0000b00b-dddd-1111-0123-456789ab0cd2", + "0000b00b-eeee-1111-0123-456789ab0cd2", + "0000b00b-ffff-1111-0123-456789ab0cd2", + "0000b00c-0000-1111-0123-456789ab0cd2", + "0000b00c-1111-1111-0123-456789ab0cd2", + "0000b00c-2222-1111-0123-456789ab0cd2", + "0000b00c-3333-1111-0123-456789ab0cd2"}; +#else char uuid_list[NUM_UUID][BT_UUID_STRING_MAX] = {"0000b00b-0000-0000-f065-080080fa49b5", /* Used by BLEAPP */ "0000b00b-1111-1111-0123-456789ab0cd2", /* Used by BLEAPP */ "0000b00b-2222-1111-0123-456789ab0cd2", @@ -67,8 +99,82 @@ char uuid_list[NUM_UUID][BT_UUID_STRING_MAX] = {"0000b00b-0000-0000-f065-080080f "0000b00b-7777-1111-0123-456789ab0cd2", "0000b00b-8888-1111-0123-456789ab0cd2", "0000b00b-9999-1111-0123-456789ab0cd2"}; +#endif + +#ifdef TIZEN_GATT_CLIENT +/* Reserved GATT client Instance UUID. This is used only internally by bt-service */ +#define DEFAULT_GATT_CLIENT_UUID "0000a00a-1111-1111-0123-456789abcdef" + +static int gatt_default_client = -1; + +struct gatt_out_conn_info_t { + int client_id; /* This value unique identifies a GATT Client instance */ + char *addr; /* Remote GATT Server address */ +}; + +/* Linked List of outgoing gatt connection list + Note: This is valid only for local GATT client */ +static GSList *outgoing_gatt_conn_list = NULL; + +/* GATT Server Info(Local Client) List Structure */ +struct gatt_server_info_t { + int connection_id; /* This value will uniquely identify a GATT client-server connection */ + int client_id; /* This value unique identifies a GATT Client instance */ + char *addr; /* Remote GATT Server address */ +}; + +/* Linked List of connected Remote GATT Servers */ +static GSList *gatt_server_info_list = NULL; + +typedef struct { + gboolean is_changed; + unsigned char uuid[BLUETOOTH_UUID_HEX_MAX_LEN]; /* If any service added */ +} bt_gatt_svc_changed_info_t; + + +typedef struct { + int conn_id; + // bluetooth_device_address_t address; /* Remote BLE Device Address */ + GSList *services; /* List of all services of above remote device */ + int count; /* Number of services browsed from remote device */ + bt_gatt_svc_changed_info_t info; +} bt_gatt_service_info_list_t; + +typedef struct { + unsigned char uuid[BLUETOOTH_UUID_HEX_MAX_LEN]; + int inst_id; + int is_primary; + GSList *chars; + GSList *included_svcs; + gboolean is_removed; /* 0 => Service is added, 1=> removed */ +} bt_gatt_service_info_t; + +typedef struct { + unsigned char uuid[BLUETOOTH_UUID_HEX_MAX_LEN]; + int inst_id; + int props; + int val_len; + unsigned char val[BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX]; + GSList *descs; +} bt_gatt_char_info_t; + +typedef struct { + unsigned char uuid[BLUETOOTH_UUID_HEX_MAX_LEN]; + int inst_id; + int val_len; + unsigned char val[BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX]; +} bt_gatt_descriptor_info_t; + +typedef struct { + unsigned char uuid[BLUETOOTH_UUID_HEX_MAX_LEN]; + int inst_id; +} bt_gatt_included_service_info_t; + +GSList *list_gatt_info; +#endif + /* App Information structure */ typedef struct { int adv_handle; @@ -82,6 +188,11 @@ typedef struct { int scan_rsp_len; gboolean is_initialized; GSList *service_handles; +#ifdef TIZEN_GATT_CLIENT + int client_id; /* GATT Client instance ID */ + bluetooth_device_address_t address; /* Remote BLE Device Address */ + gboolean is_watcher_enabled; +#endif } bt_service_app_info_t; /* GATT Server Request Info Structure */ @@ -118,6 +229,24 @@ static int __bt_gatt_send_indication_to_all_connected_clients(bluetooth_gatt_att static void __bt_remove_all_service_handles(int instance_id); +#ifdef TIZEN_GATT_CLIENT +static void __bt_handle_client_instance_registered(event_gattc_register_t *data); +static void __bt_handle_client_connected(event_gattc_conn_t *event_data); +static void __bt_handle_client_disconnected(event_gattc_conn_t *event_data); +static void __bt_handle_client_service_search_completed(event_gattc_conn_status_t *event_data); +static void __bt_handle_client_service_search_result(event_gattc_service_result_t *event_data); +static void __bt_handle_client_characteristic_search_result( + event_gattc_characteristic_result_t *event_data); +static void __bt_handle_client_descriptor_search_result(event_gattc_descriptor_result_t *event_data); +static void __bt_handle_client_characteristic_read_data(event_gattc_read_data *event_data); +static void __bt_handle_client_descriptor_read_data(event_gattc_read_data *event_data); +static void __bt_handle_client_characteristic_write_data(event_gattc_write_data *event_data); +static void __bt_handle_client_descriptor_write_data(event_gattc_write_data *event_data); +static int __bt_do_unregister_gatt_instance(int instance_id); +static void __bt_hanlde_le_device_disconnection(event_dev_conn_status_t *event_data); + +#endif + static int __bt_do_unregister_server_instance(int server_instance); /* Linked List of GATT requests from Remote GATT Clients */ @@ -243,6 +372,30 @@ void _bt_get_adv_handle_from_instance(int server_inst, int *adv_handle) } } +#ifdef TIZEN_GATT_CLIENT +char * _bt_gatt_get_default_gatt_client_uuid(void) +{ + return g_strdup(DEFAULT_GATT_CLIENT_UUID); +} + + +static void __bt_register_default_gatt_client() +{ + char *uuid_str; + oal_uuid_t uuid; + + uuid_str = _bt_gatt_get_default_gatt_client_uuid(); + _bt_string_to_uuid(uuid_str, (service_uuid_t*)&uuid); + + BT_INFO("Register Default GATT client uuid [%s]", uuid_str); + + if (OAL_STATUS_SUCCESS != gattc_register(&uuid)) /* for only Smart Control */ + BT_ERR("gattc register failed"); + + g_free(uuid_str); +} +#endif + int _bt_gatt_init(void) { BT_DBG("+"); @@ -254,6 +407,10 @@ int _bt_gatt_init(void) /* Register gatt event handler */ _bt_service_register_event_handler_callback(BT_GATT_MODULE, __bt_gatt_event_handler); +#ifdef TIZEN_GATT_CLIENT + /*In bluedroid product, defacult gatt client is handled differently*/ + __bt_register_default_gatt_client(); +#endif BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } @@ -427,6 +584,57 @@ void _bt_get_previous_scan_rsp_data(bluetooth_scan_resp_data_t *scan, int *len, } } +#ifdef TIZEN_GATT_CLIENT +static int __bt_do_unregister_gatt_instance(int instance_id) +{ + int ret = OAL_STATUS_SUCCESS; + int k; + + BT_INFO("DeAllocate server or client instance ID [%d]", instance_id); + + /* Reset data: instance_id parameter could be either for GATT Server or for GATT client */ + for (k = 1; k < MAX_APPS_SUPPORTED; k++) { + if (numapps[k].instance_id == instance_id) { + BT_INFO("This is a GATT server app, unregister: Slot [%d] vacant", k); + numapps[k].is_initialized = FALSE; + numapps[k].instance_id = -1; + numapps[k].adv_handle = 0; + numapps[k].adv_instance = -1; + memset(numapps[k].sender, 0x00, sizeof(numapps[k].sender)); + memset(numapps[k].uuid, 0x00, sizeof(numapps[k].uuid)); + memset(numapps[k].adv_data.data, 0x00, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX); + memset(numapps[k].scan_rsp.data, 0x00, BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX); + numapps[k].adv_data_len = 0; + numapps[k].scan_rsp_len = 0; + + /* Its a GATT Server Instance */ + ret = gatts_unregister(instance_id); + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("DeAllocate server instance with stack Fail ret: %d", ret); + return BLUETOOTH_ERROR_INTERNAL; + } + break; + } else if (numapps[k].client_id == instance_id) { + BT_INFO("This is a GATT client app, unregister: Slot [%d] vacant", k); + numapps[k].client_id = -1; + numapps[k].is_initialized = FALSE; + memset(numapps[k].sender, 0x00, sizeof(numapps[k].sender)); + memset(numapps[k].uuid, 0x00, sizeof(numapps[k].uuid)); + memset(&numapps[k].address.addr, 0x00, sizeof(bluetooth_device_address_t)); + + /* Its a GATT Client Instance */ + ret = gattc_deregister(instance_id); + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("DeAllocate GATT Client instance with stack Fail ret: %d", ret); + return BLUETOOTH_ERROR_INTERNAL; + } + break; + } + } + return BLUETOOTH_ERROR_NONE; +} +#endif + static int __bt_do_unregister_server_instance(int server_instance) { int ret = OAL_STATUS_SUCCESS; @@ -683,6 +891,25 @@ static void __bt_gatt_handle_pending_request_info(int result, #endif case BT_CONNECT_LE: case BT_DISCONNECT_LE: { +#ifdef TIZEN_GATT_CLIENT + char *addr = (char*)req_info->user_data; + bluetooth_device_address_t address; + + if (!g_strcmp0(addr, (char*)data)) { + BT_INFO("GATT Client connect-disconnect call pending for app [%s] addr [%s]", + req_info->sender, addr); + out_param = g_array_new(FALSE, FALSE, sizeof(gchar)); + _bt_convert_addr_string_to_type(address.addr, addr); + + g_array_append_vals(out_param, (bluetooth_device_address_t*)&address, + sizeof(bluetooth_device_address_t)); + _bt_service_method_return(req_info->context, out_param, result); + + g_free(req_info->user_data); + _bt_free_info_from_invocation_list(req_info); + g_array_free(out_param, TRUE); + } +#else out_param = g_array_new(FALSE, FALSE, sizeof(gchar)); g_array_append_vals(out_param, (bluetooth_device_address_t*)data, @@ -693,7 +920,149 @@ static void __bt_gatt_handle_pending_request_info(int result, _bt_free_info_from_invocation_list(req_info); g_array_free(out_param, TRUE); +#endif + break; + } +#ifdef TIZEN_GATT_CLIENT + case BT_GATT_CLIENT_REGISTER: { + bt_service_app_info_t *param = (bt_service_app_info_t*)data; + BT_INFO("Sender [%s] Request Sender [%s]", param->sender, req_info->sender); + if (!g_strcmp0(req_info->sender, param->sender)) { + BT_DBG("GATT Client app found [%s] created client ID [%d]", + req_info->sender, param->client_id); + + out_param = g_array_new(FALSE, FALSE, sizeof(gchar)); + g_array_append_vals(out_param, ¶m->client_id, sizeof(int)); + _bt_service_method_return(req_info->context, out_param, result); + + g_free(req_info->user_data); + _bt_free_info_from_invocation_list(req_info); + g_array_free(out_param, TRUE); + } + break; + } + case BT_GATT_GET_PRIMARY_SERVICES: { + bt_services_browse_info_t *param = (bt_services_browse_info_t*)data; + char *address = g_malloc0(BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(address, + (unsigned char *)(¶m->device_addr.addr)); + + BT_INFO("Request Sender [%s] address [%s]", req_info->sender, address); + + /* Match address to determine same request */ + if (!g_strcmp0((char*)req_info->user_data, address)) { + BT_DBG("GATT Client app found [%s] Remote address [%s]", + req_info->sender, address); + + out_param = g_array_new(FALSE, FALSE, sizeof(gchar)); + g_array_append_vals(out_param, param, + sizeof(bt_services_browse_info_t)); + + //g_array_append_vals(out_param, ¶m->client_id, sizeof(int)); + _bt_service_method_return(req_info->context, out_param, result); + + g_free(req_info->user_data); + _bt_free_info_from_invocation_list(req_info); + g_array_free(out_param, TRUE); + } + g_free(address); + break; + } + case BT_GATT_GET_SERVICE_PROPERTIES: { + bt_char_browse_info_t param; + memcpy((void*)¶m, data, sizeof(bt_char_browse_info_t)); + //bt_char_browse_info_t *param = (bt_char_browse_info_t*)data; + BT_INFO("Request Sender [%s]", req_info->sender); + bluetooth_gatt_client_svc_prop_info_t *prop = (bluetooth_gatt_client_svc_prop_info_t*)req_info->user_data; + + /* Match both address and service properties to determine same request */ + if (!memcmp(param.device_addr.addr, + prop->device_address.addr, + sizeof(bluetooth_device_address_t)) && + !memcmp(param.svc_uuid, prop->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) && + param.svc_inst_id == prop->svc.instance_id) { + BT_INFO("Returning Service properties"); + + out_param = g_array_new(FALSE, FALSE, sizeof(gchar)); + g_array_append_vals(out_param, ¶m, sizeof(bt_char_browse_info_t)); + _bt_service_method_return(req_info->context, out_param, result); + + g_free(req_info->user_data); + _bt_free_info_from_invocation_list(req_info); + g_array_free(out_param, TRUE); + } + break; + } + case BT_GATT_GET_CHARACTERISTIC_PROPERTIES: { + bt_descriptor_browse_info_t *param = (bt_descriptor_browse_info_t*)data; + + BT_INFO("Request Sender [%s]", req_info->sender); + bluetooth_gatt_client_char_prop_info_t *prop = (bluetooth_gatt_client_char_prop_info_t*)req_info->user_data; + + /* Match both address, service properties &char properties to determine same request */ + if (!memcmp(param->device_addr.addr, + prop->device_address.addr, + sizeof(bluetooth_device_address_t)) && + !memcmp(param->svc_uuid, prop->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) && + param->svc_inst_id == prop->svc.instance_id && + !memcmp(param->char_uuid, prop->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) && + param->char_inst_id == prop->characteristic.instance_id) { + BT_INFO("Returning Characteristic properties"); + out_param = g_array_new(FALSE, FALSE, sizeof(gchar)); + g_array_append_vals(out_param, param, sizeof(bt_descriptor_browse_info_t)); + _bt_service_method_return(req_info->context, out_param, result); + + g_free(req_info->user_data); + _bt_free_info_from_invocation_list(req_info); + g_array_free(out_param, TRUE); + } + break; + } + case BT_GATT_READ_CHARACTERISTIC: + case BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE: { + bluetooth_gatt_client_char_prop_info_t *param = (bluetooth_gatt_client_char_prop_info_t*)data; + BT_INFO("Request Sender [%s]", req_info->sender); + + char *addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + bluetooth_gatt_client_char_prop_info_t *prop = (bluetooth_gatt_client_char_prop_info_t*)req_info->user_data; + _bt_convert_addr_type_to_string(addr, prop->device_address.addr); + + if (!memcmp(param, prop, sizeof(bluetooth_gatt_client_char_prop_info_t))) { + BT_INFO("Gatt Char read or write request matched for address [%s]", addr); + out_param = g_array_new(FALSE, FALSE, sizeof(gchar)); + g_array_append_vals(out_param, param, sizeof(bluetooth_gatt_client_char_prop_info_t)); + _bt_service_method_return(req_info->context, out_param, result); + + g_free(req_info->user_data); + _bt_free_info_from_invocation_list(req_info); + g_array_free(out_param, TRUE); + } + g_free(addr); + break; + } + case BT_GATT_READ_DESCRIPTOR_VALUE: + case BT_GATT_WRITE_DESCRIPTOR_VALUE: { + bluetooth_gatt_client_desc_prop_info_t *param = (bluetooth_gatt_client_desc_prop_info_t*)data; + BT_INFO("Request Sender [%s]", req_info->sender); + + char *addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + bluetooth_gatt_client_desc_prop_info_t *prop = (bluetooth_gatt_client_desc_prop_info_t*)req_info->user_data; + _bt_convert_addr_type_to_string(addr, prop->device_address.addr); + + if (!memcmp(param, prop, sizeof(bluetooth_gatt_client_desc_prop_info_t))) { + BT_INFO("Descriptor read or write request matched for address [%s]", addr); + out_param = g_array_new(FALSE, FALSE, sizeof(gchar)); + g_array_append_vals(out_param, param, sizeof(bluetooth_gatt_client_desc_prop_info_t)); + _bt_service_method_return(req_info->context, out_param, result); + + g_free(req_info->user_data); + _bt_free_info_from_invocation_list(req_info); + g_array_free(out_param, TRUE); + } + g_free(addr); + break; } +#endif default: break; } @@ -988,36 +1357,62 @@ static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn_id return NULL; } +#ifdef TIZEN_GATT_CLIENT +static struct gatt_server_info_t *__bt_find_remote_gatt_server_info(char *address) +{ + GSList *l; + struct gatt_server_info_t *info = NULL; + for (l = gatt_server_info_list; l != NULL; l = g_slist_next(l)) { + info = (struct gatt_server_info_t*)l->data; + if (info == NULL) + continue; + + if (!g_strcmp0(info->addr, address)) { + BT_INFO("Remote GATT Server found addr[%s]", info->addr); + return info; + } + } + return NULL; +} + +static struct gatt_out_conn_info_t* __bt_find_gatt_outgoing_conn_info(char *address) +{ + GSList *l; + struct gatt_out_conn_info_t *info = NULL; + for (l = outgoing_gatt_conn_list; l != NULL; l = g_slist_next(l)) { + info = (struct gatt_out_conn_info_t*)l->data; + if (info == NULL) + continue; + + if (!g_strcmp0(info->addr, address)) { + BT_INFO("Outgoing connection info found addr[%s]", info->addr); + return info; + } + } + return NULL; +} +#endif + + + + +#ifdef TIZEN_GATT_CLIENT static void __bt_handle_gatt_server_connection_state(event_gatts_conn_t *event) { int result = BLUETOOTH_ERROR_NONE; struct gatt_client_info_t *conn_info = NULL; - bt_service_app_info_t *info = NULL; bluetooth_device_address_t dev_addr; - GVariant *param = NULL; - int k; char *address = g_malloc0(BT_ADDRESS_STRING_SIZE); memcpy(dev_addr.addr, event->address.addr, 6); - - /* Check if the just registered Instance ID belongs to BLEAPP or GATT Server */ - for (k = 1; k < MAX_APPS_SUPPORTED; k++) { - info = &numapps[k]; - - if (info->instance_id == event->server_inst) { - BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender); - __bt_gatt_handle_pending_request_info(result, BT_CONNECT_LE, - (bluetooth_device_address_t*)&dev_addr, sizeof(bluetooth_device_address_t)); - - break; - } - } - - /* Send event to BT-API */ + /* REPLY dbus Context to application which called BT_CONNECT_LE. There is status + in this event */ _bt_convert_addr_type_to_string(address, (unsigned char *)dev_addr.addr); + __bt_gatt_handle_pending_request_info(result, BT_CONNECT_LE, + address, BT_ADDRESS_STRING_SIZE); BT_INFO("GATT Server Connedted: Remote Client addr[%s] Server Instance [%d] Connection ID [%d]", address, event->server_inst, event->conn_id); @@ -1027,12 +1422,15 @@ static void __bt_handle_gatt_server_connection_state(event_gatts_conn_t *event) conn_info = __bt_find_remote_gatt_client_info(address); if (!conn_info) { + BT_INFO("Conn Info absent: But no need to Send Local GATT Server Connected event to apps"); +#if 0 param = g_variant_new("(is)", result, address); + /* Send event to application */ - _bt_send_event(BT_GATT_SERVER_EVENT, - BLUETOOTH_EVENT_GATT_CONNECTED, + _bt_send_event(BT_DEVICE_EVENT, + BLUETOOTH_EVENT_GATT_SERVER_CONNECTED, /* Local device is GATT server */ param); - +#endif /* Save Connection info */ conn_info = g_new0(struct gatt_client_info_t, 1); conn_info->addr = g_strdup(address); @@ -1040,7 +1438,7 @@ static void __bt_handle_gatt_server_connection_state(event_gatts_conn_t *event) conn_info->connection_id = event->conn_id; conn_info->instance_id = event->server_inst; gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info); - BT_INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list)); + BT_INFO("Total num of connected Remote GATT Clients [%d]", g_slist_length(gatt_client_info_list)); } g_free(address); @@ -1052,44 +1450,44 @@ static void __bt_handle_gatt_server_disconnection_state(event_gatts_conn_t *even int result = BLUETOOTH_ERROR_NONE; struct gatt_client_info_t *conn_info = NULL; bluetooth_device_address_t dev_addr; - bt_service_app_info_t *info = NULL; - GVariant *param = NULL; - int k; char *address = g_malloc0(BT_ADDRESS_STRING_SIZE); memcpy(dev_addr.addr, event->address.addr, 6); - /* Check if the just registered Instance ID belongs to BLEAPP or GATT Server */ - for (k = 1; k < MAX_APPS_SUPPORTED; k++) { - info = &numapps[k]; + /* REPLY dbus Context to application which called BT_DISCONNECT_LE. There is status + in this event */ + _bt_convert_addr_type_to_string(address, + (unsigned char *)dev_addr.addr); - if (info->instance_id == event->server_inst) { - BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender); - __bt_gatt_handle_pending_request_info(result, BT_DISCONNECT_LE, - (bluetooth_device_address_t*)&dev_addr, sizeof(bluetooth_device_address_t)); + if (NULL == _bt_get_request_info_data(BT_DISCONNECT_LE, address)) { + if (NULL != _bt_get_request_info_data(BT_CONNECT_LE, address)) { + result = BLUETOOTH_ERROR_INTERNAL; - break; + __bt_gatt_handle_pending_request_info(result, BT_CONNECT_LE, + address, BT_ADDRESS_STRING_SIZE); + + BT_ERR("Failed to connect Local GATT Server Remote Client addr[%s]", address); + return; } + } else { + __bt_gatt_handle_pending_request_info(result, BT_DISCONNECT_LE, + address, BT_ADDRESS_STRING_SIZE); } - /* Send event to BT-API */ - _bt_convert_addr_type_to_string(address, - (unsigned char *)dev_addr.addr); - - BT_INFO("GATT Server DisConnected: Remote Client addr[%s] Server Instance [%d] Connection ID [%d]", + BT_INFO("Local GATT Server DisConnected: Remote Client addr[%s] Server Instance [%d] Connection ID [%d]", address, event->server_inst, event->conn_id); - - param = g_variant_new("(is)", result, address); - /* Send event to application */ - _bt_send_event(BT_GATT_SERVER_EVENT, - BLUETOOTH_EVENT_GATT_DISCONNECTED, - param); - /* Remove Connection info */ conn_info = __bt_find_remote_gatt_client_info(address); if (conn_info) { - BT_INFO("Remove GATT client info from List.."); + BT_INFO("No need to Send Local GATT Server Disconnected event to apps, just remove remote client info"); +#if 0 + param = g_variant_new("(is)", result, address); + /* Send event to application */ + _bt_send_event(BT_DEVICE_EVENT, + BLUETOOTH_EVENT_GATT_SERVER_DISCONNECTED, /* Local device is GATT server */ + param); +#endif /* Remove info from List */ gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info); BT_INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list)); @@ -1099,20 +1497,134 @@ static void __bt_handle_gatt_server_disconnection_state(event_gatts_conn_t *even g_free(address); } +#else -static void __bt_handle_gatt_server_write_requested(event_gatts_srvc_write_attr_t *event) +static void __bt_handle_gatt_server_connection_state(event_gatts_conn_t *event) { - char *address; + int result = BLUETOOTH_ERROR_NONE; + struct gatt_client_info_t *conn_info = NULL; + bt_service_app_info_t *info = NULL; bluetooth_device_address_t dev_addr; GVariant *param = NULL; - int result = BLUETOOTH_ERROR_NONE; - gboolean need_resp; - gboolean is_prepare_write; - char *write_val; - GVariant *data = NULL; - int i; - struct gatt_server_req_info *req_info = NULL; - BT_INFO("GATT Server Write Requested"); + int k; + + char *address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + memcpy(dev_addr.addr, event->address.addr, 6); + + + /* Check if the just registered Instance ID belongs to BLEAPP or GATT Server */ + for (k = 1; k < MAX_APPS_SUPPORTED; k++) { + info = &numapps[k]; + + if (info->instance_id == event->server_inst) { + BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender); + __bt_gatt_handle_pending_request_info(result, BT_CONNECT_LE, + (bluetooth_device_address_t*)&dev_addr, sizeof(bluetooth_device_address_t)); + + break; + } + } + + /* Send event to BT-API */ + _bt_convert_addr_type_to_string(address, + (unsigned char *)dev_addr.addr); + + BT_INFO("GATT Server Connedted: Remote Client addr[%s] Server Instance [%d] Connection ID [%d]", + address, event->server_inst, event->conn_id); + + + /* Check if device is already in connected list */ + conn_info = __bt_find_remote_gatt_client_info(address); + + if (!conn_info) { + param = g_variant_new("(is)", result, address); + /* Send event to application */ + _bt_send_event(BT_GATT_SERVER_EVENT, + BLUETOOTH_EVENT_GATT_CONNECTED, + param); + + /* Save Connection info */ + conn_info = g_new0(struct gatt_client_info_t, 1); + conn_info->addr = g_strdup(address); + BT_INFO("Added GATT client addr[%s]", conn_info->addr); + conn_info->connection_id = event->conn_id; + conn_info->instance_id = event->server_inst; + gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info); + BT_INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list)); + } + + g_free(address); +} + +/* GATT Server Dis connected */ +static void __bt_handle_gatt_server_disconnection_state(event_gatts_conn_t *event) +{ + int result = BLUETOOTH_ERROR_NONE; + struct gatt_client_info_t *conn_info = NULL; + bluetooth_device_address_t dev_addr; + bt_service_app_info_t *info = NULL; + GVariant *param = NULL; + int k; + + char *address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + memcpy(dev_addr.addr, event->address.addr, 6); + + /* Check if the just registered Instance ID belongs to BLEAPP or GATT Server */ + for (k = 1; k < MAX_APPS_SUPPORTED; k++) { + info = &numapps[k]; + + if (info->instance_id == event->server_inst) { + BT_INFO("Found GATT Server.. UUID [%s], sender [%s]", info->uuid, info->sender); + __bt_gatt_handle_pending_request_info(result, BT_DISCONNECT_LE, + (bluetooth_device_address_t*)&dev_addr, sizeof(bluetooth_device_address_t)); + + break; + } + } + + /* Send event to BT-API */ + _bt_convert_addr_type_to_string(address, + (unsigned char *)dev_addr.addr); + + BT_INFO("GATT Server DisConnected: Remote Client addr[%s] Server Instance [%d] Connection ID [%d]", + address, event->server_inst, event->conn_id); + + param = g_variant_new("(is)", result, address); + /* Send event to application */ + _bt_send_event(BT_GATT_SERVER_EVENT, + BLUETOOTH_EVENT_GATT_DISCONNECTED, + param); + + /* Remove Connection info */ + conn_info = __bt_find_remote_gatt_client_info(address); + if (conn_info) { + BT_INFO("Remove GATT client info from List.."); + /* Remove info from List */ + gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info); + BT_INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list)); + g_free(conn_info->addr); + g_free(conn_info); + } + + g_free(address); +} +#endif + +static void __bt_handle_gatt_server_write_requested(event_gatts_srvc_write_attr_t *event) +{ + char *address; + bluetooth_device_address_t dev_addr; + GVariant *param = NULL; + int result = BLUETOOTH_ERROR_NONE; + gboolean need_resp; + gboolean is_prepare_write; + char *write_val; + GVariant *data = NULL; + int i; + struct gatt_server_req_info *req_info = NULL; + BT_INFO("GATT Server Write Requested"); memcpy(dev_addr.addr, event->address.addr, 6); @@ -1437,6 +1949,67 @@ static void __bt_gatt_event_handler(int event_type, gpointer event_data) __bt_handle_gatt_mtu_changed_event(mtu_changed); break; } +#ifdef TIZEN_GATT_CLIENT + case OAL_EVENT_GATTC_REGISTRATION: { + BT_INFO("OAL Event: GATT Client instance Registered"); + __bt_handle_client_instance_registered((event_gattc_register_t *) event_data); + break; + } + case OAL_EVENT_GATTC_CONNECTION_COMPLETED: { + BT_INFO("OAL Event: GATT Client Connected"); + __bt_handle_client_connected((event_gattc_conn_t *) event_data); + break; + } + case OAL_EVENT_GATTC_DISCONNECTION_COMPLETED: { + BT_INFO("OAL Event: GATT Client DisConnected"); + __bt_handle_client_disconnected((event_gattc_conn_t *) event_data); + break; + } + case OAL_EVENT_GATTC_SERVICE_SEARCH_RESULT: { + BT_INFO("OAL Event: GATT Client Service Search Result"); + __bt_handle_client_service_search_result((event_gattc_service_result_t *) event_data); + break; + } + case OAL_EVENT_GATTC_SERVICE_SEARCH_DONE: { + BT_INFO("OAL Event: GATT Client Service Completed"); + __bt_handle_client_service_search_completed((event_gattc_conn_status_t *) event_data); + break; + } + case OAL_EVENT_GATTC_CHARAC_SERACH_RESULT: { + BT_INFO("OAL Event: GATT Client Characteristic Search Result"); + __bt_handle_client_characteristic_search_result((event_gattc_characteristic_result_t *) event_data); + break; + } + case OAL_EVENT_GATTC_DESC_SERACH_RESULT: { + BT_INFO("OAL Event: GATT Client Descriptor Search Result"); + __bt_handle_client_descriptor_search_result((event_gattc_descriptor_result_t *) event_data); + break; + } + case OAL_EVENT_GATTC_READ_CHARAC: { + BT_INFO("OAL Event: GATT Client Characteristic Read Data"); + __bt_handle_client_characteristic_read_data((event_gattc_read_data *) event_data); + break; + } + case OAL_EVENT_GATTC_READ_DESCR: { + BT_INFO("OAL Event: GATT Client Descriptor Read Data"); + __bt_handle_client_descriptor_read_data((event_gattc_read_data *) event_data); + break; + } + case OAL_EVENT_GATTC_WRITE_CHARAC: { + BT_INFO("OAL Event: GATT Client Characteristic Write Data"); + __bt_handle_client_characteristic_write_data((event_gattc_write_data *) event_data); + break; + } + case OAL_EVENT_GATTC_WRITE_DESCR: { + BT_INFO("OAL Event: GATT Client Descriptor Write Data"); + __bt_handle_client_descriptor_write_data((event_gattc_write_data *) event_data); + break; + } + case OAL_EVENT_DEVICE_LE_DISCONNECTED: { + BT_INFO("OAL Event: LE device disconnected"); + __bt_hanlde_le_device_disconnection((event_dev_conn_status_t *)event_data); + } +#endif default: break; } @@ -1752,3 +2325,2028 @@ int _bt_get_att_mtu(bluetooth_device_address_t *address, *mtu = (unsigned int)stack_mtu; return BLUETOOTH_ERROR_NONE; } + +#ifdef TIZEN_GATT_CLIENT +static void __bt_convert_byte_ordering(char *data, int data_len, + char *converted_data) +{ + int i, j; + char temp[BLUETOOTH_UUID_HEX_MAX_LEN]; + + memcpy(&temp, data, data_len); + for (i = 0, j = data_len - 1; i < data_len; i++, j--) + converted_data[i] = temp[j]; +} + +/* GATT Client utility static functions */ +static bt_gatt_service_info_list_t * __bt_get_service_info_list(int conn_id) +{ + GSList *l; + bt_gatt_service_info_list_t *info = NULL; + + for (l = list_gatt_info; l != NULL; l = g_slist_next(l)) { + info = (bt_gatt_service_info_list_t*)l->data; + if (info == NULL) + continue; + + if (info->conn_id == conn_id) + return info; + + } + return NULL; +} + +static bt_gatt_service_info_t* __bt_find_matching_service( + bt_gatt_service_info_list_t *svc_list, oal_gatt_srvc_id_t *svc) +{ + GSList *l; + bt_gatt_service_info_t *info = NULL; + + for (l = svc_list->services; l != NULL; l = g_slist_next(l)) { + info = (bt_gatt_service_info_t*)l->data; + if (info == NULL) + continue; + + /* Match UUID and instance ID */ + if (!memcmp(&svc->id.uuid.uuid, &info->uuid, BLUETOOTH_UUID_HEX_MAX_LEN) + && (svc->id.inst_id == info->inst_id)) { + return info; + } + } + return NULL; +} + +static bt_gatt_char_info_t* __bt_find_matching_charc( + bt_gatt_service_info_t *svc_info, oal_gatt_id_t *charc) +{ + GSList *l; + bt_gatt_char_info_t *info = NULL; + + for (l = svc_info->chars; l != NULL; l = g_slist_next(l)) { + info = (bt_gatt_char_info_t*)l->data; + if (info == NULL) + continue; + + /* Match UUID and instance ID */ + if (!memcmp(&charc->uuid.uuid, &info->uuid, BLUETOOTH_UUID_HEX_MAX_LEN) + && (charc->inst_id == info->inst_id)) { + return info; + } + } + return NULL; +} + +static bt_gatt_descriptor_info_t* __bt_find_matching_desc( + bt_gatt_char_info_t *char_info, oal_gatt_id_t *desc) +{ + GSList *l; + bt_gatt_descriptor_info_t *info = NULL; + + for (l = char_info->descs; l != NULL; l = g_slist_next(l)) { + info = (bt_gatt_descriptor_info_t*)l->data; + if (info == NULL) + continue; + + /* Match UUID and instance ID */ + if (!memcmp(&desc->uuid, &info->uuid, BLUETOOTH_UUID_HEX_MAX_LEN) + && (desc->inst_id == info->inst_id)) { + return info; + } + } + return NULL; +} + + +static struct gatt_server_info_t *__bt_find_remote_gatt_server_info_from_conn_id(int conn_id) +{ + GSList *l; + struct gatt_server_info_t *info = NULL; + + for (l = gatt_server_info_list; l != NULL; l = g_slist_next(l)) { + info = (struct gatt_server_info_t*)l->data; + if (info == NULL) + continue; + + if (info->connection_id == conn_id) { + BT_INFO("Remote GATT server found addr[%s]", info->addr); + return info; + } + } + return NULL; +} + +static bt_gatt_service_info_t* __bt_find_removed_service(bt_gatt_service_info_list_t *svc_list) +{ + GSList *l; + bt_gatt_service_info_t *info = NULL; + + for (l = svc_list->services; l != NULL; l = g_slist_next(l)) { + info = (bt_gatt_service_info_t*)l->data; + if (info == NULL) + continue; + + /* Service is marked a removed */ + if (info->is_removed == 1) + return info; + } + return NULL; +} + +static void __bt_remove_service_info_from_list(bt_gatt_service_info_t *svc_info) +{ +#if 0 + GSList *l; + GSList *l1; + GSList *l2; + bt_gatt_char_info_t *charc = NULL; + bt_gatt_included_service_info_t *incl = NULL; + bt_gatt_descriptor_info_t *desc = NULL; + + /* Remove all Characteristic and Descriptors within characteristic */ + for (l = svc_info->chars; l != NULL;) { + charc = (bt_gatt_char_info_t*)l->data; + l = g_slist_next(l); /* Incase if l is removed, saving next to l */ + + if (charc == NULL) + continue; + + /* Inside Characteristic */ + for (l1 = charc->descs; l1 != NULL;) { + + desc = (bt_gatt_descriptor_info_t*)l1->data; + l1 = g_slist_next(l1); + + if (desc == NULL) + continue; + + /* Remove Descriptor */ + charc->descs = g_slist_remove(charc->descs, desc); + g_free(desc); + } + /* Remove Characteristic */ + svc_info->chars = g_slist_remove(svc_info->chars, charc); + g_free(charc); + } + + /* Remove all Included Services */ + for (l2 = svc_info->included_svcs; l2 != NULL;) { + incl = (bt_gatt_included_service_info_t*)l2->data; + l2 = g_slist_next(l2); /* Incase if l is removed, saving next to l */ + + if (incl == NULL) + continue; + + /* Remove included service */ + svc_info->included_svcs = g_slist_remove(svc_info->included_svcs, incl); + g_free(incl); + } +#endif +} + + +static void __bt_build_service_browse_info(int conn_id, + bt_services_browse_info_t* info) +{ + GSList *l; + bt_gatt_service_info_list_t *svc_info_list; + bt_gatt_service_info_t *svc_info; + + service_uuid_t uuid; + struct gatt_server_info_t *conn_info = NULL; + int count = 0; + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + BT_INFO("+"); + + conn_info = __bt_find_remote_gatt_server_info_from_conn_id(conn_id); + + if (!conn_info) + return; + + _bt_convert_addr_string_to_type(info->device_addr.addr, conn_info->addr); + + svc_info_list = __bt_get_service_info_list(conn_id); + + if (!svc_info_list) + return; + + info->count = g_slist_length(svc_info_list->services); + BT_INFO("Total services present in the svc info list for this conn id [%d] is [%d]", + conn_id, info->count); + + for (l = svc_info_list->services; l != NULL; l = g_slist_next(l)) { + svc_info = (bt_gatt_service_info_t*)l->data; + if (svc_info == NULL) + continue; + + memcpy(&uuid.uuid, &svc_info->uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + _bt_uuid_to_string(&uuid, uuid_string); + + BT_INFO("Service UUID formed [%s] strlen [%d]", uuid_string, strlen(uuid_string)); + + /* Fill UUID of service */ + g_strlcpy(info->uuids[count], uuid_string, + BLUETOOTH_UUID_STRING_MAX); + + BT_INFO("Service UUID formed TO be sent [%s] strlen [%d]", + info->uuids[count], strlen(info->uuids[count])); + /* Fill instance ID of service */ + info->inst_id[count] = svc_info->inst_id; + + /* Fill primary service or not info */ + info->primary[count] = svc_info->is_primary; + + /* Increment count of services browsed */ + count++; + } + + BT_INFO("Total services browsed [%d]", count); +} + +static void __bt_build_char_browse_info(int conn_id, + bt_gatt_service_info_t *svc_info, + bt_char_browse_info_t* info) +{ + GSList *l; + bt_gatt_char_info_t *char_info; + service_uuid_t uuid; + + struct gatt_server_info_t *conn_info = NULL; + int count = 0; + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + + BT_INFO("+"); + + conn_info = __bt_find_remote_gatt_server_info_from_conn_id(conn_id); + if (!conn_info) + return; + + /* Fill default data, this will be required even in case of failure */ + _bt_convert_addr_string_to_type(info->device_addr.addr, conn_info->addr); + memcpy(&info->svc_uuid, svc_info->uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + info->svc_inst_id = svc_info->inst_id; + + if (!svc_info->chars) { + BT_ERR("No Chars browsed for address [%s]", conn_info->addr); + return; + } + + info->count = g_slist_length(svc_info->chars); + BT_INFO("Total count of Characteristics [%d]", info->count); + + for (l = svc_info->chars; l != NULL; l = g_slist_next(l)) { + char_info = (bt_gatt_char_info_t*)l->data; + if (char_info == NULL) + continue; + + memcpy(&uuid.uuid, &char_info->uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + _bt_uuid_to_string(&uuid, uuid_string); + + /* Fill UUID of characteristic */ + g_strlcpy(info->uuids[count], uuid_string, + BLUETOOTH_UUID_STRING_MAX); + + /* Fill instance ID of characteristic */ + info->inst_id[count] = char_info->inst_id; + + /* Fill property of characteristic */ + info->props[count] = char_info->props; + + /* Increment count of services browsed */ + count++; + } + BT_INFO("Total characteristics browsed [%d]", count); +} + +static void __bt_build_descriptor_browse_info(int conn_id, + bt_gatt_service_info_t *svc_info, + bt_gatt_char_info_t *char_info, + bt_descriptor_browse_info_t* info) +{ + GSList *l; + bt_gatt_descriptor_info_t *desc_info; + + service_uuid_t uuid; + struct gatt_server_info_t *conn_info = NULL; + int count = 0; + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + + conn_info = __bt_find_remote_gatt_server_info_from_conn_id(conn_id); + + /* Fill default data, this will be required even in case of failure */ + _bt_convert_addr_string_to_type(info->device_addr.addr, conn_info->addr); + memcpy(&info->svc_uuid, svc_info->uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + info->svc_inst_id = svc_info->inst_id; + memcpy(&info->char_uuid, char_info->uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + info->char_inst_id = char_info->inst_id; + + if (!char_info->descs) { + BT_ERR("No Descriptors browsed for address [%s]", conn_info->addr); + return; + } + + info->count = g_slist_length(char_info->descs); + BT_INFO("Total count of Descriptors [%d]", info->count); + + for (l = char_info->descs; l != NULL; l = g_slist_next(l)) { + desc_info = (bt_gatt_descriptor_info_t*)l->data; + if (desc_info == NULL) + continue; + + memcpy(&uuid.uuid, &desc_info->uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + _bt_uuid_to_string(&uuid, uuid_string); + + /* Fill UUID of Descriptor */ + g_strlcpy(info->uuids[count], uuid_string, + BLUETOOTH_UUID_STRING_MAX); + + /* Fill instance ID of Descriptor */ + info->inst_id[count] = desc_info->inst_id; + + /* Fill property of the parent characteristic of this descriptor */ + info->char_props_map = char_info->props; + + /* Increment count of Descriptor browsed */ + count++; + } + + BT_INFO("Total descriptors browsed [%d]", count); +} + + +static void __bt_cleanup_remote_services(struct gatt_server_info_t *conn_info) +{ + GSList *l; + GSList *ll; + GSList *lll; + GSList *llll; + + bt_gatt_service_info_list_t * svc_info_list = NULL; + bt_gatt_service_info_t *svc = NULL; + bt_gatt_char_info_t *chr = NULL; + bt_gatt_descriptor_info_t *desc = NULL; + bt_gatt_included_service_info_t *incl_svc = NULL; + + BT_INFO("Start Cleanup of all services"); + + svc_info_list = __bt_get_service_info_list(conn_info->connection_id); + if (!svc_info_list) { + BT_INFO("Could not find Svc Info list for the connection ID [%d]", + conn_info->connection_id); + return; + } + + BT_INFO("Num Services [%d]", g_slist_length(svc_info_list->services)); + for (l = svc_info_list->services; l;) { + svc = (bt_gatt_service_info_t*)l->data; + l = g_slist_next(l); + if (svc == NULL) + continue; + + BT_INFO("Service info Is Prim[%d] Inst ID [%d]", + svc->is_primary, svc->inst_id); + BT_INFO("Num chars [%d]", g_slist_length(svc->chars)); + /* Delete all chars and its descriptors */ + for (ll = svc->chars; ll;) { + chr = (bt_gatt_char_info_t*)ll->data; + ll = g_slist_next(ll); + if (chr == NULL) + continue; + + BT_INFO("Num descs [%d]", g_slist_length(chr->descs)); + for (lll = chr->descs; lll;) { + desc = (bt_gatt_descriptor_info_t *)lll->data; + lll = g_slist_next(lll); + if (desc == NULL) + continue; + chr->descs = g_slist_remove(chr->descs, desc); + g_free(desc); + } + svc->chars = g_slist_remove(svc->chars, chr); + g_free(chr); + } + + BT_INFO("Num incl svcs [%d]", g_slist_length(svc->included_svcs)); + /* Delete all included services */ + for (llll = svc->included_svcs; llll;) { + incl_svc = (bt_gatt_included_service_info_t*)llll->data; + llll = g_slist_next(llll); + if (incl_svc == NULL) + continue; + + svc->included_svcs = g_slist_remove(svc->included_svcs, incl_svc); + g_free(incl_svc); + } + svc_info_list->services = g_slist_remove(svc_info_list->services, svc); + g_free(svc); + } + g_free(svc_info_list); + BT_INFO("Cleanup of all services done"); +} + +int _bt_register_gatt_client_instance(const char *sender, + bluetooth_device_address_t *address) +{ + int ret = OAL_STATUS_SUCCESS; + char *uuid_string = NULL; + int slot = -1; + int k; + oal_uuid_t uuid; + + /* App should ensure that it should not send */ + BT_INFO("###Check on which instance GATT Client instance can be initialized...."); + for (k = 1; k < MAX_APPS_SUPPORTED; k++) { + if (numapps[k].is_initialized == 1) { + BT_INFO("Instance ID [%d] is already in use..Check next slot", + numapps[k].instance_id); + } else { + slot = k; + BT_INFO("Time to register GATT client instancer..UUID to be used is [%s] slot [%d]", + uuid_list[slot-1], slot); + break; + } + } + + if (slot == -1) { + BT_ERR("No Slot if free for GATT Client registration.."); + return BLUETOOTH_ERROR_REGISTRATION_FAILED; + } + + uuid_string = g_malloc0(BT_UUID_STRING_MAX); + _bt_string_to_uuid(uuid_list[slot-1], (service_uuid_t*)&uuid); + g_strlcpy(uuid_string, uuid_list[slot-1], BT_UUID_STRING_MAX); + BT_INFO("Copied UUID string [%s]", uuid_string); + + /* Register GATT Client */ + ret = gattc_register(&uuid); + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + g_free(uuid_string); + return BLUETOOTH_ERROR_INTERNAL; + } + + BT_INFO("GATT Client registration call successfully accepted by OAL..wait for Instance Initialized event from OAL.."); + + /* Return & wait for GATT Client Instance Initialization event */ + memset(numapps[slot].sender, 0x00, sizeof(numapps[slot].sender)); + memset(numapps[slot].uuid, 0x00, sizeof(numapps[slot].uuid)); + + g_strlcpy(numapps[slot].sender, sender, sizeof(numapps[slot].sender)); + g_strlcpy(numapps[slot].uuid, uuid_string, sizeof(numapps[slot].uuid)); + + /* Address is saved here. When event comes, sender + address are matched for replying pending + request. It is impossible for same sender to have requests with two same addresses */ + memcpy(&numapps[slot].address.addr, address->addr, sizeof(bluetooth_device_address_t)); + + BT_INFO("Slot [%d] occupied", slot); + numapps[slot].is_initialized = TRUE; /* Set initialization to true here itself */ + + g_free(uuid_string); + return BLUETOOTH_ERROR_NONE; + +} + + + +/* GATT client events */ +static void __bt_handle_client_instance_registered(event_gattc_register_t *data) +{ + bt_service_app_info_t *info = NULL; + int k; + char *uuid_string = g_malloc0(BT_UUID_STRING_MAX); + + _bt_uuid_to_string(&(data->client_uuid), uuid_string); + BT_INFO("CLient ID is Initialized [%d] UUID initialized [%s]", data->client_if, uuid_string); + + /* Platform GATT client framwork does not use Default GATT client instance + This GATT client instance is never deregistred in the lifetime of bt-service */ + BT_INFO("Default UUID [%s] current registered uuid [%s]", + DEFAULT_GATT_CLIENT_UUID, uuid_string); + if (g_strcmp0(uuid_string, DEFAULT_GATT_CLIENT_UUID) == 0) { + BT_INFO("Default client Instance Registered [%s] Client instance [%d]", + uuid_string, data->client_if); + gatt_default_client = data->client_if; + g_free(uuid_string); + return; + } + + for (k = 1; k < MAX_APPS_SUPPORTED; k++) { + info = &numapps[k]; + + if (g_strcmp0(info->uuid, uuid_string) == 0) { + BT_INFO("Found GATT client.. UUID [%s], sender [%s]", info->uuid, info->sender); + BT_INFO("Slot [%d] occupied", k); + info->is_initialized = TRUE; + info->client_id = data->client_if; + __bt_gatt_handle_pending_request_info(BLUETOOTH_ERROR_NONE, BT_GATT_CLIENT_REGISTER, + (void*)info, sizeof(bt_service_app_info_t)); + break; + } + } + g_free(uuid_string); +} + +static void __bt_handle_client_connected(event_gattc_conn_t *event_data) +{ + int result = BLUETOOTH_ERROR_NONE; + struct gatt_server_info_t *conn_info = NULL; + struct gatt_out_conn_info_t *out_conn_info = NULL; + + GVariant *param = NULL; + + char *address = g_malloc0(BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(address, + (unsigned char *)event_data->address.addr); + + if (event_data->status != OAL_STATUS_SUCCESS) + result = BLUETOOTH_ERROR_INTERNAL; + + /* DBUS Return fo BT_CONNECT_LE for all the apps */ + __bt_gatt_handle_pending_request_info(result, BT_CONNECT_LE, address, + BT_ADDRESS_STRING_SIZE); + + BT_INFO("Local GATT Client Connected: Remote addr[%s] Client Interface [%d] Connection ID [%d] status[%d]", + address, event_data->client_if, event_data->conn_id, event_data->status); + + if (result == BLUETOOTH_ERROR_NONE) { + /* Check if device is already in connected list */ + conn_info = __bt_find_remote_gatt_server_info(address); + + if (!conn_info) { + /* Send event to BT-API */ + param = g_variant_new("(is)", result, address); + _bt_send_event(BT_DEVICE_EVENT, + BLUETOOTH_EVENT_GATT_CLIENT_CONNECTED, /* Local device is GATT client */ + param); + + /* Save Connection info */ + conn_info = g_new0(struct gatt_server_info_t, 1); + conn_info->addr = g_strdup(address); + conn_info->client_id = event_data->client_if; + BT_INFO("Added GATT server addr[%s]", conn_info->addr); + conn_info->connection_id = event_data->conn_id; + gatt_server_info_list = g_slist_append(gatt_server_info_list, conn_info); + BT_INFO("Total num of connected Remote GATT server devices [%d]", + g_slist_length(gatt_server_info_list)); + +#if 0 + BT_INFO("Do a Internal refresh"); + if (OAL_STATUS_SUCCESS != gattc_refresh(conn_info->client_id, &event_data->address)) + BT_ERR("GATT database refresh failed!!"); + else + BT_INFO("GATT database refresh Success!!"); +#endif + } else + BT_ERR("Local GATT Client connected event for addr[%s], but device is in connected list already", address); + } else + BT_ERR("GATT Client Connection failed!!"); + + /* If outgoing connection Info is present, then remove it */ + out_conn_info = __bt_find_gatt_outgoing_conn_info(address); + if (out_conn_info) { + BT_ERR("Outgoing Client connect request was sent"); + outgoing_gatt_conn_list = g_slist_remove(outgoing_gatt_conn_list, out_conn_info); + g_free(out_conn_info->addr); + g_free(out_conn_info); + } + g_free(address); +} + +static void __bt_handle_client_disconnected(event_gattc_conn_t *event_data) +{ + int result = BLUETOOTH_ERROR_NONE; + + struct gatt_server_info_t *conn_info = NULL; + struct gatt_out_conn_info_t *out_conn_info = NULL; + + GVariant *param = NULL; + + char *address = g_malloc0(BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(address, + (unsigned char *)event_data->address.addr); + + if (event_data->status != OAL_STATUS_SUCCESS) + result = BLUETOOTH_ERROR_INTERNAL; + + if (NULL == _bt_get_request_info_data(BT_DISCONNECT_LE, address)) { + if (NULL != _bt_get_request_info_data(BT_CONNECT_LE, address)) { + result = BLUETOOTH_ERROR_INTERNAL; + __bt_gatt_handle_pending_request_info(result, BT_CONNECT_LE, + address, BT_ADDRESS_STRING_SIZE); + BT_ERR("Failed to connect Local GATT Remote addr[%s]", address); + return; + } + } else { + /* DBUS Return for BT_DISCONNECT_LE for all the apps */ + __bt_gatt_handle_pending_request_info(result, BT_DISCONNECT_LE, address, + BT_ADDRESS_STRING_SIZE); + } + BT_INFO("Local GATT Client DisConnected: Remote addr[%s] Client Interface [%d] Connection ID [%d] status [%d]", + address, event_data->client_if, event_data->conn_id, event_data->status); + + /* Remove Connection info */ + conn_info = __bt_find_remote_gatt_server_info(address); + + if (conn_info) { + param = g_variant_new("(is)", result, address); + /* Send event to application */ + _bt_send_event(BT_DEVICE_EVENT, + BLUETOOTH_EVENT_GATT_CLIENT_DISCONNECTED, + param); + + BT_INFO("Remove GATT server info from List.."); + /* Remove all services from info list_gatt_info */ + __bt_cleanup_remote_services(conn_info); + + /* Remove info from List */ + gatt_server_info_list = g_slist_remove(gatt_server_info_list, conn_info); + BT_INFO("Total num of connected GATT servers [%d]", g_slist_length(gatt_server_info_list)); + g_free(conn_info->addr); + g_free(conn_info); + } else + BT_INFO("Can not find conn info, already removed!"); + + /* If outgoing connection Info is present, then remove it */ + out_conn_info = __bt_find_gatt_outgoing_conn_info(address); + if (out_conn_info) { + BT_ERR("Client Disconnected event, but outgoing connect request was sent"); + outgoing_gatt_conn_list = g_slist_remove(outgoing_gatt_conn_list, out_conn_info); + g_free(out_conn_info->addr); + g_free(out_conn_info); + } + g_free(address); +} + + +static void __bt_handle_client_service_search_result( + event_gattc_service_result_t *event_data) +{ + BT_INFO("+"); + BT_INFO("received the gatt service search result"); + /* Pre: status is never fail from OAL */ + + /* Find service list from address */ + bt_gatt_service_info_list_t *svc_info_list; + bt_gatt_service_info_t *svc_info; + BT_INFO("Search Result: status [%d] conn_id [%d]", + event_data->conn_status.status, + event_data->conn_status.conn_id); + + svc_info_list = __bt_get_service_info_list(event_data->conn_status.conn_id); + if (!svc_info_list) { + BT_INFO("Service info list not present for this connection ID, means first time browse"); + /* Means for this conn_id, no services are ever browsed, first time, + create service info list for this conn_id */ + svc_info_list = g_malloc0(sizeof(bt_gatt_service_info_list_t)); + svc_info_list->conn_id = event_data->conn_status.conn_id; + list_gatt_info = g_slist_append(list_gatt_info, svc_info_list); + } else { + BT_INFO("Service info list Already present for this connection ID, means not first time browse for this conn ID "); + } + + /* send list and current service's uuid and instance id to find it */ + svc_info = __bt_find_matching_service(svc_info_list, &event_data->srvc_id); + + + /* If not found, check if service changed, if yes, means this is a new service added + in remote GATT device, update uuid info in svc info list structure, to be used when + search is completed */ + if (!svc_info) { + BT_INFO("Service Not found in svc info list for this connection ID"); + if (svc_info_list->info.is_changed) { + BT_INFO("Service Changed indication already found for this connection ID"); + memcpy(svc_info_list->info.uuid, event_data->srvc_id.id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + } + /* Create and add new service in service list */ + svc_info = g_malloc0(sizeof(bt_gatt_service_info_t)); + memcpy(svc_info->uuid, event_data->srvc_id.id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + svc_info->inst_id = event_data->srvc_id.id.inst_id; + svc_info->is_primary = event_data->srvc_id.is_prmry; + svc_info_list->services = g_slist_append(svc_info_list->services, svc_info); + BT_INFO("Service created and added in Svc info listf or this connection ID"); + } else { + BT_INFO("Service Already found to be present inside the svc info list for this connection ID"); + /* If returned matching service info, then just update service_rmeoved value inside it to 0 */ + svc_info->is_removed = 0; + } +} + +static void __bt_handle_client_service_search_completed( + event_gattc_conn_status_t *event_data) +{ + BT_INFO("+"); + struct gatt_server_info_t *conn_info = NULL; + bt_gatt_service_info_list_t *svc_info_list; + bt_gatt_service_info_t *svc_info; + bt_services_browse_info_t browse_info; + unsigned char uuid_empty[BLUETOOTH_UUID_HEX_MAX_LEN]; + + memset(&uuid_empty, 0x00, BLUETOOTH_UUID_HEX_MAX_LEN); + memset(&browse_info, 0x00, sizeof(bt_services_browse_info_t)); + BT_INFO("Primary Services browsing completed status[%d] conn ID [%d]", + event_data->status, event_data->conn_id); + + conn_info = __bt_find_remote_gatt_server_info_from_conn_id(event_data->conn_id); + + svc_info_list = __bt_get_service_info_list(event_data->conn_id); + if (!svc_info_list) { + BT_ERR("No services browsed ever for addr [%s]", conn_info->addr); + + /* Just build response and return ERROR */ + __bt_build_service_browse_info(event_data->conn_id, &browse_info); + + __bt_gatt_handle_pending_request_info(BLUETOOTH_ERROR_INTERNAL, + BT_GATT_GET_PRIMARY_SERVICES, &browse_info, + sizeof(bt_services_browse_info_t)); + return; + } + + /* If fail, then send event with error */ + if (event_data->status != OAL_STATUS_SUCCESS) { + /* Just build response and return ERROR */ + __bt_build_service_browse_info(event_data->conn_id, &browse_info); + + __bt_gatt_handle_pending_request_info(BLUETOOTH_ERROR_INTERNAL, + BT_GATT_GET_PRIMARY_SERVICES, &browse_info, + sizeof(bt_services_browse_info_t)); + return; + } + + /* If success, then find service info list from address */ + + /* If svc_changed == 1 and uuid valid, means a new service is added*/ + if (svc_info_list->info.is_changed && !memcmp(uuid_empty, svc_info_list->info.uuid, BLUETOOTH_UUID_HEX_MAX_LEN)) { + /* TODO: Send event -Service added with instance ID and UUID of newly added service */ + BT_INFO("new service added"); + + BT_INFO("TODO new service added"); + } + + /* If svc_changed == 1 and uuid invalid, then a service is removed */ + if (svc_info_list->info.is_changed && memcmp(uuid_empty, svc_info_list->info.uuid, BLUETOOTH_UUID_HEX_MAX_LEN)) { + /* Scan through the service info list to find service with is_removed = 1*/ + svc_info = __bt_find_removed_service(svc_info_list); + + /* TODO Send event - Service removed with instance ID and UUID of just rmeoved service */ + + /* Remove that service info from service info list */ + svc_info_list->services = g_slist_remove(svc_info_list->services, svc_info); + + /* Delete that service completely from svc_info list*/ + __bt_remove_service_info_from_list(svc_info); + g_free(svc_info); + } + + /* Reset svc_changed = 0, and reset UUID = all 0's */ + svc_info_list->info.is_changed = 0; + memset(&svc_info_list->info.uuid, 0x00, BLUETOOTH_UUID_HEX_MAX_LEN); + + /* Build Reply and send to service browse primary services request of pending apps */ + __bt_build_service_browse_info(event_data->conn_id, &browse_info); + + __bt_gatt_handle_pending_request_info(BLUETOOTH_ERROR_NONE, + BT_GATT_GET_PRIMARY_SERVICES, &browse_info, + sizeof(bt_services_browse_info_t)); +} + + +static void __bt_handle_client_characteristic_search_result( + event_gattc_characteristic_result_t *event_data) +{ + bt_gatt_service_info_list_t *svc_info_list; + bt_gatt_service_info_t *svc_info; + bt_gatt_char_info_t *char_info; + bt_char_browse_info_t browse_info; + + BT_INFO("Characteristic search result status [%d]", + event_data->conn_status.status); + + memset(&browse_info, 0x00, sizeof(bt_char_browse_info_t)); + + /* If success */ + if (event_data->conn_status.status == OAL_STATUS_SUCCESS) { + /* Find service info list from address */ + svc_info_list = __bt_get_service_info_list(event_data->conn_status.conn_id); + if (svc_info_list == NULL) { + BT_ERR("svc_info_list is NULL"); + return; + } + + + /* Find matching service info from svc info list */ + svc_info = __bt_find_matching_service(svc_info_list, &event_data->srvc_id); + if (svc_info == NULL) { + BT_ERR("svc_info is NULL"); + return; + } + + /* Find Matching char from service info in event */ + char_info = __bt_find_matching_charc(svc_info, &event_data->char_id); + if (char_info == NULL) + BT_ERR("char_info is NULL"); + + /* If not found, then add new characteristic and return */ + if (!char_info) { + BT_INFO(" add new characteristic"); + char_info = g_malloc0(sizeof(bt_gatt_char_info_t)); + memcpy(char_info->uuid, event_data->char_id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + char_info->inst_id = event_data->char_id.inst_id; + char_info->props = event_data->char_prop; + svc_info->chars = g_slist_append(svc_info->chars, char_info); + } else { + /* If found, then return */ + BT_INFO("Characteristic browsed is already presesnt"); + } + } else { + /* If Not success: Means Charc browse is completed */ + /* Find char list from service in event */ + /* Find service list from address */ + svc_info_list = __bt_get_service_info_list(event_data->conn_status.conn_id); + + /* Find service info from service in event */ + svc_info = __bt_find_matching_service(svc_info_list, &event_data->srvc_id); + + /* Build char list from service in event */ + __bt_build_char_browse_info(event_data->conn_status.conn_id, + svc_info, &browse_info); + + /* Create response and return by sending event*/ + /* Build Reply and send to service browse All Included services request of pending apps */ + __bt_gatt_handle_pending_request_info(BLUETOOTH_ERROR_NONE, + BT_GATT_GET_SERVICE_PROPERTIES, + &browse_info, + sizeof(bt_char_browse_info_t)); + } +} + +static void __bt_handle_client_descriptor_search_result( + event_gattc_descriptor_result_t *event_data) +{ + bt_gatt_service_info_list_t *svc_info_list; + bt_gatt_service_info_t *svc_info; + bt_gatt_char_info_t *char_info; + bt_gatt_descriptor_info_t *desc_info; + bt_descriptor_browse_info_t browse_info; + + BT_INFO("descriptor search result status [%d]", event_data->conn_status.status); + + memset(&browse_info, 0x00, sizeof(bt_descriptor_browse_info_t)); + + /* If success */ + if (event_data->conn_status.status == OAL_STATUS_SUCCESS) { + /* Find service list from address */ + svc_info_list = __bt_get_service_info_list(event_data->conn_status.conn_id); + svc_info = __bt_find_matching_service(svc_info_list, &event_data->srvc_id); + char_info = __bt_find_matching_charc(svc_info, &event_data->char_id); + desc_info = __bt_find_matching_desc(char_info, &event_data->descr_id); + + /* If not found, add new descriptor and return */ + if (!desc_info) { + desc_info = g_malloc0(sizeof(bt_gatt_descriptor_info_t)); + memcpy(desc_info->uuid, event_data->descr_id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + desc_info->inst_id = event_data->descr_id.inst_id; + char_info->descs = g_slist_append(char_info->descs, desc_info); + + } else { + /* If found, then return */ + BT_INFO("Characteristic browsed is already presesnt"); + } + } else { + /* If Not success */ + /* Find service list from address */ + /* Find included service list from service in event */ + /* Create response and return by sending event*/ + svc_info_list = __bt_get_service_info_list(event_data->conn_status.conn_id); + + /* Find service info from service in event */ + svc_info = __bt_find_matching_service(svc_info_list, &event_data->srvc_id); + + /* Find char info from char in event */ + char_info = __bt_find_matching_charc(svc_info, &event_data->char_id); + + /* Build descriptor list from char in event */ + __bt_build_descriptor_browse_info(event_data->conn_status.conn_id, + svc_info, char_info, &browse_info); + + /* DBUS returni */ + __bt_gatt_handle_pending_request_info(BLUETOOTH_ERROR_NONE, + BT_GATT_GET_CHARACTERISTIC_PROPERTIES, + &browse_info, + sizeof(bt_descriptor_browse_info_t)); + } +} + +static void __bt_handle_client_characteristic_read_data( + event_gattc_read_data *event_data) +{ + int result = BLUETOOTH_ERROR_NONE; + struct gatt_server_info_t *conn_info = NULL; + bluetooth_gatt_client_char_prop_info_t read_info; + + /* Read Information data structures */ + GVariant *param = NULL; + GVariant *data = NULL; + GVariant *data_svc_uuid = NULL; + GVariant *data_char_uuid = NULL; + char *read_val = NULL; + char *svc_uuid = NULL; + char *char_uuid = NULL; + int i; + int uuid_len = 16; + + BT_INFO("+"); + + //memset(&read_info, 0x00, sizeof(bt_gatt_handle_property_t)); + memset(&read_info, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t)); + + /* Extract Address from conn_id of event data */ + conn_info = __bt_find_remote_gatt_server_info_from_conn_id( + event_data->uuid_status.conn_status.conn_id); + + BT_INFO("Characteristic Read result from addr [%s] status [%d]", + conn_info->addr, event_data->uuid_status.conn_status.status); + + /* Fill char in buffer */ + memcpy(&read_info.characteristic.uuid, + event_data->uuid_status.char_id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + read_info.characteristic.instance_id = event_data->uuid_status.char_id.inst_id; + + /* Fill Service in buffer */ + memcpy(&read_info.svc.uuid, + event_data->uuid_status.srvc_id.id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + read_info.svc.instance_id = event_data->uuid_status.srvc_id.id.inst_id; + + /* Fill remote device address */ + _bt_convert_addr_string_to_type(read_info.device_address.addr, conn_info->addr); + + /* Fill data and reply to all apps waiting for Read result on the same characteristic +Note: Even in case of failure, address, handles and result code should be returned */ + if (event_data->uuid_status.conn_status.status != OAL_STATUS_SUCCESS) + result = BLUETOOTH_ERROR_INTERNAL; + else { + if (event_data->data_len > 0) { + /* DEBUG */ + for (i = 0; i < event_data->data_len; i++) + BT_INFO("Data[%d] = [0x%x]", i, event_data->data[i]); + + /* Read data */ + read_val = g_memdup(&event_data->data[0], event_data->data_len); + + data = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + read_val, + event_data->data_len, + TRUE, NULL, NULL); + /* SVC uuid */ + svc_uuid = g_memdup(&event_data->uuid_status.srvc_id.id.uuid.uuid[0], uuid_len); + + data_svc_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + svc_uuid, + 16, + TRUE, NULL, NULL); + + /* Char uuid */ + char_uuid = g_memdup(&event_data->uuid_status.char_id.uuid.uuid[0], uuid_len); + + data_char_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + char_uuid, + 16, + TRUE, NULL, NULL); + param = g_variant_new("(isn@ayin@ayin@ay)", result, + conn_info->addr, + 16, + data_svc_uuid, + event_data->uuid_status.srvc_id.id.inst_id, + 16, + data_char_uuid, + event_data->uuid_status.char_id.inst_id, + event_data->data_len, + data); + + /* Send Event */ + _bt_send_event(BT_GATT_CLIENT_EVENT, + BLUETOOTH_EVENT_GATT_READ_CHAR, + param); + } else { + BT_ERR("Characteristic Read success, but no data!!!"); + result = BLUETOOTH_ERROR_INTERNAL; + } + } + /* Send DBUS return */ + __bt_gatt_handle_pending_request_info(result, + BT_GATT_READ_CHARACTERISTIC, + &read_info, + sizeof(bluetooth_gatt_client_char_prop_info_t)); + + if (read_val) + g_free(read_val); + if (svc_uuid) + g_free(svc_uuid); + if (char_uuid) + g_free(char_uuid); +} + +/* Modified */ +static void __bt_handle_client_descriptor_read_data( + event_gattc_read_data *event_data) +{ + int result = BLUETOOTH_ERROR_NONE; + struct gatt_server_info_t *conn_info = NULL; + bluetooth_gatt_client_desc_prop_info_t read_info; + + /* Read Information data structures */ + GVariant *param = NULL; + GVariant *data = NULL; + GVariant *data_svc_uuid = NULL; + GVariant *data_char_uuid = NULL; + GVariant *data_desc_uuid = NULL; + char *read_val = NULL; + char *svc_uuid = NULL; + char *char_uuid = NULL; + char *desc_uuid = NULL; + int i; + int uuid_len = 16; + BT_INFO("+"); + + memset(&read_info, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t)); + + /* Extract Address from conn_id of event data */ + conn_info = __bt_find_remote_gatt_server_info_from_conn_id( + event_data->uuid_status.conn_status.conn_id); + + BT_INFO("Descriptor Read result from addr [%s] status [%d]", + conn_info->addr, event_data->uuid_status.conn_status.status); + + /* Fill descriptor informations in buffer */ + memcpy(&read_info.descriptor.uuid, + event_data->uuid_status.descr_id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + read_info.descriptor.instance_id = event_data->uuid_status.descr_id.inst_id; + + /* Fill Characteristic informations in buffer */ + memcpy(&read_info.characteristic.uuid, + event_data->uuid_status.char_id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + read_info.characteristic.instance_id = event_data->uuid_status.char_id.inst_id; + + /* Fill Service informations in buffer */ + memcpy(&read_info.svc.uuid, + event_data->uuid_status.srvc_id.id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + read_info.svc.instance_id = event_data->uuid_status.srvc_id.id.inst_id; + + /* Fill remote device address */ + _bt_convert_addr_string_to_type(read_info.device_address.addr, conn_info->addr); + + /* Fill data and reply to all apps waiting for Read result on the same characteristic */ + if (event_data->uuid_status.conn_status.status != OAL_STATUS_SUCCESS) + result = BLUETOOTH_ERROR_INTERNAL; + else { + if (event_data->data_len > 0) { + /* DEBUG */ + for (i = 0; i < event_data->data_len; i++) + BT_DBG("Data[%d] = [0x%x]", i, event_data->data[i]); + + /* Read data */ + read_val = g_memdup(&event_data->data[0], event_data->data_len); + + data = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + read_val, + event_data->data_len, + TRUE, NULL, NULL); + /* SVC uuid */ + svc_uuid = g_memdup(&event_data->uuid_status.srvc_id.id.uuid.uuid[0], uuid_len); + + data_svc_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + svc_uuid, + 16, + TRUE, NULL, NULL); + + /* Char uuid */ + char_uuid = g_memdup(&event_data->uuid_status.char_id.uuid.uuid[0], uuid_len); + + data_char_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + char_uuid, + 16, + TRUE, NULL, NULL); + + /* Desc uuid */ + desc_uuid = g_memdup(&event_data->uuid_status.descr_id.uuid.uuid[0], uuid_len); + + data_desc_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + desc_uuid, + 16, + TRUE, NULL, NULL); + + param = g_variant_new("(isn@ayin@ayin@ayin@ay)", result, + conn_info->addr, + uuid_len, + data_svc_uuid, + event_data->uuid_status.srvc_id.id.inst_id, + 16, + data_char_uuid, + event_data->uuid_status.char_id.inst_id, + 16, + data_desc_uuid, + event_data->uuid_status.descr_id.inst_id, + event_data->data_len, + data); + + /* Send Event */ + _bt_send_event(BT_GATT_CLIENT_EVENT, + BLUETOOTH_EVENT_GATT_READ_DESC, + param); + } else { + BT_ERR("Descriptor Read success, but no data!!!"); + result = BLUETOOTH_ERROR_INTERNAL; + } + } + BT_INFO("Send DBUS rpely for GATT Read Descriptor"); + /* Send DBUS return */ + __bt_gatt_handle_pending_request_info(result, + BT_GATT_READ_DESCRIPTOR_VALUE, + &read_info, + sizeof(bluetooth_gatt_client_desc_prop_info_t)); + if (read_val) + g_free(read_val); + if (svc_uuid) + g_free(svc_uuid); + if (char_uuid) + g_free(char_uuid); + if (desc_uuid) + g_free(desc_uuid); +} + +static void __bt_handle_client_characteristic_write_data( + event_gattc_write_data *event_data) +{ + int result = BLUETOOTH_ERROR_NONE; + struct gatt_server_info_t *conn_info = NULL; + bluetooth_gatt_client_char_prop_info_t write_info; + + /* Read Information data structures */ + GVariant *param = NULL; + GVariant *data_svc_uuid = NULL; + GVariant *data_char_uuid = NULL; + char *svc_uuid = NULL; + char *char_uuid = NULL; + int uuid_len = 16; + BT_INFO("+"); + + memset(&write_info, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t)); + + /* Extract Address from conn_id of event data */ + conn_info = __bt_find_remote_gatt_server_info_from_conn_id( + event_data->conn_status.conn_id); + + BT_INFO("Characteristic Write callback from addr [%s] status [%d]", + conn_info->addr, event_data->conn_status.status); + + /* Fill char in buffer */ + memcpy(&write_info.characteristic.uuid, + event_data->char_id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + write_info.characteristic.instance_id = event_data->char_id.inst_id; + + /* Fill Service in buffer */ + memcpy(&write_info.svc.uuid, + event_data->srvc_id.id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + write_info.svc.instance_id = event_data->srvc_id.id.inst_id; + + /* Fill remote device address */ + _bt_convert_addr_string_to_type(write_info.device_address.addr, conn_info->addr); + + if (event_data->conn_status.status != OAL_STATUS_SUCCESS) { + result = BLUETOOTH_ERROR_INTERNAL; + goto done; + } + + /* Build event */ + /* SVC uuid */ + svc_uuid = g_memdup(&event_data->srvc_id.id.uuid.uuid[0], uuid_len); + + data_svc_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + svc_uuid, + uuid_len, + TRUE, NULL, NULL); + + /* Char uuid */ + char_uuid = g_memdup(&event_data->char_id.uuid.uuid[0], uuid_len); + + data_char_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + char_uuid, + uuid_len, + TRUE, NULL, NULL); + + param = g_variant_new("(isn@ayin@ayi)", result, + conn_info->addr, + 16, + data_svc_uuid, + event_data->srvc_id.id.inst_id, + 16, + data_char_uuid, + event_data->char_id.inst_id); + + /* Send Event */ + _bt_send_event(BT_GATT_CLIENT_EVENT, + BLUETOOTH_EVENT_GATT_WRITE_CHAR, + param); + + /* Free data */ + if (svc_uuid) + g_free(svc_uuid); + if (char_uuid) + g_free(char_uuid); +done: + /* Send DBUS return */ + __bt_gatt_handle_pending_request_info(result, + BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE, + &write_info, + sizeof(bluetooth_gatt_client_char_prop_info_t)); +} + + +static void __bt_handle_client_descriptor_write_data( + event_gattc_write_data *event_data) +{ + int result = BLUETOOTH_ERROR_NONE; + struct gatt_server_info_t *conn_info = NULL; + bluetooth_gatt_client_desc_prop_info_t write_info; + + /* Write Information data structures */ + GVariant *param = NULL; + GVariant *data_svc_uuid = NULL; + GVariant *data_char_uuid = NULL; + GVariant *data_desc_uuid = NULL; + char *svc_uuid = NULL; + char *char_uuid = NULL; + char *desc_uuid = NULL; + int uuid_len = 16; + BT_INFO("+"); + + memset(&write_info, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t)); + + /* Extract Address from conn_id of event data */ + conn_info = __bt_find_remote_gatt_server_info_from_conn_id( + event_data->conn_status.conn_id); + + if (NULL == conn_info) { + + BT_INFO("Failed to get the conn info for conn_id [%d]", event_data->conn_status.conn_id); + return; + } + + BT_INFO("Descriptor Write callback from addr [%s] status [%d]", + conn_info->addr, event_data->conn_status.status); + + /* Fill descriptor informations in buffer */ + memcpy(&write_info.descriptor.uuid, + event_data->descr_id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + write_info.descriptor.instance_id = event_data->descr_id.inst_id; + + /* Fill Characteristic informations in buffer */ + memcpy(&write_info.characteristic.uuid, + event_data->char_id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + write_info.characteristic.instance_id = event_data->char_id.inst_id; + + /* Fill Service informations in buffer */ + memcpy(&write_info.svc.uuid, + event_data->srvc_id.id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + write_info.svc.instance_id = event_data->srvc_id.id.inst_id; + + /* Fill remote device address */ + _bt_convert_addr_string_to_type(write_info.device_address.addr, conn_info->addr); + + if (event_data->conn_status.status != OAL_STATUS_SUCCESS) { + result = BLUETOOTH_ERROR_INTERNAL; + goto done; + } + + /* Build event */ + /* SVC uuid */ + svc_uuid = g_memdup(&event_data->srvc_id.id.uuid.uuid[0], uuid_len); + + data_svc_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + svc_uuid, + uuid_len, + TRUE, NULL, NULL); + + /* Char uuid */ + char_uuid = g_memdup(&event_data->char_id.uuid.uuid[0], uuid_len); + + data_char_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + char_uuid, + uuid_len, + TRUE, NULL, NULL); + + /* Desc uuid */ + desc_uuid = g_memdup(&event_data->descr_id.uuid.uuid[0], uuid_len); + + data_desc_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + desc_uuid, + uuid_len, + TRUE, NULL, NULL); + + param = g_variant_new("(isn@ayin@ayin@ayi)", result, + conn_info->addr, + 16, + data_svc_uuid, + event_data->srvc_id.id.inst_id, + 16, + data_char_uuid, + event_data->char_id.inst_id, + 16, + data_desc_uuid, + event_data->descr_id.inst_id); + + /* Send Event */ + _bt_send_event(BT_GATT_CLIENT_EVENT, + BLUETOOTH_EVENT_GATT_WRITE_DESC, + param); + + /* Free data */ + if (svc_uuid) + g_free(svc_uuid); + if (char_uuid) + g_free(char_uuid); + if (desc_uuid) + g_free(desc_uuid); +done: + /* Send DBUS return */ + __bt_gatt_handle_pending_request_info(result, + BT_GATT_WRITE_DESCRIPTOR_VALUE, + &write_info, + sizeof(bluetooth_gatt_client_desc_prop_info_t)); +} + +static void __bt_hanlde_le_device_disconnection(event_dev_conn_status_t *event_data) +{ + int result = BLUETOOTH_ERROR_INTERNAL; + char *address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_addr_type_to_string(address, (unsigned char *)event_data->address.addr); + + /* DBUS Return with fail of pending BT_CONNECT_LE for all the apps */ + BT_INFO("Local GATT Client disconnected: Remote addr[%s] ", address); + + __bt_gatt_handle_pending_request_info(result, BT_CONNECT_LE, address, + BT_ADDRESS_STRING_SIZE); +} + + + +gboolean _bt_is_remote_gatt_device_connected(bluetooth_device_address_t *address) +{ + char *addr; + struct gatt_server_info_t *conn_info = NULL; + gboolean connected = FALSE; + BT_INFO("+"); + + addr = g_malloc0(BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, + (unsigned char *)&(address->addr)); + + BT_INFO("Check Connected or not for [%s]", addr); + /* Check if device is already in connected list */ + conn_info = __bt_find_remote_gatt_server_info(addr); + + if (conn_info) { + BT_INFO("Remote GATT Server device [%s] is Connected", conn_info->addr); + connected = TRUE; + } else + BT_INFO("Remote GATT Server Device [%s] is not Connected", addr); + g_free(addr); + return connected; +} + + +int _bt_connect_le_device(bluetooth_device_address_t *address, + int auto_connect, int client_id) +{ + struct gatt_server_info_t *conn_info = NULL; + struct gatt_out_conn_info_t *out_conn_info = NULL; + + invocation_info_t *req_info = NULL; + int ret = OAL_STATUS_SUCCESS; + char *addr; + char *remote_address = NULL; + + BT_CHECK_PARAMETER(address, return); + + BT_INFO("+"); + + addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, address->addr); + BT_INFO("GATT Client connect request for address [%s] client instance [%d]", + addr, client_id); + + + /* Check if Remote Device is already under connection progress */ + req_info = _bt_get_request_info_data_from_function_name(BT_CONNECT_LE); + if (req_info) { + remote_address = (char*)req_info->user_data; + if (remote_address && !strcasecmp(remote_address, addr)) {/* Address matched */ + BT_INFO("Already Connection ongoing for same remote GATT Server address [%s]", remote_address); + /* Return and wait for events to be sent to all apps */ + g_free(addr); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + } + + /* Check if remote GATT Server is connected or not */ + conn_info = __bt_find_remote_gatt_server_info(addr); + if (conn_info) { + BT_ERR("GATT Server is already connected.."); + g_free(addr); + return BLUETOOTH_ERROR_ALREADY_CONNECT; + } + + /* TODO Check Requirement of holding Advertisement before initiating LE connect */ + + /* Check if app sent 0 client id for connection, in such case, use default gatt client ID */ + if (client_id == 0) { + BT_INFO("GATT CLient connect request sent by an app without any client instance [%d]", + client_id); + BT_INFO("Assign default GATT client id [%d]", gatt_default_client); + client_id = gatt_default_client; + } + + BT_INFO("Connect using CLient ID [%d]", client_id); + ret = gattc_connect(client_id, (bt_address_t*)(address), auto_connect); + + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + g_free(addr); + return BLUETOOTH_ERROR_INTERNAL; + } + + /* Mark this as outgoing connection */ + out_conn_info = g_new0(struct gatt_out_conn_info_t, 1); + out_conn_info->addr = g_strdup(addr); + out_conn_info->client_id = client_id; + BT_INFO("Added outgoing connection info addr[%s]", out_conn_info->addr); + outgoing_gatt_conn_list = g_slist_append(outgoing_gatt_conn_list, out_conn_info); + + g_free(addr); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_gatt_get_primary_services(char *address) +{ + BT_CHECK_PARAMETER(address, return); + struct gatt_server_info_t *conn_info = NULL; + invocation_info_t *req_info = NULL; + int ret = OAL_STATUS_SUCCESS; + BT_INFO("+"); + + /* Check if any app is already browsing primary services on the same remote GATT Server */ + req_info = _bt_get_request_info_data(BT_GATT_GET_PRIMARY_SERVICES, address); + if (req_info) { + BT_INFO("Already Primary Service Browsing ongoing for same rmeote GATT Server"); + /* Return and wait for events to be sent to all apps */ + return BLUETOOTH_ERROR_NONE; + } + + /* Check if remote GATT Server is connected or not */ + conn_info = __bt_find_remote_gatt_server_info(address); + if (conn_info) { + BT_INFO("GATT Server [%s] is connected, conn Id [%d]", + conn_info->addr, conn_info->connection_id); + } else { + BT_ERR("GATT Server is not yet connected.."); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + /* Send Primary Service Browsing request to stack */ + ret = gattc_search_service(conn_info->connection_id, NULL); + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + return BLUETOOTH_ERROR_INTERNAL; + } + return BLUETOOTH_ERROR_NONE; +} + +int _bt_gatt_get_all_characteristic(bluetooth_gatt_client_svc_prop_info_t *svc) +{ + BT_CHECK_PARAMETER(svc, return); + struct gatt_server_info_t *conn_info = NULL; + invocation_info_t *req_info = NULL; + bluetooth_gatt_client_svc_prop_info_t *prop; + oal_gatt_srvc_id_t srvc_id; + int ret = OAL_STATUS_SUCCESS; + char *addr; + BT_INFO("+"); + + /* Check if any app is already browsing characteristics of the same service on the same remote GATT Server */ + req_info = _bt_get_request_info_data_from_function_name(BT_GATT_GET_SERVICE_PROPERTIES); + if (req_info) { + prop = (bluetooth_gatt_client_svc_prop_info_t*)req_info->user_data; + if (prop && !memcmp(svc->device_address.addr, prop->device_address.addr, sizeof(bluetooth_device_address_t)) + && memcmp(prop->svc.uuid, svc->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) + && prop->svc.instance_id == svc->svc.instance_id) { + BT_INFO("Already Properties browsing for Primary Service ongoing for same remote GATT Server"); + /* Return and wait for events to be sent to all apps */ + return BLUETOOTH_ERROR_NONE; + } + } + + addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, svc->device_address.addr); + + /* Check if remote GATT Server is connected or not */ + conn_info = __bt_find_remote_gatt_server_info(addr); + if (conn_info) { + BT_INFO("GATT Server [%s] is connected, conn Id [%d]", + conn_info->addr, conn_info->connection_id); + } else { + BT_ERR("GATT Server is not yet connected.."); + g_free(addr); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + srvc_id.is_prmry = TRUE; + srvc_id.id.inst_id = svc->svc.instance_id; + memcpy(srvc_id.id.uuid.uuid, svc->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + /* Search All Characteristic */ + ret = gattc_get_characteristic(conn_info->connection_id, &srvc_id, NULL); + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + g_free(addr); + return BLUETOOTH_ERROR_INTERNAL; + } + g_free(addr); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_gatt_get_all_characteristic_properties( + bluetooth_gatt_client_char_prop_info_t *chr) +{ + struct gatt_server_info_t *conn_info = NULL; + invocation_info_t *req_info = NULL; + bluetooth_gatt_client_char_prop_info_t *prop; + oal_gatt_srvc_id_t srvc_id; + oal_gatt_id_t char_id; + int ret = OAL_STATUS_SUCCESS; + char *addr; + + BT_CHECK_PARAMETER(chr, return); + + BT_INFO("+"); + + /* Check if any app is already browsing descriptors of the same char of + particular service on the same remote GATT Server */ + req_info = _bt_get_request_info_data_from_function_name(BT_GATT_GET_CHARACTERISTIC_PROPERTIES); + if (req_info) { + prop = (bluetooth_gatt_client_char_prop_info_t*)req_info->user_data; + if (prop && !memcmp(chr->device_address.addr, prop->device_address.addr, sizeof(bluetooth_device_address_t)) /* Address matched */ + && memcmp(chr->svc.uuid, prop->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Service UUID matched */ + && chr->svc.instance_id == prop->svc.instance_id /* Service Instance ID matched */ + && memcmp(chr->characteristic.uuid, prop->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Characteristic UUID matched */ + && chr->characteristic.instance_id == prop->characteristic.instance_id) { /* Characteristic Instance ID matched */ + BT_INFO("Already Properties browsing for Characteristic ongoing for same remote GATT Server"); + /* Return and wait for events to be sent to all apps */ + return BLUETOOTH_ERROR_NONE; + } + } + + addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, chr->device_address.addr); + + /* Check if remote GATT Server is connected or not */ + conn_info = __bt_find_remote_gatt_server_info(addr); + if (conn_info) { + BT_INFO("GATT Server [%s] is connected, conn Id [%d]", + conn_info->addr, conn_info->connection_id); + } else { + BT_ERR("GATT Server is not yet connected.."); + g_free(addr); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + srvc_id.is_prmry = TRUE; + srvc_id.id.inst_id = chr->svc.instance_id; + memcpy(srvc_id.id.uuid.uuid, chr->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + char_id.inst_id = chr->characteristic.instance_id; + memcpy(char_id.uuid.uuid, chr->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + /* Search All Descriptors */ + ret = gattc_get_descriptor(conn_info->connection_id, &srvc_id, &char_id, NULL); + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + g_free(addr); + return BLUETOOTH_ERROR_INTERNAL; + } + g_free(addr); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_gatt_read_characteristic_value( + bluetooth_gatt_client_char_prop_info_t *chr) +{ + struct gatt_server_info_t *conn_info = NULL; + invocation_info_t *req_info = NULL; + bluetooth_gatt_client_char_prop_info_t *prop; + oal_gatt_srvc_id_t srvc_id; + oal_gatt_id_t char_id; + int ret = OAL_STATUS_SUCCESS; + char *addr; + + BT_CHECK_PARAMETER(chr, return); + + BT_INFO("+"); + + /* Check if any app is already Reading characteristic of the same char of + particular service on the same remote GATT Server */ + req_info = _bt_get_request_info_data_from_function_name(BT_GATT_READ_CHARACTERISTIC); + if (req_info) { + prop = (bluetooth_gatt_client_char_prop_info_t*)req_info->user_data; + if (prop && !memcmp(chr->device_address.addr, prop->device_address.addr, sizeof(bluetooth_device_address_t)) /* Address matched */ + && memcmp(chr->svc.uuid, prop->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Service UUID matched */ + && chr->svc.instance_id == prop->svc.instance_id /* Service Instance ID matched */ + && memcmp(chr->characteristic.uuid, prop->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Characteristic UUID matched */ + && chr->characteristic.instance_id == prop->characteristic.instance_id) { /* Characteristic Instance ID matched */ + BT_INFO("Already Characteristic value Read operation in progress for same remote GATT Server"); + /* Return and wait for events to be sent to all apps */ + return BLUETOOTH_ERROR_NONE; + } + } + + addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, chr->device_address.addr); + + /* Check if remote GATT Server is connected or not */ + conn_info = __bt_find_remote_gatt_server_info(addr); + if (conn_info) { + BT_INFO("GATT Server [%s] is connected, conn Id [%d]", + conn_info->addr, conn_info->connection_id); + } else { + BT_ERR("GATT Server is not yet connected.."); + g_free(addr); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + srvc_id.is_prmry = TRUE; + srvc_id.id.inst_id = chr->svc.instance_id; + memcpy(srvc_id.id.uuid.uuid, chr->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + char_id.inst_id = chr->characteristic.instance_id; + memcpy(char_id.uuid.uuid, chr->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + /* Search All Descriptors */ + ret = gattc_read_characteristic(conn_info->connection_id, &srvc_id, &char_id, OAL_GATT_AUTH_REQ_NONE); + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + g_free(addr); + return BLUETOOTH_ERROR_INTERNAL; + } + g_free(addr); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_gatt_read_descriptor_value( + bluetooth_gatt_client_desc_prop_info_t *desc) +{ + struct gatt_server_info_t *conn_info = NULL; + invocation_info_t *req_info = NULL; + bluetooth_gatt_client_desc_prop_info_t *prop; + oal_gatt_srvc_id_t srvc_id; + oal_gatt_id_t char_id; + oal_gatt_id_t desc_id; + int ret = OAL_STATUS_SUCCESS; + char *addr; + + BT_CHECK_PARAMETER(desc, return); + + BT_INFO("+"); + + /* Check if any app is already Reading descriptors of the same char of + particular service on the same remote GATT Server */ + req_info = _bt_get_request_info_data_from_function_name(BT_GATT_READ_DESCRIPTOR_VALUE); + if (req_info) { + prop = (bluetooth_gatt_client_desc_prop_info_t*)req_info->user_data; + if (prop && !memcmp(desc->device_address.addr, prop->device_address.addr, sizeof(bluetooth_device_address_t)) /* Address matched */ + && memcmp(desc->svc.uuid, prop->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Service UUID matched */ + && desc->svc.instance_id == prop->svc.instance_id /* Service Instance ID matched */ + && memcmp(desc->characteristic.uuid, prop->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Characteristic UUID matched */ + && desc->characteristic.instance_id == prop->characteristic.instance_id /* Characteristic Instance ID matched */ + && memcmp(desc->descriptor.uuid, prop->descriptor.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Descriptor UUID matched */ + && desc->descriptor.instance_id == prop->descriptor.instance_id) { /* Descriptor Instance ID matched */ + BT_INFO("Already Descriptor value Read operation in progress for same remote GATT Server"); + /* Return and wait for events to be sent to all apps */ + return BLUETOOTH_ERROR_NONE; + } + } + + addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, desc->device_address.addr); + + /* Check if remote GATT Server is connected or not */ + conn_info = __bt_find_remote_gatt_server_info(addr); + if (conn_info) { + BT_INFO("GATT Server [%s] is connected, conn Id [%d]", + conn_info->addr, conn_info->connection_id); + } else { + BT_ERR("GATT Server is not yet connected.."); + g_free(addr); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + srvc_id.is_prmry = TRUE; + srvc_id.id.inst_id = desc->svc.instance_id; + memcpy(srvc_id.id.uuid.uuid, desc->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + char_id.inst_id = desc->characteristic.instance_id; + memcpy(char_id.uuid.uuid, desc->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + desc_id.inst_id = desc->descriptor.instance_id; + memcpy(desc_id.uuid.uuid, desc->descriptor.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + /* Search All Descriptors */ + ret = gattc_read_descriptor(conn_info->connection_id, &srvc_id, &char_id, + &desc_id, OAL_GATT_AUTH_REQ_NONE); + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + g_free(addr); + return BLUETOOTH_ERROR_INTERNAL; + } + g_free(addr); + return BLUETOOTH_ERROR_NONE; +} + + +/* Write Characteristic */ +int _bt_gatt_write_characteristic_value_by_type( + bluetooth_gatt_client_char_prop_info_t *chr, + bluetooth_gatt_att_data_t *data, + bluetooth_gatt_write_type_e write_type) +{ + struct gatt_server_info_t *conn_info = NULL; + invocation_info_t *req_info = NULL; + bluetooth_gatt_client_char_prop_info_t *prop; + oal_gatt_srvc_id_t srvc_id; + oal_gatt_id_t char_id; + int ret = OAL_STATUS_SUCCESS; + char *addr; + int k; + + BT_CHECK_PARAMETER(chr, return); + BT_CHECK_PARAMETER(data, return); + + BT_INFO("+"); + + /* Check if any app is already writing same char of + particular service on the same remote GATT Server */ + req_info = _bt_get_request_info_data_from_function_name(BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE); + if (req_info) { + prop = (bluetooth_gatt_client_char_prop_info_t*)req_info->user_data; + if (prop && !memcmp(chr->device_address.addr, prop->device_address.addr, sizeof(bluetooth_device_address_t)) /* Address matched */ + && memcmp(chr->svc.uuid, prop->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Service UUID matched */ + && chr->svc.instance_id == prop->svc.instance_id /* Service Instance ID matched */ + && memcmp(chr->characteristic.uuid, prop->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Characteristic UUID matched */ + && chr->characteristic.instance_id == prop->characteristic.instance_id) { /* Characteristic Instance ID matched */ + BT_INFO("Already Characteristic Write Value operation in progress for same remote GATT Server"); + /* Return and wait for events to be sent to all apps */ + return BLUETOOTH_ERROR_NONE; + } + } + + addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, chr->device_address.addr); + + /* Check if remote GATT Server is connected or not */ + conn_info = __bt_find_remote_gatt_server_info(addr); + if (conn_info) { + BT_INFO("GATT Server [%s] is connected, conn Id [%d]", + conn_info->addr, conn_info->connection_id); + } else { + BT_ERR("GATT Server is not yet connected.."); + g_free(addr); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + srvc_id.is_prmry = TRUE; + srvc_id.id.inst_id = chr->svc.instance_id; + memcpy(srvc_id.id.uuid.uuid, chr->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + char_id.inst_id = chr->characteristic.instance_id; + memcpy(char_id.uuid.uuid, chr->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + /* Write CHar value */ + /* DEBUG */ + BT_INFO("Connection ID [%d] write type [%d] data length [%d]", conn_info->connection_id, write_type, data->length); + for (k = 0; k < data->length; k++) + BT_INFO("Data[%d] [0x%x]", k, data->data[k]); + + ret = gattc_write_characteristic(conn_info->connection_id, + &srvc_id, &char_id, + (oal_gatt_write_type_t)write_type, data->length, + OAL_GATT_AUTH_REQ_NONE, (char *)(&data->data[0])); + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + g_free(addr); + return BLUETOOTH_ERROR_INTERNAL; + } + g_free(addr); + return BLUETOOTH_ERROR_NONE; +} + +/* Write Descriptor */ +int _bt_gatt_write_descriptor_value_by_type( + bluetooth_gatt_client_desc_prop_info_t *desc, + bluetooth_gatt_att_data_t *data, + bluetooth_gatt_write_type_e write_type) +{ + struct gatt_server_info_t *conn_info = NULL; + invocation_info_t *req_info = NULL; + bluetooth_gatt_client_desc_prop_info_t *prop; + oal_gatt_srvc_id_t srvc_id; + oal_gatt_id_t char_id; + oal_gatt_id_t desc_id; + int ret = OAL_STATUS_SUCCESS; + char *addr; + int k; + + BT_CHECK_PARAMETER(desc, return); + BT_CHECK_PARAMETER(data, return); + + BT_INFO("+"); + + /* Check if any app is already writing on same Descriptor of the same char of + particular service on the same remote GATT Server */ + req_info = _bt_get_request_info_data_from_function_name(BT_GATT_WRITE_DESCRIPTOR_VALUE); + if (req_info) { + prop = (bluetooth_gatt_client_desc_prop_info_t*)req_info->user_data; + if (prop && !memcmp(desc->device_address.addr, prop->device_address.addr, sizeof(bluetooth_device_address_t)) /* Address matched */ + && memcmp(desc->svc.uuid, prop->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Service UUID matched */ + && desc->svc.instance_id == prop->svc.instance_id /* Service Instance ID matched */ + && memcmp(desc->characteristic.uuid, prop->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Characteristic UUID matched */ + && desc->characteristic.instance_id == prop->characteristic.instance_id /* Characteristic Instance ID matched */ + && memcmp(desc->descriptor.uuid, prop->descriptor.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) /* Descriptor UUID matched */ + && desc->descriptor.instance_id == prop->descriptor.instance_id) { /* Descriptor Instance ID matched */ + BT_INFO("Already Descriptor value Write operation in progress for same remote GATT Server"); + /* Return and wait for events to be sent to all apps */ + return BLUETOOTH_ERROR_NONE; + } + } + + addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, desc->device_address.addr); + + /* Check if remote GATT Server is connected or not */ + conn_info = __bt_find_remote_gatt_server_info(addr); + if (conn_info) { + BT_INFO("GATT Server [%s] is connected, conn Id [%d]", + conn_info->addr, conn_info->connection_id); + } else { + BT_ERR("GATT Server is not yet connected.."); + g_free(addr); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + srvc_id.is_prmry = TRUE; + srvc_id.id.inst_id = desc->svc.instance_id; + memcpy(srvc_id.id.uuid.uuid, desc->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + char_id.inst_id = desc->characteristic.instance_id; + memcpy(char_id.uuid.uuid, desc->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + desc_id.inst_id = desc->descriptor.instance_id; + memcpy(desc_id.uuid.uuid, desc->descriptor.uuid, BLUETOOTH_UUID_HEX_MAX_LEN); + + /* DEBUG */ + BT_INFO("Connection ID [%d] write type [%d] data length [%d]", conn_info->connection_id, write_type, data->length); + for (k = 0; k < data->length; k++) + BT_INFO("Data[%d] [0x%x]", k, data->data[k]); + + ret = gattc_write_descriptor(conn_info->connection_id, + &srvc_id, &char_id, &desc_id, + (oal_gatt_write_type_t)write_type, data->length, + OAL_GATT_AUTH_REQ_NONE, (char *)(&data->data[0])); + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + g_free(addr); + return BLUETOOTH_ERROR_INTERNAL; + } + g_free(addr); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_disconnect_le_device(bluetooth_device_address_t *address, + int client_id) +{ + struct gatt_server_info_t *conn_info = NULL; + invocation_info_t *req_info = NULL; + int ret = OAL_STATUS_SUCCESS; + char *addr; + char *remote_address = NULL; + + BT_CHECK_PARAMETER(address, return); + + BT_INFO("+"); + + addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, address->addr); + BT_INFO("GATT Client Disconnect request for address [%s]", addr); + + /* Check if Remote Device is already under connection progress */ + req_info = _bt_get_request_info_data_from_function_name(BT_DISCONNECT_LE); + if (req_info) { + remote_address = (char*)req_info->user_data; + if (remote_address && !strcasecmp(remote_address, addr)) {/* Address matched */ + BT_INFO("Already DisConnection ongoing for same remote GATT Server address [%s]", remote_address); + /* Return success and wait for events to be sent to all apps */ + g_free(addr); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + } + /* Check if remote GATT Server is connected or not */ + conn_info = __bt_find_remote_gatt_server_info(addr); + if (!conn_info) { + BT_ERR("GATT Server is not connected.."); + g_free(addr); + return BLUETOOTH_ERROR_NOT_IN_OPERATION; + } + + /* Check if app sent 0 client id for Disconnection, in such case, use default gatt client ID */ + if (client_id == 0) { + BT_INFO("GATT CLient Disconnect request sent by an app without any client instance [%d]", + client_id); + BT_INFO("Assign default GATT client id [%d]", gatt_default_client); + client_id = gatt_default_client; + } + + BT_INFO("Disconnect using CLient ID [%d] Connection ID [%d]", client_id, conn_info->connection_id); + ret = gattc_disconnect(client_id, (bt_address_t*)(address), + conn_info->connection_id); + + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + g_free(addr); + return BLUETOOTH_ERROR_INTERNAL; + } + g_free(addr); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_gatt_watch_service_changed_indication(const char *sender, + bluetooth_device_address_t *address, + gboolean is_enabled) +{ + int k; + bt_service_app_info_t *info = NULL; + + BT_INFO("Enable Servic changed Indication watcher [%d] for app [%s]", + is_enabled, sender); + + for (k = 1; k < MAX_APPS_SUPPORTED; k++) { + info = &numapps[k]; + + if (g_strcmp0(sender, info->sender) == 0 && + memcmp(info->address.addr, address->addr, + sizeof(bluetooth_device_address_t)) == 0) { + BT_INFO("Found GATT client App.. UUID [%s], sender [%s]", info->uuid, info->sender); + info->is_watcher_enabled = is_enabled; + } + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_unregister_gatt_client_instance(const char *sender, int client_id) +{ + BT_INFO("Unregister Allocated GATT CLient instance [%s] Client ID [%d]", + sender, client_id); + int result = BLUETOOTH_ERROR_NONE; + int k; + + /* Unregister CLient instance associated with address X. It is possible that another app still + has client_id valid for same remote address */ + bt_service_app_info_t *info = NULL; + + for (k = 1; k < MAX_APPS_SUPPORTED; k++) { + info = &numapps[k]; + + /* Exact matching of sender */ + if (!g_strcmp0(info->sender, sender) && info->client_id == client_id) { /* Check for only valid GATT client Instance */ + BT_INFO("Unregister GATT client instance [%d]", info->client_id); + result = __bt_do_unregister_gatt_instance(info->client_id); + if (result != BLUETOOTH_ERROR_NONE) + BT_ERR("Error in unregistering GATT Client Interface"); + + break; + } + } + return result; +} + +#endif diff --git a/bt-service-adaptation/services/include/bt-service-common.h b/bt-service-adaptation/services/include/bt-service-common.h index 04e7d32..c8e5e3b 100644 --- a/bt-service-adaptation/services/include/bt-service-common.h +++ b/bt-service-adaptation/services/include/bt-service-common.h @@ -443,6 +443,8 @@ GDBusConnection *_bt_gdbus_get_system_gconn(void); void _bt_copy_remote_dev_info(bt_remote_dev_info_t *dest, bt_remote_dev_info_t *src); +invocation_info_t* _bt_get_request_info_data_from_function_name(int service_function); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bt-service-adaptation/services/include/bt-service-core-device.h b/bt-service-adaptation/services/include/bt-service-core-device.h index b347ef8..59c605f 100755 --- a/bt-service-adaptation/services/include/bt-service-core-device.h +++ b/bt-service-adaptation/services/include/bt-service-core-device.h @@ -35,6 +35,13 @@ typedef struct { gboolean _bt_is_device_creating(void); +#ifdef TIZEN_GATT_CLIENT +int _bt_le_connection_update(const char *sender, + unsigned char *device_address, + float interval_min, float interval_max, + guint16 latency, guint16 time_out); +#endif + #ifdef TIZEN_FEATURE_BT_OBEX bluetooth_trusted_profile_t _bt_get_trusted_profile_enum(const char *uuid); #endif diff --git a/bt-service-adaptation/services/include/bt-service-gatt.h b/bt-service-adaptation/services/include/bt-service-gatt.h index 08c5728..3f52c88 100644 --- a/bt-service-adaptation/services/include/bt-service-gatt.h +++ b/bt-service-adaptation/services/include/bt-service-gatt.h @@ -27,6 +27,10 @@ #include "bluetooth-api.h" #include "bluetooth-gatt-server-api.h" +#ifdef TIZEN_GATT_CLIENT +#include "bluetooth-gatt-client-api.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -91,6 +95,53 @@ int _bt_gatt_server_update_attribute_value(char *sender, int instance_id, int _bt_get_att_mtu(bluetooth_device_address_t *address, unsigned int *mtu); +#ifdef TIZEN_GATT_CLIENT +char * _bt_gatt_get_default_gatt_client_uuid(void); + +int _bt_register_gatt_client_instance(const char *sender, + bluetooth_device_address_t *address); + +gboolean _bt_is_remote_gatt_device_connected(bluetooth_device_address_t *address); + + +int _bt_connect_le_device(bluetooth_device_address_t *address, + int auto_connect, int client_id); + +int _bt_gatt_get_primary_services(char *address); + +int _bt_gatt_get_all_characteristic(bluetooth_gatt_client_svc_prop_info_t *svc); + +int _bt_gatt_get_all_characteristic_properties( + bluetooth_gatt_client_char_prop_info_t *prop); + +int _bt_gatt_read_characteristic_value( + bluetooth_gatt_client_char_prop_info_t *desc); + +int _bt_gatt_read_descriptor_value( + bluetooth_gatt_client_desc_prop_info_t *desc); + +int _bt_gatt_write_characteristic_value_by_type( + bluetooth_gatt_client_char_prop_info_t *chr, + bluetooth_gatt_att_data_t *data, + bluetooth_gatt_write_type_e write_type); + +int _bt_gatt_write_descriptor_value_by_type( + bluetooth_gatt_client_desc_prop_info_t *desc, + bluetooth_gatt_att_data_t *data, + bluetooth_gatt_write_type_e write_type); + +int _bt_disconnect_le_device(bluetooth_device_address_t *address, + int client_id); + + +int _bt_gatt_watch_service_changed_indication(const char *sender, + bluetooth_device_address_t *address, + gboolean is_enabled); + +int _bt_unregister_gatt_client_instance(const char *sender, + int client_id); + +#endif //int _bt_gatt_server_enable_application(int instance_id); #if 0 int _bt_gatt_server_register(char *sender); diff --git a/include/bluetooth-api.h b/include/bluetooth-api.h index 7c21876..e5bbe73 100644 --- a/include/bluetooth-api.h +++ b/include/bluetooth-api.h @@ -36,7 +36,7 @@ extern "C" { * @{ */ -#define BLUETOOTH_ADDRESS_STRING_LENGTH 17 /**< This specifies bluetooth device address length (AA:BB:CC:DD:EE:FF) */ +#define BLUETOOTH_ADDRESS_STRING_LENGTH 18 /**< This specifies bluetooth device address length (AA:BB:CC:DD:EE:FF) */ #define BLUETOOTH_ADDRESS_LENGTH 6 /**< This specifies bluetooth device address length */ #define BLUETOOTH_VERSION_LENGTH_MAX 30 /**< This specifies bluetooth device version length */ #define BLUETOOTH_INTERFACE_NAME_LENGTH 16 @@ -58,6 +58,10 @@ extern "C" { #define BLUETOOTH_PIN_CODE_MAX_LENGTH 16 +#ifdef TIZEN_GATT_CLIENT +#define BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX 610 /**< GATT ATT value max len */ +#endif + /** * This is Bluetooth Connected event role */ @@ -786,8 +790,15 @@ typedef enum { BLUETOOTH_EVENT_GATT_READ_DESC, /** +#include +#include + +#include +#include + +#define BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX 610 /**< GATT ATT value max len */ +#define BLUETOOTH_UUID_HEX_MAX_LEN 16 /**< UUID complete len in hex */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int event; + int result; + void *param_data; + void *user_data; +} gatt_client_event_param_t; + +typedef struct { + bluetooth_device_address_t device_addr; + int count; + char uuids[BLUETOOTH_MAX_SERVICES_FOR_DEVICE][BLUETOOTH_UUID_STRING_MAX]; + int inst_id[BLUETOOTH_MAX_SERVICES_FOR_DEVICE]; + int primary[BLUETOOTH_MAX_SERVICES_FOR_DEVICE]; +} bt_services_browse_info_t; + + +typedef enum { + BLUETOOTH_GATT_TYPE_WRITE_NO_RESPONSE = 0x01, /* Write Without Response */ + BLUETOOTH_GATT_TYPE_WRITE = 0x2, /* Write */ +} bluetooth_gatt_write_type_e; + + +/* Structure used for browsing a particular service's properties(chars and Incldued svcs) */ +typedef struct { + bluetooth_device_address_t device_address; /**< device address */ + bt_gatt_handle_property_t svc; +} bluetooth_gatt_client_svc_prop_info_t; + +typedef struct { + bluetooth_device_address_t device_addr; + int count; + unsigned char svc_uuid[BLUETOOTH_UUID_HEX_MAX_LEN]; + int svc_inst_id; + char uuids[BLUETOOTH_MAX_SERVICES_FOR_DEVICE][BLUETOOTH_UUID_STRING_MAX]; + int inst_id[BLUETOOTH_MAX_SERVICES_FOR_DEVICE]; + int props[BLUETOOTH_MAX_SERVICES_FOR_DEVICE]; +} bt_char_browse_info_t; + +typedef struct { + bluetooth_device_address_t device_addr; + int count; + unsigned char svc_uuid[BLUETOOTH_UUID_HEX_MAX_LEN]; + int svc_inst_id; + char uuids[BLUETOOTH_MAX_SERVICES_FOR_DEVICE][BLUETOOTH_UUID_STRING_MAX]; + int inst_id[BLUETOOTH_MAX_SERVICES_FOR_DEVICE]; +} bt_included_services_browse_info_t; + +typedef struct { + bluetooth_device_address_t device_addr; + int count; + unsigned char svc_uuid[BLUETOOTH_UUID_HEX_MAX_LEN]; + int svc_inst_id; + unsigned char char_uuid[BLUETOOTH_UUID_HEX_MAX_LEN]; + int char_inst_id; + int char_props_map; + char uuids[BLUETOOTH_MAX_SERVICES_FOR_DEVICE][BLUETOOTH_UUID_STRING_MAX]; + int inst_id[BLUETOOTH_MAX_SERVICES_FOR_DEVICE]; +} bt_descriptor_browse_info_t; + +/* Structure used for browsing a particular charactertic's properties(descriptors) or reading char's value */ +typedef struct { + bluetooth_device_address_t device_address; /**< device address */ + bt_gatt_handle_property_t svc; + bt_gatt_handle_property_t characteristic; +} bluetooth_gatt_client_char_prop_info_t; + +/* Structure used for reading Descriptor's value */ +typedef struct { + bluetooth_device_address_t device_address; /**< device address */ + bt_gatt_handle_property_t svc; + bt_gatt_handle_property_t characteristic; + bt_gatt_handle_property_t descriptor; +} bluetooth_gatt_client_desc_prop_info_t; + + +typedef void (*gatt_client_cb_func_ptr)(int, gatt_client_event_param_t *, void *); + +/** + * @fn int bluetooth_gatt_client_init(int *client_id, gatt_client_cb_func_ptr callback_ptr, void *user_data) + * @brief Initialize GATT Client instance with BT stack and register the callback + * + * This function is a synchronous call. + * + * @remark None + * + */ +int bluetooth_gatt_client_init(int *client_id, + const bluetooth_device_address_t *address, + gatt_client_cb_func_ptr callback_ptr); + +int bluetooth_gatt_client_deinit(int client_id); + +int bluetooth_gatt_client_get_primary_services(const bluetooth_device_address_t *address, + bt_gatt_handle_info_t *prim_svc); + +int bluetooth_gatt_client_get_service_property(const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_service_property_t *service); + +int bluetooth_gatt_client_get_characteristics_property(const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + bt_gatt_char_property_t *char_prop); + +int bluetooth_gatt_client_get_char_descriptor_property(const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + bt_gatt_handle_property_t *descriptor_handle, + bt_gatt_char_descriptor_property_t *desc_prop); + +int bluetooth_gatt_client_read_characteristic_value(const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle); + +int bluetooth_gatt_client_read_descriptor_value(const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + bt_gatt_handle_property_t *descriptor_handle); + + +int bluetooth_gatt_client_write_characteristic_value_by_type( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + bluetooth_gatt_att_data_t *data, + bluetooth_gatt_write_type_e write_type); + +int bluetooth_gatt_client_write_descriptor_value( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + bt_gatt_handle_property_t *descriptor_handle, + bluetooth_gatt_att_data_t *data, + bluetooth_gatt_write_type_e write_type); + +int bluetooth_gatt_client_set_service_change_watcher( + const bluetooth_device_address_t *address, + gboolean enable); + +int bluetooth_gatt_client_watch_characteristics( + const char *address, + bt_gatt_handle_property_t *service_handle, + bt_gatt_handle_property_t *char_handle, + int client_id, + gboolean is_notify); + +#ifdef __cplusplus +} +#endif +#endif /* __BLUETOOTH_GATT_CLIENT_API_H */ diff --git a/include/bt-internal-types.h b/include/bt-internal-types.h index d3da33b..728d9c4 100644 --- a/include/bt-internal-types.h +++ b/include/bt-internal-types.h @@ -71,6 +71,9 @@ typedef enum { //#ifndef GATT_DIRECT BT_GATT_SERVER_EVENT, //#endif +#ifdef TIZEN_GATT_CLIENT + BT_GATT_CLIENT_EVENT, +#endif BT_TDS_EVENT, BT_OTP_EVENT, BT_HDP_EVENT, @@ -326,10 +329,23 @@ typedef enum { BT_HDP_UNREGISTER_SINK_APP, BT_HDP_GET_FD, - BT_GATT_GET_PRIMARY_SERVICES = BT_FUNC_GATT_BASE, + BT_GATT_GET_PRIMARY_SERVICES = BT_FUNC_GATT_BASE, /* GATT Client */ +#ifdef TIZEN_GATT_CLIENT + BT_GATT_CLIENT_REGISTER, /* GATT Client */ + BT_GATT_CLIENT_UNREGISTER, /* GATT Client */ + BT_GATT_GET_SERVICE_PROPERTIES, /* GATT Client */ + BT_GATT_GET_CHARACTERISTIC_PROPERTIES, /* GATT Client */ + BT_GATT_GET_INCLUDED_SERVICES, /* GATT Client */ +#endif BT_GATT_DISCOVER_CHARACTERISTICS, BT_GATT_SET_PROPERTY_REQUEST, - BT_GATT_READ_CHARACTERISTIC, + BT_GATT_READ_CHARACTERISTIC, /* GATT Client*/ +#ifdef TIZEN_GATT_CLIENT + BT_GATT_READ_DESCRIPTOR_VALUE, /* GATT Client */ + BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE, /* GATT Client */ + BT_GATT_WRITE_DESCRIPTOR_VALUE, /* GATT Client */ + BT_GATT_WATCH_SERVICE_CHANGED_INDICATION, /* GATT Client */ +#endif BT_GATT_DISCOVER_CHARACTERISTICS_DESCRIPTOR, #ifndef GATT_NO_RELAY BT_GATT_WATCH_CHARACTERISTIC, @@ -478,6 +494,10 @@ typedef struct { #define BT_GATT_SERVER_PATH "/org/projectx/bt/gatt_server" #endif +#ifdef TIZEN_GATT_CLIENT +#define BT_GATT_CLIENT_PATH "/org/projectx/bt/gatt_client" +#endif + #define BT_ENABLED "Enabled" #define BT_DISABLED "Disabled" #define BT_LE_ENABLED "LeEnabled" @@ -575,8 +595,16 @@ typedef struct { #define BT_MEDIA_TRACK_CHANGE "MediaTrackStatus" #define BT_MEDIA_DELAY_CHANGE "MediaDelayStatus" #define BT_NAME_OWNER_CHANGED "NameOwnerChanged" + +#ifdef TIZEN_GATT_CLIENT +#define BT_GATT_SERVER_CONNECTED "GattServerConnected" +#define BT_GATT_SERVER_DISCONNECTED "GattServerDisconnected" +#define BT_GATT_CLIENT_CONNECTED "GattClientConnected" +#define BT_GATT_CLIENT_DISCONNECTED "GattClientDisconnected" +#else #define BT_GATT_CONNECTED "GattConnected" #define BT_GATT_DISCONNECTED "GattDisconnected" +#endif #ifndef GATT_DIRECT #define BT_GATT_VALUE_CHANGED "GattValueChanged" @@ -585,6 +613,13 @@ typedef struct { #define BT_GATT_SERVER_NOTIFICATION_CHANGED "GattServerNotifChanged" #endif +#ifdef TIZEN_GATT_CLIENT +#define BT_GATT_CLIENT_READ_CHAR "GattReadCharValue" +#define BT_GATT_CLIENT_WRITE_CHAR "GattWriteCharValue" +#define BT_GATT_CLIENT_READ_DESC "GattReadDescriptor" +#define BT_GATT_CLIENT_WRITE_DESC "GattWriteDescriptor" +#endif + #define BT_GATT_REQ_ATT_MTU_CHANGED "GattReqAttMtuChanged" #define BT_GATT_CHAR_VAL_CHANGED "GattCharValueChanged" #ifdef GATT_NO_RELAY diff --git a/packaging/bluetooth-frwk.spec b/packaging/bluetooth-frwk.spec index 0593cf1..8ae5058 100644 --- a/packaging/bluetooth-frwk.spec +++ b/packaging/bluetooth-frwk.spec @@ -193,6 +193,7 @@ export CFLAGS="$CFLAGS -DTIZEN_FEATURE_BT_PAN_NAP" export CFLAGS="$CFLAGS -DTIZEN_FEATURE_BT_IPSP" export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" +export CFLAGS="$CFLAGS -DTIZEN_GATT_CLIENT" %define _servicefile packaging/bluetooth-frwk-common.service %define _servicedir starter.target.wants @@ -403,6 +404,7 @@ ln -sf %{_libdir}/systemd/system/bluetooth-frwk-core.service %{_sysconfdir}/syst %{_includedir}/bt-service/bluetooth-scmst-api.h %{_includedir}/bt-service/bluetooth-ipsp-api.h %{_includedir}/bt-service/bluetooth-gatt-server-api.h +%{_includedir}/bt-service/bluetooth-gatt-client-api.h %{_libdir}/pkgconfig/bluetooth-api.pc %{_libdir}/libbluetooth-api.so -- 2.7.4