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>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <gio/gunixfdlist.h>
29 #include "bt-common.h"
30 /* TODO_40 : 4.0 merge - Need to check why includes bt-event-handler.h */
31 #include "bt-event-handler.h"
32 #include "bt-internal-types.h"
35 #include "bluetooth-gatt-server-api.h"
36 #include "bt-request-sender.h"
37 #define BT_GATT_ATT_UUID_LEN_MAX 50
38 #define BT_GATT_SERVER_DBUS_NAME_LEN_MAX 50
40 static GSList *gatt_characteristic_server_notify_list = NULL;;
42 /* Common defintions to follow , applicable for both
43 GATT_DIRECT and RELAY */
46 #define NUMBER_OF_FLAGS 10
49 int bluetooth_gatt_convert_prop2string(
50 bt_gatt_characteristic_property_t properties,
51 char *char_properties[])
55 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
56 char_properties[flag_count] = g_strdup("broadcast");
59 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
60 char_properties[flag_count] = g_strdup("read");
63 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
64 char_properties[flag_count] = g_strdup("write-without-response");
67 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
68 char_properties[flag_count] = g_strdup("write");
71 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
72 char_properties[flag_count] = g_strdup("notify");
75 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
76 char_properties[flag_count] = g_strdup("indicate");
79 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
80 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
83 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
84 char_properties[flag_count] = g_strdup("reliable-write");
87 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
88 char_properties[flag_count] = g_strdup("writable-auxiliaries");
91 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
92 char_properties[flag_count] = g_strdup("encrypt-read");
95 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
96 char_properties[flag_count] = g_strdup("encrypt-write");
99 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
100 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
103 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
104 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
108 if (flag_count == 0) {
109 char_properties[flag_count] = g_strdup("read");
116 int bluetooth_gatt_convert_perm2string(
117 bt_gatt_permission_t properties,
118 char *char_properties[])
122 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
123 char_properties[flag_count] = g_strdup("read");
126 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
127 char_properties[flag_count] = g_strdup("write");
130 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
131 char_properties[flag_count] = g_strdup("encrypt-read");
134 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
135 char_properties[flag_count] = g_strdup("encrypt-write");
138 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
139 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
142 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
143 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
147 if (flag_count == 0) {
148 char_properties[flag_count] = g_strdup("read");
156 #define NUMBER_OF_FLAGS 10
158 GDBusConnection *g_conn;
161 static gboolean new_service = FALSE;
162 static gboolean new_char = FALSE;
163 static int serv_id = 1;
164 static int register_pending_cnt = 0;
165 static bool is_server_started = false;
167 GCancellable *register_cancel;
169 /* Introspection data for the service we are exporting */
170 static const gchar service_introspection_xml[] =
172 " <interface name='org.freedesktop.DBus.Properties'>"
173 " <property type='s' name='UUID' access='read'>"
175 " <property type='b' name='primary' access='read'>"
177 " <property type='o' name='Device' access='read'>"
179 " <property type='ao' name='Characteristics' access='read'>"
181 " <property type='s' name='Includes' access='read'>"
186 /* Introspection data for the characteristics we are exporting */
187 static const gchar characteristics_introspection_xml[] =
189 " <interface name='org.bluez.GattCharacteristic1'>"
190 " <method name='ReadValue'>"
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='ay' name='Value' direction='out'/>"
196 " <method name='WriteValue'>"
197 " <arg type='s' name='address' direction='in'/>"
198 " <arg type='u' name='id' direction='in'/>"
199 " <arg type='q' name='offset' direction='in'/>"
200 " <arg type='b' name='response_needed' direction='in'/>"
201 " <arg type='ay' name='value' direction='in'/>"
203 " <method name='StartNotify'>"
205 " <method name='StopNotify'>"
207 " <method name='IndicateConfirm'>"
208 " <arg type='s' name='address' direction='in'/>"
209 " <arg type='b' name='complete' direction='in'/>"
212 " <interface name='org.freedesktop.DBus.Properties'>"
213 " <property type='s' name='UUID' access='read'>"
215 " <property type='o' name='Service' access='read'>"
217 " <property type='ay' name='Value' access='readwrite'>"
219 " <property type='b' name='Notifying' access='read'>"
221 " <property type='as' name='Flags' access='read'>"
223 " <property type='s' name='Unicast' access='read'>"
225 " <property type='ao' name='Descriptors' access='read'>"
230 /* Introspection data for the descriptor we are exporting */
231 static const gchar descriptor_introspection_xml[] =
233 " <interface name='org.bluez.GattDescriptor1'>"
234 " <method name='ReadValue'>"
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='ay' name='Value' direction='out'/>"
240 " <method name='WriteValue'>"
241 " <arg type='s' name='address' direction='in'/>"
242 " <arg type='u' name='id' direction='in'/>"
243 " <arg type='q' name='offset' direction='in'/>"
244 " <arg type='b' name='response_needed' direction='in'/>"
245 " <arg type='ay' name='value' direction='in'/>"
248 " <interface name='org.freedesktop.DBus.Properties'>"
249 " <property type='s' name='UUID' access='read'>"
251 " <property type='o' name='Characteristic' access='read'>"
253 " <property type='ay' name='Value' access='read'>"
255 " <property type='as' name='Flags' access='read'>"
260 static const gchar manager_introspection_xml[] =
262 " <interface name='org.freedesktop.DBus.ObjectManager'>"
263 " <method name='GetManagedObjects'>"
264 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
269 struct gatt_service_info {
276 gboolean is_svc_registered;
277 gboolean is_svc_primary;
280 struct gatt_char_info {
285 gchar *char_flags[NUMBER_OF_FLAGS];
291 struct gatt_desc_info {
296 gchar *desc_flags[NUMBER_OF_FLAGS];
301 struct gatt_req_info {
306 GDBusMethodInvocation *context;
309 static GSList *gatt_services = NULL;
310 static GSList *gatt_requests = NULL;
311 static gchar *app_path = NULL;
313 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
314 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
316 #define GATT_SERV_OBJECT_PATH "/service"
318 #define GATT_MNGR_INTERFACE "org.bluez.GattManager1"
319 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
320 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
321 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
323 #ifdef TIZEN_FEATURE_BT_HPS
324 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
325 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
326 #define PROPERTIES_CHANGED "PropertiesChanged"
327 #define BT_HPS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
330 #ifdef TIZEN_FEATURE_BT_OTP
331 #define BT_OTP_OBJECT_PATH "/org/projectx/otp"
332 #define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
333 #define PROPERTIES_CHANGED "PropertiesChanged"
334 #define BT_OTP_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
337 static GDBusProxy *manager_gproxy = NULL;
339 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
340 const char *service_path, const char *char_path);
341 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
342 const char *serv_path, const char *char_path,
343 const char *desc_path);
345 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
355 } bluetooth_gatt_acquire_notify_info_t;
358 static int bluetooth_get_characteristic_fd(int att_handle , char *path)
362 BT_INFO("request found path [%s] att_handle [ %d]", path, att_handle);
363 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
364 bluetooth_gatt_acquire_notify_info_t *info = l->data;
365 BT_INFO(" sid [ %d]" , info->att_hand);
366 if (info->att_hand == att_handle)
367 return info->write_fd;
372 static bluetooth_gatt_acquire_notify_info_t * bluetooth_get_characteristic_info_from_path(int att_handle)
376 BT_INFO("request found att_handle [ %d]", att_handle);
377 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
378 bluetooth_gatt_acquire_notify_info_t *info = l->data;
379 BT_INFO(" sid [ %d]" , info->att_hand);
380 if (info->att_hand == att_handle)
387 static void bluetooth_characteristic_info_free(bluetooth_gatt_acquire_notify_info_t *chr_info)
392 static gboolean bluetooth_gatt_write_channel_watch_cb(GIOChannel *gio,
393 GIOCondition cond, gpointer data)
395 bluetooth_gatt_acquire_notify_info_t *chr_info = (bluetooth_gatt_acquire_notify_info_t *)data;
400 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
401 BT_ERR("Error : GIOCondition %d, []", cond);;
402 g_io_channel_shutdown(gio, TRUE, NULL);
403 g_io_channel_unref(gio);
405 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
406 bluetooth_characteristic_info_free(chr_info);
414 static int bluetooth_gatt_write_characteristics_value_to_fd_(
415 int fd, const guint8 *value, int length,
420 int att_result = BLUETOOTH_ERROR_NONE;
422 BT_CHECK_PARAMETER(value, return);
424 written = write(fd, value, length);
425 if (written != length) {
426 att_result = BLUETOOTH_ERROR_INTERNAL;
427 BT_INFO("write data failed %d is ", written);
429 BT_INFO("write data %s is sucess ", value);
434 static void __bt_gatt_close_gdbus_connection(void)
440 ret_if(g_conn == NULL);
442 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
443 BT_ERR("Fail to flush the connection: %s", err->message);
448 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
450 BT_ERR("Fail to close the dbus connection: %s", err->message);
455 g_object_unref(g_conn);
462 #ifdef TIZEN_FEATURE_BT_HPS
463 static int __bt_send_event_to_hps(int event, GVariant *var)
465 GError *error = NULL;
466 GVariant *parameters;
467 GDBusMessage *msg = NULL;
471 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
473 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
474 GVariantBuilder *inner_builder;
475 GVariantBuilder *invalidated_builder;
477 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
478 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
480 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
482 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
484 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
485 g_variant_builder_unref(invalidated_builder);
486 g_variant_builder_unref(inner_builder);
487 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
488 GVariantBuilder *inner_builder;
489 GVariantBuilder *invalidated_builder;
491 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
492 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
494 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
496 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
498 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
499 g_variant_builder_unref(invalidated_builder);
500 g_variant_builder_unref(inner_builder);
502 g_varaiant_unref(var);
505 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
506 g_dbus_message_set_body(msg, parameters);
507 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
509 BT_ERR("D-Bus API failure: errCode[%x], \
511 error->code, error->message);
512 g_clear_error(&error);
514 return BLUETOOTH_ERROR_INTERNAL;
516 return BLUETOOTH_ERROR_NONE;
520 #ifdef TIZEN_FEATURE_BT_OTP
521 static int __bt_send_event_to_otp(int event, GVariant *var)
523 GError *error = NULL;
524 GVariant *parameters = NULL;
525 GDBusMessage *msg = NULL;
529 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
531 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
532 GVariantBuilder *inner_builder;
533 GVariantBuilder *invalidated_builder;
535 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
536 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
538 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
540 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
542 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
543 g_variant_builder_unref(invalidated_builder);
544 g_variant_builder_unref(inner_builder);
545 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
546 GVariantBuilder *inner_builder;
547 GVariantBuilder *invalidated_builder;
549 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
550 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
552 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
554 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
556 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
557 g_variant_builder_unref(invalidated_builder);
558 g_variant_builder_unref(inner_builder);
559 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
560 GVariantBuilder *inner_builder;
561 GVariantBuilder *invalidated_builder;
563 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
564 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
566 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
568 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
570 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
571 g_variant_builder_unref(invalidated_builder);
572 g_variant_builder_unref(inner_builder);
575 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
576 g_dbus_message_set_body(msg, parameters);
577 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
579 BT_ERR("D-Bus API failure: errCode[%x], \
581 error->code, error->message);
582 g_clear_error(&error);
584 return BLUETOOTH_ERROR_INTERNAL;
586 return BLUETOOTH_ERROR_NONE;
590 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
592 const gchar *object_path,
593 const gchar *interface_name,
594 const gchar *method_name,
595 GVariant *parameters,
596 GDBusMethodInvocation *invocation,
603 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
604 BT_DBG("Getting values for service, chars and descriptors");
606 GVariantBuilder *builder;
607 GVariantBuilder *inner_builder1 = NULL;
608 GVariant *svc_char = NULL;
611 builder = g_variant_builder_new(
612 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
614 /* Prepare inner builder for GattService1 interface */
616 len = g_slist_length(gatt_services);
618 for (i = 0; i <= len; i++) {
619 GVariantBuilder *svc_builder = NULL;
620 GVariantBuilder *inner_builder = NULL;
622 if (register_pending_cnt > 1)
623 l1 = g_slist_nth(gatt_services, len - register_pending_cnt);
625 l1 = g_slist_last(gatt_services);
627 register_pending_cnt--;
630 BT_ERR("gatt service list is NULL");
631 g_dbus_method_invocation_return_value(invocation, NULL);
632 g_variant_builder_unref(builder);
636 struct gatt_service_info *serv_info = l1->data;
637 if (serv_info == NULL) {
638 BT_ERR("service info value is NULL");
639 g_dbus_method_invocation_return_value(invocation, NULL);
640 g_variant_builder_unref(builder);
644 /* Prepare inner builder for GattService1 interface */
645 BT_DBG("Creating builder for service");
646 svc_builder = g_variant_builder_new(
647 G_VARIANT_TYPE("a{sa{sv}}"));
648 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
650 g_variant_builder_add(inner_builder, "{sv}", "UUID",
651 g_variant_new_string(serv_info->service_uuid));
653 g_variant_builder_add(inner_builder, "{sv}", "Primary",
654 g_variant_new_boolean(serv_info->is_svc_primary));
657 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
658 BT_DBG("Adding Charatarisitcs list");
659 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
660 struct gatt_char_info *char_info = l4->data;
661 g_variant_builder_add(inner_builder1, "o",
662 char_info->char_path);
663 BT_DBG("%s", char_info->char_path);
666 svc_char = g_variant_new("ao", inner_builder1);
667 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
670 g_variant_builder_add(svc_builder, "{sa{sv}}",
674 g_variant_builder_add(builder, "{oa{sa{sv}}}",
675 serv_info->serv_path,
678 g_variant_builder_unref(inner_builder1);
680 /* Prepare inner builder for GattCharacteristic1 interface */
682 GSList *l2 = serv_info->char_data;
683 BT_DBG("Creating builder for characteristics \n");
686 BT_DBG("characteristic data is NULL");
688 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
690 GVariantBuilder *char_builder = NULL;
691 GVariantBuilder *inner_builder = NULL;
692 GVariantBuilder *builder1 = NULL;
693 GVariantBuilder *builder2 = NULL;
694 GVariantBuilder *builder3 = NULL;
695 GVariant *char_val = NULL;
696 GVariant *flags_val = NULL;
697 GVariant *char_desc = NULL;
698 char *unicast = NULL;
699 gboolean notify = FALSE;
702 char_builder = g_variant_builder_new(
705 inner_builder = g_variant_builder_new(
709 struct gatt_char_info *char_info = l2->data;
710 if (char_info == NULL) {
711 BT_ERR("char_info is NULL");
716 g_variant_builder_add(inner_builder, "{sv}", "UUID",
717 g_variant_new_string(char_info->char_uuid));
719 g_variant_builder_add(inner_builder, "{sv}", "Service",
720 g_variant_new("o", serv_info->serv_path));
722 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
724 if (char_info->char_value != NULL) {
725 for (i = 0; i < char_info->value_length; i++) {
726 g_variant_builder_add(builder1, "y",
727 char_info->char_value[i]);
729 char_val = g_variant_new("ay", builder1);
730 g_variant_builder_add(inner_builder, "{sv}",
734 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
736 for (i = 0; i < char_info->flags_length; i++) {
737 g_variant_builder_add(builder2, "s",
738 char_info->char_flags[i]);
741 flags_val = g_variant_new("as", builder2);
742 g_variant_builder_add(inner_builder, "{sv}", "Flags",
746 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
747 g_variant_new("b", notify));
750 unicast = g_strdup("00:00:00:00:00:00");
751 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
752 g_variant_new("s", unicast));
755 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
756 BT_DBG("Adding Descriptors list");
758 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
759 struct gatt_desc_info *desc_info = l4->data;
760 g_variant_builder_add(builder3, "o",
761 desc_info->desc_path);
762 BT_DBG("%s", desc_info->desc_path);
765 char_desc = g_variant_new("ao", builder3);
766 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
769 g_variant_builder_add(char_builder, "{sa{sv}}",
770 GATT_CHAR_INTERFACE , inner_builder);
771 g_variant_builder_add(builder, "{oa{sa{sv}}}",
772 char_info->char_path, char_builder);
774 /*Prepare inner builder for GattDescriptor1 interface*/
776 GSList *l3 = char_info->desc_data;
779 BT_DBG("descriptor data is NULL");
781 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
783 BT_DBG("Creating builder for descriptor \n");
785 GVariantBuilder *desc_builder = NULL;
786 GVariantBuilder *inner_builder = NULL;
787 GVariantBuilder *builder1 = NULL;
788 GVariantBuilder *builder2 = NULL;
789 GVariant *desc_val = NULL;
791 desc_builder = g_variant_builder_new(
794 inner_builder = g_variant_builder_new(
798 struct gatt_desc_info *desc_info = l3->data;
799 if (desc_info == NULL) {
800 BT_ERR("desc_info is NULL");
805 g_variant_builder_add(inner_builder,
807 g_variant_new_string(
808 desc_info->desc_uuid));
811 g_variant_builder_add(inner_builder, "{sv}",
814 char_info->char_path));
817 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
819 if (desc_info->desc_value != NULL) {
820 for (i = 0; i < desc_info->value_length; i++) {
821 g_variant_builder_add(builder1, "y",
822 desc_info->desc_value[i]);
824 desc_val = g_variant_new("ay", builder1);
825 g_variant_builder_add(inner_builder, "{sv}",
830 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
832 for (i = 0; i < desc_info->flags_length; i++) {
833 g_variant_builder_add(builder2, "s",
834 desc_info->desc_flags[i]);
837 flags_val = g_variant_new("as", builder2);
838 g_variant_builder_add(inner_builder, "{sv}", "Flags",
841 g_variant_builder_add(desc_builder, "{sa{sv}}",
845 g_variant_builder_add(builder, "{oa{sa{sv}}}",
846 desc_info->desc_path,
849 /*unref descriptor builder pointers*/
850 g_variant_builder_unref(builder1);
851 g_variant_builder_unref(builder2);
852 g_variant_builder_unref(inner_builder);
853 g_variant_builder_unref(desc_builder);
858 /*unref char builder pointers*/
859 g_variant_builder_unref(builder1);
860 g_variant_builder_unref(builder2);
861 g_variant_builder_unref(builder3);
862 g_variant_builder_unref(inner_builder);
863 g_variant_builder_unref(char_builder);
866 /*unref service builder pointers*/
867 g_variant_builder_unref(inner_builder);
868 g_variant_builder_unref(svc_builder);
871 /* Return builder as method reply */
872 BT_DBG("Sending gatt service builder values to Bluez");
873 g_dbus_method_invocation_return_value(invocation,
877 g_variant_builder_unref(builder);
881 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
885 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
886 struct gatt_service_info *serv_info = l1->data;
888 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
889 struct gatt_char_info *char_info = l2->data;
891 if (g_strcmp0(char_info->char_path, char_path)
896 BT_ERR("Gatt service not found");
900 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
902 GSList *l1, *l2, *l3;
904 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
905 struct gatt_service_info *serv_info = l1->data;
907 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
908 struct gatt_char_info *char_info = l2->data;
910 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
911 struct gatt_desc_info *desc_info = l3->data;
913 if (g_strcmp0(desc_info->desc_path, desc_path)
919 BT_ERR("Gatt service not found");
923 static void __bt_gatt_char_method_call(GDBusConnection *connection,
925 const gchar *object_path,
926 const gchar *interface_name,
927 const gchar *method_name,
928 GVariant *parameters,
929 GDBusMethodInvocation *invocation,
933 if (g_strcmp0(method_name, "ReadValue") == 0) {
937 bt_gatt_read_req_t read_req = {0, };
938 bt_user_info_t *user_info = NULL;
939 struct gatt_req_info *req_info = NULL;
940 struct gatt_service_info *svc_info = NULL;
941 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
942 GVariant *param = NULL;
945 BT_DBG("Application path = %s", object_path);
946 BT_DBG("Sender = %s", sender);
948 user_info = _bt_get_user_data(BT_COMMON);
949 if (user_info == NULL) {
950 BT_INFO("No callback is set for %s", object_path);
951 g_dbus_method_invocation_return_value(invocation, NULL);
955 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
956 if (svc_info == NULL) {
957 BT_ERR("Coudn't find service for %s", object_path);
958 g_dbus_method_invocation_return_value(invocation, NULL);
962 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
963 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
965 read_req.att_handle = (char *)object_path;
966 read_req.address = addr;
967 read_req.req_id = req_id;
968 read_req.offset = offset;
969 read_req.service_handle = svc_info->serv_path;
971 /* Store requets information */
972 req_info = g_new0(struct gatt_req_info, 1);
973 req_info->attr_path = g_strdup(object_path);
974 req_info->svc_path = g_strdup(read_req.service_handle);
975 req_info->request_id = req_id;
976 req_info->offset = offset;
977 req_info->context = invocation;
978 gatt_requests = g_slist_append(gatt_requests, req_info);
980 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
981 param = g_variant_new("(sssyq)",
983 read_req.service_handle,
987 #ifdef TIZEN_FEATURE_BT_HPS
988 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
990 #ifdef TIZEN_FEATURE_BT_OTP
991 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
995 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
996 BLUETOOTH_ERROR_NONE, &read_req,
997 user_info->cb, user_info->user_data);
999 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1000 GVariant *var = NULL;
1004 gboolean response_needed = FALSE;
1005 bt_gatt_value_change_t value_change = {0, };
1006 bt_user_info_t *user_info = NULL;
1008 struct gatt_service_info *svc_info = NULL;
1009 struct gatt_req_info *req_info = NULL;
1010 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
1011 GVariant *param = NULL;
1014 BT_DBG("WriteValue");
1015 BT_DBG("Application path = %s", object_path);
1016 BT_DBG("Sender = %s", sender);
1018 g_variant_get(parameters, "(&suqb@ay)",
1019 &addr, &req_id, &offset, &response_needed, &var);
1020 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1022 user_info = _bt_get_user_data(BT_COMMON);
1024 BT_INFO("No callback is set for %s", object_path);
1025 g_variant_unref(var);
1026 if (response_needed)
1027 g_dbus_method_invocation_return_value(invocation, NULL);
1029 g_object_unref(invocation);
1033 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1034 if (svc_info == NULL) {
1035 BT_ERR("Coudn't find service for %s", object_path);
1036 g_variant_unref(var);
1037 if (response_needed)
1038 g_dbus_method_invocation_return_value(invocation, NULL);
1040 g_object_unref(invocation);
1044 value_change.att_handle = (char *)object_path;
1045 value_change.address = addr;
1046 value_change.service_handle = svc_info->serv_path;
1047 value_change.offset = offset;
1048 value_change.req_id = req_id;
1049 value_change.response_needed = response_needed;
1051 len = g_variant_get_size(var);
1055 value_change.att_value = (guint8 *)g_malloc(len);
1057 data = (char *)g_variant_get_data(var);
1058 memcpy(value_change.att_value, data, len);
1060 value_change.val_len = len;
1062 if (response_needed) {
1063 /* Store requets information */
1064 req_info = g_new0(struct gatt_req_info, 1);
1065 req_info->attr_path = g_strdup(object_path);
1066 req_info->svc_path = g_strdup(value_change.service_handle);
1067 req_info->request_id = req_id;
1068 req_info->offset = offset;
1069 req_info->context = invocation;
1070 gatt_requests = g_slist_append(gatt_requests, req_info);
1072 g_object_unref(invocation);
1075 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
1078 svc_path = g_strdup(svc_info->serv_path);
1079 param = g_variant_new("(sssyq@ay)",
1086 #ifdef TIZEN_FEATURE_BT_HPS
1087 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1089 #ifdef TIZEN_FEATURE_BT_OTP
1090 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1097 _bt_common_event_cb(
1098 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1099 BLUETOOTH_ERROR_NONE, &value_change,
1100 user_info->cb, user_info->user_data);
1102 g_free(value_change.att_value);
1103 g_variant_unref(var);
1105 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1106 bt_user_info_t *user_info = NULL;
1107 bt_gatt_char_notify_change_t notify_change = {0, };
1108 #if TIZEN_FEATURE_BT_OTP
1109 GVariant *param = NULL;
1111 BT_DBG("StartNotify");
1112 user_info = _bt_get_user_data(BT_COMMON);
1113 if (user_info != NULL) {
1114 struct gatt_service_info *svc_info = NULL;
1115 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1117 notify_change.service_handle = svc_info->serv_path;
1118 notify_change.att_handle = (char *)object_path;
1119 notify_change.att_notify = TRUE;
1120 #if TIZEN_FEATURE_BT_OTP
1121 param = g_variant_new("(ssb)",
1122 notify_change.att_handle,
1123 notify_change.service_handle,
1124 notify_change.att_notify);
1125 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1127 _bt_common_event_cb(
1128 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1129 BLUETOOTH_ERROR_NONE, ¬ify_change,
1130 user_info->cb, user_info->user_data);
1133 g_object_unref(invocation);
1135 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1136 bt_user_info_t *user_info = NULL;
1137 bt_gatt_char_notify_change_t notify_change = {0, };
1138 #if TIZEN_FEATURE_BT_OTP
1139 GVariant *param = NULL;
1141 BT_DBG("StopNotify");
1142 user_info = _bt_get_user_data(BT_COMMON);
1143 if (user_info != NULL) {
1144 struct gatt_service_info *svc_info = NULL;
1145 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1147 notify_change.service_handle = svc_info->serv_path;
1148 notify_change.att_handle = (char *)object_path;
1149 notify_change.att_notify = FALSE;
1150 #if TIZEN_FEATURE_BT_OTP
1151 param = g_variant_new("(ssb)",
1152 notify_change.att_handle,
1153 notify_change.service_handle,
1154 notify_change.att_notify);
1155 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1157 _bt_common_event_cb(
1158 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1159 BLUETOOTH_ERROR_NONE, ¬ify_change,
1160 user_info->cb, user_info->user_data);
1163 g_object_unref(invocation);
1165 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1167 bt_gatt_indicate_confirm_t confirm = {0, };
1168 bt_user_info_t *user_info = NULL;
1169 gboolean complete = FALSE;
1170 struct gatt_service_info *svc_info = NULL;
1172 BT_DBG("IndicateConfirm");
1173 BT_DBG("Application path = %s", object_path);
1174 BT_DBG("Sender = %s", sender);
1176 g_variant_get(parameters, "(&sb)", &addr, &complete);
1177 BT_DBG("Remote Device address number = %s", addr);
1179 confirm.att_handle = (char *)object_path;
1180 confirm.address = addr;
1181 confirm.complete = complete;
1183 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1184 if (svc_info != NULL) {
1185 confirm.service_handle = svc_info->serv_path;
1187 user_info = _bt_get_user_data(BT_COMMON);
1188 if (user_info != NULL) {
1189 _bt_common_event_cb(
1190 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1191 BLUETOOTH_ERROR_NONE, &confirm,
1192 user_info->cb, user_info->user_data);
1197 g_dbus_method_invocation_return_value(invocation, NULL);
1200 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1201 const gchar *sender,
1202 const gchar *object_path,
1203 const gchar *interface_name,
1204 const gchar *method_name,
1205 GVariant *parameters,
1206 GDBusMethodInvocation *invocation,
1209 if (g_strcmp0(method_name, "ReadValue") == 0) {
1213 bt_gatt_read_req_t read_req = {0, };
1214 bt_user_info_t *user_info = NULL;
1215 struct gatt_req_info *req_info = NULL;
1216 struct gatt_service_info *svc_info = NULL;
1218 BT_DBG("ReadValue");
1219 BT_DBG("Application path = %s", object_path);
1220 BT_DBG("Sender = %s", sender);
1222 user_info = _bt_get_user_data(BT_COMMON);
1223 if (user_info == NULL) {
1224 BT_INFO("No callback is set for %s", object_path);
1225 g_dbus_method_invocation_return_value(invocation, NULL);
1229 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1230 if (svc_info == NULL) {
1231 BT_ERR("Coudn't find service for %s", object_path);
1232 g_dbus_method_invocation_return_value(invocation, NULL);
1236 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1237 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1239 read_req.att_handle = (char *)object_path;
1240 read_req.address = addr;
1241 read_req.req_id = req_id;
1242 read_req.offset = offset;
1243 read_req.service_handle = svc_info->serv_path;
1245 /* Store requets information */
1246 req_info = g_new0(struct gatt_req_info, 1);
1247 req_info->attr_path = g_strdup(object_path);
1248 req_info->svc_path = g_strdup(read_req.service_handle);
1249 req_info->request_id = req_id;
1250 req_info->offset = offset;
1251 req_info->context = invocation;
1252 gatt_requests = g_slist_append(gatt_requests, req_info);
1254 _bt_common_event_cb(
1255 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1256 BLUETOOTH_ERROR_NONE, &read_req,
1257 user_info->cb, user_info->user_data);
1260 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1261 GVariant *var = NULL;
1265 gboolean response_needed = FALSE;
1266 bt_gatt_value_change_t value_change = {0, };
1267 bt_user_info_t *user_info = NULL;
1269 struct gatt_service_info *svc_info = NULL;
1270 struct gatt_req_info *req_info = NULL;
1272 BT_DBG("WriteValue");
1273 BT_DBG("Application path = %s", object_path);
1274 BT_DBG("Sender = %s", sender);
1276 g_variant_get(parameters, "(&suqb@ay)",
1277 &addr, &req_id, &offset, &response_needed, &var);
1278 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1280 user_info = _bt_get_user_data(BT_COMMON);
1281 if (user_info == NULL) {
1282 BT_INFO("No callback is set for %s", object_path);
1283 g_variant_unref(var);
1284 if (response_needed)
1285 g_dbus_method_invocation_return_value(invocation, NULL);
1287 g_object_unref(invocation);
1291 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1292 if (svc_info == NULL) {
1293 BT_ERR("Coudn't find service for %s", object_path);
1294 g_variant_unref(var);
1295 if (response_needed)
1296 g_dbus_method_invocation_return_value(invocation, NULL);
1298 g_object_unref(invocation);
1302 value_change.att_handle = (char *)object_path;
1303 value_change.address = addr;
1304 value_change.service_handle = svc_info->serv_path;
1305 value_change.offset = offset;
1306 value_change.req_id = req_id;
1307 value_change.response_needed = response_needed;
1309 len = g_variant_get_size(var);
1313 value_change.att_value = (guint8 *)g_malloc(len);
1315 data = (char *)g_variant_get_data(var);
1316 memcpy(value_change.att_value, data, len);
1318 value_change.val_len = len;
1320 if (response_needed) {
1321 /* Store requets information */
1322 req_info = g_new0(struct gatt_req_info, 1);
1323 req_info->attr_path = g_strdup(object_path);
1324 req_info->svc_path = g_strdup(value_change.service_handle);
1325 req_info->request_id = req_id;
1326 req_info->offset = offset;
1327 req_info->context = invocation;
1328 gatt_requests = g_slist_append(gatt_requests, req_info);
1330 g_object_unref(invocation);
1333 _bt_common_event_cb(
1334 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1335 BLUETOOTH_ERROR_NONE, &value_change,
1336 user_info->cb, user_info->user_data);
1338 g_free(value_change.att_value);
1339 g_variant_unref(var);
1344 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1347 GError *error = NULL;
1348 GVariantBuilder *array_builder;
1350 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1351 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1352 g_variant_builder_add(array_builder, "s", interface);
1354 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1355 "org.freedesktop.Dbus.Objectmanager",
1356 "InterfacesRemoved",
1357 g_variant_new("(oas)",
1358 object_path, array_builder),
1362 if (error != NULL) {
1363 /* dbus gives error cause */
1364 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1365 error->code, error->message);
1366 g_clear_error(&error);
1369 g_variant_builder_unref(array_builder);
1374 static const GDBusInterfaceVTable desc_interface_vtable = {
1375 __bt_gatt_desc_method_call,
1381 static const GDBusInterfaceVTable char_interface_vtable = {
1382 __bt_gatt_char_method_call,
1388 static const GDBusInterfaceVTable serv_interface_vtable = {
1395 static const GDBusInterfaceVTable manager_interface_vtable = {
1396 __bt_gatt_manager_method_call,
1402 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1403 const gchar *introspection_data)
1406 GDBusNodeInfo *node_info = NULL;
1408 if (introspection_data == NULL)
1412 BT_DBG("Create new node info");
1413 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1416 BT_ERR("Unable to create node: %s", err->message);
1417 g_clear_error(&err);
1424 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1425 const char *service_path)
1429 for (l = gatt_services; l != NULL; l = l->next) {
1430 struct gatt_service_info *info = l->data;
1432 if (g_strcmp0(info->serv_path, service_path) == 0)
1435 BT_ERR("Gatt service not found");
1439 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1440 const char *service_path, const char *char_path)
1444 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1445 struct gatt_service_info *serv_info = l1->data;
1447 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1449 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1450 struct gatt_char_info *char_info = l2->data;
1452 if (g_strcmp0(char_info->char_path, char_path)
1456 BT_ERR("Gatt characteristic not found");
1460 BT_ERR("Gatt service not found");
1464 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1465 const char *serv_path, const char *char_path,
1466 const char *desc_path)
1468 GSList *l1, *l2, *l3;
1470 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1471 struct gatt_service_info *serv_info = l1->data;
1473 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1474 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1475 struct gatt_char_info *char_info = l2->data;
1477 if (g_strcmp0(char_info->char_path, char_path)
1479 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1480 struct gatt_desc_info *desc_info = l3->data;
1481 if (g_strcmp0(desc_info->desc_path,
1490 BT_ERR("Gatt descriptor not found");
1494 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1498 for (l = gatt_requests; l != NULL; l = l->next) {
1499 struct gatt_req_info *req_info = l->data;
1501 if (req_info && req_info->request_id == request_id)
1504 BT_ERR("Gatt Request not found");
1508 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1509 const gchar *path, const gchar *interface)
1515 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1520 BT_ERR("Unable to connect to gdbus: %s", err->message);
1521 g_clear_error(&err);
1526 proxy = g_dbus_proxy_new_sync(g_conn,
1527 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1529 interface, NULL, &err);
1533 BT_ERR("Unable to create proxy: %s", err->message);
1534 g_clear_error(&err);
1538 manager_gproxy = proxy;
1543 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1544 const gchar *path, const gchar *interface)
1546 return (manager_gproxy) ? manager_gproxy :
1547 __bt_gatt_gdbus_init_manager_proxy(service,
1552 static void __bt_gatt_set_service_state(const char *service_path,
1555 struct gatt_service_info *svc_info = NULL;
1556 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1558 if (svc_info != NULL) {
1559 BT_DBG("Updating the gatt service register state %d", state);
1560 svc_info->is_svc_registered = state;
1564 BT_DBG("gatt service not found");
1567 static gboolean __bt_gatt_get_service_state(const char *service_path)
1569 struct gatt_service_info *svc_info = NULL;
1571 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1573 if (svc_info != NULL) {
1574 BT_DBG("Return the state of the gatt service %d",
1575 svc_info->is_svc_registered);
1576 return svc_info->is_svc_registered;
1579 BT_DBG("gatt service info is NULL");
1583 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1585 GError *error = NULL;
1587 GVariantIter *iter = NULL;
1588 const gchar *key = NULL;
1589 GVariant *value = NULL;
1590 const gchar *service = NULL;
1591 const gchar *characteristic = NULL;
1592 const gchar *descriptor = NULL;
1596 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1598 if (result == NULL) {
1599 /* dBUS-RPC is failed */
1600 BT_ERR("Dbus-RPC is failed\n");
1602 if (error != NULL) {
1603 /* dBUS gives error cause */
1604 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1605 error->code, error->message);
1606 g_clear_error(&error);
1609 char *char_cmp = NULL;
1610 g_variant_get(result, "(a{sv})", &iter);
1611 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1613 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1614 if (g_strcmp0(key, "Service") == 0) {
1615 service = g_variant_get_string(value, NULL);
1616 BT_DBG("Service %s", service);
1617 } else if (g_strcmp0(key, char_cmp) == 0) {
1618 characteristic = g_variant_get_string(value, NULL);
1620 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1621 BT_DBG("%s", characteristic);
1622 } else if (g_strcmp0(key, "Descriptor") == 0) {
1623 descriptor = g_variant_get_string(value, NULL);
1624 BT_DBG("Descriptor %s", descriptor);
1627 g_variant_iter_free(iter);
1629 /* TODO: Store the service informationa and
1630 * Send respponse to CAPI layer. */
1632 g_variant_unref(result);
1637 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1639 BT_INFO("RegisterApplication is completed");
1641 GError *error = NULL;
1644 register_pending_cnt = 0;
1646 if (register_cancel) {
1647 g_object_unref(register_cancel);
1648 register_cancel = NULL;
1651 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1653 if (result == NULL) {
1654 /* dBUS-RPC is failed */
1655 BT_ERR("Dbus-RPC is failed\n");
1657 if (error != NULL) {
1658 /* dBUS gives error cause */
1659 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1660 error->code, error->message);
1661 g_clear_error(&error);
1664 g_variant_unref(result);
1668 static int __bt_gatt_unregister_service(const char *service_path)
1670 if (!__bt_gatt_get_service_state(service_path)) {
1671 BT_DBG("service not registered \n");
1672 return BLUETOOTH_ERROR_NOT_FOUND;
1675 return BLUETOOTH_ERROR_NONE;
1678 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1680 GDBusProxy *proxy = NULL;
1682 if (is_server_started) {
1686 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1687 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1689 if (proxy == NULL || app_path == NULL)
1690 return BLUETOOTH_ERROR_INTERNAL;
1692 BT_INFO("UnregisterApplication");
1694 is_server_started = false;
1696 /* Async Call to Unregister Service */
1697 ret = g_dbus_proxy_call_sync(proxy,
1698 "UnregisterApplication",
1699 g_variant_new("(o)",
1701 G_DBUS_CALL_FLAGS_NONE, -1,
1705 /* dBUS-RPC is failed */
1706 BT_ERR("dBUS-RPC is failed");
1708 /* dBUS gives error cause */
1709 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1710 err->code, err->message);
1712 g_clear_error(&err);
1714 return BLUETOOTH_ERROR_INTERNAL;
1716 g_variant_unref(ret);
1718 BT_INFO("UnregisterApplication is completed");
1720 return BLUETOOTH_ERROR_NONE;
1723 BT_INFO("GATT server not started");
1724 return BLUETOOTH_ERROR_NONE;
1727 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1729 GDBusConnection *local_system_gconn = NULL;
1733 if (g_conn == NULL) {
1734 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1735 if (address == NULL) {
1737 BT_ERR("Failed to get bus address: %s", err->message);
1738 g_clear_error(&err);
1743 g_conn = g_dbus_connection_new_for_address_sync(address,
1744 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1745 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1746 NULL, /* GDBusAuthObserver */
1752 BT_ERR("Unable to connect to dbus: %s", err->message);
1753 g_clear_error(&err);
1757 } else if (g_dbus_connection_is_closed(g_conn)) {
1758 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1759 if (address == NULL) {
1761 BT_ERR("Failed to get bus address: %s", err->message);
1762 g_clear_error(&err);
1767 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1768 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1769 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1770 NULL, /* GDBusAuthObserver */
1774 if (!local_system_gconn) {
1775 BT_ERR("Unable to connect to dbus: %s", err->message);
1776 g_clear_error(&err);
1779 g_conn = local_system_gconn;
1785 BT_EXPORT_API int bluetooth_gatt_init(void)
1787 GDBusConnection *conn;
1788 GError *error = NULL;
1789 GDBusNodeInfo *node_info = NULL;
1791 if (app_path != NULL) {
1792 BT_ERR("app path already exists! initialized");
1793 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1796 if (owner_id == 0) {
1797 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1798 BT_GATT_SERVICE_NAME,
1799 G_BUS_NAME_OWNER_FLAGS_NONE,
1800 NULL, NULL, NULL, NULL, NULL);
1803 BT_DBG("owner_id is [%d]", owner_id);
1804 app_path = g_strdup_printf("/com/%d", getpid());
1808 conn = __bt_gatt_get_gdbus_connection();
1810 BT_ERR("Unable to get connection");
1814 /* Register ObjectManager interface */
1815 node_info = __bt_gatt_create_method_node_info(
1816 manager_introspection_xml);
1817 if (node_info == NULL) {
1818 BT_ERR("failed to get node info");
1822 if (manager_id == 0) {
1823 BT_INFO("manager_id does not exists");
1825 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1826 node_info->interfaces[0],
1827 &manager_interface_vtable,
1828 NULL, NULL, &error);
1830 g_dbus_node_info_unref(node_info);
1831 if (manager_id == 0) {
1832 BT_ERR("failed to register: %s", error->message);
1833 g_error_free(error);
1837 return BLUETOOTH_ERROR_NONE;
1841 g_bus_unown_name(owner_id);
1848 __bt_gatt_close_gdbus_connection();
1850 return BLUETOOTH_ERROR_INTERNAL;
1853 BT_EXPORT_API int bluetooth_gatt_deinit()
1855 int ret = BLUETOOTH_ERROR_NONE;
1857 if (register_cancel) {
1858 g_cancellable_cancel(register_cancel);
1859 g_object_unref(register_cancel);
1860 register_cancel = NULL;
1863 /* Unown gdbus bus */
1865 /* remove/unregister all services */
1866 BT_DBG("removing all registered gatt service\n");
1867 bluetooth_gatt_delete_services();
1869 /* unregister the exported interface for object manager */
1870 g_dbus_connection_unregister_object(g_conn,
1875 ret = bluetooth_gatt_unregister_application();
1876 if (ret != BLUETOOTH_ERROR_NONE)
1877 BT_ERR("Fail to unregister application\n");
1879 g_bus_unown_name(owner_id);
1885 BT_DBG("Gatt service deinitialized \n");
1887 g_slist_free(gatt_services);
1888 gatt_services = NULL;
1890 g_object_unref(manager_gproxy);
1891 manager_gproxy = NULL;
1893 __bt_gatt_close_gdbus_connection();
1898 __bt_gatt_close_gdbus_connection();
1900 return BLUETOOTH_ERROR_NOT_FOUND;
1903 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1906 GError *error = NULL;
1908 GDBusNodeInfo *node_info;
1910 GVariantBuilder *builder = NULL;
1911 GVariantBuilder *builder1 = NULL;
1912 GVariantBuilder *inner_builder = NULL;
1913 gboolean svc_primary = TRUE;
1914 struct gatt_service_info *serv_info = NULL;
1916 node_info = __bt_gatt_create_method_node_info(
1917 service_introspection_xml);
1918 if (node_info == NULL)
1919 return BLUETOOTH_ERROR_INTERNAL;
1921 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1922 BT_DBG("gatt service path is [%s]", path);
1924 object_id = g_dbus_connection_register_object(g_conn, path,
1925 node_info->interfaces[0],
1926 &serv_interface_vtable,
1927 NULL, NULL, &error);
1928 g_dbus_node_info_unref(node_info);
1930 if (object_id == 0) {
1931 BT_ERR("failed to register: %s", error->message);
1932 g_error_free(error);
1935 return BLUETOOTH_ERROR_INTERNAL;
1938 /* Add object_id/gatt service information; it's required at the time of
1939 * service unregister and Getmanagedobjects
1941 serv_info = g_new0(struct gatt_service_info, 1);
1943 serv_info->serv_path = g_strdup(path);
1944 serv_info->serv_id = object_id;
1945 serv_info->service_uuid = g_strdup(svc_uuid);
1946 serv_info->is_svc_registered = FALSE;
1947 serv_info->is_svc_primary = svc_primary;
1949 gatt_services = g_slist_append(gatt_services, serv_info);
1951 /* emit interfacesadded signal here for service path */
1952 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1953 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1955 g_variant_builder_add(inner_builder, "{sv}",
1956 "UUID", g_variant_new_string(svc_uuid));
1958 g_variant_builder_add(inner_builder, "{sv}",
1959 "Primary", g_variant_new_boolean(svc_primary));
1961 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1963 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1964 g_variant_new("ao", builder1));
1966 g_variant_builder_add(builder, "{sa{sv}}",
1967 GATT_SERV_INTERFACE, inner_builder);
1969 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1970 "org.freedesktop.Dbus.ObjectManager",
1972 g_variant_new("(oa{sa{sv}})",
1975 if (error != NULL) {
1976 /* dbus gives error cause */
1977 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1978 error->code, error->message);
1979 g_clear_error(&error);
1984 *svc_path = g_strdup(path);
1987 g_variant_builder_unref(inner_builder);
1988 g_variant_builder_unref(builder);
1989 g_variant_builder_unref(builder1);
1991 return BLUETOOTH_ERROR_NONE;
1994 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1995 const char *svc_path, const char *char_uuid,
1996 bt_gatt_permission_t permissions,
1997 bt_gatt_characteristic_property_t properties,
2001 GError *error = NULL;
2003 GDBusNodeInfo *node_info;
2005 GVariantBuilder *builder = NULL;
2006 GVariantBuilder *inner_builder = NULL;
2007 struct gatt_service_info *serv_info = NULL;
2008 struct gatt_char_info *char_info = NULL;
2009 GVariantBuilder *builder2 = NULL;
2010 GVariantBuilder *builder3 = NULL;
2011 GVariant *flags_val = NULL;
2013 char *char_flags[NUMBER_OF_FLAGS];
2018 new_service = FALSE;
2021 BT_DBG("gatt svc_path path is [%s]", svc_path);
2022 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
2023 if (serv_info == NULL)
2024 return BLUETOOTH_ERROR_INVALID_PARAM;
2026 node_info = __bt_gatt_create_method_node_info(
2027 characteristics_introspection_xml);
2028 if (node_info == NULL)
2029 return BLUETOOTH_ERROR_INTERNAL;
2031 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
2032 BT_DBG("gatt characteristic path is [%s]", path);
2034 object_id = g_dbus_connection_register_object(g_conn, path,
2035 node_info->interfaces[0],
2036 &char_interface_vtable,
2037 NULL, NULL, &error);
2038 g_dbus_node_info_unref(node_info);
2040 if (object_id == 0) {
2041 BT_ERR("failed to register: %s", error->message);
2042 g_error_free(error);
2045 return BLUETOOTH_ERROR_INTERNAL;
2048 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
2049 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2050 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2051 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2052 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
2053 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2054 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2055 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2057 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
2059 char_info = g_new0(struct gatt_char_info, 1);
2061 char_info->char_path = g_strdup(path);
2062 char_info->char_id = object_id;
2063 char_info->char_uuid = g_strdup(char_uuid);
2065 for (i = 0; i < flag_count; i++)
2066 char_info->char_flags[i] = char_flags[i];
2069 char_info->flags_length = flag_count;
2071 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2073 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2074 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2076 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2077 g_variant_new("s", char_uuid));
2078 g_variant_builder_add(inner_builder, "{sv}", "Service",
2079 g_variant_new("o", svc_path));
2081 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2083 for (i = 0; i < flag_count; i++)
2084 g_variant_builder_add(builder2, "s", char_flags[i]);
2086 flags_val = g_variant_new("as", builder2);
2087 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2090 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2092 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2093 g_variant_new("ao", builder3));
2095 g_variant_builder_add(builder, "{sa{sv}}",
2096 GATT_CHAR_INTERFACE,
2099 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2100 "org.freedesktop.Dbus.ObjectManager",
2102 g_variant_new("(oa{sa{sv}})",
2107 /* dBUS gives error cause */
2108 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2109 error->code, error->message);
2110 g_clear_error(&error);
2113 *char_path = g_strdup(path);
2119 g_variant_builder_unref(inner_builder);
2120 g_variant_builder_unref(builder);
2121 g_variant_builder_unref(builder2);
2122 g_variant_builder_unref(builder3);
2124 return BLUETOOTH_ERROR_NONE;
2127 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
2128 const char *characteristic, const char *char_value,
2131 gchar **line_argv = NULL;
2132 char *serv_path = NULL;
2133 struct gatt_char_info *char_info = NULL;
2134 GVariantBuilder *builder1 = NULL;
2135 GVariantBuilder *builder = NULL;
2136 GVariantBuilder *inner_builder = NULL;
2137 GVariant *char_val = NULL;
2138 GError *error = NULL;
2140 int res = BLUETOOTH_ERROR_NONE;
2142 line_argv = g_strsplit_set(characteristic, "/", 0);
2143 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2145 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
2147 if (char_info == NULL) {
2148 /* Fix : RESOURCE_LEAK */
2149 res = BLUETOOTH_ERROR_INVALID_PARAM;
2153 char_info->value_length = value_length;
2155 char_info->char_value = (char *)malloc(value_length);
2156 /* Fix : NULL_RETURNS */
2157 if (char_info->char_value == NULL) {
2158 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2162 for (i = 0; i < value_length; i++)
2163 char_info->char_value[i] = char_value[i];
2165 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2166 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2168 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2170 for (i = 0; i < value_length; i++)
2171 g_variant_builder_add(builder1, "y", char_value[i]);
2173 char_val = g_variant_new("ay", builder1);
2174 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
2176 g_variant_builder_add(builder, "{sa{sv}}",
2177 GATT_CHAR_INTERFACE,
2180 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2181 "org.freedesktop.Dbus.ObjectManager",
2183 g_variant_new("(oa{sa{sv}})",
2184 char_info->char_path, builder),
2188 /* dBUS gives error cause */
2189 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2190 error->code, error->message);
2191 g_clear_error(&error);
2193 g_variant_builder_unref(inner_builder);
2194 g_variant_builder_unref(builder);
2195 g_variant_builder_unref(builder1);
2197 g_strfreev(line_argv);
2203 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2204 const char *char_path, const char *desc_uuid,
2205 bt_gatt_permission_t permissions,
2208 static int desc_id = 1;
2209 GError *error = NULL;
2211 GDBusNodeInfo *node_info;
2213 GVariantBuilder *builder = NULL;
2214 GVariantBuilder *inner_builder = NULL;
2215 struct gatt_char_info *char_info = NULL;
2216 struct gatt_desc_info *desc_info = NULL;
2217 gchar **line_argv = NULL;
2219 GVariantBuilder *builder2 = NULL;
2220 GVariant *flags_val = NULL;
2222 char *desc_flags[NUMBER_OF_FLAGS];
2230 line_argv = g_strsplit_set(char_path, "/", 0);
2231 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2233 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2234 if (char_info == NULL) {
2235 g_strfreev(line_argv);
2237 return BLUETOOTH_ERROR_INVALID_PARAM;
2240 node_info = __bt_gatt_create_method_node_info(
2241 descriptor_introspection_xml);
2242 if (node_info == NULL) {
2243 g_strfreev(line_argv);
2245 return BLUETOOTH_ERROR_INTERNAL;
2248 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2249 BT_DBG("gatt descriptor path is [%s]", path);
2251 object_id = g_dbus_connection_register_object(g_conn, path,
2252 node_info->interfaces[0],
2253 &desc_interface_vtable,
2254 NULL, NULL, &error);
2255 g_dbus_node_info_unref(node_info);
2257 if (object_id == 0) {
2258 BT_ERR("failed to register: %s", error->message);
2259 g_error_free(error);
2261 g_strfreev(line_argv);
2264 return BLUETOOTH_ERROR_INTERNAL;
2267 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2269 desc_info = g_new0(struct gatt_desc_info, 1);
2271 desc_info->desc_path = g_strdup(path);
2272 desc_info->desc_id = object_id;
2273 desc_info->desc_uuid = g_strdup(desc_uuid);
2275 for (i = 0; i < flag_count; i++)
2276 desc_info->desc_flags[i] = desc_flags[i];
2278 desc_info->flags_length = flag_count;
2280 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2282 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2283 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2285 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2286 g_variant_new("s", desc_uuid));
2287 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2288 g_variant_new("o", char_path));
2290 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2292 for (i = 0; i < flag_count; i++)
2293 g_variant_builder_add(builder2, "s", desc_flags[i]);
2295 flags_val = g_variant_new("as", builder2);
2296 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2299 g_variant_builder_add(builder, "{sa{sv}}",
2300 GATT_DESC_INTERFACE,
2303 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2304 "org.freedesktop.Dbus.ObjectManager",
2306 g_variant_new("(oa{sa{sv}})",
2310 /* dBUS gives error cause */
2311 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2312 error->code, error->message);
2313 g_clear_error(&error);
2316 *desc_path = g_strdup(path);
2320 g_strfreev(line_argv);
2321 g_variant_builder_unref(inner_builder);
2322 g_variant_builder_unref(builder);
2323 g_variant_builder_unref(builder2);
2325 return BLUETOOTH_ERROR_NONE;
2328 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2329 const char *desc_path, const char *desc_value,
2332 GError *error = NULL;
2333 GVariantBuilder *builder = NULL;
2334 GVariantBuilder *inner_builder = NULL;
2335 GVariantBuilder *builder1 = NULL;
2336 struct gatt_desc_info *desc_info = NULL;
2337 gchar **line_argv = NULL;
2339 GVariant *desc_val = NULL;
2340 char *serv_path = NULL;
2343 line_argv = g_strsplit_set(desc_path, "/", 0);
2344 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2345 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2347 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2349 /* Free the allocated memory */
2350 g_strfreev(line_argv);
2354 /* Fix : NULL_RETURNS */
2355 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2357 desc_info->desc_value = (char *)malloc(value_length);
2359 /* Fix : NULL_RETURNS */
2360 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2362 for (i = 0; i < value_length; i++)
2363 desc_info->desc_value[i] = desc_value[i];
2365 desc_info->value_length = value_length;
2367 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2368 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2370 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2372 for (i = 0; i < value_length; i++)
2373 g_variant_builder_add(builder1, "y", desc_value[i]);
2375 desc_val = g_variant_new("ay", builder1);
2376 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2378 g_variant_builder_add(builder, "{sa{sv}}",
2379 GATT_DESC_INTERFACE,
2382 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2383 "org.freedesktop.Dbus.ObjectManager",
2385 g_variant_new("(oa{sa{sv}})",
2386 desc_info->desc_path, builder),
2389 if (error != NULL) {
2390 BT_ERR("D-Bus API failure: errCode[%x], \
2392 error->code, error->message);
2393 g_clear_error(&error);
2396 g_variant_builder_unref(inner_builder);
2397 g_variant_builder_unref(builder);
2398 g_variant_builder_unref(builder1);
2400 return BLUETOOTH_ERROR_NONE;
2403 int bluetooth_gatt_get_service(const char *svc_uuid)
2405 GDBusProxy *proxy = NULL;
2408 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2409 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2411 return BLUETOOTH_ERROR_INTERNAL;
2413 uuid = g_strdup(svc_uuid);
2415 g_dbus_proxy_call(proxy,
2417 g_variant_new("(s)",
2419 G_DBUS_CALL_FLAGS_NONE, -1,
2421 (GAsyncReadyCallback) get_service_cb,
2426 return BLUETOOTH_ERROR_NONE;
2429 BT_EXPORT_API int bluetooth_gatt_register_service(
2430 const char *svc_path)
2432 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2433 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2434 BT_ERR("Don't have aprivilege to use this API");
2435 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2438 register_pending_cnt++;
2440 if (__bt_gatt_get_service_state(svc_path)) {
2441 BT_DBG("service already registered \n");
2442 return BLUETOOTH_ERROR_NONE;
2445 __bt_gatt_set_service_state(svc_path, TRUE);
2447 return BLUETOOTH_ERROR_NONE;
2450 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2452 GDBusProxy *proxy = NULL;
2454 if (!is_server_started) {
2456 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2457 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2458 BT_ERR("Don't have aprivilege to use this API");
2459 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2462 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2463 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2464 if (proxy == NULL || app_path == NULL)
2465 return BLUETOOTH_ERROR_INTERNAL;
2467 BT_INFO("RegisterApplication");
2469 if (register_cancel) {
2470 g_cancellable_cancel(register_cancel);
2471 g_object_unref(register_cancel);
2474 register_cancel = g_cancellable_new();
2476 g_dbus_proxy_call(proxy,
2477 "RegisterApplication",
2478 g_variant_new("(oa{sv})",
2480 G_DBUS_CALL_FLAGS_NONE, -1,
2482 (GAsyncReadyCallback) register_application_cb,
2485 is_server_started = true;
2487 return BLUETOOTH_ERROR_NONE;
2490 BT_INFO("Already RegisterApplication");
2492 return BLUETOOTH_ERROR_NONE;
2495 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2498 int ret = BLUETOOTH_ERROR_NONE;
2500 if (gatt_services == NULL) {
2501 BT_DBG("There are no registered services");
2506 for (l = gatt_services; l != NULL; ) {
2507 struct gatt_service_info *info = l->data;
2509 // In bluetooth_gatt_unregister_service, current node will be removed.
2510 // Go forward to next node before calling bluetooth_gatt_unregister_service.
2512 BT_DBG("svc_path is %s", info->serv_path);
2513 if (bluetooth_gatt_unregister_service(info->serv_path) != BLUETOOTH_ERROR_NONE) {
2514 ret = BLUETOOTH_ERROR_INTERNAL;
2515 BT_ERR("Error in removing service %s", info->serv_path);
2518 BT_INFO("All services are removed : %d", ret);
2520 g_slist_free(gatt_services);
2521 gatt_services = NULL;
2527 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2528 const char *char_path, const char* char_value,
2531 GVariantBuilder *outer_builder;
2532 GVariantBuilder *inner_builder;
2533 GVariantBuilder *invalidated_builder;
2534 GVariant *update_value = NULL;
2535 GError *error = NULL;
2536 gboolean ret = FALSE;
2537 int err = BLUETOOTH_ERROR_NONE;
2539 gchar **line_argv = NULL;
2540 gchar *serv_path = NULL;
2541 const char *value = NULL;
2543 line_argv = g_strsplit_set(char_path, "/", 0);
2544 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2546 if (!__bt_gatt_get_service_state(serv_path)) {
2547 BT_DBG("service not registered for this characteristic \n");
2549 g_strfreev(line_argv);
2550 return BLUETOOTH_ERROR_INTERNAL;
2553 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2554 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2556 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2557 for (i = 0; i < value_length; i++)
2558 g_variant_builder_add(inner_builder, "y", char_value[i]);
2560 update_value = g_variant_new("ay", inner_builder);
2562 g_variant_builder_add(outer_builder, "{sv}", "Value",
2565 BT_DBG("Updating characteristic value \n");
2566 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2568 "org.freedesktop.DBus.Properties",
2569 "PropertiesChanged",
2570 g_variant_new("(sa{sv}as)",
2571 "org.bluez.GattCharacteristic1",
2572 outer_builder, invalidated_builder),
2576 if (error != NULL) {
2577 BT_ERR("D-Bus API failure: errCode[%x], \
2579 error->code, error->message);
2580 g_clear_error(&error);
2582 err = BLUETOOTH_ERROR_INTERNAL;
2584 struct gatt_char_info *char_info = NULL;
2586 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2587 if (char_info == NULL) {
2589 g_strfreev(line_argv);
2590 g_variant_builder_unref(inner_builder);
2591 g_variant_builder_unref(outer_builder);
2592 g_variant_builder_unref(invalidated_builder);
2594 return BLUETOOTH_ERROR_INVALID_DATA;
2597 char_info->value_length = value_length;
2599 value = (char *)realloc(char_info->char_value, value_length);
2600 if (value == NULL) {
2602 g_strfreev(line_argv);
2603 g_variant_builder_unref(inner_builder);
2604 g_variant_builder_unref(outer_builder);
2605 g_variant_builder_unref(invalidated_builder);
2607 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2610 char_info->char_value = (char*)value;
2611 if (char_info->char_value) {
2612 for (i = 0; i < value_length; i++)
2613 char_info->char_value[i] = char_value[i];
2618 g_strfreev(line_argv);
2619 g_variant_builder_unref(inner_builder);
2620 g_variant_builder_unref(outer_builder);
2621 g_variant_builder_unref(invalidated_builder);
2626 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2633 g_free(desc_info->desc_path);
2634 g_free(desc_info->desc_uuid);
2635 g_free(desc_info->desc_value);
2637 for (i = 0; i < desc_info->flags_length; i++)
2638 g_free(desc_info->desc_flags[i]);
2643 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2650 g_free(char_info->char_path);
2651 g_free(char_info->char_uuid);
2652 g_free(char_info->char_value);
2654 for (i = 0; i < char_info->flags_length; i++)
2655 g_free(char_info->char_flags[i]);
2660 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2665 g_free(svc_info->serv_path);
2666 g_free(svc_info->service_uuid);
2670 static void __desc_info_free(gpointer data, gpointer user_data)
2672 struct gatt_desc_info *desc_info = data;
2673 int *err = user_data;
2676 if (desc_info == NULL)
2679 ret = g_dbus_connection_unregister_object(g_conn, desc_info->desc_id);
2681 __bt_gatt_emit_interface_removed(desc_info->desc_path, GATT_DESC_INTERFACE);
2683 *err = BLUETOOTH_ERROR_INTERNAL;
2685 __bt_gatt_free_descriptor_info(desc_info);
2688 static void __char_info_free(gpointer data, gpointer user_data)
2690 struct gatt_char_info *char_info = data;
2691 int *err = user_data;
2694 if (char_info == NULL)
2697 g_slist_foreach(char_info->desc_data, __desc_info_free, user_data);
2698 g_slist_free(char_info->desc_data);
2699 char_info->desc_data = NULL;
2701 ret = g_dbus_connection_unregister_object(g_conn, char_info->char_id);
2703 __bt_gatt_emit_interface_removed(char_info->char_path, GATT_CHAR_INTERFACE);
2705 *err = BLUETOOTH_ERROR_INTERNAL;
2707 __bt_gatt_free_characteristic_info(char_info);
2710 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2712 struct gatt_service_info *svc_info;
2714 int err = BLUETOOTH_ERROR_NONE;
2716 BT_DBG("svc_path %s", svc_path);
2717 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2720 BT_ERR("Unable to find service info");
2721 return BLUETOOTH_ERROR_NOT_FOUND;
2724 err = __bt_gatt_unregister_service(svc_path);
2725 if (err != BLUETOOTH_ERROR_NONE) {
2726 BT_ERR("Could not unregister application");
2730 g_slist_foreach(svc_info->char_data, __char_info_free, &err);
2731 g_slist_free(svc_info->char_data);
2732 svc_info->char_data = NULL;
2734 ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2736 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2737 GATT_SERV_INTERFACE);
2739 err = BLUETOOTH_ERROR_INTERNAL;
2742 ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2744 BT_DBG("Unregistered the service on properties interface");
2746 /* list remove & free */
2747 gatt_services = g_slist_remove(gatt_services, svc_info);
2748 __bt_gatt_free_service_info(svc_info);
2750 new_service = FALSE;
2752 if (gatt_services == NULL)
2754 else if (gatt_services->next == NULL)
2760 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2761 int resp_state, int offset, char *value, int value_length)
2763 struct gatt_req_info *req_info = NULL;
2765 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2766 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2767 BT_ERR("Don't have aprivilege to use this API");
2768 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2771 req_info = __bt_gatt_find_request_info(request_id);
2772 if (req_info == NULL) {
2773 BT_ERR("Coundn't find request id [%d]", request_id);
2774 return BLUETOOTH_ERROR_INTERNAL;
2777 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2778 BT_ERR("resp_state is 0x%X", resp_state);
2779 char err_msg[20] = { 0, };
2780 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2781 g_dbus_method_invocation_return_dbus_error(req_info->context,
2782 "org.bluez.Error.Failed", err_msg);
2784 gatt_requests = g_slist_remove(gatt_requests, req_info);
2786 req_info->context = NULL;
2787 if (req_info->attr_path)
2788 g_free(req_info->attr_path);
2789 if (req_info->svc_path)
2790 g_free(req_info->svc_path);
2793 return BLUETOOTH_ERROR_NONE;
2796 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2798 GVariantBuilder *inner_builder = NULL;
2799 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2800 if (value_length > 0 && value != NULL) {
2801 for (i = 0; i < value_length; i++)
2802 g_variant_builder_add(inner_builder, "y", value[i]);
2804 g_dbus_method_invocation_return_value(req_info->context,
2805 g_variant_new("(ay)", inner_builder));
2806 g_variant_builder_unref(inner_builder);
2808 g_dbus_method_invocation_return_value(req_info->context, NULL);
2810 gatt_requests = g_slist_remove(gatt_requests, req_info);
2812 req_info->context = NULL;
2813 if (req_info->attr_path)
2814 g_free(req_info->attr_path);
2815 if (req_info->svc_path)
2816 g_free(req_info->svc_path);
2819 return BLUETOOTH_ERROR_NONE;
2822 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2823 bluetooth_device_address_t *unicast_address)
2825 GVariantBuilder *outer_builder;
2826 GVariantBuilder *invalidated_builder;
2827 GError *error = NULL;
2828 gboolean notify = TRUE;
2829 gboolean ret = TRUE;
2830 int err = BLUETOOTH_ERROR_NONE;
2831 gchar **line_argv = NULL;
2832 gchar *serv_path = NULL;
2833 char addr[20] = { 0 };
2835 line_argv = g_strsplit_set(char_path, "/", 0);
2836 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2838 if (!__bt_gatt_get_service_state(serv_path)) {
2839 BT_DBG("service not registered for this characteristic \n");
2841 g_strfreev(line_argv);
2842 return BLUETOOTH_ERROR_INTERNAL;
2847 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2848 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2850 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2851 g_variant_new("b", notify));
2853 if (unicast_address) {
2854 _bt_convert_addr_type_to_string(addr,
2855 (unsigned char *)unicast_address->addr);
2857 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2858 g_variant_new("s", addr));
2860 BT_DBG("Set characteristic Notification \n");
2861 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2863 "org.freedesktop.DBus.Properties",
2864 "PropertiesChanged",
2865 g_variant_new("(sa{sv}as)",
2866 "org.bluez.GattCharacteristic1",
2867 outer_builder, invalidated_builder),
2871 if (error != NULL) {
2872 BT_ERR("D-Bus API failure: errCode[%x], \
2874 error->code, error->message);
2875 g_clear_error(&error);
2877 err = BLUETOOTH_ERROR_INTERNAL;
2880 g_strfreev(line_argv);
2881 g_variant_builder_unref(outer_builder);
2882 g_variant_builder_unref(invalidated_builder);
2889 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2893 if (!is_server_started) {
2895 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2896 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2897 BT_ERR("Don't have aprivilege to use this API");
2898 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2901 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2902 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2904 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2905 in_param1, in_param2, in_param3, in_param4, &out_param);
2906 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2908 if (ret != BLUETOOTH_ERROR_NONE) {
2909 BT_ERR("Register application failed");
2912 is_server_started = true;
2914 return BLUETOOTH_ERROR_NONE;
2917 BT_INFO("Already RegisterApplication");
2918 return BLUETOOTH_ERROR_NONE;
2922 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2925 int ret = BLUETOOTH_ERROR_NONE;
2928 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2930 /* Register event handler for GATT */
2931 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2933 if (ret != BLUETOOTH_ERROR_NONE &&
2934 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2935 BT_ERR("Fail to init the event handler");
2936 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2940 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2941 in_param1, in_param2, in_param3, in_param4, &out_param);
2943 /* App ID -1 is invalid */
2944 if (ret != BLUETOOTH_ERROR_NONE) {
2945 BT_INFO("GATT Server Registration failed result [%d]", ret);
2948 *instance_id = g_array_index(out_param, int, 0);
2949 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2953 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2955 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2959 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2962 BT_INFO("GATT Server Deinitialize");
2963 /* Unregister the event */
2964 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2966 if (ret != BLUETOOTH_ERROR_NONE) {
2967 BT_ERR("Fail to deinit the event handler");
2971 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2976 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2977 int instance_id, int *service_handle)
2979 BT_CHECK_ENABLED(return);
2980 BT_CHECK_PARAMETER(svc_uuid, return);
2983 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2985 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2988 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2990 g_array_append_vals(in_param1, &type, sizeof(int));
2991 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2992 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2993 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2995 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2996 in_param1, in_param2, in_param3, in_param4, &out_param);
2998 /* ATT handle 0 is reserved, hence it can not be used by app.
2999 It will be used to indicate error in regsitering attribute */
3000 if (result != BLUETOOTH_ERROR_NONE)
3001 *service_handle = 0;
3003 *service_handle = g_array_index(out_param, int, 0);
3005 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3010 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
3011 const bluetooth_gatt_server_attribute_params_t *param,
3014 BT_CHECK_ENABLED(return);
3015 BT_CHECK_PARAMETER(char_uuid, return);
3016 BT_CHECK_PARAMETER(param, return);
3019 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
3021 char *char_flags[NUMBER_OF_FLAGS];
3023 g_strlcpy(uuid, char_uuid, sizeof(uuid));
3024 flag_count = bluetooth_gatt_convert_prop2string(param->properties, char_flags);
3025 BT_INFO("Flag count [%d]", flag_count);
3028 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3030 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
3031 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
3033 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
3034 in_param1, in_param2, in_param3, in_param4, &out_param);
3036 /* ATT handle 0 is reserved, hence it can not be used by app.
3037 It will be used to indicate error in regsitering attribute */
3038 if (result != BLUETOOTH_ERROR_NONE) {
3039 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
3042 *char_handle = g_array_index(out_param, int, 0);
3043 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
3046 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3050 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
3051 int service_handle, int instance_id, int *descriptor_handle)
3053 BT_CHECK_ENABLED(return);
3054 BT_CHECK_PARAMETER(desc_uuid, return);
3057 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
3059 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
3062 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3064 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3065 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3066 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
3067 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
3069 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
3070 in_param1, in_param2, in_param3, in_param4, &out_param);
3072 /* ATT handle 0 is reserved, hence it can not be used by app.
3073 It will be used to indicate error in regsitering attribute */
3074 if (result != BLUETOOTH_ERROR_NONE) {
3075 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
3076 *descriptor_handle = 0;
3078 *descriptor_handle = g_array_index(out_param, int, 0);
3079 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
3082 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3087 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, 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, &service_handle, sizeof(int));
3096 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3098 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
3099 in_param1, in_param2, in_param3, in_param4, &out_param);
3101 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3106 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
3107 const bluetooth_gatt_att_data_t *value)
3109 BT_CHECK_PARAMETER(param, return);
3110 BT_CHECK_PARAMETER(value, return);
3111 BT_CHECK_ENABLED(return);
3115 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3117 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
3118 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
3120 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
3121 in_param1, in_param2, in_param3, in_param4, &out_param);
3123 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3129 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
3130 const bluetooth_gatt_server_indication_params_t *param,
3131 const bluetooth_gatt_att_data_t *att_value)
3133 BT_CHECK_PARAMETER(param, return);
3134 BT_CHECK_PARAMETER(att_value, return);
3135 BT_CHECK_ENABLED(return);
3137 char addr[BLUETOOTH_ADDRESS_STRING_LENGTH] ;
3141 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3143 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
3144 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
3145 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
3147 _bt_convert_addr_type_to_string(addr, addr_hex->addr);
3148 fd = bluetooth_get_characteristic_fd(param->atrribute_handle, addr);
3151 result = bluetooth_gatt_write_characteristics_value_to_fd_(fd, att_value->data, att_value->length, NULL);
3153 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
3154 in_param1, in_param2, in_param3, in_param4, &out_param);
3156 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3161 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
3163 BT_CHECK_ENABLED(return);
3167 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3169 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3170 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3172 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
3173 in_param1, in_param2, in_param3, in_param4, &out_param);
3175 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3180 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
3182 BT_CHECK_ENABLED(return);
3186 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3188 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3189 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3191 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
3192 in_param1, in_param2, in_param3, in_param4, &out_param);
3194 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3199 /* Tizen Platform Specific */
3200 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
3201 const bluetooth_gatt_server_update_value_t *value)
3203 BT_CHECK_ENABLED(return);
3204 BT_CHECK_PARAMETER(value, return);
3208 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3210 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3211 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3213 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3214 in_param1, in_param2, in_param3, in_param4, &out_param);
3216 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3221 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3223 BT_CHECK_ENABLED(return);
3227 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3229 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3231 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3232 in_param1, in_param2, in_param3, in_param4, &out_param);
3234 if (result != BLUETOOTH_ERROR_NONE)
3235 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3237 BT_INFO("GATT Server Unregistration successful");
3239 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3244 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3245 GIOCondition cond, gpointer data)
3248 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3250 BT_INFO("FD io write data received remote adress [%s]\n", write_data->address);
3252 if (cond & G_IO_IN) {
3253 GIOStatus status = G_IO_STATUS_NORMAL;
3255 char *buffer = NULL;
3257 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3259 buffer = g_malloc0(BUF);
3261 status = g_io_channel_read_chars(gio, buffer,
3264 if (status != G_IO_STATUS_NORMAL) {
3265 BT_ERR("IO Channel read is failed with %d", status);
3268 BT_ERR("IO Channel read error [%s]", err->message);
3269 if (status == G_IO_STATUS_ERROR) {
3270 BT_ERR("cond : %d", cond);
3272 g_io_channel_shutdown(gio, TRUE, NULL);
3273 g_io_channel_unref(gio);
3284 BT_INFO(" FD io sending value changed %s %zd \n", buffer, len);
3287 bluetooth_gatt_server_write_requested_info_t write_info;
3288 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3289 memcpy(write_info.data.data, buffer, len);
3291 write_info.length = len;
3292 write_info.need_resp = false;
3293 write_info.attribute_handle = write_data->attribute_handle;
3295 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->address);
3296 write_info.connection_id = write_data->connection_id;
3297 write_info.offset = write_data->offset;
3298 write_info.request_id = -2;
3300 BT_INFO("ACQUIRING EVENT \n");
3302 bt_event_info_t *event_info;
3303 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3307 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3308 BLUETOOTH_ERROR_NONE, &write_info,
3309 event_info->cb, event_info->user_data);
3311 BT_ERR("eventinfo failed");
3321 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
3322 BT_ERR("Error : GIOCondition %d, ]", cond);
3323 g_io_channel_shutdown(gio, TRUE, NULL);
3324 g_io_channel_unref(gio);
3332 void bluetooth_gatt_server_send_acquire_write_response(GVariant * parameters)
3337 int pipefd[2] = {-1,};
3340 char err_msg[512] = {'\0'};
3341 GIOChannel *channel = NULL;
3345 g_variant_get(parameters, "(iiiiii&s)",
3354 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3355 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3356 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3357 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3360 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3361 strerror_r(errno, err_msg, sizeof(err_msg));
3362 BT_ERR("socketpair(): %s", err_msg);
3367 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3369 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3370 bluetooth_gatt_server_acquire_response_params_t data;
3371 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
3372 data.fd = pipefd[1];
3374 data.request_id = tran_id;
3376 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3378 write_info->attribute_handle = att_han;
3379 write_info->connection_id = tran_id;
3380 write_info->offset = offset;
3382 memcpy(write_info->address, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3384 BT_INFO("FD read %d remote address [%s ] \n", pipefd[0], addr);
3387 channel = g_io_channel_unix_new(pipefd[0]);
3388 g_io_channel_set_encoding(channel, NULL, NULL);
3389 g_io_channel_set_buffered(channel, FALSE);
3390 g_io_channel_set_close_on_unref(channel, TRUE);
3391 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3392 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3393 bluetooth_gatt_server_acquire_channel_write_cb, write_info);
3396 GUnixFDList *fd_list = g_unix_fd_list_new();
3397 GError *error = NULL;
3399 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3400 g_assert_no_error(error);
3403 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3405 BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3407 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE,
3408 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3410 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3416 void bluetooth_gatt_server_send_acquire_notify_response(GVariant * parameters)
3421 int pipefd[2] = {-1,};
3424 char err_msg[512] = {'\0'};
3425 GIOChannel *channel = NULL;
3428 bluetooth_gatt_acquire_notify_info_t *chr_info;
3430 g_variant_get(parameters, "(iiiiii)",
3438 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3439 BT_DBG("GATT Server Acquire notify att handle:[%d]", att_han);
3440 BT_DBG("GATT Server Acquire Notify Offset: [%d]", offset);
3443 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3444 strerror_r(errno, err_msg, sizeof(err_msg));
3445 BT_ERR("socketpair(): %s", err_msg);
3452 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3454 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3455 bluetooth_gatt_server_acquire_response_params_t data;
3456 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
3457 data.fd = pipefd[1];
3459 data.request_id = tran_id;
3461 BT_INFO("FD write %d characterstics path \n", pipefd[0]);
3463 chr_info = bluetooth_get_characteristic_info_from_path(att_han);
3465 chr_info = g_malloc0(sizeof(bluetooth_gatt_acquire_notify_info_t));
3466 chr_info->write_fd = fd;
3467 chr_info->att_hand = att_han;
3469 gatt_characteristic_server_notify_list = g_slist_append(gatt_characteristic_server_notify_list, chr_info);
3471 chr_info->write_fd = fd;
3474 channel = g_io_channel_unix_new(fd);
3475 g_io_channel_set_encoding(channel, NULL, NULL);
3476 g_io_channel_set_buffered(channel, FALSE);
3477 g_io_channel_set_close_on_unref(channel, TRUE);
3478 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3479 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
3480 bluetooth_gatt_write_channel_watch_cb, chr_info);
3485 GUnixFDList *fd_list = g_unix_fd_list_new();
3486 GError *error = NULL;
3488 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3489 g_assert_no_error(error);
3492 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3494 BT_INFO("Sending event BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE file descriptor value [%d] ", data.fd);
3496 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE,
3497 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3499 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);