2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include<glib/gprintf.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <gio/gunixfdlist.h>
29 #include "bt-common.h"
30 /* TODO_40 : 4.0 merge - Need to check why includes bt-event-handler.h */
31 #include "bt-event-handler.h"
32 #include "bt-internal-types.h"
35 #include "bluetooth-gatt-server-api.h"
36 #include "bt-request-sender.h"
37 #define BT_GATT_ATT_UUID_LEN_MAX 50
38 #define BT_GATT_SERVER_DBUS_NAME_LEN_MAX 50
40 static GSList *gatt_characteristic_server_notify_list = NULL;;
42 /* Common defintions to follow , applicable for both
43 GATT_DIRECT and RELAY */
46 #define NUMBER_OF_FLAGS 10
49 int bluetooth_gatt_convert_prop2string(
50 bt_gatt_characteristic_property_t properties,
51 char *char_properties[])
55 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
56 char_properties[flag_count] = g_strdup("broadcast");
59 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
60 char_properties[flag_count] = g_strdup("read");
63 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
64 char_properties[flag_count] = g_strdup("write-without-response");
67 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
68 char_properties[flag_count] = g_strdup("write");
71 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
72 char_properties[flag_count] = g_strdup("notify");
75 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
76 char_properties[flag_count] = g_strdup("indicate");
79 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
80 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
83 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
84 char_properties[flag_count] = g_strdup("reliable-write");
87 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
88 char_properties[flag_count] = g_strdup("writable-auxiliaries");
91 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
92 char_properties[flag_count] = g_strdup("encrypt-read");
95 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
96 char_properties[flag_count] = g_strdup("encrypt-write");
99 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
100 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
103 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
104 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
108 if (flag_count == 0) {
109 char_properties[flag_count] = g_strdup("read");
116 int bluetooth_gatt_convert_perm2string(
117 bt_gatt_permission_t properties,
118 char *char_properties[])
122 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
123 char_properties[flag_count] = g_strdup("read");
126 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
127 char_properties[flag_count] = g_strdup("write");
130 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
131 char_properties[flag_count] = g_strdup("encrypt-read");
134 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
135 char_properties[flag_count] = g_strdup("encrypt-write");
138 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
139 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
142 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
143 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
147 if (flag_count == 0) {
148 char_properties[flag_count] = g_strdup("read");
156 #define NUMBER_OF_FLAGS 10
158 static GDBusConnection *g_conn;
159 static guint owner_id;
160 static guint manager_id;
161 static gboolean new_service = FALSE;
162 static gboolean new_char = FALSE;
163 static int serv_id = 1;
164 static bool is_server_started = false;
166 static GCancellable *register_cancel;
168 /* Introspection data for the service we are exporting */
169 static const gchar service_introspection_xml[] =
171 " <interface name='org.freedesktop.DBus.Properties'>"
172 " <property type='s' name='UUID' access='read'>"
174 " <property type='b' name='primary' access='read'>"
176 " <property type='o' name='Device' access='read'>"
178 " <property type='ao' name='Characteristics' access='read'>"
180 " <property type='s' name='Includes' access='read'>"
185 /* Introspection data for the characteristics we are exporting */
186 static const gchar characteristics_introspection_xml[] =
188 " <interface name='org.bluez.GattCharacteristic1'>"
189 " <method name='ReadValue'>"
190 " <arg type='s' name='address' direction='in'/>"
191 " <arg type='u' name='id' direction='in'/>"
192 " <arg type='q' name='offset' direction='in'/>"
193 " <arg type='ay' name='Value' direction='out'/>"
195 " <method name='WriteValue'>"
196 " <arg type='s' name='address' direction='in'/>"
197 " <arg type='u' name='id' direction='in'/>"
198 " <arg type='q' name='offset' direction='in'/>"
199 " <arg type='b' name='response_needed' direction='in'/>"
200 " <arg type='ay' name='value' direction='in'/>"
202 " <method name='StartNotify'>"
204 " <method name='StopNotify'>"
206 " <method name='IndicateConfirm'>"
207 " <arg type='s' name='address' direction='in'/>"
208 " <arg type='b' name='complete' direction='in'/>"
211 " <interface name='org.freedesktop.DBus.Properties'>"
212 " <property type='s' name='UUID' access='read'>"
214 " <property type='o' name='Service' access='read'>"
216 " <property type='ay' name='Value' access='readwrite'>"
218 " <property type='b' name='Notifying' access='read'>"
220 " <property type='as' name='Flags' access='read'>"
222 " <property type='s' name='Unicast' access='read'>"
224 " <property type='ao' name='Descriptors' access='read'>"
229 /* Introspection data for the descriptor we are exporting */
230 static const gchar descriptor_introspection_xml[] =
232 " <interface name='org.bluez.GattDescriptor1'>"
233 " <method name='ReadValue'>"
234 " <arg type='s' name='address' direction='in'/>"
235 " <arg type='u' name='id' direction='in'/>"
236 " <arg type='q' name='offset' direction='in'/>"
237 " <arg type='ay' name='Value' direction='out'/>"
239 " <method name='WriteValue'>"
240 " <arg type='s' name='address' direction='in'/>"
241 " <arg type='u' name='id' direction='in'/>"
242 " <arg type='q' name='offset' direction='in'/>"
243 " <arg type='b' name='response_needed' direction='in'/>"
244 " <arg type='ay' name='value' direction='in'/>"
247 " <interface name='org.freedesktop.DBus.Properties'>"
248 " <property type='s' name='UUID' access='read'>"
250 " <property type='o' name='Characteristic' access='read'>"
252 " <property type='ay' name='Value' access='read'>"
254 " <property type='as' name='Flags' access='read'>"
259 static const gchar manager_introspection_xml[] =
261 " <interface name='org.freedesktop.DBus.ObjectManager'>"
262 " <method name='GetManagedObjects'>"
263 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
268 struct gatt_service_info {
274 gboolean is_svc_registered;
275 gboolean is_svc_primary;
278 struct gatt_char_info {
283 gchar *char_flags[NUMBER_OF_FLAGS];
289 struct gatt_desc_info {
294 gchar *desc_flags[NUMBER_OF_FLAGS];
299 struct gatt_req_info {
304 GDBusMethodInvocation *context;
307 static GSList *gatt_services = NULL;
308 static GSList *gatt_requests = NULL;
309 static gchar *app_path = NULL;
311 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
312 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
314 #define GATT_SERV_OBJECT_PATH "/service"
316 #define GATT_MNGR_INTERFACE "org.bluez.GattManager1"
317 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
318 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
319 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
321 #ifdef TIZEN_FEATURE_BT_HPS
322 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
323 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
324 #define PROPERTIES_CHANGED "PropertiesChanged"
325 #define BT_HPS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
328 #ifdef TIZEN_FEATURE_BT_OTP
329 #define BT_OTP_OBJECT_PATH "/org/projectx/otp"
330 #define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
331 #define PROPERTIES_CHANGED "PropertiesChanged"
332 #define BT_OTP_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
335 static GDBusProxy *manager_gproxy = NULL;
337 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
338 const char *service_path, const char *char_path);
339 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
340 const char *serv_path, const char *char_path,
341 const char *desc_path);
343 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
344 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info);
354 } bluetooth_gatt_acquire_notify_info_t;
357 static int bluetooth_get_characteristic_fd(int att_handle , char *path)
361 BT_DBG("request found path [%s] att_handle [ %d]", path, att_handle);
362 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
363 bluetooth_gatt_acquire_notify_info_t *info = l->data;
365 if (info->att_hand == att_handle)
366 return info->write_fd;
371 static bluetooth_gatt_acquire_notify_info_t * bluetooth_get_characteristic_info_from_path(int att_handle)
375 BT_DBG("request found att_handle [ %d]", att_handle);
376 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
377 bluetooth_gatt_acquire_notify_info_t *info = l->data;
378 BT_DBG(" sid [ %d]" , info->att_hand);
379 if (info->att_hand == att_handle)
386 static void bluetooth_characteristic_info_free(bluetooth_gatt_acquire_notify_info_t *chr_info)
391 static gboolean bluetooth_gatt_write_channel_watch_cb(GIOChannel *gio,
392 GIOCondition cond, gpointer data)
396 bluetooth_gatt_acquire_notify_info_t *chr_info = (bluetooth_gatt_acquire_notify_info_t *)data;
399 BT_INFO("chr_info is NULL");
403 if (cond & G_IO_NVAL) {
404 BT_ERR("Invalid channel");
408 if (cond & (G_IO_HUP | G_IO_ERR)) {
409 BT_ERR("Error : GIOCondition %d", cond);
410 g_io_channel_shutdown(gio, TRUE, NULL);
411 g_io_channel_unref(gio);
413 if (g_slist_find(gatt_characteristic_server_notify_list, chr_info)) {
414 BT_INFO("found char_info in the list");
415 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
416 bluetooth_characteristic_info_free(chr_info);
422 if (g_slist_find(gatt_characteristic_server_notify_list, chr_info) == NULL) {
423 BT_INFO("chr_info is not in the list");
430 static int bluetooth_gatt_write_characteristics_value_to_fd_(
431 int fd, const guint8 *value, int length,
436 int att_result = BLUETOOTH_ERROR_NONE;
438 BT_CHECK_PARAMETER(value, return);
440 written = write(fd, value, length);
441 if (written != length) {
442 att_result = BLUETOOTH_ERROR_INTERNAL;
443 BT_ERR("write data failed %d is ", written);
449 #ifdef TIZEN_FEATURE_BT_HPS
450 static int __bt_send_event_to_hps(int event, GVariant *var)
452 GError *error = NULL;
453 GVariant *parameters;
454 GDBusMessage *msg = NULL;
458 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
460 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
461 GVariantBuilder *inner_builder;
462 GVariantBuilder *invalidated_builder;
464 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
465 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
467 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
469 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
471 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
472 g_variant_builder_unref(invalidated_builder);
473 g_variant_builder_unref(inner_builder);
474 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
475 GVariantBuilder *inner_builder;
476 GVariantBuilder *invalidated_builder;
478 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
479 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
481 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
483 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
485 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
486 g_variant_builder_unref(invalidated_builder);
487 g_variant_builder_unref(inner_builder);
489 g_varaiant_unref(var);
492 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
493 g_dbus_message_set_body(msg, parameters);
494 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
496 BT_ERR("D-Bus API failure: errCode[%x], \
498 error->code, error->message);
499 g_clear_error(&error);
501 return BLUETOOTH_ERROR_INTERNAL;
503 return BLUETOOTH_ERROR_NONE;
507 #ifdef TIZEN_FEATURE_BT_OTP
508 static int __bt_send_event_to_otp(int event, GVariant *var)
510 GError *error = NULL;
511 GVariant *parameters = NULL;
512 GDBusMessage *msg = NULL;
516 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
518 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
519 GVariantBuilder *inner_builder;
520 GVariantBuilder *invalidated_builder;
522 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
523 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
525 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
527 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
529 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
530 g_variant_builder_unref(invalidated_builder);
531 g_variant_builder_unref(inner_builder);
532 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
533 GVariantBuilder *inner_builder;
534 GVariantBuilder *invalidated_builder;
536 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
537 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
539 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
541 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
543 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
544 g_variant_builder_unref(invalidated_builder);
545 g_variant_builder_unref(inner_builder);
546 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
547 GVariantBuilder *inner_builder;
548 GVariantBuilder *invalidated_builder;
550 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
551 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
553 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
555 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
557 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
558 g_variant_builder_unref(invalidated_builder);
559 g_variant_builder_unref(inner_builder);
562 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
563 g_dbus_message_set_body(msg, parameters);
564 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
566 BT_ERR("D-Bus API failure: errCode[%x], \
568 error->code, error->message);
569 g_clear_error(&error);
571 return BLUETOOTH_ERROR_INTERNAL;
573 return BLUETOOTH_ERROR_NONE;
577 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
579 const gchar *object_path,
580 const gchar *interface_name,
581 const gchar *method_name,
582 GVariant *parameters,
583 GDBusMethodInvocation *invocation,
586 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
587 BT_DBG("Getting values for service, chars and descriptors");
590 GVariantBuilder *builder = NULL;
591 GVariantBuilder *inner_builder1 = NULL;
592 GVariant *svc_char = NULL;
593 GSList *char_list = NULL;
594 GSList *desc_list = NULL;
597 builder = g_variant_builder_new(G_VARIANT_TYPE("a{oa{sa{sv}}}"));
599 /* Prepare inner builder for GattService1 interface */
600 svc_index = g_slist_length(gatt_services) - 1;
601 for (; svc_index >= 0; svc_index--) {
602 GVariantBuilder *svc_builder = NULL;
603 GVariantBuilder *inner_builder = NULL;
604 struct gatt_service_info *serv_info = NULL;
606 serv_info = g_slist_nth_data(gatt_services, svc_index);
607 if (serv_info == NULL) {
608 BT_ERR("serv_info is NULL");
612 /* Prepare inner builder for GattService1 interface */
613 BT_DBG("Creating builder for service : %s", serv_info->service_uuid);
614 svc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
615 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
617 g_variant_builder_add(inner_builder, "{sv}", "UUID",
618 g_variant_new_string(serv_info->service_uuid));
619 g_variant_builder_add(inner_builder, "{sv}", "Primary",
620 g_variant_new_boolean(serv_info->is_svc_primary));
622 /* Characteristics */
623 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
625 BT_DBG("Adding Charatarisitcs list");
626 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
627 struct gatt_char_info *char_info = char_list->data;
628 g_variant_builder_add(inner_builder1, "o", char_info->char_path);
629 BT_DBG("%s", char_info->char_path);
632 svc_char = g_variant_new("ao", inner_builder1);
633 g_variant_builder_add(inner_builder, "{sv}", "Characteristics", svc_char);
634 g_variant_builder_add(svc_builder, "{sa{sv}}", GATT_SERV_INTERFACE, inner_builder);
635 g_variant_builder_add(builder, "{oa{sa{sv}}}", serv_info->serv_path, svc_builder);
636 g_variant_builder_unref(inner_builder1);
638 /* Prepare inner builder for GattCharacteristic1 interface */
639 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
640 GVariantBuilder *char_builder = NULL;
641 GVariantBuilder *inner_builder = NULL;
642 GVariantBuilder *builder1 = NULL;
643 GVariantBuilder *builder2 = NULL;
644 GVariantBuilder *builder3 = NULL;
645 GVariant *char_val = NULL;
646 GVariant *flags_val = NULL;
647 GVariant *char_desc = NULL;
648 char *unicast = NULL;
649 gboolean notify = FALSE;
651 struct gatt_char_info *char_info = char_list->data;
653 if (char_info == NULL) {
654 BT_ERR("char_info is NULL");
658 BT_DBG("Creating builder for characteristic : %s", char_info->char_uuid);
659 char_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
660 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
663 g_variant_builder_add(inner_builder, "{sv}", "UUID",
664 g_variant_new_string(char_info->char_uuid));
667 g_variant_builder_add(inner_builder, "{sv}", "Service",
668 g_variant_new("o", serv_info->serv_path));
671 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
672 if (char_info->char_value != NULL) {
673 for (i = 0; i < char_info->value_length; i++) {
674 g_variant_builder_add(builder1, "y", char_info->char_value[i]);
676 char_val = g_variant_new("ay", builder1);
677 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
681 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
682 for (i = 0; i < char_info->flags_length; i++) {
683 g_variant_builder_add(builder2, "s", char_info->char_flags[i]);
685 flags_val = g_variant_new("as", builder2);
686 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
689 g_variant_builder_add(inner_builder, "{sv}", "Notifying", g_variant_new("b", notify));
692 unicast = g_strdup("00:00:00:00:00:00");
693 g_variant_builder_add(inner_builder, "{sv}", "Unicast", g_variant_new("s", unicast));
696 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
697 BT_DBG("Adding Descriptors list");
698 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
699 struct gatt_desc_info *desc_info = desc_list->data;
700 g_variant_builder_add(builder3, "o", desc_info->desc_path);
701 BT_DBG("%s", desc_info->desc_path);
704 char_desc = g_variant_new("ao", builder3);
705 g_variant_builder_add(inner_builder, "{sv}", "Descriptors", char_desc);
706 g_variant_builder_add(char_builder, "{sa{sv}}", GATT_CHAR_INTERFACE , inner_builder);
707 g_variant_builder_add(builder, "{oa{sa{sv}}}", char_info->char_path, char_builder);
709 /*Prepare inner builder for GattDescriptor1 interface*/
710 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
711 GVariantBuilder *desc_builder = NULL;
712 GVariantBuilder *inner_builder = NULL;
713 GVariantBuilder *builder1 = NULL;
714 GVariantBuilder *builder2 = NULL;
715 GVariant *desc_val = NULL;
716 struct gatt_desc_info *desc_info = desc_list->data;
718 if (desc_info == NULL) {
719 BT_ERR("desc_info is NULL");
723 BT_DBG("Creating builder for descriptor : %s", desc_info->desc_uuid);
724 desc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
725 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
728 g_variant_builder_add(inner_builder, "{sv}", "UUID",
729 g_variant_new_string(desc_info->desc_uuid));
732 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
733 g_variant_new("o", char_info->char_path));
736 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
737 if (desc_info->desc_value != NULL) {
738 for (i = 0; i < desc_info->value_length; i++) {
739 g_variant_builder_add(builder1, "y", desc_info->desc_value[i]);
741 desc_val = g_variant_new("ay", builder1);
742 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
746 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
747 for (i = 0; i < desc_info->flags_length; i++) {
748 g_variant_builder_add(builder2, "s", desc_info->desc_flags[i]);
750 flags_val = g_variant_new("as", builder2);
751 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
753 g_variant_builder_add(desc_builder, "{sa{sv}}", GATT_DESC_INTERFACE,
755 g_variant_builder_add(builder, "{oa{sa{sv}}}", desc_info->desc_path,
758 /* unref descriptor builder pointers */
759 g_variant_builder_unref(builder1);
760 g_variant_builder_unref(builder2);
761 g_variant_builder_unref(inner_builder);
762 g_variant_builder_unref(desc_builder);
768 /* unref char builder pointers */
769 g_variant_builder_unref(builder1);
770 g_variant_builder_unref(builder2);
771 g_variant_builder_unref(builder3);
772 g_variant_builder_unref(inner_builder);
773 g_variant_builder_unref(char_builder);
776 /* unref service builder pointers */
777 g_variant_builder_unref(inner_builder);
778 g_variant_builder_unref(svc_builder);
781 /* Return builder as method reply */
782 BT_DBG("Sending gatt service builder values to Bluez");
783 g_dbus_method_invocation_return_value(invocation,
784 g_variant_new("(a{oa{sa{sv}}})", builder));
785 g_variant_builder_unref(builder);
789 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
793 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
794 struct gatt_service_info *serv_info = l1->data;
796 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
797 struct gatt_char_info *char_info = l2->data;
799 if (g_strcmp0(char_info->char_path, char_path) == 0)
803 BT_ERR("Gatt service not found");
807 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
809 GSList *l1, *l2, *l3;
811 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
812 struct gatt_service_info *serv_info = l1->data;
814 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
815 struct gatt_char_info *char_info = l2->data;
817 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
818 struct gatt_desc_info *desc_info = l3->data;
820 if (g_strcmp0(desc_info->desc_path, desc_path) == 0)
825 BT_ERR("Gatt service not found");
829 static void __bt_gatt_char_method_call(GDBusConnection *connection,
831 const gchar *object_path,
832 const gchar *interface_name,
833 const gchar *method_name,
834 GVariant *parameters,
835 GDBusMethodInvocation *invocation,
839 if (g_strcmp0(method_name, "ReadValue") == 0) {
843 bt_gatt_read_req_t read_req = {0, };
844 bt_user_info_t *user_info = NULL;
845 struct gatt_req_info *req_info = NULL;
846 struct gatt_service_info *svc_info = NULL;
847 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
848 GVariant *param = NULL;
851 BT_DBG("Application path = %s", object_path);
852 BT_DBG("Sender = %s", sender);
854 user_info = _bt_get_user_data(BT_COMMON);
855 if (user_info == NULL) {
856 BT_INFO("No callback is set for %s", object_path);
857 g_dbus_method_invocation_return_value(invocation, NULL);
861 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
862 if (svc_info == NULL) {
863 BT_ERR("Coudn't find service for %s", object_path);
864 g_dbus_method_invocation_return_value(invocation, NULL);
868 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
869 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
871 read_req.att_handle = (char *)object_path;
872 read_req.address = addr;
873 read_req.req_id = req_id;
874 read_req.offset = offset;
875 read_req.service_handle = svc_info->serv_path;
877 /* Store requets information */
878 req_info = g_new0(struct gatt_req_info, 1);
879 req_info->attr_path = g_strdup(object_path);
880 req_info->svc_path = g_strdup(read_req.service_handle);
881 req_info->request_id = req_id;
882 req_info->offset = offset;
883 req_info->context = invocation;
884 gatt_requests = g_slist_append(gatt_requests, req_info);
886 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
887 param = g_variant_new("(sssyq)",
889 read_req.service_handle,
893 #ifdef TIZEN_FEATURE_BT_HPS
894 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
896 #ifdef TIZEN_FEATURE_BT_OTP
897 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
901 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
902 BLUETOOTH_ERROR_NONE, &read_req,
903 user_info->cb, user_info->user_data);
905 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
906 GVariant *var = NULL;
910 gboolean response_needed = FALSE;
911 bt_gatt_value_change_t value_change = {0, };
912 bt_user_info_t *user_info = NULL;
914 struct gatt_service_info *svc_info = NULL;
915 struct gatt_req_info *req_info = NULL;
916 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
917 GVariant *param = NULL;
920 BT_DBG("WriteValue");
921 BT_DBG("Application path = %s", object_path);
922 BT_DBG("Sender = %s", sender);
924 g_variant_get(parameters, "(&suqb@ay)",
925 &addr, &req_id, &offset, &response_needed, &var);
926 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
928 user_info = _bt_get_user_data(BT_COMMON);
930 BT_INFO("No callback is set for %s", object_path);
931 g_variant_unref(var);
933 g_dbus_method_invocation_return_value(invocation, NULL);
935 g_object_unref(invocation);
939 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
940 if (svc_info == NULL) {
941 BT_ERR("Coudn't find service for %s", object_path);
942 g_variant_unref(var);
944 g_dbus_method_invocation_return_value(invocation, NULL);
946 g_object_unref(invocation);
950 value_change.att_handle = (char *)object_path;
951 value_change.address = addr;
952 value_change.service_handle = svc_info->serv_path;
953 value_change.offset = offset;
954 value_change.req_id = req_id;
955 value_change.response_needed = response_needed;
957 len = g_variant_get_size(var);
961 value_change.att_value = (guint8 *)g_malloc(len);
963 data = (char *)g_variant_get_data(var);
964 memcpy(value_change.att_value, data, len);
966 value_change.val_len = len;
968 if (response_needed) {
969 /* Store requets information */
970 req_info = g_new0(struct gatt_req_info, 1);
971 req_info->attr_path = g_strdup(object_path);
972 req_info->svc_path = g_strdup(value_change.service_handle);
973 req_info->request_id = req_id;
974 req_info->offset = offset;
975 req_info->context = invocation;
976 gatt_requests = g_slist_append(gatt_requests, req_info);
978 g_object_unref(invocation);
981 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
984 svc_path = g_strdup(svc_info->serv_path);
985 param = g_variant_new("(sssyq@ay)",
992 #ifdef TIZEN_FEATURE_BT_HPS
993 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
995 #ifdef TIZEN_FEATURE_BT_OTP
996 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1003 _bt_common_event_cb(
1004 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1005 BLUETOOTH_ERROR_NONE, &value_change,
1006 user_info->cb, user_info->user_data);
1008 g_free(value_change.att_value);
1009 g_variant_unref(var);
1011 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1012 bt_user_info_t *user_info = NULL;
1013 bt_gatt_char_notify_change_t notify_change = {0, };
1014 #if TIZEN_FEATURE_BT_OTP
1015 GVariant *param = NULL;
1017 BT_DBG("StartNotify");
1018 user_info = _bt_get_user_data(BT_COMMON);
1019 if (user_info != NULL) {
1020 struct gatt_service_info *svc_info = NULL;
1021 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1023 notify_change.service_handle = svc_info->serv_path;
1024 notify_change.att_handle = (char *)object_path;
1025 notify_change.att_notify = TRUE;
1026 #if TIZEN_FEATURE_BT_OTP
1027 param = g_variant_new("(ssb)",
1028 notify_change.att_handle,
1029 notify_change.service_handle,
1030 notify_change.att_notify);
1031 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1033 _bt_common_event_cb(
1034 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1035 BLUETOOTH_ERROR_NONE, ¬ify_change,
1036 user_info->cb, user_info->user_data);
1039 g_object_unref(invocation);
1041 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1042 bt_user_info_t *user_info = NULL;
1043 bt_gatt_char_notify_change_t notify_change = {0, };
1044 #if TIZEN_FEATURE_BT_OTP
1045 GVariant *param = NULL;
1047 BT_DBG("StopNotify");
1048 user_info = _bt_get_user_data(BT_COMMON);
1049 if (user_info != NULL) {
1050 struct gatt_service_info *svc_info = NULL;
1051 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1053 notify_change.service_handle = svc_info->serv_path;
1054 notify_change.att_handle = (char *)object_path;
1055 notify_change.att_notify = FALSE;
1056 #if TIZEN_FEATURE_BT_OTP
1057 param = g_variant_new("(ssb)",
1058 notify_change.att_handle,
1059 notify_change.service_handle,
1060 notify_change.att_notify);
1061 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1063 _bt_common_event_cb(
1064 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1065 BLUETOOTH_ERROR_NONE, ¬ify_change,
1066 user_info->cb, user_info->user_data);
1069 g_object_unref(invocation);
1071 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1073 bt_gatt_indicate_confirm_t confirm = {0, };
1074 bt_user_info_t *user_info = NULL;
1075 gboolean complete = FALSE;
1076 struct gatt_service_info *svc_info = NULL;
1078 BT_DBG("IndicateConfirm");
1079 BT_DBG("Application path = %s", object_path);
1080 BT_DBG("Sender = %s", sender);
1082 g_variant_get(parameters, "(&sb)", &addr, &complete);
1083 BT_DBG("Remote Device address number = %s", addr);
1085 confirm.att_handle = (char *)object_path;
1086 confirm.address = addr;
1087 confirm.complete = complete;
1089 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1090 if (svc_info != NULL) {
1091 confirm.service_handle = svc_info->serv_path;
1093 user_info = _bt_get_user_data(BT_COMMON);
1094 if (user_info != NULL) {
1095 _bt_common_event_cb(
1096 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1097 BLUETOOTH_ERROR_NONE, &confirm,
1098 user_info->cb, user_info->user_data);
1103 g_dbus_method_invocation_return_value(invocation, NULL);
1106 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1107 const gchar *sender,
1108 const gchar *object_path,
1109 const gchar *interface_name,
1110 const gchar *method_name,
1111 GVariant *parameters,
1112 GDBusMethodInvocation *invocation,
1115 if (g_strcmp0(method_name, "ReadValue") == 0) {
1119 bt_gatt_read_req_t read_req = {0, };
1120 bt_user_info_t *user_info = NULL;
1121 struct gatt_req_info *req_info = NULL;
1122 struct gatt_service_info *svc_info = NULL;
1124 BT_DBG("ReadValue");
1125 BT_DBG("Application path = %s", object_path);
1126 BT_DBG("Sender = %s", sender);
1128 user_info = _bt_get_user_data(BT_COMMON);
1129 if (user_info == NULL) {
1130 BT_INFO("No callback is set for %s", object_path);
1131 g_dbus_method_invocation_return_value(invocation, NULL);
1135 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1136 if (svc_info == NULL) {
1137 BT_ERR("Coudn't find service for %s", object_path);
1138 g_dbus_method_invocation_return_value(invocation, NULL);
1142 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1143 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1145 read_req.att_handle = (char *)object_path;
1146 read_req.address = addr;
1147 read_req.req_id = req_id;
1148 read_req.offset = offset;
1149 read_req.service_handle = svc_info->serv_path;
1151 /* Store requets information */
1152 req_info = g_new0(struct gatt_req_info, 1);
1153 req_info->attr_path = g_strdup(object_path);
1154 req_info->svc_path = g_strdup(read_req.service_handle);
1155 req_info->request_id = req_id;
1156 req_info->offset = offset;
1157 req_info->context = invocation;
1158 gatt_requests = g_slist_append(gatt_requests, req_info);
1160 _bt_common_event_cb(
1161 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1162 BLUETOOTH_ERROR_NONE, &read_req,
1163 user_info->cb, user_info->user_data);
1166 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1167 GVariant *var = NULL;
1171 gboolean response_needed = FALSE;
1172 bt_gatt_value_change_t value_change = {0, };
1173 bt_user_info_t *user_info = NULL;
1175 struct gatt_service_info *svc_info = NULL;
1176 struct gatt_req_info *req_info = NULL;
1178 BT_DBG("WriteValue");
1179 BT_DBG("Application path = %s", object_path);
1180 BT_DBG("Sender = %s", sender);
1182 g_variant_get(parameters, "(&suqb@ay)",
1183 &addr, &req_id, &offset, &response_needed, &var);
1184 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1186 user_info = _bt_get_user_data(BT_COMMON);
1187 if (user_info == NULL) {
1188 BT_INFO("No callback is set for %s", object_path);
1189 g_variant_unref(var);
1190 if (response_needed)
1191 g_dbus_method_invocation_return_value(invocation, NULL);
1193 g_object_unref(invocation);
1197 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1198 if (svc_info == NULL) {
1199 BT_ERR("Coudn't find service for %s", object_path);
1200 g_variant_unref(var);
1201 if (response_needed)
1202 g_dbus_method_invocation_return_value(invocation, NULL);
1204 g_object_unref(invocation);
1208 value_change.att_handle = (char *)object_path;
1209 value_change.address = addr;
1210 value_change.service_handle = svc_info->serv_path;
1211 value_change.offset = offset;
1212 value_change.req_id = req_id;
1213 value_change.response_needed = response_needed;
1215 len = g_variant_get_size(var);
1219 value_change.att_value = (guint8 *)g_malloc(len);
1221 data = (char *)g_variant_get_data(var);
1222 memcpy(value_change.att_value, data, len);
1224 value_change.val_len = len;
1226 if (response_needed) {
1227 /* Store requets information */
1228 req_info = g_new0(struct gatt_req_info, 1);
1229 req_info->attr_path = g_strdup(object_path);
1230 req_info->svc_path = g_strdup(value_change.service_handle);
1231 req_info->request_id = req_id;
1232 req_info->offset = offset;
1233 req_info->context = invocation;
1234 gatt_requests = g_slist_append(gatt_requests, req_info);
1236 g_object_unref(invocation);
1239 _bt_common_event_cb(
1240 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1241 BLUETOOTH_ERROR_NONE, &value_change,
1242 user_info->cb, user_info->user_data);
1244 g_free(value_change.att_value);
1245 g_variant_unref(var);
1250 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1253 GError *error = NULL;
1254 GVariantBuilder *array_builder;
1256 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1257 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1258 g_variant_builder_add(array_builder, "s", interface);
1260 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1261 "org.freedesktop.Dbus.Objectmanager",
1262 "InterfacesRemoved",
1263 g_variant_new("(oas)",
1264 object_path, array_builder),
1268 if (error != NULL) {
1269 /* dbus gives error cause */
1270 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1271 error->code, error->message);
1272 g_clear_error(&error);
1275 g_variant_builder_unref(array_builder);
1280 static const GDBusInterfaceVTable desc_interface_vtable = {
1281 __bt_gatt_desc_method_call,
1287 static const GDBusInterfaceVTable char_interface_vtable = {
1288 __bt_gatt_char_method_call,
1294 static const GDBusInterfaceVTable serv_interface_vtable = {
1301 static const GDBusInterfaceVTable manager_interface_vtable = {
1302 __bt_gatt_manager_method_call,
1308 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1309 const gchar *introspection_data)
1312 GDBusNodeInfo *node_info = NULL;
1314 if (introspection_data == NULL)
1318 BT_DBG("Create new node info");
1319 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1322 BT_ERR("Unable to create node: %s", err->message);
1323 g_clear_error(&err);
1330 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1331 const char *service_path)
1335 for (l = gatt_services; l != NULL; l = l->next) {
1336 struct gatt_service_info *info = l->data;
1338 if (g_strcmp0(info->serv_path, service_path) == 0)
1341 BT_ERR("Gatt service not found");
1345 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1346 const char *service_path, const char *char_path)
1350 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1351 struct gatt_service_info *serv_info = l1->data;
1353 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1355 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1356 struct gatt_char_info *char_info = l2->data;
1358 if (g_strcmp0(char_info->char_path, char_path) == 0)
1361 BT_ERR("Gatt characteristic not found");
1365 BT_ERR("Gatt service not found");
1369 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1370 const char *serv_path, const char *char_path,
1371 const char *desc_path)
1373 GSList *l1, *l2, *l3;
1375 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1376 struct gatt_service_info *serv_info = l1->data;
1378 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1379 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1380 struct gatt_char_info *char_info = l2->data;
1382 if (g_strcmp0(char_info->char_path, char_path) == 0) {
1383 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1384 struct gatt_desc_info *desc_info = l3->data;
1385 if (g_strcmp0(desc_info->desc_path,
1394 BT_ERR("Gatt descriptor not found");
1398 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1402 for (l = gatt_requests; l != NULL; l = l->next) {
1403 struct gatt_req_info *req_info = l->data;
1405 if (req_info && req_info->request_id == request_id)
1408 BT_ERR("Gatt Request not found");
1412 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1413 const gchar *path, const gchar *interface)
1418 g_conn = _bt_get_system_shared_conn();
1420 BT_ERR("Unable to get connection");
1424 proxy = g_dbus_proxy_new_sync(g_conn,
1425 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1427 interface, NULL, &err);
1431 BT_ERR("Unable to create proxy: %s", err->message);
1432 g_clear_error(&err);
1436 manager_gproxy = proxy;
1441 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1442 const gchar *path, const gchar *interface)
1444 return (manager_gproxy) ? manager_gproxy :
1445 __bt_gatt_gdbus_init_manager_proxy(service,
1449 static gboolean __bt_gatt_is_service_registered(const char *service_path)
1451 struct gatt_service_info *svc_info = NULL;
1453 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1455 if (svc_info != NULL) {
1456 BT_DBG("Return the state of the gatt service %d",
1457 svc_info->is_svc_registered);
1458 return svc_info->is_svc_registered;
1461 BT_DBG("gatt service info is NULL");
1465 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1467 GError *error = NULL;
1469 GVariantIter *iter = NULL;
1470 const gchar *key = NULL;
1471 GVariant *value = NULL;
1472 const gchar *service = NULL;
1473 const gchar *characteristic = NULL;
1474 const gchar *descriptor = NULL;
1478 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1480 if (result == NULL) {
1481 BT_ERR("Dbus-RPC is failed");
1482 if (error != NULL) {
1483 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1484 error->code, error->message);
1485 g_clear_error(&error);
1488 char *char_cmp = NULL;
1489 g_variant_get(result, "(a{sv})", &iter);
1490 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1492 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1493 if (g_strcmp0(key, "Service") == 0) {
1494 service = g_variant_get_string(value, NULL);
1495 BT_DBG("Service %s", service);
1496 } else if (g_strcmp0(key, char_cmp) == 0) {
1497 characteristic = g_variant_get_string(value, NULL);
1499 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1500 BT_DBG("%s", characteristic);
1501 } else if (g_strcmp0(key, "Descriptor") == 0) {
1502 descriptor = g_variant_get_string(value, NULL);
1503 BT_DBG("Descriptor %s", descriptor);
1506 g_variant_iter_free(iter);
1508 /* TODO: Store the service informationa and
1509 * Send respponse to CAPI layer. */
1511 g_variant_unref(result);
1516 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1518 BT_INFO("RegisterApplication is completed");
1520 GError *error = NULL;
1523 if (register_cancel) {
1524 g_object_unref(register_cancel);
1525 register_cancel = NULL;
1528 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1529 if (result == NULL) {
1530 BT_ERR("Dbus-RPC is failed");
1531 if (error != NULL) {
1532 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1533 error->code, error->message);
1534 g_clear_error(&error);
1536 is_server_started = false;
1538 g_variant_unref(result);
1542 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1544 GDBusProxy *proxy = NULL;
1546 if (is_server_started) {
1550 if (app_path == NULL) {
1551 BT_ERR("app_path is NULL");
1552 return BLUETOOTH_ERROR_INTERNAL;
1555 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1556 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1557 if (proxy == NULL) {
1558 BT_ERR("proxy is NULL");
1559 return BLUETOOTH_ERROR_INTERNAL;
1562 BT_INFO("UnregisterApplication");
1564 /* Async Call to Unregister Service */
1565 ret = g_dbus_proxy_call_sync(proxy, "UnregisterApplication",
1566 g_variant_new("(o)", app_path), G_DBUS_CALL_FLAGS_NONE, -1,
1569 BT_ERR("dBUS-RPC is failed");
1571 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1572 err->code, err->message);
1573 if (err->code == G_DBUS_ERROR_SERVICE_UNKNOWN ||
1574 g_strrstr(err->message, BT_ERROR_DOES_NOT_EXIST)) {
1575 g_clear_error(&err);
1578 g_clear_error(&err);
1580 return BLUETOOTH_ERROR_INTERNAL;
1582 g_variant_unref(ret);
1585 is_server_started = false;
1587 BT_INFO("UnregisterApplication is completed");
1589 return BLUETOOTH_ERROR_NONE;
1592 BT_INFO("GATT server not started");
1593 return BLUETOOTH_ERROR_NONE;
1596 BT_EXPORT_API int bluetooth_gatt_init(void)
1598 GError *error = NULL;
1599 GDBusNodeInfo *node_info = NULL;
1601 if (app_path != NULL) {
1602 BT_ERR("app path already exists! initialized");
1603 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1606 g_conn = _bt_get_system_shared_conn();
1608 BT_ERR("Unable to get connection");
1612 if (owner_id == 0) {
1613 gchar *name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
1614 BT_DBG("well-known name: %s", name);
1616 owner_id = g_bus_own_name_on_connection(g_conn, name,
1617 G_BUS_NAME_OWNER_FLAGS_NONE,
1618 NULL, NULL, NULL, NULL);
1621 BT_DBG("owner_id is [%d]", owner_id);
1623 app_path = g_strdup_printf("/com/%d", getpid());
1627 /* Register ObjectManager interface */
1628 node_info = __bt_gatt_create_method_node_info(
1629 manager_introspection_xml);
1630 if (node_info == NULL) {
1631 BT_ERR("failed to get node info");
1635 if (manager_id == 0) {
1636 BT_INFO("manager_id does not exists");
1638 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1639 node_info->interfaces[0],
1640 &manager_interface_vtable,
1641 NULL, NULL, &error);
1643 g_dbus_node_info_unref(node_info);
1644 if (manager_id == 0) {
1645 BT_ERR("failed to register: %s", error->message);
1646 g_error_free(error);
1650 return BLUETOOTH_ERROR_NONE;
1654 g_bus_unown_name(owner_id);
1661 return BLUETOOTH_ERROR_INTERNAL;
1664 BT_EXPORT_API int bluetooth_gatt_deinit()
1666 int ret = BLUETOOTH_ERROR_NONE;
1668 if (register_cancel) {
1669 g_cancellable_cancel(register_cancel);
1670 g_object_unref(register_cancel);
1671 register_cancel = NULL;
1674 if (owner_id == 0) {
1675 BT_ERR("owner_id is zero");
1676 return BLUETOOTH_ERROR_NOT_FOUND;
1679 BT_DBG("Removing all registered gatt services");
1680 bluetooth_gatt_delete_services();
1682 /* Unregister the exported interface for object manager */
1684 g_dbus_connection_unregister_object(g_conn, manager_id);
1688 ret = bluetooth_gatt_unregister_application();
1689 if (ret != BLUETOOTH_ERROR_NONE) {
1690 BT_ERR("Fail to unregister application");
1693 g_bus_unown_name(owner_id);
1699 if (manager_gproxy) {
1700 g_object_unref(manager_gproxy);
1701 manager_gproxy = NULL;
1708 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1711 GError *error = NULL;
1713 GDBusNodeInfo *node_info;
1715 GVariantBuilder *builder = NULL;
1716 GVariantBuilder *builder1 = NULL;
1717 GVariantBuilder *inner_builder = NULL;
1718 gboolean svc_primary = TRUE;
1719 struct gatt_service_info *serv_info = NULL;
1721 node_info = __bt_gatt_create_method_node_info(
1722 service_introspection_xml);
1723 if (node_info == NULL)
1724 return BLUETOOTH_ERROR_INTERNAL;
1726 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1727 BT_DBG("gatt service path is [%s]", path);
1729 object_id = g_dbus_connection_register_object(g_conn, path,
1730 node_info->interfaces[0],
1731 &serv_interface_vtable,
1732 NULL, NULL, &error);
1733 g_dbus_node_info_unref(node_info);
1735 if (object_id == 0) {
1736 BT_ERR("failed to register: %s", error->message);
1737 g_error_free(error);
1740 return BLUETOOTH_ERROR_INTERNAL;
1743 /* Add object_id/gatt service information; it's required at the time of
1744 * service unregister and Getmanagedobjects
1746 serv_info = g_new0(struct gatt_service_info, 1);
1748 serv_info->serv_path = g_strdup(path);
1749 serv_info->serv_id = object_id;
1750 serv_info->service_uuid = g_strdup(svc_uuid);
1751 serv_info->is_svc_registered = FALSE;
1752 serv_info->is_svc_primary = svc_primary;
1754 gatt_services = g_slist_append(gatt_services, serv_info);
1756 /* emit interfacesadded signal here for service path */
1757 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1758 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1760 g_variant_builder_add(inner_builder, "{sv}",
1761 "UUID", g_variant_new_string(svc_uuid));
1763 g_variant_builder_add(inner_builder, "{sv}",
1764 "Primary", g_variant_new_boolean(svc_primary));
1766 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1768 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1769 g_variant_new("ao", builder1));
1771 g_variant_builder_add(builder, "{sa{sv}}",
1772 GATT_SERV_INTERFACE, inner_builder);
1774 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1775 "org.freedesktop.Dbus.ObjectManager",
1777 g_variant_new("(oa{sa{sv}})",
1780 if (error != NULL) {
1781 /* dbus gives error cause */
1782 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1783 error->code, error->message);
1784 g_clear_error(&error);
1789 *svc_path = g_strdup(path);
1792 g_variant_builder_unref(inner_builder);
1793 g_variant_builder_unref(builder);
1794 g_variant_builder_unref(builder1);
1796 return BLUETOOTH_ERROR_NONE;
1799 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1800 const char *svc_path, const char *char_uuid,
1801 bt_gatt_permission_t permissions,
1802 bt_gatt_characteristic_property_t properties,
1806 GError *error = NULL;
1808 GDBusNodeInfo *node_info;
1810 GVariantBuilder *builder = NULL;
1811 GVariantBuilder *inner_builder = NULL;
1812 struct gatt_service_info *serv_info = NULL;
1813 struct gatt_char_info *char_info = NULL;
1814 GVariantBuilder *builder2 = NULL;
1815 GVariantBuilder *builder3 = NULL;
1816 GVariant *flags_val = NULL;
1818 char *char_flags[NUMBER_OF_FLAGS];
1823 new_service = FALSE;
1826 BT_DBG("gatt svc_path path is [%s]", svc_path);
1827 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1828 if (serv_info == NULL)
1829 return BLUETOOTH_ERROR_INVALID_PARAM;
1831 node_info = __bt_gatt_create_method_node_info(
1832 characteristics_introspection_xml);
1833 if (node_info == NULL)
1834 return BLUETOOTH_ERROR_INTERNAL;
1836 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1837 BT_DBG("gatt characteristic path is [%s]", path);
1839 object_id = g_dbus_connection_register_object(g_conn, path,
1840 node_info->interfaces[0],
1841 &char_interface_vtable,
1842 NULL, NULL, &error);
1843 g_dbus_node_info_unref(node_info);
1845 if (object_id == 0) {
1846 BT_ERR("failed to register: %s", error->message);
1847 g_error_free(error);
1850 return BLUETOOTH_ERROR_INTERNAL;
1853 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1854 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1855 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1856 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1857 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1858 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1859 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1860 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1862 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1864 char_info = g_new0(struct gatt_char_info, 1);
1866 char_info->char_path = g_strdup(path);
1867 char_info->char_id = object_id;
1868 char_info->char_uuid = g_strdup(char_uuid);
1870 for (i = 0; i < flag_count; i++)
1871 char_info->char_flags[i] = char_flags[i];
1874 char_info->flags_length = flag_count;
1876 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1878 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1879 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1881 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1882 g_variant_new("s", char_uuid));
1883 g_variant_builder_add(inner_builder, "{sv}", "Service",
1884 g_variant_new("o", svc_path));
1886 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1888 for (i = 0; i < flag_count; i++)
1889 g_variant_builder_add(builder2, "s", char_flags[i]);
1891 flags_val = g_variant_new("as", builder2);
1892 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1895 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1897 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1898 g_variant_new("ao", builder3));
1900 g_variant_builder_add(builder, "{sa{sv}}",
1901 GATT_CHAR_INTERFACE,
1904 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1905 "org.freedesktop.Dbus.ObjectManager",
1907 g_variant_new("(oa{sa{sv}})",
1911 /* dBUS gives error cause */
1912 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1913 error->code, error->message);
1914 g_clear_error(&error);
1917 *char_path = g_strdup(path);
1923 g_variant_builder_unref(inner_builder);
1924 g_variant_builder_unref(builder);
1925 g_variant_builder_unref(builder2);
1926 g_variant_builder_unref(builder3);
1928 return BLUETOOTH_ERROR_NONE;
1931 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1932 const char *characteristic, const char *char_value,
1935 gchar **line_argv = NULL;
1936 char *serv_path = NULL;
1937 struct gatt_char_info *char_info = NULL;
1938 GVariantBuilder *builder1 = NULL;
1939 GVariantBuilder *builder = NULL;
1940 GVariantBuilder *inner_builder = NULL;
1941 GVariant *char_val = NULL;
1942 GError *error = NULL;
1944 int res = BLUETOOTH_ERROR_NONE;
1946 line_argv = g_strsplit_set(characteristic, "/", 0);
1947 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1949 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1951 if (char_info == NULL) {
1952 /* Fix : RESOURCE_LEAK */
1953 res = BLUETOOTH_ERROR_INVALID_PARAM;
1957 char_info->value_length = value_length;
1959 char_info->char_value = (char *)malloc(value_length);
1960 /* Fix : NULL_RETURNS */
1961 if (char_info->char_value == NULL) {
1962 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1966 for (i = 0; i < value_length; i++)
1967 char_info->char_value[i] = char_value[i];
1969 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1970 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1972 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1974 for (i = 0; i < value_length; i++)
1975 g_variant_builder_add(builder1, "y", char_value[i]);
1977 char_val = g_variant_new("ay", builder1);
1978 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1980 g_variant_builder_add(builder, "{sa{sv}}",
1981 GATT_CHAR_INTERFACE,
1984 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1985 "org.freedesktop.Dbus.ObjectManager",
1987 g_variant_new("(oa{sa{sv}})",
1988 char_info->char_path, builder),
1992 /* dBUS gives error cause */
1993 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1994 error->code, error->message);
1995 g_clear_error(&error);
1997 g_variant_builder_unref(inner_builder);
1998 g_variant_builder_unref(builder);
1999 g_variant_builder_unref(builder1);
2001 g_strfreev(line_argv);
2007 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2008 const char *char_path, const char *desc_uuid,
2009 bt_gatt_permission_t permissions,
2012 static int desc_id = 1;
2013 GError *error = NULL;
2015 GDBusNodeInfo *node_info;
2017 GVariantBuilder *builder = NULL;
2018 GVariantBuilder *inner_builder = NULL;
2019 struct gatt_char_info *char_info = NULL;
2020 struct gatt_desc_info *desc_info = NULL;
2021 gchar **line_argv = NULL;
2023 GVariantBuilder *builder2 = NULL;
2024 GVariant *flags_val = NULL;
2026 char *desc_flags[NUMBER_OF_FLAGS];
2034 line_argv = g_strsplit_set(char_path, "/", 0);
2035 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2037 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2038 if (char_info == NULL) {
2039 g_strfreev(line_argv);
2041 return BLUETOOTH_ERROR_INVALID_PARAM;
2044 node_info = __bt_gatt_create_method_node_info(
2045 descriptor_introspection_xml);
2046 if (node_info == NULL) {
2047 g_strfreev(line_argv);
2049 return BLUETOOTH_ERROR_INTERNAL;
2052 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2053 BT_DBG("gatt descriptor path is [%s]", path);
2055 object_id = g_dbus_connection_register_object(g_conn, path,
2056 node_info->interfaces[0],
2057 &desc_interface_vtable,
2058 NULL, NULL, &error);
2059 g_dbus_node_info_unref(node_info);
2061 if (object_id == 0) {
2062 BT_ERR("failed to register: %s", error->message);
2063 g_error_free(error);
2065 g_strfreev(line_argv);
2068 return BLUETOOTH_ERROR_INTERNAL;
2071 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2073 desc_info = g_new0(struct gatt_desc_info, 1);
2075 desc_info->desc_path = g_strdup(path);
2076 desc_info->desc_id = object_id;
2077 desc_info->desc_uuid = g_strdup(desc_uuid);
2079 for (i = 0; i < flag_count; i++)
2080 desc_info->desc_flags[i] = desc_flags[i];
2082 desc_info->flags_length = flag_count;
2084 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2086 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2087 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2089 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2090 g_variant_new("s", desc_uuid));
2091 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2092 g_variant_new("o", char_path));
2094 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2096 for (i = 0; i < flag_count; i++)
2097 g_variant_builder_add(builder2, "s", desc_flags[i]);
2099 flags_val = g_variant_new("as", builder2);
2100 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2103 g_variant_builder_add(builder, "{sa{sv}}",
2104 GATT_DESC_INTERFACE,
2107 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2108 "org.freedesktop.Dbus.ObjectManager",
2110 g_variant_new("(oa{sa{sv}})",
2114 /* dBUS gives error cause */
2115 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2116 error->code, error->message);
2117 g_clear_error(&error);
2120 *desc_path = g_strdup(path);
2124 g_strfreev(line_argv);
2125 g_variant_builder_unref(inner_builder);
2126 g_variant_builder_unref(builder);
2127 g_variant_builder_unref(builder2);
2129 return BLUETOOTH_ERROR_NONE;
2132 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2133 const char *desc_path, const char *desc_value,
2136 GError *error = NULL;
2137 GVariantBuilder *builder = NULL;
2138 GVariantBuilder *inner_builder = NULL;
2139 GVariantBuilder *builder1 = NULL;
2140 struct gatt_desc_info *desc_info = NULL;
2141 gchar **line_argv = NULL;
2143 GVariant *desc_val = NULL;
2144 char *serv_path = NULL;
2147 line_argv = g_strsplit_set(desc_path, "/", 0);
2148 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2149 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2151 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2153 /* Free the allocated memory */
2154 g_strfreev(line_argv);
2158 /* Fix : NULL_RETURNS */
2159 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2161 desc_info->desc_value = (char *)malloc(value_length);
2163 /* Fix : NULL_RETURNS */
2164 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2166 for (i = 0; i < value_length; i++)
2167 desc_info->desc_value[i] = desc_value[i];
2169 desc_info->value_length = value_length;
2171 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2172 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2174 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2176 for (i = 0; i < value_length; i++)
2177 g_variant_builder_add(builder1, "y", desc_value[i]);
2179 desc_val = g_variant_new("ay", builder1);
2180 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2182 g_variant_builder_add(builder, "{sa{sv}}",
2183 GATT_DESC_INTERFACE,
2186 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2187 "org.freedesktop.Dbus.ObjectManager",
2189 g_variant_new("(oa{sa{sv}})",
2190 desc_info->desc_path, builder),
2193 if (error != NULL) {
2194 BT_ERR("D-Bus API failure: errCode[%x], \
2196 error->code, error->message);
2197 g_clear_error(&error);
2200 g_variant_builder_unref(inner_builder);
2201 g_variant_builder_unref(builder);
2202 g_variant_builder_unref(builder1);
2204 return BLUETOOTH_ERROR_NONE;
2207 int bluetooth_gatt_get_service(const char *svc_uuid)
2209 GDBusProxy *proxy = NULL;
2212 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2213 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2215 return BLUETOOTH_ERROR_INTERNAL;
2217 uuid = g_strdup(svc_uuid);
2219 g_dbus_proxy_call(proxy,
2221 g_variant_new("(s)",
2223 G_DBUS_CALL_FLAGS_NONE, -1,
2225 (GAsyncReadyCallback) get_service_cb,
2230 return BLUETOOTH_ERROR_NONE;
2233 BT_EXPORT_API int bluetooth_gatt_register_service(const char *svc_path)
2235 struct gatt_service_info *svc_info = NULL;
2237 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2238 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2239 BT_ERR("Don't have aprivilege to use this API");
2240 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2243 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2244 if (svc_info == NULL) {
2245 BT_ERR("Cannot find service [%s]", svc_path);
2246 return BLUETOOTH_ERROR_INTERNAL;
2248 svc_info->is_svc_registered = TRUE;
2250 return BLUETOOTH_ERROR_NONE;
2253 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2255 GDBusProxy *proxy = NULL;
2257 if (!is_server_started) {
2258 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2259 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2260 BT_ERR("Don't have aprivilege to use this API");
2261 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2264 if (g_slist_length(gatt_services) == 0) {
2265 BT_ERR("There is no registered service");
2266 return BLUETOOTH_ERROR_INTERNAL;
2269 if (app_path == NULL) {
2270 BT_ERR("app_path is NULL");
2271 return BLUETOOTH_ERROR_INTERNAL;
2274 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2275 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2276 if (proxy == NULL) {
2277 BT_ERR("proxy is NULL");
2278 return BLUETOOTH_ERROR_INTERNAL;
2281 BT_INFO("RegisterApplication");
2283 if (register_cancel) {
2284 g_cancellable_cancel(register_cancel);
2285 g_object_unref(register_cancel);
2287 register_cancel = g_cancellable_new();
2289 g_dbus_proxy_call(proxy, "RegisterApplication",
2290 g_variant_new("(oa{sv})", app_path, NULL),
2291 G_DBUS_CALL_FLAGS_NONE, -1, register_cancel,
2292 (GAsyncReadyCallback)register_application_cb, NULL);
2294 is_server_started = true;
2296 return BLUETOOTH_ERROR_NONE;
2299 BT_INFO("Already RegisterApplication");
2301 return BLUETOOTH_ERROR_NONE;
2304 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2307 int ret = BLUETOOTH_ERROR_NONE;
2309 if (gatt_services == NULL) {
2310 BT_DBG("There are no registered services");
2315 for (l = gatt_services; l != NULL; ) {
2316 struct gatt_service_info *info = l->data;
2318 // In __bt_gatt_unregister_service, current node will be removed.
2319 // Go forward to next node before calling __bt_gatt_unregister_service.
2321 if (__bt_gatt_unregister_service(info) != BLUETOOTH_ERROR_NONE) {
2322 ret = BLUETOOTH_ERROR_INTERNAL;
2325 BT_INFO("All services are removed : %d", ret);
2327 g_slist_free(gatt_services);
2328 gatt_services = NULL;
2334 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2335 const char *char_path, const char* char_value,
2338 GVariantBuilder *outer_builder;
2339 GVariantBuilder *inner_builder;
2340 GVariantBuilder *invalidated_builder;
2341 GVariant *update_value = NULL;
2342 GError *error = NULL;
2343 gboolean ret = FALSE;
2344 int err = BLUETOOTH_ERROR_NONE;
2346 gchar **line_argv = NULL;
2347 gchar *serv_path = NULL;
2348 const char *value = NULL;
2350 line_argv = g_strsplit_set(char_path, "/", 0);
2351 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2353 if (!__bt_gatt_is_service_registered(serv_path)) {
2354 BT_DBG("service not registered for this characteristic");
2356 g_strfreev(line_argv);
2357 return BLUETOOTH_ERROR_INTERNAL;
2360 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2361 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2363 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2364 for (i = 0; i < value_length; i++)
2365 g_variant_builder_add(inner_builder, "y", char_value[i]);
2367 update_value = g_variant_new("ay", inner_builder);
2369 g_variant_builder_add(outer_builder, "{sv}", "Value",
2372 BT_DBG("Updating characteristic value");
2373 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2375 "org.freedesktop.DBus.Properties",
2376 "PropertiesChanged",
2377 g_variant_new("(sa{sv}as)",
2378 "org.bluez.GattCharacteristic1",
2379 outer_builder, invalidated_builder),
2383 if (error != NULL) {
2384 BT_ERR("D-Bus API failure: errCode[%x], \
2386 error->code, error->message);
2387 g_clear_error(&error);
2389 err = BLUETOOTH_ERROR_INTERNAL;
2391 struct gatt_char_info *char_info = NULL;
2393 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2394 if (char_info == NULL) {
2396 g_strfreev(line_argv);
2397 g_variant_builder_unref(inner_builder);
2398 g_variant_builder_unref(outer_builder);
2399 g_variant_builder_unref(invalidated_builder);
2401 return BLUETOOTH_ERROR_INVALID_DATA;
2404 char_info->value_length = value_length;
2406 value = (char *)realloc(char_info->char_value, value_length);
2407 if (value == NULL) {
2409 g_strfreev(line_argv);
2410 g_variant_builder_unref(inner_builder);
2411 g_variant_builder_unref(outer_builder);
2412 g_variant_builder_unref(invalidated_builder);
2414 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2417 char_info->char_value = (char*)value;
2418 if (char_info->char_value) {
2419 for (i = 0; i < value_length; i++)
2420 char_info->char_value[i] = char_value[i];
2425 g_strfreev(line_argv);
2426 g_variant_builder_unref(inner_builder);
2427 g_variant_builder_unref(outer_builder);
2428 g_variant_builder_unref(invalidated_builder);
2433 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2440 g_free(desc_info->desc_path);
2441 g_free(desc_info->desc_uuid);
2442 g_free(desc_info->desc_value);
2444 for (i = 0; i < desc_info->flags_length; i++)
2445 g_free(desc_info->desc_flags[i]);
2450 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2457 g_free(char_info->char_path);
2458 g_free(char_info->char_uuid);
2459 g_free(char_info->char_value);
2461 for (i = 0; i < char_info->flags_length; i++)
2462 g_free(char_info->char_flags[i]);
2467 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2472 g_free(svc_info->serv_path);
2473 g_free(svc_info->service_uuid);
2477 static void __desc_info_free(gpointer data, gpointer user_data)
2479 struct gatt_desc_info *desc_info = data;
2480 int *err = user_data;
2483 if (desc_info == NULL)
2486 ret = g_dbus_connection_unregister_object(g_conn, desc_info->desc_id);
2488 __bt_gatt_emit_interface_removed(desc_info->desc_path, GATT_DESC_INTERFACE);
2490 *err = BLUETOOTH_ERROR_INTERNAL;
2492 __bt_gatt_free_descriptor_info(desc_info);
2495 static void __char_info_free(gpointer data, gpointer user_data)
2497 struct gatt_char_info *char_info = data;
2498 int *err = user_data;
2501 if (char_info == NULL)
2504 g_slist_foreach(char_info->desc_data, __desc_info_free, user_data);
2505 g_slist_free(char_info->desc_data);
2506 char_info->desc_data = NULL;
2508 ret = g_dbus_connection_unregister_object(g_conn, char_info->char_id);
2510 __bt_gatt_emit_interface_removed(char_info->char_path, GATT_CHAR_INTERFACE);
2512 *err = BLUETOOTH_ERROR_INTERNAL;
2514 __bt_gatt_free_characteristic_info(char_info);
2517 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info)
2519 int ret = BLUETOOTH_ERROR_NONE;
2521 if (svc_info == NULL) {
2522 BT_ERR("svc_info is NULL");
2523 return BLUETOOTH_ERROR_NOT_FOUND;
2526 if (svc_info->is_svc_registered == FALSE) {
2527 BT_ERR("%s is not registered", svc_info->serv_path);
2528 return BLUETOOTH_ERROR_NOT_FOUND;
2531 BT_DBG("svc_path %s", svc_info->serv_path);
2533 g_slist_foreach(svc_info->char_data, __char_info_free, &ret);
2534 g_slist_free(svc_info->char_data);
2535 svc_info->char_data = NULL;
2537 if (g_dbus_connection_unregister_object(g_conn, svc_info->serv_id) == FALSE) {
2538 BT_ERR("Cannot unregister object for [%s]", svc_info->serv_path);
2539 ret = BLUETOOTH_ERROR_INTERNAL;
2541 __bt_gatt_emit_interface_removed(svc_info->serv_path, GATT_SERV_INTERFACE);
2544 gatt_services = g_slist_remove(gatt_services, svc_info);
2545 __bt_gatt_free_service_info(svc_info);
2547 new_service = FALSE;
2549 if (gatt_services == NULL) {
2551 } else if (gatt_services->next == NULL) {
2558 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2560 struct gatt_service_info *svc_info;
2561 int ret = BLUETOOTH_ERROR_NONE;
2565 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2567 ret = __bt_gatt_unregister_service(svc_info);
2568 if (ret != BLUETOOTH_ERROR_NONE) {
2569 BT_ERR("Could not unregister service [%s]", svc_path);
2576 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2577 int resp_state, int offset, char *value, int value_length)
2579 struct gatt_req_info *req_info = NULL;
2581 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2582 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2583 BT_ERR("Don't have aprivilege to use this API");
2584 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2587 req_info = __bt_gatt_find_request_info(request_id);
2588 if (req_info == NULL) {
2589 BT_ERR("Coundn't find request id [%d]", request_id);
2590 return BLUETOOTH_ERROR_INTERNAL;
2593 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2594 BT_ERR("resp_state is 0x%X", resp_state);
2595 char err_msg[20] = { 0, };
2596 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2597 g_dbus_method_invocation_return_dbus_error(req_info->context,
2598 "org.bluez.Error.Failed", err_msg);
2600 gatt_requests = g_slist_remove(gatt_requests, req_info);
2602 req_info->context = NULL;
2603 if (req_info->attr_path)
2604 g_free(req_info->attr_path);
2605 if (req_info->svc_path)
2606 g_free(req_info->svc_path);
2609 return BLUETOOTH_ERROR_NONE;
2612 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2614 GVariantBuilder *inner_builder = NULL;
2615 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2616 if (value_length > 0 && value != NULL) {
2617 for (i = 0; i < value_length; i++)
2618 g_variant_builder_add(inner_builder, "y", value[i]);
2620 g_dbus_method_invocation_return_value(req_info->context,
2621 g_variant_new("(ay)", inner_builder));
2622 g_variant_builder_unref(inner_builder);
2624 g_dbus_method_invocation_return_value(req_info->context, NULL);
2626 gatt_requests = g_slist_remove(gatt_requests, req_info);
2628 req_info->context = NULL;
2629 if (req_info->attr_path)
2630 g_free(req_info->attr_path);
2631 if (req_info->svc_path)
2632 g_free(req_info->svc_path);
2635 return BLUETOOTH_ERROR_NONE;
2638 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2639 bluetooth_device_address_t *unicast_address)
2641 GVariantBuilder *outer_builder;
2642 GVariantBuilder *invalidated_builder;
2643 GError *error = NULL;
2644 gboolean notify = TRUE;
2645 gboolean ret = TRUE;
2646 int err = BLUETOOTH_ERROR_NONE;
2647 gchar **line_argv = NULL;
2648 gchar *serv_path = NULL;
2649 char addr[20] = { 0 };
2651 line_argv = g_strsplit_set(char_path, "/", 0);
2652 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2654 if (!__bt_gatt_is_service_registered(serv_path)) {
2655 BT_DBG("service not registered for this characteristic");
2657 g_strfreev(line_argv);
2658 return BLUETOOTH_ERROR_INTERNAL;
2663 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2664 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2666 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2667 g_variant_new("b", notify));
2669 if (unicast_address) {
2670 _bt_convert_addr_type_to_string(addr,
2671 (unsigned char *)unicast_address->addr);
2673 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2674 g_variant_new("s", addr));
2676 BT_DBG("Set characteristic Notification");
2677 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2679 "org.freedesktop.DBus.Properties",
2680 "PropertiesChanged",
2681 g_variant_new("(sa{sv}as)",
2682 "org.bluez.GattCharacteristic1",
2683 outer_builder, invalidated_builder),
2687 if (error != NULL) {
2688 BT_ERR("D-Bus API failure: errCode[%x], \
2690 error->code, error->message);
2691 g_clear_error(&error);
2693 err = BLUETOOTH_ERROR_INTERNAL;
2696 g_strfreev(line_argv);
2697 g_variant_builder_unref(outer_builder);
2698 g_variant_builder_unref(invalidated_builder);
2705 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2709 if (!is_server_started) {
2711 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2712 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2713 BT_ERR("Don't have aprivilege to use this API");
2714 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2717 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2718 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2720 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2721 in_param1, in_param2, in_param3, in_param4, &out_param);
2722 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2724 if (ret != BLUETOOTH_ERROR_NONE) {
2725 BT_ERR("Register application failed");
2728 is_server_started = true;
2730 return BLUETOOTH_ERROR_NONE;
2733 BT_INFO("Already RegisterApplication");
2734 return BLUETOOTH_ERROR_NONE;
2738 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2741 int ret = BLUETOOTH_ERROR_NONE;
2744 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2746 /* Register event handler for GATT */
2747 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2749 if (ret != BLUETOOTH_ERROR_NONE &&
2750 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2751 BT_ERR("Fail to init the event handler");
2752 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2756 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2757 in_param1, in_param2, in_param3, in_param4, &out_param);
2759 /* App ID -1 is invalid */
2760 if (ret != BLUETOOTH_ERROR_NONE) {
2761 BT_INFO("GATT Server Registration failed result [%d]", ret);
2764 *instance_id = g_array_index(out_param, int, 0);
2765 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2769 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2771 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2775 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2778 BT_INFO("GATT Server Deinitialize");
2779 /* Unregister the event */
2780 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2782 if (ret != BLUETOOTH_ERROR_NONE) {
2783 BT_ERR("Fail to deinit the event handler");
2787 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2792 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2793 int instance_id, int *service_handle)
2795 BT_CHECK_ENABLED(return);
2796 BT_CHECK_PARAMETER(svc_uuid, return);
2799 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2801 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2804 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2806 g_array_append_vals(in_param1, &type, sizeof(int));
2807 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2808 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2809 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2811 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2812 in_param1, in_param2, in_param3, in_param4, &out_param);
2814 /* ATT handle 0 is reserved, hence it can not be used by app.
2815 It will be used to indicate error in regsitering attribute */
2816 if (result != BLUETOOTH_ERROR_NONE)
2817 *service_handle = 0;
2819 *service_handle = g_array_index(out_param, int, 0);
2821 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2826 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2827 const bluetooth_gatt_server_attribute_params_t *param,
2830 BT_CHECK_ENABLED(return);
2831 BT_CHECK_PARAMETER(char_uuid, return);
2832 BT_CHECK_PARAMETER(param, return);
2835 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2837 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2840 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2842 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2843 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2845 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2846 in_param1, in_param2, in_param3, in_param4, &out_param);
2848 /* ATT handle 0 is reserved, hence it can not be used by app.
2849 It will be used to indicate error in regsitering attribute */
2850 if (result != BLUETOOTH_ERROR_NONE) {
2851 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2854 *char_handle = g_array_index(out_param, int, 0);
2855 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2858 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2862 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2863 int service_handle, int instance_id, int *descriptor_handle)
2865 BT_CHECK_ENABLED(return);
2866 BT_CHECK_PARAMETER(desc_uuid, return);
2869 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2871 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2874 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2876 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2877 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2878 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2879 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2881 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2882 in_param1, in_param2, in_param3, in_param4, &out_param);
2884 /* ATT handle 0 is reserved, hence it can not be used by app.
2885 It will be used to indicate error in regsitering attribute */
2886 if (result != BLUETOOTH_ERROR_NONE) {
2887 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2888 *descriptor_handle = 0;
2890 *descriptor_handle = g_array_index(out_param, int, 0);
2891 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2894 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2899 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2901 BT_CHECK_ENABLED(return);
2905 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2907 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2908 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2910 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2911 in_param1, in_param2, in_param3, in_param4, &out_param);
2913 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2918 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2919 const bluetooth_gatt_att_data_t *value)
2921 BT_CHECK_PARAMETER(param, return);
2922 BT_CHECK_PARAMETER(value, return);
2923 BT_CHECK_ENABLED(return);
2927 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2929 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
2930 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
2932 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
2933 in_param1, in_param2, in_param3, in_param4, &out_param);
2935 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2941 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
2942 bluetooth_gatt_server_indication_params_t *param,
2943 const bluetooth_gatt_att_data_t *att_value)
2945 BT_CHECK_PARAMETER(param, return);
2946 BT_CHECK_PARAMETER(att_value, return);
2947 BT_CHECK_ENABLED(return);
2949 char addr[BLUETOOTH_ADDRESS_STRING_LENGTH] ;
2953 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2955 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
2956 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
2957 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
2959 _bt_convert_addr_type_to_string(addr, addr_hex->addr);
2960 fd = bluetooth_get_characteristic_fd(param->atrribute_handle, addr);
2963 result = bluetooth_gatt_write_characteristics_value_to_fd_(fd, att_value->data, att_value->length, NULL);
2966 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
2967 in_param1, in_param2, in_param3, in_param4, &out_param);
2970 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2975 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
2977 BT_CHECK_ENABLED(return);
2981 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2983 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2984 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2986 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
2987 in_param1, in_param2, in_param3, in_param4, &out_param);
2989 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2994 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
2996 BT_CHECK_ENABLED(return);
3000 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3002 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3003 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3005 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
3006 in_param1, in_param2, in_param3, in_param4, &out_param);
3008 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3013 /* Tizen Platform Specific */
3014 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
3015 const bluetooth_gatt_server_update_value_t *value)
3017 BT_CHECK_ENABLED(return);
3018 BT_CHECK_PARAMETER(value, return);
3022 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3024 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3025 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3027 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3028 in_param1, in_param2, in_param3, in_param4, &out_param);
3030 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3035 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3037 BT_CHECK_ENABLED(return);
3041 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3043 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3045 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3046 in_param1, in_param2, in_param3, in_param4, &out_param);
3048 if (result != BLUETOOTH_ERROR_NONE)
3049 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3051 BT_INFO("GATT Server Unregistration successful");
3053 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3058 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3059 GIOCondition cond, gpointer data)
3062 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3064 BT_DBG("FD io write data received [%s]", write_data->address);
3066 if (cond & G_IO_NVAL) {
3067 BT_ERR("Invalid channel");
3071 if (cond & (G_IO_HUP | G_IO_ERR)) {
3072 BT_ERR("Error : GIOCondition %d", cond);
3073 g_io_channel_shutdown(gio, TRUE, NULL);
3074 g_io_channel_unref(gio);
3079 if (cond & G_IO_IN) {
3080 GIOStatus status = G_IO_STATUS_NORMAL;
3082 char *buffer = NULL;
3084 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3086 buffer = g_malloc0(BUF);
3088 status = g_io_channel_read_chars(gio, buffer,
3091 if (status != G_IO_STATUS_NORMAL) {
3092 BT_ERR("IO Channel read is failed with %d", status);
3095 BT_ERR("IO Channel read error [%s]", err->message);
3096 if (status == G_IO_STATUS_ERROR) {
3097 BT_ERR("cond : %d", cond);
3099 g_io_channel_shutdown(gio, TRUE, NULL);
3100 g_io_channel_unref(gio);
3110 bluetooth_gatt_server_write_requested_info_t write_info;
3111 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3112 memcpy(write_info.data.data, buffer, len);
3114 write_info.length = len;
3115 write_info.need_resp = false;
3116 write_info.attribute_handle = write_data->attribute_handle;
3118 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->address);
3119 write_info.connection_id = write_data->connection_id;
3120 write_info.offset = write_data->offset;
3121 write_info.request_id = -2;
3123 bt_event_info_t *event_info;
3124 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3128 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3129 BLUETOOTH_ERROR_NONE, &write_info,
3130 event_info->cb, event_info->user_data);
3132 BT_ERR("eventinfo failed");
3142 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
3143 BT_ERR("Error : GIOCondition %d, ]", cond);
3144 g_io_channel_shutdown(gio, TRUE, NULL);
3145 g_io_channel_unref(gio);
3153 void bluetooth_gatt_server_send_acquire_write_response(GVariant * parameters)
3158 int pipefd[2] = {-1,};
3161 char err_msg[512] = {'\0'};
3162 GIOChannel *channel = NULL;
3166 g_variant_get(parameters, "(iiiiii&s)",
3175 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3176 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3177 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3178 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3181 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3182 strerror_r(errno, err_msg, sizeof(err_msg));
3183 BT_ERR("socketpair(): %s", err_msg);
3188 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3190 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3191 bluetooth_gatt_server_acquire_response_params_t data;
3192 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
3193 data.fd = pipefd[1];
3195 data.request_id = tran_id;
3197 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3199 write_info->attribute_handle = att_han;
3200 write_info->connection_id = tran_id;
3201 write_info->offset = offset;
3203 memcpy(write_info->address, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3205 BT_INFO("FD read %d remote address [%s ] \n", pipefd[0], addr);
3208 channel = g_io_channel_unix_new(pipefd[0]);
3209 g_io_channel_set_encoding(channel, NULL, NULL);
3210 g_io_channel_set_buffered(channel, FALSE);
3211 g_io_channel_set_close_on_unref(channel, TRUE);
3212 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3213 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3214 bluetooth_gatt_server_acquire_channel_write_cb, write_info);
3217 GUnixFDList *fd_list = g_unix_fd_list_new();
3218 GError *error = NULL;
3220 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3221 g_assert_no_error(error);
3224 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3226 BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3228 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE,
3229 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3231 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3237 void bluetooth_gatt_server_send_acquire_notify_response(GVariant * parameters, bt_event_info_t *event_info)
3242 int pipefd[2] = {-1,};
3245 char err_msg[512] = {'\0'};
3246 GIOChannel *channel = NULL;
3249 bluetooth_gatt_acquire_notify_info_t *chr_info;
3250 const char *address = NULL;
3252 g_variant_get(parameters, "(iiiiii&s)",
3261 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3262 BT_DBG("GATT Server Acquire notify att handle:[%d]", att_han);
3263 BT_DBG("GATT Server Acquire Notify Offset: [%d]", offset);
3264 BT_DBG("GATT Server Acquire Notify address: [%s]", address);
3267 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3268 strerror_r(errno, err_msg, sizeof(err_msg));
3269 BT_ERR("socketpair(): %s", err_msg);
3276 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3278 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3279 bluetooth_gatt_server_acquire_response_params_t data;
3280 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
3281 data.fd = pipefd[1];
3283 data.request_id = tran_id;
3285 BT_INFO("FD write %d characterstics path \n", pipefd[0]);
3287 chr_info = bluetooth_get_characteristic_info_from_path(att_han);
3289 chr_info = g_malloc0(sizeof(bluetooth_gatt_acquire_notify_info_t));
3290 chr_info->write_fd = fd;
3291 chr_info->att_hand = att_han;
3293 gatt_characteristic_server_notify_list = g_slist_append(gatt_characteristic_server_notify_list, chr_info);
3295 chr_info->write_fd = fd;
3297 channel = g_io_channel_unix_new(fd);
3298 g_io_channel_set_encoding(channel, NULL, NULL);
3299 g_io_channel_set_buffered(channel, FALSE);
3300 g_io_channel_set_close_on_unref(channel, TRUE);
3301 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3302 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
3303 bluetooth_gatt_write_channel_watch_cb, chr_info);
3305 GUnixFDList *fd_list = g_unix_fd_list_new();
3306 GError *error = NULL;
3308 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3309 g_assert_no_error(error);
3312 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3314 BT_DBG("Sending event BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE file descriptor value [%d] ", data.fd);
3316 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE,
3317 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3319 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3323 if (result == BLUETOOTH_ERROR_NONE) {
3324 BT_DBG("sending gatt server notification state changed event");
3325 bluetooth_gatt_server_notification_changed_t info;
3326 bluetooth_device_address_t dev_address = { {0} };
3327 memset(&info, 0x00, sizeof(bluetooth_gatt_server_notification_changed_t));
3329 _bt_convert_addr_string_to_type(dev_address.addr, address);
3330 memcpy(info.device_address.addr,
3332 BLUETOOTH_ADDRESS_LENGTH);
3333 info.handle = att_han;
3334 info.notification = TRUE;
3336 _bt_gatt_server_event_cb(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
3338 event_info->cb, event_info->user_data);
3343 void cleanup_gatt_acquire_fd(int handle)
3345 bluetooth_gatt_acquire_notify_info_t *chr_info = NULL;
3349 chr_info = bluetooth_get_characteristic_info_from_path(handle);
3351 if (chr_info != NULL) {
3352 BT_INFO("GATT Server: acquire notification char info found");
3354 if (chr_info->write_fd >= 0) {
3355 BT_INFO("closing fd");
3356 close(chr_info->write_fd);
3359 BT_INFO("Removing char_info from the list");
3360 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
3361 bluetooth_characteristic_info_free(chr_info);