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 #ifdef TIZEN_FEATURE_BT_HPS
434 static int __bt_send_event_to_hps(int event, GVariant *var)
436 GError *error = NULL;
437 GVariant *parameters;
438 GDBusMessage *msg = NULL;
442 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
444 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
445 GVariantBuilder *inner_builder;
446 GVariantBuilder *invalidated_builder;
448 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
449 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
451 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
453 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
455 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
456 g_variant_builder_unref(invalidated_builder);
457 g_variant_builder_unref(inner_builder);
458 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
459 GVariantBuilder *inner_builder;
460 GVariantBuilder *invalidated_builder;
462 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
463 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
465 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
467 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
469 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
470 g_variant_builder_unref(invalidated_builder);
471 g_variant_builder_unref(inner_builder);
473 g_varaiant_unref(var);
476 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
477 g_dbus_message_set_body(msg, parameters);
478 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
480 BT_ERR("D-Bus API failure: errCode[%x], \
482 error->code, error->message);
483 g_clear_error(&error);
485 return BLUETOOTH_ERROR_INTERNAL;
487 return BLUETOOTH_ERROR_NONE;
491 #ifdef TIZEN_FEATURE_BT_OTP
492 static int __bt_send_event_to_otp(int event, GVariant *var)
494 GError *error = NULL;
495 GVariant *parameters = NULL;
496 GDBusMessage *msg = NULL;
500 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
502 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
503 GVariantBuilder *inner_builder;
504 GVariantBuilder *invalidated_builder;
506 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
507 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
509 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
511 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
513 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
514 g_variant_builder_unref(invalidated_builder);
515 g_variant_builder_unref(inner_builder);
516 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
517 GVariantBuilder *inner_builder;
518 GVariantBuilder *invalidated_builder;
520 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
521 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
523 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
525 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
527 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
528 g_variant_builder_unref(invalidated_builder);
529 g_variant_builder_unref(inner_builder);
530 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
531 GVariantBuilder *inner_builder;
532 GVariantBuilder *invalidated_builder;
534 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
535 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
537 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", 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);
546 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
547 g_dbus_message_set_body(msg, parameters);
548 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
550 BT_ERR("D-Bus API failure: errCode[%x], \
552 error->code, error->message);
553 g_clear_error(&error);
555 return BLUETOOTH_ERROR_INTERNAL;
557 return BLUETOOTH_ERROR_NONE;
561 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
563 const gchar *object_path,
564 const gchar *interface_name,
565 const gchar *method_name,
566 GVariant *parameters,
567 GDBusMethodInvocation *invocation,
570 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
571 BT_DBG("Getting values for service, chars and descriptors");
574 GVariantBuilder *builder = NULL;
575 GVariantBuilder *inner_builder1 = NULL;
576 GVariant *svc_char = NULL;
577 GSList *char_list = NULL;
578 GSList *desc_list = NULL;
581 builder = g_variant_builder_new(G_VARIANT_TYPE("a{oa{sa{sv}}}"));
583 /* Prepare inner builder for GattService1 interface */
584 svc_index = g_slist_length(gatt_services) - 1;
585 for (; svc_index >= 0; svc_index--) {
586 GVariantBuilder *svc_builder = NULL;
587 GVariantBuilder *inner_builder = NULL;
588 struct gatt_service_info *serv_info = NULL;
590 serv_info = g_slist_nth_data(gatt_services, svc_index);
591 if (serv_info == NULL) {
592 BT_ERR("serv_info is NULL");
596 /* Prepare inner builder for GattService1 interface */
597 BT_DBG("Creating builder for service : %s", serv_info->service_uuid);
598 svc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
599 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
601 g_variant_builder_add(inner_builder, "{sv}", "UUID",
602 g_variant_new_string(serv_info->service_uuid));
603 g_variant_builder_add(inner_builder, "{sv}", "Primary",
604 g_variant_new_boolean(serv_info->is_svc_primary));
606 /* Characteristics */
607 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
609 BT_DBG("Adding Charatarisitcs list");
610 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
611 struct gatt_char_info *char_info = char_list->data;
612 g_variant_builder_add(inner_builder1, "o", char_info->char_path);
613 BT_DBG("%s", char_info->char_path);
616 svc_char = g_variant_new("ao", inner_builder1);
617 g_variant_builder_add(inner_builder, "{sv}", "Characteristics", svc_char);
618 g_variant_builder_add(svc_builder, "{sa{sv}}", GATT_SERV_INTERFACE, inner_builder);
619 g_variant_builder_add(builder, "{oa{sa{sv}}}", serv_info->serv_path, svc_builder);
620 g_variant_builder_unref(inner_builder1);
622 /* Prepare inner builder for GattCharacteristic1 interface */
623 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
624 GVariantBuilder *char_builder = NULL;
625 GVariantBuilder *inner_builder = NULL;
626 GVariantBuilder *builder1 = NULL;
627 GVariantBuilder *builder2 = NULL;
628 GVariantBuilder *builder3 = NULL;
629 GVariant *char_val = NULL;
630 GVariant *flags_val = NULL;
631 GVariant *char_desc = NULL;
632 char *unicast = NULL;
633 gboolean notify = FALSE;
635 struct gatt_char_info *char_info = char_list->data;
637 if (char_info == NULL) {
638 BT_ERR("char_info is NULL");
642 BT_DBG("Creating builder for characteristic : %s", char_info->char_uuid);
643 char_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
644 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
647 g_variant_builder_add(inner_builder, "{sv}", "UUID",
648 g_variant_new_string(char_info->char_uuid));
651 g_variant_builder_add(inner_builder, "{sv}", "Service",
652 g_variant_new("o", serv_info->serv_path));
655 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
656 if (char_info->char_value != NULL) {
657 for (i = 0; i < char_info->value_length; i++) {
658 g_variant_builder_add(builder1, "y", char_info->char_value[i]);
660 char_val = g_variant_new("ay", builder1);
661 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
665 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
666 for (i = 0; i < char_info->flags_length; i++) {
667 g_variant_builder_add(builder2, "s", char_info->char_flags[i]);
669 flags_val = g_variant_new("as", builder2);
670 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
673 g_variant_builder_add(inner_builder, "{sv}", "Notifying", g_variant_new("b", notify));
676 unicast = g_strdup("00:00:00:00:00:00");
677 g_variant_builder_add(inner_builder, "{sv}", "Unicast", g_variant_new("s", unicast));
680 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
681 BT_DBG("Adding Descriptors list");
682 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
683 struct gatt_desc_info *desc_info = desc_list->data;
684 g_variant_builder_add(builder3, "o", desc_info->desc_path);
685 BT_DBG("%s", desc_info->desc_path);
688 char_desc = g_variant_new("ao", builder3);
689 g_variant_builder_add(inner_builder, "{sv}", "Descriptors", char_desc);
690 g_variant_builder_add(char_builder, "{sa{sv}}", GATT_CHAR_INTERFACE , inner_builder);
691 g_variant_builder_add(builder, "{oa{sa{sv}}}", char_info->char_path, char_builder);
693 /*Prepare inner builder for GattDescriptor1 interface*/
694 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
695 GVariantBuilder *desc_builder = NULL;
696 GVariantBuilder *inner_builder = NULL;
697 GVariantBuilder *builder1 = NULL;
698 GVariantBuilder *builder2 = NULL;
699 GVariant *desc_val = NULL;
700 struct gatt_desc_info *desc_info = desc_list->data;
702 if (desc_info == NULL) {
703 BT_ERR("desc_info is NULL");
707 BT_DBG("Creating builder for descriptor : %s", desc_info->desc_uuid);
708 desc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
709 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
712 g_variant_builder_add(inner_builder, "{sv}", "UUID",
713 g_variant_new_string(desc_info->desc_uuid));
716 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
717 g_variant_new("o", char_info->char_path));
720 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
721 if (desc_info->desc_value != NULL) {
722 for (i = 0; i < desc_info->value_length; i++) {
723 g_variant_builder_add(builder1, "y", desc_info->desc_value[i]);
725 desc_val = g_variant_new("ay", builder1);
726 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
730 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
731 for (i = 0; i < desc_info->flags_length; i++) {
732 g_variant_builder_add(builder2, "s", desc_info->desc_flags[i]);
734 flags_val = g_variant_new("as", builder2);
735 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
737 g_variant_builder_add(desc_builder, "{sa{sv}}", GATT_DESC_INTERFACE,
739 g_variant_builder_add(builder, "{oa{sa{sv}}}", desc_info->desc_path,
742 /* unref descriptor builder pointers */
743 g_variant_builder_unref(builder1);
744 g_variant_builder_unref(builder2);
745 g_variant_builder_unref(inner_builder);
746 g_variant_builder_unref(desc_builder);
752 /* unref char builder pointers */
753 g_variant_builder_unref(builder1);
754 g_variant_builder_unref(builder2);
755 g_variant_builder_unref(builder3);
756 g_variant_builder_unref(inner_builder);
757 g_variant_builder_unref(char_builder);
760 /* unref service builder pointers */
761 g_variant_builder_unref(inner_builder);
762 g_variant_builder_unref(svc_builder);
765 /* Return builder as method reply */
766 BT_DBG("Sending gatt service builder values to Bluez");
767 g_dbus_method_invocation_return_value(invocation,
768 g_variant_new("(a{oa{sa{sv}}})", builder));
769 g_variant_builder_unref(builder);
773 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
777 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
778 struct gatt_service_info *serv_info = l1->data;
780 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
781 struct gatt_char_info *char_info = l2->data;
783 if (g_strcmp0(char_info->char_path, char_path) == 0)
787 BT_ERR("Gatt service not found");
791 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
793 GSList *l1, *l2, *l3;
795 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
796 struct gatt_service_info *serv_info = l1->data;
798 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
799 struct gatt_char_info *char_info = l2->data;
801 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
802 struct gatt_desc_info *desc_info = l3->data;
804 if (g_strcmp0(desc_info->desc_path, desc_path) == 0)
809 BT_ERR("Gatt service not found");
813 static void __bt_gatt_char_method_call(GDBusConnection *connection,
815 const gchar *object_path,
816 const gchar *interface_name,
817 const gchar *method_name,
818 GVariant *parameters,
819 GDBusMethodInvocation *invocation,
823 if (g_strcmp0(method_name, "ReadValue") == 0) {
827 bt_gatt_read_req_t read_req = {0, };
828 bt_user_info_t *user_info = NULL;
829 struct gatt_req_info *req_info = NULL;
830 struct gatt_service_info *svc_info = NULL;
831 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
832 GVariant *param = NULL;
835 BT_DBG("Application path = %s", object_path);
836 BT_DBG("Sender = %s", sender);
838 user_info = _bt_get_user_data(BT_COMMON);
839 if (user_info == NULL) {
840 BT_INFO("No callback is set for %s", object_path);
841 g_dbus_method_invocation_return_value(invocation, NULL);
845 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
846 if (svc_info == NULL) {
847 BT_ERR("Coudn't find service for %s", object_path);
848 g_dbus_method_invocation_return_value(invocation, NULL);
852 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
853 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
855 read_req.att_handle = (char *)object_path;
856 read_req.address = addr;
857 read_req.req_id = req_id;
858 read_req.offset = offset;
859 read_req.service_handle = svc_info->serv_path;
861 /* Store requets information */
862 req_info = g_new0(struct gatt_req_info, 1);
863 req_info->attr_path = g_strdup(object_path);
864 req_info->svc_path = g_strdup(read_req.service_handle);
865 req_info->request_id = req_id;
866 req_info->offset = offset;
867 req_info->context = invocation;
868 gatt_requests = g_slist_append(gatt_requests, req_info);
870 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
871 param = g_variant_new("(sssyq)",
873 read_req.service_handle,
877 #ifdef TIZEN_FEATURE_BT_HPS
878 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
880 #ifdef TIZEN_FEATURE_BT_OTP
881 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
885 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
886 BLUETOOTH_ERROR_NONE, &read_req,
887 user_info->cb, user_info->user_data);
889 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
890 GVariant *var = NULL;
894 gboolean response_needed = FALSE;
895 bt_gatt_value_change_t value_change = {0, };
896 bt_user_info_t *user_info = NULL;
898 struct gatt_service_info *svc_info = NULL;
899 struct gatt_req_info *req_info = NULL;
900 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
901 GVariant *param = NULL;
904 BT_DBG("WriteValue");
905 BT_DBG("Application path = %s", object_path);
906 BT_DBG("Sender = %s", sender);
908 g_variant_get(parameters, "(&suqb@ay)",
909 &addr, &req_id, &offset, &response_needed, &var);
910 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
912 user_info = _bt_get_user_data(BT_COMMON);
914 BT_INFO("No callback is set for %s", object_path);
915 g_variant_unref(var);
917 g_dbus_method_invocation_return_value(invocation, NULL);
919 g_object_unref(invocation);
923 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
924 if (svc_info == NULL) {
925 BT_ERR("Coudn't find service for %s", object_path);
926 g_variant_unref(var);
928 g_dbus_method_invocation_return_value(invocation, NULL);
930 g_object_unref(invocation);
934 value_change.att_handle = (char *)object_path;
935 value_change.address = addr;
936 value_change.service_handle = svc_info->serv_path;
937 value_change.offset = offset;
938 value_change.req_id = req_id;
939 value_change.response_needed = response_needed;
941 len = g_variant_get_size(var);
945 value_change.att_value = (guint8 *)g_malloc(len);
947 data = (char *)g_variant_get_data(var);
948 memcpy(value_change.att_value, data, len);
950 value_change.val_len = len;
952 if (response_needed) {
953 /* Store requets information */
954 req_info = g_new0(struct gatt_req_info, 1);
955 req_info->attr_path = g_strdup(object_path);
956 req_info->svc_path = g_strdup(value_change.service_handle);
957 req_info->request_id = req_id;
958 req_info->offset = offset;
959 req_info->context = invocation;
960 gatt_requests = g_slist_append(gatt_requests, req_info);
962 g_object_unref(invocation);
965 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
968 svc_path = g_strdup(svc_info->serv_path);
969 param = g_variant_new("(sssyq@ay)",
976 #ifdef TIZEN_FEATURE_BT_HPS
977 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
979 #ifdef TIZEN_FEATURE_BT_OTP
980 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
988 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
989 BLUETOOTH_ERROR_NONE, &value_change,
990 user_info->cb, user_info->user_data);
992 g_free(value_change.att_value);
993 g_variant_unref(var);
995 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
996 bt_user_info_t *user_info = NULL;
997 bt_gatt_char_notify_change_t notify_change = {0, };
998 #if TIZEN_FEATURE_BT_OTP
999 GVariant *param = NULL;
1001 BT_DBG("StartNotify");
1002 user_info = _bt_get_user_data(BT_COMMON);
1003 if (user_info != NULL) {
1004 struct gatt_service_info *svc_info = NULL;
1005 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1007 notify_change.service_handle = svc_info->serv_path;
1008 notify_change.att_handle = (char *)object_path;
1009 notify_change.att_notify = TRUE;
1010 #if TIZEN_FEATURE_BT_OTP
1011 param = g_variant_new("(ssb)",
1012 notify_change.att_handle,
1013 notify_change.service_handle,
1014 notify_change.att_notify);
1015 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1017 _bt_common_event_cb(
1018 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1019 BLUETOOTH_ERROR_NONE, ¬ify_change,
1020 user_info->cb, user_info->user_data);
1023 g_object_unref(invocation);
1025 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1026 bt_user_info_t *user_info = NULL;
1027 bt_gatt_char_notify_change_t notify_change = {0, };
1028 #if TIZEN_FEATURE_BT_OTP
1029 GVariant *param = NULL;
1031 BT_DBG("StopNotify");
1032 user_info = _bt_get_user_data(BT_COMMON);
1033 if (user_info != NULL) {
1034 struct gatt_service_info *svc_info = NULL;
1035 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1037 notify_change.service_handle = svc_info->serv_path;
1038 notify_change.att_handle = (char *)object_path;
1039 notify_change.att_notify = FALSE;
1040 #if TIZEN_FEATURE_BT_OTP
1041 param = g_variant_new("(ssb)",
1042 notify_change.att_handle,
1043 notify_change.service_handle,
1044 notify_change.att_notify);
1045 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1047 _bt_common_event_cb(
1048 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1049 BLUETOOTH_ERROR_NONE, ¬ify_change,
1050 user_info->cb, user_info->user_data);
1053 g_object_unref(invocation);
1055 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1057 bt_gatt_indicate_confirm_t confirm = {0, };
1058 bt_user_info_t *user_info = NULL;
1059 gboolean complete = FALSE;
1060 struct gatt_service_info *svc_info = NULL;
1062 BT_DBG("IndicateConfirm");
1063 BT_DBG("Application path = %s", object_path);
1064 BT_DBG("Sender = %s", sender);
1066 g_variant_get(parameters, "(&sb)", &addr, &complete);
1067 BT_DBG("Remote Device address number = %s", addr);
1069 confirm.att_handle = (char *)object_path;
1070 confirm.address = addr;
1071 confirm.complete = complete;
1073 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1074 if (svc_info != NULL) {
1075 confirm.service_handle = svc_info->serv_path;
1077 user_info = _bt_get_user_data(BT_COMMON);
1078 if (user_info != NULL) {
1079 _bt_common_event_cb(
1080 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1081 BLUETOOTH_ERROR_NONE, &confirm,
1082 user_info->cb, user_info->user_data);
1087 g_dbus_method_invocation_return_value(invocation, NULL);
1090 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1091 const gchar *sender,
1092 const gchar *object_path,
1093 const gchar *interface_name,
1094 const gchar *method_name,
1095 GVariant *parameters,
1096 GDBusMethodInvocation *invocation,
1099 if (g_strcmp0(method_name, "ReadValue") == 0) {
1103 bt_gatt_read_req_t read_req = {0, };
1104 bt_user_info_t *user_info = NULL;
1105 struct gatt_req_info *req_info = NULL;
1106 struct gatt_service_info *svc_info = NULL;
1108 BT_DBG("ReadValue");
1109 BT_DBG("Application path = %s", object_path);
1110 BT_DBG("Sender = %s", sender);
1112 user_info = _bt_get_user_data(BT_COMMON);
1113 if (user_info == NULL) {
1114 BT_INFO("No callback is set for %s", object_path);
1115 g_dbus_method_invocation_return_value(invocation, NULL);
1119 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1120 if (svc_info == NULL) {
1121 BT_ERR("Coudn't find service for %s", object_path);
1122 g_dbus_method_invocation_return_value(invocation, NULL);
1126 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1127 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1129 read_req.att_handle = (char *)object_path;
1130 read_req.address = addr;
1131 read_req.req_id = req_id;
1132 read_req.offset = offset;
1133 read_req.service_handle = svc_info->serv_path;
1135 /* Store requets information */
1136 req_info = g_new0(struct gatt_req_info, 1);
1137 req_info->attr_path = g_strdup(object_path);
1138 req_info->svc_path = g_strdup(read_req.service_handle);
1139 req_info->request_id = req_id;
1140 req_info->offset = offset;
1141 req_info->context = invocation;
1142 gatt_requests = g_slist_append(gatt_requests, req_info);
1144 _bt_common_event_cb(
1145 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1146 BLUETOOTH_ERROR_NONE, &read_req,
1147 user_info->cb, user_info->user_data);
1150 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1151 GVariant *var = NULL;
1155 gboolean response_needed = FALSE;
1156 bt_gatt_value_change_t value_change = {0, };
1157 bt_user_info_t *user_info = NULL;
1159 struct gatt_service_info *svc_info = NULL;
1160 struct gatt_req_info *req_info = NULL;
1162 BT_DBG("WriteValue");
1163 BT_DBG("Application path = %s", object_path);
1164 BT_DBG("Sender = %s", sender);
1166 g_variant_get(parameters, "(&suqb@ay)",
1167 &addr, &req_id, &offset, &response_needed, &var);
1168 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1170 user_info = _bt_get_user_data(BT_COMMON);
1171 if (user_info == NULL) {
1172 BT_INFO("No callback is set for %s", object_path);
1173 g_variant_unref(var);
1174 if (response_needed)
1175 g_dbus_method_invocation_return_value(invocation, NULL);
1177 g_object_unref(invocation);
1181 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1182 if (svc_info == NULL) {
1183 BT_ERR("Coudn't find service for %s", object_path);
1184 g_variant_unref(var);
1185 if (response_needed)
1186 g_dbus_method_invocation_return_value(invocation, NULL);
1188 g_object_unref(invocation);
1192 value_change.att_handle = (char *)object_path;
1193 value_change.address = addr;
1194 value_change.service_handle = svc_info->serv_path;
1195 value_change.offset = offset;
1196 value_change.req_id = req_id;
1197 value_change.response_needed = response_needed;
1199 len = g_variant_get_size(var);
1203 value_change.att_value = (guint8 *)g_malloc(len);
1205 data = (char *)g_variant_get_data(var);
1206 memcpy(value_change.att_value, data, len);
1208 value_change.val_len = len;
1210 if (response_needed) {
1211 /* Store requets information */
1212 req_info = g_new0(struct gatt_req_info, 1);
1213 req_info->attr_path = g_strdup(object_path);
1214 req_info->svc_path = g_strdup(value_change.service_handle);
1215 req_info->request_id = req_id;
1216 req_info->offset = offset;
1217 req_info->context = invocation;
1218 gatt_requests = g_slist_append(gatt_requests, req_info);
1220 g_object_unref(invocation);
1223 _bt_common_event_cb(
1224 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1225 BLUETOOTH_ERROR_NONE, &value_change,
1226 user_info->cb, user_info->user_data);
1228 g_free(value_change.att_value);
1229 g_variant_unref(var);
1234 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1237 GError *error = NULL;
1238 GVariantBuilder *array_builder;
1240 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1241 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1242 g_variant_builder_add(array_builder, "s", interface);
1244 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1245 "org.freedesktop.Dbus.Objectmanager",
1246 "InterfacesRemoved",
1247 g_variant_new("(oas)",
1248 object_path, array_builder),
1252 if (error != NULL) {
1253 /* dbus gives error cause */
1254 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1255 error->code, error->message);
1256 g_clear_error(&error);
1259 g_variant_builder_unref(array_builder);
1264 static const GDBusInterfaceVTable desc_interface_vtable = {
1265 __bt_gatt_desc_method_call,
1271 static const GDBusInterfaceVTable char_interface_vtable = {
1272 __bt_gatt_char_method_call,
1278 static const GDBusInterfaceVTable serv_interface_vtable = {
1285 static const GDBusInterfaceVTable manager_interface_vtable = {
1286 __bt_gatt_manager_method_call,
1292 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1293 const gchar *introspection_data)
1296 GDBusNodeInfo *node_info = NULL;
1298 if (introspection_data == NULL)
1302 BT_DBG("Create new node info");
1303 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1306 BT_ERR("Unable to create node: %s", err->message);
1307 g_clear_error(&err);
1314 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1315 const char *service_path)
1319 for (l = gatt_services; l != NULL; l = l->next) {
1320 struct gatt_service_info *info = l->data;
1322 if (g_strcmp0(info->serv_path, service_path) == 0)
1325 BT_ERR("Gatt service not found");
1329 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1330 const char *service_path, const char *char_path)
1334 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1335 struct gatt_service_info *serv_info = l1->data;
1337 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1339 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1340 struct gatt_char_info *char_info = l2->data;
1342 if (g_strcmp0(char_info->char_path, char_path) == 0)
1345 BT_ERR("Gatt characteristic not found");
1349 BT_ERR("Gatt service not found");
1353 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1354 const char *serv_path, const char *char_path,
1355 const char *desc_path)
1357 GSList *l1, *l2, *l3;
1359 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1360 struct gatt_service_info *serv_info = l1->data;
1362 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1363 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1364 struct gatt_char_info *char_info = l2->data;
1366 if (g_strcmp0(char_info->char_path, char_path) == 0) {
1367 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1368 struct gatt_desc_info *desc_info = l3->data;
1369 if (g_strcmp0(desc_info->desc_path,
1378 BT_ERR("Gatt descriptor not found");
1382 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1386 for (l = gatt_requests; l != NULL; l = l->next) {
1387 struct gatt_req_info *req_info = l->data;
1389 if (req_info && req_info->request_id == request_id)
1392 BT_ERR("Gatt Request not found");
1396 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1397 const gchar *path, const gchar *interface)
1402 g_conn = _bt_get_system_shared_conn();
1404 BT_ERR("Unable to get connection");
1408 proxy = g_dbus_proxy_new_sync(g_conn,
1409 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1411 interface, NULL, &err);
1415 BT_ERR("Unable to create proxy: %s", err->message);
1416 g_clear_error(&err);
1420 manager_gproxy = proxy;
1425 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1426 const gchar *path, const gchar *interface)
1428 return (manager_gproxy) ? manager_gproxy :
1429 __bt_gatt_gdbus_init_manager_proxy(service,
1433 static gboolean __bt_gatt_is_service_registered(const char *service_path)
1435 struct gatt_service_info *svc_info = NULL;
1437 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1439 if (svc_info != NULL) {
1440 BT_DBG("Return the state of the gatt service %d",
1441 svc_info->is_svc_registered);
1442 return svc_info->is_svc_registered;
1445 BT_DBG("gatt service info is NULL");
1449 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1451 GError *error = NULL;
1453 GVariantIter *iter = NULL;
1454 const gchar *key = NULL;
1455 GVariant *value = NULL;
1456 const gchar *service = NULL;
1457 const gchar *characteristic = NULL;
1458 const gchar *descriptor = NULL;
1462 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1464 if (result == NULL) {
1465 BT_ERR("Dbus-RPC is failed");
1466 if (error != NULL) {
1467 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1468 error->code, error->message);
1469 g_clear_error(&error);
1472 char *char_cmp = NULL;
1473 g_variant_get(result, "(a{sv})", &iter);
1474 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1476 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1477 if (g_strcmp0(key, "Service") == 0) {
1478 service = g_variant_get_string(value, NULL);
1479 BT_DBG("Service %s", service);
1480 } else if (g_strcmp0(key, char_cmp) == 0) {
1481 characteristic = g_variant_get_string(value, NULL);
1483 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1484 BT_DBG("%s", characteristic);
1485 } else if (g_strcmp0(key, "Descriptor") == 0) {
1486 descriptor = g_variant_get_string(value, NULL);
1487 BT_DBG("Descriptor %s", descriptor);
1490 g_variant_iter_free(iter);
1492 /* TODO: Store the service informationa and
1493 * Send respponse to CAPI layer. */
1495 g_variant_unref(result);
1500 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1502 BT_INFO("RegisterApplication is completed");
1504 GError *error = NULL;
1507 if (register_cancel) {
1508 g_object_unref(register_cancel);
1509 register_cancel = NULL;
1512 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1513 if (result == NULL) {
1514 BT_ERR("Dbus-RPC is failed");
1515 if (error != NULL) {
1516 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1517 error->code, error->message);
1518 g_clear_error(&error);
1520 is_server_started = false;
1522 g_variant_unref(result);
1526 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1528 GDBusProxy *proxy = NULL;
1530 if (is_server_started) {
1534 if (app_path == NULL) {
1535 BT_ERR("app_path is NULL");
1536 return BLUETOOTH_ERROR_INTERNAL;
1539 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1540 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1541 if (proxy == NULL) {
1542 BT_ERR("proxy is NULL");
1543 return BLUETOOTH_ERROR_INTERNAL;
1546 BT_INFO("UnregisterApplication");
1548 /* Async Call to Unregister Service */
1549 ret = g_dbus_proxy_call_sync(proxy, "UnregisterApplication",
1550 g_variant_new("(o)", app_path), G_DBUS_CALL_FLAGS_NONE, -1,
1553 BT_ERR("dBUS-RPC is failed");
1555 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1556 err->code, err->message);
1557 g_clear_error(&err);
1559 return BLUETOOTH_ERROR_INTERNAL;
1561 g_variant_unref(ret);
1563 is_server_started = false;
1565 BT_INFO("UnregisterApplication is completed");
1567 return BLUETOOTH_ERROR_NONE;
1570 BT_INFO("GATT server not started");
1571 return BLUETOOTH_ERROR_NONE;
1574 BT_EXPORT_API int bluetooth_gatt_init(void)
1576 GError *error = NULL;
1577 GDBusNodeInfo *node_info = NULL;
1579 if (app_path != NULL) {
1580 BT_ERR("app path already exists! initialized");
1581 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1584 g_conn = _bt_get_system_shared_conn();
1586 BT_ERR("Unable to get connection");
1590 if (owner_id == 0) {
1591 gchar *name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
1592 BT_DBG("well-known name: %s", name);
1594 owner_id = g_bus_own_name_on_connection(g_conn, name,
1595 G_BUS_NAME_OWNER_FLAGS_NONE,
1596 NULL, NULL, NULL, NULL);
1599 BT_DBG("owner_id is [%d]", owner_id);
1601 app_path = g_strdup_printf("/com/%d", getpid());
1605 /* Register ObjectManager interface */
1606 node_info = __bt_gatt_create_method_node_info(
1607 manager_introspection_xml);
1608 if (node_info == NULL) {
1609 BT_ERR("failed to get node info");
1613 if (manager_id == 0) {
1614 BT_INFO("manager_id does not exists");
1616 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1617 node_info->interfaces[0],
1618 &manager_interface_vtable,
1619 NULL, NULL, &error);
1621 g_dbus_node_info_unref(node_info);
1622 if (manager_id == 0) {
1623 BT_ERR("failed to register: %s", error->message);
1624 g_error_free(error);
1628 return BLUETOOTH_ERROR_NONE;
1632 g_bus_unown_name(owner_id);
1639 return BLUETOOTH_ERROR_INTERNAL;
1642 BT_EXPORT_API int bluetooth_gatt_deinit()
1644 int ret = BLUETOOTH_ERROR_NONE;
1646 if (register_cancel) {
1647 g_cancellable_cancel(register_cancel);
1648 g_object_unref(register_cancel);
1649 register_cancel = NULL;
1652 if (owner_id == 0) {
1653 BT_ERR("owner_id is zero");
1654 return BLUETOOTH_ERROR_NOT_FOUND;
1657 BT_DBG("Removing all registered gatt services");
1658 bluetooth_gatt_delete_services();
1660 /* Unregister the exported interface for object manager */
1662 g_dbus_connection_unregister_object(g_conn, manager_id);
1666 ret = bluetooth_gatt_unregister_application();
1667 if (ret != BLUETOOTH_ERROR_NONE) {
1668 BT_ERR("Fail to unregister application");
1671 g_bus_unown_name(owner_id);
1677 if (manager_gproxy) {
1678 g_object_unref(manager_gproxy);
1679 manager_gproxy = NULL;
1686 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1689 GError *error = NULL;
1691 GDBusNodeInfo *node_info;
1693 GVariantBuilder *builder = NULL;
1694 GVariantBuilder *builder1 = NULL;
1695 GVariantBuilder *inner_builder = NULL;
1696 gboolean svc_primary = TRUE;
1697 struct gatt_service_info *serv_info = NULL;
1699 node_info = __bt_gatt_create_method_node_info(
1700 service_introspection_xml);
1701 if (node_info == NULL)
1702 return BLUETOOTH_ERROR_INTERNAL;
1704 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1705 BT_DBG("gatt service path is [%s]", path);
1707 object_id = g_dbus_connection_register_object(g_conn, path,
1708 node_info->interfaces[0],
1709 &serv_interface_vtable,
1710 NULL, NULL, &error);
1711 g_dbus_node_info_unref(node_info);
1713 if (object_id == 0) {
1714 BT_ERR("failed to register: %s", error->message);
1715 g_error_free(error);
1718 return BLUETOOTH_ERROR_INTERNAL;
1721 /* Add object_id/gatt service information; it's required at the time of
1722 * service unregister and Getmanagedobjects
1724 serv_info = g_new0(struct gatt_service_info, 1);
1726 serv_info->serv_path = g_strdup(path);
1727 serv_info->serv_id = object_id;
1728 serv_info->service_uuid = g_strdup(svc_uuid);
1729 serv_info->is_svc_registered = FALSE;
1730 serv_info->is_svc_primary = svc_primary;
1732 gatt_services = g_slist_append(gatt_services, serv_info);
1734 /* emit interfacesadded signal here for service path */
1735 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1736 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1738 g_variant_builder_add(inner_builder, "{sv}",
1739 "UUID", g_variant_new_string(svc_uuid));
1741 g_variant_builder_add(inner_builder, "{sv}",
1742 "Primary", g_variant_new_boolean(svc_primary));
1744 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1746 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1747 g_variant_new("ao", builder1));
1749 g_variant_builder_add(builder, "{sa{sv}}",
1750 GATT_SERV_INTERFACE, inner_builder);
1752 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1753 "org.freedesktop.Dbus.ObjectManager",
1755 g_variant_new("(oa{sa{sv}})",
1758 if (error != NULL) {
1759 /* dbus gives error cause */
1760 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1761 error->code, error->message);
1762 g_clear_error(&error);
1767 *svc_path = g_strdup(path);
1770 g_variant_builder_unref(inner_builder);
1771 g_variant_builder_unref(builder);
1772 g_variant_builder_unref(builder1);
1774 return BLUETOOTH_ERROR_NONE;
1777 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1778 const char *svc_path, const char *char_uuid,
1779 bt_gatt_permission_t permissions,
1780 bt_gatt_characteristic_property_t properties,
1784 GError *error = NULL;
1786 GDBusNodeInfo *node_info;
1788 GVariantBuilder *builder = NULL;
1789 GVariantBuilder *inner_builder = NULL;
1790 struct gatt_service_info *serv_info = NULL;
1791 struct gatt_char_info *char_info = NULL;
1792 GVariantBuilder *builder2 = NULL;
1793 GVariantBuilder *builder3 = NULL;
1794 GVariant *flags_val = NULL;
1796 char *char_flags[NUMBER_OF_FLAGS];
1801 new_service = FALSE;
1804 BT_DBG("gatt svc_path path is [%s]", svc_path);
1805 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1806 if (serv_info == NULL)
1807 return BLUETOOTH_ERROR_INVALID_PARAM;
1809 node_info = __bt_gatt_create_method_node_info(
1810 characteristics_introspection_xml);
1811 if (node_info == NULL)
1812 return BLUETOOTH_ERROR_INTERNAL;
1814 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1815 BT_DBG("gatt characteristic path is [%s]", path);
1817 object_id = g_dbus_connection_register_object(g_conn, path,
1818 node_info->interfaces[0],
1819 &char_interface_vtable,
1820 NULL, NULL, &error);
1821 g_dbus_node_info_unref(node_info);
1823 if (object_id == 0) {
1824 BT_ERR("failed to register: %s", error->message);
1825 g_error_free(error);
1828 return BLUETOOTH_ERROR_INTERNAL;
1831 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1832 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1833 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1834 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1835 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1836 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1837 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1838 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1840 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1842 char_info = g_new0(struct gatt_char_info, 1);
1844 char_info->char_path = g_strdup(path);
1845 char_info->char_id = object_id;
1846 char_info->char_uuid = g_strdup(char_uuid);
1848 for (i = 0; i < flag_count; i++)
1849 char_info->char_flags[i] = char_flags[i];
1852 char_info->flags_length = flag_count;
1854 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1856 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1857 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1859 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1860 g_variant_new("s", char_uuid));
1861 g_variant_builder_add(inner_builder, "{sv}", "Service",
1862 g_variant_new("o", svc_path));
1864 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1866 for (i = 0; i < flag_count; i++)
1867 g_variant_builder_add(builder2, "s", char_flags[i]);
1869 flags_val = g_variant_new("as", builder2);
1870 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1873 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1875 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1876 g_variant_new("ao", builder3));
1878 g_variant_builder_add(builder, "{sa{sv}}",
1879 GATT_CHAR_INTERFACE,
1882 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1883 "org.freedesktop.Dbus.ObjectManager",
1885 g_variant_new("(oa{sa{sv}})",
1889 /* dBUS gives error cause */
1890 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1891 error->code, error->message);
1892 g_clear_error(&error);
1895 *char_path = g_strdup(path);
1901 g_variant_builder_unref(inner_builder);
1902 g_variant_builder_unref(builder);
1903 g_variant_builder_unref(builder2);
1904 g_variant_builder_unref(builder3);
1906 return BLUETOOTH_ERROR_NONE;
1909 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1910 const char *characteristic, const char *char_value,
1913 gchar **line_argv = NULL;
1914 char *serv_path = NULL;
1915 struct gatt_char_info *char_info = NULL;
1916 GVariantBuilder *builder1 = NULL;
1917 GVariantBuilder *builder = NULL;
1918 GVariantBuilder *inner_builder = NULL;
1919 GVariant *char_val = NULL;
1920 GError *error = NULL;
1922 int res = BLUETOOTH_ERROR_NONE;
1924 line_argv = g_strsplit_set(characteristic, "/", 0);
1925 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1927 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1929 if (char_info == NULL) {
1930 /* Fix : RESOURCE_LEAK */
1931 res = BLUETOOTH_ERROR_INVALID_PARAM;
1935 char_info->value_length = value_length;
1937 char_info->char_value = (char *)malloc(value_length);
1938 /* Fix : NULL_RETURNS */
1939 if (char_info->char_value == NULL) {
1940 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1944 for (i = 0; i < value_length; i++)
1945 char_info->char_value[i] = char_value[i];
1947 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1948 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1950 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1952 for (i = 0; i < value_length; i++)
1953 g_variant_builder_add(builder1, "y", char_value[i]);
1955 char_val = g_variant_new("ay", builder1);
1956 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1958 g_variant_builder_add(builder, "{sa{sv}}",
1959 GATT_CHAR_INTERFACE,
1962 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1963 "org.freedesktop.Dbus.ObjectManager",
1965 g_variant_new("(oa{sa{sv}})",
1966 char_info->char_path, builder),
1970 /* dBUS gives error cause */
1971 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1972 error->code, error->message);
1973 g_clear_error(&error);
1975 g_variant_builder_unref(inner_builder);
1976 g_variant_builder_unref(builder);
1977 g_variant_builder_unref(builder1);
1979 g_strfreev(line_argv);
1985 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
1986 const char *char_path, const char *desc_uuid,
1987 bt_gatt_permission_t permissions,
1990 static int desc_id = 1;
1991 GError *error = NULL;
1993 GDBusNodeInfo *node_info;
1995 GVariantBuilder *builder = NULL;
1996 GVariantBuilder *inner_builder = NULL;
1997 struct gatt_char_info *char_info = NULL;
1998 struct gatt_desc_info *desc_info = NULL;
1999 gchar **line_argv = NULL;
2001 GVariantBuilder *builder2 = NULL;
2002 GVariant *flags_val = NULL;
2004 char *desc_flags[NUMBER_OF_FLAGS];
2012 line_argv = g_strsplit_set(char_path, "/", 0);
2013 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2015 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2016 if (char_info == NULL) {
2017 g_strfreev(line_argv);
2019 return BLUETOOTH_ERROR_INVALID_PARAM;
2022 node_info = __bt_gatt_create_method_node_info(
2023 descriptor_introspection_xml);
2024 if (node_info == NULL) {
2025 g_strfreev(line_argv);
2027 return BLUETOOTH_ERROR_INTERNAL;
2030 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2031 BT_DBG("gatt descriptor path is [%s]", path);
2033 object_id = g_dbus_connection_register_object(g_conn, path,
2034 node_info->interfaces[0],
2035 &desc_interface_vtable,
2036 NULL, NULL, &error);
2037 g_dbus_node_info_unref(node_info);
2039 if (object_id == 0) {
2040 BT_ERR("failed to register: %s", error->message);
2041 g_error_free(error);
2043 g_strfreev(line_argv);
2046 return BLUETOOTH_ERROR_INTERNAL;
2049 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2051 desc_info = g_new0(struct gatt_desc_info, 1);
2053 desc_info->desc_path = g_strdup(path);
2054 desc_info->desc_id = object_id;
2055 desc_info->desc_uuid = g_strdup(desc_uuid);
2057 for (i = 0; i < flag_count; i++)
2058 desc_info->desc_flags[i] = desc_flags[i];
2060 desc_info->flags_length = flag_count;
2062 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2064 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2065 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2067 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2068 g_variant_new("s", desc_uuid));
2069 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2070 g_variant_new("o", char_path));
2072 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2074 for (i = 0; i < flag_count; i++)
2075 g_variant_builder_add(builder2, "s", desc_flags[i]);
2077 flags_val = g_variant_new("as", builder2);
2078 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2081 g_variant_builder_add(builder, "{sa{sv}}",
2082 GATT_DESC_INTERFACE,
2085 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2086 "org.freedesktop.Dbus.ObjectManager",
2088 g_variant_new("(oa{sa{sv}})",
2092 /* dBUS gives error cause */
2093 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2094 error->code, error->message);
2095 g_clear_error(&error);
2098 *desc_path = g_strdup(path);
2102 g_strfreev(line_argv);
2103 g_variant_builder_unref(inner_builder);
2104 g_variant_builder_unref(builder);
2105 g_variant_builder_unref(builder2);
2107 return BLUETOOTH_ERROR_NONE;
2110 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2111 const char *desc_path, const char *desc_value,
2114 GError *error = NULL;
2115 GVariantBuilder *builder = NULL;
2116 GVariantBuilder *inner_builder = NULL;
2117 GVariantBuilder *builder1 = NULL;
2118 struct gatt_desc_info *desc_info = NULL;
2119 gchar **line_argv = NULL;
2121 GVariant *desc_val = NULL;
2122 char *serv_path = NULL;
2125 line_argv = g_strsplit_set(desc_path, "/", 0);
2126 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2127 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2129 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2131 /* Free the allocated memory */
2132 g_strfreev(line_argv);
2136 /* Fix : NULL_RETURNS */
2137 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2139 desc_info->desc_value = (char *)malloc(value_length);
2141 /* Fix : NULL_RETURNS */
2142 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2144 for (i = 0; i < value_length; i++)
2145 desc_info->desc_value[i] = desc_value[i];
2147 desc_info->value_length = value_length;
2149 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2150 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2152 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2154 for (i = 0; i < value_length; i++)
2155 g_variant_builder_add(builder1, "y", desc_value[i]);
2157 desc_val = g_variant_new("ay", builder1);
2158 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2160 g_variant_builder_add(builder, "{sa{sv}}",
2161 GATT_DESC_INTERFACE,
2164 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2165 "org.freedesktop.Dbus.ObjectManager",
2167 g_variant_new("(oa{sa{sv}})",
2168 desc_info->desc_path, builder),
2171 if (error != NULL) {
2172 BT_ERR("D-Bus API failure: errCode[%x], \
2174 error->code, error->message);
2175 g_clear_error(&error);
2178 g_variant_builder_unref(inner_builder);
2179 g_variant_builder_unref(builder);
2180 g_variant_builder_unref(builder1);
2182 return BLUETOOTH_ERROR_NONE;
2185 int bluetooth_gatt_get_service(const char *svc_uuid)
2187 GDBusProxy *proxy = NULL;
2190 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2191 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2193 return BLUETOOTH_ERROR_INTERNAL;
2195 uuid = g_strdup(svc_uuid);
2197 g_dbus_proxy_call(proxy,
2199 g_variant_new("(s)",
2201 G_DBUS_CALL_FLAGS_NONE, -1,
2203 (GAsyncReadyCallback) get_service_cb,
2208 return BLUETOOTH_ERROR_NONE;
2211 BT_EXPORT_API int bluetooth_gatt_register_service(const char *svc_path)
2213 struct gatt_service_info *svc_info = NULL;
2215 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2216 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2217 BT_ERR("Don't have aprivilege to use this API");
2218 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2221 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2222 if (svc_info == NULL) {
2223 BT_ERR("Cannot find service [%s]", svc_path);
2224 return BLUETOOTH_ERROR_INTERNAL;
2226 svc_info->is_svc_registered = TRUE;
2228 return BLUETOOTH_ERROR_NONE;
2231 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2233 GDBusProxy *proxy = NULL;
2235 if (!is_server_started) {
2236 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2237 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2238 BT_ERR("Don't have aprivilege to use this API");
2239 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2242 if (g_slist_length(gatt_services) == 0) {
2243 BT_ERR("There is no registered service");
2244 return BLUETOOTH_ERROR_INTERNAL;
2247 if (app_path == NULL) {
2248 BT_ERR("app_path is NULL");
2249 return BLUETOOTH_ERROR_INTERNAL;
2252 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2253 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2254 if (proxy == NULL) {
2255 BT_ERR("proxy is NULL");
2256 return BLUETOOTH_ERROR_INTERNAL;
2259 BT_INFO("RegisterApplication");
2261 if (register_cancel) {
2262 g_cancellable_cancel(register_cancel);
2263 g_object_unref(register_cancel);
2265 register_cancel = g_cancellable_new();
2267 g_dbus_proxy_call(proxy, "RegisterApplication",
2268 g_variant_new("(oa{sv})", app_path, NULL),
2269 G_DBUS_CALL_FLAGS_NONE, -1, register_cancel,
2270 (GAsyncReadyCallback)register_application_cb, NULL);
2272 is_server_started = true;
2274 return BLUETOOTH_ERROR_NONE;
2277 BT_INFO("Already RegisterApplication");
2279 return BLUETOOTH_ERROR_NONE;
2282 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2285 int ret = BLUETOOTH_ERROR_NONE;
2287 if (gatt_services == NULL) {
2288 BT_DBG("There are no registered services");
2293 for (l = gatt_services; l != NULL; ) {
2294 struct gatt_service_info *info = l->data;
2296 // In __bt_gatt_unregister_service, current node will be removed.
2297 // Go forward to next node before calling __bt_gatt_unregister_service.
2299 if (__bt_gatt_unregister_service(info) != BLUETOOTH_ERROR_NONE) {
2300 ret = BLUETOOTH_ERROR_INTERNAL;
2303 BT_INFO("All services are removed : %d", ret);
2305 g_slist_free(gatt_services);
2306 gatt_services = NULL;
2312 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2313 const char *char_path, const char* char_value,
2316 GVariantBuilder *outer_builder;
2317 GVariantBuilder *inner_builder;
2318 GVariantBuilder *invalidated_builder;
2319 GVariant *update_value = NULL;
2320 GError *error = NULL;
2321 gboolean ret = FALSE;
2322 int err = BLUETOOTH_ERROR_NONE;
2324 gchar **line_argv = NULL;
2325 gchar *serv_path = NULL;
2326 const char *value = NULL;
2328 line_argv = g_strsplit_set(char_path, "/", 0);
2329 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2331 if (!__bt_gatt_is_service_registered(serv_path)) {
2332 BT_DBG("service not registered for this characteristic");
2334 g_strfreev(line_argv);
2335 return BLUETOOTH_ERROR_INTERNAL;
2338 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2339 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2341 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2342 for (i = 0; i < value_length; i++)
2343 g_variant_builder_add(inner_builder, "y", char_value[i]);
2345 update_value = g_variant_new("ay", inner_builder);
2347 g_variant_builder_add(outer_builder, "{sv}", "Value",
2350 BT_DBG("Updating characteristic value");
2351 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2353 "org.freedesktop.DBus.Properties",
2354 "PropertiesChanged",
2355 g_variant_new("(sa{sv}as)",
2356 "org.bluez.GattCharacteristic1",
2357 outer_builder, invalidated_builder),
2361 if (error != NULL) {
2362 BT_ERR("D-Bus API failure: errCode[%x], \
2364 error->code, error->message);
2365 g_clear_error(&error);
2367 err = BLUETOOTH_ERROR_INTERNAL;
2369 struct gatt_char_info *char_info = NULL;
2371 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2372 if (char_info == NULL) {
2374 g_strfreev(line_argv);
2375 g_variant_builder_unref(inner_builder);
2376 g_variant_builder_unref(outer_builder);
2377 g_variant_builder_unref(invalidated_builder);
2379 return BLUETOOTH_ERROR_INVALID_DATA;
2382 char_info->value_length = value_length;
2384 value = (char *)realloc(char_info->char_value, value_length);
2385 if (value == NULL) {
2387 g_strfreev(line_argv);
2388 g_variant_builder_unref(inner_builder);
2389 g_variant_builder_unref(outer_builder);
2390 g_variant_builder_unref(invalidated_builder);
2392 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2395 char_info->char_value = (char*)value;
2396 if (char_info->char_value) {
2397 for (i = 0; i < value_length; i++)
2398 char_info->char_value[i] = char_value[i];
2403 g_strfreev(line_argv);
2404 g_variant_builder_unref(inner_builder);
2405 g_variant_builder_unref(outer_builder);
2406 g_variant_builder_unref(invalidated_builder);
2411 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2418 g_free(desc_info->desc_path);
2419 g_free(desc_info->desc_uuid);
2420 g_free(desc_info->desc_value);
2422 for (i = 0; i < desc_info->flags_length; i++)
2423 g_free(desc_info->desc_flags[i]);
2428 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2435 g_free(char_info->char_path);
2436 g_free(char_info->char_uuid);
2437 g_free(char_info->char_value);
2439 for (i = 0; i < char_info->flags_length; i++)
2440 g_free(char_info->char_flags[i]);
2445 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2450 g_free(svc_info->serv_path);
2451 g_free(svc_info->service_uuid);
2455 static void __desc_info_free(gpointer data, gpointer user_data)
2457 struct gatt_desc_info *desc_info = data;
2458 int *err = user_data;
2461 if (desc_info == NULL)
2464 ret = g_dbus_connection_unregister_object(g_conn, desc_info->desc_id);
2466 __bt_gatt_emit_interface_removed(desc_info->desc_path, GATT_DESC_INTERFACE);
2468 *err = BLUETOOTH_ERROR_INTERNAL;
2470 __bt_gatt_free_descriptor_info(desc_info);
2473 static void __char_info_free(gpointer data, gpointer user_data)
2475 struct gatt_char_info *char_info = data;
2476 int *err = user_data;
2479 if (char_info == NULL)
2482 g_slist_foreach(char_info->desc_data, __desc_info_free, user_data);
2483 g_slist_free(char_info->desc_data);
2484 char_info->desc_data = NULL;
2486 ret = g_dbus_connection_unregister_object(g_conn, char_info->char_id);
2488 __bt_gatt_emit_interface_removed(char_info->char_path, GATT_CHAR_INTERFACE);
2490 *err = BLUETOOTH_ERROR_INTERNAL;
2492 __bt_gatt_free_characteristic_info(char_info);
2495 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info)
2497 int ret = BLUETOOTH_ERROR_NONE;
2499 if (svc_info == NULL) {
2500 BT_ERR("svc_info is NULL");
2501 return BLUETOOTH_ERROR_NOT_FOUND;
2504 if (svc_info->is_svc_registered == FALSE) {
2505 BT_ERR("%s is not registered", svc_info->serv_path);
2506 return BLUETOOTH_ERROR_NOT_FOUND;
2509 BT_DBG("svc_path %s", svc_info->serv_path);
2511 g_slist_foreach(svc_info->char_data, __char_info_free, &ret);
2512 g_slist_free(svc_info->char_data);
2513 svc_info->char_data = NULL;
2515 if (g_dbus_connection_unregister_object(g_conn, svc_info->serv_id) == FALSE) {
2516 BT_ERR("Cannot unregister object for [%s]", svc_info->serv_path);
2517 ret = BLUETOOTH_ERROR_INTERNAL;
2519 __bt_gatt_emit_interface_removed(svc_info->serv_path, GATT_SERV_INTERFACE);
2522 gatt_services = g_slist_remove(gatt_services, svc_info);
2523 __bt_gatt_free_service_info(svc_info);
2525 new_service = FALSE;
2527 if (gatt_services == NULL) {
2529 } else if (gatt_services->next == NULL) {
2536 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2538 struct gatt_service_info *svc_info;
2539 int ret = BLUETOOTH_ERROR_NONE;
2543 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2545 ret = __bt_gatt_unregister_service(svc_info);
2546 if (ret != BLUETOOTH_ERROR_NONE) {
2547 BT_ERR("Could not unregister service [%s]", svc_path);
2554 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2555 int resp_state, int offset, char *value, int value_length)
2557 struct gatt_req_info *req_info = NULL;
2559 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2560 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2561 BT_ERR("Don't have aprivilege to use this API");
2562 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2565 req_info = __bt_gatt_find_request_info(request_id);
2566 if (req_info == NULL) {
2567 BT_ERR("Coundn't find request id [%d]", request_id);
2568 return BLUETOOTH_ERROR_INTERNAL;
2571 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2572 BT_ERR("resp_state is 0x%X", resp_state);
2573 char err_msg[20] = { 0, };
2574 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2575 g_dbus_method_invocation_return_dbus_error(req_info->context,
2576 "org.bluez.Error.Failed", err_msg);
2578 gatt_requests = g_slist_remove(gatt_requests, req_info);
2580 req_info->context = NULL;
2581 if (req_info->attr_path)
2582 g_free(req_info->attr_path);
2583 if (req_info->svc_path)
2584 g_free(req_info->svc_path);
2587 return BLUETOOTH_ERROR_NONE;
2590 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2592 GVariantBuilder *inner_builder = NULL;
2593 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2594 if (value_length > 0 && value != NULL) {
2595 for (i = 0; i < value_length; i++)
2596 g_variant_builder_add(inner_builder, "y", value[i]);
2598 g_dbus_method_invocation_return_value(req_info->context,
2599 g_variant_new("(ay)", inner_builder));
2600 g_variant_builder_unref(inner_builder);
2602 g_dbus_method_invocation_return_value(req_info->context, NULL);
2604 gatt_requests = g_slist_remove(gatt_requests, req_info);
2606 req_info->context = NULL;
2607 if (req_info->attr_path)
2608 g_free(req_info->attr_path);
2609 if (req_info->svc_path)
2610 g_free(req_info->svc_path);
2613 return BLUETOOTH_ERROR_NONE;
2616 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2617 bluetooth_device_address_t *unicast_address)
2619 GVariantBuilder *outer_builder;
2620 GVariantBuilder *invalidated_builder;
2621 GError *error = NULL;
2622 gboolean notify = TRUE;
2623 gboolean ret = TRUE;
2624 int err = BLUETOOTH_ERROR_NONE;
2625 gchar **line_argv = NULL;
2626 gchar *serv_path = NULL;
2627 char addr[20] = { 0 };
2629 line_argv = g_strsplit_set(char_path, "/", 0);
2630 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2632 if (!__bt_gatt_is_service_registered(serv_path)) {
2633 BT_DBG("service not registered for this characteristic");
2635 g_strfreev(line_argv);
2636 return BLUETOOTH_ERROR_INTERNAL;
2641 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2642 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2644 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2645 g_variant_new("b", notify));
2647 if (unicast_address) {
2648 _bt_convert_addr_type_to_string(addr,
2649 (unsigned char *)unicast_address->addr);
2651 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2652 g_variant_new("s", addr));
2654 BT_DBG("Set characteristic Notification");
2655 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2657 "org.freedesktop.DBus.Properties",
2658 "PropertiesChanged",
2659 g_variant_new("(sa{sv}as)",
2660 "org.bluez.GattCharacteristic1",
2661 outer_builder, invalidated_builder),
2665 if (error != NULL) {
2666 BT_ERR("D-Bus API failure: errCode[%x], \
2668 error->code, error->message);
2669 g_clear_error(&error);
2671 err = BLUETOOTH_ERROR_INTERNAL;
2674 g_strfreev(line_argv);
2675 g_variant_builder_unref(outer_builder);
2676 g_variant_builder_unref(invalidated_builder);
2683 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2687 if (!is_server_started) {
2689 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2690 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2691 BT_ERR("Don't have aprivilege to use this API");
2692 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2695 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2696 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2698 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2699 in_param1, in_param2, in_param3, in_param4, &out_param);
2700 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2702 if (ret != BLUETOOTH_ERROR_NONE) {
2703 BT_ERR("Register application failed");
2706 is_server_started = true;
2708 return BLUETOOTH_ERROR_NONE;
2711 BT_INFO("Already RegisterApplication");
2712 return BLUETOOTH_ERROR_NONE;
2716 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2719 int ret = BLUETOOTH_ERROR_NONE;
2722 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2724 /* Register event handler for GATT */
2725 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2727 if (ret != BLUETOOTH_ERROR_NONE &&
2728 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2729 BT_ERR("Fail to init the event handler");
2730 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2734 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2735 in_param1, in_param2, in_param3, in_param4, &out_param);
2737 /* App ID -1 is invalid */
2738 if (ret != BLUETOOTH_ERROR_NONE) {
2739 BT_INFO("GATT Server Registration failed result [%d]", ret);
2742 *instance_id = g_array_index(out_param, int, 0);
2743 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2747 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2749 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2753 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2756 BT_INFO("GATT Server Deinitialize");
2757 /* Unregister the event */
2758 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2760 if (ret != BLUETOOTH_ERROR_NONE) {
2761 BT_ERR("Fail to deinit the event handler");
2765 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2770 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2771 int instance_id, int *service_handle)
2773 BT_CHECK_ENABLED(return);
2774 BT_CHECK_PARAMETER(svc_uuid, return);
2777 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2779 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2782 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2784 g_array_append_vals(in_param1, &type, sizeof(int));
2785 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2786 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2787 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2789 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2790 in_param1, in_param2, in_param3, in_param4, &out_param);
2792 /* ATT handle 0 is reserved, hence it can not be used by app.
2793 It will be used to indicate error in regsitering attribute */
2794 if (result != BLUETOOTH_ERROR_NONE)
2795 *service_handle = 0;
2797 *service_handle = g_array_index(out_param, int, 0);
2799 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2804 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2805 const bluetooth_gatt_server_attribute_params_t *param,
2808 BT_CHECK_ENABLED(return);
2809 BT_CHECK_PARAMETER(char_uuid, return);
2810 BT_CHECK_PARAMETER(param, return);
2813 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2815 char *char_flags[NUMBER_OF_FLAGS];
2817 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2818 flag_count = bluetooth_gatt_convert_prop2string(param->properties, char_flags);
2819 BT_INFO("Flag count [%d]", flag_count);
2822 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2824 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2825 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2827 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2828 in_param1, in_param2, in_param3, in_param4, &out_param);
2830 /* ATT handle 0 is reserved, hence it can not be used by app.
2831 It will be used to indicate error in regsitering attribute */
2832 if (result != BLUETOOTH_ERROR_NONE) {
2833 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2836 *char_handle = g_array_index(out_param, int, 0);
2837 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2840 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2844 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2845 int service_handle, int instance_id, int *descriptor_handle)
2847 BT_CHECK_ENABLED(return);
2848 BT_CHECK_PARAMETER(desc_uuid, return);
2851 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2853 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2856 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2858 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2859 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2860 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2861 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2863 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2864 in_param1, in_param2, in_param3, in_param4, &out_param);
2866 /* ATT handle 0 is reserved, hence it can not be used by app.
2867 It will be used to indicate error in regsitering attribute */
2868 if (result != BLUETOOTH_ERROR_NONE) {
2869 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2870 *descriptor_handle = 0;
2872 *descriptor_handle = g_array_index(out_param, int, 0);
2873 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2876 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2881 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2883 BT_CHECK_ENABLED(return);
2887 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2889 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2890 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2892 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2893 in_param1, in_param2, in_param3, in_param4, &out_param);
2895 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2900 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2901 const bluetooth_gatt_att_data_t *value)
2903 BT_CHECK_PARAMETER(param, return);
2904 BT_CHECK_PARAMETER(value, return);
2905 BT_CHECK_ENABLED(return);
2909 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2911 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
2912 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
2914 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
2915 in_param1, in_param2, in_param3, in_param4, &out_param);
2917 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2923 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
2924 const bluetooth_gatt_server_indication_params_t *param,
2925 const bluetooth_gatt_att_data_t *att_value)
2927 BT_CHECK_PARAMETER(param, return);
2928 BT_CHECK_PARAMETER(att_value, return);
2929 BT_CHECK_ENABLED(return);
2931 char addr[BLUETOOTH_ADDRESS_STRING_LENGTH] ;
2935 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2937 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
2938 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
2939 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
2941 _bt_convert_addr_type_to_string(addr, addr_hex->addr);
2942 fd = bluetooth_get_characteristic_fd(param->atrribute_handle, addr);
2945 result = bluetooth_gatt_write_characteristics_value_to_fd_(fd, att_value->data, att_value->length, NULL);
2947 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
2948 in_param1, in_param2, in_param3, in_param4, &out_param);
2950 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2955 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
2957 BT_CHECK_ENABLED(return);
2961 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2963 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2964 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2966 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
2967 in_param1, in_param2, in_param3, in_param4, &out_param);
2969 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2974 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
2976 BT_CHECK_ENABLED(return);
2980 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2982 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2983 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2985 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
2986 in_param1, in_param2, in_param3, in_param4, &out_param);
2988 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2993 /* Tizen Platform Specific */
2994 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
2995 const bluetooth_gatt_server_update_value_t *value)
2997 BT_CHECK_ENABLED(return);
2998 BT_CHECK_PARAMETER(value, return);
3002 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3004 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3005 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3007 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3008 in_param1, in_param2, in_param3, in_param4, &out_param);
3010 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3015 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3017 BT_CHECK_ENABLED(return);
3021 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3023 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3025 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3026 in_param1, in_param2, in_param3, in_param4, &out_param);
3028 if (result != BLUETOOTH_ERROR_NONE)
3029 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3031 BT_INFO("GATT Server Unregistration successful");
3033 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3038 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3039 GIOCondition cond, gpointer data)
3042 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3044 BT_INFO("FD io write data received remote adress [%s]\n", write_data->address);
3046 if (cond & G_IO_IN) {
3047 GIOStatus status = G_IO_STATUS_NORMAL;
3049 char *buffer = NULL;
3051 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3053 buffer = g_malloc0(BUF);
3055 status = g_io_channel_read_chars(gio, buffer,
3058 if (status != G_IO_STATUS_NORMAL) {
3059 BT_ERR("IO Channel read is failed with %d", status);
3062 BT_ERR("IO Channel read error [%s]", err->message);
3063 if (status == G_IO_STATUS_ERROR) {
3064 BT_ERR("cond : %d", cond);
3066 g_io_channel_shutdown(gio, TRUE, NULL);
3067 g_io_channel_unref(gio);
3078 BT_INFO(" FD io sending value changed %s %zd \n", buffer, len);
3081 bluetooth_gatt_server_write_requested_info_t write_info;
3082 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3083 memcpy(write_info.data.data, buffer, len);
3085 write_info.length = len;
3086 write_info.need_resp = false;
3087 write_info.attribute_handle = write_data->attribute_handle;
3089 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->address);
3090 write_info.connection_id = write_data->connection_id;
3091 write_info.offset = write_data->offset;
3092 write_info.request_id = -2;
3094 BT_INFO("ACQUIRING EVENT \n");
3096 bt_event_info_t *event_info;
3097 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3101 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3102 BLUETOOTH_ERROR_NONE, &write_info,
3103 event_info->cb, event_info->user_data);
3105 BT_ERR("eventinfo failed");
3115 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
3116 BT_ERR("Error : GIOCondition %d, ]", cond);
3117 g_io_channel_shutdown(gio, TRUE, NULL);
3118 g_io_channel_unref(gio);
3126 void bluetooth_gatt_server_send_acquire_write_response(GVariant * parameters)
3131 int pipefd[2] = {-1,};
3134 char err_msg[512] = {'\0'};
3135 GIOChannel *channel = NULL;
3139 g_variant_get(parameters, "(iiiiii&s)",
3148 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3149 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3150 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3151 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3154 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3155 strerror_r(errno, err_msg, sizeof(err_msg));
3156 BT_ERR("socketpair(): %s", err_msg);
3161 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3163 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3164 bluetooth_gatt_server_acquire_response_params_t data;
3165 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
3166 data.fd = pipefd[1];
3168 data.request_id = tran_id;
3170 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3172 write_info->attribute_handle = att_han;
3173 write_info->connection_id = tran_id;
3174 write_info->offset = offset;
3176 memcpy(write_info->address, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3178 BT_INFO("FD read %d remote address [%s ] \n", pipefd[0], addr);
3181 channel = g_io_channel_unix_new(pipefd[0]);
3182 g_io_channel_set_encoding(channel, NULL, NULL);
3183 g_io_channel_set_buffered(channel, FALSE);
3184 g_io_channel_set_close_on_unref(channel, TRUE);
3185 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3186 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3187 bluetooth_gatt_server_acquire_channel_write_cb, write_info);
3190 GUnixFDList *fd_list = g_unix_fd_list_new();
3191 GError *error = NULL;
3193 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3194 g_assert_no_error(error);
3197 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3199 BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3201 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE,
3202 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3204 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3210 void bluetooth_gatt_server_send_acquire_notify_response(GVariant * parameters)
3215 int pipefd[2] = {-1,};
3218 char err_msg[512] = {'\0'};
3219 GIOChannel *channel = NULL;
3222 bluetooth_gatt_acquire_notify_info_t *chr_info;
3224 g_variant_get(parameters, "(iiiiii)",
3232 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3233 BT_DBG("GATT Server Acquire notify att handle:[%d]", att_han);
3234 BT_DBG("GATT Server Acquire Notify Offset: [%d]", offset);
3237 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3238 strerror_r(errno, err_msg, sizeof(err_msg));
3239 BT_ERR("socketpair(): %s", err_msg);
3246 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3248 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3249 bluetooth_gatt_server_acquire_response_params_t data;
3250 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
3251 data.fd = pipefd[1];
3253 data.request_id = tran_id;
3255 BT_INFO("FD write %d characterstics path \n", pipefd[0]);
3257 chr_info = bluetooth_get_characteristic_info_from_path(att_han);
3259 chr_info = g_malloc0(sizeof(bluetooth_gatt_acquire_notify_info_t));
3260 chr_info->write_fd = fd;
3261 chr_info->att_hand = att_han;
3263 gatt_characteristic_server_notify_list = g_slist_append(gatt_characteristic_server_notify_list, chr_info);
3265 chr_info->write_fd = fd;
3268 channel = g_io_channel_unix_new(fd);
3269 g_io_channel_set_encoding(channel, NULL, NULL);
3270 g_io_channel_set_buffered(channel, FALSE);
3271 g_io_channel_set_close_on_unref(channel, TRUE);
3272 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3273 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
3274 bluetooth_gatt_write_channel_watch_cb, chr_info);
3279 GUnixFDList *fd_list = g_unix_fd_list_new();
3280 GError *error = NULL;
3282 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3283 g_assert_no_error(error);
3286 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3288 BT_INFO("Sending event BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE file descriptor value [%d] ", data.fd);
3290 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE,
3291 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3293 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);