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 /* Fix : NULL_RETURNS */
116 for (i = 0; i < gp->len; i++) {
117 gp_path = g_ptr_array_index(gp, i);
118 path[i] = g_strdup(gp_path);
119 BT_DBG("path[%d] : [%s]", i, path[i]);
125 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
126 bt_gatt_service_property_t *service)
128 GDBusProxy *properties_proxy = NULL;
129 GError *error = NULL;
130 GVariant *result = NULL;
131 GDBusConnection *g_conn;
133 char *char_handle = NULL;
134 GPtrArray *gp_array = NULL ;
135 GVariantIter *property_iter, *char_iter;
139 BT_CHECK_PARAMETER(service_handle, return);
140 BT_CHECK_PARAMETER(service, return);
141 BT_CHECK_ENABLED(return);
143 g_conn = _bt_gdbus_get_system_gconn();
144 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
146 properties_proxy = g_dbus_proxy_new_sync(g_conn,
147 G_DBUS_PROXY_FLAGS_NONE, NULL,
150 BT_PROPERTIES_INTERFACE,
153 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
155 result = g_dbus_proxy_call_sync(properties_proxy,
157 g_variant_new("(s)", GATT_SERV_INTERFACE),
158 G_DBUS_CALL_FLAGS_NONE,
165 BT_ERR("Fail to get properties (Error: %s)", error->message);
166 g_clear_error(&error);
168 BT_ERR("Fail to get properties");
169 g_object_unref(properties_proxy);
170 return BLUETOOTH_ERROR_INTERNAL;
173 g_variant_get(result, "(a{sv})", &property_iter);
175 memset(service, 0, sizeof(bt_gatt_service_property_t));
177 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
178 if (!g_strcmp0(key,"UUID")) {
179 service->uuid = g_variant_dup_string(value,&len);
181 } else if(!g_strcmp0(key, "Primary")) {
182 service->primary = g_variant_get_boolean(value);
184 } else if (!g_strcmp0(key, "Includes")) {
185 g_variant_get(value, "ao", &char_iter);
186 gp_array = g_ptr_array_new();
187 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
188 g_ptr_array_add(gp_array, (gpointer)char_handle);
190 if (gp_array->len != 0) {
191 service->include_handles.count = gp_array->len;
192 service->include_handles.handle =
193 __get_string_array_from_gptr_array(gp_array);
195 g_ptr_array_free(gp_array, TRUE);
196 } else if (!g_strcmp0(key, "Characteristics")) {
197 g_variant_get(value, "ao", &char_iter);
198 gp_array = g_ptr_array_new();
199 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
200 g_ptr_array_add(gp_array, (gpointer)char_handle);
202 if (gp_array->len != 0) {
203 service->char_handle.count = gp_array->len;
204 service->char_handle.handle =
205 __get_string_array_from_gptr_array(gp_array);
207 g_ptr_array_free(gp_array, TRUE);
211 service->handle = g_strdup(service_handle);
213 g_variant_iter_free(property_iter);
214 g_variant_unref(result);
215 g_object_unref(properties_proxy);
217 return BLUETOOTH_ERROR_NONE;
220 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
221 const bluetooth_device_address_t *address,
222 bt_gatt_handle_info_t *prim_svc)
224 GVariant *result = NULL;
226 GVariantIter *svc_iter;
227 GVariantIter *interface_iter;
228 char *object_path = NULL;
229 char *interface_str = NULL;
230 const gchar *key = NULL;
231 GVariant *value = NULL;
232 GPtrArray *gp_array = NULL;
233 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
234 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
235 int ret = BLUETOOTH_ERROR_INTERNAL;
238 BT_CHECK_PARAMETER(address, return);
239 BT_CHECK_PARAMETER(prim_svc, return);
240 BT_CHECK_ENABLED(return);
242 result = _bt_get_managed_objects();
246 _bt_convert_addr_type_to_string(device_address,
247 (unsigned char *)address->addr);
249 gp_array = g_ptr_array_new();
250 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
252 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
254 if (object_path == NULL)
257 _bt_convert_device_path_to_address(object_path, temp_address);
259 if (g_strcmp0(temp_address, device_address) != 0)
262 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
263 &interface_str, &svc_iter)) {
264 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
267 BT_DBG("Object Path: %s", object_path);
268 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
269 if (g_strcmp0(key, "Primary") == 0) {
270 if (g_variant_get_boolean(value))
271 g_ptr_array_add(gp_array, (gpointer)object_path);
277 if (gp_array->len == 0) {
278 BT_ERR("gp_array is NULL");
279 ret = BLUETOOTH_ERROR_NOT_FOUND;
281 ret = BLUETOOTH_ERROR_NONE;
282 prim_svc->count = gp_array->len;
283 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
286 g_ptr_array_free(gp_array, TRUE);
287 g_variant_iter_free(iter);
288 g_variant_unref(result);
293 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
294 const char *service_uuid,
295 bt_gatt_service_property_t *service)
297 GVariant *result = NULL;
299 GVariantIter *svc_iter;
300 GVariantIter *interface_iter;
301 char *object_path = NULL;
302 char *interface_str = NULL;
303 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
304 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
305 int ret = BLUETOOTH_ERROR_INTERNAL;
307 BT_CHECK_PARAMETER(address, return);
308 BT_CHECK_PARAMETER(service_uuid, return);
309 BT_CHECK_PARAMETER(service, return);
310 BT_CHECK_ENABLED(return);
312 result = _bt_get_managed_objects();
316 _bt_convert_addr_type_to_string(device_address,
317 (unsigned char *)address->addr);
319 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
321 while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
323 if (object_path == NULL)
326 _bt_convert_device_path_to_address(object_path,
329 if (g_strcmp0(temp_address, device_address) != 0)
332 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
333 &interface_str, &svc_iter)) {
334 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
337 BT_DBG("Object Path: %s", object_path);
338 ret = bluetooth_gatt_get_service_property(object_path,
341 if (ret != BLUETOOTH_ERROR_NONE) {
342 BT_ERR("Get service property failed(0x%08x)", ret);
344 if (service->primary == TRUE &&
345 g_strstr_len(service->uuid, -1,
347 ret = BLUETOOTH_ERROR_NONE;
351 bluetooth_gatt_free_service_property(service);
356 g_variant_iter_free(iter);
357 g_variant_unref(result);
362 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
363 GAsyncResult *res, gpointer user_data)
366 GVariant *char_value;
367 GVariantIter *char_iter;
368 GPtrArray *gp_array = NULL;
369 bt_gatt_discovered_char_t svc_char = { 0, };
372 GError *error = NULL;
373 bt_user_info_t *user_info;
377 user_info = _bt_get_user_data(BT_COMMON);
378 svc_char.service_handle = user_data;
380 value = g_dbus_proxy_call_finish(proxy, res, &error);
384 BT_ERR("Get service characteristics failed\n errCode[%x],"
385 "message[%s]\n", error->code, error->message);
386 g_clear_error(&error);
388 BT_ERR("Get service characteristics failed\n");
391 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
392 BLUETOOTH_ERROR_INTERNAL, NULL,
393 user_info->cb, user_info->user_data);
395 g_free(svc_char.service_handle);
396 g_object_unref(proxy);
400 g_variant_get(value, "(v)", &char_value);
401 g_variant_get(char_value, "ao", &char_iter);
403 int len = g_variant_get_size((GVariant *)char_iter);
405 gp_array = g_ptr_array_new();
406 for (i = 0; i < len; i++) {
407 g_variant_iter_loop(char_iter, "&o", &char_handle);
408 g_ptr_array_add(gp_array, (gpointer)char_handle);
410 if (gp_array->len != 0) {
411 svc_char.handle_info.count = gp_array->len;
412 svc_char.handle_info.handle =
413 __get_string_array_from_gptr_array(gp_array);
415 g_ptr_array_free(gp_array, TRUE);
419 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
420 BLUETOOTH_ERROR_NONE, &svc_char,
421 user_info->cb, user_info->user_data);
424 g_strfreev(svc_char.handle_info.handle);
425 g_free(svc_char.service_handle);
426 g_variant_iter_free(char_iter);
427 g_object_unref(proxy);
430 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
431 const char *service_handle)
433 GDBusProxy *properties_proxy = NULL;
434 GDBusConnection *g_conn;
435 GError *error = NULL;
440 BT_CHECK_PARAMETER(service_handle, return);
441 BT_CHECK_ENABLED(return);
443 g_conn = _bt_gdbus_get_system_gconn();
444 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
446 properties_proxy = g_dbus_proxy_new_sync(g_conn,
447 G_DBUS_PROXY_FLAGS_NONE, NULL,
450 BT_PROPERTIES_INTERFACE,
453 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
455 handle = g_strdup(service_handle);
456 g_dbus_proxy_call(properties_proxy,
458 g_variant_new("(ss)",
459 GATT_SERV_INTERFACE, "Characteristics"),
460 G_DBUS_CALL_FLAGS_NONE,
463 (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
467 return BLUETOOTH_ERROR_NONE;
471 static int __get_permission_flag(char *permission)
475 retv_if(permission == NULL, ret);
477 BT_DBG("permission = %s",permission);
479 if (!g_strcmp0(permission,"broadcast")) {
480 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
481 } else if (!g_strcmp0(permission,"read")) {
482 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
483 } else if (!g_strcmp0(permission,"write-without-response")) {
484 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
485 } else if (!g_strcmp0(permission,"write")) {
486 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
487 } else if (!g_strcmp0(permission,"notify")) {
488 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
489 } else if (!g_strcmp0(permission,"indicate")) {
490 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
491 } else if (!g_strcmp0(permission,"authenticated-signed-writes")) {
492 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
493 } else if (!g_strcmp0(permission,"reliable-write")) {
494 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
495 } else if (!g_strcmp0(permission,"writable-auxiliaries")) {
496 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
502 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
503 const char *char_handle, bt_gatt_char_property_t *characteristic)
505 GDBusProxy *properties_proxy = NULL;
506 GError *error = NULL;
507 GVariant *value = NULL;
508 GVariant *result = NULL;
509 GByteArray *gb_array = NULL;
510 GPtrArray *gp_array = NULL ;
511 GDBusConnection *g_conn;
515 char *char_desc_handle = NULL;
517 GVariantIter *property_iter;
518 GVariantIter *char_value_iter;
519 GVariantIter *char_perm_iter;
520 GVariantIter *char_desc_iter;
523 BT_CHECK_PARAMETER(char_handle, return);
524 BT_CHECK_PARAMETER(characteristic, return);
526 BT_CHECK_ENABLED(return);
528 g_conn = _bt_gdbus_get_system_gconn();
529 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
531 properties_proxy = g_dbus_proxy_new_sync(g_conn,
532 G_DBUS_PROXY_FLAGS_NONE, NULL,
535 BT_PROPERTIES_INTERFACE,
538 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
540 result = g_dbus_proxy_call_sync(properties_proxy,
542 g_variant_new("(s)", GATT_CHAR_INTERFACE),
543 G_DBUS_CALL_FLAGS_NONE,
550 BT_ERR("Fail to get properties (Error: %s)", error->message);
551 g_clear_error(&error);
553 BT_ERR("Fail to get properties");
554 g_object_unref(properties_proxy);
555 return BLUETOOTH_ERROR_INTERNAL;
558 g_variant_get(result, "(a{sv})", &property_iter);
560 memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
561 characteristic->handle = g_strdup(char_handle);
563 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
565 if (!g_strcmp0(key,"UUID")) {
566 characteristic->uuid = g_variant_dup_string(value,&len);
567 BT_DBG("UUID of the char = %s",characteristic->uuid);
568 } else if(!g_strcmp0(key, "Value")) {
569 gb_array = g_byte_array_new();
570 g_variant_get(value, "ay", &char_value_iter);
571 while(g_variant_iter_loop(char_value_iter, "y", &char_value)) {
572 BT_DBG("value of char = %d",char_value);
573 g_byte_array_append(gb_array, &char_value, 1);
575 if (gb_array->len != 0) {
576 characteristic->val = g_malloc0(gb_array->len *
577 sizeof(unsigned char));
578 memcpy(characteristic->val, gb_array->data, gb_array->len);
580 characteristic->val_len = gb_array->len;
581 g_byte_array_free(gb_array, TRUE);
582 } else if(!g_strcmp0(key, "Flags")) {
583 g_variant_get(value, "as", &char_perm_iter);
584 characteristic->permission = 0x00;
585 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
586 BT_DBG("permission = %s",permission);
587 characteristic->permission |= __get_permission_flag(permission);
588 BT_DBG("permission check = %d",characteristic->permission);
590 g_variant_iter_free(char_perm_iter);
591 } else if (!g_strcmp0(key, "Descriptors")) {
592 g_variant_get(value, "ao", &char_desc_iter);
593 gp_array = g_ptr_array_new();
594 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
595 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
597 if (gp_array->len != 0) {
598 characteristic->char_desc_handle.count = gp_array->len;
599 characteristic->char_desc_handle.handle =
600 __get_string_array_from_gptr_array(gp_array);
602 g_ptr_array_free(gp_array, TRUE);
606 g_variant_iter_free(property_iter);
607 g_variant_unref(result);
608 g_object_unref(properties_proxy);
611 return BLUETOOTH_ERROR_NONE;
614 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
615 GAsyncResult *res, gpointer user_data)
618 GVariantIter *char_iter;
621 GError *error = NULL;
622 bt_user_info_t *user_info;
623 int ret = BLUETOOTH_ERROR_INTERNAL;
624 bt_gatt_char_property_t characteristic;
626 user_info = _bt_get_user_data(BT_COMMON);
628 value = g_dbus_proxy_call_finish(proxy, res, &error);
632 BT_ERR("Get service characteristics failed\n errCode[%x],"
633 "message[%s]\n", error->code, error->message);
634 g_clear_error(&error);
636 BT_ERR("Get service characteristics failed\n");
639 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
640 BLUETOOTH_ERROR_INTERNAL, NULL,
641 user_info->cb, user_info->user_data);
643 g_object_unref(proxy);
648 g_variant_get(value, "(ao)", &char_iter);
650 len = g_variant_get_size((GVariant *)char_iter);
652 for (i = 0; i < len; i++) {
653 g_variant_iter_loop(char_iter, "o", &char_handle);
656 ret = bluetooth_gatt_get_characteristics_property(char_handle,
659 if (ret != BLUETOOTH_ERROR_NONE) {
660 BT_ERR("Get characteristic property failed(0x%08x)", ret);
662 if (g_strstr_len(characteristic.uuid, -1, user_data)) {
663 ret = BLUETOOTH_ERROR_NONE;
667 bluetooth_gatt_free_char_property(&characteristic);
671 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
672 &characteristic, user_info->cb, user_info->user_data);
675 bluetooth_gatt_free_char_property(&characteristic);
676 g_variant_iter_free(char_iter);
680 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
681 const char *char_uuid)
683 GDBusProxy *properties_proxy = NULL;
684 GDBusConnection *g_conn;
685 GError *error = NULL;
688 BT_CHECK_PARAMETER(service_handle, return);
689 BT_CHECK_PARAMETER(char_uuid, return);
690 BT_CHECK_ENABLED(return);
692 g_conn = _bt_gdbus_get_system_gconn();
693 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
695 properties_proxy = g_dbus_proxy_new_sync(g_conn,
696 G_DBUS_PROXY_FLAGS_NONE, NULL,
699 BT_PROPERTIES_INTERFACE,
702 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
704 uuid = g_strdup(char_uuid);
705 g_dbus_proxy_call(properties_proxy,
707 g_variant_new("(ss)",
708 GATT_SERV_INTERFACE, "Characteristics"),
709 G_DBUS_CALL_FLAGS_NONE,
712 (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
715 return BLUETOOTH_ERROR_NONE;
718 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
719 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
721 GDBusProxy *properties_proxy = NULL;
722 GError *error = NULL;
723 GDBusConnection *g_conn;
724 GVariant *result = NULL;
725 GVariantIter *property_iter;
729 GVariant *value = NULL;
730 GByteArray *gb_array = NULL;
731 GVariantIter *desc_value_iter;
734 BT_CHECK_PARAMETER(descriptor_handle, return);
735 BT_CHECK_PARAMETER(descriptor, return);
737 BT_CHECK_ENABLED(return);
739 g_conn = _bt_gdbus_get_system_gconn();
740 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
742 properties_proxy = g_dbus_proxy_new_sync(g_conn,
743 G_DBUS_PROXY_FLAGS_NONE, NULL,
746 BT_PROPERTIES_INTERFACE,
749 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
751 result = g_dbus_proxy_call_sync(properties_proxy,
753 g_variant_new("(s)", GATT_DESC_INTERFACE),
754 G_DBUS_CALL_FLAGS_NONE,
761 BT_ERR("Fail to get properties (Error: %s)", error->message);
762 g_clear_error(&error);
764 BT_ERR("Fail to get properties");
765 g_object_unref(properties_proxy);
766 return BLUETOOTH_ERROR_INTERNAL;
769 g_variant_get(result, "(a{sv})", &property_iter);
771 memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
772 descriptor->handle = g_strdup(descriptor_handle);
774 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
776 if (!g_strcmp0(key,"UUID")) {
777 descriptor->uuid = g_variant_dup_string(value,&len);
778 BT_DBG("UUID of the char_desc = %s",descriptor->uuid);
779 } else if(!g_strcmp0(key, "Value")) {
780 gb_array = g_byte_array_new();
781 g_variant_get(value, "ay", &desc_value_iter);
782 while(g_variant_iter_loop(desc_value_iter, "y", &char_value)) {
783 BT_DBG("value of descriptor = %d",char_value);
784 g_byte_array_append(gb_array, &char_value, 1);
786 if (gb_array->len != 0) {
787 descriptor->val = g_malloc0(gb_array->len *
788 sizeof(unsigned char));
789 memcpy(descriptor->val, gb_array->data, gb_array->len);
791 descriptor->val_len = gb_array->len;
792 g_byte_array_free(gb_array, TRUE);
796 g_variant_iter_free(property_iter);
797 g_variant_unref(result);
798 g_object_unref(properties_proxy);
801 return BLUETOOTH_ERROR_NONE;
804 static void __bluetooth_internal_read_cb(GObject *source_object,
808 GError *error = NULL;
809 bt_user_info_t *user_info;
810 bt_gatt_char_value_t char_value = { 0, };
811 GDBusConnection *system_gconn = NULL;
813 GByteArray *gp_byte_array = NULL;
818 user_info = _bt_get_user_data(BT_COMMON);
820 system_gconn = _bt_gdbus_get_system_gconn();
821 value = g_dbus_connection_call_finish(system_gconn, res, &error);
824 BT_ERR("Error : %s \n", error->message);
825 g_clear_error(&error);
827 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
828 BLUETOOTH_ERROR_INTERNAL, NULL,
829 user_info->cb, user_info->user_data);
835 char_value.char_handle = user_data;
836 gp_byte_array = g_byte_array_new();
837 g_variant_get(value, "(ay)", &iter);
839 while (g_variant_iter_loop(iter, "y", &g_byte)) {
840 g_byte_array_append(gp_byte_array, &g_byte, 1);
843 if (gp_byte_array->len != 0) {
844 char_value.val_len = gp_byte_array->len;
845 char_value.char_value = gp_byte_array->data;
849 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
850 BLUETOOTH_ERROR_NONE, &char_value,
851 user_info->cb, user_info->user_data);
854 g_free(char_value.char_handle);
855 g_byte_array_free(gp_byte_array, TRUE);
856 g_variant_unref(value);
857 g_variant_iter_free(iter);
862 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
864 GDBusConnection *conn;
867 BT_CHECK_PARAMETER(characteristic, return);
868 BT_CHECK_ENABLED(return);
870 conn = _bt_gdbus_get_system_gconn();
871 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
873 handle = g_strdup(characteristic);
875 g_dbus_connection_call(conn,
881 G_VARIANT_TYPE("(ay)"),
882 G_DBUS_CALL_FLAGS_NONE,
885 (GAsyncReadyCallback)__bluetooth_internal_read_cb,
888 return BLUETOOTH_ERROR_NONE;
891 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
892 const char *char_handle, const guint8 *value, int length)
895 GVariantBuilder *builder;
896 GError *error = NULL;
897 GDBusConnection *conn;
901 BT_CHECK_PARAMETER(char_handle, return);
902 BT_CHECK_PARAMETER(value, return);
903 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
904 BT_CHECK_ENABLED(return);
906 conn = _bt_gdbus_get_system_gconn();
907 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
909 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
911 for (i = 0; i < length; i++) {
912 g_variant_builder_add(builder, "y", value[i]);
915 val = g_variant_new("(ay)", builder);
917 g_dbus_connection_call_sync(conn,
924 G_DBUS_CALL_FLAGS_NONE,
928 BT_ERR("Set value Failed: %s", error->message);
929 g_clear_error(&error);
930 g_variant_builder_unref(builder);
931 return BLUETOOTH_ERROR_INTERNAL;
934 g_variant_builder_unref(builder);
937 return BLUETOOTH_ERROR_NONE;
940 static void __bluetooth_internal_write_cb(GObject *source_object,
945 GError *error = NULL;
946 bt_user_info_t *user_info;
947 GDBusConnection *system_gconn = NULL;
949 int result = BLUETOOTH_ERROR_NONE;
951 user_info = _bt_get_user_data(BT_COMMON);
953 system_gconn = _bt_gdbus_get_system_gconn();
954 value = g_dbus_connection_call_finish(system_gconn, res, &error);
957 BT_ERR("Error : %s \n", error->message);
958 g_clear_error(&error);
959 result = BLUETOOTH_ERROR_INTERNAL;
962 BT_DBG("result = %d", result);
963 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
965 user_info->cb, user_info->user_data);
969 g_variant_unref(value);
974 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
975 const char *char_handle, const guint8 *value, int length, guint8 write_type)
978 GVariantBuilder *builder;
979 GDBusConnection *conn;
981 int ret = BLUETOOTH_ERROR_NONE;
983 BT_CHECK_PARAMETER(char_handle, return);
984 BT_CHECK_PARAMETER(value, return);
985 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
986 BT_CHECK_ENABLED(return);
988 conn = _bt_gdbus_get_system_gconn();
989 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
991 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
993 for (i = 0; i < length; i++) {
994 g_variant_builder_add(builder, "y", value[i]);
997 val = g_variant_new("ay", builder);
1000 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
1001 g_dbus_connection_call(conn,
1004 GATT_CHAR_INTERFACE,
1006 g_variant_new("(y@ay)", write_type, val),
1008 G_DBUS_CALL_FLAGS_NONE,
1010 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1012 } else if (write_type ==
1013 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
1014 g_dbus_connection_call(conn,
1017 GATT_CHAR_INTERFACE,
1019 g_variant_new("(y@ay)", write_type, val),
1021 G_DBUS_CALL_FLAGS_NONE,
1023 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1026 ret = BLUETOOTH_ERROR_INVALID_PARAM;
1029 g_variant_builder_unref(builder);
1033 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1034 const char *char_handle, const guint8 *value, int length)
1037 GDBusConnection *conn;
1038 GVariantBuilder *builder;
1042 BT_CHECK_PARAMETER(char_handle, return);
1043 BT_CHECK_PARAMETER(value, return);
1044 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1045 BT_CHECK_ENABLED(return);
1047 conn = _bt_gdbus_get_system_gconn();
1048 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1050 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1052 for (i = 0; i < length; i++) {
1053 g_variant_builder_add(builder, "y", value[i]);
1054 BT_DBG("value [] = %d", value[i]);
1057 val = g_variant_new("(ay)", builder);
1059 g_dbus_connection_call(conn,
1062 GATT_CHAR_INTERFACE,
1066 G_DBUS_CALL_FLAGS_NONE,
1068 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1071 g_variant_builder_unref(builder);
1074 return BLUETOOTH_ERROR_NONE;
1077 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1078 bt_gatt_char_property_t *characteristic)
1081 GDBusProxy *properties_proxy = NULL;
1082 GError *error = NULL;
1083 GVariant *value = NULL;
1084 GVariant *result = NULL;
1085 GDBusConnection *g_conn;
1086 int i, ret = BLUETOOTH_ERROR_NONE;
1087 const char *uuid = NULL;
1089 GVariantIter *desc_value_iter, *property_iter;
1091 char_descriptor_type_t desc_type = TYPE_NONE;
1093 g_conn = _bt_gdbus_get_system_gconn();
1094 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1096 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1097 G_DBUS_PROXY_FLAGS_NONE, NULL,
1100 BT_PROPERTIES_INTERFACE,
1103 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1105 result = g_dbus_proxy_call_sync(properties_proxy,
1107 g_variant_new("(s)", GATT_DESC_INTERFACE),
1108 G_DBUS_CALL_FLAGS_NONE,
1114 if (error != NULL) {
1115 BT_ERR("Fail to get properties (Error: %s)", error->message);
1116 g_clear_error(&error);
1118 BT_ERR("Fail to get properties");
1119 g_object_unref(properties_proxy);
1120 return BLUETOOTH_ERROR_INTERNAL;
1122 g_variant_get(result, "(a{sv})", &property_iter);
1123 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1124 if (!g_strcmp0(key,"UUID")) {
1125 uuid = g_variant_get_string(value, &len);
1126 if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1127 BT_DBG("GATT_USER_DESC_UUID");
1128 desc_type = USER_DESC;
1129 } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1130 BT_DBG("GATT_CHAR_FORMAT");
1131 desc_type = CHAR_FORMAT;
1132 } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1133 BT_DBG("GATT_CHAR_CLIENT_CONF");
1134 desc_type = CLIENT_CONF;
1135 } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1136 BT_DBG("GATT_CHAR_SERVER_CONF");
1137 desc_type = SERVER_CONF;
1139 BT_DBG("descriptor uuid = %s", uuid);
1141 } else if (!g_strcmp0(key, "Value")) {
1144 BT_DBG("Format descriptor");
1145 g_variant_get(value, "(yyqyq)",
1146 &(characteristic->format.format),
1147 &(characteristic->format.exponent),
1148 &(characteristic->format.unit),
1149 &(characteristic->format.name_space),
1150 &(characteristic->format.description));
1153 BT_DBG("User descriptor");
1154 g_variant_get(value, "ay", &desc_value_iter);
1155 len = g_variant_get_size((GVariant *)desc_value_iter);
1158 characteristic->description = (char *)g_malloc0(len + 1);
1159 if (!characteristic->description) {
1160 ret = BLUETOOTH_ERROR_OUT_OF_MEMORY;
1164 for (i = 0; i < len; i++) {
1165 g_variant_iter_loop(desc_value_iter, "y",
1166 &characteristic->description[i]);
1167 BT_DBG("description = %s", characteristic->description);
1171 BT_DBG(" CLIENT_CONF");
1174 BT_DBG(" SERVER_CONF");
1182 g_variant_iter_free(property_iter);
1183 g_variant_unref(result);
1184 g_object_unref(properties_proxy);
1191 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1192 GAsyncResult *res, gpointer user_data)
1196 GVariant *char_value;
1197 GVariantIter *char_iter;
1200 GError *error = NULL;
1201 bt_user_info_t *user_info;
1202 bt_gatt_char_property_t characteristic = {0, };
1203 int ret = BLUETOOTH_ERROR_INTERNAL;
1205 user_info = _bt_get_user_data(BT_COMMON);
1207 value = g_dbus_proxy_call_finish(proxy, res, &error);
1209 if (value == NULL) {
1210 if (error != NULL) {
1211 BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1212 "message[%s]\n", error->code, error->message);
1213 g_clear_error(&error);
1215 BT_ERR("Get characteristic descriptor failed\n");
1218 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1219 BLUETOOTH_ERROR_INTERNAL, NULL,
1220 user_info->cb, user_info->user_data);
1223 g_object_unref(proxy);
1227 g_variant_get(value, "(v)", &char_value);
1228 g_variant_get(char_value, "ao", &char_iter);
1230 int len = g_variant_get_size((GVariant *)char_iter);
1232 for (i = 0; i < len; i++) {
1233 g_variant_iter_loop(char_iter, "o", &char_handle);
1234 BT_DBG("object path of descriptor = %s",char_handle);
1236 ret = __bluetooth_gatt_descriptor_iter(char_handle,
1238 BT_DBG("Descriptor read status [%d]",ret);
1243 characteristic.handle = user_data;
1245 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1246 ret, &characteristic, user_info->cb, user_info->user_data);
1248 bluetooth_gatt_free_char_property(&characteristic);
1250 g_variant_iter_free(char_iter);
1254 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1255 const char *characteristic_handle)
1257 GDBusProxy *properties_proxy = NULL;
1258 GDBusConnection *g_conn;
1260 GError *error = NULL;
1262 BT_CHECK_PARAMETER(characteristic_handle, return);
1263 BT_CHECK_ENABLED(return);
1265 g_conn = _bt_gdbus_get_system_gconn();
1266 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1268 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1269 G_DBUS_PROXY_FLAGS_NONE, NULL,
1271 characteristic_handle,
1272 BT_PROPERTIES_INTERFACE,
1275 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1277 handle = g_strdup(characteristic_handle);
1278 g_dbus_proxy_call(properties_proxy,
1280 g_variant_new("(ss)",
1281 GATT_CHAR_INTERFACE, "Descriptors"),
1282 G_DBUS_CALL_FLAGS_NONE,
1284 (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1287 return BLUETOOTH_ERROR_NONE;
1290 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1294 GError *error = NULL;
1295 bt_user_info_t *user_info;
1296 bt_gatt_char_property_t char_value = { 0, };
1297 GDBusConnection *system_gconn = NULL;
1299 GByteArray *gp_byte_array = NULL;
1304 user_info = _bt_get_user_data(BT_COMMON);
1305 system_gconn = _bt_gdbus_get_system_gconn();
1307 char_value.handle = user_data;
1308 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1311 BT_ERR("Error : %s \n", error->message);
1312 g_clear_error(&error);
1314 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1315 BLUETOOTH_ERROR_INTERNAL, NULL,
1316 user_info->cb, user_info->user_data);
1318 g_free(char_value.handle);
1322 gp_byte_array = g_byte_array_new();
1323 g_variant_get(value, "(ay)", &iter);
1325 while(g_variant_iter_loop(iter, "y", &g_byte)) {
1326 g_byte_array_append(gp_byte_array, &g_byte, 1);
1329 if (gp_byte_array->len != 0) {
1330 char_value.val_len = (unsigned int )gp_byte_array->len;
1331 char_value.description= (char *)gp_byte_array->data;
1335 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1336 BLUETOOTH_ERROR_NONE, &char_value,
1337 user_info->cb, user_info->user_data);
1340 g_byte_array_free(gp_byte_array, TRUE);
1341 g_free(char_value.handle);
1342 g_variant_unref(value);
1343 g_variant_iter_free(iter);
1348 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
1350 GDBusConnection *conn;
1354 BT_CHECK_PARAMETER(char_descriptor, return);
1355 BT_CHECK_ENABLED(return);
1357 conn = _bt_gdbus_get_system_gconn();
1358 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1360 handle = g_strdup(char_descriptor);
1362 g_dbus_connection_call(conn,
1365 GATT_DESC_INTERFACE,
1368 G_VARIANT_TYPE("(ay)"),
1369 G_DBUS_CALL_FLAGS_NONE,
1372 (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1376 return BLUETOOTH_ERROR_NONE;
1379 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1383 GError *error = NULL;
1384 bt_user_info_t *user_info;
1385 GDBusConnection *system_gconn = NULL;
1387 int result = BLUETOOTH_ERROR_NONE;
1390 user_info = _bt_get_user_data(BT_COMMON);
1392 system_gconn = _bt_gdbus_get_system_gconn();
1393 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1396 BT_ERR("Error : %s \n", error->message);
1397 g_clear_error(&error);
1398 result = BLUETOOTH_ERROR_INTERNAL;
1401 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1403 user_info->cb, user_info->user_data);
1407 g_variant_unref(value);
1412 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
1413 const char *desc_handle, const guint8 *value, int length)
1416 GDBusConnection *conn;
1417 GVariantBuilder *builder;
1421 BT_CHECK_PARAMETER(desc_handle, return);
1422 BT_CHECK_PARAMETER(value, return);
1423 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1424 BT_CHECK_ENABLED(return);
1426 conn = _bt_gdbus_get_system_gconn();
1427 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1429 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1431 for (i = 0; i < length; i++) {
1432 g_variant_builder_add(builder, "y", value[i]);
1435 val = g_variant_new("(ay)", builder);
1437 g_dbus_connection_call(conn,
1440 GATT_DESC_INTERFACE,
1444 G_DBUS_CALL_FLAGS_NONE,
1446 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1449 g_variant_builder_unref(builder);
1452 return BLUETOOTH_ERROR_NONE;
1455 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
1458 GDBusConnection *conn;
1459 GError *error = NULL;
1460 int ret = BLUETOOTH_ERROR_NONE;
1462 BT_CHECK_PARAMETER(char_handle, return);
1464 BT_CHECK_ENABLED(return);
1466 BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1468 conn = _bt_gdbus_get_system_gconn();
1469 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1471 g_dbus_connection_call_sync(conn,
1474 GATT_CHAR_INTERFACE,
1478 G_DBUS_CALL_FLAGS_NONE,
1482 BT_ERR("Watch Failed: %s", error->message);
1483 if (g_strrstr(error->message, "Already notifying"))
1484 ret = BLUETOOTH_ERROR_NONE;
1485 else if (g_strrstr(error->message, "In Progress"))
1486 ret = BLUETOOTH_ERROR_IN_PROGRESS;
1487 else if (g_strrstr(error->message, "Operation is not supported"))
1488 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1489 /*failed because of either Insufficient Authorization or Write Not Permitted */
1490 else if (g_strrstr(error->message, "Write not permitted") ||
1491 g_strrstr(error->message, "Operation Not Authorized"))
1492 ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1493 /* failed because of either Insufficient Authentication,
1494 Insufficient Encryption Key Size, or Insufficient Encryption. */
1495 else if (g_strrstr(error->message, "Not paired"))
1496 ret = BLUETOOTH_ERROR_NOT_PAIRED;
1498 ret = BLUETOOTH_ERROR_INTERNAL;
1500 g_clear_error(&error);
1506 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1509 GDBusConnection *conn;
1510 GError *error = NULL;
1511 int ret = BLUETOOTH_ERROR_NONE;
1513 BT_CHECK_PARAMETER(char_handle, return);
1515 BT_CHECK_ENABLED(return);
1517 BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1519 conn = _bt_gdbus_get_system_gconn();
1520 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1522 g_dbus_connection_call_sync(conn,
1525 GATT_CHAR_INTERFACE,
1529 G_DBUS_CALL_FLAGS_NONE,
1533 BT_ERR("Watch Failed: %s", error->message);
1534 g_clear_error(&error);
1535 ret = BLUETOOTH_ERROR_INTERNAL;