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);
178 } else if(!g_strcmp0(key, "Primary")) {
179 service->primary = g_variant_get_boolean(value);
181 } else if (!g_strcmp0(key, "Includes")) {
182 g_variant_get(value, "ao", &char_iter);
183 gp_array = g_ptr_array_new();
184 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
185 g_ptr_array_add(gp_array, (gpointer)char_handle);
187 if (gp_array->len != 0) {
188 service->include_handles.count = gp_array->len;
189 service->include_handles.handle =
190 __get_string_array_from_gptr_array(gp_array);
192 g_ptr_array_free(gp_array, TRUE);
193 } else if (!g_strcmp0(key, "Characteristics")) {
194 g_variant_get(value, "ao", &char_iter);
195 gp_array = g_ptr_array_new();
196 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
197 g_ptr_array_add(gp_array, (gpointer)char_handle);
199 if (gp_array->len != 0) {
200 service->char_handle.count = gp_array->len;
201 service->char_handle.handle =
202 __get_string_array_from_gptr_array(gp_array);
204 g_ptr_array_free(gp_array, TRUE);
208 service->handle = g_strdup(service_handle);
210 g_variant_iter_free(property_iter);
211 g_variant_unref(result);
212 g_object_unref(properties_proxy);
214 return BLUETOOTH_ERROR_NONE;
217 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
218 const bluetooth_device_address_t *address,
219 bt_gatt_handle_info_t *prim_svc)
221 GVariant *result = NULL;
223 GVariantIter *svc_iter;
224 GVariantIter *interface_iter;
225 char *object_path = NULL;
226 char *interface_str = NULL;
227 const gchar *key = NULL;
228 GVariant *value = NULL;
229 GPtrArray *gp_array = NULL;
230 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
231 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
232 int ret = BLUETOOTH_ERROR_INTERNAL;
235 BT_CHECK_PARAMETER(address, return);
236 BT_CHECK_PARAMETER(prim_svc, return);
237 BT_CHECK_ENABLED_ANY(return);
239 result = _bt_get_managed_objects();
243 _bt_convert_addr_type_to_string(device_address,
244 (unsigned char *)address->addr);
246 gp_array = g_ptr_array_new();
247 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
249 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
251 if (object_path == NULL)
254 _bt_convert_device_path_to_address(object_path, temp_address);
256 if (g_strcmp0(temp_address, device_address) != 0)
259 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
260 &interface_str, &svc_iter)) {
261 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
264 BT_DBG("Object Path: %s", object_path);
265 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
266 if (g_strcmp0(key, "Primary") == 0) {
267 if (g_variant_get_boolean(value))
268 g_ptr_array_add(gp_array, (gpointer)object_path);
274 if (gp_array->len == 0) {
275 BT_ERR("gp_array is NULL");
276 ret = BLUETOOTH_ERROR_NOT_FOUND;
278 ret = BLUETOOTH_ERROR_NONE;
279 prim_svc->count = gp_array->len;
280 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
283 g_ptr_array_free(gp_array, TRUE);
284 g_variant_iter_free(iter);
285 g_variant_unref(result);
290 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
291 const char *service_uuid,
292 bt_gatt_service_property_t *service)
294 GVariant *result = NULL;
296 GVariantIter *svc_iter;
297 GVariantIter *interface_iter;
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_ANY(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, };
368 GError *error = NULL;
369 bt_user_info_t *user_info;
373 user_info = _bt_get_user_data(BT_COMMON);
374 svc_char.service_handle = user_data;
376 value = g_dbus_proxy_call_finish(proxy, res, &error);
380 BT_ERR("Get service characteristics failed\n errCode[%x],"
381 "message[%s]\n", error->code, error->message);
382 g_clear_error(&error);
384 BT_ERR("Get service characteristics failed\n");
387 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
388 BLUETOOTH_ERROR_INTERNAL, NULL,
389 user_info->cb, user_info->user_data);
391 g_free(svc_char.service_handle);
392 g_object_unref(proxy);
396 g_variant_get(value, "(v)", &char_value);
397 g_variant_get(char_value, "ao", &char_iter);
399 gp_array = g_ptr_array_new();
400 while(g_variant_iter_loop(char_iter, "&o", &char_handle));
401 g_ptr_array_add(gp_array, (gpointer)char_handle);
403 if (gp_array->len != 0) {
404 svc_char.handle_info.count = gp_array->len;
405 svc_char.handle_info.handle =
406 __get_string_array_from_gptr_array(gp_array);
408 g_ptr_array_free(gp_array, TRUE);
411 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
412 BLUETOOTH_ERROR_NONE, &svc_char,
413 user_info->cb, user_info->user_data);
416 g_strfreev(svc_char.handle_info.handle);
417 g_free(svc_char.service_handle);
418 g_variant_iter_free(char_iter);
419 g_object_unref(proxy);
422 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
423 const char *service_handle)
425 GDBusProxy *properties_proxy = NULL;
426 GDBusConnection *g_conn;
427 GError *error = NULL;
432 BT_CHECK_PARAMETER(service_handle, return);
433 BT_CHECK_ENABLED_ANY(return);
435 g_conn = _bt_gdbus_get_system_gconn();
436 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
438 properties_proxy = g_dbus_proxy_new_sync(g_conn,
439 G_DBUS_PROXY_FLAGS_NONE, NULL,
442 BT_PROPERTIES_INTERFACE,
445 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
447 handle = g_strdup(service_handle);
448 g_dbus_proxy_call(properties_proxy,
450 g_variant_new("(ss)",
451 GATT_SERV_INTERFACE, "Characteristics"),
452 G_DBUS_CALL_FLAGS_NONE,
455 (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
459 return BLUETOOTH_ERROR_NONE;
463 static int __get_permission_flag(char *permission)
467 retv_if(permission == NULL, ret);
469 BT_DBG("permission = %s",permission);
471 if (!g_strcmp0(permission,"broadcast")) {
472 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
473 } else if (!g_strcmp0(permission,"read")) {
474 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
475 } else if (!g_strcmp0(permission,"write-without-response")) {
476 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
477 } else if (!g_strcmp0(permission,"write")) {
478 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
479 } else if (!g_strcmp0(permission,"notify")) {
480 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
481 } else if (!g_strcmp0(permission,"indicate")) {
482 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
483 } else if (!g_strcmp0(permission,"authenticated-signed-writes")) {
484 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
485 } else if (!g_strcmp0(permission,"reliable-write")) {
486 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
487 } else if (!g_strcmp0(permission,"writable-auxiliaries")) {
488 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
494 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
495 const char *char_handle, bt_gatt_char_property_t *characteristic)
497 GDBusProxy *properties_proxy = NULL;
498 GError *error = NULL;
499 GVariant *value = NULL;
500 GVariant *result = NULL;
501 GByteArray *gb_array = NULL;
502 GPtrArray *gp_array = NULL ;
503 GDBusConnection *g_conn;
507 char *char_desc_handle = NULL;
509 GVariantIter *property_iter;
510 GVariantIter *char_value_iter;
511 GVariantIter *char_perm_iter;
512 GVariantIter *char_desc_iter;
515 BT_CHECK_PARAMETER(char_handle, return);
516 BT_CHECK_PARAMETER(characteristic, return);
518 BT_CHECK_ENABLED_ANY(return);
520 g_conn = _bt_gdbus_get_system_gconn();
521 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
523 properties_proxy = g_dbus_proxy_new_sync(g_conn,
524 G_DBUS_PROXY_FLAGS_NONE, NULL,
527 BT_PROPERTIES_INTERFACE,
530 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
532 result = g_dbus_proxy_call_sync(properties_proxy,
534 g_variant_new("(s)", GATT_CHAR_INTERFACE),
535 G_DBUS_CALL_FLAGS_NONE,
542 BT_ERR("Fail to get properties (Error: %s)", error->message);
543 g_clear_error(&error);
545 BT_ERR("Fail to get properties");
546 g_object_unref(properties_proxy);
547 return BLUETOOTH_ERROR_INTERNAL;
550 g_variant_get(result, "(a{sv})", &property_iter);
552 memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
553 characteristic->handle = g_strdup(char_handle);
555 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
557 if (!g_strcmp0(key,"UUID")) {
558 characteristic->uuid = g_variant_dup_string(value,&len);
559 BT_DBG("UUID of the char = %s",characteristic->uuid);
560 } else if(!g_strcmp0(key, "Value")) {
561 gb_array = g_byte_array_new();
562 g_variant_get(value, "ay", &char_value_iter);
563 while(g_variant_iter_loop(char_value_iter, "y", &char_value)) {
564 BT_DBG("value of char = %d",char_value);
565 g_byte_array_append(gb_array, &char_value, 1);
567 g_variant_iter_free(char_value_iter);
569 if (gb_array->len != 0) {
570 characteristic->val = g_malloc0(gb_array->len *
571 sizeof(unsigned char));
572 memcpy(characteristic->val, gb_array->data, gb_array->len);
574 characteristic->val_len = gb_array->len;
575 g_byte_array_free(gb_array, TRUE);
576 } else if(!g_strcmp0(key, "Flags")) {
577 g_variant_get(value, "as", &char_perm_iter);
578 characteristic->permission = 0x00;
579 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
580 BT_DBG("permission = %s",permission);
581 characteristic->permission |= __get_permission_flag(permission);
582 BT_DBG("permission check = %d",characteristic->permission);
584 g_variant_iter_free(char_perm_iter);
585 } else if (!g_strcmp0(key, "Descriptors")) {
586 g_variant_get(value, "ao", &char_desc_iter);
587 gp_array = g_ptr_array_new();
588 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
589 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
591 g_variant_iter_free(char_desc_iter);
592 if (gp_array->len != 0) {
593 characteristic->char_desc_handle.count = gp_array->len;
594 characteristic->char_desc_handle.handle =
595 __get_string_array_from_gptr_array(gp_array);
597 g_ptr_array_free(gp_array, TRUE);
601 g_variant_iter_free(property_iter);
602 g_variant_unref(result);
603 g_object_unref(properties_proxy);
606 return BLUETOOTH_ERROR_NONE;
609 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
610 GAsyncResult *res, gpointer user_data)
613 GVariantIter *char_iter;
616 GError *error = NULL;
617 bt_user_info_t *user_info;
618 int ret = BLUETOOTH_ERROR_INTERNAL;
619 bt_gatt_char_property_t characteristic;
621 user_info = _bt_get_user_data(BT_COMMON);
623 value = g_dbus_proxy_call_finish(proxy, res, &error);
627 BT_ERR("Get service characteristics failed\n errCode[%x],"
628 "message[%s]\n", error->code, error->message);
629 g_clear_error(&error);
631 BT_ERR("Get service characteristics failed\n");
634 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
635 BLUETOOTH_ERROR_INTERNAL, NULL,
636 user_info->cb, user_info->user_data);
638 g_object_unref(proxy);
643 g_variant_get(value, "(ao)", &char_iter);
645 len = g_variant_get_size((GVariant *)char_iter);
647 for (i = 0; i < len; i++) {
648 g_variant_iter_loop(char_iter, "o", &char_handle);
651 ret = bluetooth_gatt_get_characteristics_property(char_handle,
654 if (ret != BLUETOOTH_ERROR_NONE) {
655 BT_ERR("Get characteristic property failed(0x%08x)", ret);
657 if (g_strstr_len(characteristic.uuid, -1, user_data)) {
658 ret = BLUETOOTH_ERROR_NONE;
662 bluetooth_gatt_free_char_property(&characteristic);
666 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
667 &characteristic, user_info->cb, user_info->user_data);
670 bluetooth_gatt_free_char_property(&characteristic);
671 g_variant_iter_free(char_iter);
675 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
676 const char *char_uuid)
678 GDBusProxy *properties_proxy = NULL;
679 GDBusConnection *g_conn;
680 GError *error = NULL;
683 BT_CHECK_PARAMETER(service_handle, return);
684 BT_CHECK_PARAMETER(char_uuid, return);
685 BT_CHECK_ENABLED_ANY(return);
687 g_conn = _bt_gdbus_get_system_gconn();
688 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
690 properties_proxy = g_dbus_proxy_new_sync(g_conn,
691 G_DBUS_PROXY_FLAGS_NONE, NULL,
694 BT_PROPERTIES_INTERFACE,
697 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
699 uuid = g_strdup(char_uuid);
700 g_dbus_proxy_call(properties_proxy,
702 g_variant_new("(ss)",
703 GATT_SERV_INTERFACE, "Characteristics"),
704 G_DBUS_CALL_FLAGS_NONE,
707 (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
710 return BLUETOOTH_ERROR_NONE;
713 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
714 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
716 GDBusProxy *properties_proxy = NULL;
717 GError *error = NULL;
718 GDBusConnection *g_conn;
719 GVariant *result = NULL;
720 GVariantIter *property_iter;
724 GVariant *value = NULL;
725 GByteArray *gb_array = NULL;
726 GVariantIter *desc_value_iter;
729 BT_CHECK_PARAMETER(descriptor_handle, return);
730 BT_CHECK_PARAMETER(descriptor, return);
732 BT_CHECK_ENABLED_ANY(return);
734 g_conn = _bt_gdbus_get_system_gconn();
735 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
737 properties_proxy = g_dbus_proxy_new_sync(g_conn,
738 G_DBUS_PROXY_FLAGS_NONE, NULL,
741 BT_PROPERTIES_INTERFACE,
744 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
746 result = g_dbus_proxy_call_sync(properties_proxy,
748 g_variant_new("(s)", GATT_DESC_INTERFACE),
749 G_DBUS_CALL_FLAGS_NONE,
756 BT_ERR("Fail to get properties (Error: %s)", error->message);
757 g_clear_error(&error);
759 BT_ERR("Fail to get properties");
760 g_object_unref(properties_proxy);
761 return BLUETOOTH_ERROR_INTERNAL;
764 g_variant_get(result, "(a{sv})", &property_iter);
766 memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
767 descriptor->handle = g_strdup(descriptor_handle);
769 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
771 if (!g_strcmp0(key,"UUID")) {
772 descriptor->uuid = g_variant_dup_string(value,&len);
773 BT_DBG("UUID of the char_desc = %s",descriptor->uuid);
774 } else if(!g_strcmp0(key, "Value")) {
775 gb_array = g_byte_array_new();
776 g_variant_get(value, "ay", &desc_value_iter);
777 while(g_variant_iter_loop(desc_value_iter, "y", &char_value)) {
778 BT_DBG("value of descriptor = %d",char_value);
779 g_byte_array_append(gb_array, &char_value, 1);
781 g_variant_iter_free(desc_value_iter);
782 if (gb_array->len != 0) {
783 descriptor->val = g_malloc0(gb_array->len *
784 sizeof(unsigned char));
785 memcpy(descriptor->val, gb_array->data, gb_array->len);
787 descriptor->val_len = gb_array->len;
788 g_byte_array_free(gb_array, TRUE);
792 g_variant_iter_free(property_iter);
793 g_variant_unref(result);
794 g_object_unref(properties_proxy);
797 return BLUETOOTH_ERROR_NONE;
800 static void __bluetooth_internal_read_cb(GObject *source_object,
804 GError *error = NULL;
805 bt_user_info_t *user_info;
806 bt_gatt_char_value_t char_value = { 0, };
807 GDBusConnection *system_gconn = NULL;
809 GByteArray *gp_byte_array = NULL;
814 user_info = _bt_get_user_data(BT_COMMON);
816 system_gconn = _bt_gdbus_get_system_gconn();
817 value = g_dbus_connection_call_finish(system_gconn, res, &error);
820 BT_ERR("Error : %s \n", error->message);
821 g_clear_error(&error);
823 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
824 BLUETOOTH_ERROR_INTERNAL, NULL,
825 user_info->cb, user_info->user_data);
831 char_value.char_handle = user_data;
832 gp_byte_array = g_byte_array_new();
833 g_variant_get(value, "(ay)", &iter);
835 while (g_variant_iter_loop(iter, "y", &g_byte)) {
836 g_byte_array_append(gp_byte_array, &g_byte, 1);
839 if (gp_byte_array->len != 0) {
840 char_value.val_len = gp_byte_array->len;
841 char_value.char_value = gp_byte_array->data;
845 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
846 BLUETOOTH_ERROR_NONE, &char_value,
847 user_info->cb, user_info->user_data);
850 g_free(char_value.char_handle);
851 g_byte_array_free(gp_byte_array, TRUE);
852 g_variant_unref(value);
853 g_variant_iter_free(iter);
858 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
860 GDBusConnection *conn;
863 BT_CHECK_PARAMETER(characteristic, return);
864 BT_CHECK_ENABLED_ANY(return);
866 conn = _bt_gdbus_get_system_gconn();
867 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
869 handle = g_strdup(characteristic);
871 g_dbus_connection_call(conn,
877 G_VARIANT_TYPE("(ay)"),
878 G_DBUS_CALL_FLAGS_NONE,
881 (GAsyncReadyCallback)__bluetooth_internal_read_cb,
884 return BLUETOOTH_ERROR_NONE;
887 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
888 const char *char_handle, const guint8 *value, int length)
891 GVariantBuilder *builder;
892 GError *error = NULL;
893 GDBusConnection *conn;
897 BT_CHECK_PARAMETER(char_handle, return);
898 BT_CHECK_PARAMETER(value, return);
899 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
900 BT_CHECK_ENABLED_ANY(return);
902 conn = _bt_gdbus_get_system_gconn();
903 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
905 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
907 for (i = 0; i < length; i++) {
908 g_variant_builder_add(builder, "y", value[i]);
911 val = g_variant_new("(ay)", builder);
913 g_dbus_connection_call_sync(conn,
920 G_DBUS_CALL_FLAGS_NONE,
924 BT_ERR("Set value Failed: %s", error->message);
925 g_clear_error(&error);
926 g_variant_builder_unref(builder);
927 return BLUETOOTH_ERROR_INTERNAL;
930 g_variant_builder_unref(builder);
933 return BLUETOOTH_ERROR_NONE;
936 static void __bluetooth_internal_write_cb(GObject *source_object,
941 GError *error = NULL;
942 bt_user_info_t *user_info;
943 GDBusConnection *system_gconn = NULL;
945 int result = BLUETOOTH_ERROR_NONE;
947 user_info = _bt_get_user_data(BT_COMMON);
949 system_gconn = _bt_gdbus_get_system_gconn();
950 value = g_dbus_connection_call_finish(system_gconn, res, &error);
953 BT_ERR("Error : %s \n", error->message);
954 g_clear_error(&error);
955 result = BLUETOOTH_ERROR_INTERNAL;
958 BT_DBG("result = %d", result);
959 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
961 user_info->cb, user_info->user_data);
965 g_variant_unref(value);
970 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
971 const char *char_handle, const guint8 *value, int length, guint8 write_type)
974 GVariantBuilder *builder;
975 GDBusConnection *conn;
977 int ret = BLUETOOTH_ERROR_NONE;
979 BT_CHECK_PARAMETER(char_handle, return);
980 BT_CHECK_PARAMETER(value, return);
981 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
982 BT_CHECK_ENABLED_ANY(return);
984 conn = _bt_gdbus_get_system_gconn();
985 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
987 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
989 for (i = 0; i < length; i++) {
990 g_variant_builder_add(builder, "y", value[i]);
993 val = g_variant_new("ay", builder);
994 g_dbus_connection_call(conn,
999 g_variant_new("(y@ay)", write_type, val),
1001 G_DBUS_CALL_FLAGS_NONE,
1003 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1006 g_variant_builder_unref(builder);
1010 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1011 const char *char_handle, const guint8 *value, int length)
1014 GDBusConnection *conn;
1015 GVariantBuilder *builder;
1019 BT_CHECK_PARAMETER(char_handle, return);
1020 BT_CHECK_PARAMETER(value, return);
1021 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1022 BT_CHECK_ENABLED_ANY(return);
1024 conn = _bt_gdbus_get_system_gconn();
1025 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1027 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1029 for (i = 0; i < length; i++) {
1030 g_variant_builder_add(builder, "y", value[i]);
1031 BT_DBG("value [] = %d", value[i]);
1034 val = g_variant_new("(ay)", builder);
1036 g_dbus_connection_call(conn,
1039 GATT_CHAR_INTERFACE,
1043 G_DBUS_CALL_FLAGS_NONE,
1045 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1048 g_variant_builder_unref(builder);
1051 return BLUETOOTH_ERROR_NONE;
1054 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1055 bt_gatt_char_property_t *characteristic)
1058 GDBusProxy *properties_proxy = NULL;
1059 GError *error = NULL;
1060 GVariant *value = NULL;
1061 GVariant *result = NULL;
1062 GDBusConnection *g_conn;
1063 int i, ret = BLUETOOTH_ERROR_NONE;
1064 const char *uuid = NULL;
1066 GVariantIter *desc_value_iter, *property_iter;
1068 char_descriptor_type_t desc_type = TYPE_NONE;
1070 g_conn = _bt_gdbus_get_system_gconn();
1071 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1073 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1074 G_DBUS_PROXY_FLAGS_NONE, NULL,
1077 BT_PROPERTIES_INTERFACE,
1080 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1082 result = g_dbus_proxy_call_sync(properties_proxy,
1084 g_variant_new("(s)", GATT_DESC_INTERFACE),
1085 G_DBUS_CALL_FLAGS_NONE,
1091 if (error != NULL) {
1092 BT_ERR("Fail to get properties (Error: %s)", error->message);
1093 g_clear_error(&error);
1095 BT_ERR("Fail to get properties");
1096 g_object_unref(properties_proxy);
1097 return BLUETOOTH_ERROR_INTERNAL;
1099 g_variant_get(result, "(a{sv})", &property_iter);
1100 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1101 if (!g_strcmp0(key,"UUID")) {
1102 uuid = g_variant_get_string(value, &len);
1103 if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1104 BT_DBG("GATT_USER_DESC_UUID");
1105 desc_type = USER_DESC;
1106 } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1107 BT_DBG("GATT_CHAR_FORMAT");
1108 desc_type = CHAR_FORMAT;
1109 } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1110 BT_DBG("GATT_CHAR_CLIENT_CONF");
1111 desc_type = CLIENT_CONF;
1112 } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1113 BT_DBG("GATT_CHAR_SERVER_CONF");
1114 desc_type = SERVER_CONF;
1116 BT_DBG("descriptor uuid = %s", uuid);
1118 } else if (!g_strcmp0(key, "Value")) {
1121 BT_DBG("Format descriptor");
1122 g_variant_get(value, "(yyqyq)",
1123 &(characteristic->format.format),
1124 &(characteristic->format.exponent),
1125 &(characteristic->format.unit),
1126 &(characteristic->format.name_space),
1127 &(characteristic->format.description));
1130 BT_DBG("User descriptor");
1131 g_variant_get(value, "ay", &desc_value_iter);
1132 len = g_variant_get_size((GVariant *)desc_value_iter);
1135 characteristic->description = (char *)g_malloc0(len + 1);
1136 if (!characteristic->description) {
1137 ret = BLUETOOTH_ERROR_OUT_OF_MEMORY;
1141 for (i = 0; i < len; i++) {
1142 g_variant_iter_loop(desc_value_iter, "y",
1143 &characteristic->description[i]);
1144 BT_DBG("description = %s", characteristic->description);
1146 g_variant_iter_free(desc_value_iter);
1149 BT_DBG(" CLIENT_CONF");
1152 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);
1302 if (gp_byte_array->len != 0) {
1303 char_value.val_len = (unsigned int )gp_byte_array->len;
1304 char_value.description= (char *)gp_byte_array->data;
1308 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1309 BLUETOOTH_ERROR_NONE, &char_value,
1310 user_info->cb, user_info->user_data);
1313 g_byte_array_free(gp_byte_array, TRUE);
1314 g_free(char_value.handle);
1315 g_variant_unref(value);
1316 g_variant_iter_free(iter);
1321 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
1323 GDBusConnection *conn;
1327 BT_CHECK_PARAMETER(char_descriptor, return);
1328 BT_CHECK_ENABLED_ANY(return);
1330 conn = _bt_gdbus_get_system_gconn();
1331 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1333 handle = g_strdup(char_descriptor);
1335 g_dbus_connection_call(conn,
1338 GATT_DESC_INTERFACE,
1341 G_VARIANT_TYPE("(ay)"),
1342 G_DBUS_CALL_FLAGS_NONE,
1345 (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1349 return BLUETOOTH_ERROR_NONE;
1352 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1356 GError *error = NULL;
1357 bt_user_info_t *user_info;
1358 GDBusConnection *system_gconn = NULL;
1360 int result = BLUETOOTH_ERROR_NONE;
1363 user_info = _bt_get_user_data(BT_COMMON);
1365 system_gconn = _bt_gdbus_get_system_gconn();
1366 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1369 BT_ERR("Error : %s \n", error->message);
1370 g_clear_error(&error);
1371 result = BLUETOOTH_ERROR_INTERNAL;
1374 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1376 user_info->cb, user_info->user_data);
1380 g_variant_unref(value);
1385 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
1386 const char *desc_handle, const guint8 *value, int length)
1389 GDBusConnection *conn;
1390 GVariantBuilder *builder;
1394 BT_CHECK_PARAMETER(desc_handle, return);
1395 BT_CHECK_PARAMETER(value, return);
1396 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1397 BT_CHECK_ENABLED_ANY(return);
1399 conn = _bt_gdbus_get_system_gconn();
1400 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1402 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1404 for (i = 0; i < length; i++) {
1405 g_variant_builder_add(builder, "y", value[i]);
1408 val = g_variant_new("(ay)", builder);
1410 g_dbus_connection_call(conn,
1413 GATT_DESC_INTERFACE,
1417 G_DBUS_CALL_FLAGS_NONE,
1419 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1422 g_variant_builder_unref(builder);
1425 return BLUETOOTH_ERROR_NONE;
1428 #ifndef GATT_NO_RELAY
1429 static int __bluetooth_gatt_watch_characteristics(void)
1431 int result = BLUETOOTH_ERROR_NONE;
1434 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1436 result = _bt_send_request(BT_BLUEZ_SERVICE,
1437 BT_GATT_WATCH_CHARACTERISTIC,
1438 in_param1, in_param2, in_param3, in_param4, &out_param);
1440 if (result != BLUETOOTH_ERROR_NONE)
1441 BT_ERR("Watch Characteristic request failed !");
1443 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1448 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
1451 GDBusConnection *conn;
1452 GError *error = NULL;
1453 int ret = BLUETOOTH_ERROR_NONE;
1455 BT_CHECK_PARAMETER(char_handle, return);
1457 BT_CHECK_ENABLED_ANY(return);
1459 BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1461 conn = _bt_gdbus_get_system_gconn();
1462 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1464 g_dbus_connection_call_sync(conn,
1467 GATT_CHAR_INTERFACE,
1471 G_DBUS_CALL_FLAGS_NONE,
1475 BT_ERR("Watch Failed: %s", error->message);
1476 if (g_strrstr(error->message, "Already notifying"))
1477 ret = BLUETOOTH_ERROR_NONE;
1478 else if (g_strrstr(error->message, "In Progress"))
1479 ret = BLUETOOTH_ERROR_IN_PROGRESS;
1480 else if (g_strrstr(error->message, "Operation is not supported"))
1481 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1482 /*failed because of either Insufficient Authorization or Write Not Permitted */
1483 else if (g_strrstr(error->message, "Write not permitted") ||
1484 g_strrstr(error->message, "Operation Not Authorized"))
1485 ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1486 /* failed because of either Insufficient Authentication,
1487 Insufficient Encryption Key Size, or Insufficient Encryption. */
1488 else if (g_strrstr(error->message, "Not paired"))
1489 ret = BLUETOOTH_ERROR_NOT_PAIRED;
1491 ret = BLUETOOTH_ERROR_INTERNAL;
1493 g_clear_error(&error);
1495 #ifndef GATT_NO_RELAY
1497 /* Register the client sender to bt-service */
1498 ret = __bluetooth_gatt_watch_characteristics();
1505 #ifndef GATT_NO_RELAY
1506 static void __bluetooth_gatt_unwatch_characteristics(void)
1508 int result = BLUETOOTH_ERROR_NONE;
1511 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1513 result = _bt_send_request(BT_BLUEZ_SERVICE,
1514 BT_GATT_UNWATCH_CHARACTERISTIC,
1515 in_param1, in_param2, in_param3, in_param4, &out_param);
1517 if (result != BLUETOOTH_ERROR_NONE)
1518 BT_ERR("Unwatch Characteristic request failed !");
1520 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1524 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1527 GDBusConnection *conn;
1528 GError *error = NULL;
1529 int ret = BLUETOOTH_ERROR_NONE;
1531 BT_CHECK_PARAMETER(char_handle, return);
1533 BT_CHECK_ENABLED_ANY(return);
1535 BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1537 conn = _bt_gdbus_get_system_gconn();
1538 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1540 g_dbus_connection_call_sync(conn,
1543 GATT_CHAR_INTERFACE,
1547 G_DBUS_CALL_FLAGS_NONE,
1551 BT_ERR("Watch Failed: %s", error->message);
1552 g_clear_error(&error);
1553 ret = BLUETOOTH_ERROR_INTERNAL;
1555 #ifndef GATT_NO_RELAY
1557 /* Unregister the client sender to bt-service */
1558 __bluetooth_gatt_unwatch_characteristics();