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 (event == 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);
288 g_varaiant_unref(var);
291 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
292 g_dbus_message_set_body(msg, parameters);
293 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
295 BT_ERR("D-Bus API failure: errCode[%x], \
297 error->code, error->message);
298 g_clear_error(&error);
300 return BLUETOOTH_ERROR_INTERNAL;
302 return BLUETOOTH_ERROR_NONE;
306 #ifdef TIZEN_FEATURE_BT_OTP
307 static int __bt_send_event_to_otp(int event, GVariant *var)
309 GError *error = NULL;
310 GVariant *parameters = NULL;
311 GDBusMessage *msg = NULL;
315 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
317 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
318 GVariantBuilder *inner_builder;
319 GVariantBuilder *invalidated_builder;
321 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
322 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
324 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
326 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
328 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
329 g_variant_builder_unref(invalidated_builder);
330 g_variant_builder_unref(inner_builder);
331 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
332 GVariantBuilder *inner_builder;
333 GVariantBuilder *invalidated_builder;
335 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
336 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
338 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
340 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
342 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
343 g_variant_builder_unref(invalidated_builder);
344 g_variant_builder_unref(inner_builder);
345 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
346 GVariantBuilder *inner_builder;
347 GVariantBuilder *invalidated_builder;
349 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
350 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
352 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
354 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
356 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
357 g_variant_builder_unref(invalidated_builder);
358 g_variant_builder_unref(inner_builder);
361 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
362 g_dbus_message_set_body(msg, parameters);
363 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
365 BT_ERR("D-Bus API failure: errCode[%x], \
367 error->code, error->message);
368 g_clear_error(&error);
370 return BLUETOOTH_ERROR_INTERNAL;
372 return BLUETOOTH_ERROR_NONE;
376 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
378 const gchar *object_path,
379 const gchar *interface_name,
380 const gchar *method_name,
381 GVariant *parameters,
382 GDBusMethodInvocation *invocation,
389 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
390 BT_DBG("Getting values for service, chars and descriptors");
392 GVariantBuilder *builder;
393 GVariantBuilder *inner_builder1 = NULL;
394 GVariant *svc_char = NULL;
397 builder = g_variant_builder_new(
398 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
400 /* Prepare inner builder for GattService1 interface */
402 len = g_slist_length(gatt_services);
404 for (i = 0; i <= len; i++) {
405 GVariantBuilder *svc_builder = NULL;
406 GVariantBuilder *inner_builder = NULL;
408 if (register_pending_cnt > 1)
409 l1 = g_slist_nth(gatt_services, len - register_pending_cnt);
411 l1 = g_slist_last(gatt_services);
413 register_pending_cnt--;
416 BT_ERR("gatt service list is NULL");
417 g_dbus_method_invocation_return_value(invocation, NULL);
421 struct gatt_service_info *serv_info = l1->data;
422 if (serv_info == NULL) {
423 BT_ERR("service info value is NULL");
424 g_dbus_method_invocation_return_value(invocation, NULL);
428 /* Prepare inner builder for GattService1 interface */
429 BT_DBG("Creating builder for service");
430 svc_builder = g_variant_builder_new(
431 G_VARIANT_TYPE("a{sa{sv}}"));
432 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
434 g_variant_builder_add(inner_builder, "{sv}", "UUID",
435 g_variant_new_string(serv_info->service_uuid));
437 g_variant_builder_add(inner_builder, "{sv}", "Primary",
438 g_variant_new_boolean(serv_info->is_svc_primary));
441 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
442 BT_DBG("Adding Charatarisitcs list");
443 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
444 struct gatt_char_info *char_info = l4->data;
445 g_variant_builder_add(inner_builder1, "o",
446 char_info->char_path);
447 BT_DBG("%s", char_info->char_path);
450 svc_char = g_variant_new("ao", inner_builder1);
451 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
454 g_variant_builder_add(svc_builder, "{sa{sv}}",
458 g_variant_builder_add(builder, "{oa{sa{sv}}}",
459 serv_info->serv_path,
462 g_variant_builder_unref(inner_builder1);
464 /* Prepare inner builder for GattCharacteristic1 interface */
466 GSList *l2 = serv_info->char_data;
467 BT_DBG("Creating builder for characteristics \n");
470 BT_DBG("characteristic data is NULL");
472 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
474 GVariantBuilder *char_builder = NULL;
475 GVariantBuilder *inner_builder = NULL;
476 GVariantBuilder *builder1 = NULL;
477 GVariantBuilder *builder2 = NULL;
478 GVariantBuilder *builder3 = NULL;
479 GVariant *char_val = NULL;
480 GVariant *flags_val = NULL;
481 GVariant *char_desc = NULL;
482 char *unicast = NULL;
483 gboolean notify = FALSE;
486 char_builder = g_variant_builder_new(
489 inner_builder = g_variant_builder_new(
493 struct gatt_char_info *char_info = l2->data;
494 if (char_info == NULL) {
495 BT_ERR("char_info is NULL");
500 g_variant_builder_add(inner_builder, "{sv}", "UUID",
501 g_variant_new_string(char_info->char_uuid));
503 g_variant_builder_add(inner_builder, "{sv}", "Service",
504 g_variant_new("o", serv_info->serv_path));
506 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
508 if (char_info->char_value != NULL) {
509 for (i = 0; i < char_info->value_length; i++) {
510 g_variant_builder_add(builder1, "y",
511 char_info->char_value[i]);
513 char_val = g_variant_new("ay", builder1);
514 g_variant_builder_add(inner_builder, "{sv}",
518 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
520 for (i = 0; i < char_info->flags_length; i++) {
521 g_variant_builder_add(builder2, "s",
522 char_info->char_flags[i]);
525 flags_val = g_variant_new("as", builder2);
526 g_variant_builder_add(inner_builder, "{sv}", "Flags",
530 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
531 g_variant_new("b", notify));
534 unicast = g_strdup("00:00:00:00:00:00");
535 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
536 g_variant_new("s", unicast));
539 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
540 BT_DBG("Adding Descriptors list");
542 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
543 struct gatt_desc_info *desc_info = l4->data;
544 g_variant_builder_add(builder3, "o",
545 desc_info->desc_path);
546 BT_DBG("%s", desc_info->desc_path);
549 char_desc = g_variant_new("ao", builder3);
550 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
553 g_variant_builder_add(char_builder, "{sa{sv}}",
554 GATT_CHAR_INTERFACE , inner_builder);
555 g_variant_builder_add(builder, "{oa{sa{sv}}}",
556 char_info->char_path, char_builder);
558 /*Prepare inner builder for GattDescriptor1 interface*/
560 GSList *l3 = char_info->desc_data;
563 BT_DBG("descriptor data is NULL");
565 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
567 BT_DBG("Creating builder for descriptor \n");
569 GVariantBuilder *desc_builder = NULL;
570 GVariantBuilder *inner_builder = NULL;
571 GVariantBuilder *builder1 = NULL;
572 GVariantBuilder *builder2 = NULL;
573 GVariant *desc_val = NULL;
575 desc_builder = g_variant_builder_new(
578 inner_builder = g_variant_builder_new(
582 struct gatt_desc_info *desc_info = l3->data;
583 if (desc_info == NULL) {
584 BT_ERR("desc_info is NULL");
589 g_variant_builder_add(inner_builder,
591 g_variant_new_string(
592 desc_info->desc_uuid));
595 g_variant_builder_add(inner_builder, "{sv}",
598 char_info->char_path));
601 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
603 if (desc_info->desc_value != NULL) {
604 for (i = 0; i < desc_info->value_length; i++) {
605 g_variant_builder_add(builder1, "y",
606 desc_info->desc_value[i]);
608 desc_val = g_variant_new("ay", builder1);
609 g_variant_builder_add(inner_builder, "{sv}",
614 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
616 for (i = 0; i < desc_info->flags_length; i++) {
617 g_variant_builder_add(builder2, "s",
618 desc_info->desc_flags[i]);
621 flags_val = g_variant_new("as", builder2);
622 g_variant_builder_add(inner_builder, "{sv}", "Flags",
625 g_variant_builder_add(desc_builder, "{sa{sv}}",
629 g_variant_builder_add(builder, "{oa{sa{sv}}}",
630 desc_info->desc_path,
633 /*unref descriptor builder pointers*/
634 g_variant_builder_unref(builder1);
635 g_variant_builder_unref(builder2);
636 g_variant_builder_unref(inner_builder);
637 g_variant_builder_unref(desc_builder);
642 /*unref char builder pointers*/
643 g_variant_builder_unref(builder1);
644 g_variant_builder_unref(builder2);
645 g_variant_builder_unref(builder3);
646 g_variant_builder_unref(inner_builder);
647 g_variant_builder_unref(char_builder);
650 /*unref service builder pointers*/
651 g_variant_builder_unref(inner_builder);
652 g_variant_builder_unref(svc_builder);
655 /* Return builder as method reply */
656 BT_DBG("Sending gatt service builder values to Bluez");
657 g_dbus_method_invocation_return_value(invocation,
664 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
668 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
669 struct gatt_service_info *serv_info = l1->data;
671 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
672 struct gatt_char_info *char_info = l2->data;
674 if (g_strcmp0(char_info->char_path, char_path)
679 BT_ERR("Gatt service not found");
683 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
685 GSList *l1, *l2, *l3;
687 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
688 struct gatt_service_info *serv_info = l1->data;
690 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
691 struct gatt_char_info *char_info = l2->data;
693 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
694 struct gatt_desc_info *desc_info = l3->data;
696 if (g_strcmp0(desc_info->desc_path, desc_path)
702 BT_ERR("Gatt service not found");
706 static void __bt_gatt_char_method_call(GDBusConnection *connection,
708 const gchar *object_path,
709 const gchar *interface_name,
710 const gchar *method_name,
711 GVariant *parameters,
712 GDBusMethodInvocation *invocation,
716 if (g_strcmp0(method_name, "ReadValue") == 0) {
720 bt_gatt_read_req_t read_req = {0, };
721 bt_user_info_t *user_info = NULL;
722 struct gatt_req_info *req_info = NULL;
723 struct gatt_service_info *svc_info = NULL;
724 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
725 GVariant *param = NULL;
728 BT_DBG("Application path = %s", object_path);
729 BT_DBG("Sender = %s", sender);
731 user_info = _bt_get_user_data(BT_COMMON);
732 if (user_info == NULL) {
733 BT_INFO("No callback is set for %s", object_path);
734 g_dbus_method_invocation_return_value(invocation, NULL);
738 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
739 if (svc_info == NULL) {
740 BT_ERR("Coudn't find service for %s", object_path);
741 g_dbus_method_invocation_return_value(invocation, NULL);
745 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
746 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
748 read_req.att_handle = (char *)object_path;
749 read_req.address = addr;
750 read_req.req_id = req_id;
751 read_req.offset = offset;
752 read_req.service_handle = svc_info->serv_path;
754 /* Store requets information */
755 req_info = g_new0(struct gatt_req_info, 1);
756 req_info->attr_path = g_strdup(object_path);
757 req_info->svc_path = g_strdup(read_req.service_handle);
758 req_info->request_id = req_id;
759 req_info->offset = offset;
760 req_info->context = invocation;
761 gatt_requests = g_slist_append(gatt_requests, req_info);
763 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
764 BLUETOOTH_ERROR_NONE, &read_req,
765 user_info->cb, user_info->user_data);
767 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
768 param = g_variant_new("(sssyq)",
770 read_req.service_handle,
774 #ifdef TIZEN_FEATURE_BT_HPS
775 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
777 #ifdef TIZEN_FEATURE_BT_OTP
778 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
782 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
783 GVariant *var = NULL;
787 gboolean response_needed = FALSE;
788 bt_gatt_value_change_t value_change = {0, };
789 bt_user_info_t *user_info = NULL;
791 struct gatt_service_info *svc_info = NULL;
792 struct gatt_req_info *req_info = NULL;
793 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
794 GVariant *param = NULL;
797 BT_DBG("WriteValue");
798 BT_DBG("Application path = %s", object_path);
799 BT_DBG("Sender = %s", sender);
801 g_variant_get(parameters, "(&suqb@ay)",
802 &addr, &req_id, &offset, &response_needed, &var);
803 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
805 user_info = _bt_get_user_data(BT_COMMON);
807 BT_INFO("No callback is set for %s", object_path);
808 g_variant_unref(var);
810 g_dbus_method_invocation_return_value(invocation, NULL);
812 g_object_unref(invocation);
816 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
817 if (svc_info == NULL) {
818 BT_ERR("Coudn't find service for %s", object_path);
819 g_variant_unref(var);
821 g_dbus_method_invocation_return_value(invocation, NULL);
823 g_object_unref(invocation);
827 value_change.att_handle = (char *)object_path;
828 value_change.address = addr;
829 value_change.service_handle = svc_info->serv_path;
830 value_change.offset = offset;
831 value_change.req_id = req_id;
832 value_change.response_needed = response_needed;
834 len = g_variant_get_size(var);
838 value_change.att_value = (guint8 *)g_malloc(len);
840 data = (char *)g_variant_get_data(var);
841 memcpy(value_change.att_value, data, len);
843 value_change.val_len = len;
845 if (response_needed) {
846 /* Store requets information */
847 req_info = g_new0(struct gatt_req_info, 1);
848 req_info->attr_path = g_strdup(object_path);
849 req_info->svc_path = g_strdup(value_change.service_handle);
850 req_info->request_id = req_id;
851 req_info->offset = offset;
852 req_info->context = invocation;
853 gatt_requests = g_slist_append(gatt_requests, req_info);
855 g_object_unref(invocation);
859 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
860 BLUETOOTH_ERROR_NONE, &value_change,
861 user_info->cb, user_info->user_data);
863 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
866 svc_path = g_strdup(svc_info->serv_path);
867 param = g_variant_new("(sssyq@ay)",
874 #ifdef TIZEN_FEATURE_BT_HPS
875 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
877 #ifdef TIZEN_FEATURE_BT_OTP
878 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
885 g_free(value_change.att_value);
886 g_variant_unref(var);
888 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
889 bt_user_info_t *user_info = NULL;
890 bt_gatt_char_notify_change_t notify_change = {0, };
891 #if TIZEN_FEATURE_BT_OTP
892 GVariant *param = NULL;
894 BT_DBG("StartNotify");
895 user_info = _bt_get_user_data(BT_COMMON);
896 if (user_info != NULL) {
897 struct gatt_service_info *svc_info = NULL;
898 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
900 notify_change.service_handle = svc_info->serv_path;
901 notify_change.att_handle = (char *)object_path;
902 notify_change.att_notify = TRUE;
904 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
905 BLUETOOTH_ERROR_NONE, ¬ify_change,
906 user_info->cb, user_info->user_data);
907 #if TIZEN_FEATURE_BT_OTP
908 param = g_variant_new("(ssb)",
909 notify_change.att_handle,
910 notify_change.service_handle,
911 notify_change.att_notify);
912 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
916 g_object_unref(invocation);
918 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
919 bt_user_info_t *user_info = NULL;
920 bt_gatt_char_notify_change_t notify_change = {0, };
921 #if TIZEN_FEATURE_BT_OTP
922 GVariant *param = NULL;
924 BT_DBG("StopNotify");
925 user_info = _bt_get_user_data(BT_COMMON);
926 if (user_info != NULL) {
927 struct gatt_service_info *svc_info = NULL;
928 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
930 notify_change.service_handle = svc_info->serv_path;
931 notify_change.att_handle = (char *)object_path;
932 notify_change.att_notify = FALSE;
934 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
935 BLUETOOTH_ERROR_NONE, ¬ify_change,
936 user_info->cb, user_info->user_data);
937 #if TIZEN_FEATURE_BT_OTP
938 param = g_variant_new("(ssb)",
939 notify_change.att_handle,
940 notify_change.service_handle,
941 notify_change.att_notify);
942 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
946 g_object_unref(invocation);
948 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
950 bt_gatt_indicate_confirm_t confirm = {0, };
951 bt_user_info_t *user_info = NULL;
952 gboolean complete = FALSE;
953 struct gatt_service_info *svc_info = NULL;
955 BT_DBG("IndicateConfirm");
956 BT_DBG("Application path = %s", object_path);
957 BT_DBG("Sender = %s", sender);
959 g_variant_get(parameters, "(&sb)", &addr, &complete);
960 BT_DBG("Remote Device address number = %s", addr);
962 confirm.att_handle = (char *)object_path;
963 confirm.address = addr;
964 confirm.complete = complete;
966 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
967 if (svc_info != NULL) {
968 confirm.service_handle = svc_info->serv_path;
970 user_info = _bt_get_user_data(BT_COMMON);
971 if (user_info != NULL) {
973 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
974 BLUETOOTH_ERROR_NONE, &confirm,
975 user_info->cb, user_info->user_data);
980 g_dbus_method_invocation_return_value(invocation, NULL);
983 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
985 const gchar *object_path,
986 const gchar *interface_name,
987 const gchar *method_name,
988 GVariant *parameters,
989 GDBusMethodInvocation *invocation,
992 if (g_strcmp0(method_name, "ReadValue") == 0) {
996 bt_gatt_read_req_t read_req = {0, };
997 bt_user_info_t *user_info = NULL;
998 struct gatt_req_info *req_info = NULL;
999 struct gatt_service_info *svc_info = NULL;
1001 BT_DBG("ReadValue");
1002 BT_DBG("Application path = %s", object_path);
1003 BT_DBG("Sender = %s", sender);
1005 user_info = _bt_get_user_data(BT_COMMON);
1006 if (user_info == NULL) {
1007 BT_INFO("No callback is set for %s", object_path);
1008 g_dbus_method_invocation_return_value(invocation, NULL);
1012 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1013 if (svc_info == NULL) {
1014 BT_ERR("Coudn't find service for %s", object_path);
1015 g_dbus_method_invocation_return_value(invocation, NULL);
1019 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1020 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1022 read_req.att_handle = (char *)object_path;
1023 read_req.address = addr;
1024 read_req.req_id = req_id;
1025 read_req.offset = offset;
1026 read_req.service_handle = svc_info->serv_path;
1028 /* Store requets information */
1029 req_info = g_new0(struct gatt_req_info, 1);
1030 req_info->attr_path = g_strdup(object_path);
1031 req_info->svc_path = g_strdup(read_req.service_handle);
1032 req_info->request_id = req_id;
1033 req_info->offset = offset;
1034 req_info->context = invocation;
1035 gatt_requests = g_slist_append(gatt_requests, req_info);
1037 _bt_common_event_cb(
1038 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1039 BLUETOOTH_ERROR_NONE, &read_req,
1040 user_info->cb, user_info->user_data);
1043 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1044 GVariant *var = NULL;
1048 gboolean response_needed = FALSE;
1049 bt_gatt_value_change_t value_change = {0, };
1050 bt_user_info_t *user_info = NULL;
1052 struct gatt_service_info *svc_info = NULL;
1053 struct gatt_req_info *req_info = NULL;
1055 BT_DBG("WriteValue");
1056 BT_DBG("Application path = %s", object_path);
1057 BT_DBG("Sender = %s", sender);
1059 g_variant_get(parameters, "(&suqb@ay)",
1060 &addr, &req_id, &offset, &response_needed, &var);
1061 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1063 user_info = _bt_get_user_data(BT_COMMON);
1064 if (user_info == NULL) {
1065 BT_INFO("No callback is set for %s", object_path);
1066 g_variant_unref(var);
1067 if (response_needed)
1068 g_dbus_method_invocation_return_value(invocation, NULL);
1070 g_object_unref(invocation);
1074 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1075 if (svc_info == NULL) {
1076 BT_ERR("Coudn't find service for %s", object_path);
1077 g_variant_unref(var);
1078 if (response_needed)
1079 g_dbus_method_invocation_return_value(invocation, NULL);
1081 g_object_unref(invocation);
1085 value_change.att_handle = (char *)object_path;
1086 value_change.address = addr;
1087 value_change.service_handle = svc_info->serv_path;
1088 value_change.offset = offset;
1089 value_change.req_id = req_id;
1090 value_change.response_needed = response_needed;
1092 len = g_variant_get_size(var);
1096 value_change.att_value = (guint8 *)g_malloc(len);
1098 data = (char *)g_variant_get_data(var);
1099 memcpy(value_change.att_value, data, len);
1101 value_change.val_len = len;
1103 if (response_needed) {
1104 /* Store requets information */
1105 req_info = g_new0(struct gatt_req_info, 1);
1106 req_info->attr_path = g_strdup(object_path);
1107 req_info->svc_path = g_strdup(value_change.service_handle);
1108 req_info->request_id = req_id;
1109 req_info->offset = offset;
1110 req_info->context = invocation;
1111 gatt_requests = g_slist_append(gatt_requests, req_info);
1113 g_object_unref(invocation);
1116 _bt_common_event_cb(
1117 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1118 BLUETOOTH_ERROR_NONE, &value_change,
1119 user_info->cb, user_info->user_data);
1121 g_free(value_change.att_value);
1122 g_variant_unref(var);
1127 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1130 GError *error = NULL;
1131 GVariantBuilder *array_builder;
1133 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1134 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1135 g_variant_builder_add(array_builder, "s", interface);
1137 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1138 "org.freedesktop.Dbus.Objectmanager",
1139 "InterfacesRemoved",
1140 g_variant_new("(oas)",
1141 object_path, array_builder),
1145 if (error != NULL) {
1146 /* dbus gives error cause */
1147 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1148 error->code, error->message);
1149 g_clear_error(&error);
1152 g_variant_builder_unref(array_builder);
1157 static const GDBusInterfaceVTable desc_interface_vtable = {
1158 __bt_gatt_desc_method_call,
1163 static const GDBusInterfaceVTable char_interface_vtable = {
1164 __bt_gatt_char_method_call,
1169 static const GDBusInterfaceVTable serv_interface_vtable = {
1175 static const GDBusInterfaceVTable manager_interface_vtable = {
1176 __bt_gatt_manager_method_call,
1181 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1182 const gchar *introspection_data)
1185 GDBusNodeInfo *node_info = NULL;
1187 if (introspection_data == NULL)
1191 BT_DBG("Create new node info");
1192 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1195 BT_ERR("Unable to create node: %s", err->message);
1196 g_clear_error(&err);
1203 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1204 const char *service_path)
1208 for (l = gatt_services; l != NULL; l = l->next) {
1209 struct gatt_service_info *info = l->data;
1211 if (g_strcmp0(info->serv_path, service_path) == 0)
1214 BT_ERR("Gatt service not found");
1218 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1219 const char *service_path, const char *char_path)
1223 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1224 struct gatt_service_info *serv_info = l1->data;
1226 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1228 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1229 struct gatt_char_info *char_info = l2->data;
1231 if (g_strcmp0(char_info->char_path, char_path)
1235 BT_ERR("Gatt characteristic not found");
1239 BT_ERR("Gatt service not found");
1243 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1244 const char *serv_path, const char *char_path,
1245 const char *desc_path)
1247 GSList *l1, *l2, *l3;
1249 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1250 struct gatt_service_info *serv_info = l1->data;
1252 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1253 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1254 struct gatt_char_info *char_info = l2->data;
1256 if (g_strcmp0(char_info->char_path, char_path)
1258 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1259 struct gatt_desc_info *desc_info = l3->data;
1260 if (g_strcmp0(desc_info->desc_path,
1269 BT_ERR("Gatt descriptor not found");
1273 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1277 for (l = gatt_requests; l != NULL; l = l->next) {
1278 struct gatt_req_info *req_info = l->data;
1280 if (req_info && req_info->request_id == request_id)
1283 BT_ERR("Gatt Request not found");
1287 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1288 const gchar *path, const gchar *interface)
1294 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1299 BT_ERR("Unable to connect to gdbus: %s", err->message);
1300 g_clear_error(&err);
1305 proxy = g_dbus_proxy_new_sync(g_conn,
1306 G_DBUS_PROXY_FLAGS_NONE, NULL,
1308 interface, NULL, &err);
1312 BT_ERR("Unable to create proxy: %s", err->message);
1313 g_clear_error(&err);
1317 manager_gproxy = proxy;
1322 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1323 const gchar *path, const gchar *interface)
1325 return (manager_gproxy) ? manager_gproxy :
1326 __bt_gatt_gdbus_init_manager_proxy(service,
1330 int bluetooth_gatt_convert_prop2string(
1331 bt_gatt_characteristic_property_t properties,
1332 char *char_properties[])
1336 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
1337 char_properties[flag_count] = g_strdup("broadcast");
1340 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
1341 char_properties[flag_count] = g_strdup("read");
1344 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
1345 char_properties[flag_count] = g_strdup("write-without-response");
1348 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
1349 char_properties[flag_count] = g_strdup("write");
1352 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
1353 char_properties[flag_count] = g_strdup("notify");
1356 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
1357 char_properties[flag_count] = g_strdup("indicate");
1360 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
1361 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
1364 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
1365 char_properties[flag_count] = g_strdup("reliable-write");
1368 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
1369 char_properties[flag_count] = g_strdup("writable-auxiliaries");
1372 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
1373 char_properties[flag_count] = g_strdup("encrypt-read");
1376 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
1377 char_properties[flag_count] = g_strdup("encrypt-write");
1380 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
1381 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1384 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
1385 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1389 if (flag_count == 0) {
1390 char_properties[flag_count] = g_strdup("read");
1397 int bluetooth_gatt_convert_perm2string(
1398 bt_gatt_permission_t properties,
1399 char *char_properties[])
1403 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
1404 char_properties[flag_count] = g_strdup("read");
1407 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
1408 char_properties[flag_count] = g_strdup("write");
1411 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
1412 char_properties[flag_count] = g_strdup("encrypt-read");
1415 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
1416 char_properties[flag_count] = g_strdup("encrypt-write");
1419 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
1420 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1423 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
1424 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1428 if (flag_count == 0) {
1429 char_properties[flag_count] = g_strdup("read");
1436 static void __bt_gatt_set_service_state(const char *service_path,
1439 struct gatt_service_info *svc_info = NULL;
1440 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1442 if (svc_info != NULL) {
1443 BT_DBG("Updating the gatt service register state %d", state);
1444 svc_info->is_svc_registered = state;
1448 BT_DBG("gatt service not found");
1451 static gboolean __bt_gatt_get_service_state(const char *service_path)
1453 struct gatt_service_info *svc_info = NULL;
1455 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1457 if (svc_info != NULL) {
1458 BT_DBG("Return the state of the gatt service %d",
1459 svc_info->is_svc_registered);
1460 return svc_info->is_svc_registered;
1463 BT_DBG("gatt service info is NULL");
1467 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1469 GError *error = NULL;
1471 GVariantIter *iter = NULL;
1472 const gchar *key = NULL;
1473 GVariant *value = NULL;
1474 const gchar *service = NULL;
1475 const gchar *characteristic = NULL;
1476 const gchar *descriptor = NULL;
1480 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1482 if (result == NULL) {
1483 /* dBUS-RPC is failed */
1484 BT_ERR("Dbus-RPC is failed\n");
1486 if (error != NULL) {
1487 /* dBUS gives error cause */
1488 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1489 error->code, error->message);
1490 g_clear_error(&error);
1493 char *char_cmp = NULL;
1494 g_variant_get(result, "(a{sv})", &iter);
1495 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1497 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1498 if (g_strcmp0(key, "Service") == 0) {
1499 service = g_variant_get_string(value, NULL);
1500 BT_DBG("Service %s", service);
1501 } else if (g_strcmp0(key, char_cmp) == 0) {
1502 characteristic = g_variant_get_string(value, NULL);
1504 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1505 BT_DBG("%s", characteristic);
1506 } else if (g_strcmp0(key, "Descriptor") == 0) {
1507 descriptor = g_variant_get_string(value, NULL);
1508 BT_DBG("Descriptor %s", descriptor);
1511 g_variant_iter_free(iter);
1513 /* TODO: Store the service informationa and
1514 * Send respponse to CAPI layer. */
1516 g_variant_unref(result);
1521 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1523 BT_INFO("RegisterApplication is completed");
1525 GError *error = NULL;
1528 register_pending_cnt = 0;
1530 if (register_cancel) {
1531 g_object_unref(register_cancel);
1532 register_cancel = NULL;
1535 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1537 if (result == NULL) {
1538 /* dBUS-RPC is failed */
1539 BT_ERR("Dbus-RPC is failed\n");
1541 if (error != NULL) {
1542 /* dBUS gives error cause */
1543 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1544 error->code, error->message);
1545 g_clear_error(&error);
1548 g_variant_unref(result);
1552 static int __bt_gatt_unregister_service(const char *service_path)
1554 if (!__bt_gatt_get_service_state(service_path)) {
1555 BT_DBG("service not registered \n");
1556 return BLUETOOTH_ERROR_NOT_FOUND;
1559 return BLUETOOTH_ERROR_NONE;
1562 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1564 GDBusProxy *proxy = NULL;
1566 if (is_server_started) {
1570 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1571 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1573 if (proxy == NULL || app_path == NULL)
1574 return BLUETOOTH_ERROR_INTERNAL;
1576 BT_INFO("UnregisterApplication");
1578 is_server_started = false;
1580 /* Async Call to Unregister Service */
1581 ret = g_dbus_proxy_call_sync(proxy,
1582 "UnregisterApplication",
1583 g_variant_new("(o)",
1585 G_DBUS_CALL_FLAGS_NONE, -1,
1589 /* dBUS-RPC is failed */
1590 BT_ERR("dBUS-RPC is failed");
1592 /* dBUS gives error cause */
1593 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1594 err->code, err->message);
1596 g_clear_error(&err);
1598 return BLUETOOTH_ERROR_INTERNAL;
1600 g_variant_unref(ret);
1602 BT_INFO("UnregisterApplication is completed");
1604 return BLUETOOTH_ERROR_NONE;
1607 BT_INFO("GATT server not started");
1608 return BLUETOOTH_ERROR_NONE;
1611 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1613 GDBusConnection *local_system_gconn = NULL;
1617 if (g_conn == NULL) {
1618 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1619 if (address == NULL) {
1621 BT_ERR("Failed to get bus address: %s", err->message);
1622 g_clear_error(&err);
1627 g_conn = g_dbus_connection_new_for_address_sync(address,
1628 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1629 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1630 NULL, /* GDBusAuthObserver */
1636 BT_ERR("Unable to connect to dbus: %s", err->message);
1637 g_clear_error(&err);
1641 } else if (g_dbus_connection_is_closed(g_conn)) {
1642 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1643 if (address == NULL) {
1645 BT_ERR("Failed to get bus address: %s", err->message);
1646 g_clear_error(&err);
1651 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1652 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1653 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1654 NULL, /* GDBusAuthObserver */
1658 if (!local_system_gconn) {
1659 BT_ERR("Unable to connect to dbus: %s", err->message);
1660 g_clear_error(&err);
1663 g_conn = local_system_gconn;
1669 BT_EXPORT_API int bluetooth_gatt_init(void)
1671 GDBusConnection *conn;
1672 GError *error = NULL;
1673 GDBusNodeInfo *node_info = NULL;
1675 if (app_path != NULL) {
1676 BT_ERR("app path already exists! initialized");
1677 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1680 if (owner_id == 0) {
1681 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1682 BT_GATT_SERVICE_NAME,
1683 G_BUS_NAME_OWNER_FLAGS_NONE,
1684 NULL, NULL, NULL, NULL, NULL);
1687 BT_DBG("owner_id is [%d]", owner_id);
1688 app_path = g_strdup_printf("/com/%d", getpid());
1692 conn = __bt_gatt_get_gdbus_connection();
1694 BT_ERR("Unable to get connection");
1698 /* Register ObjectManager interface */
1699 node_info = __bt_gatt_create_method_node_info(
1700 manager_introspection_xml);
1701 if (node_info == NULL) {
1702 BT_ERR("failed to get node info");
1706 if (manager_id == 0) {
1707 BT_INFO("manager_id does not exists");
1709 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1710 node_info->interfaces[0],
1711 &manager_interface_vtable,
1712 NULL, NULL, &error);
1714 g_dbus_node_info_unref(node_info);
1715 if (manager_id == 0) {
1716 BT_ERR("failed to register: %s", error->message);
1717 g_error_free(error);
1721 return BLUETOOTH_ERROR_NONE;
1725 g_bus_unown_name(owner_id);
1732 __bt_gatt_close_gdbus_connection();
1734 return BLUETOOTH_ERROR_INTERNAL;
1737 BT_EXPORT_API int bluetooth_gatt_deinit()
1739 int ret = BLUETOOTH_ERROR_NONE;
1741 if (register_cancel) {
1742 g_cancellable_cancel(register_cancel);
1743 g_object_unref(register_cancel);
1744 register_cancel = NULL;
1747 /* Unown gdbus bus */
1749 /* remove/unregister all services */
1750 BT_DBG("removing all registered gatt service\n");
1751 bluetooth_gatt_delete_services();
1753 /* unregister the exported interface for object manager */
1754 g_dbus_connection_unregister_object(g_conn,
1759 ret = bluetooth_gatt_unregister_application();
1760 if (ret != BLUETOOTH_ERROR_NONE)
1761 BT_ERR("Fail to unregister application\n");
1763 g_bus_unown_name(owner_id);
1769 BT_DBG("Gatt service deinitialized \n");
1771 g_slist_free(gatt_services);
1772 gatt_services = NULL;
1774 g_object_unref(manager_gproxy);
1775 manager_gproxy = NULL;
1777 __bt_gatt_close_gdbus_connection();
1782 __bt_gatt_close_gdbus_connection();
1784 return BLUETOOTH_ERROR_NOT_FOUND;
1787 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1790 GError *error = NULL;
1792 GDBusNodeInfo *node_info;
1794 GVariantBuilder *builder = NULL;
1795 GVariantBuilder *builder1 = NULL;
1796 GVariantBuilder *inner_builder = NULL;
1797 gboolean svc_primary = TRUE;
1798 struct gatt_service_info *serv_info = NULL;
1800 node_info = __bt_gatt_create_method_node_info(
1801 service_introspection_xml);
1802 if (node_info == NULL)
1803 return BLUETOOTH_ERROR_INTERNAL;
1805 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1806 BT_DBG("gatt service path is [%s]", path);
1808 object_id = g_dbus_connection_register_object(g_conn, path,
1809 node_info->interfaces[0],
1810 &serv_interface_vtable,
1811 NULL, NULL, &error);
1812 g_dbus_node_info_unref(node_info);
1814 if (object_id == 0) {
1815 BT_ERR("failed to register: %s", error->message);
1816 g_error_free(error);
1819 return BLUETOOTH_ERROR_INTERNAL;
1822 /* Add object_id/gatt service information; it's required at the time of
1823 * service unregister and Getmanagedobjects
1825 serv_info = g_new0(struct gatt_service_info, 1);
1827 serv_info->serv_path = g_strdup(path);
1828 serv_info->serv_id = object_id;
1829 serv_info->service_uuid = g_strdup(svc_uuid);
1830 serv_info->is_svc_registered = FALSE;
1831 serv_info->is_svc_primary = svc_primary;
1833 gatt_services = g_slist_append(gatt_services, serv_info);
1835 /* emit interfacesadded signal here for service path */
1836 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1837 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1839 g_variant_builder_add(inner_builder, "{sv}",
1840 "UUID", g_variant_new_string(svc_uuid));
1842 g_variant_builder_add(inner_builder, "{sv}",
1843 "Primary", g_variant_new_boolean(svc_primary));
1845 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1847 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1848 g_variant_new("ao", builder1));
1850 g_variant_builder_add(builder, "{sa{sv}}",
1851 GATT_SERV_INTERFACE, inner_builder);
1853 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1854 "org.freedesktop.Dbus.ObjectManager",
1856 g_variant_new("(oa{sa{sv}})",
1862 *svc_path = g_strdup(path);
1865 g_variant_builder_unref(inner_builder);
1866 g_variant_builder_unref(builder);
1867 g_variant_builder_unref(builder1);
1869 return BLUETOOTH_ERROR_NONE;
1872 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1873 const char *svc_path, const char *char_uuid,
1874 bt_gatt_permission_t permissions,
1875 bt_gatt_characteristic_property_t properties,
1879 GError *error = NULL;
1881 GDBusNodeInfo *node_info;
1883 GVariantBuilder *builder = NULL;
1884 GVariantBuilder *inner_builder = NULL;
1885 struct gatt_service_info *serv_info = NULL;
1886 struct gatt_char_info *char_info = NULL;
1887 GVariantBuilder *builder2 = NULL;
1888 GVariantBuilder *builder3 = NULL;
1889 GVariant *flags_val = NULL;
1891 char *char_flags[NUMBER_OF_FLAGS];
1896 new_service = FALSE;
1899 BT_DBG("gatt svc_path path is [%s]", svc_path);
1900 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1901 if (serv_info == NULL)
1902 return BLUETOOTH_ERROR_INVALID_PARAM;
1904 node_info = __bt_gatt_create_method_node_info(
1905 characteristics_introspection_xml);
1906 if (node_info == NULL)
1907 return BLUETOOTH_ERROR_INTERNAL;
1909 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1910 BT_DBG("gatt characteristic path is [%s]", path);
1912 object_id = g_dbus_connection_register_object(g_conn, path,
1913 node_info->interfaces[0],
1914 &char_interface_vtable,
1915 NULL, NULL, &error);
1916 g_dbus_node_info_unref(node_info);
1918 if (object_id == 0) {
1919 BT_ERR("failed to register: %s", error->message);
1920 g_error_free(error);
1923 return BLUETOOTH_ERROR_INTERNAL;
1926 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1927 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1928 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1929 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1930 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1931 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1932 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1933 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1935 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1937 char_info = g_new0(struct gatt_char_info, 1);
1939 char_info->char_path = g_strdup(path);
1940 char_info->char_id = object_id;
1941 char_info->char_uuid = g_strdup(char_uuid);
1943 for (i = 0; i < flag_count; i++)
1944 char_info->char_flags[i] = char_flags[i];
1947 char_info->flags_length = flag_count;
1949 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1951 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1952 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1954 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1955 g_variant_new("s", char_uuid));
1956 g_variant_builder_add(inner_builder, "{sv}", "Service",
1957 g_variant_new("o", svc_path));
1959 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1961 for (i = 0; i < flag_count; i++)
1962 g_variant_builder_add(builder2, "s", char_flags[i]);
1964 flags_val = g_variant_new("as", builder2);
1965 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1968 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1970 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1971 g_variant_new("ao", builder3));
1973 g_variant_builder_add(builder, "{sa{sv}}",
1974 GATT_CHAR_INTERFACE,
1977 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1978 "org.freedesktop.Dbus.ObjectManager",
1980 g_variant_new("(oa{sa{sv}})",
1984 *char_path = g_strdup(path);
1990 g_variant_builder_unref(inner_builder);
1991 g_variant_builder_unref(builder);
1992 g_variant_builder_unref(builder2);
1993 g_variant_builder_unref(builder3);
1995 return BLUETOOTH_ERROR_NONE;
1998 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1999 const char *characteristic, const char *char_value,
2002 gchar **line_argv = NULL;
2003 char *serv_path = NULL;
2004 struct gatt_char_info *char_info = NULL;
2005 GVariantBuilder *builder1 = NULL;
2006 GVariantBuilder *builder = NULL;
2007 GVariantBuilder *inner_builder = NULL;
2008 GVariant *char_val = NULL;
2009 GError *error = NULL;
2011 int res = BLUETOOTH_ERROR_NONE;
2013 line_argv = g_strsplit_set(characteristic, "/", 0);
2014 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2016 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
2018 if (char_info == NULL) {
2019 /* Fix : RESOURCE_LEAK */
2020 res = BLUETOOTH_ERROR_INVALID_PARAM;
2024 char_info->value_length = value_length;
2026 char_info->char_value = (char *)malloc(value_length);
2027 /* Fix : NULL_RETURNS */
2028 if (char_info->char_value == NULL) {
2029 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2033 for (i = 0; i < value_length; i++)
2034 char_info->char_value[i] = char_value[i];
2036 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2037 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2039 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2041 for (i = 0; i < value_length; i++)
2042 g_variant_builder_add(builder1, "y", char_value[i]);
2044 char_val = g_variant_new("ay", builder1);
2045 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
2047 g_variant_builder_add(builder, "{sa{sv}}",
2048 GATT_CHAR_INTERFACE,
2051 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2052 "org.freedesktop.Dbus.ObjectManager",
2054 g_variant_new("(oa{sa{sv}})",
2055 char_info->char_path, builder),
2058 g_variant_builder_unref(inner_builder);
2059 g_variant_builder_unref(builder);
2060 g_variant_builder_unref(builder1);
2062 g_strfreev(line_argv);
2068 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2069 const char *char_path, const char *desc_uuid,
2070 bt_gatt_permission_t permissions,
2073 static int desc_id = 1;
2074 GError *error = NULL;
2076 GDBusNodeInfo *node_info;
2078 GVariantBuilder *builder = NULL;
2079 GVariantBuilder *inner_builder = NULL;
2080 struct gatt_char_info *char_info = NULL;
2081 struct gatt_desc_info *desc_info = NULL;
2082 gchar **line_argv = NULL;
2084 GVariantBuilder *builder2 = NULL;
2085 GVariant *flags_val = NULL;
2087 char *desc_flags[NUMBER_OF_FLAGS];
2095 line_argv = g_strsplit_set(char_path, "/", 0);
2096 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2098 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2099 if (char_info == NULL) {
2100 g_strfreev(line_argv);
2102 return BLUETOOTH_ERROR_INVALID_PARAM;
2105 node_info = __bt_gatt_create_method_node_info(
2106 descriptor_introspection_xml);
2107 if (node_info == NULL) {
2108 g_strfreev(line_argv);
2110 return BLUETOOTH_ERROR_INTERNAL;
2113 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2114 BT_DBG("gatt descriptor path is [%s]", path);
2116 object_id = g_dbus_connection_register_object(g_conn, path,
2117 node_info->interfaces[0],
2118 &desc_interface_vtable,
2119 NULL, NULL, &error);
2120 g_dbus_node_info_unref(node_info);
2122 if (object_id == 0) {
2123 BT_ERR("failed to register: %s", error->message);
2124 g_error_free(error);
2126 g_strfreev(line_argv);
2129 return BLUETOOTH_ERROR_INTERNAL;
2132 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2134 desc_info = g_new0(struct gatt_desc_info, 1);
2136 desc_info->desc_path = g_strdup(path);
2137 desc_info->desc_id = object_id;
2138 desc_info->desc_uuid = g_strdup(desc_uuid);
2140 for (i = 0; i < flag_count; i++)
2141 desc_info->desc_flags[i] = desc_flags[i];
2143 desc_info->flags_length = flag_count;
2145 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2147 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2148 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2150 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2151 g_variant_new("s", desc_uuid));
2152 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2153 g_variant_new("o", char_path));
2155 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2157 for (i = 0; i < flag_count; i++)
2158 g_variant_builder_add(builder2, "s", desc_flags[i]);
2160 flags_val = g_variant_new("as", builder2);
2161 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2164 g_variant_builder_add(builder, "{sa{sv}}",
2165 GATT_DESC_INTERFACE,
2168 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2169 "org.freedesktop.Dbus.ObjectManager",
2171 g_variant_new("(oa{sa{sv}})",
2175 *desc_path = g_strdup(path);
2179 g_strfreev(line_argv);
2180 g_variant_builder_unref(inner_builder);
2181 g_variant_builder_unref(builder);
2182 g_variant_builder_unref(builder2);
2184 return BLUETOOTH_ERROR_NONE;
2187 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2188 const char *desc_path, const char *desc_value,
2191 GError *error = NULL;
2192 GVariantBuilder *builder = NULL;
2193 GVariantBuilder *inner_builder = NULL;
2194 GVariantBuilder *builder1 = NULL;
2195 struct gatt_desc_info *desc_info = NULL;
2196 gchar **line_argv = NULL;
2198 GVariant *desc_val = NULL;
2199 char *serv_path = NULL;
2202 line_argv = g_strsplit_set(desc_path, "/", 0);
2203 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2204 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2206 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2208 /* Free the allocated memory */
2209 g_strfreev(line_argv);
2213 /* Fix : NULL_RETURNS */
2214 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2216 desc_info->desc_value = (char *)malloc(value_length);
2218 /* Fix : NULL_RETURNS */
2219 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2221 for (i = 0; i < value_length; i++)
2222 desc_info->desc_value[i] = desc_value[i];
2224 desc_info->value_length = value_length;
2226 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2227 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2229 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2231 for (i = 0; i < value_length; i++)
2232 g_variant_builder_add(builder1, "y", desc_value[i]);
2234 desc_val = g_variant_new("ay", builder1);
2235 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2237 g_variant_builder_add(builder, "{sa{sv}}",
2238 GATT_DESC_INTERFACE,
2241 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2242 "org.freedesktop.Dbus.ObjectManager",
2244 g_variant_new("(oa{sa{sv}})",
2245 desc_info->desc_path, builder),
2248 g_variant_builder_unref(inner_builder);
2249 g_variant_builder_unref(builder);
2250 g_variant_builder_unref(builder1);
2252 return BLUETOOTH_ERROR_NONE;
2255 int bluetooth_gatt_get_service(const char *svc_uuid)
2257 GDBusProxy *proxy = NULL;
2260 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2261 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2263 return BLUETOOTH_ERROR_INTERNAL;
2265 uuid = g_strdup(svc_uuid);
2267 g_dbus_proxy_call(proxy,
2269 g_variant_new("(s)",
2271 G_DBUS_CALL_FLAGS_NONE, -1,
2273 (GAsyncReadyCallback) get_service_cb,
2278 return BLUETOOTH_ERROR_NONE;
2281 BT_EXPORT_API int bluetooth_gatt_register_service(
2282 const char *svc_path)
2284 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2285 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2286 BT_ERR("Don't have aprivilege to use this API");
2287 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2290 register_pending_cnt++;
2292 if (__bt_gatt_get_service_state(svc_path)) {
2293 BT_DBG("service already registered \n");
2294 return BLUETOOTH_ERROR_NONE;
2297 __bt_gatt_set_service_state(svc_path, TRUE);
2299 return BLUETOOTH_ERROR_NONE;
2302 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2304 GDBusProxy *proxy = NULL;
2306 if (!is_server_started) {
2308 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2309 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2310 BT_ERR("Don't have aprivilege to use this API");
2311 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2314 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2315 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2316 if (proxy == NULL || app_path == NULL)
2317 return BLUETOOTH_ERROR_INTERNAL;
2319 BT_INFO("RegisterApplication");
2321 if (register_cancel) {
2322 g_cancellable_cancel(register_cancel);
2323 g_object_unref(register_cancel);
2326 register_cancel = g_cancellable_new();
2328 g_dbus_proxy_call(proxy,
2329 "RegisterApplication",
2330 g_variant_new("(oa{sv})",
2332 G_DBUS_CALL_FLAGS_NONE, -1,
2334 (GAsyncReadyCallback) register_application_cb,
2337 is_server_started = true;
2339 return BLUETOOTH_ERROR_NONE;
2342 BT_INFO("Already RegisterApplication");
2344 return BLUETOOTH_ERROR_NONE;
2347 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2350 int error = BLUETOOTH_ERROR_NONE;
2354 for (l = gatt_services; l != NULL; l = l->next) {
2355 struct gatt_service_info *info = l->data;
2356 BT_DBG("svc_path is %s", info->serv_path);
2357 if (bluetooth_gatt_unregister_service(info->serv_path)
2358 != BLUETOOTH_ERROR_NONE) {
2359 error = BLUETOOTH_ERROR_INTERNAL;
2360 BT_ERR("Error in removing service %s \n",
2364 BT_DBG(" All services removed successfully.\n ");
2366 BT_DBG(" There are no registered services.\n ");
2369 g_slist_free(gatt_services);
2370 gatt_services = NULL;
2373 if (error != BLUETOOTH_ERROR_NONE)
2376 return BLUETOOTH_ERROR_NONE;
2379 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2380 const char *char_path, const char* char_value,
2383 GVariantBuilder *outer_builder;
2384 GVariantBuilder *inner_builder;
2385 GVariantBuilder *invalidated_builder;
2386 GVariant *update_value = NULL;
2387 GError *error = NULL;
2388 gboolean ret = FALSE;
2389 int err = BLUETOOTH_ERROR_NONE;
2391 gchar **line_argv = NULL;
2392 gchar *serv_path = NULL;
2393 const char *value = NULL;
2395 line_argv = g_strsplit_set(char_path, "/", 0);
2396 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2398 if (!__bt_gatt_get_service_state(serv_path)) {
2399 BT_DBG("service not registered for this characteristic \n");
2401 g_strfreev(line_argv);
2402 return BLUETOOTH_ERROR_INTERNAL;
2405 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2406 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2408 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2409 for (i = 0; i < value_length; i++)
2410 g_variant_builder_add(inner_builder, "y", char_value[i]);
2412 update_value = g_variant_new("ay", inner_builder);
2414 outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2415 g_variant_builder_add(outer_builder, "{sv}", "Value",
2418 BT_DBG("Updating characteristic value \n");
2419 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2421 "org.freedesktop.DBus.Properties",
2422 "PropertiesChanged",
2423 g_variant_new("(sa{sv}as)",
2424 "org.bluez.GattCharacteristic1",
2425 outer_builder, invalidated_builder),
2429 if (error != NULL) {
2430 BT_ERR("D-Bus API failure: errCode[%x], \
2432 error->code, error->message);
2433 g_clear_error(&error);
2435 err = BLUETOOTH_ERROR_INTERNAL;
2437 struct gatt_char_info *char_info = NULL;
2439 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2440 if (char_info == NULL) {
2442 g_strfreev(line_argv);
2443 g_variant_builder_unref(inner_builder);
2444 g_variant_builder_unref(outer_builder);
2445 g_variant_builder_unref(invalidated_builder);
2447 return BLUETOOTH_ERROR_INVALID_DATA;
2450 char_info->value_length = value_length;
2452 value = (char *)realloc(char_info->char_value, value_length);
2453 if (value == NULL) {
2455 g_strfreev(line_argv);
2456 g_variant_builder_unref(inner_builder);
2457 g_variant_builder_unref(outer_builder);
2458 g_variant_builder_unref(invalidated_builder);
2460 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2463 char_info->char_value = (char*)value;
2464 if (char_info->char_value) {
2465 for (i = 0; i < value_length; i++)
2466 char_info->char_value[i] = char_value[i];
2471 g_strfreev(line_argv);
2472 g_variant_builder_unref(inner_builder);
2473 g_variant_builder_unref(outer_builder);
2474 g_variant_builder_unref(invalidated_builder);
2479 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2486 g_free(desc_info->desc_path);
2487 g_free(desc_info->desc_uuid);
2488 g_free(desc_info->desc_value);
2490 for (i = 0; i < desc_info->flags_length; i++)
2491 g_free(desc_info->desc_flags[i]);
2496 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2503 g_free(char_info->char_path);
2504 g_free(char_info->char_uuid);
2505 g_free(char_info->char_value);
2507 for (i = 0; i < char_info->flags_length; i++)
2508 g_free(char_info->char_flags[i]);
2513 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2518 g_free(svc_info->serv_path);
2519 g_free(svc_info->service_uuid);
2523 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2526 struct gatt_service_info *svc_info;
2528 int err = BLUETOOTH_ERROR_NONE;
2530 BT_DBG("svc_path %s", svc_path);
2531 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2534 BT_ERR("Unable to find service info");
2535 return BLUETOOTH_ERROR_NOT_FOUND;
2538 err = __bt_gatt_unregister_service(svc_path);
2539 if (err != BLUETOOTH_ERROR_NONE) {
2540 BT_ERR("Could not unregister application");
2544 for (l = svc_info->char_data; l != NULL; l = l->next) {
2545 struct gatt_char_info *char_info = l->data;
2547 if (char_info == NULL)
2550 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2551 struct gatt_desc_info *desc_info = l1->data;
2553 if (desc_info == NULL)
2556 ret = g_dbus_connection_unregister_object(g_conn,
2557 desc_info->desc_id);
2559 __bt_gatt_emit_interface_removed(
2560 desc_info->desc_path,
2561 GATT_DESC_INTERFACE);
2563 err = BLUETOOTH_ERROR_INTERNAL;
2566 /* list remove & free */
2567 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2568 __bt_gatt_free_descriptor_info(desc_info);
2571 g_slist_free(char_info->desc_data);
2572 char_info->desc_data = NULL;
2574 ret = g_dbus_connection_unregister_object(g_conn,
2575 char_info->char_id);
2577 __bt_gatt_emit_interface_removed(char_info->char_path,
2578 GATT_CHAR_INTERFACE);
2580 err = BLUETOOTH_ERROR_INTERNAL;
2583 /* list remove & free */
2584 svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
2585 __bt_gatt_free_characteristic_info(char_info);
2588 g_slist_free(svc_info->char_data);
2589 svc_info->char_data = NULL;
2591 ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2593 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2594 GATT_SERV_INTERFACE);
2596 err = BLUETOOTH_ERROR_INTERNAL;
2599 ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2601 BT_DBG("Unregistered the service on properties interface");
2603 /* list remove & free */
2604 gatt_services = g_slist_remove(gatt_services, svc_info);
2605 __bt_gatt_free_service_info(svc_info);
2607 new_service = FALSE;
2609 if (gatt_services == NULL)
2611 else if (gatt_services->next == NULL)
2617 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2618 int resp_state, int offset, char *value, int value_length)
2620 struct gatt_req_info *req_info = NULL;
2622 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2623 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2624 BT_ERR("Don't have aprivilege to use this API");
2625 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2628 req_info = __bt_gatt_find_request_info(request_id);
2629 if (req_info == NULL) {
2630 BT_ERR("Coundn't find request id [%d]", request_id);
2631 return BLUETOOTH_ERROR_INTERNAL;
2634 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2635 BT_ERR("resp_state is 0x%X", resp_state);
2636 char err_msg[20] = { 0, };
2637 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2638 g_dbus_method_invocation_return_dbus_error(req_info->context,
2639 "org.bluez.Error.Failed", err_msg);
2641 gatt_requests = g_slist_remove(gatt_requests, req_info);
2643 req_info->context = NULL;
2644 if (req_info->attr_path)
2645 g_free(req_info->attr_path);
2646 if (req_info->svc_path)
2647 g_free(req_info->svc_path);
2650 return BLUETOOTH_ERROR_NONE;
2653 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2655 GVariantBuilder *inner_builder = NULL;
2656 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2657 if (value_length > 0 && value != NULL) {
2658 for (i = 0; i < value_length; i++)
2659 g_variant_builder_add(inner_builder, "y", value[i]);
2661 g_dbus_method_invocation_return_value(req_info->context,
2662 g_variant_new("(ay)", inner_builder));
2663 g_variant_builder_unref(inner_builder);
2665 g_dbus_method_invocation_return_value(req_info->context, NULL);
2667 gatt_requests = g_slist_remove(gatt_requests, req_info);
2669 req_info->context = NULL;
2670 if (req_info->attr_path)
2671 g_free(req_info->attr_path);
2672 if (req_info->svc_path)
2673 g_free(req_info->svc_path);
2676 return BLUETOOTH_ERROR_NONE;
2679 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2680 bluetooth_device_address_t *unicast_address)
2682 GVariantBuilder *outer_builder;
2683 GVariantBuilder *invalidated_builder;
2684 GError *error = NULL;
2685 gboolean notify = TRUE;
2686 gboolean ret = TRUE;
2687 int err = BLUETOOTH_ERROR_NONE;
2688 gchar **line_argv = NULL;
2689 gchar *serv_path = NULL;
2690 char addr[20] = { 0 };
2692 line_argv = g_strsplit_set(char_path, "/", 0);
2693 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2695 if (!__bt_gatt_get_service_state(serv_path)) {
2696 BT_DBG("service not registered for this characteristic \n");
2698 g_strfreev(line_argv);
2699 return BLUETOOTH_ERROR_INTERNAL;
2704 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2705 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2707 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2708 g_variant_new("b", notify));
2710 if (unicast_address) {
2711 _bt_convert_addr_type_to_string(addr,
2712 (unsigned char *)unicast_address->addr);
2714 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2715 g_variant_new("s", addr));
2717 BT_DBG("Set characteristic Notification \n");
2718 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2720 "org.freedesktop.DBus.Properties",
2721 "PropertiesChanged",
2722 g_variant_new("(sa{sv}as)",
2723 "org.bluez.GattCharacteristic1",
2724 outer_builder, invalidated_builder),
2728 if (error != NULL) {
2729 BT_ERR("D-Bus API failure: errCode[%x], \
2731 error->code, error->message);
2732 g_clear_error(&error);
2734 err = BLUETOOTH_ERROR_INTERNAL;
2737 g_strfreev(line_argv);
2738 g_variant_builder_unref(outer_builder);
2739 g_variant_builder_unref(invalidated_builder);