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 bool is_server_started = false;
166 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_INFO("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;
364 BT_INFO(" sid [ %d]" , info->att_hand);
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_INFO("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_INFO(" 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_INFO("write data failed %d is ", written);
440 BT_INFO("write data %s is sucess ", value);
445 #ifdef TIZEN_FEATURE_BT_HPS
446 static int __bt_send_event_to_hps(int event, GVariant *var)
448 GError *error = NULL;
449 GVariant *parameters;
450 GDBusMessage *msg = NULL;
454 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
456 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
457 GVariantBuilder *inner_builder;
458 GVariantBuilder *invalidated_builder;
460 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
461 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
463 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
465 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
467 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
468 g_variant_builder_unref(invalidated_builder);
469 g_variant_builder_unref(inner_builder);
470 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
471 GVariantBuilder *inner_builder;
472 GVariantBuilder *invalidated_builder;
474 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
475 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
477 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
479 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
481 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
482 g_variant_builder_unref(invalidated_builder);
483 g_variant_builder_unref(inner_builder);
485 g_varaiant_unref(var);
488 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
489 g_dbus_message_set_body(msg, parameters);
490 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
492 BT_ERR("D-Bus API failure: errCode[%x], \
494 error->code, error->message);
495 g_clear_error(&error);
497 return BLUETOOTH_ERROR_INTERNAL;
499 return BLUETOOTH_ERROR_NONE;
503 #ifdef TIZEN_FEATURE_BT_OTP
504 static int __bt_send_event_to_otp(int event, GVariant *var)
506 GError *error = NULL;
507 GVariant *parameters = NULL;
508 GDBusMessage *msg = NULL;
512 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
514 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
515 GVariantBuilder *inner_builder;
516 GVariantBuilder *invalidated_builder;
518 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
519 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
521 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
523 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
525 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
526 g_variant_builder_unref(invalidated_builder);
527 g_variant_builder_unref(inner_builder);
528 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
529 GVariantBuilder *inner_builder;
530 GVariantBuilder *invalidated_builder;
532 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
533 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
535 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
537 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
539 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
540 g_variant_builder_unref(invalidated_builder);
541 g_variant_builder_unref(inner_builder);
542 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
543 GVariantBuilder *inner_builder;
544 GVariantBuilder *invalidated_builder;
546 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
547 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
549 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
551 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
553 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
554 g_variant_builder_unref(invalidated_builder);
555 g_variant_builder_unref(inner_builder);
558 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
559 g_dbus_message_set_body(msg, parameters);
560 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
562 BT_ERR("D-Bus API failure: errCode[%x], \
564 error->code, error->message);
565 g_clear_error(&error);
567 return BLUETOOTH_ERROR_INTERNAL;
569 return BLUETOOTH_ERROR_NONE;
573 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
575 const gchar *object_path,
576 const gchar *interface_name,
577 const gchar *method_name,
578 GVariant *parameters,
579 GDBusMethodInvocation *invocation,
582 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
583 BT_DBG("Getting values for service, chars and descriptors");
586 GVariantBuilder *builder = NULL;
587 GVariantBuilder *inner_builder1 = NULL;
588 GVariant *svc_char = NULL;
589 GSList *char_list = NULL;
590 GSList *desc_list = NULL;
593 builder = g_variant_builder_new(G_VARIANT_TYPE("a{oa{sa{sv}}}"));
595 /* Prepare inner builder for GattService1 interface */
596 svc_index = g_slist_length(gatt_services) - 1;
597 for (; svc_index >= 0; svc_index--) {
598 GVariantBuilder *svc_builder = NULL;
599 GVariantBuilder *inner_builder = NULL;
600 struct gatt_service_info *serv_info = NULL;
602 serv_info = g_slist_nth_data(gatt_services, svc_index);
603 if (serv_info == NULL) {
604 BT_ERR("serv_info is NULL");
608 /* Prepare inner builder for GattService1 interface */
609 BT_DBG("Creating builder for service : %s", serv_info->service_uuid);
610 svc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
611 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
613 g_variant_builder_add(inner_builder, "{sv}", "UUID",
614 g_variant_new_string(serv_info->service_uuid));
615 g_variant_builder_add(inner_builder, "{sv}", "Primary",
616 g_variant_new_boolean(serv_info->is_svc_primary));
618 /* Characteristics */
619 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
621 BT_DBG("Adding Charatarisitcs list");
622 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
623 struct gatt_char_info *char_info = char_list->data;
624 g_variant_builder_add(inner_builder1, "o", char_info->char_path);
625 BT_DBG("%s", char_info->char_path);
628 svc_char = g_variant_new("ao", inner_builder1);
629 g_variant_builder_add(inner_builder, "{sv}", "Characteristics", svc_char);
630 g_variant_builder_add(svc_builder, "{sa{sv}}", GATT_SERV_INTERFACE, inner_builder);
631 g_variant_builder_add(builder, "{oa{sa{sv}}}", serv_info->serv_path, svc_builder);
632 g_variant_builder_unref(inner_builder1);
634 /* Prepare inner builder for GattCharacteristic1 interface */
635 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
636 GVariantBuilder *char_builder = NULL;
637 GVariantBuilder *inner_builder = NULL;
638 GVariantBuilder *builder1 = NULL;
639 GVariantBuilder *builder2 = NULL;
640 GVariantBuilder *builder3 = NULL;
641 GVariant *char_val = NULL;
642 GVariant *flags_val = NULL;
643 GVariant *char_desc = NULL;
644 char *unicast = NULL;
645 gboolean notify = FALSE;
647 struct gatt_char_info *char_info = char_list->data;
649 if (char_info == NULL) {
650 BT_ERR("char_info is NULL");
654 BT_DBG("Creating builder for characteristic : %s", char_info->char_uuid);
655 char_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
656 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
659 g_variant_builder_add(inner_builder, "{sv}", "UUID",
660 g_variant_new_string(char_info->char_uuid));
663 g_variant_builder_add(inner_builder, "{sv}", "Service",
664 g_variant_new("o", serv_info->serv_path));
667 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
668 if (char_info->char_value != NULL) {
669 for (i = 0; i < char_info->value_length; i++) {
670 g_variant_builder_add(builder1, "y", char_info->char_value[i]);
672 char_val = g_variant_new("ay", builder1);
673 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
677 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
678 for (i = 0; i < char_info->flags_length; i++) {
679 g_variant_builder_add(builder2, "s", char_info->char_flags[i]);
681 flags_val = g_variant_new("as", builder2);
682 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
685 g_variant_builder_add(inner_builder, "{sv}", "Notifying", g_variant_new("b", notify));
688 unicast = g_strdup("00:00:00:00:00:00");
689 g_variant_builder_add(inner_builder, "{sv}", "Unicast", g_variant_new("s", unicast));
692 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
693 BT_DBG("Adding Descriptors list");
694 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
695 struct gatt_desc_info *desc_info = desc_list->data;
696 g_variant_builder_add(builder3, "o", desc_info->desc_path);
697 BT_DBG("%s", desc_info->desc_path);
700 char_desc = g_variant_new("ao", builder3);
701 g_variant_builder_add(inner_builder, "{sv}", "Descriptors", char_desc);
702 g_variant_builder_add(char_builder, "{sa{sv}}", GATT_CHAR_INTERFACE , inner_builder);
703 g_variant_builder_add(builder, "{oa{sa{sv}}}", char_info->char_path, char_builder);
705 /*Prepare inner builder for GattDescriptor1 interface*/
706 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
707 GVariantBuilder *desc_builder = NULL;
708 GVariantBuilder *inner_builder = NULL;
709 GVariantBuilder *builder1 = NULL;
710 GVariantBuilder *builder2 = NULL;
711 GVariant *desc_val = NULL;
712 struct gatt_desc_info *desc_info = desc_list->data;
714 if (desc_info == NULL) {
715 BT_ERR("desc_info is NULL");
719 BT_DBG("Creating builder for descriptor : %s", desc_info->desc_uuid);
720 desc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
721 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
724 g_variant_builder_add(inner_builder, "{sv}", "UUID",
725 g_variant_new_string(desc_info->desc_uuid));
728 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
729 g_variant_new("o", char_info->char_path));
732 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
733 if (desc_info->desc_value != NULL) {
734 for (i = 0; i < desc_info->value_length; i++) {
735 g_variant_builder_add(builder1, "y", desc_info->desc_value[i]);
737 desc_val = g_variant_new("ay", builder1);
738 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
742 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
743 for (i = 0; i < desc_info->flags_length; i++) {
744 g_variant_builder_add(builder2, "s", desc_info->desc_flags[i]);
746 flags_val = g_variant_new("as", builder2);
747 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
749 g_variant_builder_add(desc_builder, "{sa{sv}}", GATT_DESC_INTERFACE,
751 g_variant_builder_add(builder, "{oa{sa{sv}}}", desc_info->desc_path,
754 /* unref descriptor builder pointers */
755 g_variant_builder_unref(builder1);
756 g_variant_builder_unref(builder2);
757 g_variant_builder_unref(inner_builder);
758 g_variant_builder_unref(desc_builder);
764 /* unref char builder pointers */
765 g_variant_builder_unref(builder1);
766 g_variant_builder_unref(builder2);
767 g_variant_builder_unref(builder3);
768 g_variant_builder_unref(inner_builder);
769 g_variant_builder_unref(char_builder);
772 /* unref service builder pointers */
773 g_variant_builder_unref(inner_builder);
774 g_variant_builder_unref(svc_builder);
777 /* Return builder as method reply */
778 BT_DBG("Sending gatt service builder values to Bluez");
779 g_dbus_method_invocation_return_value(invocation,
780 g_variant_new("(a{oa{sa{sv}}})", builder));
781 g_variant_builder_unref(builder);
785 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
789 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
790 struct gatt_service_info *serv_info = l1->data;
792 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
793 struct gatt_char_info *char_info = l2->data;
795 if (g_strcmp0(char_info->char_path, char_path) == 0)
799 BT_ERR("Gatt service not found");
803 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
805 GSList *l1, *l2, *l3;
807 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
808 struct gatt_service_info *serv_info = l1->data;
810 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
811 struct gatt_char_info *char_info = l2->data;
813 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
814 struct gatt_desc_info *desc_info = l3->data;
816 if (g_strcmp0(desc_info->desc_path, desc_path) == 0)
821 BT_ERR("Gatt service not found");
825 static void __bt_gatt_char_method_call(GDBusConnection *connection,
827 const gchar *object_path,
828 const gchar *interface_name,
829 const gchar *method_name,
830 GVariant *parameters,
831 GDBusMethodInvocation *invocation,
835 if (g_strcmp0(method_name, "ReadValue") == 0) {
839 bt_gatt_read_req_t read_req = {0, };
840 bt_user_info_t *user_info = NULL;
841 struct gatt_req_info *req_info = NULL;
842 struct gatt_service_info *svc_info = NULL;
843 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
844 GVariant *param = NULL;
847 BT_DBG("Application path = %s", object_path);
848 BT_DBG("Sender = %s", sender);
850 user_info = _bt_get_user_data(BT_COMMON);
851 if (user_info == NULL) {
852 BT_INFO("No callback is set for %s", object_path);
853 g_dbus_method_invocation_return_value(invocation, NULL);
857 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
858 if (svc_info == NULL) {
859 BT_ERR("Coudn't find service for %s", object_path);
860 g_dbus_method_invocation_return_value(invocation, NULL);
864 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
865 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
867 read_req.att_handle = (char *)object_path;
868 read_req.address = addr;
869 read_req.req_id = req_id;
870 read_req.offset = offset;
871 read_req.service_handle = svc_info->serv_path;
873 /* Store requets information */
874 req_info = g_new0(struct gatt_req_info, 1);
875 req_info->attr_path = g_strdup(object_path);
876 req_info->svc_path = g_strdup(read_req.service_handle);
877 req_info->request_id = req_id;
878 req_info->offset = offset;
879 req_info->context = invocation;
880 gatt_requests = g_slist_append(gatt_requests, req_info);
882 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
883 param = g_variant_new("(sssyq)",
885 read_req.service_handle,
889 #ifdef TIZEN_FEATURE_BT_HPS
890 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
892 #ifdef TIZEN_FEATURE_BT_OTP
893 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
897 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
898 BLUETOOTH_ERROR_NONE, &read_req,
899 user_info->cb, user_info->user_data);
901 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
902 GVariant *var = NULL;
906 gboolean response_needed = FALSE;
907 bt_gatt_value_change_t value_change = {0, };
908 bt_user_info_t *user_info = NULL;
910 struct gatt_service_info *svc_info = NULL;
911 struct gatt_req_info *req_info = NULL;
912 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
913 GVariant *param = NULL;
916 BT_DBG("WriteValue");
917 BT_DBG("Application path = %s", object_path);
918 BT_DBG("Sender = %s", sender);
920 g_variant_get(parameters, "(&suqb@ay)",
921 &addr, &req_id, &offset, &response_needed, &var);
922 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
924 user_info = _bt_get_user_data(BT_COMMON);
926 BT_INFO("No callback is set for %s", object_path);
927 g_variant_unref(var);
929 g_dbus_method_invocation_return_value(invocation, NULL);
931 g_object_unref(invocation);
935 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
936 if (svc_info == NULL) {
937 BT_ERR("Coudn't find service for %s", object_path);
938 g_variant_unref(var);
940 g_dbus_method_invocation_return_value(invocation, NULL);
942 g_object_unref(invocation);
946 value_change.att_handle = (char *)object_path;
947 value_change.address = addr;
948 value_change.service_handle = svc_info->serv_path;
949 value_change.offset = offset;
950 value_change.req_id = req_id;
951 value_change.response_needed = response_needed;
953 len = g_variant_get_size(var);
957 value_change.att_value = (guint8 *)g_malloc(len);
959 data = (char *)g_variant_get_data(var);
960 memcpy(value_change.att_value, data, len);
962 value_change.val_len = len;
964 if (response_needed) {
965 /* Store requets information */
966 req_info = g_new0(struct gatt_req_info, 1);
967 req_info->attr_path = g_strdup(object_path);
968 req_info->svc_path = g_strdup(value_change.service_handle);
969 req_info->request_id = req_id;
970 req_info->offset = offset;
971 req_info->context = invocation;
972 gatt_requests = g_slist_append(gatt_requests, req_info);
974 g_object_unref(invocation);
977 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
980 svc_path = g_strdup(svc_info->serv_path);
981 param = g_variant_new("(sssyq@ay)",
988 #ifdef TIZEN_FEATURE_BT_HPS
989 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
991 #ifdef TIZEN_FEATURE_BT_OTP
992 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1000 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1001 BLUETOOTH_ERROR_NONE, &value_change,
1002 user_info->cb, user_info->user_data);
1004 g_free(value_change.att_value);
1005 g_variant_unref(var);
1007 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1008 bt_user_info_t *user_info = NULL;
1009 bt_gatt_char_notify_change_t notify_change = {0, };
1010 #if TIZEN_FEATURE_BT_OTP
1011 GVariant *param = NULL;
1013 BT_DBG("StartNotify");
1014 user_info = _bt_get_user_data(BT_COMMON);
1015 if (user_info != NULL) {
1016 struct gatt_service_info *svc_info = NULL;
1017 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1019 notify_change.service_handle = svc_info->serv_path;
1020 notify_change.att_handle = (char *)object_path;
1021 notify_change.att_notify = TRUE;
1022 #if TIZEN_FEATURE_BT_OTP
1023 param = g_variant_new("(ssb)",
1024 notify_change.att_handle,
1025 notify_change.service_handle,
1026 notify_change.att_notify);
1027 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1029 _bt_common_event_cb(
1030 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1031 BLUETOOTH_ERROR_NONE, ¬ify_change,
1032 user_info->cb, user_info->user_data);
1035 g_object_unref(invocation);
1037 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1038 bt_user_info_t *user_info = NULL;
1039 bt_gatt_char_notify_change_t notify_change = {0, };
1040 #if TIZEN_FEATURE_BT_OTP
1041 GVariant *param = NULL;
1043 BT_DBG("StopNotify");
1044 user_info = _bt_get_user_data(BT_COMMON);
1045 if (user_info != NULL) {
1046 struct gatt_service_info *svc_info = NULL;
1047 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1049 notify_change.service_handle = svc_info->serv_path;
1050 notify_change.att_handle = (char *)object_path;
1051 notify_change.att_notify = FALSE;
1052 #if TIZEN_FEATURE_BT_OTP
1053 param = g_variant_new("(ssb)",
1054 notify_change.att_handle,
1055 notify_change.service_handle,
1056 notify_change.att_notify);
1057 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1059 _bt_common_event_cb(
1060 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1061 BLUETOOTH_ERROR_NONE, ¬ify_change,
1062 user_info->cb, user_info->user_data);
1065 g_object_unref(invocation);
1067 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1069 bt_gatt_indicate_confirm_t confirm = {0, };
1070 bt_user_info_t *user_info = NULL;
1071 gboolean complete = FALSE;
1072 struct gatt_service_info *svc_info = NULL;
1074 BT_DBG("IndicateConfirm");
1075 BT_DBG("Application path = %s", object_path);
1076 BT_DBG("Sender = %s", sender);
1078 g_variant_get(parameters, "(&sb)", &addr, &complete);
1079 BT_DBG("Remote Device address number = %s", addr);
1081 confirm.att_handle = (char *)object_path;
1082 confirm.address = addr;
1083 confirm.complete = complete;
1085 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1086 if (svc_info != NULL) {
1087 confirm.service_handle = svc_info->serv_path;
1089 user_info = _bt_get_user_data(BT_COMMON);
1090 if (user_info != NULL) {
1091 _bt_common_event_cb(
1092 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1093 BLUETOOTH_ERROR_NONE, &confirm,
1094 user_info->cb, user_info->user_data);
1099 g_dbus_method_invocation_return_value(invocation, NULL);
1102 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1103 const gchar *sender,
1104 const gchar *object_path,
1105 const gchar *interface_name,
1106 const gchar *method_name,
1107 GVariant *parameters,
1108 GDBusMethodInvocation *invocation,
1111 if (g_strcmp0(method_name, "ReadValue") == 0) {
1115 bt_gatt_read_req_t read_req = {0, };
1116 bt_user_info_t *user_info = NULL;
1117 struct gatt_req_info *req_info = NULL;
1118 struct gatt_service_info *svc_info = NULL;
1120 BT_DBG("ReadValue");
1121 BT_DBG("Application path = %s", object_path);
1122 BT_DBG("Sender = %s", sender);
1124 user_info = _bt_get_user_data(BT_COMMON);
1125 if (user_info == NULL) {
1126 BT_INFO("No callback is set for %s", object_path);
1127 g_dbus_method_invocation_return_value(invocation, NULL);
1131 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1132 if (svc_info == NULL) {
1133 BT_ERR("Coudn't find service for %s", object_path);
1134 g_dbus_method_invocation_return_value(invocation, NULL);
1138 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1139 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1141 read_req.att_handle = (char *)object_path;
1142 read_req.address = addr;
1143 read_req.req_id = req_id;
1144 read_req.offset = offset;
1145 read_req.service_handle = svc_info->serv_path;
1147 /* Store requets information */
1148 req_info = g_new0(struct gatt_req_info, 1);
1149 req_info->attr_path = g_strdup(object_path);
1150 req_info->svc_path = g_strdup(read_req.service_handle);
1151 req_info->request_id = req_id;
1152 req_info->offset = offset;
1153 req_info->context = invocation;
1154 gatt_requests = g_slist_append(gatt_requests, req_info);
1156 _bt_common_event_cb(
1157 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1158 BLUETOOTH_ERROR_NONE, &read_req,
1159 user_info->cb, user_info->user_data);
1162 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1163 GVariant *var = NULL;
1167 gboolean response_needed = FALSE;
1168 bt_gatt_value_change_t value_change = {0, };
1169 bt_user_info_t *user_info = NULL;
1171 struct gatt_service_info *svc_info = NULL;
1172 struct gatt_req_info *req_info = NULL;
1174 BT_DBG("WriteValue");
1175 BT_DBG("Application path = %s", object_path);
1176 BT_DBG("Sender = %s", sender);
1178 g_variant_get(parameters, "(&suqb@ay)",
1179 &addr, &req_id, &offset, &response_needed, &var);
1180 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1182 user_info = _bt_get_user_data(BT_COMMON);
1183 if (user_info == NULL) {
1184 BT_INFO("No callback is set for %s", object_path);
1185 g_variant_unref(var);
1186 if (response_needed)
1187 g_dbus_method_invocation_return_value(invocation, NULL);
1189 g_object_unref(invocation);
1193 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1194 if (svc_info == NULL) {
1195 BT_ERR("Coudn't find service for %s", object_path);
1196 g_variant_unref(var);
1197 if (response_needed)
1198 g_dbus_method_invocation_return_value(invocation, NULL);
1200 g_object_unref(invocation);
1204 value_change.att_handle = (char *)object_path;
1205 value_change.address = addr;
1206 value_change.service_handle = svc_info->serv_path;
1207 value_change.offset = offset;
1208 value_change.req_id = req_id;
1209 value_change.response_needed = response_needed;
1211 len = g_variant_get_size(var);
1215 value_change.att_value = (guint8 *)g_malloc(len);
1217 data = (char *)g_variant_get_data(var);
1218 memcpy(value_change.att_value, data, len);
1220 value_change.val_len = len;
1222 if (response_needed) {
1223 /* Store requets information */
1224 req_info = g_new0(struct gatt_req_info, 1);
1225 req_info->attr_path = g_strdup(object_path);
1226 req_info->svc_path = g_strdup(value_change.service_handle);
1227 req_info->request_id = req_id;
1228 req_info->offset = offset;
1229 req_info->context = invocation;
1230 gatt_requests = g_slist_append(gatt_requests, req_info);
1232 g_object_unref(invocation);
1235 _bt_common_event_cb(
1236 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1237 BLUETOOTH_ERROR_NONE, &value_change,
1238 user_info->cb, user_info->user_data);
1240 g_free(value_change.att_value);
1241 g_variant_unref(var);
1246 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1249 GError *error = NULL;
1250 GVariantBuilder *array_builder;
1252 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1253 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1254 g_variant_builder_add(array_builder, "s", interface);
1256 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1257 "org.freedesktop.Dbus.Objectmanager",
1258 "InterfacesRemoved",
1259 g_variant_new("(oas)",
1260 object_path, array_builder),
1264 if (error != NULL) {
1265 /* dbus gives error cause */
1266 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1267 error->code, error->message);
1268 g_clear_error(&error);
1271 g_variant_builder_unref(array_builder);
1276 static const GDBusInterfaceVTable desc_interface_vtable = {
1277 __bt_gatt_desc_method_call,
1283 static const GDBusInterfaceVTable char_interface_vtable = {
1284 __bt_gatt_char_method_call,
1290 static const GDBusInterfaceVTable serv_interface_vtable = {
1297 static const GDBusInterfaceVTable manager_interface_vtable = {
1298 __bt_gatt_manager_method_call,
1304 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1305 const gchar *introspection_data)
1308 GDBusNodeInfo *node_info = NULL;
1310 if (introspection_data == NULL)
1314 BT_DBG("Create new node info");
1315 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1318 BT_ERR("Unable to create node: %s", err->message);
1319 g_clear_error(&err);
1326 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1327 const char *service_path)
1331 for (l = gatt_services; l != NULL; l = l->next) {
1332 struct gatt_service_info *info = l->data;
1334 if (g_strcmp0(info->serv_path, service_path) == 0)
1337 BT_ERR("Gatt service not found");
1341 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1342 const char *service_path, const char *char_path)
1346 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1347 struct gatt_service_info *serv_info = l1->data;
1349 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1351 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1352 struct gatt_char_info *char_info = l2->data;
1354 if (g_strcmp0(char_info->char_path, char_path) == 0)
1357 BT_ERR("Gatt characteristic not found");
1361 BT_ERR("Gatt service not found");
1365 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1366 const char *serv_path, const char *char_path,
1367 const char *desc_path)
1369 GSList *l1, *l2, *l3;
1371 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1372 struct gatt_service_info *serv_info = l1->data;
1374 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1375 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1376 struct gatt_char_info *char_info = l2->data;
1378 if (g_strcmp0(char_info->char_path, char_path) == 0) {
1379 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1380 struct gatt_desc_info *desc_info = l3->data;
1381 if (g_strcmp0(desc_info->desc_path,
1390 BT_ERR("Gatt descriptor not found");
1394 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1398 for (l = gatt_requests; l != NULL; l = l->next) {
1399 struct gatt_req_info *req_info = l->data;
1401 if (req_info && req_info->request_id == request_id)
1404 BT_ERR("Gatt Request not found");
1408 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1409 const gchar *path, const gchar *interface)
1414 g_conn = _bt_get_system_shared_conn();
1416 BT_ERR("Unable to get connection");
1420 proxy = g_dbus_proxy_new_sync(g_conn,
1421 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1423 interface, NULL, &err);
1427 BT_ERR("Unable to create proxy: %s", err->message);
1428 g_clear_error(&err);
1432 manager_gproxy = proxy;
1437 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1438 const gchar *path, const gchar *interface)
1440 return (manager_gproxy) ? manager_gproxy :
1441 __bt_gatt_gdbus_init_manager_proxy(service,
1445 static gboolean __bt_gatt_is_service_registered(const char *service_path)
1447 struct gatt_service_info *svc_info = NULL;
1449 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1451 if (svc_info != NULL) {
1452 BT_DBG("Return the state of the gatt service %d",
1453 svc_info->is_svc_registered);
1454 return svc_info->is_svc_registered;
1457 BT_DBG("gatt service info is NULL");
1461 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1463 GError *error = NULL;
1465 GVariantIter *iter = NULL;
1466 const gchar *key = NULL;
1467 GVariant *value = NULL;
1468 const gchar *service = NULL;
1469 const gchar *characteristic = NULL;
1470 const gchar *descriptor = NULL;
1474 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1476 if (result == NULL) {
1477 BT_ERR("Dbus-RPC is failed");
1478 if (error != NULL) {
1479 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1480 error->code, error->message);
1481 g_clear_error(&error);
1484 char *char_cmp = NULL;
1485 g_variant_get(result, "(a{sv})", &iter);
1486 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1488 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1489 if (g_strcmp0(key, "Service") == 0) {
1490 service = g_variant_get_string(value, NULL);
1491 BT_DBG("Service %s", service);
1492 } else if (g_strcmp0(key, char_cmp) == 0) {
1493 characteristic = g_variant_get_string(value, NULL);
1495 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1496 BT_DBG("%s", characteristic);
1497 } else if (g_strcmp0(key, "Descriptor") == 0) {
1498 descriptor = g_variant_get_string(value, NULL);
1499 BT_DBG("Descriptor %s", descriptor);
1502 g_variant_iter_free(iter);
1504 /* TODO: Store the service informationa and
1505 * Send respponse to CAPI layer. */
1507 g_variant_unref(result);
1512 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1514 BT_INFO("RegisterApplication is completed");
1516 GError *error = NULL;
1519 if (register_cancel) {
1520 g_object_unref(register_cancel);
1521 register_cancel = NULL;
1524 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1525 if (result == NULL) {
1526 BT_ERR("Dbus-RPC is failed");
1527 if (error != NULL) {
1528 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1529 error->code, error->message);
1530 g_clear_error(&error);
1532 is_server_started = false;
1534 g_variant_unref(result);
1538 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1540 GDBusProxy *proxy = NULL;
1542 if (is_server_started) {
1546 if (app_path == NULL) {
1547 BT_ERR("app_path is NULL");
1548 return BLUETOOTH_ERROR_INTERNAL;
1551 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1552 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1553 if (proxy == NULL) {
1554 BT_ERR("proxy is NULL");
1555 return BLUETOOTH_ERROR_INTERNAL;
1558 BT_INFO("UnregisterApplication");
1560 /* Async Call to Unregister Service */
1561 ret = g_dbus_proxy_call_sync(proxy, "UnregisterApplication",
1562 g_variant_new("(o)", app_path), G_DBUS_CALL_FLAGS_NONE, -1,
1565 BT_ERR("dBUS-RPC is failed");
1567 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1568 err->code, err->message);
1569 g_clear_error(&err);
1571 return BLUETOOTH_ERROR_INTERNAL;
1573 g_variant_unref(ret);
1575 is_server_started = false;
1577 BT_INFO("UnregisterApplication is completed");
1579 return BLUETOOTH_ERROR_NONE;
1582 BT_INFO("GATT server not started");
1583 return BLUETOOTH_ERROR_NONE;
1586 BT_EXPORT_API int bluetooth_gatt_init(void)
1588 GError *error = NULL;
1589 GDBusNodeInfo *node_info = NULL;
1591 if (app_path != NULL) {
1592 BT_ERR("app path already exists! initialized");
1593 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1596 g_conn = _bt_get_system_shared_conn();
1598 BT_ERR("Unable to get connection");
1602 if (owner_id == 0) {
1603 gchar *name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
1604 BT_DBG("well-known name: %s", name);
1606 owner_id = g_bus_own_name_on_connection(g_conn, name,
1607 G_BUS_NAME_OWNER_FLAGS_NONE,
1608 NULL, NULL, NULL, NULL);
1611 BT_DBG("owner_id is [%d]", owner_id);
1613 app_path = g_strdup_printf("/com/%d", getpid());
1617 /* Register ObjectManager interface */
1618 node_info = __bt_gatt_create_method_node_info(
1619 manager_introspection_xml);
1620 if (node_info == NULL) {
1621 BT_ERR("failed to get node info");
1625 if (manager_id == 0) {
1626 BT_INFO("manager_id does not exists");
1628 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1629 node_info->interfaces[0],
1630 &manager_interface_vtable,
1631 NULL, NULL, &error);
1633 g_dbus_node_info_unref(node_info);
1634 if (manager_id == 0) {
1635 BT_ERR("failed to register: %s", error->message);
1636 g_error_free(error);
1640 return BLUETOOTH_ERROR_NONE;
1644 g_bus_unown_name(owner_id);
1651 return BLUETOOTH_ERROR_INTERNAL;
1654 BT_EXPORT_API int bluetooth_gatt_deinit()
1656 int ret = BLUETOOTH_ERROR_NONE;
1658 if (register_cancel) {
1659 g_cancellable_cancel(register_cancel);
1660 g_object_unref(register_cancel);
1661 register_cancel = NULL;
1664 if (owner_id == 0) {
1665 BT_ERR("owner_id is zero");
1666 return BLUETOOTH_ERROR_NOT_FOUND;
1669 BT_DBG("Removing all registered gatt services");
1670 bluetooth_gatt_delete_services();
1672 /* Unregister the exported interface for object manager */
1674 g_dbus_connection_unregister_object(g_conn, manager_id);
1678 ret = bluetooth_gatt_unregister_application();
1679 if (ret != BLUETOOTH_ERROR_NONE) {
1680 BT_ERR("Fail to unregister application");
1683 g_bus_unown_name(owner_id);
1689 if (manager_gproxy) {
1690 g_object_unref(manager_gproxy);
1691 manager_gproxy = NULL;
1698 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1701 GError *error = NULL;
1703 GDBusNodeInfo *node_info;
1705 GVariantBuilder *builder = NULL;
1706 GVariantBuilder *builder1 = NULL;
1707 GVariantBuilder *inner_builder = NULL;
1708 gboolean svc_primary = TRUE;
1709 struct gatt_service_info *serv_info = NULL;
1711 node_info = __bt_gatt_create_method_node_info(
1712 service_introspection_xml);
1713 if (node_info == NULL)
1714 return BLUETOOTH_ERROR_INTERNAL;
1716 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1717 BT_DBG("gatt service path is [%s]", path);
1719 object_id = g_dbus_connection_register_object(g_conn, path,
1720 node_info->interfaces[0],
1721 &serv_interface_vtable,
1722 NULL, NULL, &error);
1723 g_dbus_node_info_unref(node_info);
1725 if (object_id == 0) {
1726 BT_ERR("failed to register: %s", error->message);
1727 g_error_free(error);
1730 return BLUETOOTH_ERROR_INTERNAL;
1733 /* Add object_id/gatt service information; it's required at the time of
1734 * service unregister and Getmanagedobjects
1736 serv_info = g_new0(struct gatt_service_info, 1);
1738 serv_info->serv_path = g_strdup(path);
1739 serv_info->serv_id = object_id;
1740 serv_info->service_uuid = g_strdup(svc_uuid);
1741 serv_info->is_svc_registered = FALSE;
1742 serv_info->is_svc_primary = svc_primary;
1744 gatt_services = g_slist_append(gatt_services, serv_info);
1746 /* emit interfacesadded signal here for service path */
1747 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1748 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1750 g_variant_builder_add(inner_builder, "{sv}",
1751 "UUID", g_variant_new_string(svc_uuid));
1753 g_variant_builder_add(inner_builder, "{sv}",
1754 "Primary", g_variant_new_boolean(svc_primary));
1756 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1758 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1759 g_variant_new("ao", builder1));
1761 g_variant_builder_add(builder, "{sa{sv}}",
1762 GATT_SERV_INTERFACE, inner_builder);
1764 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1765 "org.freedesktop.Dbus.ObjectManager",
1767 g_variant_new("(oa{sa{sv}})",
1770 if (error != NULL) {
1771 /* dbus gives error cause */
1772 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1773 error->code, error->message);
1774 g_clear_error(&error);
1779 *svc_path = g_strdup(path);
1782 g_variant_builder_unref(inner_builder);
1783 g_variant_builder_unref(builder);
1784 g_variant_builder_unref(builder1);
1786 return BLUETOOTH_ERROR_NONE;
1789 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1790 const char *svc_path, const char *char_uuid,
1791 bt_gatt_permission_t permissions,
1792 bt_gatt_characteristic_property_t properties,
1796 GError *error = NULL;
1798 GDBusNodeInfo *node_info;
1800 GVariantBuilder *builder = NULL;
1801 GVariantBuilder *inner_builder = NULL;
1802 struct gatt_service_info *serv_info = NULL;
1803 struct gatt_char_info *char_info = NULL;
1804 GVariantBuilder *builder2 = NULL;
1805 GVariantBuilder *builder3 = NULL;
1806 GVariant *flags_val = NULL;
1808 char *char_flags[NUMBER_OF_FLAGS];
1813 new_service = FALSE;
1816 BT_DBG("gatt svc_path path is [%s]", svc_path);
1817 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1818 if (serv_info == NULL)
1819 return BLUETOOTH_ERROR_INVALID_PARAM;
1821 node_info = __bt_gatt_create_method_node_info(
1822 characteristics_introspection_xml);
1823 if (node_info == NULL)
1824 return BLUETOOTH_ERROR_INTERNAL;
1826 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1827 BT_DBG("gatt characteristic path is [%s]", path);
1829 object_id = g_dbus_connection_register_object(g_conn, path,
1830 node_info->interfaces[0],
1831 &char_interface_vtable,
1832 NULL, NULL, &error);
1833 g_dbus_node_info_unref(node_info);
1835 if (object_id == 0) {
1836 BT_ERR("failed to register: %s", error->message);
1837 g_error_free(error);
1840 return BLUETOOTH_ERROR_INTERNAL;
1843 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1844 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1845 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1846 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1847 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1848 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1849 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1850 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1852 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1854 char_info = g_new0(struct gatt_char_info, 1);
1856 char_info->char_path = g_strdup(path);
1857 char_info->char_id = object_id;
1858 char_info->char_uuid = g_strdup(char_uuid);
1860 for (i = 0; i < flag_count; i++)
1861 char_info->char_flags[i] = char_flags[i];
1864 char_info->flags_length = flag_count;
1866 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1868 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1869 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1871 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1872 g_variant_new("s", char_uuid));
1873 g_variant_builder_add(inner_builder, "{sv}", "Service",
1874 g_variant_new("o", svc_path));
1876 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1878 for (i = 0; i < flag_count; i++)
1879 g_variant_builder_add(builder2, "s", char_flags[i]);
1881 flags_val = g_variant_new("as", builder2);
1882 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1885 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1887 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1888 g_variant_new("ao", builder3));
1890 g_variant_builder_add(builder, "{sa{sv}}",
1891 GATT_CHAR_INTERFACE,
1894 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1895 "org.freedesktop.Dbus.ObjectManager",
1897 g_variant_new("(oa{sa{sv}})",
1901 /* dBUS gives error cause */
1902 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1903 error->code, error->message);
1904 g_clear_error(&error);
1907 *char_path = g_strdup(path);
1913 g_variant_builder_unref(inner_builder);
1914 g_variant_builder_unref(builder);
1915 g_variant_builder_unref(builder2);
1916 g_variant_builder_unref(builder3);
1918 return BLUETOOTH_ERROR_NONE;
1921 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1922 const char *characteristic, const char *char_value,
1925 gchar **line_argv = NULL;
1926 char *serv_path = NULL;
1927 struct gatt_char_info *char_info = NULL;
1928 GVariantBuilder *builder1 = NULL;
1929 GVariantBuilder *builder = NULL;
1930 GVariantBuilder *inner_builder = NULL;
1931 GVariant *char_val = NULL;
1932 GError *error = NULL;
1934 int res = BLUETOOTH_ERROR_NONE;
1936 line_argv = g_strsplit_set(characteristic, "/", 0);
1937 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1939 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1941 if (char_info == NULL) {
1942 /* Fix : RESOURCE_LEAK */
1943 res = BLUETOOTH_ERROR_INVALID_PARAM;
1947 char_info->value_length = value_length;
1949 char_info->char_value = (char *)malloc(value_length);
1950 /* Fix : NULL_RETURNS */
1951 if (char_info->char_value == NULL) {
1952 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1956 for (i = 0; i < value_length; i++)
1957 char_info->char_value[i] = char_value[i];
1959 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1960 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1962 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1964 for (i = 0; i < value_length; i++)
1965 g_variant_builder_add(builder1, "y", char_value[i]);
1967 char_val = g_variant_new("ay", builder1);
1968 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1970 g_variant_builder_add(builder, "{sa{sv}}",
1971 GATT_CHAR_INTERFACE,
1974 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1975 "org.freedesktop.Dbus.ObjectManager",
1977 g_variant_new("(oa{sa{sv}})",
1978 char_info->char_path, builder),
1982 /* dBUS gives error cause */
1983 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1984 error->code, error->message);
1985 g_clear_error(&error);
1987 g_variant_builder_unref(inner_builder);
1988 g_variant_builder_unref(builder);
1989 g_variant_builder_unref(builder1);
1991 g_strfreev(line_argv);
1997 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
1998 const char *char_path, const char *desc_uuid,
1999 bt_gatt_permission_t permissions,
2002 static int desc_id = 1;
2003 GError *error = NULL;
2005 GDBusNodeInfo *node_info;
2007 GVariantBuilder *builder = NULL;
2008 GVariantBuilder *inner_builder = NULL;
2009 struct gatt_char_info *char_info = NULL;
2010 struct gatt_desc_info *desc_info = NULL;
2011 gchar **line_argv = NULL;
2013 GVariantBuilder *builder2 = NULL;
2014 GVariant *flags_val = NULL;
2016 char *desc_flags[NUMBER_OF_FLAGS];
2024 line_argv = g_strsplit_set(char_path, "/", 0);
2025 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2027 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2028 if (char_info == NULL) {
2029 g_strfreev(line_argv);
2031 return BLUETOOTH_ERROR_INVALID_PARAM;
2034 node_info = __bt_gatt_create_method_node_info(
2035 descriptor_introspection_xml);
2036 if (node_info == NULL) {
2037 g_strfreev(line_argv);
2039 return BLUETOOTH_ERROR_INTERNAL;
2042 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2043 BT_DBG("gatt descriptor path is [%s]", path);
2045 object_id = g_dbus_connection_register_object(g_conn, path,
2046 node_info->interfaces[0],
2047 &desc_interface_vtable,
2048 NULL, NULL, &error);
2049 g_dbus_node_info_unref(node_info);
2051 if (object_id == 0) {
2052 BT_ERR("failed to register: %s", error->message);
2053 g_error_free(error);
2055 g_strfreev(line_argv);
2058 return BLUETOOTH_ERROR_INTERNAL;
2061 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2063 desc_info = g_new0(struct gatt_desc_info, 1);
2065 desc_info->desc_path = g_strdup(path);
2066 desc_info->desc_id = object_id;
2067 desc_info->desc_uuid = g_strdup(desc_uuid);
2069 for (i = 0; i < flag_count; i++)
2070 desc_info->desc_flags[i] = desc_flags[i];
2072 desc_info->flags_length = flag_count;
2074 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2076 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2077 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2079 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2080 g_variant_new("s", desc_uuid));
2081 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2082 g_variant_new("o", char_path));
2084 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2086 for (i = 0; i < flag_count; i++)
2087 g_variant_builder_add(builder2, "s", desc_flags[i]);
2089 flags_val = g_variant_new("as", builder2);
2090 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2093 g_variant_builder_add(builder, "{sa{sv}}",
2094 GATT_DESC_INTERFACE,
2097 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2098 "org.freedesktop.Dbus.ObjectManager",
2100 g_variant_new("(oa{sa{sv}})",
2104 /* dBUS gives error cause */
2105 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2106 error->code, error->message);
2107 g_clear_error(&error);
2110 *desc_path = g_strdup(path);
2114 g_strfreev(line_argv);
2115 g_variant_builder_unref(inner_builder);
2116 g_variant_builder_unref(builder);
2117 g_variant_builder_unref(builder2);
2119 return BLUETOOTH_ERROR_NONE;
2122 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2123 const char *desc_path, const char *desc_value,
2126 GError *error = NULL;
2127 GVariantBuilder *builder = NULL;
2128 GVariantBuilder *inner_builder = NULL;
2129 GVariantBuilder *builder1 = NULL;
2130 struct gatt_desc_info *desc_info = NULL;
2131 gchar **line_argv = NULL;
2133 GVariant *desc_val = NULL;
2134 char *serv_path = NULL;
2137 line_argv = g_strsplit_set(desc_path, "/", 0);
2138 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2139 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2141 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2143 /* Free the allocated memory */
2144 g_strfreev(line_argv);
2148 /* Fix : NULL_RETURNS */
2149 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2151 desc_info->desc_value = (char *)malloc(value_length);
2153 /* Fix : NULL_RETURNS */
2154 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2156 for (i = 0; i < value_length; i++)
2157 desc_info->desc_value[i] = desc_value[i];
2159 desc_info->value_length = value_length;
2161 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2162 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2164 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2166 for (i = 0; i < value_length; i++)
2167 g_variant_builder_add(builder1, "y", desc_value[i]);
2169 desc_val = g_variant_new("ay", builder1);
2170 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2172 g_variant_builder_add(builder, "{sa{sv}}",
2173 GATT_DESC_INTERFACE,
2176 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2177 "org.freedesktop.Dbus.ObjectManager",
2179 g_variant_new("(oa{sa{sv}})",
2180 desc_info->desc_path, builder),
2183 if (error != NULL) {
2184 BT_ERR("D-Bus API failure: errCode[%x], \
2186 error->code, error->message);
2187 g_clear_error(&error);
2190 g_variant_builder_unref(inner_builder);
2191 g_variant_builder_unref(builder);
2192 g_variant_builder_unref(builder1);
2194 return BLUETOOTH_ERROR_NONE;
2197 int bluetooth_gatt_get_service(const char *svc_uuid)
2199 GDBusProxy *proxy = NULL;
2202 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2203 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2205 return BLUETOOTH_ERROR_INTERNAL;
2207 uuid = g_strdup(svc_uuid);
2209 g_dbus_proxy_call(proxy,
2211 g_variant_new("(s)",
2213 G_DBUS_CALL_FLAGS_NONE, -1,
2215 (GAsyncReadyCallback) get_service_cb,
2220 return BLUETOOTH_ERROR_NONE;
2223 BT_EXPORT_API int bluetooth_gatt_register_service(const char *svc_path)
2225 struct gatt_service_info *svc_info = NULL;
2227 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2228 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2229 BT_ERR("Don't have aprivilege to use this API");
2230 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2233 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2234 if (svc_info == NULL) {
2235 BT_ERR("Cannot find service [%s]", svc_path);
2236 return BLUETOOTH_ERROR_INTERNAL;
2238 svc_info->is_svc_registered = TRUE;
2240 return BLUETOOTH_ERROR_NONE;
2243 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2245 GDBusProxy *proxy = NULL;
2247 if (!is_server_started) {
2248 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2249 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2250 BT_ERR("Don't have aprivilege to use this API");
2251 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2254 if (g_slist_length(gatt_services) == 0) {
2255 BT_ERR("There is no registered service");
2256 return BLUETOOTH_ERROR_INTERNAL;
2259 if (app_path == NULL) {
2260 BT_ERR("app_path is NULL");
2261 return BLUETOOTH_ERROR_INTERNAL;
2264 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2265 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2266 if (proxy == NULL) {
2267 BT_ERR("proxy is NULL");
2268 return BLUETOOTH_ERROR_INTERNAL;
2271 BT_INFO("RegisterApplication");
2273 if (register_cancel) {
2274 g_cancellable_cancel(register_cancel);
2275 g_object_unref(register_cancel);
2277 register_cancel = g_cancellable_new();
2279 g_dbus_proxy_call(proxy, "RegisterApplication",
2280 g_variant_new("(oa{sv})", app_path, NULL),
2281 G_DBUS_CALL_FLAGS_NONE, -1, register_cancel,
2282 (GAsyncReadyCallback)register_application_cb, NULL);
2284 is_server_started = true;
2286 return BLUETOOTH_ERROR_NONE;
2289 BT_INFO("Already RegisterApplication");
2291 return BLUETOOTH_ERROR_NONE;
2294 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2297 int ret = BLUETOOTH_ERROR_NONE;
2299 if (gatt_services == NULL) {
2300 BT_DBG("There are no registered services");
2305 for (l = gatt_services; l != NULL; ) {
2306 struct gatt_service_info *info = l->data;
2308 // In __bt_gatt_unregister_service, current node will be removed.
2309 // Go forward to next node before calling __bt_gatt_unregister_service.
2311 if (__bt_gatt_unregister_service(info) != BLUETOOTH_ERROR_NONE) {
2312 ret = BLUETOOTH_ERROR_INTERNAL;
2315 BT_INFO("All services are removed : %d", ret);
2317 g_slist_free(gatt_services);
2318 gatt_services = NULL;
2324 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2325 const char *char_path, const char* char_value,
2328 GVariantBuilder *outer_builder;
2329 GVariantBuilder *inner_builder;
2330 GVariantBuilder *invalidated_builder;
2331 GVariant *update_value = NULL;
2332 GError *error = NULL;
2333 gboolean ret = FALSE;
2334 int err = BLUETOOTH_ERROR_NONE;
2336 gchar **line_argv = NULL;
2337 gchar *serv_path = NULL;
2338 const char *value = NULL;
2340 line_argv = g_strsplit_set(char_path, "/", 0);
2341 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2343 if (!__bt_gatt_is_service_registered(serv_path)) {
2344 BT_DBG("service not registered for this characteristic");
2346 g_strfreev(line_argv);
2347 return BLUETOOTH_ERROR_INTERNAL;
2350 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2351 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2353 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2354 for (i = 0; i < value_length; i++)
2355 g_variant_builder_add(inner_builder, "y", char_value[i]);
2357 update_value = g_variant_new("ay", inner_builder);
2359 g_variant_builder_add(outer_builder, "{sv}", "Value",
2362 BT_DBG("Updating characteristic value");
2363 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2365 "org.freedesktop.DBus.Properties",
2366 "PropertiesChanged",
2367 g_variant_new("(sa{sv}as)",
2368 "org.bluez.GattCharacteristic1",
2369 outer_builder, invalidated_builder),
2373 if (error != NULL) {
2374 BT_ERR("D-Bus API failure: errCode[%x], \
2376 error->code, error->message);
2377 g_clear_error(&error);
2379 err = BLUETOOTH_ERROR_INTERNAL;
2381 struct gatt_char_info *char_info = NULL;
2383 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2384 if (char_info == NULL) {
2386 g_strfreev(line_argv);
2387 g_variant_builder_unref(inner_builder);
2388 g_variant_builder_unref(outer_builder);
2389 g_variant_builder_unref(invalidated_builder);
2391 return BLUETOOTH_ERROR_INVALID_DATA;
2394 char_info->value_length = value_length;
2396 value = (char *)realloc(char_info->char_value, value_length);
2397 if (value == NULL) {
2399 g_strfreev(line_argv);
2400 g_variant_builder_unref(inner_builder);
2401 g_variant_builder_unref(outer_builder);
2402 g_variant_builder_unref(invalidated_builder);
2404 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2407 char_info->char_value = (char*)value;
2408 if (char_info->char_value) {
2409 for (i = 0; i < value_length; i++)
2410 char_info->char_value[i] = char_value[i];
2415 g_strfreev(line_argv);
2416 g_variant_builder_unref(inner_builder);
2417 g_variant_builder_unref(outer_builder);
2418 g_variant_builder_unref(invalidated_builder);
2423 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2430 g_free(desc_info->desc_path);
2431 g_free(desc_info->desc_uuid);
2432 g_free(desc_info->desc_value);
2434 for (i = 0; i < desc_info->flags_length; i++)
2435 g_free(desc_info->desc_flags[i]);
2440 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2447 g_free(char_info->char_path);
2448 g_free(char_info->char_uuid);
2449 g_free(char_info->char_value);
2451 for (i = 0; i < char_info->flags_length; i++)
2452 g_free(char_info->char_flags[i]);
2457 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2462 g_free(svc_info->serv_path);
2463 g_free(svc_info->service_uuid);
2467 static void __desc_info_free(gpointer data, gpointer user_data)
2469 struct gatt_desc_info *desc_info = data;
2470 int *err = user_data;
2473 if (desc_info == NULL)
2476 ret = g_dbus_connection_unregister_object(g_conn, desc_info->desc_id);
2478 __bt_gatt_emit_interface_removed(desc_info->desc_path, GATT_DESC_INTERFACE);
2480 *err = BLUETOOTH_ERROR_INTERNAL;
2482 __bt_gatt_free_descriptor_info(desc_info);
2485 static void __char_info_free(gpointer data, gpointer user_data)
2487 struct gatt_char_info *char_info = data;
2488 int *err = user_data;
2491 if (char_info == NULL)
2494 g_slist_foreach(char_info->desc_data, __desc_info_free, user_data);
2495 g_slist_free(char_info->desc_data);
2496 char_info->desc_data = NULL;
2498 ret = g_dbus_connection_unregister_object(g_conn, char_info->char_id);
2500 __bt_gatt_emit_interface_removed(char_info->char_path, GATT_CHAR_INTERFACE);
2502 *err = BLUETOOTH_ERROR_INTERNAL;
2504 __bt_gatt_free_characteristic_info(char_info);
2507 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info)
2509 int ret = BLUETOOTH_ERROR_NONE;
2511 if (svc_info == NULL) {
2512 BT_ERR("svc_info is NULL");
2513 return BLUETOOTH_ERROR_NOT_FOUND;
2516 if (svc_info->is_svc_registered == FALSE) {
2517 BT_ERR("%s is not registered", svc_info->serv_path);
2518 return BLUETOOTH_ERROR_NOT_FOUND;
2521 BT_DBG("svc_path %s", svc_info->serv_path);
2523 g_slist_foreach(svc_info->char_data, __char_info_free, &ret);
2524 g_slist_free(svc_info->char_data);
2525 svc_info->char_data = NULL;
2527 if (g_dbus_connection_unregister_object(g_conn, svc_info->serv_id) == FALSE) {
2528 BT_ERR("Cannot unregister object for [%s]", svc_info->serv_path);
2529 ret = BLUETOOTH_ERROR_INTERNAL;
2531 __bt_gatt_emit_interface_removed(svc_info->serv_path, GATT_SERV_INTERFACE);
2534 gatt_services = g_slist_remove(gatt_services, svc_info);
2535 __bt_gatt_free_service_info(svc_info);
2537 new_service = FALSE;
2539 if (gatt_services == NULL) {
2541 } else if (gatt_services->next == NULL) {
2548 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2550 struct gatt_service_info *svc_info;
2551 int ret = BLUETOOTH_ERROR_NONE;
2555 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2557 ret = __bt_gatt_unregister_service(svc_info);
2558 if (ret != BLUETOOTH_ERROR_NONE) {
2559 BT_ERR("Could not unregister service [%s]", svc_path);
2566 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2567 int resp_state, int offset, char *value, int value_length)
2569 struct gatt_req_info *req_info = NULL;
2571 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2572 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2573 BT_ERR("Don't have aprivilege to use this API");
2574 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2577 req_info = __bt_gatt_find_request_info(request_id);
2578 if (req_info == NULL) {
2579 BT_ERR("Coundn't find request id [%d]", request_id);
2580 return BLUETOOTH_ERROR_INTERNAL;
2583 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2584 BT_ERR("resp_state is 0x%X", resp_state);
2585 char err_msg[20] = { 0, };
2586 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2587 g_dbus_method_invocation_return_dbus_error(req_info->context,
2588 "org.bluez.Error.Failed", err_msg);
2590 gatt_requests = g_slist_remove(gatt_requests, req_info);
2592 req_info->context = NULL;
2593 if (req_info->attr_path)
2594 g_free(req_info->attr_path);
2595 if (req_info->svc_path)
2596 g_free(req_info->svc_path);
2599 return BLUETOOTH_ERROR_NONE;
2602 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2604 GVariantBuilder *inner_builder = NULL;
2605 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2606 if (value_length > 0 && value != NULL) {
2607 for (i = 0; i < value_length; i++)
2608 g_variant_builder_add(inner_builder, "y", value[i]);
2610 g_dbus_method_invocation_return_value(req_info->context,
2611 g_variant_new("(ay)", inner_builder));
2612 g_variant_builder_unref(inner_builder);
2614 g_dbus_method_invocation_return_value(req_info->context, NULL);
2616 gatt_requests = g_slist_remove(gatt_requests, req_info);
2618 req_info->context = NULL;
2619 if (req_info->attr_path)
2620 g_free(req_info->attr_path);
2621 if (req_info->svc_path)
2622 g_free(req_info->svc_path);
2625 return BLUETOOTH_ERROR_NONE;
2628 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2629 bluetooth_device_address_t *unicast_address)
2631 GVariantBuilder *outer_builder;
2632 GVariantBuilder *invalidated_builder;
2633 GError *error = NULL;
2634 gboolean notify = TRUE;
2635 gboolean ret = TRUE;
2636 int err = BLUETOOTH_ERROR_NONE;
2637 gchar **line_argv = NULL;
2638 gchar *serv_path = NULL;
2639 char addr[20] = { 0 };
2641 line_argv = g_strsplit_set(char_path, "/", 0);
2642 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2644 if (!__bt_gatt_is_service_registered(serv_path)) {
2645 BT_DBG("service not registered for this characteristic");
2647 g_strfreev(line_argv);
2648 return BLUETOOTH_ERROR_INTERNAL;
2653 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2654 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2656 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2657 g_variant_new("b", notify));
2659 if (unicast_address) {
2660 _bt_convert_addr_type_to_string(addr,
2661 (unsigned char *)unicast_address->addr);
2663 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2664 g_variant_new("s", addr));
2666 BT_DBG("Set characteristic Notification");
2667 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2669 "org.freedesktop.DBus.Properties",
2670 "PropertiesChanged",
2671 g_variant_new("(sa{sv}as)",
2672 "org.bluez.GattCharacteristic1",
2673 outer_builder, invalidated_builder),
2677 if (error != NULL) {
2678 BT_ERR("D-Bus API failure: errCode[%x], \
2680 error->code, error->message);
2681 g_clear_error(&error);
2683 err = BLUETOOTH_ERROR_INTERNAL;
2686 g_strfreev(line_argv);
2687 g_variant_builder_unref(outer_builder);
2688 g_variant_builder_unref(invalidated_builder);
2695 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2699 if (!is_server_started) {
2701 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2702 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2703 BT_ERR("Don't have aprivilege to use this API");
2704 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2707 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2708 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2710 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2711 in_param1, in_param2, in_param3, in_param4, &out_param);
2712 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2714 if (ret != BLUETOOTH_ERROR_NONE) {
2715 BT_ERR("Register application failed");
2718 is_server_started = true;
2720 return BLUETOOTH_ERROR_NONE;
2723 BT_INFO("Already RegisterApplication");
2724 return BLUETOOTH_ERROR_NONE;
2728 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2731 int ret = BLUETOOTH_ERROR_NONE;
2734 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2736 /* Register event handler for GATT */
2737 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2739 if (ret != BLUETOOTH_ERROR_NONE &&
2740 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2741 BT_ERR("Fail to init the event handler");
2742 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2746 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2747 in_param1, in_param2, in_param3, in_param4, &out_param);
2749 /* App ID -1 is invalid */
2750 if (ret != BLUETOOTH_ERROR_NONE) {
2751 BT_INFO("GATT Server Registration failed result [%d]", ret);
2754 *instance_id = g_array_index(out_param, int, 0);
2755 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2759 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2761 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2765 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2768 BT_INFO("GATT Server Deinitialize");
2769 /* Unregister the event */
2770 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2772 if (ret != BLUETOOTH_ERROR_NONE) {
2773 BT_ERR("Fail to deinit the event handler");
2777 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2782 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2783 int instance_id, int *service_handle)
2785 BT_CHECK_ENABLED(return);
2786 BT_CHECK_PARAMETER(svc_uuid, return);
2789 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2791 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2794 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2796 g_array_append_vals(in_param1, &type, sizeof(int));
2797 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2798 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2799 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2801 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2802 in_param1, in_param2, in_param3, in_param4, &out_param);
2804 /* ATT handle 0 is reserved, hence it can not be used by app.
2805 It will be used to indicate error in regsitering attribute */
2806 if (result != BLUETOOTH_ERROR_NONE)
2807 *service_handle = 0;
2809 *service_handle = g_array_index(out_param, int, 0);
2811 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2816 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2817 const bluetooth_gatt_server_attribute_params_t *param,
2820 BT_CHECK_ENABLED(return);
2821 BT_CHECK_PARAMETER(char_uuid, return);
2822 BT_CHECK_PARAMETER(param, return);
2825 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2827 char *char_flags[NUMBER_OF_FLAGS];
2829 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2830 flag_count = bluetooth_gatt_convert_prop2string(param->properties, char_flags);
2831 BT_INFO("Flag count [%d]", flag_count);
2834 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2836 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2837 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2839 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2840 in_param1, in_param2, in_param3, in_param4, &out_param);
2842 /* ATT handle 0 is reserved, hence it can not be used by app.
2843 It will be used to indicate error in regsitering attribute */
2844 if (result != BLUETOOTH_ERROR_NONE) {
2845 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2848 *char_handle = g_array_index(out_param, int, 0);
2849 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2852 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2856 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2857 int service_handle, int instance_id, int *descriptor_handle)
2859 BT_CHECK_ENABLED(return);
2860 BT_CHECK_PARAMETER(desc_uuid, return);
2863 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2865 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2868 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2870 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2871 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2872 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2873 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2875 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2876 in_param1, in_param2, in_param3, in_param4, &out_param);
2878 /* ATT handle 0 is reserved, hence it can not be used by app.
2879 It will be used to indicate error in regsitering attribute */
2880 if (result != BLUETOOTH_ERROR_NONE) {
2881 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2882 *descriptor_handle = 0;
2884 *descriptor_handle = g_array_index(out_param, int, 0);
2885 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2888 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2893 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2895 BT_CHECK_ENABLED(return);
2899 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2901 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2902 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2904 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2905 in_param1, in_param2, in_param3, in_param4, &out_param);
2907 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2912 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2913 const bluetooth_gatt_att_data_t *value)
2915 BT_CHECK_PARAMETER(param, return);
2916 BT_CHECK_PARAMETER(value, return);
2917 BT_CHECK_ENABLED(return);
2921 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2923 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
2924 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
2926 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
2927 in_param1, in_param2, in_param3, in_param4, &out_param);
2929 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2935 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
2936 const bluetooth_gatt_server_indication_params_t *param,
2937 const bluetooth_gatt_att_data_t *att_value)
2939 BT_CHECK_PARAMETER(param, return);
2940 BT_CHECK_PARAMETER(att_value, return);
2941 BT_CHECK_ENABLED(return);
2943 char addr[BLUETOOTH_ADDRESS_STRING_LENGTH] ;
2947 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2949 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
2950 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
2951 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
2953 _bt_convert_addr_type_to_string(addr, addr_hex->addr);
2954 fd = bluetooth_get_characteristic_fd(param->atrribute_handle, addr);
2957 result = bluetooth_gatt_write_characteristics_value_to_fd_(fd, att_value->data, att_value->length, NULL);
2959 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
2960 in_param1, in_param2, in_param3, in_param4, &out_param);
2962 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2967 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
2969 BT_CHECK_ENABLED(return);
2973 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2975 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2976 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2978 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
2979 in_param1, in_param2, in_param3, in_param4, &out_param);
2981 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2986 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
2988 BT_CHECK_ENABLED(return);
2992 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2994 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2995 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2997 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
2998 in_param1, in_param2, in_param3, in_param4, &out_param);
3000 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3005 /* Tizen Platform Specific */
3006 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
3007 const bluetooth_gatt_server_update_value_t *value)
3009 BT_CHECK_ENABLED(return);
3010 BT_CHECK_PARAMETER(value, return);
3014 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3016 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3017 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3019 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3020 in_param1, in_param2, in_param3, in_param4, &out_param);
3022 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3027 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3029 BT_CHECK_ENABLED(return);
3033 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3035 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3037 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3038 in_param1, in_param2, in_param3, in_param4, &out_param);
3040 if (result != BLUETOOTH_ERROR_NONE)
3041 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3043 BT_INFO("GATT Server Unregistration successful");
3045 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3050 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3051 GIOCondition cond, gpointer data)
3054 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3056 BT_INFO("FD io write data received remote adress [%s]\n", write_data->address);
3058 if (cond & G_IO_IN) {
3059 GIOStatus status = G_IO_STATUS_NORMAL;
3061 char *buffer = NULL;
3063 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3065 buffer = g_malloc0(BUF);
3067 status = g_io_channel_read_chars(gio, buffer,
3070 if (status != G_IO_STATUS_NORMAL) {
3071 BT_ERR("IO Channel read is failed with %d", status);
3074 BT_ERR("IO Channel read error [%s]", err->message);
3075 if (status == G_IO_STATUS_ERROR) {
3076 BT_ERR("cond : %d", cond);
3078 g_io_channel_shutdown(gio, TRUE, NULL);
3079 g_io_channel_unref(gio);
3090 BT_INFO(" FD io sending value changed %s %zd \n", buffer, len);
3093 bluetooth_gatt_server_write_requested_info_t write_info;
3094 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3095 memcpy(write_info.data.data, buffer, len);
3097 write_info.length = len;
3098 write_info.need_resp = false;
3099 write_info.attribute_handle = write_data->attribute_handle;
3101 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->address);
3102 write_info.connection_id = write_data->connection_id;
3103 write_info.offset = write_data->offset;
3104 write_info.request_id = -2;
3106 BT_INFO("ACQUIRING EVENT \n");
3108 bt_event_info_t *event_info;
3109 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3113 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3114 BLUETOOTH_ERROR_NONE, &write_info,
3115 event_info->cb, event_info->user_data);
3117 BT_ERR("eventinfo failed");
3127 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
3128 BT_ERR("Error : GIOCondition %d, ]", cond);
3129 g_io_channel_shutdown(gio, TRUE, NULL);
3130 g_io_channel_unref(gio);
3138 void bluetooth_gatt_server_send_acquire_write_response(GVariant * parameters)
3143 int pipefd[2] = {-1,};
3146 char err_msg[512] = {'\0'};
3147 GIOChannel *channel = NULL;
3151 g_variant_get(parameters, "(iiiiii&s)",
3160 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3161 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3162 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3163 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3166 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3167 strerror_r(errno, err_msg, sizeof(err_msg));
3168 BT_ERR("socketpair(): %s", err_msg);
3173 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3175 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3176 bluetooth_gatt_server_acquire_response_params_t data;
3177 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
3178 data.fd = pipefd[1];
3180 data.request_id = tran_id;
3182 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3184 write_info->attribute_handle = att_han;
3185 write_info->connection_id = tran_id;
3186 write_info->offset = offset;
3188 memcpy(write_info->address, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3190 BT_INFO("FD read %d remote address [%s ] \n", pipefd[0], addr);
3193 channel = g_io_channel_unix_new(pipefd[0]);
3194 g_io_channel_set_encoding(channel, NULL, NULL);
3195 g_io_channel_set_buffered(channel, FALSE);
3196 g_io_channel_set_close_on_unref(channel, TRUE);
3197 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3198 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3199 bluetooth_gatt_server_acquire_channel_write_cb, write_info);
3202 GUnixFDList *fd_list = g_unix_fd_list_new();
3203 GError *error = NULL;
3205 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3206 g_assert_no_error(error);
3209 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3211 BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3213 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE,
3214 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3216 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3222 void bluetooth_gatt_server_send_acquire_notify_response(GVariant * parameters, bt_event_info_t *event_info)
3227 int pipefd[2] = {-1,};
3230 char err_msg[512] = {'\0'};
3231 GIOChannel *channel = NULL;
3234 bluetooth_gatt_acquire_notify_info_t *chr_info;
3235 const char *address = NULL;
3237 g_variant_get(parameters, "(iiiiiis)",
3246 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3247 BT_DBG("GATT Server Acquire notify att handle:[%d]", att_han);
3248 BT_DBG("GATT Server Acquire Notify Offset: [%d]", offset);
3249 BT_DBG("GATT Server Acquire Notify address: [%s]", address);
3252 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3253 strerror_r(errno, err_msg, sizeof(err_msg));
3254 BT_ERR("socketpair(): %s", err_msg);
3261 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3263 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3264 bluetooth_gatt_server_acquire_response_params_t data;
3265 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
3266 data.fd = pipefd[1];
3268 data.request_id = tran_id;
3270 BT_INFO("FD write %d characterstics path \n", pipefd[0]);
3272 chr_info = bluetooth_get_characteristic_info_from_path(att_han);
3274 chr_info = g_malloc0(sizeof(bluetooth_gatt_acquire_notify_info_t));
3275 chr_info->write_fd = fd;
3276 chr_info->att_hand = att_han;
3278 gatt_characteristic_server_notify_list = g_slist_append(gatt_characteristic_server_notify_list, chr_info);
3280 chr_info->write_fd = fd;
3283 BT_INFO("setting up g_io channel");
3284 channel = g_io_channel_unix_new(fd);
3285 g_io_channel_set_encoding(channel, NULL, NULL);
3286 g_io_channel_set_buffered(channel, FALSE);
3287 g_io_channel_set_close_on_unref(channel, TRUE);
3288 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3289 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
3290 bluetooth_gatt_write_channel_watch_cb, chr_info);
3295 GUnixFDList *fd_list = g_unix_fd_list_new();
3296 GError *error = NULL;
3298 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3299 g_assert_no_error(error);
3302 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3304 BT_INFO("Sending event BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE file descriptor value [%d] ", data.fd);
3306 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE,
3307 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3309 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3313 if (result == BLUETOOTH_ERROR_NONE) {
3315 BT_INFO("sending gatt server notification state changed event");
3316 bluetooth_gatt_server_notification_changed_t info;
3317 bluetooth_device_address_t dev_address = { {0} };
3318 memset(&info, 0x00, sizeof(bluetooth_gatt_server_notification_changed_t));
3320 _bt_convert_addr_string_to_type(dev_address.addr, address);
3321 memcpy(info.device_address.addr,
3323 BLUETOOTH_ADDRESS_LENGTH);
3324 info.handle = att_han;
3325 info.notification = TRUE;
3327 _bt_gatt_server_event_cb(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
3329 event_info->cb, event_info->user_data);
3334 void cleanup_gatt_acquire_fd(int handle)
3336 bluetooth_gatt_acquire_notify_info_t *chr_info = NULL;
3340 chr_info = bluetooth_get_characteristic_info_from_path(handle);
3342 if (chr_info != NULL) {
3343 BT_INFO("GATT Server: acquire notification char info found");
3345 if (chr_info->write_fd >= 0) {
3346 BT_INFO("closing fd");
3347 close(chr_info->write_fd);
3350 BT_INFO("Removing char_info from the list");
3351 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
3352 bluetooth_characteristic_info_free(chr_info);