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 /* TODO_40 : 4.0 merge - Need to check why includes bt-event-handler.h */
28 #include "bt-event-handler.h"
29 #include "bt-internal-types.h"
32 #include "bluetooth-gatt-server-api.h"
33 #include "bt-request-sender.h"
34 #define BT_GATT_ATT_UUID_LEN_MAX 50
35 #define BT_GATT_SERVER_DBUS_NAME_LEN_MAX 50
38 /* Common defintions to follow , applicable for both
39 GATT_DIRECT and RELAY */
42 #define NUMBER_OF_FLAGS 10
43 int bluetooth_gatt_convert_prop2string(
44 bt_gatt_characteristic_property_t properties,
45 char *char_properties[])
49 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
50 char_properties[flag_count] = g_strdup("broadcast");
53 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
54 char_properties[flag_count] = g_strdup("read");
57 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
58 char_properties[flag_count] = g_strdup("write-without-response");
61 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
62 char_properties[flag_count] = g_strdup("write");
65 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
66 char_properties[flag_count] = g_strdup("notify");
69 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
70 char_properties[flag_count] = g_strdup("indicate");
73 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
74 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
77 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
78 char_properties[flag_count] = g_strdup("reliable-write");
81 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
82 char_properties[flag_count] = g_strdup("writable-auxiliaries");
85 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
86 char_properties[flag_count] = g_strdup("encrypt-read");
89 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
90 char_properties[flag_count] = g_strdup("encrypt-write");
93 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
94 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
97 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
98 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
102 if (flag_count == 0) {
103 char_properties[flag_count] = g_strdup("read");
110 int bluetooth_gatt_convert_perm2string(
111 bt_gatt_permission_t properties,
112 char *char_properties[])
116 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
117 char_properties[flag_count] = g_strdup("read");
120 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
121 char_properties[flag_count] = g_strdup("write");
124 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
125 char_properties[flag_count] = g_strdup("encrypt-read");
128 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
129 char_properties[flag_count] = g_strdup("encrypt-write");
132 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
133 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
136 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
137 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
141 if (flag_count == 0) {
142 char_properties[flag_count] = g_strdup("read");
150 #define NUMBER_OF_FLAGS 10
152 GDBusConnection *g_conn;
155 static gboolean new_service = FALSE;
156 static gboolean new_char = FALSE;
157 static int serv_id = 1;
158 static int register_pending_cnt = 0;
159 static bool is_server_started = false;
161 GCancellable *register_cancel;
163 /* Introspection data for the service we are exporting */
164 static const gchar service_introspection_xml[] =
166 " <interface name='org.freedesktop.DBus.Properties'>"
167 " <property type='s' name='UUID' access='read'>"
169 " <property type='b' name='primary' access='read'>"
171 " <property type='o' name='Device' access='read'>"
173 " <property type='ao' name='Characteristics' access='read'>"
175 " <property type='s' name='Includes' access='read'>"
180 /* Introspection data for the characteristics we are exporting */
181 static const gchar characteristics_introspection_xml[] =
183 " <interface name='org.bluez.GattCharacteristic1'>"
184 " <method name='ReadValue'>"
185 " <arg type='s' name='address' direction='in'/>"
186 " <arg type='u' name='id' direction='in'/>"
187 " <arg type='q' name='offset' direction='in'/>"
188 " <arg type='ay' name='Value' direction='out'/>"
190 " <method name='WriteValue'>"
191 " <arg type='s' name='address' direction='in'/>"
192 " <arg type='u' name='id' direction='in'/>"
193 " <arg type='q' name='offset' direction='in'/>"
194 " <arg type='b' name='response_needed' direction='in'/>"
195 " <arg type='ay' name='value' direction='in'/>"
197 " <method name='StartNotify'>"
199 " <method name='StopNotify'>"
201 " <method name='IndicateConfirm'>"
202 " <arg type='s' name='address' direction='in'/>"
203 " <arg type='b' name='complete' direction='in'/>"
206 " <interface name='org.freedesktop.DBus.Properties'>"
207 " <property type='s' name='UUID' access='read'>"
209 " <property type='o' name='Service' access='read'>"
211 " <property type='ay' name='Value' access='readwrite'>"
213 " <property type='b' name='Notifying' access='read'>"
215 " <property type='as' name='Flags' access='read'>"
217 " <property type='s' name='Unicast' access='read'>"
219 " <property type='ao' name='Descriptors' access='read'>"
224 /* Introspection data for the descriptor we are exporting */
225 static const gchar descriptor_introspection_xml[] =
227 " <interface name='org.bluez.GattDescriptor1'>"
228 " <method name='ReadValue'>"
229 " <arg type='s' name='address' direction='in'/>"
230 " <arg type='u' name='id' direction='in'/>"
231 " <arg type='q' name='offset' direction='in'/>"
232 " <arg type='ay' name='Value' direction='out'/>"
234 " <method name='WriteValue'>"
235 " <arg type='s' name='address' direction='in'/>"
236 " <arg type='u' name='id' direction='in'/>"
237 " <arg type='q' name='offset' direction='in'/>"
238 " <arg type='b' name='response_needed' direction='in'/>"
239 " <arg type='ay' name='value' direction='in'/>"
242 " <interface name='org.freedesktop.DBus.Properties'>"
243 " <property type='s' name='UUID' access='read'>"
245 " <property type='o' name='Characteristic' access='read'>"
247 " <property type='ay' name='Value' access='read'>"
249 " <property type='as' name='Flags' access='read'>"
254 static const gchar manager_introspection_xml[] =
256 " <interface name='org.freedesktop.DBus.ObjectManager'>"
257 " <method name='GetManagedObjects'>"
258 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
263 struct gatt_service_info {
270 gboolean is_svc_registered;
271 gboolean is_svc_primary;
274 struct gatt_char_info {
279 gchar *char_flags[NUMBER_OF_FLAGS];
285 struct gatt_desc_info {
290 gchar *desc_flags[NUMBER_OF_FLAGS];
295 struct gatt_req_info {
300 GDBusMethodInvocation *context;
303 static GSList *gatt_services = NULL;
304 static GSList *gatt_requests = NULL;
305 static gchar *app_path = NULL;
307 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
308 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
310 #define GATT_SERV_OBJECT_PATH "/service"
312 #define GATT_MNGR_INTERFACE "org.bluez.GattManager1"
313 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
314 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
315 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
317 #ifdef TIZEN_FEATURE_BT_HPS
318 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
319 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
320 #define PROPERTIES_CHANGED "PropertiesChanged"
321 #define BT_HPS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
324 #ifdef TIZEN_FEATURE_BT_OTP
325 #define BT_OTP_OBJECT_PATH "/org/projectx/otp"
326 #define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
327 #define PROPERTIES_CHANGED "PropertiesChanged"
328 #define BT_OTP_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
331 static GDBusProxy *manager_gproxy = NULL;
333 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
334 const char *service_path, const char *char_path);
335 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
336 const char *serv_path, const char *char_path,
337 const char *desc_path);
339 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
341 static void __bt_gatt_close_gdbus_connection(void)
347 ret_if(g_conn == NULL);
349 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
350 BT_ERR("Fail to flush the connection: %s", err->message);
355 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
357 BT_ERR("Fail to close the dbus connection: %s", err->message);
362 g_object_unref(g_conn);
369 #ifdef TIZEN_FEATURE_BT_HPS
370 static int __bt_send_event_to_hps(int event, GVariant *var)
372 GError *error = NULL;
373 GVariant *parameters;
374 GDBusMessage *msg = NULL;
378 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
380 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
381 GVariantBuilder *inner_builder;
382 GVariantBuilder *invalidated_builder;
384 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
385 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
387 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
389 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
391 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
392 g_variant_builder_unref(invalidated_builder);
393 g_variant_builder_unref(inner_builder);
394 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
395 GVariantBuilder *inner_builder;
396 GVariantBuilder *invalidated_builder;
398 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
399 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
401 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
403 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
405 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
406 g_variant_builder_unref(invalidated_builder);
407 g_variant_builder_unref(inner_builder);
409 g_varaiant_unref(var);
412 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
413 g_dbus_message_set_body(msg, parameters);
414 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
416 BT_ERR("D-Bus API failure: errCode[%x], \
418 error->code, error->message);
419 g_clear_error(&error);
421 return BLUETOOTH_ERROR_INTERNAL;
423 return BLUETOOTH_ERROR_NONE;
427 #ifdef TIZEN_FEATURE_BT_OTP
428 static int __bt_send_event_to_otp(int event, GVariant *var)
430 GError *error = NULL;
431 GVariant *parameters = NULL;
432 GDBusMessage *msg = NULL;
436 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
438 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
439 GVariantBuilder *inner_builder;
440 GVariantBuilder *invalidated_builder;
442 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
443 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
445 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
447 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
449 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
450 g_variant_builder_unref(invalidated_builder);
451 g_variant_builder_unref(inner_builder);
452 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
453 GVariantBuilder *inner_builder;
454 GVariantBuilder *invalidated_builder;
456 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
457 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
459 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
461 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
463 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
464 g_variant_builder_unref(invalidated_builder);
465 g_variant_builder_unref(inner_builder);
466 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
467 GVariantBuilder *inner_builder;
468 GVariantBuilder *invalidated_builder;
470 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
471 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
473 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
475 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
477 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
478 g_variant_builder_unref(invalidated_builder);
479 g_variant_builder_unref(inner_builder);
482 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
483 g_dbus_message_set_body(msg, parameters);
484 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
486 BT_ERR("D-Bus API failure: errCode[%x], \
488 error->code, error->message);
489 g_clear_error(&error);
491 return BLUETOOTH_ERROR_INTERNAL;
493 return BLUETOOTH_ERROR_NONE;
497 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
499 const gchar *object_path,
500 const gchar *interface_name,
501 const gchar *method_name,
502 GVariant *parameters,
503 GDBusMethodInvocation *invocation,
510 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
511 BT_DBG("Getting values for service, chars and descriptors");
513 GVariantBuilder *builder;
514 GVariantBuilder *inner_builder1 = NULL;
515 GVariant *svc_char = NULL;
518 builder = g_variant_builder_new(
519 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
521 /* Prepare inner builder for GattService1 interface */
523 len = g_slist_length(gatt_services);
525 for (i = 0; i <= len; i++) {
526 GVariantBuilder *svc_builder = NULL;
527 GVariantBuilder *inner_builder = NULL;
529 if (register_pending_cnt > 1)
530 l1 = g_slist_nth(gatt_services, len - register_pending_cnt);
532 l1 = g_slist_last(gatt_services);
534 register_pending_cnt--;
537 BT_ERR("gatt service list is NULL");
538 g_dbus_method_invocation_return_value(invocation, NULL);
539 g_variant_builder_unref(builder);
543 struct gatt_service_info *serv_info = l1->data;
544 if (serv_info == NULL) {
545 BT_ERR("service info value is NULL");
546 g_dbus_method_invocation_return_value(invocation, NULL);
547 g_variant_builder_unref(builder);
551 /* Prepare inner builder for GattService1 interface */
552 BT_DBG("Creating builder for service");
553 svc_builder = g_variant_builder_new(
554 G_VARIANT_TYPE("a{sa{sv}}"));
555 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
557 g_variant_builder_add(inner_builder, "{sv}", "UUID",
558 g_variant_new_string(serv_info->service_uuid));
560 g_variant_builder_add(inner_builder, "{sv}", "Primary",
561 g_variant_new_boolean(serv_info->is_svc_primary));
564 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
565 BT_DBG("Adding Charatarisitcs list");
566 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
567 struct gatt_char_info *char_info = l4->data;
568 g_variant_builder_add(inner_builder1, "o",
569 char_info->char_path);
570 BT_DBG("%s", char_info->char_path);
573 svc_char = g_variant_new("ao", inner_builder1);
574 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
577 g_variant_builder_add(svc_builder, "{sa{sv}}",
581 g_variant_builder_add(builder, "{oa{sa{sv}}}",
582 serv_info->serv_path,
585 g_variant_builder_unref(inner_builder1);
587 /* Prepare inner builder for GattCharacteristic1 interface */
589 GSList *l2 = serv_info->char_data;
590 BT_DBG("Creating builder for characteristics \n");
593 BT_DBG("characteristic data is NULL");
595 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
597 GVariantBuilder *char_builder = NULL;
598 GVariantBuilder *inner_builder = NULL;
599 GVariantBuilder *builder1 = NULL;
600 GVariantBuilder *builder2 = NULL;
601 GVariantBuilder *builder3 = NULL;
602 GVariant *char_val = NULL;
603 GVariant *flags_val = NULL;
604 GVariant *char_desc = NULL;
605 char *unicast = NULL;
606 gboolean notify = FALSE;
609 char_builder = g_variant_builder_new(
612 inner_builder = g_variant_builder_new(
616 struct gatt_char_info *char_info = l2->data;
617 if (char_info == NULL) {
618 BT_ERR("char_info is NULL");
623 g_variant_builder_add(inner_builder, "{sv}", "UUID",
624 g_variant_new_string(char_info->char_uuid));
626 g_variant_builder_add(inner_builder, "{sv}", "Service",
627 g_variant_new("o", serv_info->serv_path));
629 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
631 if (char_info->char_value != NULL) {
632 for (i = 0; i < char_info->value_length; i++) {
633 g_variant_builder_add(builder1, "y",
634 char_info->char_value[i]);
636 char_val = g_variant_new("ay", builder1);
637 g_variant_builder_add(inner_builder, "{sv}",
641 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
643 for (i = 0; i < char_info->flags_length; i++) {
644 g_variant_builder_add(builder2, "s",
645 char_info->char_flags[i]);
648 flags_val = g_variant_new("as", builder2);
649 g_variant_builder_add(inner_builder, "{sv}", "Flags",
653 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
654 g_variant_new("b", notify));
657 unicast = g_strdup("00:00:00:00:00:00");
658 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
659 g_variant_new("s", unicast));
662 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
663 BT_DBG("Adding Descriptors list");
665 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
666 struct gatt_desc_info *desc_info = l4->data;
667 g_variant_builder_add(builder3, "o",
668 desc_info->desc_path);
669 BT_DBG("%s", desc_info->desc_path);
672 char_desc = g_variant_new("ao", builder3);
673 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
676 g_variant_builder_add(char_builder, "{sa{sv}}",
677 GATT_CHAR_INTERFACE , inner_builder);
678 g_variant_builder_add(builder, "{oa{sa{sv}}}",
679 char_info->char_path, char_builder);
681 /*Prepare inner builder for GattDescriptor1 interface*/
683 GSList *l3 = char_info->desc_data;
686 BT_DBG("descriptor data is NULL");
688 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
690 BT_DBG("Creating builder for descriptor \n");
692 GVariantBuilder *desc_builder = NULL;
693 GVariantBuilder *inner_builder = NULL;
694 GVariantBuilder *builder1 = NULL;
695 GVariantBuilder *builder2 = NULL;
696 GVariant *desc_val = NULL;
698 desc_builder = g_variant_builder_new(
701 inner_builder = g_variant_builder_new(
705 struct gatt_desc_info *desc_info = l3->data;
706 if (desc_info == NULL) {
707 BT_ERR("desc_info is NULL");
712 g_variant_builder_add(inner_builder,
714 g_variant_new_string(
715 desc_info->desc_uuid));
718 g_variant_builder_add(inner_builder, "{sv}",
721 char_info->char_path));
724 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
726 if (desc_info->desc_value != NULL) {
727 for (i = 0; i < desc_info->value_length; i++) {
728 g_variant_builder_add(builder1, "y",
729 desc_info->desc_value[i]);
731 desc_val = g_variant_new("ay", builder1);
732 g_variant_builder_add(inner_builder, "{sv}",
737 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
739 for (i = 0; i < desc_info->flags_length; i++) {
740 g_variant_builder_add(builder2, "s",
741 desc_info->desc_flags[i]);
744 flags_val = g_variant_new("as", builder2);
745 g_variant_builder_add(inner_builder, "{sv}", "Flags",
748 g_variant_builder_add(desc_builder, "{sa{sv}}",
752 g_variant_builder_add(builder, "{oa{sa{sv}}}",
753 desc_info->desc_path,
756 /*unref descriptor builder pointers*/
757 g_variant_builder_unref(builder1);
758 g_variant_builder_unref(builder2);
759 g_variant_builder_unref(inner_builder);
760 g_variant_builder_unref(desc_builder);
765 /*unref char builder pointers*/
766 g_variant_builder_unref(builder1);
767 g_variant_builder_unref(builder2);
768 g_variant_builder_unref(builder3);
769 g_variant_builder_unref(inner_builder);
770 g_variant_builder_unref(char_builder);
773 /*unref service builder pointers*/
774 g_variant_builder_unref(inner_builder);
775 g_variant_builder_unref(svc_builder);
778 /* Return builder as method reply */
779 BT_DBG("Sending gatt service builder values to Bluez");
780 g_dbus_method_invocation_return_value(invocation,
784 g_variant_builder_unref(builder);
788 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
792 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
793 struct gatt_service_info *serv_info = l1->data;
795 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
796 struct gatt_char_info *char_info = l2->data;
798 if (g_strcmp0(char_info->char_path, char_path)
803 BT_ERR("Gatt service not found");
807 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
809 GSList *l1, *l2, *l3;
811 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
812 struct gatt_service_info *serv_info = l1->data;
814 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
815 struct gatt_char_info *char_info = l2->data;
817 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
818 struct gatt_desc_info *desc_info = l3->data;
820 if (g_strcmp0(desc_info->desc_path, desc_path)
826 BT_ERR("Gatt service not found");
830 static void __bt_gatt_char_method_call(GDBusConnection *connection,
832 const gchar *object_path,
833 const gchar *interface_name,
834 const gchar *method_name,
835 GVariant *parameters,
836 GDBusMethodInvocation *invocation,
840 if (g_strcmp0(method_name, "ReadValue") == 0) {
844 bt_gatt_read_req_t read_req = {0, };
845 bt_user_info_t *user_info = NULL;
846 struct gatt_req_info *req_info = NULL;
847 struct gatt_service_info *svc_info = NULL;
848 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
849 GVariant *param = NULL;
852 BT_DBG("Application path = %s", object_path);
853 BT_DBG("Sender = %s", sender);
855 user_info = _bt_get_user_data(BT_COMMON);
856 if (user_info == NULL) {
857 BT_INFO("No callback is set for %s", object_path);
858 g_dbus_method_invocation_return_value(invocation, NULL);
862 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
863 if (svc_info == NULL) {
864 BT_ERR("Coudn't find service for %s", object_path);
865 g_dbus_method_invocation_return_value(invocation, NULL);
869 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
870 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
872 read_req.att_handle = (char *)object_path;
873 read_req.address = addr;
874 read_req.req_id = req_id;
875 read_req.offset = offset;
876 read_req.service_handle = svc_info->serv_path;
878 /* Store requets information */
879 req_info = g_new0(struct gatt_req_info, 1);
880 req_info->attr_path = g_strdup(object_path);
881 req_info->svc_path = g_strdup(read_req.service_handle);
882 req_info->request_id = req_id;
883 req_info->offset = offset;
884 req_info->context = invocation;
885 gatt_requests = g_slist_append(gatt_requests, req_info);
887 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
888 BLUETOOTH_ERROR_NONE, &read_req,
889 user_info->cb, user_info->user_data);
891 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
892 param = g_variant_new("(sssyq)",
894 read_req.service_handle,
898 #ifdef TIZEN_FEATURE_BT_HPS
899 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
901 #ifdef TIZEN_FEATURE_BT_OTP
902 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
906 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
907 GVariant *var = NULL;
911 gboolean response_needed = FALSE;
912 bt_gatt_value_change_t value_change = {0, };
913 bt_user_info_t *user_info = NULL;
915 struct gatt_service_info *svc_info = NULL;
916 struct gatt_req_info *req_info = NULL;
917 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
918 GVariant *param = NULL;
921 BT_DBG("WriteValue");
922 BT_DBG("Application path = %s", object_path);
923 BT_DBG("Sender = %s", sender);
925 g_variant_get(parameters, "(&suqb@ay)",
926 &addr, &req_id, &offset, &response_needed, &var);
927 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
929 user_info = _bt_get_user_data(BT_COMMON);
931 BT_INFO("No callback is set for %s", object_path);
932 g_variant_unref(var);
934 g_dbus_method_invocation_return_value(invocation, NULL);
936 g_object_unref(invocation);
940 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
941 if (svc_info == NULL) {
942 BT_ERR("Coudn't find service for %s", object_path);
943 g_variant_unref(var);
945 g_dbus_method_invocation_return_value(invocation, NULL);
947 g_object_unref(invocation);
951 value_change.att_handle = (char *)object_path;
952 value_change.address = addr;
953 value_change.service_handle = svc_info->serv_path;
954 value_change.offset = offset;
955 value_change.req_id = req_id;
956 value_change.response_needed = response_needed;
958 len = g_variant_get_size(var);
962 value_change.att_value = (guint8 *)g_malloc(len);
964 data = (char *)g_variant_get_data(var);
965 memcpy(value_change.att_value, data, len);
967 value_change.val_len = len;
969 if (response_needed) {
970 /* Store requets information */
971 req_info = g_new0(struct gatt_req_info, 1);
972 req_info->attr_path = g_strdup(object_path);
973 req_info->svc_path = g_strdup(value_change.service_handle);
974 req_info->request_id = req_id;
975 req_info->offset = offset;
976 req_info->context = invocation;
977 gatt_requests = g_slist_append(gatt_requests, req_info);
979 g_object_unref(invocation);
983 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
984 BLUETOOTH_ERROR_NONE, &value_change,
985 user_info->cb, user_info->user_data);
987 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
990 svc_path = g_strdup(svc_info->serv_path);
991 param = g_variant_new("(sssyq@ay)",
998 #ifdef TIZEN_FEATURE_BT_HPS
999 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1001 #ifdef TIZEN_FEATURE_BT_OTP
1002 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1009 g_free(value_change.att_value);
1010 g_variant_unref(var);
1012 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1013 bt_user_info_t *user_info = NULL;
1014 bt_gatt_char_notify_change_t notify_change = {0, };
1015 #if TIZEN_FEATURE_BT_OTP
1016 GVariant *param = NULL;
1018 BT_DBG("StartNotify");
1019 user_info = _bt_get_user_data(BT_COMMON);
1020 if (user_info != NULL) {
1021 struct gatt_service_info *svc_info = NULL;
1022 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1024 notify_change.service_handle = svc_info->serv_path;
1025 notify_change.att_handle = (char *)object_path;
1026 notify_change.att_notify = TRUE;
1027 _bt_common_event_cb(
1028 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1029 BLUETOOTH_ERROR_NONE, ¬ify_change,
1030 user_info->cb, user_info->user_data);
1031 #if TIZEN_FEATURE_BT_OTP
1032 param = g_variant_new("(ssb)",
1033 notify_change.att_handle,
1034 notify_change.service_handle,
1035 notify_change.att_notify);
1036 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1040 g_object_unref(invocation);
1042 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1043 bt_user_info_t *user_info = NULL;
1044 bt_gatt_char_notify_change_t notify_change = {0, };
1045 #if TIZEN_FEATURE_BT_OTP
1046 GVariant *param = NULL;
1048 BT_DBG("StopNotify");
1049 user_info = _bt_get_user_data(BT_COMMON);
1050 if (user_info != NULL) {
1051 struct gatt_service_info *svc_info = NULL;
1052 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1054 notify_change.service_handle = svc_info->serv_path;
1055 notify_change.att_handle = (char *)object_path;
1056 notify_change.att_notify = FALSE;
1057 _bt_common_event_cb(
1058 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1059 BLUETOOTH_ERROR_NONE, ¬ify_change,
1060 user_info->cb, user_info->user_data);
1061 #if TIZEN_FEATURE_BT_OTP
1062 param = g_variant_new("(ssb)",
1063 notify_change.att_handle,
1064 notify_change.service_handle,
1065 notify_change.att_notify);
1066 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1070 g_object_unref(invocation);
1072 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1074 bt_gatt_indicate_confirm_t confirm = {0, };
1075 bt_user_info_t *user_info = NULL;
1076 gboolean complete = FALSE;
1077 struct gatt_service_info *svc_info = NULL;
1079 BT_DBG("IndicateConfirm");
1080 BT_DBG("Application path = %s", object_path);
1081 BT_DBG("Sender = %s", sender);
1083 g_variant_get(parameters, "(&sb)", &addr, &complete);
1084 BT_DBG("Remote Device address number = %s", addr);
1086 confirm.att_handle = (char *)object_path;
1087 confirm.address = addr;
1088 confirm.complete = complete;
1090 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1091 if (svc_info != NULL) {
1092 confirm.service_handle = svc_info->serv_path;
1094 user_info = _bt_get_user_data(BT_COMMON);
1095 if (user_info != NULL) {
1096 _bt_common_event_cb(
1097 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1098 BLUETOOTH_ERROR_NONE, &confirm,
1099 user_info->cb, user_info->user_data);
1104 g_dbus_method_invocation_return_value(invocation, NULL);
1107 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1108 const gchar *sender,
1109 const gchar *object_path,
1110 const gchar *interface_name,
1111 const gchar *method_name,
1112 GVariant *parameters,
1113 GDBusMethodInvocation *invocation,
1116 if (g_strcmp0(method_name, "ReadValue") == 0) {
1120 bt_gatt_read_req_t read_req = {0, };
1121 bt_user_info_t *user_info = NULL;
1122 struct gatt_req_info *req_info = NULL;
1123 struct gatt_service_info *svc_info = NULL;
1125 BT_DBG("ReadValue");
1126 BT_DBG("Application path = %s", object_path);
1127 BT_DBG("Sender = %s", sender);
1129 user_info = _bt_get_user_data(BT_COMMON);
1130 if (user_info == NULL) {
1131 BT_INFO("No callback is set for %s", object_path);
1132 g_dbus_method_invocation_return_value(invocation, NULL);
1136 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1137 if (svc_info == NULL) {
1138 BT_ERR("Coudn't find service for %s", object_path);
1139 g_dbus_method_invocation_return_value(invocation, NULL);
1143 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1144 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1146 read_req.att_handle = (char *)object_path;
1147 read_req.address = addr;
1148 read_req.req_id = req_id;
1149 read_req.offset = offset;
1150 read_req.service_handle = svc_info->serv_path;
1152 /* Store requets information */
1153 req_info = g_new0(struct gatt_req_info, 1);
1154 req_info->attr_path = g_strdup(object_path);
1155 req_info->svc_path = g_strdup(read_req.service_handle);
1156 req_info->request_id = req_id;
1157 req_info->offset = offset;
1158 req_info->context = invocation;
1159 gatt_requests = g_slist_append(gatt_requests, req_info);
1161 _bt_common_event_cb(
1162 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1163 BLUETOOTH_ERROR_NONE, &read_req,
1164 user_info->cb, user_info->user_data);
1167 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1168 GVariant *var = NULL;
1172 gboolean response_needed = FALSE;
1173 bt_gatt_value_change_t value_change = {0, };
1174 bt_user_info_t *user_info = NULL;
1176 struct gatt_service_info *svc_info = NULL;
1177 struct gatt_req_info *req_info = NULL;
1179 BT_DBG("WriteValue");
1180 BT_DBG("Application path = %s", object_path);
1181 BT_DBG("Sender = %s", sender);
1183 g_variant_get(parameters, "(&suqb@ay)",
1184 &addr, &req_id, &offset, &response_needed, &var);
1185 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1187 user_info = _bt_get_user_data(BT_COMMON);
1188 if (user_info == NULL) {
1189 BT_INFO("No callback is set for %s", object_path);
1190 g_variant_unref(var);
1191 if (response_needed)
1192 g_dbus_method_invocation_return_value(invocation, NULL);
1194 g_object_unref(invocation);
1198 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1199 if (svc_info == NULL) {
1200 BT_ERR("Coudn't find service for %s", object_path);
1201 g_variant_unref(var);
1202 if (response_needed)
1203 g_dbus_method_invocation_return_value(invocation, NULL);
1205 g_object_unref(invocation);
1209 value_change.att_handle = (char *)object_path;
1210 value_change.address = addr;
1211 value_change.service_handle = svc_info->serv_path;
1212 value_change.offset = offset;
1213 value_change.req_id = req_id;
1214 value_change.response_needed = response_needed;
1216 len = g_variant_get_size(var);
1220 value_change.att_value = (guint8 *)g_malloc(len);
1222 data = (char *)g_variant_get_data(var);
1223 memcpy(value_change.att_value, data, len);
1225 value_change.val_len = len;
1227 if (response_needed) {
1228 /* Store requets information */
1229 req_info = g_new0(struct gatt_req_info, 1);
1230 req_info->attr_path = g_strdup(object_path);
1231 req_info->svc_path = g_strdup(value_change.service_handle);
1232 req_info->request_id = req_id;
1233 req_info->offset = offset;
1234 req_info->context = invocation;
1235 gatt_requests = g_slist_append(gatt_requests, req_info);
1237 g_object_unref(invocation);
1240 _bt_common_event_cb(
1241 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1242 BLUETOOTH_ERROR_NONE, &value_change,
1243 user_info->cb, user_info->user_data);
1245 g_free(value_change.att_value);
1246 g_variant_unref(var);
1251 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1254 GError *error = NULL;
1255 GVariantBuilder *array_builder;
1257 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1258 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1259 g_variant_builder_add(array_builder, "s", interface);
1261 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1262 "org.freedesktop.Dbus.Objectmanager",
1263 "InterfacesRemoved",
1264 g_variant_new("(oas)",
1265 object_path, array_builder),
1269 if (error != NULL) {
1270 /* dbus gives error cause */
1271 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1272 error->code, error->message);
1273 g_clear_error(&error);
1276 g_variant_builder_unref(array_builder);
1281 static const GDBusInterfaceVTable desc_interface_vtable = {
1282 __bt_gatt_desc_method_call,
1288 static const GDBusInterfaceVTable char_interface_vtable = {
1289 __bt_gatt_char_method_call,
1295 static const GDBusInterfaceVTable serv_interface_vtable = {
1302 static const GDBusInterfaceVTable manager_interface_vtable = {
1303 __bt_gatt_manager_method_call,
1309 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1310 const gchar *introspection_data)
1313 GDBusNodeInfo *node_info = NULL;
1315 if (introspection_data == NULL)
1319 BT_DBG("Create new node info");
1320 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1323 BT_ERR("Unable to create node: %s", err->message);
1324 g_clear_error(&err);
1331 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1332 const char *service_path)
1336 for (l = gatt_services; l != NULL; l = l->next) {
1337 struct gatt_service_info *info = l->data;
1339 if (g_strcmp0(info->serv_path, service_path) == 0)
1342 BT_ERR("Gatt service not found");
1346 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1347 const char *service_path, const char *char_path)
1351 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1352 struct gatt_service_info *serv_info = l1->data;
1354 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1356 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1357 struct gatt_char_info *char_info = l2->data;
1359 if (g_strcmp0(char_info->char_path, char_path)
1363 BT_ERR("Gatt characteristic not found");
1367 BT_ERR("Gatt service not found");
1371 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1372 const char *serv_path, const char *char_path,
1373 const char *desc_path)
1375 GSList *l1, *l2, *l3;
1377 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1378 struct gatt_service_info *serv_info = l1->data;
1380 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1381 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1382 struct gatt_char_info *char_info = l2->data;
1384 if (g_strcmp0(char_info->char_path, char_path)
1386 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1387 struct gatt_desc_info *desc_info = l3->data;
1388 if (g_strcmp0(desc_info->desc_path,
1397 BT_ERR("Gatt descriptor not found");
1401 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1405 for (l = gatt_requests; l != NULL; l = l->next) {
1406 struct gatt_req_info *req_info = l->data;
1408 if (req_info && req_info->request_id == request_id)
1411 BT_ERR("Gatt Request not found");
1415 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1416 const gchar *path, const gchar *interface)
1422 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1427 BT_ERR("Unable to connect to gdbus: %s", err->message);
1428 g_clear_error(&err);
1433 proxy = g_dbus_proxy_new_sync(g_conn,
1434 G_DBUS_PROXY_FLAGS_NONE, NULL,
1436 interface, NULL, &err);
1440 BT_ERR("Unable to create proxy: %s", err->message);
1441 g_clear_error(&err);
1445 manager_gproxy = proxy;
1450 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1451 const gchar *path, const gchar *interface)
1453 return (manager_gproxy) ? manager_gproxy :
1454 __bt_gatt_gdbus_init_manager_proxy(service,
1459 static void __bt_gatt_set_service_state(const char *service_path,
1462 struct gatt_service_info *svc_info = NULL;
1463 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1465 if (svc_info != NULL) {
1466 BT_DBG("Updating the gatt service register state %d", state);
1467 svc_info->is_svc_registered = state;
1471 BT_DBG("gatt service not found");
1474 static gboolean __bt_gatt_get_service_state(const char *service_path)
1476 struct gatt_service_info *svc_info = NULL;
1478 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1480 if (svc_info != NULL) {
1481 BT_DBG("Return the state of the gatt service %d",
1482 svc_info->is_svc_registered);
1483 return svc_info->is_svc_registered;
1486 BT_DBG("gatt service info is NULL");
1490 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1492 GError *error = NULL;
1494 GVariantIter *iter = NULL;
1495 const gchar *key = NULL;
1496 GVariant *value = NULL;
1497 const gchar *service = NULL;
1498 const gchar *characteristic = NULL;
1499 const gchar *descriptor = NULL;
1503 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1505 if (result == NULL) {
1506 /* dBUS-RPC is failed */
1507 BT_ERR("Dbus-RPC is failed\n");
1509 if (error != NULL) {
1510 /* dBUS gives error cause */
1511 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1512 error->code, error->message);
1513 g_clear_error(&error);
1516 char *char_cmp = NULL;
1517 g_variant_get(result, "(a{sv})", &iter);
1518 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1520 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1521 if (g_strcmp0(key, "Service") == 0) {
1522 service = g_variant_get_string(value, NULL);
1523 BT_DBG("Service %s", service);
1524 } else if (g_strcmp0(key, char_cmp) == 0) {
1525 characteristic = g_variant_get_string(value, NULL);
1527 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1528 BT_DBG("%s", characteristic);
1529 } else if (g_strcmp0(key, "Descriptor") == 0) {
1530 descriptor = g_variant_get_string(value, NULL);
1531 BT_DBG("Descriptor %s", descriptor);
1534 g_variant_iter_free(iter);
1536 /* TODO: Store the service informationa and
1537 * Send respponse to CAPI layer. */
1539 g_variant_unref(result);
1544 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1546 BT_INFO("RegisterApplication is completed");
1548 GError *error = NULL;
1551 register_pending_cnt = 0;
1553 if (register_cancel) {
1554 g_object_unref(register_cancel);
1555 register_cancel = NULL;
1558 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1560 if (result == NULL) {
1561 /* dBUS-RPC is failed */
1562 BT_ERR("Dbus-RPC is failed\n");
1564 if (error != NULL) {
1565 /* dBUS gives error cause */
1566 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1567 error->code, error->message);
1568 g_clear_error(&error);
1571 g_variant_unref(result);
1575 static int __bt_gatt_unregister_service(const char *service_path)
1577 if (!__bt_gatt_get_service_state(service_path)) {
1578 BT_DBG("service not registered \n");
1579 return BLUETOOTH_ERROR_NOT_FOUND;
1582 return BLUETOOTH_ERROR_NONE;
1585 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1587 GDBusProxy *proxy = NULL;
1589 if (is_server_started) {
1593 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1594 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1596 if (proxy == NULL || app_path == NULL)
1597 return BLUETOOTH_ERROR_INTERNAL;
1599 BT_INFO("UnregisterApplication");
1601 is_server_started = false;
1603 /* Async Call to Unregister Service */
1604 ret = g_dbus_proxy_call_sync(proxy,
1605 "UnregisterApplication",
1606 g_variant_new("(o)",
1608 G_DBUS_CALL_FLAGS_NONE, -1,
1612 /* dBUS-RPC is failed */
1613 BT_ERR("dBUS-RPC is failed");
1615 /* dBUS gives error cause */
1616 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1617 err->code, err->message);
1619 g_clear_error(&err);
1621 return BLUETOOTH_ERROR_INTERNAL;
1623 g_variant_unref(ret);
1625 BT_INFO("UnregisterApplication is completed");
1627 return BLUETOOTH_ERROR_NONE;
1630 BT_INFO("GATT server not started");
1631 return BLUETOOTH_ERROR_NONE;
1634 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1636 GDBusConnection *local_system_gconn = NULL;
1640 if (g_conn == NULL) {
1641 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1642 if (address == NULL) {
1644 BT_ERR("Failed to get bus address: %s", err->message);
1645 g_clear_error(&err);
1650 g_conn = g_dbus_connection_new_for_address_sync(address,
1651 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1652 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1653 NULL, /* GDBusAuthObserver */
1659 BT_ERR("Unable to connect to dbus: %s", err->message);
1660 g_clear_error(&err);
1664 } else if (g_dbus_connection_is_closed(g_conn)) {
1665 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1666 if (address == NULL) {
1668 BT_ERR("Failed to get bus address: %s", err->message);
1669 g_clear_error(&err);
1674 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1675 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1676 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1677 NULL, /* GDBusAuthObserver */
1681 if (!local_system_gconn) {
1682 BT_ERR("Unable to connect to dbus: %s", err->message);
1683 g_clear_error(&err);
1686 g_conn = local_system_gconn;
1692 BT_EXPORT_API int bluetooth_gatt_init(void)
1694 GDBusConnection *conn;
1695 GError *error = NULL;
1696 GDBusNodeInfo *node_info = NULL;
1698 if (app_path != NULL) {
1699 BT_ERR("app path already exists! initialized");
1700 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1703 if (owner_id == 0) {
1704 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1705 BT_GATT_SERVICE_NAME,
1706 G_BUS_NAME_OWNER_FLAGS_NONE,
1707 NULL, NULL, NULL, NULL, NULL);
1710 BT_DBG("owner_id is [%d]", owner_id);
1711 app_path = g_strdup_printf("/com/%d", getpid());
1715 conn = __bt_gatt_get_gdbus_connection();
1717 BT_ERR("Unable to get connection");
1721 /* Register ObjectManager interface */
1722 node_info = __bt_gatt_create_method_node_info(
1723 manager_introspection_xml);
1724 if (node_info == NULL) {
1725 BT_ERR("failed to get node info");
1729 if (manager_id == 0) {
1730 BT_INFO("manager_id does not exists");
1732 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1733 node_info->interfaces[0],
1734 &manager_interface_vtable,
1735 NULL, NULL, &error);
1737 g_dbus_node_info_unref(node_info);
1738 if (manager_id == 0) {
1739 BT_ERR("failed to register: %s", error->message);
1740 g_error_free(error);
1744 return BLUETOOTH_ERROR_NONE;
1748 g_bus_unown_name(owner_id);
1755 __bt_gatt_close_gdbus_connection();
1757 return BLUETOOTH_ERROR_INTERNAL;
1760 BT_EXPORT_API int bluetooth_gatt_deinit()
1762 int ret = BLUETOOTH_ERROR_NONE;
1764 if (register_cancel) {
1765 g_cancellable_cancel(register_cancel);
1766 g_object_unref(register_cancel);
1767 register_cancel = NULL;
1770 /* Unown gdbus bus */
1772 /* remove/unregister all services */
1773 BT_DBG("removing all registered gatt service\n");
1774 bluetooth_gatt_delete_services();
1776 /* unregister the exported interface for object manager */
1777 g_dbus_connection_unregister_object(g_conn,
1782 ret = bluetooth_gatt_unregister_application();
1783 if (ret != BLUETOOTH_ERROR_NONE)
1784 BT_ERR("Fail to unregister application\n");
1786 g_bus_unown_name(owner_id);
1792 BT_DBG("Gatt service deinitialized \n");
1794 g_slist_free(gatt_services);
1795 gatt_services = NULL;
1797 g_object_unref(manager_gproxy);
1798 manager_gproxy = NULL;
1800 __bt_gatt_close_gdbus_connection();
1805 __bt_gatt_close_gdbus_connection();
1807 return BLUETOOTH_ERROR_NOT_FOUND;
1810 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1813 GError *error = NULL;
1815 GDBusNodeInfo *node_info;
1817 GVariantBuilder *builder = NULL;
1818 GVariantBuilder *builder1 = NULL;
1819 GVariantBuilder *inner_builder = NULL;
1820 gboolean svc_primary = TRUE;
1821 struct gatt_service_info *serv_info = NULL;
1823 node_info = __bt_gatt_create_method_node_info(
1824 service_introspection_xml);
1825 if (node_info == NULL)
1826 return BLUETOOTH_ERROR_INTERNAL;
1828 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1829 BT_DBG("gatt service path is [%s]", path);
1831 object_id = g_dbus_connection_register_object(g_conn, path,
1832 node_info->interfaces[0],
1833 &serv_interface_vtable,
1834 NULL, NULL, &error);
1835 g_dbus_node_info_unref(node_info);
1837 if (object_id == 0) {
1838 BT_ERR("failed to register: %s", error->message);
1839 g_error_free(error);
1842 return BLUETOOTH_ERROR_INTERNAL;
1845 /* Add object_id/gatt service information; it's required at the time of
1846 * service unregister and Getmanagedobjects
1848 serv_info = g_new0(struct gatt_service_info, 1);
1850 serv_info->serv_path = g_strdup(path);
1851 serv_info->serv_id = object_id;
1852 serv_info->service_uuid = g_strdup(svc_uuid);
1853 serv_info->is_svc_registered = FALSE;
1854 serv_info->is_svc_primary = svc_primary;
1856 gatt_services = g_slist_append(gatt_services, serv_info);
1858 /* emit interfacesadded signal here for service path */
1859 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1860 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1862 g_variant_builder_add(inner_builder, "{sv}",
1863 "UUID", g_variant_new_string(svc_uuid));
1865 g_variant_builder_add(inner_builder, "{sv}",
1866 "Primary", g_variant_new_boolean(svc_primary));
1868 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1870 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1871 g_variant_new("ao", builder1));
1873 g_variant_builder_add(builder, "{sa{sv}}",
1874 GATT_SERV_INTERFACE, inner_builder);
1876 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1877 "org.freedesktop.Dbus.ObjectManager",
1879 g_variant_new("(oa{sa{sv}})",
1882 if (error != NULL) {
1883 /* dbus gives error cause */
1884 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1885 error->code, error->message);
1886 g_clear_error(&error);
1891 *svc_path = g_strdup(path);
1894 g_variant_builder_unref(inner_builder);
1895 g_variant_builder_unref(builder);
1896 g_variant_builder_unref(builder1);
1898 return BLUETOOTH_ERROR_NONE;
1901 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1902 const char *svc_path, const char *char_uuid,
1903 bt_gatt_permission_t permissions,
1904 bt_gatt_characteristic_property_t properties,
1908 GError *error = NULL;
1910 GDBusNodeInfo *node_info;
1912 GVariantBuilder *builder = NULL;
1913 GVariantBuilder *inner_builder = NULL;
1914 struct gatt_service_info *serv_info = NULL;
1915 struct gatt_char_info *char_info = NULL;
1916 GVariantBuilder *builder2 = NULL;
1917 GVariantBuilder *builder3 = NULL;
1918 GVariant *flags_val = NULL;
1920 char *char_flags[NUMBER_OF_FLAGS];
1925 new_service = FALSE;
1928 BT_DBG("gatt svc_path path is [%s]", svc_path);
1929 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1930 if (serv_info == NULL)
1931 return BLUETOOTH_ERROR_INVALID_PARAM;
1933 node_info = __bt_gatt_create_method_node_info(
1934 characteristics_introspection_xml);
1935 if (node_info == NULL)
1936 return BLUETOOTH_ERROR_INTERNAL;
1938 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1939 BT_DBG("gatt characteristic path is [%s]", path);
1941 object_id = g_dbus_connection_register_object(g_conn, path,
1942 node_info->interfaces[0],
1943 &char_interface_vtable,
1944 NULL, NULL, &error);
1945 g_dbus_node_info_unref(node_info);
1947 if (object_id == 0) {
1948 BT_ERR("failed to register: %s", error->message);
1949 g_error_free(error);
1952 return BLUETOOTH_ERROR_INTERNAL;
1955 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1956 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1957 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1958 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1959 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1960 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1961 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1962 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1964 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1966 char_info = g_new0(struct gatt_char_info, 1);
1968 char_info->char_path = g_strdup(path);
1969 char_info->char_id = object_id;
1970 char_info->char_uuid = g_strdup(char_uuid);
1972 for (i = 0; i < flag_count; i++)
1973 char_info->char_flags[i] = char_flags[i];
1976 char_info->flags_length = flag_count;
1978 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1980 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1981 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1983 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1984 g_variant_new("s", char_uuid));
1985 g_variant_builder_add(inner_builder, "{sv}", "Service",
1986 g_variant_new("o", svc_path));
1988 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1990 for (i = 0; i < flag_count; i++)
1991 g_variant_builder_add(builder2, "s", char_flags[i]);
1993 flags_val = g_variant_new("as", builder2);
1994 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1997 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1999 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2000 g_variant_new("ao", builder3));
2002 g_variant_builder_add(builder, "{sa{sv}}",
2003 GATT_CHAR_INTERFACE,
2006 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2007 "org.freedesktop.Dbus.ObjectManager",
2009 g_variant_new("(oa{sa{sv}})",
2014 /* dBUS gives error cause */
2015 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2016 error->code, error->message);
2017 g_clear_error(&error);
2020 *char_path = g_strdup(path);
2026 g_variant_builder_unref(inner_builder);
2027 g_variant_builder_unref(builder);
2028 g_variant_builder_unref(builder2);
2029 g_variant_builder_unref(builder3);
2031 return BLUETOOTH_ERROR_NONE;
2034 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
2035 const char *characteristic, const char *char_value,
2038 gchar **line_argv = NULL;
2039 char *serv_path = NULL;
2040 struct gatt_char_info *char_info = NULL;
2041 GVariantBuilder *builder1 = NULL;
2042 GVariantBuilder *builder = NULL;
2043 GVariantBuilder *inner_builder = NULL;
2044 GVariant *char_val = NULL;
2045 GError *error = NULL;
2047 int res = BLUETOOTH_ERROR_NONE;
2049 line_argv = g_strsplit_set(characteristic, "/", 0);
2050 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2052 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
2054 if (char_info == NULL) {
2055 /* Fix : RESOURCE_LEAK */
2056 res = BLUETOOTH_ERROR_INVALID_PARAM;
2060 char_info->value_length = value_length;
2062 char_info->char_value = (char *)malloc(value_length);
2063 /* Fix : NULL_RETURNS */
2064 if (char_info->char_value == NULL) {
2065 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2069 for (i = 0; i < value_length; i++)
2070 char_info->char_value[i] = char_value[i];
2072 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2073 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2075 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2077 for (i = 0; i < value_length; i++)
2078 g_variant_builder_add(builder1, "y", char_value[i]);
2080 char_val = g_variant_new("ay", builder1);
2081 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
2083 g_variant_builder_add(builder, "{sa{sv}}",
2084 GATT_CHAR_INTERFACE,
2087 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2088 "org.freedesktop.Dbus.ObjectManager",
2090 g_variant_new("(oa{sa{sv}})",
2091 char_info->char_path, builder),
2095 /* dBUS gives error cause */
2096 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2097 error->code, error->message);
2098 g_clear_error(&error);
2100 g_variant_builder_unref(inner_builder);
2101 g_variant_builder_unref(builder);
2102 g_variant_builder_unref(builder1);
2104 g_strfreev(line_argv);
2110 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2111 const char *char_path, const char *desc_uuid,
2112 bt_gatt_permission_t permissions,
2115 static int desc_id = 1;
2116 GError *error = NULL;
2118 GDBusNodeInfo *node_info;
2120 GVariantBuilder *builder = NULL;
2121 GVariantBuilder *inner_builder = NULL;
2122 struct gatt_char_info *char_info = NULL;
2123 struct gatt_desc_info *desc_info = NULL;
2124 gchar **line_argv = NULL;
2126 GVariantBuilder *builder2 = NULL;
2127 GVariant *flags_val = NULL;
2129 char *desc_flags[NUMBER_OF_FLAGS];
2137 line_argv = g_strsplit_set(char_path, "/", 0);
2138 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2140 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2141 if (char_info == NULL) {
2142 g_strfreev(line_argv);
2144 return BLUETOOTH_ERROR_INVALID_PARAM;
2147 node_info = __bt_gatt_create_method_node_info(
2148 descriptor_introspection_xml);
2149 if (node_info == NULL) {
2150 g_strfreev(line_argv);
2152 return BLUETOOTH_ERROR_INTERNAL;
2155 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2156 BT_DBG("gatt descriptor path is [%s]", path);
2158 object_id = g_dbus_connection_register_object(g_conn, path,
2159 node_info->interfaces[0],
2160 &desc_interface_vtable,
2161 NULL, NULL, &error);
2162 g_dbus_node_info_unref(node_info);
2164 if (object_id == 0) {
2165 BT_ERR("failed to register: %s", error->message);
2166 g_error_free(error);
2168 g_strfreev(line_argv);
2171 return BLUETOOTH_ERROR_INTERNAL;
2174 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2176 desc_info = g_new0(struct gatt_desc_info, 1);
2178 desc_info->desc_path = g_strdup(path);
2179 desc_info->desc_id = object_id;
2180 desc_info->desc_uuid = g_strdup(desc_uuid);
2182 for (i = 0; i < flag_count; i++)
2183 desc_info->desc_flags[i] = desc_flags[i];
2185 desc_info->flags_length = flag_count;
2187 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2189 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2190 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2192 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2193 g_variant_new("s", desc_uuid));
2194 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2195 g_variant_new("o", char_path));
2197 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2199 for (i = 0; i < flag_count; i++)
2200 g_variant_builder_add(builder2, "s", desc_flags[i]);
2202 flags_val = g_variant_new("as", builder2);
2203 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2206 g_variant_builder_add(builder, "{sa{sv}}",
2207 GATT_DESC_INTERFACE,
2210 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2211 "org.freedesktop.Dbus.ObjectManager",
2213 g_variant_new("(oa{sa{sv}})",
2217 /* dBUS gives error cause */
2218 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2219 error->code, error->message);
2220 g_clear_error(&error);
2223 *desc_path = g_strdup(path);
2227 g_strfreev(line_argv);
2228 g_variant_builder_unref(inner_builder);
2229 g_variant_builder_unref(builder);
2230 g_variant_builder_unref(builder2);
2232 return BLUETOOTH_ERROR_NONE;
2235 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2236 const char *desc_path, const char *desc_value,
2239 GError *error = NULL;
2240 GVariantBuilder *builder = NULL;
2241 GVariantBuilder *inner_builder = NULL;
2242 GVariantBuilder *builder1 = NULL;
2243 struct gatt_desc_info *desc_info = NULL;
2244 gchar **line_argv = NULL;
2246 GVariant *desc_val = NULL;
2247 char *serv_path = NULL;
2250 line_argv = g_strsplit_set(desc_path, "/", 0);
2251 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2252 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2254 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2256 /* Free the allocated memory */
2257 g_strfreev(line_argv);
2261 /* Fix : NULL_RETURNS */
2262 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2264 desc_info->desc_value = (char *)malloc(value_length);
2266 /* Fix : NULL_RETURNS */
2267 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2269 for (i = 0; i < value_length; i++)
2270 desc_info->desc_value[i] = desc_value[i];
2272 desc_info->value_length = value_length;
2274 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2275 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2277 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2279 for (i = 0; i < value_length; i++)
2280 g_variant_builder_add(builder1, "y", desc_value[i]);
2282 desc_val = g_variant_new("ay", builder1);
2283 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2285 g_variant_builder_add(builder, "{sa{sv}}",
2286 GATT_DESC_INTERFACE,
2289 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2290 "org.freedesktop.Dbus.ObjectManager",
2292 g_variant_new("(oa{sa{sv}})",
2293 desc_info->desc_path, builder),
2296 if (error != NULL) {
2297 BT_ERR("D-Bus API failure: errCode[%x], \
2299 error->code, error->message);
2300 g_clear_error(&error);
2303 g_variant_builder_unref(inner_builder);
2304 g_variant_builder_unref(builder);
2305 g_variant_builder_unref(builder1);
2307 return BLUETOOTH_ERROR_NONE;
2310 int bluetooth_gatt_get_service(const char *svc_uuid)
2312 GDBusProxy *proxy = NULL;
2315 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2316 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2318 return BLUETOOTH_ERROR_INTERNAL;
2320 uuid = g_strdup(svc_uuid);
2322 g_dbus_proxy_call(proxy,
2324 g_variant_new("(s)",
2326 G_DBUS_CALL_FLAGS_NONE, -1,
2328 (GAsyncReadyCallback) get_service_cb,
2333 return BLUETOOTH_ERROR_NONE;
2336 BT_EXPORT_API int bluetooth_gatt_register_service(
2337 const char *svc_path)
2339 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2340 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2341 BT_ERR("Don't have aprivilege to use this API");
2342 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2345 register_pending_cnt++;
2347 if (__bt_gatt_get_service_state(svc_path)) {
2348 BT_DBG("service already registered \n");
2349 return BLUETOOTH_ERROR_NONE;
2352 __bt_gatt_set_service_state(svc_path, TRUE);
2354 return BLUETOOTH_ERROR_NONE;
2357 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2359 GDBusProxy *proxy = NULL;
2361 if (!is_server_started) {
2363 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2364 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2365 BT_ERR("Don't have aprivilege to use this API");
2366 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2369 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2370 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2371 if (proxy == NULL || app_path == NULL)
2372 return BLUETOOTH_ERROR_INTERNAL;
2374 BT_INFO("RegisterApplication");
2376 if (register_cancel) {
2377 g_cancellable_cancel(register_cancel);
2378 g_object_unref(register_cancel);
2381 register_cancel = g_cancellable_new();
2383 g_dbus_proxy_call(proxy,
2384 "RegisterApplication",
2385 g_variant_new("(oa{sv})",
2387 G_DBUS_CALL_FLAGS_NONE, -1,
2389 (GAsyncReadyCallback) register_application_cb,
2392 is_server_started = true;
2394 return BLUETOOTH_ERROR_NONE;
2397 BT_INFO("Already RegisterApplication");
2399 return BLUETOOTH_ERROR_NONE;
2402 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2405 int error = BLUETOOTH_ERROR_NONE;
2409 for (l = gatt_services; l != NULL; l = l->next) {
2410 struct gatt_service_info *info = l->data;
2411 BT_DBG("svc_path is %s", info->serv_path);
2412 if (bluetooth_gatt_unregister_service(info->serv_path)
2413 != BLUETOOTH_ERROR_NONE) {
2414 error = BLUETOOTH_ERROR_INTERNAL;
2415 BT_ERR("Error in removing service %s \n",
2419 BT_DBG(" All services removed successfully.\n ");
2421 BT_DBG(" There are no registered services.\n ");
2424 g_slist_free(gatt_services);
2425 gatt_services = NULL;
2428 if (error != BLUETOOTH_ERROR_NONE)
2431 return BLUETOOTH_ERROR_NONE;
2434 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2435 const char *char_path, const char* char_value,
2438 GVariantBuilder *outer_builder;
2439 GVariantBuilder *inner_builder;
2440 GVariantBuilder *invalidated_builder;
2441 GVariant *update_value = NULL;
2442 GError *error = NULL;
2443 gboolean ret = FALSE;
2444 int err = BLUETOOTH_ERROR_NONE;
2446 gchar **line_argv = NULL;
2447 gchar *serv_path = NULL;
2448 const char *value = NULL;
2450 line_argv = g_strsplit_set(char_path, "/", 0);
2451 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2453 if (!__bt_gatt_get_service_state(serv_path)) {
2454 BT_DBG("service not registered for this characteristic \n");
2456 g_strfreev(line_argv);
2457 return BLUETOOTH_ERROR_INTERNAL;
2460 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2461 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2463 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2464 for (i = 0; i < value_length; i++)
2465 g_variant_builder_add(inner_builder, "y", char_value[i]);
2467 update_value = g_variant_new("ay", inner_builder);
2469 g_variant_builder_add(outer_builder, "{sv}", "Value",
2472 BT_DBG("Updating characteristic value \n");
2473 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2475 "org.freedesktop.DBus.Properties",
2476 "PropertiesChanged",
2477 g_variant_new("(sa{sv}as)",
2478 "org.bluez.GattCharacteristic1",
2479 outer_builder, invalidated_builder),
2483 if (error != NULL) {
2484 BT_ERR("D-Bus API failure: errCode[%x], \
2486 error->code, error->message);
2487 g_clear_error(&error);
2489 err = BLUETOOTH_ERROR_INTERNAL;
2491 struct gatt_char_info *char_info = NULL;
2493 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2494 if (char_info == NULL) {
2496 g_strfreev(line_argv);
2497 g_variant_builder_unref(inner_builder);
2498 g_variant_builder_unref(outer_builder);
2499 g_variant_builder_unref(invalidated_builder);
2501 return BLUETOOTH_ERROR_INVALID_DATA;
2504 char_info->value_length = value_length;
2506 value = (char *)realloc(char_info->char_value, value_length);
2507 if (value == NULL) {
2509 g_strfreev(line_argv);
2510 g_variant_builder_unref(inner_builder);
2511 g_variant_builder_unref(outer_builder);
2512 g_variant_builder_unref(invalidated_builder);
2514 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2517 char_info->char_value = (char*)value;
2518 if (char_info->char_value) {
2519 for (i = 0; i < value_length; i++)
2520 char_info->char_value[i] = char_value[i];
2525 g_strfreev(line_argv);
2526 g_variant_builder_unref(inner_builder);
2527 g_variant_builder_unref(outer_builder);
2528 g_variant_builder_unref(invalidated_builder);
2533 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2540 g_free(desc_info->desc_path);
2541 g_free(desc_info->desc_uuid);
2542 g_free(desc_info->desc_value);
2544 for (i = 0; i < desc_info->flags_length; i++)
2545 g_free(desc_info->desc_flags[i]);
2550 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2557 g_free(char_info->char_path);
2558 g_free(char_info->char_uuid);
2559 g_free(char_info->char_value);
2561 for (i = 0; i < char_info->flags_length; i++)
2562 g_free(char_info->char_flags[i]);
2567 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2572 g_free(svc_info->serv_path);
2573 g_free(svc_info->service_uuid);
2577 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2580 struct gatt_service_info *svc_info;
2582 int err = BLUETOOTH_ERROR_NONE;
2584 BT_DBG("svc_path %s", svc_path);
2585 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2588 BT_ERR("Unable to find service info");
2589 return BLUETOOTH_ERROR_NOT_FOUND;
2592 err = __bt_gatt_unregister_service(svc_path);
2593 if (err != BLUETOOTH_ERROR_NONE) {
2594 BT_ERR("Could not unregister application");
2598 for (l = svc_info->char_data; l != NULL; l = l->next) {
2599 struct gatt_char_info *char_info = l->data;
2601 if (char_info == NULL)
2604 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2605 struct gatt_desc_info *desc_info = l1->data;
2607 if (desc_info == NULL)
2610 ret = g_dbus_connection_unregister_object(g_conn,
2611 desc_info->desc_id);
2613 __bt_gatt_emit_interface_removed(
2614 desc_info->desc_path,
2615 GATT_DESC_INTERFACE);
2617 err = BLUETOOTH_ERROR_INTERNAL;
2620 /* list remove & free */
2621 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2622 __bt_gatt_free_descriptor_info(desc_info);
2625 g_slist_free(char_info->desc_data);
2626 char_info->desc_data = NULL;
2628 ret = g_dbus_connection_unregister_object(g_conn,
2629 char_info->char_id);
2631 __bt_gatt_emit_interface_removed(char_info->char_path,
2632 GATT_CHAR_INTERFACE);
2634 err = BLUETOOTH_ERROR_INTERNAL;
2637 /* list remove & free */
2638 svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
2639 __bt_gatt_free_characteristic_info(char_info);
2642 g_slist_free(svc_info->char_data);
2643 svc_info->char_data = NULL;
2645 ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2647 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2648 GATT_SERV_INTERFACE);
2650 err = BLUETOOTH_ERROR_INTERNAL;
2653 ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2655 BT_DBG("Unregistered the service on properties interface");
2657 /* list remove & free */
2658 gatt_services = g_slist_remove(gatt_services, svc_info);
2659 __bt_gatt_free_service_info(svc_info);
2661 new_service = FALSE;
2663 if (gatt_services == NULL)
2665 else if (gatt_services->next == NULL)
2671 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2672 int resp_state, int offset, char *value, int value_length)
2674 struct gatt_req_info *req_info = NULL;
2676 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2677 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2678 BT_ERR("Don't have aprivilege to use this API");
2679 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2682 req_info = __bt_gatt_find_request_info(request_id);
2683 if (req_info == NULL) {
2684 BT_ERR("Coundn't find request id [%d]", request_id);
2685 return BLUETOOTH_ERROR_INTERNAL;
2688 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2689 BT_ERR("resp_state is 0x%X", resp_state);
2690 char err_msg[20] = { 0, };
2691 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2692 g_dbus_method_invocation_return_dbus_error(req_info->context,
2693 "org.bluez.Error.Failed", err_msg);
2695 gatt_requests = g_slist_remove(gatt_requests, req_info);
2697 req_info->context = NULL;
2698 if (req_info->attr_path)
2699 g_free(req_info->attr_path);
2700 if (req_info->svc_path)
2701 g_free(req_info->svc_path);
2704 return BLUETOOTH_ERROR_NONE;
2707 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2709 GVariantBuilder *inner_builder = NULL;
2710 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2711 if (value_length > 0 && value != NULL) {
2712 for (i = 0; i < value_length; i++)
2713 g_variant_builder_add(inner_builder, "y", value[i]);
2715 g_dbus_method_invocation_return_value(req_info->context,
2716 g_variant_new("(ay)", inner_builder));
2717 g_variant_builder_unref(inner_builder);
2719 g_dbus_method_invocation_return_value(req_info->context, NULL);
2721 gatt_requests = g_slist_remove(gatt_requests, req_info);
2723 req_info->context = NULL;
2724 if (req_info->attr_path)
2725 g_free(req_info->attr_path);
2726 if (req_info->svc_path)
2727 g_free(req_info->svc_path);
2730 return BLUETOOTH_ERROR_NONE;
2733 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2734 bluetooth_device_address_t *unicast_address)
2736 GVariantBuilder *outer_builder;
2737 GVariantBuilder *invalidated_builder;
2738 GError *error = NULL;
2739 gboolean notify = TRUE;
2740 gboolean ret = TRUE;
2741 int err = BLUETOOTH_ERROR_NONE;
2742 gchar **line_argv = NULL;
2743 gchar *serv_path = NULL;
2744 char addr[20] = { 0 };
2746 line_argv = g_strsplit_set(char_path, "/", 0);
2747 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2749 if (!__bt_gatt_get_service_state(serv_path)) {
2750 BT_DBG("service not registered for this characteristic \n");
2752 g_strfreev(line_argv);
2753 return BLUETOOTH_ERROR_INTERNAL;
2758 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2759 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2761 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2762 g_variant_new("b", notify));
2764 if (unicast_address) {
2765 _bt_convert_addr_type_to_string(addr,
2766 (unsigned char *)unicast_address->addr);
2768 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2769 g_variant_new("s", addr));
2771 BT_DBG("Set characteristic Notification \n");
2772 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2774 "org.freedesktop.DBus.Properties",
2775 "PropertiesChanged",
2776 g_variant_new("(sa{sv}as)",
2777 "org.bluez.GattCharacteristic1",
2778 outer_builder, invalidated_builder),
2782 if (error != NULL) {
2783 BT_ERR("D-Bus API failure: errCode[%x], \
2785 error->code, error->message);
2786 g_clear_error(&error);
2788 err = BLUETOOTH_ERROR_INTERNAL;
2791 g_strfreev(line_argv);
2792 g_variant_builder_unref(outer_builder);
2793 g_variant_builder_unref(invalidated_builder);
2800 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2804 if (!is_server_started) {
2806 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2807 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2808 BT_ERR("Don't have aprivilege to use this API");
2809 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2812 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2813 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2815 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2816 in_param1, in_param2, in_param3, in_param4, &out_param);
2817 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2819 if (ret != BLUETOOTH_ERROR_NONE) {
2820 BT_ERR("Register application failed");
2823 is_server_started = true;
2825 return BLUETOOTH_ERROR_NONE;
2828 BT_INFO("Already RegisterApplication");
2829 return BLUETOOTH_ERROR_NONE;
2833 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2836 int ret = BLUETOOTH_ERROR_NONE;
2839 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2841 /* Register event handler for GATT */
2842 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2844 if (ret != BLUETOOTH_ERROR_NONE &&
2845 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2846 BT_ERR("Fail to init the event handler");
2847 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2851 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2852 in_param1, in_param2, in_param3, in_param4, &out_param);
2854 /* App ID -1 is invalid */
2855 if (ret != BLUETOOTH_ERROR_NONE) {
2856 BT_INFO("GATT Server Registration failed result [%d]", ret);
2859 *instance_id = g_array_index(out_param, int, 0);
2860 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2864 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2866 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2870 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2873 BT_INFO("GATT Server Deinitialize");
2874 /* Unregister the event */
2875 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2877 if (ret != BLUETOOTH_ERROR_NONE) {
2878 BT_ERR("Fail to deinit the event handler");
2882 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2887 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2888 int instance_id, int *service_handle)
2890 BT_CHECK_ENABLED(return);
2891 BT_CHECK_PARAMETER(svc_uuid, return);
2894 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2896 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2899 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2901 g_array_append_vals(in_param1, &type, sizeof(int));
2902 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2903 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2904 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2906 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2907 in_param1, in_param2, in_param3, in_param4, &out_param);
2909 /* ATT handle 0 is reserved, hence it can not be used by app.
2910 It will be used to indicate error in regsitering attribute */
2911 if (result != BLUETOOTH_ERROR_NONE)
2912 *service_handle = 0;
2914 *service_handle = g_array_index(out_param, int, 0);
2916 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2921 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2922 const bluetooth_gatt_server_attribute_params_t *param,
2925 BT_CHECK_ENABLED(return);
2926 BT_CHECK_PARAMETER(char_uuid, return);
2927 BT_CHECK_PARAMETER(param, return);
2930 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2932 char *char_flags[NUMBER_OF_FLAGS];
2934 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2935 flag_count = bluetooth_gatt_convert_prop2string(param->properties, char_flags);
2936 BT_INFO("Flag count [%d]", flag_count);
2939 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2941 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2942 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2944 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2945 in_param1, in_param2, in_param3, in_param4, &out_param);
2947 /* ATT handle 0 is reserved, hence it can not be used by app.
2948 It will be used to indicate error in regsitering attribute */
2949 if (result != BLUETOOTH_ERROR_NONE) {
2950 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2953 *char_handle = g_array_index(out_param, int, 0);
2954 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2957 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2961 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2962 int service_handle, int instance_id, int *descriptor_handle)
2964 BT_CHECK_ENABLED(return);
2965 BT_CHECK_PARAMETER(desc_uuid, return);
2968 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2970 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2973 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2975 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2976 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2977 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2978 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2980 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2981 in_param1, in_param2, in_param3, in_param4, &out_param);
2983 /* ATT handle 0 is reserved, hence it can not be used by app.
2984 It will be used to indicate error in regsitering attribute */
2985 if (result != BLUETOOTH_ERROR_NONE) {
2986 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2987 *descriptor_handle = 0;
2989 *descriptor_handle = g_array_index(out_param, int, 0);
2990 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2993 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2998 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
3000 BT_CHECK_ENABLED(return);
3004 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3006 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3007 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3009 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
3010 in_param1, in_param2, in_param3, in_param4, &out_param);
3012 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3017 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
3018 const bluetooth_gatt_att_data_t *value)
3020 BT_CHECK_PARAMETER(param, return);
3021 BT_CHECK_PARAMETER(value, return);
3022 BT_CHECK_ENABLED(return);
3026 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3028 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
3029 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
3031 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
3032 in_param1, in_param2, in_param3, in_param4, &out_param);
3034 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3040 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
3041 const bluetooth_gatt_server_indication_params_t *param,
3042 const bluetooth_gatt_att_data_t *att_value)
3044 BT_CHECK_PARAMETER(param, return);
3045 BT_CHECK_PARAMETER(att_value, return);
3046 BT_CHECK_ENABLED(return);
3050 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3052 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
3053 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
3054 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
3056 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
3057 in_param1, in_param2, in_param3, in_param4, &out_param);
3059 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3064 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
3066 BT_CHECK_ENABLED(return);
3070 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3072 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3073 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3075 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
3076 in_param1, in_param2, in_param3, in_param4, &out_param);
3078 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3083 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
3085 BT_CHECK_ENABLED(return);
3089 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3091 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3092 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3094 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
3095 in_param1, in_param2, in_param3, in_param4, &out_param);
3097 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3102 /* Tizen Platform Specific */
3103 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
3104 const bluetooth_gatt_server_update_value_t *value)
3106 BT_CHECK_ENABLED(return);
3107 BT_CHECK_PARAMETER(value, return);
3111 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3113 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3114 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3116 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3117 in_param1, in_param2, in_param3, in_param4, &out_param);
3119 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3124 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3126 BT_CHECK_ENABLED(return);
3130 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3132 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3134 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3135 in_param1, in_param2, in_param3, in_param4, &out_param);
3137 if (result != BLUETOOTH_ERROR_NONE)
3138 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3140 BT_INFO("GATT Server Unregistration successful");
3142 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);