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>
25 #include "bt-common.h"
26 #include "bt-internal-types.h"
27 #include "bt-request-sender.h"
29 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
30 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
31 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
33 #define GATT_USER_DESC_UUID "00002901-0000-1000-8000-00805f9b34fb"
34 #define GATT_CHAR_CLIENT_CONF "00002902-0000-1000-8000-00805f9b34fb"
35 #define GATT_CHAR_SERVER_CONF "00002903-0000-1000-8000-00805f9b34fb"
36 #define GATT_CHAR_FORMAT "00002904-0000-1000-8000-00805f9b34fb"
44 } char_descriptor_type_t;
46 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
50 BT_CHECK_PARAMETER(svc_pty, return);
52 g_free(svc_pty->uuid);
53 g_free(svc_pty->handle);
54 g_strfreev(svc_pty->include_handles.handle);
55 g_strfreev(svc_pty->char_handle.handle);
57 memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
60 return BLUETOOTH_ERROR_NONE;
63 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
67 BT_CHECK_PARAMETER(char_pty, return);
69 g_free(char_pty->uuid);
70 g_free(char_pty->name);
71 g_free(char_pty->description);
72 g_free(char_pty->val);
73 g_free(char_pty->handle);
74 g_strfreev(char_pty->char_desc_handle.handle);
76 memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
79 return BLUETOOTH_ERROR_NONE;
82 BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty)
86 BT_CHECK_PARAMETER(desc_pty, return);
88 g_free(desc_pty->uuid);
89 g_free(desc_pty->val);
90 g_free(desc_pty->handle);
92 memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t));
95 return BLUETOOTH_ERROR_NONE;
98 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
100 gchar *gp_path = NULL;
107 path = g_malloc0((gp->len + 1) * sizeof(char *));
109 /* Fix : NULL_RETURNS */
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 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
123 bt_gatt_service_property_t *service)
125 GDBusProxy *properties_proxy = NULL;
126 GError *error = NULL;
127 GVariant *result = NULL;
128 GDBusConnection *g_conn;
130 char *char_handle = NULL;
131 GPtrArray *gp_array = NULL ;
132 GVariantIter *property_iter, *char_iter;
136 BT_CHECK_PARAMETER(service_handle, return);
137 BT_CHECK_PARAMETER(service, return);
138 BT_CHECK_ENABLED_ANY(return);
140 g_conn = _bt_gdbus_get_system_gconn();
141 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
143 properties_proxy = g_dbus_proxy_new_sync(g_conn,
144 G_DBUS_PROXY_FLAGS_NONE, NULL,
147 BT_PROPERTIES_INTERFACE,
150 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
152 result = g_dbus_proxy_call_sync(properties_proxy,
154 g_variant_new("(s)", GATT_SERV_INTERFACE),
155 G_DBUS_CALL_FLAGS_NONE,
162 BT_ERR("Fail to get properties (Error: %s)", error->message);
163 g_clear_error(&error);
165 BT_ERR("Fail to get properties");
166 g_object_unref(properties_proxy);
167 return BLUETOOTH_ERROR_INTERNAL;
170 g_variant_get(result, "(a{sv})", &property_iter);
172 memset(service, 0, sizeof(bt_gatt_service_property_t));
174 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
175 if (!g_strcmp0(key, "UUID")) {
176 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_ANY(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 char *object_path = NULL;
298 char *interface_str = NULL;
299 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
300 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
301 int ret = BLUETOOTH_ERROR_INTERNAL;
303 BT_CHECK_PARAMETER(address, return);
304 BT_CHECK_PARAMETER(service_uuid, return);
305 BT_CHECK_PARAMETER(service, return);
306 BT_CHECK_ENABLED_ANY(return);
308 result = _bt_get_managed_objects();
312 _bt_convert_addr_type_to_string(device_address,
313 (unsigned char *)address->addr);
315 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
317 while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
319 if (object_path == NULL)
322 _bt_convert_device_path_to_address(object_path,
325 if (g_strcmp0(temp_address, device_address) != 0)
328 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
329 &interface_str, &svc_iter)) {
330 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
333 BT_DBG("Object Path: %s", object_path);
334 ret = bluetooth_gatt_get_service_property(object_path,
337 if (ret != BLUETOOTH_ERROR_NONE) {
338 BT_ERR("Get service property failed(0x%08x)", ret);
340 if (service->primary == TRUE &&
341 g_strstr_len(service->uuid, -1,
343 ret = BLUETOOTH_ERROR_NONE;
347 bluetooth_gatt_free_service_property(service);
352 g_variant_iter_free(iter);
353 g_variant_unref(result);
358 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
359 GAsyncResult *res, gpointer user_data)
362 GVariant *char_value;
363 GVariantIter *char_iter;
364 GPtrArray *gp_array = NULL;
365 bt_gatt_discovered_char_t svc_char = { 0, };
367 GError *error = NULL;
368 bt_user_info_t *user_info;
372 user_info = _bt_get_user_data(BT_COMMON);
373 svc_char.service_handle = user_data;
375 value = g_dbus_proxy_call_finish(proxy, res, &error);
379 BT_ERR("Get service characteristics failed\n errCode[%x],"
380 "message[%s]\n", error->code, error->message);
381 g_clear_error(&error);
383 BT_ERR("Get service characteristics failed\n");
386 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
387 BLUETOOTH_ERROR_INTERNAL, NULL,
388 user_info->cb, user_info->user_data);
390 g_free(svc_char.service_handle);
391 g_object_unref(proxy);
395 g_variant_get(value, "(v)", &char_value);
396 g_variant_get(char_value, "ao", &char_iter);
398 gp_array = g_ptr_array_new();
399 while (g_variant_iter_loop(char_iter, "&o", &char_handle));
400 g_ptr_array_add(gp_array, (gpointer)char_handle);
402 if (gp_array->len != 0) {
403 svc_char.handle_info.count = gp_array->len;
404 svc_char.handle_info.handle =
405 __get_string_array_from_gptr_array(gp_array);
407 g_ptr_array_free(gp_array, TRUE);
410 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
411 BLUETOOTH_ERROR_NONE, &svc_char,
412 user_info->cb, user_info->user_data);
415 g_strfreev(svc_char.handle_info.handle);
416 g_free(svc_char.service_handle);
417 g_variant_iter_free(char_iter);
418 g_object_unref(proxy);
421 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
422 const char *service_handle)
424 GDBusProxy *properties_proxy = NULL;
425 GDBusConnection *g_conn;
426 GError *error = NULL;
431 BT_CHECK_PARAMETER(service_handle, return);
432 BT_CHECK_ENABLED_ANY(return);
434 g_conn = _bt_gdbus_get_system_gconn();
435 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
437 properties_proxy = g_dbus_proxy_new_sync(g_conn,
438 G_DBUS_PROXY_FLAGS_NONE, NULL,
441 BT_PROPERTIES_INTERFACE,
444 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
446 handle = g_strdup(service_handle);
447 g_dbus_proxy_call(properties_proxy,
449 g_variant_new("(ss)",
450 GATT_SERV_INTERFACE, "Characteristics"),
451 G_DBUS_CALL_FLAGS_NONE,
454 (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
458 return BLUETOOTH_ERROR_NONE;
462 static int __get_permission_flag(char *permission)
466 retv_if(permission == NULL, ret);
468 BT_DBG("permission = %s", permission);
470 if (!g_strcmp0(permission, "broadcast")) {
471 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
472 } else if (!g_strcmp0(permission, "read")) {
473 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
474 } else if (!g_strcmp0(permission, "write-without-response")) {
475 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
476 } else if (!g_strcmp0(permission, "write")) {
477 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
478 } else if (!g_strcmp0(permission, "notify")) {
479 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
480 } else if (!g_strcmp0(permission, "indicate")) {
481 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
482 } else if (!g_strcmp0(permission, "authenticated-signed-writes")) {
483 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
484 } else if (!g_strcmp0(permission, "reliable-write")) {
485 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
486 } else if (!g_strcmp0(permission, "writable-auxiliaries")) {
487 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
493 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
494 const char *char_handle, bt_gatt_char_property_t *characteristic)
496 GDBusProxy *properties_proxy = NULL;
497 GError *error = NULL;
498 GVariant *value = NULL;
499 GVariant *result = NULL;
500 GByteArray *gb_array = NULL;
501 GPtrArray *gp_array = NULL ;
502 GDBusConnection *g_conn;
506 char *char_desc_handle = NULL;
508 GVariantIter *property_iter;
509 GVariantIter *char_value_iter;
510 GVariantIter *char_perm_iter;
511 GVariantIter *char_desc_iter;
514 BT_CHECK_PARAMETER(char_handle, return);
515 BT_CHECK_PARAMETER(characteristic, return);
517 BT_CHECK_ENABLED_ANY(return);
519 g_conn = _bt_gdbus_get_system_gconn();
520 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
522 properties_proxy = g_dbus_proxy_new_sync(g_conn,
523 G_DBUS_PROXY_FLAGS_NONE, NULL,
526 BT_PROPERTIES_INTERFACE,
529 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
531 result = g_dbus_proxy_call_sync(properties_proxy,
533 g_variant_new("(s)", GATT_CHAR_INTERFACE),
534 G_DBUS_CALL_FLAGS_NONE,
541 BT_ERR("Fail to get properties (Error: %s)", error->message);
542 g_clear_error(&error);
544 BT_ERR("Fail to get properties");
545 g_object_unref(properties_proxy);
546 return BLUETOOTH_ERROR_INTERNAL;
549 g_variant_get(result, "(a{sv})", &property_iter);
551 memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
552 characteristic->handle = g_strdup(char_handle);
554 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
556 if (!g_strcmp0(key, "UUID")) {
557 characteristic->uuid = g_variant_dup_string(value, &len);
558 BT_DBG("UUID of the char = %s", characteristic->uuid);
559 } else if (!g_strcmp0(key, "Value")) {
560 gb_array = g_byte_array_new();
561 g_variant_get(value, "ay", &char_value_iter);
562 while (g_variant_iter_loop(char_value_iter, "y", &char_value)) {
563 BT_DBG("value of char = %d", char_value);
564 g_byte_array_append(gb_array, &char_value, 1);
566 g_variant_iter_free(char_value_iter);
568 if (gb_array->len != 0) {
569 characteristic->val = g_malloc0(gb_array->len *
570 sizeof(unsigned char));
571 memcpy(characteristic->val, gb_array->data, gb_array->len);
573 characteristic->val_len = gb_array->len;
574 g_byte_array_free(gb_array, TRUE);
575 } else if (!g_strcmp0(key, "Flags")) {
576 g_variant_get(value, "as", &char_perm_iter);
577 characteristic->permission = 0x00;
578 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
579 BT_DBG("permission = %s", permission);
580 characteristic->permission |= __get_permission_flag(permission);
581 BT_DBG("permission check = %d", characteristic->permission);
583 g_variant_iter_free(char_perm_iter);
584 } else if (!g_strcmp0(key, "Descriptors")) {
585 g_variant_get(value, "ao", &char_desc_iter);
586 gp_array = g_ptr_array_new();
587 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
588 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
590 g_variant_iter_free(char_desc_iter);
591 if (gp_array->len != 0) {
592 characteristic->char_desc_handle.count = gp_array->len;
593 characteristic->char_desc_handle.handle =
594 __get_string_array_from_gptr_array(gp_array);
596 g_ptr_array_free(gp_array, TRUE);
600 g_variant_iter_free(property_iter);
601 g_variant_unref(result);
602 g_object_unref(properties_proxy);
605 return BLUETOOTH_ERROR_NONE;
608 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
609 GAsyncResult *res, gpointer user_data)
612 GVariantIter *char_iter;
615 GError *error = NULL;
616 bt_user_info_t *user_info;
617 int ret = BLUETOOTH_ERROR_INTERNAL;
618 bt_gatt_char_property_t characteristic;
620 user_info = _bt_get_user_data(BT_COMMON);
622 value = g_dbus_proxy_call_finish(proxy, res, &error);
626 BT_ERR("Get service characteristics failed\n errCode[%x],"
627 "message[%s]\n", error->code, error->message);
628 g_clear_error(&error);
630 BT_ERR("Get service characteristics failed\n");
633 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
634 BLUETOOTH_ERROR_INTERNAL, NULL,
635 user_info->cb, user_info->user_data);
637 g_object_unref(proxy);
642 g_variant_get(value, "(ao)", &char_iter);
644 len = g_variant_get_size((GVariant *)char_iter);
646 for (i = 0; i < len; i++) {
647 g_variant_iter_loop(char_iter, "o", &char_handle);
650 ret = bluetooth_gatt_get_characteristics_property(char_handle,
653 if (ret != BLUETOOTH_ERROR_NONE) {
654 BT_ERR("Get characteristic property failed(0x%08x)", ret);
656 if (g_strstr_len(characteristic.uuid, -1, user_data)) {
657 ret = BLUETOOTH_ERROR_NONE;
661 bluetooth_gatt_free_char_property(&characteristic);
665 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
666 &characteristic, user_info->cb, user_info->user_data);
669 bluetooth_gatt_free_char_property(&characteristic);
670 g_variant_iter_free(char_iter);
674 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
675 const char *char_uuid)
677 GDBusProxy *properties_proxy = NULL;
678 GDBusConnection *g_conn;
679 GError *error = NULL;
682 BT_CHECK_PARAMETER(service_handle, return);
683 BT_CHECK_PARAMETER(char_uuid, return);
684 BT_CHECK_ENABLED_ANY(return);
686 g_conn = _bt_gdbus_get_system_gconn();
687 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
689 properties_proxy = g_dbus_proxy_new_sync(g_conn,
690 G_DBUS_PROXY_FLAGS_NONE, NULL,
693 BT_PROPERTIES_INTERFACE,
696 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
698 uuid = g_strdup(char_uuid);
699 g_dbus_proxy_call(properties_proxy,
701 g_variant_new("(ss)",
702 GATT_SERV_INTERFACE, "Characteristics"),
703 G_DBUS_CALL_FLAGS_NONE,
706 (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
709 return BLUETOOTH_ERROR_NONE;
712 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
713 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
715 GDBusProxy *properties_proxy = NULL;
716 GError *error = NULL;
717 GDBusConnection *g_conn;
718 GVariant *result = NULL;
719 GVariantIter *property_iter;
723 GVariant *value = NULL;
724 GByteArray *gb_array = NULL;
725 GVariantIter *desc_value_iter;
728 BT_CHECK_PARAMETER(descriptor_handle, return);
729 BT_CHECK_PARAMETER(descriptor, return);
731 BT_CHECK_ENABLED_ANY(return);
733 g_conn = _bt_gdbus_get_system_gconn();
734 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
736 properties_proxy = g_dbus_proxy_new_sync(g_conn,
737 G_DBUS_PROXY_FLAGS_NONE, NULL,
740 BT_PROPERTIES_INTERFACE,
743 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
745 result = g_dbus_proxy_call_sync(properties_proxy,
747 g_variant_new("(s)", GATT_DESC_INTERFACE),
748 G_DBUS_CALL_FLAGS_NONE,
755 BT_ERR("Fail to get properties (Error: %s)", error->message);
756 g_clear_error(&error);
758 BT_ERR("Fail to get properties");
759 g_object_unref(properties_proxy);
760 return BLUETOOTH_ERROR_INTERNAL;
763 g_variant_get(result, "(a{sv})", &property_iter);
765 memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
766 descriptor->handle = g_strdup(descriptor_handle);
768 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
770 if (!g_strcmp0(key, "UUID")) {
771 descriptor->uuid = g_variant_dup_string(value, &len);
772 BT_DBG("UUID of the char_desc = %s", descriptor->uuid);
773 } else if (!g_strcmp0(key, "Value")) {
774 gb_array = g_byte_array_new();
775 g_variant_get(value, "ay", &desc_value_iter);
776 while (g_variant_iter_loop(desc_value_iter, "y", &char_value)) {
777 BT_DBG("value of descriptor = %d", char_value);
778 g_byte_array_append(gb_array, &char_value, 1);
780 g_variant_iter_free(desc_value_iter);
781 if (gb_array->len != 0) {
782 descriptor->val = g_malloc0(gb_array->len *
783 sizeof(unsigned char));
784 memcpy(descriptor->val, gb_array->data, gb_array->len);
786 descriptor->val_len = gb_array->len;
787 g_byte_array_free(gb_array, TRUE);
791 g_variant_iter_free(property_iter);
792 g_variant_unref(result);
793 g_object_unref(properties_proxy);
796 return BLUETOOTH_ERROR_NONE;
799 static void __bluetooth_internal_read_cb(GObject *source_object,
803 GError *error = NULL;
804 bt_user_info_t *user_info;
805 bt_gatt_char_value_t char_value = { 0, };
806 GDBusConnection *system_gconn = NULL;
808 GByteArray *gp_byte_array = NULL;
813 user_info = _bt_get_user_data(BT_COMMON);
815 system_gconn = _bt_gdbus_get_system_gconn();
816 value = g_dbus_connection_call_finish(system_gconn, res, &error);
819 BT_ERR("Error : %s \n", error->message);
820 g_clear_error(&error);
822 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
823 BLUETOOTH_ERROR_INTERNAL, NULL,
824 user_info->cb, user_info->user_data);
830 char_value.char_handle = user_data;
831 gp_byte_array = g_byte_array_new();
832 g_variant_get(value, "(ay)", &iter);
834 while (g_variant_iter_loop(iter, "y", &g_byte)) {
835 g_byte_array_append(gp_byte_array, &g_byte, 1);
838 if (gp_byte_array->len != 0) {
839 char_value.val_len = gp_byte_array->len;
840 char_value.char_value = gp_byte_array->data;
844 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
845 BLUETOOTH_ERROR_NONE, &char_value,
846 user_info->cb, user_info->user_data);
849 g_free(char_value.char_handle);
850 g_byte_array_free(gp_byte_array, TRUE);
851 g_variant_unref(value);
852 g_variant_iter_free(iter);
857 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
859 GDBusConnection *conn;
862 BT_CHECK_PARAMETER(characteristic, return);
863 BT_CHECK_ENABLED_ANY(return);
865 conn = _bt_gdbus_get_system_gconn();
866 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
868 handle = g_strdup(characteristic);
870 g_dbus_connection_call(conn,
876 G_VARIANT_TYPE("(ay)"),
877 G_DBUS_CALL_FLAGS_NONE,
880 (GAsyncReadyCallback)__bluetooth_internal_read_cb,
883 return BLUETOOTH_ERROR_NONE;
886 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
887 const char *char_handle, const guint8 *value, int length)
890 GVariantBuilder *builder;
891 GError *error = NULL;
892 GDBusConnection *conn;
896 BT_CHECK_PARAMETER(char_handle, return);
897 BT_CHECK_PARAMETER(value, return);
898 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
899 BT_CHECK_ENABLED_ANY(return);
901 conn = _bt_gdbus_get_system_gconn();
902 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
904 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
906 for (i = 0; i < length; i++) {
907 g_variant_builder_add(builder, "y", value[i]);
910 val = g_variant_new("(ay)", builder);
912 g_dbus_connection_call_sync(conn,
919 G_DBUS_CALL_FLAGS_NONE,
923 BT_ERR("Set value Failed: %s", error->message);
924 g_clear_error(&error);
925 g_variant_builder_unref(builder);
926 return BLUETOOTH_ERROR_INTERNAL;
929 g_variant_builder_unref(builder);
932 return BLUETOOTH_ERROR_NONE;
935 static void __bluetooth_internal_write_cb(GObject *source_object,
940 GError *error = NULL;
941 bt_user_info_t *user_info;
942 GDBusConnection *system_gconn = NULL;
944 int result = BLUETOOTH_ERROR_NONE;
946 user_info = _bt_get_user_data(BT_COMMON);
948 system_gconn = _bt_gdbus_get_system_gconn();
949 value = g_dbus_connection_call_finish(system_gconn, res, &error);
952 BT_ERR("Error : %s \n", error->message);
953 g_clear_error(&error);
954 result = BLUETOOTH_ERROR_INTERNAL;
957 BT_DBG("result = %d", result);
958 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
960 user_info->cb, user_info->user_data);
964 g_variant_unref(value);
969 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
970 const char *char_handle, const guint8 *value, int length, guint8 write_type)
973 GVariantBuilder *builder;
974 GDBusConnection *conn;
976 int ret = BLUETOOTH_ERROR_NONE;
978 BT_CHECK_PARAMETER(char_handle, return);
979 BT_CHECK_PARAMETER(value, return);
980 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
981 BT_CHECK_ENABLED_ANY(return);
983 conn = _bt_gdbus_get_system_gconn();
984 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
986 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
988 for (i = 0; i < length; i++) {
989 g_variant_builder_add(builder, "y", value[i]);
992 val = g_variant_new("ay", builder);
993 g_dbus_connection_call(conn,
998 g_variant_new("(y@ay)", write_type, val),
1000 G_DBUS_CALL_FLAGS_NONE,
1002 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1005 g_variant_builder_unref(builder);
1009 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1010 const char *char_handle, const guint8 *value, int length)
1013 GDBusConnection *conn;
1014 GVariantBuilder *builder;
1018 BT_CHECK_PARAMETER(char_handle, return);
1019 BT_CHECK_PARAMETER(value, return);
1020 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1021 BT_CHECK_ENABLED_ANY(return);
1023 conn = _bt_gdbus_get_system_gconn();
1024 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1026 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1028 for (i = 0; i < length; i++) {
1029 g_variant_builder_add(builder, "y", value[i]);
1030 BT_DBG("value [] = %d", value[i]);
1033 val = g_variant_new("(ay)", builder);
1035 g_dbus_connection_call(conn,
1038 GATT_CHAR_INTERFACE,
1042 G_DBUS_CALL_FLAGS_NONE,
1044 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1047 g_variant_builder_unref(builder);
1050 return BLUETOOTH_ERROR_NONE;
1053 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1054 bt_gatt_char_property_t *characteristic)
1057 GDBusProxy *properties_proxy = NULL;
1058 GError *error = NULL;
1059 GVariant *value = NULL;
1060 GVariant *result = NULL;
1061 GDBusConnection *g_conn;
1062 int i, ret = BLUETOOTH_ERROR_NONE;
1063 const char *uuid = NULL;
1065 GVariantIter *desc_value_iter, *property_iter;
1067 char_descriptor_type_t desc_type = TYPE_NONE;
1069 g_conn = _bt_gdbus_get_system_gconn();
1070 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1072 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1073 G_DBUS_PROXY_FLAGS_NONE, NULL,
1076 BT_PROPERTIES_INTERFACE,
1079 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1081 result = g_dbus_proxy_call_sync(properties_proxy,
1083 g_variant_new("(s)", GATT_DESC_INTERFACE),
1084 G_DBUS_CALL_FLAGS_NONE,
1090 if (error != NULL) {
1091 BT_ERR("Fail to get properties (Error: %s)", error->message);
1092 g_clear_error(&error);
1094 BT_ERR("Fail to get properties");
1095 g_object_unref(properties_proxy);
1096 return BLUETOOTH_ERROR_INTERNAL;
1098 g_variant_get(result, "(a{sv})", &property_iter);
1099 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1100 if (!g_strcmp0(key, "UUID")) {
1101 uuid = g_variant_get_string(value, &len);
1102 if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1103 BT_DBG("GATT_USER_DESC_UUID");
1104 desc_type = USER_DESC;
1105 } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1106 BT_DBG("GATT_CHAR_FORMAT");
1107 desc_type = CHAR_FORMAT;
1108 } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1109 BT_DBG("GATT_CHAR_CLIENT_CONF");
1110 desc_type = CLIENT_CONF;
1111 } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1112 BT_DBG("GATT_CHAR_SERVER_CONF");
1113 desc_type = SERVER_CONF;
1115 BT_DBG("descriptor uuid = %s", uuid);
1117 } else if (!g_strcmp0(key, "Value")) {
1118 switch (desc_type) {
1120 BT_DBG("Format descriptor");
1121 g_variant_get(value, "(yyqyq)",
1122 &(characteristic->format.format),
1123 &(characteristic->format.exponent),
1124 &(characteristic->format.unit),
1125 &(characteristic->format.name_space),
1126 &(characteristic->format.description));
1129 BT_DBG("User descriptor");
1130 g_variant_get(value, "ay", &desc_value_iter);
1131 len = g_variant_get_size((GVariant *)desc_value_iter);
1134 characteristic->description = (char *)g_malloc0(len + 1);
1135 if (!characteristic->description) {
1136 ret = BLUETOOTH_ERROR_OUT_OF_MEMORY;
1140 for (i = 0; i < len; i++) {
1141 g_variant_iter_loop(desc_value_iter, "y",
1142 &characteristic->description[i]);
1143 BT_DBG("description = %s", characteristic->description);
1145 g_variant_iter_free(desc_value_iter);
1148 BT_DBG(" CLIENT_CONF");
1151 BT_DBG(" SERVER_CONF");
1160 g_variant_iter_free(property_iter);
1161 g_variant_unref(result);
1162 g_object_unref(properties_proxy);
1169 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1170 GAsyncResult *res, gpointer user_data)
1174 GVariant *char_value;
1175 GVariantIter *char_iter;
1177 GError *error = NULL;
1178 bt_user_info_t *user_info;
1179 bt_gatt_char_property_t characteristic = {0, };
1180 int ret = BLUETOOTH_ERROR_INTERNAL;
1182 user_info = _bt_get_user_data(BT_COMMON);
1184 value = g_dbus_proxy_call_finish(proxy, res, &error);
1186 if (value == NULL) {
1187 if (error != NULL) {
1188 BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1189 "message[%s]\n", error->code, error->message);
1190 g_clear_error(&error);
1192 BT_ERR("Get characteristic descriptor failed\n");
1195 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1196 BLUETOOTH_ERROR_INTERNAL, NULL,
1197 user_info->cb, user_info->user_data);
1200 g_object_unref(proxy);
1204 g_variant_get(value, "(v)", &char_value);
1205 g_variant_get(char_value, "ao", &char_iter);
1207 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
1208 BT_DBG("object path of descriptor = %s", char_handle);
1210 ret = __bluetooth_gatt_descriptor_iter(char_handle,
1212 BT_DBG("Descriptor read status [%d]", ret);
1216 characteristic.handle = user_data;
1218 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1219 ret, &characteristic, user_info->cb, user_info->user_data);
1221 bluetooth_gatt_free_char_property(&characteristic);
1223 g_variant_iter_free(char_iter);
1227 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1228 const char *characteristic_handle)
1230 GDBusProxy *properties_proxy = NULL;
1231 GDBusConnection *g_conn;
1233 GError *error = NULL;
1235 BT_CHECK_PARAMETER(characteristic_handle, return);
1236 BT_CHECK_ENABLED_ANY(return);
1238 g_conn = _bt_gdbus_get_system_gconn();
1239 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1241 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1242 G_DBUS_PROXY_FLAGS_NONE, NULL,
1244 characteristic_handle,
1245 BT_PROPERTIES_INTERFACE,
1248 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1250 handle = g_strdup(characteristic_handle);
1251 g_dbus_proxy_call(properties_proxy,
1253 g_variant_new("(ss)",
1254 GATT_CHAR_INTERFACE, "Descriptors"),
1255 G_DBUS_CALL_FLAGS_NONE,
1257 (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1260 return BLUETOOTH_ERROR_NONE;
1263 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1267 GError *error = NULL;
1268 bt_user_info_t *user_info;
1269 bt_gatt_char_property_t char_value = { 0, };
1270 GDBusConnection *system_gconn = NULL;
1272 GByteArray *gp_byte_array = NULL;
1277 user_info = _bt_get_user_data(BT_COMMON);
1278 system_gconn = _bt_gdbus_get_system_gconn();
1280 char_value.handle = user_data;
1281 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1284 BT_ERR("Error : %s \n", error->message);
1285 g_clear_error(&error);
1287 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1288 BLUETOOTH_ERROR_INTERNAL, NULL,
1289 user_info->cb, user_info->user_data);
1291 g_free(char_value.handle);
1295 gp_byte_array = g_byte_array_new();
1296 g_variant_get(value, "(ay)", &iter);
1298 while (g_variant_iter_loop(iter, "y", &g_byte))
1299 g_byte_array_append(gp_byte_array, &g_byte, 1);
1301 if (gp_byte_array->len != 0) {
1302 char_value.val_len = (unsigned int)gp_byte_array->len;
1303 char_value.description = (char *)gp_byte_array->data;
1307 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1308 BLUETOOTH_ERROR_NONE, &char_value,
1309 user_info->cb, user_info->user_data);
1312 g_byte_array_free(gp_byte_array, TRUE);
1313 g_free(char_value.handle);
1314 g_variant_unref(value);
1315 g_variant_iter_free(iter);
1320 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
1322 GDBusConnection *conn;
1326 BT_CHECK_PARAMETER(char_descriptor, return);
1327 BT_CHECK_ENABLED_ANY(return);
1329 conn = _bt_gdbus_get_system_gconn();
1330 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1332 handle = g_strdup(char_descriptor);
1334 g_dbus_connection_call(conn,
1337 GATT_DESC_INTERFACE,
1340 G_VARIANT_TYPE("(ay)"),
1341 G_DBUS_CALL_FLAGS_NONE,
1344 (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1348 return BLUETOOTH_ERROR_NONE;
1351 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1355 GError *error = NULL;
1356 bt_user_info_t *user_info;
1357 GDBusConnection *system_gconn = NULL;
1359 int result = BLUETOOTH_ERROR_NONE;
1362 user_info = _bt_get_user_data(BT_COMMON);
1364 system_gconn = _bt_gdbus_get_system_gconn();
1365 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1368 BT_ERR("Error : %s \n", error->message);
1369 g_clear_error(&error);
1370 result = BLUETOOTH_ERROR_INTERNAL;
1373 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1375 user_info->cb, user_info->user_data);
1379 g_variant_unref(value);
1384 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
1385 const char *desc_handle, const guint8 *value, int length)
1388 GDBusConnection *conn;
1389 GVariantBuilder *builder;
1393 BT_CHECK_PARAMETER(desc_handle, return);
1394 BT_CHECK_PARAMETER(value, return);
1395 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1396 BT_CHECK_ENABLED_ANY(return);
1398 conn = _bt_gdbus_get_system_gconn();
1399 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1401 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1403 for (i = 0; i < length; i++) {
1404 g_variant_builder_add(builder, "y", value[i]);
1407 val = g_variant_new("(ay)", builder);
1409 g_dbus_connection_call(conn,
1412 GATT_DESC_INTERFACE,
1416 G_DBUS_CALL_FLAGS_NONE,
1418 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1421 g_variant_builder_unref(builder);
1424 return BLUETOOTH_ERROR_NONE;
1427 #ifndef GATT_NO_RELAY
1428 static int __bluetooth_gatt_watch_characteristics(void)
1430 int result = BLUETOOTH_ERROR_NONE;
1433 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1435 result = _bt_send_request(BT_BLUEZ_SERVICE,
1436 BT_GATT_WATCH_CHARACTERISTIC,
1437 in_param1, in_param2, in_param3, in_param4, &out_param);
1439 if (result != BLUETOOTH_ERROR_NONE)
1440 BT_ERR("Watch Characteristic request failed !");
1442 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1447 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
1450 GDBusConnection *conn;
1451 GError *error = NULL;
1452 int ret = BLUETOOTH_ERROR_NONE;
1454 BT_CHECK_PARAMETER(char_handle, return);
1456 BT_CHECK_ENABLED_ANY(return);
1458 BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1460 conn = _bt_gdbus_get_system_gconn();
1461 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1463 g_dbus_connection_call_sync(conn,
1466 GATT_CHAR_INTERFACE,
1470 G_DBUS_CALL_FLAGS_NONE,
1474 BT_ERR("Watch Failed: %s", error->message);
1475 if (g_strrstr(error->message, "Already notifying"))
1476 ret = BLUETOOTH_ERROR_NONE;
1477 else if (g_strrstr(error->message, "In Progress"))
1478 ret = BLUETOOTH_ERROR_IN_PROGRESS;
1479 else if (g_strrstr(error->message, "Operation is not supported"))
1480 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1481 /*failed because of either Insufficient Authorization or Write Not Permitted */
1482 else if (g_strrstr(error->message, "Write not permitted") ||
1483 g_strrstr(error->message, "Operation Not Authorized"))
1484 ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1485 /* failed because of either Insufficient Authentication,
1486 Insufficient Encryption Key Size, or Insufficient Encryption. */
1487 else if (g_strrstr(error->message, "Not paired"))
1488 ret = BLUETOOTH_ERROR_NOT_PAIRED;
1490 ret = BLUETOOTH_ERROR_INTERNAL;
1492 g_clear_error(&error);
1494 #ifndef GATT_NO_RELAY
1496 /* Register the client sender to bt-service */
1497 ret = __bluetooth_gatt_watch_characteristics();
1504 #ifndef GATT_NO_RELAY
1505 static void __bluetooth_gatt_unwatch_characteristics(void)
1507 int result = BLUETOOTH_ERROR_NONE;
1510 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1512 result = _bt_send_request(BT_BLUEZ_SERVICE,
1513 BT_GATT_UNWATCH_CHARACTERISTIC,
1514 in_param1, in_param2, in_param3, in_param4, &out_param);
1516 if (result != BLUETOOTH_ERROR_NONE)
1517 BT_ERR("Unwatch Characteristic request failed !");
1519 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1523 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1526 GDBusConnection *conn;
1527 GError *error = NULL;
1528 int ret = BLUETOOTH_ERROR_NONE;
1530 BT_CHECK_PARAMETER(char_handle, return);
1532 BT_CHECK_ENABLED_ANY(return);
1534 BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1536 conn = _bt_gdbus_get_system_gconn();
1537 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1539 g_dbus_connection_call_sync(conn,
1542 GATT_CHAR_INTERFACE,
1546 G_DBUS_CALL_FLAGS_NONE,
1550 BT_ERR("Watch Failed: %s", error->message);
1551 g_clear_error(&error);
1552 ret = BLUETOOTH_ERROR_INTERNAL;
1554 #ifndef GATT_NO_RELAY
1556 /* Unregister the client sender to bt-service */
1557 __bluetooth_gatt_unwatch_characteristics();