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 static GDBusConnection *g_conn;
159 static guint owner_id;
160 static guint manager_id;
161 static gboolean new_service = FALSE;
162 static gboolean new_char = FALSE;
163 static int serv_id = 1;
164 static bool is_server_started = false;
166 static GCancellable *register_cancel;
168 /* Introspection data for the service we are exporting */
169 static const gchar service_introspection_xml[] =
171 " <interface name='org.freedesktop.DBus.Properties'>"
172 " <property type='s' name='UUID' access='read'>"
174 " <property type='b' name='primary' access='read'>"
176 " <property type='o' name='Device' access='read'>"
178 " <property type='ao' name='Characteristics' access='read'>"
180 " <property type='s' name='Includes' access='read'>"
185 /* Introspection data for the characteristics we are exporting */
186 static const gchar characteristics_introspection_xml[] =
188 " <interface name='org.bluez.GattCharacteristic1'>"
189 " <method name='ReadValue'>"
190 " <arg type='s' name='address' direction='in'/>"
191 " <arg type='u' name='id' direction='in'/>"
192 " <arg type='q' name='offset' direction='in'/>"
193 " <arg type='ay' name='Value' direction='out'/>"
195 " <method name='WriteValue'>"
196 " <arg type='s' name='address' direction='in'/>"
197 " <arg type='u' name='id' direction='in'/>"
198 " <arg type='q' name='offset' direction='in'/>"
199 " <arg type='b' name='response_needed' direction='in'/>"
200 " <arg type='ay' name='value' direction='in'/>"
202 " <method name='StartNotify'>"
204 " <method name='StopNotify'>"
206 " <method name='IndicateConfirm'>"
207 " <arg type='s' name='address' direction='in'/>"
208 " <arg type='b' name='complete' direction='in'/>"
211 " <interface name='org.freedesktop.DBus.Properties'>"
212 " <property type='s' name='UUID' access='read'>"
214 " <property type='o' name='Service' access='read'>"
216 " <property type='ay' name='Value' access='readwrite'>"
218 " <property type='b' name='Notifying' access='read'>"
220 " <property type='as' name='Flags' access='read'>"
222 " <property type='s' name='Unicast' access='read'>"
224 " <property type='ao' name='Descriptors' access='read'>"
229 /* Introspection data for the descriptor we are exporting */
230 static const gchar descriptor_introspection_xml[] =
232 " <interface name='org.bluez.GattDescriptor1'>"
233 " <method name='ReadValue'>"
234 " <arg type='s' name='address' direction='in'/>"
235 " <arg type='u' name='id' direction='in'/>"
236 " <arg type='q' name='offset' direction='in'/>"
237 " <arg type='ay' name='Value' direction='out'/>"
239 " <method name='WriteValue'>"
240 " <arg type='s' name='address' direction='in'/>"
241 " <arg type='u' name='id' direction='in'/>"
242 " <arg type='q' name='offset' direction='in'/>"
243 " <arg type='b' name='response_needed' direction='in'/>"
244 " <arg type='ay' name='value' direction='in'/>"
247 " <interface name='org.freedesktop.DBus.Properties'>"
248 " <property type='s' name='UUID' access='read'>"
250 " <property type='o' name='Characteristic' access='read'>"
252 " <property type='ay' name='Value' access='read'>"
254 " <property type='as' name='Flags' access='read'>"
259 static const gchar manager_introspection_xml[] =
261 " <interface name='org.freedesktop.DBus.ObjectManager'>"
262 " <method name='GetManagedObjects'>"
263 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
268 struct gatt_service_info {
274 gboolean is_svc_registered;
275 gboolean is_svc_primary;
278 struct gatt_char_info {
283 gchar *char_flags[NUMBER_OF_FLAGS];
289 struct gatt_desc_info {
294 gchar *desc_flags[NUMBER_OF_FLAGS];
299 struct gatt_req_info {
304 GDBusMethodInvocation *context;
307 static GSList *gatt_services = NULL;
308 static GSList *gatt_requests = NULL;
309 static gchar *app_path = NULL;
311 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
312 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
314 #define GATT_SERV_OBJECT_PATH "/service"
316 #define GATT_MNGR_INTERFACE "org.bluez.GattManager1"
317 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
318 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
319 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
321 #ifdef TIZEN_FEATURE_BT_HPS
322 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
323 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
324 #define PROPERTIES_CHANGED "PropertiesChanged"
325 #define BT_HPS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
328 #ifdef TIZEN_FEATURE_BT_OTP
329 #define BT_OTP_OBJECT_PATH "/org/projectx/otp"
330 #define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
331 #define PROPERTIES_CHANGED "PropertiesChanged"
332 #define BT_OTP_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
335 static GDBusProxy *manager_gproxy = NULL;
337 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
338 const char *service_path, const char *char_path);
339 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
340 const char *serv_path, const char *char_path,
341 const char *desc_path);
343 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
344 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info);
354 } bluetooth_gatt_acquire_notify_info_t;
357 static int bluetooth_get_characteristic_fd(int att_handle , char *path)
361 BT_DBG("request found path [%s] att_handle [ %d]", path, att_handle);
362 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
363 bluetooth_gatt_acquire_notify_info_t *info = l->data;
365 if (info->att_hand == att_handle)
366 return info->write_fd;
371 static bluetooth_gatt_acquire_notify_info_t * bluetooth_get_characteristic_info_from_path(int att_handle)
375 BT_DBG("request found att_handle [ %d]", att_handle);
376 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
377 bluetooth_gatt_acquire_notify_info_t *info = l->data;
378 BT_DBG(" sid [ %d]" , info->att_hand);
379 if (info->att_hand == att_handle)
386 static void bluetooth_characteristic_info_free(bluetooth_gatt_acquire_notify_info_t *chr_info)
391 static gboolean bluetooth_gatt_write_channel_watch_cb(GIOChannel *gio,
392 GIOCondition cond, gpointer data)
396 bluetooth_gatt_acquire_notify_info_t *chr_info = (bluetooth_gatt_acquire_notify_info_t *)data;
399 BT_INFO("chr_info is NULL");
403 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
404 BT_ERR("Error : GIOCondition %d, []", cond);;
405 g_io_channel_shutdown(gio, TRUE, NULL);
406 g_io_channel_unref(gio);
408 if (g_slist_find(gatt_characteristic_server_notify_list, chr_info)) {
409 BT_INFO("found char_info in the list");
410 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
411 bluetooth_characteristic_info_free(chr_info);
417 if (g_slist_find(gatt_characteristic_server_notify_list, chr_info) == NULL) {
418 BT_INFO("chr_info is not in the list");
425 static int bluetooth_gatt_write_characteristics_value_to_fd_(
426 int fd, const guint8 *value, int length,
431 int att_result = BLUETOOTH_ERROR_NONE;
433 BT_CHECK_PARAMETER(value, return);
435 written = write(fd, value, length);
436 if (written != length) {
437 att_result = BLUETOOTH_ERROR_INTERNAL;
438 BT_ERR("write data failed %d is ", written);
444 #ifdef TIZEN_FEATURE_BT_HPS
445 static int __bt_send_event_to_hps(int event, GVariant *var)
447 GError *error = NULL;
448 GVariant *parameters;
449 GDBusMessage *msg = NULL;
453 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
455 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
456 GVariantBuilder *inner_builder;
457 GVariantBuilder *invalidated_builder;
459 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
460 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
462 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
464 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
466 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
467 g_variant_builder_unref(invalidated_builder);
468 g_variant_builder_unref(inner_builder);
469 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
470 GVariantBuilder *inner_builder;
471 GVariantBuilder *invalidated_builder;
473 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
474 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
476 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
478 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
480 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
481 g_variant_builder_unref(invalidated_builder);
482 g_variant_builder_unref(inner_builder);
484 g_varaiant_unref(var);
487 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
488 g_dbus_message_set_body(msg, parameters);
489 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
491 BT_ERR("D-Bus API failure: errCode[%x], \
493 error->code, error->message);
494 g_clear_error(&error);
496 return BLUETOOTH_ERROR_INTERNAL;
498 return BLUETOOTH_ERROR_NONE;
502 #ifdef TIZEN_FEATURE_BT_OTP
503 static int __bt_send_event_to_otp(int event, GVariant *var)
505 GError *error = NULL;
506 GVariant *parameters = NULL;
507 GDBusMessage *msg = NULL;
511 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
513 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
514 GVariantBuilder *inner_builder;
515 GVariantBuilder *invalidated_builder;
517 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
518 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
520 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
522 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
524 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
525 g_variant_builder_unref(invalidated_builder);
526 g_variant_builder_unref(inner_builder);
527 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
528 GVariantBuilder *inner_builder;
529 GVariantBuilder *invalidated_builder;
531 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
532 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
534 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
536 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
538 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
539 g_variant_builder_unref(invalidated_builder);
540 g_variant_builder_unref(inner_builder);
541 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
542 GVariantBuilder *inner_builder;
543 GVariantBuilder *invalidated_builder;
545 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
546 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
548 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
550 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
552 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
553 g_variant_builder_unref(invalidated_builder);
554 g_variant_builder_unref(inner_builder);
557 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
558 g_dbus_message_set_body(msg, parameters);
559 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
561 BT_ERR("D-Bus API failure: errCode[%x], \
563 error->code, error->message);
564 g_clear_error(&error);
566 return BLUETOOTH_ERROR_INTERNAL;
568 return BLUETOOTH_ERROR_NONE;
572 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
574 const gchar *object_path,
575 const gchar *interface_name,
576 const gchar *method_name,
577 GVariant *parameters,
578 GDBusMethodInvocation *invocation,
581 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
582 BT_DBG("Getting values for service, chars and descriptors");
585 GVariantBuilder *builder = NULL;
586 GVariantBuilder *inner_builder1 = NULL;
587 GVariant *svc_char = NULL;
588 GSList *char_list = NULL;
589 GSList *desc_list = NULL;
592 builder = g_variant_builder_new(G_VARIANT_TYPE("a{oa{sa{sv}}}"));
594 /* Prepare inner builder for GattService1 interface */
595 svc_index = g_slist_length(gatt_services) - 1;
596 for (; svc_index >= 0; svc_index--) {
597 GVariantBuilder *svc_builder = NULL;
598 GVariantBuilder *inner_builder = NULL;
599 struct gatt_service_info *serv_info = NULL;
601 serv_info = g_slist_nth_data(gatt_services, svc_index);
602 if (serv_info == NULL) {
603 BT_ERR("serv_info is NULL");
607 /* Prepare inner builder for GattService1 interface */
608 BT_DBG("Creating builder for service : %s", serv_info->service_uuid);
609 svc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
610 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
612 g_variant_builder_add(inner_builder, "{sv}", "UUID",
613 g_variant_new_string(serv_info->service_uuid));
614 g_variant_builder_add(inner_builder, "{sv}", "Primary",
615 g_variant_new_boolean(serv_info->is_svc_primary));
617 /* Characteristics */
618 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
620 BT_DBG("Adding Charatarisitcs list");
621 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
622 struct gatt_char_info *char_info = char_list->data;
623 g_variant_builder_add(inner_builder1, "o", char_info->char_path);
624 BT_DBG("%s", char_info->char_path);
627 svc_char = g_variant_new("ao", inner_builder1);
628 g_variant_builder_add(inner_builder, "{sv}", "Characteristics", svc_char);
629 g_variant_builder_add(svc_builder, "{sa{sv}}", GATT_SERV_INTERFACE, inner_builder);
630 g_variant_builder_add(builder, "{oa{sa{sv}}}", serv_info->serv_path, svc_builder);
631 g_variant_builder_unref(inner_builder1);
633 /* Prepare inner builder for GattCharacteristic1 interface */
634 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
635 GVariantBuilder *char_builder = NULL;
636 GVariantBuilder *inner_builder = NULL;
637 GVariantBuilder *builder1 = NULL;
638 GVariantBuilder *builder2 = NULL;
639 GVariantBuilder *builder3 = NULL;
640 GVariant *char_val = NULL;
641 GVariant *flags_val = NULL;
642 GVariant *char_desc = NULL;
643 char *unicast = NULL;
644 gboolean notify = FALSE;
646 struct gatt_char_info *char_info = char_list->data;
648 if (char_info == NULL) {
649 BT_ERR("char_info is NULL");
653 BT_DBG("Creating builder for characteristic : %s", char_info->char_uuid);
654 char_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
655 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
658 g_variant_builder_add(inner_builder, "{sv}", "UUID",
659 g_variant_new_string(char_info->char_uuid));
662 g_variant_builder_add(inner_builder, "{sv}", "Service",
663 g_variant_new("o", serv_info->serv_path));
666 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
667 if (char_info->char_value != NULL) {
668 for (i = 0; i < char_info->value_length; i++) {
669 g_variant_builder_add(builder1, "y", char_info->char_value[i]);
671 char_val = g_variant_new("ay", builder1);
672 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
676 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
677 for (i = 0; i < char_info->flags_length; i++) {
678 g_variant_builder_add(builder2, "s", char_info->char_flags[i]);
680 flags_val = g_variant_new("as", builder2);
681 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
684 g_variant_builder_add(inner_builder, "{sv}", "Notifying", g_variant_new("b", notify));
687 unicast = g_strdup("00:00:00:00:00:00");
688 g_variant_builder_add(inner_builder, "{sv}", "Unicast", g_variant_new("s", unicast));
691 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
692 BT_DBG("Adding Descriptors list");
693 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
694 struct gatt_desc_info *desc_info = desc_list->data;
695 g_variant_builder_add(builder3, "o", desc_info->desc_path);
696 BT_DBG("%s", desc_info->desc_path);
699 char_desc = g_variant_new("ao", builder3);
700 g_variant_builder_add(inner_builder, "{sv}", "Descriptors", char_desc);
701 g_variant_builder_add(char_builder, "{sa{sv}}", GATT_CHAR_INTERFACE , inner_builder);
702 g_variant_builder_add(builder, "{oa{sa{sv}}}", char_info->char_path, char_builder);
704 /*Prepare inner builder for GattDescriptor1 interface*/
705 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
706 GVariantBuilder *desc_builder = NULL;
707 GVariantBuilder *inner_builder = NULL;
708 GVariantBuilder *builder1 = NULL;
709 GVariantBuilder *builder2 = NULL;
710 GVariant *desc_val = NULL;
711 struct gatt_desc_info *desc_info = desc_list->data;
713 if (desc_info == NULL) {
714 BT_ERR("desc_info is NULL");
718 BT_DBG("Creating builder for descriptor : %s", desc_info->desc_uuid);
719 desc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
720 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
723 g_variant_builder_add(inner_builder, "{sv}", "UUID",
724 g_variant_new_string(desc_info->desc_uuid));
727 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
728 g_variant_new("o", char_info->char_path));
731 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
732 if (desc_info->desc_value != NULL) {
733 for (i = 0; i < desc_info->value_length; i++) {
734 g_variant_builder_add(builder1, "y", desc_info->desc_value[i]);
736 desc_val = g_variant_new("ay", builder1);
737 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
741 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
742 for (i = 0; i < desc_info->flags_length; i++) {
743 g_variant_builder_add(builder2, "s", desc_info->desc_flags[i]);
745 flags_val = g_variant_new("as", builder2);
746 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
748 g_variant_builder_add(desc_builder, "{sa{sv}}", GATT_DESC_INTERFACE,
750 g_variant_builder_add(builder, "{oa{sa{sv}}}", desc_info->desc_path,
753 /* unref descriptor builder pointers */
754 g_variant_builder_unref(builder1);
755 g_variant_builder_unref(builder2);
756 g_variant_builder_unref(inner_builder);
757 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,
779 g_variant_new("(a{oa{sa{sv}}})", builder));
780 g_variant_builder_unref(builder);
784 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
788 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
789 struct gatt_service_info *serv_info = l1->data;
791 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
792 struct gatt_char_info *char_info = l2->data;
794 if (g_strcmp0(char_info->char_path, char_path) == 0)
798 BT_ERR("Gatt service not found");
802 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
804 GSList *l1, *l2, *l3;
806 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
807 struct gatt_service_info *serv_info = l1->data;
809 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
810 struct gatt_char_info *char_info = l2->data;
812 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
813 struct gatt_desc_info *desc_info = l3->data;
815 if (g_strcmp0(desc_info->desc_path, desc_path) == 0)
820 BT_ERR("Gatt service not found");
824 static void __bt_gatt_char_method_call(GDBusConnection *connection,
826 const gchar *object_path,
827 const gchar *interface_name,
828 const gchar *method_name,
829 GVariant *parameters,
830 GDBusMethodInvocation *invocation,
834 if (g_strcmp0(method_name, "ReadValue") == 0) {
838 bt_gatt_read_req_t read_req = {0, };
839 bt_user_info_t *user_info = NULL;
840 struct gatt_req_info *req_info = NULL;
841 struct gatt_service_info *svc_info = NULL;
842 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
843 GVariant *param = NULL;
846 BT_DBG("Application path = %s", object_path);
847 BT_DBG("Sender = %s", sender);
849 user_info = _bt_get_user_data(BT_COMMON);
850 if (user_info == NULL) {
851 BT_INFO("No callback is set for %s", object_path);
852 g_dbus_method_invocation_return_value(invocation, NULL);
856 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
857 if (svc_info == NULL) {
858 BT_ERR("Coudn't find service for %s", object_path);
859 g_dbus_method_invocation_return_value(invocation, NULL);
863 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
864 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
866 read_req.att_handle = (char *)object_path;
867 read_req.address = addr;
868 read_req.req_id = req_id;
869 read_req.offset = offset;
870 read_req.service_handle = svc_info->serv_path;
872 /* Store requets information */
873 req_info = g_new0(struct gatt_req_info, 1);
874 req_info->attr_path = g_strdup(object_path);
875 req_info->svc_path = g_strdup(read_req.service_handle);
876 req_info->request_id = req_id;
877 req_info->offset = offset;
878 req_info->context = invocation;
879 gatt_requests = g_slist_append(gatt_requests, req_info);
881 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
882 param = g_variant_new("(sssyq)",
884 read_req.service_handle,
888 #ifdef TIZEN_FEATURE_BT_HPS
889 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
891 #ifdef TIZEN_FEATURE_BT_OTP
892 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
896 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
897 BLUETOOTH_ERROR_NONE, &read_req,
898 user_info->cb, user_info->user_data);
900 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
901 GVariant *var = NULL;
905 gboolean response_needed = FALSE;
906 bt_gatt_value_change_t value_change = {0, };
907 bt_user_info_t *user_info = NULL;
909 struct gatt_service_info *svc_info = NULL;
910 struct gatt_req_info *req_info = NULL;
911 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
912 GVariant *param = NULL;
915 BT_DBG("WriteValue");
916 BT_DBG("Application path = %s", object_path);
917 BT_DBG("Sender = %s", sender);
919 g_variant_get(parameters, "(&suqb@ay)",
920 &addr, &req_id, &offset, &response_needed, &var);
921 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
923 user_info = _bt_get_user_data(BT_COMMON);
925 BT_INFO("No callback is set for %s", object_path);
926 g_variant_unref(var);
928 g_dbus_method_invocation_return_value(invocation, NULL);
930 g_object_unref(invocation);
934 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
935 if (svc_info == NULL) {
936 BT_ERR("Coudn't find service for %s", object_path);
937 g_variant_unref(var);
939 g_dbus_method_invocation_return_value(invocation, NULL);
941 g_object_unref(invocation);
945 value_change.att_handle = (char *)object_path;
946 value_change.address = addr;
947 value_change.service_handle = svc_info->serv_path;
948 value_change.offset = offset;
949 value_change.req_id = req_id;
950 value_change.response_needed = response_needed;
952 len = g_variant_get_size(var);
956 value_change.att_value = (guint8 *)g_malloc(len);
958 data = (char *)g_variant_get_data(var);
959 memcpy(value_change.att_value, data, len);
961 value_change.val_len = len;
963 if (response_needed) {
964 /* Store requets information */
965 req_info = g_new0(struct gatt_req_info, 1);
966 req_info->attr_path = g_strdup(object_path);
967 req_info->svc_path = g_strdup(value_change.service_handle);
968 req_info->request_id = req_id;
969 req_info->offset = offset;
970 req_info->context = invocation;
971 gatt_requests = g_slist_append(gatt_requests, req_info);
973 g_object_unref(invocation);
976 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
979 svc_path = g_strdup(svc_info->serv_path);
980 param = g_variant_new("(sssyq@ay)",
987 #ifdef TIZEN_FEATURE_BT_HPS
988 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
990 #ifdef TIZEN_FEATURE_BT_OTP
991 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
999 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1000 BLUETOOTH_ERROR_NONE, &value_change,
1001 user_info->cb, user_info->user_data);
1003 g_free(value_change.att_value);
1004 g_variant_unref(var);
1006 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1007 bt_user_info_t *user_info = NULL;
1008 bt_gatt_char_notify_change_t notify_change = {0, };
1009 #if TIZEN_FEATURE_BT_OTP
1010 GVariant *param = NULL;
1012 BT_DBG("StartNotify");
1013 user_info = _bt_get_user_data(BT_COMMON);
1014 if (user_info != NULL) {
1015 struct gatt_service_info *svc_info = NULL;
1016 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1018 notify_change.service_handle = svc_info->serv_path;
1019 notify_change.att_handle = (char *)object_path;
1020 notify_change.att_notify = TRUE;
1021 #if TIZEN_FEATURE_BT_OTP
1022 param = g_variant_new("(ssb)",
1023 notify_change.att_handle,
1024 notify_change.service_handle,
1025 notify_change.att_notify);
1026 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1028 _bt_common_event_cb(
1029 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1030 BLUETOOTH_ERROR_NONE, ¬ify_change,
1031 user_info->cb, user_info->user_data);
1034 g_object_unref(invocation);
1036 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1037 bt_user_info_t *user_info = NULL;
1038 bt_gatt_char_notify_change_t notify_change = {0, };
1039 #if TIZEN_FEATURE_BT_OTP
1040 GVariant *param = NULL;
1042 BT_DBG("StopNotify");
1043 user_info = _bt_get_user_data(BT_COMMON);
1044 if (user_info != NULL) {
1045 struct gatt_service_info *svc_info = NULL;
1046 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1048 notify_change.service_handle = svc_info->serv_path;
1049 notify_change.att_handle = (char *)object_path;
1050 notify_change.att_notify = FALSE;
1051 #if TIZEN_FEATURE_BT_OTP
1052 param = g_variant_new("(ssb)",
1053 notify_change.att_handle,
1054 notify_change.service_handle,
1055 notify_change.att_notify);
1056 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1058 _bt_common_event_cb(
1059 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1060 BLUETOOTH_ERROR_NONE, ¬ify_change,
1061 user_info->cb, user_info->user_data);
1064 g_object_unref(invocation);
1066 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1068 bt_gatt_indicate_confirm_t confirm = {0, };
1069 bt_user_info_t *user_info = NULL;
1070 gboolean complete = FALSE;
1071 struct gatt_service_info *svc_info = NULL;
1073 BT_DBG("IndicateConfirm");
1074 BT_DBG("Application path = %s", object_path);
1075 BT_DBG("Sender = %s", sender);
1077 g_variant_get(parameters, "(&sb)", &addr, &complete);
1078 BT_DBG("Remote Device address number = %s", addr);
1080 confirm.att_handle = (char *)object_path;
1081 confirm.address = addr;
1082 confirm.complete = complete;
1084 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1085 if (svc_info != NULL) {
1086 confirm.service_handle = svc_info->serv_path;
1088 user_info = _bt_get_user_data(BT_COMMON);
1089 if (user_info != NULL) {
1090 _bt_common_event_cb(
1091 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1092 BLUETOOTH_ERROR_NONE, &confirm,
1093 user_info->cb, user_info->user_data);
1098 g_dbus_method_invocation_return_value(invocation, NULL);
1101 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1102 const gchar *sender,
1103 const gchar *object_path,
1104 const gchar *interface_name,
1105 const gchar *method_name,
1106 GVariant *parameters,
1107 GDBusMethodInvocation *invocation,
1110 if (g_strcmp0(method_name, "ReadValue") == 0) {
1114 bt_gatt_read_req_t read_req = {0, };
1115 bt_user_info_t *user_info = NULL;
1116 struct gatt_req_info *req_info = NULL;
1117 struct gatt_service_info *svc_info = NULL;
1119 BT_DBG("ReadValue");
1120 BT_DBG("Application path = %s", object_path);
1121 BT_DBG("Sender = %s", sender);
1123 user_info = _bt_get_user_data(BT_COMMON);
1124 if (user_info == NULL) {
1125 BT_INFO("No callback is set for %s", object_path);
1126 g_dbus_method_invocation_return_value(invocation, NULL);
1130 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1131 if (svc_info == NULL) {
1132 BT_ERR("Coudn't find service for %s", object_path);
1133 g_dbus_method_invocation_return_value(invocation, NULL);
1137 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1138 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1140 read_req.att_handle = (char *)object_path;
1141 read_req.address = addr;
1142 read_req.req_id = req_id;
1143 read_req.offset = offset;
1144 read_req.service_handle = svc_info->serv_path;
1146 /* Store requets information */
1147 req_info = g_new0(struct gatt_req_info, 1);
1148 req_info->attr_path = g_strdup(object_path);
1149 req_info->svc_path = g_strdup(read_req.service_handle);
1150 req_info->request_id = req_id;
1151 req_info->offset = offset;
1152 req_info->context = invocation;
1153 gatt_requests = g_slist_append(gatt_requests, req_info);
1155 _bt_common_event_cb(
1156 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1157 BLUETOOTH_ERROR_NONE, &read_req,
1158 user_info->cb, user_info->user_data);
1161 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1162 GVariant *var = NULL;
1166 gboolean response_needed = FALSE;
1167 bt_gatt_value_change_t value_change = {0, };
1168 bt_user_info_t *user_info = NULL;
1170 struct gatt_service_info *svc_info = NULL;
1171 struct gatt_req_info *req_info = NULL;
1173 BT_DBG("WriteValue");
1174 BT_DBG("Application path = %s", object_path);
1175 BT_DBG("Sender = %s", sender);
1177 g_variant_get(parameters, "(&suqb@ay)",
1178 &addr, &req_id, &offset, &response_needed, &var);
1179 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1181 user_info = _bt_get_user_data(BT_COMMON);
1182 if (user_info == NULL) {
1183 BT_INFO("No callback is set for %s", object_path);
1184 g_variant_unref(var);
1185 if (response_needed)
1186 g_dbus_method_invocation_return_value(invocation, NULL);
1188 g_object_unref(invocation);
1192 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1193 if (svc_info == NULL) {
1194 BT_ERR("Coudn't find service for %s", object_path);
1195 g_variant_unref(var);
1196 if (response_needed)
1197 g_dbus_method_invocation_return_value(invocation, NULL);
1199 g_object_unref(invocation);
1203 value_change.att_handle = (char *)object_path;
1204 value_change.address = addr;
1205 value_change.service_handle = svc_info->serv_path;
1206 value_change.offset = offset;
1207 value_change.req_id = req_id;
1208 value_change.response_needed = response_needed;
1210 len = g_variant_get_size(var);
1214 value_change.att_value = (guint8 *)g_malloc(len);
1216 data = (char *)g_variant_get_data(var);
1217 memcpy(value_change.att_value, data, len);
1219 value_change.val_len = len;
1221 if (response_needed) {
1222 /* Store requets information */
1223 req_info = g_new0(struct gatt_req_info, 1);
1224 req_info->attr_path = g_strdup(object_path);
1225 req_info->svc_path = g_strdup(value_change.service_handle);
1226 req_info->request_id = req_id;
1227 req_info->offset = offset;
1228 req_info->context = invocation;
1229 gatt_requests = g_slist_append(gatt_requests, req_info);
1231 g_object_unref(invocation);
1234 _bt_common_event_cb(
1235 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1236 BLUETOOTH_ERROR_NONE, &value_change,
1237 user_info->cb, user_info->user_data);
1239 g_free(value_change.att_value);
1240 g_variant_unref(var);
1245 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1248 GError *error = NULL;
1249 GVariantBuilder *array_builder;
1251 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1252 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1253 g_variant_builder_add(array_builder, "s", interface);
1255 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1256 "org.freedesktop.Dbus.Objectmanager",
1257 "InterfacesRemoved",
1258 g_variant_new("(oas)",
1259 object_path, array_builder),
1263 if (error != NULL) {
1264 /* dbus gives error cause */
1265 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1266 error->code, error->message);
1267 g_clear_error(&error);
1270 g_variant_builder_unref(array_builder);
1275 static const GDBusInterfaceVTable desc_interface_vtable = {
1276 __bt_gatt_desc_method_call,
1282 static const GDBusInterfaceVTable char_interface_vtable = {
1283 __bt_gatt_char_method_call,
1289 static const GDBusInterfaceVTable serv_interface_vtable = {
1296 static const GDBusInterfaceVTable manager_interface_vtable = {
1297 __bt_gatt_manager_method_call,
1303 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1304 const gchar *introspection_data)
1307 GDBusNodeInfo *node_info = NULL;
1309 if (introspection_data == NULL)
1313 BT_DBG("Create new node info");
1314 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1317 BT_ERR("Unable to create node: %s", err->message);
1318 g_clear_error(&err);
1325 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1326 const char *service_path)
1330 for (l = gatt_services; l != NULL; l = l->next) {
1331 struct gatt_service_info *info = l->data;
1333 if (g_strcmp0(info->serv_path, service_path) == 0)
1336 BT_ERR("Gatt service not found");
1340 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1341 const char *service_path, const char *char_path)
1345 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1346 struct gatt_service_info *serv_info = l1->data;
1348 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1350 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1351 struct gatt_char_info *char_info = l2->data;
1353 if (g_strcmp0(char_info->char_path, char_path) == 0)
1356 BT_ERR("Gatt characteristic not found");
1360 BT_ERR("Gatt service not found");
1364 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1365 const char *serv_path, const char *char_path,
1366 const char *desc_path)
1368 GSList *l1, *l2, *l3;
1370 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1371 struct gatt_service_info *serv_info = l1->data;
1373 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1374 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1375 struct gatt_char_info *char_info = l2->data;
1377 if (g_strcmp0(char_info->char_path, char_path) == 0) {
1378 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1379 struct gatt_desc_info *desc_info = l3->data;
1380 if (g_strcmp0(desc_info->desc_path,
1389 BT_ERR("Gatt descriptor not found");
1393 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1397 for (l = gatt_requests; l != NULL; l = l->next) {
1398 struct gatt_req_info *req_info = l->data;
1400 if (req_info && req_info->request_id == request_id)
1403 BT_ERR("Gatt Request not found");
1407 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1408 const gchar *path, const gchar *interface)
1413 g_conn = _bt_get_system_shared_conn();
1415 BT_ERR("Unable to get connection");
1419 proxy = g_dbus_proxy_new_sync(g_conn,
1420 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1422 interface, NULL, &err);
1426 BT_ERR("Unable to create proxy: %s", err->message);
1427 g_clear_error(&err);
1431 manager_gproxy = proxy;
1436 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1437 const gchar *path, const gchar *interface)
1439 return (manager_gproxy) ? manager_gproxy :
1440 __bt_gatt_gdbus_init_manager_proxy(service,
1444 static gboolean __bt_gatt_is_service_registered(const char *service_path)
1446 struct gatt_service_info *svc_info = NULL;
1448 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1450 if (svc_info != NULL) {
1451 BT_DBG("Return the state of the gatt service %d",
1452 svc_info->is_svc_registered);
1453 return svc_info->is_svc_registered;
1456 BT_DBG("gatt service info is NULL");
1460 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1462 GError *error = NULL;
1464 GVariantIter *iter = NULL;
1465 const gchar *key = NULL;
1466 GVariant *value = NULL;
1467 const gchar *service = NULL;
1468 const gchar *characteristic = NULL;
1469 const gchar *descriptor = NULL;
1473 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1475 if (result == NULL) {
1476 BT_ERR("Dbus-RPC is failed");
1477 if (error != NULL) {
1478 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1479 error->code, error->message);
1480 g_clear_error(&error);
1483 char *char_cmp = NULL;
1484 g_variant_get(result, "(a{sv})", &iter);
1485 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1487 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1488 if (g_strcmp0(key, "Service") == 0) {
1489 service = g_variant_get_string(value, NULL);
1490 BT_DBG("Service %s", service);
1491 } else if (g_strcmp0(key, char_cmp) == 0) {
1492 characteristic = g_variant_get_string(value, NULL);
1494 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1495 BT_DBG("%s", characteristic);
1496 } else if (g_strcmp0(key, "Descriptor") == 0) {
1497 descriptor = g_variant_get_string(value, NULL);
1498 BT_DBG("Descriptor %s", descriptor);
1501 g_variant_iter_free(iter);
1503 /* TODO: Store the service informationa and
1504 * Send respponse to CAPI layer. */
1506 g_variant_unref(result);
1511 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1513 BT_INFO("RegisterApplication is completed");
1515 GError *error = NULL;
1518 if (register_cancel) {
1519 g_object_unref(register_cancel);
1520 register_cancel = NULL;
1523 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1524 if (result == NULL) {
1525 BT_ERR("Dbus-RPC is failed");
1526 if (error != NULL) {
1527 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1528 error->code, error->message);
1529 g_clear_error(&error);
1531 is_server_started = false;
1533 g_variant_unref(result);
1537 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1539 GDBusProxy *proxy = NULL;
1541 if (is_server_started) {
1545 if (app_path == NULL) {
1546 BT_ERR("app_path is NULL");
1547 return BLUETOOTH_ERROR_INTERNAL;
1550 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1551 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1552 if (proxy == NULL) {
1553 BT_ERR("proxy is NULL");
1554 return BLUETOOTH_ERROR_INTERNAL;
1557 BT_INFO("UnregisterApplication");
1559 /* Async Call to Unregister Service */
1560 ret = g_dbus_proxy_call_sync(proxy, "UnregisterApplication",
1561 g_variant_new("(o)", app_path), G_DBUS_CALL_FLAGS_NONE, -1,
1564 BT_ERR("dBUS-RPC is failed");
1566 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1567 err->code, err->message);
1568 if (err->code == G_DBUS_ERROR_SERVICE_UNKNOWN ||
1569 g_strrstr(err->message, BT_ERROR_DOES_NOT_EXIST)) {
1570 g_clear_error(&err);
1573 g_clear_error(&err);
1575 return BLUETOOTH_ERROR_INTERNAL;
1577 g_variant_unref(ret);
1580 is_server_started = false;
1582 BT_INFO("UnregisterApplication is completed");
1584 return BLUETOOTH_ERROR_NONE;
1587 BT_INFO("GATT server not started");
1588 return BLUETOOTH_ERROR_NONE;
1591 BT_EXPORT_API int bluetooth_gatt_init(void)
1593 GError *error = NULL;
1594 GDBusNodeInfo *node_info = NULL;
1596 if (app_path != NULL) {
1597 BT_ERR("app path already exists! initialized");
1598 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1601 g_conn = _bt_get_system_shared_conn();
1603 BT_ERR("Unable to get connection");
1607 if (owner_id == 0) {
1608 gchar *name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
1609 BT_DBG("well-known name: %s", name);
1611 owner_id = g_bus_own_name_on_connection(g_conn, name,
1612 G_BUS_NAME_OWNER_FLAGS_NONE,
1613 NULL, NULL, NULL, NULL);
1616 BT_DBG("owner_id is [%d]", owner_id);
1618 app_path = g_strdup_printf("/com/%d", getpid());
1622 /* Register ObjectManager interface */
1623 node_info = __bt_gatt_create_method_node_info(
1624 manager_introspection_xml);
1625 if (node_info == NULL) {
1626 BT_ERR("failed to get node info");
1630 if (manager_id == 0) {
1631 BT_INFO("manager_id does not exists");
1633 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1634 node_info->interfaces[0],
1635 &manager_interface_vtable,
1636 NULL, NULL, &error);
1638 g_dbus_node_info_unref(node_info);
1639 if (manager_id == 0) {
1640 BT_ERR("failed to register: %s", error->message);
1641 g_error_free(error);
1645 return BLUETOOTH_ERROR_NONE;
1649 g_bus_unown_name(owner_id);
1656 return BLUETOOTH_ERROR_INTERNAL;
1659 BT_EXPORT_API int bluetooth_gatt_deinit()
1661 int ret = BLUETOOTH_ERROR_NONE;
1663 if (register_cancel) {
1664 g_cancellable_cancel(register_cancel);
1665 g_object_unref(register_cancel);
1666 register_cancel = NULL;
1669 if (owner_id == 0) {
1670 BT_ERR("owner_id is zero");
1671 return BLUETOOTH_ERROR_NOT_FOUND;
1674 BT_DBG("Removing all registered gatt services");
1675 bluetooth_gatt_delete_services();
1677 /* Unregister the exported interface for object manager */
1679 g_dbus_connection_unregister_object(g_conn, manager_id);
1683 ret = bluetooth_gatt_unregister_application();
1684 if (ret != BLUETOOTH_ERROR_NONE) {
1685 BT_ERR("Fail to unregister application");
1688 g_bus_unown_name(owner_id);
1694 if (manager_gproxy) {
1695 g_object_unref(manager_gproxy);
1696 manager_gproxy = NULL;
1703 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1706 GError *error = NULL;
1708 GDBusNodeInfo *node_info;
1710 GVariantBuilder *builder = NULL;
1711 GVariantBuilder *builder1 = NULL;
1712 GVariantBuilder *inner_builder = NULL;
1713 gboolean svc_primary = TRUE;
1714 struct gatt_service_info *serv_info = NULL;
1716 node_info = __bt_gatt_create_method_node_info(
1717 service_introspection_xml);
1718 if (node_info == NULL)
1719 return BLUETOOTH_ERROR_INTERNAL;
1721 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1722 BT_DBG("gatt service path is [%s]", path);
1724 object_id = g_dbus_connection_register_object(g_conn, path,
1725 node_info->interfaces[0],
1726 &serv_interface_vtable,
1727 NULL, NULL, &error);
1728 g_dbus_node_info_unref(node_info);
1730 if (object_id == 0) {
1731 BT_ERR("failed to register: %s", error->message);
1732 g_error_free(error);
1735 return BLUETOOTH_ERROR_INTERNAL;
1738 /* Add object_id/gatt service information; it's required at the time of
1739 * service unregister and Getmanagedobjects
1741 serv_info = g_new0(struct gatt_service_info, 1);
1743 serv_info->serv_path = g_strdup(path);
1744 serv_info->serv_id = object_id;
1745 serv_info->service_uuid = g_strdup(svc_uuid);
1746 serv_info->is_svc_registered = FALSE;
1747 serv_info->is_svc_primary = svc_primary;
1749 gatt_services = g_slist_append(gatt_services, serv_info);
1751 /* emit interfacesadded signal here for service path */
1752 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1753 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1755 g_variant_builder_add(inner_builder, "{sv}",
1756 "UUID", g_variant_new_string(svc_uuid));
1758 g_variant_builder_add(inner_builder, "{sv}",
1759 "Primary", g_variant_new_boolean(svc_primary));
1761 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1763 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1764 g_variant_new("ao", builder1));
1766 g_variant_builder_add(builder, "{sa{sv}}",
1767 GATT_SERV_INTERFACE, inner_builder);
1769 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1770 "org.freedesktop.Dbus.ObjectManager",
1772 g_variant_new("(oa{sa{sv}})",
1775 if (error != NULL) {
1776 /* dbus gives error cause */
1777 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1778 error->code, error->message);
1779 g_clear_error(&error);
1784 *svc_path = g_strdup(path);
1787 g_variant_builder_unref(inner_builder);
1788 g_variant_builder_unref(builder);
1789 g_variant_builder_unref(builder1);
1791 return BLUETOOTH_ERROR_NONE;
1794 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1795 const char *svc_path, const char *char_uuid,
1796 bt_gatt_permission_t permissions,
1797 bt_gatt_characteristic_property_t properties,
1801 GError *error = NULL;
1803 GDBusNodeInfo *node_info;
1805 GVariantBuilder *builder = NULL;
1806 GVariantBuilder *inner_builder = NULL;
1807 struct gatt_service_info *serv_info = NULL;
1808 struct gatt_char_info *char_info = NULL;
1809 GVariantBuilder *builder2 = NULL;
1810 GVariantBuilder *builder3 = NULL;
1811 GVariant *flags_val = NULL;
1813 char *char_flags[NUMBER_OF_FLAGS];
1818 new_service = FALSE;
1821 BT_DBG("gatt svc_path path is [%s]", svc_path);
1822 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1823 if (serv_info == NULL)
1824 return BLUETOOTH_ERROR_INVALID_PARAM;
1826 node_info = __bt_gatt_create_method_node_info(
1827 characteristics_introspection_xml);
1828 if (node_info == NULL)
1829 return BLUETOOTH_ERROR_INTERNAL;
1831 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1832 BT_DBG("gatt characteristic path is [%s]", path);
1834 object_id = g_dbus_connection_register_object(g_conn, path,
1835 node_info->interfaces[0],
1836 &char_interface_vtable,
1837 NULL, NULL, &error);
1838 g_dbus_node_info_unref(node_info);
1840 if (object_id == 0) {
1841 BT_ERR("failed to register: %s", error->message);
1842 g_error_free(error);
1845 return BLUETOOTH_ERROR_INTERNAL;
1848 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1849 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1850 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1851 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1852 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1853 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1854 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1855 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1857 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1859 char_info = g_new0(struct gatt_char_info, 1);
1861 char_info->char_path = g_strdup(path);
1862 char_info->char_id = object_id;
1863 char_info->char_uuid = g_strdup(char_uuid);
1865 for (i = 0; i < flag_count; i++)
1866 char_info->char_flags[i] = char_flags[i];
1869 char_info->flags_length = flag_count;
1871 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1873 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1874 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1876 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1877 g_variant_new("s", char_uuid));
1878 g_variant_builder_add(inner_builder, "{sv}", "Service",
1879 g_variant_new("o", svc_path));
1881 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1883 for (i = 0; i < flag_count; i++)
1884 g_variant_builder_add(builder2, "s", char_flags[i]);
1886 flags_val = g_variant_new("as", builder2);
1887 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1890 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1892 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1893 g_variant_new("ao", builder3));
1895 g_variant_builder_add(builder, "{sa{sv}}",
1896 GATT_CHAR_INTERFACE,
1899 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1900 "org.freedesktop.Dbus.ObjectManager",
1902 g_variant_new("(oa{sa{sv}})",
1906 /* dBUS gives error cause */
1907 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1908 error->code, error->message);
1909 g_clear_error(&error);
1912 *char_path = g_strdup(path);
1918 g_variant_builder_unref(inner_builder);
1919 g_variant_builder_unref(builder);
1920 g_variant_builder_unref(builder2);
1921 g_variant_builder_unref(builder3);
1923 return BLUETOOTH_ERROR_NONE;
1926 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1927 const char *characteristic, const char *char_value,
1930 gchar **line_argv = NULL;
1931 char *serv_path = NULL;
1932 struct gatt_char_info *char_info = NULL;
1933 GVariantBuilder *builder1 = NULL;
1934 GVariantBuilder *builder = NULL;
1935 GVariantBuilder *inner_builder = NULL;
1936 GVariant *char_val = NULL;
1937 GError *error = NULL;
1939 int res = BLUETOOTH_ERROR_NONE;
1941 line_argv = g_strsplit_set(characteristic, "/", 0);
1942 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1944 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1946 if (char_info == NULL) {
1947 /* Fix : RESOURCE_LEAK */
1948 res = BLUETOOTH_ERROR_INVALID_PARAM;
1952 char_info->value_length = value_length;
1954 char_info->char_value = (char *)malloc(value_length);
1955 /* Fix : NULL_RETURNS */
1956 if (char_info->char_value == NULL) {
1957 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1961 for (i = 0; i < value_length; i++)
1962 char_info->char_value[i] = char_value[i];
1964 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1965 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1967 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1969 for (i = 0; i < value_length; i++)
1970 g_variant_builder_add(builder1, "y", char_value[i]);
1972 char_val = g_variant_new("ay", builder1);
1973 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1975 g_variant_builder_add(builder, "{sa{sv}}",
1976 GATT_CHAR_INTERFACE,
1979 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1980 "org.freedesktop.Dbus.ObjectManager",
1982 g_variant_new("(oa{sa{sv}})",
1983 char_info->char_path, builder),
1987 /* dBUS gives error cause */
1988 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1989 error->code, error->message);
1990 g_clear_error(&error);
1992 g_variant_builder_unref(inner_builder);
1993 g_variant_builder_unref(builder);
1994 g_variant_builder_unref(builder1);
1996 g_strfreev(line_argv);
2002 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2003 const char *char_path, const char *desc_uuid,
2004 bt_gatt_permission_t permissions,
2007 static int desc_id = 1;
2008 GError *error = NULL;
2010 GDBusNodeInfo *node_info;
2012 GVariantBuilder *builder = NULL;
2013 GVariantBuilder *inner_builder = NULL;
2014 struct gatt_char_info *char_info = NULL;
2015 struct gatt_desc_info *desc_info = NULL;
2016 gchar **line_argv = NULL;
2018 GVariantBuilder *builder2 = NULL;
2019 GVariant *flags_val = NULL;
2021 char *desc_flags[NUMBER_OF_FLAGS];
2029 line_argv = g_strsplit_set(char_path, "/", 0);
2030 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2032 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2033 if (char_info == NULL) {
2034 g_strfreev(line_argv);
2036 return BLUETOOTH_ERROR_INVALID_PARAM;
2039 node_info = __bt_gatt_create_method_node_info(
2040 descriptor_introspection_xml);
2041 if (node_info == NULL) {
2042 g_strfreev(line_argv);
2044 return BLUETOOTH_ERROR_INTERNAL;
2047 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2048 BT_DBG("gatt descriptor path is [%s]", path);
2050 object_id = g_dbus_connection_register_object(g_conn, path,
2051 node_info->interfaces[0],
2052 &desc_interface_vtable,
2053 NULL, NULL, &error);
2054 g_dbus_node_info_unref(node_info);
2056 if (object_id == 0) {
2057 BT_ERR("failed to register: %s", error->message);
2058 g_error_free(error);
2060 g_strfreev(line_argv);
2063 return BLUETOOTH_ERROR_INTERNAL;
2066 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2068 desc_info = g_new0(struct gatt_desc_info, 1);
2070 desc_info->desc_path = g_strdup(path);
2071 desc_info->desc_id = object_id;
2072 desc_info->desc_uuid = g_strdup(desc_uuid);
2074 for (i = 0; i < flag_count; i++)
2075 desc_info->desc_flags[i] = desc_flags[i];
2077 desc_info->flags_length = flag_count;
2079 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2081 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2082 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2084 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2085 g_variant_new("s", desc_uuid));
2086 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2087 g_variant_new("o", char_path));
2089 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2091 for (i = 0; i < flag_count; i++)
2092 g_variant_builder_add(builder2, "s", desc_flags[i]);
2094 flags_val = g_variant_new("as", builder2);
2095 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2098 g_variant_builder_add(builder, "{sa{sv}}",
2099 GATT_DESC_INTERFACE,
2102 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2103 "org.freedesktop.Dbus.ObjectManager",
2105 g_variant_new("(oa{sa{sv}})",
2109 /* dBUS gives error cause */
2110 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2111 error->code, error->message);
2112 g_clear_error(&error);
2115 *desc_path = g_strdup(path);
2119 g_strfreev(line_argv);
2120 g_variant_builder_unref(inner_builder);
2121 g_variant_builder_unref(builder);
2122 g_variant_builder_unref(builder2);
2124 return BLUETOOTH_ERROR_NONE;
2127 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2128 const char *desc_path, const char *desc_value,
2131 GError *error = NULL;
2132 GVariantBuilder *builder = NULL;
2133 GVariantBuilder *inner_builder = NULL;
2134 GVariantBuilder *builder1 = NULL;
2135 struct gatt_desc_info *desc_info = NULL;
2136 gchar **line_argv = NULL;
2138 GVariant *desc_val = NULL;
2139 char *serv_path = NULL;
2142 line_argv = g_strsplit_set(desc_path, "/", 0);
2143 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2144 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2146 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2148 /* Free the allocated memory */
2149 g_strfreev(line_argv);
2153 /* Fix : NULL_RETURNS */
2154 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2156 desc_info->desc_value = (char *)malloc(value_length);
2158 /* Fix : NULL_RETURNS */
2159 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2161 for (i = 0; i < value_length; i++)
2162 desc_info->desc_value[i] = desc_value[i];
2164 desc_info->value_length = value_length;
2166 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2167 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2169 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2171 for (i = 0; i < value_length; i++)
2172 g_variant_builder_add(builder1, "y", desc_value[i]);
2174 desc_val = g_variant_new("ay", builder1);
2175 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2177 g_variant_builder_add(builder, "{sa{sv}}",
2178 GATT_DESC_INTERFACE,
2181 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2182 "org.freedesktop.Dbus.ObjectManager",
2184 g_variant_new("(oa{sa{sv}})",
2185 desc_info->desc_path, builder),
2188 if (error != NULL) {
2189 BT_ERR("D-Bus API failure: errCode[%x], \
2191 error->code, error->message);
2192 g_clear_error(&error);
2195 g_variant_builder_unref(inner_builder);
2196 g_variant_builder_unref(builder);
2197 g_variant_builder_unref(builder1);
2199 return BLUETOOTH_ERROR_NONE;
2202 int bluetooth_gatt_get_service(const char *svc_uuid)
2204 GDBusProxy *proxy = NULL;
2207 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2208 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2210 return BLUETOOTH_ERROR_INTERNAL;
2212 uuid = g_strdup(svc_uuid);
2214 g_dbus_proxy_call(proxy,
2216 g_variant_new("(s)",
2218 G_DBUS_CALL_FLAGS_NONE, -1,
2220 (GAsyncReadyCallback) get_service_cb,
2225 return BLUETOOTH_ERROR_NONE;
2228 BT_EXPORT_API int bluetooth_gatt_register_service(const char *svc_path)
2230 struct gatt_service_info *svc_info = NULL;
2232 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2233 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2234 BT_ERR("Don't have aprivilege to use this API");
2235 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2238 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2239 if (svc_info == NULL) {
2240 BT_ERR("Cannot find service [%s]", svc_path);
2241 return BLUETOOTH_ERROR_INTERNAL;
2243 svc_info->is_svc_registered = TRUE;
2245 return BLUETOOTH_ERROR_NONE;
2248 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2250 GDBusProxy *proxy = NULL;
2252 if (!is_server_started) {
2253 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2254 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2255 BT_ERR("Don't have aprivilege to use this API");
2256 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2259 if (g_slist_length(gatt_services) == 0) {
2260 BT_ERR("There is no registered service");
2261 return BLUETOOTH_ERROR_INTERNAL;
2264 if (app_path == NULL) {
2265 BT_ERR("app_path is NULL");
2266 return BLUETOOTH_ERROR_INTERNAL;
2269 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2270 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2271 if (proxy == NULL) {
2272 BT_ERR("proxy is NULL");
2273 return BLUETOOTH_ERROR_INTERNAL;
2276 BT_INFO("RegisterApplication");
2278 if (register_cancel) {
2279 g_cancellable_cancel(register_cancel);
2280 g_object_unref(register_cancel);
2282 register_cancel = g_cancellable_new();
2284 g_dbus_proxy_call(proxy, "RegisterApplication",
2285 g_variant_new("(oa{sv})", app_path, NULL),
2286 G_DBUS_CALL_FLAGS_NONE, -1, register_cancel,
2287 (GAsyncReadyCallback)register_application_cb, NULL);
2289 is_server_started = true;
2291 return BLUETOOTH_ERROR_NONE;
2294 BT_INFO("Already RegisterApplication");
2296 return BLUETOOTH_ERROR_NONE;
2299 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2302 int ret = BLUETOOTH_ERROR_NONE;
2304 if (gatt_services == NULL) {
2305 BT_DBG("There are no registered services");
2310 for (l = gatt_services; l != NULL; ) {
2311 struct gatt_service_info *info = l->data;
2313 // In __bt_gatt_unregister_service, current node will be removed.
2314 // Go forward to next node before calling __bt_gatt_unregister_service.
2316 if (__bt_gatt_unregister_service(info) != BLUETOOTH_ERROR_NONE) {
2317 ret = BLUETOOTH_ERROR_INTERNAL;
2320 BT_INFO("All services are removed : %d", ret);
2322 g_slist_free(gatt_services);
2323 gatt_services = NULL;
2329 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2330 const char *char_path, const char* char_value,
2333 GVariantBuilder *outer_builder;
2334 GVariantBuilder *inner_builder;
2335 GVariantBuilder *invalidated_builder;
2336 GVariant *update_value = NULL;
2337 GError *error = NULL;
2338 gboolean ret = FALSE;
2339 int err = BLUETOOTH_ERROR_NONE;
2341 gchar **line_argv = NULL;
2342 gchar *serv_path = NULL;
2343 const char *value = NULL;
2345 line_argv = g_strsplit_set(char_path, "/", 0);
2346 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2348 if (!__bt_gatt_is_service_registered(serv_path)) {
2349 BT_DBG("service not registered for this characteristic");
2351 g_strfreev(line_argv);
2352 return BLUETOOTH_ERROR_INTERNAL;
2355 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2356 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2358 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2359 for (i = 0; i < value_length; i++)
2360 g_variant_builder_add(inner_builder, "y", char_value[i]);
2362 update_value = g_variant_new("ay", inner_builder);
2364 g_variant_builder_add(outer_builder, "{sv}", "Value",
2367 BT_DBG("Updating characteristic value");
2368 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2370 "org.freedesktop.DBus.Properties",
2371 "PropertiesChanged",
2372 g_variant_new("(sa{sv}as)",
2373 "org.bluez.GattCharacteristic1",
2374 outer_builder, invalidated_builder),
2378 if (error != NULL) {
2379 BT_ERR("D-Bus API failure: errCode[%x], \
2381 error->code, error->message);
2382 g_clear_error(&error);
2384 err = BLUETOOTH_ERROR_INTERNAL;
2386 struct gatt_char_info *char_info = NULL;
2388 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2389 if (char_info == NULL) {
2391 g_strfreev(line_argv);
2392 g_variant_builder_unref(inner_builder);
2393 g_variant_builder_unref(outer_builder);
2394 g_variant_builder_unref(invalidated_builder);
2396 return BLUETOOTH_ERROR_INVALID_DATA;
2399 char_info->value_length = value_length;
2401 value = (char *)realloc(char_info->char_value, value_length);
2402 if (value == NULL) {
2404 g_strfreev(line_argv);
2405 g_variant_builder_unref(inner_builder);
2406 g_variant_builder_unref(outer_builder);
2407 g_variant_builder_unref(invalidated_builder);
2409 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2412 char_info->char_value = (char*)value;
2413 if (char_info->char_value) {
2414 for (i = 0; i < value_length; i++)
2415 char_info->char_value[i] = char_value[i];
2420 g_strfreev(line_argv);
2421 g_variant_builder_unref(inner_builder);
2422 g_variant_builder_unref(outer_builder);
2423 g_variant_builder_unref(invalidated_builder);
2428 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2435 g_free(desc_info->desc_path);
2436 g_free(desc_info->desc_uuid);
2437 g_free(desc_info->desc_value);
2439 for (i = 0; i < desc_info->flags_length; i++)
2440 g_free(desc_info->desc_flags[i]);
2445 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2452 g_free(char_info->char_path);
2453 g_free(char_info->char_uuid);
2454 g_free(char_info->char_value);
2456 for (i = 0; i < char_info->flags_length; i++)
2457 g_free(char_info->char_flags[i]);
2462 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2467 g_free(svc_info->serv_path);
2468 g_free(svc_info->service_uuid);
2472 static void __desc_info_free(gpointer data, gpointer user_data)
2474 struct gatt_desc_info *desc_info = data;
2475 int *err = user_data;
2478 if (desc_info == NULL)
2481 ret = g_dbus_connection_unregister_object(g_conn, desc_info->desc_id);
2483 __bt_gatt_emit_interface_removed(desc_info->desc_path, GATT_DESC_INTERFACE);
2485 *err = BLUETOOTH_ERROR_INTERNAL;
2487 __bt_gatt_free_descriptor_info(desc_info);
2490 static void __char_info_free(gpointer data, gpointer user_data)
2492 struct gatt_char_info *char_info = data;
2493 int *err = user_data;
2496 if (char_info == NULL)
2499 g_slist_foreach(char_info->desc_data, __desc_info_free, user_data);
2500 g_slist_free(char_info->desc_data);
2501 char_info->desc_data = NULL;
2503 ret = g_dbus_connection_unregister_object(g_conn, char_info->char_id);
2505 __bt_gatt_emit_interface_removed(char_info->char_path, GATT_CHAR_INTERFACE);
2507 *err = BLUETOOTH_ERROR_INTERNAL;
2509 __bt_gatt_free_characteristic_info(char_info);
2512 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info)
2514 int ret = BLUETOOTH_ERROR_NONE;
2516 if (svc_info == NULL) {
2517 BT_ERR("svc_info is NULL");
2518 return BLUETOOTH_ERROR_NOT_FOUND;
2521 if (svc_info->is_svc_registered == FALSE) {
2522 BT_ERR("%s is not registered", svc_info->serv_path);
2523 return BLUETOOTH_ERROR_NOT_FOUND;
2526 BT_DBG("svc_path %s", svc_info->serv_path);
2528 g_slist_foreach(svc_info->char_data, __char_info_free, &ret);
2529 g_slist_free(svc_info->char_data);
2530 svc_info->char_data = NULL;
2532 if (g_dbus_connection_unregister_object(g_conn, svc_info->serv_id) == FALSE) {
2533 BT_ERR("Cannot unregister object for [%s]", svc_info->serv_path);
2534 ret = BLUETOOTH_ERROR_INTERNAL;
2536 __bt_gatt_emit_interface_removed(svc_info->serv_path, GATT_SERV_INTERFACE);
2539 gatt_services = g_slist_remove(gatt_services, svc_info);
2540 __bt_gatt_free_service_info(svc_info);
2542 new_service = FALSE;
2544 if (gatt_services == NULL) {
2546 } else if (gatt_services->next == NULL) {
2553 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2555 struct gatt_service_info *svc_info;
2556 int ret = BLUETOOTH_ERROR_NONE;
2560 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2562 ret = __bt_gatt_unregister_service(svc_info);
2563 if (ret != BLUETOOTH_ERROR_NONE) {
2564 BT_ERR("Could not unregister service [%s]", svc_path);
2571 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2572 int resp_state, int offset, char *value, int value_length)
2574 struct gatt_req_info *req_info = NULL;
2576 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2577 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2578 BT_ERR("Don't have aprivilege to use this API");
2579 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2582 req_info = __bt_gatt_find_request_info(request_id);
2583 if (req_info == NULL) {
2584 BT_ERR("Coundn't find request id [%d]", request_id);
2585 return BLUETOOTH_ERROR_INTERNAL;
2588 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2589 BT_ERR("resp_state is 0x%X", resp_state);
2590 char err_msg[20] = { 0, };
2591 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2592 g_dbus_method_invocation_return_dbus_error(req_info->context,
2593 "org.bluez.Error.Failed", err_msg);
2595 gatt_requests = g_slist_remove(gatt_requests, req_info);
2597 req_info->context = NULL;
2598 if (req_info->attr_path)
2599 g_free(req_info->attr_path);
2600 if (req_info->svc_path)
2601 g_free(req_info->svc_path);
2604 return BLUETOOTH_ERROR_NONE;
2607 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2609 GVariantBuilder *inner_builder = NULL;
2610 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2611 if (value_length > 0 && value != NULL) {
2612 for (i = 0; i < value_length; i++)
2613 g_variant_builder_add(inner_builder, "y", value[i]);
2615 g_dbus_method_invocation_return_value(req_info->context,
2616 g_variant_new("(ay)", inner_builder));
2617 g_variant_builder_unref(inner_builder);
2619 g_dbus_method_invocation_return_value(req_info->context, NULL);
2621 gatt_requests = g_slist_remove(gatt_requests, req_info);
2623 req_info->context = NULL;
2624 if (req_info->attr_path)
2625 g_free(req_info->attr_path);
2626 if (req_info->svc_path)
2627 g_free(req_info->svc_path);
2630 return BLUETOOTH_ERROR_NONE;
2633 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2634 bluetooth_device_address_t *unicast_address)
2636 GVariantBuilder *outer_builder;
2637 GVariantBuilder *invalidated_builder;
2638 GError *error = NULL;
2639 gboolean notify = TRUE;
2640 gboolean ret = TRUE;
2641 int err = BLUETOOTH_ERROR_NONE;
2642 gchar **line_argv = NULL;
2643 gchar *serv_path = NULL;
2644 char addr[20] = { 0 };
2646 line_argv = g_strsplit_set(char_path, "/", 0);
2647 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2649 if (!__bt_gatt_is_service_registered(serv_path)) {
2650 BT_DBG("service not registered for this characteristic");
2652 g_strfreev(line_argv);
2653 return BLUETOOTH_ERROR_INTERNAL;
2658 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2659 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2661 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2662 g_variant_new("b", notify));
2664 if (unicast_address) {
2665 _bt_convert_addr_type_to_string(addr,
2666 (unsigned char *)unicast_address->addr);
2668 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2669 g_variant_new("s", addr));
2671 BT_DBG("Set characteristic Notification");
2672 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2674 "org.freedesktop.DBus.Properties",
2675 "PropertiesChanged",
2676 g_variant_new("(sa{sv}as)",
2677 "org.bluez.GattCharacteristic1",
2678 outer_builder, invalidated_builder),
2682 if (error != NULL) {
2683 BT_ERR("D-Bus API failure: errCode[%x], \
2685 error->code, error->message);
2686 g_clear_error(&error);
2688 err = BLUETOOTH_ERROR_INTERNAL;
2691 g_strfreev(line_argv);
2692 g_variant_builder_unref(outer_builder);
2693 g_variant_builder_unref(invalidated_builder);
2700 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2704 if (!is_server_started) {
2706 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2707 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2708 BT_ERR("Don't have aprivilege to use this API");
2709 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2712 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2713 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2715 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2716 in_param1, in_param2, in_param3, in_param4, &out_param);
2717 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2719 if (ret != BLUETOOTH_ERROR_NONE) {
2720 BT_ERR("Register application failed");
2723 is_server_started = true;
2725 return BLUETOOTH_ERROR_NONE;
2728 BT_INFO("Already RegisterApplication");
2729 return BLUETOOTH_ERROR_NONE;
2733 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2736 int ret = BLUETOOTH_ERROR_NONE;
2739 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2741 /* Register event handler for GATT */
2742 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2744 if (ret != BLUETOOTH_ERROR_NONE &&
2745 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2746 BT_ERR("Fail to init the event handler");
2747 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2751 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2752 in_param1, in_param2, in_param3, in_param4, &out_param);
2754 /* App ID -1 is invalid */
2755 if (ret != BLUETOOTH_ERROR_NONE) {
2756 BT_INFO("GATT Server Registration failed result [%d]", ret);
2759 *instance_id = g_array_index(out_param, int, 0);
2760 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2764 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2766 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2770 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2773 BT_INFO("GATT Server Deinitialize");
2774 /* Unregister the event */
2775 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2777 if (ret != BLUETOOTH_ERROR_NONE) {
2778 BT_ERR("Fail to deinit the event handler");
2782 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2787 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2788 int instance_id, int *service_handle)
2790 BT_CHECK_ENABLED(return);
2791 BT_CHECK_PARAMETER(svc_uuid, return);
2794 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2796 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2799 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2801 g_array_append_vals(in_param1, &type, sizeof(int));
2802 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2803 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2804 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2806 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2807 in_param1, in_param2, in_param3, in_param4, &out_param);
2809 /* ATT handle 0 is reserved, hence it can not be used by app.
2810 It will be used to indicate error in regsitering attribute */
2811 if (result != BLUETOOTH_ERROR_NONE)
2812 *service_handle = 0;
2814 *service_handle = g_array_index(out_param, int, 0);
2816 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2821 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2822 const bluetooth_gatt_server_attribute_params_t *param,
2825 BT_CHECK_ENABLED(return);
2826 BT_CHECK_PARAMETER(char_uuid, return);
2827 BT_CHECK_PARAMETER(param, return);
2830 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2832 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2835 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2837 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2838 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2840 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2841 in_param1, in_param2, in_param3, in_param4, &out_param);
2843 /* ATT handle 0 is reserved, hence it can not be used by app.
2844 It will be used to indicate error in regsitering attribute */
2845 if (result != BLUETOOTH_ERROR_NONE) {
2846 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2849 *char_handle = g_array_index(out_param, int, 0);
2850 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2853 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2857 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2858 int service_handle, int instance_id, int *descriptor_handle)
2860 BT_CHECK_ENABLED(return);
2861 BT_CHECK_PARAMETER(desc_uuid, return);
2864 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2866 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2869 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2871 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2872 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2873 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2874 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2876 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2877 in_param1, in_param2, in_param3, in_param4, &out_param);
2879 /* ATT handle 0 is reserved, hence it can not be used by app.
2880 It will be used to indicate error in regsitering attribute */
2881 if (result != BLUETOOTH_ERROR_NONE) {
2882 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2883 *descriptor_handle = 0;
2885 *descriptor_handle = g_array_index(out_param, int, 0);
2886 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2889 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2894 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2896 BT_CHECK_ENABLED(return);
2900 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2902 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2903 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2905 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2906 in_param1, in_param2, in_param3, in_param4, &out_param);
2908 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2913 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2914 const bluetooth_gatt_att_data_t *value)
2916 BT_CHECK_PARAMETER(param, return);
2917 BT_CHECK_PARAMETER(value, return);
2918 BT_CHECK_ENABLED(return);
2922 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2924 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
2925 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
2927 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
2928 in_param1, in_param2, in_param3, in_param4, &out_param);
2930 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2936 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
2937 const bluetooth_gatt_server_indication_params_t *param,
2938 const bluetooth_gatt_att_data_t *att_value)
2940 BT_CHECK_PARAMETER(param, return);
2941 BT_CHECK_PARAMETER(att_value, return);
2942 BT_CHECK_ENABLED(return);
2944 char addr[BLUETOOTH_ADDRESS_STRING_LENGTH] ;
2948 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2950 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
2951 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
2952 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
2954 _bt_convert_addr_type_to_string(addr, addr_hex->addr);
2955 fd = bluetooth_get_characteristic_fd(param->atrribute_handle, addr);
2958 result = bluetooth_gatt_write_characteristics_value_to_fd_(fd, att_value->data, att_value->length, NULL);
2960 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
2961 in_param1, in_param2, in_param3, in_param4, &out_param);
2963 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2968 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
2970 BT_CHECK_ENABLED(return);
2974 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2976 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2977 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2979 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
2980 in_param1, in_param2, in_param3, in_param4, &out_param);
2982 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2987 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
2989 BT_CHECK_ENABLED(return);
2993 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2995 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2996 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2998 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
2999 in_param1, in_param2, in_param3, in_param4, &out_param);
3001 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3006 /* Tizen Platform Specific */
3007 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
3008 const bluetooth_gatt_server_update_value_t *value)
3010 BT_CHECK_ENABLED(return);
3011 BT_CHECK_PARAMETER(value, return);
3015 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3017 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3018 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3020 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3021 in_param1, in_param2, in_param3, in_param4, &out_param);
3023 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3028 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3030 BT_CHECK_ENABLED(return);
3034 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3036 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3038 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3039 in_param1, in_param2, in_param3, in_param4, &out_param);
3041 if (result != BLUETOOTH_ERROR_NONE)
3042 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3044 BT_INFO("GATT Server Unregistration successful");
3046 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3051 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3052 GIOCondition cond, gpointer data)
3055 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3057 BT_DBG("FD io write data received [%s]", write_data->address);
3059 if (cond & G_IO_IN) {
3060 GIOStatus status = G_IO_STATUS_NORMAL;
3062 char *buffer = NULL;
3064 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3066 buffer = g_malloc0(BUF);
3068 status = g_io_channel_read_chars(gio, buffer,
3071 if (status != G_IO_STATUS_NORMAL) {
3072 BT_ERR("IO Channel read is failed with %d", status);
3075 BT_ERR("IO Channel read error [%s]", err->message);
3076 if (status == G_IO_STATUS_ERROR) {
3077 BT_ERR("cond : %d", cond);
3079 g_io_channel_shutdown(gio, TRUE, NULL);
3080 g_io_channel_unref(gio);
3090 bluetooth_gatt_server_write_requested_info_t write_info;
3091 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3092 memcpy(write_info.data.data, buffer, len);
3094 write_info.length = len;
3095 write_info.need_resp = false;
3096 write_info.attribute_handle = write_data->attribute_handle;
3098 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->address);
3099 write_info.connection_id = write_data->connection_id;
3100 write_info.offset = write_data->offset;
3101 write_info.request_id = -2;
3103 bt_event_info_t *event_info;
3104 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3108 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3109 BLUETOOTH_ERROR_NONE, &write_info,
3110 event_info->cb, event_info->user_data);
3112 BT_ERR("eventinfo failed");
3122 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
3123 BT_ERR("Error : GIOCondition %d, ]", cond);
3124 g_io_channel_shutdown(gio, TRUE, NULL);
3125 g_io_channel_unref(gio);
3133 void bluetooth_gatt_server_send_acquire_write_response(GVariant * parameters)
3138 int pipefd[2] = {-1,};
3141 char err_msg[512] = {'\0'};
3142 GIOChannel *channel = NULL;
3146 g_variant_get(parameters, "(iiiiii&s)",
3155 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3156 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3157 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3158 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3161 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3162 strerror_r(errno, err_msg, sizeof(err_msg));
3163 BT_ERR("socketpair(): %s", err_msg);
3168 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3170 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3171 bluetooth_gatt_server_acquire_response_params_t data;
3172 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
3173 data.fd = pipefd[1];
3175 data.request_id = tran_id;
3177 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3179 write_info->attribute_handle = att_han;
3180 write_info->connection_id = tran_id;
3181 write_info->offset = offset;
3183 memcpy(write_info->address, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3185 BT_INFO("FD read %d remote address [%s ] \n", pipefd[0], addr);
3188 channel = g_io_channel_unix_new(pipefd[0]);
3189 g_io_channel_set_encoding(channel, NULL, NULL);
3190 g_io_channel_set_buffered(channel, FALSE);
3191 g_io_channel_set_close_on_unref(channel, TRUE);
3192 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3193 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3194 bluetooth_gatt_server_acquire_channel_write_cb, write_info);
3197 GUnixFDList *fd_list = g_unix_fd_list_new();
3198 GError *error = NULL;
3200 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3201 g_assert_no_error(error);
3204 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3206 BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3208 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE,
3209 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3211 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3217 void bluetooth_gatt_server_send_acquire_notify_response(GVariant * parameters, bt_event_info_t *event_info)
3222 int pipefd[2] = {-1,};
3225 char err_msg[512] = {'\0'};
3226 GIOChannel *channel = NULL;
3229 bluetooth_gatt_acquire_notify_info_t *chr_info;
3230 const char *address = NULL;
3232 g_variant_get(parameters, "(iiiiii&s)",
3241 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3242 BT_DBG("GATT Server Acquire notify att handle:[%d]", att_han);
3243 BT_DBG("GATT Server Acquire Notify Offset: [%d]", offset);
3244 BT_DBG("GATT Server Acquire Notify address: [%s]", address);
3247 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3248 strerror_r(errno, err_msg, sizeof(err_msg));
3249 BT_ERR("socketpair(): %s", err_msg);
3256 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3258 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3259 bluetooth_gatt_server_acquire_response_params_t data;
3260 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
3261 data.fd = pipefd[1];
3263 data.request_id = tran_id;
3265 BT_INFO("FD write %d characterstics path \n", pipefd[0]);
3267 chr_info = bluetooth_get_characteristic_info_from_path(att_han);
3269 chr_info = g_malloc0(sizeof(bluetooth_gatt_acquire_notify_info_t));
3270 chr_info->write_fd = fd;
3271 chr_info->att_hand = att_han;
3273 gatt_characteristic_server_notify_list = g_slist_append(gatt_characteristic_server_notify_list, chr_info);
3275 chr_info->write_fd = fd;
3277 channel = g_io_channel_unix_new(fd);
3278 g_io_channel_set_encoding(channel, NULL, NULL);
3279 g_io_channel_set_buffered(channel, FALSE);
3280 g_io_channel_set_close_on_unref(channel, TRUE);
3281 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3282 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
3283 bluetooth_gatt_write_channel_watch_cb, chr_info);
3285 GUnixFDList *fd_list = g_unix_fd_list_new();
3286 GError *error = NULL;
3288 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3289 g_assert_no_error(error);
3292 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3294 BT_DBG("Sending event BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE file descriptor value [%d] ", data.fd);
3296 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE,
3297 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3299 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3303 if (result == BLUETOOTH_ERROR_NONE) {
3304 BT_DBG("sending gatt server notification state changed event");
3305 bluetooth_gatt_server_notification_changed_t info;
3306 bluetooth_device_address_t dev_address = { {0} };
3307 memset(&info, 0x00, sizeof(bluetooth_gatt_server_notification_changed_t));
3309 _bt_convert_addr_string_to_type(dev_address.addr, address);
3310 memcpy(info.device_address.addr,
3312 BLUETOOTH_ADDRESS_LENGTH);
3313 info.handle = att_han;
3314 info.notification = TRUE;
3316 _bt_gatt_server_event_cb(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
3318 event_info->cb, event_info->user_data);
3323 void cleanup_gatt_acquire_fd(int handle)
3325 bluetooth_gatt_acquire_notify_info_t *chr_info = NULL;
3329 chr_info = bluetooth_get_characteristic_info_from_path(handle);
3331 if (chr_info != NULL) {
3332 BT_INFO("GATT Server: acquire notification char info found");
3334 if (chr_info->write_fd >= 0) {
3335 BT_INFO("closing fd");
3336 close(chr_info->write_fd);
3339 BT_INFO("Removing char_info from the list");
3340 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
3341 bluetooth_characteristic_info_free(chr_info);