From e3b95eee9e7fe07140319d1485d6f04b9c18a970 Mon Sep 17 00:00:00 2001 From: Amit Purwar Date: Thu, 17 May 2018 13:00:08 +0530 Subject: CAPI changes for gatt client adaptation Change-Id: I2a424cc32498e54aa852d572523503123d59bbf0 Signed-off-by: Amit Purwar --- include/bluetooth_private.h | 57 +- packaging/capi-network-bluetooth.spec | 2 +- src/bluetooth-common.c | 143 ++- src/bluetooth-gatt.c | 1806 +++++++++++++++++++++++++++++++-- 4 files changed, 1916 insertions(+), 92 deletions(-) diff --git a/include/bluetooth_private.h b/include/bluetooth_private.h index 77e4136..518e5f5 100644 --- a/include/bluetooth_private.h +++ b/include/bluetooth_private.h @@ -32,6 +32,10 @@ #include #endif +#ifdef TIZEN_GATT_CLIENT +#include +#endif + #include "bluetooth.h" #include "bluetooth_internal.h" @@ -328,6 +332,9 @@ typedef struct { bt_gatt_client_service_changed_cb service_changed_cb; void *service_changed_user_data; void *att_mtu_changed_user_data; +#ifdef TIZEN_GATT_CLIENT + int client_id; +#endif } bt_gatt_client_s; typedef struct { @@ -358,6 +365,11 @@ typedef struct { GSList *included_services; GSList *characteristics; +#ifdef TIZEN_GATT_CLIENT + int instance_id; /* Instance ID of the service object */ + bt_gatt_handle_info_t svc_include_handles; + bt_gatt_handle_info_t charc_handles; +#endif char **include_handles; char **char_handles; } bt_gatt_service_s; @@ -378,6 +390,10 @@ typedef struct { GSList *descriptors; +#ifdef TIZEN_GATT_CLIENT + int instance_id; /* Instance ID of the characteristic object */ + bt_gatt_handle_info_t descriptor_handles; +#endif char **desc_handles; bt_gatt_client_characteristic_value_changed_cb value_changed_cb; @@ -397,12 +413,13 @@ typedef struct { int value_length; char *value; - +#ifdef TIZEN_GATT_CLIENT bt_gatt_client_request_completed_cb read_cb; void *read_user_data; bt_gatt_client_request_completed_cb write_cb; void *write_user_data; +#endif } bt_gatt_characteristic_s; typedef struct { @@ -413,6 +430,9 @@ typedef struct { char *uuid; #ifdef TIZEN_FEATURE_GATT_RELAY int handle; +#endif +#ifdef TIZEN_GATT_CLIENT + int instance_id; /* Instance ID of the descriptor object */ #endif int permissions; @@ -424,12 +444,13 @@ typedef struct { int value_length; char *value; - +#ifdef TIZEN_GATT_CLIENT bt_gatt_client_request_completed_cb read_cb; void *read_user_data; bt_gatt_client_request_completed_cb write_cb; void *write_user_data; +#endif } bt_gatt_descriptor_s; typedef struct { @@ -497,6 +518,23 @@ typedef void (*bt_rssi_strength_cb)(char *bt_address, typedef void (*_bt_gatt_client_value_changed_cb)(char *char_path, unsigned char *value, int value_length, void *user_data); +#ifdef TIZEN_GATT_CLIENT +typedef void (*_bt_gatt_client_val_changed_cb)(unsigned char *uuid, char *remote_address, + char *value, int value_length, void *user_data); + +void _bt_handle_gatt_client_char_read_completed_event(int result, + void *resp); + +void _bt_handle_gatt_client_desc_read_completed_event(int result, + void *resp); + +void _bt_handle_gatt_client_char_write_completed_event(int result, + void *resp); + +void _bt_handle_gatt_client_desc_write_completed_event(int result, + void *resp); +#endif + /** * @internal * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE @@ -566,7 +604,7 @@ do { \ do { \ bool is_supported = false; \ if (!system_info_get_platform_bool(feature_name1, &is_supported)) { \ - if (is_supported == false) { \ + if (is_supported == false) { \ LOGE("[%s] NOT_SUPPORTED(0x%08x)", __FUNCTION__, BT_ERROR_NOT_SUPPORTED); \ return BT_ERROR_NOT_SUPPORTED; \ } \ @@ -574,7 +612,7 @@ do { \ LOGE("[%s] Fail to get the system feature: [%s]", __FUNCTION__, feature_name1); \ } \ if (!system_info_get_platform_bool(feature_name2, &is_supported)) { \ - if (is_supported == false) { \ + if (is_supported == false) { \ LOGE("[%s] NOT_SUPPORTED(0x%08x)", __FUNCTION__, BT_ERROR_NOT_SUPPORTED); \ return BT_ERROR_NOT_SUPPORTED; \ } \ @@ -771,7 +809,12 @@ bt_gatt_client_h _bt_gatt_get_client(const char *remote_addr); const GSList* _bt_gatt_get_server_list(void); +#ifdef TIZEN_GATT_CLIENT +bt_gatt_h _bt_gatt_client_add_service(bt_gatt_client_h client, + const char *uuid, int instance_id); +#else bt_gatt_h _bt_gatt_client_add_service(bt_gatt_client_h client, const char *path); +#endif int _bt_gatt_client_update_services(bt_gatt_client_h client); @@ -790,6 +833,12 @@ void _bt_gatt_server_event_proxy(int event, gatt_server_event_param_t *param, vo #endif +#ifdef TIZEN_GATT_CLIENT +void _bt_gatt_client_event_proxy(int event, + gatt_client_event_param_t *param, void *user_data); +#endif + + /** * @ingroup CAPI_NETWORK_BLUETOOTH_LE_MODULE * @brief Reads the maximum data length of LE packets supported by the controller. diff --git a/packaging/capi-network-bluetooth.spec b/packaging/capi-network-bluetooth.spec index ac6a66d..eb1d305 100644 --- a/packaging/capi-network-bluetooth.spec +++ b/packaging/capi-network-bluetooth.spec @@ -57,7 +57,7 @@ export LDFLAGS+=" -lgcov" #export CXXFLAGS="$CXXFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT" #export FFLAGS="$FFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT" -export CFLAGS="$CFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT -DTIZEN_FEATURE_GATT_RELAY -DTIZEN_FEATURE_TCT_TMP_SUPPORT" +export CFLAGS="$CFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT -DTIZEN_FEATURE_GATT_RELAY -DTIZEN_FEATURE_TCT_TMP_SUPPORT -DTIZEN_GATT_CLIENT" export CXXFLAGS="$CXXFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT -DTIZEN_FEATURE_GATT_RELAY -DTIZEN_FEATURE_TCT_TMP_SUPPORT" export FFLAGS="$FFLAGS -DTIZEN_FEATURE_AUDIO_HF_DISABLE -DTIZEN_FEATURE_OTP_SUPPORT -DTIZEN_FEATURE_GATT_RELAY -DTIZEN_FEATURE_TCT_TMP_SUPPORT" diff --git a/src/bluetooth-common.c b/src/bluetooth-common.c index 3200a89..30e3341 100644 --- a/src/bluetooth-common.c +++ b/src/bluetooth-common.c @@ -81,7 +81,6 @@ int bt_initialize(void) int bt_deinitialize(void) { - BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); BT_CHECK_INIT_STATUS(); if (bluetooth_unregister_callback() != BLUETOOTH_ERROR_NONE) { @@ -1079,6 +1078,20 @@ void _bt_hid_event_proxy(int event, hid_event_param_t *param, void *user_data) new_param.user_data = param->user_data; __bt_event_proxy(event, &new_param, user_data); } + +#ifdef TIZEN_GATT_CLIENT +void _bt_gatt_client_event_proxy(int event, + gatt_client_event_param_t *param, void *user_data) +{ + bluetooth_event_param_t new_param; + new_param.event = param->event; + new_param.param_data = param->param_data; + new_param.result = param->result; + new_param.user_data = NULL; + __bt_event_proxy(event, &new_param, user_data); +} +#endif + /* LCOV_EXCL_STOP */ static bool __bt_need_to_handle(int event) @@ -1088,8 +1101,15 @@ static bool __bt_need_to_handle(int event) switch (event) { case BLUETOOTH_EVENT_ADVERTISING_STARTED: case BLUETOOTH_EVENT_ADVERTISING_STOPPED: +#ifdef TIZEN_GATT_CLIENT + case BLUETOOTH_EVENT_GATT_CLIENT_CONNECTED: + case BLUETOOTH_EVENT_GATT_CLIENT_DISCONNECTED: + case BLUETOOTH_EVENT_GATT_SERVER_CONNECTED: + case BLUETOOTH_EVENT_GATT_SERVER_DISCONNECTED: +#else case BLUETOOTH_EVENT_GATT_CONNECTED: case BLUETOOTH_EVENT_GATT_DISCONNECTED: +#endif case BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED: case BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED: case BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED: @@ -2032,6 +2052,94 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us ((bt_hid_device_data_received_cb)bt_event_slot_container[event_index].callback) ((bt_hid_device_received_data_s *)(param->param_data), bt_event_slot_container[event_index].user_data); break; +#ifdef TIZEN_GATT_CLIENT + /* Local is GATT server */ + case BLUETOOTH_EVENT_GATT_SERVER_CONNECTED: { + bt_gatt_connection_state_changed_cb cb = NULL; + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_CONNECTED"); + _bt_convert_address_to_string(&device_addr, + (bluetooth_device_address_t *)(param->param_data)); + BT_INFO("GATT Server Connected address[%s]", device_addr); + if (event_index >= 0) + cb = bt_event_slot_container[event_index].callback; + if (cb) + cb(_bt_get_error_code(param->result), TRUE, device_addr, + bt_event_slot_container[event_index].user_data); + g_free(device_addr); + device_addr = NULL; + break; + } + case BLUETOOTH_EVENT_GATT_SERVER_DISCONNECTED: { + bt_gatt_connection_state_changed_cb cb = NULL; + BT_INFO("BLUETOOTH_EVENT_GATT_SERVER_DISCONNECTED"); + _bt_convert_address_to_string(&device_addr, + (bluetooth_device_address_t *)(param->param_data)); + if (event_index >= 0) + cb = bt_event_slot_container[event_index].callback; + if (cb) + cb(_bt_get_error_code(param->result), FALSE, device_addr, + bt_event_slot_container[event_index].user_data); + g_free(device_addr); + device_addr = NULL; + break; + } + /* Local is GATT client */ + case BLUETOOTH_EVENT_GATT_CLIENT_CONNECTED: { + bt_gatt_client_s *client_s; + bt_gatt_connection_state_changed_cb cb = NULL; + BT_INFO("BLUETOOTH_EVENT_GATT_CLIENT_CONNECTED"); + _bt_convert_address_to_string(&device_addr, + (bluetooth_device_address_t *)(param->param_data)); + BT_INFO("GATT Connected address[%s] result [%d]", device_addr, + _bt_get_error_code(param->result)); + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(device_addr); + + if (BT_ERROR_NONE == _bt_get_error_code(param->result)) { + if (client_s && !client_s->services_discovered) { + BT_INFO("GATT Connected but services are not discovered yet, start browse client id [%d]", + client_s->client_id); + BT_INFO("GATT Client Connected address[%s]", device_addr); + if (client_s) + client_s->connected = true; + _bt_gatt_client_update_services(client_s); + } + } + + if (event_index >= 0) + cb = bt_event_slot_container[event_index].callback; + if (cb) + cb(_bt_get_error_code(param->result), TRUE, device_addr, + bt_event_slot_container[event_index].user_data); + g_free(device_addr); + device_addr = NULL; + break; + } + case BLUETOOTH_EVENT_GATT_CLIENT_DISCONNECTED: { + bt_gatt_client_s *client_s; + bt_gatt_connection_state_changed_cb cb = NULL; + BT_INFO("BLUETOOTH_EVENT_GATT_CLIENT_DISCONNECTED"); + _bt_convert_address_to_string(&device_addr, + (bluetooth_device_address_t *)(param->param_data)); + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(device_addr); + BT_INFO("GATT DisConnected address[%s] result [%d]", device_addr, + _bt_get_error_code(param->result)); + if (client_s) { + BT_INFO("GATT CLient instance present for addr [%s] client ID [%d]", + client_s->remote_address, client_s->client_id); + client_s->connected = false; + /* Mark services not discovered */ + client_s->services_discovered = false; + } + if (event_index >= 0) + cb = bt_event_slot_container[event_index].callback; + if (cb) + cb(_bt_get_error_code(param->result), FALSE, device_addr, + bt_event_slot_container[event_index].user_data); + g_free(device_addr); + device_addr = NULL; + break; + } +#else case BLUETOOTH_EVENT_GATT_CONNECTED: { bt_gatt_client_s *client_s; bt_gatt_connection_state_changed_cb cb = NULL; @@ -2097,6 +2205,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us device_addr = NULL; break; } +#endif case BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED: char_val = (bt_gatt_char_value_t *)(param->param_data); @@ -2108,6 +2217,24 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us bt_event_slot_container[event_index].user_data); break; +#ifdef TIZEN_GATT_CLIENT + case BLUETOOTH_EVENT_GATT_READ_CHAR: + BT_INFO("BLUETOOTH_EVENT_GATT_READ_CHAR"); + _bt_handle_gatt_client_char_read_completed_event(param->result, param->param_data); + break; + case BLUETOOTH_EVENT_GATT_WRITE_CHAR: + BT_INFO("BLUETOOTH_EVENT_GATT_WRITE_CHAR"); + _bt_handle_gatt_client_char_write_completed_event(param->result, param->param_data); + break; + case BLUETOOTH_EVENT_GATT_READ_DESC: + BT_INFO("BLUETOOTH_EVENT_GATT_READ_DESC"); + _bt_handle_gatt_client_desc_read_completed_event(param->result, param->param_data); + break; + case BLUETOOTH_EVENT_GATT_WRITE_DESC: + BT_INFO("BLUETOOTH_EVENT_GATT_WRITE_DESC"); + _bt_handle_gatt_client_desc_write_completed_event(param->result, param->param_data); + break; +#else case BLUETOOTH_EVENT_GATT_READ_CHAR: BT_INFO("BLUETOOTH_EVENT_GATT_READ_CHAR"); _handle_gatt_client_read_completed_event(param->result, @@ -2128,6 +2255,7 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us _handle_gatt_client_write_completed_event(param->result, param->param_data); break; +#endif case BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED: { #ifdef TIZEN_FEATURE_GATT_RELAY bluetooth_gatt_server_read_requested_info_t *read_req = @@ -2434,9 +2562,12 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us BT_INFO("already added service : %s", svc->path); break; } - +#ifdef TIZEN_GATT_CLIENT + BT_INFO("TODO this task"); +#else svc = _bt_gatt_client_add_service(client, service_change->svc_path); +#endif if (svc == NULL) { BT_ERR("_bt_gatt_client_add_service is failed"); break; @@ -3343,9 +3474,17 @@ static int __bt_get_cb_index(int event) case BLUETOOTH_EVENT_DEVICE_CONNECTED: case BLUETOOTH_EVENT_DEVICE_DISCONNECTED: return BT_EVENT_DEVICE_CONNECTION_STATUS; +#ifdef TIZEN_GATT_CLIENT + case BLUETOOTH_EVENT_GATT_CLIENT_CONNECTED: + case BLUETOOTH_EVENT_GATT_CLIENT_DISCONNECTED: + case BLUETOOTH_EVENT_GATT_SERVER_CONNECTED: + case BLUETOOTH_EVENT_GATT_SERVER_DISCONNECTED: + return BT_EVENT_GATT_CONNECTION_STATUS; +#else case BLUETOOTH_EVENT_GATT_CONNECTED: case BLUETOOTH_EVENT_GATT_DISCONNECTED: return BT_EVENT_GATT_CONNECTION_STATUS; +#endif case BLUETOOTH_EVENT_SERVICE_SEARCHED: return BT_EVENT_SERVICE_SEARCHED; case BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED: diff --git a/src/bluetooth-gatt.c b/src/bluetooth-gatt.c index 2b6313e..a698f47 100644 --- a/src/bluetooth-gatt.c +++ b/src/bluetooth-gatt.c @@ -30,10 +30,20 @@ int instance_id; #endif +#ifdef TIZEN_GATT_CLIENT +#include +#include +#include +#include +#include "bluetooth-gatt-client-api.h" +#endif + #define BT_ADDR_STR_LEN 17 static GSList *gatt_client_list = NULL; +static GSList *gatt_handle_list = NULL; + static GSList *gatt_server_list = NULL; static bool is_gatt_server_initialized = false; static bool is_gatt_server_started = false; @@ -70,6 +80,51 @@ static void __bt_gatt_free_service(bt_gatt_h gatt_handle); } \ } +#define BT_VALIDATE_GATT_HANDLE(h1) \ +{ \ + GSList *l; \ + bool valid = FALSE; \ + for (l = gatt_handle_list; l; l = g_slist_next(l)) { \ + bt_gatt_h h2 = (bt_gatt_h)l->data; \ + if (h1 == h2) { \ + BT_INFO("Handle matched [%p]", h2); \ + valid = TRUE; break; \ + } \ + } \ + if (valid == FALSE) { \ + BT_ERR("App Handle [%p] did not match with any stored handles!!! Must be Invalid Handle!!", h1); \ + return BT_ERROR_INVALID_PARAMETER; \ + } \ +} \ + +#ifdef TIZEN_GATT_CLIENT +static void __bt_gatt_free_service(bt_gatt_h gatt_handle); + +void __bt_string_to_uuid_hex(const char *str, unsigned char *uuid) +{ + uint32_t uuid0, uuid4; + uint16_t uuid1, uuid2, uuid3, uuid5; + + sscanf(str, "%08x-%04hx-%04hx-%04hx-%08x%04hx", + &uuid0, &uuid1, &uuid2, &uuid3, &uuid4, &uuid5); + + uuid0 = htonl(uuid0); + uuid1 = htons(uuid1); + uuid2 = htons(uuid2); + uuid3 = htons(uuid3); + uuid4 = htonl(uuid4); + uuid5 = htons(uuid5); + + memcpy(&(uuid[0]), &uuid0, 4); + memcpy(&(uuid[4]), &uuid1, 2); + memcpy(&(uuid[6]), &uuid2, 2); + memcpy(&(uuid[8]), &uuid3, 2); + memcpy(&(uuid[10]), &uuid4, 4); + memcpy(&(uuid[14]), &uuid5, 2); + return; +} +#endif + /* LCOV_EXCL_START */ static int __bt_check_gatt_server_init_status(void) { @@ -88,6 +143,7 @@ static int __get_gatt_handle_by_uuid(GSList *list, const char *uuid, char *uuid128_a; char *uuid128_b; + BT_INFO("UUID [%s]", uuid); uuid128_a = _bt_convert_uuid_to_uuid128(uuid); if (uuid128_a == NULL) { BT_ERR("Wrong type of uuid : %s", uuid); @@ -145,6 +201,75 @@ const GSList* _bt_gatt_get_server_list(void) return gatt_server_list; } +static void __bt_gatt_client_handle_destroy(bt_gatt_h gatt_handle) +{ + bt_gatt_common_s *handle = (bt_gatt_common_s*)gatt_handle; + + if (handle->type == BT_GATT_TYPE_SERVICE) + bt_gatt_service_destroy(gatt_handle); + else if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) + bt_gatt_characteristic_destroy(gatt_handle); + else if (handle->type == BT_GATT_TYPE_DESCRIPTOR) + bt_gatt_descriptor_destroy(gatt_handle); +} + +#ifdef TIZEN_GATT_CLIENT +bt_gatt_h _bt_gatt_client_add_service(bt_gatt_client_h client, + const char *uuid, int instance_id) +{ + int ret; + bt_gatt_client_s *client_s = (bt_gatt_client_s*)client; + bt_gatt_service_s *svc = NULL; + bt_gatt_service_property_t property; + bt_gatt_handle_property_t service; + + if (client == NULL || uuid == NULL) { + BT_ERR("Invalid parameter"); + return NULL; + } + + memset(&property, 0x00, sizeof(bt_gatt_service_property_t)); + memset(&service, 0x00, sizeof(bt_gatt_handle_property_t)); + + __bt_string_to_uuid_hex(uuid, service.uuid); + service.instance_id = instance_id; + + BT_INFO("GATT client add service: get all properties of this service"); + ret = bluetooth_gatt_client_get_service_property(client_s->remote_address, + &service, &property); + ret = _bt_get_error_code(ret); + if (ret != BT_ERROR_NONE) { + BT_ERR("bluetooth_gatt_get_service_property is failed"); + return NULL; + } + + BT_INFO("Service properties are retrieved successfully, now create and add service object"); + svc = __bt_gatt_service_create(property.uuid, + BT_GATT_SERVICE_TYPE_PRIMARY); + if (svc == NULL) { + BT_ERR("svc is NULL"); + return NULL; + } + svc->role = BT_GATT_ROLE_CLIENT; + svc->instance_id = instance_id; + svc->parent = (void *)client_s; + svc->is_included_service = false; + + /* Copy included service handles and charc handles in just created service object */ + memcpy(&svc->svc_include_handles, &property.include_handles, sizeof(bt_gatt_handle_info_t)); + BT_INFO("Total number of Included service handles [%d]", svc->svc_include_handles.count); + memcpy(&svc->charc_handles, &property.char_handle, sizeof(bt_gatt_handle_info_t)); + BT_INFO("Total number of Characteristic handles [%d]", svc->charc_handles.count); + + bluetooth_gatt_free_service_property(&property); + + client_s->services = g_slist_append(client_s->services, svc); + BT_INFO("GATT service added , current count of Client services [%d]", + g_slist_length(client_s->services)); + + return svc; +} +#else bt_gatt_h _bt_gatt_client_add_service(bt_gatt_client_h client, const char *path) { int ret; @@ -189,7 +314,61 @@ bt_gatt_h _bt_gatt_client_add_service(bt_gatt_client_h client, const char *path) return svc; } +#endif + +#ifdef TIZEN_GATT_CLIENT +int _bt_gatt_client_update_services(bt_gatt_client_h client) +{ + bt_gatt_client_s *client_s = client; + bluetooth_device_address_t addr_hex = { {0, } }; + bt_gatt_handle_info_t prim_svc; + int ret; + int i; + if (!client_s->connected) { + BT_INFO("Not connected"); + return BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED; + } + + if (client_s->services_discovered) { + BT_INFO("Already discovered"); + return BT_ERROR_ALREADY_DONE; + } + + BT_INFO("Update services for remote GATT server [%s]", + client_s->remote_address); + _bt_convert_address_to_hex(&addr_hex, client_s->remote_address); + + ret = bluetooth_gatt_client_get_primary_services(&addr_hex, &prim_svc); + ret = _bt_get_error_code(ret); + if (ret != BT_ERROR_NONE) { + BT_ERR("bluetooth_gatt_client_get_primary_services is failed"); + return ret; + } + + if (client_s->services) + g_slist_free_full(client_s->services, __bt_gatt_free_service); + client_s->services = NULL; + + if (prim_svc.count == 0) { + BT_INFO("There is no service"); + return BT_ERROR_NONE; + } + + BT_INFO("Services discovered"); + client_s->services_discovered = true; + for (i = 0; i < prim_svc.count; i++) { + BT_INFO("Service UUID[%d][%s] Instance ID[%d]", + i, prim_svc.uuids[i], prim_svc.inst_id[i]); + if (!_bt_gatt_client_add_service(client, prim_svc.uuids[i], prim_svc.inst_id[i])) { + BT_ERR("_bt_gatt_client_add_service is failed [%s]", + prim_svc.uuids[i]); + client_s->services_discovered = false; + } + } + return BT_ERROR_NONE; +} +#else int _bt_gatt_client_update_services(bt_gatt_client_h client) { bt_gatt_client_s *client_s = client; @@ -239,6 +418,7 @@ int _bt_gatt_client_update_services(bt_gatt_client_h client) return BT_ERROR_NONE; } +#endif int _bt_gatt_client_update_include_services(bt_gatt_h service) { @@ -296,6 +476,109 @@ next: return BT_ERROR_NONE; } +#ifdef TIZEN_GATT_CLIENT +int _bt_gatt_client_update_characteristics(bt_gatt_h service) +{ + bt_gatt_service_s *svc = service; + bt_gatt_client_s *client_s; + bt_gatt_handle_property_t svc_handle; + bt_gatt_handle_property_t char_handle; + GSList *chr_list = NULL; + int i; + + BT_INFO("+"); + if (svc == NULL) + return BT_ERROR_INVALID_PARAMETER; + + if (svc->charc_handles.count == 0) + return BT_ERROR_NONE; + + memset(&svc_handle, 0x00, sizeof(bt_gatt_handle_property_t)); + memset(&char_handle, 0x00, sizeof(bt_gatt_handle_property_t)); + + client_s = (bt_gatt_client_s*)svc->parent; + + __bt_string_to_uuid_hex(svc->uuid, svc_handle.uuid); + svc_handle.instance_id = svc->instance_id; + + BT_INFO("Total number of charcs [%d]", svc->charc_handles.count); + + for (i = 0; i < svc->charc_handles.count; i++) { + bt_gatt_characteristic_s *chr = NULL; + bt_gatt_char_property_t char_property; + int ret; + + memset(&char_property, 0x00, sizeof(char_property)); + + __bt_string_to_uuid_hex(svc->charc_handles.uuids[i], char_handle.uuid); + char_handle.instance_id = svc->charc_handles.inst_id[i]; + + BT_INFO("Retrieve Characteristics properties"); + ret = bluetooth_gatt_client_get_characteristics_property( + client_s->remote_address, + &svc_handle, + &char_handle, + &char_property); + ret = _bt_get_error_code(ret); + if (ret != BT_ERROR_NONE) { + BT_ERR("bluetooth_gatt_get_characteristics_property is failed"); + continue; + } + + BT_INFO("Characteristics properties are retreived, not create charc object"); + ret = bt_gatt_characteristic_create(char_property.uuid, 0, + char_property.permission, + (char *)char_property.val, + (int)char_property.val_len, (bt_gatt_h *)&chr); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_gatt_characteristic_create is failed"); + goto next; + } + + if (char_property.permission & BT_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE) { + chr->write_type = BT_GATT_WRITE_TYPE_WRITE_NO_RESPONSE; + BT_INFO("Characterics has Write No Response property"); + } + if (char_property.permission & BT_GATT_PROPERTY_WRITE) { + BT_INFO("Characterics has Write property"); + chr->write_type = BT_GATT_WRITE_TYPE_WRITE; + } + if (char_property.permission & BT_GATT_PROPERTY_READ) + BT_INFO("Characterics has Read property"); + + if (char_property.permission & BT_GATT_PROPERTY_BROADCAST) + BT_INFO("Characterics has Broadcast property"); + + if (char_property.permission & BT_GATT_PROPERTY_INDICATE) + BT_INFO("Characterics has Indicate property"); + + if (char_property.permission & BT_GATT_PROPERTY_NOTIFY) + BT_INFO("Characterics has Notify property"); + + /* Copy descriptor handles in just created charc object */ + memcpy(&chr->descriptor_handles, &char_property.char_desc_handle, + sizeof(bt_gatt_handle_info_t)); + chr->instance_id = char_handle.instance_id; + chr->parent = (void *)svc; + chr->role = BT_GATT_ROLE_CLIENT; + chr->properties = char_property.permission; + + chr_list = g_slist_append(chr_list, chr); +next: + bluetooth_gatt_free_char_property(&char_property); + } + + memset(&svc->charc_handles, 0x00, sizeof(bt_gatt_handle_info_t)); + g_slist_free_full(svc->characteristics, + __bt_gatt_client_handle_destroy); + + svc->characteristics = chr_list; + BT_INFO("Total number of characteristics whose properties are retrieved is [%d]", + g_slist_length(svc->characteristics)); + + return BT_ERROR_NONE; +} +#else int _bt_gatt_client_update_characteristics(bt_gatt_h service) { bt_gatt_service_s *svc = service; @@ -357,7 +640,96 @@ next: return BT_ERROR_NONE; } +#endif + + +#ifdef TIZEN_GATT_CLIENT +int _bt_gatt_client_update_descriptors(bt_gatt_h characteristic) +{ + bt_gatt_characteristic_s *chr = characteristic; + GSList *desc_list = NULL; + int i; + + bt_gatt_service_s *svc; + bt_gatt_client_s *client_s; + bt_gatt_handle_property_t svc_handle; + bt_gatt_handle_property_t char_handle; + bt_gatt_handle_property_t desc_handle; + + BT_INFO("+"); + if (chr == NULL) + return BT_ERROR_INVALID_PARAMETER; + if (chr->descriptor_handles.count == 0) + return BT_ERROR_NONE; + + svc = (bt_gatt_service_s*)chr->parent; + memset(&svc_handle, 0x00, sizeof(bt_gatt_handle_property_t)); + memset(&char_handle, 0x00, sizeof(bt_gatt_handle_property_t)); + memset(&desc_handle, 0x00, sizeof(bt_gatt_handle_property_t)); + + client_s = (bt_gatt_client_s*)svc->parent; + + __bt_string_to_uuid_hex(svc->uuid, svc_handle.uuid); + svc_handle.instance_id = svc->instance_id; + + __bt_string_to_uuid_hex(chr->uuid, char_handle.uuid); + char_handle.instance_id = chr->instance_id; + + for (i = 0; i < chr->descriptor_handles.count; i++) { + bt_gatt_descriptor_s *desc = NULL; + bt_gatt_char_descriptor_property_t desc_property; + int ret; + + memset(&desc_property, 0x00, sizeof(desc_property)); + + + __bt_string_to_uuid_hex(chr->descriptor_handles.uuids[i], desc_handle.uuid); + desc_handle.instance_id = chr->descriptor_handles.inst_id[i]; + + BT_INFO("Retreieve Desceriptor Properties from remote [%s]", + client_s->remote_address); + ret = bluetooth_gatt_client_get_char_descriptor_property( + client_s->remote_address, + &svc_handle, + &char_handle, + &desc_handle, + &desc_property); + ret = _bt_get_error_code(ret); + if (ret != BT_ERROR_NONE) { + BT_ERR("bluetooth_gatt_get_char_descriptor_property is failed"); + continue; + } + + BT_INFO("Retreieved Desceriptor Properties, now create Descriptor object"); + ret = bt_gatt_descriptor_create(desc_property.uuid, 0, + (char*)desc_property.val, + (int)desc_property.val_len, + (bt_gatt_h *)&desc); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_gatt_descriptor_create is failed"); + goto next; + } + + + desc->instance_id = desc_handle.instance_id; + desc->parent = (void *)characteristic; + desc->role = BT_GATT_ROLE_CLIENT; + desc_list = g_slist_append(desc_list, desc); +next: + bluetooth_gatt_free_desc_property(&desc_property); + } + + + memset(&chr->descriptor_handles, 0x00, sizeof(bt_gatt_handle_info_t)); + g_slist_free_full(chr->descriptors, + __bt_gatt_client_handle_destroy); + + chr->descriptors = desc_list; + + return BT_ERROR_NONE; +} +#else int _bt_gatt_client_update_descriptors(bt_gatt_h characteristic) { bt_gatt_characteristic_s *chr = characteristic; @@ -412,7 +784,47 @@ next: return BT_ERROR_NONE; } +#endif + +#ifdef TIZEN_GATT_CLIENT +/* LCOV_EXCL_STOP */ +int bt_gatt_connect(const char *address, bool auto_connect) +{ + int ret; + bluetooth_device_address_t bd_addr = { {0,} }; + + bt_gatt_client_s *client_s; + + BT_INFO("Address [%s] Auto Connect [%d]", + address, auto_connect); + BT_CHECK_GATT_CLIENT_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(address); + _bt_convert_address_to_hex(&bd_addr, address); + + /* Find any client attached with remote address or not */ + client_s = _bt_gatt_get_client(address); + if (client_s) { + BT_INFO("GATT client instance is already present for the rmeote addr [%s] client_id[%d]", + address, client_s->client_id); + ret = _bt_get_error_code(bluetooth_connect_le(&bd_addr, + auto_connect, client_s->client_id)); + } else { + BT_INFO("GATT client instance is NOT present for the remote addr [%s]", + address); + + ret = _bt_get_error_code(bluetooth_connect_le(&bd_addr, + auto_connect, 0/* Default Client ID */)); + + } + + if (ret != BT_ERROR_NONE) + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + + return ret; +} +#else /* LCOV_EXCL_STOP */ int bt_gatt_connect(const char *address, bool auto_connect) { @@ -425,25 +837,43 @@ int bt_gatt_connect(const char *address, bool auto_connect) _bt_convert_address_to_hex(&bd_addr, address); ret = _bt_get_error_code(bluetooth_connect_le(&bd_addr, - auto_connect ? TRUE : FALSE)); + auto_connect ? TRUE : FALSE)); if (ret != BT_ERROR_NONE) BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); return ret; } +#endif int bt_gatt_disconnect(const char *address) { int ret; bluetooth_device_address_t bd_addr = { {0,} }; +#ifdef TIZEN_GATT_CLIENT + bt_gatt_client_s *client_s; +#endif BT_CHECK_GATT_CLIENT_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(address); _bt_convert_address_to_hex(&bd_addr, address); +#ifdef TIZEN_GATT_CLIENT + /* Find any client attached with remote address or not */ + client_s = _bt_gatt_get_client(address); + if (client_s) { + BT_INFO("GATT client instance is already present for the remote addr [%s] client interface [%d]", + address, client_s->client_id); + ret = _bt_get_error_code(bluetooth_disconnect_le(&bd_addr, client_s->client_id)); + } else { + BT_INFO("GATT client instance is NOT present for the remote addr [%s]", + address); + ret = _bt_get_error_code(bluetooth_disconnect_le(&bd_addr, 0 /* Default CLient ID */)); + } +#else ret = _bt_get_error_code(bluetooth_disconnect_le(&bd_addr)); +#endif if (ret != BT_ERROR_NONE) BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); @@ -474,6 +904,10 @@ static void __bt_gatt_free_descriptor(bt_gatt_h gatt_handle) { bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)gatt_handle; + /* Remove descriptor from List of GATT handles */ + if (gatt_handle_list) + gatt_handle_list = g_slist_remove(gatt_handle_list, gatt_handle); + g_free(desc->path); g_free(desc->uuid); g_free(desc->value); @@ -487,21 +921,63 @@ static void __bt_gatt_free_descriptor(bt_gatt_h gatt_handle) static void __bt_gatt_free_characteristic(bt_gatt_h gatt_handle) { int ret; +#ifdef TIZEN_GATT_CLIENT + bt_gatt_handle_property_t svc_handle; + bt_gatt_handle_property_t chr_handle; + bt_gatt_service_s *service_s; + bt_gatt_client_s *client_s; +#endif + bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s*)gatt_handle; - if (chr->role == BT_GATT_ROLE_CLIENT && chr->value_changed_cb && - chr->properties & - (BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_INDICATE)) { - BT_DBG("Unwatch characteristic"); - ret = _bt_get_error_code(bluetooth_gatt_unwatch_characteristics( - chr->path)); - if (ret != BT_ERROR_NONE) + BT_INFO("+"); + + /* Remove characteristic from List of GATT handles */ + if (gatt_handle_list) + gatt_handle_list = g_slist_remove(gatt_handle_list, gatt_handle); + +#ifdef TIZEN_GATT_CLIENT + service_s = (bt_gatt_service_s*)chr->parent; + if (!service_s) { + BT_ERR("service_s is null"); + goto fail; + } + client_s = (bt_gatt_client_s*)service_s->parent; + if (!client_s) { + BT_ERR("client_s is null"); + goto fail; + } + /* Create Service and Charc handles */ + __bt_string_to_uuid_hex(service_s->uuid, svc_handle.uuid); + svc_handle.instance_id = service_s->instance_id; + + BT_INFO("Service UUID [%s]", service_s->uuid); + BT_INFO("Charc Instance ID [%d]", service_s->instance_id); + + BT_INFO("Charc UUID [%s]", chr->uuid); + BT_INFO("Charc Instance ID [%d]", chr->instance_id); + + BT_INFO("Client ID [%d]", client_s->client_id); + + __bt_string_to_uuid_hex(chr->uuid, chr_handle.uuid); + chr_handle.instance_id = chr->instance_id; +#endif + if (chr->role == BT_GATT_ROLE_CLIENT && chr->value_changed_cb && + chr->properties & + (BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_INDICATE)) { + BT_DBG("Unwatch characteristic"); + ret = _bt_get_error_code(bluetooth_gatt_unwatch_characteristics( + chr->path)); + if (ret != BT_ERROR_NONE) BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); } +fail: g_slist_free_full(chr->descriptors, __bt_gatt_free_descriptor); +#ifndef TIZEN_GATT_CLIENT g_strfreev(chr->desc_handles); +#endif g_free(chr->path); g_free(chr->uuid); @@ -521,6 +997,10 @@ static void __bt_gatt_free_service(bt_gatt_h gatt_handle) g_slist_free_full(svc->included_services, __bt_gatt_free_service); g_slist_free_full(svc->characteristics, __bt_gatt_free_characteristic); + /* Remove service from List of GATT handles */ + if (gatt_handle_list) + gatt_handle_list = g_slist_remove(gatt_handle_list, gatt_handle); + if (svc->role == BT_GATT_ROLE_SERVER) { #ifdef TIZEN_FEATURE_GATT_RELAY if (is_gatt_server_initialized) { @@ -723,7 +1203,6 @@ int bt_gatt_destroy(bt_gatt_h gatt_handle) return BT_ERROR_NONE; } -/* LCOV_EXCL_START */ static int __get_write_prop(bt_gatt_write_type_e type, bt_gatt_property_e *prop) { if (!prop) @@ -758,6 +1237,9 @@ int bt_gatt_service_destroy(bt_gatt_h gatt_handle) BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(gatt_handle); + BT_INFO("Destroy GATT Service"); + + BT_VALIDATE_GATT_HANDLE(gatt_handle); if (handle->type == BT_GATT_TYPE_SERVICE) __bt_gatt_destroy_service(gatt_handle); @@ -820,6 +1302,8 @@ int bt_gatt_get_value(bt_gatt_h gatt_handle, char **value, int *value_length) BT_CHECK_INPUT_PARAMETER(value); /* LCOV_EXCL_START */ BT_CHECK_INPUT_PARAMETER(value_length); + BT_VALIDATE_GATT_HANDLE(gatt_handle); + if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) { *value_length = chr->value_length; if (chr->value_length > 0) @@ -962,16 +1446,21 @@ int bt_gatt_set_value(bt_gatt_h gatt_handle, const char *value, bluetooth_gatt_server_update_value_t param; #endif + BT_INFO("+"); BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(gatt_handle); BT_CHECK_INPUT_PARAMETER(value); /* LCOV_EXCL_START */ + BT_VALIDATE_GATT_HANDLE(gatt_handle); + if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) { + BT_INFO("Request is for Char write value"); val = &chr->value; val_len = &chr->value_length; } else if (handle->type == BT_GATT_TYPE_DESCRIPTOR) { + BT_INFO("Request is for Descriptor write value"); val = &desc->value; val_len = &desc->value_length; } else { @@ -1015,6 +1504,7 @@ int bt_gatt_set_value(bt_gatt_h gatt_handle, const char *value, *val = g_memdup(value, value_length); *val_len = value_length; + BT_INFO("Value is set"); return BT_ERROR_NONE; /* LCOV_EXCL_STOP */ } @@ -1064,16 +1554,22 @@ int bt_gatt_set_int_value(bt_gatt_h gatt_handle, bt_data_type_int_e type, *val_len = fmt_size; } else if (*val_len == offset) { /* Added */ tmp = g_malloc0(*val_len + fmt_size); - if (tmp == NULL) + /* Fix : NULL_RETURNS */ + if (!tmp) { + g_free(*val); return BT_ERROR_OUT_OF_MEMORY; + } memcpy(tmp, *val, *val_len); g_free(*val); *val = tmp; *val_len += fmt_size; } else if (*val_len < offset + fmt_size) {/* Overlapped */ tmp = g_malloc0(offset + fmt_size); - if (tmp == NULL) + /* Fix : NULL_RETURNS */ + if (!tmp) { + g_free(*val); return BT_ERROR_OUT_OF_MEMORY; + } memcpy(tmp, *val, *val_len); g_free(*val); *val = tmp; @@ -1187,15 +1683,28 @@ int bt_gatt_set_float_value(bt_gatt_h gatt_handle, bt_data_type_float_e type, if (*val == NULL) { *val = g_malloc0(fmt_size); + /* Fix : NULL_RETURNS */ + if (*val == NULL) + return BT_ERROR_OUT_OF_MEMORY; *val_len = fmt_size; } else if (*val_len == offset) {/* Added */ tmp = g_malloc0(*val_len + fmt_size); + /* Fix : NULL_RETURNS */ + if (tmp == NULL) { + g_free(*val); + return BT_ERROR_OUT_OF_MEMORY; + } memcpy(tmp, *val, *val_len); g_free(*val); *val = tmp; *val_len += fmt_size; } else if (*val_len < offset + fmt_size) {/* Overlapped */ tmp = g_malloc0(offset + fmt_size); + /* Fix : NULL_RETURNS */ + if (tmp == NULL) { + g_free(*val); + return BT_ERROR_OUT_OF_MEMORY; + } memcpy(tmp, *val, *val_len); g_free(*val); *val = tmp; @@ -1258,6 +1767,8 @@ int bt_gatt_characteristic_get_permissions(bt_gatt_h gatt_handle, int *permissio BT_CHECK_INPUT_PARAMETER(gatt_handle); BT_CHECK_INPUT_PARAMETER(permissions); + BT_VALIDATE_GATT_HANDLE(gatt_handle); + if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) *permissions = chr->permissions; else { @@ -1279,6 +1790,8 @@ int bt_gatt_descriptor_get_permissions(bt_gatt_h gatt_handle, int *permissions) BT_CHECK_INPUT_PARAMETER(gatt_handle); BT_CHECK_INPUT_PARAMETER(permissions); + BT_VALIDATE_GATT_HANDLE(gatt_handle); + if (handle->type == BT_GATT_TYPE_DESCRIPTOR) *permissions = desc->permissions; else { @@ -1300,6 +1813,8 @@ int bt_gatt_set_permissions(bt_gatt_h gatt_handle, int permissions) BT_CHECK_INPUT_PARAMETER(gatt_handle); + BT_VALIDATE_GATT_HANDLE(gatt_handle); + if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) chr->permissions = permissions; else if (handle->type == BT_GATT_TYPE_DESCRIPTOR) @@ -1400,6 +1915,9 @@ int bt_gatt_service_create(const char *uuid, bt_gatt_service_type_e type, #endif *service = (bt_gatt_h)svc; + /* Add service to list of GATT handles */ + gatt_handle_list = g_slist_append(gatt_handle_list, (gpointer)svc); + return BT_ERROR_NONE; } @@ -1414,6 +1932,10 @@ int bt_gatt_service_add_characteristic(bt_gatt_h service, BT_CHECK_INPUT_PARAMETER(service); BT_CHECK_INPUT_PARAMETER(characteristic); + + BT_VALIDATE_GATT_HANDLE(service); + BT_VALIDATE_GATT_HANDLE(characteristic); + if (chr->parent) { BT_ERR("This characteristic is already added."); return BT_ERROR_INVALID_PARAMETER; @@ -1421,12 +1943,6 @@ int bt_gatt_service_add_characteristic(bt_gatt_h service, svc->characteristics = g_slist_append(svc->characteristics, chr); chr->parent = (void *)service; -#ifdef TIZEN_FEATURE_GATT_RELAY - if (svc) { - BT_INFO("Current handle count of service [%d]", svc->numhandles); - svc->numhandles += 2; - } -#endif return BT_ERROR_NONE; } @@ -1441,6 +1957,10 @@ int bt_gatt_service_add_included_service(bt_gatt_h service, BT_CHECK_INPUT_PARAMETER(service); BT_CHECK_INPUT_PARAMETER(included_service); + + BT_VALIDATE_GATT_HANDLE(service); + BT_VALIDATE_GATT_HANDLE(included_service); + if (included_svc->parent) { BT_ERR("This service is already added."); return BT_ERROR_INVALID_PARAMETER; @@ -1523,7 +2043,13 @@ int bt_gatt_service_get_characteristic(bt_gatt_h service, const char *uuid, BT_CHECK_INPUT_PARAMETER(uuid); /* LCOV_EXCL_START */ BT_CHECK_INPUT_PARAMETER(characteristic); + BT_INFO("Get Characteristic rom service, charc uuid [%s], total charcs of this service [%d]", + uuid, svc->charc_handles.count); +#ifdef TIZEN_GATT_CLIENT + if (svc->charc_handles.count > 0) { +#else if (svc->char_handles) { +#endif ret = _bt_gatt_client_update_characteristics(svc); if (ret != BT_ERROR_NONE) { BT_ERR("_bt_gatt_client_update_characteristics failed"); @@ -1557,7 +2083,12 @@ int bt_gatt_service_foreach_characteristics(bt_gatt_h service, BT_CHECK_INPUT_PARAMETER(service); BT_CHECK_INPUT_PARAMETER(callback); /* LCOV_EXCL_START */ +#ifdef TIZEN_GATT_CLIENT + BT_INFO("Total num of characteristics [%d]", svc->charc_handles.count); + if (svc->charc_handles.count > 0) { +#else if (svc->char_handles) { +#endif int ret; ret = _bt_gatt_client_update_characteristics(svc); @@ -1568,6 +2099,7 @@ int bt_gatt_service_foreach_characteristics(bt_gatt_h service, } total = g_slist_length(svc->characteristics); + BT_INFO("Total charcs [%d]", total); for (l = svc->characteristics; l; l = g_slist_next(l)) { chr = l->data; @@ -1647,6 +2179,7 @@ int bt_gatt_service_foreach_included_services(bt_gatt_h service, return BT_ERROR_NONE; } + /* LCOV_EXCL_START */ int bt_gatt_characteristic_create(const char *uuid, int permissions, int properties, const char *value, @@ -1670,6 +2203,9 @@ int bt_gatt_characteristic_create(const char *uuid, int permissions, chr->type = BT_GATT_TYPE_CHARACTERISTIC; chr->role = BT_GATT_ROLE_SERVER; + BT_INFO("Characteristic UUID : [%s] len [%d] permissions [%d] properties [%d]", + uuid, strlen(uuid), permissions, properties); + #ifdef TIZEN_FEATURE_GATT_RELAY chr->uuid = _bt_convert_uuid_to_uuid128(uuid); #else @@ -1678,6 +2214,7 @@ int bt_gatt_characteristic_create(const char *uuid, int permissions, else chr->uuid = g_strdup(uuid); #endif + if (chr->uuid == NULL) { ret = BT_ERROR_OUT_OF_MEMORY; goto fail; @@ -1696,6 +2233,9 @@ int bt_gatt_characteristic_create(const char *uuid, int permissions, *characteristic = (bt_gatt_h)chr; + /* Add charactristic to list of GATT handles */ + gatt_handle_list = g_slist_append(gatt_handle_list, (gpointer)chr); + return BT_ERROR_NONE; fail: @@ -1718,8 +2258,11 @@ int bt_gatt_characteristic_add_descriptor(bt_gatt_h characteristic, BT_CHECK_INPUT_PARAMETER(characteristic); BT_CHECK_INPUT_PARAMETER(descriptor); + BT_VALIDATE_GATT_HANDLE(characteristic); + BT_VALIDATE_GATT_HANDLE(descriptor); + if (chr->type != BT_GATT_TYPE_CHARACTERISTIC || - desc->type != BT_GATT_TYPE_DESCRIPTOR) { + desc->type != BT_GATT_TYPE_DESCRIPTOR) { BT_ERR("Wrong type. chr : %d, desc : %d", chr->type, desc->type); return BT_ERROR_INVALID_PARAMETER; } @@ -1731,18 +2274,10 @@ int bt_gatt_characteristic_add_descriptor(bt_gatt_h characteristic, chr->descriptors = g_slist_append(chr->descriptors, desc); desc->parent = (void *)characteristic; -#ifdef TIZEN_FEATURE_GATT_RELAY -{ - bt_gatt_service_s *svc = (bt_gatt_service_s *)chr->parent; - if (svc) { - BT_INFO("Current handle count of service [%d]", svc->numhandles); - svc->numhandles += 1; /* Initalize numhandles to 1 */ - } -} -#endif return BT_ERROR_NONE; } + /* LCOV_EXCL_STOP */ int bt_gatt_characteristic_get_service(bt_gatt_h characteristic, bt_gatt_h *service) { @@ -1868,8 +2403,11 @@ int bt_gatt_characteristic_get_descriptor(bt_gatt_h characteristic, BT_ERR("Wrong type of GATT handle : %d", chr->type); return BT_ERROR_INVALID_PARAMETER; } - +#ifdef TIZEN_GATT_CLIENT + if (chr->descriptor_handles.count > 0) { +#else if (chr->desc_handles) { +#endif ret = _bt_gatt_client_update_descriptors(chr); if (ret != BT_ERROR_NONE) { BT_ERR("_bt_gatt_client_update_descriptors is failed"); @@ -1895,6 +2433,7 @@ int bt_gatt_characteristic_foreach_descriptors(bt_gatt_h characteristic, int total; int i; + BT_INFO("+"); BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); @@ -1906,7 +2445,12 @@ int bt_gatt_characteristic_foreach_descriptors(bt_gatt_h characteristic, return BT_ERROR_INVALID_PARAMETER; } +#ifdef TIZEN_GATT_CLIENT + BT_INFO("Total Descriptors for the current characteristic [%d]", chr->descriptor_handles.count); + if (chr->descriptor_handles.count > 0) { +#else if (chr->desc_handles) { +#endif int ret; ret = _bt_gatt_client_update_descriptors(chr); @@ -1917,6 +2461,7 @@ int bt_gatt_characteristic_foreach_descriptors(bt_gatt_h characteristic, } total = g_slist_length(chr->descriptors); + BT_INFO("Total number of descriptors found [%d]", total); i = 1; for (l = chr->descriptors; l; l = g_slist_next(l)) { @@ -1926,6 +2471,7 @@ int bt_gatt_characteristic_foreach_descriptors(bt_gatt_h characteristic, return BT_ERROR_NONE; } + /* LCOV_EXCL_START */ int bt_gatt_descriptor_create(const char *uuid, int permissions, const char *value, int value_length, @@ -1948,6 +2494,7 @@ int bt_gatt_descriptor_create(const char *uuid, int permissions, desc->type = BT_GATT_TYPE_DESCRIPTOR; desc->role = BT_GATT_ROLE_SERVER; + BT_INFO("Descriptor UUID : [%s] len [%d] permissions [%d]", uuid, strlen(uuid), permissions); #ifdef TIZEN_FEATURE_GATT_RELAY desc->uuid = _bt_convert_uuid_to_uuid128(uuid); #else @@ -1956,6 +2503,7 @@ int bt_gatt_descriptor_create(const char *uuid, int permissions, else desc->uuid = g_strdup(uuid); #endif + if (desc->uuid == NULL) { ret = BT_ERROR_OUT_OF_MEMORY; goto fail; @@ -1973,6 +2521,9 @@ int bt_gatt_descriptor_create(const char *uuid, int permissions, *descriptor = (bt_gatt_h)desc; + /* Add charactristic to list of GATT handles */ + gatt_handle_list = g_slist_append(gatt_handle_list, (gpointer)desc); + return ret; fail: @@ -1982,6 +2533,7 @@ fail: return ret; } + /* LCOV_EXCL_STOP */ int bt_gatt_descriptor_get_characteristic(bt_gatt_h descriptor, bt_gatt_h *characteristic) @@ -2006,6 +2558,9 @@ int bt_gatt_server_initialize(void) int ret = BT_ERROR_NONE; + BT_INFO("gatt_server_initialized [%d] gatt_server_started[%d] instance_id [%d]", + is_gatt_server_initialized, is_gatt_server_started, instance_id); + if (is_gatt_server_started) { BT_ERR("Already Server started"); return BT_ERROR_OPERATION_FAILED; @@ -2028,7 +2583,7 @@ int bt_gatt_server_initialize(void) return BT_ERROR_NONE; } - BT_DBG("Gatt-service already initialized"); + BT_INFO("Gatt-service already initialized"); return ret; } @@ -2040,6 +2595,9 @@ int bt_gatt_server_deinitialize(void) int ret = BT_ERROR_NONE; + BT_INFO("gatt_server_initialized [%d] gatt_server_started[%d] instance_id [%d]", + is_gatt_server_initialized, is_gatt_server_started, instance_id); + if (is_gatt_server_initialized) { GSList *l; for (l = gatt_server_list; l; l = g_slist_next(l)) { @@ -2050,7 +2608,7 @@ int bt_gatt_server_deinitialize(void) gatt_server_list = NULL; #ifdef TIZEN_FEATURE_GATT_RELAY - ret = _bt_get_error_code(bluetooth_gatt_deinit()); + ret = _bt_get_error_code(bluetooth_gatt_server_deinit()); if (ret != BT_ERROR_NONE) { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); @@ -2073,10 +2631,12 @@ int bt_gatt_server_deinitialize(void) is_gatt_server_initialized = false; is_gatt_server_started = false; instance_id = -1; + + BT_INFO("gatt server deinitialised completed"); return BT_ERROR_NONE; } - BT_DBG("Gatt-service is not initialized"); + BT_INFO("Gatt-service is not initialized"); return ret; } @@ -2100,8 +2660,12 @@ int bt_gatt_server_create(bt_gatt_server_h *server) *server = (bt_gatt_server_h)serv; + BT_INFO("Creating a GATT Server"); gatt_server_list = g_slist_append(gatt_server_list, serv); + /* Add server to list of GATT handles */ + gatt_handle_list = g_slist_append(gatt_handle_list, (gpointer)serv); + return BT_ERROR_NONE; } @@ -2112,6 +2676,12 @@ int bt_gatt_server_destroy(bt_gatt_server_h server) BT_CHECK_GATT_SERVER_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(server); + BT_VALIDATE_GATT_HANDLE(server); + BT_INFO("Destroy GATT Server"); + + /* Remove Server from list of GATT handles */ + if (gatt_handle_list) + gatt_handle_list = g_slist_remove(gatt_handle_list, serv); g_slist_free_full(serv->services, __bt_gatt_free_service); gatt_server_list = g_slist_remove(gatt_server_list, serv); @@ -2134,6 +2704,8 @@ int bt_gatt_server_set_read_value_requested_cb(bt_gatt_h gatt_handle, BT_CHECK_INPUT_PARAMETER(gatt_handle); BT_CHECK_INPUT_PARAMETER(callback); + BT_VALIDATE_GATT_HANDLE(gatt_handle); + if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) { chr->read_requested_cb = callback; chr->read_requested_user_data = user_data; @@ -2162,6 +2734,8 @@ int bt_gatt_server_set_characteristic_notification_state_change_cb(bt_gatt_h gat BT_CHECK_INPUT_PARAMETER(gatt_handle); BT_CHECK_INPUT_PARAMETER(callback); + BT_VALIDATE_GATT_HANDLE(gatt_handle); + chr->notification_changed_cb = callback; chr->notification_changed_user_data = user_data; @@ -2169,6 +2743,36 @@ int bt_gatt_server_set_characteristic_notification_state_change_cb(bt_gatt_h gat } #ifdef TIZEN_FEATURE_GATT_RELAY +static int __gatt_service_add_num_handle(bt_gatt_service_s *service) +{ + int handles_count = 0; + GSList *char_l = NULL; + + BT_CHECK_INPUT_PARAMETER(service); + + BT_INFO("total service handles [%d]", service->numhandles); + + for (char_l = service->characteristics; char_l; char_l = g_slist_next(char_l)) { + bt_gatt_characteristic_s *chr = char_l->data; + int desc_numhandles = 0; + + if (chr) { + handles_count += 2; + + /*descriptor of each characteristic*/ + if (chr->descriptors) { + desc_numhandles = g_slist_length(chr->descriptors); + handles_count += desc_numhandles; + } + } + } + + service->numhandles += handles_count; + BT_INFO("total service handles [%d]", service->numhandles); + + return BT_ERROR_NONE; +} + int bt_gatt_server_register_service(bt_gatt_server_h server, bt_gatt_h service) { int ret = BT_ERROR_NONE; @@ -2182,6 +2786,7 @@ int bt_gatt_server_register_service(bt_gatt_server_h server, bt_gatt_h service) BT_CHECK_GATT_SERVER_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(server); BT_CHECK_INPUT_PARAMETER(service); + BT_VALIDATE_GATT_HANDLE(server); if (g_slist_find(serv->services, svc)) { BT_ERR("Already added service."); @@ -2193,6 +2798,7 @@ int bt_gatt_server_register_service(bt_gatt_server_h server, bt_gatt_h service) return BT_ERROR_OPERATION_FAILED; } + __gatt_service_add_num_handle(svc); BT_INFO("Service number of total handles [%d]", svc->numhandles); ret = _bt_get_error_code(bluetooth_gatt_server_add_service(svc->uuid, svc->type, @@ -2357,6 +2963,8 @@ int bt_gatt_server_unregister_service(bt_gatt_server_h server, bt_gatt_server_s *serv = (bt_gatt_server_s *)server; bt_gatt_service_s *svc = (bt_gatt_service_s *)service; + BT_INFO("Unregister GATT Service"); + BT_CHECK_GATT_SERVER_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_GATT_SERVER_INIT_STATUS(); @@ -2378,6 +2986,7 @@ int bt_gatt_server_unregister_all_services(bt_gatt_server_h server) int ret = BT_ERROR_NONE; bt_gatt_server_s *serv = (bt_gatt_server_s*)server; + BT_INFO("Unregister All GATT Services"); BT_CHECK_GATT_SERVER_SUPPORT(); BT_CHECK_INIT_STATUS(); @@ -2508,6 +3117,8 @@ int bt_gatt_server_notify_characteristic_changed_value(bt_gatt_h characteristic, BT_CHECK_INPUT_PARAMETER(characteristic); BT_CHECK_INPUT_PARAMETER(callback); + BT_VALIDATE_GATT_HANDLE(characteristic); + _bt_convert_address_to_hex(&addr_hex, device_address); #ifdef TIZEN_FEATURE_GATT_RELAY @@ -2615,6 +3226,8 @@ int bt_gatt_server_set_write_value_requested_cb(bt_gatt_h gatt_handle, BT_CHECK_INPUT_PARAMETER(gatt_handle); BT_CHECK_INPUT_PARAMETER(callback); + BT_VALIDATE_GATT_HANDLE(gatt_handle); + if (handle->type == BT_GATT_TYPE_CHARACTERISTIC) { chr->write_value_requested_cb = callback; chr->write_value_requested_user_data = user_data; @@ -2679,6 +3292,85 @@ int bt_gatt_server_foreach_services(bt_gatt_server_h server, return BT_ERROR_NONE; } + +#ifdef TIZEN_GATT_CLIENT +int bt_gatt_client_create(const char *remote_address, bt_gatt_client_h *client) +{ + int ret = BT_ERROR_NONE; + bt_gatt_client_s *client_s; + bool connected = false; + GSList *l; + bluetooth_device_address_t bd_addr = { {0,} }; + + BT_CHECK_GATT_CLIENT_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(remote_address); /* LCOV_EXCL_START */ + + BT_INFO("Create GATT client: address[%s] Total gatt client instance list [%d]", + remote_address, g_slist_length(gatt_client_list)); + + for (l = gatt_client_list; l; l = g_slist_next(l)) { + bt_gatt_client_s *c = (bt_gatt_client_s *)l->data; + BT_INFO("Already present GATT client instance addr [%s]", c->remote_address); + + if ((c == NULL) || (c->remote_address == NULL)) { + BT_ERR("bt_gatt_client_create Error Parameter are NULL..\n"); + continue; + } else if (!g_ascii_strcasecmp(c->remote_address, remote_address)) { + BT_ERR("Gatt client for %s is already created", + remote_address); + return BT_ERROR_ALREADY_DONE; + } + } + + client_s = g_malloc0(sizeof(*client_s)); + if (client_s == NULL) { + ret = BT_ERROR_OUT_OF_MEMORY; + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + return ret; + } + + client_s->remote_address = g_strdup(remote_address); + if (client_s->remote_address == NULL) { + free(client_s); + ret = BT_ERROR_OUT_OF_MEMORY; + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + return ret; + } + + /* Attempt to Register GATT Client instance */ + _bt_convert_address_to_hex(&bd_addr, client_s->remote_address); + + ret = bluetooth_gatt_client_init(&client_s->client_id, &bd_addr, + _bt_gatt_client_event_proxy); + + if (BLUETOOTH_ERROR_NONE != ret) { + free(client_s->remote_address); + free(client_s); + return ret; + } + if (bt_device_is_profile_connected(remote_address, BT_PROFILE_GATT, + &connected) != BT_ERROR_NONE) + BT_ERR("bt_device_is_profile_connected is failed"); + else + client_s->connected = connected; + + ret = _bt_gatt_client_update_services(client_s); + if (ret != BT_ERROR_NONE) { + BT_INFO("_bt_gatt_client_update_services returns 0x%X. " + "It could be updated when service is available.", ret); + ret = BT_ERROR_NONE; + } + + BT_INFO("GATT Client Handle is created instance ID [%d]", + client_s->client_id); + + *client = (bt_gatt_client_h)client_s; + gatt_client_list = g_slist_append(gatt_client_list, client_s); + + return ret; /* LCOV_EXCL_STOP */ +} +#else /* LCOV_EXCL_STOP */ int bt_gatt_client_create(const char *remote_address, bt_gatt_client_h *client) { @@ -2739,6 +3431,7 @@ int bt_gatt_client_create(const char *remote_address, bt_gatt_client_h *client) return ret; /* LCOV_EXCL_STOP */ } +#endif int bt_gatt_client_destroy(bt_gatt_client_h client) { @@ -2747,17 +3440,28 @@ int bt_gatt_client_destroy(bt_gatt_client_h client) BT_CHECK_GATT_CLIENT_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(client); /* LCOV_EXCL_START */ + BT_INFO("Destroy GATT client: Client interface ID [%d] REmote address [%s]", + client_s->client_id, client_s->remote_address); if (client_s->service_changed_cb) { bluetooth_device_address_t bd_addr = { {0,} }; _bt_convert_address_to_hex(&bd_addr, client_s->remote_address); +#ifdef TIZEN_GATT_CLIENT + bluetooth_gatt_client_set_service_change_watcher(&bd_addr, FALSE); +#else bluetooth_gatt_set_service_change_watcher(&bd_addr, FALSE); +#endif } - g_free(client_s->remote_address); g_slist_free_full(client_s->services, __bt_gatt_free_service); gatt_client_list = g_slist_remove(gatt_client_list, client_s); + +#ifdef TIZEN_GATT_CLIENT + /* Unregister GATT Client instance: Unregister should never fail */ + bluetooth_gatt_client_deinit(client_s->client_id); + g_free(client_s->remote_address); +#endif g_free(client_s); return BT_ERROR_NONE; /* LCOV_EXCL_STOP */ @@ -2778,6 +3482,20 @@ int bt_gatt_client_get_remote_address(bt_gatt_client_h client, return BT_ERROR_NONE; } +static bool __bt_gatt_client_is_in_progress(void) +{ + if (_bt_check_cb(BT_EVENT_GATT_CLIENT_WRITE_CHARACTERISTIC) || + _bt_check_cb(BT_EVENT_GATT_CLIENT_WRITE_DESCRIPTOR) || + _bt_check_cb(BT_EVENT_GATT_CLIENT_READ_CHARACTERISTIC) || + _bt_check_cb(BT_EVENT_GATT_CLIENT_READ_DESCRIPTOR)) { + BT_ERR("Operation is in progress"); + return true; + } + + return false; /* LCOV_EXCL_STOP */ +} + + void _handle_gatt_client_read_completed_event(int result, bt_gatt_resp_data_t *resp) { bt_gatt_common_s *handle; @@ -2883,17 +3601,31 @@ void _handle_gatt_client_write_completed_event(int result, bt_gatt_resp_data_t * return; /* LCOV_EXCL_STOP */ } +#ifdef TIZEN_GATT_CLIENT int bt_gatt_client_read_value(bt_gatt_h gatt_handle, bt_gatt_client_request_completed_cb callback, void *user_data) { int ret = BT_ERROR_NONE; bt_gatt_common_s *c = (bt_gatt_common_s *)gatt_handle; + BT_INFO("+"); + bt_gatt_handle_property_t svc_handle; + bt_gatt_handle_property_t chr_handle; + bt_gatt_handle_property_t desc_handle; + bt_gatt_service_s *service_s; + bt_gatt_characteristic_s *charc_s; + bt_gatt_client_s *client_s; + BT_CHECK_GATT_CLIENT_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(gatt_handle); BT_CHECK_INPUT_PARAMETER(callback); /* LCOV_EXCL_START */ + if (__bt_gatt_client_is_in_progress()) { + BT_ERR("Operation is in progress"); + return BT_ERROR_NOW_IN_PROGRESS; + } + if (c->type == BT_GATT_TYPE_CHARACTERISTIC) { bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)gatt_handle; @@ -2902,9 +3634,28 @@ int bt_gatt_client_read_value(bt_gatt_h gatt_handle, return BT_ERROR_NOW_IN_PROGRESS; } + service_s = (bt_gatt_service_s*)chr->parent; + client_s = (bt_gatt_client_s*)service_s->parent; + BT_INFO("Read Characteristic from remote address [%s] service UUID [%s] char UUID [%s]", + client_s->remote_address, + service_s->uuid, + chr->uuid); + + /* Create Service and Charc handles */ + __bt_string_to_uuid_hex(service_s->uuid, svc_handle.uuid); + svc_handle.instance_id = service_s->instance_id; + + __bt_string_to_uuid_hex(chr->uuid, chr_handle.uuid); + chr_handle.instance_id = chr->instance_id; + ret = _bt_get_error_code( - bluetooth_gatt_read_characteristic_value(chr->path, gatt_handle)); + bluetooth_gatt_client_read_characteristic_value( + client_s->remote_address, + &svc_handle, + &chr_handle)); + if (ret == BT_ERROR_NONE) { + BT_INFO("Characteristic read scheduled successfully, set callback"); chr->read_cb = callback; chr->read_user_data = user_data; } else { @@ -2918,9 +3669,34 @@ int bt_gatt_client_read_value(bt_gatt_h gatt_handle, return BT_ERROR_NOW_IN_PROGRESS; } + charc_s = (bt_gatt_characteristic_s*)desc->parent; + service_s = (bt_gatt_service_s*)charc_s->parent; + client_s = (bt_gatt_client_s*)service_s->parent; + + BT_INFO("Read Descriptor from remote address [%s] service UUID [%s] char UUID [%s] desc UUID [%s]", + client_s->remote_address, + service_s->uuid, + charc_s->uuid, + desc->uuid); + /* Create Service and Charc & desc handles */ + __bt_string_to_uuid_hex(service_s->uuid, svc_handle.uuid); + svc_handle.instance_id = service_s->instance_id; + + __bt_string_to_uuid_hex(charc_s->uuid, chr_handle.uuid); + chr_handle.instance_id = charc_s->instance_id; + + __bt_string_to_uuid_hex(desc->uuid, desc_handle.uuid); + desc_handle.instance_id = desc->instance_id; + ret = _bt_get_error_code( - bluetooth_gatt_read_descriptor_value(desc->path, gatt_handle)); + bluetooth_gatt_client_read_descriptor_value( + client_s->remote_address, + &svc_handle, + &chr_handle, + &desc_handle)); + if (ret == BT_ERROR_NONE) { + BT_INFO("Descriptor read scheduled successfully, set callback"); desc->read_cb = callback; desc->read_user_data = user_data; } else { @@ -2931,85 +3707,266 @@ int bt_gatt_client_read_value(bt_gatt_h gatt_handle, BT_ERR("Invalid handle type for read "); } + BT_INFO("Result [%d]", ret); return ret; /* LCOV_EXCL_STOP */ } - -int bt_gatt_client_write_value(bt_gatt_h gatt_handle, +#else +int bt_gatt_client_read_value(bt_gatt_h gatt_handle, bt_gatt_client_request_completed_cb callback, void *user_data) { - bt_gatt_common_s *c = (bt_gatt_common_s *)gatt_handle; - bt_gatt_property_e write_prop = BT_GATT_PROPERTY_WRITE; int ret = BT_ERROR_NONE; + bt_gatt_common_s *c = (bt_gatt_common_s *)gatt_handle; BT_CHECK_GATT_CLIENT_SUPPORT(); BT_CHECK_INIT_STATUS(); - BT_CHECK_INPUT_PARAMETER(gatt_handle); /* LCOV_EXCL_START */ + BT_CHECK_INPUT_PARAMETER(gatt_handle); + BT_CHECK_INPUT_PARAMETER(callback); /* LCOV_EXCL_START */ if (c->type == BT_GATT_TYPE_CHARACTERISTIC) { bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)gatt_handle; - if (chr->write_cb) { - BT_ERR("write request is now in progress"); + if (chr->read_cb) { + BT_ERR("read request is now in progress"); return BT_ERROR_NOW_IN_PROGRESS; } - ret = __get_write_prop(chr->write_type, &write_prop); - if (ret != BT_ERROR_NONE) - return BT_ERROR_OPERATION_FAILED; - - ret = _bt_get_error_code(bluetooth_gatt_set_characteristics_value_by_type( - chr->path, (guint8 *)chr->value, - chr->value_length, write_prop, - gatt_handle)); + ret = _bt_get_error_code( + bluetooth_gatt_read_characteristic_value(chr->path, gatt_handle)); if (ret == BT_ERROR_NONE) { - chr->write_cb = callback; - chr->write_user_data = user_data; + chr->read_cb = callback; + chr->read_user_data = user_data; } else { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); } } else if (c->type == BT_GATT_TYPE_DESCRIPTOR) { bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)gatt_handle; - if (desc->write_cb) { - BT_ERR("write request is now in progress"); + if (desc->read_cb) { + BT_ERR("read request is now in progress"); return BT_ERROR_NOW_IN_PROGRESS; } - ret = _bt_get_error_code(bluetooth_gatt_write_descriptor_value( - desc->path, (guint8 *)desc->value, - desc->value_length, gatt_handle)); + ret = _bt_get_error_code( + bluetooth_gatt_read_descriptor_value(desc->path, gatt_handle)); if (ret == BT_ERROR_NONE) { - desc->write_cb = callback; - desc->write_user_data = user_data; + desc->read_cb = callback; + desc->read_user_data = user_data; } else { BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); } } else { - BT_ERR("Invalid handle type for write"); ret = BT_ERROR_INVALID_PARAMETER; + BT_ERR("Invalid handle type for read "); } - return ret; + return ret; /* LCOV_EXCL_STOP */ } +#endif -static bt_gatt_client_h __find_gatt_client(const char *remote_address) +#ifdef TIZEN_GATT_CLIENT +int bt_gatt_client_write_value(bt_gatt_h gatt_handle, + bt_gatt_client_request_completed_cb callback, void *user_data) { - GSList *l = NULL; + int ret = BT_ERROR_NONE; + bt_gatt_common_s *c = (bt_gatt_common_s *)gatt_handle; - for (l = gatt_client_list; l; l = g_slist_next(l)) { - bt_gatt_client_s *client_s = l->data; + bt_gatt_handle_property_t svc_handle; + bt_gatt_handle_property_t chr_handle; + bt_gatt_handle_property_t desc_handle; + bt_gatt_service_s *service_s; + bt_gatt_characteristic_s *charc_s; + bt_gatt_client_s *client_s; + bluetooth_gatt_att_data_t write_data; - if (!g_strcmp0(client_s->remote_address, remote_address)) - return (const bt_gatt_client_h)l->data; + BT_INFO("+"); + BT_CHECK_GATT_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(gatt_handle); + BT_CHECK_INPUT_PARAMETER(callback); /* LCOV_EXCL_START */ + + if (__bt_gatt_client_is_in_progress()) { + BT_ERR("Operation is in progress"); + return BT_ERROR_NOW_IN_PROGRESS; } - return NULL; -} + if (c->type == BT_GATT_TYPE_CHARACTERISTIC) { + bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)gatt_handle; -static gboolean __get_bdaddr_from_path(const char *path, char *addr) -{ - int i; - char *tmp; + int k; + memset(&write_data, 0x00, sizeof(bluetooth_gatt_att_data_t)); + write_data.length = chr->value_length; + BT_INFO("Char write value length [%d]", write_data.length); + for (k = 0; k < chr->value_length; k++) + BT_INFO("Character val [%d] [0x%x]", k, chr->value[k]); + memcpy(&write_data.data[0], chr->value, chr->value_length); + for (k = 0; k < write_data.length; k++) + BT_INFO("Write val [%d] [0x%x]", k, write_data.data[k]); + + service_s = (bt_gatt_service_s*)chr->parent; + client_s = (bt_gatt_client_s*)service_s->parent; + + /* Create Service and Charc handles */ + __bt_string_to_uuid_hex(service_s->uuid, svc_handle.uuid); + svc_handle.instance_id = service_s->instance_id; + + __bt_string_to_uuid_hex(chr->uuid, chr_handle.uuid); + chr_handle.instance_id = chr->instance_id; + + if (chr->write_type == BT_GATT_WRITE_TYPE_WRITE) { + BT_INFO("Write characteristic: write type [%d]", chr->write_type); + ret = _bt_get_error_code( + bluetooth_gatt_client_write_characteristic_value_by_type( + client_s->remote_address, + &svc_handle, + &chr_handle, + &write_data, + BLUETOOTH_GATT_TYPE_WRITE)); + } else if (chr->write_type == BT_GATT_WRITE_TYPE_WRITE_NO_RESPONSE) { + BT_INFO("Write characteristic: write type [%d]", chr->write_type); + ret = _bt_get_error_code( + bluetooth_gatt_client_write_characteristic_value_by_type( + client_s->remote_address, + &svc_handle, + &chr_handle, + &write_data, + BLUETOOTH_GATT_TYPE_WRITE_NO_RESPONSE)); + } else { + BT_ERR("Unknow write type : %d", chr->write_type); + ret = BT_ERROR_OPERATION_FAILED; + } + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } else { + BT_INFO("GATT char write value scheuled successfully, set callback"); + chr->write_cb = callback; + chr->write_user_data = user_data; + } + } else if (c->type == BT_GATT_TYPE_DESCRIPTOR) { + bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)gatt_handle; + + BT_INFO("Write Descriptor"); + int k; + charc_s = (bt_gatt_characteristic_s*)desc->parent; + service_s = (bt_gatt_service_s*)charc_s->parent; + client_s = (bt_gatt_client_s*)service_s->parent; + + memset(&write_data, 0x00, sizeof(bluetooth_gatt_att_data_t)); + write_data.length = desc->value_length; + BT_INFO("Desc write value length [%d]", write_data.length); + memcpy(&write_data.data[0], desc->value, desc->value_length); + for (k = 0; k < write_data.length; k++) + BT_INFO("Write val [%d] [0x%x]", k, write_data.data[k]); + + /* Create Service and Charc & desc handles */ + __bt_string_to_uuid_hex(service_s->uuid, svc_handle.uuid); + svc_handle.instance_id = service_s->instance_id; + + __bt_string_to_uuid_hex(charc_s->uuid, chr_handle.uuid); + chr_handle.instance_id = charc_s->instance_id; + + __bt_string_to_uuid_hex(desc->uuid, desc_handle.uuid); + desc_handle.instance_id = desc->instance_id; + + ret = _bt_get_error_code( + bluetooth_gatt_client_write_descriptor_value( + client_s->remote_address, + &svc_handle, + &chr_handle, + &desc_handle, + &write_data, + BLUETOOTH_GATT_TYPE_WRITE_NO_RESPONSE)); + if (ret != BT_ERROR_NONE) { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } else { + BT_INFO("GATT Descriptor write value scheuled successfully, set callback"); + desc->write_cb = callback; + desc->write_user_data = user_data; + } + } else { + BT_ERR("Invalid handle type for write "); + } + + return ret; +} +#else +int bt_gatt_client_write_value(bt_gatt_h gatt_handle, + bt_gatt_client_request_completed_cb callback, void *user_data) +{ + bt_gatt_common_s *c = (bt_gatt_common_s *)gatt_handle; + bt_gatt_property_e write_prop = BT_GATT_PROPERTY_WRITE; + int ret = BT_ERROR_NONE; + + BT_CHECK_GATT_CLIENT_SUPPORT(); + BT_CHECK_INIT_STATUS(); + BT_CHECK_INPUT_PARAMETER(gatt_handle); /* LCOV_EXCL_START */ + + if (c->type == BT_GATT_TYPE_CHARACTERISTIC) { + bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)gatt_handle; + + if (chr->write_cb) { + BT_ERR("write request is now in progress"); + return BT_ERROR_NOW_IN_PROGRESS; + } + + ret = __get_write_prop(chr->write_type, &write_prop); + if (ret != BT_ERROR_NONE) + return BT_ERROR_OPERATION_FAILED; + + ret = _bt_get_error_code(bluetooth_gatt_set_characteristics_value_by_type( + chr->path, (guint8 *)chr->value, + chr->value_length, write_prop, + gatt_handle)); + if (ret == BT_ERROR_NONE) { + chr->write_cb = callback; + chr->write_user_data = user_data; + } else { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } + } else if (c->type == BT_GATT_TYPE_DESCRIPTOR) { + bt_gatt_descriptor_s *desc = (bt_gatt_descriptor_s *)gatt_handle; + + if (desc->write_cb) { + BT_ERR("write request is now in progress"); + return BT_ERROR_NOW_IN_PROGRESS; + } + + ret = _bt_get_error_code(bluetooth_gatt_write_descriptor_value( + desc->path, (guint8 *)desc->value, + desc->value_length, gatt_handle)); + if (ret == BT_ERROR_NONE) { + desc->write_cb = callback; + desc->write_user_data = user_data; + } else { + BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); + } + } else { + BT_ERR("Invalid handle type for write"); + ret = BT_ERROR_INVALID_PARAMETER; + } + + return ret; +} +#endif + +static bt_gatt_client_h __find_gatt_client(const char *remote_address) +{ + GSList *l = NULL; + + for (l = gatt_client_list; l; l = g_slist_next(l)) { + bt_gatt_client_s *client_s = l->data; + + if (!g_strcmp0(client_s->remote_address, remote_address)) + return (const bt_gatt_client_h)l->data; + } + + return NULL; +} + +#ifndef TIZEN_GATT_CLIENT +static gboolean __get_bdaddr_from_path(const char *path, char *addr) +{ + int i; + char *tmp; /* * e.g. @@ -3028,11 +3985,199 @@ static gboolean __get_bdaddr_from_path(const char *path, char *addr) } addr[i] = '\0'; + BT_DBG("path : %s, addr : %s", path, addr); + return TRUE; } +#endif + +#ifdef TIZEN_GATT_CLIENT +void __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 bt_gatt_characteristic_s* __gatt_get_characteristic_handle( + unsigned char *svc_uuid, + int svc_inst, + unsigned char *uuid, + int instance_id, + char *remote_address) +{ + GSList *l; + GSList *ll; + bt_gatt_client_h client; + bt_gatt_client_s *client_s; + bt_gatt_service_s *svc; + bt_gatt_characteristic_s *chr; + + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + char svc_uuid_string[BLUETOOTH_UUID_STRING_MAX]; + + __uuid_hex_to_string(svc_uuid, svc_uuid_string); + __uuid_hex_to_string(uuid, uuid_string) ; + + BT_INFO("Address [%s] Char UUID [%s]", remote_address, uuid_string); + + + client = __find_gatt_client(remote_address); + if (client == NULL) { + BT_ERR("Cannot find client [%s]", remote_address); + return NULL; + } + + client_s = (bt_gatt_client_s *)client; + for (l = client_s->services; l; l = g_slist_next(l)) { + svc = (bt_gatt_service_s *)l->data; + + if (svc == NULL) + continue; + + if (g_ascii_strcasecmp(svc->uuid, svc_uuid_string) == 0 && + svc->instance_id == svc_inst) { + + for (ll = svc->characteristics; ll; ll = g_slist_next(ll)) { + chr = (bt_gatt_characteristic_s *)ll->data; + + if (chr == NULL) + continue; + if (g_ascii_strcasecmp(chr->uuid, uuid_string) == 0 && + chr->instance_id == instance_id) { + return chr; + } + } + } + } + return NULL; +} /* LCOV_EXCL_STOP */ + +static bt_gatt_descriptor_s* __gatt_get_descriptor_handle( + unsigned char *svc_uuid, + int svc_inst, + unsigned char *char_uuid, + int char_inst, + unsigned char *uuid, + int instance_id, + char *remote_address) +{ + GSList *l; + GSList *ll; + GSList *lll; + bt_gatt_client_h client; + bt_gatt_client_s *client_s; + bt_gatt_service_s *svc; + bt_gatt_characteristic_s *chr; + bt_gatt_descriptor_s *desc; + + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + char svc_uuid_string[BLUETOOTH_UUID_STRING_MAX]; + char char_uuid_string[BLUETOOTH_UUID_STRING_MAX]; + + __uuid_hex_to_string(uuid, uuid_string); + __uuid_hex_to_string(svc_uuid, svc_uuid_string); + __uuid_hex_to_string(char_uuid, char_uuid_string); + + BT_INFO("Address [%s] Descriptor UUID [%s]", remote_address, uuid_string); + + client = __find_gatt_client(remote_address); + if (client == NULL) { + BT_ERR("Cannot find client [%s]", remote_address); + return NULL; + } + + client_s = (bt_gatt_client_s *)client; + for (l = client_s->services; l; l = g_slist_next(l)) { + svc = (bt_gatt_service_s *)l->data; + + if (svc == NULL) + continue; + + if (g_ascii_strcasecmp(svc->uuid, svc_uuid_string) == 0 && + svc->instance_id == svc_inst) { + + for (ll = svc->characteristics; ll; ll = g_slist_next(ll)) { + chr = (bt_gatt_characteristic_s *)ll->data; + + if (chr == NULL) + continue; + + if (g_ascii_strcasecmp(chr->uuid, char_uuid_string) == 0 && + chr->instance_id == char_inst) { + + for (lll = chr->descriptors; lll; lll = g_slist_next(lll)) { + desc = (bt_gatt_descriptor_s *)lll->data; + + if (desc == NULL) + continue; + + if (g_ascii_strcasecmp(desc->uuid, uuid_string) == 0 && + desc->instance_id == instance_id) { + return desc; + } + } + } + } + } + } + return NULL; +} /* LCOV_EXCL_STOP */ + +static void __gatt_value_changed_cb(unsigned char *uuid, char *remote_address, + char *value, int value_length, void *user_data) +{ + GSList *l; + GSList *ll; + bt_gatt_client_h client; + bt_gatt_client_s *client_s; + bt_gatt_service_s *svc; + bt_gatt_characteristic_s *chr; + BT_INFO("+"); + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + __uuid_hex_to_string(uuid, uuid_string) ; + + BT_INFO("Address [%s] Char UUID [%s]", remote_address, uuid_string); + + client = __find_gatt_client(remote_address); + if (client == NULL) { + BT_ERR("Cannot find client [%s]", remote_address); + return; + } + + client_s = (bt_gatt_client_s *)client; + for (l = client_s->services; l; l = g_slist_next(l)) { + svc = (bt_gatt_service_s *)l->data; + for (ll = svc->characteristics; ll; ll = g_slist_next(ll)) { + chr = (bt_gatt_characteristic_s *)ll->data; + if (g_ascii_strcasecmp(chr->uuid, uuid_string) == 0) { + if (chr->value_changed_cb) + chr->value_changed_cb(chr, value, + value_length, + chr->value_changed_user_data); + + bt_gatt_set_value(chr, value, value_length); + return; + } + } + } +} /* LCOV_EXCL_STOP */ +#else static void __value_changed_cb(char *char_path, - char *value, int value_length, void *user_data) + char *value, int value_length, void *user_data) { GSList *l; GSList *ll; @@ -3042,6 +4187,8 @@ static void __value_changed_cb(char *char_path, bt_gatt_characteristic_s *chr; char remote_address[BT_ADDR_STR_LEN + 1] = { 0, }; + BT_DBG("%s", char_path); + if (__get_bdaddr_from_path(char_path, remote_address) == FALSE) { BT_ERR("Cannot get addr from path : %s", char_path); return; @@ -3074,37 +4221,78 @@ static void __value_changed_cb(char *char_path, } } } /* LCOV_EXCL_STOP */ +#endif int bt_gatt_client_set_characteristic_value_changed_cb(bt_gatt_h characteristic, bt_gatt_client_characteristic_value_changed_cb callback, void *user_data) { int ret; - char *name = NULL; bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)characteristic; - BT_CHECK_GATT_CLIENT_SUPPORT(); +#ifdef TIZEN_GATT_CLIENT + bt_gatt_handle_property_t svc_handle; + bt_gatt_handle_property_t chr_handle; + bt_gatt_service_s *service_s; + bt_gatt_client_s *client_s; +#endif + + BT_INFO("+"); + + BT_CHECK_GATT_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(characteristic); BT_CHECK_INPUT_PARAMETER(callback); - bt_gatt_service_s *svc = (bt_gatt_service_s *)chr->parent; - chr->value_changed_cb = callback; chr->value_changed_user_data = user_data; +#ifdef TIZEN_GATT_CLIENT + + service_s = (bt_gatt_service_s*)chr->parent; + client_s = (bt_gatt_client_s*)service_s->parent; + + /* Create Service and Charc handles */ + __bt_string_to_uuid_hex(service_s->uuid, svc_handle.uuid); + svc_handle.instance_id = service_s->instance_id; + + __bt_string_to_uuid_hex(chr->uuid, chr_handle.uuid); + chr_handle.instance_id = chr->instance_id; +#endif + + BT_INFO("Characteristic properties [%d] charc UUID [%s]", + chr->properties, chr->uuid); + if (chr->properties & - (BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_INDICATE)) { - bt_get_uuid_name(svc->uuid, &name); + (BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_INDICATE)) { + +#ifdef TIZEN_GATT_CLIENT + ret = _bt_get_error_code(bluetooth_gatt_client_watch_characteristics( + client_s->remote_address, + &svc_handle, + &chr_handle, + client_s->client_id, + TRUE)); +#else ret = _bt_get_error_code(bluetooth_gatt_watch_characteristics( - chr->path, name)); - g_free(name); + chr->path)); + + +#endif if (ret != BT_ERROR_NONE) BT_ERR("%s(0x%08x)", - _bt_convert_error_to_string(ret), ret); - else + _bt_convert_error_to_string(ret), ret); + else { +#ifdef TIZEN_GATT_CLIENT + BT_INFO("Set Char val changed callback at index [%d]", BT_EVENT_GATT_CLIENT_VALUE_CHANGED); + _bt_set_cb(BT_EVENT_GATT_CLIENT_VALUE_CHANGED, + __gatt_value_changed_cb, NULL); +#else _bt_set_cb(BT_EVENT_GATT_CLIENT_VALUE_CHANGED, __value_changed_cb, NULL); +#endif + BT_INFO("Char value changed callback registsred successfully"); + } } else { BT_DBG("notify or indication is not supported"); ret = BT_ERROR_NOT_SUPPORTED; @@ -3118,14 +4306,43 @@ int bt_gatt_client_unset_characteristic_value_changed_cb(bt_gatt_h characteristi int ret; bt_gatt_characteristic_s *chr = (bt_gatt_characteristic_s *)characteristic; +#ifdef TIZEN_GATT_CLIENT + bt_gatt_handle_property_t svc_handle; + bt_gatt_handle_property_t chr_handle; + bt_gatt_service_s *service_s; + bt_gatt_client_s *client_s; +#endif + BT_CHECK_GATT_CLIENT_SUPPORT(); BT_CHECK_INIT_STATUS(); BT_CHECK_INPUT_PARAMETER(characteristic); /* LCOV_EXCL_START */ + BT_INFO("+"); + +#ifdef TIZEN_GATT_CLIENT + service_s = (bt_gatt_service_s*)chr->parent; + client_s = (bt_gatt_client_s*)service_s->parent; + + /* Create Service and Charc handles */ + __bt_string_to_uuid_hex(service_s->uuid, svc_handle.uuid); + svc_handle.instance_id = service_s->instance_id; + + __bt_string_to_uuid_hex(chr->uuid, chr_handle.uuid); + chr_handle.instance_id = chr->instance_id; +#endif if (chr->properties & - (BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_INDICATE)) { + (BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_INDICATE)) { +#ifdef TIZEN_GATT_CLIENT + ret = _bt_get_error_code(bluetooth_gatt_client_watch_characteristics( + client_s->remote_address, + &svc_handle, + &chr_handle, + client_s->client_id, + FALSE)); +#else ret = _bt_get_error_code( - bluetooth_gatt_unwatch_characteristics(chr->path)); + bluetooth_gatt_unwatch_characteristics(chr->path)); +#endif if (ret != BT_ERROR_NONE) BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret); @@ -3154,6 +4371,7 @@ int bt_gatt_client_get_service(bt_gatt_client_h client, const char *uuid, BT_CHECK_INPUT_PARAMETER(uuid); BT_CHECK_INPUT_PARAMETER(service); + BT_INFO("Get Service from UUID [%s]", uuid); ret = __get_gatt_handle_by_uuid(client_s->services, uuid, &gatt_handle); if (ret == BT_ERROR_NONE && gatt_handle != NULL) { *service = gatt_handle; @@ -3181,6 +4399,7 @@ int bt_gatt_client_foreach_services(bt_gatt_client_h client, total = g_slist_length(client_s->services); /* LCOV_EXCL_LINE */ for (l = client_s->services; l; l = g_slist_next(l)) { /* LCOV_EXCL_LINE */ + BT_INFO("Call one service callback"); if (!callback(total, index++, (bt_gatt_h)l->data, user_data)) /* LCOV_EXCL_LINE */ break; @@ -3209,7 +4428,11 @@ int bt_gatt_client_set_service_changed_cb(bt_gatt_client_h client, } _bt_convert_address_to_hex(&bd_addr, client_s->remote_address); +#ifdef TIZEN_GATT_CLIENT + ret = _bt_get_error_code(bluetooth_gatt_client_set_service_change_watcher(&bd_addr, TRUE)); +#else ret = _bt_get_error_code(bluetooth_gatt_set_service_change_watcher(&bd_addr, TRUE)); +#endif if (ret == BT_ERROR_NONE) { BT_INFO("Service Changed callback registered"); @@ -3233,7 +4456,11 @@ int bt_gatt_client_unset_service_changed_cb(bt_gatt_client_h client) BT_CHECK_INPUT_PARAMETER(client); _bt_convert_address_to_hex(&bd_addr, client_s->remote_address); +#ifdef TIZEN_GATT_CLIENT + ret = _bt_get_error_code(bluetooth_gatt_client_set_service_change_watcher(&bd_addr, FALSE)); +#else ret = _bt_get_error_code(bluetooth_gatt_set_service_change_watcher(&bd_addr, FALSE)); +#endif if (ret == BT_ERROR_NONE) { BT_INFO("Service Changed callback unregistered [%s]", client_s->remote_address); client_s->service_changed_cb = NULL; @@ -3245,6 +4472,415 @@ int bt_gatt_client_unset_service_changed_cb(bt_gatt_client_h client) return BT_ERROR_NONE; } +#ifdef TIZEN_GATT_CLIENT +void _bt_handle_gatt_client_char_read_completed_event(int result, + void *resp) +{ + bt_gatt_client_request_completed_cb cb = NULL; + void *user_data = NULL; + bt_gatt_service_s *svc; + bt_gatt_characteristic_s *chr; + + bt_gatt_char_property_t *char_prop1; /* Pass Case */ + bluetooth_gatt_client_char_prop_info_t *char_prop2; /* Fail Case */ + bt_gatt_client_s *client_s; + + bt_gatt_h gatt_handle = NULL; + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + + if (resp == NULL) { + BT_ERR("GATT Client response data is NULL"); + return; + } + if (result != BLUETOOTH_ERROR_NONE) { + char_prop2 = (bluetooth_gatt_client_char_prop_info_t*)resp; + char *device_addr = NULL; + _bt_convert_address_to_string(&device_addr, &char_prop2->device_address); + + /* Return if Client not found */ + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(device_addr); + if (!client_s) { + BT_ERR("GATT client not found against address [%s]", device_addr); + g_free(device_addr); + return; + } + chr = __gatt_get_characteristic_handle(char_prop2->svc.uuid, + char_prop2->svc.instance_id, + char_prop2->characteristic.uuid, + char_prop2->characteristic.instance_id, + device_addr); + + __uuid_hex_to_string(char_prop2->characteristic.uuid, uuid_string); + BT_INFO("GATT Char read completed Failed event UUID [%s] address [%s]", + uuid_string, device_addr); + g_free(device_addr); + if (!chr) { + BT_ERR("No characteristic found"); + return; + } + } else { + char_prop1 = (bt_gatt_char_property_t *)resp; + /* Return if Client not found */ + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(char_prop1->address); + if (!client_s) { + BT_ERR("GATT client not found against address [%s]", + char_prop1->address); + return; + } + chr = __gatt_get_characteristic_handle( + char_prop1->svc_prop.uuid, + char_prop1->svc_prop.instance_id, + char_prop1->prop.uuid, + char_prop1->prop.instance_id, + char_prop1->address); + + if (!chr) { + BT_ERR("No characteristic found"); + return; + } + + __uuid_hex_to_string(char_prop1->prop.uuid, uuid_string); + BT_INFO("GATT Char read completed Success event UUID [%s] address [%s]", + uuid_string, char_prop1->address); + } + + cb = chr->read_cb; + user_data = chr->read_user_data; + + chr->read_cb = NULL; + chr->read_user_data = NULL; + + if (!chr->parent) { + BT_INFO("Already destroyed handle : %p", chr); + if (!chr->write_cb) + g_free(chr); + return; + } + + svc = (bt_gatt_service_s*) chr->parent; + + __get_gatt_handle_by_uuid(svc->characteristics, uuid_string, &gatt_handle); + + if (result == BLUETOOTH_ERROR_NONE) { + BT_INFO("Set value"); + bt_gatt_set_value(gatt_handle, + (char *)char_prop1->value, (int)char_prop1->val_len); + } + + if (cb) { + BT_INFO("callback present"); + cb(result, gatt_handle, user_data); + } else + BT_ERR("Callback not present!!!"); + return; +} + +void _bt_handle_gatt_client_desc_read_completed_event(int result, + void *resp) +{ + void *user_data = NULL; + bt_gatt_h gatt_handle = NULL; + bt_gatt_characteristic_s *chr; + bt_gatt_client_request_completed_cb cb = NULL; + + bt_gatt_char_descriptor_property_t *desc_prop1; /* Pass Case */ + bluetooth_gatt_client_desc_prop_info_t *desc_prop2; /* Fail Case */ + bt_gatt_descriptor_s *desc; + bt_gatt_client_s *client_s; + + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + + if (resp == NULL) { + BT_ERR("GATT Client response data is NULL"); + return; + } + if (result != BLUETOOTH_ERROR_NONE) { + desc_prop2 = (bluetooth_gatt_client_desc_prop_info_t*)resp; + char *device_addr = NULL; + _bt_convert_address_to_string(&device_addr, &desc_prop2->device_address); + + /* Return if Client not found */ + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(device_addr); + if (!client_s) { + BT_INFO("GATT client not found against address [%s]", device_addr); + g_free(device_addr); + return; + } + desc = __gatt_get_descriptor_handle(desc_prop2->svc.uuid, + desc_prop2->svc.instance_id, + desc_prop2->characteristic.uuid, + desc_prop2->characteristic.instance_id, + desc_prop2->descriptor.uuid, + desc_prop2->descriptor.instance_id, + device_addr); + + + __uuid_hex_to_string(desc_prop2->descriptor.uuid, uuid_string); + BT_INFO("GATT Desc read completed Failed event UUID [%s] address [%s]", + uuid_string, device_addr); + + g_free(device_addr); + if (!desc) { + BT_ERR("No Descriptor found"); + return; + } + } else { + desc_prop1 = (bt_gatt_char_descriptor_property_t *)resp; + /* Return if Client not found */ + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(desc_prop1->address); + if (!client_s) { + BT_INFO("GATT client not found against address [%s]", + desc_prop1->address); + return; + } + desc = __gatt_get_descriptor_handle(desc_prop1->svc_prop.uuid, + desc_prop1->svc_prop.instance_id, + desc_prop1->char_prop.uuid, + desc_prop1->char_prop.instance_id, + desc_prop1->prop.uuid, + desc_prop1->prop.instance_id, + desc_prop1->address); + if (!desc) { + BT_ERR("No Descriptor found"); + return; + } + __uuid_hex_to_string(desc_prop1->prop.uuid, uuid_string); + BT_INFO("GATT Desc read completed Success event UUID [%s] address [%s]", + uuid_string, desc_prop1->address); + } + + cb = desc->read_cb; + user_data = desc->read_user_data; + + desc->read_cb = NULL; + desc->read_user_data = NULL; + + if (!desc->parent) { + BT_INFO("Already destroyed handle : %p", desc); + if (!desc->write_cb) + g_free(desc); + return; + } + + chr = (bt_gatt_characteristic_s*)desc->parent; + + __get_gatt_handle_by_uuid(chr->descriptors, uuid_string, &gatt_handle); + + if (result == BLUETOOTH_ERROR_NONE) { + BT_INFO("Set value"); + bt_gatt_set_value(gatt_handle, + (char *)desc_prop1->value, (int)desc_prop1->val_len); + } + + if (cb) { + BT_INFO("callback present"); + cb(result, gatt_handle, user_data); + } else + BT_ERR("Callback not present!!!!"); + + return; +} + +void _bt_handle_gatt_client_char_write_completed_event(int result, + void *resp) +{ + bt_gatt_client_request_completed_cb cb = NULL; + void *user_data = NULL; + bt_gatt_service_s *svc; + bt_gatt_h gatt_handle = NULL; + + bt_gatt_char_property_t *char_prop1; /* Pass Case */ + bluetooth_gatt_client_char_prop_info_t *char_prop2; /* Fail Case */ + bt_gatt_characteristic_s *chr; + bt_gatt_client_s *client_s; + + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + + if (resp == NULL) { + BT_ERR("GATT Client response data is NULL"); + return; + } + + BT_INFO("GATT Char Write Clalback result [%d]", result); + + if (result != BLUETOOTH_ERROR_NONE) { + char_prop2 = (bluetooth_gatt_client_char_prop_info_t*)resp; + char *device_addr = NULL; + _bt_convert_address_to_string(&device_addr, &char_prop2->device_address); + + /* Return if Client not found */ + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(device_addr); + if (!client_s) { + BT_INFO("GATT client not found against address [%s]", device_addr); + g_free(device_addr); + return; + } + chr = __gatt_get_characteristic_handle(char_prop2->svc.uuid, + char_prop2->svc.instance_id, + char_prop2->characteristic.uuid, + char_prop2->characteristic.instance_id, + device_addr); + + __uuid_hex_to_string(char_prop2->characteristic.uuid, uuid_string); + BT_INFO("GATT Char Write completed Failed event UUID [%s] address [%s]", + uuid_string, device_addr); + g_free(device_addr); + if (!chr) { + BT_ERR("No characteristic found"); + return; + } + } else { + char_prop1 = (bt_gatt_char_property_t *)resp; + /* Return if Client not found */ + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(char_prop1->address); + if (!client_s) { + BT_INFO("GATT client not found against address [%s]", + char_prop1->address); + return; + } + chr = __gatt_get_characteristic_handle( + char_prop1->svc_prop.uuid, + char_prop1->svc_prop.instance_id, + char_prop1->prop.uuid, + char_prop1->prop.instance_id, + char_prop1->address); + + if (!chr) { + BT_ERR("No characteristic found"); + return; + } + + __uuid_hex_to_string(char_prop1->prop.uuid, uuid_string); + BT_INFO("GATT Char Write completed Success event UUID [%s] address [%s]", + uuid_string, char_prop1->address); + } + + cb = chr->write_cb; + user_data = chr->write_user_data; + + chr->write_cb = NULL; + chr->write_user_data = NULL; + + if (!chr->parent) { + BT_INFO("Already destroyed handle : %p", chr); + if (!chr->read_cb) + g_free(chr); + return; + } + + svc = (bt_gatt_service_s*) chr->parent; + + __get_gatt_handle_by_uuid(svc->characteristics, uuid_string, &gatt_handle); + + if (cb) + cb(result, gatt_handle, user_data); + else + BT_ERR("Callback not present!!!"); + return; +} + +void _bt_handle_gatt_client_desc_write_completed_event(int result, + void *resp) +{ + void *user_data = NULL; + bt_gatt_client_request_completed_cb cb = NULL; + bt_gatt_characteristic_s *chr; + bt_gatt_h gatt_handle; + + bt_gatt_char_descriptor_property_t *desc_prop1; /* Pass Case */ + bluetooth_gatt_client_desc_prop_info_t *desc_prop2; /* Fail Case */ + bt_gatt_descriptor_s *desc; + bt_gatt_client_s *client_s; + + char uuid_string[BLUETOOTH_UUID_STRING_MAX]; + + if (resp == NULL) { + BT_ERR("GATT Client response data is NULL"); + return; + } + if (result != BLUETOOTH_ERROR_NONE) { + desc_prop2 = (bluetooth_gatt_client_desc_prop_info_t*)resp; + char *device_addr = NULL; + _bt_convert_address_to_string(&device_addr, &desc_prop2->device_address); + + /* Return if Client not found */ + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(device_addr); + if (!client_s) { + BT_INFO("GATT client not found against address [%s]", device_addr); + g_free(device_addr); + return; + } + desc = __gatt_get_descriptor_handle(desc_prop2->svc.uuid, + desc_prop2->svc.instance_id, + desc_prop2->characteristic.uuid, + desc_prop2->characteristic.instance_id, + desc_prop2->descriptor.uuid, + desc_prop2->descriptor.instance_id, + device_addr); + + __uuid_hex_to_string(desc_prop2->descriptor.uuid, uuid_string); + BT_INFO("GATT Desc Write completed Failed event UUID [%s] address [%s]", + uuid_string, device_addr); + + g_free(device_addr); + if (!desc) { + BT_ERR("No Descriptor found"); + return; + } + } else { + desc_prop1 = (bt_gatt_char_descriptor_property_t *)resp; + /* Return if Client not found */ + client_s = (bt_gatt_client_s *)_bt_gatt_get_client(desc_prop1->address); + if (!client_s) { + BT_INFO("GATT client not found against address [%s]", + desc_prop1->address); + return; + } + desc = __gatt_get_descriptor_handle(desc_prop1->svc_prop.uuid, + desc_prop1->svc_prop.instance_id, + desc_prop1->char_prop.uuid, + desc_prop1->char_prop.instance_id, + desc_prop1->prop.uuid, + desc_prop1->prop.instance_id, + desc_prop1->address); + if (!desc) { + BT_ERR("No Descriptor found"); + return; + } + __uuid_hex_to_string(desc_prop1->prop.uuid, uuid_string); + BT_INFO("GATT Desc read completed Success event UUID [%s] address [%s]", + uuid_string, desc_prop1->address); + } + + cb = desc->write_cb; + user_data = desc->write_user_data; + + desc->write_cb = NULL; + desc->write_user_data = NULL; + + if (!desc->parent) { + BT_INFO("Already destroyed handle : %p", desc); + if (!desc->read_cb) + g_free(desc); + return; + } + + chr = (bt_gatt_characteristic_s*)desc->parent; + + BT_INFO("Total descriptors char has [%d]", g_slist_length(chr->descriptors)); + + __get_gatt_handle_by_uuid(chr->descriptors, uuid_string, &gatt_handle); + + if (cb) + cb(result, gatt_handle, user_data); + else + BT_ERR("Callback not present!!!"); + + return; +} +#endif + + int bt_gatt_client_request_att_mtu_change(bt_gatt_client_h client, unsigned int mtu) { int ret; -- cgit v1.2.3