2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include<glib/gprintf.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <gio/gunixfdlist.h>
29 #include "bt-common.h"
30 /* TODO_40 : 4.0 merge - Need to check why includes bt-event-handler.h */
31 #include "bt-event-handler.h"
32 #include "bt-internal-types.h"
35 #include "bluetooth-gatt-server-api.h"
36 #include "bt-request-sender.h"
37 #define BT_GATT_ATT_UUID_LEN_MAX 50
38 #define BT_GATT_SERVER_DBUS_NAME_LEN_MAX 50
40 static GSList *gatt_characteristic_server_notify_list = NULL;;
42 /* Common defintions to follow , applicable for both
43 GATT_DIRECT and RELAY */
46 #define NUMBER_OF_FLAGS 10
49 int bluetooth_gatt_convert_prop2string(
50 bt_gatt_characteristic_property_t properties,
51 char *char_properties[])
55 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
56 char_properties[flag_count] = g_strdup("broadcast");
59 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
60 char_properties[flag_count] = g_strdup("read");
63 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
64 char_properties[flag_count] = g_strdup("write-without-response");
67 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
68 char_properties[flag_count] = g_strdup("write");
71 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
72 char_properties[flag_count] = g_strdup("notify");
75 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
76 char_properties[flag_count] = g_strdup("indicate");
79 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
80 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
83 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
84 char_properties[flag_count] = g_strdup("reliable-write");
87 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
88 char_properties[flag_count] = g_strdup("writable-auxiliaries");
91 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
92 char_properties[flag_count] = g_strdup("encrypt-read");
95 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
96 char_properties[flag_count] = g_strdup("encrypt-write");
99 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
100 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
103 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
104 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
108 if (flag_count == 0) {
109 char_properties[flag_count] = g_strdup("read");
116 int bluetooth_gatt_convert_perm2string(
117 bt_gatt_permission_t properties,
118 char *char_properties[])
122 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
123 char_properties[flag_count] = g_strdup("read");
126 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
127 char_properties[flag_count] = g_strdup("write");
130 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
131 char_properties[flag_count] = g_strdup("encrypt-read");
134 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
135 char_properties[flag_count] = g_strdup("encrypt-write");
138 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
139 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
142 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
143 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
147 if (flag_count == 0) {
148 char_properties[flag_count] = g_strdup("read");
156 #define NUMBER_OF_FLAGS 10
158 GDBusConnection *g_conn;
161 static gboolean new_service = FALSE;
162 static gboolean new_char = FALSE;
163 static int serv_id = 1;
164 static bool is_server_started = false;
166 GCancellable *register_cancel;
168 /* Introspection data for the service we are exporting */
169 static const gchar service_introspection_xml[] =
171 " <interface name='org.freedesktop.DBus.Properties'>"
172 " <property type='s' name='UUID' access='read'>"
174 " <property type='b' name='primary' access='read'>"
176 " <property type='o' name='Device' access='read'>"
178 " <property type='ao' name='Characteristics' access='read'>"
180 " <property type='s' name='Includes' access='read'>"
185 /* Introspection data for the characteristics we are exporting */
186 static const gchar characteristics_introspection_xml[] =
188 " <interface name='org.bluez.GattCharacteristic1'>"
189 " <method name='ReadValue'>"
190 " <arg type='s' name='address' direction='in'/>"
191 " <arg type='u' name='id' direction='in'/>"
192 " <arg type='q' name='offset' direction='in'/>"
193 " <arg type='ay' name='Value' direction='out'/>"
195 " <method name='WriteValue'>"
196 " <arg type='s' name='address' direction='in'/>"
197 " <arg type='u' name='id' direction='in'/>"
198 " <arg type='q' name='offset' direction='in'/>"
199 " <arg type='b' name='response_needed' direction='in'/>"
200 " <arg type='ay' name='value' direction='in'/>"
202 " <method name='StartNotify'>"
204 " <method name='StopNotify'>"
206 " <method name='IndicateConfirm'>"
207 " <arg type='s' name='address' direction='in'/>"
208 " <arg type='b' name='complete' direction='in'/>"
211 " <interface name='org.freedesktop.DBus.Properties'>"
212 " <property type='s' name='UUID' access='read'>"
214 " <property type='o' name='Service' access='read'>"
216 " <property type='ay' name='Value' access='readwrite'>"
218 " <property type='b' name='Notifying' access='read'>"
220 " <property type='as' name='Flags' access='read'>"
222 " <property type='s' name='Unicast' access='read'>"
224 " <property type='ao' name='Descriptors' access='read'>"
229 /* Introspection data for the descriptor we are exporting */
230 static const gchar descriptor_introspection_xml[] =
232 " <interface name='org.bluez.GattDescriptor1'>"
233 " <method name='ReadValue'>"
234 " <arg type='s' name='address' direction='in'/>"
235 " <arg type='u' name='id' direction='in'/>"
236 " <arg type='q' name='offset' direction='in'/>"
237 " <arg type='ay' name='Value' direction='out'/>"
239 " <method name='WriteValue'>"
240 " <arg type='s' name='address' direction='in'/>"
241 " <arg type='u' name='id' direction='in'/>"
242 " <arg type='q' name='offset' direction='in'/>"
243 " <arg type='b' name='response_needed' direction='in'/>"
244 " <arg type='ay' name='value' direction='in'/>"
247 " <interface name='org.freedesktop.DBus.Properties'>"
248 " <property type='s' name='UUID' access='read'>"
250 " <property type='o' name='Characteristic' access='read'>"
252 " <property type='ay' name='Value' access='read'>"
254 " <property type='as' name='Flags' access='read'>"
259 static const gchar manager_introspection_xml[] =
261 " <interface name='org.freedesktop.DBus.ObjectManager'>"
262 " <method name='GetManagedObjects'>"
263 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
268 struct gatt_service_info {
274 gboolean is_svc_registered;
275 gboolean is_svc_primary;
278 struct gatt_char_info {
283 gchar *char_flags[NUMBER_OF_FLAGS];
289 struct gatt_desc_info {
294 gchar *desc_flags[NUMBER_OF_FLAGS];
299 struct gatt_req_info {
304 GDBusMethodInvocation *context;
307 static GSList *gatt_services = NULL;
308 static GSList *gatt_requests = NULL;
309 static gchar *app_path = NULL;
311 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
312 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
314 #define GATT_SERV_OBJECT_PATH "/service"
316 #define GATT_MNGR_INTERFACE "org.bluez.GattManager1"
317 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
318 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
319 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
321 #ifdef TIZEN_FEATURE_BT_HPS
322 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
323 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
324 #define PROPERTIES_CHANGED "PropertiesChanged"
325 #define BT_HPS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
328 #ifdef TIZEN_FEATURE_BT_OTP
329 #define BT_OTP_OBJECT_PATH "/org/projectx/otp"
330 #define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
331 #define PROPERTIES_CHANGED "PropertiesChanged"
332 #define BT_OTP_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
335 static GDBusProxy *manager_gproxy = NULL;
337 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
338 const char *service_path, const char *char_path);
339 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
340 const char *serv_path, const char *char_path,
341 const char *desc_path);
343 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
344 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info);
354 } bluetooth_gatt_acquire_notify_info_t;
357 static int bluetooth_get_characteristic_fd(int att_handle , char *path)
361 BT_INFO("request found path [%s] att_handle [ %d]", path, att_handle);
362 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
363 bluetooth_gatt_acquire_notify_info_t *info = l->data;
364 BT_INFO(" sid [ %d]" , info->att_hand);
365 if (info->att_hand == att_handle)
366 return info->write_fd;
371 static bluetooth_gatt_acquire_notify_info_t * bluetooth_get_characteristic_info_from_path(int att_handle)
375 BT_INFO("request found att_handle [ %d]", att_handle);
376 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
377 bluetooth_gatt_acquire_notify_info_t *info = l->data;
378 BT_INFO(" sid [ %d]" , info->att_hand);
379 if (info->att_hand == att_handle)
386 static void bluetooth_characteristic_info_free(bluetooth_gatt_acquire_notify_info_t *chr_info)
391 static gboolean bluetooth_gatt_write_channel_watch_cb(GIOChannel *gio,
392 GIOCondition cond, gpointer data)
396 bluetooth_gatt_acquire_notify_info_t *chr_info = (bluetooth_gatt_acquire_notify_info_t *)data;
399 BT_INFO("chr_info is NULL");
403 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
404 BT_ERR("Error : GIOCondition %d, []", cond);;
405 g_io_channel_shutdown(gio, TRUE, NULL);
406 g_io_channel_unref(gio);
408 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
409 bluetooth_characteristic_info_free(chr_info);
417 static int bluetooth_gatt_write_characteristics_value_to_fd_(
418 int fd, const guint8 *value, int length,
423 int att_result = BLUETOOTH_ERROR_NONE;
425 BT_CHECK_PARAMETER(value, return);
427 written = write(fd, value, length);
428 if (written != length) {
429 att_result = BLUETOOTH_ERROR_INTERNAL;
430 BT_INFO("write data failed %d is ", written);
432 BT_INFO("write data %s is sucess ", value);
437 #ifdef TIZEN_FEATURE_BT_HPS
438 static int __bt_send_event_to_hps(int event, GVariant *var)
440 GError *error = NULL;
441 GVariant *parameters;
442 GDBusMessage *msg = NULL;
446 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
448 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
449 GVariantBuilder *inner_builder;
450 GVariantBuilder *invalidated_builder;
452 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
453 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
455 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
457 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
459 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
460 g_variant_builder_unref(invalidated_builder);
461 g_variant_builder_unref(inner_builder);
462 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
463 GVariantBuilder *inner_builder;
464 GVariantBuilder *invalidated_builder;
466 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
467 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
469 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
471 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
473 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
474 g_variant_builder_unref(invalidated_builder);
475 g_variant_builder_unref(inner_builder);
477 g_varaiant_unref(var);
480 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
481 g_dbus_message_set_body(msg, parameters);
482 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
484 BT_ERR("D-Bus API failure: errCode[%x], \
486 error->code, error->message);
487 g_clear_error(&error);
489 return BLUETOOTH_ERROR_INTERNAL;
491 return BLUETOOTH_ERROR_NONE;
495 #ifdef TIZEN_FEATURE_BT_OTP
496 static int __bt_send_event_to_otp(int event, GVariant *var)
498 GError *error = NULL;
499 GVariant *parameters = NULL;
500 GDBusMessage *msg = NULL;
504 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
506 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
507 GVariantBuilder *inner_builder;
508 GVariantBuilder *invalidated_builder;
510 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
511 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
513 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
515 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
517 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
518 g_variant_builder_unref(invalidated_builder);
519 g_variant_builder_unref(inner_builder);
520 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
521 GVariantBuilder *inner_builder;
522 GVariantBuilder *invalidated_builder;
524 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
525 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
527 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
529 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
531 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
532 g_variant_builder_unref(invalidated_builder);
533 g_variant_builder_unref(inner_builder);
534 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
535 GVariantBuilder *inner_builder;
536 GVariantBuilder *invalidated_builder;
538 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
539 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
541 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
543 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
545 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
546 g_variant_builder_unref(invalidated_builder);
547 g_variant_builder_unref(inner_builder);
550 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
551 g_dbus_message_set_body(msg, parameters);
552 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
554 BT_ERR("D-Bus API failure: errCode[%x], \
556 error->code, error->message);
557 g_clear_error(&error);
559 return BLUETOOTH_ERROR_INTERNAL;
561 return BLUETOOTH_ERROR_NONE;
565 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
567 const gchar *object_path,
568 const gchar *interface_name,
569 const gchar *method_name,
570 GVariant *parameters,
571 GDBusMethodInvocation *invocation,
574 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
575 BT_DBG("Getting values for service, chars and descriptors");
578 GVariantBuilder *builder = NULL;
579 GVariantBuilder *inner_builder1 = NULL;
580 GVariant *svc_char = NULL;
581 GSList *char_list = NULL;
582 GSList *desc_list = NULL;
585 builder = g_variant_builder_new(G_VARIANT_TYPE("a{oa{sa{sv}}}"));
587 /* Prepare inner builder for GattService1 interface */
588 svc_index = g_slist_length(gatt_services) - 1;
589 for (; svc_index >= 0; svc_index--) {
590 GVariantBuilder *svc_builder = NULL;
591 GVariantBuilder *inner_builder = NULL;
592 struct gatt_service_info *serv_info = NULL;
594 serv_info = g_slist_nth_data(gatt_services, svc_index);
595 if (serv_info == NULL) {
596 BT_ERR("serv_info is NULL");
600 /* Prepare inner builder for GattService1 interface */
601 BT_DBG("Creating builder for service : %s", serv_info->service_uuid);
602 svc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
603 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
605 g_variant_builder_add(inner_builder, "{sv}", "UUID",
606 g_variant_new_string(serv_info->service_uuid));
607 g_variant_builder_add(inner_builder, "{sv}", "Primary",
608 g_variant_new_boolean(serv_info->is_svc_primary));
610 /* Characteristics */
611 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
613 BT_DBG("Adding Charatarisitcs list");
614 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
615 struct gatt_char_info *char_info = char_list->data;
616 g_variant_builder_add(inner_builder1, "o", char_info->char_path);
617 BT_DBG("%s", char_info->char_path);
620 svc_char = g_variant_new("ao", inner_builder1);
621 g_variant_builder_add(inner_builder, "{sv}", "Characteristics", svc_char);
622 g_variant_builder_add(svc_builder, "{sa{sv}}", GATT_SERV_INTERFACE, inner_builder);
623 g_variant_builder_add(builder, "{oa{sa{sv}}}", serv_info->serv_path, svc_builder);
624 g_variant_builder_unref(inner_builder1);
626 /* Prepare inner builder for GattCharacteristic1 interface */
627 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
628 GVariantBuilder *char_builder = NULL;
629 GVariantBuilder *inner_builder = NULL;
630 GVariantBuilder *builder1 = NULL;
631 GVariantBuilder *builder2 = NULL;
632 GVariantBuilder *builder3 = NULL;
633 GVariant *char_val = NULL;
634 GVariant *flags_val = NULL;
635 GVariant *char_desc = NULL;
636 char *unicast = NULL;
637 gboolean notify = FALSE;
639 struct gatt_char_info *char_info = char_list->data;
641 if (char_info == NULL) {
642 BT_ERR("char_info is NULL");
646 BT_DBG("Creating builder for characteristic : %s", char_info->char_uuid);
647 char_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
648 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
651 g_variant_builder_add(inner_builder, "{sv}", "UUID",
652 g_variant_new_string(char_info->char_uuid));
655 g_variant_builder_add(inner_builder, "{sv}", "Service",
656 g_variant_new("o", serv_info->serv_path));
659 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
660 if (char_info->char_value != NULL) {
661 for (i = 0; i < char_info->value_length; i++) {
662 g_variant_builder_add(builder1, "y", char_info->char_value[i]);
664 char_val = g_variant_new("ay", builder1);
665 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
669 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
670 for (i = 0; i < char_info->flags_length; i++) {
671 g_variant_builder_add(builder2, "s", char_info->char_flags[i]);
673 flags_val = g_variant_new("as", builder2);
674 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
677 g_variant_builder_add(inner_builder, "{sv}", "Notifying", g_variant_new("b", notify));
680 unicast = g_strdup("00:00:00:00:00:00");
681 g_variant_builder_add(inner_builder, "{sv}", "Unicast", g_variant_new("s", unicast));
684 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
685 BT_DBG("Adding Descriptors list");
686 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
687 struct gatt_desc_info *desc_info = desc_list->data;
688 g_variant_builder_add(builder3, "o", desc_info->desc_path);
689 BT_DBG("%s", desc_info->desc_path);
692 char_desc = g_variant_new("ao", builder3);
693 g_variant_builder_add(inner_builder, "{sv}", "Descriptors", char_desc);
694 g_variant_builder_add(char_builder, "{sa{sv}}", GATT_CHAR_INTERFACE , inner_builder);
695 g_variant_builder_add(builder, "{oa{sa{sv}}}", char_info->char_path, char_builder);
697 /*Prepare inner builder for GattDescriptor1 interface*/
698 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
699 GVariantBuilder *desc_builder = NULL;
700 GVariantBuilder *inner_builder = NULL;
701 GVariantBuilder *builder1 = NULL;
702 GVariantBuilder *builder2 = NULL;
703 GVariant *desc_val = NULL;
704 struct gatt_desc_info *desc_info = desc_list->data;
706 if (desc_info == NULL) {
707 BT_ERR("desc_info is NULL");
711 BT_DBG("Creating builder for descriptor : %s", desc_info->desc_uuid);
712 desc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
713 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
716 g_variant_builder_add(inner_builder, "{sv}", "UUID",
717 g_variant_new_string(desc_info->desc_uuid));
720 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
721 g_variant_new("o", char_info->char_path));
724 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
725 if (desc_info->desc_value != NULL) {
726 for (i = 0; i < desc_info->value_length; i++) {
727 g_variant_builder_add(builder1, "y", desc_info->desc_value[i]);
729 desc_val = g_variant_new("ay", builder1);
730 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
734 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
735 for (i = 0; i < desc_info->flags_length; i++) {
736 g_variant_builder_add(builder2, "s", desc_info->desc_flags[i]);
738 flags_val = g_variant_new("as", builder2);
739 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
741 g_variant_builder_add(desc_builder, "{sa{sv}}", GATT_DESC_INTERFACE,
743 g_variant_builder_add(builder, "{oa{sa{sv}}}", desc_info->desc_path,
746 /* unref descriptor builder pointers */
747 g_variant_builder_unref(builder1);
748 g_variant_builder_unref(builder2);
749 g_variant_builder_unref(inner_builder);
750 g_variant_builder_unref(desc_builder);
756 /* unref char builder pointers */
757 g_variant_builder_unref(builder1);
758 g_variant_builder_unref(builder2);
759 g_variant_builder_unref(builder3);
760 g_variant_builder_unref(inner_builder);
761 g_variant_builder_unref(char_builder);
764 /* unref service builder pointers */
765 g_variant_builder_unref(inner_builder);
766 g_variant_builder_unref(svc_builder);
769 /* Return builder as method reply */
770 BT_DBG("Sending gatt service builder values to Bluez");
771 g_dbus_method_invocation_return_value(invocation,
772 g_variant_new("(a{oa{sa{sv}}})", builder));
773 g_variant_builder_unref(builder);
777 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
781 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
782 struct gatt_service_info *serv_info = l1->data;
784 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
785 struct gatt_char_info *char_info = l2->data;
787 if (g_strcmp0(char_info->char_path, char_path) == 0)
791 BT_ERR("Gatt service not found");
795 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
797 GSList *l1, *l2, *l3;
799 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
800 struct gatt_service_info *serv_info = l1->data;
802 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
803 struct gatt_char_info *char_info = l2->data;
805 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
806 struct gatt_desc_info *desc_info = l3->data;
808 if (g_strcmp0(desc_info->desc_path, desc_path) == 0)
813 BT_ERR("Gatt service not found");
817 static void __bt_gatt_char_method_call(GDBusConnection *connection,
819 const gchar *object_path,
820 const gchar *interface_name,
821 const gchar *method_name,
822 GVariant *parameters,
823 GDBusMethodInvocation *invocation,
827 if (g_strcmp0(method_name, "ReadValue") == 0) {
831 bt_gatt_read_req_t read_req = {0, };
832 bt_user_info_t *user_info = NULL;
833 struct gatt_req_info *req_info = NULL;
834 struct gatt_service_info *svc_info = NULL;
835 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
836 GVariant *param = NULL;
839 BT_DBG("Application path = %s", object_path);
840 BT_DBG("Sender = %s", sender);
842 user_info = _bt_get_user_data(BT_COMMON);
843 if (user_info == NULL) {
844 BT_INFO("No callback is set for %s", object_path);
845 g_dbus_method_invocation_return_value(invocation, NULL);
849 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
850 if (svc_info == NULL) {
851 BT_ERR("Coudn't find service for %s", object_path);
852 g_dbus_method_invocation_return_value(invocation, NULL);
856 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
857 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
859 read_req.att_handle = (char *)object_path;
860 read_req.address = addr;
861 read_req.req_id = req_id;
862 read_req.offset = offset;
863 read_req.service_handle = svc_info->serv_path;
865 /* Store requets information */
866 req_info = g_new0(struct gatt_req_info, 1);
867 req_info->attr_path = g_strdup(object_path);
868 req_info->svc_path = g_strdup(read_req.service_handle);
869 req_info->request_id = req_id;
870 req_info->offset = offset;
871 req_info->context = invocation;
872 gatt_requests = g_slist_append(gatt_requests, req_info);
874 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
875 param = g_variant_new("(sssyq)",
877 read_req.service_handle,
881 #ifdef TIZEN_FEATURE_BT_HPS
882 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
884 #ifdef TIZEN_FEATURE_BT_OTP
885 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
889 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
890 BLUETOOTH_ERROR_NONE, &read_req,
891 user_info->cb, user_info->user_data);
893 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
894 GVariant *var = NULL;
898 gboolean response_needed = FALSE;
899 bt_gatt_value_change_t value_change = {0, };
900 bt_user_info_t *user_info = NULL;
902 struct gatt_service_info *svc_info = NULL;
903 struct gatt_req_info *req_info = NULL;
904 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
905 GVariant *param = NULL;
908 BT_DBG("WriteValue");
909 BT_DBG("Application path = %s", object_path);
910 BT_DBG("Sender = %s", sender);
912 g_variant_get(parameters, "(&suqb@ay)",
913 &addr, &req_id, &offset, &response_needed, &var);
914 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
916 user_info = _bt_get_user_data(BT_COMMON);
918 BT_INFO("No callback is set for %s", object_path);
919 g_variant_unref(var);
921 g_dbus_method_invocation_return_value(invocation, NULL);
923 g_object_unref(invocation);
927 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
928 if (svc_info == NULL) {
929 BT_ERR("Coudn't find service for %s", object_path);
930 g_variant_unref(var);
932 g_dbus_method_invocation_return_value(invocation, NULL);
934 g_object_unref(invocation);
938 value_change.att_handle = (char *)object_path;
939 value_change.address = addr;
940 value_change.service_handle = svc_info->serv_path;
941 value_change.offset = offset;
942 value_change.req_id = req_id;
943 value_change.response_needed = response_needed;
945 len = g_variant_get_size(var);
949 value_change.att_value = (guint8 *)g_malloc(len);
951 data = (char *)g_variant_get_data(var);
952 memcpy(value_change.att_value, data, len);
954 value_change.val_len = len;
956 if (response_needed) {
957 /* Store requets information */
958 req_info = g_new0(struct gatt_req_info, 1);
959 req_info->attr_path = g_strdup(object_path);
960 req_info->svc_path = g_strdup(value_change.service_handle);
961 req_info->request_id = req_id;
962 req_info->offset = offset;
963 req_info->context = invocation;
964 gatt_requests = g_slist_append(gatt_requests, req_info);
966 g_object_unref(invocation);
969 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
972 svc_path = g_strdup(svc_info->serv_path);
973 param = g_variant_new("(sssyq@ay)",
980 #ifdef TIZEN_FEATURE_BT_HPS
981 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
983 #ifdef TIZEN_FEATURE_BT_OTP
984 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
992 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
993 BLUETOOTH_ERROR_NONE, &value_change,
994 user_info->cb, user_info->user_data);
996 g_free(value_change.att_value);
997 g_variant_unref(var);
999 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1000 bt_user_info_t *user_info = NULL;
1001 bt_gatt_char_notify_change_t notify_change = {0, };
1002 #if TIZEN_FEATURE_BT_OTP
1003 GVariant *param = NULL;
1005 BT_DBG("StartNotify");
1006 user_info = _bt_get_user_data(BT_COMMON);
1007 if (user_info != NULL) {
1008 struct gatt_service_info *svc_info = NULL;
1009 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1011 notify_change.service_handle = svc_info->serv_path;
1012 notify_change.att_handle = (char *)object_path;
1013 notify_change.att_notify = TRUE;
1014 #if TIZEN_FEATURE_BT_OTP
1015 param = g_variant_new("(ssb)",
1016 notify_change.att_handle,
1017 notify_change.service_handle,
1018 notify_change.att_notify);
1019 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1021 _bt_common_event_cb(
1022 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1023 BLUETOOTH_ERROR_NONE, ¬ify_change,
1024 user_info->cb, user_info->user_data);
1027 g_object_unref(invocation);
1029 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1030 bt_user_info_t *user_info = NULL;
1031 bt_gatt_char_notify_change_t notify_change = {0, };
1032 #if TIZEN_FEATURE_BT_OTP
1033 GVariant *param = NULL;
1035 BT_DBG("StopNotify");
1036 user_info = _bt_get_user_data(BT_COMMON);
1037 if (user_info != NULL) {
1038 struct gatt_service_info *svc_info = NULL;
1039 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1041 notify_change.service_handle = svc_info->serv_path;
1042 notify_change.att_handle = (char *)object_path;
1043 notify_change.att_notify = FALSE;
1044 #if TIZEN_FEATURE_BT_OTP
1045 param = g_variant_new("(ssb)",
1046 notify_change.att_handle,
1047 notify_change.service_handle,
1048 notify_change.att_notify);
1049 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1051 _bt_common_event_cb(
1052 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1053 BLUETOOTH_ERROR_NONE, ¬ify_change,
1054 user_info->cb, user_info->user_data);
1057 g_object_unref(invocation);
1059 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1061 bt_gatt_indicate_confirm_t confirm = {0, };
1062 bt_user_info_t *user_info = NULL;
1063 gboolean complete = FALSE;
1064 struct gatt_service_info *svc_info = NULL;
1066 BT_DBG("IndicateConfirm");
1067 BT_DBG("Application path = %s", object_path);
1068 BT_DBG("Sender = %s", sender);
1070 g_variant_get(parameters, "(&sb)", &addr, &complete);
1071 BT_DBG("Remote Device address number = %s", addr);
1073 confirm.att_handle = (char *)object_path;
1074 confirm.address = addr;
1075 confirm.complete = complete;
1077 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1078 if (svc_info != NULL) {
1079 confirm.service_handle = svc_info->serv_path;
1081 user_info = _bt_get_user_data(BT_COMMON);
1082 if (user_info != NULL) {
1083 _bt_common_event_cb(
1084 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1085 BLUETOOTH_ERROR_NONE, &confirm,
1086 user_info->cb, user_info->user_data);
1091 g_dbus_method_invocation_return_value(invocation, NULL);
1094 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1095 const gchar *sender,
1096 const gchar *object_path,
1097 const gchar *interface_name,
1098 const gchar *method_name,
1099 GVariant *parameters,
1100 GDBusMethodInvocation *invocation,
1103 if (g_strcmp0(method_name, "ReadValue") == 0) {
1107 bt_gatt_read_req_t read_req = {0, };
1108 bt_user_info_t *user_info = NULL;
1109 struct gatt_req_info *req_info = NULL;
1110 struct gatt_service_info *svc_info = NULL;
1112 BT_DBG("ReadValue");
1113 BT_DBG("Application path = %s", object_path);
1114 BT_DBG("Sender = %s", sender);
1116 user_info = _bt_get_user_data(BT_COMMON);
1117 if (user_info == NULL) {
1118 BT_INFO("No callback is set for %s", object_path);
1119 g_dbus_method_invocation_return_value(invocation, NULL);
1123 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1124 if (svc_info == NULL) {
1125 BT_ERR("Coudn't find service for %s", object_path);
1126 g_dbus_method_invocation_return_value(invocation, NULL);
1130 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1131 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1133 read_req.att_handle = (char *)object_path;
1134 read_req.address = addr;
1135 read_req.req_id = req_id;
1136 read_req.offset = offset;
1137 read_req.service_handle = svc_info->serv_path;
1139 /* Store requets information */
1140 req_info = g_new0(struct gatt_req_info, 1);
1141 req_info->attr_path = g_strdup(object_path);
1142 req_info->svc_path = g_strdup(read_req.service_handle);
1143 req_info->request_id = req_id;
1144 req_info->offset = offset;
1145 req_info->context = invocation;
1146 gatt_requests = g_slist_append(gatt_requests, req_info);
1148 _bt_common_event_cb(
1149 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1150 BLUETOOTH_ERROR_NONE, &read_req,
1151 user_info->cb, user_info->user_data);
1154 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1155 GVariant *var = NULL;
1159 gboolean response_needed = FALSE;
1160 bt_gatt_value_change_t value_change = {0, };
1161 bt_user_info_t *user_info = NULL;
1163 struct gatt_service_info *svc_info = NULL;
1164 struct gatt_req_info *req_info = NULL;
1166 BT_DBG("WriteValue");
1167 BT_DBG("Application path = %s", object_path);
1168 BT_DBG("Sender = %s", sender);
1170 g_variant_get(parameters, "(&suqb@ay)",
1171 &addr, &req_id, &offset, &response_needed, &var);
1172 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1174 user_info = _bt_get_user_data(BT_COMMON);
1175 if (user_info == NULL) {
1176 BT_INFO("No callback is set for %s", object_path);
1177 g_variant_unref(var);
1178 if (response_needed)
1179 g_dbus_method_invocation_return_value(invocation, NULL);
1181 g_object_unref(invocation);
1185 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1186 if (svc_info == NULL) {
1187 BT_ERR("Coudn't find service for %s", object_path);
1188 g_variant_unref(var);
1189 if (response_needed)
1190 g_dbus_method_invocation_return_value(invocation, NULL);
1192 g_object_unref(invocation);
1196 value_change.att_handle = (char *)object_path;
1197 value_change.address = addr;
1198 value_change.service_handle = svc_info->serv_path;
1199 value_change.offset = offset;
1200 value_change.req_id = req_id;
1201 value_change.response_needed = response_needed;
1203 len = g_variant_get_size(var);
1207 value_change.att_value = (guint8 *)g_malloc(len);
1209 data = (char *)g_variant_get_data(var);
1210 memcpy(value_change.att_value, data, len);
1212 value_change.val_len = len;
1214 if (response_needed) {
1215 /* Store requets information */
1216 req_info = g_new0(struct gatt_req_info, 1);
1217 req_info->attr_path = g_strdup(object_path);
1218 req_info->svc_path = g_strdup(value_change.service_handle);
1219 req_info->request_id = req_id;
1220 req_info->offset = offset;
1221 req_info->context = invocation;
1222 gatt_requests = g_slist_append(gatt_requests, req_info);
1224 g_object_unref(invocation);
1227 _bt_common_event_cb(
1228 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1229 BLUETOOTH_ERROR_NONE, &value_change,
1230 user_info->cb, user_info->user_data);
1232 g_free(value_change.att_value);
1233 g_variant_unref(var);
1238 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1241 GError *error = NULL;
1242 GVariantBuilder *array_builder;
1244 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1245 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1246 g_variant_builder_add(array_builder, "s", interface);
1248 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1249 "org.freedesktop.Dbus.Objectmanager",
1250 "InterfacesRemoved",
1251 g_variant_new("(oas)",
1252 object_path, array_builder),
1256 if (error != NULL) {
1257 /* dbus gives error cause */
1258 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1259 error->code, error->message);
1260 g_clear_error(&error);
1263 g_variant_builder_unref(array_builder);
1268 static const GDBusInterfaceVTable desc_interface_vtable = {
1269 __bt_gatt_desc_method_call,
1275 static const GDBusInterfaceVTable char_interface_vtable = {
1276 __bt_gatt_char_method_call,
1282 static const GDBusInterfaceVTable serv_interface_vtable = {
1289 static const GDBusInterfaceVTable manager_interface_vtable = {
1290 __bt_gatt_manager_method_call,
1296 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1297 const gchar *introspection_data)
1300 GDBusNodeInfo *node_info = NULL;
1302 if (introspection_data == NULL)
1306 BT_DBG("Create new node info");
1307 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1310 BT_ERR("Unable to create node: %s", err->message);
1311 g_clear_error(&err);
1318 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1319 const char *service_path)
1323 for (l = gatt_services; l != NULL; l = l->next) {
1324 struct gatt_service_info *info = l->data;
1326 if (g_strcmp0(info->serv_path, service_path) == 0)
1329 BT_ERR("Gatt service not found");
1333 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1334 const char *service_path, const char *char_path)
1338 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1339 struct gatt_service_info *serv_info = l1->data;
1341 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1343 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1344 struct gatt_char_info *char_info = l2->data;
1346 if (g_strcmp0(char_info->char_path, char_path) == 0)
1349 BT_ERR("Gatt characteristic not found");
1353 BT_ERR("Gatt service not found");
1357 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1358 const char *serv_path, const char *char_path,
1359 const char *desc_path)
1361 GSList *l1, *l2, *l3;
1363 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1364 struct gatt_service_info *serv_info = l1->data;
1366 if (g_strcmp0(serv_info->serv_path, serv_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) {
1371 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1372 struct gatt_desc_info *desc_info = l3->data;
1373 if (g_strcmp0(desc_info->desc_path,
1382 BT_ERR("Gatt descriptor not found");
1386 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1390 for (l = gatt_requests; l != NULL; l = l->next) {
1391 struct gatt_req_info *req_info = l->data;
1393 if (req_info && req_info->request_id == request_id)
1396 BT_ERR("Gatt Request not found");
1400 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1401 const gchar *path, const gchar *interface)
1406 g_conn = _bt_get_system_shared_conn();
1408 BT_ERR("Unable to get connection");
1412 proxy = g_dbus_proxy_new_sync(g_conn,
1413 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1415 interface, NULL, &err);
1419 BT_ERR("Unable to create proxy: %s", err->message);
1420 g_clear_error(&err);
1424 manager_gproxy = proxy;
1429 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1430 const gchar *path, const gchar *interface)
1432 return (manager_gproxy) ? manager_gproxy :
1433 __bt_gatt_gdbus_init_manager_proxy(service,
1437 static gboolean __bt_gatt_is_service_registered(const char *service_path)
1439 struct gatt_service_info *svc_info = NULL;
1441 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1443 if (svc_info != NULL) {
1444 BT_DBG("Return the state of the gatt service %d",
1445 svc_info->is_svc_registered);
1446 return svc_info->is_svc_registered;
1449 BT_DBG("gatt service info is NULL");
1453 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1455 GError *error = NULL;
1457 GVariantIter *iter = NULL;
1458 const gchar *key = NULL;
1459 GVariant *value = NULL;
1460 const gchar *service = NULL;
1461 const gchar *characteristic = NULL;
1462 const gchar *descriptor = NULL;
1466 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1468 if (result == NULL) {
1469 BT_ERR("Dbus-RPC is failed");
1470 if (error != NULL) {
1471 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1472 error->code, error->message);
1473 g_clear_error(&error);
1476 char *char_cmp = NULL;
1477 g_variant_get(result, "(a{sv})", &iter);
1478 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1480 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1481 if (g_strcmp0(key, "Service") == 0) {
1482 service = g_variant_get_string(value, NULL);
1483 BT_DBG("Service %s", service);
1484 } else if (g_strcmp0(key, char_cmp) == 0) {
1485 characteristic = g_variant_get_string(value, NULL);
1487 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1488 BT_DBG("%s", characteristic);
1489 } else if (g_strcmp0(key, "Descriptor") == 0) {
1490 descriptor = g_variant_get_string(value, NULL);
1491 BT_DBG("Descriptor %s", descriptor);
1494 g_variant_iter_free(iter);
1496 /* TODO: Store the service informationa and
1497 * Send respponse to CAPI layer. */
1499 g_variant_unref(result);
1504 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1506 BT_INFO("RegisterApplication is completed");
1508 GError *error = NULL;
1511 if (register_cancel) {
1512 g_object_unref(register_cancel);
1513 register_cancel = NULL;
1516 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1517 if (result == NULL) {
1518 BT_ERR("Dbus-RPC is failed");
1519 if (error != NULL) {
1520 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1521 error->code, error->message);
1522 g_clear_error(&error);
1524 is_server_started = false;
1526 g_variant_unref(result);
1530 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1532 GDBusProxy *proxy = NULL;
1534 if (is_server_started) {
1538 if (app_path == NULL) {
1539 BT_ERR("app_path is NULL");
1540 return BLUETOOTH_ERROR_INTERNAL;
1543 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1544 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1545 if (proxy == NULL) {
1546 BT_ERR("proxy is NULL");
1547 return BLUETOOTH_ERROR_INTERNAL;
1550 BT_INFO("UnregisterApplication");
1552 /* Async Call to Unregister Service */
1553 ret = g_dbus_proxy_call_sync(proxy, "UnregisterApplication",
1554 g_variant_new("(o)", app_path), G_DBUS_CALL_FLAGS_NONE, -1,
1557 BT_ERR("dBUS-RPC is failed");
1559 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1560 err->code, err->message);
1561 g_clear_error(&err);
1563 return BLUETOOTH_ERROR_INTERNAL;
1565 g_variant_unref(ret);
1567 is_server_started = false;
1569 BT_INFO("UnregisterApplication is completed");
1571 return BLUETOOTH_ERROR_NONE;
1574 BT_INFO("GATT server not started");
1575 return BLUETOOTH_ERROR_NONE;
1578 BT_EXPORT_API int bluetooth_gatt_init(void)
1580 GError *error = NULL;
1581 GDBusNodeInfo *node_info = NULL;
1583 if (app_path != NULL) {
1584 BT_ERR("app path already exists! initialized");
1585 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1588 g_conn = _bt_get_system_shared_conn();
1590 BT_ERR("Unable to get connection");
1594 if (owner_id == 0) {
1595 gchar *name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
1596 BT_DBG("well-known name: %s", name);
1598 owner_id = g_bus_own_name_on_connection(g_conn, name,
1599 G_BUS_NAME_OWNER_FLAGS_NONE,
1600 NULL, NULL, NULL, NULL);
1603 BT_DBG("owner_id is [%d]", owner_id);
1605 app_path = g_strdup_printf("/com/%d", getpid());
1609 /* Register ObjectManager interface */
1610 node_info = __bt_gatt_create_method_node_info(
1611 manager_introspection_xml);
1612 if (node_info == NULL) {
1613 BT_ERR("failed to get node info");
1617 if (manager_id == 0) {
1618 BT_INFO("manager_id does not exists");
1620 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1621 node_info->interfaces[0],
1622 &manager_interface_vtable,
1623 NULL, NULL, &error);
1625 g_dbus_node_info_unref(node_info);
1626 if (manager_id == 0) {
1627 BT_ERR("failed to register: %s", error->message);
1628 g_error_free(error);
1632 return BLUETOOTH_ERROR_NONE;
1636 g_bus_unown_name(owner_id);
1643 return BLUETOOTH_ERROR_INTERNAL;
1646 BT_EXPORT_API int bluetooth_gatt_deinit()
1648 int ret = BLUETOOTH_ERROR_NONE;
1650 if (register_cancel) {
1651 g_cancellable_cancel(register_cancel);
1652 g_object_unref(register_cancel);
1653 register_cancel = NULL;
1656 if (owner_id == 0) {
1657 BT_ERR("owner_id is zero");
1658 return BLUETOOTH_ERROR_NOT_FOUND;
1661 BT_DBG("Removing all registered gatt services");
1662 bluetooth_gatt_delete_services();
1664 /* Unregister the exported interface for object manager */
1666 g_dbus_connection_unregister_object(g_conn, manager_id);
1670 ret = bluetooth_gatt_unregister_application();
1671 if (ret != BLUETOOTH_ERROR_NONE) {
1672 BT_ERR("Fail to unregister application");
1675 g_bus_unown_name(owner_id);
1681 if (manager_gproxy) {
1682 g_object_unref(manager_gproxy);
1683 manager_gproxy = NULL;
1690 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1693 GError *error = NULL;
1695 GDBusNodeInfo *node_info;
1697 GVariantBuilder *builder = NULL;
1698 GVariantBuilder *builder1 = NULL;
1699 GVariantBuilder *inner_builder = NULL;
1700 gboolean svc_primary = TRUE;
1701 struct gatt_service_info *serv_info = NULL;
1703 node_info = __bt_gatt_create_method_node_info(
1704 service_introspection_xml);
1705 if (node_info == NULL)
1706 return BLUETOOTH_ERROR_INTERNAL;
1708 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1709 BT_DBG("gatt service path is [%s]", path);
1711 object_id = g_dbus_connection_register_object(g_conn, path,
1712 node_info->interfaces[0],
1713 &serv_interface_vtable,
1714 NULL, NULL, &error);
1715 g_dbus_node_info_unref(node_info);
1717 if (object_id == 0) {
1718 BT_ERR("failed to register: %s", error->message);
1719 g_error_free(error);
1722 return BLUETOOTH_ERROR_INTERNAL;
1725 /* Add object_id/gatt service information; it's required at the time of
1726 * service unregister and Getmanagedobjects
1728 serv_info = g_new0(struct gatt_service_info, 1);
1730 serv_info->serv_path = g_strdup(path);
1731 serv_info->serv_id = object_id;
1732 serv_info->service_uuid = g_strdup(svc_uuid);
1733 serv_info->is_svc_registered = FALSE;
1734 serv_info->is_svc_primary = svc_primary;
1736 gatt_services = g_slist_append(gatt_services, serv_info);
1738 /* emit interfacesadded signal here for service path */
1739 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1740 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1742 g_variant_builder_add(inner_builder, "{sv}",
1743 "UUID", g_variant_new_string(svc_uuid));
1745 g_variant_builder_add(inner_builder, "{sv}",
1746 "Primary", g_variant_new_boolean(svc_primary));
1748 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1750 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1751 g_variant_new("ao", builder1));
1753 g_variant_builder_add(builder, "{sa{sv}}",
1754 GATT_SERV_INTERFACE, inner_builder);
1756 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1757 "org.freedesktop.Dbus.ObjectManager",
1759 g_variant_new("(oa{sa{sv}})",
1762 if (error != NULL) {
1763 /* dbus gives error cause */
1764 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1765 error->code, error->message);
1766 g_clear_error(&error);
1771 *svc_path = g_strdup(path);
1774 g_variant_builder_unref(inner_builder);
1775 g_variant_builder_unref(builder);
1776 g_variant_builder_unref(builder1);
1778 return BLUETOOTH_ERROR_NONE;
1781 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1782 const char *svc_path, const char *char_uuid,
1783 bt_gatt_permission_t permissions,
1784 bt_gatt_characteristic_property_t properties,
1788 GError *error = NULL;
1790 GDBusNodeInfo *node_info;
1792 GVariantBuilder *builder = NULL;
1793 GVariantBuilder *inner_builder = NULL;
1794 struct gatt_service_info *serv_info = NULL;
1795 struct gatt_char_info *char_info = NULL;
1796 GVariantBuilder *builder2 = NULL;
1797 GVariantBuilder *builder3 = NULL;
1798 GVariant *flags_val = NULL;
1800 char *char_flags[NUMBER_OF_FLAGS];
1805 new_service = FALSE;
1808 BT_DBG("gatt svc_path path is [%s]", svc_path);
1809 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1810 if (serv_info == NULL)
1811 return BLUETOOTH_ERROR_INVALID_PARAM;
1813 node_info = __bt_gatt_create_method_node_info(
1814 characteristics_introspection_xml);
1815 if (node_info == NULL)
1816 return BLUETOOTH_ERROR_INTERNAL;
1818 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1819 BT_DBG("gatt characteristic path is [%s]", path);
1821 object_id = g_dbus_connection_register_object(g_conn, path,
1822 node_info->interfaces[0],
1823 &char_interface_vtable,
1824 NULL, NULL, &error);
1825 g_dbus_node_info_unref(node_info);
1827 if (object_id == 0) {
1828 BT_ERR("failed to register: %s", error->message);
1829 g_error_free(error);
1832 return BLUETOOTH_ERROR_INTERNAL;
1835 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1836 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1837 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1838 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1839 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1840 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1841 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1842 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1844 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1846 char_info = g_new0(struct gatt_char_info, 1);
1848 char_info->char_path = g_strdup(path);
1849 char_info->char_id = object_id;
1850 char_info->char_uuid = g_strdup(char_uuid);
1852 for (i = 0; i < flag_count; i++)
1853 char_info->char_flags[i] = char_flags[i];
1856 char_info->flags_length = flag_count;
1858 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1860 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1861 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1863 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1864 g_variant_new("s", char_uuid));
1865 g_variant_builder_add(inner_builder, "{sv}", "Service",
1866 g_variant_new("o", svc_path));
1868 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1870 for (i = 0; i < flag_count; i++)
1871 g_variant_builder_add(builder2, "s", char_flags[i]);
1873 flags_val = g_variant_new("as", builder2);
1874 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1877 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1879 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1880 g_variant_new("ao", builder3));
1882 g_variant_builder_add(builder, "{sa{sv}}",
1883 GATT_CHAR_INTERFACE,
1886 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1887 "org.freedesktop.Dbus.ObjectManager",
1889 g_variant_new("(oa{sa{sv}})",
1893 /* dBUS gives error cause */
1894 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1895 error->code, error->message);
1896 g_clear_error(&error);
1899 *char_path = g_strdup(path);
1905 g_variant_builder_unref(inner_builder);
1906 g_variant_builder_unref(builder);
1907 g_variant_builder_unref(builder2);
1908 g_variant_builder_unref(builder3);
1910 return BLUETOOTH_ERROR_NONE;
1913 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1914 const char *characteristic, const char *char_value,
1917 gchar **line_argv = NULL;
1918 char *serv_path = NULL;
1919 struct gatt_char_info *char_info = NULL;
1920 GVariantBuilder *builder1 = NULL;
1921 GVariantBuilder *builder = NULL;
1922 GVariantBuilder *inner_builder = NULL;
1923 GVariant *char_val = NULL;
1924 GError *error = NULL;
1926 int res = BLUETOOTH_ERROR_NONE;
1928 line_argv = g_strsplit_set(characteristic, "/", 0);
1929 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1931 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1933 if (char_info == NULL) {
1934 /* Fix : RESOURCE_LEAK */
1935 res = BLUETOOTH_ERROR_INVALID_PARAM;
1939 char_info->value_length = value_length;
1941 char_info->char_value = (char *)malloc(value_length);
1942 /* Fix : NULL_RETURNS */
1943 if (char_info->char_value == NULL) {
1944 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1948 for (i = 0; i < value_length; i++)
1949 char_info->char_value[i] = char_value[i];
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 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1956 for (i = 0; i < value_length; i++)
1957 g_variant_builder_add(builder1, "y", char_value[i]);
1959 char_val = g_variant_new("ay", builder1);
1960 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1962 g_variant_builder_add(builder, "{sa{sv}}",
1963 GATT_CHAR_INTERFACE,
1966 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1967 "org.freedesktop.Dbus.ObjectManager",
1969 g_variant_new("(oa{sa{sv}})",
1970 char_info->char_path, builder),
1974 /* dBUS gives error cause */
1975 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1976 error->code, error->message);
1977 g_clear_error(&error);
1979 g_variant_builder_unref(inner_builder);
1980 g_variant_builder_unref(builder);
1981 g_variant_builder_unref(builder1);
1983 g_strfreev(line_argv);
1989 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
1990 const char *char_path, const char *desc_uuid,
1991 bt_gatt_permission_t permissions,
1994 static int desc_id = 1;
1995 GError *error = NULL;
1997 GDBusNodeInfo *node_info;
1999 GVariantBuilder *builder = NULL;
2000 GVariantBuilder *inner_builder = NULL;
2001 struct gatt_char_info *char_info = NULL;
2002 struct gatt_desc_info *desc_info = NULL;
2003 gchar **line_argv = NULL;
2005 GVariantBuilder *builder2 = NULL;
2006 GVariant *flags_val = NULL;
2008 char *desc_flags[NUMBER_OF_FLAGS];
2016 line_argv = g_strsplit_set(char_path, "/", 0);
2017 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2019 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2020 if (char_info == NULL) {
2021 g_strfreev(line_argv);
2023 return BLUETOOTH_ERROR_INVALID_PARAM;
2026 node_info = __bt_gatt_create_method_node_info(
2027 descriptor_introspection_xml);
2028 if (node_info == NULL) {
2029 g_strfreev(line_argv);
2031 return BLUETOOTH_ERROR_INTERNAL;
2034 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2035 BT_DBG("gatt descriptor path is [%s]", path);
2037 object_id = g_dbus_connection_register_object(g_conn, path,
2038 node_info->interfaces[0],
2039 &desc_interface_vtable,
2040 NULL, NULL, &error);
2041 g_dbus_node_info_unref(node_info);
2043 if (object_id == 0) {
2044 BT_ERR("failed to register: %s", error->message);
2045 g_error_free(error);
2047 g_strfreev(line_argv);
2050 return BLUETOOTH_ERROR_INTERNAL;
2053 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2055 desc_info = g_new0(struct gatt_desc_info, 1);
2057 desc_info->desc_path = g_strdup(path);
2058 desc_info->desc_id = object_id;
2059 desc_info->desc_uuid = g_strdup(desc_uuid);
2061 for (i = 0; i < flag_count; i++)
2062 desc_info->desc_flags[i] = desc_flags[i];
2064 desc_info->flags_length = flag_count;
2066 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2068 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2069 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2071 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2072 g_variant_new("s", desc_uuid));
2073 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2074 g_variant_new("o", char_path));
2076 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2078 for (i = 0; i < flag_count; i++)
2079 g_variant_builder_add(builder2, "s", desc_flags[i]);
2081 flags_val = g_variant_new("as", builder2);
2082 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2085 g_variant_builder_add(builder, "{sa{sv}}",
2086 GATT_DESC_INTERFACE,
2089 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2090 "org.freedesktop.Dbus.ObjectManager",
2092 g_variant_new("(oa{sa{sv}})",
2096 /* dBUS gives error cause */
2097 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2098 error->code, error->message);
2099 g_clear_error(&error);
2102 *desc_path = g_strdup(path);
2106 g_strfreev(line_argv);
2107 g_variant_builder_unref(inner_builder);
2108 g_variant_builder_unref(builder);
2109 g_variant_builder_unref(builder2);
2111 return BLUETOOTH_ERROR_NONE;
2114 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2115 const char *desc_path, const char *desc_value,
2118 GError *error = NULL;
2119 GVariantBuilder *builder = NULL;
2120 GVariantBuilder *inner_builder = NULL;
2121 GVariantBuilder *builder1 = NULL;
2122 struct gatt_desc_info *desc_info = NULL;
2123 gchar **line_argv = NULL;
2125 GVariant *desc_val = NULL;
2126 char *serv_path = NULL;
2129 line_argv = g_strsplit_set(desc_path, "/", 0);
2130 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2131 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2133 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2135 /* Free the allocated memory */
2136 g_strfreev(line_argv);
2140 /* Fix : NULL_RETURNS */
2141 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2143 desc_info->desc_value = (char *)malloc(value_length);
2145 /* Fix : NULL_RETURNS */
2146 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2148 for (i = 0; i < value_length; i++)
2149 desc_info->desc_value[i] = desc_value[i];
2151 desc_info->value_length = value_length;
2153 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2154 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2156 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2158 for (i = 0; i < value_length; i++)
2159 g_variant_builder_add(builder1, "y", desc_value[i]);
2161 desc_val = g_variant_new("ay", builder1);
2162 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2164 g_variant_builder_add(builder, "{sa{sv}}",
2165 GATT_DESC_INTERFACE,
2168 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2169 "org.freedesktop.Dbus.ObjectManager",
2171 g_variant_new("(oa{sa{sv}})",
2172 desc_info->desc_path, builder),
2175 if (error != NULL) {
2176 BT_ERR("D-Bus API failure: errCode[%x], \
2178 error->code, error->message);
2179 g_clear_error(&error);
2182 g_variant_builder_unref(inner_builder);
2183 g_variant_builder_unref(builder);
2184 g_variant_builder_unref(builder1);
2186 return BLUETOOTH_ERROR_NONE;
2189 int bluetooth_gatt_get_service(const char *svc_uuid)
2191 GDBusProxy *proxy = NULL;
2194 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2195 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2197 return BLUETOOTH_ERROR_INTERNAL;
2199 uuid = g_strdup(svc_uuid);
2201 g_dbus_proxy_call(proxy,
2203 g_variant_new("(s)",
2205 G_DBUS_CALL_FLAGS_NONE, -1,
2207 (GAsyncReadyCallback) get_service_cb,
2212 return BLUETOOTH_ERROR_NONE;
2215 BT_EXPORT_API int bluetooth_gatt_register_service(const char *svc_path)
2217 struct gatt_service_info *svc_info = NULL;
2219 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2220 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2221 BT_ERR("Don't have aprivilege to use this API");
2222 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2225 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2226 if (svc_info == NULL) {
2227 BT_ERR("Cannot find service [%s]", svc_path);
2228 return BLUETOOTH_ERROR_INTERNAL;
2230 svc_info->is_svc_registered = TRUE;
2232 return BLUETOOTH_ERROR_NONE;
2235 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2237 GDBusProxy *proxy = NULL;
2239 if (!is_server_started) {
2240 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2241 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2242 BT_ERR("Don't have aprivilege to use this API");
2243 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2246 if (g_slist_length(gatt_services) == 0) {
2247 BT_ERR("There is no registered service");
2248 return BLUETOOTH_ERROR_INTERNAL;
2251 if (app_path == NULL) {
2252 BT_ERR("app_path is NULL");
2253 return BLUETOOTH_ERROR_INTERNAL;
2256 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2257 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2258 if (proxy == NULL) {
2259 BT_ERR("proxy is NULL");
2260 return BLUETOOTH_ERROR_INTERNAL;
2263 BT_INFO("RegisterApplication");
2265 if (register_cancel) {
2266 g_cancellable_cancel(register_cancel);
2267 g_object_unref(register_cancel);
2269 register_cancel = g_cancellable_new();
2271 g_dbus_proxy_call(proxy, "RegisterApplication",
2272 g_variant_new("(oa{sv})", app_path, NULL),
2273 G_DBUS_CALL_FLAGS_NONE, -1, register_cancel,
2274 (GAsyncReadyCallback)register_application_cb, NULL);
2276 is_server_started = true;
2278 return BLUETOOTH_ERROR_NONE;
2281 BT_INFO("Already RegisterApplication");
2283 return BLUETOOTH_ERROR_NONE;
2286 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2289 int ret = BLUETOOTH_ERROR_NONE;
2291 if (gatt_services == NULL) {
2292 BT_DBG("There are no registered services");
2297 for (l = gatt_services; l != NULL; ) {
2298 struct gatt_service_info *info = l->data;
2300 // In __bt_gatt_unregister_service, current node will be removed.
2301 // Go forward to next node before calling __bt_gatt_unregister_service.
2303 if (__bt_gatt_unregister_service(info) != BLUETOOTH_ERROR_NONE) {
2304 ret = BLUETOOTH_ERROR_INTERNAL;
2307 BT_INFO("All services are removed : %d", ret);
2309 g_slist_free(gatt_services);
2310 gatt_services = NULL;
2316 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2317 const char *char_path, const char* char_value,
2320 GVariantBuilder *outer_builder;
2321 GVariantBuilder *inner_builder;
2322 GVariantBuilder *invalidated_builder;
2323 GVariant *update_value = NULL;
2324 GError *error = NULL;
2325 gboolean ret = FALSE;
2326 int err = BLUETOOTH_ERROR_NONE;
2328 gchar **line_argv = NULL;
2329 gchar *serv_path = NULL;
2330 const char *value = NULL;
2332 line_argv = g_strsplit_set(char_path, "/", 0);
2333 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2335 if (!__bt_gatt_is_service_registered(serv_path)) {
2336 BT_DBG("service not registered for this characteristic");
2338 g_strfreev(line_argv);
2339 return BLUETOOTH_ERROR_INTERNAL;
2342 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2343 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2345 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2346 for (i = 0; i < value_length; i++)
2347 g_variant_builder_add(inner_builder, "y", char_value[i]);
2349 update_value = g_variant_new("ay", inner_builder);
2351 g_variant_builder_add(outer_builder, "{sv}", "Value",
2354 BT_DBG("Updating characteristic value");
2355 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2357 "org.freedesktop.DBus.Properties",
2358 "PropertiesChanged",
2359 g_variant_new("(sa{sv}as)",
2360 "org.bluez.GattCharacteristic1",
2361 outer_builder, invalidated_builder),
2365 if (error != NULL) {
2366 BT_ERR("D-Bus API failure: errCode[%x], \
2368 error->code, error->message);
2369 g_clear_error(&error);
2371 err = BLUETOOTH_ERROR_INTERNAL;
2373 struct gatt_char_info *char_info = NULL;
2375 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2376 if (char_info == NULL) {
2378 g_strfreev(line_argv);
2379 g_variant_builder_unref(inner_builder);
2380 g_variant_builder_unref(outer_builder);
2381 g_variant_builder_unref(invalidated_builder);
2383 return BLUETOOTH_ERROR_INVALID_DATA;
2386 char_info->value_length = value_length;
2388 value = (char *)realloc(char_info->char_value, value_length);
2389 if (value == NULL) {
2391 g_strfreev(line_argv);
2392 g_variant_builder_unref(inner_builder);
2393 g_variant_builder_unref(outer_builder);
2394 g_variant_builder_unref(invalidated_builder);
2396 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2399 char_info->char_value = (char*)value;
2400 if (char_info->char_value) {
2401 for (i = 0; i < value_length; i++)
2402 char_info->char_value[i] = char_value[i];
2407 g_strfreev(line_argv);
2408 g_variant_builder_unref(inner_builder);
2409 g_variant_builder_unref(outer_builder);
2410 g_variant_builder_unref(invalidated_builder);
2415 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2422 g_free(desc_info->desc_path);
2423 g_free(desc_info->desc_uuid);
2424 g_free(desc_info->desc_value);
2426 for (i = 0; i < desc_info->flags_length; i++)
2427 g_free(desc_info->desc_flags[i]);
2432 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2439 g_free(char_info->char_path);
2440 g_free(char_info->char_uuid);
2441 g_free(char_info->char_value);
2443 for (i = 0; i < char_info->flags_length; i++)
2444 g_free(char_info->char_flags[i]);
2449 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2454 g_free(svc_info->serv_path);
2455 g_free(svc_info->service_uuid);
2459 static void __desc_info_free(gpointer data, gpointer user_data)
2461 struct gatt_desc_info *desc_info = data;
2462 int *err = user_data;
2465 if (desc_info == NULL)
2468 ret = g_dbus_connection_unregister_object(g_conn, desc_info->desc_id);
2470 __bt_gatt_emit_interface_removed(desc_info->desc_path, GATT_DESC_INTERFACE);
2472 *err = BLUETOOTH_ERROR_INTERNAL;
2474 __bt_gatt_free_descriptor_info(desc_info);
2477 static void __char_info_free(gpointer data, gpointer user_data)
2479 struct gatt_char_info *char_info = data;
2480 int *err = user_data;
2483 if (char_info == NULL)
2486 g_slist_foreach(char_info->desc_data, __desc_info_free, user_data);
2487 g_slist_free(char_info->desc_data);
2488 char_info->desc_data = NULL;
2490 ret = g_dbus_connection_unregister_object(g_conn, char_info->char_id);
2492 __bt_gatt_emit_interface_removed(char_info->char_path, GATT_CHAR_INTERFACE);
2494 *err = BLUETOOTH_ERROR_INTERNAL;
2496 __bt_gatt_free_characteristic_info(char_info);
2499 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info)
2501 int ret = BLUETOOTH_ERROR_NONE;
2503 if (svc_info == NULL) {
2504 BT_ERR("svc_info is NULL");
2505 return BLUETOOTH_ERROR_NOT_FOUND;
2508 if (svc_info->is_svc_registered == FALSE) {
2509 BT_ERR("%s is not registered", svc_info->serv_path);
2510 return BLUETOOTH_ERROR_NOT_FOUND;
2513 BT_DBG("svc_path %s", svc_info->serv_path);
2515 g_slist_foreach(svc_info->char_data, __char_info_free, &ret);
2516 g_slist_free(svc_info->char_data);
2517 svc_info->char_data = NULL;
2519 if (g_dbus_connection_unregister_object(g_conn, svc_info->serv_id) == FALSE) {
2520 BT_ERR("Cannot unregister object for [%s]", svc_info->serv_path);
2521 ret = BLUETOOTH_ERROR_INTERNAL;
2523 __bt_gatt_emit_interface_removed(svc_info->serv_path, GATT_SERV_INTERFACE);
2526 gatt_services = g_slist_remove(gatt_services, svc_info);
2527 __bt_gatt_free_service_info(svc_info);
2529 new_service = FALSE;
2531 if (gatt_services == NULL) {
2533 } else if (gatt_services->next == NULL) {
2540 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2542 struct gatt_service_info *svc_info;
2543 int ret = BLUETOOTH_ERROR_NONE;
2547 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2549 ret = __bt_gatt_unregister_service(svc_info);
2550 if (ret != BLUETOOTH_ERROR_NONE) {
2551 BT_ERR("Could not unregister service [%s]", svc_path);
2558 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2559 int resp_state, int offset, char *value, int value_length)
2561 struct gatt_req_info *req_info = NULL;
2563 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2564 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2565 BT_ERR("Don't have aprivilege to use this API");
2566 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2569 req_info = __bt_gatt_find_request_info(request_id);
2570 if (req_info == NULL) {
2571 BT_ERR("Coundn't find request id [%d]", request_id);
2572 return BLUETOOTH_ERROR_INTERNAL;
2575 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2576 BT_ERR("resp_state is 0x%X", resp_state);
2577 char err_msg[20] = { 0, };
2578 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2579 g_dbus_method_invocation_return_dbus_error(req_info->context,
2580 "org.bluez.Error.Failed", err_msg);
2582 gatt_requests = g_slist_remove(gatt_requests, req_info);
2584 req_info->context = NULL;
2585 if (req_info->attr_path)
2586 g_free(req_info->attr_path);
2587 if (req_info->svc_path)
2588 g_free(req_info->svc_path);
2591 return BLUETOOTH_ERROR_NONE;
2594 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2596 GVariantBuilder *inner_builder = NULL;
2597 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2598 if (value_length > 0 && value != NULL) {
2599 for (i = 0; i < value_length; i++)
2600 g_variant_builder_add(inner_builder, "y", value[i]);
2602 g_dbus_method_invocation_return_value(req_info->context,
2603 g_variant_new("(ay)", inner_builder));
2604 g_variant_builder_unref(inner_builder);
2606 g_dbus_method_invocation_return_value(req_info->context, NULL);
2608 gatt_requests = g_slist_remove(gatt_requests, req_info);
2610 req_info->context = NULL;
2611 if (req_info->attr_path)
2612 g_free(req_info->attr_path);
2613 if (req_info->svc_path)
2614 g_free(req_info->svc_path);
2617 return BLUETOOTH_ERROR_NONE;
2620 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2621 bluetooth_device_address_t *unicast_address)
2623 GVariantBuilder *outer_builder;
2624 GVariantBuilder *invalidated_builder;
2625 GError *error = NULL;
2626 gboolean notify = TRUE;
2627 gboolean ret = TRUE;
2628 int err = BLUETOOTH_ERROR_NONE;
2629 gchar **line_argv = NULL;
2630 gchar *serv_path = NULL;
2631 char addr[20] = { 0 };
2633 line_argv = g_strsplit_set(char_path, "/", 0);
2634 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2636 if (!__bt_gatt_is_service_registered(serv_path)) {
2637 BT_DBG("service not registered for this characteristic");
2639 g_strfreev(line_argv);
2640 return BLUETOOTH_ERROR_INTERNAL;
2645 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2646 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2648 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2649 g_variant_new("b", notify));
2651 if (unicast_address) {
2652 _bt_convert_addr_type_to_string(addr,
2653 (unsigned char *)unicast_address->addr);
2655 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2656 g_variant_new("s", addr));
2658 BT_DBG("Set characteristic Notification");
2659 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2661 "org.freedesktop.DBus.Properties",
2662 "PropertiesChanged",
2663 g_variant_new("(sa{sv}as)",
2664 "org.bluez.GattCharacteristic1",
2665 outer_builder, invalidated_builder),
2669 if (error != NULL) {
2670 BT_ERR("D-Bus API failure: errCode[%x], \
2672 error->code, error->message);
2673 g_clear_error(&error);
2675 err = BLUETOOTH_ERROR_INTERNAL;
2678 g_strfreev(line_argv);
2679 g_variant_builder_unref(outer_builder);
2680 g_variant_builder_unref(invalidated_builder);
2687 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2691 if (!is_server_started) {
2693 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2694 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2695 BT_ERR("Don't have aprivilege to use this API");
2696 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2699 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2700 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2702 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2703 in_param1, in_param2, in_param3, in_param4, &out_param);
2704 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2706 if (ret != BLUETOOTH_ERROR_NONE) {
2707 BT_ERR("Register application failed");
2710 is_server_started = true;
2712 return BLUETOOTH_ERROR_NONE;
2715 BT_INFO("Already RegisterApplication");
2716 return BLUETOOTH_ERROR_NONE;
2720 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2723 int ret = BLUETOOTH_ERROR_NONE;
2726 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2728 /* Register event handler for GATT */
2729 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2731 if (ret != BLUETOOTH_ERROR_NONE &&
2732 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2733 BT_ERR("Fail to init the event handler");
2734 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2738 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2739 in_param1, in_param2, in_param3, in_param4, &out_param);
2741 /* App ID -1 is invalid */
2742 if (ret != BLUETOOTH_ERROR_NONE) {
2743 BT_INFO("GATT Server Registration failed result [%d]", ret);
2746 *instance_id = g_array_index(out_param, int, 0);
2747 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2751 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2753 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2757 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2760 BT_INFO("GATT Server Deinitialize");
2761 /* Unregister the event */
2762 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2764 if (ret != BLUETOOTH_ERROR_NONE) {
2765 BT_ERR("Fail to deinit the event handler");
2769 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2774 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2775 int instance_id, int *service_handle)
2777 BT_CHECK_ENABLED(return);
2778 BT_CHECK_PARAMETER(svc_uuid, return);
2781 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2783 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2786 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2788 g_array_append_vals(in_param1, &type, sizeof(int));
2789 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2790 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2791 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2793 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2794 in_param1, in_param2, in_param3, in_param4, &out_param);
2796 /* ATT handle 0 is reserved, hence it can not be used by app.
2797 It will be used to indicate error in regsitering attribute */
2798 if (result != BLUETOOTH_ERROR_NONE)
2799 *service_handle = 0;
2801 *service_handle = g_array_index(out_param, int, 0);
2803 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2808 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2809 const bluetooth_gatt_server_attribute_params_t *param,
2812 BT_CHECK_ENABLED(return);
2813 BT_CHECK_PARAMETER(char_uuid, return);
2814 BT_CHECK_PARAMETER(param, return);
2817 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2819 char *char_flags[NUMBER_OF_FLAGS];
2821 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2822 flag_count = bluetooth_gatt_convert_prop2string(param->properties, char_flags);
2823 BT_INFO("Flag count [%d]", flag_count);
2826 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2828 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2829 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2831 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2832 in_param1, in_param2, in_param3, in_param4, &out_param);
2834 /* ATT handle 0 is reserved, hence it can not be used by app.
2835 It will be used to indicate error in regsitering attribute */
2836 if (result != BLUETOOTH_ERROR_NONE) {
2837 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2840 *char_handle = g_array_index(out_param, int, 0);
2841 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2844 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2848 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2849 int service_handle, int instance_id, int *descriptor_handle)
2851 BT_CHECK_ENABLED(return);
2852 BT_CHECK_PARAMETER(desc_uuid, return);
2855 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2857 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2860 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2862 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2863 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2864 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2865 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2867 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2868 in_param1, in_param2, in_param3, in_param4, &out_param);
2870 /* ATT handle 0 is reserved, hence it can not be used by app.
2871 It will be used to indicate error in regsitering attribute */
2872 if (result != BLUETOOTH_ERROR_NONE) {
2873 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2874 *descriptor_handle = 0;
2876 *descriptor_handle = g_array_index(out_param, int, 0);
2877 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2880 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2885 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2887 BT_CHECK_ENABLED(return);
2891 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2893 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2894 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2896 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2897 in_param1, in_param2, in_param3, in_param4, &out_param);
2899 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2904 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2905 const bluetooth_gatt_att_data_t *value)
2907 BT_CHECK_PARAMETER(param, return);
2908 BT_CHECK_PARAMETER(value, return);
2909 BT_CHECK_ENABLED(return);
2913 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2915 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
2916 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
2918 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
2919 in_param1, in_param2, in_param3, in_param4, &out_param);
2921 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2927 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
2928 const bluetooth_gatt_server_indication_params_t *param,
2929 const bluetooth_gatt_att_data_t *att_value)
2931 BT_CHECK_PARAMETER(param, return);
2932 BT_CHECK_PARAMETER(att_value, return);
2933 BT_CHECK_ENABLED(return);
2935 char addr[BLUETOOTH_ADDRESS_STRING_LENGTH] ;
2939 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2941 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
2942 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
2943 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
2945 _bt_convert_addr_type_to_string(addr, addr_hex->addr);
2946 fd = bluetooth_get_characteristic_fd(param->atrribute_handle, addr);
2949 result = bluetooth_gatt_write_characteristics_value_to_fd_(fd, att_value->data, att_value->length, NULL);
2951 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
2952 in_param1, in_param2, in_param3, in_param4, &out_param);
2954 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2959 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
2961 BT_CHECK_ENABLED(return);
2965 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2967 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2968 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2970 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
2971 in_param1, in_param2, in_param3, in_param4, &out_param);
2973 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2978 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
2980 BT_CHECK_ENABLED(return);
2984 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2986 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2987 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2989 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
2990 in_param1, in_param2, in_param3, in_param4, &out_param);
2992 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2997 /* Tizen Platform Specific */
2998 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
2999 const bluetooth_gatt_server_update_value_t *value)
3001 BT_CHECK_ENABLED(return);
3002 BT_CHECK_PARAMETER(value, return);
3006 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3008 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3009 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3011 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3012 in_param1, in_param2, in_param3, in_param4, &out_param);
3014 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3019 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3021 BT_CHECK_ENABLED(return);
3025 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3027 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3029 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3030 in_param1, in_param2, in_param3, in_param4, &out_param);
3032 if (result != BLUETOOTH_ERROR_NONE)
3033 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3035 BT_INFO("GATT Server Unregistration successful");
3037 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3042 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3043 GIOCondition cond, gpointer data)
3046 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3048 BT_INFO("FD io write data received remote adress [%s]\n", write_data->address);
3050 if (cond & G_IO_IN) {
3051 GIOStatus status = G_IO_STATUS_NORMAL;
3053 char *buffer = NULL;
3055 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3057 buffer = g_malloc0(BUF);
3059 status = g_io_channel_read_chars(gio, buffer,
3062 if (status != G_IO_STATUS_NORMAL) {
3063 BT_ERR("IO Channel read is failed with %d", status);
3066 BT_ERR("IO Channel read error [%s]", err->message);
3067 if (status == G_IO_STATUS_ERROR) {
3068 BT_ERR("cond : %d", cond);
3070 g_io_channel_shutdown(gio, TRUE, NULL);
3071 g_io_channel_unref(gio);
3082 BT_INFO(" FD io sending value changed %s %zd \n", buffer, len);
3085 bluetooth_gatt_server_write_requested_info_t write_info;
3086 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3087 memcpy(write_info.data.data, buffer, len);
3089 write_info.length = len;
3090 write_info.need_resp = false;
3091 write_info.attribute_handle = write_data->attribute_handle;
3093 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->address);
3094 write_info.connection_id = write_data->connection_id;
3095 write_info.offset = write_data->offset;
3096 write_info.request_id = -2;
3098 BT_INFO("ACQUIRING EVENT \n");
3100 bt_event_info_t *event_info;
3101 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3105 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3106 BLUETOOTH_ERROR_NONE, &write_info,
3107 event_info->cb, event_info->user_data);
3109 BT_ERR("eventinfo failed");
3119 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
3120 BT_ERR("Error : GIOCondition %d, ]", cond);
3121 g_io_channel_shutdown(gio, TRUE, NULL);
3122 g_io_channel_unref(gio);
3130 void bluetooth_gatt_server_send_acquire_write_response(GVariant * parameters)
3135 int pipefd[2] = {-1,};
3138 char err_msg[512] = {'\0'};
3139 GIOChannel *channel = NULL;
3143 g_variant_get(parameters, "(iiiiii&s)",
3152 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3153 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3154 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3155 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3158 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3159 strerror_r(errno, err_msg, sizeof(err_msg));
3160 BT_ERR("socketpair(): %s", err_msg);
3165 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3167 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3168 bluetooth_gatt_server_acquire_response_params_t data;
3169 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
3170 data.fd = pipefd[1];
3172 data.request_id = tran_id;
3174 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3176 write_info->attribute_handle = att_han;
3177 write_info->connection_id = tran_id;
3178 write_info->offset = offset;
3180 memcpy(write_info->address, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3182 BT_INFO("FD read %d remote address [%s ] \n", pipefd[0], addr);
3185 channel = g_io_channel_unix_new(pipefd[0]);
3186 g_io_channel_set_encoding(channel, NULL, NULL);
3187 g_io_channel_set_buffered(channel, FALSE);
3188 g_io_channel_set_close_on_unref(channel, TRUE);
3189 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3190 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3191 bluetooth_gatt_server_acquire_channel_write_cb, write_info);
3194 GUnixFDList *fd_list = g_unix_fd_list_new();
3195 GError *error = NULL;
3197 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3198 g_assert_no_error(error);
3201 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3203 BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3205 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE,
3206 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3208 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3214 void bluetooth_gatt_server_send_acquire_notify_response(GVariant * parameters, bt_event_info_t *event_info)
3219 int pipefd[2] = {-1,};
3222 char err_msg[512] = {'\0'};
3223 GIOChannel *channel = NULL;
3226 bluetooth_gatt_acquire_notify_info_t *chr_info;
3227 const char *address = NULL;
3229 g_variant_get(parameters, "(iiiiiis)",
3238 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3239 BT_DBG("GATT Server Acquire notify att handle:[%d]", att_han);
3240 BT_DBG("GATT Server Acquire Notify Offset: [%d]", offset);
3241 BT_DBG("GATT Server Acquire Notify address: [%s]", address);
3244 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3245 strerror_r(errno, err_msg, sizeof(err_msg));
3246 BT_ERR("socketpair(): %s", err_msg);
3253 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3255 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3256 bluetooth_gatt_server_acquire_response_params_t data;
3257 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
3258 data.fd = pipefd[1];
3260 data.request_id = tran_id;
3262 BT_INFO("FD write %d characterstics path \n", pipefd[0]);
3264 chr_info = bluetooth_get_characteristic_info_from_path(att_han);
3266 chr_info = g_malloc0(sizeof(bluetooth_gatt_acquire_notify_info_t));
3267 chr_info->write_fd = fd;
3268 chr_info->att_hand = att_han;
3270 gatt_characteristic_server_notify_list = g_slist_append(gatt_characteristic_server_notify_list, chr_info);
3272 chr_info->write_fd = fd;
3275 BT_INFO("setting up g_io channel");
3276 channel = g_io_channel_unix_new(fd);
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 | G_IO_NVAL),
3282 bluetooth_gatt_write_channel_watch_cb, chr_info);
3287 GUnixFDList *fd_list = g_unix_fd_list_new();
3288 GError *error = NULL;
3290 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3291 g_assert_no_error(error);
3294 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3296 BT_INFO("Sending event BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE file descriptor value [%d] ", data.fd);
3298 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE,
3299 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3301 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3305 if (result == BLUETOOTH_ERROR_NONE) {
3307 BT_INFO("sending gatt server notification state changed event");
3308 bluetooth_gatt_server_notification_changed_t info;
3309 bluetooth_device_address_t dev_address = { {0} };
3310 memset(&info, 0x00, sizeof(bluetooth_gatt_server_notification_changed_t));
3312 _bt_convert_addr_string_to_type(dev_address.addr, address);
3313 memcpy(info.device_address.addr,
3315 BLUETOOTH_ADDRESS_LENGTH);
3316 info.handle = att_han;
3317 info.notification = TRUE;
3319 _bt_gatt_server_event_cb(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
3321 event_info->cb, event_info->user_data);
3326 void cleanup_gatt_acquire_fd(int handle)
3328 bluetooth_gatt_acquire_notify_info_t *chr_info = NULL;
3332 chr_info = bluetooth_get_characteristic_info_from_path(handle);
3334 if (chr_info != NULL) {
3335 BT_INFO("GATT Server: acquire notification char info found");
3337 if (chr_info->write_fd >= 0) {
3338 BT_INFO("closing fd");
3339 close(chr_info->write_fd);