2 * Bluetooth-frwk low energy (GATT Client)
4 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Chanyeol Park <chanyeol.park@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
25 #include <glib/gprintf.h>
30 #include "bt-common.h"
31 #include "bt-internal-types.h"
32 #include "bt-request-sender.h"
34 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
35 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
36 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
38 #define GATT_USER_DESC_UUID "00002901-0000-1000-8000-00805f9b34fb"
39 #define GATT_CHAR_CLIENT_CONF "00002902-0000-1000-8000-00805f9b34fb"
40 #define GATT_CHAR_SERVER_CONF "00002903-0000-1000-8000-00805f9b34fb"
41 #define GATT_CHAR_FORMAT "00002904-0000-1000-8000-00805f9b34fb"
49 }char_descriptor_type_t;
51 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
55 BT_CHECK_PARAMETER(svc_pty, return);
57 g_free(svc_pty->uuid);
58 g_free(svc_pty->handle);
59 g_strfreev(svc_pty->include_handles.handle);
60 g_strfreev(svc_pty->char_handle.handle);
62 memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
65 return BLUETOOTH_ERROR_NONE;
68 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
72 BT_CHECK_PARAMETER(char_pty, return);
74 g_free(char_pty->uuid);
75 g_free(char_pty->name);
76 g_free(char_pty->description);
77 g_free(char_pty->val);
78 g_free(char_pty->handle);
79 g_strfreev(char_pty->char_desc_handle.handle);
81 memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
84 return BLUETOOTH_ERROR_NONE;
87 BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty)
91 BT_CHECK_PARAMETER(desc_pty, return);
93 g_free(desc_pty->uuid);
94 g_free(desc_pty->val);
95 g_free(desc_pty->handle);
97 memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t));
100 return BLUETOOTH_ERROR_NONE;
103 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
105 gchar *gp_path = NULL;
112 path = g_malloc0((gp->len + 1) * sizeof(char *));
114 /* Fix : NULL_RETURNS */
118 for (i = 0; i < gp->len; i++) {
119 gp_path = g_ptr_array_index(gp, i);
120 path[i] = g_strdup(gp_path);
121 BT_DBG("path[%d] : [%s]", i, path[i]);
127 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
128 bt_gatt_service_property_t *service)
130 GDBusProxy *properties_proxy = NULL;
131 GError *error = NULL;
132 GVariant *result = NULL;
133 GDBusConnection *g_conn;
135 char *char_handle = NULL;
136 GPtrArray *gp_array = NULL ;
137 GVariantIter *property_iter, *char_iter;
141 BT_CHECK_PARAMETER(service_handle, return);
142 BT_CHECK_PARAMETER(service, return);
143 BT_CHECK_ENABLED_ANY(return);
145 g_conn = _bt_gdbus_get_system_gconn();
146 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
148 properties_proxy = g_dbus_proxy_new_sync(g_conn,
149 G_DBUS_PROXY_FLAGS_NONE, NULL,
152 BT_PROPERTIES_INTERFACE,
155 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
157 result = g_dbus_proxy_call_sync(properties_proxy,
159 g_variant_new("(s)", GATT_SERV_INTERFACE),
160 G_DBUS_CALL_FLAGS_NONE,
167 BT_ERR("Fail to get properties (Error: %s)", error->message);
168 g_clear_error(&error);
170 BT_ERR("Fail to get properties");
171 g_object_unref(properties_proxy);
172 return BLUETOOTH_ERROR_INTERNAL;
175 g_variant_get(result, "(a{sv})", &property_iter);
177 memset(service, 0, sizeof(bt_gatt_service_property_t));
179 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
180 if (!g_strcmp0(key,"UUID")) {
181 service->uuid = g_variant_dup_string(value,&len);
183 } else if(!g_strcmp0(key, "Primary")) {
184 service->primary = g_variant_get_boolean(value);
186 } else if (!g_strcmp0(key, "Includes")) {
187 g_variant_get(value, "ao", &char_iter);
188 gp_array = g_ptr_array_new();
189 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
190 g_ptr_array_add(gp_array, (gpointer)char_handle);
192 if (gp_array->len != 0) {
193 service->include_handles.count = gp_array->len;
194 service->include_handles.handle =
195 __get_string_array_from_gptr_array(gp_array);
197 g_ptr_array_free(gp_array, TRUE);
198 } else if (!g_strcmp0(key, "Characteristics")) {
199 g_variant_get(value, "ao", &char_iter);
200 gp_array = g_ptr_array_new();
201 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
202 g_ptr_array_add(gp_array, (gpointer)char_handle);
204 if (gp_array->len != 0) {
205 service->char_handle.count = gp_array->len;
206 service->char_handle.handle =
207 __get_string_array_from_gptr_array(gp_array);
209 g_ptr_array_free(gp_array, TRUE);
213 service->handle = g_strdup(service_handle);
215 g_variant_iter_free(property_iter);
216 g_variant_unref(result);
217 g_object_unref(properties_proxy);
219 return BLUETOOTH_ERROR_NONE;
222 BT_EXPORT_API int bluetooth_gatt_get_primary_services(
223 const bluetooth_device_address_t *address,
224 bt_gatt_handle_info_t *prim_svc)
226 GVariant *result = NULL;
228 GVariantIter *svc_iter;
229 GVariantIter *interface_iter;
230 char *object_path = NULL;
231 char *interface_str = NULL;
232 const gchar *key = NULL;
233 GVariant *value = NULL;
234 GPtrArray *gp_array = NULL;
235 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
236 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
237 int ret = BLUETOOTH_ERROR_INTERNAL;
240 BT_CHECK_PARAMETER(address, return);
241 BT_CHECK_PARAMETER(prim_svc, return);
242 BT_CHECK_ENABLED_ANY(return);
244 result = _bt_get_managed_objects();
248 _bt_convert_addr_type_to_string(device_address,
249 (unsigned char *)address->addr);
251 gp_array = g_ptr_array_new();
252 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
254 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
256 if (object_path == NULL)
259 _bt_convert_device_path_to_address(object_path, temp_address);
261 if (g_strcmp0(temp_address, device_address) != 0)
264 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
265 &interface_str, &svc_iter)) {
266 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
269 BT_DBG("Object Path: %s", object_path);
270 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
271 if (g_strcmp0(key, "Primary") == 0) {
272 if (g_variant_get_boolean(value))
273 g_ptr_array_add(gp_array, (gpointer)object_path);
279 if (gp_array->len == 0) {
280 BT_ERR("gp_array is NULL");
281 ret = BLUETOOTH_ERROR_NOT_FOUND;
283 ret = BLUETOOTH_ERROR_NONE;
284 prim_svc->count = gp_array->len;
285 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
288 g_ptr_array_free(gp_array, TRUE);
289 g_variant_iter_free(iter);
290 g_variant_unref(result);
295 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
296 const char *service_uuid,
297 bt_gatt_service_property_t *service)
299 GVariant *result = NULL;
301 GVariantIter *svc_iter;
302 GVariantIter *interface_iter;
303 char *object_path = NULL;
304 char *interface_str = NULL;
305 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
306 char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 };
307 int ret = BLUETOOTH_ERROR_INTERNAL;
309 BT_CHECK_PARAMETER(address, return);
310 BT_CHECK_PARAMETER(service_uuid, return);
311 BT_CHECK_PARAMETER(service, return);
312 BT_CHECK_ENABLED_ANY(return);
314 result = _bt_get_managed_objects();
318 _bt_convert_addr_type_to_string(device_address,
319 (unsigned char *)address->addr);
321 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
323 while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path,
325 if (object_path == NULL)
328 _bt_convert_device_path_to_address(object_path,
331 if (g_strcmp0(temp_address, device_address) != 0)
334 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
335 &interface_str, &svc_iter)) {
336 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
339 BT_DBG("Object Path: %s", object_path);
340 ret = bluetooth_gatt_get_service_property(object_path,
343 if (ret != BLUETOOTH_ERROR_NONE) {
344 BT_ERR("Get service property failed(0x%08x)", ret);
346 if (service->primary == TRUE &&
347 g_strstr_len(service->uuid, -1,
349 ret = BLUETOOTH_ERROR_NONE;
353 bluetooth_gatt_free_service_property(service);
358 g_variant_iter_free(iter);
359 g_variant_unref(result);
364 static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy,
365 GAsyncResult *res, gpointer user_data)
368 GVariant *char_value;
369 GVariantIter *char_iter;
370 GPtrArray *gp_array = NULL;
371 bt_gatt_discovered_char_t svc_char = { 0, };
373 GError *error = NULL;
374 bt_user_info_t *user_info;
378 user_info = _bt_get_user_data(BT_COMMON);
379 svc_char.service_handle = user_data;
381 value = g_dbus_proxy_call_finish(proxy, res, &error);
385 BT_ERR("Get service characteristics failed\n errCode[%x],"
386 "message[%s]\n", error->code, error->message);
387 g_clear_error(&error);
389 BT_ERR("Get service characteristics failed\n");
392 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
393 BLUETOOTH_ERROR_INTERNAL, NULL,
394 user_info->cb, user_info->user_data);
396 g_free(svc_char.service_handle);
397 g_object_unref(proxy);
401 g_variant_get(value, "(v)", &char_value);
402 g_variant_get(char_value, "ao", &char_iter);
404 gp_array = g_ptr_array_new();
405 while(g_variant_iter_loop(char_iter, "&o", &char_handle));
406 g_ptr_array_add(gp_array, (gpointer)char_handle);
408 if (gp_array->len != 0) {
409 svc_char.handle_info.count = gp_array->len;
410 svc_char.handle_info.handle =
411 __get_string_array_from_gptr_array(gp_array);
413 g_ptr_array_free(gp_array, TRUE);
416 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
417 BLUETOOTH_ERROR_NONE, &svc_char,
418 user_info->cb, user_info->user_data);
421 g_strfreev(svc_char.handle_info.handle);
422 g_free(svc_char.service_handle);
423 g_variant_iter_free(char_iter);
424 g_object_unref(proxy);
427 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(
428 const char *service_handle)
430 GDBusProxy *properties_proxy = NULL;
431 GDBusConnection *g_conn;
432 GError *error = NULL;
437 BT_CHECK_PARAMETER(service_handle, return);
438 BT_CHECK_ENABLED_ANY(return);
440 g_conn = _bt_gdbus_get_system_gconn();
441 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
443 properties_proxy = g_dbus_proxy_new_sync(g_conn,
444 G_DBUS_PROXY_FLAGS_NONE, NULL,
447 BT_PROPERTIES_INTERFACE,
450 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
452 handle = g_strdup(service_handle);
453 g_dbus_proxy_call(properties_proxy,
455 g_variant_new("(ss)",
456 GATT_SERV_INTERFACE, "Characteristics"),
457 G_DBUS_CALL_FLAGS_NONE,
460 (GAsyncReadyCallback)__bluetooth_internal_get_char_cb,
464 return BLUETOOTH_ERROR_NONE;
468 static int __get_permission_flag(char *permission)
472 retv_if(permission == NULL, ret);
474 BT_DBG("permission = %s",permission);
476 if (!g_strcmp0(permission,"broadcast")) {
477 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
478 } else if (!g_strcmp0(permission,"read")) {
479 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
480 } else if (!g_strcmp0(permission,"write-without-response")) {
481 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
482 } else if (!g_strcmp0(permission,"write")) {
483 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
484 } else if (!g_strcmp0(permission,"notify")) {
485 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
486 } else if (!g_strcmp0(permission,"indicate")) {
487 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
488 } else if (!g_strcmp0(permission,"authenticated-signed-writes")) {
489 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
490 } else if (!g_strcmp0(permission,"reliable-write")) {
491 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
492 } else if (!g_strcmp0(permission,"writable-auxiliaries")) {
493 ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS;
499 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(
500 const char *char_handle, bt_gatt_char_property_t *characteristic)
502 GDBusProxy *properties_proxy = NULL;
503 GError *error = NULL;
504 GVariant *value = NULL;
505 GVariant *result = NULL;
506 GByteArray *gb_array = NULL;
507 GPtrArray *gp_array = NULL ;
508 GDBusConnection *g_conn;
512 char *char_desc_handle = NULL;
514 GVariantIter *property_iter;
515 GVariantIter *char_value_iter;
516 GVariantIter *char_perm_iter;
517 GVariantIter *char_desc_iter;
520 BT_CHECK_PARAMETER(char_handle, return);
521 BT_CHECK_PARAMETER(characteristic, return);
523 BT_CHECK_ENABLED_ANY(return);
525 g_conn = _bt_gdbus_get_system_gconn();
526 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
528 properties_proxy = g_dbus_proxy_new_sync(g_conn,
529 G_DBUS_PROXY_FLAGS_NONE, NULL,
532 BT_PROPERTIES_INTERFACE,
535 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
537 result = g_dbus_proxy_call_sync(properties_proxy,
539 g_variant_new("(s)", GATT_CHAR_INTERFACE),
540 G_DBUS_CALL_FLAGS_NONE,
547 BT_ERR("Fail to get properties (Error: %s)", error->message);
548 g_clear_error(&error);
550 BT_ERR("Fail to get properties");
551 g_object_unref(properties_proxy);
552 return BLUETOOTH_ERROR_INTERNAL;
555 g_variant_get(result, "(a{sv})", &property_iter);
557 memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
558 characteristic->handle = g_strdup(char_handle);
560 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
562 if (!g_strcmp0(key,"UUID")) {
563 characteristic->uuid = g_variant_dup_string(value,&len);
564 BT_DBG("UUID of the char = %s",characteristic->uuid);
565 } else if(!g_strcmp0(key, "Value")) {
566 gb_array = g_byte_array_new();
567 g_variant_get(value, "ay", &char_value_iter);
568 while(g_variant_iter_loop(char_value_iter, "y", &char_value)) {
569 BT_DBG("value of char = %d",char_value);
570 g_byte_array_append(gb_array, &char_value, 1);
572 if (gb_array->len != 0) {
573 characteristic->val = g_malloc0(gb_array->len *
574 sizeof(unsigned char));
575 memcpy(characteristic->val, gb_array->data, gb_array->len);
577 characteristic->val_len = gb_array->len;
578 g_byte_array_free(gb_array, TRUE);
579 } else if(!g_strcmp0(key, "Flags")) {
580 g_variant_get(value, "as", &char_perm_iter);
581 characteristic->permission = 0x00;
582 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
583 BT_DBG("permission = %s",permission);
584 characteristic->permission |= __get_permission_flag(permission);
585 BT_DBG("permission check = %d",characteristic->permission);
587 g_variant_iter_free(char_perm_iter);
588 } else if (!g_strcmp0(key, "Descriptors")) {
589 g_variant_get(value, "ao", &char_desc_iter);
590 gp_array = g_ptr_array_new();
591 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
592 g_ptr_array_add(gp_array, (gpointer)char_desc_handle);
594 if (gp_array->len != 0) {
595 characteristic->char_desc_handle.count = gp_array->len;
596 characteristic->char_desc_handle.handle =
597 __get_string_array_from_gptr_array(gp_array);
599 g_ptr_array_free(gp_array, TRUE);
603 g_variant_iter_free(property_iter);
604 g_variant_unref(result);
605 g_object_unref(properties_proxy);
608 return BLUETOOTH_ERROR_NONE;
611 void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy,
612 GAsyncResult *res, gpointer user_data)
615 GVariantIter *char_iter;
618 GError *error = NULL;
619 bt_user_info_t *user_info;
620 int ret = BLUETOOTH_ERROR_INTERNAL;
621 bt_gatt_char_property_t characteristic;
623 user_info = _bt_get_user_data(BT_COMMON);
625 value = g_dbus_proxy_call_finish(proxy, res, &error);
629 BT_ERR("Get service characteristics failed\n errCode[%x],"
630 "message[%s]\n", error->code, error->message);
631 g_clear_error(&error);
633 BT_ERR("Get service characteristics failed\n");
636 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
637 BLUETOOTH_ERROR_INTERNAL, NULL,
638 user_info->cb, user_info->user_data);
640 g_object_unref(proxy);
645 g_variant_get(value, "(ao)", &char_iter);
647 len = g_variant_get_size((GVariant *)char_iter);
649 for (i = 0; i < len; i++) {
650 g_variant_iter_loop(char_iter, "o", &char_handle);
653 ret = bluetooth_gatt_get_characteristics_property(char_handle,
656 if (ret != BLUETOOTH_ERROR_NONE) {
657 BT_ERR("Get characteristic property failed(0x%08x)", ret);
659 if (g_strstr_len(characteristic.uuid, -1, user_data)) {
660 ret = BLUETOOTH_ERROR_NONE;
664 bluetooth_gatt_free_char_property(&characteristic);
668 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
669 &characteristic, user_info->cb, user_info->user_data);
672 bluetooth_gatt_free_char_property(&characteristic);
673 g_variant_iter_free(char_iter);
677 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
678 const char *char_uuid)
680 GDBusProxy *properties_proxy = NULL;
681 GDBusConnection *g_conn;
682 GError *error = NULL;
685 BT_CHECK_PARAMETER(service_handle, return);
686 BT_CHECK_PARAMETER(char_uuid, return);
687 BT_CHECK_ENABLED_ANY(return);
689 g_conn = _bt_gdbus_get_system_gconn();
690 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
692 properties_proxy = g_dbus_proxy_new_sync(g_conn,
693 G_DBUS_PROXY_FLAGS_NONE, NULL,
696 BT_PROPERTIES_INTERFACE,
699 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
701 uuid = g_strdup(char_uuid);
702 g_dbus_proxy_call(properties_proxy,
704 g_variant_new("(ss)",
705 GATT_SERV_INTERFACE, "Characteristics"),
706 G_DBUS_CALL_FLAGS_NONE,
709 (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb,
712 return BLUETOOTH_ERROR_NONE;
715 BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property(
716 const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor)
718 GDBusProxy *properties_proxy = NULL;
719 GError *error = NULL;
720 GDBusConnection *g_conn;
721 GVariant *result = NULL;
722 GVariantIter *property_iter;
726 GVariant *value = NULL;
727 GByteArray *gb_array = NULL;
728 GVariantIter *desc_value_iter;
731 BT_CHECK_PARAMETER(descriptor_handle, return);
732 BT_CHECK_PARAMETER(descriptor, return);
734 BT_CHECK_ENABLED_ANY(return);
736 g_conn = _bt_gdbus_get_system_gconn();
737 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
739 properties_proxy = g_dbus_proxy_new_sync(g_conn,
740 G_DBUS_PROXY_FLAGS_NONE, NULL,
743 BT_PROPERTIES_INTERFACE,
746 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
748 result = g_dbus_proxy_call_sync(properties_proxy,
750 g_variant_new("(s)", GATT_DESC_INTERFACE),
751 G_DBUS_CALL_FLAGS_NONE,
758 BT_ERR("Fail to get properties (Error: %s)", error->message);
759 g_clear_error(&error);
761 BT_ERR("Fail to get properties");
762 g_object_unref(properties_proxy);
763 return BLUETOOTH_ERROR_INTERNAL;
766 g_variant_get(result, "(a{sv})", &property_iter);
768 memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t));
769 descriptor->handle = g_strdup(descriptor_handle);
771 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
773 if (!g_strcmp0(key,"UUID")) {
774 descriptor->uuid = g_variant_dup_string(value,&len);
775 BT_DBG("UUID of the char_desc = %s",descriptor->uuid);
776 } else if(!g_strcmp0(key, "Value")) {
777 gb_array = g_byte_array_new();
778 g_variant_get(value, "ay", &desc_value_iter);
779 while(g_variant_iter_loop(desc_value_iter, "y", &char_value)) {
780 BT_DBG("value of descriptor = %d",char_value);
781 g_byte_array_append(gb_array, &char_value, 1);
783 if (gb_array->len != 0) {
784 descriptor->val = g_malloc0(gb_array->len *
785 sizeof(unsigned char));
786 memcpy(descriptor->val, gb_array->data, gb_array->len);
788 descriptor->val_len = gb_array->len;
789 g_byte_array_free(gb_array, TRUE);
793 g_variant_iter_free(property_iter);
794 g_variant_unref(result);
795 g_object_unref(properties_proxy);
798 return BLUETOOTH_ERROR_NONE;
801 static void __bluetooth_internal_read_cb(GObject *source_object,
805 GError *error = NULL;
806 bt_user_info_t *user_info;
807 bt_gatt_char_value_t char_value = { 0, };
808 GDBusConnection *system_gconn = NULL;
810 GByteArray *gp_byte_array = NULL;
815 user_info = _bt_get_user_data(BT_COMMON);
817 system_gconn = _bt_gdbus_get_system_gconn();
818 value = g_dbus_connection_call_finish(system_gconn, res, &error);
821 BT_ERR("Error : %s \n", error->message);
822 g_clear_error(&error);
824 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
825 BLUETOOTH_ERROR_INTERNAL, NULL,
826 user_info->cb, user_info->user_data);
832 char_value.char_handle = user_data;
833 gp_byte_array = g_byte_array_new();
834 g_variant_get(value, "(ay)", &iter);
836 while (g_variant_iter_loop(iter, "y", &g_byte)) {
837 g_byte_array_append(gp_byte_array, &g_byte, 1);
840 if (gp_byte_array->len != 0) {
841 char_value.val_len = gp_byte_array->len;
842 char_value.char_value = gp_byte_array->data;
846 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
847 BLUETOOTH_ERROR_NONE, &char_value,
848 user_info->cb, user_info->user_data);
851 g_free(char_value.char_handle);
852 g_byte_array_free(gp_byte_array, TRUE);
853 g_variant_unref(value);
854 g_variant_iter_free(iter);
859 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
861 GDBusConnection *conn;
864 BT_CHECK_PARAMETER(characteristic, return);
865 BT_CHECK_ENABLED_ANY(return);
867 conn = _bt_gdbus_get_system_gconn();
868 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
870 handle = g_strdup(characteristic);
872 g_dbus_connection_call(conn,
878 G_VARIANT_TYPE("(ay)"),
879 G_DBUS_CALL_FLAGS_NONE,
882 (GAsyncReadyCallback)__bluetooth_internal_read_cb,
885 return BLUETOOTH_ERROR_NONE;
888 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(
889 const char *char_handle, const guint8 *value, int length)
892 GVariantBuilder *builder;
893 GError *error = NULL;
894 GDBusConnection *conn;
898 BT_CHECK_PARAMETER(char_handle, return);
899 BT_CHECK_PARAMETER(value, return);
900 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
901 BT_CHECK_ENABLED_ANY(return);
903 conn = _bt_gdbus_get_system_gconn();
904 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
906 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
908 for (i = 0; i < length; i++) {
909 g_variant_builder_add(builder, "y", value[i]);
912 val = g_variant_new("(ay)", builder);
914 g_dbus_connection_call_sync(conn,
921 G_DBUS_CALL_FLAGS_NONE,
925 BT_ERR("Set value Failed: %s", error->message);
926 g_clear_error(&error);
927 g_variant_builder_unref(builder);
928 return BLUETOOTH_ERROR_INTERNAL;
931 g_variant_builder_unref(builder);
934 return BLUETOOTH_ERROR_NONE;
937 static void __bluetooth_internal_write_cb(GObject *source_object,
942 GError *error = NULL;
943 bt_user_info_t *user_info;
944 GDBusConnection *system_gconn = NULL;
946 int result = BLUETOOTH_ERROR_NONE;
948 user_info = _bt_get_user_data(BT_COMMON);
950 system_gconn = _bt_gdbus_get_system_gconn();
951 value = g_dbus_connection_call_finish(system_gconn, res, &error);
954 BT_ERR("Error : %s \n", error->message);
955 g_clear_error(&error);
956 result = BLUETOOTH_ERROR_INTERNAL;
959 BT_DBG("result = %d", result);
960 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
962 user_info->cb, user_info->user_data);
966 g_variant_unref(value);
971 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_by_type(
972 const char *char_handle, const guint8 *value, int length, guint8 write_type)
975 GVariantBuilder *builder;
976 GDBusConnection *conn;
978 int ret = BLUETOOTH_ERROR_NONE;
980 BT_CHECK_PARAMETER(char_handle, return);
981 BT_CHECK_PARAMETER(value, return);
982 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
983 BT_CHECK_ENABLED_ANY(return);
985 conn = _bt_gdbus_get_system_gconn();
986 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
988 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
990 for (i = 0; i < length; i++) {
991 g_variant_builder_add(builder, "y", value[i]);
994 val = g_variant_new("ay", builder);
995 g_dbus_connection_call(conn,
1000 g_variant_new("(y@ay)", write_type, val),
1002 G_DBUS_CALL_FLAGS_NONE,
1004 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1007 g_variant_builder_unref(builder);
1011 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
1012 const char *char_handle, const guint8 *value, int length)
1015 GDBusConnection *conn;
1016 GVariantBuilder *builder;
1020 BT_CHECK_PARAMETER(char_handle, return);
1021 BT_CHECK_PARAMETER(value, return);
1022 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
1023 BT_CHECK_ENABLED_ANY(return);
1025 conn = _bt_gdbus_get_system_gconn();
1026 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1028 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1030 for (i = 0; i < length; i++) {
1031 g_variant_builder_add(builder, "y", value[i]);
1032 BT_DBG("value [] = %d", value[i]);
1035 val = g_variant_new("(ay)", builder);
1037 g_dbus_connection_call(conn,
1040 GATT_CHAR_INTERFACE,
1044 G_DBUS_CALL_FLAGS_NONE,
1046 (GAsyncReadyCallback)__bluetooth_internal_write_cb,
1049 g_variant_builder_unref(builder);
1052 return BLUETOOTH_ERROR_NONE;
1055 static int __bluetooth_gatt_descriptor_iter(const char *char_handle,
1056 bt_gatt_char_property_t *characteristic)
1059 GDBusProxy *properties_proxy = NULL;
1060 GError *error = NULL;
1061 GVariant *value = NULL;
1062 GVariant *result = NULL;
1063 GDBusConnection *g_conn;
1064 int i, ret = BLUETOOTH_ERROR_NONE;
1065 const char *uuid = NULL;
1067 GVariantIter *desc_value_iter, *property_iter;
1069 char_descriptor_type_t desc_type = TYPE_NONE;
1071 g_conn = _bt_gdbus_get_system_gconn();
1072 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1074 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1075 G_DBUS_PROXY_FLAGS_NONE, NULL,
1078 BT_PROPERTIES_INTERFACE,
1081 retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1083 result = g_dbus_proxy_call_sync(properties_proxy,
1085 g_variant_new("(s)", GATT_DESC_INTERFACE),
1086 G_DBUS_CALL_FLAGS_NONE,
1092 if (error != NULL) {
1093 BT_ERR("Fail to get properties (Error: %s)", error->message);
1094 g_clear_error(&error);
1096 BT_ERR("Fail to get properties");
1097 g_object_unref(properties_proxy);
1098 return BLUETOOTH_ERROR_INTERNAL;
1100 g_variant_get(result, "(a{sv})", &property_iter);
1101 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1102 if (!g_strcmp0(key,"UUID")) {
1103 uuid = g_variant_get_string(value, &len);
1104 if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) {
1105 BT_DBG("GATT_USER_DESC_UUID");
1106 desc_type = USER_DESC;
1107 } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) {
1108 BT_DBG("GATT_CHAR_FORMAT");
1109 desc_type = CHAR_FORMAT;
1110 } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) {
1111 BT_DBG("GATT_CHAR_CLIENT_CONF");
1112 desc_type = CLIENT_CONF;
1113 } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) {
1114 BT_DBG("GATT_CHAR_SERVER_CONF");
1115 desc_type = SERVER_CONF;
1117 BT_DBG("descriptor uuid = %s", uuid);
1119 } else if (!g_strcmp0(key, "Value")) {
1122 BT_DBG("Format descriptor");
1123 g_variant_get(value, "(yyqyq)",
1124 &(characteristic->format.format),
1125 &(characteristic->format.exponent),
1126 &(characteristic->format.unit),
1127 &(characteristic->format.name_space),
1128 &(characteristic->format.description));
1131 BT_DBG("User descriptor");
1132 g_variant_get(value, "ay", &desc_value_iter);
1133 len = g_variant_get_size((GVariant *)desc_value_iter);
1136 characteristic->description = (char *)g_malloc0(len + 1);
1137 if (!characteristic->description) {
1138 ret = BLUETOOTH_ERROR_OUT_OF_MEMORY;
1142 for (i = 0; i < len; i++) {
1143 g_variant_iter_loop(desc_value_iter, "y",
1144 &characteristic->description[i]);
1145 BT_DBG("description = %s", characteristic->description);
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();