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);
346 static int bluetooth_get_characteristic_fd(int att_handle , char *address)
351 BT_DBG("Find FD for address [%s] att_handle [ %d]", address, att_handle);
353 /* Check for NULL address */
354 if (g_strcmp0(address, "00:00:00:00:00:00") != 0) {
355 BT_INFO("Unicast address: Use DBUS send indication");
359 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
360 bluetooth_gatt_acquire_notify_info_t *info = l->data;
362 if (info->att_hand == att_handle) {
363 BT_INFO("ATT handle Matched: AquireNotify Set: Remote addr[%s]", info->address);
364 return info->write_fd;
370 static bluetooth_gatt_acquire_notify_info_t * bluetooth_get_characteristic_info_from_path(int att_handle)
374 BT_DBG("request found att_handle [ %d]", att_handle);
375 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
376 bluetooth_gatt_acquire_notify_info_t *info = l->data;
377 BT_DBG(" sid [ %d]" , info->att_hand);
378 if (info->att_hand == att_handle)
385 static void bluetooth_characteristic_info_free(bluetooth_gatt_acquire_notify_info_t *chr_info)
390 static gboolean bluetooth_gatt_write_channel_watch_cb(GIOChannel *gio,
391 GIOCondition cond, gpointer data)
393 bluetooth_gatt_acquire_notify_info_t *chr_info = (bluetooth_gatt_acquire_notify_info_t *)data;
396 BT_INFO("chr_info is NULL");
400 if (cond & G_IO_NVAL) {
401 BT_ERR("Invalid channel");
405 if (cond & (G_IO_HUP | G_IO_ERR)) {
406 BT_ERR("Error : GIOCondition %d", cond);
407 g_io_channel_shutdown(gio, TRUE, NULL);
408 g_io_channel_unref(gio);
410 if (g_slist_find(gatt_characteristic_server_notify_list, chr_info)) {
411 BT_INFO("found char_info in the list");
412 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
413 bluetooth_characteristic_info_free(chr_info);
419 if (g_slist_find(gatt_characteristic_server_notify_list, chr_info) == NULL) {
420 BT_INFO("chr_info is not in the list");
427 static int bluetooth_gatt_write_characteristics_value_to_fd_(
428 int fd, const guint8 *value, int length,
433 int att_result = BLUETOOTH_ERROR_NONE;
435 BT_CHECK_PARAMETER(value, return);
437 written = write(fd, value, length);
438 if (written != length) {
439 att_result = BLUETOOTH_ERROR_INTERNAL;
440 BT_ERR("write data failed %d is ", written);
446 #ifdef TIZEN_FEATURE_BT_HPS
447 static int __bt_send_event_to_hps(int event, GVariant *var)
449 GError *error = NULL;
450 GVariant *parameters;
451 GDBusMessage *msg = NULL;
455 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
457 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
458 GVariantBuilder *inner_builder;
459 GVariantBuilder *invalidated_builder;
461 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
462 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
464 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
466 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
468 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
469 g_variant_builder_unref(invalidated_builder);
470 g_variant_builder_unref(inner_builder);
471 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
472 GVariantBuilder *inner_builder;
473 GVariantBuilder *invalidated_builder;
475 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
476 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
478 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
480 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
482 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
483 g_variant_builder_unref(invalidated_builder);
484 g_variant_builder_unref(inner_builder);
486 g_varaiant_unref(var);
489 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
490 g_dbus_message_set_body(msg, parameters);
491 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
493 BT_ERR("D-Bus API failure: errCode[%x], \
495 error->code, error->message);
496 g_clear_error(&error);
498 return BLUETOOTH_ERROR_INTERNAL;
500 return BLUETOOTH_ERROR_NONE;
504 #ifdef TIZEN_FEATURE_BT_OTP
505 static int __bt_send_event_to_otp(int event, GVariant *var)
507 GError *error = NULL;
508 GVariant *parameters = NULL;
509 GDBusMessage *msg = NULL;
513 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
515 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
516 GVariantBuilder *inner_builder;
517 GVariantBuilder *invalidated_builder;
519 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
520 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
522 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
524 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
526 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
527 g_variant_builder_unref(invalidated_builder);
528 g_variant_builder_unref(inner_builder);
529 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
530 GVariantBuilder *inner_builder;
531 GVariantBuilder *invalidated_builder;
533 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
534 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
536 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
538 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
540 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
541 g_variant_builder_unref(invalidated_builder);
542 g_variant_builder_unref(inner_builder);
543 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
544 GVariantBuilder *inner_builder;
545 GVariantBuilder *invalidated_builder;
547 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
548 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
550 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
552 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
554 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
555 g_variant_builder_unref(invalidated_builder);
556 g_variant_builder_unref(inner_builder);
559 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
560 g_dbus_message_set_body(msg, parameters);
561 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
563 BT_ERR("D-Bus API failure: errCode[%x], \
565 error->code, error->message);
566 g_clear_error(&error);
568 return BLUETOOTH_ERROR_INTERNAL;
570 return BLUETOOTH_ERROR_NONE;
574 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
576 const gchar *object_path,
577 const gchar *interface_name,
578 const gchar *method_name,
579 GVariant *parameters,
580 GDBusMethodInvocation *invocation,
583 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
584 BT_DBG("Getting values for service, chars and descriptors");
587 GVariantBuilder *builder = NULL;
588 GVariantBuilder *inner_builder1 = NULL;
589 GVariant *svc_char = NULL;
590 GSList *char_list = NULL;
591 GSList *desc_list = NULL;
594 builder = g_variant_builder_new(G_VARIANT_TYPE("a{oa{sa{sv}}}"));
596 /* Prepare inner builder for GattService1 interface */
597 svc_index = g_slist_length(gatt_services) - 1;
598 for (; svc_index >= 0; svc_index--) {
599 GVariantBuilder *svc_builder = NULL;
600 GVariantBuilder *inner_builder = NULL;
601 struct gatt_service_info *serv_info = NULL;
603 serv_info = g_slist_nth_data(gatt_services, svc_index);
604 if (serv_info == NULL) {
605 BT_ERR("serv_info is NULL");
609 /* Prepare inner builder for GattService1 interface */
610 BT_DBG("Creating builder for service : %s", serv_info->service_uuid);
611 svc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
612 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
614 g_variant_builder_add(inner_builder, "{sv}", "UUID",
615 g_variant_new_string(serv_info->service_uuid));
616 g_variant_builder_add(inner_builder, "{sv}", "Primary",
617 g_variant_new_boolean(serv_info->is_svc_primary));
619 /* Characteristics */
620 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
622 BT_DBG("Adding Charatarisitcs list");
623 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
624 struct gatt_char_info *char_info = char_list->data;
625 g_variant_builder_add(inner_builder1, "o", char_info->char_path);
626 BT_DBG("%s", char_info->char_path);
629 svc_char = g_variant_new("ao", inner_builder1);
630 g_variant_builder_add(inner_builder, "{sv}", "Characteristics", svc_char);
631 g_variant_builder_add(svc_builder, "{sa{sv}}", GATT_SERV_INTERFACE, inner_builder);
632 g_variant_builder_add(builder, "{oa{sa{sv}}}", serv_info->serv_path, svc_builder);
633 g_variant_builder_unref(inner_builder1);
635 /* Prepare inner builder for GattCharacteristic1 interface */
636 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
637 GVariantBuilder *char_builder = NULL;
638 GVariantBuilder *inner_builder = NULL;
639 GVariantBuilder *builder1 = NULL;
640 GVariantBuilder *builder2 = NULL;
641 GVariantBuilder *builder3 = NULL;
642 GVariant *char_val = NULL;
643 GVariant *flags_val = NULL;
644 GVariant *char_desc = NULL;
645 char *unicast = NULL;
646 gboolean notify = FALSE;
648 struct gatt_char_info *char_info = char_list->data;
650 if (char_info == NULL) {
651 BT_ERR("char_info is NULL");
655 BT_DBG("Creating builder for characteristic : %s", char_info->char_uuid);
656 char_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
657 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
660 g_variant_builder_add(inner_builder, "{sv}", "UUID",
661 g_variant_new_string(char_info->char_uuid));
664 g_variant_builder_add(inner_builder, "{sv}", "Service",
665 g_variant_new("o", serv_info->serv_path));
668 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
669 if (char_info->char_value != NULL) {
670 for (i = 0; i < char_info->value_length; i++) {
671 g_variant_builder_add(builder1, "y", char_info->char_value[i]);
673 char_val = g_variant_new("ay", builder1);
674 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
678 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
679 for (i = 0; i < char_info->flags_length; i++) {
680 g_variant_builder_add(builder2, "s", char_info->char_flags[i]);
682 flags_val = g_variant_new("as", builder2);
683 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
686 g_variant_builder_add(inner_builder, "{sv}", "Notifying", g_variant_new("b", notify));
689 unicast = g_strdup("00:00:00:00:00:00");
690 g_variant_builder_add(inner_builder, "{sv}", "Unicast", g_variant_new("s", unicast));
693 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
694 BT_DBG("Adding Descriptors list");
695 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
696 struct gatt_desc_info *desc_info = desc_list->data;
697 g_variant_builder_add(builder3, "o", desc_info->desc_path);
698 BT_DBG("%s", desc_info->desc_path);
701 char_desc = g_variant_new("ao", builder3);
702 g_variant_builder_add(inner_builder, "{sv}", "Descriptors", char_desc);
703 g_variant_builder_add(char_builder, "{sa{sv}}", GATT_CHAR_INTERFACE , inner_builder);
704 g_variant_builder_add(builder, "{oa{sa{sv}}}", char_info->char_path, char_builder);
706 /*Prepare inner builder for GattDescriptor1 interface*/
707 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
708 GVariantBuilder *desc_builder = NULL;
709 GVariantBuilder *inner_builder = NULL;
710 GVariantBuilder *builder1 = NULL;
711 GVariantBuilder *builder2 = NULL;
712 GVariant *desc_val = NULL;
713 struct gatt_desc_info *desc_info = desc_list->data;
715 if (desc_info == NULL) {
716 BT_ERR("desc_info is NULL");
720 BT_DBG("Creating builder for descriptor : %s", desc_info->desc_uuid);
721 desc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
722 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
725 g_variant_builder_add(inner_builder, "{sv}", "UUID",
726 g_variant_new_string(desc_info->desc_uuid));
729 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
730 g_variant_new("o", char_info->char_path));
733 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
734 if (desc_info->desc_value != NULL) {
735 for (i = 0; i < desc_info->value_length; i++) {
736 g_variant_builder_add(builder1, "y", desc_info->desc_value[i]);
738 desc_val = g_variant_new("ay", builder1);
739 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
743 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
744 for (i = 0; i < desc_info->flags_length; i++) {
745 g_variant_builder_add(builder2, "s", desc_info->desc_flags[i]);
747 flags_val = g_variant_new("as", builder2);
748 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
750 g_variant_builder_add(desc_builder, "{sa{sv}}", GATT_DESC_INTERFACE,
752 g_variant_builder_add(builder, "{oa{sa{sv}}}", desc_info->desc_path,
755 /* unref descriptor builder pointers */
756 g_variant_builder_unref(builder1);
757 g_variant_builder_unref(builder2);
758 g_variant_builder_unref(inner_builder);
759 g_variant_builder_unref(desc_builder);
765 /* unref char builder pointers */
766 g_variant_builder_unref(builder1);
767 g_variant_builder_unref(builder2);
768 g_variant_builder_unref(builder3);
769 g_variant_builder_unref(inner_builder);
770 g_variant_builder_unref(char_builder);
773 /* unref service builder pointers */
774 g_variant_builder_unref(inner_builder);
775 g_variant_builder_unref(svc_builder);
778 /* Return builder as method reply */
779 BT_DBG("Sending gatt service builder values to Bluez");
780 g_dbus_method_invocation_return_value(invocation,
781 g_variant_new("(a{oa{sa{sv}}})", builder));
782 g_variant_builder_unref(builder);
786 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
790 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
791 struct gatt_service_info *serv_info = l1->data;
793 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
794 struct gatt_char_info *char_info = l2->data;
796 if (g_strcmp0(char_info->char_path, char_path) == 0)
800 BT_ERR("Gatt service not found");
804 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
806 GSList *l1, *l2, *l3;
808 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
809 struct gatt_service_info *serv_info = l1->data;
811 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
812 struct gatt_char_info *char_info = l2->data;
814 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
815 struct gatt_desc_info *desc_info = l3->data;
817 if (g_strcmp0(desc_info->desc_path, desc_path) == 0)
822 BT_ERR("Gatt service not found");
826 static void __bt_gatt_char_method_call(GDBusConnection *connection,
828 const gchar *object_path,
829 const gchar *interface_name,
830 const gchar *method_name,
831 GVariant *parameters,
832 GDBusMethodInvocation *invocation,
836 if (g_strcmp0(method_name, "ReadValue") == 0) {
840 bt_gatt_read_req_t read_req = {0, };
841 bt_user_info_t *user_info = NULL;
842 struct gatt_req_info *req_info = NULL;
843 struct gatt_service_info *svc_info = NULL;
844 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
845 GVariant *param = NULL;
848 BT_DBG("Application path = %s", object_path);
849 BT_DBG("Sender = %s", sender);
851 user_info = _bt_get_user_data(BT_COMMON);
852 if (user_info == NULL) {
853 BT_INFO("No callback is set for %s", object_path);
854 g_dbus_method_invocation_return_value(invocation, NULL);
858 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
859 if (svc_info == NULL) {
860 BT_ERR("Coudn't find service for %s", object_path);
861 g_dbus_method_invocation_return_value(invocation, NULL);
865 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
866 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
868 read_req.att_handle = (char *)object_path;
869 read_req.address = addr;
870 read_req.req_id = req_id;
871 read_req.offset = offset;
872 read_req.service_handle = svc_info->serv_path;
874 /* Store requets information */
875 req_info = g_new0(struct gatt_req_info, 1);
876 req_info->attr_path = g_strdup(object_path);
877 req_info->svc_path = g_strdup(read_req.service_handle);
878 req_info->request_id = req_id;
879 req_info->offset = offset;
880 req_info->context = invocation;
881 gatt_requests = g_slist_append(gatt_requests, req_info);
883 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
884 param = g_variant_new("(sssyq)",
886 read_req.service_handle,
890 #ifdef TIZEN_FEATURE_BT_HPS
891 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
893 #ifdef TIZEN_FEATURE_BT_OTP
894 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
898 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
899 BLUETOOTH_ERROR_NONE, &read_req,
900 user_info->cb, user_info->user_data);
902 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
903 GVariant *var = NULL;
907 gboolean response_needed = FALSE;
908 bt_gatt_value_change_t value_change = {0, };
909 bt_user_info_t *user_info = NULL;
911 struct gatt_service_info *svc_info = NULL;
912 struct gatt_req_info *req_info = NULL;
913 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
914 GVariant *param = NULL;
917 BT_DBG("WriteValue");
918 BT_DBG("Application path = %s", object_path);
919 BT_DBG("Sender = %s", sender);
921 g_variant_get(parameters, "(&suqb@ay)",
922 &addr, &req_id, &offset, &response_needed, &var);
923 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
925 user_info = _bt_get_user_data(BT_COMMON);
927 BT_INFO("No callback is set for %s", object_path);
928 g_variant_unref(var);
930 g_dbus_method_invocation_return_value(invocation, NULL);
932 g_object_unref(invocation);
936 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
937 if (svc_info == NULL) {
938 BT_ERR("Coudn't find service for %s", object_path);
939 g_variant_unref(var);
941 g_dbus_method_invocation_return_value(invocation, NULL);
943 g_object_unref(invocation);
947 value_change.att_handle = (char *)object_path;
948 value_change.address = addr;
949 value_change.service_handle = svc_info->serv_path;
950 value_change.offset = offset;
951 value_change.req_id = req_id;
952 value_change.response_needed = response_needed;
954 len = g_variant_get_size(var);
958 value_change.att_value = (guint8 *)g_malloc(len);
960 data = (char *)g_variant_get_data(var);
961 memcpy(value_change.att_value, data, len);
963 value_change.val_len = len;
965 if (response_needed) {
966 /* Store requets information */
967 req_info = g_new0(struct gatt_req_info, 1);
968 req_info->attr_path = g_strdup(object_path);
969 req_info->svc_path = g_strdup(value_change.service_handle);
970 req_info->request_id = req_id;
971 req_info->offset = offset;
972 req_info->context = invocation;
973 gatt_requests = g_slist_append(gatt_requests, req_info);
975 g_object_unref(invocation);
978 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
981 svc_path = g_strdup(svc_info->serv_path);
982 param = g_variant_new("(sssyq@ay)",
989 #ifdef TIZEN_FEATURE_BT_HPS
990 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
992 #ifdef TIZEN_FEATURE_BT_OTP
993 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1000 _bt_common_event_cb(
1001 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1002 BLUETOOTH_ERROR_NONE, &value_change,
1003 user_info->cb, user_info->user_data);
1005 g_free(value_change.att_value);
1006 g_variant_unref(var);
1008 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1009 bt_user_info_t *user_info = NULL;
1010 bt_gatt_char_notify_change_t notify_change = {0, };
1011 #if TIZEN_FEATURE_BT_OTP
1012 GVariant *param = NULL;
1014 BT_DBG("StartNotify");
1015 user_info = _bt_get_user_data(BT_COMMON);
1016 if (user_info != NULL) {
1017 struct gatt_service_info *svc_info = NULL;
1018 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1020 notify_change.service_handle = svc_info->serv_path;
1021 notify_change.att_handle = (char *)object_path;
1022 notify_change.att_notify = TRUE;
1023 #if TIZEN_FEATURE_BT_OTP
1024 param = g_variant_new("(ssb)",
1025 notify_change.att_handle,
1026 notify_change.service_handle,
1027 notify_change.att_notify);
1028 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1030 _bt_common_event_cb(
1031 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1032 BLUETOOTH_ERROR_NONE, ¬ify_change,
1033 user_info->cb, user_info->user_data);
1036 g_object_unref(invocation);
1038 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1039 bt_user_info_t *user_info = NULL;
1040 bt_gatt_char_notify_change_t notify_change = {0, };
1041 #if TIZEN_FEATURE_BT_OTP
1042 GVariant *param = NULL;
1044 BT_DBG("StopNotify");
1045 user_info = _bt_get_user_data(BT_COMMON);
1046 if (user_info != NULL) {
1047 struct gatt_service_info *svc_info = NULL;
1048 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1050 notify_change.service_handle = svc_info->serv_path;
1051 notify_change.att_handle = (char *)object_path;
1052 notify_change.att_notify = FALSE;
1053 #if TIZEN_FEATURE_BT_OTP
1054 param = g_variant_new("(ssb)",
1055 notify_change.att_handle,
1056 notify_change.service_handle,
1057 notify_change.att_notify);
1058 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1060 _bt_common_event_cb(
1061 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1062 BLUETOOTH_ERROR_NONE, ¬ify_change,
1063 user_info->cb, user_info->user_data);
1066 g_object_unref(invocation);
1068 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1070 bt_gatt_indicate_confirm_t confirm = {0, };
1071 bt_user_info_t *user_info = NULL;
1072 gboolean complete = FALSE;
1073 struct gatt_service_info *svc_info = NULL;
1075 BT_DBG("IndicateConfirm");
1076 BT_DBG("Application path = %s", object_path);
1077 BT_DBG("Sender = %s", sender);
1079 g_variant_get(parameters, "(&sb)", &addr, &complete);
1080 BT_DBG("Remote Device address number = %s", addr);
1082 confirm.att_handle = (char *)object_path;
1083 confirm.address = addr;
1084 confirm.complete = complete;
1086 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1087 if (svc_info != NULL) {
1088 confirm.service_handle = svc_info->serv_path;
1090 user_info = _bt_get_user_data(BT_COMMON);
1091 if (user_info != NULL) {
1092 _bt_common_event_cb(
1093 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1094 BLUETOOTH_ERROR_NONE, &confirm,
1095 user_info->cb, user_info->user_data);
1100 g_dbus_method_invocation_return_value(invocation, NULL);
1103 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1104 const gchar *sender,
1105 const gchar *object_path,
1106 const gchar *interface_name,
1107 const gchar *method_name,
1108 GVariant *parameters,
1109 GDBusMethodInvocation *invocation,
1112 if (g_strcmp0(method_name, "ReadValue") == 0) {
1116 bt_gatt_read_req_t read_req = {0, };
1117 bt_user_info_t *user_info = NULL;
1118 struct gatt_req_info *req_info = NULL;
1119 struct gatt_service_info *svc_info = NULL;
1121 BT_DBG("ReadValue");
1122 BT_DBG("Application path = %s", object_path);
1123 BT_DBG("Sender = %s", sender);
1125 user_info = _bt_get_user_data(BT_COMMON);
1126 if (user_info == NULL) {
1127 BT_INFO("No callback is set for %s", object_path);
1128 g_dbus_method_invocation_return_value(invocation, NULL);
1132 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1133 if (svc_info == NULL) {
1134 BT_ERR("Coudn't find service for %s", object_path);
1135 g_dbus_method_invocation_return_value(invocation, NULL);
1139 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1140 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1142 read_req.att_handle = (char *)object_path;
1143 read_req.address = addr;
1144 read_req.req_id = req_id;
1145 read_req.offset = offset;
1146 read_req.service_handle = svc_info->serv_path;
1148 /* Store requets information */
1149 req_info = g_new0(struct gatt_req_info, 1);
1150 req_info->attr_path = g_strdup(object_path);
1151 req_info->svc_path = g_strdup(read_req.service_handle);
1152 req_info->request_id = req_id;
1153 req_info->offset = offset;
1154 req_info->context = invocation;
1155 gatt_requests = g_slist_append(gatt_requests, req_info);
1157 _bt_common_event_cb(
1158 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1159 BLUETOOTH_ERROR_NONE, &read_req,
1160 user_info->cb, user_info->user_data);
1163 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1164 GVariant *var = NULL;
1168 gboolean response_needed = FALSE;
1169 bt_gatt_value_change_t value_change = {0, };
1170 bt_user_info_t *user_info = NULL;
1172 struct gatt_service_info *svc_info = NULL;
1173 struct gatt_req_info *req_info = NULL;
1175 BT_DBG("WriteValue");
1176 BT_DBG("Application path = %s", object_path);
1177 BT_DBG("Sender = %s", sender);
1179 g_variant_get(parameters, "(&suqb@ay)",
1180 &addr, &req_id, &offset, &response_needed, &var);
1181 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1183 user_info = _bt_get_user_data(BT_COMMON);
1184 if (user_info == NULL) {
1185 BT_INFO("No callback is set for %s", object_path);
1186 g_variant_unref(var);
1187 if (response_needed)
1188 g_dbus_method_invocation_return_value(invocation, NULL);
1190 g_object_unref(invocation);
1194 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1195 if (svc_info == NULL) {
1196 BT_ERR("Coudn't find service for %s", object_path);
1197 g_variant_unref(var);
1198 if (response_needed)
1199 g_dbus_method_invocation_return_value(invocation, NULL);
1201 g_object_unref(invocation);
1205 value_change.att_handle = (char *)object_path;
1206 value_change.address = addr;
1207 value_change.service_handle = svc_info->serv_path;
1208 value_change.offset = offset;
1209 value_change.req_id = req_id;
1210 value_change.response_needed = response_needed;
1212 len = g_variant_get_size(var);
1216 value_change.att_value = (guint8 *)g_malloc(len);
1218 data = (char *)g_variant_get_data(var);
1219 memcpy(value_change.att_value, data, len);
1221 value_change.val_len = len;
1223 if (response_needed) {
1224 /* Store requets information */
1225 req_info = g_new0(struct gatt_req_info, 1);
1226 req_info->attr_path = g_strdup(object_path);
1227 req_info->svc_path = g_strdup(value_change.service_handle);
1228 req_info->request_id = req_id;
1229 req_info->offset = offset;
1230 req_info->context = invocation;
1231 gatt_requests = g_slist_append(gatt_requests, req_info);
1233 g_object_unref(invocation);
1236 _bt_common_event_cb(
1237 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1238 BLUETOOTH_ERROR_NONE, &value_change,
1239 user_info->cb, user_info->user_data);
1241 g_free(value_change.att_value);
1242 g_variant_unref(var);
1247 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1250 GError *error = NULL;
1251 GVariantBuilder *array_builder;
1253 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1254 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1255 g_variant_builder_add(array_builder, "s", interface);
1257 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1258 "org.freedesktop.Dbus.Objectmanager",
1259 "InterfacesRemoved",
1260 g_variant_new("(oas)",
1261 object_path, array_builder),
1265 if (error != NULL) {
1266 /* dbus gives error cause */
1267 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1268 error->code, error->message);
1269 g_clear_error(&error);
1272 g_variant_builder_unref(array_builder);
1277 static const GDBusInterfaceVTable desc_interface_vtable = {
1278 __bt_gatt_desc_method_call,
1284 static const GDBusInterfaceVTable char_interface_vtable = {
1285 __bt_gatt_char_method_call,
1291 static const GDBusInterfaceVTable serv_interface_vtable = {
1298 static const GDBusInterfaceVTable manager_interface_vtable = {
1299 __bt_gatt_manager_method_call,
1305 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1306 const gchar *introspection_data)
1309 GDBusNodeInfo *node_info = NULL;
1311 if (introspection_data == NULL)
1315 BT_DBG("Create new node info");
1316 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1319 BT_ERR("Unable to create node: %s", err->message);
1320 g_clear_error(&err);
1327 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1328 const char *service_path)
1332 for (l = gatt_services; l != NULL; l = l->next) {
1333 struct gatt_service_info *info = l->data;
1335 if (g_strcmp0(info->serv_path, service_path) == 0)
1338 BT_ERR("Gatt service not found");
1342 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1343 const char *service_path, const char *char_path)
1347 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1348 struct gatt_service_info *serv_info = l1->data;
1350 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1352 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1353 struct gatt_char_info *char_info = l2->data;
1355 if (g_strcmp0(char_info->char_path, char_path) == 0)
1358 BT_ERR("Gatt characteristic not found");
1362 BT_ERR("Gatt service not found");
1366 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1367 const char *serv_path, const char *char_path,
1368 const char *desc_path)
1370 GSList *l1, *l2, *l3;
1372 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1373 struct gatt_service_info *serv_info = l1->data;
1375 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1376 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1377 struct gatt_char_info *char_info = l2->data;
1379 if (g_strcmp0(char_info->char_path, char_path) == 0) {
1380 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1381 struct gatt_desc_info *desc_info = l3->data;
1382 if (g_strcmp0(desc_info->desc_path,
1391 BT_ERR("Gatt descriptor not found");
1395 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1399 for (l = gatt_requests; l != NULL; l = l->next) {
1400 struct gatt_req_info *req_info = l->data;
1402 if (req_info && req_info->request_id == request_id)
1405 BT_ERR("Gatt Request not found");
1409 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1410 const gchar *path, const gchar *interface)
1415 g_conn = _bt_get_system_shared_conn();
1417 BT_ERR("Unable to get connection");
1421 proxy = g_dbus_proxy_new_sync(g_conn,
1422 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1424 interface, NULL, &err);
1428 BT_ERR("Unable to create proxy: %s", err->message);
1429 g_clear_error(&err);
1433 manager_gproxy = proxy;
1438 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1439 const gchar *path, const gchar *interface)
1441 return (manager_gproxy) ? manager_gproxy :
1442 __bt_gatt_gdbus_init_manager_proxy(service,
1446 static gboolean __bt_gatt_is_service_registered(const char *service_path)
1448 struct gatt_service_info *svc_info = NULL;
1450 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1452 if (svc_info != NULL) {
1453 BT_DBG("Return the state of the gatt service %d",
1454 svc_info->is_svc_registered);
1455 return svc_info->is_svc_registered;
1458 BT_DBG("gatt service info is NULL");
1462 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1464 GError *error = NULL;
1466 GVariantIter *iter = NULL;
1467 const gchar *key = NULL;
1468 GVariant *value = NULL;
1469 const gchar *service = NULL;
1470 const gchar *characteristic = NULL;
1471 const gchar *descriptor = NULL;
1475 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1477 if (result == NULL) {
1478 BT_ERR("Dbus-RPC is failed");
1479 if (error != NULL) {
1480 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1481 error->code, error->message);
1482 g_clear_error(&error);
1485 char *char_cmp = NULL;
1486 g_variant_get(result, "(a{sv})", &iter);
1487 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1489 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1490 if (g_strcmp0(key, "Service") == 0) {
1491 service = g_variant_get_string(value, NULL);
1492 BT_DBG("Service %s", service);
1493 } else if (g_strcmp0(key, char_cmp) == 0) {
1494 characteristic = g_variant_get_string(value, NULL);
1496 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1497 BT_DBG("%s", characteristic);
1498 } else if (g_strcmp0(key, "Descriptor") == 0) {
1499 descriptor = g_variant_get_string(value, NULL);
1500 BT_DBG("Descriptor %s", descriptor);
1503 g_variant_iter_free(iter);
1505 /* TODO: Store the service informationa and
1506 * Send respponse to CAPI layer. */
1508 g_variant_unref(result);
1513 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1515 BT_INFO("RegisterApplication is completed");
1517 GError *error = NULL;
1520 if (register_cancel) {
1521 g_object_unref(register_cancel);
1522 register_cancel = NULL;
1525 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1526 if (result == NULL) {
1527 BT_ERR("Dbus-RPC is failed");
1528 if (error != NULL) {
1529 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1530 error->code, error->message);
1531 g_clear_error(&error);
1533 is_server_started = false;
1535 g_variant_unref(result);
1539 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1541 GDBusProxy *proxy = NULL;
1543 if (is_server_started) {
1547 if (app_path == NULL) {
1548 BT_ERR("app_path is NULL");
1549 return BLUETOOTH_ERROR_INTERNAL;
1552 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1553 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1554 if (proxy == NULL) {
1555 BT_ERR("proxy is NULL");
1556 return BLUETOOTH_ERROR_INTERNAL;
1559 BT_INFO("UnregisterApplication");
1561 /* Async Call to Unregister Service */
1562 ret = g_dbus_proxy_call_sync(proxy, "UnregisterApplication",
1563 g_variant_new("(o)", app_path), G_DBUS_CALL_FLAGS_NONE, -1,
1566 BT_ERR("dBUS-RPC is failed");
1568 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1569 err->code, err->message);
1570 if (err->code == G_DBUS_ERROR_SERVICE_UNKNOWN ||
1571 g_strrstr(err->message, BT_ERROR_DOES_NOT_EXIST)) {
1572 g_clear_error(&err);
1575 g_clear_error(&err);
1577 return BLUETOOTH_ERROR_INTERNAL;
1579 g_variant_unref(ret);
1582 is_server_started = false;
1584 BT_INFO("UnregisterApplication is completed");
1586 return BLUETOOTH_ERROR_NONE;
1589 BT_INFO("GATT server not started");
1590 return BLUETOOTH_ERROR_NONE;
1593 BT_EXPORT_API int bluetooth_gatt_init(void)
1595 GError *error = NULL;
1596 GDBusNodeInfo *node_info = NULL;
1598 if (app_path != NULL) {
1599 BT_ERR("app path already exists! initialized");
1600 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1603 g_conn = _bt_get_system_shared_conn();
1605 BT_ERR("Unable to get connection");
1609 if (owner_id == 0) {
1610 gchar *name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
1611 BT_DBG("well-known name: %s", name);
1613 owner_id = g_bus_own_name_on_connection(g_conn, name,
1614 G_BUS_NAME_OWNER_FLAGS_NONE,
1615 NULL, NULL, NULL, NULL);
1618 BT_DBG("owner_id is [%d]", owner_id);
1620 app_path = g_strdup_printf("/com/%d", getpid());
1624 /* Register ObjectManager interface */
1625 node_info = __bt_gatt_create_method_node_info(
1626 manager_introspection_xml);
1627 if (node_info == NULL) {
1628 BT_ERR("failed to get node info");
1632 if (manager_id == 0) {
1633 BT_INFO("manager_id does not exists");
1635 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1636 node_info->interfaces[0],
1637 &manager_interface_vtable,
1638 NULL, NULL, &error);
1640 g_dbus_node_info_unref(node_info);
1641 if (manager_id == 0) {
1642 BT_ERR("failed to register: %s", error->message);
1643 g_error_free(error);
1647 return BLUETOOTH_ERROR_NONE;
1651 g_bus_unown_name(owner_id);
1658 return BLUETOOTH_ERROR_INTERNAL;
1661 BT_EXPORT_API int bluetooth_gatt_deinit()
1663 int ret = BLUETOOTH_ERROR_NONE;
1665 if (register_cancel) {
1666 g_cancellable_cancel(register_cancel);
1667 g_object_unref(register_cancel);
1668 register_cancel = NULL;
1671 if (owner_id == 0) {
1672 BT_ERR("owner_id is zero");
1673 return BLUETOOTH_ERROR_NOT_FOUND;
1676 BT_DBG("Removing all registered gatt services");
1677 bluetooth_gatt_delete_services();
1679 /* Unregister the exported interface for object manager */
1681 g_dbus_connection_unregister_object(g_conn, manager_id);
1685 ret = bluetooth_gatt_unregister_application();
1686 if (ret != BLUETOOTH_ERROR_NONE) {
1687 BT_ERR("Fail to unregister application");
1690 g_bus_unown_name(owner_id);
1696 if (manager_gproxy) {
1697 g_object_unref(manager_gproxy);
1698 manager_gproxy = NULL;
1705 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1708 GError *error = NULL;
1710 GDBusNodeInfo *node_info;
1712 GVariantBuilder *builder = NULL;
1713 GVariantBuilder *builder1 = NULL;
1714 GVariantBuilder *inner_builder = NULL;
1715 gboolean svc_primary = TRUE;
1716 struct gatt_service_info *serv_info = NULL;
1718 node_info = __bt_gatt_create_method_node_info(
1719 service_introspection_xml);
1720 if (node_info == NULL)
1721 return BLUETOOTH_ERROR_INTERNAL;
1723 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1724 BT_DBG("gatt service path is [%s]", path);
1726 object_id = g_dbus_connection_register_object(g_conn, path,
1727 node_info->interfaces[0],
1728 &serv_interface_vtable,
1729 NULL, NULL, &error);
1730 g_dbus_node_info_unref(node_info);
1732 if (object_id == 0) {
1733 BT_ERR("failed to register: %s", error->message);
1734 g_error_free(error);
1737 return BLUETOOTH_ERROR_INTERNAL;
1740 /* Add object_id/gatt service information; it's required at the time of
1741 * service unregister and Getmanagedobjects
1743 serv_info = g_new0(struct gatt_service_info, 1);
1745 serv_info->serv_path = g_strdup(path);
1746 serv_info->serv_id = object_id;
1747 serv_info->service_uuid = g_strdup(svc_uuid);
1748 serv_info->is_svc_registered = FALSE;
1749 serv_info->is_svc_primary = svc_primary;
1751 gatt_services = g_slist_append(gatt_services, serv_info);
1753 /* emit interfacesadded signal here for service path */
1754 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1755 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1757 g_variant_builder_add(inner_builder, "{sv}",
1758 "UUID", g_variant_new_string(svc_uuid));
1760 g_variant_builder_add(inner_builder, "{sv}",
1761 "Primary", g_variant_new_boolean(svc_primary));
1763 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1765 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1766 g_variant_new("ao", builder1));
1768 g_variant_builder_add(builder, "{sa{sv}}",
1769 GATT_SERV_INTERFACE, inner_builder);
1771 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1772 "org.freedesktop.Dbus.ObjectManager",
1774 g_variant_new("(oa{sa{sv}})",
1777 if (error != NULL) {
1778 /* dbus gives error cause */
1779 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1780 error->code, error->message);
1781 g_clear_error(&error);
1786 *svc_path = g_strdup(path);
1789 g_variant_builder_unref(inner_builder);
1790 g_variant_builder_unref(builder);
1791 g_variant_builder_unref(builder1);
1793 return BLUETOOTH_ERROR_NONE;
1796 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1797 const char *svc_path, const char *char_uuid,
1798 bt_gatt_permission_t permissions,
1799 bt_gatt_characteristic_property_t properties,
1803 GError *error = NULL;
1805 GDBusNodeInfo *node_info;
1807 GVariantBuilder *builder = NULL;
1808 GVariantBuilder *inner_builder = NULL;
1809 struct gatt_service_info *serv_info = NULL;
1810 struct gatt_char_info *char_info = NULL;
1811 GVariantBuilder *builder2 = NULL;
1812 GVariantBuilder *builder3 = NULL;
1813 GVariant *flags_val = NULL;
1815 char *char_flags[NUMBER_OF_FLAGS];
1820 new_service = FALSE;
1823 BT_DBG("gatt svc_path path is [%s]", svc_path);
1824 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1825 if (serv_info == NULL)
1826 return BLUETOOTH_ERROR_INVALID_PARAM;
1828 node_info = __bt_gatt_create_method_node_info(
1829 characteristics_introspection_xml);
1830 if (node_info == NULL)
1831 return BLUETOOTH_ERROR_INTERNAL;
1833 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1834 BT_DBG("gatt characteristic path is [%s]", path);
1836 object_id = g_dbus_connection_register_object(g_conn, path,
1837 node_info->interfaces[0],
1838 &char_interface_vtable,
1839 NULL, NULL, &error);
1840 g_dbus_node_info_unref(node_info);
1842 if (object_id == 0) {
1843 BT_ERR("failed to register: %s", error->message);
1844 g_error_free(error);
1847 return BLUETOOTH_ERROR_INTERNAL;
1850 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1851 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1852 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1853 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1854 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1855 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1856 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1857 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1859 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1861 char_info = g_new0(struct gatt_char_info, 1);
1863 char_info->char_path = g_strdup(path);
1864 char_info->char_id = object_id;
1865 char_info->char_uuid = g_strdup(char_uuid);
1867 for (i = 0; i < flag_count; i++)
1868 char_info->char_flags[i] = char_flags[i];
1871 char_info->flags_length = flag_count;
1873 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1875 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1876 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1878 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1879 g_variant_new("s", char_uuid));
1880 g_variant_builder_add(inner_builder, "{sv}", "Service",
1881 g_variant_new("o", svc_path));
1883 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1885 for (i = 0; i < flag_count; i++)
1886 g_variant_builder_add(builder2, "s", char_flags[i]);
1888 flags_val = g_variant_new("as", builder2);
1889 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1892 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1894 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1895 g_variant_new("ao", builder3));
1897 g_variant_builder_add(builder, "{sa{sv}}",
1898 GATT_CHAR_INTERFACE,
1901 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1902 "org.freedesktop.Dbus.ObjectManager",
1904 g_variant_new("(oa{sa{sv}})",
1908 /* dBUS gives error cause */
1909 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1910 error->code, error->message);
1911 g_clear_error(&error);
1914 *char_path = g_strdup(path);
1920 g_variant_builder_unref(inner_builder);
1921 g_variant_builder_unref(builder);
1922 g_variant_builder_unref(builder2);
1923 g_variant_builder_unref(builder3);
1925 return BLUETOOTH_ERROR_NONE;
1928 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1929 const char *characteristic, const char *char_value,
1932 gchar **line_argv = NULL;
1933 char *serv_path = NULL;
1934 struct gatt_char_info *char_info = NULL;
1935 GVariantBuilder *builder1 = NULL;
1936 GVariantBuilder *builder = NULL;
1937 GVariantBuilder *inner_builder = NULL;
1938 GVariant *char_val = NULL;
1939 GError *error = NULL;
1941 int res = BLUETOOTH_ERROR_NONE;
1943 line_argv = g_strsplit_set(characteristic, "/", 0);
1944 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1946 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1948 if (char_info == NULL) {
1949 /* Fix : RESOURCE_LEAK */
1950 res = BLUETOOTH_ERROR_INVALID_PARAM;
1954 char_info->value_length = value_length;
1956 char_info->char_value = (char *)malloc(value_length);
1957 /* Fix : NULL_RETURNS */
1958 if (char_info->char_value == NULL) {
1959 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1963 for (i = 0; i < value_length; i++)
1964 char_info->char_value[i] = char_value[i];
1966 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1967 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1969 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1971 for (i = 0; i < value_length; i++)
1972 g_variant_builder_add(builder1, "y", char_value[i]);
1974 char_val = g_variant_new("ay", builder1);
1975 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1977 g_variant_builder_add(builder, "{sa{sv}}",
1978 GATT_CHAR_INTERFACE,
1981 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1982 "org.freedesktop.Dbus.ObjectManager",
1984 g_variant_new("(oa{sa{sv}})",
1985 char_info->char_path, builder),
1989 /* dBUS gives error cause */
1990 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1991 error->code, error->message);
1992 g_clear_error(&error);
1994 g_variant_builder_unref(inner_builder);
1995 g_variant_builder_unref(builder);
1996 g_variant_builder_unref(builder1);
1998 g_strfreev(line_argv);
2004 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2005 const char *char_path, const char *desc_uuid,
2006 bt_gatt_permission_t permissions,
2009 static int desc_id = 1;
2010 GError *error = NULL;
2012 GDBusNodeInfo *node_info;
2014 GVariantBuilder *builder = NULL;
2015 GVariantBuilder *inner_builder = NULL;
2016 struct gatt_char_info *char_info = NULL;
2017 struct gatt_desc_info *desc_info = NULL;
2018 gchar **line_argv = NULL;
2020 GVariantBuilder *builder2 = NULL;
2021 GVariant *flags_val = NULL;
2023 char *desc_flags[NUMBER_OF_FLAGS];
2031 line_argv = g_strsplit_set(char_path, "/", 0);
2032 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2034 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2035 if (char_info == NULL) {
2036 g_strfreev(line_argv);
2038 return BLUETOOTH_ERROR_INVALID_PARAM;
2041 node_info = __bt_gatt_create_method_node_info(
2042 descriptor_introspection_xml);
2043 if (node_info == NULL) {
2044 g_strfreev(line_argv);
2046 return BLUETOOTH_ERROR_INTERNAL;
2049 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2050 BT_DBG("gatt descriptor path is [%s]", path);
2052 object_id = g_dbus_connection_register_object(g_conn, path,
2053 node_info->interfaces[0],
2054 &desc_interface_vtable,
2055 NULL, NULL, &error);
2056 g_dbus_node_info_unref(node_info);
2058 if (object_id == 0) {
2059 BT_ERR("failed to register: %s", error->message);
2060 g_error_free(error);
2062 g_strfreev(line_argv);
2065 return BLUETOOTH_ERROR_INTERNAL;
2068 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2070 desc_info = g_new0(struct gatt_desc_info, 1);
2072 desc_info->desc_path = g_strdup(path);
2073 desc_info->desc_id = object_id;
2074 desc_info->desc_uuid = g_strdup(desc_uuid);
2076 for (i = 0; i < flag_count; i++)
2077 desc_info->desc_flags[i] = desc_flags[i];
2079 desc_info->flags_length = flag_count;
2081 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2083 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2084 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2086 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2087 g_variant_new("s", desc_uuid));
2088 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2089 g_variant_new("o", char_path));
2091 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2093 for (i = 0; i < flag_count; i++)
2094 g_variant_builder_add(builder2, "s", desc_flags[i]);
2096 flags_val = g_variant_new("as", builder2);
2097 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2100 g_variant_builder_add(builder, "{sa{sv}}",
2101 GATT_DESC_INTERFACE,
2104 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2105 "org.freedesktop.Dbus.ObjectManager",
2107 g_variant_new("(oa{sa{sv}})",
2111 /* dBUS gives error cause */
2112 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2113 error->code, error->message);
2114 g_clear_error(&error);
2117 *desc_path = g_strdup(path);
2121 g_strfreev(line_argv);
2122 g_variant_builder_unref(inner_builder);
2123 g_variant_builder_unref(builder);
2124 g_variant_builder_unref(builder2);
2126 return BLUETOOTH_ERROR_NONE;
2129 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2130 const char *desc_path, const char *desc_value,
2133 GError *error = NULL;
2134 GVariantBuilder *builder = NULL;
2135 GVariantBuilder *inner_builder = NULL;
2136 GVariantBuilder *builder1 = NULL;
2137 struct gatt_desc_info *desc_info = NULL;
2138 gchar **line_argv = NULL;
2140 GVariant *desc_val = NULL;
2141 char *serv_path = NULL;
2144 line_argv = g_strsplit_set(desc_path, "/", 0);
2145 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2146 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2148 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2150 /* Free the allocated memory */
2151 g_strfreev(line_argv);
2155 /* Fix : NULL_RETURNS */
2156 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2158 desc_info->desc_value = (char *)malloc(value_length);
2160 /* Fix : NULL_RETURNS */
2161 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2163 for (i = 0; i < value_length; i++)
2164 desc_info->desc_value[i] = desc_value[i];
2166 desc_info->value_length = value_length;
2168 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2169 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2171 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2173 for (i = 0; i < value_length; i++)
2174 g_variant_builder_add(builder1, "y", desc_value[i]);
2176 desc_val = g_variant_new("ay", builder1);
2177 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2179 g_variant_builder_add(builder, "{sa{sv}}",
2180 GATT_DESC_INTERFACE,
2183 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2184 "org.freedesktop.Dbus.ObjectManager",
2186 g_variant_new("(oa{sa{sv}})",
2187 desc_info->desc_path, builder),
2190 if (error != NULL) {
2191 BT_ERR("D-Bus API failure: errCode[%x], \
2193 error->code, error->message);
2194 g_clear_error(&error);
2197 g_variant_builder_unref(inner_builder);
2198 g_variant_builder_unref(builder);
2199 g_variant_builder_unref(builder1);
2201 return BLUETOOTH_ERROR_NONE;
2204 int bluetooth_gatt_get_service(const char *svc_uuid)
2206 GDBusProxy *proxy = NULL;
2209 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2210 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2212 return BLUETOOTH_ERROR_INTERNAL;
2214 uuid = g_strdup(svc_uuid);
2216 g_dbus_proxy_call(proxy,
2218 g_variant_new("(s)",
2220 G_DBUS_CALL_FLAGS_NONE, -1,
2222 (GAsyncReadyCallback) get_service_cb,
2227 return BLUETOOTH_ERROR_NONE;
2230 BT_EXPORT_API int bluetooth_gatt_register_service(const char *svc_path)
2232 struct gatt_service_info *svc_info = NULL;
2234 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2235 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2236 BT_ERR("Don't have aprivilege to use this API");
2237 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2240 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2241 if (svc_info == NULL) {
2242 BT_ERR("Cannot find service [%s]", svc_path);
2243 return BLUETOOTH_ERROR_INTERNAL;
2245 svc_info->is_svc_registered = TRUE;
2247 return BLUETOOTH_ERROR_NONE;
2250 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2252 GDBusProxy *proxy = NULL;
2254 if (!is_server_started) {
2255 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2256 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2257 BT_ERR("Don't have aprivilege to use this API");
2258 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2261 if (g_slist_length(gatt_services) == 0) {
2262 BT_ERR("There is no registered service");
2263 return BLUETOOTH_ERROR_INTERNAL;
2266 if (app_path == NULL) {
2267 BT_ERR("app_path is NULL");
2268 return BLUETOOTH_ERROR_INTERNAL;
2271 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2272 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2273 if (proxy == NULL) {
2274 BT_ERR("proxy is NULL");
2275 return BLUETOOTH_ERROR_INTERNAL;
2278 BT_INFO("RegisterApplication");
2280 if (register_cancel) {
2281 g_cancellable_cancel(register_cancel);
2282 g_object_unref(register_cancel);
2284 register_cancel = g_cancellable_new();
2286 g_dbus_proxy_call(proxy, "RegisterApplication",
2287 g_variant_new("(oa{sv})", app_path, NULL),
2288 G_DBUS_CALL_FLAGS_NONE, -1, register_cancel,
2289 (GAsyncReadyCallback)register_application_cb, NULL);
2291 is_server_started = true;
2293 return BLUETOOTH_ERROR_NONE;
2296 BT_INFO("Already RegisterApplication");
2298 return BLUETOOTH_ERROR_NONE;
2301 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2304 int ret = BLUETOOTH_ERROR_NONE;
2306 if (gatt_services == NULL) {
2307 BT_DBG("There are no registered services");
2312 for (l = gatt_services; l != NULL; ) {
2313 struct gatt_service_info *info = l->data;
2315 // In __bt_gatt_unregister_service, current node will be removed.
2316 // Go forward to next node before calling __bt_gatt_unregister_service.
2318 if (__bt_gatt_unregister_service(info) != BLUETOOTH_ERROR_NONE) {
2319 ret = BLUETOOTH_ERROR_INTERNAL;
2322 BT_INFO("All services are removed : %d", ret);
2324 g_slist_free(gatt_services);
2325 gatt_services = NULL;
2331 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2332 const char *char_path, const char* char_value,
2335 GVariantBuilder *outer_builder;
2336 GVariantBuilder *inner_builder;
2337 GVariantBuilder *invalidated_builder;
2338 GVariant *update_value = NULL;
2339 GError *error = NULL;
2340 gboolean ret = FALSE;
2341 int err = BLUETOOTH_ERROR_NONE;
2343 gchar **line_argv = NULL;
2344 gchar *serv_path = NULL;
2345 const char *value = NULL;
2347 line_argv = g_strsplit_set(char_path, "/", 0);
2348 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2350 if (!__bt_gatt_is_service_registered(serv_path)) {
2351 BT_DBG("service not registered for this characteristic");
2353 g_strfreev(line_argv);
2354 return BLUETOOTH_ERROR_INTERNAL;
2357 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2358 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2360 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2361 for (i = 0; i < value_length; i++)
2362 g_variant_builder_add(inner_builder, "y", char_value[i]);
2364 update_value = g_variant_new("ay", inner_builder);
2366 g_variant_builder_add(outer_builder, "{sv}", "Value",
2369 BT_DBG("Updating characteristic value");
2370 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2372 "org.freedesktop.DBus.Properties",
2373 "PropertiesChanged",
2374 g_variant_new("(sa{sv}as)",
2375 "org.bluez.GattCharacteristic1",
2376 outer_builder, invalidated_builder),
2380 if (error != NULL) {
2381 BT_ERR("D-Bus API failure: errCode[%x], \
2383 error->code, error->message);
2384 g_clear_error(&error);
2386 err = BLUETOOTH_ERROR_INTERNAL;
2388 struct gatt_char_info *char_info = NULL;
2390 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2391 if (char_info == NULL) {
2393 g_strfreev(line_argv);
2394 g_variant_builder_unref(inner_builder);
2395 g_variant_builder_unref(outer_builder);
2396 g_variant_builder_unref(invalidated_builder);
2398 return BLUETOOTH_ERROR_INVALID_DATA;
2401 char_info->value_length = value_length;
2403 value = (char *)realloc(char_info->char_value, value_length);
2404 if (value == NULL) {
2406 g_strfreev(line_argv);
2407 g_variant_builder_unref(inner_builder);
2408 g_variant_builder_unref(outer_builder);
2409 g_variant_builder_unref(invalidated_builder);
2411 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2414 char_info->char_value = (char*)value;
2415 if (char_info->char_value) {
2416 for (i = 0; i < value_length; i++)
2417 char_info->char_value[i] = char_value[i];
2422 g_strfreev(line_argv);
2423 g_variant_builder_unref(inner_builder);
2424 g_variant_builder_unref(outer_builder);
2425 g_variant_builder_unref(invalidated_builder);
2430 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2437 g_free(desc_info->desc_path);
2438 g_free(desc_info->desc_uuid);
2439 g_free(desc_info->desc_value);
2441 for (i = 0; i < desc_info->flags_length; i++)
2442 g_free(desc_info->desc_flags[i]);
2447 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2454 g_free(char_info->char_path);
2455 g_free(char_info->char_uuid);
2456 g_free(char_info->char_value);
2458 for (i = 0; i < char_info->flags_length; i++)
2459 g_free(char_info->char_flags[i]);
2464 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2469 g_free(svc_info->serv_path);
2470 g_free(svc_info->service_uuid);
2474 static void __desc_info_free(gpointer data, gpointer user_data)
2476 struct gatt_desc_info *desc_info = data;
2477 int *err = user_data;
2480 if (desc_info == NULL)
2483 ret = g_dbus_connection_unregister_object(g_conn, desc_info->desc_id);
2485 __bt_gatt_emit_interface_removed(desc_info->desc_path, GATT_DESC_INTERFACE);
2487 *err = BLUETOOTH_ERROR_INTERNAL;
2489 __bt_gatt_free_descriptor_info(desc_info);
2492 static void __char_info_free(gpointer data, gpointer user_data)
2494 struct gatt_char_info *char_info = data;
2495 int *err = user_data;
2498 if (char_info == NULL)
2501 g_slist_foreach(char_info->desc_data, __desc_info_free, user_data);
2502 g_slist_free(char_info->desc_data);
2503 char_info->desc_data = NULL;
2505 ret = g_dbus_connection_unregister_object(g_conn, char_info->char_id);
2507 __bt_gatt_emit_interface_removed(char_info->char_path, GATT_CHAR_INTERFACE);
2509 *err = BLUETOOTH_ERROR_INTERNAL;
2511 __bt_gatt_free_characteristic_info(char_info);
2514 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info)
2516 int ret = BLUETOOTH_ERROR_NONE;
2518 if (svc_info == NULL) {
2519 BT_ERR("svc_info is NULL");
2520 return BLUETOOTH_ERROR_NOT_FOUND;
2523 if (svc_info->is_svc_registered == FALSE) {
2524 BT_ERR("%s is not registered", svc_info->serv_path);
2525 return BLUETOOTH_ERROR_NOT_FOUND;
2528 BT_DBG("svc_path %s", svc_info->serv_path);
2530 g_slist_foreach(svc_info->char_data, __char_info_free, &ret);
2531 g_slist_free(svc_info->char_data);
2532 svc_info->char_data = NULL;
2534 if (g_dbus_connection_unregister_object(g_conn, svc_info->serv_id) == FALSE) {
2535 BT_ERR("Cannot unregister object for [%s]", svc_info->serv_path);
2536 ret = BLUETOOTH_ERROR_INTERNAL;
2538 __bt_gatt_emit_interface_removed(svc_info->serv_path, GATT_SERV_INTERFACE);
2541 gatt_services = g_slist_remove(gatt_services, svc_info);
2542 __bt_gatt_free_service_info(svc_info);
2544 new_service = FALSE;
2546 if (gatt_services == NULL) {
2548 } else if (gatt_services->next == NULL) {
2555 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2557 struct gatt_service_info *svc_info;
2558 int ret = BLUETOOTH_ERROR_NONE;
2562 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2564 ret = __bt_gatt_unregister_service(svc_info);
2565 if (ret != BLUETOOTH_ERROR_NONE) {
2566 BT_ERR("Could not unregister service [%s]", svc_path);
2573 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2574 int resp_state, int offset, char *value, int value_length)
2576 struct gatt_req_info *req_info = NULL;
2578 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2579 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2580 BT_ERR("Don't have aprivilege to use this API");
2581 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2584 req_info = __bt_gatt_find_request_info(request_id);
2585 if (req_info == NULL) {
2586 BT_ERR("Coundn't find request id [%d]", request_id);
2587 return BLUETOOTH_ERROR_INTERNAL;
2590 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2591 BT_ERR("resp_state is 0x%X", resp_state);
2592 char err_msg[20] = { 0, };
2593 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2594 g_dbus_method_invocation_return_dbus_error(req_info->context,
2595 "org.bluez.Error.Failed", err_msg);
2597 gatt_requests = g_slist_remove(gatt_requests, req_info);
2599 req_info->context = NULL;
2600 if (req_info->attr_path)
2601 g_free(req_info->attr_path);
2602 if (req_info->svc_path)
2603 g_free(req_info->svc_path);
2606 return BLUETOOTH_ERROR_NONE;
2609 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2611 GVariantBuilder *inner_builder = NULL;
2612 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2613 if (value_length > 0 && value != NULL) {
2614 for (i = 0; i < value_length; i++)
2615 g_variant_builder_add(inner_builder, "y", value[i]);
2617 g_dbus_method_invocation_return_value(req_info->context,
2618 g_variant_new("(ay)", inner_builder));
2619 g_variant_builder_unref(inner_builder);
2621 g_dbus_method_invocation_return_value(req_info->context, NULL);
2623 gatt_requests = g_slist_remove(gatt_requests, req_info);
2625 req_info->context = NULL;
2626 if (req_info->attr_path)
2627 g_free(req_info->attr_path);
2628 if (req_info->svc_path)
2629 g_free(req_info->svc_path);
2632 return BLUETOOTH_ERROR_NONE;
2635 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2636 bluetooth_device_address_t *unicast_address)
2638 GVariantBuilder *outer_builder;
2639 GVariantBuilder *invalidated_builder;
2640 GError *error = NULL;
2641 gboolean notify = TRUE;
2642 gboolean ret = TRUE;
2643 int err = BLUETOOTH_ERROR_NONE;
2644 gchar **line_argv = NULL;
2645 gchar *serv_path = NULL;
2646 char addr[20] = { 0 };
2648 line_argv = g_strsplit_set(char_path, "/", 0);
2649 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2651 if (!__bt_gatt_is_service_registered(serv_path)) {
2652 BT_DBG("service not registered for this characteristic");
2654 g_strfreev(line_argv);
2655 return BLUETOOTH_ERROR_INTERNAL;
2660 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2661 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2663 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2664 g_variant_new("b", notify));
2666 if (unicast_address) {
2667 _bt_convert_addr_type_to_string(addr,
2668 (unsigned char *)unicast_address->addr);
2670 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2671 g_variant_new("s", addr));
2673 BT_DBG("Set characteristic Notification");
2674 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2676 "org.freedesktop.DBus.Properties",
2677 "PropertiesChanged",
2678 g_variant_new("(sa{sv}as)",
2679 "org.bluez.GattCharacteristic1",
2680 outer_builder, invalidated_builder),
2684 if (error != NULL) {
2685 BT_ERR("D-Bus API failure: errCode[%x], \
2687 error->code, error->message);
2688 g_clear_error(&error);
2690 err = BLUETOOTH_ERROR_INTERNAL;
2693 g_strfreev(line_argv);
2694 g_variant_builder_unref(outer_builder);
2695 g_variant_builder_unref(invalidated_builder);
2700 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2703 int ret = BLUETOOTH_ERROR_NONE;
2706 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2708 /* Register event handler for GATT */
2709 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2711 if (ret != BLUETOOTH_ERROR_NONE &&
2712 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2713 BT_ERR("Fail to init the event handler");
2714 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2718 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2719 in_param1, in_param2, in_param3, in_param4, &out_param);
2721 /* App ID -1 is invalid */
2722 if (ret != BLUETOOTH_ERROR_NONE) {
2723 BT_INFO("GATT Server Registration failed result [%d]", ret);
2726 *instance_id = g_array_index(out_param, int, 0);
2727 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2731 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2733 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2737 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2740 BT_INFO("GATT Server Deinitialize");
2741 /* Unregister the event */
2742 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2744 if (ret != BLUETOOTH_ERROR_NONE) {
2745 BT_ERR("Fail to deinit the event handler");
2749 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2754 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2755 int instance_id, int *service_handle)
2757 BT_CHECK_ENABLED(return);
2758 BT_CHECK_PARAMETER(svc_uuid, return);
2761 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2763 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2766 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2768 g_array_append_vals(in_param1, &type, sizeof(int));
2769 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2770 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2771 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2773 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2774 in_param1, in_param2, in_param3, in_param4, &out_param);
2776 /* ATT handle 0 is reserved, hence it can not be used by app.
2777 It will be used to indicate error in regsitering attribute */
2778 if (result != BLUETOOTH_ERROR_NONE)
2779 *service_handle = 0;
2781 *service_handle = g_array_index(out_param, int, 0);
2783 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2788 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2789 const bluetooth_gatt_server_attribute_params_t *param,
2792 BT_CHECK_ENABLED(return);
2793 BT_CHECK_PARAMETER(char_uuid, return);
2794 BT_CHECK_PARAMETER(param, return);
2797 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2799 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2802 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2804 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2805 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2807 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2808 in_param1, in_param2, in_param3, in_param4, &out_param);
2810 /* ATT handle 0 is reserved, hence it can not be used by app.
2811 It will be used to indicate error in regsitering attribute */
2812 if (result != BLUETOOTH_ERROR_NONE) {
2813 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2816 *char_handle = g_array_index(out_param, int, 0);
2817 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2820 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2824 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2825 int service_handle, int instance_id, int *descriptor_handle)
2827 BT_CHECK_ENABLED(return);
2828 BT_CHECK_PARAMETER(desc_uuid, return);
2831 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2833 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2836 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2838 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2839 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2840 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2841 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2843 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2844 in_param1, in_param2, in_param3, in_param4, &out_param);
2846 /* ATT handle 0 is reserved, hence it can not be used by app.
2847 It will be used to indicate error in regsitering attribute */
2848 if (result != BLUETOOTH_ERROR_NONE) {
2849 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2850 *descriptor_handle = 0;
2852 *descriptor_handle = g_array_index(out_param, int, 0);
2853 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2856 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2861 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2863 BT_CHECK_ENABLED(return);
2867 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2869 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2870 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2872 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2873 in_param1, in_param2, in_param3, in_param4, &out_param);
2875 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2880 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2881 const bluetooth_gatt_att_data_t *value)
2883 BT_CHECK_PARAMETER(param, return);
2884 BT_CHECK_PARAMETER(value, return);
2885 BT_CHECK_ENABLED(return);
2889 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2891 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
2892 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
2894 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
2895 in_param1, in_param2, in_param3, in_param4, &out_param);
2897 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2903 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
2904 bluetooth_gatt_server_indication_params_t *param,
2905 const bluetooth_gatt_att_data_t *att_value)
2907 BT_CHECK_PARAMETER(param, return);
2908 BT_CHECK_PARAMETER(att_value, return);
2909 BT_CHECK_ENABLED(return);
2911 char addr[BLUETOOTH_ADDRESS_STRING_LENGTH] ;
2915 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2917 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
2918 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
2919 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
2921 _bt_convert_addr_type_to_string(addr, addr_hex->addr);
2922 BT_INFO("Send Indication to address [%s]", addr);
2923 fd = bluetooth_get_characteristic_fd(param->atrribute_handle, addr);
2926 BT_INFO("Acquire Notify FD found: Send Multicast Indication over Socket");
2927 result = bluetooth_gatt_write_characteristics_value_to_fd_(fd, att_value->data, att_value->length, NULL);
2930 BT_ERR("Acquire Notify FD not found for charatcristic handle: Send DBUS indication");
2931 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
2932 in_param1, in_param2, in_param3, in_param4, &out_param);
2935 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2940 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
2942 BT_CHECK_ENABLED(return);
2946 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2948 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2949 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2951 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
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_delete_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_DELETE_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 /* Tizen Platform Specific */
2979 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
2980 const bluetooth_gatt_server_update_value_t *value)
2982 BT_CHECK_ENABLED(return);
2983 BT_CHECK_PARAMETER(value, return);
2987 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2989 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2990 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
2992 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
2993 in_param1, in_param2, in_param3, in_param4, &out_param);
2995 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3000 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3002 BT_CHECK_ENABLED(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));
3010 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3011 in_param1, in_param2, in_param3, in_param4, &out_param);
3013 if (result != BLUETOOTH_ERROR_NONE)
3014 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3016 BT_INFO("GATT Server Unregistration successful");
3018 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3022 BT_EXPORT_API int bluetooth_gatt_server_set_service_persistence(const char *svc_uuid)
3024 BT_CHECK_ENABLED(return);
3026 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
3028 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
3031 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3033 g_array_append_vals(in_param1, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
3035 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SET_SERVICE_PERSISTENCE,
3036 in_param1, in_param2, in_param3, in_param4, &out_param);
3038 if (result != BLUETOOTH_ERROR_NONE)
3039 BT_INFO("GATT Server Set service persistence failed result [%d]", result);
3041 BT_INFO("GATT Server Set service persistence successful");
3043 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3047 BT_EXPORT_API int bluetooth_gatt_server_unset_service_persistence(const char *svc_uuid)
3049 BT_CHECK_ENABLED(return);
3051 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
3053 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
3056 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3058 g_array_append_vals(in_param1, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
3060 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UNSET_SERVICE_PERSISTENCE,
3061 in_param1, in_param2, in_param3, in_param4, &out_param);
3063 if (result != BLUETOOTH_ERROR_NONE)
3064 BT_INFO("GATT Server Unset service persistence failed result [%d]", result);
3066 BT_INFO("GATT Server Unset service persistence successful");
3068 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3072 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3073 GIOCondition cond, gpointer data)
3076 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3078 BT_DBG("FD io write data received [%s]", write_data->address);
3080 if (cond & G_IO_NVAL) {
3081 BT_ERR("Invalid channel");
3085 if (cond & (G_IO_HUP | G_IO_ERR)) {
3086 BT_ERR("Error : GIOCondition %d", cond);
3087 g_io_channel_shutdown(gio, TRUE, NULL);
3088 g_io_channel_unref(gio);
3093 if (cond & G_IO_IN) {
3094 GIOStatus status = G_IO_STATUS_NORMAL;
3096 char *buffer = NULL;
3098 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3100 buffer = g_malloc0(BUF);
3102 status = g_io_channel_read_chars(gio, buffer,
3105 if (status != G_IO_STATUS_NORMAL) {
3106 BT_ERR("IO Channel read is failed with %d", status);
3109 BT_ERR("IO Channel read error [%s]", err->message);
3110 if (status == G_IO_STATUS_ERROR) {
3111 BT_ERR("cond : %d", cond);
3113 g_io_channel_shutdown(gio, TRUE, NULL);
3114 g_io_channel_unref(gio);
3124 bluetooth_gatt_server_write_requested_info_t write_info;
3125 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3126 memcpy(write_info.data.data, buffer, len);
3128 write_info.length = len;
3129 write_info.need_resp = false;
3130 write_info.attribute_handle = write_data->attribute_handle;
3132 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->address);
3133 write_info.connection_id = write_data->connection_id;
3134 write_info.offset = write_data->offset;
3135 write_info.request_id = -2;
3137 bt_event_info_t *event_info;
3138 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3142 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3143 BLUETOOTH_ERROR_NONE, &write_info,
3144 event_info->cb, event_info->user_data);
3146 BT_ERR("eventinfo failed");
3157 void bluetooth_gatt_server_send_acquire_write_response(GVariant * parameters)
3162 int pipefd[2] = {-1,};
3165 char err_msg[512] = {'\0'};
3166 GIOChannel *channel = NULL;
3170 g_variant_get(parameters, "(iiiiii&s)",
3179 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3180 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3181 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3182 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3185 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pipefd) < 0) {
3186 strerror_r(errno, err_msg, sizeof(err_msg));
3187 BT_ERR("socketpair(): %s", err_msg);
3192 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3194 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3195 bluetooth_gatt_server_acquire_response_params_t data;
3196 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
3197 data.fd = pipefd[1];
3199 data.request_id = tran_id;
3201 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3203 write_info->attribute_handle = att_han;
3204 write_info->connection_id = tran_id;
3205 write_info->offset = offset;
3207 memcpy(write_info->address, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3209 BT_INFO("FD read %d remote address [%s ] \n", pipefd[0], addr);
3211 channel = g_io_channel_unix_new(pipefd[0]);
3212 g_io_channel_set_encoding(channel, NULL, NULL);
3213 g_io_channel_set_buffered(channel, FALSE);
3214 g_io_channel_set_close_on_unref(channel, TRUE);
3215 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3216 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3217 bluetooth_gatt_server_acquire_channel_write_cb, write_info);
3219 GUnixFDList *fd_list = g_unix_fd_list_new();
3220 GError *error = NULL;
3222 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3223 g_assert_no_error(error);
3226 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3228 BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3230 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE,
3231 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3233 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3234 g_object_unref(fd_list);
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", pipefd[0]);
3287 chr_info = bluetooth_get_characteristic_info_from_path(att_han);
3289 BT_INFO("char info not found for ATT handle [%u]", att_han);
3290 chr_info = g_malloc0(sizeof(bluetooth_gatt_acquire_notify_info_t));
3291 chr_info->write_fd = fd;
3292 chr_info->att_hand = att_han;
3293 memcpy(chr_info->address, address, BLUETOOTH_ADDRESS_STRING_LENGTH);
3295 gatt_characteristic_server_notify_list = g_slist_append(gatt_characteristic_server_notify_list, chr_info);
3297 BT_INFO("Already AcquireNotify Set for this attribute handle by remote Client [%s]", chr_info->address);
3298 chr_info->write_fd = fd;
3301 channel = g_io_channel_unix_new(fd);
3302 chr_info->io_channel = channel;
3303 g_io_channel_set_encoding(channel, NULL, NULL);
3304 g_io_channel_set_buffered(channel, FALSE);
3305 g_io_channel_set_close_on_unref(channel, TRUE);
3306 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3307 chr_info->watch_id =
3308 g_io_add_watch(channel,
3309 (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
3310 bluetooth_gatt_write_channel_watch_cb, chr_info);
3312 GUnixFDList *fd_list = g_unix_fd_list_new();
3313 GError *error = NULL;
3315 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3316 g_assert_no_error(error);
3319 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3321 BT_DBG("Sending event BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE file descriptor value [%d] ", data.fd);
3323 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE,
3324 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3326 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3327 g_object_unref(fd_list);
3330 if (result == BLUETOOTH_ERROR_NONE) {
3331 BT_DBG("sending gatt server notification state changed event");
3332 bluetooth_gatt_server_notification_changed_t info;
3333 bluetooth_device_address_t dev_address = { {0} };
3334 memset(&info, 0x00, sizeof(bluetooth_gatt_server_notification_changed_t));
3336 _bt_convert_addr_string_to_type(dev_address.addr, address);
3337 memcpy(info.device_address.addr,
3339 BLUETOOTH_ADDRESS_LENGTH);
3340 info.handle = att_han;
3341 info.notification = TRUE;
3343 _bt_gatt_server_event_cb(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
3345 event_info->cb, event_info->user_data);
3350 void cleanup_gatt_acquire_fd(int handle)
3352 bluetooth_gatt_acquire_notify_info_t *chr_info = NULL;
3356 chr_info = bluetooth_get_characteristic_info_from_path(handle);
3358 if (chr_info != NULL) {
3359 BT_INFO("GATT Server: acquire notification char info found [%s]", chr_info->path);
3361 if (chr_info->watch_id > 0)
3362 g_source_remove(chr_info->watch_id);
3364 if (chr_info->io_channel) {
3365 g_io_channel_shutdown(chr_info->io_channel, TRUE, NULL);
3366 g_io_channel_unref(chr_info->io_channel);
3369 BT_INFO("Removing char_info from the list");
3370 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
3371 bluetooth_characteristic_info_free(chr_info);
3375 BT_EXPORT_API int bluetooth_gatt_server_read_phy(const bluetooth_device_address_t *device_address)
3379 BT_CHECK_PARAMETER(device_address, return);
3380 BT_CHECK_ENABLED(return);
3383 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3385 g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t));
3387 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_READ_PHY,
3388 in_param1, in_param2, in_param3, in_param4, &out_param);
3390 if (result != BLUETOOTH_ERROR_NONE)
3391 BT_INFO("GATT Server Read PHY failed result [%d]", result);
3393 BT_INFO("GATT Server Read PHY successful");
3395 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3400 BT_EXPORT_API int bluetooth_gatt_server_set_phy(const bluetooth_device_address_t *device_address,
3401 int tx_phy, int rx_phy, int phy_options)
3405 BT_CHECK_PARAMETER(device_address, return);
3406 BT_CHECK_ENABLED(return);
3408 BT_INFO("Set PHY: Tx[%d], Rx[%d], Phy_options[%d]", tx_phy, rx_phy, phy_options);
3411 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3413 g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t));
3414 g_array_append_vals(in_param2, &tx_phy, sizeof(int));
3415 g_array_append_vals(in_param3, &rx_phy, sizeof(int));
3416 g_array_append_vals(in_param4, &phy_options, sizeof(int));
3418 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SET_PHY,
3419 in_param1, in_param2, in_param3, in_param4, &out_param);
3421 if (result != BLUETOOTH_ERROR_NONE)
3422 BT_INFO("GATT Server Set PHY failed result [%d]", result);
3424 BT_INFO("GATT Server Set PHY successful");
3426 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);