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 #ifdef TIZEN_GATT_CLIENT
33 #include "bluetooth-gatt-client-api.h"
34 #include <arpa/inet.h>
35 static GSList *gatt_characteristic_notify_list;
36 static GSList *gatt_characteristic_write_list = NULL;;
39 #define GATT_DEFAULT_TIMEOUT (6 * 1000) // Dependent on supervision timeout 6 sec
47 } char_descriptor_type_t;
49 static GSList *service_monitor_list = NULL;
51 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
53 BT_CHECK_PARAMETER(svc_pty, return);
55 #ifdef TIZEN_GATT_CLIENT
56 g_free(svc_pty->uuid);
58 g_free(svc_pty->uuid);
59 g_free(svc_pty->handle);
60 g_strfreev(svc_pty->include_handles.handle);
61 g_strfreev(svc_pty->char_handle.handle);
64 memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
66 return BLUETOOTH_ERROR_NONE;
69 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
71 BT_CHECK_PARAMETER(char_pty, return);
73 g_free(char_pty->uuid);
74 g_free(char_pty->name);
75 g_free(char_pty->description);
76 g_free(char_pty->val);
77 #ifndef TIZEN_GATT_CLIENT
78 g_free(char_pty->handle);
79 g_strfreev(char_pty->char_desc_handle.handle);
82 memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
84 return BLUETOOTH_ERROR_NONE;
87 BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty)
89 BT_CHECK_PARAMETER(desc_pty, return);
91 g_free(desc_pty->uuid);
92 g_free(desc_pty->val);
93 #ifndef TIZEN_GATT_CLIENT
94 g_free(desc_pty->handle);
97 memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t));
99 return BLUETOOTH_ERROR_NONE;
102 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
104 gchar *gp_path = NULL;
111 path = g_malloc0((gp->len + 1) * sizeof(char *));
113 for (i = 0; i < gp->len; i++) {
114 gp_path = g_ptr_array_index(gp, i);
115 path[i] = g_strdup(gp_path);
116 // BT_DBG("path[%d] : [%s]", i, path[i]);
122 gboolean _bluetooth_gatt_check_service_change_watcher_address(
123 const bluetooth_device_address_t *device_addr)
126 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
127 char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
129 _bt_convert_addr_type_to_string(device_address,
130 (unsigned char *)device_addr->addr);
132 for (l = service_monitor_list; l != NULL; l = l->next) {
133 char device_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
134 char secure_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
135 bluetooth_device_address_t *addr = l->data;
137 _bt_convert_addr_type_to_string(device_address2,
138 (unsigned char *)addr->addr);
139 _bt_convert_addr_string_to_secure_string(secure_address,
141 _bt_convert_addr_string_to_secure_string(secure_address2,
143 BT_INFO("service_monitor_list [%s] - Input [%s]",
144 secure_address2, secure_address);
146 if (!memcmp(device_addr, addr,
147 sizeof(bluetooth_device_address_t)))
154 BT_EXPORT_API int bluetooth_gatt_set_service_change_watcher(
155 const bluetooth_device_address_t *address, gboolean enable)
158 bluetooth_device_address_t *addr = NULL;
159 char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
161 _bt_convert_addr_type_to_secure_string(secure_address, (unsigned char *)address->addr);
162 BT_INFO("Set watcher for %s with %d", secure_address, enable);
164 if (enable == TRUE) {
165 if (_bluetooth_gatt_check_service_change_watcher_address(address)
167 BT_INFO("The watcher is already set");
168 return BLUETOOTH_ERROR_NONE;
171 if (service_monitor_list == NULL)
172 _bt_register_manager_subscribe_signal(TRUE);
174 addr = g_malloc0(sizeof(bluetooth_device_address_t));
175 memcpy(addr, address, sizeof(bluetooth_device_address_t));
177 service_monitor_list =
178 g_slist_append(service_monitor_list, addr);
180 for (l = service_monitor_list; l != NULL; l = l->next) {
183 if (!memcmp(address, addr,
184 sizeof(bluetooth_device_address_t))) {
185 service_monitor_list =
186 g_slist_remove(service_monitor_list, addr);
192 if (service_monitor_list == NULL)
193 _bt_register_manager_subscribe_signal(FALSE);
196 return BLUETOOTH_ERROR_NONE;
199 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
200 bt_gatt_service_property_t *service)
202 GDBusProxy *properties_proxy = NULL;
203 GError *error = NULL;
204 GVariant *result = NULL;
205 GDBusConnection *g_conn;
207 char *char_handle = NULL;
208 GPtrArray *gp_array = NULL ;
209 GVariantIter *property_iter, *char_iter = NULL;
213 BT_CHECK_PARAMETER(service_handle, return);
214 BT_CHECK_PARAMETER(service, return);
215 BT_CHECK_ENABLED(return);
217 g_conn = _bt_get_system_private_conn();
218 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
220 properties_proxy = g_dbus_proxy_new_sync(g_conn,
221 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
224 BT_PROPERTIES_INTERFACE,
227 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
229 result = g_dbus_proxy_call_sync(properties_proxy,
231 g_variant_new("(s)", GATT_SERV_INTERFACE),
232 G_DBUS_CALL_FLAGS_NONE,
239 BT_ERR("Fail to get properties (Error: %s)", error->message);
240 g_clear_error(&error);
242 BT_ERR("Fail to get properties");
243 g_object_unref(properties_proxy);
244 return BLUETOOTH_ERROR_INTERNAL;
247 g_variant_get(result, "(a{sv})", &property_iter);
249 memset(service, 0, sizeof(bt_gatt_service_property_t));
251 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
252 if (!g_strcmp0(key, "UUID")) {
254 service->uuid = g_variant_dup_string(value, &len);
255 bluetooth_get_uuid_name(service->uuid, &name);
256 BT_INFO("%s %s [%s]", service_handle + 37, service->uuid, name);
258 } else if (!g_strcmp0(key, "Primary")) {
259 service->primary = g_variant_get_boolean(value);
261 } else if (!g_strcmp0(key, "Includes")) {
262 g_variant_get(value, "ao", &char_iter);
263 if (char_iter != NULL) {
264 gp_array = g_ptr_array_new();
265 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
266 g_ptr_array_add(gp_array, (gpointer)char_handle);
268 if (gp_array->len != 0) {
269 service->include_handles.count = gp_array->len;
270 service->include_handles.handle =
271 __get_string_array_from_gptr_array(gp_array);
273 g_ptr_array_free(gp_array, TRUE);
274 g_variant_iter_free(char_iter);
276 } else if (!g_strcmp0(key, "Characteristics")) {
277 g_variant_get(value, "ao", &char_iter);
278 if (char_iter != NULL) {
279 gp_array = g_ptr_array_new();
280 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
281 g_ptr_array_add(gp_array, (gpointer)char_handle);
283 if (gp_array->len != 0) {
284 service->char_handle.count = gp_array->len;
285 service->char_handle.handle =
286 __get_string_array_from_gptr_array(gp_array);
288 g_ptr_array_free(gp_array, TRUE);
289 g_variant_iter_free(char_iter);
291 BT_DBG("Characteristics count : %d", service->char_handle.count);
295 service->handle = g_strdup(service_handle);
297 g_variant_iter_free(property_iter);
298 g_variant_unref(result);
299 g_object_unref(properties_proxy);
301 return BLUETOOTH_ERROR_NONE;
304 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
305 const bluetooth_device_address_t *address,
306 bt_gatt_handle_info_t *prim_svc)
308 GVariant *result = NULL;
310 GVariantIter *svc_iter;
311 GVariantIter *interface_iter;
312 char *object_path = NULL;
313 char *interface_str = NULL;
314 const gchar *key = NULL;
315 GVariant *value = NULL;
316 GPtrArray *gp_array = NULL;
317 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
318 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
319 int ret = BLUETOOTH_ERROR_INTERNAL;
323 BT_CHECK_PARAMETER(address, return);
324 BT_CHECK_PARAMETER(prim_svc, return);
325 BT_CHECK_ENABLED(return);
327 result = _bt_get_managed_objects();
331 _bt_convert_addr_type_to_string(device_address,
332 (unsigned char *)address->addr);
334 gp_array = g_ptr_array_new();
335 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
337 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
339 if (object_path == NULL)
342 _bt_convert_device_path_to_address(object_path, temp_address);
344 if (g_strcmp0(temp_address, device_address) != 0)
347 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
348 &interface_str, &svc_iter)) {
349 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
352 BT_DBG("[%d] Object Path : %s", idx++, object_path);
353 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
354 if (g_strcmp0(key, "Primary") == 0) {
355 if (g_variant_get_boolean(value))
356 g_ptr_array_add(gp_array, (gpointer)object_path);
362 if (gp_array->len == 0) {
363 BT_ERR("gp_array is NULL");
364 ret = BLUETOOTH_ERROR_NOT_FOUND;
366 ret = BLUETOOTH_ERROR_NONE;
367 prim_svc->count = gp_array->len;
368 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
371 g_ptr_array_free(gp_array, TRUE);
372 g_variant_iter_free(iter);
373 g_variant_unref(result);
378 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
379 const char *service_uuid,
380 bt_gatt_service_property_t *service)
382 GVariant *result = NULL;
384 GVariantIter *svc_iter;
385 GVariantIter *interface_iter;
386 char *object_path = NULL;
387 char *interface_str = NULL;
388 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
389 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
390 int ret = BLUETOOTH_ERROR_INTERNAL;
392 BT_CHECK_PARAMETER(address, return);
393 BT_CHECK_PARAMETER(service_uuid, return);
394 BT_CHECK_PARAMETER(service, return);
395 BT_CHECK_ENABLED(return);
397 result = _bt_get_managed_objects();
401 _bt_convert_addr_type_to_string(device_address,
402 (unsigned char *)address->addr);
404 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
406 while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
408 if (object_path == NULL)
411 _bt_convert_device_path_to_address(object_path,
414 if (g_strcmp0(temp_address, device_address) != 0)
417 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
418 &interface_str, &svc_iter)) {
419 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
422 BT_DBG("Object Path: %s", object_path);
423 ret = bluetooth_gatt_get_service_property(object_path,
426 if (ret != BLUETOOTH_ERROR_NONE) {
427 BT_ERR("Get service property failed(0x%08x)", ret);
429 if (service->primary == TRUE &&
430 g_strstr_len(service->uuid, -1,
432 ret = BLUETOOTH_ERROR_NONE;
434 /* release resources */
436 g_variant_iter_free(interface_iter);
437 g_free(interface_str);
438 g_variant_iter_free(svc_iter);
443 bluetooth_gatt_free_service_property(service);
448 g_variant_iter_free(iter);
449 g_variant_unref(result);
454 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
455 GAsyncResult *res, gpointer user_data)
458 GVariant *char_value;
459 GVariantIter *char_iter;
460 GPtrArray *gp_array = NULL;
461 bt_gatt_discovered_char_t svc_char = { 0, };
463 GError *error = NULL;
464 bt_user_info_t *user_info;
468 user_info = _bt_get_user_data(BT_COMMON);
469 svc_char.service_handle = user_data;
471 value = g_dbus_proxy_call_finish(proxy, res, &error);
475 BT_ERR("Get service characteristics failed\n errCode[%x],"
476 "message[%s]\n", error->code, error->message);
477 g_clear_error(&error);
479 BT_ERR("Get service characteristics failed\n");
482 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
483 BLUETOOTH_ERROR_INTERNAL, NULL,
484 user_info->cb, user_info->user_data);
486 g_free(svc_char.service_handle);
487 g_object_unref(proxy);
491 g_variant_get(value, "(v)", &char_value);
492 g_variant_get(char_value, "ao", &char_iter);
494 gp_array = g_ptr_array_new();
495 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
496 g_ptr_array_add(gp_array, (gpointer)char_handle);
498 if (gp_array->len != 0) {
499 svc_char.handle_info.count = gp_array->len;
500 svc_char.handle_info.handle =
501 __get_string_array_from_gptr_array(gp_array);
503 g_ptr_array_free(gp_array, TRUE);
506 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
507 BLUETOOTH_ERROR_NONE, &svc_char,
508 user_info->cb, user_info->user_data);
511 g_strfreev(svc_char.handle_info.handle);
512 g_free(svc_char.service_handle);
513 g_variant_iter_free(char_iter);
514 g_variant_unref(value);
515 g_object_unref(proxy);
516 g_variant_unref(char_value);
519 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
520 const char *service_handle)
522 GDBusProxy *properties_proxy = NULL;
523 GDBusConnection *g_conn;
524 GError *error = NULL;
529 BT_CHECK_PARAMETER(service_handle, return);
530 BT_CHECK_ENABLED(return);
532 g_conn = _bt_get_system_private_conn();
533 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
535 properties_proxy = g_dbus_proxy_new_sync(g_conn,
536 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
539 BT_PROPERTIES_INTERFACE,
542 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
544 handle = g_strdup(service_handle);
545 g_dbus_proxy_call(properties_proxy,
547 g_variant_new("(ss)",
548 GATT_SERV_INTERFACE, "Characteristics"),
549 G_DBUS_CALL_FLAGS_NONE,
552 (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
556 return BLUETOOTH_ERROR_NONE;
560 static int __get_permission_flag(char *permission)
564 retv_if(permission == NULL, ret);
566 if (!g_strcmp0(permission, "broadcast"))
567 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
568 else if (!g_strcmp0(permission, "read"))
569 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
570 else if (!g_strcmp0(permission, "write-without-response"))
571 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
572 else if (!g_strcmp0(permission, "write"))
573 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
574 else if (!g_strcmp0(permission, "notify"))
575 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
576 else if (!g_strcmp0(permission, "indicate"))
577 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
578 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
579 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
580 else if (!g_strcmp0(permission, "reliable-write"))
581 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
582 else if (!g_strcmp0(permission, "writable-auxiliaries"))
583 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
584 else if (!g_strcmp0(permission, "encrypt-read"))
585 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
586 else if (!g_strcmp0(permission, "encrypt-write"))
587 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
588 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
589 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
590 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
591 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
596 static void __convert_permission_flag_to_str(unsigned int permission)
598 char perm[200] = { 0, };
600 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
601 g_strlcat(perm, "broadcast ", sizeof(perm));
602 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ)
603 g_strlcat(perm, "read ", sizeof(perm));
604 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
605 g_strlcat(perm, "write-without-response ", sizeof(perm));
606 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE)
607 g_strlcat(perm, "write ", sizeof(perm));
608 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
609 g_strlcat(perm, "notify ", sizeof(perm));
610 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
611 g_strlcat(perm, "indicate ", sizeof(perm));
612 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
613 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
614 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
615 g_strlcat(perm, "reliable-write ", sizeof(perm));
616 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
617 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
618 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
619 g_strlcat(perm, "encrypt-read ", sizeof(perm));
620 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
621 g_strlcat(perm, "encrypt-write ", sizeof(perm));
622 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
623 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
624 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
625 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
627 BT_INFO("permission [0x%04x] : %s\n", permission, perm);
631 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
632 const char *char_handle, bt_gatt_char_property_t *characteristic)
634 GDBusProxy *properties_proxy = NULL;
635 GError *error = NULL;
636 GVariant *value = NULL;
637 GVariant *result = NULL;
638 GByteArray *gb_array = NULL;
639 GPtrArray *gp_array = NULL ;
640 GDBusConnection *g_conn;
644 char *char_desc_handle = NULL;
646 GVariantIter *property_iter;
647 GVariantIter *char_value_iter;
648 GVariantIter *char_perm_iter;
649 GVariantIter *char_desc_iter;
651 BT_CHECK_PARAMETER(char_handle, return);
652 BT_CHECK_PARAMETER(characteristic, return);
654 BT_CHECK_ENABLED(return);
656 g_conn = _bt_get_system_private_conn();
657 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
659 properties_proxy = g_dbus_proxy_new_sync(g_conn,
660 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
663 BT_PROPERTIES_INTERFACE,
666 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
668 result = g_dbus_proxy_call_sync(properties_proxy,
670 g_variant_new("(s)", GATT_CHAR_INTERFACE),
671 G_DBUS_CALL_FLAGS_NONE,
678 BT_ERR("Fail to get properties (Error: %s)", error->message);
679 g_clear_error(&error);
681 BT_ERR("Fail to get properties");
682 g_object_unref(properties_proxy);
683 return BLUETOOTH_ERROR_INTERNAL;
686 g_variant_get(result, "(a{sv})", &property_iter);
688 memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
689 characteristic->handle = g_strdup(char_handle);
691 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
692 if (!g_strcmp0(key, "UUID")) {
694 characteristic->uuid = g_variant_dup_string(value, &len);
695 bluetooth_get_uuid_name(characteristic->uuid, &name);
696 BT_INFO("%s %s [%s]", char_handle + 37, characteristic->uuid, name);
698 } else if (!g_strcmp0(key, "Value")) {
699 gb_array = g_byte_array_new();
700 g_variant_get(value, "ay", &char_value_iter);
701 while (g_variant_iter_loop(char_value_iter, "y", &char_value)) {
702 // BT_DBG("value of char = %d",char_value);
703 g_byte_array_append(gb_array, &char_value, 1);
705 g_variant_iter_free(char_value_iter);
707 if (gb_array->len != 0) {
708 characteristic->val = g_malloc0(gb_array->len *
709 sizeof(unsigned char));
710 memcpy(characteristic->val, gb_array->data, gb_array->len);
712 characteristic->val_len = gb_array->len;
713 g_byte_array_free(gb_array, TRUE);
714 } else if (!g_strcmp0(key, "Flags")) {
715 g_variant_get(value, "as", &char_perm_iter);
716 characteristic->permission = 0x00;
718 while (g_variant_iter_loop(char_perm_iter, "s", &permission))
719 characteristic->permission |= __get_permission_flag(permission);
720 __convert_permission_flag_to_str(characteristic->permission);
722 g_variant_iter_free(char_perm_iter);
723 } else if (!g_strcmp0(key, "Descriptors")) {
724 g_variant_get(value, "ao", &char_desc_iter);
725 gp_array = g_ptr_array_new();
726 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle))
727 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
729 g_variant_iter_free(char_desc_iter);
730 if (gp_array->len != 0) {
731 characteristic->char_desc_handle.count = gp_array->len;
732 characteristic->char_desc_handle.handle =
733 __get_string_array_from_gptr_array(gp_array);
735 g_ptr_array_free(gp_array, TRUE);
739 g_variant_iter_free(property_iter);
740 g_variant_unref(result);
741 g_object_unref(properties_proxy);
743 return BLUETOOTH_ERROR_NONE;
746 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
747 GAsyncResult *res, gpointer user_data)
750 GVariantIter *char_iter;
752 GError *error = NULL;
753 bt_user_info_t *user_info;
754 int ret = BLUETOOTH_ERROR_INTERNAL;
755 bt_gatt_char_property_t characteristic;
757 user_info = _bt_get_user_data(BT_COMMON);
759 value = g_dbus_proxy_call_finish(proxy, res, &error);
763 BT_ERR("Get service characteristics failed\n errCode[%x],"
764 "message[%s]\n", error->code, error->message);
765 g_clear_error(&error);
767 BT_ERR("Get service characteristics failed\n");
770 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
771 BLUETOOTH_ERROR_INTERNAL, NULL,
772 user_info->cb, user_info->user_data);
774 g_object_unref(proxy);
779 g_variant_get(value, "(ao)", &char_iter);
781 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
784 ret = bluetooth_gatt_get_characteristics_property(char_handle,
787 if (ret != BLUETOOTH_ERROR_NONE) {
788 BT_ERR("Get characteristic property failed(0x%08x)", ret);
790 if (g_strstr_len(characteristic.uuid, -1, user_data)) {
791 ret = BLUETOOTH_ERROR_NONE;
795 bluetooth_gatt_free_char_property(&characteristic);
799 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
800 &characteristic, user_info->cb, user_info->user_data);
803 bluetooth_gatt_free_char_property(&characteristic);
804 g_variant_iter_free(char_iter);
805 g_variant_unref(value);
809 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
810 const char *char_uuid)
812 GDBusProxy *properties_proxy = NULL;
813 GDBusConnection *g_conn;
814 GError *error = NULL;
817 BT_CHECK_PARAMETER(service_handle, return);
818 BT_CHECK_PARAMETER(char_uuid, return);
819 BT_CHECK_ENABLED(return);
821 g_conn = _bt_get_system_private_conn();
822 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
824 properties_proxy = g_dbus_proxy_new_sync(g_conn,
825 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
828 BT_PROPERTIES_INTERFACE,
831 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
833 uuid = g_strdup(char_uuid);
834 g_dbus_proxy_call(properties_proxy,
836 g_variant_new("(ss)",
837 GATT_SERV_INTERFACE, "Characteristics"),
838 G_DBUS_CALL_FLAGS_NONE,
841 (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
844 return BLUETOOTH_ERROR_NONE;
847 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
848 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
850 GDBusProxy *properties_proxy = NULL;
851 GError *error = NULL;
852 GDBusConnection *g_conn;
853 GVariant *result = NULL;
854 GVariantIter *property_iter;
858 GVariant *value = NULL;
859 GByteArray *gb_array = NULL;
860 GVariantIter *desc_value_iter;
862 BT_CHECK_PARAMETER(descriptor_handle, return);
863 BT_CHECK_PARAMETER(descriptor, return);
865 BT_CHECK_ENABLED(return);
867 g_conn = _bt_get_system_private_conn();
868 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
870 properties_proxy = g_dbus_proxy_new_sync(g_conn,
871 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
874 BT_PROPERTIES_INTERFACE,
877 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
879 result = g_dbus_proxy_call_sync(properties_proxy,
881 g_variant_new("(s)", GATT_DESC_INTERFACE),
882 G_DBUS_CALL_FLAGS_NONE,
889 BT_ERR("Fail to get properties (Error: %s)", error->message);
890 g_clear_error(&error);
892 BT_ERR("Fail to get properties");
893 g_object_unref(properties_proxy);
894 return BLUETOOTH_ERROR_INTERNAL;
897 g_variant_get(result, "(a{sv})", &property_iter);
899 memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
900 descriptor->handle = g_strdup(descriptor_handle);
902 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
903 if (!g_strcmp0(key, "UUID")) {
905 descriptor->uuid = g_variant_dup_string(value, &len);
906 bluetooth_get_uuid_name(descriptor->uuid, &name);
907 BT_INFO("Descriptor : %s [%s]", descriptor->uuid, name);
909 } else if (!g_strcmp0(key, "Value")) {
910 gb_array = g_byte_array_new();
911 g_variant_get(value, "ay", &desc_value_iter);
912 while (g_variant_iter_loop(desc_value_iter, "y", &char_value)) {
913 BT_DBG("value of descriptor = %d", char_value);
914 g_byte_array_append(gb_array, &char_value, 1);
916 g_variant_iter_free(desc_value_iter);
918 if (gb_array->len != 0) {
919 descriptor->val = g_malloc0(gb_array->len *
920 sizeof(unsigned char));
921 memcpy(descriptor->val, gb_array->data, gb_array->len);
923 descriptor->val_len = gb_array->len;
924 g_byte_array_free(gb_array, TRUE);
928 g_variant_iter_free(property_iter);
929 g_variant_unref(result);
930 g_object_unref(properties_proxy);
932 return BLUETOOTH_ERROR_NONE;
935 static int __bluetooth_get_att_error_code(GError *error, char *handle)
941 BT_ERR("Error : %s [%s]", error->message, handle + 15);
942 str = g_strrstr(error->message, "ATT error: 0x");
945 att_ecode = g_ascii_xdigit_value(str[len - 2]) << 4;
946 att_ecode += g_ascii_xdigit_value(str[len - 1]);
948 return BLUETOOTH_ATT_ERROR_INTERNAL;
951 case BLUETOOTH_ATT_ERROR_READ_NOT_PERMITTED:
952 BT_ERR("Read not permitted");
954 case BLUETOOTH_ATT_ERROR_WRITE_NOT_PERMITTED:
955 BT_ERR("Write not permitted");
957 case BLUETOOTH_ATT_ERROR_AUTHENTICATION:
958 case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
959 case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
960 BT_ERR("Not paired");
962 case BLUETOOTH_ATT_ERROR_INVALID_OFFSET:
963 BT_ERR("Invalid offset");
965 case BLUETOOTH_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
966 BT_ERR("Invalid Length");
968 case BLUETOOTH_ATT_ERROR_AUTHORIZATION:
969 BT_ERR("Operation not Authorized");
972 BT_ERR("default ecode");
976 if (att_ecode >= 0x80 && att_ecode <= 0x9F)
977 BT_ERR("Application error");
982 static void __bluetooth_internal_read_cb(GObject *source_object,
983 GAsyncResult *res, gpointer user_data)
985 GError *error = NULL;
986 GDBusConnection *system_gconn = NULL;
988 bt_user_info_t *user_info;
990 GByteArray *gp_byte_array = NULL;
993 bt_gatt_resp_data_t *resp_data = user_data;
997 system_gconn = _bt_get_system_private_conn();
998 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1000 user_info = _bt_get_user_data(BT_COMMON);
1003 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1004 g_clear_error(&error);
1009 g_variant_unref(value);
1014 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1015 g_clear_error(&error);
1017 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1018 att_ecode, resp_data,
1019 user_info->cb, user_info->user_data);
1024 gp_byte_array = g_byte_array_new();
1025 g_variant_get(value, "(ay)", &iter);
1027 while (g_variant_iter_loop(iter, "y", &g_byte))
1028 g_byte_array_append(gp_byte_array, &g_byte, 1);
1030 if (gp_byte_array->len != 0) {
1031 resp_data->len = gp_byte_array->len;
1032 resp_data->value = gp_byte_array->data;
1035 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1036 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1037 user_info->cb, user_info->user_data);
1040 g_byte_array_free(gp_byte_array, TRUE);
1041 g_variant_iter_free(iter);
1042 g_variant_unref(value);
1047 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *chr,
1050 GDBusConnection *conn;
1051 bt_gatt_resp_data_t *resp_data;
1052 GVariantBuilder *builder = NULL;
1055 BT_CHECK_PARAMETER(chr, return);
1056 BT_CHECK_ENABLED(return);
1058 conn = _bt_get_system_private_conn();
1059 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1061 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1062 resp_data->user_data = user_data;
1063 resp_data->handle = (char *)chr;
1065 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1068 g_variant_builder_add(builder, "{sv}", "offset",
1069 g_variant_new("q", offset));
1071 /* Device Object path*/
1072 // g_variant_builder_add(builder, "{sv}", "device",
1073 // g_variant_new_object("o", NULL));
1075 g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1076 "ReadValue", g_variant_new("(a{sv})", builder),
1077 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1078 (GAsyncReadyCallback)__bluetooth_internal_read_cb,
1079 (gpointer)resp_data);
1080 g_variant_builder_unref(builder);
1082 return BLUETOOTH_ERROR_NONE;
1085 static void __bluetooth_internal_write_cb(GObject *source_object,
1086 GAsyncResult *res, gpointer user_data)
1088 GError *error = NULL;
1089 GDBusConnection *system_gconn = NULL;
1090 bt_user_info_t *user_info;
1093 bt_gatt_resp_data_t *resp_data = user_data;
1095 system_gconn = _bt_get_system_private_conn();
1096 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1098 user_info = _bt_get_user_data(BT_COMMON);
1101 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1102 g_clear_error(&error);
1107 g_variant_unref(value);
1112 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1113 g_clear_error(&error);
1115 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1116 att_ecode, resp_data,
1117 user_info->cb, user_info->user_data);
1122 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1123 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1124 user_info->cb, user_info->user_data);
1127 g_variant_unref(value);
1131 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
1132 const char *char_handle, const guint8 *value, int length)
1134 GVariant *val, *options;
1135 GVariantBuilder *builder1;
1136 GVariantBuilder *builder2;
1137 GError *error = NULL;
1138 GDBusConnection *conn;
1143 BT_CHECK_PARAMETER(char_handle, return);
1144 BT_CHECK_PARAMETER(value, return);
1145 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1146 BT_CHECK_ENABLED(return);
1148 conn = _bt_get_system_private_conn();
1149 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1151 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1152 for (i = 0; i < length; i++)
1153 g_variant_builder_add(builder1, "y", value[i]);
1155 val = g_variant_new("ay", builder1);
1157 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1159 g_variant_builder_add(builder2, "{sv}", "offset",
1160 g_variant_new_uint16(offset));
1162 /* Device Object path*/
1163 // g_variant_builder_add(builder2, "{sv}", "device",
1164 // g_variant_new_object("o", NULL));
1166 options = g_variant_new("a{sv}", builder2);
1168 g_dbus_connection_call(conn,
1171 GATT_CHAR_INTERFACE,
1173 g_variant_new("(@ay@a{sv})",
1176 G_DBUS_CALL_FLAGS_NONE,
1178 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1183 BT_ERR("Set value Failed: %s", error->message);
1184 g_clear_error(&error);
1185 g_variant_builder_unref(builder1);
1186 return BLUETOOTH_ERROR_INTERNAL;
1188 g_variant_builder_unref(builder1);
1189 g_variant_builder_unref(builder2);
1192 return BLUETOOTH_ERROR_NONE;
1195 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1196 const char *chr, const guint8 *value, int length,
1197 guint8 write_type, gpointer user_data)
1199 GVariant *val, *options;
1200 GVariantBuilder *builder1;
1201 GVariantBuilder *builder2;
1202 GDBusConnection *conn;
1205 int ret = BLUETOOTH_ERROR_NONE;
1206 bt_gatt_resp_data_t *resp_data;
1208 BT_CHECK_PARAMETER(chr, return);
1209 BT_CHECK_PARAMETER(value, return);
1210 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1211 BT_CHECK_ENABLED_INTERNAL(return);
1213 conn = _bt_get_system_private_conn();
1214 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1216 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1218 for (i = 0; i < length; i++)
1219 g_variant_builder_add(builder1, "y", value[i]);
1221 val = g_variant_new("ay", builder1);
1223 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1225 g_variant_builder_add(builder2, "{sv}", "offset",
1226 g_variant_new_uint16(offset));
1228 /* Device Object path*/
1229 // g_variant_builder_add(builder2, "{sv}", "device",
1230 // g_variant_new_object("o", NULL));
1232 options = g_variant_new("a{sv}", builder2);
1234 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1235 resp_data->user_data = user_data;
1236 resp_data->handle = (char *)chr;
1238 g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1240 g_variant_new("(y@ay@a{sv})", write_type, val, options),
1242 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1243 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1244 (gpointer)resp_data);
1246 g_variant_builder_unref(builder1);
1247 g_variant_builder_unref(builder2);
1252 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1253 const char *char_handle, const guint8 *value, int length)
1255 GVariant *val, *options;
1256 GDBusConnection *conn;
1257 GVariantBuilder *builder1;
1258 GVariantBuilder *builder2;
1263 BT_CHECK_PARAMETER(char_handle, return);
1264 BT_CHECK_PARAMETER(value, return);
1265 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1266 BT_CHECK_ENABLED(return);
1268 conn = _bt_get_system_private_conn();
1269 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1271 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1273 for (i = 0; i < length; i++) {
1274 g_variant_builder_add(builder1, "y", value[i]);
1275 BT_DBG("value [] = %d", value[i]);
1278 val = g_variant_new("ay", builder1);
1280 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1282 g_variant_builder_add(builder2, "{sv}", "offset",
1283 g_variant_new_uint16(offset));
1285 /* Device Object path*/
1286 // g_variant_builder_add(builder2, "{sv}", "device",
1287 // g_variant_new_object("o", NULL));
1289 options = g_variant_new("a{sv}", builder2);
1291 g_dbus_connection_call(conn,
1294 GATT_CHAR_INTERFACE,
1296 g_variant_new("(@ay@a{sv})",
1299 G_DBUS_CALL_FLAGS_NONE,
1301 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1304 g_variant_builder_unref(builder1);
1305 g_variant_builder_unref(builder2);
1308 return BLUETOOTH_ERROR_NONE;
1311 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1312 bt_gatt_char_property_t *characteristic)
1315 GDBusProxy *properties_proxy = NULL;
1316 GError *error = NULL;
1317 GVariant *value = NULL;
1318 GVariant *result = NULL;
1319 GDBusConnection *g_conn;
1320 int i, ret = BLUETOOTH_ERROR_NONE;
1321 const char *uuid = NULL;
1323 GVariantIter *desc_value_iter, *property_iter;
1325 char_descriptor_type_t desc_type = TYPE_NONE;
1327 g_conn = _bt_get_system_private_conn();
1328 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1330 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1331 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1334 BT_PROPERTIES_INTERFACE,
1337 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1339 result = g_dbus_proxy_call_sync(properties_proxy,
1341 g_variant_new("(s)", GATT_DESC_INTERFACE),
1342 G_DBUS_CALL_FLAGS_NONE,
1348 if (error != NULL) {
1349 BT_ERR("Fail to get properties (Error: %s)", error->message);
1350 g_clear_error(&error);
1352 BT_ERR("Fail to get properties");
1353 g_object_unref(properties_proxy);
1354 return BLUETOOTH_ERROR_INTERNAL;
1356 g_variant_get(result, "(a{sv})", &property_iter);
1357 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1358 if (!g_strcmp0(key, "UUID")) {
1359 uuid = g_variant_get_string(value, &len);
1360 if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1361 BT_DBG("GATT_USER_DESC_UUID");
1362 desc_type = USER_DESC;
1363 } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1364 BT_DBG("GATT_CHAR_FORMAT");
1365 desc_type = CHAR_FORMAT;
1366 } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1367 BT_DBG("GATT_CHAR_CLIENT_CONF");
1368 desc_type = CLIENT_CONF;
1369 } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1370 BT_DBG("GATT_CHAR_SERVER_CONF");
1371 desc_type = SERVER_CONF;
1373 BT_DBG("descriptor uuid = %s", uuid);
1375 } else if (!g_strcmp0(key, "Value")) {
1376 switch (desc_type) {
1378 BT_DBG("Format descriptor");
1379 g_variant_get(value, "(yyqyq)",
1380 &(characteristic->format.format),
1381 &(characteristic->format.exponent),
1382 &(characteristic->format.unit),
1383 &(characteristic->format.name_space),
1384 &(characteristic->format.description));
1387 BT_DBG("User descriptor");
1388 g_variant_get(value, "ay", &desc_value_iter);
1389 len = g_variant_get_size((GVariant *)desc_value_iter);
1392 characteristic->description = (char *)g_malloc0(len + 1);
1394 for (i = 0; i < len; i++) {
1395 g_variant_iter_loop(desc_value_iter, "y",
1396 &characteristic->description[i]);
1397 BT_DBG("description = %s", characteristic->description);
1399 g_variant_iter_free(desc_value_iter);
1402 BT_DBG(" CLIENT_CONF");
1405 BT_DBG(" SERVER_CONF");
1413 g_variant_iter_free(property_iter);
1414 g_variant_unref(result);
1415 g_object_unref(properties_proxy);
1422 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1423 GAsyncResult *res, gpointer user_data)
1427 GVariant *char_value;
1428 GVariantIter *char_iter;
1430 GError *error = NULL;
1431 bt_user_info_t *user_info;
1432 bt_gatt_char_property_t characteristic = {0, };
1433 int ret = BLUETOOTH_ERROR_INTERNAL;
1435 user_info = _bt_get_user_data(BT_COMMON);
1437 value = g_dbus_proxy_call_finish(proxy, res, &error);
1438 characteristic.handle = user_data;
1440 if (value == NULL) {
1441 if (error != NULL) {
1442 BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1443 "message[%s]\n", error->code, error->message);
1444 g_clear_error(&error);
1446 BT_ERR("Get characteristic descriptor failed\n");
1449 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1450 BLUETOOTH_ERROR_INTERNAL, NULL,
1451 user_info->cb, user_info->user_data);
1453 g_free(characteristic.handle);
1454 g_object_unref(proxy);
1458 g_variant_get(value, "(v)", &char_value);
1459 g_variant_get(char_value, "ao", &char_iter);
1461 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
1462 BT_DBG("object path of descriptor = %s", char_handle);
1464 ret = __bluetooth_gatt_descriptor_iter(char_handle,
1466 BT_DBG("Descriptor read status [%d]", ret);
1471 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1472 ret, &characteristic, user_info->cb, user_info->user_data);
1474 bluetooth_gatt_free_char_property(&characteristic);
1476 g_variant_iter_free(char_iter);
1477 g_variant_unref(value);
1478 g_variant_unref(char_value);
1482 BT_EXPORT_API int bltooth_gatt_discover_characteristic_descriptor(
1483 const char *characteristic_handle)
1485 GDBusProxy *properties_proxy = NULL;
1486 GDBusConnection *g_conn;
1488 GError *error = NULL;
1490 BT_CHECK_PARAMETER(characteristic_handle, return);
1491 BT_CHECK_ENABLED(return);
1493 g_conn = _bt_get_system_private_conn();
1494 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1496 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1497 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1499 characteristic_handle,
1500 BT_PROPERTIES_INTERFACE,
1503 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1505 handle = g_strdup(characteristic_handle);
1506 g_dbus_proxy_call(properties_proxy,
1508 g_variant_new("(ss)",
1509 GATT_CHAR_INTERFACE, "Descriptors"),
1510 G_DBUS_CALL_FLAGS_NONE,
1512 (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1515 return BLUETOOTH_ERROR_NONE;
1518 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1522 GError *error = NULL;
1523 GDBusConnection *system_gconn = NULL;
1525 bt_user_info_t *user_info;
1526 GByteArray *gp_byte_array = NULL;
1530 bt_gatt_resp_data_t *resp_data = user_data;
1534 system_gconn = _bt_get_system_private_conn();
1535 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1537 user_info = _bt_get_user_data(BT_COMMON);
1540 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1541 g_clear_error(&error);
1546 g_variant_unref(value);
1551 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1552 g_clear_error(&error);
1554 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1555 att_ecode, resp_data,
1556 user_info->cb, user_info->user_data);
1561 gp_byte_array = g_byte_array_new();
1562 g_variant_get(value, "(ay)", &iter);
1564 while (g_variant_iter_loop(iter, "y", &g_byte))
1565 g_byte_array_append(gp_byte_array, &g_byte, 1);
1567 if (gp_byte_array->len != 0) {
1568 resp_data->len = gp_byte_array->len;
1569 resp_data->value = gp_byte_array->data;
1572 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1573 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1574 user_info->cb, user_info->user_data);
1578 g_byte_array_free(gp_byte_array, TRUE);
1579 g_variant_iter_free(iter);
1580 g_variant_unref(value);
1585 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *desc,
1588 GDBusConnection *conn;
1589 GVariantBuilder *builder;
1591 bt_gatt_resp_data_t *resp_data;
1595 BT_CHECK_PARAMETER(desc, return);
1596 BT_CHECK_ENABLED(return);
1598 conn = _bt_get_system_private_conn();
1599 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1601 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1602 resp_data->user_data = user_data;
1603 resp_data->handle = (char *)desc;
1605 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1608 g_variant_builder_add(builder, "{sv}", "offset",
1609 g_variant_new("q", offset));
1610 /* Device Object path*/
1611 // g_variant_builder_add(builder, "{sv}", "device",
1612 // g_variant_new("o", serv_info->serv_path));
1614 g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1615 "ReadValue", g_variant_new("(a{sv})", builder),
1616 G_VARIANT_TYPE("(ay)"),
1617 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1618 (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1619 (gpointer)resp_data);
1620 g_variant_builder_unref(builder);
1623 return BLUETOOTH_ERROR_NONE;
1626 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1627 GAsyncResult *res, gpointer user_data)
1629 GError *error = NULL;
1630 bt_user_info_t *user_info;
1631 GDBusConnection *system_gconn = NULL;
1633 int att_ecode = BLUETOOTH_ATT_ERROR_NONE;
1634 bt_gatt_resp_data_t *resp_data = user_data;
1638 system_gconn = _bt_get_system_private_conn();
1639 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1641 user_info = _bt_get_user_data(BT_COMMON);
1644 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1645 g_clear_error(&error);
1650 g_variant_unref(value);
1655 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1656 g_clear_error(&error);
1658 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1659 att_ecode, resp_data,
1660 user_info->cb, user_info->user_data);
1665 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1666 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1667 user_info->cb, user_info->user_data);
1670 g_variant_unref(value);
1674 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(const char *desc,
1675 const guint8 *value, int length, gpointer user_data)
1677 GVariant *val, *options;
1678 GDBusConnection *conn;
1679 GVariantBuilder *builder1;
1680 GVariantBuilder *builder2;
1683 bt_gatt_resp_data_t *resp_data;
1687 BT_CHECK_PARAMETER(desc, return);
1688 BT_CHECK_PARAMETER(value, return);
1689 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1690 BT_CHECK_ENABLED(return);
1692 conn = _bt_get_system_private_conn();
1693 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1695 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1697 for (i = 0; i < length; i++)
1698 g_variant_builder_add(builder1, "y", value[i]);
1700 val = g_variant_new("ay", builder1);
1702 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1704 g_variant_builder_add(builder2, "{sv}", "offset",
1705 g_variant_new_uint16(offset));
1707 /* Device Object path*/
1708 // g_variant_builder_add(builder2, "{sv}", "device",
1709 // g_variant_new_object("o", NULL));
1711 options = g_variant_new("a{sv}", builder2);
1713 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1714 resp_data->user_data = user_data;
1715 resp_data->handle = (char *)desc;
1717 g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1718 "WriteValue", g_variant_new("(@ay@a{sv})",
1719 val, options), NULL,
1720 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1721 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1722 (gpointer)resp_data);
1724 g_variant_builder_unref(builder1);
1725 g_variant_builder_unref(builder2);
1728 return BLUETOOTH_ERROR_NONE;
1731 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle, const char *svc_name)
1733 GDBusConnection *conn;
1734 GError *error = NULL;
1735 int ret = BLUETOOTH_ERROR_NONE;
1737 BT_CHECK_PARAMETER(char_handle, return);
1738 BT_CHECK_ENABLED(return);
1740 BT_INFO_C("### Enable CCCD : %s [%s]", char_handle + 15, svc_name);
1742 conn = _bt_get_system_private_conn();
1743 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1745 g_dbus_connection_call_sync(conn,
1748 GATT_CHAR_INTERFACE,
1752 G_DBUS_CALL_FLAGS_NONE,
1753 GATT_DEFAULT_TIMEOUT, NULL, &error);
1756 g_dbus_error_strip_remote_error(error);
1757 BT_ERR_C("### Watch Failed: %s", error->message);
1758 if (g_strrstr(error->message, "Already notifying"))
1759 ret = BLUETOOTH_ERROR_NONE;
1760 else if (g_strrstr(error->message, "In Progress"))
1761 ret = BLUETOOTH_ERROR_IN_PROGRESS;
1762 else if (g_strrstr(error->message, "Operation is not supported"))
1763 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1764 /*failed because of either Insufficient Authorization or Write Not Permitted */
1765 else if (g_strrstr(error->message, "Write not permitted") ||
1766 g_strrstr(error->message, "Operation Not Authorized"))
1767 ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1768 /* failed because of either Insufficient Authentication,
1769 Insufficient Encryption Key Size, or Insufficient Encryption. */
1770 else if (g_strrstr(error->message, "Not paired"))
1771 ret = BLUETOOTH_ERROR_NOT_PAIRED;
1773 ret = BLUETOOTH_ERROR_INTERNAL;
1775 g_clear_error(&error);
1781 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1783 GDBusConnection *conn;
1784 GError *error = NULL;
1785 int ret = BLUETOOTH_ERROR_NONE;
1786 BT_CHECK_PARAMETER(char_handle, return);
1788 BT_CHECK_ENABLED(return);
1790 BT_INFO("Disable CCCD : %s", char_handle);
1792 conn = _bt_get_system_private_conn();
1793 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1795 g_dbus_connection_call_sync(conn,
1798 GATT_CHAR_INTERFACE,
1802 G_DBUS_CALL_FLAGS_NONE,
1803 GATT_DEFAULT_TIMEOUT, NULL, &error);
1806 BT_ERR("Watch Failed: %s", error->message);
1807 g_clear_error(&error);
1808 ret = BLUETOOTH_ERROR_INTERNAL;
1814 #ifdef TIZEN_GATT_CLIENT
1815 void __bt_uuid_hex_to_string(unsigned char *uuid, char *str)
1817 uint32_t uuid0, uuid4;
1818 uint16_t uuid1, uuid2, uuid3, uuid5;
1820 memcpy(&uuid0, &(uuid[0]), 4);
1821 memcpy(&uuid1, &(uuid[4]), 2);
1822 memcpy(&uuid2, &(uuid[6]), 2);
1823 memcpy(&uuid3, &(uuid[8]), 2);
1824 memcpy(&uuid4, &(uuid[10]), 4);
1825 memcpy(&uuid5, &(uuid[14]), 2);
1827 snprintf((char *)str, BLUETOOTH_UUID_STRING_MAX, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
1828 ntohl(uuid0), ntohs(uuid1),
1829 ntohs(uuid2), ntohs(uuid3),
1830 ntohl(uuid4), ntohs(uuid5));
1835 static void __bt_fill_service_handle_informations(bt_services_browse_info_t *props,
1836 bt_gatt_handle_info_t *svcs)
1840 if (props->count == 0)
1843 svcs->count = props->count;
1845 for (count = 0; count < props->count; count++) {
1846 BT_DBG("[%d] %s instance_id [%d] Is Primary [%d]",
1847 count, props->uuids[count], props->inst_id[count], props->primary[count]);
1848 g_strlcpy(svcs->uuids[count], props->uuids[count],
1849 BLUETOOTH_UUID_STRING_MAX);
1850 svcs->inst_id[count] = props->inst_id[count];
1854 static void __bt_fill_char_handle_informations(bt_char_browse_info_t *props, bt_gatt_service_property_t *service)
1857 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1859 service->char_handle.count = props->count;
1861 /* Before filling all char handles, fill the service's UUID and instance ID */
1862 __bt_uuid_hex_to_string(props->svc_uuid, uuid_string);
1863 service->uuid = g_strdup(uuid_string);
1864 service->primary = TRUE;
1866 /* Now fill all the char handles [UUID and Instance ID's]*/
1867 for (count = 0; count < props->count; count++) {
1868 BT_INFO("[%d] %s instance_id [%d] properties [%d]",
1869 count, props->uuids[count], props->inst_id[count], props->props[count]);
1871 g_strlcpy(service->char_handle.uuids[count],
1872 props->uuids[count],
1873 BLUETOOTH_UUID_STRING_MAX);
1875 service->char_handle.inst_id[count] = props->inst_id[count];
1879 static void __bt_fill_desc_handle_informations(bt_descriptor_browse_info_t *props,
1880 bt_gatt_char_property_t *charc)
1883 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1885 charc->char_desc_handle.count = props->count;
1887 /* Before filling all desc handles, fill the charac's UUID and instance ID */
1888 __bt_uuid_hex_to_string(props->char_uuid, uuid_string);
1889 charc->uuid = g_strdup(uuid_string);
1891 /* Now fill all the descriptor handles [UUID and Instance ID's]*/
1892 for (count = 0; count < props->count; count++) {
1893 BT_INFO("[%d] %s instance_id [%d]",
1894 count, props->uuids[count], props->inst_id[count]);
1896 g_strlcpy(charc->char_desc_handle.uuids[count],
1897 props->uuids[count],
1898 BLUETOOTH_UUID_STRING_MAX);
1900 charc->char_desc_handle.inst_id[count] = props->inst_id[count];
1902 charc->permission = props->char_props_map;
1903 __convert_permission_flag_to_str(charc->permission);
1907 BT_EXPORT_API int bluetooth_gatt_client_init(
1909 const bluetooth_device_address_t *address,
1910 gatt_client_cb_func_ptr callback_ptr)
1912 int ret = BLUETOOTH_ERROR_NONE;
1913 bt_event_info_t *event_info;
1916 BT_CHECK_PARAMETER(client_id, return);
1917 BT_CHECK_PARAMETER(callback_ptr, return);
1918 BT_CHECK_ENABLED(return);
1921 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1923 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1925 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_REGISTER,
1926 in_param1, in_param2, in_param3, in_param4, &out_param);
1928 /* App ID -1 is invalid */
1929 if (ret == BLUETOOTH_ERROR_NONE) {
1931 *client_id = g_array_index(out_param, int, 0);
1933 BT_INFO("GATT Client Registered successfully: Client instance ID [%d]", *client_id);
1935 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
1938 count = (int*)event_info->user_data;
1940 BT_INFO("Total num of GATT client instances [%d]", *count);
1942 /* Increement the count */
1945 BT_INFO("No GATT Client instances found in this application: Set User data");
1946 count = g_malloc0(sizeof(int));
1949 /* Register event handler for GATT */
1950 _bt_register_event(BT_GATT_CLIENT_EVENT,
1951 (void *)callback_ptr,
1953 _bt_set_user_data(BT_GATT_CLIENT, (void *)callback_ptr, NULL);
1956 BT_ERR("GATT Client Registration failed!! ret [%d]", ret);
1958 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1965 BT_EXPORT_API int bluetooth_gatt_client_get_primary_services(
1966 const bluetooth_device_address_t *address, /* Remote GATT Server */
1967 bt_gatt_handle_info_t *prim_svc) /* UUID & instance_id */
1970 int result = BLUETOOTH_ERROR_NONE;
1971 bt_services_browse_info_t service_props;
1973 BT_CHECK_PARAMETER(address, return);
1974 BT_CHECK_PARAMETER(prim_svc, return);
1975 BT_CHECK_ENABLED(return);
1978 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1979 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1981 result = _bt_send_request(BT_BLUEZ_SERVICE,
1982 BT_GATT_GET_PRIMARY_SERVICES,
1983 in_param1, in_param2, in_param3, in_param4, &out_param);
1985 if (BLUETOOTH_ERROR_NONE != result)
1988 memset(&service_props, 0x00, sizeof(bt_services_browse_info_t));
1990 service_props = g_array_index(
1991 out_param, bt_services_browse_info_t, 0);
1993 __bt_fill_service_handle_informations(
1994 &service_props, prim_svc);
1997 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2001 BT_EXPORT_API int bluetooth_gatt_client_get_service_property(
2002 const char *address,
2003 bt_gatt_handle_property_t *service_handle,
2004 bt_gatt_service_property_t *service)
2006 int result = BLUETOOTH_ERROR_NONE;
2007 bluetooth_gatt_client_svc_prop_info_t svc_prop;
2008 bt_char_browse_info_t char_handles_info;
2010 BT_CHECK_PARAMETER(address, return);
2011 BT_CHECK_PARAMETER(service_handle, return);
2012 BT_CHECK_PARAMETER(service, return);
2013 BT_CHECK_ENABLED(return);
2015 /* Call to bt-service (sync) and send address and service_handle info */
2017 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2019 memset(&svc_prop, 0x00, sizeof(bluetooth_gatt_client_svc_prop_info_t));
2020 /* All characteristics handles are discovered */
2021 memset(&char_handles_info, 0x00, sizeof(bt_char_browse_info_t));
2023 svc_prop.svc.instance_id = service_handle->instance_id;
2024 memcpy(&svc_prop.svc.uuid, &service_handle->uuid, 16);
2026 _bt_convert_addr_string_to_type(svc_prop.device_address.addr, address);
2028 g_array_append_vals(in_param1, &svc_prop, sizeof(bluetooth_gatt_client_svc_prop_info_t));
2030 result = _bt_send_request(BT_BLUEZ_SERVICE,
2031 BT_GATT_GET_SERVICE_PROPERTIES,
2032 in_param1, in_param2, in_param3, in_param4, &out_param);
2034 if (BLUETOOTH_ERROR_NONE != result)
2037 char_handles_info = g_array_index(
2038 out_param, bt_char_browse_info_t, 0);
2039 __bt_fill_char_handle_informations(&char_handles_info,
2041 /* TODO Get all Included Services */
2044 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2048 BT_EXPORT_API int bluetooth_gatt_client_get_characteristics_property(
2049 const char *address,
2050 bt_gatt_handle_property_t *service_handle,
2051 bt_gatt_handle_property_t *char_handle,
2052 bt_gatt_char_property_t *char_property)
2054 int result = BLUETOOTH_ERROR_NONE;
2055 bt_descriptor_browse_info_t desc_handles_info;
2056 bluetooth_gatt_client_char_prop_info_t char_prop;
2058 BT_CHECK_PARAMETER(address, return);
2059 BT_CHECK_PARAMETER(service_handle, return);
2060 BT_CHECK_PARAMETER(char_handle, return);
2061 BT_CHECK_PARAMETER(char_property, return);
2062 BT_CHECK_ENABLED(return);
2065 /* Call to bt-service (sync) and send address service_handle info & char handle info */
2067 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2069 memset(&char_prop, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2070 char_prop.svc.instance_id = service_handle->instance_id;
2071 memcpy(&char_prop.svc.uuid, &service_handle->uuid, 16);
2073 char_prop.characteristic.instance_id = char_handle->instance_id;
2074 memcpy(&char_prop.characteristic.uuid, &char_handle->uuid, 16);
2076 _bt_convert_addr_string_to_type(char_prop.device_address.addr, address);
2078 g_array_append_vals(in_param1, &char_prop, sizeof(bluetooth_gatt_client_char_prop_info_t));
2080 result = _bt_send_request(BT_BLUEZ_SERVICE,
2081 BT_GATT_GET_CHARACTERISTIC_PROPERTIES,
2082 in_param1, in_param2, in_param3, in_param4, &out_param);
2084 if (BLUETOOTH_ERROR_NONE != result)
2087 /* All descriptors handles are discovered */
2088 memset(&desc_handles_info, 0x00, sizeof(bt_descriptor_browse_info_t));
2090 desc_handles_info = g_array_index(
2091 out_param, bt_descriptor_browse_info_t, 0);
2093 __bt_fill_desc_handle_informations(&desc_handles_info,
2097 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2099 /* Call to bt-service (sync) and send address, service_handle & char_handle infos */
2101 /* After result is fetched, extract descriptor handles (UUID's & instance_id's) */
2103 /* Fill the info in *char_prop */
2105 /*No: Before returning, call bluetooth_gatt_client_read_characteristic_value as
2106 an asyn function and leave every thing else in the callback */
2109 BT_EXPORT_API int bluetooth_gatt_client_get_char_descriptor_property(
2110 const char *address,
2111 bt_gatt_handle_property_t *service_handle,
2112 bt_gatt_handle_property_t *char_handle,
2113 bt_gatt_handle_property_t *descriptor_handle,
2114 bt_gatt_char_descriptor_property_t *desc_prop)
2116 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
2118 BT_CHECK_PARAMETER(address, return);
2119 BT_CHECK_PARAMETER(service_handle, return);
2120 BT_CHECK_PARAMETER(char_handle, return);
2121 BT_CHECK_PARAMETER(descriptor_handle, return);
2122 BT_CHECK_PARAMETER(desc_prop, return);
2123 /* No Need to Call to bt-service (sync) and send address, service_handle,
2124 char_handle & descriptor handle infos */
2125 /* After result is fetched, extract descriptior handles (UUID's & instance_id's) */
2126 /* Fill the info in *desc_prop */
2127 __bt_uuid_hex_to_string(descriptor_handle->uuid, uuid_string);
2129 /* Before filling all desc handles, fill the charac's UUID and instance ID */
2130 desc_prop->uuid = g_strdup(uuid_string);
2132 return BLUETOOTH_ERROR_NONE;
2133 /* No: Before returning, call bluetooth_gatt_client_read_descriptor_value
2134 as an asyn function and leave every thing else in the callback */
2138 static gboolean bluetooth_gatt_client_notify_channel_watch_cb(GIOChannel *gio,
2139 GIOCondition cond, gpointer data)
2141 bt_gatt_characteristic_notify_info_t *chr_info = (bt_gatt_characteristic_notify_info_t *)data;
2144 BT_ERR("chr_info is invalid");
2147 if (cond & G_IO_IN) {
2148 GIOStatus status = G_IO_STATUS_NORMAL;
2150 char *buffer = NULL;
2152 bt_event_info_t *event_info;
2154 buffer = g_malloc0(chr_info->mtu + 1);
2155 memset(buffer, 0, chr_info->mtu + 1);
2157 status = g_io_channel_read_chars(gio, buffer,
2158 chr_info->mtu, &len, &err);
2159 if (status != G_IO_STATUS_NORMAL) {
2160 BT_ERR("IO Channel read is failed with %d", status);
2163 BT_ERR("IO Channel read error [%s]", err->message);
2164 if (status == G_IO_STATUS_ERROR) {
2165 BT_ERR("cond : %d", cond);
2167 g_io_channel_shutdown(gio, TRUE, NULL);
2168 g_io_channel_unref(gio);
2170 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2179 if (len > 0 && len < chr_info->mtu) {
2180 bt_gatt_char_property_t char_val;
2181 // 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);
2183 memcpy(char_val.prop.uuid, chr_info->UUID, 16);
2184 memcpy(char_val.value, buffer, len);
2185 char_val.val_len = len;
2186 memcpy(char_val.address, chr_info->address, 18);
2188 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2190 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
2191 BLUETOOTH_ERROR_NONE, &char_val,
2192 event_info->cb, event_info->user_data);
2194 BT_ERR("event_info failed");
2198 BT_ERR("Packet corrupted");
2205 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
2206 BT_ERR("Error : GIOCondition %d, [%s]", cond, chr_info->UUID);
2207 g_io_channel_shutdown(gio, TRUE, NULL);
2208 g_io_channel_unref(gio);
2210 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2219 #ifndef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2220 static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_get_characteristic_notify_info(unsigned char *handle , int id)
2224 for (l = gatt_characteristic_notify_list; l != NULL; l = l->next) {
2225 bt_gatt_characteristic_notify_info_t *info = l->data;
2226 if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
2233 static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_create_watch_io(int fd, int id, int mtu, char * address, unsigned char *uuid)
2235 GIOChannel *channel;
2236 bt_gatt_characteristic_notify_info_t *chr_info;
2238 chr_info = g_malloc0(sizeof(bt_gatt_characteristic_notify_info_t));
2239 chr_info->notify_fd = fd;
2241 chr_info->mtu = mtu;
2242 g_strlcpy(chr_info->address, address, 18);
2243 memcpy(chr_info->UUID, uuid, 16);
2245 channel = g_io_channel_unix_new(fd);
2247 chr_info->io_channel = channel;
2249 g_io_channel_set_encoding(channel, NULL, NULL);
2250 g_io_channel_set_buffered(channel, FALSE);
2251 g_io_channel_set_close_on_unref(channel, TRUE);
2252 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
2254 chr_info->watch_id = g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
2255 bluetooth_gatt_client_notify_channel_watch_cb, chr_info);
2261 BT_EXPORT_API int bluetooth_gatt_client_watch_characteristics(
2262 const char *address,
2263 bt_gatt_handle_property_t *service_handle,
2264 bt_gatt_handle_property_t *char_handle,
2267 gboolean is_indicate)
2269 int result = BLUETOOTH_ERROR_NONE;
2270 bluetooth_gatt_client_char_prop_info_t param;
2271 bt_gatt_characteristic_notify_info_t *chr_info;
2273 BT_CHECK_PARAMETER(address, return);
2274 BT_CHECK_PARAMETER(service_handle, return);
2275 BT_CHECK_PARAMETER(char_handle, return);
2277 #ifndef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2278 chr_info = bluetooth_gatt_client_get_characteristic_notify_info(char_handle->uuid , char_handle->instance_id);
2279 if (chr_info && !is_notify) {
2280 BT_INFO("Already CCCD enabled. fd %d", chr_info->notify_fd);
2282 if (chr_info->watch_id > 0)
2283 g_source_remove(chr_info->watch_id);
2285 if (chr_info->io_channel) {
2286 g_io_channel_shutdown(chr_info->io_channel, TRUE, NULL);
2287 g_io_channel_unref(chr_info->io_channel);
2290 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2298 /* ASync Function, result expected in callback from bt-service */
2301 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2303 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2305 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2306 param.svc.instance_id = service_handle->instance_id;
2308 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2309 param.characteristic.instance_id = char_handle->instance_id;
2311 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2313 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_char_prop_info_t));
2314 g_array_append_vals(in_param2, &client_id, sizeof(int));
2315 g_array_append_vals(in_param3, &is_notify, sizeof(gboolean));
2316 g_array_append_vals(in_param4, &is_indicate, sizeof(gboolean));
2318 #ifdef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2319 result = _bt_send_request(BT_BLUEZ_SERVICE,
2320 BT_GATT_WATCH_CHARACTERISTIC,
2321 in_param1, in_param2, in_param3, in_param4, &out_param);
2323 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2325 BT_INFO("Result [%d]", result);
2329 GUnixFDList *out_fd_list = NULL;
2330 char *svc_name = NULL;
2333 _bt_convert_uuid_type_to_string(str_uuid, param.svc.uuid);
2334 bluetooth_get_uuid_name(str_uuid, &svc_name);
2336 _bt_convert_uuid_type_to_string(str_uuid, param.characteristic.uuid);
2338 BT_INFO_C("### Request subscription Notify : %s [%s]", str_uuid, svc_name);
2341 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_WATCH_CHARACTERISTIC,
2342 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
2343 if (result != BLUETOOTH_ERROR_NONE) {
2344 BT_ERR("Fail to get Nofify FD. result %d", result);
2345 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2349 if (is_indicate == false) {
2350 if (NULL == out_fd_list) {
2351 BT_ERR("out_fd_list is NULL");
2352 result = BLUETOOTH_ERROR_INTERNAL;
2359 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
2360 BT_DBG("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
2361 fd = fd_list_array[0];
2362 mtu = g_array_index(out_param, int, 0);
2364 BT_INFO("Acquired characteristic Notify FD %d, mtu %d", fd, mtu);
2365 chr_info = bluetooth_gatt_client_create_watch_io(fd, char_handle->instance_id, mtu, (char *)address, char_handle->uuid);
2367 gatt_characteristic_notify_list = g_slist_append(gatt_characteristic_notify_list, chr_info);
2369 g_free(fd_list_array);
2370 g_object_unref(out_fd_list);
2374 /*result = _bt_send_request(BT_BLUEZ_SERVICE,
2375 BT_GATT_WATCH_CHARACTERISTIC,
2376 in_param1, in_param2, in_param3, in_param4, &out_param);*/
2378 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2383 BT_EXPORT_API int bluetooth_gatt_client_read_characteristic_value(
2384 const char *address,
2385 bt_gatt_handle_property_t *service_handle,
2386 bt_gatt_handle_property_t *char_handle)
2388 int result = BLUETOOTH_ERROR_NONE;
2389 bt_user_info_t *user_info;
2390 bluetooth_gatt_client_char_prop_info_t param;
2392 BT_CHECK_PARAMETER(address, return);
2393 BT_CHECK_PARAMETER(service_handle, return);
2394 BT_CHECK_PARAMETER(char_handle, return);
2396 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2397 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2400 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2402 /* Async Function, result expected in callback from bt-service */
2403 /* Call to bt-service (sync) and send address service_handle info & char handle info */
2404 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2406 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2407 param.svc.instance_id = service_handle->instance_id;
2409 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2410 param.characteristic.instance_id = char_handle->instance_id;
2412 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2414 g_array_append_vals(in_param1, ¶m,
2415 sizeof(bluetooth_gatt_client_char_prop_info_t));
2417 result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC,
2418 in_param1, in_param2, in_param3, in_param4,
2419 user_info->cb, user_info->user_data);
2421 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2425 BT_EXPORT_API int bluetooth_gatt_client_read_descriptor_value(
2426 const char *address,
2427 bt_gatt_handle_property_t *service_handle,
2428 bt_gatt_handle_property_t *char_handle,
2429 bt_gatt_handle_property_t *descriptor_handle)
2431 int result = BLUETOOTH_ERROR_NONE;
2432 bt_user_info_t *user_info;
2433 bluetooth_gatt_client_desc_prop_info_t param;
2435 BT_CHECK_PARAMETER(address, return);
2436 BT_CHECK_PARAMETER(service_handle, return);
2437 BT_CHECK_PARAMETER(char_handle, return);
2438 BT_CHECK_PARAMETER(descriptor_handle, return);
2440 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2441 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2444 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2446 /* Async Function, result expected in callback from bt-service */
2447 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2449 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2450 param.svc.instance_id = service_handle->instance_id;
2452 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2453 param.characteristic.instance_id = char_handle->instance_id;
2455 memcpy(¶m.descriptor.uuid, descriptor_handle->uuid, 16);
2456 param.descriptor.instance_id = descriptor_handle->instance_id;
2458 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2460 g_array_append_vals(in_param1, ¶m,
2461 sizeof(bluetooth_gatt_client_desc_prop_info_t));
2463 result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_DESCRIPTOR_VALUE,
2464 in_param1, in_param2, in_param3, in_param4,
2465 user_info->cb, user_info->user_data);
2467 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2472 static bt_gatt_characteristic_write_info_t * bluetooth_gatt_client_get_characteristic_fd(unsigned char *handle, int id)
2477 for (l = gatt_characteristic_write_list; l != NULL; l = l->next) {
2478 bt_gatt_characteristic_write_info_t *info = l->data;
2480 if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
2484 _bt_convert_uuid_type_to_string(str, handle);
2485 BT_ERR("Unable to get characteristic fd. [%s] id [ %d]", str, id);
2489 static gboolean bluetooth_gatt_client_write_channel_watch_cb(GIOChannel *gio,
2490 GIOCondition cond, gpointer data)
2492 bt_gatt_characteristic_write_info_t *chr_info = (bt_gatt_characteristic_write_info_t *)data;
2497 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
2498 BT_ERR("Error : GIOCondition %d, [%s]", cond, chr_info->UUID);
2499 g_io_channel_shutdown(gio, TRUE, NULL);
2500 g_io_channel_unref(gio);
2502 gatt_characteristic_write_list = g_slist_remove(gatt_characteristic_write_list, chr_info);
2511 static int bluetooth_gatt_client_write_characteristics_value_to_fd(
2512 int fd, const guint8 *value, int length, int mtu,
2516 int att_result = BLUETOOTH_ERROR_NONE;
2517 BT_CHECK_PARAMETER(value, return);
2518 written = write(fd, value, length);
2519 if (written != length) {
2520 att_result = BLUETOOTH_ERROR_INTERNAL;
2521 BT_ERR("write data failed. ret : %d ", written);
2527 static void bluetooth_gatt_client_create_write_io_channel(int fd, unsigned char * uuid, int id, int mtu)
2529 bt_gatt_characteristic_write_info_t *chr_info;
2530 GIOChannel *channel;
2532 chr_info = g_malloc0(sizeof(bt_gatt_characteristic_write_info_t));
2533 chr_info->write_fd = fd;
2535 chr_info->mtu = mtu;
2537 memcpy(chr_info->UUID, uuid, 16);
2538 channel = g_io_channel_unix_new(fd);
2539 g_io_channel_set_encoding(channel, NULL, NULL);
2540 g_io_channel_set_buffered(channel, FALSE);
2541 g_io_channel_set_close_on_unref(channel, TRUE);
2542 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
2543 g_io_add_watch(channel, (G_IO_ERR | G_IO_HUP | G_IO_NVAL),
2544 bluetooth_gatt_client_write_channel_watch_cb, chr_info);
2546 gatt_characteristic_write_list = g_slist_append(gatt_characteristic_write_list, chr_info);
2550 BT_EXPORT_API int bluetooth_gatt_client_write_characteristic_value_by_type(
2551 const char *address,
2552 bt_gatt_handle_property_t *service_handle,
2553 bt_gatt_handle_property_t *char_handle,
2554 bluetooth_gatt_att_data_t *data,
2555 bluetooth_gatt_write_type_e write_type)
2557 int result = BLUETOOTH_ERROR_NONE;
2558 bt_user_info_t *user_info;
2559 bluetooth_gatt_client_char_prop_info_t param;
2561 BT_CHECK_PARAMETER(address, return);
2562 BT_CHECK_PARAMETER(service_handle, return);
2563 BT_CHECK_PARAMETER(char_handle, return);
2564 BT_CHECK_PARAMETER(data, return);
2566 /* ASync Function, result expected in callback from bt-service */
2567 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2568 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2571 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2573 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2575 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2576 param.svc.instance_id = service_handle->instance_id;
2578 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2579 param.characteristic.instance_id = char_handle->instance_id;
2581 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2583 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_char_prop_info_t));
2584 g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2585 g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2587 #ifdef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2591 if (write_type == BLUETOOTH_GATT_TYPE_WRITE_NO_RESPONSE) {
2594 bt_gatt_characteristic_write_info_t *info;
2595 info = bluetooth_gatt_client_get_characteristic_fd(char_handle->uuid, service_handle->instance_id);
2598 fd = info->write_fd;
2604 GUnixFDList *out_fd_list = NULL;
2606 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_ACQUIRE_WRITE,
2607 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
2609 mtu = g_array_index(out_param, int, 0);
2611 if (result != BLUETOOTH_ERROR_NONE) {
2612 BT_ERR("Fail to get Write FD. result %d", result);
2613 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2615 } else if (NULL == out_fd_list) {
2616 BT_ERR("out_fd_list is NULL");
2617 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2618 return BLUETOOTH_ERROR_INTERNAL;
2623 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
2624 fd = fd_list_array[0];
2626 g_free(fd_list_array);
2627 g_object_unref(out_fd_list);
2629 BT_INFO("Acquired characteristic Write FD %d, mtu %d", fd, mtu);
2632 bluetooth_gatt_client_create_write_io_channel(fd, char_handle->uuid, service_handle->instance_id, mtu);
2634 result = bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
2637 BT_ERR("characteristic info FD is invalid");
2642 result = bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
2647 result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2648 BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE,
2649 in_param1, in_param2, in_param3, in_param4,
2650 user_info->cb, user_info->user_data);
2653 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2658 BT_EXPORT_API int bluetooth_gatt_client_write_descriptor_value(
2659 const char *address,
2660 bt_gatt_handle_property_t *service_handle,
2661 bt_gatt_handle_property_t *char_handle,
2662 bt_gatt_handle_property_t *descriptor_handle,
2663 bluetooth_gatt_att_data_t *data,
2664 bluetooth_gatt_write_type_e write_type)
2666 int result = BLUETOOTH_ERROR_NONE;
2667 bt_user_info_t *user_info;
2668 bluetooth_gatt_client_desc_prop_info_t param;
2670 BT_CHECK_PARAMETER(address, return);
2671 BT_CHECK_PARAMETER(service_handle, return);
2672 BT_CHECK_PARAMETER(char_handle, return);
2673 BT_CHECK_PARAMETER(descriptor_handle, return);
2674 BT_CHECK_PARAMETER(data, return);
2676 /* Async Function, result expected in callback from bt-service */
2677 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2678 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2681 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2683 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2685 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2686 param.svc.instance_id = service_handle->instance_id;
2688 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2689 param.characteristic.instance_id = char_handle->instance_id;
2691 memcpy(¶m.descriptor.uuid, descriptor_handle->uuid, 16);
2692 param.descriptor.instance_id = descriptor_handle->instance_id;
2694 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2696 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2697 g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2698 g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2700 result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2701 BT_GATT_WRITE_DESCRIPTOR_VALUE,
2702 in_param1, in_param2, in_param3, in_param4,
2703 user_info->cb, user_info->user_data);
2705 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2710 BT_EXPORT_API int bluetooth_gatt_client_set_service_change_watcher(
2711 const bluetooth_device_address_t *address, gboolean enable)
2714 bluetooth_device_address_t *addr = NULL;
2715 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2716 char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2717 int result = BLUETOOTH_ERROR_NONE;
2720 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2722 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
2723 g_array_append_vals(in_param2, &enable, sizeof(gboolean));
2725 _bt_convert_addr_type_to_string(device_address, (unsigned char *)address->addr);
2726 _bt_convert_addr_string_to_secure_string(secure_address, device_address);
2727 BT_INFO("%s watcher for [%s]", enable ? "Set":"Unset", secure_address);
2729 if (enable == TRUE) {
2730 if (_bluetooth_gatt_check_service_change_watcher_address(address)
2732 BT_INFO("The watcher is already set");
2736 if (service_monitor_list == NULL) {
2737 //_bt_register_manager_subscribe_signal(TRUE);
2739 result = _bt_send_request(BT_BLUEZ_SERVICE,
2740 BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2741 in_param1, in_param2, in_param3, in_param4, &out_param);
2744 if (result == BLUETOOTH_ERROR_NONE) {
2745 addr = g_malloc0(sizeof(bluetooth_device_address_t));
2746 memcpy(addr, address, sizeof(bluetooth_device_address_t));
2748 service_monitor_list =
2749 g_slist_append(service_monitor_list, addr);
2752 for (l = service_monitor_list; l != NULL; l = l->next) {
2755 if (!memcmp(address, addr,
2756 sizeof(bluetooth_device_address_t))) {
2757 service_monitor_list =
2758 g_slist_remove(service_monitor_list, addr);
2764 if (service_monitor_list == NULL) {
2765 //_bt_register_manager_subscribe_signal(FALSE);
2766 result = _bt_send_request(BT_BLUEZ_SERVICE,
2767 BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2768 in_param1, in_param2, in_param3, in_param4, &out_param);
2774 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2778 BT_EXPORT_API int bluetooth_gatt_client_deinit(
2783 bt_event_info_t *event_info;
2785 BT_CHECK_ENABLED(return);
2787 BT_INFO("GATT Client Deinit Client instance ID [%d]", client_id);
2790 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2792 g_array_append_vals(in_param1, &client_id, sizeof(int));
2794 /* Unregistration MUST NOT FAIL */
2795 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_UNREGISTER,
2796 in_param1, in_param2, in_param3, in_param4, &out_param);
2798 if (result != BLUETOOTH_ERROR_NONE)
2799 BT_ERR("GATT Client Unregistration failed result [%d]", result);
2801 BT_INFO("GATT Client Unregistration successful");
2803 /* Unregister event handler if this is the only instance */
2804 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2807 count = (int*)event_info->user_data;
2809 BT_INFO("Total num of GATT client instances [%d]", *count);
2812 BT_DBG("Currently only one GATT client instance, so remove it and unregister GATT client events");
2813 _bt_unregister_event(BT_GATT_CLIENT_EVENT);
2814 _bt_set_user_data(BT_GATT_CLIENT, NULL, NULL);
2818 BT_ERR("Impossible that client is created, but no event handler is registered!!!");
2820 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);