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 };
128 _bt_convert_addr_type_to_string(device_address,
129 (unsigned char *)device_addr->addr);
131 for (l = service_monitor_list; l != NULL; l = l->next) {
132 char device_address2[BT_ADDRESS_STRING_SIZE] = { 0 };
133 bluetooth_device_address_t *addr = l->data;
135 _bt_convert_addr_type_to_string(device_address2,
136 (unsigned char *)addr->addr);
138 if (!memcmp(device_addr, addr,
139 sizeof(bluetooth_device_address_t)))
146 BT_EXPORT_API int bluetooth_gatt_set_service_change_watcher(
147 const bluetooth_device_address_t *address, gboolean enable)
150 bluetooth_device_address_t *addr = NULL;
151 char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
153 _bt_convert_addr_type_to_secure_string(secure_address, (unsigned char *)address->addr);
154 BT_INFO("Set watcher for %s with %d", secure_address, enable);
156 if (enable == TRUE) {
157 if (_bluetooth_gatt_check_service_change_watcher_address(address)
159 BT_INFO("The watcher is already set");
160 return BLUETOOTH_ERROR_NONE;
163 if (service_monitor_list == NULL)
164 _bt_register_manager_subscribe_signal(TRUE);
166 addr = g_malloc0(sizeof(bluetooth_device_address_t));
167 memcpy(addr, address, sizeof(bluetooth_device_address_t));
169 service_monitor_list =
170 g_slist_append(service_monitor_list, addr);
172 for (l = service_monitor_list; l != NULL; l = l->next) {
175 if (!memcmp(address, addr,
176 sizeof(bluetooth_device_address_t))) {
177 service_monitor_list =
178 g_slist_remove(service_monitor_list, addr);
184 if (service_monitor_list == NULL)
185 _bt_register_manager_subscribe_signal(FALSE);
188 return BLUETOOTH_ERROR_NONE;
191 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
192 bt_gatt_service_property_t *service)
194 GDBusProxy *properties_proxy = NULL;
195 GError *error = NULL;
196 GVariant *result = NULL;
197 GDBusConnection *g_conn;
199 char *char_handle = NULL;
200 GPtrArray *gp_array = NULL ;
201 GVariantIter *property_iter, *char_iter = NULL;
205 BT_CHECK_PARAMETER(service_handle, return);
206 BT_CHECK_PARAMETER(service, return);
207 BT_CHECK_ENABLED(return);
209 g_conn = _bt_get_system_private_conn();
210 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
212 properties_proxy = g_dbus_proxy_new_sync(g_conn,
213 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
216 BT_PROPERTIES_INTERFACE,
219 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
221 result = g_dbus_proxy_call_sync(properties_proxy,
223 g_variant_new("(s)", GATT_SERV_INTERFACE),
224 G_DBUS_CALL_FLAGS_NONE,
231 BT_ERR("Fail to get properties (Error: %s)", error->message);
232 g_clear_error(&error);
234 BT_ERR("Fail to get properties");
235 g_object_unref(properties_proxy);
236 return BLUETOOTH_ERROR_INTERNAL;
239 g_variant_get(result, "(a{sv})", &property_iter);
241 memset(service, 0, sizeof(bt_gatt_service_property_t));
243 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
244 if (!g_strcmp0(key, "UUID")) {
246 service->uuid = g_variant_dup_string(value, &len);
247 bluetooth_get_uuid_name(service->uuid, &name);
248 BT_INFO("%s %s [%s]", service_handle + 37, service->uuid, name);
250 } else if (!g_strcmp0(key, "Primary")) {
251 service->primary = g_variant_get_boolean(value);
253 } else if (!g_strcmp0(key, "Includes")) {
254 g_variant_get(value, "ao", &char_iter);
255 if (char_iter != NULL) {
256 gp_array = g_ptr_array_new();
257 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
258 g_ptr_array_add(gp_array, (gpointer)char_handle);
260 if (gp_array->len != 0) {
261 service->include_handles.count = gp_array->len;
262 service->include_handles.handle =
263 __get_string_array_from_gptr_array(gp_array);
265 g_ptr_array_free(gp_array, TRUE);
266 g_variant_iter_free(char_iter);
268 } else if (!g_strcmp0(key, "Characteristics")) {
269 g_variant_get(value, "ao", &char_iter);
270 if (char_iter != NULL) {
271 gp_array = g_ptr_array_new();
272 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
273 g_ptr_array_add(gp_array, (gpointer)char_handle);
275 if (gp_array->len != 0) {
276 service->char_handle.count = gp_array->len;
277 service->char_handle.handle =
278 __get_string_array_from_gptr_array(gp_array);
280 g_ptr_array_free(gp_array, TRUE);
281 g_variant_iter_free(char_iter);
283 BT_DBG("Characteristics count : %d", service->char_handle.count);
287 service->handle = g_strdup(service_handle);
289 g_variant_iter_free(property_iter);
290 g_variant_unref(result);
291 g_object_unref(properties_proxy);
293 return BLUETOOTH_ERROR_NONE;
296 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
297 const bluetooth_device_address_t *address,
298 bt_gatt_handle_info_t *prim_svc)
300 GVariant *result = NULL;
302 GVariantIter *svc_iter;
303 GVariantIter *interface_iter;
304 char *object_path = NULL;
305 char *interface_str = NULL;
306 const gchar *key = NULL;
307 GVariant *value = NULL;
308 GPtrArray *gp_array = NULL;
309 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
310 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
311 int ret = BLUETOOTH_ERROR_INTERNAL;
315 BT_CHECK_PARAMETER(address, return);
316 BT_CHECK_PARAMETER(prim_svc, return);
317 BT_CHECK_ENABLED(return);
319 result = _bt_get_managed_objects();
323 _bt_convert_addr_type_to_string(device_address,
324 (unsigned char *)address->addr);
326 gp_array = g_ptr_array_new();
327 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
329 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
331 if (object_path == NULL)
334 _bt_convert_device_path_to_address(object_path, temp_address);
336 if (g_strcmp0(temp_address, device_address) != 0)
339 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
340 &interface_str, &svc_iter)) {
341 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
344 BT_DBG("[%d] Object Path : %s", idx++, object_path);
345 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
346 if (g_strcmp0(key, "Primary") == 0) {
347 if (g_variant_get_boolean(value))
348 g_ptr_array_add(gp_array, (gpointer)object_path);
354 if (gp_array->len == 0) {
355 BT_ERR("gp_array is NULL");
356 ret = BLUETOOTH_ERROR_NOT_FOUND;
358 ret = BLUETOOTH_ERROR_NONE;
359 prim_svc->count = gp_array->len;
360 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
363 g_ptr_array_free(gp_array, TRUE);
364 g_variant_iter_free(iter);
365 g_variant_unref(result);
370 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
371 const char *service_uuid,
372 bt_gatt_service_property_t *service)
374 GVariant *result = NULL;
376 GVariantIter *svc_iter;
377 GVariantIter *interface_iter;
378 char *object_path = NULL;
379 char *interface_str = NULL;
380 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
381 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
382 int ret = BLUETOOTH_ERROR_INTERNAL;
384 BT_CHECK_PARAMETER(address, return);
385 BT_CHECK_PARAMETER(service_uuid, return);
386 BT_CHECK_PARAMETER(service, return);
387 BT_CHECK_ENABLED(return);
389 result = _bt_get_managed_objects();
393 _bt_convert_addr_type_to_string(device_address,
394 (unsigned char *)address->addr);
396 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
398 while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
400 if (object_path == NULL)
403 _bt_convert_device_path_to_address(object_path,
406 if (g_strcmp0(temp_address, device_address) != 0)
409 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
410 &interface_str, &svc_iter)) {
411 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
414 BT_DBG("Object Path: %s", object_path);
415 ret = bluetooth_gatt_get_service_property(object_path,
418 if (ret != BLUETOOTH_ERROR_NONE) {
419 BT_ERR("Get service property failed(0x%08x)", ret);
421 if (service->primary == TRUE &&
422 g_strstr_len(service->uuid, -1,
424 ret = BLUETOOTH_ERROR_NONE;
426 /* release resources */
428 g_variant_iter_free(interface_iter);
429 g_free(interface_str);
430 g_variant_iter_free(svc_iter);
435 bluetooth_gatt_free_service_property(service);
440 g_variant_iter_free(iter);
441 g_variant_unref(result);
446 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
447 GAsyncResult *res, gpointer user_data)
450 GVariant *char_value;
451 GVariantIter *char_iter;
452 GPtrArray *gp_array = NULL;
453 bt_gatt_discovered_char_t svc_char = { 0, };
455 GError *error = NULL;
456 bt_user_info_t *user_info;
460 user_info = _bt_get_user_data(BT_COMMON);
461 svc_char.service_handle = user_data;
463 value = g_dbus_proxy_call_finish(proxy, res, &error);
467 BT_ERR("Get service characteristics failed\n errCode[%x],"
468 "message[%s]\n", error->code, error->message);
469 g_clear_error(&error);
471 BT_ERR("Get service characteristics failed\n");
474 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
475 BLUETOOTH_ERROR_INTERNAL, NULL,
476 user_info->cb, user_info->user_data);
478 g_free(svc_char.service_handle);
479 g_object_unref(proxy);
483 g_variant_get(value, "(v)", &char_value);
484 g_variant_get(char_value, "ao", &char_iter);
486 gp_array = g_ptr_array_new();
487 while (g_variant_iter_loop(char_iter, "&o", &char_handle))
488 g_ptr_array_add(gp_array, (gpointer)char_handle);
490 if (gp_array->len != 0) {
491 svc_char.handle_info.count = gp_array->len;
492 svc_char.handle_info.handle =
493 __get_string_array_from_gptr_array(gp_array);
495 g_ptr_array_free(gp_array, TRUE);
498 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
499 BLUETOOTH_ERROR_NONE, &svc_char,
500 user_info->cb, user_info->user_data);
503 g_strfreev(svc_char.handle_info.handle);
504 g_free(svc_char.service_handle);
505 g_variant_iter_free(char_iter);
506 g_variant_unref(value);
507 g_object_unref(proxy);
508 g_variant_unref(char_value);
511 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
512 const char *service_handle)
514 GDBusProxy *properties_proxy = NULL;
515 GDBusConnection *g_conn;
516 GError *error = NULL;
521 BT_CHECK_PARAMETER(service_handle, return);
522 BT_CHECK_ENABLED(return);
524 g_conn = _bt_get_system_private_conn();
525 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
527 properties_proxy = g_dbus_proxy_new_sync(g_conn,
528 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
531 BT_PROPERTIES_INTERFACE,
534 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
536 handle = g_strdup(service_handle);
537 g_dbus_proxy_call(properties_proxy,
539 g_variant_new("(ss)",
540 GATT_SERV_INTERFACE, "Characteristics"),
541 G_DBUS_CALL_FLAGS_NONE,
544 (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
548 return BLUETOOTH_ERROR_NONE;
552 static int __get_permission_flag(char *permission)
556 retv_if(permission == NULL, ret);
558 if (!g_strcmp0(permission, "broadcast"))
559 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
560 else if (!g_strcmp0(permission, "read"))
561 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
562 else if (!g_strcmp0(permission, "write-without-response"))
563 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
564 else if (!g_strcmp0(permission, "write"))
565 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
566 else if (!g_strcmp0(permission, "notify"))
567 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
568 else if (!g_strcmp0(permission, "indicate"))
569 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
570 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
571 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
572 else if (!g_strcmp0(permission, "reliable-write"))
573 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
574 else if (!g_strcmp0(permission, "writable-auxiliaries"))
575 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
576 else if (!g_strcmp0(permission, "encrypt-read"))
577 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
578 else if (!g_strcmp0(permission, "encrypt-write"))
579 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
580 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
581 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
582 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
583 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
588 static void __convert_permission_flag_to_str(unsigned int permission)
590 char perm[200] = { 0, };
592 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
593 g_strlcat(perm, "broadcast ", sizeof(perm));
594 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ)
595 g_strlcat(perm, "read ", sizeof(perm));
596 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
597 g_strlcat(perm, "write-without-response ", sizeof(perm));
598 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE)
599 g_strlcat(perm, "write ", sizeof(perm));
600 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
601 g_strlcat(perm, "notify ", sizeof(perm));
602 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
603 g_strlcat(perm, "indicate ", sizeof(perm));
604 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
605 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
606 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
607 g_strlcat(perm, "reliable-write ", sizeof(perm));
608 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
609 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
610 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
611 g_strlcat(perm, "encrypt-read ", sizeof(perm));
612 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
613 g_strlcat(perm, "encrypt-write ", sizeof(perm));
614 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
615 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
616 if (permission & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
617 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
619 BT_INFO("permission [0x%04x] : %s\n", permission, perm);
623 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
624 const char *char_handle, bt_gatt_char_property_t *characteristic)
626 GDBusProxy *properties_proxy = NULL;
627 GError *error = NULL;
628 GVariant *value = NULL;
629 GVariant *result = NULL;
630 GByteArray *gb_array = NULL;
631 GPtrArray *gp_array = NULL ;
632 GDBusConnection *g_conn;
636 char *char_desc_handle = NULL;
638 GVariantIter *property_iter;
639 GVariantIter *char_value_iter;
640 GVariantIter *char_perm_iter;
641 GVariantIter *char_desc_iter;
643 BT_CHECK_PARAMETER(char_handle, return);
644 BT_CHECK_PARAMETER(characteristic, return);
646 BT_CHECK_ENABLED(return);
648 g_conn = _bt_get_system_private_conn();
649 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
651 properties_proxy = g_dbus_proxy_new_sync(g_conn,
652 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
655 BT_PROPERTIES_INTERFACE,
658 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
660 result = g_dbus_proxy_call_sync(properties_proxy,
662 g_variant_new("(s)", GATT_CHAR_INTERFACE),
663 G_DBUS_CALL_FLAGS_NONE,
670 BT_ERR("Fail to get properties (Error: %s)", error->message);
671 g_clear_error(&error);
673 BT_ERR("Fail to get properties");
674 g_object_unref(properties_proxy);
675 return BLUETOOTH_ERROR_INTERNAL;
678 g_variant_get(result, "(a{sv})", &property_iter);
680 memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
681 characteristic->handle = g_strdup(char_handle);
683 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
684 if (!g_strcmp0(key, "UUID")) {
686 characteristic->uuid = g_variant_dup_string(value, &len);
687 bluetooth_get_uuid_name(characteristic->uuid, &name);
688 BT_INFO("%s %s [%s]", char_handle + 37, characteristic->uuid, name);
690 } else if (!g_strcmp0(key, "Value")) {
691 gb_array = g_byte_array_new();
692 g_variant_get(value, "ay", &char_value_iter);
693 while (g_variant_iter_loop(char_value_iter, "y", &char_value)) {
694 // BT_DBG("value of char = %d",char_value);
695 g_byte_array_append(gb_array, &char_value, 1);
697 g_variant_iter_free(char_value_iter);
699 if (gb_array->len != 0) {
700 characteristic->val = g_malloc0(gb_array->len *
701 sizeof(unsigned char));
702 memcpy(characteristic->val, gb_array->data, gb_array->len);
704 characteristic->val_len = gb_array->len;
705 g_byte_array_free(gb_array, TRUE);
706 } else if (!g_strcmp0(key, "Flags")) {
707 g_variant_get(value, "as", &char_perm_iter);
708 characteristic->permission = 0x00;
710 while (g_variant_iter_loop(char_perm_iter, "s", &permission))
711 characteristic->permission |= __get_permission_flag(permission);
712 __convert_permission_flag_to_str(characteristic->permission);
714 g_variant_iter_free(char_perm_iter);
715 } else if (!g_strcmp0(key, "Descriptors")) {
716 g_variant_get(value, "ao", &char_desc_iter);
717 gp_array = g_ptr_array_new();
718 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle))
719 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
721 g_variant_iter_free(char_desc_iter);
722 if (gp_array->len != 0) {
723 characteristic->char_desc_handle.count = gp_array->len;
724 characteristic->char_desc_handle.handle =
725 __get_string_array_from_gptr_array(gp_array);
727 g_ptr_array_free(gp_array, TRUE);
731 g_variant_iter_free(property_iter);
732 g_variant_unref(result);
733 g_object_unref(properties_proxy);
735 return BLUETOOTH_ERROR_NONE;
738 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
739 GAsyncResult *res, gpointer user_data)
742 GVariantIter *char_iter;
744 GError *error = NULL;
745 bt_user_info_t *user_info;
746 int ret = BLUETOOTH_ERROR_INTERNAL;
747 bt_gatt_char_property_t characteristic;
749 user_info = _bt_get_user_data(BT_COMMON);
751 value = g_dbus_proxy_call_finish(proxy, res, &error);
755 BT_ERR("Get service characteristics failed\n errCode[%x],"
756 "message[%s]\n", error->code, error->message);
757 g_clear_error(&error);
759 BT_ERR("Get service characteristics failed\n");
762 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
763 BLUETOOTH_ERROR_INTERNAL, NULL,
764 user_info->cb, user_info->user_data);
766 g_object_unref(proxy);
771 g_variant_get(value, "(ao)", &char_iter);
773 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
776 ret = bluetooth_gatt_get_characteristics_property(char_handle,
779 if (ret != BLUETOOTH_ERROR_NONE) {
780 BT_ERR("Get characteristic property failed(0x%08x)", ret);
782 if (g_strstr_len(characteristic.uuid, -1, user_data)) {
783 ret = BLUETOOTH_ERROR_NONE;
787 bluetooth_gatt_free_char_property(&characteristic);
791 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
792 &characteristic, user_info->cb, user_info->user_data);
795 bluetooth_gatt_free_char_property(&characteristic);
796 g_variant_iter_free(char_iter);
797 g_variant_unref(value);
801 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
802 const char *char_uuid)
804 GDBusProxy *properties_proxy = NULL;
805 GDBusConnection *g_conn;
806 GError *error = NULL;
809 BT_CHECK_PARAMETER(service_handle, return);
810 BT_CHECK_PARAMETER(char_uuid, return);
811 BT_CHECK_ENABLED(return);
813 g_conn = _bt_get_system_private_conn();
814 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
816 properties_proxy = g_dbus_proxy_new_sync(g_conn,
817 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
820 BT_PROPERTIES_INTERFACE,
823 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
825 uuid = g_strdup(char_uuid);
826 g_dbus_proxy_call(properties_proxy,
828 g_variant_new("(ss)",
829 GATT_SERV_INTERFACE, "Characteristics"),
830 G_DBUS_CALL_FLAGS_NONE,
833 (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
836 return BLUETOOTH_ERROR_NONE;
839 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
840 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
842 GDBusProxy *properties_proxy = NULL;
843 GError *error = NULL;
844 GDBusConnection *g_conn;
845 GVariant *result = NULL;
846 GVariantIter *property_iter;
850 GVariant *value = NULL;
851 GByteArray *gb_array = NULL;
852 GVariantIter *desc_value_iter;
854 BT_CHECK_PARAMETER(descriptor_handle, return);
855 BT_CHECK_PARAMETER(descriptor, return);
857 BT_CHECK_ENABLED(return);
859 g_conn = _bt_get_system_private_conn();
860 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
862 properties_proxy = g_dbus_proxy_new_sync(g_conn,
863 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
866 BT_PROPERTIES_INTERFACE,
869 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
871 result = g_dbus_proxy_call_sync(properties_proxy,
873 g_variant_new("(s)", GATT_DESC_INTERFACE),
874 G_DBUS_CALL_FLAGS_NONE,
881 BT_ERR("Fail to get properties (Error: %s)", error->message);
882 g_clear_error(&error);
884 BT_ERR("Fail to get properties");
885 g_object_unref(properties_proxy);
886 return BLUETOOTH_ERROR_INTERNAL;
889 g_variant_get(result, "(a{sv})", &property_iter);
891 memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
892 descriptor->handle = g_strdup(descriptor_handle);
894 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
895 if (!g_strcmp0(key, "UUID")) {
897 descriptor->uuid = g_variant_dup_string(value, &len);
898 bluetooth_get_uuid_name(descriptor->uuid, &name);
899 BT_INFO("Descriptor : %s [%s]", descriptor->uuid, name);
901 } else if (!g_strcmp0(key, "Value")) {
902 gb_array = g_byte_array_new();
903 g_variant_get(value, "ay", &desc_value_iter);
904 while (g_variant_iter_loop(desc_value_iter, "y", &char_value)) {
905 BT_DBG("value of descriptor = %d", char_value);
906 g_byte_array_append(gb_array, &char_value, 1);
908 g_variant_iter_free(desc_value_iter);
910 if (gb_array->len != 0) {
911 descriptor->val = g_malloc0(gb_array->len *
912 sizeof(unsigned char));
913 memcpy(descriptor->val, gb_array->data, gb_array->len);
915 descriptor->val_len = gb_array->len;
916 g_byte_array_free(gb_array, TRUE);
920 g_variant_iter_free(property_iter);
921 g_variant_unref(result);
922 g_object_unref(properties_proxy);
924 return BLUETOOTH_ERROR_NONE;
927 static int __bluetooth_get_att_error_code(GError *error, char *handle)
933 BT_ERR("Error : %s [%s]", error->message, handle + 15);
934 str = g_strrstr(error->message, "ATT error: 0x");
937 att_ecode = g_ascii_xdigit_value(str[len - 2]) << 4;
938 att_ecode += g_ascii_xdigit_value(str[len - 1]);
940 return BLUETOOTH_ATT_ERROR_INTERNAL;
943 case BLUETOOTH_ATT_ERROR_READ_NOT_PERMITTED:
944 BT_ERR("Read not permitted");
946 case BLUETOOTH_ATT_ERROR_WRITE_NOT_PERMITTED:
947 BT_ERR("Write not permitted");
949 case BLUETOOTH_ATT_ERROR_AUTHENTICATION:
950 case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION:
951 case BLUETOOTH_ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
952 BT_ERR("Not paired");
954 case BLUETOOTH_ATT_ERROR_INVALID_OFFSET:
955 BT_ERR("Invalid offset");
957 case BLUETOOTH_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN:
958 BT_ERR("Invalid Length");
960 case BLUETOOTH_ATT_ERROR_AUTHORIZATION:
961 BT_ERR("Operation not Authorized");
964 BT_ERR("default ecode");
968 if (att_ecode >= 0x80 && att_ecode <= 0x9F)
969 BT_ERR("Application error");
974 static void __bluetooth_internal_read_cb(GObject *source_object,
975 GAsyncResult *res, gpointer user_data)
977 GError *error = NULL;
978 GDBusConnection *system_gconn = NULL;
980 bt_user_info_t *user_info;
982 GByteArray *gp_byte_array = NULL;
985 bt_gatt_resp_data_t *resp_data = user_data;
989 system_gconn = _bt_get_system_private_conn();
990 value = g_dbus_connection_call_finish(system_gconn, res, &error);
992 user_info = _bt_get_user_data(BT_COMMON);
995 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
996 g_clear_error(&error);
1001 g_variant_unref(value);
1006 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1007 g_clear_error(&error);
1009 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1010 att_ecode, resp_data,
1011 user_info->cb, user_info->user_data);
1016 gp_byte_array = g_byte_array_new();
1017 g_variant_get(value, "(ay)", &iter);
1019 while (g_variant_iter_loop(iter, "y", &g_byte))
1020 g_byte_array_append(gp_byte_array, &g_byte, 1);
1022 if (gp_byte_array->len != 0) {
1023 resp_data->len = gp_byte_array->len;
1024 resp_data->value = gp_byte_array->data;
1027 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
1028 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1029 user_info->cb, user_info->user_data);
1032 g_byte_array_free(gp_byte_array, TRUE);
1033 g_variant_iter_free(iter);
1034 g_variant_unref(value);
1039 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *chr,
1042 GDBusConnection *conn;
1043 bt_gatt_resp_data_t *resp_data;
1044 GVariantBuilder *builder = NULL;
1047 BT_CHECK_PARAMETER(chr, return);
1048 BT_CHECK_ENABLED(return);
1050 conn = _bt_get_system_private_conn();
1051 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1053 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1054 resp_data->user_data = user_data;
1055 resp_data->handle = (char *)chr;
1057 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1060 g_variant_builder_add(builder, "{sv}", "offset",
1061 g_variant_new("q", offset));
1063 /* Device Object path*/
1064 // g_variant_builder_add(builder, "{sv}", "device",
1065 // g_variant_new_object("o", NULL));
1067 g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1068 "ReadValue", g_variant_new("(a{sv})", builder),
1069 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1070 (GAsyncReadyCallback)__bluetooth_internal_read_cb,
1071 (gpointer)resp_data);
1072 g_variant_builder_unref(builder);
1074 return BLUETOOTH_ERROR_NONE;
1077 static void __bluetooth_internal_write_cb(GObject *source_object,
1078 GAsyncResult *res, gpointer user_data)
1080 GError *error = NULL;
1081 GDBusConnection *system_gconn = NULL;
1082 bt_user_info_t *user_info;
1085 bt_gatt_resp_data_t *resp_data = user_data;
1087 system_gconn = _bt_get_system_private_conn();
1088 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1090 user_info = _bt_get_user_data(BT_COMMON);
1093 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1094 g_clear_error(&error);
1099 g_variant_unref(value);
1104 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1105 g_clear_error(&error);
1107 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1108 att_ecode, resp_data,
1109 user_info->cb, user_info->user_data);
1114 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
1115 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1116 user_info->cb, user_info->user_data);
1119 g_variant_unref(value);
1123 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
1124 const char *char_handle, const guint8 *value, int length)
1126 GVariant *val, *options;
1127 GVariantBuilder *builder1;
1128 GVariantBuilder *builder2;
1129 GError *error = NULL;
1130 GDBusConnection *conn;
1135 BT_CHECK_PARAMETER(char_handle, return);
1136 BT_CHECK_PARAMETER(value, return);
1137 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1138 BT_CHECK_ENABLED(return);
1140 conn = _bt_get_system_private_conn();
1141 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1143 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1144 for (i = 0; i < length; i++)
1145 g_variant_builder_add(builder1, "y", value[i]);
1147 val = g_variant_new("ay", builder1);
1149 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1151 g_variant_builder_add(builder2, "{sv}", "offset",
1152 g_variant_new_uint16(offset));
1154 /* Device Object path*/
1155 // g_variant_builder_add(builder2, "{sv}", "device",
1156 // g_variant_new_object("o", NULL));
1158 options = g_variant_new("a{sv}", builder2);
1160 g_dbus_connection_call(conn,
1163 GATT_CHAR_INTERFACE,
1165 g_variant_new("(@ay@a{sv})",
1168 G_DBUS_CALL_FLAGS_NONE,
1170 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1175 BT_ERR("Set value Failed: %s", error->message);
1176 g_clear_error(&error);
1177 g_variant_builder_unref(builder1);
1178 return BLUETOOTH_ERROR_INTERNAL;
1180 g_variant_builder_unref(builder1);
1181 g_variant_builder_unref(builder2);
1184 return BLUETOOTH_ERROR_NONE;
1187 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
1188 const char *chr, const guint8 *value, int length,
1189 guint8 write_type, gpointer user_data)
1191 GVariant *val, *options;
1192 GVariantBuilder *builder1;
1193 GVariantBuilder *builder2;
1194 GDBusConnection *conn;
1197 int ret = BLUETOOTH_ERROR_NONE;
1198 bt_gatt_resp_data_t *resp_data;
1200 BT_CHECK_PARAMETER(chr, return);
1201 BT_CHECK_PARAMETER(value, return);
1202 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1203 BT_CHECK_ENABLED_INTERNAL(return);
1205 conn = _bt_get_system_private_conn();
1206 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1208 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1210 for (i = 0; i < length; i++)
1211 g_variant_builder_add(builder1, "y", value[i]);
1213 val = g_variant_new("ay", builder1);
1215 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1217 g_variant_builder_add(builder2, "{sv}", "offset",
1218 g_variant_new_uint16(offset));
1220 /* Device Object path*/
1221 // g_variant_builder_add(builder2, "{sv}", "device",
1222 // g_variant_new_object("o", NULL));
1224 options = g_variant_new("a{sv}", builder2);
1226 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1227 resp_data->user_data = user_data;
1228 resp_data->handle = (char *)chr;
1230 g_dbus_connection_call(conn, BT_BLUEZ_NAME, chr, GATT_CHAR_INTERFACE,
1232 g_variant_new("(y@ay@a{sv})", write_type, val, options),
1234 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1235 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1236 (gpointer)resp_data);
1238 g_variant_builder_unref(builder1);
1239 g_variant_builder_unref(builder2);
1244 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1245 const char *char_handle, const guint8 *value, int length)
1247 GVariant *val, *options;
1248 GDBusConnection *conn;
1249 GVariantBuilder *builder1;
1250 GVariantBuilder *builder2;
1255 BT_CHECK_PARAMETER(char_handle, return);
1256 BT_CHECK_PARAMETER(value, return);
1257 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1258 BT_CHECK_ENABLED(return);
1260 conn = _bt_get_system_private_conn();
1261 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1263 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1265 for (i = 0; i < length; i++) {
1266 g_variant_builder_add(builder1, "y", value[i]);
1267 BT_DBG("value [] = %d", value[i]);
1270 val = g_variant_new("ay", builder1);
1272 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1274 g_variant_builder_add(builder2, "{sv}", "offset",
1275 g_variant_new_uint16(offset));
1277 /* Device Object path*/
1278 // g_variant_builder_add(builder2, "{sv}", "device",
1279 // g_variant_new_object("o", NULL));
1281 options = g_variant_new("a{sv}", builder2);
1283 g_dbus_connection_call(conn,
1286 GATT_CHAR_INTERFACE,
1288 g_variant_new("(@ay@a{sv})",
1291 G_DBUS_CALL_FLAGS_NONE,
1293 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1296 g_variant_builder_unref(builder1);
1297 g_variant_builder_unref(builder2);
1300 return BLUETOOTH_ERROR_NONE;
1303 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1304 bt_gatt_char_property_t *characteristic)
1307 GDBusProxy *properties_proxy = NULL;
1308 GError *error = NULL;
1309 GVariant *value = NULL;
1310 GVariant *result = NULL;
1311 GDBusConnection *g_conn;
1312 int i, ret = BLUETOOTH_ERROR_NONE;
1313 const char *uuid = NULL;
1315 GVariantIter *desc_value_iter, *property_iter;
1317 char_descriptor_type_t desc_type = TYPE_NONE;
1319 g_conn = _bt_get_system_private_conn();
1320 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1322 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1323 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1326 BT_PROPERTIES_INTERFACE,
1329 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1331 result = g_dbus_proxy_call_sync(properties_proxy,
1333 g_variant_new("(s)", GATT_DESC_INTERFACE),
1334 G_DBUS_CALL_FLAGS_NONE,
1340 if (error != NULL) {
1341 BT_ERR("Fail to get properties (Error: %s)", error->message);
1342 g_clear_error(&error);
1344 BT_ERR("Fail to get properties");
1345 g_object_unref(properties_proxy);
1346 return BLUETOOTH_ERROR_INTERNAL;
1348 g_variant_get(result, "(a{sv})", &property_iter);
1349 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1350 if (!g_strcmp0(key, "UUID")) {
1351 uuid = g_variant_get_string(value, &len);
1352 if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1353 BT_DBG("GATT_USER_DESC_UUID");
1354 desc_type = USER_DESC;
1355 } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1356 BT_DBG("GATT_CHAR_FORMAT");
1357 desc_type = CHAR_FORMAT;
1358 } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1359 BT_DBG("GATT_CHAR_CLIENT_CONF");
1360 desc_type = CLIENT_CONF;
1361 } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1362 BT_DBG("GATT_CHAR_SERVER_CONF");
1363 desc_type = SERVER_CONF;
1365 BT_DBG("descriptor uuid = %s", uuid);
1367 } else if (!g_strcmp0(key, "Value")) {
1368 switch (desc_type) {
1370 BT_DBG("Format descriptor");
1371 g_variant_get(value, "(yyqyq)",
1372 &(characteristic->format.format),
1373 &(characteristic->format.exponent),
1374 &(characteristic->format.unit),
1375 &(characteristic->format.name_space),
1376 &(characteristic->format.description));
1379 BT_DBG("User descriptor");
1380 g_variant_get(value, "ay", &desc_value_iter);
1381 len = g_variant_get_size((GVariant *)desc_value_iter);
1384 characteristic->description = (char *)g_malloc0(len + 1);
1386 for (i = 0; i < len; i++) {
1387 g_variant_iter_loop(desc_value_iter, "y",
1388 &characteristic->description[i]);
1389 BT_DBG("description = %s", characteristic->description);
1391 g_variant_iter_free(desc_value_iter);
1394 BT_DBG(" CLIENT_CONF");
1397 BT_DBG(" SERVER_CONF");
1405 g_variant_iter_free(property_iter);
1406 g_variant_unref(result);
1407 g_object_unref(properties_proxy);
1414 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1415 GAsyncResult *res, gpointer user_data)
1419 GVariant *char_value;
1420 GVariantIter *char_iter;
1422 GError *error = NULL;
1423 bt_user_info_t *user_info;
1424 bt_gatt_char_property_t characteristic = {0, };
1425 int ret = BLUETOOTH_ERROR_INTERNAL;
1427 user_info = _bt_get_user_data(BT_COMMON);
1429 value = g_dbus_proxy_call_finish(proxy, res, &error);
1430 characteristic.handle = user_data;
1432 if (value == NULL) {
1433 if (error != NULL) {
1434 BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1435 "message[%s]\n", error->code, error->message);
1436 g_clear_error(&error);
1438 BT_ERR("Get characteristic descriptor failed\n");
1441 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1442 BLUETOOTH_ERROR_INTERNAL, NULL,
1443 user_info->cb, user_info->user_data);
1445 g_free(characteristic.handle);
1446 g_object_unref(proxy);
1450 g_variant_get(value, "(v)", &char_value);
1451 g_variant_get(char_value, "ao", &char_iter);
1453 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
1454 BT_DBG("object path of descriptor = %s", char_handle);
1456 ret = __bluetooth_gatt_descriptor_iter(char_handle,
1458 BT_DBG("Descriptor read status [%d]", ret);
1463 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1464 ret, &characteristic, user_info->cb, user_info->user_data);
1466 bluetooth_gatt_free_char_property(&characteristic);
1468 g_variant_iter_free(char_iter);
1469 g_variant_unref(value);
1470 g_variant_unref(char_value);
1474 BT_EXPORT_API int bltooth_gatt_discover_characteristic_descriptor(
1475 const char *characteristic_handle)
1477 GDBusProxy *properties_proxy = NULL;
1478 GDBusConnection *g_conn;
1480 GError *error = NULL;
1482 BT_CHECK_PARAMETER(characteristic_handle, return);
1483 BT_CHECK_ENABLED(return);
1485 g_conn = _bt_get_system_private_conn();
1486 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1488 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1489 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1491 characteristic_handle,
1492 BT_PROPERTIES_INTERFACE,
1495 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1497 handle = g_strdup(characteristic_handle);
1498 g_dbus_proxy_call(properties_proxy,
1500 g_variant_new("(ss)",
1501 GATT_CHAR_INTERFACE, "Descriptors"),
1502 G_DBUS_CALL_FLAGS_NONE,
1504 (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1507 return BLUETOOTH_ERROR_NONE;
1510 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1514 GError *error = NULL;
1515 GDBusConnection *system_gconn = NULL;
1517 bt_user_info_t *user_info;
1518 GByteArray *gp_byte_array = NULL;
1522 bt_gatt_resp_data_t *resp_data = user_data;
1526 system_gconn = _bt_get_system_private_conn();
1527 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1529 user_info = _bt_get_user_data(BT_COMMON);
1532 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1533 g_clear_error(&error);
1538 g_variant_unref(value);
1543 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1544 g_clear_error(&error);
1546 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1547 att_ecode, resp_data,
1548 user_info->cb, user_info->user_data);
1553 gp_byte_array = g_byte_array_new();
1554 g_variant_get(value, "(ay)", &iter);
1556 while (g_variant_iter_loop(iter, "y", &g_byte))
1557 g_byte_array_append(gp_byte_array, &g_byte, 1);
1559 if (gp_byte_array->len != 0) {
1560 resp_data->len = gp_byte_array->len;
1561 resp_data->value = gp_byte_array->data;
1564 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1565 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1566 user_info->cb, user_info->user_data);
1570 g_byte_array_free(gp_byte_array, TRUE);
1571 g_variant_iter_free(iter);
1572 g_variant_unref(value);
1577 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *desc,
1580 GDBusConnection *conn;
1581 GVariantBuilder *builder;
1583 bt_gatt_resp_data_t *resp_data;
1587 BT_CHECK_PARAMETER(desc, return);
1588 BT_CHECK_ENABLED(return);
1590 conn = _bt_get_system_private_conn();
1591 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1593 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1594 resp_data->user_data = user_data;
1595 resp_data->handle = (char *)desc;
1597 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1600 g_variant_builder_add(builder, "{sv}", "offset",
1601 g_variant_new("q", offset));
1602 /* Device Object path*/
1603 // g_variant_builder_add(builder, "{sv}", "device",
1604 // g_variant_new("o", serv_info->serv_path));
1606 g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1607 "ReadValue", g_variant_new("(a{sv})", builder),
1608 G_VARIANT_TYPE("(ay)"),
1609 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1610 (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1611 (gpointer)resp_data);
1612 g_variant_builder_unref(builder);
1615 return BLUETOOTH_ERROR_NONE;
1618 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1619 GAsyncResult *res, gpointer user_data)
1621 GError *error = NULL;
1622 bt_user_info_t *user_info;
1623 GDBusConnection *system_gconn = NULL;
1625 int att_ecode = BLUETOOTH_ATT_ERROR_NONE;
1626 bt_gatt_resp_data_t *resp_data = user_data;
1630 system_gconn = _bt_get_system_private_conn();
1631 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1633 user_info = _bt_get_user_data(BT_COMMON);
1636 BT_ERR("Error : %s [%s]", error->message, resp_data->handle + 15);
1637 g_clear_error(&error);
1642 g_variant_unref(value);
1647 att_ecode = __bluetooth_get_att_error_code(error, resp_data->handle);
1648 g_clear_error(&error);
1650 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1651 att_ecode, resp_data,
1652 user_info->cb, user_info->user_data);
1657 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1658 BLUETOOTH_ATT_ERROR_NONE, resp_data,
1659 user_info->cb, user_info->user_data);
1662 g_variant_unref(value);
1666 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(const char *desc,
1667 const guint8 *value, int length, gpointer user_data)
1669 GVariant *val, *options;
1670 GDBusConnection *conn;
1671 GVariantBuilder *builder1;
1672 GVariantBuilder *builder2;
1675 bt_gatt_resp_data_t *resp_data;
1679 BT_CHECK_PARAMETER(desc, return);
1680 BT_CHECK_PARAMETER(value, return);
1681 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1682 BT_CHECK_ENABLED(return);
1684 conn = _bt_get_system_private_conn();
1685 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1687 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1689 for (i = 0; i < length; i++)
1690 g_variant_builder_add(builder1, "y", value[i]);
1692 val = g_variant_new("ay", builder1);
1694 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1696 g_variant_builder_add(builder2, "{sv}", "offset",
1697 g_variant_new_uint16(offset));
1699 /* Device Object path*/
1700 // g_variant_builder_add(builder2, "{sv}", "device",
1701 // g_variant_new_object("o", NULL));
1703 options = g_variant_new("a{sv}", builder2);
1705 resp_data = g_malloc0(sizeof(bt_gatt_resp_data_t));
1706 resp_data->user_data = user_data;
1707 resp_data->handle = (char *)desc;
1709 g_dbus_connection_call(conn, BT_BLUEZ_NAME, desc, GATT_DESC_INTERFACE,
1710 "WriteValue", g_variant_new("(@ay@a{sv})",
1711 val, options), NULL,
1712 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1713 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1714 (gpointer)resp_data);
1716 g_variant_builder_unref(builder1);
1717 g_variant_builder_unref(builder2);
1720 return BLUETOOTH_ERROR_NONE;
1723 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle, const char *svc_name)
1725 GDBusConnection *conn;
1726 GError *error = NULL;
1727 int ret = BLUETOOTH_ERROR_NONE;
1729 BT_CHECK_PARAMETER(char_handle, return);
1730 BT_CHECK_ENABLED(return);
1732 BT_INFO_C("### Enable CCCD : %s [%s]", char_handle + 15, svc_name);
1734 conn = _bt_get_system_private_conn();
1735 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1737 g_dbus_connection_call_sync(conn,
1740 GATT_CHAR_INTERFACE,
1744 G_DBUS_CALL_FLAGS_NONE,
1745 GATT_DEFAULT_TIMEOUT, NULL, &error);
1748 g_dbus_error_strip_remote_error(error);
1749 BT_ERR_C("### Watch Failed: %s", error->message);
1750 if (g_strrstr(error->message, "Already notifying"))
1751 ret = BLUETOOTH_ERROR_NONE;
1752 else if (g_strrstr(error->message, "In Progress"))
1753 ret = BLUETOOTH_ERROR_IN_PROGRESS;
1754 else if (g_strrstr(error->message, "Operation is not supported"))
1755 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1756 /*failed because of either Insufficient Authorization or Write Not Permitted */
1757 else if (g_strrstr(error->message, "Write not permitted") ||
1758 g_strrstr(error->message, "Operation Not Authorized"))
1759 ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1760 /* failed because of either Insufficient Authentication,
1761 Insufficient Encryption Key Size, or Insufficient Encryption. */
1762 else if (g_strrstr(error->message, "Not paired"))
1763 ret = BLUETOOTH_ERROR_NOT_PAIRED;
1765 ret = BLUETOOTH_ERROR_INTERNAL;
1767 g_clear_error(&error);
1773 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1775 GDBusConnection *conn;
1776 GError *error = NULL;
1777 int ret = BLUETOOTH_ERROR_NONE;
1778 BT_CHECK_PARAMETER(char_handle, return);
1780 BT_CHECK_ENABLED(return);
1782 BT_INFO("Disable CCCD : %s", char_handle);
1784 conn = _bt_get_system_private_conn();
1785 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1787 g_dbus_connection_call_sync(conn,
1790 GATT_CHAR_INTERFACE,
1794 G_DBUS_CALL_FLAGS_NONE,
1795 GATT_DEFAULT_TIMEOUT, NULL, &error);
1798 BT_ERR("Watch Failed: %s", error->message);
1799 g_clear_error(&error);
1800 ret = BLUETOOTH_ERROR_INTERNAL;
1806 #ifdef TIZEN_GATT_CLIENT
1807 void __bt_uuid_hex_to_string(unsigned char *uuid, char *str)
1809 uint32_t uuid0, uuid4;
1810 uint16_t uuid1, uuid2, uuid3, uuid5;
1812 memcpy(&uuid0, &(uuid[0]), 4);
1813 memcpy(&uuid1, &(uuid[4]), 2);
1814 memcpy(&uuid2, &(uuid[6]), 2);
1815 memcpy(&uuid3, &(uuid[8]), 2);
1816 memcpy(&uuid4, &(uuid[10]), 4);
1817 memcpy(&uuid5, &(uuid[14]), 2);
1819 snprintf((char *)str, BLUETOOTH_UUID_STRING_MAX, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
1820 ntohl(uuid0), ntohs(uuid1),
1821 ntohs(uuid2), ntohs(uuid3),
1822 ntohl(uuid4), ntohs(uuid5));
1827 static void __bt_fill_service_handle_informations(bt_services_browse_info_t *props,
1828 bt_gatt_handle_info_t *svcs)
1832 if (props->count == 0)
1835 svcs->count = props->count;
1837 for (count = 0; count < props->count; count++) {
1838 BT_DBG("[%d] %s instance_id [%d] Is Primary [%d]",
1839 count, props->uuids[count], props->inst_id[count], props->primary[count]);
1840 g_strlcpy(svcs->uuids[count], props->uuids[count],
1841 BLUETOOTH_UUID_STRING_MAX);
1842 svcs->inst_id[count] = props->inst_id[count];
1846 static void __bt_fill_char_handle_informations(bt_char_browse_info_t *props, bt_gatt_service_property_t *service)
1849 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1851 service->char_handle.count = props->count;
1853 /* Before filling all char handles, fill the service's UUID and instance ID */
1854 __bt_uuid_hex_to_string(props->svc_uuid, uuid_string);
1855 service->uuid = g_strdup(uuid_string);
1856 service->primary = TRUE;
1858 /* Now fill all the char handles [UUID and Instance ID's]*/
1859 for (count = 0; count < props->count; count++) {
1860 BT_DBG("[%d] %s instance_id [%d] properties [%d]",
1861 count, props->uuids[count], props->inst_id[count], props->props[count]);
1863 g_strlcpy(service->char_handle.uuids[count],
1864 props->uuids[count],
1865 BLUETOOTH_UUID_STRING_MAX);
1867 service->char_handle.inst_id[count] = props->inst_id[count];
1871 static void __bt_fill_desc_handle_informations(bt_descriptor_browse_info_t *props,
1872 bt_gatt_char_property_t *charc)
1875 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
1877 charc->char_desc_handle.count = props->count;
1879 /* Before filling all desc handles, fill the charac's UUID and instance ID */
1880 __bt_uuid_hex_to_string(props->char_uuid, uuid_string);
1881 charc->uuid = g_strdup(uuid_string);
1883 /* Now fill all the descriptor handles [UUID and Instance ID's]*/
1884 for (count = 0; count < props->count; count++) {
1885 BT_DBG("[%d] %s instance_id [%d]",
1886 count, props->uuids[count], props->inst_id[count]);
1888 g_strlcpy(charc->char_desc_handle.uuids[count],
1889 props->uuids[count],
1890 BLUETOOTH_UUID_STRING_MAX);
1892 charc->char_desc_handle.inst_id[count] = props->inst_id[count];
1894 charc->permission = props->char_props_map;
1895 __convert_permission_flag_to_str(charc->permission);
1899 BT_EXPORT_API int bluetooth_gatt_client_init(
1901 const bluetooth_device_address_t *address,
1902 gatt_client_cb_func_ptr callback_ptr)
1904 int ret = BLUETOOTH_ERROR_NONE;
1905 bt_event_info_t *event_info;
1908 BT_CHECK_PARAMETER(client_id, return);
1909 BT_CHECK_PARAMETER(callback_ptr, return);
1910 BT_CHECK_ENABLED(return);
1913 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1915 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1917 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_REGISTER,
1918 in_param1, in_param2, in_param3, in_param4, &out_param);
1920 /* App ID -1 is invalid */
1921 if (ret == BLUETOOTH_ERROR_NONE) {
1923 *client_id = g_array_index(out_param, int, 0);
1925 BT_INFO("GATT Client Registered successfully: Client instance ID [%d]", *client_id);
1927 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
1930 count = (int*)event_info->user_data;
1932 BT_INFO("Total num of GATT client instances [%d]", *count);
1934 /* Increement the count */
1937 BT_INFO("No GATT Client instances found in this application: Set User data");
1938 count = g_malloc0(sizeof(int));
1941 /* Register event handler for GATT */
1942 _bt_register_event(BT_GATT_CLIENT_EVENT,
1943 (void *)callback_ptr,
1945 _bt_set_user_data(BT_GATT_CLIENT, (void *)callback_ptr, NULL);
1948 BT_ERR("GATT Client Registration failed!! ret [%d]", ret);
1950 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1957 BT_EXPORT_API int bluetooth_gatt_client_get_primary_services(
1958 const bluetooth_device_address_t *address, /* Remote GATT Server */
1959 bt_gatt_handle_info_t *prim_svc) /* UUID & instance_id */
1962 int result = BLUETOOTH_ERROR_NONE;
1963 bt_services_browse_info_t service_props;
1965 BT_CHECK_PARAMETER(address, return);
1966 BT_CHECK_PARAMETER(prim_svc, return);
1967 BT_CHECK_ENABLED(return);
1970 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1971 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
1973 result = _bt_send_request(BT_BLUEZ_SERVICE,
1974 BT_GATT_GET_PRIMARY_SERVICES,
1975 in_param1, in_param2, in_param3, in_param4, &out_param);
1977 if (BLUETOOTH_ERROR_NONE != result)
1980 memset(&service_props, 0x00, sizeof(bt_services_browse_info_t));
1982 service_props = g_array_index(
1983 out_param, bt_services_browse_info_t, 0);
1985 __bt_fill_service_handle_informations(
1986 &service_props, prim_svc);
1989 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1993 BT_EXPORT_API int bluetooth_gatt_client_get_service_property(
1994 const char *address,
1995 bt_gatt_handle_property_t *service_handle,
1996 bt_gatt_service_property_t *service)
1998 int result = BLUETOOTH_ERROR_NONE;
1999 bluetooth_gatt_client_svc_prop_info_t svc_prop;
2000 bt_char_browse_info_t char_handles_info;
2002 BT_CHECK_PARAMETER(address, return);
2003 BT_CHECK_PARAMETER(service_handle, return);
2004 BT_CHECK_PARAMETER(service, return);
2005 BT_CHECK_ENABLED(return);
2007 /* Call to bt-service (sync) and send address and service_handle info */
2009 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2011 memset(&svc_prop, 0x00, sizeof(bluetooth_gatt_client_svc_prop_info_t));
2012 /* All characteristics handles are discovered */
2013 memset(&char_handles_info, 0x00, sizeof(bt_char_browse_info_t));
2015 svc_prop.svc.instance_id = service_handle->instance_id;
2016 memcpy(&svc_prop.svc.uuid, &service_handle->uuid, 16);
2018 _bt_convert_addr_string_to_type(svc_prop.device_address.addr, address);
2020 g_array_append_vals(in_param1, &svc_prop, sizeof(bluetooth_gatt_client_svc_prop_info_t));
2022 result = _bt_send_request(BT_BLUEZ_SERVICE,
2023 BT_GATT_GET_SERVICE_PROPERTIES,
2024 in_param1, in_param2, in_param3, in_param4, &out_param);
2026 if (BLUETOOTH_ERROR_NONE != result)
2029 char_handles_info = g_array_index(
2030 out_param, bt_char_browse_info_t, 0);
2031 __bt_fill_char_handle_informations(&char_handles_info,
2033 /* TODO Get all Included Services */
2036 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2040 BT_EXPORT_API int bluetooth_gatt_client_get_characteristics_property(
2041 const char *address,
2042 bt_gatt_handle_property_t *service_handle,
2043 bt_gatt_handle_property_t *char_handle,
2044 bt_gatt_char_property_t *char_property)
2046 int result = BLUETOOTH_ERROR_NONE;
2047 bt_descriptor_browse_info_t desc_handles_info;
2048 bluetooth_gatt_client_char_prop_info_t char_prop;
2050 BT_CHECK_PARAMETER(address, return);
2051 BT_CHECK_PARAMETER(service_handle, return);
2052 BT_CHECK_PARAMETER(char_handle, return);
2053 BT_CHECK_PARAMETER(char_property, return);
2054 BT_CHECK_ENABLED(return);
2057 /* Call to bt-service (sync) and send address service_handle info & char handle info */
2059 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2061 memset(&char_prop, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2062 char_prop.svc.instance_id = service_handle->instance_id;
2063 memcpy(&char_prop.svc.uuid, &service_handle->uuid, 16);
2065 char_prop.characteristic.instance_id = char_handle->instance_id;
2066 memcpy(&char_prop.characteristic.uuid, &char_handle->uuid, 16);
2068 _bt_convert_addr_string_to_type(char_prop.device_address.addr, address);
2070 g_array_append_vals(in_param1, &char_prop, sizeof(bluetooth_gatt_client_char_prop_info_t));
2072 result = _bt_send_request(BT_BLUEZ_SERVICE,
2073 BT_GATT_GET_CHARACTERISTIC_PROPERTIES,
2074 in_param1, in_param2, in_param3, in_param4, &out_param);
2076 if (BLUETOOTH_ERROR_NONE != result)
2079 /* All descriptors handles are discovered */
2080 memset(&desc_handles_info, 0x00, sizeof(bt_descriptor_browse_info_t));
2082 desc_handles_info = g_array_index(
2083 out_param, bt_descriptor_browse_info_t, 0);
2085 __bt_fill_desc_handle_informations(&desc_handles_info,
2089 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2091 /* Call to bt-service (sync) and send address, service_handle & char_handle infos */
2093 /* After result is fetched, extract descriptor handles (UUID's & instance_id's) */
2095 /* Fill the info in *char_prop */
2097 /*No: Before returning, call bluetooth_gatt_client_read_characteristic_value as
2098 an asyn function and leave every thing else in the callback */
2101 BT_EXPORT_API int bluetooth_gatt_client_get_char_descriptor_property(
2102 const char *address,
2103 bt_gatt_handle_property_t *service_handle,
2104 bt_gatt_handle_property_t *char_handle,
2105 bt_gatt_handle_property_t *descriptor_handle,
2106 bt_gatt_char_descriptor_property_t *desc_prop)
2108 char uuid_string[BLUETOOTH_UUID_STRING_MAX];
2110 BT_CHECK_PARAMETER(address, return);
2111 BT_CHECK_PARAMETER(service_handle, return);
2112 BT_CHECK_PARAMETER(char_handle, return);
2113 BT_CHECK_PARAMETER(descriptor_handle, return);
2114 BT_CHECK_PARAMETER(desc_prop, return);
2115 /* No Need to Call to bt-service (sync) and send address, service_handle,
2116 char_handle & descriptor handle infos */
2117 /* After result is fetched, extract descriptior handles (UUID's & instance_id's) */
2118 /* Fill the info in *desc_prop */
2119 __bt_uuid_hex_to_string(descriptor_handle->uuid, uuid_string);
2121 /* Before filling all desc handles, fill the charac's UUID and instance ID */
2122 desc_prop->uuid = g_strdup(uuid_string);
2124 return BLUETOOTH_ERROR_NONE;
2125 /* No: Before returning, call bluetooth_gatt_client_read_descriptor_value
2126 as an asyn function and leave every thing else in the callback */
2130 static gboolean bluetooth_gatt_client_notify_channel_watch_cb(GIOChannel *gio,
2131 GIOCondition cond, gpointer data)
2133 bt_gatt_characteristic_notify_info_t *chr_info = (bt_gatt_characteristic_notify_info_t *)data;
2136 BT_ERR("chr_info is invalid");
2139 if (cond & G_IO_IN) {
2140 GIOStatus status = G_IO_STATUS_NORMAL;
2142 char *buffer = NULL;
2144 bt_event_info_t *event_info;
2146 buffer = g_malloc0(chr_info->mtu + 1);
2147 memset(buffer, 0, chr_info->mtu + 1);
2149 status = g_io_channel_read_chars(gio, buffer,
2150 chr_info->mtu, &len, &err);
2151 if (status != G_IO_STATUS_NORMAL) {
2152 BT_ERR("IO Channel read is failed with %d", status);
2155 BT_ERR("IO Channel read error [%s]", err->message);
2156 if (status == G_IO_STATUS_ERROR) {
2157 BT_ERR("cond : %d", cond);
2159 g_io_channel_shutdown(gio, TRUE, NULL);
2160 g_io_channel_unref(gio);
2162 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2171 if (len > 0 && len < chr_info->mtu) {
2172 bt_gatt_char_property_t char_val;
2173 // 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);
2175 memcpy(char_val.prop.uuid, chr_info->UUID, 16);
2176 memcpy(char_val.value, buffer, len);
2177 char_val.val_len = len;
2178 memcpy(char_val.address, chr_info->address, 18);
2180 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2182 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
2183 BLUETOOTH_ERROR_NONE, &char_val,
2184 event_info->cb, event_info->user_data);
2186 BT_ERR("event_info failed");
2190 BT_ERR("Packet corrupted");
2197 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
2198 BT_ERR("Error : GIOCondition %d, [%s]", cond, chr_info->UUID);
2199 g_io_channel_shutdown(gio, TRUE, NULL);
2200 g_io_channel_unref(gio);
2202 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2211 #ifndef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2212 static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_get_characteristic_notify_info(unsigned char *handle , int id)
2216 for (l = gatt_characteristic_notify_list; l != NULL; l = l->next) {
2217 bt_gatt_characteristic_notify_info_t *info = l->data;
2218 if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
2225 static bt_gatt_characteristic_notify_info_t * bluetooth_gatt_client_create_watch_io(int fd, int id, int mtu, char * address, unsigned char *uuid)
2227 GIOChannel *channel;
2228 bt_gatt_characteristic_notify_info_t *chr_info;
2230 chr_info = g_malloc0(sizeof(bt_gatt_characteristic_notify_info_t));
2231 chr_info->notify_fd = fd;
2233 chr_info->mtu = mtu;
2234 g_strlcpy(chr_info->address, address, 18);
2235 memcpy(chr_info->UUID, uuid, 16);
2237 channel = g_io_channel_unix_new(fd);
2239 chr_info->io_channel = channel;
2241 g_io_channel_set_encoding(channel, NULL, NULL);
2242 g_io_channel_set_buffered(channel, FALSE);
2243 g_io_channel_set_close_on_unref(channel, TRUE);
2244 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
2246 chr_info->watch_id = g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
2247 bluetooth_gatt_client_notify_channel_watch_cb, chr_info);
2253 BT_EXPORT_API int bluetooth_gatt_client_watch_characteristics(
2254 const char *address,
2255 bt_gatt_handle_property_t *service_handle,
2256 bt_gatt_handle_property_t *char_handle,
2259 gboolean is_indicate)
2261 int result = BLUETOOTH_ERROR_NONE;
2262 bluetooth_gatt_client_char_prop_info_t param;
2263 bt_gatt_characteristic_notify_info_t *chr_info;
2265 BT_CHECK_PARAMETER(address, return);
2266 BT_CHECK_PARAMETER(service_handle, return);
2267 BT_CHECK_PARAMETER(char_handle, return);
2269 #ifndef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2270 chr_info = bluetooth_gatt_client_get_characteristic_notify_info(char_handle->uuid , char_handle->instance_id);
2271 if (chr_info && !is_notify) {
2272 BT_INFO("Already CCCD enabled. fd %d", chr_info->notify_fd);
2274 if (chr_info->watch_id > 0)
2275 g_source_remove(chr_info->watch_id);
2277 if (chr_info->io_channel) {
2278 g_io_channel_shutdown(chr_info->io_channel, TRUE, NULL);
2279 g_io_channel_unref(chr_info->io_channel);
2282 gatt_characteristic_notify_list = g_slist_remove(gatt_characteristic_notify_list, chr_info);
2290 /* ASync Function, result expected in callback from bt-service */
2293 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2295 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2297 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2298 param.svc.instance_id = service_handle->instance_id;
2300 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2301 param.characteristic.instance_id = char_handle->instance_id;
2303 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2305 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_char_prop_info_t));
2306 g_array_append_vals(in_param2, &client_id, sizeof(int));
2307 g_array_append_vals(in_param3, &is_notify, sizeof(gboolean));
2308 g_array_append_vals(in_param4, &is_indicate, sizeof(gboolean));
2310 #ifdef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2311 result = _bt_send_request(BT_BLUEZ_SERVICE,
2312 BT_GATT_WATCH_CHARACTERISTIC,
2313 in_param1, in_param2, in_param3, in_param4, &out_param);
2315 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2317 BT_INFO("Result [%d]", result);
2321 GUnixFDList *out_fd_list = NULL;
2322 char *svc_name = NULL;
2325 _bt_convert_uuid_type_to_string(str_uuid, param.svc.uuid);
2326 bluetooth_get_uuid_name(str_uuid, &svc_name);
2328 _bt_convert_uuid_type_to_string(str_uuid, param.characteristic.uuid);
2330 BT_INFO_C("### Request subscription Notify : %s [%s]", str_uuid, svc_name);
2333 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_WATCH_CHARACTERISTIC,
2334 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
2335 if (result != BLUETOOTH_ERROR_NONE) {
2336 BT_ERR("Fail to get Nofify FD. result %d", result);
2337 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2341 if (is_indicate == false) {
2342 if (NULL == out_fd_list) {
2343 BT_ERR("out_fd_list is NULL");
2344 result = BLUETOOTH_ERROR_INTERNAL;
2351 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
2352 BT_DBG("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
2353 fd = fd_list_array[0];
2354 mtu = g_array_index(out_param, int, 0);
2356 BT_INFO("Acquired characteristic Notify FD %d, mtu %d", fd, mtu);
2357 chr_info = bluetooth_gatt_client_create_watch_io(fd, char_handle->instance_id, mtu, (char *)address, char_handle->uuid);
2359 gatt_characteristic_notify_list = g_slist_append(gatt_characteristic_notify_list, chr_info);
2361 g_free(fd_list_array);
2362 g_object_unref(out_fd_list);
2366 /*result = _bt_send_request(BT_BLUEZ_SERVICE,
2367 BT_GATT_WATCH_CHARACTERISTIC,
2368 in_param1, in_param2, in_param3, in_param4, &out_param);*/
2370 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2375 BT_EXPORT_API int bluetooth_gatt_client_read_characteristic_value(
2376 const char *address,
2377 bt_gatt_handle_property_t *service_handle,
2378 bt_gatt_handle_property_t *char_handle)
2380 int result = BLUETOOTH_ERROR_NONE;
2381 bt_user_info_t *user_info;
2382 bluetooth_gatt_client_char_prop_info_t param;
2384 BT_CHECK_PARAMETER(address, return);
2385 BT_CHECK_PARAMETER(service_handle, return);
2386 BT_CHECK_PARAMETER(char_handle, return);
2388 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2389 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2392 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2394 /* Async Function, result expected in callback from bt-service */
2395 /* Call to bt-service (sync) and send address service_handle info & char handle info */
2396 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2398 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2399 param.svc.instance_id = service_handle->instance_id;
2401 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2402 param.characteristic.instance_id = char_handle->instance_id;
2404 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2406 g_array_append_vals(in_param1, ¶m,
2407 sizeof(bluetooth_gatt_client_char_prop_info_t));
2409 result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC,
2410 in_param1, in_param2, in_param3, in_param4,
2411 user_info->cb, user_info->user_data);
2413 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2417 BT_EXPORT_API int bluetooth_gatt_client_read_descriptor_value(
2418 const char *address,
2419 bt_gatt_handle_property_t *service_handle,
2420 bt_gatt_handle_property_t *char_handle,
2421 bt_gatt_handle_property_t *descriptor_handle)
2423 int result = BLUETOOTH_ERROR_NONE;
2424 bt_user_info_t *user_info;
2425 bluetooth_gatt_client_desc_prop_info_t param;
2427 BT_CHECK_PARAMETER(address, return);
2428 BT_CHECK_PARAMETER(service_handle, return);
2429 BT_CHECK_PARAMETER(char_handle, return);
2430 BT_CHECK_PARAMETER(descriptor_handle, return);
2432 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2433 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2436 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2438 /* Async Function, result expected in callback from bt-service */
2439 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2441 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2442 param.svc.instance_id = service_handle->instance_id;
2444 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2445 param.characteristic.instance_id = char_handle->instance_id;
2447 memcpy(¶m.descriptor.uuid, descriptor_handle->uuid, 16);
2448 param.descriptor.instance_id = descriptor_handle->instance_id;
2450 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2452 g_array_append_vals(in_param1, ¶m,
2453 sizeof(bluetooth_gatt_client_desc_prop_info_t));
2455 result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_GATT_READ_DESCRIPTOR_VALUE,
2456 in_param1, in_param2, in_param3, in_param4,
2457 user_info->cb, user_info->user_data);
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)
2469 for (l = gatt_characteristic_write_list; l != NULL; l = l->next) {
2470 bt_gatt_characteristic_write_info_t *info = l->data;
2472 if (memcmp(info->UUID, handle, 16) == 0 && info->id == id)
2476 _bt_convert_uuid_type_to_string(str, handle);
2477 BT_ERR("Unable to get characteristic fd. [%s] id [ %d]", str, id);
2481 static gboolean bluetooth_gatt_client_write_channel_watch_cb(GIOChannel *gio,
2482 GIOCondition cond, gpointer data)
2484 bt_gatt_characteristic_write_info_t *chr_info = (bt_gatt_characteristic_write_info_t *)data;
2489 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
2491 _bt_convert_uuid_type_to_string(uuid_str, chr_info->UUID);
2492 BT_ERR("Error : GIOCondition %d, [%s]", cond, uuid_str);
2493 g_io_channel_shutdown(gio, TRUE, NULL);
2494 g_io_channel_unref(gio);
2496 gatt_characteristic_write_list = g_slist_remove(gatt_characteristic_write_list, chr_info);
2505 static int bluetooth_gatt_client_write_characteristics_value_to_fd(
2506 int fd, const guint8 *value, int length, int mtu,
2510 int att_result = BLUETOOTH_ERROR_NONE;
2511 BT_CHECK_PARAMETER(value, return);
2512 written = write(fd, value, length);
2513 if (written != length) {
2514 att_result = BLUETOOTH_ERROR_INTERNAL;
2515 BT_ERR("write data failed. ret : %d ", written);
2521 static void bluetooth_gatt_client_create_write_io_channel(int fd, unsigned char * uuid, int id, int mtu)
2523 bt_gatt_characteristic_write_info_t *chr_info;
2524 GIOChannel *channel;
2526 chr_info = g_malloc0(sizeof(bt_gatt_characteristic_write_info_t));
2527 chr_info->write_fd = fd;
2529 chr_info->mtu = mtu;
2531 memcpy(chr_info->UUID, uuid, 16);
2532 channel = g_io_channel_unix_new(fd);
2533 g_io_channel_set_encoding(channel, NULL, NULL);
2534 g_io_channel_set_buffered(channel, FALSE);
2535 g_io_channel_set_close_on_unref(channel, TRUE);
2536 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
2537 g_io_add_watch(channel, (G_IO_ERR | G_IO_HUP | G_IO_NVAL),
2538 bluetooth_gatt_client_write_channel_watch_cb, chr_info);
2540 gatt_characteristic_write_list = g_slist_append(gatt_characteristic_write_list, chr_info);
2544 BT_EXPORT_API int bluetooth_gatt_client_write_characteristic_value_by_type(
2545 const char *address,
2546 bt_gatt_handle_property_t *service_handle,
2547 bt_gatt_handle_property_t *char_handle,
2548 bluetooth_gatt_att_data_t *data,
2549 bluetooth_gatt_write_type_e write_type)
2551 int result = BLUETOOTH_ERROR_NONE;
2552 bt_user_info_t *user_info;
2553 bluetooth_gatt_client_char_prop_info_t param;
2555 BT_CHECK_PARAMETER(address, return);
2556 BT_CHECK_PARAMETER(service_handle, return);
2557 BT_CHECK_PARAMETER(char_handle, return);
2558 BT_CHECK_PARAMETER(data, return);
2560 /* ASync Function, result expected in callback from bt-service */
2561 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2562 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2565 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2567 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
2569 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2570 param.svc.instance_id = service_handle->instance_id;
2572 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2573 param.characteristic.instance_id = char_handle->instance_id;
2575 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2577 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_char_prop_info_t));
2578 g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2579 g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2581 #ifdef TIZEN_FEATURE_BT_GATT_CLIENT_FD_DISABLE
2585 if (write_type == BLUETOOTH_GATT_TYPE_WRITE_NO_RESPONSE) {
2588 bt_gatt_characteristic_write_info_t *info;
2589 info = bluetooth_gatt_client_get_characteristic_fd(char_handle->uuid, service_handle->instance_id);
2592 fd = info->write_fd;
2598 GUnixFDList *out_fd_list = NULL;
2600 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_ACQUIRE_WRITE,
2601 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
2603 mtu = g_array_index(out_param, int, 0);
2605 if (result != BLUETOOTH_ERROR_NONE) {
2606 BT_ERR("Fail to get Write FD. result %d", result);
2607 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2609 } else if (NULL == out_fd_list) {
2610 BT_ERR("out_fd_list is NULL");
2611 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2612 return BLUETOOTH_ERROR_INTERNAL;
2617 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
2618 fd = fd_list_array[0];
2620 g_free(fd_list_array);
2621 g_object_unref(out_fd_list);
2623 BT_INFO("Acquired characteristic Write FD %d, mtu %d", fd, mtu);
2626 bluetooth_gatt_client_create_write_io_channel(fd, char_handle->uuid, service_handle->instance_id, mtu);
2628 result = bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
2631 BT_ERR("characteristic info FD is invalid");
2636 result = bluetooth_gatt_client_write_characteristics_value_to_fd(fd, data->data, data->length, mtu, NULL);
2641 result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2642 BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE,
2643 in_param1, in_param2, in_param3, in_param4,
2644 user_info->cb, user_info->user_data);
2647 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2652 BT_EXPORT_API int bluetooth_gatt_client_write_descriptor_value(
2653 const char *address,
2654 bt_gatt_handle_property_t *service_handle,
2655 bt_gatt_handle_property_t *char_handle,
2656 bt_gatt_handle_property_t *descriptor_handle,
2657 bluetooth_gatt_att_data_t *data,
2658 bluetooth_gatt_write_type_e write_type)
2660 int result = BLUETOOTH_ERROR_NONE;
2661 bt_user_info_t *user_info;
2662 bluetooth_gatt_client_desc_prop_info_t param;
2664 BT_CHECK_PARAMETER(address, return);
2665 BT_CHECK_PARAMETER(service_handle, return);
2666 BT_CHECK_PARAMETER(char_handle, return);
2667 BT_CHECK_PARAMETER(descriptor_handle, return);
2668 BT_CHECK_PARAMETER(data, return);
2670 /* Async Function, result expected in callback from bt-service */
2671 user_info = _bt_get_user_data(BT_GATT_CLIENT);
2672 retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
2675 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2677 memset(¶m, 0x00, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2679 memcpy(¶m.svc.uuid, service_handle->uuid, 16);
2680 param.svc.instance_id = service_handle->instance_id;
2682 memcpy(¶m.characteristic.uuid, char_handle->uuid, 16);
2683 param.characteristic.instance_id = char_handle->instance_id;
2685 memcpy(¶m.descriptor.uuid, descriptor_handle->uuid, 16);
2686 param.descriptor.instance_id = descriptor_handle->instance_id;
2688 _bt_convert_addr_string_to_type(param.device_address.addr, address);
2690 g_array_append_vals(in_param1, ¶m, sizeof(bluetooth_gatt_client_desc_prop_info_t));
2691 g_array_append_vals(in_param2, data, sizeof(bluetooth_gatt_att_data_t));
2692 g_array_append_vals(in_param3, &write_type, sizeof(bluetooth_gatt_write_type_e));
2694 result = _bt_send_request_async(BT_BLUEZ_SERVICE,
2695 BT_GATT_WRITE_DESCRIPTOR_VALUE,
2696 in_param1, in_param2, in_param3, in_param4,
2697 user_info->cb, user_info->user_data);
2699 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2704 BT_EXPORT_API int bluetooth_gatt_client_set_service_change_watcher(
2705 const bluetooth_device_address_t *address, gboolean enable)
2708 bluetooth_device_address_t *addr = NULL;
2709 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2710 char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2711 int result = BLUETOOTH_ERROR_NONE;
2714 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2716 g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t));
2717 g_array_append_vals(in_param2, &enable, sizeof(gboolean));
2719 _bt_convert_addr_type_to_string(device_address, (unsigned char *)address->addr);
2720 _bt_convert_addr_string_to_secure_string(secure_address, device_address);
2721 BT_INFO("%s watcher for [%s]", enable ? "Set":"Unset", secure_address);
2723 if (enable == TRUE) {
2724 if (_bluetooth_gatt_check_service_change_watcher_address(address)
2726 BT_INFO("The watcher is already set");
2730 if (service_monitor_list == NULL) {
2731 //_bt_register_manager_subscribe_signal(TRUE);
2733 result = _bt_send_request(BT_BLUEZ_SERVICE,
2734 BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2735 in_param1, in_param2, in_param3, in_param4, &out_param);
2738 if (result == BLUETOOTH_ERROR_NONE) {
2739 addr = g_malloc0(sizeof(bluetooth_device_address_t));
2740 memcpy(addr, address, sizeof(bluetooth_device_address_t));
2742 service_monitor_list =
2743 g_slist_append(service_monitor_list, addr);
2746 for (l = service_monitor_list; l != NULL; l = l->next) {
2749 if (!memcmp(address, addr,
2750 sizeof(bluetooth_device_address_t))) {
2751 service_monitor_list =
2752 g_slist_remove(service_monitor_list, addr);
2758 if (service_monitor_list == NULL) {
2759 //_bt_register_manager_subscribe_signal(FALSE);
2760 result = _bt_send_request(BT_BLUEZ_SERVICE,
2761 BT_GATT_WATCH_SERVICE_CHANGED_INDICATION,
2762 in_param1, in_param2, in_param3, in_param4, &out_param);
2768 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2772 BT_EXPORT_API int bluetooth_gatt_client_deinit(
2777 bt_event_info_t *event_info;
2779 BT_CHECK_ENABLED(return);
2781 BT_INFO("GATT Client Deinit Client instance ID [%d]", client_id);
2784 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2786 g_array_append_vals(in_param1, &client_id, sizeof(int));
2788 /* Unregistration MUST NOT FAIL */
2789 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_CLIENT_UNREGISTER,
2790 in_param1, in_param2, in_param3, in_param4, &out_param);
2792 if (result != BLUETOOTH_ERROR_NONE)
2793 BT_ERR("GATT Client Unregistration failed result [%d]", result);
2795 /* Unregister event handler if this is the only instance */
2796 event_info = _bt_event_get_cb_data(BT_GATT_CLIENT_EVENT);
2799 count = (int*)event_info->user_data;
2801 BT_DBG("Total num of GATT client instances [%d]", *count);
2804 BT_DBG("Currently only one GATT client instance, so remove it and unregister GATT client events");
2805 _bt_unregister_event(BT_GATT_CLIENT_EVENT);
2806 _bt_set_user_data(BT_GATT_CLIENT, NULL, NULL);
2810 BT_ERR("Impossible that client is created, but no event handler is registered!!!");
2812 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);