2 * Bluetooth-frwk low energy
4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Girishashok Joshi <girish.joshi@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
25 #include <dbus/dbus.h>
26 #include <dbus/dbus-glib.h>
29 #include "bluetooth-api.h"
30 #include "bt-common.h"
31 #include "bt-internal-types.h"
34 #define BLUEZ_CHAR_INTERFACE "org.bluez.Characteristic"
36 #define GATT_OBJECT_PATH "/org/bluez/gatt_attrib"
40 } BluetoothGattService;
44 } BluetoothGattServiceClass;
51 GType bluetooth_gatt_service_get_type(void);
53 #define BLUETOOTH_GATT_TYPE_SERVICE (bluetooth_gatt_service_get_type())
55 #define BLUETOOTH_GATT_SERVICE(object) \
56 (G_TYPE_CHECK_INSTANCE_CAST((object), \
57 BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattService))
59 #define BLUETOOTH_GATT_SERVICE_CLASS(klass) \
60 (G_TYPE_CHECK_CLASS_CAST((klass), \
61 BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattServiceClass))
63 #define BLUETOOTH_GATT_IS_SERVICE(object) \
64 (G_TYPE_CHECK_INSTANCE_TYPE((object), BLUETOOTH_GATT_TYPE_SERVICE))
66 #define BLUETOOTH_GATT_IS_SERVICE_CLASS(klass) \
67 (G_TYPE_CHECK_CLASS_TYPE((klass), BLUETOOTH_GATT_TYPE_SERVICE))
69 #define BLUETOOTH_GATT_SERVICE_GET_CLASS(obj) \
70 (G_TYPE_INSTANCE_GET_CLASS((obj), \
71 BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattServiceClass))
73 G_DEFINE_TYPE(BluetoothGattService, bluetooth_gatt_service, G_TYPE_OBJECT)
75 static gboolean bluetooth_gatt_value_changed(BluetoothGattService *agent,
78 DBusGMethodInvocation *context);
80 #include "bt-gatt-glue.h"
82 static void bluetooth_gatt_service_init(BluetoothGattService *obj)
84 g_assert(obj != NULL);
87 static void bluetooth_gatt_service_finalize(GObject *obj)
89 G_OBJECT_CLASS(bluetooth_gatt_service_parent_class)->finalize(obj);
92 static void bluetooth_gatt_service_class_init(BluetoothGattServiceClass *klass)
94 GObjectClass *object_class = (GObjectClass *)klass;
96 g_assert(klass != NULL);
98 object_class->finalize = bluetooth_gatt_service_finalize;
100 dbus_g_object_type_install_info(BLUETOOTH_GATT_TYPE_SERVICE,
101 &dbus_glib_bluetooth_gatt_object_info);
104 static gboolean bluetooth_gatt_value_changed(BluetoothGattService *agent,
107 DBusGMethodInvocation *context)
109 bt_gatt_char_value_t char_val;
110 bt_user_info_t *user_info;
113 char_val.char_handle = obj_path;
114 char_val.char_value = &g_array_index(byte_array, guint8, 0);
115 char_val.val_len = byte_array->len;
116 BT_DBG("Byte array length = %d", char_val.val_len);
118 user_info = _bt_get_user_data(BT_COMMON);
121 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
122 BLUETOOTH_ERROR_NONE, &char_val,
123 user_info->cb, user_info->user_data);
131 static void __add_value_changed_method(DBusGConnection *conn)
133 static gboolean method_added = FALSE;
134 BluetoothGattService *bluetooth_gatt_obj = NULL;
137 BT_ERR("Method already added. \n");
143 bluetooth_gatt_obj = g_object_new(BLUETOOTH_GATT_TYPE_SERVICE, NULL);
145 dbus_g_connection_register_g_object(conn, GATT_OBJECT_PATH,
146 G_OBJECT(bluetooth_gatt_obj));
150 static char **__get_string_array_from_gptr_array(GPtrArray *gp)
152 gchar *gp_path = NULL;
159 path = g_malloc0((gp->len + 1) * sizeof(char *));
161 for (i = 0; i < gp->len; i++) {
162 gp_path = g_ptr_array_index(gp, i);
163 path[i] = g_strdup(gp_path);
164 BT_DBG("path[%d] : [%s]", i, path[i]);
170 static void __bluetooth_internal_get_char_cb(DBusGProxy *proxy,
171 DBusGProxyCall *call,
174 GError *error = NULL;
175 GPtrArray *gp_array = NULL;
176 bt_gatt_discovered_char_t svc_char = { 0, };
177 bt_user_info_t *user_info;
179 svc_char.service_handle = user_data;
181 user_info = _bt_get_user_data(BT_COMMON);
183 if (!dbus_g_proxy_end_call(proxy, call, &error,
184 dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
185 &gp_array, G_TYPE_INVALID)) {
186 BT_ERR("Error : %s \n", error->message);
190 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
191 BLUETOOTH_ERROR_NONE, &svc_char,
192 user_info->cb, user_info->user_data);
194 g_free(svc_char.service_handle);
195 g_object_unref(proxy);
199 if (NULL != gp_array) {
200 svc_char.handle_info.count = gp_array->len;
201 svc_char.handle_info.handle = __get_string_array_from_gptr_array(gp_array);
205 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
206 BLUETOOTH_ERROR_NONE, &svc_char,
207 user_info->cb, user_info->user_data);
210 g_ptr_array_free(gp_array, TRUE);
211 g_free(svc_char.service_handle);
212 g_free(svc_char.handle_info.handle);
213 g_object_unref(proxy);
216 static void __bluetooth_internal_read_cb(GObject *source_object,
220 GError *error = NULL;
221 bt_user_info_t *user_info;
222 bt_gatt_char_value_t rsp = { 0, };
223 GDBusConnection *system_gconn = NULL;
224 GVariant *return_data;
225 GByteArray *gp_byte_array = NULL;
229 user_info = _bt_get_user_data(BT_COMMON);
231 system_gconn = _bt_init_system_gdbus_conn();
232 return_data = g_dbus_connection_call_finish(system_gconn, res, &error);
235 BT_ERR("Error : %s \n", error->message);
237 g_variant_unref(return_data);
238 g_clear_error(&error);
242 gp_byte_array = g_byte_array_new();
243 g_variant_get(return_data, "(ay)", &iter);
245 while (g_variant_iter_loop(iter, "y", &g_byte)) {
246 g_byte_array_append(gp_byte_array, &g_byte, 1);
249 if (NULL != gp_byte_array) {
250 rsp.val_len = gp_byte_array->len;
251 rsp.char_value = gp_byte_array->data;
255 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR,
256 BLUETOOTH_ERROR_NONE, &rsp,
257 user_info->cb, user_info->user_data);
260 g_byte_array_free(gp_byte_array, TRUE);
261 g_variant_unref(return_data);
262 g_variant_iter_free(iter);
266 static void __bluetooth_internal_write_cb(GObject *source_object,
270 GError *error = NULL;
271 bt_user_info_t *user_info;
272 GDBusConnection *system_gconn = NULL;
273 GVariant *return_data;
274 int result = BLUETOOTH_ERROR_NONE;
276 BT_DBG("__bluetooth_internal_write_cb");
277 user_info = _bt_get_user_data(BT_COMMON);
279 system_gconn = _bt_init_system_gdbus_conn();
280 return_data = g_dbus_connection_call_finish(system_gconn, res, &error);
283 BT_ERR("Error : %s \n", error->message);
284 g_clear_error(&error);
285 result = BLUETOOTH_ERROR_INTERNAL;
288 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR,
290 user_info->cb, user_info->user_data);
292 BT_DBG("BP 0>>>>>>");
295 g_variant_unref(return_data);
300 static void __bluetooth_internal_get_char_desc_cb(GObject *source_object,
304 GError *error = NULL;
305 GByteArray *gp_byte_array = NULL;
306 bt_gatt_char_property_t svc_char_desc = { 0, };
307 bt_user_info_t *user_info;
308 GDBusConnection *system_gconn = NULL;
309 GVariant *return_data;
313 svc_char_desc.handle = user_data;
314 svc_char_desc.val_len = 0x00;
315 svc_char_desc.description = NULL;
317 user_info = _bt_get_user_data(BT_COMMON);
318 system_gconn = _bt_init_system_gdbus_conn();
319 return_data = g_dbus_connection_call_finish(system_gconn, res, &error);
320 BT_DBG("result data received..");
322 BT_ERR("Error : %s \n", error->message);
323 g_clear_error(&error);
324 g_free(svc_char_desc.handle);
327 gp_byte_array = g_byte_array_new();
328 g_variant_get(return_data, "(ay)", &iter);
331 if (g_variant_iter_loop(iter, "y", &g_byte))
332 svc_char_desc.format.format = g_byte;
335 while (g_variant_iter_loop(iter, "y", &g_byte)) {
336 g_byte_array_append(gp_byte_array, &g_byte, 1);
339 if (NULL != gp_byte_array) {
340 svc_char_desc.val_len = gp_byte_array->len;
341 svc_char_desc.description = (char *)gp_byte_array->data;
345 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED,
346 BLUETOOTH_ERROR_NONE, &svc_char_desc,
347 user_info->cb, user_info->user_data);
350 g_byte_array_free(gp_byte_array, TRUE);
351 g_free(svc_char_desc.handle);
352 g_variant_unref(return_data);
353 g_variant_iter_free(iter);
356 static void __free_char_req(char_pty_req_t *char_req)
358 g_free(char_req->char_uuid);
359 g_strfreev(char_req->handle);
363 static gboolean __filter_chars_with_uuid(gpointer data)
366 bt_gatt_char_property_t *char_pty;
367 char_pty_req_t *char_req = data;
368 bt_user_info_t *user_info;
371 user_info = _bt_get_user_data(BT_COMMON);
372 if (user_info->cb == NULL) {
373 __free_char_req(char_req);
377 char_pty = g_new0(bt_gatt_char_property_t, 1);
379 while (char_req->handle[i] != NULL) {
380 BT_DBG("char_pty[%d] = %s", i, char_req->handle[i]);
381 ret = bluetooth_gatt_get_characteristics_property(char_req->handle[i],
383 if (ret != BLUETOOTH_ERROR_NONE) {
384 BT_ERR("get char property failed");
388 if (char_pty->uuid && g_strstr_len(char_pty->uuid, -1,
389 char_req->char_uuid) != NULL) {
390 BT_DBG("Requested Char recieved");
391 ret = BLUETOOTH_ERROR_NONE;
395 bluetooth_gatt_free_char_property(char_pty);
401 if (char_req->handle[i] == NULL)
402 ret = BLUETOOTH_ERROR_NOT_FOUND;
404 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret,
405 char_pty, user_info->cb, user_info->user_data);
408 __free_char_req(char_req);
413 static void __disc_char_from_uuid_cb(DBusGProxy *proxy,
414 DBusGProxyCall *call,
417 GError *error = NULL;
418 GPtrArray *gp_array = NULL;
419 bt_user_info_t *user_info;
420 char_pty_req_t *char_req = user_data;
422 user_info = _bt_get_user_data(BT_COMMON);
423 if (!user_info->cb) {
424 __free_char_req(char_req);
428 if (!dbus_g_proxy_end_call(proxy, call, &error,
429 dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
430 &gp_array, G_TYPE_INVALID)) {
431 BT_ERR("Error : %s \n", error->message);
434 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
435 BLUETOOTH_ERROR_INTERNAL, NULL,
436 user_info->cb, user_info->user_data);
438 __free_char_req(char_req);
439 g_object_unref(proxy);
443 if (gp_array == NULL) {
444 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID,
445 BLUETOOTH_ERROR_NOT_FOUND, NULL,
446 user_info->cb, user_info->user_data);
448 __free_char_req(char_req);
449 g_object_unref(proxy);
454 char_req->handle = __get_string_array_from_gptr_array(gp_array);
456 __filter_chars_with_uuid(char_req);
458 g_ptr_array_free(gp_array, TRUE);
459 g_object_unref(proxy);
463 static int __discover_char_from_uuid(const char *service_handle,
464 const char *char_uuid){
465 DBusGProxy *service_proxy = NULL;
466 DBusGConnection *conn;
467 char_pty_req_t *char_req;
469 conn = _bt_get_system_gconn();
470 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
472 service_proxy = dbus_g_proxy_new_for_name(conn,
473 BT_BLUEZ_NAME, service_handle,
474 BLUEZ_CHAR_INTERFACE);
475 retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
477 char_req = g_new0(char_pty_req_t, 1);
479 char_req->char_uuid = g_strdup(char_uuid);
480 BT_DBG("Char uuid %s ", char_uuid);
482 if (!dbus_g_proxy_begin_call(service_proxy, "DiscoverCharacteristics",
483 (DBusGProxyCallNotify)__disc_char_from_uuid_cb,
484 char_req, NULL, G_TYPE_INVALID)) {
485 __free_char_req(char_req);
486 g_object_unref(service_proxy);
487 return BLUETOOTH_ERROR_INTERNAL;
490 return BLUETOOTH_ERROR_NONE;
493 BT_EXPORT_API int bluetooth_gatt_free_primary_services(bt_gatt_handle_info_t *prim_svc)
497 BT_CHECK_PARAMETER(prim_svc, return);
499 g_strfreev(prim_svc->handle);
501 memset(prim_svc, 0, sizeof(bt_gatt_handle_info_t));
504 return BLUETOOTH_ERROR_NONE;
507 BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
511 BT_CHECK_PARAMETER(svc_pty, return);
513 g_free(svc_pty->uuid);
514 g_free(svc_pty->handle);
515 g_strfreev(svc_pty->handle_info.handle);
517 memset(svc_pty, 0, sizeof(bt_gatt_service_property_t));
520 return BLUETOOTH_ERROR_NONE;
523 BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
527 BT_CHECK_PARAMETER(char_pty, return);
529 g_free(char_pty->uuid);
530 g_free(char_pty->name);
531 g_free(char_pty->description);
532 g_free(char_pty->val);
533 g_free(char_pty->handle);
535 memset(char_pty, 0, sizeof(bt_gatt_char_property_t));
538 return BLUETOOTH_ERROR_NONE;
541 BT_EXPORT_API int bluetooth_gatt_get_primary_services(const bluetooth_device_address_t *address,
542 bt_gatt_handle_info_t *prim_svc)
544 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
545 gchar *device_path = NULL;
546 GError *error = NULL;
550 GDBusConnection *conn;
551 GVariant *value = NULL;
554 GPtrArray *gp_array = NULL;
555 int ret = BLUETOOTH_ERROR_INTERNAL;
559 BT_CHECK_PARAMETER(address, return);
560 BT_CHECK_PARAMETER(prim_svc, return);
562 BT_CHECK_ENABLED(return);
564 /* About org.tizen.device1 interface, dbus SMACK is not working. So use bt-service's
565 privilege checking logic */
566 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_GET_PRIMARY_SERVICES)
567 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
568 BT_ERR("Don't have a privilege to use this API");
569 return BLUETOOTH_ERROR_PERMISSION_DEINED;
572 _bt_convert_addr_type_to_string(device_address,
573 (unsigned char *)address->addr);
575 BT_INFO("bluetooth address [%s]\n", device_address);
577 device_path = _bt_get_device_object_path(device_address);
579 retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL);
581 conn = _bt_init_system_gdbus_conn();
582 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
584 result = g_dbus_connection_call_sync(conn,
590 G_VARIANT_TYPE ("(ao)"),
591 G_DBUS_CALL_FLAGS_NONE,
596 BT_ERR("GetPrimServices Call Error %s[%s]", error->message,
598 g_clear_error(&error);
599 return BLUETOOTH_ERROR_INTERNAL;
603 gp_array = g_ptr_array_new();
604 g_variant_get(result, "(ao)", &iter);
605 while ((value = g_variant_iter_next_value(iter))) {
606 g_variant_get(value, "o", &g_str);
607 g_ptr_array_add(gp_array, (gpointer)g_str);
610 if (gp_array == NULL) {
611 BT_ERR("gp_array == NULL");
615 prim_svc->count = gp_array->len;
616 prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
618 g_ptr_array_free(gp_array, TRUE);
619 g_variant_iter_free(iter);
620 g_variant_unref(result);
622 ret = BLUETOOTH_ERROR_NONE;
628 BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(const char *service_handle)
630 DBusGProxy *service_proxy = NULL;
632 DBusGConnection *conn;
634 BT_CHECK_PARAMETER(service_handle, return);
636 BT_CHECK_ENABLED(return);
638 /* Because this API is async call, so can't use dbus SMACK */
639 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_DISCOVER_CHARACTERISTICS)
640 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
641 BT_ERR("Don't have a privilege to use this API");
642 return BLUETOOTH_ERROR_PERMISSION_DEINED;
645 conn = _bt_get_system_gconn();
646 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
648 service_proxy = dbus_g_proxy_new_for_name(conn,
649 BT_BLUEZ_NAME, service_handle,
650 BLUEZ_CHAR_INTERFACE);
652 retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
654 handle = g_strdup(service_handle);
655 BT_DBG("Requested characteristic handle:%s \n ", handle);
657 if (!dbus_g_proxy_begin_call(service_proxy, "DiscoverCharacteristics",
658 (DBusGProxyCallNotify)__bluetooth_internal_get_char_cb,
659 handle, NULL, G_TYPE_INVALID)) {
661 g_object_unref(service_proxy);
662 return BLUETOOTH_ERROR_INTERNAL;
665 return BLUETOOTH_ERROR_NONE;
668 BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
669 bt_gatt_service_property_t *service)
671 DBusGProxy *service_proxy = NULL;
672 GHashTable *hash = NULL;
673 GError *error = NULL;
674 GValue *value = NULL;
675 GPtrArray *gp_array = NULL ;
676 DBusGConnection *conn;
677 int ret = BLUETOOTH_ERROR_NONE;
679 BT_CHECK_PARAMETER(service_handle, return);
680 BT_CHECK_PARAMETER(service, return);
682 BT_CHECK_ENABLED(return);
684 conn = _bt_get_system_gconn();
685 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
687 service_proxy = dbus_g_proxy_new_for_name(conn,
688 BT_BLUEZ_NAME, service_handle,
689 BLUEZ_CHAR_INTERFACE);
691 retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
693 dbus_g_proxy_call(service_proxy, "GetProperties", &error, G_TYPE_INVALID,
694 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
695 &hash, G_TYPE_INVALID);
697 g_object_unref(service_proxy);
700 BT_ERR("GetProperties Call Error %s\n", error->message);
702 if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG))
703 ret = BLUETOOTH_ERROR_ACCESS_DENIED;
705 ret = BLUETOOTH_ERROR_INTERNAL;
711 retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
713 memset(service, 0, sizeof(bt_gatt_service_property_t));
715 value = g_hash_table_lookup(hash, "UUID");
716 service->uuid = value ? g_value_dup_string(value) : NULL;
718 BT_DBG("svc_pty.uuid = [%s] \n", service->uuid);
721 value = g_hash_table_lookup(hash, "Characteristics");
722 gp_array = value ? g_value_get_boxed(value) : NULL;
724 service->handle_info.count = gp_array->len;
725 service->handle_info.handle = __get_string_array_from_gptr_array(gp_array);
728 service->handle = g_strdup(service_handle);
729 g_hash_table_destroy(hash);
730 return BLUETOOTH_ERROR_NONE;
733 BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *service_handle)
735 DBusGProxy *watch_proxy = NULL;
736 GError *error = NULL;
737 DBusGConnection *conn;
738 int ret = BLUETOOTH_ERROR_NONE;
740 BT_CHECK_PARAMETER(service_handle, return);
742 BT_CHECK_ENABLED(return);
744 BT_DBG("Entered service handle:%s \n ", service_handle);
746 conn = _bt_get_system_gconn();
747 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
749 watch_proxy = dbus_g_proxy_new_for_name(conn,
750 BT_BLUEZ_NAME, service_handle,
751 BLUEZ_CHAR_INTERFACE);
753 retv_if(watch_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
755 __add_value_changed_method(conn);
757 dbus_g_proxy_call(watch_proxy, "RegisterCharacteristicsWatcher", &error,
758 DBUS_TYPE_G_OBJECT_PATH, GATT_OBJECT_PATH,
759 G_TYPE_INVALID, G_TYPE_INVALID);
761 BT_ERR("Method call Fail: %s", error->message);
763 if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG))
764 ret = BLUETOOTH_ERROR_ACCESS_DENIED;
766 ret = BLUETOOTH_ERROR_INTERNAL;
769 g_object_unref(watch_proxy);
773 g_object_unref(watch_proxy);
775 return BLUETOOTH_ERROR_NONE;
778 BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *service_handle)
780 DBusGProxy *watch_proxy = NULL;
781 GError *error = NULL;
782 DBusGConnection *conn;
783 int ret = BLUETOOTH_ERROR_NONE;
785 BT_CHECK_PARAMETER(service_handle, return);
787 BT_CHECK_ENABLED(return);
789 conn = _bt_get_system_gconn();
790 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
792 watch_proxy = dbus_g_proxy_new_for_name(conn,
793 BT_BLUEZ_NAME, service_handle,
794 BLUEZ_CHAR_INTERFACE);
796 retv_if(watch_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
798 dbus_g_proxy_call(watch_proxy, "UnregisterCharacteristicsWatcher", &error,
799 DBUS_TYPE_G_OBJECT_PATH, GATT_OBJECT_PATH,
800 G_TYPE_INVALID, G_TYPE_INVALID);
802 BT_ERR("Method call Fail: %s", error->message);
804 if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG))
805 ret = BLUETOOTH_ERROR_ACCESS_DENIED;
807 ret = BLUETOOTH_ERROR_INTERNAL;
810 g_object_unref(watch_proxy);
814 g_object_unref(watch_proxy);
816 return BLUETOOTH_ERROR_NONE;
819 BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(const char *char_handle,
820 bt_gatt_char_property_t *characteristic)
822 DBusGProxy *characteristic_proxy = NULL;
823 GHashTable *hash = NULL;
824 GError *error = NULL;
825 GValue *value = NULL;
826 GByteArray *gb_array = NULL;
827 DBusGConnection *conn;
828 int ret = BLUETOOTH_ERROR_NONE;
830 BT_CHECK_PARAMETER(char_handle, return);
831 BT_CHECK_PARAMETER(characteristic, return);
833 BT_CHECK_ENABLED(return);
835 conn = _bt_get_system_gconn();
836 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
838 characteristic_proxy = dbus_g_proxy_new_for_name(conn,
839 BT_BLUEZ_NAME, char_handle,
840 BLUEZ_CHAR_INTERFACE);
842 retv_if(characteristic_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
844 dbus_g_proxy_call(characteristic_proxy, "GetProperties", &error, G_TYPE_INVALID,
845 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
846 &hash, G_TYPE_INVALID);
848 BT_ERR("GetProperties Call Error %s\n", error->message);
850 if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG))
851 ret = BLUETOOTH_ERROR_ACCESS_DENIED;
853 ret = BLUETOOTH_ERROR_INTERNAL;
856 g_object_unref(characteristic_proxy);
859 g_object_unref(characteristic_proxy);
861 retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
863 memset(characteristic, 0, sizeof(bt_gatt_char_property_t));
865 value = g_hash_table_lookup(hash, "UUID");
866 characteristic->uuid = value ? g_value_dup_string(value) : NULL;
867 if (characteristic->uuid) {
868 BT_DBG("characteristic->uuid = [%s] \n", characteristic->uuid);
871 value = g_hash_table_lookup(hash, "Name");
872 characteristic->name = value ? g_value_dup_string(value) : NULL;
873 if (characteristic->name) {
874 DBG_SECURE("characteristic->name = [%s] \n", characteristic->name);
877 value = g_hash_table_lookup(hash, "Description");
878 characteristic->description = value ? g_value_dup_string(value) : NULL;
879 if (characteristic->description) {
880 BT_DBG("characteristic->description = [%s] \n", characteristic->description);
883 value = g_hash_table_lookup(hash, "Value");
885 gb_array = value ? g_value_get_boxed(value) : NULL;
888 BT_DBG("gb_array->len = %d \n", gb_array->len);
889 characteristic->val_len = gb_array->len;
891 characteristic->val = g_malloc0(gb_array->len * sizeof(unsigned char));
892 memcpy(characteristic->val, gb_array->data, gb_array->len);
894 characteristic->val = NULL;
895 characteristic->val_len = 0;
898 characteristic->val = NULL;
899 characteristic->val_len = 0;
901 characteristic->handle = g_strdup(char_handle);
902 g_hash_table_destroy(hash);
903 return BLUETOOTH_ERROR_NONE;
906 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(const char *char_handle,
907 const guint8 *value, int length)
911 GVariantBuilder *builder;
912 GError *error = NULL;
913 DBusGConnection *conn;
915 int ret = BLUETOOTH_ERROR_NONE;
917 BT_CHECK_PARAMETER(char_handle, return);
918 BT_CHECK_PARAMETER(value, return);
919 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
921 BT_CHECK_ENABLED(return);
923 conn = _bt_get_system_gconn();
924 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
926 BT_DBG("Requested characteristic handle:%s \n ", char_handle);
928 builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
930 for (i = 0; i < length; i++) {
931 g_variant_builder_add(builder, "y", value[i]);
932 BT_DBG("value idx:%d, %d", i, value[i]);
935 val = g_variant_new("ay", builder);
937 handle = g_strdup(char_handle);
940 g_dbus_connection_call_sync(conn,
943 BLUEZ_CHAR_INTERFACE,
945 g_variant_new("(sv)",
948 G_DBUS_CALL_FLAGS_NONE,
954 BT_ERR("Set value Fail: %s", error->message);
956 if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG))
957 ret = BLUETOOTH_ERROR_ACCESS_DENIED;
959 ret = BLUETOOTH_ERROR_INTERNAL;
962 g_variant_builder_unref(builder);
967 g_variant_builder_unref(builder);
968 return BLUETOOTH_ERROR_NONE;
971 BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request(
972 const char *char_handle, const guint8 *value, int length)
975 GError *error = NULL;
976 GDBusConnection *conn;
978 GVariantBuilder *builder;
981 BT_CHECK_PARAMETER(char_handle, return);
982 BT_CHECK_PARAMETER(value, return);
983 retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM);
985 BT_CHECK_ENABLED(return);
987 /* Because this API is async call, so can't use dbus SMACK */
988 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_SET_PROPERTY_REQUEST)
989 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
990 BT_ERR("Don't have a privilege to use this API");
991 return BLUETOOTH_ERROR_PERMISSION_DEINED;
994 conn = _bt_init_system_gdbus_conn();
995 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
997 builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
999 for (i = 0; i < length; i++) {
1000 g_variant_builder_add(builder, "y", value[i]);
1003 val = g_variant_new("ay", builder);
1005 handle = g_strdup(char_handle);
1007 g_dbus_connection_call(conn,
1010 BLUEZ_CHAR_INTERFACE,
1011 "SetPropertyRequest",
1012 g_variant_new("(sv)",
1015 G_DBUS_CALL_FLAGS_NONE,
1018 (GAsyncReadyCallback)
1019 __bluetooth_internal_write_cb,
1023 BT_ERR("Set value Fail: %s", error->message);
1024 g_clear_error(&error);
1025 g_variant_builder_unref(builder);
1026 return BLUETOOTH_ERROR_INTERNAL;
1028 g_variant_builder_unref(builder);
1030 return BLUETOOTH_ERROR_NONE;
1033 BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address,
1034 const char *service_uuid,
1035 bt_gatt_service_property_t *service)
1039 bt_gatt_handle_info_t prim_svc;
1041 BT_CHECK_PARAMETER(address, return);
1042 BT_CHECK_PARAMETER(service_uuid, return);
1043 BT_CHECK_PARAMETER(service, return);
1045 BT_CHECK_ENABLED(return);
1047 ret = bluetooth_gatt_get_primary_services(address, &prim_svc);
1048 if (ret != BLUETOOTH_ERROR_NONE) {
1049 BT_ERR("Get primary service failed ");
1053 for (i = 0; i < prim_svc.count; i++) {
1055 BT_DBG("prim_svc [%d] = %s", i, prim_svc.handle[i]);
1057 ret = bluetooth_gatt_get_service_property(prim_svc.handle[i],
1059 if (ret != BLUETOOTH_ERROR_NONE) {
1060 BT_ERR("Get service property failed ");
1061 bluetooth_gatt_free_primary_services(&prim_svc);
1065 BT_DBG("Service uuid %s", service->uuid);
1067 if (g_strstr_len(service->uuid, -1, service_uuid)) {
1068 BT_INFO("Found requested service");
1069 ret = BLUETOOTH_ERROR_NONE;
1073 bluetooth_gatt_free_service_property(service);
1076 if (i == prim_svc.count)
1077 ret = BLUETOOTH_ERROR_NOT_FOUND;
1079 bluetooth_gatt_free_primary_services(&prim_svc);
1084 BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle,
1085 const char *char_uuid)
1087 char **char_handles;
1088 char_pty_req_t *char_pty;
1090 bt_gatt_service_property_t svc_pty;
1093 BT_CHECK_PARAMETER(service_handle, return);
1094 BT_CHECK_PARAMETER(char_uuid, return);
1096 BT_CHECK_ENABLED(return);
1098 ret = bluetooth_gatt_get_service_property(service_handle, &svc_pty);
1099 if (ret != BLUETOOTH_ERROR_NONE) {
1100 BT_ERR("Get primary service failed ");
1104 if (bluetooth_gatt_get_service_property(service_handle, &svc_pty) !=
1105 BLUETOOTH_ERROR_NONE) {
1106 BT_ERR("Invalid service");
1107 return BLUETOOTH_ERROR_NOT_FOUND;
1110 char_handles = svc_pty.handle_info.handle;
1112 if (char_handles == NULL)
1113 return __discover_char_from_uuid(svc_pty.handle, char_uuid);
1115 char_pty = g_new0(char_pty_req_t, 1);
1117 char_pty->handle = g_malloc0((svc_pty.handle_info.count + 1) *
1119 for (i = 0; i < svc_pty.handle_info.count; i++) {
1120 char_pty->handle[i] = char_handles[i];
1121 BT_DBG("char_path[%d] : [%s]", i, char_pty->handle[i]);
1123 char_pty->char_uuid = g_strdup(char_uuid);
1125 g_idle_add(__filter_chars_with_uuid, char_pty);
1127 return BLUETOOTH_ERROR_NONE;
1130 BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic)
1132 GDBusConnection *conn;
1135 BT_CHECK_PARAMETER(characteristic, return);
1136 BT_CHECK_ENABLED(return);
1138 /* Because this API is async call, so can't use dbus SMACK */
1139 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC)
1140 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1141 BT_ERR("Don't have a privilege to use this API");
1142 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1145 conn = _bt_init_system_gdbus_conn();
1146 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1148 handle = g_strdup(characteristic);
1149 g_dbus_connection_call(conn,
1152 BLUEZ_CHAR_INTERFACE,
1153 "ReadCharacteristic",
1155 G_VARIANT_TYPE("(ay)"),
1156 G_DBUS_CALL_FLAGS_NONE,
1159 (GAsyncReadyCallback)
1160 __bluetooth_internal_read_cb,
1162 return BLUETOOTH_ERROR_NONE;
1165 BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor
1166 (const char *characteristic_handle)
1169 GDBusConnection *conn;
1171 BT_CHECK_PARAMETER(characteristic_handle, return);
1173 BT_CHECK_ENABLED(return);
1175 /* Because this API is async call, so can't use dbus SMACK */
1176 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_DISCOVER_CHARACTERISTICS_DESCRIPTOR)
1177 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1178 BT_ERR("Don't have a privilege to use this API");
1179 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1182 conn = _bt_init_system_gdbus_conn();
1183 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1184 handle = g_strdup(characteristic_handle);
1185 g_dbus_connection_call(conn,
1187 characteristic_handle,
1188 BLUEZ_CHAR_INTERFACE,
1189 "DiscoverCharacteristicsDescriptor",
1191 G_VARIANT_TYPE("(ay)"),
1192 G_DBUS_CALL_FLAGS_NONE,
1195 (GAsyncReadyCallback)
1196 __bluetooth_internal_get_char_desc_cb,
1199 return BLUETOOTH_ERROR_NONE;