2 * Copyright (c) 2014 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>
26 #include "bt-common.h"
27 #include "bt-internal-types.h"
29 #define NUMBER_OF_FLAGS 10
31 GDBusConnection *g_conn;
34 static gboolean new_service = FALSE;
35 static gboolean new_char = FALSE;
36 static int serv_id = 1;
37 static int register_pending_cnt = 0;
38 static bool is_server_started = false;
40 GCancellable *register_cancel;
42 /* Introspection data for the service we are exporting */
43 static const gchar service_introspection_xml[] =
45 " <interface name='org.freedesktop.DBus.Properties'>"
46 " <property type='s' name='UUID' access='read'>"
48 " <property type='b' name='primary' access='read'>"
50 " <property type='o' name='Device' access='read'>"
52 " <property type='ao' name='Characteristics' access='read'>"
54 " <property type='s' name='Includes' access='read'>"
59 /* Introspection data for the characteristics we are exporting */
60 static const gchar characteristics_introspection_xml[] =
62 " <interface name='org.bluez.GattCharacteristic1'>"
63 " <method name='ReadValue'>"
64 " <arg type='s' name='address' direction='in'/>"
65 " <arg type='u' name='id' direction='in'/>"
66 " <arg type='q' name='offset' direction='in'/>"
67 " <arg type='ay' name='Value' direction='out'/>"
69 " <method name='WriteValue'>"
70 " <arg type='s' name='address' direction='in'/>"
71 " <arg type='u' name='id' direction='in'/>"
72 " <arg type='q' name='offset' direction='in'/>"
73 " <arg type='b' name='response_needed' direction='in'/>"
74 " <arg type='ay' name='value' direction='in'/>"
76 " <method name='StartNotify'>"
78 " <method name='StopNotify'>"
80 " <method name='IndicateConfirm'>"
81 " <arg type='s' name='address' direction='in'/>"
82 " <arg type='b' name='complete' direction='in'/>"
85 " <interface name='org.freedesktop.DBus.Properties'>"
86 " <property type='s' name='UUID' access='read'>"
88 " <property type='o' name='Service' access='read'>"
90 " <property type='ay' name='Value' access='readwrite'>"
92 " <property type='b' name='Notifying' access='read'>"
94 " <property type='as' name='Flags' access='read'>"
96 " <property type='s' name='Unicast' access='read'>"
98 " <property type='ao' name='Descriptors' access='read'>"
103 /* Introspection data for the descriptor we are exporting */
104 static const gchar descriptor_introspection_xml[] =
106 " <interface name='org.bluez.GattDescriptor1'>"
107 " <method name='ReadValue'>"
108 " <arg type='s' name='address' direction='in'/>"
109 " <arg type='u' name='id' direction='in'/>"
110 " <arg type='q' name='offset' direction='in'/>"
111 " <arg type='ay' name='Value' direction='out'/>"
113 " <method name='WriteValue'>"
114 " <arg type='s' name='address' direction='in'/>"
115 " <arg type='u' name='id' direction='in'/>"
116 " <arg type='q' name='offset' direction='in'/>"
117 " <arg type='b' name='response_needed' direction='in'/>"
118 " <arg type='ay' name='value' direction='in'/>"
121 " <interface name='org.freedesktop.DBus.Properties'>"
122 " <property type='s' name='UUID' access='read'>"
124 " <property type='o' name='Characteristic' access='read'>"
126 " <property type='ay' name='Value' access='read'>"
128 " <property type='as' name='Flags' access='read'>"
133 static const gchar manager_introspection_xml[] =
135 " <interface name='org.freedesktop.DBus.ObjectManager'>"
136 " <method name='GetManagedObjects'>"
137 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
142 struct gatt_service_info {
149 gboolean is_svc_registered;
150 gboolean is_svc_primary;
153 struct gatt_char_info {
158 gchar *char_flags[NUMBER_OF_FLAGS];
164 struct gatt_desc_info {
169 gchar *desc_flags[NUMBER_OF_FLAGS];
174 struct gatt_req_info {
179 GDBusMethodInvocation *context;
182 static GSList *gatt_services = NULL;
183 static GSList *gatt_requests = NULL;
184 static gchar *app_path = NULL;
186 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
187 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
189 #define GATT_SERV_OBJECT_PATH "/service"
191 #define GATT_MNGR_INTERFACE "org.bluez.GattManager1"
192 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
193 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
194 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
196 #ifdef TIZEN_FEATURE_BT_HPS
197 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
198 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
199 #define PROPERTIES_CHANGED "PropertiesChanged"
200 #define BT_HPS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
203 #ifdef TIZEN_FEATURE_BT_OTP
204 #define BT_OTP_OBJECT_PATH "/org/projectx/otp"
205 #define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
206 #define PROPERTIES_CHANGED "PropertiesChanged"
207 #define BT_OTP_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
210 static GDBusProxy *manager_gproxy = NULL;
212 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
213 const char *service_path, const char *char_path);
214 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
215 const char *serv_path, const char *char_path,
216 const char *desc_path);
218 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
220 static void __bt_gatt_close_gdbus_connection(void)
226 ret_if(g_conn == NULL);
228 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
229 BT_ERR("Fail to flush the connection: %s", err->message);
234 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
236 BT_ERR("Fail to close the dbus connection: %s", err->message);
241 g_object_unref(g_conn);
248 #ifdef TIZEN_FEATURE_BT_HPS
249 static int __bt_send_event_to_hps(int event, GVariant *var)
251 GError *error = NULL;
252 GVariant *parameters;
253 GDBusMessage *msg = NULL;
257 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
259 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
260 GVariantBuilder *inner_builder;
261 GVariantBuilder *invalidated_builder;
263 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
264 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
266 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
268 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
270 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
271 g_variant_builder_unref(invalidated_builder);
272 g_variant_builder_unref(inner_builder);
273 } else if (BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
274 GVariantBuilder *inner_builder;
275 GVariantBuilder *invalidated_builder;
277 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
278 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
280 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
282 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
284 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
285 g_variant_builder_unref(invalidated_builder);
286 g_variant_builder_unref(inner_builder);
289 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
290 g_dbus_message_set_body(msg, parameters);
291 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
293 BT_ERR("D-Bus API failure: errCode[%x], \
295 error->code, error->message);
296 g_clear_error(&error);
298 return BLUETOOTH_ERROR_INTERNAL;
300 return BLUETOOTH_ERROR_NONE;
304 #ifdef TIZEN_FEATURE_BT_OTP
305 static int __bt_send_event_to_otp(int event, GVariant *var)
307 GError *error = NULL;
308 GVariant *parameters = NULL;
309 GDBusMessage *msg = NULL;
313 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
315 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
316 GVariantBuilder *inner_builder;
317 GVariantBuilder *invalidated_builder;
319 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
320 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
322 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
324 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
326 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
327 g_variant_builder_unref(invalidated_builder);
328 g_variant_builder_unref(inner_builder);
329 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
330 GVariantBuilder *inner_builder;
331 GVariantBuilder *invalidated_builder;
333 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
334 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
336 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
338 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
340 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
341 g_variant_builder_unref(invalidated_builder);
342 g_variant_builder_unref(inner_builder);
343 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
344 GVariantBuilder *inner_builder;
345 GVariantBuilder *invalidated_builder;
347 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
348 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
350 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
352 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
354 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
355 g_variant_builder_unref(invalidated_builder);
356 g_variant_builder_unref(inner_builder);
359 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
360 g_dbus_message_set_body(msg, parameters);
361 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
363 BT_ERR("D-Bus API failure: errCode[%x], \
365 error->code, error->message);
366 g_clear_error(&error);
368 return BLUETOOTH_ERROR_INTERNAL;
370 return BLUETOOTH_ERROR_NONE;
374 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
376 const gchar *object_path,
377 const gchar *interface_name,
378 const gchar *method_name,
379 GVariant *parameters,
380 GDBusMethodInvocation *invocation,
387 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
388 BT_DBG("Getting values for service, chars and descriptors");
390 GVariantBuilder *builder;
391 GVariantBuilder *inner_builder1 = NULL;
392 GVariant *svc_char = NULL;
395 builder = g_variant_builder_new(
396 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
398 /* Prepare inner builder for GattService1 interface */
400 len = g_slist_length(gatt_services);
402 for (i = 0; i <= len; i++) {
403 GVariantBuilder *svc_builder = NULL;
404 GVariantBuilder *inner_builder = NULL;
406 if (register_pending_cnt > 1)
407 l1 = g_slist_nth(gatt_services, len - register_pending_cnt);
409 l1 = g_slist_last(gatt_services);
411 register_pending_cnt--;
414 BT_ERR("gatt service list is NULL");
415 g_dbus_method_invocation_return_value(invocation, NULL);
419 struct gatt_service_info *serv_info = l1->data;
420 if (serv_info == NULL) {
421 BT_ERR("service info value is NULL");
422 g_dbus_method_invocation_return_value(invocation, NULL);
426 /* Prepare inner builder for GattService1 interface */
427 BT_DBG("Creating builder for service");
428 svc_builder = g_variant_builder_new(
429 G_VARIANT_TYPE("a{sa{sv}}"));
430 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
432 g_variant_builder_add(inner_builder, "{sv}", "UUID",
433 g_variant_new_string(serv_info->service_uuid));
435 g_variant_builder_add(inner_builder, "{sv}", "Primary",
436 g_variant_new_boolean(serv_info->is_svc_primary));
439 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
440 BT_DBG("Adding Charatarisitcs list");
441 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
442 struct gatt_char_info *char_info = l4->data;
443 g_variant_builder_add(inner_builder1, "o",
444 char_info->char_path);
445 BT_DBG("%s", char_info->char_path);
448 svc_char = g_variant_new("ao", inner_builder1);
449 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
452 g_variant_builder_add(svc_builder, "{sa{sv}}",
456 g_variant_builder_add(builder, "{oa{sa{sv}}}",
457 serv_info->serv_path,
460 g_variant_builder_unref(inner_builder1);
462 /* Prepare inner builder for GattCharacteristic1 interface */
464 GSList *l2 = serv_info->char_data;
465 BT_DBG("Creating builder for characteristics \n");
468 BT_DBG("characteristic data is NULL");
470 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
472 GVariantBuilder *char_builder = NULL;
473 GVariantBuilder *inner_builder = NULL;
474 GVariantBuilder *builder1 = NULL;
475 GVariantBuilder *builder2 = NULL;
476 GVariantBuilder *builder3 = NULL;
477 GVariant *char_val = NULL;
478 GVariant *flags_val = NULL;
479 GVariant *char_desc = NULL;
480 char *unicast = NULL;
481 gboolean notify = FALSE;
484 char_builder = g_variant_builder_new(
487 inner_builder = g_variant_builder_new(
491 struct gatt_char_info *char_info = l2->data;
492 if (char_info == NULL) {
493 BT_ERR("char_info is NULL");
498 g_variant_builder_add(inner_builder, "{sv}", "UUID",
499 g_variant_new_string(char_info->char_uuid));
501 g_variant_builder_add(inner_builder, "{sv}", "Service",
502 g_variant_new("o", serv_info->serv_path));
504 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
506 if (char_info->char_value != NULL) {
507 for (i = 0; i < char_info->value_length; i++) {
508 g_variant_builder_add(builder1, "y",
509 char_info->char_value[i]);
511 char_val = g_variant_new("ay", builder1);
512 g_variant_builder_add(inner_builder, "{sv}",
516 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
518 for (i = 0; i < char_info->flags_length; i++) {
519 g_variant_builder_add(builder2, "s",
520 char_info->char_flags[i]);
523 flags_val = g_variant_new("as", builder2);
524 g_variant_builder_add(inner_builder, "{sv}", "Flags",
528 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
529 g_variant_new("b", notify));
532 unicast = g_strdup("00:00:00:00:00:00");
533 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
534 g_variant_new("s", unicast));
537 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
538 BT_DBG("Adding Descriptors list");
540 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
541 struct gatt_desc_info *desc_info = l4->data;
542 g_variant_builder_add(builder3, "o",
543 desc_info->desc_path);
544 BT_DBG("%s", desc_info->desc_path);
547 char_desc = g_variant_new("ao", builder3);
548 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
551 g_variant_builder_add(char_builder, "{sa{sv}}",
552 GATT_CHAR_INTERFACE , inner_builder);
553 g_variant_builder_add(builder, "{oa{sa{sv}}}",
554 char_info->char_path, char_builder);
556 /*Prepare inner builder for GattDescriptor1 interface*/
558 GSList *l3 = char_info->desc_data;
561 BT_DBG("descriptor data is NULL");
563 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
565 BT_DBG("Creating builder for descriptor \n");
567 GVariantBuilder *desc_builder = NULL;
568 GVariantBuilder *inner_builder = NULL;
569 GVariantBuilder *builder1 = NULL;
570 GVariantBuilder *builder2 = NULL;
571 GVariant *desc_val = NULL;
573 desc_builder = g_variant_builder_new(
576 inner_builder = g_variant_builder_new(
580 struct gatt_desc_info *desc_info = l3->data;
581 if (desc_info == NULL) {
582 BT_ERR("desc_info is NULL");
587 g_variant_builder_add(inner_builder,
589 g_variant_new_string(
590 desc_info->desc_uuid));
593 g_variant_builder_add(inner_builder, "{sv}",
596 char_info->char_path));
599 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
601 if (desc_info->desc_value != NULL) {
602 for (i = 0; i < desc_info->value_length; i++) {
603 g_variant_builder_add(builder1, "y",
604 desc_info->desc_value[i]);
606 desc_val = g_variant_new("ay", builder1);
607 g_variant_builder_add(inner_builder, "{sv}",
612 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
614 for (i = 0; i < desc_info->flags_length; i++) {
615 g_variant_builder_add(builder2, "s",
616 desc_info->desc_flags[i]);
619 flags_val = g_variant_new("as", builder2);
620 g_variant_builder_add(inner_builder, "{sv}", "Flags",
623 g_variant_builder_add(desc_builder, "{sa{sv}}",
627 g_variant_builder_add(builder, "{oa{sa{sv}}}",
628 desc_info->desc_path,
631 /*unref descriptor builder pointers*/
632 g_variant_builder_unref(builder1);
633 g_variant_builder_unref(builder2);
634 g_variant_builder_unref(inner_builder);
635 g_variant_builder_unref(desc_builder);
640 /*unref char builder pointers*/
641 g_variant_builder_unref(builder1);
642 g_variant_builder_unref(builder2);
643 g_variant_builder_unref(builder3);
644 g_variant_builder_unref(inner_builder);
645 g_variant_builder_unref(char_builder);
648 /*unref service builder pointers*/
649 g_variant_builder_unref(inner_builder);
650 g_variant_builder_unref(svc_builder);
653 /* Return builder as method reply */
654 BT_DBG("Sending gatt service builder values to Bluez");
655 g_dbus_method_invocation_return_value(invocation,
662 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
666 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
667 struct gatt_service_info *serv_info = l1->data;
669 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
670 struct gatt_char_info *char_info = l2->data;
672 if (g_strcmp0(char_info->char_path, char_path)
677 BT_ERR("Gatt service not found");
681 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
683 GSList *l1, *l2, *l3;
685 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
686 struct gatt_service_info *serv_info = l1->data;
688 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
689 struct gatt_char_info *char_info = l2->data;
691 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
692 struct gatt_desc_info *desc_info = l3->data;
694 if (g_strcmp0(desc_info->desc_path, desc_path)
700 BT_ERR("Gatt service not found");
704 static void __bt_gatt_char_method_call(GDBusConnection *connection,
706 const gchar *object_path,
707 const gchar *interface_name,
708 const gchar *method_name,
709 GVariant *parameters,
710 GDBusMethodInvocation *invocation,
714 if (g_strcmp0(method_name, "ReadValue") == 0) {
718 bt_gatt_read_req_t read_req = {0, };
719 bt_user_info_t *user_info = NULL;
720 struct gatt_req_info *req_info = NULL;
721 struct gatt_service_info *svc_info = NULL;
722 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
723 GVariant *param = NULL;
726 BT_DBG("Application path = %s", object_path);
727 BT_DBG("Sender = %s", sender);
729 user_info = _bt_get_user_data(BT_COMMON);
730 if (user_info == NULL) {
731 BT_INFO("No callback is set for %s", object_path);
732 g_dbus_method_invocation_return_value(invocation, NULL);
736 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
737 if (svc_info == NULL) {
738 BT_ERR("Coudn't find service for %s", object_path);
739 g_dbus_method_invocation_return_value(invocation, NULL);
743 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
744 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
746 read_req.att_handle = (char *)object_path;
747 read_req.address = addr;
748 read_req.req_id = req_id;
749 read_req.offset = offset;
750 read_req.service_handle = svc_info->serv_path;
752 /* Store requets information */
753 req_info = g_new0(struct gatt_req_info, 1);
754 req_info->attr_path = g_strdup(object_path);
755 req_info->svc_path = g_strdup(read_req.service_handle);
756 req_info->request_id = req_id;
757 req_info->offset = offset;
758 req_info->context = invocation;
759 gatt_requests = g_slist_append(gatt_requests, req_info);
761 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
762 BLUETOOTH_ERROR_NONE, &read_req,
763 user_info->cb, user_info->user_data);
765 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
766 param = g_variant_new("(sssyq)",
768 read_req.service_handle,
772 #ifdef TIZEN_FEATURE_BT_HPS
773 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
775 #ifdef TIZEN_FEATURE_BT_OTP
776 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
780 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
781 GVariant *var = NULL;
785 gboolean response_needed = FALSE;
786 bt_gatt_value_change_t value_change = {0, };
787 bt_user_info_t *user_info = NULL;
789 struct gatt_service_info *svc_info = NULL;
790 struct gatt_req_info *req_info = NULL;
791 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
792 GVariant *param = NULL;
795 BT_DBG("WriteValue");
796 BT_DBG("Application path = %s", object_path);
797 BT_DBG("Sender = %s", sender);
799 g_variant_get(parameters, "(&suqb@ay)",
800 &addr, &req_id, &offset, &response_needed, &var);
801 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
803 user_info = _bt_get_user_data(BT_COMMON);
805 BT_INFO("No callback is set for %s", object_path);
806 g_variant_unref(var);
808 g_dbus_method_invocation_return_value(invocation, NULL);
810 g_object_unref(invocation);
814 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
815 if (svc_info == NULL) {
816 BT_ERR("Coudn't find service for %s", object_path);
817 g_variant_unref(var);
819 g_dbus_method_invocation_return_value(invocation, NULL);
821 g_object_unref(invocation);
825 value_change.att_handle = (char *)object_path;
826 value_change.address = addr;
827 value_change.service_handle = svc_info->serv_path;
828 value_change.offset = offset;
829 value_change.req_id = req_id;
830 value_change.response_needed = response_needed;
832 len = g_variant_get_size(var);
836 value_change.att_value = (guint8 *)g_malloc(len);
838 data = (char *)g_variant_get_data(var);
839 memcpy(value_change.att_value, data, len);
841 value_change.val_len = len;
843 if (response_needed) {
844 /* Store requets information */
845 req_info = g_new0(struct gatt_req_info, 1);
846 req_info->attr_path = g_strdup(object_path);
847 req_info->svc_path = g_strdup(value_change.service_handle);
848 req_info->request_id = req_id;
849 req_info->offset = offset;
850 req_info->context = invocation;
851 gatt_requests = g_slist_append(gatt_requests, req_info);
853 g_object_unref(invocation);
857 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
858 BLUETOOTH_ERROR_NONE, &value_change,
859 user_info->cb, user_info->user_data);
861 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
864 svc_path = g_strdup(svc_info->serv_path);
865 param = g_variant_new("(sssyq@ay)",
872 #ifdef TIZEN_FEATURE_BT_HPS
873 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
875 #ifdef TIZEN_FEATURE_BT_OTP
876 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
883 g_free(value_change.att_value);
884 g_variant_unref(var);
886 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
887 bt_user_info_t *user_info = NULL;
888 bt_gatt_char_notify_change_t notify_change = {0, };
889 #if TIZEN_FEATURE_BT_OTP
890 GVariant *param = NULL;
892 BT_DBG("StartNotify");
893 user_info = _bt_get_user_data(BT_COMMON);
894 if (user_info != NULL) {
895 struct gatt_service_info *svc_info = NULL;
896 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
898 notify_change.service_handle = svc_info->serv_path;
899 notify_change.att_handle = (char *)object_path;
900 notify_change.att_notify = TRUE;
902 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
903 BLUETOOTH_ERROR_NONE, ¬ify_change,
904 user_info->cb, user_info->user_data);
905 #if TIZEN_FEATURE_BT_OTP
906 param = g_variant_new("(ssb)",
907 notify_change.att_handle,
908 notify_change.service_handle,
909 notify_change.att_notify);
910 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
914 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
915 bt_user_info_t *user_info = NULL;
916 bt_gatt_char_notify_change_t notify_change = {0, };
917 #if TIZEN_FEATURE_BT_OTP
918 GVariant *param = NULL;
920 BT_DBG("StopNotify");
921 user_info = _bt_get_user_data(BT_COMMON);
922 if (user_info != NULL) {
923 struct gatt_service_info *svc_info = NULL;
924 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
926 notify_change.service_handle = svc_info->serv_path;
927 notify_change.att_handle = (char *)object_path;
928 notify_change.att_notify = FALSE;
930 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
931 BLUETOOTH_ERROR_NONE, ¬ify_change,
932 user_info->cb, user_info->user_data);
933 #if TIZEN_FEATURE_BT_OTP
934 param = g_variant_new("(ssb)",
935 notify_change.att_handle,
936 notify_change.service_handle,
937 notify_change.att_notify);
938 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
942 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
944 bt_gatt_indicate_confirm_t confirm = {0, };
945 bt_user_info_t *user_info = NULL;
946 gboolean complete = FALSE;
947 struct gatt_service_info *svc_info = NULL;
949 BT_DBG("IndicateConfirm");
950 BT_DBG("Application path = %s", object_path);
951 BT_DBG("Sender = %s", sender);
953 g_variant_get(parameters, "(&sb)", &addr, &complete);
954 BT_DBG("Remote Device address number = %s", addr);
956 confirm.att_handle = (char *)object_path;
957 confirm.address = addr;
958 confirm.complete = complete;
960 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
961 if (svc_info != NULL) {
962 confirm.service_handle = svc_info->serv_path;
964 user_info = _bt_get_user_data(BT_COMMON);
965 if (user_info != NULL) {
967 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
968 BLUETOOTH_ERROR_NONE, &confirm,
969 user_info->cb, user_info->user_data);
974 g_dbus_method_invocation_return_value(invocation, NULL);
977 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
979 const gchar *object_path,
980 const gchar *interface_name,
981 const gchar *method_name,
982 GVariant *parameters,
983 GDBusMethodInvocation *invocation,
986 if (g_strcmp0(method_name, "ReadValue") == 0) {
990 bt_gatt_read_req_t read_req = {0, };
991 bt_user_info_t *user_info = NULL;
992 struct gatt_req_info *req_info = NULL;
993 struct gatt_service_info *svc_info = NULL;
996 BT_DBG("Application path = %s", object_path);
997 BT_DBG("Sender = %s", sender);
999 user_info = _bt_get_user_data(BT_COMMON);
1000 if (user_info == NULL) {
1001 BT_INFO("No callback is set for %s", object_path);
1002 g_dbus_method_invocation_return_value(invocation, NULL);
1006 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1007 if (svc_info == NULL) {
1008 BT_ERR("Coudn't find service for %s", object_path);
1009 g_dbus_method_invocation_return_value(invocation, NULL);
1013 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1014 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1016 read_req.att_handle = (char *)object_path;
1017 read_req.address = addr;
1018 read_req.req_id = req_id;
1019 read_req.offset = offset;
1020 read_req.service_handle = svc_info->serv_path;
1022 /* Store requets information */
1023 req_info = g_new0(struct gatt_req_info, 1);
1024 req_info->attr_path = g_strdup(object_path);
1025 req_info->svc_path = g_strdup(read_req.service_handle);
1026 req_info->request_id = req_id;
1027 req_info->offset = offset;
1028 req_info->context = invocation;
1029 gatt_requests = g_slist_append(gatt_requests, req_info);
1031 _bt_common_event_cb(
1032 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1033 BLUETOOTH_ERROR_NONE, &read_req,
1034 user_info->cb, user_info->user_data);
1037 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1038 GVariant *var = NULL;
1042 gboolean response_needed = FALSE;
1043 bt_gatt_value_change_t value_change = {0, };
1044 bt_user_info_t *user_info = NULL;
1046 struct gatt_service_info *svc_info = NULL;
1047 struct gatt_req_info *req_info = NULL;
1049 BT_DBG("WriteValue");
1050 BT_DBG("Application path = %s", object_path);
1051 BT_DBG("Sender = %s", sender);
1053 g_variant_get(parameters, "(&suqb@ay)",
1054 &addr, &req_id, &offset, &response_needed, &var);
1055 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1057 user_info = _bt_get_user_data(BT_COMMON);
1058 if (user_info == NULL) {
1059 BT_INFO("No callback is set for %s", object_path);
1060 g_variant_unref(var);
1061 if (response_needed)
1062 g_dbus_method_invocation_return_value(invocation, NULL);
1064 g_object_unref(invocation);
1068 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1069 if (svc_info == NULL) {
1070 BT_ERR("Coudn't find service for %s", object_path);
1071 g_variant_unref(var);
1072 if (response_needed)
1073 g_dbus_method_invocation_return_value(invocation, NULL);
1075 g_object_unref(invocation);
1079 value_change.att_handle = (char *)object_path;
1080 value_change.address = addr;
1081 value_change.service_handle = svc_info->serv_path;
1082 value_change.offset = offset;
1083 value_change.req_id = req_id;
1084 value_change.response_needed = response_needed;
1086 len = g_variant_get_size(var);
1090 value_change.att_value = (guint8 *)g_malloc(len);
1092 data = (char *)g_variant_get_data(var);
1093 memcpy(value_change.att_value, data, len);
1095 value_change.val_len = len;
1097 if (response_needed) {
1098 /* Store requets information */
1099 req_info = g_new0(struct gatt_req_info, 1);
1100 req_info->attr_path = g_strdup(object_path);
1101 req_info->svc_path = g_strdup(value_change.service_handle);
1102 req_info->request_id = req_id;
1103 req_info->offset = offset;
1104 req_info->context = invocation;
1105 gatt_requests = g_slist_append(gatt_requests, req_info);
1107 g_object_unref(invocation);
1110 _bt_common_event_cb(
1111 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1112 BLUETOOTH_ERROR_NONE, &value_change,
1113 user_info->cb, user_info->user_data);
1115 g_free(value_change.att_value);
1116 g_variant_unref(var);
1121 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1124 GError *error = NULL;
1125 GVariantBuilder *array_builder;
1127 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1128 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1129 g_variant_builder_add(array_builder, "s", interface);
1131 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1132 "org.freedesktop.Dbus.Objectmanager",
1133 "InterfacesRemoved",
1134 g_variant_new("(oas)",
1135 object_path, array_builder),
1139 if (error != NULL) {
1140 /* dbus gives error cause */
1141 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1142 error->code, error->message);
1143 g_clear_error(&error);
1146 g_variant_builder_unref(array_builder);
1151 static const GDBusInterfaceVTable desc_interface_vtable = {
1152 __bt_gatt_desc_method_call,
1157 static const GDBusInterfaceVTable char_interface_vtable = {
1158 __bt_gatt_char_method_call,
1163 static const GDBusInterfaceVTable serv_interface_vtable = {
1169 static const GDBusInterfaceVTable manager_interface_vtable = {
1170 __bt_gatt_manager_method_call,
1175 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1176 const gchar *introspection_data)
1179 GDBusNodeInfo *node_info = NULL;
1181 if (introspection_data == NULL)
1185 BT_DBG("Create new node info");
1186 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1189 BT_ERR("Unable to create node: %s", err->message);
1190 g_clear_error(&err);
1197 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1198 const char *service_path)
1202 for (l = gatt_services; l != NULL; l = l->next) {
1203 struct gatt_service_info *info = l->data;
1205 if (g_strcmp0(info->serv_path, service_path) == 0)
1208 BT_ERR("Gatt service not found");
1212 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1213 const char *service_path, const char *char_path)
1217 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1218 struct gatt_service_info *serv_info = l1->data;
1220 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1222 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1223 struct gatt_char_info *char_info = l2->data;
1225 if (g_strcmp0(char_info->char_path, char_path)
1229 BT_ERR("Gatt characteristic not found");
1233 BT_ERR("Gatt service not found");
1237 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1238 const char *serv_path, const char *char_path,
1239 const char *desc_path)
1241 GSList *l1, *l2, *l3;
1243 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1244 struct gatt_service_info *serv_info = l1->data;
1246 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1247 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1248 struct gatt_char_info *char_info = l2->data;
1250 if (g_strcmp0(char_info->char_path, char_path)
1252 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1253 struct gatt_desc_info *desc_info = l3->data;
1254 if (g_strcmp0(desc_info->desc_path,
1263 BT_ERR("Gatt descriptor not found");
1267 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1271 for (l = gatt_requests; l != NULL; l = l->next) {
1272 struct gatt_req_info *req_info = l->data;
1274 if (req_info && req_info->request_id == request_id)
1277 BT_ERR("Gatt Request not found");
1281 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1282 const gchar *path, const gchar *interface)
1288 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1293 BT_ERR("Unable to connect to gdbus: %s", err->message);
1294 g_clear_error(&err);
1299 proxy = g_dbus_proxy_new_sync(g_conn,
1300 G_DBUS_PROXY_FLAGS_NONE, NULL,
1302 interface, NULL, &err);
1306 BT_ERR("Unable to create proxy: %s", err->message);
1307 g_clear_error(&err);
1311 manager_gproxy = proxy;
1316 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1317 const gchar *path, const gchar *interface)
1319 return (manager_gproxy) ? manager_gproxy :
1320 __bt_gatt_gdbus_init_manager_proxy(service,
1324 int bluetooth_gatt_convert_prop2string(
1325 bt_gatt_characteristic_property_t properties,
1326 char *char_properties[])
1330 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
1331 char_properties[flag_count] = g_strdup("broadcast");
1334 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
1335 char_properties[flag_count] = g_strdup("read");
1338 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
1339 char_properties[flag_count] = g_strdup("write-without-response");
1342 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
1343 char_properties[flag_count] = g_strdup("write");
1346 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
1347 char_properties[flag_count] = g_strdup("notify");
1350 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
1351 char_properties[flag_count] = g_strdup("indicate");
1354 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
1355 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
1358 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
1359 char_properties[flag_count] = g_strdup("reliable-write");
1362 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
1363 char_properties[flag_count] = g_strdup("writable-auxiliaries");
1366 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
1367 char_properties[flag_count] = g_strdup("encrypt-read");
1370 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
1371 char_properties[flag_count] = g_strdup("encrypt-write");
1374 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
1375 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1378 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
1379 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1383 if (flag_count == 0) {
1384 char_properties[flag_count] = g_strdup("read");
1391 int bluetooth_gatt_convert_perm2string(
1392 bt_gatt_permission_t properties,
1393 char *char_properties[])
1397 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
1398 char_properties[flag_count] = g_strdup("read");
1401 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
1402 char_properties[flag_count] = g_strdup("write");
1405 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
1406 char_properties[flag_count] = g_strdup("encrypt-read");
1409 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
1410 char_properties[flag_count] = g_strdup("encrypt-write");
1413 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
1414 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1417 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
1418 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1422 if (flag_count == 0) {
1423 char_properties[flag_count] = g_strdup("read");
1430 static void __bt_gatt_set_service_state(const char *service_path,
1433 struct gatt_service_info *svc_info = NULL;
1434 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1436 if (svc_info != NULL) {
1437 BT_DBG("Updating the gatt service register state %d", state);
1438 svc_info->is_svc_registered = state;
1442 BT_DBG("gatt service not found");
1445 static gboolean __bt_gatt_get_service_state(const char *service_path)
1447 struct gatt_service_info *svc_info = NULL;
1449 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1451 if (svc_info != NULL) {
1452 BT_DBG("Return the state of the gatt service %d",
1453 svc_info->is_svc_registered);
1454 return svc_info->is_svc_registered;
1457 BT_DBG("gatt service info is NULL");
1461 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1463 GError *error = NULL;
1465 GVariantIter *iter = NULL;
1466 const gchar *key = NULL;
1467 GVariant *value = NULL;
1468 const gchar *service = NULL;
1469 const gchar *characteristic = NULL;
1470 const gchar *descriptor = NULL;
1474 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1476 if (result == NULL) {
1477 /* dBUS-RPC is failed */
1478 BT_ERR("Dbus-RPC is failed\n");
1480 if (error != NULL) {
1481 /* dBUS gives error cause */
1482 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1483 error->code, error->message);
1484 g_clear_error(&error);
1487 char *char_cmp = NULL;
1488 g_variant_get(result, "(a{sv})", &iter);
1489 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1491 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1492 if (g_strcmp0(key, "Service") == 0) {
1493 service = g_variant_get_string(value, NULL);
1494 BT_DBG("Service %s", service);
1495 } else if (g_strcmp0(key, char_cmp) == 0) {
1496 characteristic = g_variant_get_string(value, NULL);
1498 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1499 BT_DBG("%s", characteristic);
1500 } else if (g_strcmp0(key, "Descriptor") == 0) {
1501 descriptor = g_variant_get_string(value, NULL);
1502 BT_DBG("Descriptor %s", descriptor);
1505 g_variant_iter_free(iter);
1507 /* TODO: Store the service informationa and
1508 * Send respponse to CAPI layer. */
1510 g_variant_unref(result);
1515 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1517 BT_INFO("RegisterApplication is completed");
1519 GError *error = NULL;
1522 register_pending_cnt = 0;
1524 if (register_cancel) {
1525 g_object_unref(register_cancel);
1526 register_cancel = NULL;
1529 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1531 if (result == NULL) {
1532 /* dBUS-RPC is failed */
1533 BT_ERR("Dbus-RPC is failed\n");
1535 if (error != NULL) {
1536 /* dBUS gives error cause */
1537 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1538 error->code, error->message);
1539 g_clear_error(&error);
1542 g_variant_unref(result);
1546 static int __bt_gatt_unregister_service(const char *service_path)
1548 if (!__bt_gatt_get_service_state(service_path)) {
1549 BT_DBG("service not registered \n");
1550 return BLUETOOTH_ERROR_NOT_FOUND;
1553 return BLUETOOTH_ERROR_NONE;
1556 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1558 GDBusProxy *proxy = NULL;
1560 if (is_server_started) {
1564 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1565 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1567 if (proxy == NULL || app_path == NULL)
1568 return BLUETOOTH_ERROR_INTERNAL;
1570 BT_INFO("UnregisterApplication");
1572 is_server_started = false;
1574 /* Async Call to Unregister Service */
1575 ret = g_dbus_proxy_call_sync(proxy,
1576 "UnregisterApplication",
1577 g_variant_new("(o)",
1579 G_DBUS_CALL_FLAGS_NONE, -1,
1583 /* dBUS-RPC is failed */
1584 BT_ERR("dBUS-RPC is failed");
1586 /* dBUS gives error cause */
1587 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1588 err->code, err->message);
1590 g_clear_error(&err);
1592 return BLUETOOTH_ERROR_INTERNAL;
1594 g_variant_unref(ret);
1596 BT_INFO("UnregisterApplication is completed");
1598 return BLUETOOTH_ERROR_NONE;
1601 BT_INFO("GATT server not started");
1602 return BLUETOOTH_ERROR_NONE;
1605 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1607 GDBusConnection *local_system_gconn = NULL;
1611 if (g_conn == NULL) {
1612 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1613 if (address == NULL) {
1615 BT_ERR("Failed to get bus address: %s", err->message);
1616 g_clear_error(&err);
1621 g_conn = g_dbus_connection_new_for_address_sync(address,
1622 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1623 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1624 NULL, /* GDBusAuthObserver */
1630 BT_ERR("Unable to connect to dbus: %s", err->message);
1631 g_clear_error(&err);
1635 } else if (g_dbus_connection_is_closed(g_conn)) {
1636 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1637 if (address == NULL) {
1639 BT_ERR("Failed to get bus address: %s", err->message);
1640 g_clear_error(&err);
1645 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1646 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1647 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1648 NULL, /* GDBusAuthObserver */
1652 if (!local_system_gconn) {
1653 BT_ERR("Unable to connect to dbus: %s", err->message);
1654 g_clear_error(&err);
1657 g_conn = local_system_gconn;
1663 BT_EXPORT_API int bluetooth_gatt_init(void)
1665 GDBusConnection *conn;
1666 GError *error = NULL;
1667 GDBusNodeInfo *node_info = NULL;
1669 if (app_path != NULL) {
1670 BT_ERR("app path already exists! initialized");
1671 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1674 if (owner_id == 0) {
1675 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1676 BT_GATT_SERVICE_NAME,
1677 G_BUS_NAME_OWNER_FLAGS_NONE,
1678 NULL, NULL, NULL, NULL, NULL);
1681 BT_DBG("owner_id is [%d]", owner_id);
1682 app_path = g_strdup_printf("/com/%d", getpid());
1686 conn = __bt_gatt_get_gdbus_connection();
1688 BT_ERR("Unable to get connection");
1692 /* Register ObjectManager interface */
1693 node_info = __bt_gatt_create_method_node_info(
1694 manager_introspection_xml);
1695 if (node_info == NULL) {
1696 BT_ERR("failed to get node info");
1700 if (manager_id == 0) {
1701 BT_INFO("manager_id does not exists");
1703 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1704 node_info->interfaces[0],
1705 &manager_interface_vtable,
1706 NULL, NULL, &error);
1708 g_dbus_node_info_unref(node_info);
1709 if (manager_id == 0) {
1710 BT_ERR("failed to register: %s", error->message);
1711 g_error_free(error);
1715 return BLUETOOTH_ERROR_NONE;
1719 g_bus_unown_name(owner_id);
1726 __bt_gatt_close_gdbus_connection();
1728 return BLUETOOTH_ERROR_INTERNAL;
1731 BT_EXPORT_API int bluetooth_gatt_deinit()
1733 int ret = BLUETOOTH_ERROR_NONE;
1735 if (register_cancel) {
1736 g_cancellable_cancel(register_cancel);
1737 g_object_unref(register_cancel);
1738 register_cancel = NULL;
1741 /* Unown gdbus bus */
1743 /* remove/unregister all services */
1744 BT_DBG("removing all registered gatt service\n");
1745 bluetooth_gatt_delete_services();
1747 /* unregister the exported interface for object manager */
1748 g_dbus_connection_unregister_object(g_conn,
1753 ret = bluetooth_gatt_unregister_application();
1754 if (ret != BLUETOOTH_ERROR_NONE)
1755 BT_ERR("Fail to unregister application\n");
1757 g_bus_unown_name(owner_id);
1763 BT_DBG("Gatt service deinitialized \n");
1765 g_slist_free(gatt_services);
1766 gatt_services = NULL;
1768 g_object_unref(manager_gproxy);
1769 manager_gproxy = NULL;
1771 __bt_gatt_close_gdbus_connection();
1776 __bt_gatt_close_gdbus_connection();
1778 return BLUETOOTH_ERROR_NOT_FOUND;
1781 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1784 GError *error = NULL;
1786 GDBusNodeInfo *node_info;
1788 GVariantBuilder *builder = NULL;
1789 GVariantBuilder *builder1 = NULL;
1790 GVariantBuilder *inner_builder = NULL;
1791 gboolean svc_primary = TRUE;
1792 struct gatt_service_info *serv_info = NULL;
1794 node_info = __bt_gatt_create_method_node_info(
1795 service_introspection_xml);
1796 if (node_info == NULL)
1797 return BLUETOOTH_ERROR_INTERNAL;
1799 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1800 BT_DBG("gatt service path is [%s]", path);
1802 object_id = g_dbus_connection_register_object(g_conn, path,
1803 node_info->interfaces[0],
1804 &serv_interface_vtable,
1805 NULL, NULL, &error);
1806 g_dbus_node_info_unref(node_info);
1808 if (object_id == 0) {
1809 BT_ERR("failed to register: %s", error->message);
1810 g_error_free(error);
1813 return BLUETOOTH_ERROR_INTERNAL;
1816 /* Add object_id/gatt service information; it's required at the time of
1817 * service unregister and Getmanagedobjects
1819 serv_info = g_new0(struct gatt_service_info, 1);
1821 serv_info->serv_path = g_strdup(path);
1822 serv_info->serv_id = object_id;
1823 serv_info->service_uuid = g_strdup(svc_uuid);
1824 serv_info->is_svc_registered = FALSE;
1825 serv_info->is_svc_primary = svc_primary;
1827 gatt_services = g_slist_append(gatt_services, serv_info);
1829 /* emit interfacesadded signal here for service path */
1830 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1831 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1833 g_variant_builder_add(inner_builder, "{sv}",
1834 "UUID", g_variant_new_string(svc_uuid));
1836 g_variant_builder_add(inner_builder, "{sv}",
1837 "Primary", g_variant_new_boolean(svc_primary));
1839 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1841 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1842 g_variant_new("ao", builder1));
1844 g_variant_builder_add(builder, "{sa{sv}}",
1845 GATT_SERV_INTERFACE, inner_builder);
1847 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1848 "org.freedesktop.Dbus.ObjectManager",
1850 g_variant_new("(oa{sa{sv}})",
1856 *svc_path = g_strdup(path);
1859 g_variant_builder_unref(inner_builder);
1860 g_variant_builder_unref(builder);
1861 g_variant_builder_unref(builder1);
1863 return BLUETOOTH_ERROR_NONE;
1866 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1867 const char *svc_path, const char *char_uuid,
1868 bt_gatt_permission_t permissions,
1869 bt_gatt_characteristic_property_t properties,
1873 GError *error = NULL;
1875 GDBusNodeInfo *node_info;
1877 GVariantBuilder *builder = NULL;
1878 GVariantBuilder *inner_builder = NULL;
1879 struct gatt_service_info *serv_info = NULL;
1880 struct gatt_char_info *char_info = NULL;
1881 GVariantBuilder *builder2 = NULL;
1882 GVariantBuilder *builder3 = NULL;
1883 GVariant *flags_val = NULL;
1885 char *char_flags[NUMBER_OF_FLAGS];
1890 new_service = FALSE;
1893 BT_DBG("gatt svc_path path is [%s]", svc_path);
1894 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1895 if (serv_info == NULL)
1896 return BLUETOOTH_ERROR_INVALID_PARAM;
1898 node_info = __bt_gatt_create_method_node_info(
1899 characteristics_introspection_xml);
1900 if (node_info == NULL)
1901 return BLUETOOTH_ERROR_INTERNAL;
1903 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1904 BT_DBG("gatt characteristic path is [%s]", path);
1906 object_id = g_dbus_connection_register_object(g_conn, path,
1907 node_info->interfaces[0],
1908 &char_interface_vtable,
1909 NULL, NULL, &error);
1910 g_dbus_node_info_unref(node_info);
1912 if (object_id == 0) {
1913 BT_ERR("failed to register: %s", error->message);
1914 g_error_free(error);
1917 return BLUETOOTH_ERROR_INTERNAL;
1920 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1921 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1922 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1923 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1924 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1925 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1926 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1927 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1929 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1931 char_info = g_new0(struct gatt_char_info, 1);
1933 char_info->char_path = g_strdup(path);
1934 char_info->char_id = object_id;
1935 char_info->char_uuid = g_strdup(char_uuid);
1937 for (i = 0; i < flag_count; i++)
1938 char_info->char_flags[i] = char_flags[i];
1941 char_info->flags_length = flag_count;
1943 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1945 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1946 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1948 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1949 g_variant_new("s", char_uuid));
1950 g_variant_builder_add(inner_builder, "{sv}", "Service",
1951 g_variant_new("o", svc_path));
1953 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1955 for (i = 0; i < flag_count; i++)
1956 g_variant_builder_add(builder2, "s", char_flags[i]);
1958 flags_val = g_variant_new("as", builder2);
1959 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1962 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1964 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1965 g_variant_new("ao", builder3));
1967 g_variant_builder_add(builder, "{sa{sv}}",
1968 GATT_CHAR_INTERFACE,
1971 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1972 "org.freedesktop.Dbus.ObjectManager",
1974 g_variant_new("(oa{sa{sv}})",
1978 *char_path = g_strdup(path);
1984 g_variant_builder_unref(inner_builder);
1985 g_variant_builder_unref(builder);
1986 g_variant_builder_unref(builder2);
1987 g_variant_builder_unref(builder3);
1989 return BLUETOOTH_ERROR_NONE;
1992 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1993 const char *characteristic, const char *char_value,
1996 gchar **line_argv = NULL;
1997 char *serv_path = NULL;
1998 struct gatt_char_info *char_info = NULL;
1999 GVariantBuilder *builder1 = NULL;
2000 GVariantBuilder *builder = NULL;
2001 GVariantBuilder *inner_builder = NULL;
2002 GVariant *char_val = NULL;
2003 GError *error = NULL;
2005 int res = BLUETOOTH_ERROR_NONE;
2007 line_argv = g_strsplit_set(characteristic, "/", 0);
2008 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2010 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
2012 if (char_info == NULL) {
2013 /* Fix : RESOURCE_LEAK */
2014 res = BLUETOOTH_ERROR_INVALID_PARAM;
2018 char_info->value_length = value_length;
2020 char_info->char_value = (char *)malloc(value_length);
2021 /* Fix : NULL_RETURNS */
2022 if (char_info->char_value == NULL) {
2023 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2027 for (i = 0; i < value_length; i++)
2028 char_info->char_value[i] = char_value[i];
2030 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2031 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2033 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2035 for (i = 0; i < value_length; i++)
2036 g_variant_builder_add(builder1, "y", char_value[i]);
2038 char_val = g_variant_new("ay", builder1);
2039 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
2041 g_variant_builder_add(builder, "{sa{sv}}",
2042 GATT_CHAR_INTERFACE,
2045 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2046 "org.freedesktop.Dbus.ObjectManager",
2048 g_variant_new("(oa{sa{sv}})",
2049 char_info->char_path, builder),
2052 g_variant_builder_unref(inner_builder);
2053 g_variant_builder_unref(builder);
2054 g_variant_builder_unref(builder1);
2056 g_strfreev(line_argv);
2062 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2063 const char *char_path, const char *desc_uuid,
2064 bt_gatt_permission_t permissions,
2067 static int desc_id = 1;
2068 GError *error = NULL;
2070 GDBusNodeInfo *node_info;
2072 GVariantBuilder *builder = NULL;
2073 GVariantBuilder *inner_builder = NULL;
2074 struct gatt_char_info *char_info = NULL;
2075 struct gatt_desc_info *desc_info = NULL;
2076 gchar **line_argv = NULL;
2078 GVariantBuilder *builder2 = NULL;
2079 GVariant *flags_val = NULL;
2081 char *desc_flags[NUMBER_OF_FLAGS];
2089 line_argv = g_strsplit_set(char_path, "/", 0);
2090 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2092 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2093 if (char_info == NULL) {
2094 g_strfreev(line_argv);
2096 return BLUETOOTH_ERROR_INVALID_PARAM;
2099 node_info = __bt_gatt_create_method_node_info(
2100 descriptor_introspection_xml);
2101 if (node_info == NULL) {
2102 g_strfreev(line_argv);
2104 return BLUETOOTH_ERROR_INTERNAL;
2107 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2108 BT_DBG("gatt descriptor path is [%s]", path);
2110 object_id = g_dbus_connection_register_object(g_conn, path,
2111 node_info->interfaces[0],
2112 &desc_interface_vtable,
2113 NULL, NULL, &error);
2114 g_dbus_node_info_unref(node_info);
2116 if (object_id == 0) {
2117 BT_ERR("failed to register: %s", error->message);
2118 g_error_free(error);
2120 g_strfreev(line_argv);
2123 return BLUETOOTH_ERROR_INTERNAL;
2126 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2128 desc_info = g_new0(struct gatt_desc_info, 1);
2130 desc_info->desc_path = g_strdup(path);
2131 desc_info->desc_id = object_id;
2132 desc_info->desc_uuid = g_strdup(desc_uuid);
2134 for (i = 0; i < flag_count; i++)
2135 desc_info->desc_flags[i] = desc_flags[i];
2137 desc_info->flags_length = flag_count;
2139 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2141 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2142 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2144 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2145 g_variant_new("s", desc_uuid));
2146 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2147 g_variant_new("o", char_path));
2149 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2151 for (i = 0; i < flag_count; i++)
2152 g_variant_builder_add(builder2, "s", desc_flags[i]);
2154 flags_val = g_variant_new("as", builder2);
2155 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2158 g_variant_builder_add(builder, "{sa{sv}}",
2159 GATT_DESC_INTERFACE,
2162 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2163 "org.freedesktop.Dbus.ObjectManager",
2165 g_variant_new("(oa{sa{sv}})",
2169 *desc_path = g_strdup(path);
2173 g_strfreev(line_argv);
2174 g_variant_builder_unref(inner_builder);
2175 g_variant_builder_unref(builder);
2176 g_variant_builder_unref(builder2);
2178 return BLUETOOTH_ERROR_NONE;
2181 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2182 const char *desc_path, const char *desc_value,
2185 GError *error = NULL;
2186 GVariantBuilder *builder = NULL;
2187 GVariantBuilder *inner_builder = NULL;
2188 GVariantBuilder *builder1 = NULL;
2189 struct gatt_desc_info *desc_info = NULL;
2190 gchar **line_argv = NULL;
2192 GVariant *desc_val = NULL;
2193 char *serv_path = NULL;
2196 line_argv = g_strsplit_set(desc_path, "/", 0);
2197 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2198 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2200 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2202 /* Free the allocated memory */
2203 g_strfreev(line_argv);
2207 /* Fix : NULL_RETURNS */
2208 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2210 desc_info->desc_value = (char *)malloc(value_length);
2212 /* Fix : NULL_RETURNS */
2213 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2215 for (i = 0; i < value_length; i++)
2216 desc_info->desc_value[i] = desc_value[i];
2218 desc_info->value_length = value_length;
2220 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2221 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2223 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2225 for (i = 0; i < value_length; i++)
2226 g_variant_builder_add(builder1, "y", desc_value[i]);
2228 desc_val = g_variant_new("ay", builder1);
2229 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2231 g_variant_builder_add(builder, "{sa{sv}}",
2232 GATT_DESC_INTERFACE,
2235 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2236 "org.freedesktop.Dbus.ObjectManager",
2238 g_variant_new("(oa{sa{sv}})",
2239 desc_info->desc_path, builder),
2242 g_variant_builder_unref(inner_builder);
2243 g_variant_builder_unref(builder);
2244 g_variant_builder_unref(builder1);
2246 return BLUETOOTH_ERROR_NONE;
2249 int bluetooth_gatt_get_service(const char *svc_uuid)
2251 GDBusProxy *proxy = NULL;
2254 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2255 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2257 return BLUETOOTH_ERROR_INTERNAL;
2259 uuid = g_strdup(svc_uuid);
2261 g_dbus_proxy_call(proxy,
2263 g_variant_new("(s)",
2265 G_DBUS_CALL_FLAGS_NONE, -1,
2267 (GAsyncReadyCallback) get_service_cb,
2272 return BLUETOOTH_ERROR_NONE;
2275 BT_EXPORT_API int bluetooth_gatt_register_service(
2276 const char *svc_path)
2278 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2279 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2280 BT_ERR("Don't have aprivilege to use this API");
2281 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2284 register_pending_cnt++;
2286 if (__bt_gatt_get_service_state(svc_path)) {
2287 BT_DBG("service already registered \n");
2288 return BLUETOOTH_ERROR_NONE;
2291 __bt_gatt_set_service_state(svc_path, TRUE);
2293 return BLUETOOTH_ERROR_NONE;
2296 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2298 GDBusProxy *proxy = NULL;
2300 if (!is_server_started) {
2302 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2303 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2304 BT_ERR("Don't have aprivilege to use this API");
2305 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2308 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2309 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2310 if (proxy == NULL || app_path == NULL)
2311 return BLUETOOTH_ERROR_INTERNAL;
2313 BT_INFO("RegisterApplication");
2315 if (register_cancel) {
2316 g_cancellable_cancel(register_cancel);
2317 g_object_unref(register_cancel);
2320 register_cancel = g_cancellable_new();
2322 g_dbus_proxy_call(proxy,
2323 "RegisterApplication",
2324 g_variant_new("(oa{sv})",
2326 G_DBUS_CALL_FLAGS_NONE, -1,
2328 (GAsyncReadyCallback) register_application_cb,
2331 is_server_started = true;
2333 return BLUETOOTH_ERROR_NONE;
2336 BT_INFO("Already RegisterApplication");
2338 return BLUETOOTH_ERROR_NONE;
2341 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2344 int error = BLUETOOTH_ERROR_NONE;
2348 for (l = gatt_services; l != NULL; l = l->next) {
2349 struct gatt_service_info *info = l->data;
2350 BT_DBG("svc_path is %s", info->serv_path);
2351 if (bluetooth_gatt_unregister_service(info->serv_path)
2352 != BLUETOOTH_ERROR_NONE) {
2353 error = BLUETOOTH_ERROR_INTERNAL;
2354 BT_ERR("Error in removing service %s \n",
2358 BT_DBG(" All services removed successfully.\n ");
2360 BT_DBG(" There are no registered services.\n ");
2363 g_slist_free(gatt_services);
2364 gatt_services = NULL;
2367 if (error != BLUETOOTH_ERROR_NONE)
2370 return BLUETOOTH_ERROR_NONE;
2373 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2374 const char *char_path, const char* char_value,
2377 GVariantBuilder *outer_builder;
2378 GVariantBuilder *inner_builder;
2379 GVariantBuilder *invalidated_builder;
2380 GVariant *update_value = NULL;
2381 GError *error = NULL;
2382 gboolean ret = FALSE;
2383 int err = BLUETOOTH_ERROR_NONE;
2385 gchar **line_argv = NULL;
2386 gchar *serv_path = NULL;
2387 const char *value = NULL;
2389 line_argv = g_strsplit_set(char_path, "/", 0);
2390 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2392 if (!__bt_gatt_get_service_state(serv_path)) {
2393 BT_DBG("service not registered for this characteristic \n");
2395 g_strfreev(line_argv);
2396 return BLUETOOTH_ERROR_INTERNAL;
2399 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2400 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2402 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2403 for (i = 0; i < value_length; i++)
2404 g_variant_builder_add(inner_builder, "y", char_value[i]);
2406 update_value = g_variant_new("ay", inner_builder);
2408 outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2409 g_variant_builder_add(outer_builder, "{sv}", "Value",
2412 BT_DBG("Updating characteristic value \n");
2413 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2415 "org.freedesktop.DBus.Properties",
2416 "PropertiesChanged",
2417 g_variant_new("(sa{sv}as)",
2418 "org.bluez.GattCharacteristic1",
2419 outer_builder, invalidated_builder),
2423 if (error != NULL) {
2424 BT_ERR("D-Bus API failure: errCode[%x], \
2426 error->code, error->message);
2427 g_clear_error(&error);
2429 err = BLUETOOTH_ERROR_INTERNAL;
2431 struct gatt_char_info *char_info = NULL;
2433 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2434 if (char_info == NULL) {
2436 g_strfreev(line_argv);
2437 g_variant_builder_unref(inner_builder);
2438 g_variant_builder_unref(outer_builder);
2439 g_variant_builder_unref(invalidated_builder);
2441 return BLUETOOTH_ERROR_INVALID_DATA;
2444 char_info->value_length = value_length;
2446 value = (char *)realloc(char_info->char_value, value_length);
2447 if (value == NULL) {
2449 g_strfreev(line_argv);
2450 g_variant_builder_unref(inner_builder);
2451 g_variant_builder_unref(outer_builder);
2452 g_variant_builder_unref(invalidated_builder);
2454 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2457 char_info->char_value = (char*)value;
2458 if (char_info->char_value) {
2459 for (i = 0; i < value_length; i++)
2460 char_info->char_value[i] = char_value[i];
2465 g_strfreev(line_argv);
2466 g_variant_builder_unref(inner_builder);
2467 g_variant_builder_unref(outer_builder);
2468 g_variant_builder_unref(invalidated_builder);
2473 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2480 g_free(desc_info->desc_path);
2481 g_free(desc_info->desc_uuid);
2482 g_free(desc_info->desc_value);
2484 for (i = 0; i < desc_info->flags_length; i++)
2485 g_free(desc_info->desc_flags[i]);
2490 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2497 g_free(char_info->char_path);
2498 g_free(char_info->char_uuid);
2499 g_free(char_info->char_value);
2501 for (i = 0; i < char_info->flags_length; i++)
2502 g_free(char_info->char_flags[i]);
2507 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2512 g_free(svc_info->serv_path);
2513 g_free(svc_info->service_uuid);
2517 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2520 struct gatt_service_info *svc_info;
2522 int err = BLUETOOTH_ERROR_NONE;
2524 BT_DBG("svc_path %s", svc_path);
2525 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2528 BT_ERR("Unable to find service info");
2529 return BLUETOOTH_ERROR_NOT_FOUND;
2532 err = __bt_gatt_unregister_service(svc_path);
2533 if (err != BLUETOOTH_ERROR_NONE) {
2534 BT_ERR("Could not unregister application");
2538 for (l = svc_info->char_data; l != NULL; l = l->next) {
2539 struct gatt_char_info *char_info = l->data;
2541 if (char_info == NULL)
2544 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2545 struct gatt_desc_info *desc_info = l1->data;
2547 if (desc_info == NULL)
2550 ret = g_dbus_connection_unregister_object(g_conn,
2551 desc_info->desc_id);
2553 __bt_gatt_emit_interface_removed(
2554 desc_info->desc_path,
2555 GATT_DESC_INTERFACE);
2557 err = BLUETOOTH_ERROR_INTERNAL;
2560 /* list remove & free */
2561 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2562 __bt_gatt_free_descriptor_info(desc_info);
2565 g_slist_free(char_info->desc_data);
2566 char_info->desc_data = NULL;
2568 ret = g_dbus_connection_unregister_object(g_conn,
2569 char_info->char_id);
2571 __bt_gatt_emit_interface_removed(char_info->char_path,
2572 GATT_CHAR_INTERFACE);
2574 err = BLUETOOTH_ERROR_INTERNAL;
2577 /* list remove & free */
2578 svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
2579 __bt_gatt_free_characteristic_info(char_info);
2582 g_slist_free(svc_info->char_data);
2583 svc_info->char_data = NULL;
2585 ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2587 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2588 GATT_SERV_INTERFACE);
2590 err = BLUETOOTH_ERROR_INTERNAL;
2593 ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2595 BT_DBG("Unregistered the service on properties interface");
2597 /* list remove & free */
2598 gatt_services = g_slist_remove(gatt_services, svc_info);
2599 __bt_gatt_free_service_info(svc_info);
2601 new_service = FALSE;
2603 if (gatt_services == NULL)
2605 else if (gatt_services->next == NULL)
2611 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2612 int resp_state, int offset, char *value, int value_length)
2614 struct gatt_req_info *req_info = NULL;
2616 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2617 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2618 BT_ERR("Don't have aprivilege to use this API");
2619 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2622 req_info = __bt_gatt_find_request_info(request_id);
2623 if (req_info == NULL) {
2624 BT_ERR("Coundn't find request id [%d]", request_id);
2625 return BLUETOOTH_ERROR_INTERNAL;
2628 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2629 BT_ERR("resp_state is 0x%X", resp_state);
2630 char err_msg[20] = { 0, };
2631 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2632 g_dbus_method_invocation_return_dbus_error(req_info->context,
2633 "org.bluez.Error.Failed", err_msg);
2635 gatt_requests = g_slist_remove(gatt_requests, req_info);
2637 req_info->context = NULL;
2638 if (req_info->attr_path)
2639 g_free(req_info->attr_path);
2640 if (req_info->svc_path)
2641 g_free(req_info->svc_path);
2644 return BLUETOOTH_ERROR_NONE;
2647 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2649 GVariantBuilder *inner_builder = NULL;
2650 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2651 if (value_length > 0 && value != NULL) {
2652 for (i = 0; i < value_length; i++)
2653 g_variant_builder_add(inner_builder, "y", value[i]);
2655 g_dbus_method_invocation_return_value(req_info->context,
2656 g_variant_new("(ay)", inner_builder));
2657 g_variant_builder_unref(inner_builder);
2659 g_dbus_method_invocation_return_value(req_info->context, NULL);
2661 gatt_requests = g_slist_remove(gatt_requests, req_info);
2663 req_info->context = NULL;
2664 if (req_info->attr_path)
2665 g_free(req_info->attr_path);
2666 if (req_info->svc_path)
2667 g_free(req_info->svc_path);
2670 return BLUETOOTH_ERROR_NONE;
2673 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2674 bluetooth_device_address_t *unicast_address)
2676 GVariantBuilder *outer_builder;
2677 GVariantBuilder *invalidated_builder;
2678 GError *error = NULL;
2679 gboolean notify = TRUE;
2680 gboolean ret = TRUE;
2681 int err = BLUETOOTH_ERROR_NONE;
2682 gchar **line_argv = NULL;
2683 gchar *serv_path = NULL;
2684 char addr[20] = { 0 };
2686 line_argv = g_strsplit_set(char_path, "/", 0);
2687 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2689 if (!__bt_gatt_get_service_state(serv_path)) {
2690 BT_DBG("service not registered for this characteristic \n");
2692 g_strfreev(line_argv);
2693 return BLUETOOTH_ERROR_INTERNAL;
2698 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2699 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2701 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2702 g_variant_new("b", notify));
2704 if (unicast_address) {
2705 _bt_convert_addr_type_to_string(addr,
2706 (unsigned char *)unicast_address->addr);
2708 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2709 g_variant_new("s", addr));
2711 BT_DBG("Set characteristic Notification \n");
2712 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2714 "org.freedesktop.DBus.Properties",
2715 "PropertiesChanged",
2716 g_variant_new("(sa{sv}as)",
2717 "org.bluez.GattCharacteristic1",
2718 outer_builder, invalidated_builder),
2722 if (error != NULL) {
2723 BT_ERR("D-Bus API failure: errCode[%x], \
2725 error->code, error->message);
2726 g_clear_error(&error);
2728 err = BLUETOOTH_ERROR_INTERNAL;
2731 g_strfreev(line_argv);
2732 g_variant_builder_unref(outer_builder);
2733 g_variant_builder_unref(invalidated_builder);