2 * Bluetooth-frwk low energy (GATT Client)
4 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Chanyeol Park <chanyeol.park@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
25 #include <glib/gprintf.h>
30 #include "bt-common.h"
32 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
33 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
34 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
36 #define GATT_USER_DESC_UUID "00002901-0000-1000-8000-00805f9b34fb"
37 #define GATT_CHAR_CLIENT_CONF "00002902-0000-1000-8000-00805f9b34fb"
38 #define GATT_CHAR_SERVER_CONF "00002903-0000-1000-8000-00805f9b34fb"
39 #define GATT_CHAR_FORMAT "00002904-0000-1000-8000-00805f9b34fb"
47 }char_descriptor_type_t;
49 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
53 BT_CHECK_PARAMETER(svc_pty, return);
55 g_free(svc_pty->uuid);
56 g_free(svc_pty->handle);
57 g_strfreev(svc_pty->include_handles.handle);
58 g_strfreev(svc_pty->char_handle.handle);
60 memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
63 return BLUETOOTH_ERROR_NONE;
66 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
70 BT_CHECK_PARAMETER(char_pty, return);
72 g_free(char_pty->uuid);
73 g_free(char_pty->name);
74 g_free(char_pty->description);
75 g_free(char_pty->val);
76 g_free(char_pty->handle);
77 g_strfreev(char_pty->char_desc_handle.handle);
79 memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
82 return BLUETOOTH_ERROR_NONE;
85 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 g_free(desc_pty->handle);
95 memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t));
98 return BLUETOOTH_ERROR_NONE;
101 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
103 gchar *gp_path = NULL;
110 path = g_malloc0((gp->len + 1) * sizeof(char *));
112 for (i = 0; i < gp->len; i++) {
113 gp_path = g_ptr_array_index(gp, i);
114 path[i] = g_strdup(gp_path);
115 BT_DBG("path[%d] : [%s]", i, path[i]);
121 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
122 bt_gatt_service_property_t *service)
124 GDBusProxy *properties_proxy = NULL;
125 GError *error = NULL;
126 GVariant *result = NULL;
127 GDBusConnection *g_conn;
129 char *char_handle = NULL;
130 GPtrArray *gp_array = NULL ;
131 GVariantIter *property_iter, *char_iter;
135 BT_CHECK_PARAMETER(service_handle, return);
136 BT_CHECK_PARAMETER(service, return);
137 BT_CHECK_ENABLED(return);
139 g_conn = _bt_gdbus_get_system_gconn();
140 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
142 properties_proxy = g_dbus_proxy_new_sync(g_conn,
143 G_DBUS_PROXY_FLAGS_NONE, NULL,
146 BT_PROPERTIES_INTERFACE,
149 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
151 result = g_dbus_proxy_call_sync(properties_proxy,
153 g_variant_new("(s)", GATT_SERV_INTERFACE),
154 G_DBUS_CALL_FLAGS_NONE,
161 BT_ERR("Fail to get properties (Error: %s)", error->message);
162 g_clear_error(&error);
164 BT_ERR("Fail to get properties");
165 g_object_unref(properties_proxy);
166 return BLUETOOTH_ERROR_INTERNAL;
169 g_variant_get(result, "(a{sv})", &property_iter);
171 memset(service, 0, sizeof(bt_gatt_service_property_t));
173 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
174 if (!g_strcmp0(key,"UUID")) {
175 service->uuid = g_variant_dup_string(value,&len);
177 } else if(!g_strcmp0(key, "Primary")) {
178 service->primary = g_variant_get_boolean(value);
180 } else if (!g_strcmp0(key, "Includes")) {
181 g_variant_get(value, "ao", &char_iter);
182 gp_array = g_ptr_array_new();
183 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
184 g_ptr_array_add(gp_array, (gpointer)char_handle);
186 if (gp_array->len != 0) {
187 service->include_handles.count = gp_array->len;
188 service->include_handles.handle =
189 __get_string_array_from_gptr_array(gp_array);
191 g_ptr_array_free(gp_array, TRUE);
192 } else if (!g_strcmp0(key, "Characteristics")) {
193 g_variant_get(value, "ao", &char_iter);
194 gp_array = g_ptr_array_new();
195 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
196 g_ptr_array_add(gp_array, (gpointer)char_handle);
198 if (gp_array->len != 0) {
199 service->char_handle.count = gp_array->len;
200 service->char_handle.handle =
201 __get_string_array_from_gptr_array(gp_array);
203 g_ptr_array_free(gp_array, TRUE);
207 service->handle = g_strdup(service_handle);
209 g_variant_iter_free(property_iter);
210 g_variant_unref(result);
211 g_object_unref(properties_proxy);
213 return BLUETOOTH_ERROR_NONE;
216 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
217 const bluetooth_device_address_t *address,
218 bt_gatt_handle_info_t *prim_svc)
220 GVariant *result = NULL;
222 GVariantIter *svc_iter;
223 GVariantIter *interface_iter;
224 char *object_path = NULL;
225 char *interface_str = NULL;
226 const gchar *key = NULL;
227 GVariant *value = NULL;
228 GPtrArray *gp_array = NULL;
229 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
230 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
231 int ret = BLUETOOTH_ERROR_INTERNAL;
234 BT_CHECK_PARAMETER(address, return);
235 BT_CHECK_PARAMETER(prim_svc, return);
236 BT_CHECK_ENABLED(return);
238 result = _bt_get_managed_objects();
242 _bt_convert_addr_type_to_string(device_address,
243 (unsigned char *)address->addr);
245 gp_array = g_ptr_array_new();
246 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
248 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
250 if (object_path == NULL)
253 _bt_convert_device_path_to_address(object_path, temp_address);
255 if (g_strcmp0(temp_address, device_address) != 0)
258 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
259 &interface_str, &svc_iter)) {
260 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
263 BT_DBG("Object Path: %s", object_path);
264 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
265 if (g_strcmp0(key, "Primary") == 0) {
266 if (g_variant_get_boolean(value))
267 g_ptr_array_add(gp_array, (gpointer)object_path);
273 if (gp_array->len == 0) {
274 BT_ERR("gp_array is NULL");
275 ret = BLUETOOTH_ERROR_NOT_FOUND;
277 ret = BLUETOOTH_ERROR_NONE;
278 prim_svc->count = gp_array->len;
279 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
282 g_ptr_array_free(gp_array, TRUE);
283 g_variant_iter_free(iter);
284 g_variant_unref(result);
289 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
290 const char *service_uuid,
291 bt_gatt_service_property_t *service)
293 GVariant *result = NULL;
295 GVariantIter *svc_iter;
296 GVariantIter *interface_iter;
297 GError *error = NULL;
298 char *object_path = NULL;
299 char *interface_str = NULL;
300 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
301 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
302 int ret = BLUETOOTH_ERROR_INTERNAL;
304 BT_CHECK_PARAMETER(address, return);
305 BT_CHECK_PARAMETER(service_uuid, return);
306 BT_CHECK_PARAMETER(service, return);
307 BT_CHECK_ENABLED(return);
309 result = _bt_get_managed_objects();
313 _bt_convert_addr_type_to_string(device_address,
314 (unsigned char *)address->addr);
316 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
318 while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
320 if (object_path == NULL)
323 _bt_convert_device_path_to_address(object_path,
326 if (g_strcmp0(temp_address, device_address) != 0)
329 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
330 &interface_str, &svc_iter)) {
331 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
334 BT_DBG("Object Path: %s", object_path);
335 ret = bluetooth_gatt_get_service_property(object_path,
338 if (ret != BLUETOOTH_ERROR_NONE) {
339 BT_ERR("Get service property failed(0x%08x)", ret);
341 if (service->primary == TRUE &&
342 g_strstr_len(service->uuid, -1,
344 ret = BLUETOOTH_ERROR_NONE;
348 bluetooth_gatt_free_service_property(service);
353 g_variant_iter_free(iter);
354 g_variant_unref(result);
359 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
360 GAsyncResult *res, gpointer user_data)
363 GVariant *char_value;
364 GVariantIter *char_iter;
365 GPtrArray *gp_array = NULL;
366 bt_gatt_discovered_char_t svc_char = { 0, };
369 GError *error = NULL;
370 bt_user_info_t *user_info;
374 user_info = _bt_get_user_data(BT_COMMON);
375 svc_char.service_handle = user_data;
377 value = g_dbus_proxy_call_finish(proxy, res, &error);
381 BT_ERR("Get service characteristics failed\n errCode[%x],"
382 "message[%s]\n", error->code, error->message);
383 g_clear_error(&error);
385 BT_ERR("Get service characteristics failed\n");
388 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
389 BLUETOOTH_ERROR_INTERNAL, NULL,
390 user_info->cb, user_info->user_data);
392 g_free(svc_char.service_handle);
393 g_object_unref(proxy);
397 g_variant_get(value, "(v)", &char_value);
398 g_variant_get(char_value, "ao", &char_iter);
400 int len = g_variant_get_size(char_iter);
402 gp_array = g_ptr_array_new();
403 for (i = 0; i < len; i++) {
404 g_variant_iter_loop(char_iter, "&o", &char_handle);
405 g_ptr_array_add(gp_array, (gpointer)char_handle);
407 if (gp_array->len != 0) {
408 svc_char.handle_info.count = gp_array->len;
409 svc_char.handle_info.handle =
410 __get_string_array_from_gptr_array(gp_array);
412 g_ptr_array_free(gp_array, TRUE);
416 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
417 BLUETOOTH_ERROR_NONE, &svc_char,
418 user_info->cb, user_info->user_data);
421 g_strfreev(svc_char.handle_info.handle);
422 g_free(svc_char.service_handle);
423 g_variant_iter_free(char_iter);
424 g_object_unref(proxy);
427 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
428 const char *service_handle)
430 GDBusProxy *properties_proxy = NULL;
431 GDBusConnection *g_conn;
432 GError *error = NULL;
437 BT_CHECK_PARAMETER(service_handle, return);
438 BT_CHECK_ENABLED(return);
440 g_conn = _bt_gdbus_get_system_gconn();
441 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
443 properties_proxy = g_dbus_proxy_new_sync(g_conn,
444 G_DBUS_PROXY_FLAGS_NONE, NULL,
447 BT_PROPERTIES_INTERFACE,
450 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
452 handle = g_strdup(service_handle);
453 g_dbus_proxy_call(properties_proxy,
455 g_variant_new("(ss)",
456 GATT_SERV_INTERFACE, "Characteristics"),
457 G_DBUS_CALL_FLAGS_NONE,
460 (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
464 return BLUETOOTH_ERROR_NONE;
468 static int __get_permission_flag(char *permission)
472 retv_if(permission == NULL, ret);
474 BT_DBG("permission = %s",permission);
476 if (!g_strcmp0(permission,"broadcast")) {
477 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
478 } else if (!g_strcmp0(permission,"read")) {
479 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
480 } else if (!g_strcmp0(permission,"write-without-response")) {
481 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
482 } else if (!g_strcmp0(permission,"write")) {
483 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
484 } else if (!g_strcmp0(permission,"notify")) {
485 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
486 } else if (!g_strcmp0(permission,"indicate")) {
487 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
488 } else if (!g_strcmp0(permission,"authenticated-signed-writes")) {
489 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
490 } else if (!g_strcmp0(permission,"reliable-write")) {
491 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
492 } else if (!g_strcmp0(permission,"writable-auxiliaries")) {
493 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
499 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
500 const char *char_handle, bt_gatt_char_property_t *characteristic)
502 GDBusProxy *properties_proxy = NULL;
503 GError *error = NULL;
504 GVariant *value = NULL;
505 GVariant *result = NULL;
506 GByteArray *gb_array = NULL;
507 GPtrArray *gp_array = NULL ;
508 GDBusConnection *g_conn;
512 char *char_desc_handle = NULL;
514 GVariantIter *property_iter;
515 GVariantIter *char_value_iter;
516 GVariantIter *char_perm_iter;
517 GVariantIter *char_desc_iter;
520 BT_CHECK_PARAMETER(char_handle, return);
521 BT_CHECK_PARAMETER(characteristic, return);
523 BT_CHECK_ENABLED(return);
525 g_conn = _bt_gdbus_get_system_gconn();
526 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
528 properties_proxy = g_dbus_proxy_new_sync(g_conn,
529 G_DBUS_PROXY_FLAGS_NONE, NULL,
532 BT_PROPERTIES_INTERFACE,
535 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
537 result = g_dbus_proxy_call_sync(properties_proxy,
539 g_variant_new("(s)", GATT_CHAR_INTERFACE),
540 G_DBUS_CALL_FLAGS_NONE,
547 BT_ERR("Fail to get properties (Error: %s)", error->message);
548 g_clear_error(&error);
550 BT_ERR("Fail to get properties");
551 g_object_unref(properties_proxy);
552 return BLUETOOTH_ERROR_INTERNAL;
555 g_variant_get(result, "(a{sv})", &property_iter);
557 memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
558 characteristic->handle = g_strdup(char_handle);
560 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
562 if (!g_strcmp0(key,"UUID")) {
563 characteristic->uuid = g_variant_dup_string(value,&len);
564 BT_DBG("UUID of the char = %s",characteristic->uuid);
565 } else if(!g_strcmp0(key, "Value")) {
566 gb_array = g_byte_array_new();
567 g_variant_get(value, "ay", &char_value_iter);
568 while(g_variant_iter_loop(char_value_iter, "y", &char_value)) {
569 BT_DBG("value of char = %d",char_value);
570 g_byte_array_append(gb_array, &char_value, 1);
572 if (gb_array->len != 0) {
573 characteristic->val = g_malloc0(gb_array->len *
574 sizeof(unsigned char));
575 memcpy(characteristic->val, gb_array->data, gb_array->len);
577 characteristic->val_len = gb_array->len;
578 g_byte_array_free(gb_array, TRUE);
579 } else if(!g_strcmp0(key, "Flags")) {
580 g_variant_get(value, "as", &char_perm_iter);
581 characteristic->permission = 0x00;
582 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
583 BT_DBG("permission = %s",permission);
584 characteristic->permission |= __get_permission_flag(permission);
585 BT_DBG("permission check = %d",characteristic->permission);
587 g_variant_iter_free(char_perm_iter);
588 } else if (!g_strcmp0(key, "Descriptors")) {
589 g_variant_get(value, "ao", &char_desc_iter);
590 gp_array = g_ptr_array_new();
591 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
592 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
594 if (gp_array->len != 0) {
595 characteristic->char_desc_handle.count = gp_array->len;
596 characteristic->char_desc_handle.handle =
597 __get_string_array_from_gptr_array(gp_array);
599 g_ptr_array_free(gp_array, TRUE);
603 g_variant_iter_free(property_iter);
604 g_variant_unref(result);
605 g_object_unref(properties_proxy);
608 return BLUETOOTH_ERROR_NONE;
611 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
612 GAsyncResult *res, gpointer user_data)
615 GVariantIter *char_iter;
618 GError *error = NULL;
619 bt_user_info_t *user_info;
620 int ret = BLUETOOTH_ERROR_INTERNAL;
621 bt_gatt_char_property_t characteristic;
623 user_info = _bt_get_user_data(BT_COMMON);
625 value = g_dbus_proxy_call_finish(proxy, res, &error);
629 BT_ERR("Get service characteristics failed\n errCode[%x],"
630 "message[%s]\n", error->code, error->message);
631 g_clear_error(&error);
633 BT_ERR("Get service characteristics failed\n");
636 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
637 BLUETOOTH_ERROR_INTERNAL, NULL,
638 user_info->cb, user_info->user_data);
640 g_object_unref(proxy);
645 g_variant_get(value, "(ao)", &char_iter);
647 len = g_variant_get_size(char_iter);
649 for (i = 0; i < len; i++) {
650 g_variant_iter_loop(char_iter, "o", &char_handle);
653 ret = bluetooth_gatt_get_characteristics_property(char_handle,
656 if (ret != BLUETOOTH_ERROR_NONE) {
657 BT_ERR("Get characteristic property failed(0x%08x)", ret);
659 if (g_strstr_len(characteristic.uuid, -1, user_data)) {
660 ret = BLUETOOTH_ERROR_NONE;
664 bluetooth_gatt_free_char_property(&characteristic);
668 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
669 &characteristic, user_info->cb, user_info->user_data);
672 bluetooth_gatt_free_char_property(&characteristic);
673 g_variant_iter_free(char_iter);
677 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
678 const char *char_uuid)
680 GDBusProxy *properties_proxy = NULL;
681 GDBusConnection *g_conn;
682 GError *error = NULL;
685 BT_CHECK_PARAMETER(service_handle, return);
686 BT_CHECK_PARAMETER(char_uuid, return);
687 BT_CHECK_ENABLED(return);
689 g_conn = _bt_gdbus_get_system_gconn();
690 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
692 properties_proxy = g_dbus_proxy_new_sync(g_conn,
693 G_DBUS_PROXY_FLAGS_NONE, NULL,
696 BT_PROPERTIES_INTERFACE,
699 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
701 uuid = g_strdup(char_uuid);
702 g_dbus_proxy_call(properties_proxy,
704 g_variant_new("(ss)",
705 GATT_SERV_INTERFACE, "Characteristics"),
706 G_DBUS_CALL_FLAGS_NONE,
709 (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
712 return BLUETOOTH_ERROR_NONE;
715 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
716 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
718 GDBusProxy *properties_proxy = NULL;
719 GError *error = NULL;
720 GDBusConnection *g_conn;
721 GVariant *result = NULL;
722 GVariantIter *property_iter;
726 GVariant *value = NULL;
727 GByteArray *gb_array = NULL;
728 GVariantIter *desc_value_iter;
731 BT_CHECK_PARAMETER(descriptor_handle, return);
732 BT_CHECK_PARAMETER(descriptor, return);
734 BT_CHECK_ENABLED(return);
736 g_conn = _bt_gdbus_get_system_gconn();
737 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
739 properties_proxy = g_dbus_proxy_new_sync(g_conn,
740 G_DBUS_PROXY_FLAGS_NONE, NULL,
743 BT_PROPERTIES_INTERFACE,
746 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
748 result = g_dbus_proxy_call_sync(properties_proxy,
750 g_variant_new("(s)", GATT_DESC_INTERFACE),
751 G_DBUS_CALL_FLAGS_NONE,
758 BT_ERR("Fail to get properties (Error: %s)", error->message);
759 g_clear_error(&error);
761 BT_ERR("Fail to get properties");
762 g_object_unref(properties_proxy);
763 return BLUETOOTH_ERROR_INTERNAL;
766 g_variant_get(result, "(a{sv})", &property_iter);
768 memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
769 descriptor->handle = g_strdup(descriptor_handle);
771 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
773 if (!g_strcmp0(key,"UUID")) {
774 descriptor->uuid = g_variant_dup_string(value,&len);
775 BT_DBG("UUID of the char_desc = %s",descriptor->uuid);
776 } else if(!g_strcmp0(key, "Value")) {
777 gb_array = g_byte_array_new();
778 g_variant_get(value, "ay", &desc_value_iter);
779 while(g_variant_iter_loop(desc_value_iter, "y", &char_value)) {
780 BT_DBG("value of descriptor = %d",char_value);
781 g_byte_array_append(gb_array, &char_value, 1);
783 if (gb_array->len != 0) {
784 descriptor->val = g_malloc0(gb_array->len *
785 sizeof(unsigned char));
786 memcpy(descriptor->val, gb_array->data, gb_array->len);
788 descriptor->val_len = gb_array->len;
789 g_byte_array_free(gb_array, TRUE);
793 g_variant_iter_free(property_iter);
794 g_variant_unref(result);
795 g_object_unref(properties_proxy);
798 return BLUETOOTH_ERROR_NONE;
801 static void __bluetooth_internal_read_cb(GObject *source_object,
805 GError *error = NULL;
806 bt_user_info_t *user_info;
807 bt_gatt_char_value_t char_value = { 0, };
808 GDBusConnection *system_gconn = NULL;
810 GByteArray *gp_byte_array = NULL;
815 user_info = _bt_get_user_data(BT_COMMON);
817 system_gconn = _bt_gdbus_get_system_gconn();
818 value = g_dbus_connection_call_finish(system_gconn, res, &error);
821 BT_ERR("Error : %s \n", error->message);
822 g_clear_error(&error);
824 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
825 BLUETOOTH_ERROR_INTERNAL, NULL,
826 user_info->cb, user_info->user_data);
832 char_value.char_handle = user_data;
833 gp_byte_array = g_byte_array_new();
834 g_variant_get(value, "(ay)", &iter);
836 while (g_variant_iter_loop(iter, "y", &g_byte)) {
837 g_byte_array_append(gp_byte_array, &g_byte, 1);
840 if (gp_byte_array->len != 0) {
841 char_value.val_len = gp_byte_array->len;
842 char_value.char_value = gp_byte_array->data;
846 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
847 BLUETOOTH_ERROR_NONE, &char_value,
848 user_info->cb, user_info->user_data);
851 g_free(char_value.char_handle);
852 g_byte_array_free(gp_byte_array, TRUE);
853 g_variant_unref(value);
854 g_variant_iter_free(iter);
859 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
861 GDBusConnection *conn;
864 BT_CHECK_PARAMETER(characteristic, return);
865 BT_CHECK_ENABLED(return);
867 conn = _bt_gdbus_get_system_gconn();
868 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
870 handle = g_strdup(characteristic);
872 g_dbus_connection_call(conn,
878 G_VARIANT_TYPE("(ay)"),
879 G_DBUS_CALL_FLAGS_NONE,
882 (GAsyncReadyCallback)__bluetooth_internal_read_cb,
885 return BLUETOOTH_ERROR_NONE;
888 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
889 const char *char_handle, const guint8 *value, int length)
892 GVariantBuilder *builder;
893 GError *error = NULL;
894 GDBusConnection *conn;
898 BT_CHECK_PARAMETER(char_handle, return);
899 BT_CHECK_PARAMETER(value, return);
900 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
901 BT_CHECK_ENABLED(return);
903 conn = _bt_gdbus_get_system_gconn();
904 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
906 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
908 for (i = 0; i < length; i++) {
909 g_variant_builder_add(builder, "y", value[i]);
912 val = g_variant_new("(ay)", builder);
914 g_dbus_connection_call_sync(conn,
921 G_DBUS_CALL_FLAGS_NONE,
925 BT_ERR("Set value Failed: %s", error->message);
926 g_clear_error(&error);
927 g_variant_builder_unref(builder);
928 return BLUETOOTH_ERROR_INTERNAL;
931 g_variant_builder_unref(builder);
934 return BLUETOOTH_ERROR_NONE;
937 static void __bluetooth_internal_write_cb(GObject *source_object,
942 GError *error = NULL;
943 bt_user_info_t *user_info;
944 GDBusConnection *system_gconn = NULL;
946 int result = BLUETOOTH_ERROR_NONE;
948 user_info = _bt_get_user_data(BT_COMMON);
950 system_gconn = _bt_gdbus_get_system_gconn();
951 value = g_dbus_connection_call_finish(system_gconn, res, &error);
954 BT_ERR("Error : %s \n", error->message);
955 g_clear_error(&error);
956 result = BLUETOOTH_ERROR_INTERNAL;
959 BT_DBG("result = %d", result);
960 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
962 user_info->cb, user_info->user_data);
966 g_variant_unref(value);
971 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
972 const char *char_handle, const guint8 *value, int length)
975 GDBusConnection *conn;
976 GVariantBuilder *builder;
980 BT_CHECK_PARAMETER(char_handle, return);
981 BT_CHECK_PARAMETER(value, return);
982 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
983 BT_CHECK_ENABLED(return);
985 conn = _bt_gdbus_get_system_gconn();
986 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
988 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
990 for (i = 0; i < length; i++) {
991 g_variant_builder_add(builder, "y", value[i]);
992 BT_DBG("value [] = %d", value[i]);
995 val = g_variant_new("(ay)", builder);
997 g_dbus_connection_call(conn,
1000 GATT_CHAR_INTERFACE,
1004 G_DBUS_CALL_FLAGS_NONE,
1006 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1009 g_variant_builder_unref(builder);
1012 return BLUETOOTH_ERROR_NONE;
1015 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1016 bt_gatt_char_property_t *characteristic)
1019 GDBusProxy *properties_proxy = NULL;
1020 GError *error = NULL;
1021 GVariant *value = NULL;
1022 GVariant *result = NULL;
1023 GDBusConnection *g_conn;
1024 int i, ret = BLUETOOTH_ERROR_NONE;
1027 GVariantIter *desc_value_iter, *property_iter;
1029 char_descriptor_type_t desc_type = TYPE_NONE;
1031 g_conn = _bt_gdbus_get_system_gconn();
1032 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1034 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1035 G_DBUS_PROXY_FLAGS_NONE, NULL,
1038 BT_PROPERTIES_INTERFACE,
1041 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1043 result = g_dbus_proxy_call_sync(properties_proxy,
1045 g_variant_new("(s)", GATT_DESC_INTERFACE),
1046 G_DBUS_CALL_FLAGS_NONE,
1052 if (error != NULL) {
1053 BT_ERR("Fail to get properties (Error: %s)", error->message);
1054 g_clear_error(&error);
1056 BT_ERR("Fail to get properties");
1057 g_object_unref(properties_proxy);
1058 return BLUETOOTH_ERROR_INTERNAL;
1060 g_variant_get(result, "(a{sv})", &property_iter);
1061 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1062 if (!g_strcmp0(key,"UUID")) {
1063 uuid = g_variant_get_string(value, &len);
1064 if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1065 BT_DBG("GATT_USER_DESC_UUID");
1066 desc_type = USER_DESC;
1067 } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1068 BT_DBG("GATT_CHAR_FORMAT");
1069 desc_type = CHAR_FORMAT;
1070 } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1071 BT_DBG("GATT_CHAR_CLIENT_CONF");
1072 desc_type = CLIENT_CONF;
1073 } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1074 BT_DBG("GATT_CHAR_SERVER_CONF");
1075 desc_type = SERVER_CONF;
1077 BT_DBG("descriptor uuid = %s", uuid);
1079 } else if (!g_strcmp0(key, "Value")) {
1082 BT_DBG("Format descriptor");
1083 g_variant_get(value, "(yyqyq)",
1084 &(characteristic->format.format),
1085 &(characteristic->format.exponent),
1086 &(characteristic->format.unit),
1087 &(characteristic->format.name_space),
1088 &(characteristic->format.description));
1091 BT_DBG("User descriptor");
1092 g_variant_get(value, "ay", &desc_value_iter);
1093 len = g_variant_get_size(desc_value_iter);
1096 characteristic->description = (guint8 *)g_malloc0(len + 1);
1097 if (!characteristic->description) {
1098 ret = BLUETOOTH_ERROR_OUT_OF_MEMORY;
1102 for (i = 0; i < len; i++) {
1103 g_variant_iter_loop(desc_value_iter, "y",
1104 &characteristic->description[i]);
1105 BT_DBG("description = %s", characteristic->description);
1109 BT_DBG(" CLIENT_CONF");
1112 BT_DBG(" SERVER_CONF");
1119 g_variant_iter_free(property_iter);
1120 g_variant_unref(result);
1121 g_object_unref(properties_proxy);
1128 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1129 GAsyncResult *res, gpointer user_data)
1133 GVariant *char_value;
1134 GVariantIter *char_iter;
1137 GError *error = NULL;
1138 bt_user_info_t *user_info;
1139 bt_gatt_char_property_t characteristic = {0, };
1140 int ret = BLUETOOTH_ERROR_INTERNAL;
1142 user_info = _bt_get_user_data(BT_COMMON);
1144 value = g_dbus_proxy_call_finish(proxy, res, &error);
1146 if (value == NULL) {
1147 if (error != NULL) {
1148 BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1149 "message[%s]\n", error->code, error->message);
1150 g_clear_error(&error);
1152 BT_ERR("Get characteristic descriptor failed\n");
1155 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1156 BLUETOOTH_ERROR_INTERNAL, NULL,
1157 user_info->cb, user_info->user_data);
1160 g_object_unref(proxy);
1164 g_variant_get(value, "(v)", &char_value);
1165 g_variant_get(char_value, "ao", &char_iter);
1167 int len = g_variant_get_size(char_iter);
1169 for (i = 0; i < len; i++) {
1170 g_variant_iter_loop(char_iter, "o", &char_handle);
1171 BT_DBG("object path of descriptor = %s",char_handle);
1173 ret = __bluetooth_gatt_descriptor_iter(char_handle,
1175 BT_DBG("Descriptor read status [%d]",ret);
1180 characteristic.handle = user_data;
1182 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1183 ret, &characteristic, user_info->cb, user_info->user_data);
1185 bluetooth_gatt_free_char_property(&characteristic);
1187 g_variant_iter_free(char_iter);
1191 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1192 const char *characteristic_handle)
1194 GDBusProxy *properties_proxy = NULL;
1195 GDBusConnection *g_conn;
1197 GError *error = NULL;
1199 BT_CHECK_PARAMETER(characteristic_handle, return);
1200 BT_CHECK_ENABLED(return);
1202 g_conn = _bt_gdbus_get_system_gconn();
1203 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1205 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1206 G_DBUS_PROXY_FLAGS_NONE, NULL,
1208 characteristic_handle,
1209 BT_PROPERTIES_INTERFACE,
1212 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1214 handle = g_strdup(characteristic_handle);
1215 g_dbus_proxy_call(properties_proxy,
1217 g_variant_new("(ss)",
1218 GATT_CHAR_INTERFACE, "Descriptors"),
1219 G_DBUS_CALL_FLAGS_NONE,
1221 (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1224 return BLUETOOTH_ERROR_NONE;
1227 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1231 GError *error = NULL;
1232 bt_user_info_t *user_info;
1233 bt_gatt_char_property_t char_value = { 0, };
1234 GDBusConnection *system_gconn = NULL;
1236 GByteArray *gp_byte_array = NULL;
1241 user_info = _bt_get_user_data(BT_COMMON);
1242 system_gconn = _bt_gdbus_get_system_gconn();
1244 char_value.handle = user_data;
1245 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1248 BT_ERR("Error : %s \n", error->message);
1249 g_clear_error(&error);
1251 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1252 BLUETOOTH_ERROR_INTERNAL, NULL,
1253 user_info->cb, user_info->user_data);
1255 g_free(char_value.handle);
1259 gp_byte_array = g_byte_array_new();
1260 g_variant_get(value, "(ay)", &iter);
1262 while(g_variant_iter_loop(iter, "y", &g_byte)) {
1263 g_byte_array_append(gp_byte_array, &g_byte, 1);
1266 if (gp_byte_array->len != 0) {
1267 char_value.val_len = gp_byte_array->len;
1268 char_value.description= gp_byte_array->data;
1272 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1273 BLUETOOTH_ERROR_NONE, &char_value,
1274 user_info->cb, user_info->user_data);
1277 g_byte_array_free(gp_byte_array, TRUE);
1278 g_free(char_value.handle);
1279 g_variant_unref(value);
1280 g_variant_iter_free(iter);
1285 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
1287 GDBusConnection *conn;
1291 BT_CHECK_PARAMETER(char_descriptor, return);
1292 BT_CHECK_ENABLED(return);
1294 conn = _bt_gdbus_get_system_gconn();
1295 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1297 handle = g_strdup(char_descriptor);
1299 g_dbus_connection_call(conn,
1302 GATT_DESC_INTERFACE,
1305 G_VARIANT_TYPE("(ay)"),
1306 G_DBUS_CALL_FLAGS_NONE,
1309 (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1313 return BLUETOOTH_ERROR_NONE;
1316 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1320 GError *error = NULL;
1321 bt_user_info_t *user_info;
1322 GDBusConnection *system_gconn = NULL;
1324 int result = BLUETOOTH_ERROR_NONE;
1327 user_info = _bt_get_user_data(BT_COMMON);
1329 system_gconn = _bt_gdbus_get_system_gconn();
1330 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1333 BT_ERR("Error : %s \n", error->message);
1334 g_clear_error(&error);
1335 result = BLUETOOTH_ERROR_INTERNAL;
1338 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1340 user_info->cb, user_info->user_data);
1344 g_variant_unref(value);
1349 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
1350 const char *desc_handle, const guint8 *value, int length)
1353 GDBusConnection *conn;
1354 GVariantBuilder *builder;
1358 BT_CHECK_PARAMETER(desc_handle, return);
1359 BT_CHECK_PARAMETER(value, return);
1360 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1361 BT_CHECK_ENABLED(return);
1363 conn = _bt_gdbus_get_system_gconn();
1364 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1366 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1368 for (i = 0; i < length; i++) {
1369 g_variant_builder_add(builder, "y", value[i]);
1372 val = g_variant_new("(ay)", builder);
1374 g_dbus_connection_call(conn,
1377 GATT_DESC_INTERFACE,
1381 G_DBUS_CALL_FLAGS_NONE,
1383 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1386 g_variant_builder_unref(builder);
1389 return BLUETOOTH_ERROR_NONE;
1392 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
1395 GDBusConnection *conn;
1396 GError *error = NULL;
1397 int ret = BLUETOOTH_ERROR_NONE;
1399 /* Implementation in Bluez is not complete */
1401 BT_CHECK_PARAMETER(char_handle, return);
1403 BT_CHECK_ENABLED(return);
1405 BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1407 conn = _bt_gdbus_get_system_gconn();
1408 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1410 g_dbus_connection_call_sync(conn,
1413 GATT_CHAR_INTERFACE,
1417 G_DBUS_CALL_FLAGS_NONE,
1421 BT_ERR("Watch Failed: %s", error->message);
1422 g_clear_error(&error);
1423 ret = BLUETOOTH_ERROR_INTERNAL;
1430 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *service_handle)
1433 GDBusConnection *conn;
1434 GError *error = NULL;
1435 int ret = BLUETOOTH_ERROR_NONE;
1437 /* Implementation in Bluez is not complete */
1439 BT_CHECK_PARAMETER(char_handle, return);
1441 BT_CHECK_ENABLED(return);
1443 BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1445 conn = _bt_gdbus_get_system_gconn();
1446 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1448 g_dbus_connection_call_sync(conn,
1451 GATT_CHAR_INTERFACE,
1455 G_DBUS_CALL_FLAGS_NONE,
1459 BT_ERR("Watch Failed: %s", error->message);
1460 g_clear_error(&error);
1461 ret = BLUETOOTH_ERROR_INTERNAL;