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 if (gb_array->len != 0) {
568 characteristic->val = g_malloc0(gb_array->len *
569 sizeof(unsigned char));
570 memcpy(characteristic->val, gb_array->data, gb_array->len);
572 characteristic->val_len = gb_array->len;
573 g_byte_array_free(gb_array, TRUE);
574 } else if(!g_strcmp0(key, "Flags")) {
575 g_variant_get(value, "as", &char_perm_iter);
576 characteristic->permission = 0x00;
577 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
578 BT_DBG("permission = %s",permission);
579 characteristic->permission |= __get_permission_flag(permission);
580 BT_DBG("permission check = %d",characteristic->permission);
582 g_variant_iter_free(char_perm_iter);
583 } else if (!g_strcmp0(key, "Descriptors")) {
584 g_variant_get(value, "ao", &char_desc_iter);
585 gp_array = g_ptr_array_new();
586 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
587 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
589 if (gp_array->len != 0) {
590 characteristic->char_desc_handle.count = gp_array->len;
591 characteristic->char_desc_handle.handle =
592 __get_string_array_from_gptr_array(gp_array);
594 g_ptr_array_free(gp_array, TRUE);
598 g_variant_iter_free(property_iter);
599 g_variant_unref(result);
600 g_object_unref(properties_proxy);
603 return BLUETOOTH_ERROR_NONE;
606 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
607 GAsyncResult *res, gpointer user_data)
610 GVariantIter *char_iter;
613 GError *error = NULL;
614 bt_user_info_t *user_info;
615 int ret = BLUETOOTH_ERROR_INTERNAL;
616 bt_gatt_char_property_t characteristic;
618 user_info = _bt_get_user_data(BT_COMMON);
620 value = g_dbus_proxy_call_finish(proxy, res, &error);
624 BT_ERR("Get service characteristics failed\n errCode[%x],"
625 "message[%s]\n", error->code, error->message);
626 g_clear_error(&error);
628 BT_ERR("Get service characteristics failed\n");
631 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
632 BLUETOOTH_ERROR_INTERNAL, NULL,
633 user_info->cb, user_info->user_data);
635 g_object_unref(proxy);
640 g_variant_get(value, "(ao)", &char_iter);
642 len = g_variant_get_size((GVariant *)char_iter);
644 for (i = 0; i < len; i++) {
645 g_variant_iter_loop(char_iter, "o", &char_handle);
648 ret = bluetooth_gatt_get_characteristics_property(char_handle,
651 if (ret != BLUETOOTH_ERROR_NONE) {
652 BT_ERR("Get characteristic property failed(0x%08x)", ret);
654 if (g_strstr_len(characteristic.uuid, -1, user_data)) {
655 ret = BLUETOOTH_ERROR_NONE;
659 bluetooth_gatt_free_char_property(&characteristic);
663 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
664 &characteristic, user_info->cb, user_info->user_data);
667 bluetooth_gatt_free_char_property(&characteristic);
668 g_variant_iter_free(char_iter);
672 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
673 const char *char_uuid)
675 GDBusProxy *properties_proxy = NULL;
676 GDBusConnection *g_conn;
677 GError *error = NULL;
680 BT_CHECK_PARAMETER(service_handle, return);
681 BT_CHECK_PARAMETER(char_uuid, return);
682 BT_CHECK_ENABLED_ANY(return);
684 g_conn = _bt_gdbus_get_system_gconn();
685 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
687 properties_proxy = g_dbus_proxy_new_sync(g_conn,
688 G_DBUS_PROXY_FLAGS_NONE, NULL,
691 BT_PROPERTIES_INTERFACE,
694 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
696 uuid = g_strdup(char_uuid);
697 g_dbus_proxy_call(properties_proxy,
699 g_variant_new("(ss)",
700 GATT_SERV_INTERFACE, "Characteristics"),
701 G_DBUS_CALL_FLAGS_NONE,
704 (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
707 return BLUETOOTH_ERROR_NONE;
710 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
711 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
713 GDBusProxy *properties_proxy = NULL;
714 GError *error = NULL;
715 GDBusConnection *g_conn;
716 GVariant *result = NULL;
717 GVariantIter *property_iter;
721 GVariant *value = NULL;
722 GByteArray *gb_array = NULL;
723 GVariantIter *desc_value_iter;
726 BT_CHECK_PARAMETER(descriptor_handle, return);
727 BT_CHECK_PARAMETER(descriptor, return);
729 BT_CHECK_ENABLED_ANY(return);
731 g_conn = _bt_gdbus_get_system_gconn();
732 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
734 properties_proxy = g_dbus_proxy_new_sync(g_conn,
735 G_DBUS_PROXY_FLAGS_NONE, NULL,
738 BT_PROPERTIES_INTERFACE,
741 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
743 result = g_dbus_proxy_call_sync(properties_proxy,
745 g_variant_new("(s)", GATT_DESC_INTERFACE),
746 G_DBUS_CALL_FLAGS_NONE,
753 BT_ERR("Fail to get properties (Error: %s)", error->message);
754 g_clear_error(&error);
756 BT_ERR("Fail to get properties");
757 g_object_unref(properties_proxy);
758 return BLUETOOTH_ERROR_INTERNAL;
761 g_variant_get(result, "(a{sv})", &property_iter);
763 memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
764 descriptor->handle = g_strdup(descriptor_handle);
766 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
768 if (!g_strcmp0(key,"UUID")) {
769 descriptor->uuid = g_variant_dup_string(value,&len);
770 BT_DBG("UUID of the char_desc = %s",descriptor->uuid);
771 } else if(!g_strcmp0(key, "Value")) {
772 gb_array = g_byte_array_new();
773 g_variant_get(value, "ay", &desc_value_iter);
774 while(g_variant_iter_loop(desc_value_iter, "y", &char_value)) {
775 BT_DBG("value of descriptor = %d",char_value);
776 g_byte_array_append(gb_array, &char_value, 1);
778 if (gb_array->len != 0) {
779 descriptor->val = g_malloc0(gb_array->len *
780 sizeof(unsigned char));
781 memcpy(descriptor->val, gb_array->data, gb_array->len);
783 descriptor->val_len = gb_array->len;
784 g_byte_array_free(gb_array, TRUE);
788 g_variant_iter_free(property_iter);
789 g_variant_unref(result);
790 g_object_unref(properties_proxy);
793 return BLUETOOTH_ERROR_NONE;
796 static void __bluetooth_internal_read_cb(GObject *source_object,
800 GError *error = NULL;
801 bt_user_info_t *user_info;
802 bt_gatt_char_value_t char_value = { 0, };
803 GDBusConnection *system_gconn = NULL;
805 GByteArray *gp_byte_array = NULL;
810 user_info = _bt_get_user_data(BT_COMMON);
812 system_gconn = _bt_gdbus_get_system_gconn();
813 value = g_dbus_connection_call_finish(system_gconn, res, &error);
816 BT_ERR("Error : %s \n", error->message);
817 g_clear_error(&error);
819 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
820 BLUETOOTH_ERROR_INTERNAL, NULL,
821 user_info->cb, user_info->user_data);
827 char_value.char_handle = user_data;
828 gp_byte_array = g_byte_array_new();
829 g_variant_get(value, "(ay)", &iter);
831 while (g_variant_iter_loop(iter, "y", &g_byte)) {
832 g_byte_array_append(gp_byte_array, &g_byte, 1);
835 if (gp_byte_array->len != 0) {
836 char_value.val_len = gp_byte_array->len;
837 char_value.char_value = gp_byte_array->data;
841 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
842 BLUETOOTH_ERROR_NONE, &char_value,
843 user_info->cb, user_info->user_data);
846 g_free(char_value.char_handle);
847 g_byte_array_free(gp_byte_array, TRUE);
848 g_variant_unref(value);
849 g_variant_iter_free(iter);
854 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
856 GDBusConnection *conn;
859 BT_CHECK_PARAMETER(characteristic, return);
860 BT_CHECK_ENABLED_ANY(return);
862 conn = _bt_gdbus_get_system_gconn();
863 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
865 handle = g_strdup(characteristic);
867 g_dbus_connection_call(conn,
873 G_VARIANT_TYPE("(ay)"),
874 G_DBUS_CALL_FLAGS_NONE,
877 (GAsyncReadyCallback)__bluetooth_internal_read_cb,
880 return BLUETOOTH_ERROR_NONE;
883 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
884 const char *char_handle, const guint8 *value, int length)
887 GVariantBuilder *builder;
888 GError *error = NULL;
889 GDBusConnection *conn;
893 BT_CHECK_PARAMETER(char_handle, return);
894 BT_CHECK_PARAMETER(value, return);
895 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
896 BT_CHECK_ENABLED_ANY(return);
898 conn = _bt_gdbus_get_system_gconn();
899 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
901 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
903 for (i = 0; i < length; i++) {
904 g_variant_builder_add(builder, "y", value[i]);
907 val = g_variant_new("(ay)", builder);
909 g_dbus_connection_call_sync(conn,
916 G_DBUS_CALL_FLAGS_NONE,
920 BT_ERR("Set value Failed: %s", error->message);
921 g_clear_error(&error);
922 g_variant_builder_unref(builder);
923 return BLUETOOTH_ERROR_INTERNAL;
926 g_variant_builder_unref(builder);
929 return BLUETOOTH_ERROR_NONE;
932 static void __bluetooth_internal_write_cb(GObject *source_object,
937 GError *error = NULL;
938 bt_user_info_t *user_info;
939 GDBusConnection *system_gconn = NULL;
941 int result = BLUETOOTH_ERROR_NONE;
943 user_info = _bt_get_user_data(BT_COMMON);
945 system_gconn = _bt_gdbus_get_system_gconn();
946 value = g_dbus_connection_call_finish(system_gconn, res, &error);
949 BT_ERR("Error : %s \n", error->message);
950 g_clear_error(&error);
951 result = BLUETOOTH_ERROR_INTERNAL;
954 BT_DBG("result = %d", result);
955 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
957 user_info->cb, user_info->user_data);
961 g_variant_unref(value);
966 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
967 const char *char_handle, const guint8 *value, int length, guint8 write_type)
970 GVariantBuilder *builder;
971 GDBusConnection *conn;
973 int ret = BLUETOOTH_ERROR_NONE;
975 BT_CHECK_PARAMETER(char_handle, return);
976 BT_CHECK_PARAMETER(value, return);
977 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
978 BT_CHECK_ENABLED_ANY(return);
980 conn = _bt_gdbus_get_system_gconn();
981 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
983 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
985 for (i = 0; i < length; i++) {
986 g_variant_builder_add(builder, "y", value[i]);
989 val = g_variant_new("ay", builder);
990 g_dbus_connection_call(conn,
995 g_variant_new("(y@ay)", write_type, val),
997 G_DBUS_CALL_FLAGS_NONE,
999 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1002 g_variant_builder_unref(builder);
1006 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1007 const char *char_handle, const guint8 *value, int length)
1010 GDBusConnection *conn;
1011 GVariantBuilder *builder;
1015 BT_CHECK_PARAMETER(char_handle, return);
1016 BT_CHECK_PARAMETER(value, return);
1017 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1018 BT_CHECK_ENABLED_ANY(return);
1020 conn = _bt_gdbus_get_system_gconn();
1021 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1023 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1025 for (i = 0; i < length; i++) {
1026 g_variant_builder_add(builder, "y", value[i]);
1027 BT_DBG("value [] = %d", value[i]);
1030 val = g_variant_new("(ay)", builder);
1032 g_dbus_connection_call(conn,
1035 GATT_CHAR_INTERFACE,
1039 G_DBUS_CALL_FLAGS_NONE,
1041 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1044 g_variant_builder_unref(builder);
1047 return BLUETOOTH_ERROR_NONE;
1050 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1051 bt_gatt_char_property_t *characteristic)
1054 GDBusProxy *properties_proxy = NULL;
1055 GError *error = NULL;
1056 GVariant *value = NULL;
1057 GVariant *result = NULL;
1058 GDBusConnection *g_conn;
1059 int i, ret = BLUETOOTH_ERROR_NONE;
1060 const char *uuid = NULL;
1062 GVariantIter *desc_value_iter, *property_iter;
1064 char_descriptor_type_t desc_type = TYPE_NONE;
1066 g_conn = _bt_gdbus_get_system_gconn();
1067 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1069 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1070 G_DBUS_PROXY_FLAGS_NONE, NULL,
1073 BT_PROPERTIES_INTERFACE,
1076 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1078 result = g_dbus_proxy_call_sync(properties_proxy,
1080 g_variant_new("(s)", GATT_DESC_INTERFACE),
1081 G_DBUS_CALL_FLAGS_NONE,
1087 if (error != NULL) {
1088 BT_ERR("Fail to get properties (Error: %s)", error->message);
1089 g_clear_error(&error);
1091 BT_ERR("Fail to get properties");
1092 g_object_unref(properties_proxy);
1093 return BLUETOOTH_ERROR_INTERNAL;
1095 g_variant_get(result, "(a{sv})", &property_iter);
1096 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1097 if (!g_strcmp0(key,"UUID")) {
1098 uuid = g_variant_get_string(value, &len);
1099 if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1100 BT_DBG("GATT_USER_DESC_UUID");
1101 desc_type = USER_DESC;
1102 } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1103 BT_DBG("GATT_CHAR_FORMAT");
1104 desc_type = CHAR_FORMAT;
1105 } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1106 BT_DBG("GATT_CHAR_CLIENT_CONF");
1107 desc_type = CLIENT_CONF;
1108 } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1109 BT_DBG("GATT_CHAR_SERVER_CONF");
1110 desc_type = SERVER_CONF;
1112 BT_DBG("descriptor uuid = %s", uuid);
1114 } else if (!g_strcmp0(key, "Value")) {
1117 BT_DBG("Format descriptor");
1118 g_variant_get(value, "(yyqyq)",
1119 &(characteristic->format.format),
1120 &(characteristic->format.exponent),
1121 &(characteristic->format.unit),
1122 &(characteristic->format.name_space),
1123 &(characteristic->format.description));
1126 BT_DBG("User descriptor");
1127 g_variant_get(value, "ay", &desc_value_iter);
1128 len = g_variant_get_size((GVariant *)desc_value_iter);
1131 characteristic->description = (char *)g_malloc0(len + 1);
1132 if (!characteristic->description) {
1133 ret = BLUETOOTH_ERROR_OUT_OF_MEMORY;
1137 for (i = 0; i < len; i++) {
1138 g_variant_iter_loop(desc_value_iter, "y",
1139 &characteristic->description[i]);
1140 BT_DBG("description = %s", characteristic->description);
1144 BT_DBG(" CLIENT_CONF");
1147 BT_DBG(" SERVER_CONF");
1155 g_variant_iter_free(property_iter);
1156 g_variant_unref(result);
1157 g_object_unref(properties_proxy);
1164 static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy,
1165 GAsyncResult *res, gpointer user_data)
1169 GVariant *char_value;
1170 GVariantIter *char_iter;
1172 GError *error = NULL;
1173 bt_user_info_t *user_info;
1174 bt_gatt_char_property_t characteristic = {0, };
1175 int ret = BLUETOOTH_ERROR_INTERNAL;
1177 user_info = _bt_get_user_data(BT_COMMON);
1179 value = g_dbus_proxy_call_finish(proxy, res, &error);
1181 if (value == NULL) {
1182 if (error != NULL) {
1183 BT_ERR("Get characteristic descriptor failed\n errCode[%x],"
1184 "message[%s]\n", error->code, error->message);
1185 g_clear_error(&error);
1187 BT_ERR("Get characteristic descriptor failed\n");
1190 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1191 BLUETOOTH_ERROR_INTERNAL, NULL,
1192 user_info->cb, user_info->user_data);
1195 g_object_unref(proxy);
1199 g_variant_get(value, "(v)", &char_value);
1200 g_variant_get(char_value, "ao", &char_iter);
1202 while(g_variant_iter_loop(char_iter, "&o", &char_handle)) {
1203 BT_DBG("object path of descriptor = %s",char_handle);
1205 ret = __bluetooth_gatt_descriptor_iter(char_handle,
1207 BT_DBG("Descriptor read status [%d]",ret);
1211 characteristic.handle = user_data;
1213 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
1214 ret, &characteristic, user_info->cb, user_info->user_data);
1216 bluetooth_gatt_free_char_property(&characteristic);
1218 g_variant_iter_free(char_iter);
1222 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor(
1223 const char *characteristic_handle)
1225 GDBusProxy *properties_proxy = NULL;
1226 GDBusConnection *g_conn;
1228 GError *error = NULL;
1230 BT_CHECK_PARAMETER(characteristic_handle, return);
1231 BT_CHECK_ENABLED_ANY(return);
1233 g_conn = _bt_gdbus_get_system_gconn();
1234 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1236 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1237 G_DBUS_PROXY_FLAGS_NONE, NULL,
1239 characteristic_handle,
1240 BT_PROPERTIES_INTERFACE,
1243 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1245 handle = g_strdup(characteristic_handle);
1246 g_dbus_proxy_call(properties_proxy,
1248 g_variant_new("(ss)",
1249 GATT_CHAR_INTERFACE, "Descriptors"),
1250 G_DBUS_CALL_FLAGS_NONE,
1252 (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb,
1255 return BLUETOOTH_ERROR_NONE;
1258 static void __bluetooth_internal_read_desc_cb(GObject *source_object,
1262 GError *error = NULL;
1263 bt_user_info_t *user_info;
1264 bt_gatt_char_property_t char_value = { 0, };
1265 GDBusConnection *system_gconn = NULL;
1267 GByteArray *gp_byte_array = NULL;
1272 user_info = _bt_get_user_data(BT_COMMON);
1273 system_gconn = _bt_gdbus_get_system_gconn();
1275 char_value.handle = user_data;
1276 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1279 BT_ERR("Error : %s \n", error->message);
1280 g_clear_error(&error);
1282 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1283 BLUETOOTH_ERROR_INTERNAL, NULL,
1284 user_info->cb, user_info->user_data);
1286 g_free(char_value.handle);
1290 gp_byte_array = g_byte_array_new();
1291 g_variant_get(value, "(ay)", &iter);
1293 while(g_variant_iter_loop(iter, "y", &g_byte)) {
1294 g_byte_array_append(gp_byte_array, &g_byte, 1);
1297 if (gp_byte_array->len != 0) {
1298 char_value.val_len = (unsigned int )gp_byte_array->len;
1299 char_value.description= (char *)gp_byte_array->data;
1303 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC,
1304 BLUETOOTH_ERROR_NONE, &char_value,
1305 user_info->cb, user_info->user_data);
1308 g_byte_array_free(gp_byte_array, TRUE);
1309 g_free(char_value.handle);
1310 g_variant_unref(value);
1311 g_variant_iter_free(iter);
1316 BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor)
1318 GDBusConnection *conn;
1322 BT_CHECK_PARAMETER(char_descriptor, return);
1323 BT_CHECK_ENABLED_ANY(return);
1325 conn = _bt_gdbus_get_system_gconn();
1326 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1328 handle = g_strdup(char_descriptor);
1330 g_dbus_connection_call(conn,
1333 GATT_DESC_INTERFACE,
1336 G_VARIANT_TYPE("(ay)"),
1337 G_DBUS_CALL_FLAGS_NONE,
1340 (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb,
1344 return BLUETOOTH_ERROR_NONE;
1347 static void __bluetooth_internal_write_desc_cb(GObject *source_object,
1351 GError *error = NULL;
1352 bt_user_info_t *user_info;
1353 GDBusConnection *system_gconn = NULL;
1355 int result = BLUETOOTH_ERROR_NONE;
1358 user_info = _bt_get_user_data(BT_COMMON);
1360 system_gconn = _bt_gdbus_get_system_gconn();
1361 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1364 BT_ERR("Error : %s \n", error->message);
1365 g_clear_error(&error);
1366 result = BLUETOOTH_ERROR_INTERNAL;
1369 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
1371 user_info->cb, user_info->user_data);
1375 g_variant_unref(value);
1380 BT_EXPORT_API int bluetooth_gatt_write_descriptor_value(
1381 const char *desc_handle, const guint8 *value, int length)
1384 GDBusConnection *conn;
1385 GVariantBuilder *builder;
1389 BT_CHECK_PARAMETER(desc_handle, return);
1390 BT_CHECK_PARAMETER(value, return);
1391 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1392 BT_CHECK_ENABLED_ANY(return);
1394 conn = _bt_gdbus_get_system_gconn();
1395 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1397 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1399 for (i = 0; i < length; i++) {
1400 g_variant_builder_add(builder, "y", value[i]);
1403 val = g_variant_new("(ay)", builder);
1405 g_dbus_connection_call(conn,
1408 GATT_DESC_INTERFACE,
1412 G_DBUS_CALL_FLAGS_NONE,
1414 (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb,
1417 g_variant_builder_unref(builder);
1420 return BLUETOOTH_ERROR_NONE;
1423 #ifndef GATT_NO_RELAY
1424 static int __bluetooth_gatt_watch_characteristics(void)
1426 int result = BLUETOOTH_ERROR_NONE;
1429 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1431 result = _bt_send_request(BT_BLUEZ_SERVICE,
1432 BT_GATT_WATCH_CHARACTERISTIC,
1433 in_param1, in_param2, in_param3, in_param4, &out_param);
1435 if (result != BLUETOOTH_ERROR_NONE)
1436 BT_ERR("Watch Characteristic request failed !");
1438 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1443 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle)
1446 GDBusConnection *conn;
1447 GError *error = NULL;
1448 int ret = BLUETOOTH_ERROR_NONE;
1450 BT_CHECK_PARAMETER(char_handle, return);
1452 BT_CHECK_ENABLED_ANY(return);
1454 BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1456 conn = _bt_gdbus_get_system_gconn();
1457 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1459 g_dbus_connection_call_sync(conn,
1462 GATT_CHAR_INTERFACE,
1466 G_DBUS_CALL_FLAGS_NONE,
1470 BT_ERR("Watch Failed: %s", error->message);
1471 if (g_strrstr(error->message, "Already notifying"))
1472 ret = BLUETOOTH_ERROR_NONE;
1473 else if (g_strrstr(error->message, "In Progress"))
1474 ret = BLUETOOTH_ERROR_IN_PROGRESS;
1475 else if (g_strrstr(error->message, "Operation is not supported"))
1476 ret = BLUETOOTH_ERROR_NOT_SUPPORT;
1477 /*failed because of either Insufficient Authorization or Write Not Permitted */
1478 else if (g_strrstr(error->message, "Write not permitted") ||
1479 g_strrstr(error->message, "Operation Not Authorized"))
1480 ret = BLUETOOTH_ERROR_PERMISSION_DEINED;
1481 /* failed because of either Insufficient Authentication,
1482 Insufficient Encryption Key Size, or Insufficient Encryption. */
1483 else if (g_strrstr(error->message, "Not paired"))
1484 ret = BLUETOOTH_ERROR_NOT_PAIRED;
1486 ret = BLUETOOTH_ERROR_INTERNAL;
1488 g_clear_error(&error);
1490 #ifndef GATT_NO_RELAY
1492 /* Register the client sender to bt-service */
1493 ret = __bluetooth_gatt_watch_characteristics();
1500 #ifndef GATT_NO_RELAY
1501 static void __bluetooth_gatt_unwatch_characteristics(void)
1503 int result = BLUETOOTH_ERROR_NONE;
1506 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1508 result = _bt_send_request(BT_BLUEZ_SERVICE,
1509 BT_GATT_UNWATCH_CHARACTERISTIC,
1510 in_param1, in_param2, in_param3, in_param4, &out_param);
1512 if (result != BLUETOOTH_ERROR_NONE)
1513 BT_ERR("Unwatch Characteristic request failed !");
1515 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1519 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *char_handle)
1522 GDBusConnection *conn;
1523 GError *error = NULL;
1524 int ret = BLUETOOTH_ERROR_NONE;
1526 BT_CHECK_PARAMETER(char_handle, return);
1528 BT_CHECK_ENABLED_ANY(return);
1530 BT_DBG("Entered characteristic handle:%s \n ", char_handle);
1532 conn = _bt_gdbus_get_system_gconn();
1533 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1535 g_dbus_connection_call_sync(conn,
1538 GATT_CHAR_INTERFACE,
1542 G_DBUS_CALL_FLAGS_NONE,
1546 BT_ERR("Watch Failed: %s", error->message);
1547 g_clear_error(&error);
1548 ret = BLUETOOTH_ERROR_INTERNAL;
1550 #ifndef GATT_NO_RELAY
1552 /* Unregister the client sender to bt-service */
1553 __bluetooth_gatt_unwatch_characteristics();