#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
+#include <gio/gunixfdlist.h>
#include "bt-common.h"
#include "bt-event-handler.h"
#include "bt-internal-types.h"
#include "bt-request-sender.h"
+#include "bluetooth-gatt-client-api.h"
+#include <arpa/inet.h>
+static GSList *gatt_characteristic_notify_list;
+static GSList *gatt_characteristic_write_list = NULL;;
+
#define GATT_DEFAULT_TIMEOUT (6 * 1000) // Dependent on supervision timeout 6 sec
typedef enum {
BT_CHECK_PARAMETER(svc_pty, return);
g_free(svc_pty->uuid);
- g_free(svc_pty->handle);
- g_strfreev(svc_pty->include_handles.handle);
- g_strfreev(svc_pty->char_handle.handle);
memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
g_free(char_pty->name);
g_free(char_pty->description);
g_free(char_pty->val);
- g_free(char_pty->handle);
- g_strfreev(char_pty->char_desc_handle.handle);
memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
g_free(desc_pty->uuid);
g_free(desc_pty->val);
- g_free(desc_pty->handle);
memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t));
{
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)))
+ sizeof(bluetooth_device_address_t)))
return TRUE;
}
{
GSList *l;
bluetooth_device_address_t *addr = NULL;
- 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 *)address->addr);
- _bt_convert_addr_string_to_secure_string(secure_address,
- device_address);
+ _bt_convert_addr_type_to_secure_string(secure_address, (unsigned char *)address->addr);
BT_INFO("Set watcher for %s with %d", secure_address, enable);
if (enable == TRUE) {
- if (service_monitor_list == NULL)
- _bt_register_manager_subscribe_signal(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);
+
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))) {
+ sizeof(bluetooth_device_address_t))) {
service_monitor_list =
g_slist_remove(service_monitor_list, addr);
g_free(addr);
BT_CHECK_PARAMETER(service, return);
BT_CHECK_ENABLED(return);
- g_conn = _bt_gdbus_get_system_gconn();
+ g_conn = _bt_get_system_private_conn();
retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
properties_proxy = g_dbus_proxy_new_sync(g_conn,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
BT_BLUEZ_NAME,
service_handle,
BT_PROPERTIES_INTERFACE,
if (!g_strcmp0(key, "UUID")) {
char *name = NULL;
service->uuid = g_variant_dup_string(value, &len);
- _bt_get_uuid_specification_name(service->uuid, &name);
- BT_INFO("======> Service : %s [%s]", service->uuid, name);
+ bluetooth_get_uuid_name(service->uuid, &name);
+ BT_INFO("%s %s [%s]", service_handle + 37, service->uuid, name);
g_free(name);
} else if (!g_strcmp0(key, "Primary")) {
service->primary = g_variant_get_boolean(value);
} else if (!g_strcmp0(key, "Includes")) {
g_variant_get(value, "ao", &char_iter);
- gp_array = g_ptr_array_new();
- while (g_variant_iter_loop(char_iter, "&o", &char_handle))
- g_ptr_array_add(gp_array, (gpointer)char_handle);
-
- if (gp_array->len != 0) {
- service->include_handles.count = gp_array->len;
- service->include_handles.handle =
- __get_string_array_from_gptr_array(gp_array);
+ if (char_iter != NULL) {
+ gp_array = g_ptr_array_new();
+ while (g_variant_iter_loop(char_iter, "&o", &char_handle))
+ g_ptr_array_add(gp_array, (gpointer)char_handle);
+
+ if (gp_array->len != 0) {
+ service->include_handles.count = gp_array->len;
+ service->include_handles.handle =
+ __get_string_array_from_gptr_array(gp_array);
+ }
+ g_ptr_array_free(gp_array, TRUE);
+ g_variant_iter_free(char_iter);
}
- g_ptr_array_free(gp_array, TRUE);
- g_variant_iter_free(char_iter);
} else if (!g_strcmp0(key, "Characteristics")) {
g_variant_get(value, "ao", &char_iter);
- gp_array = g_ptr_array_new();
- while (g_variant_iter_loop(char_iter, "&o", &char_handle))
- g_ptr_array_add(gp_array, (gpointer)char_handle);
-
- if (gp_array->len != 0) {
- service->char_handle.count = gp_array->len;
- service->char_handle.handle =
- __get_string_array_from_gptr_array(gp_array);
+ if (char_iter != NULL) {
+ gp_array = g_ptr_array_new();
+ while (g_variant_iter_loop(char_iter, "&o", &char_handle))
+ g_ptr_array_add(gp_array, (gpointer)char_handle);
+
+ if (gp_array->len != 0) {
+ service->char_handle.count = gp_array->len;
+ service->char_handle.handle =
+ __get_string_array_from_gptr_array(gp_array);
+ }
+ g_ptr_array_free(gp_array, TRUE);
+ g_variant_iter_free(char_iter);
}
BT_DBG("Characteristics count : %d", service->char_handle.count);
- g_ptr_array_free(gp_array, TRUE);
- g_variant_iter_free(char_iter);
}
}
char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
int ret = BLUETOOTH_ERROR_INTERNAL;
+ int idx = 0;
- BT_INFO("+");
+ BT_DBG("+");
BT_CHECK_PARAMETER(address, return);
BT_CHECK_PARAMETER(prim_svc, return);
BT_CHECK_ENABLED(return);
if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
continue;
- BT_DBG("Object Path: %s", object_path);
+ BT_DBG("[%d] Object Path : %s", idx++, object_path);
while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
if (g_strcmp0(key, "Primary") == 0) {
if (g_variant_get_boolean(value))
g_strstr_len(service->uuid, -1,
service_uuid)) {
ret = BLUETOOTH_ERROR_NONE;
+
+ /* release resources */
+ g_free(object_path);
+ g_variant_iter_free(interface_iter);
+ g_free(interface_str);
+ g_variant_iter_free(svc_iter);
+
goto done;
}
}
g_variant_iter_free(char_iter);
g_variant_unref(value);
g_object_unref(proxy);
+ g_variant_unref(char_value);
}
BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
BT_CHECK_PARAMETER(service_handle, return);
BT_CHECK_ENABLED(return);
- g_conn = _bt_gdbus_get_system_gconn();
+ g_conn = _bt_get_system_private_conn();
retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
properties_proxy = g_dbus_proxy_new_sync(g_conn,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
BT_BLUEZ_NAME,
service_handle,
BT_PROPERTIES_INTERFACE,
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"))
return ret;
}
+static void __convert_permission_flag_to_str(unsigned int permission)
+{
+ char perm[200] = { 0, };
+
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
+ g_strlcat(perm, "broadcast ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ)
+ g_strlcat(perm, "read ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
+ g_strlcat(perm, "write-without-response ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE)
+ g_strlcat(perm, "write ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
+ g_strlcat(perm, "notify ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
+ g_strlcat(perm, "indicate ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
+ g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
+ g_strlcat(perm, "reliable-write ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
+ g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
+ g_strlcat(perm, "encrypt-read ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
+ g_strlcat(perm, "encrypt-write ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
+ g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
+ if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
+ g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
+
+ BT_INFO("permission [0x%04x] : %s\n", permission, perm);
+ return;
+}
+
BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
const char *char_handle, bt_gatt_char_property_t *characteristic)
{
BT_CHECK_ENABLED(return);
- g_conn = _bt_gdbus_get_system_gconn();
+ g_conn = _bt_get_system_private_conn();
retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
properties_proxy = g_dbus_proxy_new_sync(g_conn,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
BT_BLUEZ_NAME,
char_handle,
BT_PROPERTIES_INTERFACE,
if (!g_strcmp0(key, "UUID")) {
char *name = NULL;
characteristic->uuid = g_variant_dup_string(value, &len);
- _bt_get_uuid_specification_name(characteristic->uuid, &name);
- BT_INFO("Characteristic : %s [%s]", characteristic->uuid, name);
+ bluetooth_get_uuid_name(characteristic->uuid, &name);
+ BT_INFO("%s %s [%s]", char_handle + 37, characteristic->uuid, name);
g_free(name);
} else if (!g_strcmp0(key, "Value")) {
gb_array = g_byte_array_new();
while (g_variant_iter_loop(char_perm_iter, "s", &permission))
characteristic->permission |= __get_permission_flag(permission);
+ __convert_permission_flag_to_str(characteristic->permission);
g_variant_iter_free(char_perm_iter);
} else if (!g_strcmp0(key, "Descriptors")) {
BT_CHECK_PARAMETER(char_uuid, return);
BT_CHECK_ENABLED(return);
- g_conn = _bt_gdbus_get_system_gconn();
+ g_conn = _bt_get_system_private_conn();
retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
properties_proxy = g_dbus_proxy_new_sync(g_conn,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
BT_BLUEZ_NAME,
service_handle,
BT_PROPERTIES_INTERFACE,
BT_CHECK_ENABLED(return);
- g_conn = _bt_gdbus_get_system_gconn();
+ g_conn = _bt_get_system_private_conn();
retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
properties_proxy = g_dbus_proxy_new_sync(g_conn,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
BT_BLUEZ_NAME,
descriptor_handle,
BT_PROPERTIES_INTERFACE,
if (!g_strcmp0(key, "UUID")) {
char *name = NULL;
descriptor->uuid = g_variant_dup_string(value, &len);
- _bt_get_uuid_specification_name(descriptor->uuid, &name);
+ bluetooth_get_uuid_name(descriptor->uuid, &name);
BT_INFO("Descriptor : %s [%s]", descriptor->uuid, name);
g_free(name);
} else if (!g_strcmp0(key, "Value")) {
return BLUETOOTH_ERROR_NONE;
}
+static int __bluetooth_get_att_error_code(GError *error, char *handle)
+{
+ int att_ecode = 0;
+ int len;
+ char *str = NULL;
+
+ BT_ERR("Error : %s [%s]", error->message, handle + 15);
+ str = g_strrstr(error->message, "ATT error: 0x");
+ if (str) {
+ len = strlen(str);
+ att_ecode = g_ascii_xdigit_value(str[len - 2]) << 4;
+ att_ecode += g_ascii_xdigit_value(str[len - 1]);
+ } else
+ return BLUETOOTH_ATT_ERROR_INTERNAL;
+
+ switch (att_ecode) {
+ case BLUETOOTH_ATT_ERROR_READ_NOT_PERMITTED:
+ BT_ERR("Read not permitted");
+ break;
+ case BLUETOOTH_ATT_ERROR_WRITE_NOT_PERMITTED:
+ BT_ERR("Write not permitted");
+ break;
+ case BLUETOOTH_ATT_ERROR_AUTHENTICATION:
+ case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
+ case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
+ BT_ERR("Not paired");
+ break;
+ case BLUETOOTH_ATT_ERROR_INVALID_OFFSET:
+ BT_ERR("Invalid offset");
+ break;
+ case BLUETOOTH_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
+ BT_ERR("Invalid Length");
+ break;
+ case BLUETOOTH_ATT_ERROR_AUTHORIZATION:
+ BT_ERR("Operation not Authorized");
+ break;
+ default:
+ BT_ERR("default ecode");
+ break;
+ }
+
+ if (att_ecode >= 0x80 && att_ecode <= 0x9F)
+ BT_ERR("Application error");
+
+ return att_ecode;
+}
+
static void __bluetooth_internal_read_cb(GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
+ GAsyncResult *res, gpointer user_data)
{
GError *error = NULL;
- bt_user_info_t *user_info;
- bt_gatt_char_value_t char_value = { 0, };
GDBusConnection *system_gconn = NULL;
GVariant *value;
- GByteArray *gp_byte_array = NULL;
+ bt_user_info_t *user_info;
GVariantIter *iter;
+ GByteArray *gp_byte_array = NULL;
guint8 g_byte;
- int ret = BLUETOOTH_ERROR_NONE;
+ int att_ecode = 0;
+ bt_gatt_resp_data_t *resp_data = user_data;
BT_DBG("+");
- user_info = _bt_get_user_data(BT_COMMON);
- system_gconn = _bt_gdbus_get_system_gconn();
+ system_gconn = _bt_get_system_private_conn();
value = g_dbus_connection_call_finish(system_gconn, res, &error);
- if (error) {
- BT_ERR("Error : %s \n", error->message);
- if (g_strrstr(error->message, "Not paired"))
- ret = BLUETOOTH_ERROR_NOT_PAIRED;
- else
- ret = BLUETOOTH_ERROR_INTERNAL;
+ user_info = _bt_get_user_data(BT_COMMON);
+ if (!user_info) {
+ if (error) {
+ BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
+ g_clear_error(&error);
+ g_free(resp_data);
+ return;
+ }
+ g_free(resp_data);
+ g_variant_unref(value);
+ return;
+ }
+ if (error) {
+ att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
g_clear_error(&error);
- if (user_info) {
- _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
- ret, NULL,
- user_info->cb, user_info->user_data);
- }
- g_free(user_data);
+
+ _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
+ att_ecode, resp_data,
+ user_info->cb, user_info->user_data);
+ g_free(resp_data);
return;
}
- char_value.char_handle = user_data;
gp_byte_array = g_byte_array_new();
g_variant_get(value, "(ay)", &iter);
g_byte_array_append(gp_byte_array, &g_byte, 1);
if (gp_byte_array->len != 0) {
- char_value.val_len = gp_byte_array->len;
- char_value.char_value = gp_byte_array->data;
+ resp_data->len = gp_byte_array->len;
+ resp_data->value = gp_byte_array->data;
}
- if (user_info) {
- _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
- BLUETOOTH_ERROR_NONE, &char_value,
- user_info->cb, user_info->user_data);
- }
+ _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
+ BLUETOOTH_ATT_ERROR_NONE, resp_data,
+ user_info->cb, user_info->user_data);
+ g_free(resp_data);
- g_free(char_value.char_handle);
g_byte_array_free(gp_byte_array, TRUE);
- g_variant_unref(value);
g_variant_iter_free(iter);
+ g_variant_unref(value);
BT_DBG("-");
}
-BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
+BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *chr,
+ gpointer user_data)
{
GDBusConnection *conn;
- char *handle;
+ bt_gatt_resp_data_t *resp_data;
GVariantBuilder *builder = NULL;
guint16 offset = 0;
- BT_CHECK_PARAMETER(characteristic, return);
+ BT_CHECK_PARAMETER(chr, return);
BT_CHECK_ENABLED(return);
- conn = _bt_gdbus_get_system_gconn();
+ conn = _bt_get_system_private_conn();
retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
- handle = g_strdup(characteristic);
+ resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
+ resp_data->user_data = user_data;
+ resp_data->handle = (char *)chr;
builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
g_variant_new("q", offset));
/* Device Object path*/
-// g_variant_builder_add(builder, "{sv}", "device",
-// g_variant_new_object("o", NULL));
+// g_variant_builder_add(builder, "{sv}", "device",
+// g_variant_new_object("o", NULL));
- g_dbus_connection_call(conn,
- BT_BLUEZ_NAME,
- characteristic,
- GATT_CHAR_INTERFACE,
- "ReadValue",
- g_variant_new("(a{sv})", builder),
- G_VARIANT_TYPE("(ay)"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
+ g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
+ "ReadValue", g_variant_new("(a{sv})", builder),
+ G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
(GAsyncReadyCallback)__bluetooth_internal_read_cb,
- (gpointer)handle);
+ (gpointer)resp_data);
g_variant_builder_unref(builder);
return BLUETOOTH_ERROR_NONE;
}
+static void __bluetooth_internal_write_cb(GObject *source_object,
+ GAsyncResult *res, gpointer user_data)
+{
+ GError *error = NULL;
+ GDBusConnection *system_gconn = NULL;
+ bt_user_info_t *user_info;
+ GVariant *value;
+ int att_ecode = 0;
+ bt_gatt_resp_data_t *resp_data = user_data;
+
+ system_gconn = _bt_get_system_private_conn();
+ value = g_dbus_connection_call_finish(system_gconn, res, &error);
+
+ user_info = _bt_get_user_data(BT_COMMON);
+ if (!user_info) {
+ if (error) {
+ BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
+ g_clear_error(&error);
+ g_free(resp_data);
+ return;
+ }
+ g_free(resp_data);
+ g_variant_unref(value);
+ return;
+ }
+
+ if (error) {
+ att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
+ g_clear_error(&error);
+
+ _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
+ att_ecode, resp_data,
+ user_info->cb, user_info->user_data);
+ g_free(resp_data);
+ return;
+ }
+
+ _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
+ BLUETOOTH_ATT_ERROR_NONE, resp_data,
+ user_info->cb, user_info->user_data);
+ g_free(resp_data);
+
+ g_variant_unref(value);
+ return;
+}
+
BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
const char *char_handle, const guint8 *value, int length)
{
retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
BT_CHECK_ENABLED(return);
- conn = _bt_gdbus_get_system_gconn();
+ conn = _bt_get_system_private_conn();
retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
g_variant_new_uint16(offset));
/* Device Object path*/
-// g_variant_builder_add(builder2, "{sv}", "device",
-// g_variant_new_object("o", NULL));
+// g_variant_builder_add(builder2, "{sv}", "device",
+// g_variant_new_object("o", NULL));
options = g_variant_new("a{sv}", builder2);
- g_dbus_connection_call_sync(conn,
- BT_BLUEZ_NAME,
- char_handle,
- GATT_CHAR_INTERFACE,
- "WriteValue",
- g_variant_new("(@ay@a{sv})", val, options),
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
+ g_dbus_connection_call(conn,
+ BT_BLUEZ_NAME,
+ char_handle,
+ GATT_CHAR_INTERFACE,
+ "WriteValue",
+ g_variant_new("(@ay@a{sv})",
+ val, options),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL,
+ (GAsyncReadyCallback)__bluetooth_internal_write_cb,
+ NULL);
+
if (error) {
BT_ERR("Set value Failed: %s", error->message);
return BLUETOOTH_ERROR_NONE;
}
-static void __bluetooth_internal_write_cb(GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- GError *error = NULL;
- bt_user_info_t *user_info;
- GDBusConnection *system_gconn = NULL;
- GVariant *value;
- int result = BLUETOOTH_ERROR_NONE;
- guint8 att_ecode = 0;
-
- user_info = _bt_get_user_data(BT_COMMON);
-
- system_gconn = _bt_gdbus_get_system_gconn();
- value = g_dbus_connection_call_finish(system_gconn, res, &error);
-
- if (error) {
- BT_ERR("Error : %s \n", error->message);
- g_clear_error(&error);
- result = BLUETOOTH_ERROR_INTERNAL;
- } else {
- g_variant_get(value, "(y)", &att_ecode);
- if (att_ecode) {
- result = att_ecode;
- BT_ERR("ATT Error code: %d \n", att_ecode);
- }
- }
-
- if (user_info) {
- _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
- result, NULL,
- user_info->cb, user_info->user_data);
- } else {
- BT_ERR("user info is null");
- }
-
- if (value)
- g_variant_unref(value);
-
- return;
-}
-
BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
- const char *char_handle, const guint8 *value, int length, guint8 write_type)
+ const char *chr, const guint8 *value, int length,
+ guint8 write_type, gpointer user_data)
{
GVariant *val, *options;
GVariantBuilder *builder1;
guint16 offset = 0;
int i = 0;
int ret = BLUETOOTH_ERROR_NONE;
+ bt_gatt_resp_data_t *resp_data;
- BT_CHECK_PARAMETER(char_handle, return);
+ BT_CHECK_PARAMETER(chr, return);
BT_CHECK_PARAMETER(value, return);
retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
BT_CHECK_ENABLED_INTERNAL(return);
- conn = _bt_gdbus_get_system_gconn();
+ conn = _bt_get_system_private_conn();
retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
g_variant_new_uint16(offset));
/* Device Object path*/
-// g_variant_builder_add(builder2, "{sv}", "device",
-// g_variant_new_object("o", NULL));
+// g_variant_builder_add(builder2, "{sv}", "device",
+// g_variant_new_object("o", NULL));
options = g_variant_new("a{sv}", builder2);
- g_dbus_connection_call(conn,
- BT_BLUEZ_NAME,
- char_handle,
- GATT_CHAR_INTERFACE,
+ resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
+ resp_data->user_data = user_data;
+ resp_data->handle = (char *)chr;
+
+ g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
"WriteValuebyType",
- g_variant_new("(y@ay@a{sv})",
- write_type, val, options),
- G_VARIANT_TYPE("(y)"),
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL,
+ g_variant_new("(y@ay@a{sv})", write_type, val, options),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
(GAsyncReadyCallback)__bluetooth_internal_write_cb,
- NULL);
+ (gpointer)resp_data);
g_variant_builder_unref(builder1);
g_variant_builder_unref(builder2);
+
return ret;
}
retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
BT_CHECK_ENABLED(return);
- conn = _bt_gdbus_get_system_gconn();
+ conn = _bt_get_system_private_conn();
retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
g_variant_new_uint16(offset));
/* Device Object path*/
-// g_variant_builder_add(builder2, "{sv}", "device",
-// g_variant_new_object("o", NULL));
+// g_variant_builder_add(builder2, "{sv}", "device",
+// g_variant_new_object("o", NULL));
options = g_variant_new("a{sv}", builder2);
const gchar *key;
char_descriptor_type_t desc_type = TYPE_NONE;
- g_conn = _bt_gdbus_get_system_gconn();
+ g_conn = _bt_get_system_private_conn();
retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
properties_proxy = g_dbus_proxy_new_sync(g_conn,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
BT_BLUEZ_NAME,
char_handle,
BT_PROPERTIES_INTERFACE,
user_info = _bt_get_user_data(BT_COMMON);
value = g_dbus_proxy_call_finish(proxy, res, &error);
+ characteristic.handle = user_data;
if (value == NULL) {
if (error != NULL) {
BLUETOOTH_ERROR_INTERNAL, NULL,
user_info->cb, user_info->user_data);
}
- g_free(user_data);
+ g_free(characteristic.handle);
g_object_unref(proxy);
return;
}
}
}
- characteristic.handle = user_data;
if (user_info) {
_bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
ret, &characteristic, user_info->cb, user_info->user_data);
g_variant_iter_free(char_iter);
g_variant_unref(value);
+ g_variant_unref(char_value);
BT_DBG("-");
}
-BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
+BT_EXPORT_API int bltooth_gatt_discover_characteristic_descriptor(
const char *characteristic_handle)
{
GDBusProxy *properties_proxy = NULL;
BT_CHECK_PARAMETER(characteristic_handle, return);
BT_CHECK_ENABLED(return);
- g_conn = _bt_gdbus_get_system_gconn();
+ g_conn = _bt_get_system_private_conn();
retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
properties_proxy = g_dbus_proxy_new_sync(g_conn,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
BT_BLUEZ_NAME,
characteristic_handle,
BT_PROPERTIES_INTERFACE,
gpointer user_data)
{
GError *error = NULL;
- bt_user_info_t *user_info;
- bt_gatt_char_property_t char_value = { 0, };
GDBusConnection *system_gconn = NULL;
GVariant *value;
+ bt_user_info_t *user_info;
GByteArray *gp_byte_array = NULL;
GVariantIter *iter;
guint8 g_byte;
+ int att_ecode = 0;
+ bt_gatt_resp_data_t *resp_data = user_data;
BT_DBG("+");
- user_info = _bt_get_user_data(BT_COMMON);
- system_gconn = _bt_gdbus_get_system_gconn();
- char_value.handle = user_data;
+ system_gconn = _bt_get_system_private_conn();
value = g_dbus_connection_call_finish(system_gconn, res, &error);
+ user_info = _bt_get_user_data(BT_COMMON);
+ if (!user_info) {
+ if (error) {
+ BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
+ g_clear_error(&error);
+ g_free(resp_data);
+ return;
+ }
+ g_free(resp_data);
+ g_variant_unref(value);
+ return;
+ }
+
if (error) {
- BT_ERR("Error : %s \n", error->message);
+ att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
g_clear_error(&error);
- if (user_info) {
- _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
- BLUETOOTH_ERROR_INTERNAL, NULL,
- user_info->cb, user_info->user_data);
- }
- g_free(char_value.handle);
+
+ _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
+ att_ecode, resp_data,
+ user_info->cb, user_info->user_data);
+ g_free(resp_data);
return;
}
gp_byte_array = g_byte_array_new();
g_variant_get(value, "(ay)", &iter);
- while (g_variant_iter_loop(iter, "y", &g_byte))
+ while (g_variant_iter_loop(iter, "y", &g_byte))
g_byte_array_append(gp_byte_array, &g_byte, 1);
if (gp_byte_array->len != 0) {
- char_value.val_len = (unsigned int)gp_byte_array->len;
- char_value.description = (char *)gp_byte_array->data;
+ resp_data->len = gp_byte_array->len;
+ resp_data->value = gp_byte_array->data;
}
- if (user_info) {
- _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
- BLUETOOTH_ERROR_NONE, &char_value,
- user_info->cb, user_info->user_data);
- }
+ _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
+ BLUETOOTH_ATT_ERROR_NONE, resp_data,
+ user_info->cb, user_info->user_data);
+ g_free(resp_data);
+
g_byte_array_free(gp_byte_array, TRUE);
- g_free(char_value.handle);
- g_variant_unref(value);
g_variant_iter_free(iter);
+ g_variant_unref(value);
BT_DBG("-");
}
-BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
+BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *desc,
+ gpointer user_data)
{
GDBusConnection *conn;
GVariantBuilder *builder;
guint offset = 0;
- char *handle;
+ bt_gatt_resp_data_t *resp_data;
BT_DBG("+");
- BT_CHECK_PARAMETER(char_descriptor, return);
+
+ BT_CHECK_PARAMETER(desc, return);
BT_CHECK_ENABLED(return);
- conn = _bt_gdbus_get_system_gconn();
+ conn = _bt_get_system_private_conn();
retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
- handle = g_strdup(char_descriptor);
+ resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
+ resp_data->user_data = user_data;
+ resp_data->handle = (char *)desc;
builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
// g_variant_builder_add(builder, "{sv}", "device",
// g_variant_new("o", serv_info->serv_path));
- g_dbus_connection_call(conn,
- BT_BLUEZ_NAME,
- char_descriptor,
- GATT_DESC_INTERFACE,
- "ReadValue",
- g_variant_new("(a{sv})", builder),
+ g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
+ "ReadValue", g_variant_new("(a{sv})", builder),
G_VARIANT_TYPE("(ay)"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
(GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
- (gpointer)handle);
+ (gpointer)resp_data);
g_variant_builder_unref(builder);
BT_DBG("-");
}
static void __bluetooth_internal_write_desc_cb(GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
+ GAsyncResult *res, gpointer user_data)
{
GError *error = NULL;
bt_user_info_t *user_info;
GDBusConnection *system_gconn = NULL;
GVariant *value;
- int result = BLUETOOTH_ERROR_NONE;
- guint8 att_ecode = 0;
+ int att_ecode = BLUETOOTH_ATT_ERROR_NONE;
+ bt_gatt_resp_data_t *resp_data = user_data;
BT_DBG("+");
- user_info = _bt_get_user_data(BT_COMMON);
- system_gconn = _bt_gdbus_get_system_gconn();
+ system_gconn = _bt_get_system_private_conn();
value = g_dbus_connection_call_finish(system_gconn, res, &error);
- if (error) {
- BT_ERR("Error : %s \n", error->message);
- g_clear_error(&error);
- result = BLUETOOTH_ERROR_INTERNAL;
- } else {
- g_variant_get(value, "(y)", &att_ecode);
- if (att_ecode) {
- result = att_ecode;
- BT_ERR("ATT Error code: %d \n", att_ecode);
+ user_info = _bt_get_user_data(BT_COMMON);
+ if (!user_info) {
+ if (error) {
+ BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
+ g_clear_error(&error);
+ g_free(resp_data);
+ return;
}
+ g_free(resp_data);
+ g_variant_unref(value);
+ return;
}
- if (user_info) {
+ if (error) {
+ att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
+ g_clear_error(&error);
+
_bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
- result, NULL,
+ att_ecode, resp_data,
user_info->cb, user_info->user_data);
+ g_free(resp_data);
+ return;
}
- if (value)
- g_variant_unref(value);
+ _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
+ BLUETOOTH_ATT_ERROR_NONE, resp_data,
+ user_info->cb, user_info->user_data);
+ g_free(resp_data);
+ g_variant_unref(value);
BT_DBG("-");
}
-BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
- const char *desc_handle, const guint8 *value, int length)
+BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(const char *desc,
+ const guint8 *value, int length, gpointer user_data)
{
GVariant *val, *options;
GDBusConnection *conn;
GVariantBuilder *builder2;
guint offset = 0;
int i;
+ bt_gatt_resp_data_t *resp_data;
BT_DBG("+");
- BT_CHECK_PARAMETER(desc_handle, return);
+
+ BT_CHECK_PARAMETER(desc, return);
BT_CHECK_PARAMETER(value, return);
retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
BT_CHECK_ENABLED(return);
- conn = _bt_gdbus_get_system_gconn();
+ conn = _bt_get_system_private_conn();
retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
g_variant_new_uint16(offset));
/* Device Object path*/
-// g_variant_builder_add(builder2, "{sv}", "device",
-// g_variant_new_object("o", NULL));
+// g_variant_builder_add(builder2, "{sv}", "device",
+// g_variant_new_object("o", NULL));
options = g_variant_new("a{sv}", builder2);
- g_dbus_connection_call(conn,
- BT_BLUEZ_NAME,
- desc_handle,
- GATT_DESC_INTERFACE,
- "WriteValue",
- g_variant_new("(@ay@a{sv})",
- val, options),
- G_VARIANT_TYPE("(y)"),
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL,
- (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
- NULL);
+ resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
+ resp_data->user_data = user_data;
+ resp_data->handle = (char *)desc;
+
+ g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
+ "WriteValue", g_variant_new("(@ay@a{sv})",
+ val, options), NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+ (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
+ (gpointer)resp_data);
g_variant_builder_unref(builder1);
g_variant_builder_unref(builder2);
return BLUETOOTH_ERROR_NONE;
}
-BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
+BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle, const char *svc_name)
{
GDBusConnection *conn;
GError *error = NULL;
BT_CHECK_PARAMETER(char_handle, return);
BT_CHECK_ENABLED(return);
- BT_INFO_C("### Enable CCCD : %s", char_handle);
+ BT_INFO_C("### Enable CCCD : %s [%s]", char_handle + 15, svc_name);
- conn = _bt_gdbus_get_system_gconn();
+ conn = _bt_get_system_private_conn();
retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
g_dbus_connection_call_sync(conn,
BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
{
-
GDBusConnection *conn;
GError *error = NULL;
int ret = BLUETOOTH_ERROR_NONE;
BT_INFO("Disable CCCD : %s", char_handle);
- conn = _bt_gdbus_get_system_gconn();
+ conn = _bt_get_system_private_conn();
retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
g_dbus_connection_call_sync(conn,
return ret;
}
+
+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;
+
+ if (props->count == 0)
+ return;
+
+ svcs->count = props->count;
+
+ for (count = 0; count < props->count; count++) {
+ BT_DBG("[%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];
+
+ 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_DBG("[%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];
+
+ 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_DBG("[%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;
+ __convert_permission_flag_to_str(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_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_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);
+ 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_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);
+ 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_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);
+
+ 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);
+ 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_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 */
+}
+
+
+static gboolean bluetooth_gatt_client_notify_channel_watch_cb(GIOChannel *gio,
+ GIOCondition cond, gpointer data)
+{
+ bt_gatt_characteristic_notify_info_t *chr_info = (bt_gatt_characteristic_notify_info_t *)data;
+
+ if (!chr_info) {
+ BT_ERR("chr_info is invalid");
+ return FALSE;
+ }
+ if (cond & G_IO_IN) {
+ GIOStatus status = G_IO_STATUS_NORMAL;
+ GError *err = NULL;
+ char *buffer = NULL;
+ gsize len = 0;
+ bt_event_info_t *event_info;
+
+ buffer = g_malloc0(chr_info->mtu + 1);
+ memset(buffer, 0, chr_info->mtu + 1);
+
+ status = g_io_channel_read_chars(gio, buffer,
+ chr_info->mtu, &len, &err);
+ if (status != G_IO_STATUS_NORMAL) {
+ BT_ERR("IO Channel read is failed with %d", status);
+ g_free(buffer);
+ if (err) {
+ BT_ERR("IO Channel read error [%s]", err->message);
+ if (status == G_IO_STATUS_ERROR) {
+ BT_ERR("cond : %d", cond);
+ g_error_free(err);
+ g_io_channel_shutdown(gio, TRUE, NULL);
+ g_io_channel_unref(gio);
+
+ gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
+ g_free(chr_info);
+ return FALSE;
+ }
+ g_error_free(err);
+ }
+ return FALSE;
+ }
+
+ if (len > 0 && len < chr_info->mtu) {
+ bt_gatt_char_property_t char_val;
+// BT_DBG("FD io sending value changed %x %x %x %x %x %x %x %zd \n", buffer[0], buffer[1], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], len);
+
+ memcpy(char_val.prop.uuid, chr_info->UUID, 16);
+ memcpy(char_val.value, buffer, len);
+ char_val.val_len = len;
+ memcpy(char_val.address, chr_info->address, 18);
+
+ event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
+ if (event_info) {
+ _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
+ BLUETOOTH_ERROR_NONE, &char_val,
+ event_info->cb, event_info->user_data);
+ } else {
+ BT_ERR("event_info failed");
+ }
+
+ } else
+ BT_ERR("Packet corrupted");
+
+ g_free(buffer);
+
+ return TRUE;
+ }
+
+ if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
+ BT_ERR("Error : GIOCondition %d, [%s]", cond, chr_info->UUID);
+ g_io_channel_shutdown(gio, TRUE, NULL);
+ g_io_channel_unref(gio);
+
+ gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
+ g_free(chr_info);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#ifndef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
+static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_get_characteristic_notify_info(unsigned char *handle , int id)
+{
+ GSList *l;
+
+ for (l = gatt_characteristic_notify_list; l != NULL; l = l->next) {
+ bt_gatt_characteristic_notify_info_t *info = l->data;
+ if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
+ return info;
+ }
+ return NULL;
+}
+#endif
+
+static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_create_watch_io(int fd, int id, int mtu, char * address, unsigned char *uuid)
+{
+ GIOChannel *channel;
+ bt_gatt_characteristic_notify_info_t *chr_info;
+
+ chr_info = g_malloc0(sizeof(bt_gatt_characteristic_notify_info_t));
+ chr_info->notify_fd = fd;
+ chr_info->id = id;
+ chr_info->mtu = mtu;
+ g_strlcpy(chr_info->address, address, 18);
+ memcpy(chr_info->UUID, uuid, 16);
+
+ channel = g_io_channel_unix_new(fd);
+
+ chr_info->io_channel = channel;
+
+ g_io_channel_set_encoding(channel, NULL, NULL);
+ g_io_channel_set_buffered(channel, FALSE);
+ g_io_channel_set_close_on_unref(channel, TRUE);
+ g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
+
+ chr_info->watch_id = g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
+ bluetooth_gatt_client_notify_channel_watch_cb, chr_info);
+
+ return chr_info;
+
+}
+
+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,
+ gboolean is_indicate)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ bluetooth_gatt_client_char_prop_info_t param;
+ bt_gatt_characteristic_notify_info_t *chr_info;
+
+ BT_CHECK_PARAMETER(address, return);
+ BT_CHECK_PARAMETER(service_handle, return);
+ BT_CHECK_PARAMETER(char_handle, return);
+
+#ifndef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
+ chr_info = bluetooth_gatt_client_get_characteristic_notify_info(char_handle->uuid , char_handle->instance_id);
+ if (chr_info && !is_notify) {
+ BT_INFO("Already CCCD enabled. fd %d", chr_info->notify_fd);
+
+ if (chr_info->watch_id > 0)
+ g_source_remove(chr_info->watch_id);
+
+ if (chr_info->io_channel) {
+ g_io_channel_shutdown(chr_info->io_channel, TRUE, NULL);
+ g_io_channel_unref(chr_info->io_channel);
+ }
+
+ gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
+
+ g_free(chr_info);
+
+ return result;
+ }
+#endif
+
+ /* 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);
+
+ 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));
+ g_array_append_vals(in_param4, &is_indicate, sizeof(gboolean));
+
+#ifdef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
+ 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;
+#endif
+
+ GUnixFDList *out_fd_list = NULL;
+ char *svc_name = NULL;
+ char str_uuid[37];
+
+ _bt_convert_uuid_type_to_string(str_uuid, param.svc.uuid);
+ bluetooth_get_uuid_name(str_uuid, &svc_name);
+
+ _bt_convert_uuid_type_to_string(str_uuid, param.characteristic.uuid);
+
+ BT_INFO_C("### Request subscription Notify : %s [%s]", str_uuid, svc_name);
+ g_free(svc_name);
+
+ result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_WATCH_CHARACTERISTIC,
+ in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
+ if (result != BLUETOOTH_ERROR_NONE) {
+ BT_ERR("Fail to get Nofify FD. result %d", result);
+ BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+ return result;
+ }
+
+ if (is_indicate == false) {
+ if (NULL == out_fd_list) {
+ BT_ERR("out_fd_list is NULL");
+ result = BLUETOOTH_ERROR_INTERNAL;
+ } else {
+ int *fd_list_array;
+ int len = 0;
+ int mtu;
+ int fd = -1;
+
+ fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
+ BT_DBG("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
+ fd = fd_list_array[0];
+ mtu = g_array_index(out_param, int, 0);
+
+ BT_INFO("Acquired characteristic Notify FD %d, mtu %d", fd, mtu);
+ chr_info = bluetooth_gatt_client_create_watch_io(fd, char_handle->instance_id, mtu, (char *)address, char_handle->uuid);
+
+ gatt_characteristic_notify_list = g_slist_append(gatt_characteristic_notify_list, chr_info);
+
+ g_free(fd_list_array);
+ g_object_unref(out_fd_list);
+ }
+ }
+
+ /*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);
+
+ 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_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_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_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_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+ return result;
+}
+
+
+static bt_gatt_characteristic_write_info_t * bluetooth_gatt_client_get_characteristic_fd(unsigned char *handle, int id)
+{
+ GSList *l;
+ char str[37];
+
+ for (l = gatt_characteristic_write_list; l != NULL; l = l->next) {
+ bt_gatt_characteristic_write_info_t *info = l->data;
+
+ if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
+ return info;
+ }
+
+ _bt_convert_uuid_type_to_string(str, handle);
+ BT_ERR("Unable to get characteristic fd. [%s] id [ %d]", str, id);
+ return NULL;
+}
+
+static gboolean bluetooth_gatt_client_write_channel_watch_cb(GIOChannel *gio,
+ GIOCondition cond, gpointer data)
+{
+ bt_gatt_characteristic_write_info_t *chr_info = (bt_gatt_characteristic_write_info_t *)data;
+
+ if (!chr_info)
+ return FALSE;
+
+ if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
+ char uuid_str[37];
+ _bt_convert_uuid_type_to_string(uuid_str, chr_info->UUID);
+ BT_ERR("Error : GIOCondition %d, [%s]", cond, uuid_str);
+ g_io_channel_shutdown(gio, TRUE, NULL);
+ g_io_channel_unref(gio);
+
+ gatt_characteristic_write_list = g_slist_remove(gatt_characteristic_write_list, chr_info);
+ g_free(chr_info);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int bluetooth_gatt_client_write_characteristics_value_to_fd(
+ int fd, const guint8 *value, int length, int mtu,
+ gpointer user_data)
+{
+ int written;
+ int att_result = BLUETOOTH_ERROR_NONE;
+ BT_CHECK_PARAMETER(value, return);
+ written = write(fd, value, length);
+ if (written != length) {
+ att_result = BLUETOOTH_ERROR_INTERNAL;
+ BT_ERR("write data failed. ret : %d ", written);
+ }
+
+ return att_result;
+}
+
+static void bluetooth_gatt_client_create_write_io_channel(int fd, unsigned char * uuid, int id, int mtu)
+{
+ bt_gatt_characteristic_write_info_t *chr_info;
+ GIOChannel *channel;
+
+ chr_info = g_malloc0(sizeof(bt_gatt_characteristic_write_info_t));
+ chr_info->write_fd = fd;
+ chr_info->id = id;
+ chr_info->mtu = mtu;
+
+ memcpy(chr_info->UUID, uuid, 16);
+ channel = g_io_channel_unix_new(fd);
+ g_io_channel_set_encoding(channel, NULL, NULL);
+ g_io_channel_set_buffered(channel, FALSE);
+ g_io_channel_set_close_on_unref(channel, TRUE);
+ g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_add_watch(channel, (G_IO_ERR | G_IO_HUP | G_IO_NVAL),
+ bluetooth_gatt_client_write_channel_watch_cb, chr_info);
+
+ gatt_characteristic_write_list = g_slist_append(gatt_characteristic_write_list, chr_info);
+
+}
+
+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_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));
+
+#ifdef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
+ goto done;
+#endif
+
+ if (write_type == BLUETOOTH_GATT_TYPE_WRITE_NO_RESPONSE) {
+ int fd = -1;
+ int mtu = 0;
+ bt_gatt_characteristic_write_info_t *info;
+ info = bluetooth_gatt_client_get_characteristic_fd(char_handle->uuid, service_handle->instance_id);
+
+ if (info) {
+ fd = info->write_fd;
+ mtu = info->mtu;
+ }
+
+ if (fd < 0) {
+
+ GUnixFDList *out_fd_list = NULL;
+
+ result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_ACQUIRE_WRITE,
+ in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
+
+ mtu = g_array_index(out_param, int, 0);
+
+ if (result != BLUETOOTH_ERROR_NONE) {
+ BT_ERR("Fail to get Write FD. result %d", result);
+ BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+ return result;
+ } else if (NULL == out_fd_list) {
+ BT_ERR("out_fd_list is NULL");
+ BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+ return BLUETOOTH_ERROR_INTERNAL;
+ } else {
+ int *fd_list_array;
+ int len = 0;
+
+ fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
+ fd = fd_list_array[0];
+
+ g_free(fd_list_array);
+ g_object_unref(out_fd_list);
+ }
+ BT_INFO("Acquired characteristic Write FD %d, mtu %d", fd, mtu);
+
+ if (fd > -1) {
+ bluetooth_gatt_client_create_write_io_channel(fd, char_handle->uuid, service_handle->instance_id, mtu);
+
+ result = bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
+
+ } else {
+ BT_ERR("characteristic info FD is invalid");
+ goto done;
+ }
+
+ } else {
+ result = bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
+ }
+
+ } else {
+done:
+ 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_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 device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+ char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+ int result = BLUETOOTH_ERROR_NONE;
+
+ 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_type_to_string(device_address, (unsigned char *)address->addr);
+ _bt_convert_addr_string_to_secure_string(secure_address, device_address);
+ BT_INFO("%s watcher for [%s]", enable ? "Set":"Unset", secure_address);
+
+ if (enable == TRUE) {
+ if (_bluetooth_gatt_check_service_change_watcher_address(address)
+ == TRUE) {
+ BT_INFO("The watcher is already set");
+ goto done;
+ }
+
+ 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);
+
+ }
+ }
+
+done:
+ 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_ERR("GATT Client Unregistration failed result [%d]", result);
+
+ /* 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_DBG("Total num of GATT client instances [%d]", *count);
+
+ if (*count == 1) {
+ BT_DBG("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;
+}