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);
542 struct gatt_service_info *serv_info = l1->data;
543 if (serv_info == NULL) {
544 BT_ERR("service info value is NULL");
545 g_dbus_method_invocation_return_value(invocation, NULL);
549 /* Prepare inner builder for GattService1 interface */
550 BT_DBG("Creating builder for service");
551 svc_builder = g_variant_builder_new(
552 G_VARIANT_TYPE("a{sa{sv}}"));
553 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
555 g_variant_builder_add(inner_builder, "{sv}", "UUID",
556 g_variant_new_string(serv_info->service_uuid));
558 g_variant_builder_add(inner_builder, "{sv}", "Primary",
559 g_variant_new_boolean(serv_info->is_svc_primary));
562 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
563 BT_DBG("Adding Charatarisitcs list");
564 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
565 struct gatt_char_info *char_info = l4->data;
566 g_variant_builder_add(inner_builder1, "o",
567 char_info->char_path);
568 BT_DBG("%s", char_info->char_path);
571 svc_char = g_variant_new("ao", inner_builder1);
572 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
575 g_variant_builder_add(svc_builder, "{sa{sv}}",
579 g_variant_builder_add(builder, "{oa{sa{sv}}}",
580 serv_info->serv_path,
583 g_variant_builder_unref(inner_builder1);
585 /* Prepare inner builder for GattCharacteristic1 interface */
587 GSList *l2 = serv_info->char_data;
588 BT_DBG("Creating builder for characteristics \n");
591 BT_DBG("characteristic data is NULL");
593 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
595 GVariantBuilder *char_builder = NULL;
596 GVariantBuilder *inner_builder = NULL;
597 GVariantBuilder *builder1 = NULL;
598 GVariantBuilder *builder2 = NULL;
599 GVariantBuilder *builder3 = NULL;
600 GVariant *char_val = NULL;
601 GVariant *flags_val = NULL;
602 GVariant *char_desc = NULL;
603 char *unicast = NULL;
604 gboolean notify = FALSE;
607 char_builder = g_variant_builder_new(
610 inner_builder = g_variant_builder_new(
614 struct gatt_char_info *char_info = l2->data;
615 if (char_info == NULL) {
616 BT_ERR("char_info is NULL");
621 g_variant_builder_add(inner_builder, "{sv}", "UUID",
622 g_variant_new_string(char_info->char_uuid));
624 g_variant_builder_add(inner_builder, "{sv}", "Service",
625 g_variant_new("o", serv_info->serv_path));
627 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
629 if (char_info->char_value != NULL) {
630 for (i = 0; i < char_info->value_length; i++) {
631 g_variant_builder_add(builder1, "y",
632 char_info->char_value[i]);
634 char_val = g_variant_new("ay", builder1);
635 g_variant_builder_add(inner_builder, "{sv}",
639 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
641 for (i = 0; i < char_info->flags_length; i++) {
642 g_variant_builder_add(builder2, "s",
643 char_info->char_flags[i]);
646 flags_val = g_variant_new("as", builder2);
647 g_variant_builder_add(inner_builder, "{sv}", "Flags",
651 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
652 g_variant_new("b", notify));
655 unicast = g_strdup("00:00:00:00:00:00");
656 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
657 g_variant_new("s", unicast));
660 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
661 BT_DBG("Adding Descriptors list");
663 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
664 struct gatt_desc_info *desc_info = l4->data;
665 g_variant_builder_add(builder3, "o",
666 desc_info->desc_path);
667 BT_DBG("%s", desc_info->desc_path);
670 char_desc = g_variant_new("ao", builder3);
671 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
674 g_variant_builder_add(char_builder, "{sa{sv}}",
675 GATT_CHAR_INTERFACE , inner_builder);
676 g_variant_builder_add(builder, "{oa{sa{sv}}}",
677 char_info->char_path, char_builder);
679 /*Prepare inner builder for GattDescriptor1 interface*/
681 GSList *l3 = char_info->desc_data;
684 BT_DBG("descriptor data is NULL");
686 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
688 BT_DBG("Creating builder for descriptor \n");
690 GVariantBuilder *desc_builder = NULL;
691 GVariantBuilder *inner_builder = NULL;
692 GVariantBuilder *builder1 = NULL;
693 GVariantBuilder *builder2 = NULL;
694 GVariant *desc_val = NULL;
696 desc_builder = g_variant_builder_new(
699 inner_builder = g_variant_builder_new(
703 struct gatt_desc_info *desc_info = l3->data;
704 if (desc_info == NULL) {
705 BT_ERR("desc_info is NULL");
710 g_variant_builder_add(inner_builder,
712 g_variant_new_string(
713 desc_info->desc_uuid));
716 g_variant_builder_add(inner_builder, "{sv}",
719 char_info->char_path));
722 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
724 if (desc_info->desc_value != NULL) {
725 for (i = 0; i < desc_info->value_length; i++) {
726 g_variant_builder_add(builder1, "y",
727 desc_info->desc_value[i]);
729 desc_val = g_variant_new("ay", builder1);
730 g_variant_builder_add(inner_builder, "{sv}",
735 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
737 for (i = 0; i < desc_info->flags_length; i++) {
738 g_variant_builder_add(builder2, "s",
739 desc_info->desc_flags[i]);
742 flags_val = g_variant_new("as", builder2);
743 g_variant_builder_add(inner_builder, "{sv}", "Flags",
746 g_variant_builder_add(desc_builder, "{sa{sv}}",
750 g_variant_builder_add(builder, "{oa{sa{sv}}}",
751 desc_info->desc_path,
754 /*unref descriptor builder pointers*/
755 g_variant_builder_unref(builder1);
756 g_variant_builder_unref(builder2);
757 g_variant_builder_unref(inner_builder);
758 g_variant_builder_unref(desc_builder);
763 /*unref char builder pointers*/
764 g_variant_builder_unref(builder1);
765 g_variant_builder_unref(builder2);
766 g_variant_builder_unref(builder3);
767 g_variant_builder_unref(inner_builder);
768 g_variant_builder_unref(char_builder);
771 /*unref service builder pointers*/
772 g_variant_builder_unref(inner_builder);
773 g_variant_builder_unref(svc_builder);
776 /* Return builder as method reply */
777 BT_DBG("Sending gatt service builder values to Bluez");
778 g_dbus_method_invocation_return_value(invocation,
785 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
789 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
790 struct gatt_service_info *serv_info = l1->data;
792 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
793 struct gatt_char_info *char_info = l2->data;
795 if (g_strcmp0(char_info->char_path, char_path)
800 BT_ERR("Gatt service not found");
804 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
806 GSList *l1, *l2, *l3;
808 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
809 struct gatt_service_info *serv_info = l1->data;
811 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
812 struct gatt_char_info *char_info = l2->data;
814 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
815 struct gatt_desc_info *desc_info = l3->data;
817 if (g_strcmp0(desc_info->desc_path, desc_path)
823 BT_ERR("Gatt service not found");
827 static void __bt_gatt_char_method_call(GDBusConnection *connection,
829 const gchar *object_path,
830 const gchar *interface_name,
831 const gchar *method_name,
832 GVariant *parameters,
833 GDBusMethodInvocation *invocation,
837 if (g_strcmp0(method_name, "ReadValue") == 0) {
841 bt_gatt_read_req_t read_req = {0, };
842 bt_user_info_t *user_info = NULL;
843 struct gatt_req_info *req_info = NULL;
844 struct gatt_service_info *svc_info = NULL;
845 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
846 GVariant *param = NULL;
849 BT_DBG("Application path = %s", object_path);
850 BT_DBG("Sender = %s", sender);
852 user_info = _bt_get_user_data(BT_COMMON);
853 if (user_info == NULL) {
854 BT_INFO("No callback is set for %s", object_path);
855 g_dbus_method_invocation_return_value(invocation, NULL);
859 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
860 if (svc_info == NULL) {
861 BT_ERR("Coudn't find service for %s", object_path);
862 g_dbus_method_invocation_return_value(invocation, NULL);
866 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
867 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
869 read_req.att_handle = (char *)object_path;
870 read_req.address = addr;
871 read_req.req_id = req_id;
872 read_req.offset = offset;
873 read_req.service_handle = svc_info->serv_path;
875 /* Store requets information */
876 req_info = g_new0(struct gatt_req_info, 1);
877 req_info->attr_path = g_strdup(object_path);
878 req_info->svc_path = g_strdup(read_req.service_handle);
879 req_info->request_id = req_id;
880 req_info->offset = offset;
881 req_info->context = invocation;
882 gatt_requests = g_slist_append(gatt_requests, req_info);
884 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
885 BLUETOOTH_ERROR_NONE, &read_req,
886 user_info->cb, user_info->user_data);
888 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
889 param = g_variant_new("(sssyq)",
891 read_req.service_handle,
895 #ifdef TIZEN_FEATURE_BT_HPS
896 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
898 #ifdef TIZEN_FEATURE_BT_OTP
899 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
903 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
904 GVariant *var = NULL;
908 gboolean response_needed = FALSE;
909 bt_gatt_value_change_t value_change = {0, };
910 bt_user_info_t *user_info = NULL;
912 struct gatt_service_info *svc_info = NULL;
913 struct gatt_req_info *req_info = NULL;
914 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
915 GVariant *param = NULL;
918 BT_DBG("WriteValue");
919 BT_DBG("Application path = %s", object_path);
920 BT_DBG("Sender = %s", sender);
922 g_variant_get(parameters, "(&suqb@ay)",
923 &addr, &req_id, &offset, &response_needed, &var);
924 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
926 user_info = _bt_get_user_data(BT_COMMON);
928 BT_INFO("No callback is set for %s", object_path);
929 g_variant_unref(var);
931 g_dbus_method_invocation_return_value(invocation, NULL);
933 g_object_unref(invocation);
937 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
938 if (svc_info == NULL) {
939 BT_ERR("Coudn't find service for %s", object_path);
940 g_variant_unref(var);
942 g_dbus_method_invocation_return_value(invocation, NULL);
944 g_object_unref(invocation);
948 value_change.att_handle = (char *)object_path;
949 value_change.address = addr;
950 value_change.service_handle = svc_info->serv_path;
951 value_change.offset = offset;
952 value_change.req_id = req_id;
953 value_change.response_needed = response_needed;
955 len = g_variant_get_size(var);
959 value_change.att_value = (guint8 *)g_malloc(len);
961 data = (char *)g_variant_get_data(var);
962 memcpy(value_change.att_value, data, len);
964 value_change.val_len = len;
966 if (response_needed) {
967 /* Store requets information */
968 req_info = g_new0(struct gatt_req_info, 1);
969 req_info->attr_path = g_strdup(object_path);
970 req_info->svc_path = g_strdup(value_change.service_handle);
971 req_info->request_id = req_id;
972 req_info->offset = offset;
973 req_info->context = invocation;
974 gatt_requests = g_slist_append(gatt_requests, req_info);
976 g_object_unref(invocation);
980 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
981 BLUETOOTH_ERROR_NONE, &value_change,
982 user_info->cb, user_info->user_data);
984 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
987 svc_path = g_strdup(svc_info->serv_path);
988 param = g_variant_new("(sssyq@ay)",
995 #ifdef TIZEN_FEATURE_BT_HPS
996 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
998 #ifdef TIZEN_FEATURE_BT_OTP
999 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1006 g_free(value_change.att_value);
1007 g_variant_unref(var);
1009 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1010 bt_user_info_t *user_info = NULL;
1011 bt_gatt_char_notify_change_t notify_change = {0, };
1012 #if TIZEN_FEATURE_BT_OTP
1013 GVariant *param = NULL;
1015 BT_DBG("StartNotify");
1016 user_info = _bt_get_user_data(BT_COMMON);
1017 if (user_info != NULL) {
1018 struct gatt_service_info *svc_info = NULL;
1019 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1021 notify_change.service_handle = svc_info->serv_path;
1022 notify_change.att_handle = (char *)object_path;
1023 notify_change.att_notify = TRUE;
1024 _bt_common_event_cb(
1025 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1026 BLUETOOTH_ERROR_NONE, ¬ify_change,
1027 user_info->cb, user_info->user_data);
1028 #if TIZEN_FEATURE_BT_OTP
1029 param = g_variant_new("(ssb)",
1030 notify_change.att_handle,
1031 notify_change.service_handle,
1032 notify_change.att_notify);
1033 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1037 g_object_unref(invocation);
1039 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1040 bt_user_info_t *user_info = NULL;
1041 bt_gatt_char_notify_change_t notify_change = {0, };
1042 #if TIZEN_FEATURE_BT_OTP
1043 GVariant *param = NULL;
1045 BT_DBG("StopNotify");
1046 user_info = _bt_get_user_data(BT_COMMON);
1047 if (user_info != NULL) {
1048 struct gatt_service_info *svc_info = NULL;
1049 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1051 notify_change.service_handle = svc_info->serv_path;
1052 notify_change.att_handle = (char *)object_path;
1053 notify_change.att_notify = FALSE;
1054 _bt_common_event_cb(
1055 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1056 BLUETOOTH_ERROR_NONE, ¬ify_change,
1057 user_info->cb, user_info->user_data);
1058 #if TIZEN_FEATURE_BT_OTP
1059 param = g_variant_new("(ssb)",
1060 notify_change.att_handle,
1061 notify_change.service_handle,
1062 notify_change.att_notify);
1063 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1067 g_object_unref(invocation);
1069 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1071 bt_gatt_indicate_confirm_t confirm = {0, };
1072 bt_user_info_t *user_info = NULL;
1073 gboolean complete = FALSE;
1074 struct gatt_service_info *svc_info = NULL;
1076 BT_DBG("IndicateConfirm");
1077 BT_DBG("Application path = %s", object_path);
1078 BT_DBG("Sender = %s", sender);
1080 g_variant_get(parameters, "(&sb)", &addr, &complete);
1081 BT_DBG("Remote Device address number = %s", addr);
1083 confirm.att_handle = (char *)object_path;
1084 confirm.address = addr;
1085 confirm.complete = complete;
1087 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1088 if (svc_info != NULL) {
1089 confirm.service_handle = svc_info->serv_path;
1091 user_info = _bt_get_user_data(BT_COMMON);
1092 if (user_info != NULL) {
1093 _bt_common_event_cb(
1094 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1095 BLUETOOTH_ERROR_NONE, &confirm,
1096 user_info->cb, user_info->user_data);
1101 g_dbus_method_invocation_return_value(invocation, NULL);
1104 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1105 const gchar *sender,
1106 const gchar *object_path,
1107 const gchar *interface_name,
1108 const gchar *method_name,
1109 GVariant *parameters,
1110 GDBusMethodInvocation *invocation,
1113 if (g_strcmp0(method_name, "ReadValue") == 0) {
1117 bt_gatt_read_req_t read_req = {0, };
1118 bt_user_info_t *user_info = NULL;
1119 struct gatt_req_info *req_info = NULL;
1120 struct gatt_service_info *svc_info = NULL;
1122 BT_DBG("ReadValue");
1123 BT_DBG("Application path = %s", object_path);
1124 BT_DBG("Sender = %s", sender);
1126 user_info = _bt_get_user_data(BT_COMMON);
1127 if (user_info == NULL) {
1128 BT_INFO("No callback is set for %s", object_path);
1129 g_dbus_method_invocation_return_value(invocation, NULL);
1133 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1134 if (svc_info == NULL) {
1135 BT_ERR("Coudn't find service for %s", object_path);
1136 g_dbus_method_invocation_return_value(invocation, NULL);
1140 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1141 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1143 read_req.att_handle = (char *)object_path;
1144 read_req.address = addr;
1145 read_req.req_id = req_id;
1146 read_req.offset = offset;
1147 read_req.service_handle = svc_info->serv_path;
1149 /* Store requets information */
1150 req_info = g_new0(struct gatt_req_info, 1);
1151 req_info->attr_path = g_strdup(object_path);
1152 req_info->svc_path = g_strdup(read_req.service_handle);
1153 req_info->request_id = req_id;
1154 req_info->offset = offset;
1155 req_info->context = invocation;
1156 gatt_requests = g_slist_append(gatt_requests, req_info);
1158 _bt_common_event_cb(
1159 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1160 BLUETOOTH_ERROR_NONE, &read_req,
1161 user_info->cb, user_info->user_data);
1164 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1165 GVariant *var = NULL;
1169 gboolean response_needed = FALSE;
1170 bt_gatt_value_change_t value_change = {0, };
1171 bt_user_info_t *user_info = NULL;
1173 struct gatt_service_info *svc_info = NULL;
1174 struct gatt_req_info *req_info = NULL;
1176 BT_DBG("WriteValue");
1177 BT_DBG("Application path = %s", object_path);
1178 BT_DBG("Sender = %s", sender);
1180 g_variant_get(parameters, "(&suqb@ay)",
1181 &addr, &req_id, &offset, &response_needed, &var);
1182 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1184 user_info = _bt_get_user_data(BT_COMMON);
1185 if (user_info == NULL) {
1186 BT_INFO("No callback is set for %s", object_path);
1187 g_variant_unref(var);
1188 if (response_needed)
1189 g_dbus_method_invocation_return_value(invocation, NULL);
1191 g_object_unref(invocation);
1195 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1196 if (svc_info == NULL) {
1197 BT_ERR("Coudn't find service for %s", object_path);
1198 g_variant_unref(var);
1199 if (response_needed)
1200 g_dbus_method_invocation_return_value(invocation, NULL);
1202 g_object_unref(invocation);
1206 value_change.att_handle = (char *)object_path;
1207 value_change.address = addr;
1208 value_change.service_handle = svc_info->serv_path;
1209 value_change.offset = offset;
1210 value_change.req_id = req_id;
1211 value_change.response_needed = response_needed;
1213 len = g_variant_get_size(var);
1217 value_change.att_value = (guint8 *)g_malloc(len);
1219 data = (char *)g_variant_get_data(var);
1220 memcpy(value_change.att_value, data, len);
1222 value_change.val_len = len;
1224 if (response_needed) {
1225 /* Store requets information */
1226 req_info = g_new0(struct gatt_req_info, 1);
1227 req_info->attr_path = g_strdup(object_path);
1228 req_info->svc_path = g_strdup(value_change.service_handle);
1229 req_info->request_id = req_id;
1230 req_info->offset = offset;
1231 req_info->context = invocation;
1232 gatt_requests = g_slist_append(gatt_requests, req_info);
1234 g_object_unref(invocation);
1237 _bt_common_event_cb(
1238 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1239 BLUETOOTH_ERROR_NONE, &value_change,
1240 user_info->cb, user_info->user_data);
1242 g_free(value_change.att_value);
1243 g_variant_unref(var);
1248 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1251 GError *error = NULL;
1252 GVariantBuilder *array_builder;
1254 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1255 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1256 g_variant_builder_add(array_builder, "s", interface);
1258 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1259 "org.freedesktop.Dbus.Objectmanager",
1260 "InterfacesRemoved",
1261 g_variant_new("(oas)",
1262 object_path, array_builder),
1266 if (error != NULL) {
1267 /* dbus gives error cause */
1268 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1269 error->code, error->message);
1270 g_clear_error(&error);
1273 g_variant_builder_unref(array_builder);
1278 static const GDBusInterfaceVTable desc_interface_vtable = {
1279 __bt_gatt_desc_method_call,
1285 static const GDBusInterfaceVTable char_interface_vtable = {
1286 __bt_gatt_char_method_call,
1292 static const GDBusInterfaceVTable serv_interface_vtable = {
1299 static const GDBusInterfaceVTable manager_interface_vtable = {
1300 __bt_gatt_manager_method_call,
1306 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1307 const gchar *introspection_data)
1310 GDBusNodeInfo *node_info = NULL;
1312 if (introspection_data == NULL)
1316 BT_DBG("Create new node info");
1317 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1320 BT_ERR("Unable to create node: %s", err->message);
1321 g_clear_error(&err);
1328 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1329 const char *service_path)
1333 for (l = gatt_services; l != NULL; l = l->next) {
1334 struct gatt_service_info *info = l->data;
1336 if (g_strcmp0(info->serv_path, service_path) == 0)
1339 BT_ERR("Gatt service not found");
1343 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1344 const char *service_path, const char *char_path)
1348 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1349 struct gatt_service_info *serv_info = l1->data;
1351 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1353 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1354 struct gatt_char_info *char_info = l2->data;
1356 if (g_strcmp0(char_info->char_path, char_path)
1360 BT_ERR("Gatt characteristic not found");
1364 BT_ERR("Gatt service not found");
1368 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1369 const char *serv_path, const char *char_path,
1370 const char *desc_path)
1372 GSList *l1, *l2, *l3;
1374 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1375 struct gatt_service_info *serv_info = l1->data;
1377 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1378 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1379 struct gatt_char_info *char_info = l2->data;
1381 if (g_strcmp0(char_info->char_path, char_path)
1383 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1384 struct gatt_desc_info *desc_info = l3->data;
1385 if (g_strcmp0(desc_info->desc_path,
1394 BT_ERR("Gatt descriptor not found");
1398 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1402 for (l = gatt_requests; l != NULL; l = l->next) {
1403 struct gatt_req_info *req_info = l->data;
1405 if (req_info && req_info->request_id == request_id)
1408 BT_ERR("Gatt Request not found");
1412 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1413 const gchar *path, const gchar *interface)
1419 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1424 BT_ERR("Unable to connect to gdbus: %s", err->message);
1425 g_clear_error(&err);
1430 proxy = g_dbus_proxy_new_sync(g_conn,
1431 G_DBUS_PROXY_FLAGS_NONE, NULL,
1433 interface, NULL, &err);
1437 BT_ERR("Unable to create proxy: %s", err->message);
1438 g_clear_error(&err);
1442 manager_gproxy = proxy;
1447 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1448 const gchar *path, const gchar *interface)
1450 return (manager_gproxy) ? manager_gproxy :
1451 __bt_gatt_gdbus_init_manager_proxy(service,
1456 static void __bt_gatt_set_service_state(const char *service_path,
1459 struct gatt_service_info *svc_info = NULL;
1460 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1462 if (svc_info != NULL) {
1463 BT_DBG("Updating the gatt service register state %d", state);
1464 svc_info->is_svc_registered = state;
1468 BT_DBG("gatt service not found");
1471 static gboolean __bt_gatt_get_service_state(const char *service_path)
1473 struct gatt_service_info *svc_info = NULL;
1475 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1477 if (svc_info != NULL) {
1478 BT_DBG("Return the state of the gatt service %d",
1479 svc_info->is_svc_registered);
1480 return svc_info->is_svc_registered;
1483 BT_DBG("gatt service info is NULL");
1487 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1489 GError *error = NULL;
1491 GVariantIter *iter = NULL;
1492 const gchar *key = NULL;
1493 GVariant *value = NULL;
1494 const gchar *service = NULL;
1495 const gchar *characteristic = NULL;
1496 const gchar *descriptor = NULL;
1500 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1502 if (result == NULL) {
1503 /* dBUS-RPC is failed */
1504 BT_ERR("Dbus-RPC is failed\n");
1506 if (error != NULL) {
1507 /* dBUS gives error cause */
1508 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1509 error->code, error->message);
1510 g_clear_error(&error);
1513 char *char_cmp = NULL;
1514 g_variant_get(result, "(a{sv})", &iter);
1515 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1517 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1518 if (g_strcmp0(key, "Service") == 0) {
1519 service = g_variant_get_string(value, NULL);
1520 BT_DBG("Service %s", service);
1521 } else if (g_strcmp0(key, char_cmp) == 0) {
1522 characteristic = g_variant_get_string(value, NULL);
1524 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1525 BT_DBG("%s", characteristic);
1526 } else if (g_strcmp0(key, "Descriptor") == 0) {
1527 descriptor = g_variant_get_string(value, NULL);
1528 BT_DBG("Descriptor %s", descriptor);
1531 g_variant_iter_free(iter);
1533 /* TODO: Store the service informationa and
1534 * Send respponse to CAPI layer. */
1536 g_variant_unref(result);
1541 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1543 BT_INFO("RegisterApplication is completed");
1545 GError *error = NULL;
1548 register_pending_cnt = 0;
1550 if (register_cancel) {
1551 g_object_unref(register_cancel);
1552 register_cancel = NULL;
1555 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1557 if (result == NULL) {
1558 /* dBUS-RPC is failed */
1559 BT_ERR("Dbus-RPC is failed\n");
1561 if (error != NULL) {
1562 /* dBUS gives error cause */
1563 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1564 error->code, error->message);
1565 g_clear_error(&error);
1568 g_variant_unref(result);
1572 static int __bt_gatt_unregister_service(const char *service_path)
1574 if (!__bt_gatt_get_service_state(service_path)) {
1575 BT_DBG("service not registered \n");
1576 return BLUETOOTH_ERROR_NOT_FOUND;
1579 return BLUETOOTH_ERROR_NONE;
1582 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1584 GDBusProxy *proxy = NULL;
1586 if (is_server_started) {
1590 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1591 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1593 if (proxy == NULL || app_path == NULL)
1594 return BLUETOOTH_ERROR_INTERNAL;
1596 BT_INFO("UnregisterApplication");
1598 is_server_started = false;
1600 /* Async Call to Unregister Service */
1601 ret = g_dbus_proxy_call_sync(proxy,
1602 "UnregisterApplication",
1603 g_variant_new("(o)",
1605 G_DBUS_CALL_FLAGS_NONE, -1,
1609 /* dBUS-RPC is failed */
1610 BT_ERR("dBUS-RPC is failed");
1612 /* dBUS gives error cause */
1613 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1614 err->code, err->message);
1616 g_clear_error(&err);
1618 return BLUETOOTH_ERROR_INTERNAL;
1620 g_variant_unref(ret);
1622 BT_INFO("UnregisterApplication is completed");
1624 return BLUETOOTH_ERROR_NONE;
1627 BT_INFO("GATT server not started");
1628 return BLUETOOTH_ERROR_NONE;
1631 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1633 GDBusConnection *local_system_gconn = NULL;
1637 if (g_conn == NULL) {
1638 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1639 if (address == NULL) {
1641 BT_ERR("Failed to get bus address: %s", err->message);
1642 g_clear_error(&err);
1647 g_conn = g_dbus_connection_new_for_address_sync(address,
1648 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1649 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1650 NULL, /* GDBusAuthObserver */
1656 BT_ERR("Unable to connect to dbus: %s", err->message);
1657 g_clear_error(&err);
1661 } else if (g_dbus_connection_is_closed(g_conn)) {
1662 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1663 if (address == NULL) {
1665 BT_ERR("Failed to get bus address: %s", err->message);
1666 g_clear_error(&err);
1671 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1672 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1673 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1674 NULL, /* GDBusAuthObserver */
1678 if (!local_system_gconn) {
1679 BT_ERR("Unable to connect to dbus: %s", err->message);
1680 g_clear_error(&err);
1683 g_conn = local_system_gconn;
1689 BT_EXPORT_API int bluetooth_gatt_init(void)
1691 GDBusConnection *conn;
1692 GError *error = NULL;
1693 GDBusNodeInfo *node_info = NULL;
1695 if (app_path != NULL) {
1696 BT_ERR("app path already exists! initialized");
1697 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1700 if (owner_id == 0) {
1701 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1702 BT_GATT_SERVICE_NAME,
1703 G_BUS_NAME_OWNER_FLAGS_NONE,
1704 NULL, NULL, NULL, NULL, NULL);
1707 BT_DBG("owner_id is [%d]", owner_id);
1708 app_path = g_strdup_printf("/com/%d", getpid());
1712 conn = __bt_gatt_get_gdbus_connection();
1714 BT_ERR("Unable to get connection");
1718 /* Register ObjectManager interface */
1719 node_info = __bt_gatt_create_method_node_info(
1720 manager_introspection_xml);
1721 if (node_info == NULL) {
1722 BT_ERR("failed to get node info");
1726 if (manager_id == 0) {
1727 BT_INFO("manager_id does not exists");
1729 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1730 node_info->interfaces[0],
1731 &manager_interface_vtable,
1732 NULL, NULL, &error);
1734 g_dbus_node_info_unref(node_info);
1735 if (manager_id == 0) {
1736 BT_ERR("failed to register: %s", error->message);
1737 g_error_free(error);
1741 return BLUETOOTH_ERROR_NONE;
1745 g_bus_unown_name(owner_id);
1752 __bt_gatt_close_gdbus_connection();
1754 return BLUETOOTH_ERROR_INTERNAL;
1757 BT_EXPORT_API int bluetooth_gatt_deinit()
1759 int ret = BLUETOOTH_ERROR_NONE;
1761 if (register_cancel) {
1762 g_cancellable_cancel(register_cancel);
1763 g_object_unref(register_cancel);
1764 register_cancel = NULL;
1767 /* Unown gdbus bus */
1769 /* remove/unregister all services */
1770 BT_DBG("removing all registered gatt service\n");
1771 bluetooth_gatt_delete_services();
1773 /* unregister the exported interface for object manager */
1774 g_dbus_connection_unregister_object(g_conn,
1779 ret = bluetooth_gatt_unregister_application();
1780 if (ret != BLUETOOTH_ERROR_NONE)
1781 BT_ERR("Fail to unregister application\n");
1783 g_bus_unown_name(owner_id);
1789 BT_DBG("Gatt service deinitialized \n");
1791 g_slist_free(gatt_services);
1792 gatt_services = NULL;
1794 g_object_unref(manager_gproxy);
1795 manager_gproxy = NULL;
1797 __bt_gatt_close_gdbus_connection();
1802 __bt_gatt_close_gdbus_connection();
1804 return BLUETOOTH_ERROR_NOT_FOUND;
1807 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1810 GError *error = NULL;
1812 GDBusNodeInfo *node_info;
1814 GVariantBuilder *builder = NULL;
1815 GVariantBuilder *builder1 = NULL;
1816 GVariantBuilder *inner_builder = NULL;
1817 gboolean svc_primary = TRUE;
1818 struct gatt_service_info *serv_info = NULL;
1820 node_info = __bt_gatt_create_method_node_info(
1821 service_introspection_xml);
1822 if (node_info == NULL)
1823 return BLUETOOTH_ERROR_INTERNAL;
1825 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1826 BT_DBG("gatt service path is [%s]", path);
1828 object_id = g_dbus_connection_register_object(g_conn, path,
1829 node_info->interfaces[0],
1830 &serv_interface_vtable,
1831 NULL, NULL, &error);
1832 g_dbus_node_info_unref(node_info);
1834 if (object_id == 0) {
1835 BT_ERR("failed to register: %s", error->message);
1836 g_error_free(error);
1839 return BLUETOOTH_ERROR_INTERNAL;
1842 /* Add object_id/gatt service information; it's required at the time of
1843 * service unregister and Getmanagedobjects
1845 serv_info = g_new0(struct gatt_service_info, 1);
1847 serv_info->serv_path = g_strdup(path);
1848 serv_info->serv_id = object_id;
1849 serv_info->service_uuid = g_strdup(svc_uuid);
1850 serv_info->is_svc_registered = FALSE;
1851 serv_info->is_svc_primary = svc_primary;
1853 gatt_services = g_slist_append(gatt_services, serv_info);
1855 /* emit interfacesadded signal here for service path */
1856 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1857 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1859 g_variant_builder_add(inner_builder, "{sv}",
1860 "UUID", g_variant_new_string(svc_uuid));
1862 g_variant_builder_add(inner_builder, "{sv}",
1863 "Primary", g_variant_new_boolean(svc_primary));
1865 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1867 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1868 g_variant_new("ao", builder1));
1870 g_variant_builder_add(builder, "{sa{sv}}",
1871 GATT_SERV_INTERFACE, inner_builder);
1873 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1874 "org.freedesktop.Dbus.ObjectManager",
1876 g_variant_new("(oa{sa{sv}})",
1882 *svc_path = g_strdup(path);
1885 g_variant_builder_unref(inner_builder);
1886 g_variant_builder_unref(builder);
1887 g_variant_builder_unref(builder1);
1889 return BLUETOOTH_ERROR_NONE;
1892 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1893 const char *svc_path, const char *char_uuid,
1894 bt_gatt_permission_t permissions,
1895 bt_gatt_characteristic_property_t properties,
1899 GError *error = NULL;
1901 GDBusNodeInfo *node_info;
1903 GVariantBuilder *builder = NULL;
1904 GVariantBuilder *inner_builder = NULL;
1905 struct gatt_service_info *serv_info = NULL;
1906 struct gatt_char_info *char_info = NULL;
1907 GVariantBuilder *builder2 = NULL;
1908 GVariantBuilder *builder3 = NULL;
1909 GVariant *flags_val = NULL;
1911 char *char_flags[NUMBER_OF_FLAGS];
1916 new_service = FALSE;
1919 BT_DBG("gatt svc_path path is [%s]", svc_path);
1920 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1921 if (serv_info == NULL)
1922 return BLUETOOTH_ERROR_INVALID_PARAM;
1924 node_info = __bt_gatt_create_method_node_info(
1925 characteristics_introspection_xml);
1926 if (node_info == NULL)
1927 return BLUETOOTH_ERROR_INTERNAL;
1929 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1930 BT_DBG("gatt characteristic path is [%s]", path);
1932 object_id = g_dbus_connection_register_object(g_conn, path,
1933 node_info->interfaces[0],
1934 &char_interface_vtable,
1935 NULL, NULL, &error);
1936 g_dbus_node_info_unref(node_info);
1938 if (object_id == 0) {
1939 BT_ERR("failed to register: %s", error->message);
1940 g_error_free(error);
1943 return BLUETOOTH_ERROR_INTERNAL;
1946 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1947 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1948 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1949 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1950 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1951 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1952 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1953 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1955 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1957 char_info = g_new0(struct gatt_char_info, 1);
1959 char_info->char_path = g_strdup(path);
1960 char_info->char_id = object_id;
1961 char_info->char_uuid = g_strdup(char_uuid);
1963 for (i = 0; i < flag_count; i++)
1964 char_info->char_flags[i] = char_flags[i];
1967 char_info->flags_length = flag_count;
1969 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1971 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1972 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1974 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1975 g_variant_new("s", char_uuid));
1976 g_variant_builder_add(inner_builder, "{sv}", "Service",
1977 g_variant_new("o", svc_path));
1979 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1981 for (i = 0; i < flag_count; i++)
1982 g_variant_builder_add(builder2, "s", char_flags[i]);
1984 flags_val = g_variant_new("as", builder2);
1985 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1988 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1990 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1991 g_variant_new("ao", builder3));
1993 g_variant_builder_add(builder, "{sa{sv}}",
1994 GATT_CHAR_INTERFACE,
1997 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1998 "org.freedesktop.Dbus.ObjectManager",
2000 g_variant_new("(oa{sa{sv}})",
2004 *char_path = g_strdup(path);
2010 g_variant_builder_unref(inner_builder);
2011 g_variant_builder_unref(builder);
2012 g_variant_builder_unref(builder2);
2013 g_variant_builder_unref(builder3);
2015 return BLUETOOTH_ERROR_NONE;
2018 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
2019 const char *characteristic, const char *char_value,
2022 gchar **line_argv = NULL;
2023 char *serv_path = NULL;
2024 struct gatt_char_info *char_info = NULL;
2025 GVariantBuilder *builder1 = NULL;
2026 GVariantBuilder *builder = NULL;
2027 GVariantBuilder *inner_builder = NULL;
2028 GVariant *char_val = NULL;
2029 GError *error = NULL;
2031 int res = BLUETOOTH_ERROR_NONE;
2033 line_argv = g_strsplit_set(characteristic, "/", 0);
2034 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2036 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
2038 if (char_info == NULL) {
2039 /* Fix : RESOURCE_LEAK */
2040 res = BLUETOOTH_ERROR_INVALID_PARAM;
2044 char_info->value_length = value_length;
2046 char_info->char_value = (char *)malloc(value_length);
2047 /* Fix : NULL_RETURNS */
2048 if (char_info->char_value == NULL) {
2049 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2053 for (i = 0; i < value_length; i++)
2054 char_info->char_value[i] = char_value[i];
2056 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2057 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2059 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2061 for (i = 0; i < value_length; i++)
2062 g_variant_builder_add(builder1, "y", char_value[i]);
2064 char_val = g_variant_new("ay", builder1);
2065 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
2067 g_variant_builder_add(builder, "{sa{sv}}",
2068 GATT_CHAR_INTERFACE,
2071 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2072 "org.freedesktop.Dbus.ObjectManager",
2074 g_variant_new("(oa{sa{sv}})",
2075 char_info->char_path, builder),
2078 g_variant_builder_unref(inner_builder);
2079 g_variant_builder_unref(builder);
2080 g_variant_builder_unref(builder1);
2082 g_strfreev(line_argv);
2088 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2089 const char *char_path, const char *desc_uuid,
2090 bt_gatt_permission_t permissions,
2093 static int desc_id = 1;
2094 GError *error = NULL;
2096 GDBusNodeInfo *node_info;
2098 GVariantBuilder *builder = NULL;
2099 GVariantBuilder *inner_builder = NULL;
2100 struct gatt_char_info *char_info = NULL;
2101 struct gatt_desc_info *desc_info = NULL;
2102 gchar **line_argv = NULL;
2104 GVariantBuilder *builder2 = NULL;
2105 GVariant *flags_val = NULL;
2107 char *desc_flags[NUMBER_OF_FLAGS];
2115 line_argv = g_strsplit_set(char_path, "/", 0);
2116 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2118 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2119 if (char_info == NULL) {
2120 g_strfreev(line_argv);
2122 return BLUETOOTH_ERROR_INVALID_PARAM;
2125 node_info = __bt_gatt_create_method_node_info(
2126 descriptor_introspection_xml);
2127 if (node_info == NULL) {
2128 g_strfreev(line_argv);
2130 return BLUETOOTH_ERROR_INTERNAL;
2133 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2134 BT_DBG("gatt descriptor path is [%s]", path);
2136 object_id = g_dbus_connection_register_object(g_conn, path,
2137 node_info->interfaces[0],
2138 &desc_interface_vtable,
2139 NULL, NULL, &error);
2140 g_dbus_node_info_unref(node_info);
2142 if (object_id == 0) {
2143 BT_ERR("failed to register: %s", error->message);
2144 g_error_free(error);
2146 g_strfreev(line_argv);
2149 return BLUETOOTH_ERROR_INTERNAL;
2152 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2154 desc_info = g_new0(struct gatt_desc_info, 1);
2156 desc_info->desc_path = g_strdup(path);
2157 desc_info->desc_id = object_id;
2158 desc_info->desc_uuid = g_strdup(desc_uuid);
2160 for (i = 0; i < flag_count; i++)
2161 desc_info->desc_flags[i] = desc_flags[i];
2163 desc_info->flags_length = flag_count;
2165 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2167 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2168 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2170 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2171 g_variant_new("s", desc_uuid));
2172 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2173 g_variant_new("o", char_path));
2175 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2177 for (i = 0; i < flag_count; i++)
2178 g_variant_builder_add(builder2, "s", desc_flags[i]);
2180 flags_val = g_variant_new("as", builder2);
2181 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2184 g_variant_builder_add(builder, "{sa{sv}}",
2185 GATT_DESC_INTERFACE,
2188 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2189 "org.freedesktop.Dbus.ObjectManager",
2191 g_variant_new("(oa{sa{sv}})",
2195 *desc_path = g_strdup(path);
2199 g_strfreev(line_argv);
2200 g_variant_builder_unref(inner_builder);
2201 g_variant_builder_unref(builder);
2202 g_variant_builder_unref(builder2);
2204 return BLUETOOTH_ERROR_NONE;
2207 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2208 const char *desc_path, const char *desc_value,
2211 GError *error = NULL;
2212 GVariantBuilder *builder = NULL;
2213 GVariantBuilder *inner_builder = NULL;
2214 GVariantBuilder *builder1 = NULL;
2215 struct gatt_desc_info *desc_info = NULL;
2216 gchar **line_argv = NULL;
2218 GVariant *desc_val = NULL;
2219 char *serv_path = NULL;
2222 line_argv = g_strsplit_set(desc_path, "/", 0);
2223 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2224 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2226 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2228 /* Free the allocated memory */
2229 g_strfreev(line_argv);
2233 /* Fix : NULL_RETURNS */
2234 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2236 desc_info->desc_value = (char *)malloc(value_length);
2238 /* Fix : NULL_RETURNS */
2239 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2241 for (i = 0; i < value_length; i++)
2242 desc_info->desc_value[i] = desc_value[i];
2244 desc_info->value_length = value_length;
2246 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2247 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2249 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2251 for (i = 0; i < value_length; i++)
2252 g_variant_builder_add(builder1, "y", desc_value[i]);
2254 desc_val = g_variant_new("ay", builder1);
2255 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2257 g_variant_builder_add(builder, "{sa{sv}}",
2258 GATT_DESC_INTERFACE,
2261 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2262 "org.freedesktop.Dbus.ObjectManager",
2264 g_variant_new("(oa{sa{sv}})",
2265 desc_info->desc_path, builder),
2268 g_variant_builder_unref(inner_builder);
2269 g_variant_builder_unref(builder);
2270 g_variant_builder_unref(builder1);
2272 return BLUETOOTH_ERROR_NONE;
2275 int bluetooth_gatt_get_service(const char *svc_uuid)
2277 GDBusProxy *proxy = NULL;
2280 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2281 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2283 return BLUETOOTH_ERROR_INTERNAL;
2285 uuid = g_strdup(svc_uuid);
2287 g_dbus_proxy_call(proxy,
2289 g_variant_new("(s)",
2291 G_DBUS_CALL_FLAGS_NONE, -1,
2293 (GAsyncReadyCallback) get_service_cb,
2298 return BLUETOOTH_ERROR_NONE;
2301 BT_EXPORT_API int bluetooth_gatt_register_service(
2302 const char *svc_path)
2304 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2305 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2306 BT_ERR("Don't have aprivilege to use this API");
2307 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2310 register_pending_cnt++;
2312 if (__bt_gatt_get_service_state(svc_path)) {
2313 BT_DBG("service already registered \n");
2314 return BLUETOOTH_ERROR_NONE;
2317 __bt_gatt_set_service_state(svc_path, TRUE);
2319 return BLUETOOTH_ERROR_NONE;
2322 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2324 GDBusProxy *proxy = NULL;
2326 if (!is_server_started) {
2328 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2329 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2330 BT_ERR("Don't have aprivilege to use this API");
2331 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2334 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2335 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2336 if (proxy == NULL || app_path == NULL)
2337 return BLUETOOTH_ERROR_INTERNAL;
2339 BT_INFO("RegisterApplication");
2341 if (register_cancel) {
2342 g_cancellable_cancel(register_cancel);
2343 g_object_unref(register_cancel);
2346 register_cancel = g_cancellable_new();
2348 g_dbus_proxy_call(proxy,
2349 "RegisterApplication",
2350 g_variant_new("(oa{sv})",
2352 G_DBUS_CALL_FLAGS_NONE, -1,
2354 (GAsyncReadyCallback) register_application_cb,
2357 is_server_started = true;
2359 return BLUETOOTH_ERROR_NONE;
2362 BT_INFO("Already RegisterApplication");
2364 return BLUETOOTH_ERROR_NONE;
2367 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2370 int error = BLUETOOTH_ERROR_NONE;
2374 for (l = gatt_services; l != NULL; l = l->next) {
2375 struct gatt_service_info *info = l->data;
2376 BT_DBG("svc_path is %s", info->serv_path);
2377 if (bluetooth_gatt_unregister_service(info->serv_path)
2378 != BLUETOOTH_ERROR_NONE) {
2379 error = BLUETOOTH_ERROR_INTERNAL;
2380 BT_ERR("Error in removing service %s \n",
2384 BT_DBG(" All services removed successfully.\n ");
2386 BT_DBG(" There are no registered services.\n ");
2389 g_slist_free(gatt_services);
2390 gatt_services = NULL;
2393 if (error != BLUETOOTH_ERROR_NONE)
2396 return BLUETOOTH_ERROR_NONE;
2399 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2400 const char *char_path, const char* char_value,
2403 GVariantBuilder *outer_builder;
2404 GVariantBuilder *inner_builder;
2405 GVariantBuilder *invalidated_builder;
2406 GVariant *update_value = NULL;
2407 GError *error = NULL;
2408 gboolean ret = FALSE;
2409 int err = BLUETOOTH_ERROR_NONE;
2411 gchar **line_argv = NULL;
2412 gchar *serv_path = NULL;
2413 const char *value = NULL;
2415 line_argv = g_strsplit_set(char_path, "/", 0);
2416 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2418 if (!__bt_gatt_get_service_state(serv_path)) {
2419 BT_DBG("service not registered for this characteristic \n");
2421 g_strfreev(line_argv);
2422 return BLUETOOTH_ERROR_INTERNAL;
2425 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2426 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2428 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2429 for (i = 0; i < value_length; i++)
2430 g_variant_builder_add(inner_builder, "y", char_value[i]);
2432 update_value = g_variant_new("ay", inner_builder);
2434 outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2435 g_variant_builder_add(outer_builder, "{sv}", "Value",
2438 BT_DBG("Updating characteristic value \n");
2439 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2441 "org.freedesktop.DBus.Properties",
2442 "PropertiesChanged",
2443 g_variant_new("(sa{sv}as)",
2444 "org.bluez.GattCharacteristic1",
2445 outer_builder, invalidated_builder),
2449 if (error != NULL) {
2450 BT_ERR("D-Bus API failure: errCode[%x], \
2452 error->code, error->message);
2453 g_clear_error(&error);
2455 err = BLUETOOTH_ERROR_INTERNAL;
2457 struct gatt_char_info *char_info = NULL;
2459 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2460 if (char_info == NULL) {
2462 g_strfreev(line_argv);
2463 g_variant_builder_unref(inner_builder);
2464 g_variant_builder_unref(outer_builder);
2465 g_variant_builder_unref(invalidated_builder);
2467 return BLUETOOTH_ERROR_INVALID_DATA;
2470 char_info->value_length = value_length;
2472 value = (char *)realloc(char_info->char_value, value_length);
2473 if (value == NULL) {
2475 g_strfreev(line_argv);
2476 g_variant_builder_unref(inner_builder);
2477 g_variant_builder_unref(outer_builder);
2478 g_variant_builder_unref(invalidated_builder);
2480 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2483 char_info->char_value = (char*)value;
2484 if (char_info->char_value) {
2485 for (i = 0; i < value_length; i++)
2486 char_info->char_value[i] = char_value[i];
2491 g_strfreev(line_argv);
2492 g_variant_builder_unref(inner_builder);
2493 g_variant_builder_unref(outer_builder);
2494 g_variant_builder_unref(invalidated_builder);
2499 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2506 g_free(desc_info->desc_path);
2507 g_free(desc_info->desc_uuid);
2508 g_free(desc_info->desc_value);
2510 for (i = 0; i < desc_info->flags_length; i++)
2511 g_free(desc_info->desc_flags[i]);
2516 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2523 g_free(char_info->char_path);
2524 g_free(char_info->char_uuid);
2525 g_free(char_info->char_value);
2527 for (i = 0; i < char_info->flags_length; i++)
2528 g_free(char_info->char_flags[i]);
2533 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2538 g_free(svc_info->serv_path);
2539 g_free(svc_info->service_uuid);
2543 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2546 struct gatt_service_info *svc_info;
2548 int err = BLUETOOTH_ERROR_NONE;
2550 BT_DBG("svc_path %s", svc_path);
2551 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2554 BT_ERR("Unable to find service info");
2555 return BLUETOOTH_ERROR_NOT_FOUND;
2558 err = __bt_gatt_unregister_service(svc_path);
2559 if (err != BLUETOOTH_ERROR_NONE) {
2560 BT_ERR("Could not unregister application");
2564 for (l = svc_info->char_data; l != NULL; l = l->next) {
2565 struct gatt_char_info *char_info = l->data;
2567 if (char_info == NULL)
2570 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2571 struct gatt_desc_info *desc_info = l1->data;
2573 if (desc_info == NULL)
2576 ret = g_dbus_connection_unregister_object(g_conn,
2577 desc_info->desc_id);
2579 __bt_gatt_emit_interface_removed(
2580 desc_info->desc_path,
2581 GATT_DESC_INTERFACE);
2583 err = BLUETOOTH_ERROR_INTERNAL;
2586 /* list remove & free */
2587 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2588 __bt_gatt_free_descriptor_info(desc_info);
2591 g_slist_free(char_info->desc_data);
2592 char_info->desc_data = NULL;
2594 ret = g_dbus_connection_unregister_object(g_conn,
2595 char_info->char_id);
2597 __bt_gatt_emit_interface_removed(char_info->char_path,
2598 GATT_CHAR_INTERFACE);
2600 err = BLUETOOTH_ERROR_INTERNAL;
2603 /* list remove & free */
2604 svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
2605 __bt_gatt_free_characteristic_info(char_info);
2608 g_slist_free(svc_info->char_data);
2609 svc_info->char_data = NULL;
2611 ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2613 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2614 GATT_SERV_INTERFACE);
2616 err = BLUETOOTH_ERROR_INTERNAL;
2619 ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2621 BT_DBG("Unregistered the service on properties interface");
2623 /* list remove & free */
2624 gatt_services = g_slist_remove(gatt_services, svc_info);
2625 __bt_gatt_free_service_info(svc_info);
2627 new_service = FALSE;
2629 if (gatt_services == NULL)
2631 else if (gatt_services->next == NULL)
2637 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2638 int resp_state, int offset, char *value, int value_length)
2640 struct gatt_req_info *req_info = NULL;
2642 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2643 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2644 BT_ERR("Don't have aprivilege to use this API");
2645 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2648 req_info = __bt_gatt_find_request_info(request_id);
2649 if (req_info == NULL) {
2650 BT_ERR("Coundn't find request id [%d]", request_id);
2651 return BLUETOOTH_ERROR_INTERNAL;
2654 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2655 BT_ERR("resp_state is 0x%X", resp_state);
2656 char err_msg[20] = { 0, };
2657 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2658 g_dbus_method_invocation_return_dbus_error(req_info->context,
2659 "org.bluez.Error.Failed", err_msg);
2661 gatt_requests = g_slist_remove(gatt_requests, req_info);
2663 req_info->context = NULL;
2664 if (req_info->attr_path)
2665 g_free(req_info->attr_path);
2666 if (req_info->svc_path)
2667 g_free(req_info->svc_path);
2670 return BLUETOOTH_ERROR_NONE;
2673 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2675 GVariantBuilder *inner_builder = NULL;
2676 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2677 if (value_length > 0 && value != NULL) {
2678 for (i = 0; i < value_length; i++)
2679 g_variant_builder_add(inner_builder, "y", value[i]);
2681 g_dbus_method_invocation_return_value(req_info->context,
2682 g_variant_new("(ay)", inner_builder));
2683 g_variant_builder_unref(inner_builder);
2685 g_dbus_method_invocation_return_value(req_info->context, NULL);
2687 gatt_requests = g_slist_remove(gatt_requests, req_info);
2689 req_info->context = NULL;
2690 if (req_info->attr_path)
2691 g_free(req_info->attr_path);
2692 if (req_info->svc_path)
2693 g_free(req_info->svc_path);
2696 return BLUETOOTH_ERROR_NONE;
2699 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2700 bluetooth_device_address_t *unicast_address)
2702 GVariantBuilder *outer_builder;
2703 GVariantBuilder *invalidated_builder;
2704 GError *error = NULL;
2705 gboolean notify = TRUE;
2706 gboolean ret = TRUE;
2707 int err = BLUETOOTH_ERROR_NONE;
2708 gchar **line_argv = NULL;
2709 gchar *serv_path = NULL;
2710 char addr[20] = { 0 };
2712 line_argv = g_strsplit_set(char_path, "/", 0);
2713 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2715 if (!__bt_gatt_get_service_state(serv_path)) {
2716 BT_DBG("service not registered for this characteristic \n");
2718 g_strfreev(line_argv);
2719 return BLUETOOTH_ERROR_INTERNAL;
2724 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2725 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2727 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2728 g_variant_new("b", notify));
2730 if (unicast_address) {
2731 _bt_convert_addr_type_to_string(addr,
2732 (unsigned char *)unicast_address->addr);
2734 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2735 g_variant_new("s", addr));
2737 BT_DBG("Set characteristic Notification \n");
2738 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2740 "org.freedesktop.DBus.Properties",
2741 "PropertiesChanged",
2742 g_variant_new("(sa{sv}as)",
2743 "org.bluez.GattCharacteristic1",
2744 outer_builder, invalidated_builder),
2748 if (error != NULL) {
2749 BT_ERR("D-Bus API failure: errCode[%x], \
2751 error->code, error->message);
2752 g_clear_error(&error);
2754 err = BLUETOOTH_ERROR_INTERNAL;
2757 g_strfreev(line_argv);
2758 g_variant_builder_unref(outer_builder);
2759 g_variant_builder_unref(invalidated_builder);
2766 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2770 if (!is_server_started) {
2772 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2773 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2774 BT_ERR("Don't have aprivilege to use this API");
2775 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2778 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2779 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2781 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2782 in_param1, in_param2, in_param3, in_param4, &out_param);
2783 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2785 if (ret != BLUETOOTH_ERROR_NONE) {
2786 BT_ERR("Register application failed");
2789 is_server_started = true;
2791 return BLUETOOTH_ERROR_NONE;
2794 BT_INFO("Already RegisterApplication");
2795 return BLUETOOTH_ERROR_NONE;
2799 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2802 int ret = BLUETOOTH_ERROR_NONE;
2805 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2807 /* Register event handler for GATT */
2808 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2810 if (ret != BLUETOOTH_ERROR_NONE &&
2811 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2812 BT_ERR("Fail to init the event handler");
2816 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2817 in_param1, in_param2, in_param3, in_param4, &out_param);
2819 /* App ID -1 is invalid */
2820 if (ret != BLUETOOTH_ERROR_NONE) {
2821 BT_INFO("GATT Server Registration failed result [%d]", ret);
2824 *instance_id = g_array_index(out_param, int, 0);
2825 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2828 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2830 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2834 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2837 BT_INFO("GATT Server Deinitialize");
2838 /* Unregister the event */
2839 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2841 if (ret != BLUETOOTH_ERROR_NONE) {
2842 BT_ERR("Fail to deinit the event handler");
2846 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2851 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2852 int instance_id, int *service_handle)
2854 BT_CHECK_ENABLED(return);
2855 BT_CHECK_PARAMETER(svc_uuid, return);
2858 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2860 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2863 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2865 g_array_append_vals(in_param1, &type, sizeof(int));
2866 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2867 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2868 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2870 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2871 in_param1, in_param2, in_param3, in_param4, &out_param);
2873 /* ATT handle 0 is reserved, hence it can not be used by app.
2874 It will be used to indicate error in regsitering attribute */
2875 if (result != BLUETOOTH_ERROR_NONE)
2876 *service_handle = 0;
2878 *service_handle = g_array_index(out_param, int, 0);
2880 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2885 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2886 const bluetooth_gatt_server_attribute_params_t *param,
2889 BT_CHECK_ENABLED(return);
2890 BT_CHECK_PARAMETER(char_uuid, return);
2891 BT_CHECK_PARAMETER(param, return);
2894 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2896 char *char_flags[NUMBER_OF_FLAGS];
2898 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2899 flag_count = bluetooth_gatt_convert_prop2string(param->properties, char_flags);
2900 BT_INFO("Flag count [%d]", flag_count);
2903 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2905 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2906 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2908 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2909 in_param1, in_param2, in_param3, in_param4, &out_param);
2911 /* ATT handle 0 is reserved, hence it can not be used by app.
2912 It will be used to indicate error in regsitering attribute */
2913 if (result != BLUETOOTH_ERROR_NONE) {
2914 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2917 *char_handle = g_array_index(out_param, int, 0);
2918 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2924 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2925 int service_handle, int instance_id, int *descriptor_handle)
2927 BT_CHECK_ENABLED(return);
2928 BT_CHECK_PARAMETER(desc_uuid, return);
2931 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2933 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2936 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2938 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2939 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2940 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2941 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2943 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2944 in_param1, in_param2, in_param3, in_param4, &out_param);
2946 /* ATT handle 0 is reserved, hence it can not be used by app.
2947 It will be used to indicate error in regsitering attribute */
2948 if (result != BLUETOOTH_ERROR_NONE) {
2949 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2950 *descriptor_handle = 0;
2952 *descriptor_handle = g_array_index(out_param, int, 0);
2953 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2956 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2961 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2963 BT_CHECK_ENABLED(return);
2967 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2969 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2970 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2972 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2973 in_param1, in_param2, in_param3, in_param4, &out_param);
2975 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2980 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2981 const bluetooth_gatt_att_data_t *value)
2983 BT_CHECK_PARAMETER(param, return);
2984 BT_CHECK_PARAMETER(value, return);
2985 BT_CHECK_ENABLED(return);
2989 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2991 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
2992 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
2994 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
2995 in_param1, in_param2, in_param3, in_param4, &out_param);
2997 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3003 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
3004 const bluetooth_gatt_server_indication_params_t *param,
3005 const bluetooth_gatt_att_data_t *att_value)
3007 BT_CHECK_PARAMETER(param, return);
3008 BT_CHECK_PARAMETER(att_value, return);
3009 BT_CHECK_ENABLED(return);
3013 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3015 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
3016 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
3017 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
3019 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
3020 in_param1, in_param2, in_param3, in_param4, &out_param);
3022 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3027 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
3029 BT_CHECK_ENABLED(return);
3033 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3035 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3036 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3038 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
3039 in_param1, in_param2, in_param3, in_param4, &out_param);
3041 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3046 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
3048 BT_CHECK_ENABLED(return);
3052 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3054 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3055 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3057 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
3058 in_param1, in_param2, in_param3, in_param4, &out_param);
3060 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3065 /* Tizen Platform Specific */
3066 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
3067 const bluetooth_gatt_server_update_value_t *value)
3069 BT_CHECK_ENABLED(return);
3070 BT_CHECK_PARAMETER(value, return);
3074 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3076 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3077 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3079 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3080 in_param1, in_param2, in_param3, in_param4, &out_param);
3082 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3087 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3089 BT_CHECK_ENABLED(return);
3093 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3095 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3097 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3098 in_param1, in_param2, in_param3, in_param4, &out_param);
3100 if (result != BLUETOOTH_ERROR_NONE)
3101 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3103 BT_INFO("GATT Server Unregistration successful");
3105 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);