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)
55 BT_CHECK_PARAMETER(svc_pty, return);
57 #ifdef TIZEN_GATT_CLIENT
58 g_free(svc_pty->uuid);
60 g_free(svc_pty->uuid);
61 g_free(svc_pty->handle);
62 g_strfreev(svc_pty->include_handles.handle);
63 g_strfreev(svc_pty->char_handle.handle);
66 memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
69 return BLUETOOTH_ERROR_NONE;
72 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
76 BT_CHECK_PARAMETER(char_pty, return);
78 g_free(char_pty->uuid);
79 g_free(char_pty->name);
80 g_free(char_pty->description);
81 g_free(char_pty->val);
82 #ifndef TIZEN_GATT_CLIENT
83 g_free(char_pty->handle);
84 g_strfreev(char_pty->char_desc_handle.handle);
87 memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
90 return BLUETOOTH_ERROR_NONE;
93 BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty)
97 BT_CHECK_PARAMETER(desc_pty, return);
99 g_free(desc_pty->uuid);
100 g_free(desc_pty->val);
101 #ifndef TIZEN_GATT_CLIENT
102 g_free(desc_pty->handle);
105 memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t));
108 return BLUETOOTH_ERROR_NONE;
111 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
113 gchar *gp_path = NULL;
120 path = g_malloc0((gp->len + 1) * sizeof(char *));
122 for (i = 0; i < gp->len; i++) {
123 gp_path = g_ptr_array_index(gp, i);
124 path[i] = g_strdup(gp_path);
125 // BT_DBG("path[%d] : [%s]", i, path[i]);
131 gboolean _bluetooth_gatt_check_service_change_watcher_address(
132 const bluetooth_device_address_t *device_addr)
135 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
136 char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
138 _bt_convert_addr_type_to_string(device_address,
139 (unsigned char *)device_addr->addr);
141 for (l = service_monitor_list; l != NULL; l = l->next) {
142 char device_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
143 char secure_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
144 bluetooth_device_address_t *addr = l->data;
146 _bt_convert_addr_type_to_string(device_address2,
147 (unsigned char *)addr->addr);
148 _bt_convert_addr_string_to_secure_string(secure_address,
150 _bt_convert_addr_string_to_secure_string(secure_address2,
152 BT_INFO("service_monitor_list [%s] - Input [%s]",
153 secure_address2, secure_address);
155 if (!memcmp(device_addr, addr,
156 sizeof(bluetooth_device_address_t)))
163 BT_EXPORT_API int bluetooth_gatt_set_service_change_watcher(
164 const bluetooth_device_address_t *address, gboolean enable)
167 bluetooth_device_address_t *addr = NULL;
168 char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
170 _bt_convert_addr_type_to_secure_string(secure_address, (unsigned char *)address->addr);
171 BT_INFO("Set watcher for %s with %d", secure_address, enable);
173 if (enable == TRUE) {
174 if (_bluetooth_gatt_check_service_change_watcher_address(address)
176 BT_INFO("The watcher is already set");
177 return BLUETOOTH_ERROR_NONE;
180 if (service_monitor_list == NULL)
181 _bt_register_manager_subscribe_signal(TRUE);
183 addr = g_malloc0(sizeof(bluetooth_device_address_t));
184 memcpy(addr, address, sizeof(bluetooth_device_address_t));
186 service_monitor_list =
187 g_slist_append(service_monitor_list, addr);
189 for (l = service_monitor_list; l != NULL; l = l->next) {
192 if (!memcmp(address, addr,
193 sizeof(bluetooth_device_address_t))) {
194 service_monitor_list =
195 g_slist_remove(service_monitor_list, addr);
201 if (service_monitor_list == NULL)
202 _bt_register_manager_subscribe_signal(FALSE);
205 return BLUETOOTH_ERROR_NONE;
208 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
209 bt_gatt_service_property_t *service)
211 GDBusProxy *properties_proxy = NULL;
212 GError *error = NULL;
213 GVariant *result = NULL;
214 GDBusConnection *g_conn;
216 char *char_handle = NULL;
217 GPtrArray *gp_array = NULL ;
218 GVariantIter *property_iter, *char_iter = NULL;
222 BT_CHECK_PARAMETER(service_handle, return);
223 BT_CHECK_PARAMETER(service, return);
224 BT_CHECK_ENABLED(return);
226 g_conn = _bt_gdbus_get_system_gconn();
227 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
229 properties_proxy = g_dbus_proxy_new_sync(g_conn,
230 G_DBUS_PROXY_FLAGS_NONE, NULL,
233 BT_PROPERTIES_INTERFACE,
236 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
238 result = g_dbus_proxy_call_sync(properties_proxy,
240 g_variant_new("(s)", GATT_SERV_INTERFACE),
241 G_DBUS_CALL_FLAGS_NONE,
248 BT_ERR("Fail to get properties (Error: %s)", error->message);
249 g_clear_error(&error);
251 BT_ERR("Fail to get properties");
252 g_object_unref(properties_proxy);
253 return BLUETOOTH_ERROR_INTERNAL;
256 g_variant_get(result, "(a{sv})", &property_iter);
258 memset(service, 0, sizeof(bt_gatt_service_property_t));
260 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
261 if (!g_strcmp0(key, "UUID")) {
263 service->uuid = g_variant_dup_string(value, &len);
264 bluetooth_get_uuid_name(service->uuid, &name);
265 BT_INFO("%s %s [%s]", service_handle + 37, service->uuid, name);
267 } else if (!g_strcmp0(key, "Primary")) {
268 service->primary = g_variant_get_boolean(value);
270 } else if (!g_strcmp0(key, "Includes")) {
271 g_variant_get(value, "ao", &char_iter);
272 if (char_iter != NULL) {
273 gp_array = g_ptr_array_new();
274 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
275 g_ptr_array_add(gp_array, (gpointer)char_handle);
277 if (gp_array->len != 0) {
278 service->include_handles.count = gp_array->len;
279 service->include_handles.handle =
280 __get_string_array_from_gptr_array(gp_array);
282 g_ptr_array_free(gp_array, TRUE);
283 g_variant_iter_free(char_iter);
285 } else if (!g_strcmp0(key, "Characteristics")) {
286 g_variant_get(value, "ao", &char_iter);
287 if (char_iter != NULL) {
288 gp_array = g_ptr_array_new();
289 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
290 g_ptr_array_add(gp_array, (gpointer)char_handle);
292 if (gp_array->len != 0) {
293 service->char_handle.count = gp_array->len;
294 service->char_handle.handle =
295 __get_string_array_from_gptr_array(gp_array);
297 g_ptr_array_free(gp_array, TRUE);
298 g_variant_iter_free(char_iter);
300 BT_DBG("Characteristics count : %d", service->char_handle.count);
304 service->handle = g_strdup(service_handle);
306 g_variant_iter_free(property_iter);
307 g_variant_unref(result);
308 g_object_unref(properties_proxy);
310 return BLUETOOTH_ERROR_NONE;
313 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
314 const bluetooth_device_address_t *address,
315 bt_gatt_handle_info_t *prim_svc)
317 GVariant *result = NULL;
319 GVariantIter *svc_iter;
320 GVariantIter *interface_iter;
321 char *object_path = NULL;
322 char *interface_str = NULL;
323 const gchar *key = NULL;
324 GVariant *value = NULL;
325 GPtrArray *gp_array = NULL;
326 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
327 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
328 int ret = BLUETOOTH_ERROR_INTERNAL;
332 BT_CHECK_PARAMETER(address, return);
333 BT_CHECK_PARAMETER(prim_svc, return);
334 BT_CHECK_ENABLED(return);
336 result = _bt_get_managed_objects();
340 _bt_convert_addr_type_to_string(device_address,
341 (unsigned char *)address->addr);
343 gp_array = g_ptr_array_new();
344 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
346 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
348 if (object_path == NULL)
351 _bt_convert_device_path_to_address(object_path, temp_address);
353 if (g_strcmp0(temp_address, device_address) != 0)
356 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
357 &interface_str, &svc_iter)) {
358 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
361 BT_DBG("[%d] Object Path : %s", idx++, object_path);
362 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
363 if (g_strcmp0(key, "Primary") == 0) {
364 if (g_variant_get_boolean(value))
365 g_ptr_array_add(gp_array, (gpointer)object_path);
371 if (gp_array->len == 0) {
372 BT_ERR("gp_array is NULL");
373 ret = BLUETOOTH_ERROR_NOT_FOUND;
375 ret = BLUETOOTH_ERROR_NONE;
376 prim_svc->count = gp_array->len;
377 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
380 g_ptr_array_free(gp_array, TRUE);
381 g_variant_iter_free(iter);
382 g_variant_unref(result);
387 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
388 const char *service_uuid,
389 bt_gatt_service_property_t *service)
391 GVariant *result = NULL;
393 GVariantIter *svc_iter;
394 GVariantIter *interface_iter;
395 char *object_path = NULL;
396 char *interface_str = NULL;
397 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
398 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
399 int ret = BLUETOOTH_ERROR_INTERNAL;
401 BT_CHECK_PARAMETER(address, return);
402 BT_CHECK_PARAMETER(service_uuid, return);
403 BT_CHECK_PARAMETER(service, return);
404 BT_CHECK_ENABLED(return);
406 result = _bt_get_managed_objects();
410 _bt_convert_addr_type_to_string(device_address,
411 (unsigned char *)address->addr);
413 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
415 while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
417 if (object_path == NULL)
420 _bt_convert_device_path_to_address(object_path,
423 if (g_strcmp0(temp_address, device_address) != 0)
426 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
427 &interface_str, &svc_iter)) {
428 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
431 BT_DBG("Object Path: %s", object_path);
432 ret = bluetooth_gatt_get_service_property(object_path,
435 if (ret != BLUETOOTH_ERROR_NONE) {
436 BT_ERR("Get service property failed(0x%08x)", ret);
438 if (service->primary == TRUE &&
439 g_strstr_len(service->uuid, -1,
441 ret = BLUETOOTH_ERROR_NONE;
445 bluetooth_gatt_free_service_property(service);
450 g_variant_iter_free(iter);
451 g_variant_unref(result);
456 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
457 GAsyncResult *res, gpointer user_data)
460 GVariant *char_value;
461 GVariantIter *char_iter;
462 GPtrArray *gp_array = NULL;
463 bt_gatt_discovered_char_t svc_char = { 0, };
465 GError *error = NULL;
466 bt_user_info_t *user_info;
470 user_info = _bt_get_user_data(BT_COMMON);
471 svc_char.service_handle = user_data;
473 value = g_dbus_proxy_call_finish(proxy, res, &error);
477 BT_ERR("Get service characteristics failed\n errCode[%x],"
478 "message[%s]\n", error->code, error->message);
479 g_clear_error(&error);
481 BT_ERR("Get service characteristics failed\n");
484 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
485 BLUETOOTH_ERROR_INTERNAL, NULL,
486 user_info->cb, user_info->user_data);
488 g_free(svc_char.service_handle);
489 g_object_unref(proxy);
493 g_variant_get(value, "(v)", &char_value);
494 g_variant_get(char_value, "ao", &char_iter);
496 gp_array = g_ptr_array_new();
497 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
498 g_ptr_array_add(gp_array, (gpointer)char_handle);
500 if (gp_array->len != 0) {
501 svc_char.handle_info.count = gp_array->len;
502 svc_char.handle_info.handle =
503 __get_string_array_from_gptr_array(gp_array);
505 g_ptr_array_free(gp_array, TRUE);
508 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
509 BLUETOOTH_ERROR_NONE, &svc_char,
510 user_info->cb, user_info->user_data);
513 g_strfreev(svc_char.handle_info.handle);
514 g_free(svc_char.service_handle);
515 g_variant_iter_free(char_iter);
516 g_variant_unref(value);
517 g_object_unref(proxy);
520 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
521 const char *service_handle)
523 GDBusProxy *properties_proxy = NULL;
524 GDBusConnection *g_conn;
525 GError *error = NULL;
530 BT_CHECK_PARAMETER(service_handle, return);
531 BT_CHECK_ENABLED(return);
533 g_conn = _bt_gdbus_get_system_gconn();
534 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
536 properties_proxy = g_dbus_proxy_new_sync(g_conn,
537 G_DBUS_PROXY_FLAGS_NONE, NULL,
540 BT_PROPERTIES_INTERFACE,
543 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
545 handle = g_strdup(service_handle);
546 g_dbus_proxy_call(properties_proxy,
548 g_variant_new("(ss)",
549 GATT_SERV_INTERFACE, "Characteristics"),
550 G_DBUS_CALL_FLAGS_NONE,
553 (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
557 return BLUETOOTH_ERROR_NONE;
561 static int __get_permission_flag(char *permission)
565 retv_if(permission == NULL, ret);
567 if (!g_strcmp0(permission, "broadcast"))
568 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
569 else if (!g_strcmp0(permission, "read"))
570 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
571 else if (!g_strcmp0(permission, "write-without-response"))
572 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
573 else if (!g_strcmp0(permission, "write"))
574 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
575 else if (!g_strcmp0(permission, "notify"))
576 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
577 else if (!g_strcmp0(permission, "indicate"))
578 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
579 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
580 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
581 else if (!g_strcmp0(permission, "reliable-write"))
582 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
583 else if (!g_strcmp0(permission, "writable-auxiliaries"))
584 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
585 else if (!g_strcmp0(permission, "encrypt-read"))
586 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
587 else if (!g_strcmp0(permission, "encrypt-write"))
588 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
589 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
590 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
591 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
592 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
597 static void __convert_permission_flag_to_str(unsigned int permission)
599 char perm[200] = { 0, };
601 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
602 g_strlcat(perm, "broadcast ", sizeof(perm));
603 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ)
604 g_strlcat(perm, "read ", sizeof(perm));
605 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
606 g_strlcat(perm, "write-without-response ", sizeof(perm));
607 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE)
608 g_strlcat(perm, "write ", sizeof(perm));
609 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
610 g_strlcat(perm, "notify ", sizeof(perm));
611 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
612 g_strlcat(perm, "indicate ", sizeof(perm));
613 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
614 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
615 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
616 g_strlcat(perm, "reliable-write ", sizeof(perm));
617 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
618 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
619 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
620 g_strlcat(perm, "encrypt-read ", sizeof(perm));
621 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
622 g_strlcat(perm, "encrypt-write ", sizeof(perm));
623 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
624 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
625 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
626 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
628 BT_INFO("permission [0x%04x] : %s\n", permission, perm);
632 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
633 const char *char_handle, bt_gatt_char_property_t *characteristic)
635 GDBusProxy *properties_proxy = NULL;
636 GError *error = NULL;
637 GVariant *value = NULL;
638 GVariant *result = NULL;
639 GByteArray *gb_array = NULL;
640 GPtrArray *gp_array = NULL ;
641 GDBusConnection *g_conn;
645 char *char_desc_handle = NULL;
647 GVariantIter *property_iter;
648 GVariantIter *char_value_iter;
649 GVariantIter *char_perm_iter;
650 GVariantIter *char_desc_iter;
652 BT_CHECK_PARAMETER(char_handle, return);
653 BT_CHECK_PARAMETER(characteristic, return);
655 BT_CHECK_ENABLED(return);
657 g_conn = _bt_gdbus_get_system_gconn();
658 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
660 properties_proxy = g_dbus_proxy_new_sync(g_conn,
661 G_DBUS_PROXY_FLAGS_NONE, NULL,
664 BT_PROPERTIES_INTERFACE,
667 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
669 result = g_dbus_proxy_call_sync(properties_proxy,
671 g_variant_new("(s)", GATT_CHAR_INTERFACE),
672 G_DBUS_CALL_FLAGS_NONE,
679 BT_ERR("Fail to get properties (Error: %s)", error->message);
680 g_clear_error(&error);
682 BT_ERR("Fail to get properties");
683 g_object_unref(properties_proxy);
684 return BLUETOOTH_ERROR_INTERNAL;
687 g_variant_get(result, "(a{sv})", &property_iter);
689 memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
690 characteristic->handle = g_strdup(char_handle);
692 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
693 if (!g_strcmp0(key, "UUID")) {
695 characteristic->uuid = g_variant_dup_string(value, &len);
696 bluetooth_get_uuid_name(characteristic->uuid, &name);
697 BT_INFO("%s %s [%s]", char_handle + 37, characteristic->uuid, name);
699 } else if (!g_strcmp0(key, "Value")) {
700 gb_array = g_byte_array_new();
701 g_variant_get(value, "ay", &char_value_iter);
702 while (g_variant_iter_loop(char_value_iter, "y", &char_value)) {
703 // BT_DBG("value of char = %d",char_value);
704 g_byte_array_append(gb_array, &char_value, 1);
706 g_variant_iter_free(char_value_iter);
708 if (gb_array->len != 0) {
709 characteristic->val = g_malloc0(gb_array->len *
710 sizeof(unsigned char));
711 memcpy(characteristic->val, gb_array->data, gb_array->len);
713 characteristic->val_len = gb_array->len;
714 g_byte_array_free(gb_array, TRUE);
715 } else if (!g_strcmp0(key, "Flags")) {
716 g_variant_get(value, "as", &char_perm_iter);
717 characteristic->permission = 0x00;
719 while (g_variant_iter_loop(char_perm_iter, "s", &permission))
720 characteristic->permission |= __get_permission_flag(permission);
721 __convert_permission_flag_to_str(characteristic->permission);
723 g_variant_iter_free(char_perm_iter);
724 } else if (!g_strcmp0(key, "Descriptors")) {
725 g_variant_get(value, "ao", &char_desc_iter);
726 gp_array = g_ptr_array_new();
727 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle))
728 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
730 g_variant_iter_free(char_desc_iter);
731 if (gp_array->len != 0) {
732 characteristic->char_desc_handle.count = gp_array->len;
733 characteristic->char_desc_handle.handle =
734 __get_string_array_from_gptr_array(gp_array);
736 g_ptr_array_free(gp_array, TRUE);
740 g_variant_iter_free(property_iter);
741 g_variant_unref(result);
742 g_object_unref(properties_proxy);
744 return BLUETOOTH_ERROR_NONE;
747 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
748 GAsyncResult *res, gpointer user_data)
751 GVariantIter *char_iter;
753 GError *error = NULL;
754 bt_user_info_t *user_info;
755 int ret = BLUETOOTH_ERROR_INTERNAL;
756 bt_gatt_char_property_t characteristic;
758 user_info = _bt_get_user_data(BT_COMMON);
760 value = g_dbus_proxy_call_finish(proxy, res, &error);
764 BT_ERR("Get service characteristics failed\n errCode[%x],"
765 "message[%s]\n", error->code, error->message);
766 g_clear_error(&error);
768 BT_ERR("Get service characteristics failed\n");
771 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
772 BLUETOOTH_ERROR_INTERNAL, NULL,
773 user_info->cb, user_info->user_data);
775 g_object_unref(proxy);
780 g_variant_get(value, "(ao)", &char_iter);
782 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
785 ret = bluetooth_gatt_get_characteristics_property(char_handle,
788 if (ret != BLUETOOTH_ERROR_NONE) {
789 BT_ERR("Get characteristic property failed(0x%08x)", ret);
791 if (g_strstr_len(characteristic.uuid, -1, user_data)) {
792 ret = BLUETOOTH_ERROR_NONE;
796 bluetooth_gatt_free_char_property(&characteristic);
800 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
801 &characteristic, user_info->cb, user_info->user_data);
804 bluetooth_gatt_free_char_property(&characteristic);
805 g_variant_iter_free(char_iter);
806 g_variant_unref(value);
810 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
811 const char *char_uuid)
813 GDBusProxy *properties_proxy = NULL;
814 GDBusConnection *g_conn;
815 GError *error = NULL;
818 BT_CHECK_PARAMETER(service_handle, return);
819 BT_CHECK_PARAMETER(char_uuid, return);
820 BT_CHECK_ENABLED(return);
822 g_conn = _bt_gdbus_get_system_gconn();
823 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
825 properties_proxy = g_dbus_proxy_new_sync(g_conn,
826 G_DBUS_PROXY_FLAGS_NONE, NULL,
829 BT_PROPERTIES_INTERFACE,
832 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
834 uuid = g_strdup(char_uuid);
835 g_dbus_proxy_call(properties_proxy,
837 g_variant_new("(ss)",
838 GATT_SERV_INTERFACE, "Characteristics"),
839 G_DBUS_CALL_FLAGS_NONE,
842 (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
845 return BLUETOOTH_ERROR_NONE;
848 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
849 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
851 GDBusProxy *properties_proxy = NULL;
852 GError *error = NULL;
853 GDBusConnection *g_conn;
854 GVariant *result = NULL;
855 GVariantIter *property_iter;
859 GVariant *value = NULL;
860 GByteArray *gb_array = NULL;
861 GVariantIter *desc_value_iter;
863 BT_CHECK_PARAMETER(descriptor_handle, return);
864 BT_CHECK_PARAMETER(descriptor, return);
866 BT_CHECK_ENABLED(return);
868 g_conn = _bt_gdbus_get_system_gconn();
869 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
871 properties_proxy = g_dbus_proxy_new_sync(g_conn,
872 G_DBUS_PROXY_FLAGS_NONE, NULL,
875 BT_PROPERTIES_INTERFACE,
878 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
880 result = g_dbus_proxy_call_sync(properties_proxy,
882 g_variant_new("(s)", GATT_DESC_INTERFACE),
883 G_DBUS_CALL_FLAGS_NONE,
890 BT_ERR("Fail to get properties (Error: %s)", error->message);
891 g_clear_error(&error);
893 BT_ERR("Fail to get properties");
894 g_object_unref(properties_proxy);
895 return BLUETOOTH_ERROR_INTERNAL;
898 g_variant_get(result, "(a{sv})", &property_iter);
900 memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
901 descriptor->handle = g_strdup(descriptor_handle);
903 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
904 if (!g_strcmp0(key, "UUID")) {
906 descriptor->uuid = g_variant_dup_string(value, &len);
907 bluetooth_get_uuid_name(descriptor->uuid, &name);
908 BT_INFO("Descriptor : %s [%s]", descriptor->uuid, name);
910 } else if (!g_strcmp0(key, "Value")) {
911 gb_array = g_byte_array_new();
912 g_variant_get(value, "ay", &desc_value_iter);
913 while (g_variant_iter_loop(desc_value_iter, "y", &char_value)) {
914 BT_DBG("value of descriptor = %d", char_value);
915 g_byte_array_append(gb_array, &char_value, 1);
917 g_variant_iter_free(desc_value_iter);
919 if (gb_array->len != 0) {
920 descriptor->val = g_malloc0(gb_array->len *
921 sizeof(unsigned char));
922 memcpy(descriptor->val, gb_array->data, gb_array->len);
924 descriptor->val_len = gb_array->len;
925 g_byte_array_free(gb_array, TRUE);
929 g_variant_iter_free(property_iter);
930 g_variant_unref(result);
931 g_object_unref(properties_proxy);
933 return BLUETOOTH_ERROR_NONE;
936 static int __bluetooth_get_att_error_code(GError *error, char *handle)
942 BT_ERR("Error : %s [%s]", error->message, handle + 15);
943 str = g_strrstr(error->message, "ATT error: 0x");
946 att_ecode = g_ascii_xdigit_value(str[len - 2]) << 4;
947 att_ecode += g_ascii_xdigit_value(str[len - 1]);
949 return BLUETOOTH_ATT_ERROR_INTERNAL;
952 case BLUETOOTH_ATT_ERROR_READ_NOT_PERMITTED:
953 BT_ERR("Read not permitted");
955 case BLUETOOTH_ATT_ERROR_WRITE_NOT_PERMITTED:
956 BT_ERR("Write not permitted");
958 case BLUETOOTH_ATT_ERROR_AUTHENTICATION:
959 case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
960 case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
961 BT_ERR("Not paired");
963 case BLUETOOTH_ATT_ERROR_INVALID_OFFSET:
964 BT_ERR("Invalid offset");
966 case BLUETOOTH_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
967 BT_ERR("Invalid Length");
969 case BLUETOOTH_ATT_ERROR_AUTHORIZATION:
970 BT_ERR("Operation not Authorized");
973 BT_ERR("default ecode");
977 if (att_ecode >= 0x80 && att_ecode <= 0x9F)
978 BT_ERR("Application error");
983 static void __bluetooth_internal_read_cb(GObject *source_object,
984 GAsyncResult *res, gpointer user_data)
986 GError *error = NULL;
987 GDBusConnection *system_gconn = NULL;
989 bt_user_info_t *user_info;
991 GByteArray *gp_byte_array = NULL;
994 bt_gatt_resp_data_t *resp_data = user_data;
998 system_gconn = _bt_gdbus_get_system_gconn();
999 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1001 user_info = _bt_get_user_data(BT_COMMON);
1004 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1005 g_clear_error(&error);
1010 g_variant_unref(value);
1015 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1016 g_clear_error(&error);
1018 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1019 att_ecode, resp_data,
1020 user_info->cb, user_info->user_data);
1025 gp_byte_array = g_byte_array_new();
1026 g_variant_get(value, "(ay)", &iter);
1028 while (g_variant_iter_loop(iter, "y", &g_byte))
1029 g_byte_array_append(gp_byte_array, &g_byte, 1);
1031 if (gp_byte_array->len != 0) {
1032 resp_data->len = gp_byte_array->len;
1033 resp_data->value = gp_byte_array->data;
1036 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1037 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1038 user_info->cb, user_info->user_data);
1041 g_byte_array_free(gp_byte_array, TRUE);
1042 g_variant_iter_free(iter);
1043 g_variant_unref(value);
1048 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *chr,
1051 GDBusConnection *conn;
1052 bt_gatt_resp_data_t *resp_data;
1053 GVariantBuilder *builder = NULL;
1056 BT_CHECK_PARAMETER(chr, return);
1057 BT_CHECK_ENABLED(return);
1059 conn = _bt_gdbus_get_system_gconn();
1060 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1062 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1063 resp_data->user_data = user_data;
1064 resp_data->handle = (char *)chr;
1066 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1069 g_variant_builder_add(builder, "{sv}", "offset",
1070 g_variant_new("q", offset));
1072 /* Device Object path*/
1073 // g_variant_builder_add(builder, "{sv}", "device",
1074 // g_variant_new_object("o", NULL));
1076 g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1077 "ReadValue", g_variant_new("(a{sv})", builder),
1078 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1079 (GAsyncReadyCallback)__bluetooth_internal_read_cb,
1080 (gpointer)resp_data);
1081 g_variant_builder_unref(builder);
1083 return BLUETOOTH_ERROR_NONE;
1086 static void __bluetooth_internal_write_cb(GObject *source_object,
1087 GAsyncResult *res, gpointer user_data)
1089 GError *error = NULL;
1090 GDBusConnection *system_gconn = NULL;
1091 bt_user_info_t *user_info;
1094 bt_gatt_resp_data_t *resp_data = user_data;
1096 system_gconn = _bt_gdbus_get_system_gconn();
1097 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1099 user_info = _bt_get_user_data(BT_COMMON);
1102 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1103 g_clear_error(&error);
1108 g_variant_unref(value);
1113 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1114 g_clear_error(&error);
1116 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1117 att_ecode, resp_data,
1118 user_info->cb, user_info->user_data);
1123 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1124 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1125 user_info->cb, user_info->user_data);
1128 g_variant_unref(value);
1132 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
1133 const char *char_handle, const guint8 *value, int length)
1135 GVariant *val, *options;
1136 GVariantBuilder *builder1;
1137 GVariantBuilder *builder2;
1138 GError *error = NULL;
1139 GDBusConnection *conn;
1144 BT_CHECK_PARAMETER(char_handle, return);
1145 BT_CHECK_PARAMETER(value, return);
1146 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1147 BT_CHECK_ENABLED(return);
1149 conn = _bt_gdbus_get_system_gconn();
1150 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1152 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1153 for (i = 0; i < length; i++)
1154 g_variant_builder_add(builder1, "y", value[i]);
1156 val = g_variant_new("ay", builder1);
1158 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1160 g_variant_builder_add(builder2, "{sv}", "offset",
1161 g_variant_new_uint16(offset));
1163 /* Device Object path*/
1164 // g_variant_builder_add(builder2, "{sv}", "device",
1165 // g_variant_new_object("o", NULL));
1167 options = g_variant_new("a{sv}", builder2);
1169 g_dbus_connection_call(conn,
1172 GATT_CHAR_INTERFACE,
1174 g_variant_new("(@ay@a{sv})",
1177 G_DBUS_CALL_FLAGS_NONE,
1179 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1184 BT_ERR("Set value Failed: %s", error->message);
1185 g_clear_error(&error);
1186 g_variant_builder_unref(builder1);
1187 return BLUETOOTH_ERROR_INTERNAL;
1189 g_variant_builder_unref(builder1);
1190 g_variant_builder_unref(builder2);
1193 return BLUETOOTH_ERROR_NONE;
1196 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1197 const char *chr, const guint8 *value, int length,
1198 guint8 write_type, gpointer user_data)
1200 GVariant *val, *options;
1201 GVariantBuilder *builder1;
1202 GVariantBuilder *builder2;
1203 GDBusConnection *conn;
1206 int ret = BLUETOOTH_ERROR_NONE;
1207 bt_gatt_resp_data_t *resp_data;
1209 BT_CHECK_PARAMETER(chr, return);
1210 BT_CHECK_PARAMETER(value, return);
1211 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1212 BT_CHECK_ENABLED_INTERNAL(return);
1214 conn = _bt_gdbus_get_system_gconn();
1215 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1217 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1219 for (i = 0; i < length; i++)
1220 g_variant_builder_add(builder1, "y", value[i]);
1222 val = g_variant_new("ay", builder1);
1224 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1226 g_variant_builder_add(builder2, "{sv}", "offset",
1227 g_variant_new_uint16(offset));
1229 /* Device Object path*/
1230 // g_variant_builder_add(builder2, "{sv}", "device",
1231 // g_variant_new_object("o", NULL));
1233 options = g_variant_new("a{sv}", builder2);
1235 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1236 resp_data->user_data = user_data;
1237 resp_data->handle = (char *)chr;
1239 g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1241 g_variant_new("(y@ay@a{sv})", write_type, val, options),
1243 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1244 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1245 (gpointer)resp_data);
1247 g_variant_builder_unref(builder1);
1248 g_variant_builder_unref(builder2);
1253 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1254 const char *char_handle, const guint8 *value, int length)
1256 GVariant *val, *options;
1257 GDBusConnection *conn;
1258 GVariantBuilder *builder1;
1259 GVariantBuilder *builder2;
1264 BT_CHECK_PARAMETER(char_handle, return);
1265 BT_CHECK_PARAMETER(value, return);
1266 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1267 BT_CHECK_ENABLED(return);
1269 conn = _bt_gdbus_get_system_gconn();
1270 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1272 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1274 for (i = 0; i < length; i++) {
1275 g_variant_builder_add(builder1, "y", value[i]);
1276 BT_DBG("value [] = %d", value[i]);
1279 val = g_variant_new("ay", builder1);
1281 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1283 g_variant_builder_add(builder2, "{sv}", "offset",
1284 g_variant_new_uint16(offset));
1286 /* Device Object path*/
1287 // g_variant_builder_add(builder2, "{sv}", "device",
1288 // g_variant_new_object("o", NULL));
1290 options = g_variant_new("a{sv}", builder2);
1292 g_dbus_connection_call(conn,
1295 GATT_CHAR_INTERFACE,
1297 g_variant_new("(@ay@a{sv})",
1300 G_DBUS_CALL_FLAGS_NONE,
1302 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1305 g_variant_builder_unref(builder1);
1306 g_variant_builder_unref(builder2);
1309 return BLUETOOTH_ERROR_NONE;
1312 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1313 bt_gatt_char_property_t *characteristic)
1316 GDBusProxy *properties_proxy = NULL;
1317 GError *error = NULL;
1318 GVariant *value = NULL;
1319 GVariant *result = NULL;
1320 GDBusConnection *g_conn;
1321 int i, ret = BLUETOOTH_ERROR_NONE;
1322 const char *uuid = NULL;
1324 GVariantIter *desc_value_iter, *property_iter;
1326 char_descriptor_type_t desc_type = TYPE_NONE;
1328 g_conn = _bt_gdbus_get_system_gconn();
1329 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1331 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1332 G_DBUS_PROXY_FLAGS_NONE, NULL,
1335 BT_PROPERTIES_INTERFACE,
1338 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1340 result = g_dbus_proxy_call_sync(properties_proxy,
1342 g_variant_new("(s)", GATT_DESC_INTERFACE),
1343 G_DBUS_CALL_FLAGS_NONE,
1349 if (error != NULL) {
1350 BT_ERR("Fail to get properties (Error: %s)", error->message);
1351 g_clear_error(&error);
1353 BT_ERR("Fail to get properties");
1354 g_object_unref(properties_proxy);
1355 return BLUETOOTH_ERROR_INTERNAL;
1357 g_variant_get(result, "(a{sv})", &property_iter);
1358 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1359 if (!g_strcmp0(key, "UUID")) {
1360 uuid = g_variant_get_string(value, &len);
1361 if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1362 BT_DBG("GATT_USER_DESC_UUID");
1363 desc_type = USER_DESC;
1364 } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1365 BT_DBG("GATT_CHAR_FORMAT");
1366 desc_type = CHAR_FORMAT;
1367 } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1368 BT_DBG("GATT_CHAR_CLIENT_CONF");
1369 desc_type = CLIENT_CONF;
1370 } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1371 BT_DBG("GATT_CHAR_SERVER_CONF");
1372 desc_type = SERVER_CONF;
1374 BT_DBG("descriptor uuid = %s", uuid);
1376 } else if (!g_strcmp0(key, "Value")) {
1377 switch (desc_type) {
1379 BT_DBG("Format descriptor");
1380 g_variant_get(value, "(yyqyq)",
1381 &(characteristic->format.format),
1382 &(characteristic->format.exponent),
1383 &(characteristic->format.unit),
1384 &(characteristic->format.name_space),
1385 &(characteristic->format.description));
1388 BT_DBG("User descriptor");
1389 g_variant_get(value, "ay", &desc_value_iter);
1390 len = g_variant_get_size((GVariant *)desc_value_iter);
1393 characteristic->description = (char *)g_malloc0(len + 1);
1395 for (i = 0; i < len; i++) {
1396 g_variant_iter_loop(desc_value_iter, "y",
1397 &characteristic->description[i]);
1398 BT_DBG("description = %s", characteristic->description);
1400 g_variant_iter_free(desc_value_iter);
1403 BT_DBG(" CLIENT_CONF");
1406 BT_DBG(" SERVER_CONF");
1414 g_variant_iter_free(property_iter);
1415 g_variant_unref(result);
1416 g_object_unref(properties_proxy);
1423 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1424 GAsyncResult *res, gpointer user_data)
1428 GVariant *char_value;
1429 GVariantIter *char_iter;
1431 GError *error = NULL;
1432 bt_user_info_t *user_info;
1433 bt_gatt_char_property_t characteristic = {0, };
1434 int ret = BLUETOOTH_ERROR_INTERNAL;
1436 user_info = _bt_get_user_data(BT_COMMON);
1438 value = g_dbus_proxy_call_finish(proxy, res, &error);
1439 characteristic.handle = user_data;
1441 if (value == NULL) {
1442 if (error != NULL) {
1443 BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1444 "message[%s]\n", error->code, error->message);
1445 g_clear_error(&error);
1447 BT_ERR("Get characteristic descriptor failed\n");
1450 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1451 BLUETOOTH_ERROR_INTERNAL, NULL,
1452 user_info->cb, user_info->user_data);
1454 g_free(characteristic.handle);
1455 g_object_unref(proxy);
1459 g_variant_get(value, "(v)", &char_value);
1460 g_variant_get(char_value, "ao", &char_iter);
1462 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
1463 BT_DBG("object path of descriptor = %s", char_handle);
1465 ret = __bluetooth_gatt_descriptor_iter(char_handle,
1467 BT_DBG("Descriptor read status [%d]", ret);
1472 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1473 ret, &characteristic, user_info->cb, user_info->user_data);
1475 bluetooth_gatt_free_char_property(&characteristic);
1477 g_variant_iter_free(char_iter);
1478 g_variant_unref(value);
1482 BT_EXPORT_API int bluetooth_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_gdbus_get_system_gconn();
1494 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1496 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1497 G_DBUS_PROXY_FLAGS_NONE, 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_gdbus_get_system_gconn();
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_gdbus_get_system_gconn();
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_gdbus_get_system_gconn();
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_gdbus_get_system_gconn();
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_gdbus_get_system_gconn();
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_gdbus_get_system_gconn();
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)
1839 BT_INFO("Total services found [%d]", props->count);
1841 if (props->count == 0)
1844 svcs->count = props->count;
1846 for (count = 0; count < props->count; count++) {
1847 BT_INFO("UUID[%d] = [%s] instance_id [%d] Is Primary [%d]",
1848 count, props->uuids[count], props->inst_id[count], props->primary[count]);
1849 g_strlcpy(svcs->uuids[count], props->uuids[count],
1850 BLUETOOTH_UUID_STRING_MAX);
1851 svcs->inst_id[count] = props->inst_id[count];
1855 static void __bt_fill_char_handle_informations(bt_char_browse_info_t *props, bt_gatt_service_property_t *service)
1858 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1859 BT_INFO("Total number of characteristics found [%d]",
1862 service->char_handle.count = props->count;
1864 /* Before filling all char handles, fill the service's UUID and instance ID */
1865 __bt_uuid_hex_to_string(props->svc_uuid, uuid_string);
1866 service->uuid = g_strdup(uuid_string);
1867 service->primary = TRUE;
1869 /* Now fill all the char handles [UUID and Instance ID's]*/
1870 for (count = 0; count < props->count; count++) {
1871 BT_INFO("UUID[%d] = [%s] instance_id [%d] properties [%d]",
1872 count, props->uuids[count], props->inst_id[count], props->props[count]);
1874 g_strlcpy(service->char_handle.uuids[count],
1875 props->uuids[count],
1876 BLUETOOTH_UUID_STRING_MAX);
1878 service->char_handle.inst_id[count] = props->inst_id[count];
1882 static void __bt_fill_desc_handle_informations(bt_descriptor_browse_info_t *props,
1883 bt_gatt_char_property_t *charc)
1886 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1887 BT_INFO("Total descriptor count found [%d]", props->count);
1889 charc->char_desc_handle.count = props->count;
1891 /* Before filling all desc handles, fill the charac's UUID and instance ID */
1892 __bt_uuid_hex_to_string(props->char_uuid, uuid_string);
1893 charc->uuid = g_strdup(uuid_string);
1895 /* Now fill all the descriptor handles [UUID and Instance ID's]*/
1896 for (count = 0; count < props->count; count++) {
1897 BT_INFO("UUID[%d] = [%s] instance_id [%d]",
1898 count, props->uuids[count], props->inst_id[count]);
1900 g_strlcpy(charc->char_desc_handle.uuids[count],
1901 props->uuids[count],
1902 BLUETOOTH_UUID_STRING_MAX);
1904 charc->char_desc_handle.inst_id[count] = props->inst_id[count];
1906 charc->permission = props->char_props_map;
1907 BT_INFO("Characteritic property map val [%d]", charc->permission);
1911 BT_EXPORT_API int bluetooth_gatt_client_init(
1913 const bluetooth_device_address_t *address,
1914 gatt_client_cb_func_ptr callback_ptr)
1916 int ret = BLUETOOTH_ERROR_NONE;
1917 bt_event_info_t *event_info;
1920 BT_CHECK_PARAMETER(client_id, return);
1921 BT_CHECK_PARAMETER(callback_ptr, return);
1922 BT_CHECK_ENABLED(return);
1927 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1929 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1931 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_REGISTER,
1932 in_param1, in_param2, in_param3, in_param4, &out_param);
1934 /* App ID -1 is invalid */
1935 if (ret == BLUETOOTH_ERROR_NONE) {
1937 *client_id = g_array_index(out_param, int, 0);
1939 BT_INFO("GATT Client Registered successfully: Client instance ID [%d]", *client_id);
1941 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
1944 count = (int*)event_info->user_data;
1946 BT_INFO("Total num of GATT client instances [%d]", *count);
1948 /* Increement the count */
1951 BT_INFO("No GATT Client instances found in this application: Set User data");
1952 count = g_malloc0(sizeof(int));
1955 /* Register event handler for GATT */
1956 _bt_register_event(BT_GATT_CLIENT_EVENT,
1957 (void *)callback_ptr,
1959 _bt_set_user_data(BT_GATT_CLIENT, (void *)callback_ptr, NULL);
1962 BT_ERR("GATT Client Registration failed!! ret [%d]", ret);
1964 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1971 BT_EXPORT_API int bluetooth_gatt_client_get_primary_services(
1972 const bluetooth_device_address_t *address, /* Remote GATT Server */
1973 bt_gatt_handle_info_t *prim_svc) /* UUID & instance_id */
1976 int result = BLUETOOTH_ERROR_NONE;
1977 bt_services_browse_info_t service_props;
1981 BT_CHECK_PARAMETER(address, return);
1982 BT_CHECK_PARAMETER(prim_svc, return);
1983 BT_CHECK_ENABLED(return);
1986 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1987 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1989 result = _bt_send_request(BT_BLUEZ_SERVICE,
1990 BT_GATT_GET_PRIMARY_SERVICES,
1991 in_param1, in_param2, in_param3, in_param4, &out_param);
1993 if (BLUETOOTH_ERROR_NONE != result)
1996 memset(&service_props, 0x00, sizeof(bt_services_browse_info_t));
1998 service_props = g_array_index(
1999 out_param, bt_services_browse_info_t, 0);
2001 __bt_fill_service_handle_informations(
2002 &service_props, prim_svc);
2005 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2006 BT_DBG("result = %d", result);
2010 BT_EXPORT_API int bluetooth_gatt_client_get_service_property(
2011 const char *address,
2012 bt_gatt_handle_property_t *service_handle,
2013 bt_gatt_service_property_t *service)
2015 int result = BLUETOOTH_ERROR_NONE;
2016 bluetooth_gatt_client_svc_prop_info_t svc_prop;
2017 bt_char_browse_info_t char_handles_info;
2018 BT_INFO("Remote Address [%s]", address);
2020 BT_CHECK_PARAMETER(address, return);
2021 BT_CHECK_PARAMETER(service_handle, return);
2022 BT_CHECK_PARAMETER(service, return);
2023 BT_CHECK_ENABLED(return);
2025 /* Call to bt-service (sync) and send address and service_handle info */
2027 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2029 memset(&svc_prop, 0x00, sizeof(bluetooth_gatt_client_svc_prop_info_t));
2030 /* All characteristics handles are discovered */
2031 memset(&char_handles_info, 0x00, sizeof(bt_char_browse_info_t));
2033 svc_prop.svc.instance_id = service_handle->instance_id;
2034 memcpy(&svc_prop.svc.uuid, &service_handle->uuid, 16);
2036 _bt_convert_addr_string_to_type(svc_prop.device_address.addr, address);
2038 g_array_append_vals(in_param1, &svc_prop, sizeof(bluetooth_gatt_client_svc_prop_info_t));
2040 result = _bt_send_request(BT_BLUEZ_SERVICE,
2041 BT_GATT_GET_SERVICE_PROPERTIES,
2042 in_param1, in_param2, in_param3, in_param4, &out_param);
2044 if (BLUETOOTH_ERROR_NONE != result)
2047 char_handles_info = g_array_index(
2048 out_param, bt_char_browse_info_t, 0);
2049 __bt_fill_char_handle_informations(&char_handles_info,
2051 /* TODO Get all Included Services */
2054 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2055 BT_INFO("result = %d", result);
2059 BT_EXPORT_API int bluetooth_gatt_client_get_characteristics_property(
2060 const char *address,
2061 bt_gatt_handle_property_t *service_handle,
2062 bt_gatt_handle_property_t *char_handle,
2063 bt_gatt_char_property_t *char_property)
2065 int result = BLUETOOTH_ERROR_NONE;
2066 bt_descriptor_browse_info_t desc_handles_info;
2067 bluetooth_gatt_client_char_prop_info_t char_prop;
2068 BT_INFO("Get Properties of characteristics from remote device [%s]", address);
2070 BT_CHECK_PARAMETER(address, return);
2071 BT_CHECK_PARAMETER(service_handle, return);
2072 BT_CHECK_PARAMETER(char_handle, return);
2073 BT_CHECK_PARAMETER(char_property, return);
2074 BT_CHECK_ENABLED(return);
2077 /* Call to bt-service (sync) and send address service_handle info & char handle info */
2079 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2081 memset(&char_prop, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2082 char_prop.svc.instance_id = service_handle->instance_id;
2083 memcpy(&char_prop.svc.uuid, &service_handle->uuid, 16);
2085 char_prop.characteristic.instance_id = char_handle->instance_id;
2086 memcpy(&char_prop.characteristic.uuid, &char_handle->uuid, 16);
2088 _bt_convert_addr_string_to_type(char_prop.device_address.addr, address);
2090 g_array_append_vals(in_param1, &char_prop, sizeof(bluetooth_gatt_client_char_prop_info_t));
2092 result = _bt_send_request(BT_BLUEZ_SERVICE,
2093 BT_GATT_GET_CHARACTERISTIC_PROPERTIES,
2094 in_param1, in_param2, in_param3, in_param4, &out_param);
2096 BT_INFO("result = [%d]", result);
2097 if (BLUETOOTH_ERROR_NONE != result)
2100 /* All descriptors handles are discovered */
2101 memset(&desc_handles_info, 0x00, sizeof(bt_descriptor_browse_info_t));
2103 desc_handles_info = g_array_index(
2104 out_param, bt_descriptor_browse_info_t, 0);
2106 __bt_fill_desc_handle_informations(&desc_handles_info,
2110 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2111 BT_INFO("result = %d", result);
2113 /* Call to bt-service (sync) and send address, service_handle & char_handle infos */
2115 /* After result is fetched, extract descriptor handles (UUID's & instance_id's) */
2117 /* Fill the info in *char_prop */
2119 /*No: Before returning, call bluetooth_gatt_client_read_characteristic_value as
2120 an asyn function and leave every thing else in the callback */
2123 BT_EXPORT_API int bluetooth_gatt_client_get_char_descriptor_property(
2124 const char *address,
2125 bt_gatt_handle_property_t *service_handle,
2126 bt_gatt_handle_property_t *char_handle,
2127 bt_gatt_handle_property_t *descriptor_handle,
2128 bt_gatt_char_descriptor_property_t *desc_prop)
2130 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
2131 BT_DBG("Remote Address [%s]", address);
2133 BT_CHECK_PARAMETER(address, return);
2134 BT_CHECK_PARAMETER(service_handle, return);
2135 BT_CHECK_PARAMETER(char_handle, return);
2136 BT_CHECK_PARAMETER(descriptor_handle, return);
2137 BT_CHECK_PARAMETER(desc_prop, return);
2138 /* No Need to Call to bt-service (sync) and send address, service_handle,
2139 char_handle & descriptor handle infos */
2140 /* After result is fetched, extract descriptior handles (UUID's & instance_id's) */
2141 /* Fill the info in *desc_prop */
2142 __bt_uuid_hex_to_string(descriptor_handle->uuid, uuid_string);
2144 /* Before filling all desc handles, fill the charac's UUID and instance ID */
2145 desc_prop->uuid = g_strdup(uuid_string);
2147 return BLUETOOTH_ERROR_NONE;
2148 /* No: Before returning, call bluetooth_gatt_client_read_descriptor_value
2149 as an asyn function and leave every thing else in the callback */
2153 static gboolean bluetooth_gatt_client_notify_channel_watch_cb(GIOChannel *gio,
2154 GIOCondition cond, gpointer data)
2156 bt_gatt_characteristic_notify_info_t *chr_info = (bt_gatt_characteristic_notify_info_t *)data;
2158 BT_INFO(" FD io NOTIFICATION recived\n");
2161 BT_ERR("char INFO nort recieved");
2164 if (cond & G_IO_IN) {
2165 GIOStatus status = G_IO_STATUS_NORMAL;
2167 char *buffer = NULL;
2169 bt_event_info_t *event_info;
2171 buffer = g_malloc0(chr_info->mtu + 1);
2172 memset(buffer, 0, chr_info->mtu + 1);
2174 status = g_io_channel_read_chars(gio, buffer,
2175 chr_info->mtu, &len, &err);
2176 if (status != G_IO_STATUS_NORMAL) {
2177 BT_ERR("IO Channel read is failed with %d", status);
2180 BT_ERR("IO Channel read error [%s]", err->message);
2181 if (status == G_IO_STATUS_ERROR) {
2182 BT_ERR("cond : %d", cond);
2184 g_io_channel_shutdown(gio, TRUE, NULL);
2185 g_io_channel_unref(gio);
2187 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2196 if (len > 0 && len < chr_info->mtu) {
2198 bt_gatt_char_property_t char_val;
2199 BT_INFO("FD io sending value changed %x %x %x %x %x %x %x %d \n", buffer[0], buffer[1], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], len);
2202 memcpy(char_val.prop.uuid, chr_info->UUID, 16);
2203 memcpy(char_val.value, buffer, len);
2204 char_val.val_len = len;
2205 memcpy(char_val.address, chr_info->address, 18);
2207 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2211 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
2212 BLUETOOTH_ERROR_NONE, &char_val,
2213 event_info->cb, event_info->user_data);
2215 BT_ERR("eventinfo failed");
2219 BT_ERR("Packet corrupted");
2224 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
2225 BT_ERR("Error : GIOCondition %d, [%s]", cond, chr_info->UUID);
2226 g_io_channel_shutdown(gio, TRUE, NULL);
2227 g_io_channel_unref(gio);
2229 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2238 static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_get_characteristic_notify_info(unsigned char *handle , int id)
2242 for (l = gatt_characteristic_notify_list; l != NULL; l = l->next) {
2243 bt_gatt_characteristic_notify_info_t *info = l->data;
2244 if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
2250 static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_create_watch_io(int fd, int id, int mtu, char * address, unsigned char *uuid)
2252 GIOChannel *channel;
2253 bt_gatt_characteristic_notify_info_t *chr_info;
2255 chr_info = g_malloc0(sizeof(bt_gatt_characteristic_notify_info_t));
2256 chr_info->notify_fd = fd;
2258 chr_info->mtu = mtu;
2259 g_strlcpy(chr_info->address, address, 18);
2260 memcpy(chr_info->UUID, uuid, 16);
2262 channel = g_io_channel_unix_new(fd);
2263 g_io_channel_set_encoding(channel, NULL, NULL);
2264 g_io_channel_set_buffered(channel, FALSE);
2265 g_io_channel_set_close_on_unref(channel, FALSE);
2266 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
2267 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
2268 bluetooth_gatt_client_notify_channel_watch_cb, chr_info);
2274 BT_EXPORT_API int bluetooth_gatt_client_watch_characteristics(
2275 const char *address,
2276 bt_gatt_handle_property_t *service_handle,
2277 bt_gatt_handle_property_t *char_handle,
2280 gboolean is_indicate)
2282 int result = BLUETOOTH_ERROR_NONE;
2283 bluetooth_gatt_client_char_prop_info_t param;
2284 bt_gatt_characteristic_notify_info_t *chr_info;
2288 BT_CHECK_PARAMETER(address, return);
2289 BT_CHECK_PARAMETER(service_handle, return);
2290 BT_CHECK_PARAMETER(char_handle, return);
2292 chr_info = bluetooth_gatt_client_get_characteristic_notify_info(char_handle->uuid , char_handle->instance_id);
2293 if (chr_info && !is_notify) {
2294 BT_INFO("Already CCCD enabled. fd %d", chr_info->notify_fd);
2296 close(chr_info->notify_fd);
2300 /* ASync Function, result expected in callback from bt-service */
2303 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2305 BT_INFO("Address [%s]", address);
2306 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2308 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2309 param.svc.instance_id = service_handle->instance_id;
2311 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2312 param.characteristic.instance_id = char_handle->instance_id;
2314 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2316 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_char_prop_info_t));
2317 g_array_append_vals(in_param2, &client_id, sizeof(int));
2318 g_array_append_vals(in_param3, &is_notify, sizeof(gboolean));
2319 g_array_append_vals(in_param4, &is_indicate, sizeof(gboolean));
2322 GUnixFDList *out_fd_list = NULL;
2324 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_WATCH_CHARACTERISTIC,
2325 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
2326 BT_DBG("result: %x", result);
2328 if (result != BLUETOOTH_ERROR_NONE) {
2329 BT_ERR("Fail to send request");
2330 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2334 if (is_indicate == false) {
2335 if (NULL == out_fd_list) {
2336 BT_ERR("out_fd_list is NULL");
2337 result = BLUETOOTH_ERROR_INTERNAL;
2344 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
2345 BT_INFO("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
2346 fd = fd_list_array[0];
2347 mtu = g_array_index(out_param, int, 0);
2349 chr_info = bluetooth_gatt_client_create_watch_io(fd, char_handle->instance_id, mtu, (char *)address, char_handle->uuid);
2351 gatt_characteristic_notify_list = g_slist_append(gatt_characteristic_notify_list, chr_info);
2353 g_free(fd_list_array);
2354 g_object_unref(out_fd_list);
2358 /*result = _bt_send_request(BT_BLUEZ_SERVICE,
2359 BT_GATT_WATCH_CHARACTERISTIC,
2360 in_param1, in_param2, in_param3, in_param4, &out_param);*/
2362 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2364 BT_INFO("Result [%d]", result);
2368 BT_EXPORT_API int bluetooth_gatt_client_read_characteristic_value(
2369 const char *address,
2370 bt_gatt_handle_property_t *service_handle,
2371 bt_gatt_handle_property_t *char_handle)
2373 int result = BLUETOOTH_ERROR_NONE;
2374 bt_user_info_t *user_info;
2375 bluetooth_gatt_client_char_prop_info_t param;
2378 BT_CHECK_PARAMETER(address, return);
2379 BT_CHECK_PARAMETER(service_handle, return);
2380 BT_CHECK_PARAMETER(char_handle, return);
2382 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2383 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2386 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2388 /* Async Function, result expected in callback from bt-service */
2389 /* Call to bt-service (sync) and send address service_handle info & char handle info */
2390 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2392 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2393 param.svc.instance_id = service_handle->instance_id;
2395 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2396 param.characteristic.instance_id = char_handle->instance_id;
2398 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2400 g_array_append_vals(in_param1, ¶m,
2401 sizeof(bluetooth_gatt_client_char_prop_info_t));
2404 result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC,
2405 in_param1, in_param2, in_param3, in_param4,
2406 user_info->cb, user_info->user_data);
2409 BT_INFO("result = [%d]", result);
2410 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2414 BT_EXPORT_API int bluetooth_gatt_client_read_descriptor_value(
2415 const char *address,
2416 bt_gatt_handle_property_t *service_handle,
2417 bt_gatt_handle_property_t *char_handle,
2418 bt_gatt_handle_property_t *descriptor_handle)
2420 int result = BLUETOOTH_ERROR_NONE;
2421 bt_user_info_t *user_info;
2422 bluetooth_gatt_client_desc_prop_info_t param;
2425 BT_CHECK_PARAMETER(address, return);
2426 BT_CHECK_PARAMETER(service_handle, return);
2427 BT_CHECK_PARAMETER(char_handle, return);
2428 BT_CHECK_PARAMETER(descriptor_handle, return);
2430 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2431 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2434 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2436 /* Async Function, result expected in callback from bt-service */
2437 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2439 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2440 param.svc.instance_id = service_handle->instance_id;
2442 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2443 param.characteristic.instance_id = char_handle->instance_id;
2445 memcpy(¶m.descriptor.uuid, descriptor_handle->uuid, 16);
2446 param.descriptor.instance_id = descriptor_handle->instance_id;
2448 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2450 g_array_append_vals(in_param1, ¶m,
2451 sizeof(bluetooth_gatt_client_desc_prop_info_t));
2454 result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_DESCRIPTOR_VALUE,
2455 in_param1, in_param2, in_param3, in_param4,
2456 user_info->cb, user_info->user_data);
2458 BT_INFO("result = [%d]", result);
2459 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2464 static bt_gatt_characteristic_write_info_t * bluetooth_gatt_client_get_characteristic_fd(unsigned char *handle, int id)
2468 _bt_convert_uuid_type_to_string(str, handle);
2469 BT_INFO("request found UUID [%s], sid [ %d]", str, id);
2470 for (l = gatt_characteristic_write_list; l != NULL; l = l->next) {
2471 bt_gatt_characteristic_write_info_t *info = l->data;
2472 _bt_convert_uuid_type_to_string(str, info->UUID);
2473 BT_INFO("UUID [%s], sid [ %d]" , str, info->id);
2474 if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
2480 static gboolean bluetooth_gatt_client_write_channel_watch_cb(GIOChannel *gio,
2481 GIOCondition cond, gpointer data)
2483 bt_gatt_characteristic_write_info_t *chr_info = (bt_gatt_characteristic_write_info_t *)data;
2488 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
2489 BT_ERR("Error : GIOCondition %d, [%s]", cond, chr_info->UUID);
2490 g_io_channel_shutdown(gio, TRUE, NULL);
2491 g_io_channel_unref(gio);
2493 gatt_characteristic_write_list = g_slist_remove(gatt_characteristic_write_list, chr_info);
2502 static int bluetooth_gatt_client_write_characteristics_value_to_fd(
2503 int fd, const guint8 *value, int length, int mtu,
2507 int att_result = BLUETOOTH_ERROR_NONE;
2508 BT_CHECK_PARAMETER(value, return);
2509 written = write(fd, value, length);
2510 if (written != length) {
2511 att_result = BLUETOOTH_ERROR_INTERNAL;
2512 BT_INFO("write data failed %d is ", written);
2514 BT_INFO("write data %s is sucess ", value);
2519 static void bluetooth_gatt_client_create_write_io_channel(int fd, unsigned char * uuid, int id, int mtu)
2521 bt_gatt_characteristic_write_info_t *chr_info;
2522 GIOChannel *channel;
2524 chr_info = g_malloc0(sizeof(bt_gatt_characteristic_write_info_t));
2525 chr_info->write_fd = fd;
2527 chr_info->mtu = mtu;
2529 memcpy(chr_info->UUID, uuid, 16);
2530 channel = g_io_channel_unix_new(fd);
2531 g_io_channel_set_encoding(channel, NULL, NULL);
2532 g_io_channel_set_buffered(channel, FALSE);
2533 g_io_channel_set_close_on_unref(channel, TRUE);
2534 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
2535 g_io_add_watch(channel, (G_IO_ERR | G_IO_HUP | G_IO_NVAL),
2536 bluetooth_gatt_client_write_channel_watch_cb, chr_info);
2538 gatt_characteristic_write_list = g_slist_append(gatt_characteristic_write_list, chr_info);
2542 BT_EXPORT_API int bluetooth_gatt_client_write_characteristic_value_by_type(
2543 const char *address,
2544 bt_gatt_handle_property_t *service_handle,
2545 bt_gatt_handle_property_t *char_handle,
2546 bluetooth_gatt_att_data_t *data,
2547 bluetooth_gatt_write_type_e write_type)
2549 int result = BLUETOOTH_ERROR_NONE;
2550 bt_user_info_t *user_info;
2551 bluetooth_gatt_client_char_prop_info_t param;
2554 BT_CHECK_PARAMETER(address, return);
2555 BT_CHECK_PARAMETER(service_handle, return);
2556 BT_CHECK_PARAMETER(char_handle, return);
2557 BT_CHECK_PARAMETER(data, return);
2559 /* ASync Function, result expected in callback from bt-service */
2560 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2561 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2564 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2566 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2568 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2569 param.svc.instance_id = service_handle->instance_id;
2571 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2572 param.characteristic.instance_id = char_handle->instance_id;
2574 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2576 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_char_prop_info_t));
2577 g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2578 g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2580 if (write_type == BLUETOOTH_GATT_TYPE_WRITE_NO_RESPONSE) {
2583 bt_gatt_characteristic_write_info_t *info;
2584 info = bluetooth_gatt_client_get_characteristic_fd(char_handle->uuid, service_handle->instance_id);
2587 fd = info->write_fd;
2593 GUnixFDList *out_fd_list = NULL;
2595 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_ACQUIRE_WRITE,
2596 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
2597 BT_DBG("result: %x", result);
2599 mtu = g_array_index(out_param, int, 0);
2601 if (result != BLUETOOTH_ERROR_NONE) {
2602 BT_ERR("Fail to send request");
2603 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2605 } else if (NULL == out_fd_list) {
2606 BT_ERR("out_fd_list is NULL");
2607 return BLUETOOTH_ERROR_INTERNAL;
2613 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2614 return BLUETOOTH_ERROR_INTERNAL;
2617 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
2618 BT_INFO("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
2619 fd = fd_list_array[0];
2621 g_free(fd_list_array);
2622 g_object_unref(out_fd_list);
2624 BT_INFO("Acquired characteristic fd %d --------------- mtu %d, ", fd, mtu);
2628 bluetooth_gatt_client_create_write_io_channel(fd, char_handle->uuid, service_handle->instance_id, mtu);
2630 result = bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
2633 BT_INFO(" characteristic info FD is invalid\n");
2638 BT_INFO("Acquired characteristic fd %d --------------- mtu %d, ", fd, mtu);
2639 result = bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
2644 result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2645 BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE,
2646 in_param1, in_param2, in_param3, in_param4,
2647 user_info->cb, user_info->user_data);
2650 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2655 BT_EXPORT_API int bluetooth_gatt_client_write_descriptor_value(
2656 const char *address,
2657 bt_gatt_handle_property_t *service_handle,
2658 bt_gatt_handle_property_t *char_handle,
2659 bt_gatt_handle_property_t *descriptor_handle,
2660 bluetooth_gatt_att_data_t *data,
2661 bluetooth_gatt_write_type_e write_type)
2663 int result = BLUETOOTH_ERROR_NONE;
2664 bt_user_info_t *user_info;
2665 bluetooth_gatt_client_desc_prop_info_t param;
2668 BT_CHECK_PARAMETER(address, return);
2669 BT_CHECK_PARAMETER(service_handle, return);
2670 BT_CHECK_PARAMETER(char_handle, return);
2671 BT_CHECK_PARAMETER(descriptor_handle, return);
2672 BT_CHECK_PARAMETER(data, return);
2674 /* Async Function, result expected in callback from bt-service */
2675 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2676 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2679 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2681 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2683 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2684 param.svc.instance_id = service_handle->instance_id;
2686 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2687 param.characteristic.instance_id = char_handle->instance_id;
2689 memcpy(¶m.descriptor.uuid, descriptor_handle->uuid, 16);
2690 param.descriptor.instance_id = descriptor_handle->instance_id;
2692 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2694 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2695 g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2696 g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2698 result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2699 BT_GATT_WRITE_DESCRIPTOR_VALUE,
2700 in_param1, in_param2, in_param3, in_param4,
2701 user_info->cb, user_info->user_data);
2703 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2708 BT_EXPORT_API int bluetooth_gatt_client_set_service_change_watcher(
2709 const bluetooth_device_address_t *address, gboolean enable)
2712 bluetooth_device_address_t *addr = NULL;
2713 char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2714 int result = BLUETOOTH_ERROR_NONE;
2719 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2721 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
2722 g_array_append_vals(in_param2, &enable, sizeof(gboolean));
2725 _bt_convert_addr_string_to_secure_string(secure_address, (const char *)address->addr);
2726 BT_INFO("Set watcher for %s with %d", secure_address, enable);
2728 if (enable == TRUE) {
2729 if (_bluetooth_gatt_check_service_change_watcher_address(address)
2731 BT_INFO("The watcher is already set");
2735 if (service_monitor_list == NULL) {
2736 //_bt_register_manager_subscribe_signal(TRUE);
2738 result = _bt_send_request(BT_BLUEZ_SERVICE,
2739 BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2740 in_param1, in_param2, in_param3, in_param4, &out_param);
2743 if (result == BLUETOOTH_ERROR_NONE) {
2744 addr = g_malloc0(sizeof(bluetooth_device_address_t));
2745 memcpy(addr, address, sizeof(bluetooth_device_address_t));
2747 service_monitor_list =
2748 g_slist_append(service_monitor_list, addr);
2751 for (l = service_monitor_list; l != NULL; l = l->next) {
2754 if (!memcmp(address, addr,
2755 sizeof(bluetooth_device_address_t))) {
2756 service_monitor_list =
2757 g_slist_remove(service_monitor_list, addr);
2763 if (service_monitor_list == NULL) {
2764 //_bt_register_manager_subscribe_signal(FALSE);
2765 result = _bt_send_request(BT_BLUEZ_SERVICE,
2766 BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2767 in_param1, in_param2, in_param3, in_param4, &out_param);
2773 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2777 BT_EXPORT_API int bluetooth_gatt_client_deinit(
2782 bt_event_info_t *event_info;
2784 BT_CHECK_ENABLED(return);
2786 BT_INFO("GATT Client Deinit Client instance ID [%d]", client_id);
2789 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2791 g_array_append_vals(in_param1, &client_id, sizeof(int));
2793 /* Unregistration MUST NOT FAIL */
2794 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_UNREGISTER,
2795 in_param1, in_param2, in_param3, in_param4, &out_param);
2797 if (result != BLUETOOTH_ERROR_NONE)
2798 BT_INFO("GATT Client Unregistration failed result [%d]", result);
2800 BT_INFO("GATT Client Unregistration successful");
2802 /* Unregister event handler if this is the only instance */
2803 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2806 count = (int*)event_info->user_data;
2808 BT_INFO("Total num of GATT client instances [%d]", *count);
2811 BT_INFO("Currently only one GATT client instance, so remove it and unregister GATT client events");
2812 _bt_unregister_event(BT_GATT_CLIENT_EVENT);
2813 _bt_set_user_data(BT_GATT_CLIENT, NULL, NULL);
2817 BT_ERR("Impossible that client is created, but no event handler is registered!!!");
2819 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);