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)
394 bluetooth_gatt_acquire_notify_info_t *chr_info = (bluetooth_gatt_acquire_notify_info_t *)data;
399 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
400 BT_ERR("Error : GIOCondition %d, []", cond);;
401 g_io_channel_shutdown(gio, TRUE, NULL);
402 g_io_channel_unref(gio);
404 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
405 bluetooth_characteristic_info_free(chr_info);
413 static int bluetooth_gatt_write_characteristics_value_to_fd_(
414 int fd, const guint8 *value, int length,
419 int att_result = BLUETOOTH_ERROR_NONE;
421 BT_CHECK_PARAMETER(value, return);
423 written = write(fd, value, length);
424 if (written != length) {
425 att_result = BLUETOOTH_ERROR_INTERNAL;
426 BT_INFO("write data failed %d is ", written);
428 BT_INFO("write data %s is sucess ", value);
433 static void __bt_gatt_close_gdbus_connection(void)
439 ret_if(g_conn == NULL);
441 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
442 BT_ERR("Fail to flush the connection: %s", err->message);
447 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
449 BT_ERR("Fail to close the dbus connection: %s", err->message);
454 g_object_unref(g_conn);
461 #ifdef TIZEN_FEATURE_BT_HPS
462 static int __bt_send_event_to_hps(int event, GVariant *var)
464 GError *error = NULL;
465 GVariant *parameters;
466 GDBusMessage *msg = NULL;
470 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
472 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
473 GVariantBuilder *inner_builder;
474 GVariantBuilder *invalidated_builder;
476 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
477 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
479 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
481 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
483 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
484 g_variant_builder_unref(invalidated_builder);
485 g_variant_builder_unref(inner_builder);
486 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
487 GVariantBuilder *inner_builder;
488 GVariantBuilder *invalidated_builder;
490 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
491 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
493 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
495 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
497 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
498 g_variant_builder_unref(invalidated_builder);
499 g_variant_builder_unref(inner_builder);
501 g_varaiant_unref(var);
504 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
505 g_dbus_message_set_body(msg, parameters);
506 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
508 BT_ERR("D-Bus API failure: errCode[%x], \
510 error->code, error->message);
511 g_clear_error(&error);
513 return BLUETOOTH_ERROR_INTERNAL;
515 return BLUETOOTH_ERROR_NONE;
519 #ifdef TIZEN_FEATURE_BT_OTP
520 static int __bt_send_event_to_otp(int event, GVariant *var)
522 GError *error = NULL;
523 GVariant *parameters = NULL;
524 GDBusMessage *msg = NULL;
528 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
530 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
531 GVariantBuilder *inner_builder;
532 GVariantBuilder *invalidated_builder;
534 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
535 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
537 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
539 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
541 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
542 g_variant_builder_unref(invalidated_builder);
543 g_variant_builder_unref(inner_builder);
544 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
545 GVariantBuilder *inner_builder;
546 GVariantBuilder *invalidated_builder;
548 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
549 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
551 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
553 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
555 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
556 g_variant_builder_unref(invalidated_builder);
557 g_variant_builder_unref(inner_builder);
558 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
559 GVariantBuilder *inner_builder;
560 GVariantBuilder *invalidated_builder;
562 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
563 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
565 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
567 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
569 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
570 g_variant_builder_unref(invalidated_builder);
571 g_variant_builder_unref(inner_builder);
574 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
575 g_dbus_message_set_body(msg, parameters);
576 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
578 BT_ERR("D-Bus API failure: errCode[%x], \
580 error->code, error->message);
581 g_clear_error(&error);
583 return BLUETOOTH_ERROR_INTERNAL;
585 return BLUETOOTH_ERROR_NONE;
589 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
591 const gchar *object_path,
592 const gchar *interface_name,
593 const gchar *method_name,
594 GVariant *parameters,
595 GDBusMethodInvocation *invocation,
598 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
599 BT_DBG("Getting values for service, chars and descriptors");
602 GVariantBuilder *builder = NULL;
603 GVariantBuilder *inner_builder1 = NULL;
604 GVariant *svc_char = NULL;
605 GSList *char_list = NULL;
606 GSList *desc_list = NULL;
609 builder = g_variant_builder_new(G_VARIANT_TYPE("a{oa{sa{sv}}}"));
611 /* Prepare inner builder for GattService1 interface */
612 svc_index = g_slist_length(gatt_services) - 1;
613 for (; svc_index >= 0; svc_index--) {
614 GVariantBuilder *svc_builder = NULL;
615 GVariantBuilder *inner_builder = NULL;
616 struct gatt_service_info *serv_info = NULL;
618 serv_info = g_slist_nth_data(gatt_services, svc_index);
619 if (serv_info == NULL) {
620 BT_ERR("serv_info is NULL");
624 /* Prepare inner builder for GattService1 interface */
625 BT_DBG("Creating builder for service : %s", serv_info->service_uuid);
626 svc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
627 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
629 g_variant_builder_add(inner_builder, "{sv}", "UUID",
630 g_variant_new_string(serv_info->service_uuid));
631 g_variant_builder_add(inner_builder, "{sv}", "Primary",
632 g_variant_new_boolean(serv_info->is_svc_primary));
634 /* Characteristics */
635 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
637 BT_DBG("Adding Charatarisitcs list");
638 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
639 struct gatt_char_info *char_info = char_list->data;
640 g_variant_builder_add(inner_builder1, "o", char_info->char_path);
641 BT_DBG("%s", char_info->char_path);
644 svc_char = g_variant_new("ao", inner_builder1);
645 g_variant_builder_add(inner_builder, "{sv}", "Characteristics", svc_char);
646 g_variant_builder_add(svc_builder, "{sa{sv}}", GATT_SERV_INTERFACE, inner_builder);
647 g_variant_builder_add(builder, "{oa{sa{sv}}}", serv_info->serv_path, svc_builder);
648 g_variant_builder_unref(inner_builder1);
650 /* Prepare inner builder for GattCharacteristic1 interface */
651 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
652 GVariantBuilder *char_builder = NULL;
653 GVariantBuilder *inner_builder = NULL;
654 GVariantBuilder *builder1 = NULL;
655 GVariantBuilder *builder2 = NULL;
656 GVariantBuilder *builder3 = NULL;
657 GVariant *char_val = NULL;
658 GVariant *flags_val = NULL;
659 GVariant *char_desc = NULL;
660 char *unicast = NULL;
661 gboolean notify = FALSE;
663 struct gatt_char_info *char_info = char_list->data;
665 if (char_info == NULL) {
666 BT_ERR("char_info is NULL");
670 BT_DBG("Creating builder for characteristic : %s", char_info->char_uuid);
671 char_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
672 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
675 g_variant_builder_add(inner_builder, "{sv}", "UUID",
676 g_variant_new_string(char_info->char_uuid));
679 g_variant_builder_add(inner_builder, "{sv}", "Service",
680 g_variant_new("o", serv_info->serv_path));
683 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
684 if (char_info->char_value != NULL) {
685 for (i = 0; i < char_info->value_length; i++) {
686 g_variant_builder_add(builder1, "y", char_info->char_value[i]);
688 char_val = g_variant_new("ay", builder1);
689 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
693 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
694 for (i = 0; i < char_info->flags_length; i++) {
695 g_variant_builder_add(builder2, "s", char_info->char_flags[i]);
697 flags_val = g_variant_new("as", builder2);
698 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
701 g_variant_builder_add(inner_builder, "{sv}", "Notifying", g_variant_new("b", notify));
704 unicast = g_strdup("00:00:00:00:00:00");
705 g_variant_builder_add(inner_builder, "{sv}", "Unicast", g_variant_new("s", unicast));
708 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
709 BT_DBG("Adding Descriptors list");
710 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
711 struct gatt_desc_info *desc_info = desc_list->data;
712 g_variant_builder_add(builder3, "o", desc_info->desc_path);
713 BT_DBG("%s", desc_info->desc_path);
716 char_desc = g_variant_new("ao", builder3);
717 g_variant_builder_add(inner_builder, "{sv}", "Descriptors", char_desc);
718 g_variant_builder_add(char_builder, "{sa{sv}}", GATT_CHAR_INTERFACE , inner_builder);
719 g_variant_builder_add(builder, "{oa{sa{sv}}}", char_info->char_path, char_builder);
721 /*Prepare inner builder for GattDescriptor1 interface*/
722 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
723 GVariantBuilder *desc_builder = NULL;
724 GVariantBuilder *inner_builder = NULL;
725 GVariantBuilder *builder1 = NULL;
726 GVariantBuilder *builder2 = NULL;
727 GVariant *desc_val = NULL;
728 struct gatt_desc_info *desc_info = desc_list->data;
730 if (desc_info == NULL) {
731 BT_ERR("desc_info is NULL");
735 BT_DBG("Creating builder for descriptor : %s", desc_info->desc_uuid);
736 desc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
737 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
740 g_variant_builder_add(inner_builder, "{sv}", "UUID",
741 g_variant_new_string(desc_info->desc_uuid));
744 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
745 g_variant_new("o", char_info->char_path));
748 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
749 if (desc_info->desc_value != NULL) {
750 for (i = 0; i < desc_info->value_length; i++) {
751 g_variant_builder_add(builder1, "y", desc_info->desc_value[i]);
753 desc_val = g_variant_new("ay", builder1);
754 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
758 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
759 for (i = 0; i < desc_info->flags_length; i++) {
760 g_variant_builder_add(builder2, "s", desc_info->desc_flags[i]);
762 flags_val = g_variant_new("as", builder2);
763 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
765 g_variant_builder_add(desc_builder, "{sa{sv}}", GATT_DESC_INTERFACE,
767 g_variant_builder_add(builder, "{oa{sa{sv}}}", desc_info->desc_path,
770 /* unref descriptor builder pointers */
771 g_variant_builder_unref(builder1);
772 g_variant_builder_unref(builder2);
773 g_variant_builder_unref(inner_builder);
774 g_variant_builder_unref(desc_builder);
780 /* unref char builder pointers */
781 g_variant_builder_unref(builder1);
782 g_variant_builder_unref(builder2);
783 g_variant_builder_unref(builder3);
784 g_variant_builder_unref(inner_builder);
785 g_variant_builder_unref(char_builder);
788 /* unref service builder pointers */
789 g_variant_builder_unref(inner_builder);
790 g_variant_builder_unref(svc_builder);
793 /* Return builder as method reply */
794 BT_DBG("Sending gatt service builder values to Bluez");
795 g_dbus_method_invocation_return_value(invocation,
796 g_variant_new("(a{oa{sa{sv}}})", builder));
797 g_variant_builder_unref(builder);
801 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
805 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
806 struct gatt_service_info *serv_info = l1->data;
808 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
809 struct gatt_char_info *char_info = l2->data;
811 if (g_strcmp0(char_info->char_path, char_path) == 0)
815 BT_ERR("Gatt service not found");
819 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
821 GSList *l1, *l2, *l3;
823 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
824 struct gatt_service_info *serv_info = l1->data;
826 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
827 struct gatt_char_info *char_info = l2->data;
829 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
830 struct gatt_desc_info *desc_info = l3->data;
832 if (g_strcmp0(desc_info->desc_path, desc_path) == 0)
837 BT_ERR("Gatt service not found");
841 static void __bt_gatt_char_method_call(GDBusConnection *connection,
843 const gchar *object_path,
844 const gchar *interface_name,
845 const gchar *method_name,
846 GVariant *parameters,
847 GDBusMethodInvocation *invocation,
851 if (g_strcmp0(method_name, "ReadValue") == 0) {
855 bt_gatt_read_req_t read_req = {0, };
856 bt_user_info_t *user_info = NULL;
857 struct gatt_req_info *req_info = NULL;
858 struct gatt_service_info *svc_info = NULL;
859 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
860 GVariant *param = NULL;
863 BT_DBG("Application path = %s", object_path);
864 BT_DBG("Sender = %s", sender);
866 user_info = _bt_get_user_data(BT_COMMON);
867 if (user_info == NULL) {
868 BT_INFO("No callback is set for %s", object_path);
869 g_dbus_method_invocation_return_value(invocation, NULL);
873 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
874 if (svc_info == NULL) {
875 BT_ERR("Coudn't find service for %s", object_path);
876 g_dbus_method_invocation_return_value(invocation, NULL);
880 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
881 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
883 read_req.att_handle = (char *)object_path;
884 read_req.address = addr;
885 read_req.req_id = req_id;
886 read_req.offset = offset;
887 read_req.service_handle = svc_info->serv_path;
889 /* Store requets information */
890 req_info = g_new0(struct gatt_req_info, 1);
891 req_info->attr_path = g_strdup(object_path);
892 req_info->svc_path = g_strdup(read_req.service_handle);
893 req_info->request_id = req_id;
894 req_info->offset = offset;
895 req_info->context = invocation;
896 gatt_requests = g_slist_append(gatt_requests, req_info);
898 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
899 param = g_variant_new("(sssyq)",
901 read_req.service_handle,
905 #ifdef TIZEN_FEATURE_BT_HPS
906 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
908 #ifdef TIZEN_FEATURE_BT_OTP
909 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
913 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
914 BLUETOOTH_ERROR_NONE, &read_req,
915 user_info->cb, user_info->user_data);
917 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
918 GVariant *var = NULL;
922 gboolean response_needed = FALSE;
923 bt_gatt_value_change_t value_change = {0, };
924 bt_user_info_t *user_info = NULL;
926 struct gatt_service_info *svc_info = NULL;
927 struct gatt_req_info *req_info = NULL;
928 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
929 GVariant *param = NULL;
932 BT_DBG("WriteValue");
933 BT_DBG("Application path = %s", object_path);
934 BT_DBG("Sender = %s", sender);
936 g_variant_get(parameters, "(&suqb@ay)",
937 &addr, &req_id, &offset, &response_needed, &var);
938 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
940 user_info = _bt_get_user_data(BT_COMMON);
942 BT_INFO("No callback is set for %s", object_path);
943 g_variant_unref(var);
945 g_dbus_method_invocation_return_value(invocation, NULL);
947 g_object_unref(invocation);
951 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
952 if (svc_info == NULL) {
953 BT_ERR("Coudn't find service for %s", object_path);
954 g_variant_unref(var);
956 g_dbus_method_invocation_return_value(invocation, NULL);
958 g_object_unref(invocation);
962 value_change.att_handle = (char *)object_path;
963 value_change.address = addr;
964 value_change.service_handle = svc_info->serv_path;
965 value_change.offset = offset;
966 value_change.req_id = req_id;
967 value_change.response_needed = response_needed;
969 len = g_variant_get_size(var);
973 value_change.att_value = (guint8 *)g_malloc(len);
975 data = (char *)g_variant_get_data(var);
976 memcpy(value_change.att_value, data, len);
978 value_change.val_len = len;
980 if (response_needed) {
981 /* Store requets information */
982 req_info = g_new0(struct gatt_req_info, 1);
983 req_info->attr_path = g_strdup(object_path);
984 req_info->svc_path = g_strdup(value_change.service_handle);
985 req_info->request_id = req_id;
986 req_info->offset = offset;
987 req_info->context = invocation;
988 gatt_requests = g_slist_append(gatt_requests, req_info);
990 g_object_unref(invocation);
993 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
996 svc_path = g_strdup(svc_info->serv_path);
997 param = g_variant_new("(sssyq@ay)",
1004 #ifdef TIZEN_FEATURE_BT_HPS
1005 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1007 #ifdef TIZEN_FEATURE_BT_OTP
1008 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1015 _bt_common_event_cb(
1016 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1017 BLUETOOTH_ERROR_NONE, &value_change,
1018 user_info->cb, user_info->user_data);
1020 g_free(value_change.att_value);
1021 g_variant_unref(var);
1023 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1024 bt_user_info_t *user_info = NULL;
1025 bt_gatt_char_notify_change_t notify_change = {0, };
1026 #if TIZEN_FEATURE_BT_OTP
1027 GVariant *param = NULL;
1029 BT_DBG("StartNotify");
1030 user_info = _bt_get_user_data(BT_COMMON);
1031 if (user_info != NULL) {
1032 struct gatt_service_info *svc_info = NULL;
1033 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1035 notify_change.service_handle = svc_info->serv_path;
1036 notify_change.att_handle = (char *)object_path;
1037 notify_change.att_notify = TRUE;
1038 #if TIZEN_FEATURE_BT_OTP
1039 param = g_variant_new("(ssb)",
1040 notify_change.att_handle,
1041 notify_change.service_handle,
1042 notify_change.att_notify);
1043 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1045 _bt_common_event_cb(
1046 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1047 BLUETOOTH_ERROR_NONE, ¬ify_change,
1048 user_info->cb, user_info->user_data);
1051 g_object_unref(invocation);
1053 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1054 bt_user_info_t *user_info = NULL;
1055 bt_gatt_char_notify_change_t notify_change = {0, };
1056 #if TIZEN_FEATURE_BT_OTP
1057 GVariant *param = NULL;
1059 BT_DBG("StopNotify");
1060 user_info = _bt_get_user_data(BT_COMMON);
1061 if (user_info != NULL) {
1062 struct gatt_service_info *svc_info = NULL;
1063 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1065 notify_change.service_handle = svc_info->serv_path;
1066 notify_change.att_handle = (char *)object_path;
1067 notify_change.att_notify = FALSE;
1068 #if TIZEN_FEATURE_BT_OTP
1069 param = g_variant_new("(ssb)",
1070 notify_change.att_handle,
1071 notify_change.service_handle,
1072 notify_change.att_notify);
1073 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1075 _bt_common_event_cb(
1076 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1077 BLUETOOTH_ERROR_NONE, ¬ify_change,
1078 user_info->cb, user_info->user_data);
1081 g_object_unref(invocation);
1083 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1085 bt_gatt_indicate_confirm_t confirm = {0, };
1086 bt_user_info_t *user_info = NULL;
1087 gboolean complete = FALSE;
1088 struct gatt_service_info *svc_info = NULL;
1090 BT_DBG("IndicateConfirm");
1091 BT_DBG("Application path = %s", object_path);
1092 BT_DBG("Sender = %s", sender);
1094 g_variant_get(parameters, "(&sb)", &addr, &complete);
1095 BT_DBG("Remote Device address number = %s", addr);
1097 confirm.att_handle = (char *)object_path;
1098 confirm.address = addr;
1099 confirm.complete = complete;
1101 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1102 if (svc_info != NULL) {
1103 confirm.service_handle = svc_info->serv_path;
1105 user_info = _bt_get_user_data(BT_COMMON);
1106 if (user_info != NULL) {
1107 _bt_common_event_cb(
1108 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1109 BLUETOOTH_ERROR_NONE, &confirm,
1110 user_info->cb, user_info->user_data);
1115 g_dbus_method_invocation_return_value(invocation, NULL);
1118 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1119 const gchar *sender,
1120 const gchar *object_path,
1121 const gchar *interface_name,
1122 const gchar *method_name,
1123 GVariant *parameters,
1124 GDBusMethodInvocation *invocation,
1127 if (g_strcmp0(method_name, "ReadValue") == 0) {
1131 bt_gatt_read_req_t read_req = {0, };
1132 bt_user_info_t *user_info = NULL;
1133 struct gatt_req_info *req_info = NULL;
1134 struct gatt_service_info *svc_info = NULL;
1136 BT_DBG("ReadValue");
1137 BT_DBG("Application path = %s", object_path);
1138 BT_DBG("Sender = %s", sender);
1140 user_info = _bt_get_user_data(BT_COMMON);
1141 if (user_info == NULL) {
1142 BT_INFO("No callback is set for %s", object_path);
1143 g_dbus_method_invocation_return_value(invocation, NULL);
1147 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1148 if (svc_info == NULL) {
1149 BT_ERR("Coudn't find service for %s", object_path);
1150 g_dbus_method_invocation_return_value(invocation, NULL);
1154 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1155 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1157 read_req.att_handle = (char *)object_path;
1158 read_req.address = addr;
1159 read_req.req_id = req_id;
1160 read_req.offset = offset;
1161 read_req.service_handle = svc_info->serv_path;
1163 /* Store requets information */
1164 req_info = g_new0(struct gatt_req_info, 1);
1165 req_info->attr_path = g_strdup(object_path);
1166 req_info->svc_path = g_strdup(read_req.service_handle);
1167 req_info->request_id = req_id;
1168 req_info->offset = offset;
1169 req_info->context = invocation;
1170 gatt_requests = g_slist_append(gatt_requests, req_info);
1172 _bt_common_event_cb(
1173 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1174 BLUETOOTH_ERROR_NONE, &read_req,
1175 user_info->cb, user_info->user_data);
1178 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1179 GVariant *var = NULL;
1183 gboolean response_needed = FALSE;
1184 bt_gatt_value_change_t value_change = {0, };
1185 bt_user_info_t *user_info = NULL;
1187 struct gatt_service_info *svc_info = NULL;
1188 struct gatt_req_info *req_info = NULL;
1190 BT_DBG("WriteValue");
1191 BT_DBG("Application path = %s", object_path);
1192 BT_DBG("Sender = %s", sender);
1194 g_variant_get(parameters, "(&suqb@ay)",
1195 &addr, &req_id, &offset, &response_needed, &var);
1196 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1198 user_info = _bt_get_user_data(BT_COMMON);
1199 if (user_info == NULL) {
1200 BT_INFO("No callback is set for %s", object_path);
1201 g_variant_unref(var);
1202 if (response_needed)
1203 g_dbus_method_invocation_return_value(invocation, NULL);
1205 g_object_unref(invocation);
1209 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1210 if (svc_info == NULL) {
1211 BT_ERR("Coudn't find service for %s", object_path);
1212 g_variant_unref(var);
1213 if (response_needed)
1214 g_dbus_method_invocation_return_value(invocation, NULL);
1216 g_object_unref(invocation);
1220 value_change.att_handle = (char *)object_path;
1221 value_change.address = addr;
1222 value_change.service_handle = svc_info->serv_path;
1223 value_change.offset = offset;
1224 value_change.req_id = req_id;
1225 value_change.response_needed = response_needed;
1227 len = g_variant_get_size(var);
1231 value_change.att_value = (guint8 *)g_malloc(len);
1233 data = (char *)g_variant_get_data(var);
1234 memcpy(value_change.att_value, data, len);
1236 value_change.val_len = len;
1238 if (response_needed) {
1239 /* Store requets information */
1240 req_info = g_new0(struct gatt_req_info, 1);
1241 req_info->attr_path = g_strdup(object_path);
1242 req_info->svc_path = g_strdup(value_change.service_handle);
1243 req_info->request_id = req_id;
1244 req_info->offset = offset;
1245 req_info->context = invocation;
1246 gatt_requests = g_slist_append(gatt_requests, req_info);
1248 g_object_unref(invocation);
1251 _bt_common_event_cb(
1252 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1253 BLUETOOTH_ERROR_NONE, &value_change,
1254 user_info->cb, user_info->user_data);
1256 g_free(value_change.att_value);
1257 g_variant_unref(var);
1262 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1265 GError *error = NULL;
1266 GVariantBuilder *array_builder;
1268 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1269 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1270 g_variant_builder_add(array_builder, "s", interface);
1272 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1273 "org.freedesktop.Dbus.Objectmanager",
1274 "InterfacesRemoved",
1275 g_variant_new("(oas)",
1276 object_path, array_builder),
1280 if (error != NULL) {
1281 /* dbus gives error cause */
1282 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1283 error->code, error->message);
1284 g_clear_error(&error);
1287 g_variant_builder_unref(array_builder);
1292 static const GDBusInterfaceVTable desc_interface_vtable = {
1293 __bt_gatt_desc_method_call,
1299 static const GDBusInterfaceVTable char_interface_vtable = {
1300 __bt_gatt_char_method_call,
1306 static const GDBusInterfaceVTable serv_interface_vtable = {
1313 static const GDBusInterfaceVTable manager_interface_vtable = {
1314 __bt_gatt_manager_method_call,
1320 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1321 const gchar *introspection_data)
1324 GDBusNodeInfo *node_info = NULL;
1326 if (introspection_data == NULL)
1330 BT_DBG("Create new node info");
1331 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1334 BT_ERR("Unable to create node: %s", err->message);
1335 g_clear_error(&err);
1342 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1343 const char *service_path)
1347 for (l = gatt_services; l != NULL; l = l->next) {
1348 struct gatt_service_info *info = l->data;
1350 if (g_strcmp0(info->serv_path, service_path) == 0)
1353 BT_ERR("Gatt service not found");
1357 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1358 const char *service_path, const char *char_path)
1362 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1363 struct gatt_service_info *serv_info = l1->data;
1365 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1367 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1368 struct gatt_char_info *char_info = l2->data;
1370 if (g_strcmp0(char_info->char_path, char_path) == 0)
1373 BT_ERR("Gatt characteristic not found");
1377 BT_ERR("Gatt service not found");
1381 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1382 const char *serv_path, const char *char_path,
1383 const char *desc_path)
1385 GSList *l1, *l2, *l3;
1387 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1388 struct gatt_service_info *serv_info = l1->data;
1390 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1391 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1392 struct gatt_char_info *char_info = l2->data;
1394 if (g_strcmp0(char_info->char_path, char_path) == 0) {
1395 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1396 struct gatt_desc_info *desc_info = l3->data;
1397 if (g_strcmp0(desc_info->desc_path,
1406 BT_ERR("Gatt descriptor not found");
1410 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1414 for (l = gatt_requests; l != NULL; l = l->next) {
1415 struct gatt_req_info *req_info = l->data;
1417 if (req_info && req_info->request_id == request_id)
1420 BT_ERR("Gatt Request not found");
1424 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1425 const gchar *path, const gchar *interface)
1431 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1436 BT_ERR("Unable to connect to gdbus: %s", err->message);
1437 g_clear_error(&err);
1442 proxy = g_dbus_proxy_new_sync(g_conn,
1443 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1445 interface, NULL, &err);
1449 BT_ERR("Unable to create proxy: %s", err->message);
1450 g_clear_error(&err);
1454 manager_gproxy = proxy;
1459 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1460 const gchar *path, const gchar *interface)
1462 return (manager_gproxy) ? manager_gproxy :
1463 __bt_gatt_gdbus_init_manager_proxy(service,
1467 static gboolean __bt_gatt_is_service_registered(const char *service_path)
1469 struct gatt_service_info *svc_info = NULL;
1471 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1473 if (svc_info != NULL) {
1474 BT_DBG("Return the state of the gatt service %d",
1475 svc_info->is_svc_registered);
1476 return svc_info->is_svc_registered;
1479 BT_DBG("gatt service info is NULL");
1483 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1485 GError *error = NULL;
1487 GVariantIter *iter = NULL;
1488 const gchar *key = NULL;
1489 GVariant *value = NULL;
1490 const gchar *service = NULL;
1491 const gchar *characteristic = NULL;
1492 const gchar *descriptor = NULL;
1496 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1498 if (result == NULL) {
1499 BT_ERR("Dbus-RPC is failed");
1500 if (error != NULL) {
1501 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1502 error->code, error->message);
1503 g_clear_error(&error);
1506 char *char_cmp = NULL;
1507 g_variant_get(result, "(a{sv})", &iter);
1508 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1510 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1511 if (g_strcmp0(key, "Service") == 0) {
1512 service = g_variant_get_string(value, NULL);
1513 BT_DBG("Service %s", service);
1514 } else if (g_strcmp0(key, char_cmp) == 0) {
1515 characteristic = g_variant_get_string(value, NULL);
1517 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1518 BT_DBG("%s", characteristic);
1519 } else if (g_strcmp0(key, "Descriptor") == 0) {
1520 descriptor = g_variant_get_string(value, NULL);
1521 BT_DBG("Descriptor %s", descriptor);
1524 g_variant_iter_free(iter);
1526 /* TODO: Store the service informationa and
1527 * Send respponse to CAPI layer. */
1529 g_variant_unref(result);
1534 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1536 BT_INFO("RegisterApplication is completed");
1538 GError *error = NULL;
1541 if (register_cancel) {
1542 g_object_unref(register_cancel);
1543 register_cancel = NULL;
1546 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1547 if (result == NULL) {
1548 BT_ERR("Dbus-RPC is failed");
1549 if (error != NULL) {
1550 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1551 error->code, error->message);
1552 g_clear_error(&error);
1554 is_server_started = false;
1556 g_variant_unref(result);
1560 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1562 GDBusProxy *proxy = NULL;
1564 if (is_server_started) {
1568 if (app_path == NULL) {
1569 BT_ERR("app_path is NULL");
1570 return BLUETOOTH_ERROR_INTERNAL;
1573 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1574 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1575 if (proxy == NULL) {
1576 BT_ERR("proxy is NULL");
1577 return BLUETOOTH_ERROR_INTERNAL;
1580 BT_INFO("UnregisterApplication");
1582 /* Async Call to Unregister Service */
1583 ret = g_dbus_proxy_call_sync(proxy, "UnregisterApplication",
1584 g_variant_new("(o)", app_path), G_DBUS_CALL_FLAGS_NONE, -1,
1587 BT_ERR("dBUS-RPC is failed");
1589 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1590 err->code, err->message);
1591 g_clear_error(&err);
1593 return BLUETOOTH_ERROR_INTERNAL;
1595 g_variant_unref(ret);
1597 is_server_started = false;
1599 BT_INFO("UnregisterApplication is completed");
1601 return BLUETOOTH_ERROR_NONE;
1604 BT_INFO("GATT server not started");
1605 return BLUETOOTH_ERROR_NONE;
1608 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1610 GDBusConnection *local_system_gconn = NULL;
1614 if (g_conn == NULL) {
1615 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1616 if (address == NULL) {
1618 BT_ERR("Failed to get bus address: %s", err->message);
1619 g_clear_error(&err);
1624 g_conn = g_dbus_connection_new_for_address_sync(address,
1625 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1626 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1627 NULL, /* GDBusAuthObserver */
1633 BT_ERR("Unable to connect to dbus: %s", err->message);
1634 g_clear_error(&err);
1638 } else if (g_dbus_connection_is_closed(g_conn)) {
1639 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1640 if (address == NULL) {
1642 BT_ERR("Failed to get bus address: %s", err->message);
1643 g_clear_error(&err);
1648 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1649 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1650 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1651 NULL, /* GDBusAuthObserver */
1655 if (!local_system_gconn) {
1656 BT_ERR("Unable to connect to dbus: %s", err->message);
1657 g_clear_error(&err);
1660 g_conn = local_system_gconn;
1666 BT_EXPORT_API int bluetooth_gatt_init(void)
1668 GDBusConnection *conn;
1669 GError *error = NULL;
1670 GDBusNodeInfo *node_info = NULL;
1672 if (app_path != NULL) {
1673 BT_ERR("app path already exists! initialized");
1674 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1677 if (owner_id == 0) {
1678 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1679 BT_GATT_SERVICE_NAME,
1680 G_BUS_NAME_OWNER_FLAGS_NONE,
1681 NULL, NULL, NULL, NULL, NULL);
1684 BT_DBG("owner_id is [%d]", owner_id);
1685 app_path = g_strdup_printf("/com/%d", getpid());
1689 conn = __bt_gatt_get_gdbus_connection();
1691 BT_ERR("Unable to get connection");
1695 /* Register ObjectManager interface */
1696 node_info = __bt_gatt_create_method_node_info(
1697 manager_introspection_xml);
1698 if (node_info == NULL) {
1699 BT_ERR("failed to get node info");
1703 if (manager_id == 0) {
1704 BT_INFO("manager_id does not exists");
1706 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1707 node_info->interfaces[0],
1708 &manager_interface_vtable,
1709 NULL, NULL, &error);
1711 g_dbus_node_info_unref(node_info);
1712 if (manager_id == 0) {
1713 BT_ERR("failed to register: %s", error->message);
1714 g_error_free(error);
1718 return BLUETOOTH_ERROR_NONE;
1722 g_bus_unown_name(owner_id);
1729 __bt_gatt_close_gdbus_connection();
1731 return BLUETOOTH_ERROR_INTERNAL;
1734 BT_EXPORT_API int bluetooth_gatt_deinit()
1736 int ret = BLUETOOTH_ERROR_NONE;
1738 if (register_cancel) {
1739 g_cancellable_cancel(register_cancel);
1740 g_object_unref(register_cancel);
1741 register_cancel = NULL;
1744 if (owner_id == 0) {
1745 BT_ERR("owner_id is zero");
1746 __bt_gatt_close_gdbus_connection();
1747 return BLUETOOTH_ERROR_NOT_FOUND;
1750 BT_DBG("Removing all registered gatt services");
1751 bluetooth_gatt_delete_services();
1753 /* Unregister the exported interface for object manager */
1755 g_dbus_connection_unregister_object(g_conn, manager_id);
1759 ret = bluetooth_gatt_unregister_application();
1760 if (ret != BLUETOOTH_ERROR_NONE) {
1761 BT_ERR("Fail to unregister application");
1764 g_bus_unown_name(owner_id);
1770 if (manager_gproxy) {
1771 g_object_unref(manager_gproxy);
1772 manager_gproxy = NULL;
1775 __bt_gatt_close_gdbus_connection();
1781 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1784 GError *error = NULL;
1786 GDBusNodeInfo *node_info;
1788 GVariantBuilder *builder = NULL;
1789 GVariantBuilder *builder1 = NULL;
1790 GVariantBuilder *inner_builder = NULL;
1791 gboolean svc_primary = TRUE;
1792 struct gatt_service_info *serv_info = NULL;
1794 node_info = __bt_gatt_create_method_node_info(
1795 service_introspection_xml);
1796 if (node_info == NULL)
1797 return BLUETOOTH_ERROR_INTERNAL;
1799 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1800 BT_DBG("gatt service path is [%s]", path);
1802 object_id = g_dbus_connection_register_object(g_conn, path,
1803 node_info->interfaces[0],
1804 &serv_interface_vtable,
1805 NULL, NULL, &error);
1806 g_dbus_node_info_unref(node_info);
1808 if (object_id == 0) {
1809 BT_ERR("failed to register: %s", error->message);
1810 g_error_free(error);
1813 return BLUETOOTH_ERROR_INTERNAL;
1816 /* Add object_id/gatt service information; it's required at the time of
1817 * service unregister and Getmanagedobjects
1819 serv_info = g_new0(struct gatt_service_info, 1);
1821 serv_info->serv_path = g_strdup(path);
1822 serv_info->serv_id = object_id;
1823 serv_info->service_uuid = g_strdup(svc_uuid);
1824 serv_info->is_svc_registered = FALSE;
1825 serv_info->is_svc_primary = svc_primary;
1827 gatt_services = g_slist_append(gatt_services, serv_info);
1829 /* emit interfacesadded signal here for service path */
1830 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1831 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1833 g_variant_builder_add(inner_builder, "{sv}",
1834 "UUID", g_variant_new_string(svc_uuid));
1836 g_variant_builder_add(inner_builder, "{sv}",
1837 "Primary", g_variant_new_boolean(svc_primary));
1839 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1841 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1842 g_variant_new("ao", builder1));
1844 g_variant_builder_add(builder, "{sa{sv}}",
1845 GATT_SERV_INTERFACE, inner_builder);
1847 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1848 "org.freedesktop.Dbus.ObjectManager",
1850 g_variant_new("(oa{sa{sv}})",
1853 if (error != NULL) {
1854 /* dbus gives error cause */
1855 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1856 error->code, error->message);
1857 g_clear_error(&error);
1862 *svc_path = g_strdup(path);
1865 g_variant_builder_unref(inner_builder);
1866 g_variant_builder_unref(builder);
1867 g_variant_builder_unref(builder1);
1869 return BLUETOOTH_ERROR_NONE;
1872 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1873 const char *svc_path, const char *char_uuid,
1874 bt_gatt_permission_t permissions,
1875 bt_gatt_characteristic_property_t properties,
1879 GError *error = NULL;
1881 GDBusNodeInfo *node_info;
1883 GVariantBuilder *builder = NULL;
1884 GVariantBuilder *inner_builder = NULL;
1885 struct gatt_service_info *serv_info = NULL;
1886 struct gatt_char_info *char_info = NULL;
1887 GVariantBuilder *builder2 = NULL;
1888 GVariantBuilder *builder3 = NULL;
1889 GVariant *flags_val = NULL;
1891 char *char_flags[NUMBER_OF_FLAGS];
1896 new_service = FALSE;
1899 BT_DBG("gatt svc_path path is [%s]", svc_path);
1900 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1901 if (serv_info == NULL)
1902 return BLUETOOTH_ERROR_INVALID_PARAM;
1904 node_info = __bt_gatt_create_method_node_info(
1905 characteristics_introspection_xml);
1906 if (node_info == NULL)
1907 return BLUETOOTH_ERROR_INTERNAL;
1909 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1910 BT_DBG("gatt characteristic path is [%s]", path);
1912 object_id = g_dbus_connection_register_object(g_conn, path,
1913 node_info->interfaces[0],
1914 &char_interface_vtable,
1915 NULL, NULL, &error);
1916 g_dbus_node_info_unref(node_info);
1918 if (object_id == 0) {
1919 BT_ERR("failed to register: %s", error->message);
1920 g_error_free(error);
1923 return BLUETOOTH_ERROR_INTERNAL;
1926 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1927 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1928 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1929 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1930 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1931 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1932 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1933 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1935 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1937 char_info = g_new0(struct gatt_char_info, 1);
1939 char_info->char_path = g_strdup(path);
1940 char_info->char_id = object_id;
1941 char_info->char_uuid = g_strdup(char_uuid);
1943 for (i = 0; i < flag_count; i++)
1944 char_info->char_flags[i] = char_flags[i];
1947 char_info->flags_length = flag_count;
1949 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1951 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1952 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1954 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1955 g_variant_new("s", char_uuid));
1956 g_variant_builder_add(inner_builder, "{sv}", "Service",
1957 g_variant_new("o", svc_path));
1959 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1961 for (i = 0; i < flag_count; i++)
1962 g_variant_builder_add(builder2, "s", char_flags[i]);
1964 flags_val = g_variant_new("as", builder2);
1965 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1968 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1970 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1971 g_variant_new("ao", builder3));
1973 g_variant_builder_add(builder, "{sa{sv}}",
1974 GATT_CHAR_INTERFACE,
1977 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1978 "org.freedesktop.Dbus.ObjectManager",
1980 g_variant_new("(oa{sa{sv}})",
1984 /* dBUS gives error cause */
1985 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1986 error->code, error->message);
1987 g_clear_error(&error);
1990 *char_path = g_strdup(path);
1996 g_variant_builder_unref(inner_builder);
1997 g_variant_builder_unref(builder);
1998 g_variant_builder_unref(builder2);
1999 g_variant_builder_unref(builder3);
2001 return BLUETOOTH_ERROR_NONE;
2004 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
2005 const char *characteristic, const char *char_value,
2008 gchar **line_argv = NULL;
2009 char *serv_path = NULL;
2010 struct gatt_char_info *char_info = NULL;
2011 GVariantBuilder *builder1 = NULL;
2012 GVariantBuilder *builder = NULL;
2013 GVariantBuilder *inner_builder = NULL;
2014 GVariant *char_val = NULL;
2015 GError *error = NULL;
2017 int res = BLUETOOTH_ERROR_NONE;
2019 line_argv = g_strsplit_set(characteristic, "/", 0);
2020 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2022 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
2024 if (char_info == NULL) {
2025 /* Fix : RESOURCE_LEAK */
2026 res = BLUETOOTH_ERROR_INVALID_PARAM;
2030 char_info->value_length = value_length;
2032 char_info->char_value = (char *)malloc(value_length);
2033 /* Fix : NULL_RETURNS */
2034 if (char_info->char_value == NULL) {
2035 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2039 for (i = 0; i < value_length; i++)
2040 char_info->char_value[i] = char_value[i];
2042 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2043 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2045 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2047 for (i = 0; i < value_length; i++)
2048 g_variant_builder_add(builder1, "y", char_value[i]);
2050 char_val = g_variant_new("ay", builder1);
2051 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
2053 g_variant_builder_add(builder, "{sa{sv}}",
2054 GATT_CHAR_INTERFACE,
2057 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2058 "org.freedesktop.Dbus.ObjectManager",
2060 g_variant_new("(oa{sa{sv}})",
2061 char_info->char_path, builder),
2065 /* dBUS gives error cause */
2066 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2067 error->code, error->message);
2068 g_clear_error(&error);
2070 g_variant_builder_unref(inner_builder);
2071 g_variant_builder_unref(builder);
2072 g_variant_builder_unref(builder1);
2074 g_strfreev(line_argv);
2080 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2081 const char *char_path, const char *desc_uuid,
2082 bt_gatt_permission_t permissions,
2085 static int desc_id = 1;
2086 GError *error = NULL;
2088 GDBusNodeInfo *node_info;
2090 GVariantBuilder *builder = NULL;
2091 GVariantBuilder *inner_builder = NULL;
2092 struct gatt_char_info *char_info = NULL;
2093 struct gatt_desc_info *desc_info = NULL;
2094 gchar **line_argv = NULL;
2096 GVariantBuilder *builder2 = NULL;
2097 GVariant *flags_val = NULL;
2099 char *desc_flags[NUMBER_OF_FLAGS];
2107 line_argv = g_strsplit_set(char_path, "/", 0);
2108 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2110 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2111 if (char_info == NULL) {
2112 g_strfreev(line_argv);
2114 return BLUETOOTH_ERROR_INVALID_PARAM;
2117 node_info = __bt_gatt_create_method_node_info(
2118 descriptor_introspection_xml);
2119 if (node_info == NULL) {
2120 g_strfreev(line_argv);
2122 return BLUETOOTH_ERROR_INTERNAL;
2125 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2126 BT_DBG("gatt descriptor path is [%s]", path);
2128 object_id = g_dbus_connection_register_object(g_conn, path,
2129 node_info->interfaces[0],
2130 &desc_interface_vtable,
2131 NULL, NULL, &error);
2132 g_dbus_node_info_unref(node_info);
2134 if (object_id == 0) {
2135 BT_ERR("failed to register: %s", error->message);
2136 g_error_free(error);
2138 g_strfreev(line_argv);
2141 return BLUETOOTH_ERROR_INTERNAL;
2144 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2146 desc_info = g_new0(struct gatt_desc_info, 1);
2148 desc_info->desc_path = g_strdup(path);
2149 desc_info->desc_id = object_id;
2150 desc_info->desc_uuid = g_strdup(desc_uuid);
2152 for (i = 0; i < flag_count; i++)
2153 desc_info->desc_flags[i] = desc_flags[i];
2155 desc_info->flags_length = flag_count;
2157 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2159 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2160 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2162 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2163 g_variant_new("s", desc_uuid));
2164 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2165 g_variant_new("o", char_path));
2167 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2169 for (i = 0; i < flag_count; i++)
2170 g_variant_builder_add(builder2, "s", desc_flags[i]);
2172 flags_val = g_variant_new("as", builder2);
2173 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2176 g_variant_builder_add(builder, "{sa{sv}}",
2177 GATT_DESC_INTERFACE,
2180 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2181 "org.freedesktop.Dbus.ObjectManager",
2183 g_variant_new("(oa{sa{sv}})",
2187 /* dBUS gives error cause */
2188 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2189 error->code, error->message);
2190 g_clear_error(&error);
2193 *desc_path = g_strdup(path);
2197 g_strfreev(line_argv);
2198 g_variant_builder_unref(inner_builder);
2199 g_variant_builder_unref(builder);
2200 g_variant_builder_unref(builder2);
2202 return BLUETOOTH_ERROR_NONE;
2205 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2206 const char *desc_path, const char *desc_value,
2209 GError *error = NULL;
2210 GVariantBuilder *builder = NULL;
2211 GVariantBuilder *inner_builder = NULL;
2212 GVariantBuilder *builder1 = NULL;
2213 struct gatt_desc_info *desc_info = NULL;
2214 gchar **line_argv = NULL;
2216 GVariant *desc_val = NULL;
2217 char *serv_path = NULL;
2220 line_argv = g_strsplit_set(desc_path, "/", 0);
2221 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2222 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2224 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2226 /* Free the allocated memory */
2227 g_strfreev(line_argv);
2231 /* Fix : NULL_RETURNS */
2232 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2234 desc_info->desc_value = (char *)malloc(value_length);
2236 /* Fix : NULL_RETURNS */
2237 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2239 for (i = 0; i < value_length; i++)
2240 desc_info->desc_value[i] = desc_value[i];
2242 desc_info->value_length = value_length;
2244 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2245 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2247 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2249 for (i = 0; i < value_length; i++)
2250 g_variant_builder_add(builder1, "y", desc_value[i]);
2252 desc_val = g_variant_new("ay", builder1);
2253 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2255 g_variant_builder_add(builder, "{sa{sv}}",
2256 GATT_DESC_INTERFACE,
2259 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2260 "org.freedesktop.Dbus.ObjectManager",
2262 g_variant_new("(oa{sa{sv}})",
2263 desc_info->desc_path, builder),
2266 if (error != NULL) {
2267 BT_ERR("D-Bus API failure: errCode[%x], \
2269 error->code, error->message);
2270 g_clear_error(&error);
2273 g_variant_builder_unref(inner_builder);
2274 g_variant_builder_unref(builder);
2275 g_variant_builder_unref(builder1);
2277 return BLUETOOTH_ERROR_NONE;
2280 int bluetooth_gatt_get_service(const char *svc_uuid)
2282 GDBusProxy *proxy = NULL;
2285 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2286 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2288 return BLUETOOTH_ERROR_INTERNAL;
2290 uuid = g_strdup(svc_uuid);
2292 g_dbus_proxy_call(proxy,
2294 g_variant_new("(s)",
2296 G_DBUS_CALL_FLAGS_NONE, -1,
2298 (GAsyncReadyCallback) get_service_cb,
2303 return BLUETOOTH_ERROR_NONE;
2306 BT_EXPORT_API int bluetooth_gatt_register_service(const char *svc_path)
2308 struct gatt_service_info *svc_info = NULL;
2310 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2311 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2312 BT_ERR("Don't have aprivilege to use this API");
2313 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2316 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2317 if (svc_info == NULL) {
2318 BT_ERR("Cannot find service [%s]", svc_path);
2319 return BLUETOOTH_ERROR_INTERNAL;
2321 svc_info->is_svc_registered = TRUE;
2323 return BLUETOOTH_ERROR_NONE;
2326 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2328 GDBusProxy *proxy = NULL;
2330 if (!is_server_started) {
2331 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2332 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2333 BT_ERR("Don't have aprivilege to use this API");
2334 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2337 if (g_slist_length(gatt_services) == 0) {
2338 BT_ERR("There is no registered service");
2339 return BLUETOOTH_ERROR_INTERNAL;
2342 if (app_path == NULL) {
2343 BT_ERR("app_path is NULL");
2344 return BLUETOOTH_ERROR_INTERNAL;
2347 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2348 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2349 if (proxy == NULL) {
2350 BT_ERR("proxy is NULL");
2351 return BLUETOOTH_ERROR_INTERNAL;
2354 BT_INFO("RegisterApplication");
2356 if (register_cancel) {
2357 g_cancellable_cancel(register_cancel);
2358 g_object_unref(register_cancel);
2360 register_cancel = g_cancellable_new();
2362 g_dbus_proxy_call(proxy, "RegisterApplication",
2363 g_variant_new("(oa{sv})", app_path, NULL),
2364 G_DBUS_CALL_FLAGS_NONE, -1, register_cancel,
2365 (GAsyncReadyCallback)register_application_cb, NULL);
2367 is_server_started = true;
2369 return BLUETOOTH_ERROR_NONE;
2372 BT_INFO("Already RegisterApplication");
2374 return BLUETOOTH_ERROR_NONE;
2377 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2380 int ret = BLUETOOTH_ERROR_NONE;
2382 if (gatt_services == NULL) {
2383 BT_DBG("There are no registered services");
2388 for (l = gatt_services; l != NULL; ) {
2389 struct gatt_service_info *info = l->data;
2391 // In __bt_gatt_unregister_service, current node will be removed.
2392 // Go forward to next node before calling __bt_gatt_unregister_service.
2394 if (__bt_gatt_unregister_service(info) != BLUETOOTH_ERROR_NONE) {
2395 ret = BLUETOOTH_ERROR_INTERNAL;
2398 BT_INFO("All services are removed : %d", ret);
2400 g_slist_free(gatt_services);
2401 gatt_services = NULL;
2407 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2408 const char *char_path, const char* char_value,
2411 GVariantBuilder *outer_builder;
2412 GVariantBuilder *inner_builder;
2413 GVariantBuilder *invalidated_builder;
2414 GVariant *update_value = NULL;
2415 GError *error = NULL;
2416 gboolean ret = FALSE;
2417 int err = BLUETOOTH_ERROR_NONE;
2419 gchar **line_argv = NULL;
2420 gchar *serv_path = NULL;
2421 const char *value = NULL;
2423 line_argv = g_strsplit_set(char_path, "/", 0);
2424 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2426 if (!__bt_gatt_is_service_registered(serv_path)) {
2427 BT_DBG("service not registered for this characteristic");
2429 g_strfreev(line_argv);
2430 return BLUETOOTH_ERROR_INTERNAL;
2433 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2434 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2436 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2437 for (i = 0; i < value_length; i++)
2438 g_variant_builder_add(inner_builder, "y", char_value[i]);
2440 update_value = g_variant_new("ay", inner_builder);
2442 g_variant_builder_add(outer_builder, "{sv}", "Value",
2445 BT_DBG("Updating characteristic value");
2446 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2448 "org.freedesktop.DBus.Properties",
2449 "PropertiesChanged",
2450 g_variant_new("(sa{sv}as)",
2451 "org.bluez.GattCharacteristic1",
2452 outer_builder, invalidated_builder),
2456 if (error != NULL) {
2457 BT_ERR("D-Bus API failure: errCode[%x], \
2459 error->code, error->message);
2460 g_clear_error(&error);
2462 err = BLUETOOTH_ERROR_INTERNAL;
2464 struct gatt_char_info *char_info = NULL;
2466 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2467 if (char_info == NULL) {
2469 g_strfreev(line_argv);
2470 g_variant_builder_unref(inner_builder);
2471 g_variant_builder_unref(outer_builder);
2472 g_variant_builder_unref(invalidated_builder);
2474 return BLUETOOTH_ERROR_INVALID_DATA;
2477 char_info->value_length = value_length;
2479 value = (char *)realloc(char_info->char_value, value_length);
2480 if (value == NULL) {
2482 g_strfreev(line_argv);
2483 g_variant_builder_unref(inner_builder);
2484 g_variant_builder_unref(outer_builder);
2485 g_variant_builder_unref(invalidated_builder);
2487 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2490 char_info->char_value = (char*)value;
2491 if (char_info->char_value) {
2492 for (i = 0; i < value_length; i++)
2493 char_info->char_value[i] = char_value[i];
2498 g_strfreev(line_argv);
2499 g_variant_builder_unref(inner_builder);
2500 g_variant_builder_unref(outer_builder);
2501 g_variant_builder_unref(invalidated_builder);
2506 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2513 g_free(desc_info->desc_path);
2514 g_free(desc_info->desc_uuid);
2515 g_free(desc_info->desc_value);
2517 for (i = 0; i < desc_info->flags_length; i++)
2518 g_free(desc_info->desc_flags[i]);
2523 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2530 g_free(char_info->char_path);
2531 g_free(char_info->char_uuid);
2532 g_free(char_info->char_value);
2534 for (i = 0; i < char_info->flags_length; i++)
2535 g_free(char_info->char_flags[i]);
2540 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2545 g_free(svc_info->serv_path);
2546 g_free(svc_info->service_uuid);
2550 static void __desc_info_free(gpointer data, gpointer user_data)
2552 struct gatt_desc_info *desc_info = data;
2553 int *err = user_data;
2556 if (desc_info == NULL)
2559 ret = g_dbus_connection_unregister_object(g_conn, desc_info->desc_id);
2561 __bt_gatt_emit_interface_removed(desc_info->desc_path, GATT_DESC_INTERFACE);
2563 *err = BLUETOOTH_ERROR_INTERNAL;
2565 __bt_gatt_free_descriptor_info(desc_info);
2568 static void __char_info_free(gpointer data, gpointer user_data)
2570 struct gatt_char_info *char_info = data;
2571 int *err = user_data;
2574 if (char_info == NULL)
2577 g_slist_foreach(char_info->desc_data, __desc_info_free, user_data);
2578 g_slist_free(char_info->desc_data);
2579 char_info->desc_data = NULL;
2581 ret = g_dbus_connection_unregister_object(g_conn, char_info->char_id);
2583 __bt_gatt_emit_interface_removed(char_info->char_path, GATT_CHAR_INTERFACE);
2585 *err = BLUETOOTH_ERROR_INTERNAL;
2587 __bt_gatt_free_characteristic_info(char_info);
2590 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info)
2592 int ret = BLUETOOTH_ERROR_NONE;
2594 if (svc_info == NULL) {
2595 BT_ERR("svc_info is NULL");
2596 return BLUETOOTH_ERROR_NOT_FOUND;
2599 if (svc_info->is_svc_registered == FALSE) {
2600 BT_ERR("%s is not registered", svc_info->serv_path);
2601 return BLUETOOTH_ERROR_NOT_FOUND;
2604 BT_DBG("svc_path %s", svc_info->serv_path);
2606 g_slist_foreach(svc_info->char_data, __char_info_free, &ret);
2607 g_slist_free(svc_info->char_data);
2608 svc_info->char_data = NULL;
2610 if (g_dbus_connection_unregister_object(g_conn, svc_info->serv_id) == FALSE) {
2611 BT_ERR("Cannot unregister object for [%s]", svc_info->serv_path);
2612 ret = BLUETOOTH_ERROR_INTERNAL;
2614 __bt_gatt_emit_interface_removed(svc_info->serv_path, GATT_SERV_INTERFACE);
2617 gatt_services = g_slist_remove(gatt_services, svc_info);
2618 __bt_gatt_free_service_info(svc_info);
2620 new_service = FALSE;
2622 if (gatt_services == NULL) {
2624 } else if (gatt_services->next == NULL) {
2631 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2633 struct gatt_service_info *svc_info;
2634 int ret = BLUETOOTH_ERROR_NONE;
2638 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2640 ret = __bt_gatt_unregister_service(svc_info);
2641 if (ret != BLUETOOTH_ERROR_NONE) {
2642 BT_ERR("Could not unregister service [%s]", svc_path);
2649 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2650 int resp_state, int offset, char *value, int value_length)
2652 struct gatt_req_info *req_info = NULL;
2654 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2655 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2656 BT_ERR("Don't have aprivilege to use this API");
2657 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2660 req_info = __bt_gatt_find_request_info(request_id);
2661 if (req_info == NULL) {
2662 BT_ERR("Coundn't find request id [%d]", request_id);
2663 return BLUETOOTH_ERROR_INTERNAL;
2666 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2667 BT_ERR("resp_state is 0x%X", resp_state);
2668 char err_msg[20] = { 0, };
2669 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2670 g_dbus_method_invocation_return_dbus_error(req_info->context,
2671 "org.bluez.Error.Failed", err_msg);
2673 gatt_requests = g_slist_remove(gatt_requests, req_info);
2675 req_info->context = NULL;
2676 if (req_info->attr_path)
2677 g_free(req_info->attr_path);
2678 if (req_info->svc_path)
2679 g_free(req_info->svc_path);
2682 return BLUETOOTH_ERROR_NONE;
2685 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2687 GVariantBuilder *inner_builder = NULL;
2688 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2689 if (value_length > 0 && value != NULL) {
2690 for (i = 0; i < value_length; i++)
2691 g_variant_builder_add(inner_builder, "y", value[i]);
2693 g_dbus_method_invocation_return_value(req_info->context,
2694 g_variant_new("(ay)", inner_builder));
2695 g_variant_builder_unref(inner_builder);
2697 g_dbus_method_invocation_return_value(req_info->context, NULL);
2699 gatt_requests = g_slist_remove(gatt_requests, req_info);
2701 req_info->context = NULL;
2702 if (req_info->attr_path)
2703 g_free(req_info->attr_path);
2704 if (req_info->svc_path)
2705 g_free(req_info->svc_path);
2708 return BLUETOOTH_ERROR_NONE;
2711 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2712 bluetooth_device_address_t *unicast_address)
2714 GVariantBuilder *outer_builder;
2715 GVariantBuilder *invalidated_builder;
2716 GError *error = NULL;
2717 gboolean notify = TRUE;
2718 gboolean ret = TRUE;
2719 int err = BLUETOOTH_ERROR_NONE;
2720 gchar **line_argv = NULL;
2721 gchar *serv_path = NULL;
2722 char addr[20] = { 0 };
2724 line_argv = g_strsplit_set(char_path, "/", 0);
2725 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2727 if (!__bt_gatt_is_service_registered(serv_path)) {
2728 BT_DBG("service not registered for this characteristic");
2730 g_strfreev(line_argv);
2731 return BLUETOOTH_ERROR_INTERNAL;
2736 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2737 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2739 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2740 g_variant_new("b", notify));
2742 if (unicast_address) {
2743 _bt_convert_addr_type_to_string(addr,
2744 (unsigned char *)unicast_address->addr);
2746 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2747 g_variant_new("s", addr));
2749 BT_DBG("Set characteristic Notification");
2750 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2752 "org.freedesktop.DBus.Properties",
2753 "PropertiesChanged",
2754 g_variant_new("(sa{sv}as)",
2755 "org.bluez.GattCharacteristic1",
2756 outer_builder, invalidated_builder),
2760 if (error != NULL) {
2761 BT_ERR("D-Bus API failure: errCode[%x], \
2763 error->code, error->message);
2764 g_clear_error(&error);
2766 err = BLUETOOTH_ERROR_INTERNAL;
2769 g_strfreev(line_argv);
2770 g_variant_builder_unref(outer_builder);
2771 g_variant_builder_unref(invalidated_builder);
2778 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2782 if (!is_server_started) {
2784 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2785 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2786 BT_ERR("Don't have aprivilege to use this API");
2787 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2790 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2791 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2793 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2794 in_param1, in_param2, in_param3, in_param4, &out_param);
2795 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2797 if (ret != BLUETOOTH_ERROR_NONE) {
2798 BT_ERR("Register application failed");
2801 is_server_started = true;
2803 return BLUETOOTH_ERROR_NONE;
2806 BT_INFO("Already RegisterApplication");
2807 return BLUETOOTH_ERROR_NONE;
2811 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2814 int ret = BLUETOOTH_ERROR_NONE;
2817 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2819 /* Register event handler for GATT */
2820 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2822 if (ret != BLUETOOTH_ERROR_NONE &&
2823 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2824 BT_ERR("Fail to init the event handler");
2825 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2829 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2830 in_param1, in_param2, in_param3, in_param4, &out_param);
2832 /* App ID -1 is invalid */
2833 if (ret != BLUETOOTH_ERROR_NONE) {
2834 BT_INFO("GATT Server Registration failed result [%d]", ret);
2837 *instance_id = g_array_index(out_param, int, 0);
2838 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2842 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2844 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2848 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2851 BT_INFO("GATT Server Deinitialize");
2852 /* Unregister the event */
2853 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2855 if (ret != BLUETOOTH_ERROR_NONE) {
2856 BT_ERR("Fail to deinit the event handler");
2860 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2865 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2866 int instance_id, int *service_handle)
2868 BT_CHECK_ENABLED(return);
2869 BT_CHECK_PARAMETER(svc_uuid, return);
2872 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2874 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2877 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2879 g_array_append_vals(in_param1, &type, sizeof(int));
2880 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2881 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2882 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2884 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2885 in_param1, in_param2, in_param3, in_param4, &out_param);
2887 /* ATT handle 0 is reserved, hence it can not be used by app.
2888 It will be used to indicate error in regsitering attribute */
2889 if (result != BLUETOOTH_ERROR_NONE)
2890 *service_handle = 0;
2892 *service_handle = g_array_index(out_param, int, 0);
2894 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2899 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2900 const bluetooth_gatt_server_attribute_params_t *param,
2903 BT_CHECK_ENABLED(return);
2904 BT_CHECK_PARAMETER(char_uuid, return);
2905 BT_CHECK_PARAMETER(param, return);
2908 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2910 char *char_flags[NUMBER_OF_FLAGS];
2912 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2913 flag_count = bluetooth_gatt_convert_prop2string(param->properties, char_flags);
2914 BT_INFO("Flag count [%d]", flag_count);
2917 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2919 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2920 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2922 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2923 in_param1, in_param2, in_param3, in_param4, &out_param);
2925 /* ATT handle 0 is reserved, hence it can not be used by app.
2926 It will be used to indicate error in regsitering attribute */
2927 if (result != BLUETOOTH_ERROR_NONE) {
2928 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2931 *char_handle = g_array_index(out_param, int, 0);
2932 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2935 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2939 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2940 int service_handle, int instance_id, int *descriptor_handle)
2942 BT_CHECK_ENABLED(return);
2943 BT_CHECK_PARAMETER(desc_uuid, return);
2946 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2948 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2951 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2953 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2954 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2955 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2956 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2958 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2959 in_param1, in_param2, in_param3, in_param4, &out_param);
2961 /* ATT handle 0 is reserved, hence it can not be used by app.
2962 It will be used to indicate error in regsitering attribute */
2963 if (result != BLUETOOTH_ERROR_NONE) {
2964 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2965 *descriptor_handle = 0;
2967 *descriptor_handle = g_array_index(out_param, int, 0);
2968 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2971 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2976 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2978 BT_CHECK_ENABLED(return);
2982 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2984 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2985 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2987 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2988 in_param1, in_param2, in_param3, in_param4, &out_param);
2990 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2995 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2996 const bluetooth_gatt_att_data_t *value)
2998 BT_CHECK_PARAMETER(param, return);
2999 BT_CHECK_PARAMETER(value, return);
3000 BT_CHECK_ENABLED(return);
3004 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3006 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
3007 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
3009 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
3010 in_param1, in_param2, in_param3, in_param4, &out_param);
3012 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3018 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
3019 const bluetooth_gatt_server_indication_params_t *param,
3020 const bluetooth_gatt_att_data_t *att_value)
3022 BT_CHECK_PARAMETER(param, return);
3023 BT_CHECK_PARAMETER(att_value, return);
3024 BT_CHECK_ENABLED(return);
3026 char addr[BLUETOOTH_ADDRESS_STRING_LENGTH] ;
3030 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3032 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
3033 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
3034 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
3036 _bt_convert_addr_type_to_string(addr, addr_hex->addr);
3037 fd = bluetooth_get_characteristic_fd(param->atrribute_handle, addr);
3040 result = bluetooth_gatt_write_characteristics_value_to_fd_(fd, att_value->data, att_value->length, NULL);
3042 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
3043 in_param1, in_param2, in_param3, in_param4, &out_param);
3045 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3050 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
3052 BT_CHECK_ENABLED(return);
3056 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3058 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3059 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3061 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
3062 in_param1, in_param2, in_param3, in_param4, &out_param);
3064 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3069 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
3071 BT_CHECK_ENABLED(return);
3075 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3077 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3078 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3080 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
3081 in_param1, in_param2, in_param3, in_param4, &out_param);
3083 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3088 /* Tizen Platform Specific */
3089 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
3090 const bluetooth_gatt_server_update_value_t *value)
3092 BT_CHECK_ENABLED(return);
3093 BT_CHECK_PARAMETER(value, return);
3097 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3099 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3100 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3102 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3103 in_param1, in_param2, in_param3, in_param4, &out_param);
3105 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3110 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3112 BT_CHECK_ENABLED(return);
3116 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3118 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3120 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3121 in_param1, in_param2, in_param3, in_param4, &out_param);
3123 if (result != BLUETOOTH_ERROR_NONE)
3124 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3126 BT_INFO("GATT Server Unregistration successful");
3128 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3133 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3134 GIOCondition cond, gpointer data)
3137 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3139 BT_INFO("FD io write data received remote adress [%s]\n", write_data->address);
3141 if (cond & G_IO_IN) {
3142 GIOStatus status = G_IO_STATUS_NORMAL;
3144 char *buffer = NULL;
3146 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3148 buffer = g_malloc0(BUF);
3150 status = g_io_channel_read_chars(gio, buffer,
3153 if (status != G_IO_STATUS_NORMAL) {
3154 BT_ERR("IO Channel read is failed with %d", status);
3157 BT_ERR("IO Channel read error [%s]", err->message);
3158 if (status == G_IO_STATUS_ERROR) {
3159 BT_ERR("cond : %d", cond);
3161 g_io_channel_shutdown(gio, TRUE, NULL);
3162 g_io_channel_unref(gio);
3173 BT_INFO(" FD io sending value changed %s %zd \n", buffer, len);
3176 bluetooth_gatt_server_write_requested_info_t write_info;
3177 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3178 memcpy(write_info.data.data, buffer, len);
3180 write_info.length = len;
3181 write_info.need_resp = false;
3182 write_info.attribute_handle = write_data->attribute_handle;
3184 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->address);
3185 write_info.connection_id = write_data->connection_id;
3186 write_info.offset = write_data->offset;
3187 write_info.request_id = -2;
3189 BT_INFO("ACQUIRING EVENT \n");
3191 bt_event_info_t *event_info;
3192 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3196 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3197 BLUETOOTH_ERROR_NONE, &write_info,
3198 event_info->cb, event_info->user_data);
3200 BT_ERR("eventinfo failed");
3210 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
3211 BT_ERR("Error : GIOCondition %d, ]", cond);
3212 g_io_channel_shutdown(gio, TRUE, NULL);
3213 g_io_channel_unref(gio);
3221 void bluetooth_gatt_server_send_acquire_write_response(GVariant * parameters)
3226 int pipefd[2] = {-1,};
3229 char err_msg[512] = {'\0'};
3230 GIOChannel *channel = NULL;
3234 g_variant_get(parameters, "(iiiiii&s)",
3243 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3244 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3245 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3246 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3249 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3250 strerror_r(errno, err_msg, sizeof(err_msg));
3251 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_WRITE;
3261 data.fd = pipefd[1];
3263 data.request_id = tran_id;
3265 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3267 write_info->attribute_handle = att_han;
3268 write_info->connection_id = tran_id;
3269 write_info->offset = offset;
3271 memcpy(write_info->address, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3273 BT_INFO("FD read %d remote address [%s ] \n", pipefd[0], addr);
3276 channel = g_io_channel_unix_new(pipefd[0]);
3277 g_io_channel_set_encoding(channel, NULL, NULL);
3278 g_io_channel_set_buffered(channel, FALSE);
3279 g_io_channel_set_close_on_unref(channel, TRUE);
3280 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3281 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3282 bluetooth_gatt_server_acquire_channel_write_cb, write_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_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3296 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_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);
3305 void bluetooth_gatt_server_send_acquire_notify_response(GVariant * parameters)
3310 int pipefd[2] = {-1,};
3313 char err_msg[512] = {'\0'};
3314 GIOChannel *channel = NULL;
3317 bluetooth_gatt_acquire_notify_info_t *chr_info;
3319 g_variant_get(parameters, "(iiiiii)",
3327 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3328 BT_DBG("GATT Server Acquire notify att handle:[%d]", att_han);
3329 BT_DBG("GATT Server Acquire Notify Offset: [%d]", offset);
3332 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3333 strerror_r(errno, err_msg, sizeof(err_msg));
3334 BT_ERR("socketpair(): %s", err_msg);
3341 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3343 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3344 bluetooth_gatt_server_acquire_response_params_t data;
3345 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
3346 data.fd = pipefd[1];
3348 data.request_id = tran_id;
3350 BT_INFO("FD write %d characterstics path \n", pipefd[0]);
3352 chr_info = bluetooth_get_characteristic_info_from_path(att_han);
3354 chr_info = g_malloc0(sizeof(bluetooth_gatt_acquire_notify_info_t));
3355 chr_info->write_fd = fd;
3356 chr_info->att_hand = att_han;
3358 gatt_characteristic_server_notify_list = g_slist_append(gatt_characteristic_server_notify_list, chr_info);
3360 chr_info->write_fd = fd;
3363 channel = g_io_channel_unix_new(fd);
3364 g_io_channel_set_encoding(channel, NULL, NULL);
3365 g_io_channel_set_buffered(channel, FALSE);
3366 g_io_channel_set_close_on_unref(channel, TRUE);
3367 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3368 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
3369 bluetooth_gatt_write_channel_watch_cb, chr_info);
3374 GUnixFDList *fd_list = g_unix_fd_list_new();
3375 GError *error = NULL;
3377 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3378 g_assert_no_error(error);
3381 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3383 BT_INFO("Sending event BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE file descriptor value [%d] ", data.fd);
3385 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE,
3386 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3388 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);