2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <glib/gprintf.h>
24 #include <gio/gunixfdlist.h>
26 #include "bt-common.h"
27 #include "bt-event-handler.h"
28 #include "bt-gatt-client.h"
29 #include "bt-internal-types.h"
30 #include "bt-request-sender.h"
32 #include "bluetooth-gatt-client-api.h"
33 #include <arpa/inet.h>
34 static GSList *gatt_characteristic_notify_list;
35 static GSList *gatt_characteristic_write_list = NULL;;
37 #define GATT_DEFAULT_TIMEOUT (6 * 1000) // Dependent on supervision timeout 6 sec
45 } char_descriptor_type_t;
47 static GSList *service_monitor_list = NULL;
49 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
51 BT_CHECK_PARAMETER(svc_pty, return);
53 g_free(svc_pty->uuid);
55 memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
57 return BLUETOOTH_ERROR_NONE;
60 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
62 BT_CHECK_PARAMETER(char_pty, return);
64 g_free(char_pty->uuid);
65 g_free(char_pty->name);
66 g_free(char_pty->description);
67 g_free(char_pty->val);
69 memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
71 return BLUETOOTH_ERROR_NONE;
74 BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty)
76 BT_CHECK_PARAMETER(desc_pty, return);
78 g_free(desc_pty->uuid);
79 g_free(desc_pty->val);
81 memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t));
83 return BLUETOOTH_ERROR_NONE;
86 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
88 gchar *gp_path = NULL;
95 path = g_malloc0((gp->len + 1) * sizeof(char *));
97 for (i = 0; i < gp->len; i++) {
98 gp_path = g_ptr_array_index(gp, i);
99 path[i] = g_strdup(gp_path);
100 // BT_DBG("path[%d] : [%s]", i, path[i]);
106 gboolean _bluetooth_gatt_check_service_change_watcher_address(
107 const bluetooth_device_address_t *device_addr)
110 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
112 _bt_convert_addr_type_to_string(device_address,
113 (unsigned char *)device_addr->addr);
115 for (l = service_monitor_list; l != NULL; l = l->next) {
116 char device_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
117 bluetooth_device_address_t *addr = l->data;
119 _bt_convert_addr_type_to_string(device_address2,
120 (unsigned char *)addr->addr);
122 if (!memcmp(device_addr, addr,
123 sizeof(bluetooth_device_address_t)))
130 BT_EXPORT_API int bluetooth_gatt_set_service_change_watcher(
131 const bluetooth_device_address_t *address, gboolean enable)
134 bluetooth_device_address_t *addr = NULL;
135 char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
137 _bt_convert_addr_type_to_secure_string(secure_address, (unsigned char *)address->addr);
138 BT_INFO("Set watcher for %s with %d", secure_address, enable);
140 if (enable == TRUE) {
141 if (_bluetooth_gatt_check_service_change_watcher_address(address)
143 BT_INFO("The watcher is already set");
144 return BLUETOOTH_ERROR_NONE;
147 if (service_monitor_list == NULL)
148 _bt_register_manager_subscribe_signal(TRUE);
150 addr = g_malloc0(sizeof(bluetooth_device_address_t));
151 memcpy(addr, address, sizeof(bluetooth_device_address_t));
153 service_monitor_list =
154 g_slist_append(service_monitor_list, addr);
156 for (l = service_monitor_list; l != NULL; l = l->next) {
159 if (!memcmp(address, addr,
160 sizeof(bluetooth_device_address_t))) {
161 service_monitor_list =
162 g_slist_remove(service_monitor_list, addr);
168 if (service_monitor_list == NULL)
169 _bt_register_manager_subscribe_signal(FALSE);
172 return BLUETOOTH_ERROR_NONE;
175 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
176 bt_gatt_service_property_t *service)
178 GDBusProxy *properties_proxy = NULL;
179 GError *error = NULL;
180 GVariant *result = NULL;
181 GDBusConnection *g_conn;
183 char *char_handle = NULL;
184 GPtrArray *gp_array = NULL ;
185 GVariantIter *property_iter, *char_iter = NULL;
189 BT_CHECK_PARAMETER(service_handle, return);
190 BT_CHECK_PARAMETER(service, return);
191 BT_CHECK_ENABLED(return);
193 g_conn = _bt_get_system_common_conn();
194 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
196 properties_proxy = g_dbus_proxy_new_sync(g_conn,
197 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
200 BT_PROPERTIES_INTERFACE,
203 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
205 result = g_dbus_proxy_call_sync(properties_proxy,
207 g_variant_new("(s)", GATT_SERV_INTERFACE),
208 G_DBUS_CALL_FLAGS_NONE,
215 BT_ERR("Fail to get properties (Error: %s)", error->message);
216 g_clear_error(&error);
218 BT_ERR("Fail to get properties");
219 g_object_unref(properties_proxy);
220 return BLUETOOTH_ERROR_INTERNAL;
223 g_variant_get(result, "(a{sv})", &property_iter);
225 memset(service, 0, sizeof(bt_gatt_service_property_t));
227 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
228 if (!g_strcmp0(key, "UUID")) {
230 service->uuid = g_variant_dup_string(value, &len);
231 bluetooth_get_uuid_name(service->uuid, &name);
232 BT_INFO("%s %s [%s]", service_handle + 37, service->uuid, name);
234 } else if (!g_strcmp0(key, "Primary")) {
235 service->primary = g_variant_get_boolean(value);
237 } else if (!g_strcmp0(key, "Includes")) {
238 g_variant_get(value, "ao", &char_iter);
239 if (char_iter != NULL) {
240 gp_array = g_ptr_array_new();
241 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
242 g_ptr_array_add(gp_array, (gpointer)char_handle);
244 if (gp_array->len != 0) {
245 service->include_handles.count = gp_array->len;
246 service->include_handles.handle =
247 __get_string_array_from_gptr_array(gp_array);
249 g_ptr_array_free(gp_array, TRUE);
250 g_variant_iter_free(char_iter);
252 } else if (!g_strcmp0(key, "Characteristics")) {
253 g_variant_get(value, "ao", &char_iter);
254 if (char_iter != NULL) {
255 gp_array = g_ptr_array_new();
256 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
257 g_ptr_array_add(gp_array, (gpointer)char_handle);
259 if (gp_array->len != 0) {
260 service->char_handle.count = gp_array->len;
261 service->char_handle.handle =
262 __get_string_array_from_gptr_array(gp_array);
264 g_ptr_array_free(gp_array, TRUE);
265 g_variant_iter_free(char_iter);
267 BT_DBG("Characteristics count : %d", service->char_handle.count);
271 service->handle = g_strdup(service_handle);
273 g_variant_iter_free(property_iter);
274 g_variant_unref(result);
275 g_object_unref(properties_proxy);
277 return BLUETOOTH_ERROR_NONE;
280 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
281 const bluetooth_device_address_t *address,
282 bt_gatt_handle_info_t *prim_svc)
284 GVariant *result = NULL;
286 GVariantIter *svc_iter;
287 GVariantIter *interface_iter;
288 char *object_path = NULL;
289 char *interface_str = NULL;
290 const gchar *key = NULL;
291 GVariant *value = NULL;
292 GPtrArray *gp_array = NULL;
293 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
294 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
295 int ret = BLUETOOTH_ERROR_INTERNAL;
299 BT_CHECK_PARAMETER(address, return);
300 BT_CHECK_PARAMETER(prim_svc, return);
301 BT_CHECK_ENABLED(return);
303 result = _bt_get_managed_objects();
307 _bt_convert_addr_type_to_string(device_address,
308 (unsigned char *)address->addr);
310 gp_array = g_ptr_array_new();
311 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
313 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
315 if (object_path == NULL)
318 _bt_convert_device_path_to_address(object_path, temp_address);
320 if (g_strcmp0(temp_address, device_address) != 0)
323 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
324 &interface_str, &svc_iter)) {
325 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
328 BT_DBG("[%d] Object Path : %s", idx++, object_path);
329 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
330 if (g_strcmp0(key, "Primary") == 0) {
331 if (g_variant_get_boolean(value))
332 g_ptr_array_add(gp_array, (gpointer)object_path);
338 if (gp_array->len == 0) {
339 BT_ERR("gp_array is NULL");
340 ret = BLUETOOTH_ERROR_NOT_FOUND;
342 ret = BLUETOOTH_ERROR_NONE;
343 prim_svc->count = gp_array->len;
344 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
347 g_ptr_array_free(gp_array, TRUE);
348 g_variant_iter_free(iter);
349 g_variant_unref(result);
354 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
355 const char *service_uuid,
356 bt_gatt_service_property_t *service)
358 GVariant *result = NULL;
360 GVariantIter *svc_iter;
361 GVariantIter *interface_iter;
362 char *object_path = NULL;
363 char *interface_str = NULL;
364 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
365 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
366 int ret = BLUETOOTH_ERROR_INTERNAL;
368 BT_CHECK_PARAMETER(address, return);
369 BT_CHECK_PARAMETER(service_uuid, return);
370 BT_CHECK_PARAMETER(service, return);
371 BT_CHECK_ENABLED(return);
373 result = _bt_get_managed_objects();
377 _bt_convert_addr_type_to_string(device_address,
378 (unsigned char *)address->addr);
380 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
382 while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
384 if (object_path == NULL)
387 _bt_convert_device_path_to_address(object_path,
390 if (g_strcmp0(temp_address, device_address) != 0)
393 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
394 &interface_str, &svc_iter)) {
395 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
398 BT_DBG("Object Path: %s", object_path);
399 ret = bluetooth_gatt_get_service_property(object_path,
402 if (ret != BLUETOOTH_ERROR_NONE) {
403 BT_ERR("Get service property failed(0x%08x)", ret);
405 if (service->primary == TRUE &&
406 g_strstr_len(service->uuid, -1,
408 ret = BLUETOOTH_ERROR_NONE;
410 /* release resources */
412 g_variant_iter_free(interface_iter);
413 g_free(interface_str);
414 g_variant_iter_free(svc_iter);
419 bluetooth_gatt_free_service_property(service);
424 g_variant_iter_free(iter);
425 g_variant_unref(result);
430 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
431 GAsyncResult *res, gpointer user_data)
434 GVariant *char_value;
435 GVariantIter *char_iter;
436 GPtrArray *gp_array = NULL;
437 bt_gatt_discovered_char_t svc_char = { 0, };
439 GError *error = NULL;
440 bt_user_info_t *user_info;
444 user_info = _bt_get_user_data(BT_COMMON);
445 svc_char.service_handle = user_data;
447 value = g_dbus_proxy_call_finish(proxy, res, &error);
451 BT_ERR("Get service characteristics failed\n errCode[%x],"
452 "message[%s]\n", error->code, error->message);
453 g_clear_error(&error);
455 BT_ERR("Get service characteristics failed\n");
458 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
459 BLUETOOTH_ERROR_INTERNAL, NULL,
460 user_info->cb, user_info->user_data);
462 g_free(svc_char.service_handle);
463 g_object_unref(proxy);
467 g_variant_get(value, "(v)", &char_value);
468 g_variant_get(char_value, "ao", &char_iter);
470 gp_array = g_ptr_array_new();
471 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
472 g_ptr_array_add(gp_array, (gpointer)char_handle);
474 if (gp_array->len != 0) {
475 svc_char.handle_info.count = gp_array->len;
476 svc_char.handle_info.handle =
477 __get_string_array_from_gptr_array(gp_array);
479 g_ptr_array_free(gp_array, TRUE);
482 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
483 BLUETOOTH_ERROR_NONE, &svc_char,
484 user_info->cb, user_info->user_data);
487 g_strfreev(svc_char.handle_info.handle);
488 g_free(svc_char.service_handle);
489 g_variant_iter_free(char_iter);
490 g_variant_unref(value);
491 g_object_unref(proxy);
492 g_variant_unref(char_value);
495 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
496 const char *service_handle)
498 GDBusProxy *properties_proxy = NULL;
499 GDBusConnection *g_conn;
500 GError *error = NULL;
505 BT_CHECK_PARAMETER(service_handle, return);
506 BT_CHECK_ENABLED(return);
508 g_conn = _bt_get_system_common_conn();
509 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
511 properties_proxy = g_dbus_proxy_new_sync(g_conn,
512 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
515 BT_PROPERTIES_INTERFACE,
518 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
520 handle = g_strdup(service_handle);
521 g_dbus_proxy_call(properties_proxy,
523 g_variant_new("(ss)",
524 GATT_SERV_INTERFACE, "Characteristics"),
525 G_DBUS_CALL_FLAGS_NONE,
528 (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
532 return BLUETOOTH_ERROR_NONE;
536 static int __get_permission_flag(char *permission)
540 retv_if(permission == NULL, ret);
542 if (!g_strcmp0(permission, "broadcast"))
543 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
544 else if (!g_strcmp0(permission, "read"))
545 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
546 else if (!g_strcmp0(permission, "write-without-response"))
547 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
548 else if (!g_strcmp0(permission, "write"))
549 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
550 else if (!g_strcmp0(permission, "notify"))
551 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
552 else if (!g_strcmp0(permission, "indicate"))
553 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
554 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
555 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
556 else if (!g_strcmp0(permission, "reliable-write"))
557 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
558 else if (!g_strcmp0(permission, "writable-auxiliaries"))
559 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
560 else if (!g_strcmp0(permission, "encrypt-read"))
561 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
562 else if (!g_strcmp0(permission, "encrypt-write"))
563 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
564 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
565 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
566 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
567 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
572 static void __convert_permission_flag_to_str(unsigned int permission)
574 char perm[200] = { 0, };
576 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
577 g_strlcat(perm, "broadcast ", sizeof(perm));
578 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ)
579 g_strlcat(perm, "read ", sizeof(perm));
580 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
581 g_strlcat(perm, "write-without-response ", sizeof(perm));
582 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE)
583 g_strlcat(perm, "write ", sizeof(perm));
584 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
585 g_strlcat(perm, "notify ", sizeof(perm));
586 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
587 g_strlcat(perm, "indicate ", sizeof(perm));
588 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
589 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
590 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
591 g_strlcat(perm, "reliable-write ", sizeof(perm));
592 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
593 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
594 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
595 g_strlcat(perm, "encrypt-read ", sizeof(perm));
596 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
597 g_strlcat(perm, "encrypt-write ", sizeof(perm));
598 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
599 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
600 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
601 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
603 BT_INFO("permission [0x%04x] : %s\n", permission, perm);
607 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
608 const char *char_handle, bt_gatt_char_property_t *characteristic)
610 GDBusProxy *properties_proxy = NULL;
611 GError *error = NULL;
612 GVariant *value = NULL;
613 GVariant *result = NULL;
614 GByteArray *gb_array = NULL;
615 GPtrArray *gp_array = NULL ;
616 GDBusConnection *g_conn;
620 char *char_desc_handle = NULL;
622 GVariantIter *property_iter;
623 GVariantIter *char_value_iter;
624 GVariantIter *char_perm_iter;
625 GVariantIter *char_desc_iter;
627 BT_CHECK_PARAMETER(char_handle, return);
628 BT_CHECK_PARAMETER(characteristic, return);
630 BT_CHECK_ENABLED(return);
632 g_conn = _bt_get_system_common_conn();
633 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
635 properties_proxy = g_dbus_proxy_new_sync(g_conn,
636 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
639 BT_PROPERTIES_INTERFACE,
642 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
644 result = g_dbus_proxy_call_sync(properties_proxy,
646 g_variant_new("(s)", GATT_CHAR_INTERFACE),
647 G_DBUS_CALL_FLAGS_NONE,
654 BT_ERR("Fail to get properties (Error: %s)", error->message);
655 g_clear_error(&error);
657 BT_ERR("Fail to get properties");
658 g_object_unref(properties_proxy);
659 return BLUETOOTH_ERROR_INTERNAL;
662 g_variant_get(result, "(a{sv})", &property_iter);
664 memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
665 characteristic->handle = g_strdup(char_handle);
667 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
668 if (!g_strcmp0(key, "UUID")) {
670 characteristic->uuid = g_variant_dup_string(value, &len);
671 bluetooth_get_uuid_name(characteristic->uuid, &name);
672 BT_INFO("%s %s [%s]", char_handle + 37, characteristic->uuid, name);
674 } else if (!g_strcmp0(key, "Value")) {
675 gb_array = g_byte_array_new();
676 g_variant_get(value, "ay", &char_value_iter);
677 while (g_variant_iter_loop(char_value_iter, "y", &char_value)) {
678 // BT_DBG("value of char = %d",char_value);
679 g_byte_array_append(gb_array, &char_value, 1);
681 g_variant_iter_free(char_value_iter);
683 if (gb_array->len != 0) {
684 characteristic->val = g_malloc0(gb_array->len *
685 sizeof(unsigned char));
686 memcpy(characteristic->val, gb_array->data, gb_array->len);
688 characteristic->val_len = gb_array->len;
689 g_byte_array_free(gb_array, TRUE);
690 } else if (!g_strcmp0(key, "Flags")) {
691 g_variant_get(value, "as", &char_perm_iter);
692 characteristic->permission = 0x00;
694 while (g_variant_iter_loop(char_perm_iter, "s", &permission))
695 characteristic->permission |= __get_permission_flag(permission);
696 __convert_permission_flag_to_str(characteristic->permission);
698 g_variant_iter_free(char_perm_iter);
699 } else if (!g_strcmp0(key, "Descriptors")) {
700 g_variant_get(value, "ao", &char_desc_iter);
701 gp_array = g_ptr_array_new();
702 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle))
703 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
705 g_variant_iter_free(char_desc_iter);
706 if (gp_array->len != 0) {
707 characteristic->char_desc_handle.count = gp_array->len;
708 characteristic->char_desc_handle.handle =
709 __get_string_array_from_gptr_array(gp_array);
711 g_ptr_array_free(gp_array, TRUE);
715 g_variant_iter_free(property_iter);
716 g_variant_unref(result);
717 g_object_unref(properties_proxy);
719 return BLUETOOTH_ERROR_NONE;
722 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
723 GAsyncResult *res, gpointer user_data)
726 GVariantIter *char_iter;
728 GError *error = NULL;
729 bt_user_info_t *user_info;
730 int ret = BLUETOOTH_ERROR_INTERNAL;
731 bt_gatt_char_property_t characteristic;
733 user_info = _bt_get_user_data(BT_COMMON);
735 value = g_dbus_proxy_call_finish(proxy, res, &error);
739 BT_ERR("Get service characteristics failed\n errCode[%x],"
740 "message[%s]\n", error->code, error->message);
741 g_clear_error(&error);
743 BT_ERR("Get service characteristics failed\n");
746 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
747 BLUETOOTH_ERROR_INTERNAL, NULL,
748 user_info->cb, user_info->user_data);
750 g_object_unref(proxy);
755 g_variant_get(value, "(ao)", &char_iter);
757 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
760 ret = bluetooth_gatt_get_characteristics_property(char_handle,
763 if (ret != BLUETOOTH_ERROR_NONE) {
764 BT_ERR("Get characteristic property failed(0x%08x)", ret);
766 if (g_strstr_len(characteristic.uuid, -1, user_data)) {
767 ret = BLUETOOTH_ERROR_NONE;
771 bluetooth_gatt_free_char_property(&characteristic);
775 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
776 &characteristic, user_info->cb, user_info->user_data);
779 bluetooth_gatt_free_char_property(&characteristic);
780 g_variant_iter_free(char_iter);
781 g_variant_unref(value);
785 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
786 const char *char_uuid)
788 GDBusProxy *properties_proxy = NULL;
789 GDBusConnection *g_conn;
790 GError *error = NULL;
793 BT_CHECK_PARAMETER(service_handle, return);
794 BT_CHECK_PARAMETER(char_uuid, return);
795 BT_CHECK_ENABLED(return);
797 g_conn = _bt_get_system_common_conn();
798 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
800 properties_proxy = g_dbus_proxy_new_sync(g_conn,
801 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
804 BT_PROPERTIES_INTERFACE,
807 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
809 uuid = g_strdup(char_uuid);
810 g_dbus_proxy_call(properties_proxy,
812 g_variant_new("(ss)",
813 GATT_SERV_INTERFACE, "Characteristics"),
814 G_DBUS_CALL_FLAGS_NONE,
817 (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
820 return BLUETOOTH_ERROR_NONE;
823 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
824 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
826 GDBusProxy *properties_proxy = NULL;
827 GError *error = NULL;
828 GDBusConnection *g_conn;
829 GVariant *result = NULL;
830 GVariantIter *property_iter;
834 GVariant *value = NULL;
835 GByteArray *gb_array = NULL;
836 GVariantIter *desc_value_iter;
838 BT_CHECK_PARAMETER(descriptor_handle, return);
839 BT_CHECK_PARAMETER(descriptor, return);
841 BT_CHECK_ENABLED(return);
843 g_conn = _bt_get_system_common_conn();
844 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
846 properties_proxy = g_dbus_proxy_new_sync(g_conn,
847 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
850 BT_PROPERTIES_INTERFACE,
853 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
855 result = g_dbus_proxy_call_sync(properties_proxy,
857 g_variant_new("(s)", GATT_DESC_INTERFACE),
858 G_DBUS_CALL_FLAGS_NONE,
865 BT_ERR("Fail to get properties (Error: %s)", error->message);
866 g_clear_error(&error);
868 BT_ERR("Fail to get properties");
869 g_object_unref(properties_proxy);
870 return BLUETOOTH_ERROR_INTERNAL;
873 g_variant_get(result, "(a{sv})", &property_iter);
875 memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
876 descriptor->handle = g_strdup(descriptor_handle);
878 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
879 if (!g_strcmp0(key, "UUID")) {
881 descriptor->uuid = g_variant_dup_string(value, &len);
882 bluetooth_get_uuid_name(descriptor->uuid, &name);
883 BT_INFO("Descriptor : %s [%s]", descriptor->uuid, name);
885 } else if (!g_strcmp0(key, "Value")) {
886 gb_array = g_byte_array_new();
887 g_variant_get(value, "ay", &desc_value_iter);
888 while (g_variant_iter_loop(desc_value_iter, "y", &char_value)) {
889 BT_DBG("value of descriptor = %d", char_value);
890 g_byte_array_append(gb_array, &char_value, 1);
892 g_variant_iter_free(desc_value_iter);
894 if (gb_array->len != 0) {
895 descriptor->val = g_malloc0(gb_array->len *
896 sizeof(unsigned char));
897 memcpy(descriptor->val, gb_array->data, gb_array->len);
899 descriptor->val_len = gb_array->len;
900 g_byte_array_free(gb_array, TRUE);
904 g_variant_iter_free(property_iter);
905 g_variant_unref(result);
906 g_object_unref(properties_proxy);
908 return BLUETOOTH_ERROR_NONE;
911 static int __bluetooth_get_att_error_code(GError *error, char *handle)
917 BT_ERR("Error : %s [%s]", error->message, handle + 15);
918 str = g_strrstr(error->message, "ATT error: 0x");
921 att_ecode = g_ascii_xdigit_value(str[len - 2]) << 4;
922 att_ecode += g_ascii_xdigit_value(str[len - 1]);
924 return BLUETOOTH_ATT_ERROR_INTERNAL;
927 case BLUETOOTH_ATT_ERROR_READ_NOT_PERMITTED:
928 BT_ERR("Read not permitted");
930 case BLUETOOTH_ATT_ERROR_WRITE_NOT_PERMITTED:
931 BT_ERR("Write not permitted");
933 case BLUETOOTH_ATT_ERROR_AUTHENTICATION:
934 case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
935 case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
936 BT_ERR("Not paired");
938 case BLUETOOTH_ATT_ERROR_INVALID_OFFSET:
939 BT_ERR("Invalid offset");
941 case BLUETOOTH_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
942 BT_ERR("Invalid Length");
944 case BLUETOOTH_ATT_ERROR_AUTHORIZATION:
945 BT_ERR("Operation not Authorized");
948 BT_ERR("default ecode");
952 if (att_ecode >= 0x80 && att_ecode <= 0x9F)
953 BT_ERR("Application error");
958 static void __bluetooth_internal_read_cb(GObject *source_object,
959 GAsyncResult *res, gpointer user_data)
961 GError *error = NULL;
962 GDBusConnection *system_gconn = NULL;
964 bt_user_info_t *user_info;
966 GByteArray *gp_byte_array = NULL;
969 bt_gatt_resp_data_t *resp_data = user_data;
973 system_gconn = _bt_get_system_common_conn();
974 value = g_dbus_connection_call_finish(system_gconn, res, &error);
976 user_info = _bt_get_user_data(BT_COMMON);
979 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
980 g_clear_error(&error);
985 g_variant_unref(value);
990 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
991 g_clear_error(&error);
993 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
994 att_ecode, resp_data,
995 user_info->cb, user_info->user_data);
1000 gp_byte_array = g_byte_array_new();
1001 g_variant_get(value, "(ay)", &iter);
1003 while (g_variant_iter_loop(iter, "y", &g_byte))
1004 g_byte_array_append(gp_byte_array, &g_byte, 1);
1006 if (gp_byte_array->len != 0) {
1007 resp_data->len = gp_byte_array->len;
1008 resp_data->value = gp_byte_array->data;
1011 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1012 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1013 user_info->cb, user_info->user_data);
1016 g_byte_array_free(gp_byte_array, TRUE);
1017 g_variant_iter_free(iter);
1018 g_variant_unref(value);
1023 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *chr,
1026 GDBusConnection *conn;
1027 bt_gatt_resp_data_t *resp_data;
1028 GVariantBuilder *builder = NULL;
1031 BT_CHECK_PARAMETER(chr, return);
1032 BT_CHECK_ENABLED(return);
1034 conn = _bt_get_system_common_conn();
1035 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1037 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1038 resp_data->user_data = user_data;
1039 resp_data->handle = (char *)chr;
1041 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1044 g_variant_builder_add(builder, "{sv}", "offset",
1045 g_variant_new("q", offset));
1047 /* Device Object path*/
1048 // g_variant_builder_add(builder, "{sv}", "device",
1049 // g_variant_new_object("o", NULL));
1051 g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1052 "ReadValue", g_variant_new("(a{sv})", builder),
1053 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1054 (GAsyncReadyCallback)__bluetooth_internal_read_cb,
1055 (gpointer)resp_data);
1056 g_variant_builder_unref(builder);
1058 return BLUETOOTH_ERROR_NONE;
1061 static void __bluetooth_internal_write_cb(GObject *source_object,
1062 GAsyncResult *res, gpointer user_data)
1064 GError *error = NULL;
1065 GDBusConnection *system_gconn = NULL;
1066 bt_user_info_t *user_info;
1069 bt_gatt_resp_data_t *resp_data = user_data;
1071 system_gconn = _bt_get_system_common_conn();
1072 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1074 user_info = _bt_get_user_data(BT_COMMON);
1077 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1078 g_clear_error(&error);
1083 g_variant_unref(value);
1088 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1089 g_clear_error(&error);
1091 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1092 att_ecode, resp_data,
1093 user_info->cb, user_info->user_data);
1098 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1099 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1100 user_info->cb, user_info->user_data);
1103 g_variant_unref(value);
1107 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
1108 const char *char_handle, const guint8 *value, int length)
1110 GVariant *val, *options;
1111 GVariantBuilder *builder1;
1112 GVariantBuilder *builder2;
1113 GDBusConnection *conn;
1118 BT_CHECK_PARAMETER(char_handle, return);
1119 BT_CHECK_PARAMETER(value, return);
1120 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1121 BT_CHECK_ENABLED(return);
1123 conn = _bt_get_system_common_conn();
1124 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1126 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1127 for (i = 0; i < length; i++)
1128 g_variant_builder_add(builder1, "y", value[i]);
1130 val = g_variant_new("ay", builder1);
1132 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1134 g_variant_builder_add(builder2, "{sv}", "offset",
1135 g_variant_new_uint16(offset));
1137 /* Device Object path*/
1138 // g_variant_builder_add(builder2, "{sv}", "device",
1139 // g_variant_new_object("o", NULL));
1141 options = g_variant_new("a{sv}", builder2);
1143 g_dbus_connection_call(conn,
1146 GATT_CHAR_INTERFACE,
1148 g_variant_new("(@ay@a{sv})",
1151 G_DBUS_CALL_FLAGS_NONE,
1153 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1156 g_variant_builder_unref(builder1);
1157 g_variant_builder_unref(builder2);
1160 return BLUETOOTH_ERROR_NONE;
1163 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1164 const char *chr, const guint8 *value, int length,
1165 guint8 write_type, gpointer user_data)
1167 GVariant *val, *options;
1168 GVariantBuilder *builder1;
1169 GVariantBuilder *builder2;
1170 GDBusConnection *conn;
1173 int ret = BLUETOOTH_ERROR_NONE;
1174 bt_gatt_resp_data_t *resp_data;
1176 BT_CHECK_PARAMETER(chr, return);
1177 BT_CHECK_PARAMETER(value, return);
1178 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1179 BT_CHECK_ENABLED_INTERNAL(return);
1181 conn = _bt_get_system_common_conn();
1182 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1184 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1186 for (i = 0; i < length; i++)
1187 g_variant_builder_add(builder1, "y", value[i]);
1189 val = g_variant_new("ay", builder1);
1191 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1193 g_variant_builder_add(builder2, "{sv}", "offset",
1194 g_variant_new_uint16(offset));
1196 /* Device Object path*/
1197 // g_variant_builder_add(builder2, "{sv}", "device",
1198 // g_variant_new_object("o", NULL));
1200 options = g_variant_new("a{sv}", builder2);
1202 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1203 resp_data->user_data = user_data;
1204 resp_data->handle = (char *)chr;
1206 g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1208 g_variant_new("(y@ay@a{sv})", write_type, val, options),
1210 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1211 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1212 (gpointer)resp_data);
1214 g_variant_builder_unref(builder1);
1215 g_variant_builder_unref(builder2);
1220 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1221 const char *char_handle, const guint8 *value, int length)
1223 GVariant *val, *options;
1224 GDBusConnection *conn;
1225 GVariantBuilder *builder1;
1226 GVariantBuilder *builder2;
1231 BT_CHECK_PARAMETER(char_handle, return);
1232 BT_CHECK_PARAMETER(value, return);
1233 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1234 BT_CHECK_ENABLED(return);
1236 conn = _bt_get_system_common_conn();
1237 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1239 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1241 for (i = 0; i < length; i++) {
1242 g_variant_builder_add(builder1, "y", value[i]);
1243 BT_DBG("value [] = %d", value[i]);
1246 val = g_variant_new("ay", builder1);
1248 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1250 g_variant_builder_add(builder2, "{sv}", "offset",
1251 g_variant_new_uint16(offset));
1253 /* Device Object path*/
1254 // g_variant_builder_add(builder2, "{sv}", "device",
1255 // g_variant_new_object("o", NULL));
1257 options = g_variant_new("a{sv}", builder2);
1259 g_dbus_connection_call(conn,
1262 GATT_CHAR_INTERFACE,
1264 g_variant_new("(@ay@a{sv})",
1267 G_DBUS_CALL_FLAGS_NONE,
1269 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1272 g_variant_builder_unref(builder1);
1273 g_variant_builder_unref(builder2);
1276 return BLUETOOTH_ERROR_NONE;
1279 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1280 bt_gatt_char_property_t *characteristic)
1283 GDBusProxy *properties_proxy = NULL;
1284 GError *error = NULL;
1285 GVariant *value = NULL;
1286 GVariant *result = NULL;
1287 GDBusConnection *g_conn;
1288 int i, ret = BLUETOOTH_ERROR_NONE;
1289 const char *uuid = NULL;
1291 GVariantIter *desc_value_iter, *property_iter;
1293 char_descriptor_type_t desc_type = TYPE_NONE;
1295 g_conn = _bt_get_system_common_conn();
1296 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1298 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1299 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1302 BT_PROPERTIES_INTERFACE,
1305 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1307 result = g_dbus_proxy_call_sync(properties_proxy,
1309 g_variant_new("(s)", GATT_DESC_INTERFACE),
1310 G_DBUS_CALL_FLAGS_NONE,
1316 if (error != NULL) {
1317 BT_ERR("Fail to get properties (Error: %s)", error->message);
1318 g_clear_error(&error);
1320 BT_ERR("Fail to get properties");
1321 g_object_unref(properties_proxy);
1322 return BLUETOOTH_ERROR_INTERNAL;
1324 g_variant_get(result, "(a{sv})", &property_iter);
1325 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1326 if (!g_strcmp0(key, "UUID")) {
1327 uuid = g_variant_get_string(value, &len);
1328 if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1329 BT_DBG("GATT_USER_DESC_UUID");
1330 desc_type = USER_DESC;
1331 } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1332 BT_DBG("GATT_CHAR_FORMAT");
1333 desc_type = CHAR_FORMAT;
1334 } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1335 BT_DBG("GATT_CHAR_CLIENT_CONF");
1336 desc_type = CLIENT_CONF;
1337 } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1338 BT_DBG("GATT_CHAR_SERVER_CONF");
1339 desc_type = SERVER_CONF;
1341 BT_DBG("descriptor uuid = %s", uuid);
1343 } else if (!g_strcmp0(key, "Value")) {
1344 switch (desc_type) {
1346 BT_DBG("Format descriptor");
1347 g_variant_get(value, "(yyqyq)",
1348 &(characteristic->format.format),
1349 &(characteristic->format.exponent),
1350 &(characteristic->format.unit),
1351 &(characteristic->format.name_space),
1352 &(characteristic->format.description));
1355 BT_DBG("User descriptor");
1356 g_variant_get(value, "ay", &desc_value_iter);
1357 len = g_variant_get_size((GVariant *)desc_value_iter);
1360 characteristic->description = (char *)g_malloc0(len + 1);
1362 for (i = 0; i < len; i++) {
1363 g_variant_iter_loop(desc_value_iter, "y",
1364 &characteristic->description[i]);
1365 BT_DBG("description = %s", characteristic->description);
1367 g_variant_iter_free(desc_value_iter);
1370 BT_DBG(" CLIENT_CONF");
1373 BT_DBG(" SERVER_CONF");
1381 g_variant_iter_free(property_iter);
1382 g_variant_unref(result);
1383 g_object_unref(properties_proxy);
1390 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1391 GAsyncResult *res, gpointer user_data)
1395 GVariant *char_value;
1396 GVariantIter *char_iter;
1398 GError *error = NULL;
1399 bt_user_info_t *user_info;
1400 bt_gatt_char_property_t characteristic = {0, };
1401 int ret = BLUETOOTH_ERROR_INTERNAL;
1403 user_info = _bt_get_user_data(BT_COMMON);
1405 value = g_dbus_proxy_call_finish(proxy, res, &error);
1406 characteristic.handle = user_data;
1408 if (value == NULL) {
1409 if (error != NULL) {
1410 BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1411 "message[%s]\n", error->code, error->message);
1412 g_clear_error(&error);
1414 BT_ERR("Get characteristic descriptor failed\n");
1417 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1418 BLUETOOTH_ERROR_INTERNAL, NULL,
1419 user_info->cb, user_info->user_data);
1421 g_free(characteristic.handle);
1422 g_object_unref(proxy);
1426 g_variant_get(value, "(v)", &char_value);
1427 g_variant_get(char_value, "ao", &char_iter);
1429 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
1430 BT_DBG("object path of descriptor = %s", char_handle);
1432 ret = __bluetooth_gatt_descriptor_iter(char_handle,
1434 BT_DBG("Descriptor read status [%d]", ret);
1439 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1440 ret, &characteristic, user_info->cb, user_info->user_data);
1442 bluetooth_gatt_free_char_property(&characteristic);
1444 g_variant_iter_free(char_iter);
1445 g_variant_unref(value);
1446 g_variant_unref(char_value);
1450 BT_EXPORT_API int bltooth_gatt_discover_characteristic_descriptor(
1451 const char *characteristic_handle)
1453 GDBusProxy *properties_proxy = NULL;
1454 GDBusConnection *g_conn;
1456 GError *error = NULL;
1458 BT_CHECK_PARAMETER(characteristic_handle, return);
1459 BT_CHECK_ENABLED(return);
1461 g_conn = _bt_get_system_common_conn();
1462 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1464 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1465 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1467 characteristic_handle,
1468 BT_PROPERTIES_INTERFACE,
1471 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1473 handle = g_strdup(characteristic_handle);
1474 g_dbus_proxy_call(properties_proxy,
1476 g_variant_new("(ss)",
1477 GATT_CHAR_INTERFACE, "Descriptors"),
1478 G_DBUS_CALL_FLAGS_NONE,
1480 (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1483 return BLUETOOTH_ERROR_NONE;
1486 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1490 GError *error = NULL;
1491 GDBusConnection *system_gconn = NULL;
1493 bt_user_info_t *user_info;
1494 GByteArray *gp_byte_array = NULL;
1498 bt_gatt_resp_data_t *resp_data = user_data;
1502 system_gconn = _bt_get_system_common_conn();
1503 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1505 user_info = _bt_get_user_data(BT_COMMON);
1508 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1509 g_clear_error(&error);
1514 g_variant_unref(value);
1519 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1520 g_clear_error(&error);
1522 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1523 att_ecode, resp_data,
1524 user_info->cb, user_info->user_data);
1529 gp_byte_array = g_byte_array_new();
1530 g_variant_get(value, "(ay)", &iter);
1532 while (g_variant_iter_loop(iter, "y", &g_byte))
1533 g_byte_array_append(gp_byte_array, &g_byte, 1);
1535 if (gp_byte_array->len != 0) {
1536 resp_data->len = gp_byte_array->len;
1537 resp_data->value = gp_byte_array->data;
1540 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1541 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1542 user_info->cb, user_info->user_data);
1546 g_byte_array_free(gp_byte_array, TRUE);
1547 g_variant_iter_free(iter);
1548 g_variant_unref(value);
1553 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *desc,
1556 GDBusConnection *conn;
1557 GVariantBuilder *builder;
1559 bt_gatt_resp_data_t *resp_data;
1563 BT_CHECK_PARAMETER(desc, return);
1564 BT_CHECK_ENABLED(return);
1566 conn = _bt_get_system_common_conn();
1567 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1569 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1570 resp_data->user_data = user_data;
1571 resp_data->handle = (char *)desc;
1573 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1576 g_variant_builder_add(builder, "{sv}", "offset",
1577 g_variant_new("q", offset));
1578 /* Device Object path*/
1579 // g_variant_builder_add(builder, "{sv}", "device",
1580 // g_variant_new("o", serv_info->serv_path));
1582 g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1583 "ReadValue", g_variant_new("(a{sv})", builder),
1584 G_VARIANT_TYPE("(ay)"),
1585 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1586 (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1587 (gpointer)resp_data);
1588 g_variant_builder_unref(builder);
1591 return BLUETOOTH_ERROR_NONE;
1594 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1595 GAsyncResult *res, gpointer user_data)
1597 GError *error = NULL;
1598 bt_user_info_t *user_info;
1599 GDBusConnection *system_gconn = NULL;
1601 int att_ecode = BLUETOOTH_ATT_ERROR_NONE;
1602 bt_gatt_resp_data_t *resp_data = user_data;
1606 system_gconn = _bt_get_system_common_conn();
1607 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1609 user_info = _bt_get_user_data(BT_COMMON);
1612 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1613 g_clear_error(&error);
1618 g_variant_unref(value);
1623 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1624 g_clear_error(&error);
1626 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1627 att_ecode, resp_data,
1628 user_info->cb, user_info->user_data);
1633 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1634 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1635 user_info->cb, user_info->user_data);
1638 g_variant_unref(value);
1642 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(const char *desc,
1643 const guint8 *value, int length, gpointer user_data)
1645 GVariant *val, *options;
1646 GDBusConnection *conn;
1647 GVariantBuilder *builder1;
1648 GVariantBuilder *builder2;
1651 bt_gatt_resp_data_t *resp_data;
1655 BT_CHECK_PARAMETER(desc, return);
1656 BT_CHECK_PARAMETER(value, return);
1657 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1658 BT_CHECK_ENABLED(return);
1660 conn = _bt_get_system_common_conn();
1661 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1663 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1665 for (i = 0; i < length; i++)
1666 g_variant_builder_add(builder1, "y", value[i]);
1668 val = g_variant_new("ay", builder1);
1670 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1672 g_variant_builder_add(builder2, "{sv}", "offset",
1673 g_variant_new_uint16(offset));
1675 /* Device Object path*/
1676 // g_variant_builder_add(builder2, "{sv}", "device",
1677 // g_variant_new_object("o", NULL));
1679 options = g_variant_new("a{sv}", builder2);
1681 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1682 resp_data->user_data = user_data;
1683 resp_data->handle = (char *)desc;
1685 g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1686 "WriteValue", g_variant_new("(@ay@a{sv})",
1687 val, options), NULL,
1688 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1689 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1690 (gpointer)resp_data);
1692 g_variant_builder_unref(builder1);
1693 g_variant_builder_unref(builder2);
1696 return BLUETOOTH_ERROR_NONE;
1699 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle, const char *svc_name)
1701 GDBusConnection *conn;
1702 GError *error = NULL;
1703 int ret = BLUETOOTH_ERROR_NONE;
1705 BT_CHECK_PARAMETER(char_handle, return);
1706 BT_CHECK_ENABLED(return);
1708 BT_INFO_C("### Enable CCCD : %s [%s]", char_handle + 15, svc_name);
1710 conn = _bt_get_system_common_conn();
1711 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1713 g_dbus_connection_call_sync(conn,
1716 GATT_CHAR_INTERFACE,
1720 G_DBUS_CALL_FLAGS_NONE,
1721 GATT_DEFAULT_TIMEOUT, NULL, &error);
1724 g_dbus_error_strip_remote_error(error);
1725 BT_ERR_C("### Watch Failed: %s", error->message);
1726 if (g_strrstr(error->message, "Already notifying"))
1727 ret = BLUETOOTH_ERROR_NONE;
1728 else if (g_strrstr(error->message, "In Progress"))
1729 ret = BLUETOOTH_ERROR_IN_PROGRESS;
1730 else if (g_strrstr(error->message, "Operation is not supported"))
1731 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1732 /*failed because of either Insufficient Authorization or Write Not Permitted */
1733 else if (g_strrstr(error->message, "Write not permitted") ||
1734 g_strrstr(error->message, "Operation Not Authorized"))
1735 ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1736 /* failed because of either Insufficient Authentication,
1737 Insufficient Encryption Key Size, or Insufficient Encryption. */
1738 else if (g_strrstr(error->message, "Not paired"))
1739 ret = BLUETOOTH_ERROR_NOT_PAIRED;
1741 ret = BLUETOOTH_ERROR_INTERNAL;
1743 g_clear_error(&error);
1749 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1751 GDBusConnection *conn;
1752 GError *error = NULL;
1753 int ret = BLUETOOTH_ERROR_NONE;
1754 BT_CHECK_PARAMETER(char_handle, return);
1756 BT_CHECK_ENABLED(return);
1758 BT_INFO("Disable CCCD : %s", char_handle);
1760 conn = _bt_get_system_common_conn();
1761 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1763 g_dbus_connection_call_sync(conn,
1766 GATT_CHAR_INTERFACE,
1770 G_DBUS_CALL_FLAGS_NONE,
1771 GATT_DEFAULT_TIMEOUT, NULL, &error);
1774 BT_ERR("Watch Failed: %s", error->message);
1775 g_clear_error(&error);
1776 ret = BLUETOOTH_ERROR_INTERNAL;
1782 void __bt_uuid_hex_to_string(unsigned char *uuid, char *str)
1784 uint32_t uuid0, uuid4;
1785 uint16_t uuid1, uuid2, uuid3, uuid5;
1787 memcpy(&uuid0, &(uuid[0]), 4);
1788 memcpy(&uuid1, &(uuid[4]), 2);
1789 memcpy(&uuid2, &(uuid[6]), 2);
1790 memcpy(&uuid3, &(uuid[8]), 2);
1791 memcpy(&uuid4, &(uuid[10]), 4);
1792 memcpy(&uuid5, &(uuid[14]), 2);
1794 snprintf((char *)str, BLUETOOTH_UUID_STRING_MAX, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
1795 ntohl(uuid0), ntohs(uuid1),
1796 ntohs(uuid2), ntohs(uuid3),
1797 ntohl(uuid4), ntohs(uuid5));
1802 static void __bt_fill_service_handle_informations(bt_services_browse_info_t *props,
1803 bt_gatt_handle_info_t *svcs)
1807 if (props->count == 0)
1810 svcs->count = props->count;
1812 for (count = 0; count < props->count; count++) {
1813 BT_DBG("[%d] %s instance_id [%d] Is Primary [%d]",
1814 count, props->uuids[count], props->inst_id[count], props->primary[count]);
1815 g_strlcpy(svcs->uuids[count], props->uuids[count],
1816 BLUETOOTH_UUID_STRING_MAX);
1817 svcs->inst_id[count] = props->inst_id[count];
1821 static void __bt_fill_char_handle_informations(bt_char_browse_info_t *props, bt_gatt_service_property_t *service)
1824 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1826 service->char_handle.count = props->count;
1828 /* Before filling all char handles, fill the service's UUID and instance ID */
1829 __bt_uuid_hex_to_string(props->svc_uuid, uuid_string);
1830 service->uuid = g_strdup(uuid_string);
1831 service->primary = TRUE;
1833 /* Now fill all the char handles [UUID and Instance ID's]*/
1834 for (count = 0; count < props->count; count++) {
1835 BT_DBG("[%d] %s instance_id [%d] properties [%d]",
1836 count, props->uuids[count], props->inst_id[count], props->props[count]);
1838 g_strlcpy(service->char_handle.uuids[count],
1839 props->uuids[count],
1840 BLUETOOTH_UUID_STRING_MAX);
1842 service->char_handle.inst_id[count] = props->inst_id[count];
1846 static void __bt_fill_desc_handle_informations(bt_descriptor_browse_info_t *props,
1847 bt_gatt_char_property_t *charc)
1850 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1852 charc->char_desc_handle.count = props->count;
1854 /* Before filling all desc handles, fill the charac's UUID and instance ID */
1855 __bt_uuid_hex_to_string(props->char_uuid, uuid_string);
1856 charc->uuid = g_strdup(uuid_string);
1858 /* Now fill all the descriptor handles [UUID and Instance ID's]*/
1859 for (count = 0; count < props->count; count++) {
1860 BT_DBG("[%d] %s instance_id [%d]",
1861 count, props->uuids[count], props->inst_id[count]);
1863 g_strlcpy(charc->char_desc_handle.uuids[count],
1864 props->uuids[count],
1865 BLUETOOTH_UUID_STRING_MAX);
1867 charc->char_desc_handle.inst_id[count] = props->inst_id[count];
1869 charc->permission = props->char_props_map;
1870 __convert_permission_flag_to_str(charc->permission);
1874 BT_EXPORT_API int bluetooth_gatt_client_init(
1876 const bluetooth_device_address_t *address,
1877 gatt_client_cb_func_ptr callback_ptr)
1879 int ret = BLUETOOTH_ERROR_NONE;
1880 bt_event_info_t *event_info;
1883 BT_CHECK_PARAMETER(client_id, return);
1884 BT_CHECK_PARAMETER(callback_ptr, return);
1885 BT_CHECK_ENABLED(return);
1888 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1890 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1892 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_REGISTER,
1893 in_param1, in_param2, in_param3, in_param4, &out_param);
1895 /* App ID -1 is invalid */
1896 if (ret == BLUETOOTH_ERROR_NONE) {
1898 *client_id = g_array_index(out_param, int, 0);
1900 BT_INFO("GATT Client Registered successfully: Client instance ID [%d]", *client_id);
1902 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
1905 count = (int*)event_info->user_data;
1907 BT_INFO("Total num of GATT client instances [%d]", *count);
1909 /* Increement the count */
1912 BT_INFO("No GATT Client instances found in this application: Set User data");
1913 count = g_malloc0(sizeof(int));
1916 /* Register event handler for GATT */
1917 _bt_register_event(BT_GATT_CLIENT_EVENT,
1918 (void *)callback_ptr,
1920 _bt_set_user_data(BT_GATT_CLIENT, (void *)callback_ptr, NULL);
1923 BT_ERR("GATT Client Registration failed!! ret [%d]", ret);
1925 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1932 BT_EXPORT_API int bluetooth_gatt_client_get_primary_services(
1933 const bluetooth_device_address_t *address, /* Remote GATT Server */
1934 bt_gatt_handle_info_t *prim_svc) /* UUID & instance_id */
1937 int result = BLUETOOTH_ERROR_NONE;
1938 bt_services_browse_info_t service_props;
1940 BT_CHECK_PARAMETER(address, return);
1941 BT_CHECK_PARAMETER(prim_svc, return);
1942 BT_CHECK_ENABLED(return);
1945 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1946 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1948 result = _bt_send_request(BT_BLUEZ_SERVICE,
1949 BT_GATT_GET_PRIMARY_SERVICES,
1950 in_param1, in_param2, in_param3, in_param4, &out_param);
1952 if (BLUETOOTH_ERROR_NONE != result)
1955 memset(&service_props, 0x00, sizeof(bt_services_browse_info_t));
1957 service_props = g_array_index(
1958 out_param, bt_services_browse_info_t, 0);
1960 __bt_fill_service_handle_informations(
1961 &service_props, prim_svc);
1964 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1968 BT_EXPORT_API int bluetooth_gatt_client_get_service_property(
1969 const char *address,
1970 bt_gatt_handle_property_t *service_handle,
1971 bt_gatt_service_property_t *service)
1973 int result = BLUETOOTH_ERROR_NONE;
1974 bluetooth_gatt_client_svc_prop_info_t svc_prop;
1975 bt_char_browse_info_t char_handles_info;
1977 BT_CHECK_PARAMETER(address, return);
1978 BT_CHECK_PARAMETER(service_handle, return);
1979 BT_CHECK_PARAMETER(service, return);
1980 BT_CHECK_ENABLED(return);
1982 /* Call to bt-service (sync) and send address and service_handle info */
1984 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1986 memset(&svc_prop, 0x00, sizeof(bluetooth_gatt_client_svc_prop_info_t));
1987 /* All characteristics handles are discovered */
1988 memset(&char_handles_info, 0x00, sizeof(bt_char_browse_info_t));
1990 svc_prop.svc.instance_id = service_handle->instance_id;
1991 memcpy(&svc_prop.svc.uuid, &service_handle->uuid, 16);
1993 _bt_convert_addr_string_to_type(svc_prop.device_address.addr, address);
1995 g_array_append_vals(in_param1, &svc_prop, sizeof(bluetooth_gatt_client_svc_prop_info_t));
1997 result = _bt_send_request(BT_BLUEZ_SERVICE,
1998 BT_GATT_GET_SERVICE_PROPERTIES,
1999 in_param1, in_param2, in_param3, in_param4, &out_param);
2001 if (BLUETOOTH_ERROR_NONE != result)
2004 char_handles_info = g_array_index(
2005 out_param, bt_char_browse_info_t, 0);
2006 __bt_fill_char_handle_informations(&char_handles_info,
2008 /* TODO Get all Included Services */
2011 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2015 BT_EXPORT_API int bluetooth_gatt_client_get_characteristics_property(
2016 const char *address,
2017 bt_gatt_handle_property_t *service_handle,
2018 bt_gatt_handle_property_t *char_handle,
2019 bt_gatt_char_property_t *char_property)
2021 int result = BLUETOOTH_ERROR_NONE;
2022 bt_descriptor_browse_info_t desc_handles_info;
2023 bluetooth_gatt_client_char_prop_info_t char_prop;
2025 BT_CHECK_PARAMETER(address, return);
2026 BT_CHECK_PARAMETER(service_handle, return);
2027 BT_CHECK_PARAMETER(char_handle, return);
2028 BT_CHECK_PARAMETER(char_property, return);
2029 BT_CHECK_ENABLED(return);
2032 /* Call to bt-service (sync) and send address service_handle info & char handle info */
2034 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2036 memset(&char_prop, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2037 char_prop.svc.instance_id = service_handle->instance_id;
2038 memcpy(&char_prop.svc.uuid, &service_handle->uuid, 16);
2040 char_prop.characteristic.instance_id = char_handle->instance_id;
2041 memcpy(&char_prop.characteristic.uuid, &char_handle->uuid, 16);
2043 _bt_convert_addr_string_to_type(char_prop.device_address.addr, address);
2045 g_array_append_vals(in_param1, &char_prop, sizeof(bluetooth_gatt_client_char_prop_info_t));
2047 result = _bt_send_request(BT_BLUEZ_SERVICE,
2048 BT_GATT_GET_CHARACTERISTIC_PROPERTIES,
2049 in_param1, in_param2, in_param3, in_param4, &out_param);
2051 if (BLUETOOTH_ERROR_NONE != result)
2054 /* All descriptors handles are discovered */
2055 memset(&desc_handles_info, 0x00, sizeof(bt_descriptor_browse_info_t));
2057 desc_handles_info = g_array_index(
2058 out_param, bt_descriptor_browse_info_t, 0);
2060 __bt_fill_desc_handle_informations(&desc_handles_info,
2064 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2066 /* Call to bt-service (sync) and send address, service_handle & char_handle infos */
2068 /* After result is fetched, extract descriptor handles (UUID's & instance_id's) */
2070 /* Fill the info in *char_prop */
2072 /*No: Before returning, call bluetooth_gatt_client_read_characteristic_value as
2073 an asyn function and leave every thing else in the callback */
2076 BT_EXPORT_API int bluetooth_gatt_client_get_char_descriptor_property(
2077 const char *address,
2078 bt_gatt_handle_property_t *service_handle,
2079 bt_gatt_handle_property_t *char_handle,
2080 bt_gatt_handle_property_t *descriptor_handle,
2081 bt_gatt_char_descriptor_property_t *desc_prop)
2083 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
2085 BT_CHECK_PARAMETER(address, return);
2086 BT_CHECK_PARAMETER(service_handle, return);
2087 BT_CHECK_PARAMETER(char_handle, return);
2088 BT_CHECK_PARAMETER(descriptor_handle, return);
2089 BT_CHECK_PARAMETER(desc_prop, return);
2090 /* No Need to Call to bt-service (sync) and send address, service_handle,
2091 char_handle & descriptor handle infos */
2092 /* After result is fetched, extract descriptior handles (UUID's & instance_id's) */
2093 /* Fill the info in *desc_prop */
2094 __bt_uuid_hex_to_string(descriptor_handle->uuid, uuid_string);
2096 /* Before filling all desc handles, fill the charac's UUID and instance ID */
2097 desc_prop->uuid = g_strdup(uuid_string);
2099 return BLUETOOTH_ERROR_NONE;
2100 /* No: Before returning, call bluetooth_gatt_client_read_descriptor_value
2101 as an asyn function and leave every thing else in the callback */
2105 static gboolean bluetooth_gatt_client_notify_channel_watch_cb(GIOChannel *gio,
2106 GIOCondition cond, gpointer data)
2108 bt_gatt_characteristic_notify_info_t *chr_info = (bt_gatt_characteristic_notify_info_t *)data;
2111 BT_ERR("chr_info is invalid");
2115 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
2116 BT_ERR("Error : GIOCondition %d, [%s]", cond, chr_info->UUID);
2117 g_io_channel_shutdown(gio, TRUE, NULL);
2118 g_io_channel_unref(gio);
2120 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2126 if (cond & G_IO_IN) {
2127 GIOStatus status = G_IO_STATUS_NORMAL;
2129 char *buffer = NULL;
2131 bt_event_info_t *event_info;
2133 buffer = g_malloc0(chr_info->mtu + 1);
2134 memset(buffer, 0, chr_info->mtu + 1);
2136 status = g_io_channel_read_chars(gio, buffer,
2137 chr_info->mtu, &len, &err);
2138 if (status != G_IO_STATUS_NORMAL) {
2139 BT_ERR("IO Channel read is failed with %d", status);
2142 BT_ERR("IO Channel read error [%s]", err->message);
2143 if (status == G_IO_STATUS_ERROR) {
2144 BT_ERR("cond : %d", cond);
2146 g_io_channel_shutdown(gio, TRUE, NULL);
2147 g_io_channel_unref(gio);
2149 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2158 if (len > 0 && len < chr_info->mtu) {
2159 bt_gatt_char_property_t char_val;
2160 // 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);
2162 memcpy(char_val.prop.uuid, chr_info->UUID, 16);
2163 memcpy(char_val.value, buffer, len);
2164 char_val.val_len = len;
2165 memcpy(char_val.address, chr_info->address, 18);
2167 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2169 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
2170 BLUETOOTH_ERROR_NONE, &char_val,
2171 event_info->cb, event_info->user_data);
2173 BT_ERR("event_info failed");
2177 BT_ERR("Packet corrupted");
2187 #ifndef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2188 static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_get_characteristic_notify_info(unsigned char *handle , int id)
2192 for (l = gatt_characteristic_notify_list; l != NULL; l = l->next) {
2193 bt_gatt_characteristic_notify_info_t *info = l->data;
2194 if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
2201 static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_create_watch_io(int fd, int id, int mtu, char * address, unsigned char *uuid)
2203 GIOChannel *channel;
2204 bt_gatt_characteristic_notify_info_t *chr_info;
2206 chr_info = g_malloc0(sizeof(bt_gatt_characteristic_notify_info_t));
2207 chr_info->notify_fd = fd;
2209 chr_info->mtu = mtu;
2210 g_strlcpy(chr_info->address, address, 18);
2211 memcpy(chr_info->UUID, uuid, 16);
2213 channel = g_io_channel_unix_new(fd);
2215 chr_info->io_channel = channel;
2217 g_io_channel_set_encoding(channel, NULL, NULL);
2218 g_io_channel_set_buffered(channel, FALSE);
2219 g_io_channel_set_close_on_unref(channel, TRUE);
2220 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
2222 chr_info->watch_id = g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
2223 bluetooth_gatt_client_notify_channel_watch_cb, chr_info);
2229 BT_EXPORT_API int bluetooth_gatt_client_watch_characteristics(
2230 const char *address,
2231 bt_gatt_handle_property_t *service_handle,
2232 bt_gatt_handle_property_t *char_handle,
2235 gboolean is_indicate)
2237 int result = BLUETOOTH_ERROR_NONE;
2238 bluetooth_gatt_client_char_prop_info_t param;
2239 bt_gatt_characteristic_notify_info_t *chr_info;
2241 BT_CHECK_PARAMETER(address, return);
2242 BT_CHECK_PARAMETER(service_handle, return);
2243 BT_CHECK_PARAMETER(char_handle, return);
2245 #ifndef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2246 chr_info = bluetooth_gatt_client_get_characteristic_notify_info(char_handle->uuid , char_handle->instance_id);
2247 if (chr_info && !is_notify) {
2248 BT_INFO("Already CCCD enabled. fd %d", chr_info->notify_fd);
2250 if (chr_info->watch_id > 0)
2251 g_source_remove(chr_info->watch_id);
2253 if (chr_info->io_channel) {
2254 g_io_channel_shutdown(chr_info->io_channel, TRUE, NULL);
2255 g_io_channel_unref(chr_info->io_channel);
2258 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2266 /* ASync Function, result expected in callback from bt-service */
2269 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2271 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2273 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2274 param.svc.instance_id = service_handle->instance_id;
2276 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2277 param.characteristic.instance_id = char_handle->instance_id;
2279 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2281 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_char_prop_info_t));
2282 g_array_append_vals(in_param2, &client_id, sizeof(int));
2283 g_array_append_vals(in_param3, &is_notify, sizeof(gboolean));
2284 g_array_append_vals(in_param4, &is_indicate, sizeof(gboolean));
2286 #ifdef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2287 result = _bt_send_request(BT_BLUEZ_SERVICE,
2288 BT_GATT_WATCH_CHARACTERISTIC,
2289 in_param1, in_param2, in_param3, in_param4, &out_param);
2291 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2293 BT_INFO("Result [%d]", result);
2297 GUnixFDList *out_fd_list = NULL;
2298 char *svc_name = NULL;
2301 _bt_convert_uuid_type_to_string(str_uuid, param.svc.uuid);
2302 bluetooth_get_uuid_name(str_uuid, &svc_name);
2304 _bt_convert_uuid_type_to_string(str_uuid, param.characteristic.uuid);
2306 BT_INFO_C("### Request subscription Notify : %s [%s]", str_uuid, svc_name);
2309 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_WATCH_CHARACTERISTIC,
2310 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
2311 if (result != BLUETOOTH_ERROR_NONE) {
2312 BT_ERR("Fail to get Nofify FD. result %d", result);
2313 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2317 if (is_indicate == false) {
2318 if (NULL == out_fd_list) {
2319 BT_ERR("out_fd_list is NULL");
2320 result = BLUETOOTH_ERROR_INTERNAL;
2327 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
2328 BT_DBG("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
2329 fd = fd_list_array[0];
2330 mtu = g_array_index(out_param, int, 0);
2332 BT_INFO("Acquired characteristic Notify FD %d, mtu %d", fd, mtu);
2333 chr_info = bluetooth_gatt_client_create_watch_io(fd, char_handle->instance_id, mtu, (char *)address, char_handle->uuid);
2335 gatt_characteristic_notify_list = g_slist_append(gatt_characteristic_notify_list, chr_info);
2337 g_free(fd_list_array);
2338 g_object_unref(out_fd_list);
2342 /*result = _bt_send_request(BT_BLUEZ_SERVICE,
2343 BT_GATT_WATCH_CHARACTERISTIC,
2344 in_param1, in_param2, in_param3, in_param4, &out_param);*/
2346 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2351 BT_EXPORT_API int bluetooth_gatt_client_read_characteristic_value(
2352 const char *address,
2353 bt_gatt_handle_property_t *service_handle,
2354 bt_gatt_handle_property_t *char_handle)
2356 int result = BLUETOOTH_ERROR_NONE;
2357 bt_user_info_t *user_info;
2358 bluetooth_gatt_client_char_prop_info_t param;
2360 BT_CHECK_PARAMETER(address, return);
2361 BT_CHECK_PARAMETER(service_handle, return);
2362 BT_CHECK_PARAMETER(char_handle, return);
2364 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2365 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2368 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2370 /* Async Function, result expected in callback from bt-service */
2371 /* Call to bt-service (sync) and send address service_handle info & char handle info */
2372 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2374 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2375 param.svc.instance_id = service_handle->instance_id;
2377 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2378 param.characteristic.instance_id = char_handle->instance_id;
2380 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2382 g_array_append_vals(in_param1, ¶m,
2383 sizeof(bluetooth_gatt_client_char_prop_info_t));
2385 result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC,
2386 in_param1, in_param2, in_param3, in_param4,
2387 user_info->cb, user_info->user_data);
2389 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2393 BT_EXPORT_API int bluetooth_gatt_client_read_descriptor_value(
2394 const char *address,
2395 bt_gatt_handle_property_t *service_handle,
2396 bt_gatt_handle_property_t *char_handle,
2397 bt_gatt_handle_property_t *descriptor_handle)
2399 int result = BLUETOOTH_ERROR_NONE;
2400 bt_user_info_t *user_info;
2401 bluetooth_gatt_client_desc_prop_info_t param;
2403 BT_CHECK_PARAMETER(address, return);
2404 BT_CHECK_PARAMETER(service_handle, return);
2405 BT_CHECK_PARAMETER(char_handle, return);
2406 BT_CHECK_PARAMETER(descriptor_handle, return);
2408 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2409 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2412 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2414 /* Async Function, result expected in callback from bt-service */
2415 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2417 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2418 param.svc.instance_id = service_handle->instance_id;
2420 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2421 param.characteristic.instance_id = char_handle->instance_id;
2423 memcpy(¶m.descriptor.uuid, descriptor_handle->uuid, 16);
2424 param.descriptor.instance_id = descriptor_handle->instance_id;
2426 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2428 g_array_append_vals(in_param1, ¶m,
2429 sizeof(bluetooth_gatt_client_desc_prop_info_t));
2431 result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_DESCRIPTOR_VALUE,
2432 in_param1, in_param2, in_param3, in_param4,
2433 user_info->cb, user_info->user_data);
2435 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2440 static bt_gatt_characteristic_write_info_t * bluetooth_gatt_client_get_characteristic_fd(unsigned char *handle, int id)
2445 for (l = gatt_characteristic_write_list; l != NULL; l = l->next) {
2446 bt_gatt_characteristic_write_info_t *info = l->data;
2448 if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
2452 _bt_convert_uuid_type_to_string(str, handle);
2453 BT_ERR("Unable to get characteristic fd. [%s] id [ %d]", str, id);
2457 static gboolean bluetooth_gatt_client_write_channel_watch_cb(GIOChannel *gio,
2458 GIOCondition cond, gpointer data)
2460 bt_gatt_characteristic_write_info_t *chr_info = (bt_gatt_characteristic_write_info_t *)data;
2465 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
2467 _bt_convert_uuid_type_to_string(uuid_str, chr_info->UUID);
2468 BT_ERR("Error : GIOCondition %d, [%s]", cond, uuid_str);
2469 g_io_channel_shutdown(gio, TRUE, NULL);
2470 g_io_channel_unref(gio);
2472 gatt_characteristic_write_list = g_slist_remove(gatt_characteristic_write_list, chr_info);
2481 static int bluetooth_gatt_client_write_characteristics_value_to_fd(
2482 int fd, const guint8 *value, int length, int mtu,
2486 int att_result = BLUETOOTH_ERROR_NONE;
2487 BT_CHECK_PARAMETER(value, return);
2488 written = write(fd, value, length);
2489 if (written != length) {
2490 att_result = BLUETOOTH_ERROR_INTERNAL;
2491 BT_ERR("write data failed. ret : %d ", written);
2497 static void bluetooth_gatt_client_create_write_io_channel(int fd, unsigned char * uuid, int id, int mtu)
2499 bt_gatt_characteristic_write_info_t *chr_info;
2500 GIOChannel *channel;
2502 chr_info = g_malloc0(sizeof(bt_gatt_characteristic_write_info_t));
2503 chr_info->write_fd = fd;
2505 chr_info->mtu = mtu;
2507 memcpy(chr_info->UUID, uuid, 16);
2508 channel = g_io_channel_unix_new(fd);
2509 g_io_channel_set_encoding(channel, NULL, NULL);
2510 g_io_channel_set_buffered(channel, FALSE);
2511 g_io_channel_set_close_on_unref(channel, TRUE);
2512 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
2513 g_io_add_watch(channel, (G_IO_ERR | G_IO_HUP | G_IO_NVAL),
2514 bluetooth_gatt_client_write_channel_watch_cb, chr_info);
2516 gatt_characteristic_write_list = g_slist_append(gatt_characteristic_write_list, chr_info);
2520 BT_EXPORT_API int bluetooth_gatt_client_write_characteristic_value_by_type(
2521 const char *address,
2522 bt_gatt_handle_property_t *service_handle,
2523 bt_gatt_handle_property_t *char_handle,
2524 bluetooth_gatt_att_data_t *data,
2525 bluetooth_gatt_write_type_e write_type)
2527 int result = BLUETOOTH_ERROR_NONE;
2528 bt_user_info_t *user_info;
2529 bluetooth_gatt_client_char_prop_info_t param;
2531 BT_CHECK_PARAMETER(address, return);
2532 BT_CHECK_PARAMETER(service_handle, return);
2533 BT_CHECK_PARAMETER(char_handle, return);
2534 BT_CHECK_PARAMETER(data, return);
2536 /* ASync Function, result expected in callback from bt-service */
2537 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2538 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2541 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2543 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2545 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2546 param.svc.instance_id = service_handle->instance_id;
2548 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2549 param.characteristic.instance_id = char_handle->instance_id;
2551 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2553 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_char_prop_info_t));
2554 g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2555 g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2557 #ifdef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2561 if (write_type == BLUETOOTH_GATT_TYPE_WRITE_NO_RESPONSE) {
2564 bt_gatt_characteristic_write_info_t *info;
2565 info = bluetooth_gatt_client_get_characteristic_fd(char_handle->uuid, service_handle->instance_id);
2568 fd = info->write_fd;
2574 GUnixFDList *out_fd_list = NULL;
2576 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_ACQUIRE_WRITE,
2577 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
2579 mtu = g_array_index(out_param, int, 0);
2581 if (result != BLUETOOTH_ERROR_NONE) {
2582 BT_ERR("Fail to get Write FD. result %d", result);
2583 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2585 } else if (NULL == out_fd_list) {
2586 BT_ERR("out_fd_list is NULL");
2587 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2588 return BLUETOOTH_ERROR_INTERNAL;
2593 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
2594 fd = fd_list_array[0];
2596 g_free(fd_list_array);
2597 g_object_unref(out_fd_list);
2599 BT_INFO("Acquired characteristic Write FD %d, mtu %d", fd, mtu);
2602 bluetooth_gatt_client_create_write_io_channel(fd, char_handle->uuid, service_handle->instance_id, mtu);
2604 result = bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
2607 BT_ERR("characteristic info FD is invalid");
2612 result = bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
2617 result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2618 BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE,
2619 in_param1, in_param2, in_param3, in_param4,
2620 user_info->cb, user_info->user_data);
2623 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2628 BT_EXPORT_API int bluetooth_gatt_client_write_descriptor_value(
2629 const char *address,
2630 bt_gatt_handle_property_t *service_handle,
2631 bt_gatt_handle_property_t *char_handle,
2632 bt_gatt_handle_property_t *descriptor_handle,
2633 bluetooth_gatt_att_data_t *data,
2634 bluetooth_gatt_write_type_e write_type)
2636 int result = BLUETOOTH_ERROR_NONE;
2637 bt_user_info_t *user_info;
2638 bluetooth_gatt_client_desc_prop_info_t param;
2640 BT_CHECK_PARAMETER(address, return);
2641 BT_CHECK_PARAMETER(service_handle, return);
2642 BT_CHECK_PARAMETER(char_handle, return);
2643 BT_CHECK_PARAMETER(descriptor_handle, return);
2644 BT_CHECK_PARAMETER(data, return);
2646 /* Async Function, result expected in callback from bt-service */
2647 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2648 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2651 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2653 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2655 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2656 param.svc.instance_id = service_handle->instance_id;
2658 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2659 param.characteristic.instance_id = char_handle->instance_id;
2661 memcpy(¶m.descriptor.uuid, descriptor_handle->uuid, 16);
2662 param.descriptor.instance_id = descriptor_handle->instance_id;
2664 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2666 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2667 g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2668 g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2670 result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2671 BT_GATT_WRITE_DESCRIPTOR_VALUE,
2672 in_param1, in_param2, in_param3, in_param4,
2673 user_info->cb, user_info->user_data);
2675 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2680 BT_EXPORT_API int bluetooth_gatt_client_set_service_change_watcher(
2681 const bluetooth_device_address_t *address, gboolean enable)
2684 bluetooth_device_address_t *addr = NULL;
2685 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2686 char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2687 int result = BLUETOOTH_ERROR_NONE;
2690 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2692 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
2693 g_array_append_vals(in_param2, &enable, sizeof(gboolean));
2695 _bt_convert_addr_type_to_string(device_address, (unsigned char *)address->addr);
2696 _bt_convert_addr_string_to_secure_string(secure_address, device_address);
2697 BT_INFO("%s watcher for [%s]", enable ? "Set":"Unset", secure_address);
2699 if (enable == TRUE) {
2700 if (_bluetooth_gatt_check_service_change_watcher_address(address)
2702 BT_INFO("The watcher is already set");
2706 if (service_monitor_list == NULL) {
2707 //_bt_register_manager_subscribe_signal(TRUE);
2709 result = _bt_send_request(BT_BLUEZ_SERVICE,
2710 BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2711 in_param1, in_param2, in_param3, in_param4, &out_param);
2714 if (result == BLUETOOTH_ERROR_NONE) {
2715 addr = g_malloc0(sizeof(bluetooth_device_address_t));
2716 memcpy(addr, address, sizeof(bluetooth_device_address_t));
2718 service_monitor_list =
2719 g_slist_append(service_monitor_list, addr);
2722 for (l = service_monitor_list; l != NULL; l = l->next) {
2725 if (!memcmp(address, addr,
2726 sizeof(bluetooth_device_address_t))) {
2727 service_monitor_list =
2728 g_slist_remove(service_monitor_list, addr);
2734 if (service_monitor_list == NULL) {
2735 //_bt_register_manager_subscribe_signal(FALSE);
2736 result = _bt_send_request(BT_BLUEZ_SERVICE,
2737 BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2738 in_param1, in_param2, in_param3, in_param4, &out_param);
2744 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2748 BT_EXPORT_API int bluetooth_gatt_client_deinit(
2753 bt_event_info_t *event_info;
2755 BT_CHECK_ENABLED(return);
2757 BT_INFO("GATT Client Deinit Client instance ID [%d]", client_id);
2760 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2762 g_array_append_vals(in_param1, &client_id, sizeof(int));
2764 /* Unregistration MUST NOT FAIL */
2765 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_UNREGISTER,
2766 in_param1, in_param2, in_param3, in_param4, &out_param);
2768 if (result != BLUETOOTH_ERROR_NONE)
2769 BT_ERR("GATT Client Unregistration failed result [%d]", result);
2771 /* Unregister event handler if this is the only instance */
2772 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2775 count = (int*)event_info->user_data;
2777 BT_DBG("Total num of GATT client instances [%d]", *count);
2780 BT_DBG("Currently only one GATT client instance, so remove it and unregister GATT client events");
2781 _bt_unregister_event(BT_GATT_CLIENT_EVENT);
2782 _bt_set_user_data(BT_GATT_CLIENT, NULL, NULL);
2786 BT_ERR("Impossible that client is created, but no event handler is registered!!!");
2788 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2792 BT_EXPORT_API int bluetooth_gatt_client_read_phy(const bluetooth_device_address_t *device_address)
2796 BT_CHECK_PARAMETER(device_address, return);
2797 BT_CHECK_ENABLED(return);
2800 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2802 g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t));
2804 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_READ_PHY,
2805 in_param1, in_param2, in_param3, in_param4, &out_param);
2807 if (result != BLUETOOTH_ERROR_NONE)
2808 BT_INFO("GATT Client Read PHY failed result [%d]", result);
2810 BT_INFO("GATT Client Read PHY successful");
2812 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2817 BT_EXPORT_API int bluetooth_gatt_client_set_phy(const bluetooth_device_address_t *device_address,
2818 int tx_phy, int rx_phy, int phy_options)
2822 BT_CHECK_PARAMETER(device_address, return);
2823 BT_CHECK_ENABLED(return);
2825 BT_INFO("Set PHY: Tx[%d], Rx[%d], Phy_options[%d]", tx_phy, rx_phy, phy_options);
2828 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2830 g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t));
2831 g_array_append_vals(in_param2, &tx_phy, sizeof(int));
2832 g_array_append_vals(in_param3, &rx_phy, sizeof(int));
2833 g_array_append_vals(in_param4, &phy_options, sizeof(int));
2835 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_SET_PHY,
2836 in_param1, in_param2, in_param3, in_param4, &out_param);
2838 if (result != BLUETOOTH_ERROR_NONE)
2839 BT_INFO("GATT Client Set PHY failed result [%d]", result);
2841 BT_INFO("GATT Client Set PHY successful");
2843 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);