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 *path)
350 BT_DBG("request found path [%s] att_handle [ %d]", path, att_handle);
351 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
352 bluetooth_gatt_acquire_notify_info_t *info = l->data;
354 if (info->att_hand == att_handle)
355 return info->write_fd;
360 static bluetooth_gatt_acquire_notify_info_t * bluetooth_get_characteristic_info_from_path(int att_handle)
364 BT_DBG("request found att_handle [ %d]", att_handle);
365 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
366 bluetooth_gatt_acquire_notify_info_t *info = l->data;
367 BT_DBG(" sid [ %d]" , info->att_hand);
368 if (info->att_hand == att_handle)
375 static void bluetooth_characteristic_info_free(bluetooth_gatt_acquire_notify_info_t *chr_info)
380 static gboolean bluetooth_gatt_write_channel_watch_cb(GIOChannel *gio,
381 GIOCondition cond, gpointer data)
385 bluetooth_gatt_acquire_notify_info_t *chr_info = (bluetooth_gatt_acquire_notify_info_t *)data;
388 BT_INFO("chr_info is NULL");
392 if (cond & G_IO_NVAL) {
393 BT_ERR("Invalid channel");
397 if (cond & (G_IO_HUP | G_IO_ERR)) {
398 BT_ERR("Error : GIOCondition %d", cond);
399 g_io_channel_shutdown(gio, TRUE, NULL);
400 g_io_channel_unref(gio);
402 if (g_slist_find(gatt_characteristic_server_notify_list, chr_info)) {
403 BT_INFO("found char_info in the list");
404 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
405 bluetooth_characteristic_info_free(chr_info);
411 if (g_slist_find(gatt_characteristic_server_notify_list, chr_info) == NULL) {
412 BT_INFO("chr_info is not in the list");
419 static int bluetooth_gatt_write_characteristics_value_to_fd_(
420 int fd, const guint8 *value, int length,
425 int att_result = BLUETOOTH_ERROR_NONE;
427 BT_CHECK_PARAMETER(value, return);
429 written = write(fd, value, length);
430 if (written != length) {
431 att_result = BLUETOOTH_ERROR_INTERNAL;
432 BT_ERR("write data failed %d is ", written);
438 #ifdef TIZEN_FEATURE_BT_HPS
439 static int __bt_send_event_to_hps(int event, GVariant *var)
441 GError *error = NULL;
442 GVariant *parameters;
443 GDBusMessage *msg = NULL;
447 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
449 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
450 GVariantBuilder *inner_builder;
451 GVariantBuilder *invalidated_builder;
453 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
454 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
456 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
458 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
460 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
461 g_variant_builder_unref(invalidated_builder);
462 g_variant_builder_unref(inner_builder);
463 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
464 GVariantBuilder *inner_builder;
465 GVariantBuilder *invalidated_builder;
467 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
468 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
470 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
472 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
474 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
475 g_variant_builder_unref(invalidated_builder);
476 g_variant_builder_unref(inner_builder);
478 g_varaiant_unref(var);
481 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
482 g_dbus_message_set_body(msg, parameters);
483 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
485 BT_ERR("D-Bus API failure: errCode[%x], \
487 error->code, error->message);
488 g_clear_error(&error);
490 return BLUETOOTH_ERROR_INTERNAL;
492 return BLUETOOTH_ERROR_NONE;
496 #ifdef TIZEN_FEATURE_BT_OTP
497 static int __bt_send_event_to_otp(int event, GVariant *var)
499 GError *error = NULL;
500 GVariant *parameters = NULL;
501 GDBusMessage *msg = NULL;
505 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
507 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
508 GVariantBuilder *inner_builder;
509 GVariantBuilder *invalidated_builder;
511 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
512 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
514 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
516 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
518 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
519 g_variant_builder_unref(invalidated_builder);
520 g_variant_builder_unref(inner_builder);
521 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
522 GVariantBuilder *inner_builder;
523 GVariantBuilder *invalidated_builder;
525 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
526 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
528 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
530 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
532 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
533 g_variant_builder_unref(invalidated_builder);
534 g_variant_builder_unref(inner_builder);
535 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
536 GVariantBuilder *inner_builder;
537 GVariantBuilder *invalidated_builder;
539 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
540 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
542 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
544 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
546 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
547 g_variant_builder_unref(invalidated_builder);
548 g_variant_builder_unref(inner_builder);
551 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
552 g_dbus_message_set_body(msg, parameters);
553 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
555 BT_ERR("D-Bus API failure: errCode[%x], \
557 error->code, error->message);
558 g_clear_error(&error);
560 return BLUETOOTH_ERROR_INTERNAL;
562 return BLUETOOTH_ERROR_NONE;
566 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
568 const gchar *object_path,
569 const gchar *interface_name,
570 const gchar *method_name,
571 GVariant *parameters,
572 GDBusMethodInvocation *invocation,
575 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
576 BT_DBG("Getting values for service, chars and descriptors");
579 GVariantBuilder *builder = NULL;
580 GVariantBuilder *inner_builder1 = NULL;
581 GVariant *svc_char = NULL;
582 GSList *char_list = NULL;
583 GSList *desc_list = NULL;
586 builder = g_variant_builder_new(G_VARIANT_TYPE("a{oa{sa{sv}}}"));
588 /* Prepare inner builder for GattService1 interface */
589 svc_index = g_slist_length(gatt_services) - 1;
590 for (; svc_index >= 0; svc_index--) {
591 GVariantBuilder *svc_builder = NULL;
592 GVariantBuilder *inner_builder = NULL;
593 struct gatt_service_info *serv_info = NULL;
595 serv_info = g_slist_nth_data(gatt_services, svc_index);
596 if (serv_info == NULL) {
597 BT_ERR("serv_info is NULL");
601 /* Prepare inner builder for GattService1 interface */
602 BT_DBG("Creating builder for service : %s", serv_info->service_uuid);
603 svc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
604 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
606 g_variant_builder_add(inner_builder, "{sv}", "UUID",
607 g_variant_new_string(serv_info->service_uuid));
608 g_variant_builder_add(inner_builder, "{sv}", "Primary",
609 g_variant_new_boolean(serv_info->is_svc_primary));
611 /* Characteristics */
612 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
614 BT_DBG("Adding Charatarisitcs list");
615 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
616 struct gatt_char_info *char_info = char_list->data;
617 g_variant_builder_add(inner_builder1, "o", char_info->char_path);
618 BT_DBG("%s", char_info->char_path);
621 svc_char = g_variant_new("ao", inner_builder1);
622 g_variant_builder_add(inner_builder, "{sv}", "Characteristics", svc_char);
623 g_variant_builder_add(svc_builder, "{sa{sv}}", GATT_SERV_INTERFACE, inner_builder);
624 g_variant_builder_add(builder, "{oa{sa{sv}}}", serv_info->serv_path, svc_builder);
625 g_variant_builder_unref(inner_builder1);
627 /* Prepare inner builder for GattCharacteristic1 interface */
628 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
629 GVariantBuilder *char_builder = NULL;
630 GVariantBuilder *inner_builder = NULL;
631 GVariantBuilder *builder1 = NULL;
632 GVariantBuilder *builder2 = NULL;
633 GVariantBuilder *builder3 = NULL;
634 GVariant *char_val = NULL;
635 GVariant *flags_val = NULL;
636 GVariant *char_desc = NULL;
637 char *unicast = NULL;
638 gboolean notify = FALSE;
640 struct gatt_char_info *char_info = char_list->data;
642 if (char_info == NULL) {
643 BT_ERR("char_info is NULL");
647 BT_DBG("Creating builder for characteristic : %s", char_info->char_uuid);
648 char_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
649 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
652 g_variant_builder_add(inner_builder, "{sv}", "UUID",
653 g_variant_new_string(char_info->char_uuid));
656 g_variant_builder_add(inner_builder, "{sv}", "Service",
657 g_variant_new("o", serv_info->serv_path));
660 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
661 if (char_info->char_value != NULL) {
662 for (i = 0; i < char_info->value_length; i++) {
663 g_variant_builder_add(builder1, "y", char_info->char_value[i]);
665 char_val = g_variant_new("ay", builder1);
666 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
670 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
671 for (i = 0; i < char_info->flags_length; i++) {
672 g_variant_builder_add(builder2, "s", char_info->char_flags[i]);
674 flags_val = g_variant_new("as", builder2);
675 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
678 g_variant_builder_add(inner_builder, "{sv}", "Notifying", g_variant_new("b", notify));
681 unicast = g_strdup("00:00:00:00:00:00");
682 g_variant_builder_add(inner_builder, "{sv}", "Unicast", g_variant_new("s", unicast));
685 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
686 BT_DBG("Adding Descriptors list");
687 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
688 struct gatt_desc_info *desc_info = desc_list->data;
689 g_variant_builder_add(builder3, "o", desc_info->desc_path);
690 BT_DBG("%s", desc_info->desc_path);
693 char_desc = g_variant_new("ao", builder3);
694 g_variant_builder_add(inner_builder, "{sv}", "Descriptors", char_desc);
695 g_variant_builder_add(char_builder, "{sa{sv}}", GATT_CHAR_INTERFACE , inner_builder);
696 g_variant_builder_add(builder, "{oa{sa{sv}}}", char_info->char_path, char_builder);
698 /*Prepare inner builder for GattDescriptor1 interface*/
699 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
700 GVariantBuilder *desc_builder = NULL;
701 GVariantBuilder *inner_builder = NULL;
702 GVariantBuilder *builder1 = NULL;
703 GVariantBuilder *builder2 = NULL;
704 GVariant *desc_val = NULL;
705 struct gatt_desc_info *desc_info = desc_list->data;
707 if (desc_info == NULL) {
708 BT_ERR("desc_info is NULL");
712 BT_DBG("Creating builder for descriptor : %s", desc_info->desc_uuid);
713 desc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
714 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
717 g_variant_builder_add(inner_builder, "{sv}", "UUID",
718 g_variant_new_string(desc_info->desc_uuid));
721 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
722 g_variant_new("o", char_info->char_path));
725 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
726 if (desc_info->desc_value != NULL) {
727 for (i = 0; i < desc_info->value_length; i++) {
728 g_variant_builder_add(builder1, "y", desc_info->desc_value[i]);
730 desc_val = g_variant_new("ay", builder1);
731 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
735 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
736 for (i = 0; i < desc_info->flags_length; i++) {
737 g_variant_builder_add(builder2, "s", desc_info->desc_flags[i]);
739 flags_val = g_variant_new("as", builder2);
740 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
742 g_variant_builder_add(desc_builder, "{sa{sv}}", GATT_DESC_INTERFACE,
744 g_variant_builder_add(builder, "{oa{sa{sv}}}", desc_info->desc_path,
747 /* unref descriptor builder pointers */
748 g_variant_builder_unref(builder1);
749 g_variant_builder_unref(builder2);
750 g_variant_builder_unref(inner_builder);
751 g_variant_builder_unref(desc_builder);
757 /* unref char builder pointers */
758 g_variant_builder_unref(builder1);
759 g_variant_builder_unref(builder2);
760 g_variant_builder_unref(builder3);
761 g_variant_builder_unref(inner_builder);
762 g_variant_builder_unref(char_builder);
765 /* unref service builder pointers */
766 g_variant_builder_unref(inner_builder);
767 g_variant_builder_unref(svc_builder);
770 /* Return builder as method reply */
771 BT_DBG("Sending gatt service builder values to Bluez");
772 g_dbus_method_invocation_return_value(invocation,
773 g_variant_new("(a{oa{sa{sv}}})", builder));
774 g_variant_builder_unref(builder);
778 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
782 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
783 struct gatt_service_info *serv_info = l1->data;
785 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
786 struct gatt_char_info *char_info = l2->data;
788 if (g_strcmp0(char_info->char_path, char_path) == 0)
792 BT_ERR("Gatt service not found");
796 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
798 GSList *l1, *l2, *l3;
800 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
801 struct gatt_service_info *serv_info = l1->data;
803 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
804 struct gatt_char_info *char_info = l2->data;
806 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
807 struct gatt_desc_info *desc_info = l3->data;
809 if (g_strcmp0(desc_info->desc_path, desc_path) == 0)
814 BT_ERR("Gatt service not found");
818 static void __bt_gatt_char_method_call(GDBusConnection *connection,
820 const gchar *object_path,
821 const gchar *interface_name,
822 const gchar *method_name,
823 GVariant *parameters,
824 GDBusMethodInvocation *invocation,
828 if (g_strcmp0(method_name, "ReadValue") == 0) {
832 bt_gatt_read_req_t read_req = {0, };
833 bt_user_info_t *user_info = NULL;
834 struct gatt_req_info *req_info = NULL;
835 struct gatt_service_info *svc_info = NULL;
836 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
837 GVariant *param = NULL;
840 BT_DBG("Application path = %s", object_path);
841 BT_DBG("Sender = %s", sender);
843 user_info = _bt_get_user_data(BT_COMMON);
844 if (user_info == NULL) {
845 BT_INFO("No callback is set for %s", object_path);
846 g_dbus_method_invocation_return_value(invocation, NULL);
850 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
851 if (svc_info == NULL) {
852 BT_ERR("Coudn't find service for %s", object_path);
853 g_dbus_method_invocation_return_value(invocation, NULL);
857 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
858 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
860 read_req.att_handle = (char *)object_path;
861 read_req.address = addr;
862 read_req.req_id = req_id;
863 read_req.offset = offset;
864 read_req.service_handle = svc_info->serv_path;
866 /* Store requets information */
867 req_info = g_new0(struct gatt_req_info, 1);
868 req_info->attr_path = g_strdup(object_path);
869 req_info->svc_path = g_strdup(read_req.service_handle);
870 req_info->request_id = req_id;
871 req_info->offset = offset;
872 req_info->context = invocation;
873 gatt_requests = g_slist_append(gatt_requests, req_info);
875 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
876 param = g_variant_new("(sssyq)",
878 read_req.service_handle,
882 #ifdef TIZEN_FEATURE_BT_HPS
883 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
885 #ifdef TIZEN_FEATURE_BT_OTP
886 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
890 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
891 BLUETOOTH_ERROR_NONE, &read_req,
892 user_info->cb, user_info->user_data);
894 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
895 GVariant *var = NULL;
899 gboolean response_needed = FALSE;
900 bt_gatt_value_change_t value_change = {0, };
901 bt_user_info_t *user_info = NULL;
903 struct gatt_service_info *svc_info = NULL;
904 struct gatt_req_info *req_info = NULL;
905 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
906 GVariant *param = NULL;
909 BT_DBG("WriteValue");
910 BT_DBG("Application path = %s", object_path);
911 BT_DBG("Sender = %s", sender);
913 g_variant_get(parameters, "(&suqb@ay)",
914 &addr, &req_id, &offset, &response_needed, &var);
915 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
917 user_info = _bt_get_user_data(BT_COMMON);
919 BT_INFO("No callback is set for %s", object_path);
920 g_variant_unref(var);
922 g_dbus_method_invocation_return_value(invocation, NULL);
924 g_object_unref(invocation);
928 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
929 if (svc_info == NULL) {
930 BT_ERR("Coudn't find service for %s", object_path);
931 g_variant_unref(var);
933 g_dbus_method_invocation_return_value(invocation, NULL);
935 g_object_unref(invocation);
939 value_change.att_handle = (char *)object_path;
940 value_change.address = addr;
941 value_change.service_handle = svc_info->serv_path;
942 value_change.offset = offset;
943 value_change.req_id = req_id;
944 value_change.response_needed = response_needed;
946 len = g_variant_get_size(var);
950 value_change.att_value = (guint8 *)g_malloc(len);
952 data = (char *)g_variant_get_data(var);
953 memcpy(value_change.att_value, data, len);
955 value_change.val_len = len;
957 if (response_needed) {
958 /* Store requets information */
959 req_info = g_new0(struct gatt_req_info, 1);
960 req_info->attr_path = g_strdup(object_path);
961 req_info->svc_path = g_strdup(value_change.service_handle);
962 req_info->request_id = req_id;
963 req_info->offset = offset;
964 req_info->context = invocation;
965 gatt_requests = g_slist_append(gatt_requests, req_info);
967 g_object_unref(invocation);
970 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
973 svc_path = g_strdup(svc_info->serv_path);
974 param = g_variant_new("(sssyq@ay)",
981 #ifdef TIZEN_FEATURE_BT_HPS
982 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
984 #ifdef TIZEN_FEATURE_BT_OTP
985 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
993 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
994 BLUETOOTH_ERROR_NONE, &value_change,
995 user_info->cb, user_info->user_data);
997 g_free(value_change.att_value);
998 g_variant_unref(var);
1000 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1001 bt_user_info_t *user_info = NULL;
1002 bt_gatt_char_notify_change_t notify_change = {0, };
1003 #if TIZEN_FEATURE_BT_OTP
1004 GVariant *param = NULL;
1006 BT_DBG("StartNotify");
1007 user_info = _bt_get_user_data(BT_COMMON);
1008 if (user_info != NULL) {
1009 struct gatt_service_info *svc_info = NULL;
1010 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1012 notify_change.service_handle = svc_info->serv_path;
1013 notify_change.att_handle = (char *)object_path;
1014 notify_change.att_notify = TRUE;
1015 #if TIZEN_FEATURE_BT_OTP
1016 param = g_variant_new("(ssb)",
1017 notify_change.att_handle,
1018 notify_change.service_handle,
1019 notify_change.att_notify);
1020 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1022 _bt_common_event_cb(
1023 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1024 BLUETOOTH_ERROR_NONE, ¬ify_change,
1025 user_info->cb, user_info->user_data);
1028 g_object_unref(invocation);
1030 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1031 bt_user_info_t *user_info = NULL;
1032 bt_gatt_char_notify_change_t notify_change = {0, };
1033 #if TIZEN_FEATURE_BT_OTP
1034 GVariant *param = NULL;
1036 BT_DBG("StopNotify");
1037 user_info = _bt_get_user_data(BT_COMMON);
1038 if (user_info != NULL) {
1039 struct gatt_service_info *svc_info = NULL;
1040 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1042 notify_change.service_handle = svc_info->serv_path;
1043 notify_change.att_handle = (char *)object_path;
1044 notify_change.att_notify = FALSE;
1045 #if TIZEN_FEATURE_BT_OTP
1046 param = g_variant_new("(ssb)",
1047 notify_change.att_handle,
1048 notify_change.service_handle,
1049 notify_change.att_notify);
1050 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1052 _bt_common_event_cb(
1053 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1054 BLUETOOTH_ERROR_NONE, ¬ify_change,
1055 user_info->cb, user_info->user_data);
1058 g_object_unref(invocation);
1060 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1062 bt_gatt_indicate_confirm_t confirm = {0, };
1063 bt_user_info_t *user_info = NULL;
1064 gboolean complete = FALSE;
1065 struct gatt_service_info *svc_info = NULL;
1067 BT_DBG("IndicateConfirm");
1068 BT_DBG("Application path = %s", object_path);
1069 BT_DBG("Sender = %s", sender);
1071 g_variant_get(parameters, "(&sb)", &addr, &complete);
1072 BT_DBG("Remote Device address number = %s", addr);
1074 confirm.att_handle = (char *)object_path;
1075 confirm.address = addr;
1076 confirm.complete = complete;
1078 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1079 if (svc_info != NULL) {
1080 confirm.service_handle = svc_info->serv_path;
1082 user_info = _bt_get_user_data(BT_COMMON);
1083 if (user_info != NULL) {
1084 _bt_common_event_cb(
1085 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1086 BLUETOOTH_ERROR_NONE, &confirm,
1087 user_info->cb, user_info->user_data);
1092 g_dbus_method_invocation_return_value(invocation, NULL);
1095 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1096 const gchar *sender,
1097 const gchar *object_path,
1098 const gchar *interface_name,
1099 const gchar *method_name,
1100 GVariant *parameters,
1101 GDBusMethodInvocation *invocation,
1104 if (g_strcmp0(method_name, "ReadValue") == 0) {
1108 bt_gatt_read_req_t read_req = {0, };
1109 bt_user_info_t *user_info = NULL;
1110 struct gatt_req_info *req_info = NULL;
1111 struct gatt_service_info *svc_info = NULL;
1113 BT_DBG("ReadValue");
1114 BT_DBG("Application path = %s", object_path);
1115 BT_DBG("Sender = %s", sender);
1117 user_info = _bt_get_user_data(BT_COMMON);
1118 if (user_info == NULL) {
1119 BT_INFO("No callback is set for %s", object_path);
1120 g_dbus_method_invocation_return_value(invocation, NULL);
1124 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1125 if (svc_info == NULL) {
1126 BT_ERR("Coudn't find service for %s", object_path);
1127 g_dbus_method_invocation_return_value(invocation, NULL);
1131 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1132 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1134 read_req.att_handle = (char *)object_path;
1135 read_req.address = addr;
1136 read_req.req_id = req_id;
1137 read_req.offset = offset;
1138 read_req.service_handle = svc_info->serv_path;
1140 /* Store requets information */
1141 req_info = g_new0(struct gatt_req_info, 1);
1142 req_info->attr_path = g_strdup(object_path);
1143 req_info->svc_path = g_strdup(read_req.service_handle);
1144 req_info->request_id = req_id;
1145 req_info->offset = offset;
1146 req_info->context = invocation;
1147 gatt_requests = g_slist_append(gatt_requests, req_info);
1149 _bt_common_event_cb(
1150 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1151 BLUETOOTH_ERROR_NONE, &read_req,
1152 user_info->cb, user_info->user_data);
1155 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1156 GVariant *var = NULL;
1160 gboolean response_needed = FALSE;
1161 bt_gatt_value_change_t value_change = {0, };
1162 bt_user_info_t *user_info = NULL;
1164 struct gatt_service_info *svc_info = NULL;
1165 struct gatt_req_info *req_info = NULL;
1167 BT_DBG("WriteValue");
1168 BT_DBG("Application path = %s", object_path);
1169 BT_DBG("Sender = %s", sender);
1171 g_variant_get(parameters, "(&suqb@ay)",
1172 &addr, &req_id, &offset, &response_needed, &var);
1173 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1175 user_info = _bt_get_user_data(BT_COMMON);
1176 if (user_info == NULL) {
1177 BT_INFO("No callback is set for %s", object_path);
1178 g_variant_unref(var);
1179 if (response_needed)
1180 g_dbus_method_invocation_return_value(invocation, NULL);
1182 g_object_unref(invocation);
1186 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1187 if (svc_info == NULL) {
1188 BT_ERR("Coudn't find service for %s", object_path);
1189 g_variant_unref(var);
1190 if (response_needed)
1191 g_dbus_method_invocation_return_value(invocation, NULL);
1193 g_object_unref(invocation);
1197 value_change.att_handle = (char *)object_path;
1198 value_change.address = addr;
1199 value_change.service_handle = svc_info->serv_path;
1200 value_change.offset = offset;
1201 value_change.req_id = req_id;
1202 value_change.response_needed = response_needed;
1204 len = g_variant_get_size(var);
1208 value_change.att_value = (guint8 *)g_malloc(len);
1210 data = (char *)g_variant_get_data(var);
1211 memcpy(value_change.att_value, data, len);
1213 value_change.val_len = len;
1215 if (response_needed) {
1216 /* Store requets information */
1217 req_info = g_new0(struct gatt_req_info, 1);
1218 req_info->attr_path = g_strdup(object_path);
1219 req_info->svc_path = g_strdup(value_change.service_handle);
1220 req_info->request_id = req_id;
1221 req_info->offset = offset;
1222 req_info->context = invocation;
1223 gatt_requests = g_slist_append(gatt_requests, req_info);
1225 g_object_unref(invocation);
1228 _bt_common_event_cb(
1229 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1230 BLUETOOTH_ERROR_NONE, &value_change,
1231 user_info->cb, user_info->user_data);
1233 g_free(value_change.att_value);
1234 g_variant_unref(var);
1239 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1242 GError *error = NULL;
1243 GVariantBuilder *array_builder;
1245 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1246 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1247 g_variant_builder_add(array_builder, "s", interface);
1249 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1250 "org.freedesktop.Dbus.Objectmanager",
1251 "InterfacesRemoved",
1252 g_variant_new("(oas)",
1253 object_path, array_builder),
1257 if (error != NULL) {
1258 /* dbus gives error cause */
1259 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1260 error->code, error->message);
1261 g_clear_error(&error);
1264 g_variant_builder_unref(array_builder);
1269 static const GDBusInterfaceVTable desc_interface_vtable = {
1270 __bt_gatt_desc_method_call,
1276 static const GDBusInterfaceVTable char_interface_vtable = {
1277 __bt_gatt_char_method_call,
1283 static const GDBusInterfaceVTable serv_interface_vtable = {
1290 static const GDBusInterfaceVTable manager_interface_vtable = {
1291 __bt_gatt_manager_method_call,
1297 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1298 const gchar *introspection_data)
1301 GDBusNodeInfo *node_info = NULL;
1303 if (introspection_data == NULL)
1307 BT_DBG("Create new node info");
1308 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1311 BT_ERR("Unable to create node: %s", err->message);
1312 g_clear_error(&err);
1319 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1320 const char *service_path)
1324 for (l = gatt_services; l != NULL; l = l->next) {
1325 struct gatt_service_info *info = l->data;
1327 if (g_strcmp0(info->serv_path, service_path) == 0)
1330 BT_ERR("Gatt service not found");
1334 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1335 const char *service_path, const char *char_path)
1339 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1340 struct gatt_service_info *serv_info = l1->data;
1342 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1344 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1345 struct gatt_char_info *char_info = l2->data;
1347 if (g_strcmp0(char_info->char_path, char_path) == 0)
1350 BT_ERR("Gatt characteristic not found");
1354 BT_ERR("Gatt service not found");
1358 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1359 const char *serv_path, const char *char_path,
1360 const char *desc_path)
1362 GSList *l1, *l2, *l3;
1364 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1365 struct gatt_service_info *serv_info = l1->data;
1367 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1368 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1369 struct gatt_char_info *char_info = l2->data;
1371 if (g_strcmp0(char_info->char_path, char_path) == 0) {
1372 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1373 struct gatt_desc_info *desc_info = l3->data;
1374 if (g_strcmp0(desc_info->desc_path,
1383 BT_ERR("Gatt descriptor not found");
1387 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1391 for (l = gatt_requests; l != NULL; l = l->next) {
1392 struct gatt_req_info *req_info = l->data;
1394 if (req_info && req_info->request_id == request_id)
1397 BT_ERR("Gatt Request not found");
1401 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1402 const gchar *path, const gchar *interface)
1407 g_conn = _bt_get_system_shared_conn();
1409 BT_ERR("Unable to get connection");
1413 proxy = g_dbus_proxy_new_sync(g_conn,
1414 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1416 interface, NULL, &err);
1420 BT_ERR("Unable to create proxy: %s", err->message);
1421 g_clear_error(&err);
1425 manager_gproxy = proxy;
1430 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1431 const gchar *path, const gchar *interface)
1433 return (manager_gproxy) ? manager_gproxy :
1434 __bt_gatt_gdbus_init_manager_proxy(service,
1438 static gboolean __bt_gatt_is_service_registered(const char *service_path)
1440 struct gatt_service_info *svc_info = NULL;
1442 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1444 if (svc_info != NULL) {
1445 BT_DBG("Return the state of the gatt service %d",
1446 svc_info->is_svc_registered);
1447 return svc_info->is_svc_registered;
1450 BT_DBG("gatt service info is NULL");
1454 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1456 GError *error = NULL;
1458 GVariantIter *iter = NULL;
1459 const gchar *key = NULL;
1460 GVariant *value = NULL;
1461 const gchar *service = NULL;
1462 const gchar *characteristic = NULL;
1463 const gchar *descriptor = NULL;
1467 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1469 if (result == NULL) {
1470 BT_ERR("Dbus-RPC is failed");
1471 if (error != NULL) {
1472 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1473 error->code, error->message);
1474 g_clear_error(&error);
1477 char *char_cmp = NULL;
1478 g_variant_get(result, "(a{sv})", &iter);
1479 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1481 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1482 if (g_strcmp0(key, "Service") == 0) {
1483 service = g_variant_get_string(value, NULL);
1484 BT_DBG("Service %s", service);
1485 } else if (g_strcmp0(key, char_cmp) == 0) {
1486 characteristic = g_variant_get_string(value, NULL);
1488 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1489 BT_DBG("%s", characteristic);
1490 } else if (g_strcmp0(key, "Descriptor") == 0) {
1491 descriptor = g_variant_get_string(value, NULL);
1492 BT_DBG("Descriptor %s", descriptor);
1495 g_variant_iter_free(iter);
1497 /* TODO: Store the service informationa and
1498 * Send respponse to CAPI layer. */
1500 g_variant_unref(result);
1505 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1507 BT_INFO("RegisterApplication is completed");
1509 GError *error = NULL;
1512 if (register_cancel) {
1513 g_object_unref(register_cancel);
1514 register_cancel = NULL;
1517 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1518 if (result == NULL) {
1519 BT_ERR("Dbus-RPC is failed");
1520 if (error != NULL) {
1521 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1522 error->code, error->message);
1523 g_clear_error(&error);
1525 is_server_started = false;
1527 g_variant_unref(result);
1531 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1533 GDBusProxy *proxy = NULL;
1535 if (is_server_started) {
1539 if (app_path == NULL) {
1540 BT_ERR("app_path is NULL");
1541 return BLUETOOTH_ERROR_INTERNAL;
1544 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1545 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1546 if (proxy == NULL) {
1547 BT_ERR("proxy is NULL");
1548 return BLUETOOTH_ERROR_INTERNAL;
1551 BT_INFO("UnregisterApplication");
1553 /* Async Call to Unregister Service */
1554 ret = g_dbus_proxy_call_sync(proxy, "UnregisterApplication",
1555 g_variant_new("(o)", app_path), G_DBUS_CALL_FLAGS_NONE, -1,
1558 BT_ERR("dBUS-RPC is failed");
1560 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1561 err->code, err->message);
1562 if (err->code == G_DBUS_ERROR_SERVICE_UNKNOWN ||
1563 g_strrstr(err->message, BT_ERROR_DOES_NOT_EXIST)) {
1564 g_clear_error(&err);
1567 g_clear_error(&err);
1569 return BLUETOOTH_ERROR_INTERNAL;
1571 g_variant_unref(ret);
1574 is_server_started = false;
1576 BT_INFO("UnregisterApplication is completed");
1578 return BLUETOOTH_ERROR_NONE;
1581 BT_INFO("GATT server not started");
1582 return BLUETOOTH_ERROR_NONE;
1585 BT_EXPORT_API int bluetooth_gatt_init(void)
1587 GError *error = NULL;
1588 GDBusNodeInfo *node_info = NULL;
1590 if (app_path != NULL) {
1591 BT_ERR("app path already exists! initialized");
1592 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1595 g_conn = _bt_get_system_shared_conn();
1597 BT_ERR("Unable to get connection");
1601 if (owner_id == 0) {
1602 gchar *name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
1603 BT_DBG("well-known name: %s", name);
1605 owner_id = g_bus_own_name_on_connection(g_conn, name,
1606 G_BUS_NAME_OWNER_FLAGS_NONE,
1607 NULL, NULL, NULL, NULL);
1610 BT_DBG("owner_id is [%d]", owner_id);
1612 app_path = g_strdup_printf("/com/%d", getpid());
1616 /* Register ObjectManager interface */
1617 node_info = __bt_gatt_create_method_node_info(
1618 manager_introspection_xml);
1619 if (node_info == NULL) {
1620 BT_ERR("failed to get node info");
1624 if (manager_id == 0) {
1625 BT_INFO("manager_id does not exists");
1627 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1628 node_info->interfaces[0],
1629 &manager_interface_vtable,
1630 NULL, NULL, &error);
1632 g_dbus_node_info_unref(node_info);
1633 if (manager_id == 0) {
1634 BT_ERR("failed to register: %s", error->message);
1635 g_error_free(error);
1639 return BLUETOOTH_ERROR_NONE;
1643 g_bus_unown_name(owner_id);
1650 return BLUETOOTH_ERROR_INTERNAL;
1653 BT_EXPORT_API int bluetooth_gatt_deinit()
1655 int ret = BLUETOOTH_ERROR_NONE;
1657 if (register_cancel) {
1658 g_cancellable_cancel(register_cancel);
1659 g_object_unref(register_cancel);
1660 register_cancel = NULL;
1663 if (owner_id == 0) {
1664 BT_ERR("owner_id is zero");
1665 return BLUETOOTH_ERROR_NOT_FOUND;
1668 BT_DBG("Removing all registered gatt services");
1669 bluetooth_gatt_delete_services();
1671 /* Unregister the exported interface for object manager */
1673 g_dbus_connection_unregister_object(g_conn, manager_id);
1677 ret = bluetooth_gatt_unregister_application();
1678 if (ret != BLUETOOTH_ERROR_NONE) {
1679 BT_ERR("Fail to unregister application");
1682 g_bus_unown_name(owner_id);
1688 if (manager_gproxy) {
1689 g_object_unref(manager_gproxy);
1690 manager_gproxy = NULL;
1697 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1700 GError *error = NULL;
1702 GDBusNodeInfo *node_info;
1704 GVariantBuilder *builder = NULL;
1705 GVariantBuilder *builder1 = NULL;
1706 GVariantBuilder *inner_builder = NULL;
1707 gboolean svc_primary = TRUE;
1708 struct gatt_service_info *serv_info = NULL;
1710 node_info = __bt_gatt_create_method_node_info(
1711 service_introspection_xml);
1712 if (node_info == NULL)
1713 return BLUETOOTH_ERROR_INTERNAL;
1715 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1716 BT_DBG("gatt service path is [%s]", path);
1718 object_id = g_dbus_connection_register_object(g_conn, path,
1719 node_info->interfaces[0],
1720 &serv_interface_vtable,
1721 NULL, NULL, &error);
1722 g_dbus_node_info_unref(node_info);
1724 if (object_id == 0) {
1725 BT_ERR("failed to register: %s", error->message);
1726 g_error_free(error);
1729 return BLUETOOTH_ERROR_INTERNAL;
1732 /* Add object_id/gatt service information; it's required at the time of
1733 * service unregister and Getmanagedobjects
1735 serv_info = g_new0(struct gatt_service_info, 1);
1737 serv_info->serv_path = g_strdup(path);
1738 serv_info->serv_id = object_id;
1739 serv_info->service_uuid = g_strdup(svc_uuid);
1740 serv_info->is_svc_registered = FALSE;
1741 serv_info->is_svc_primary = svc_primary;
1743 gatt_services = g_slist_append(gatt_services, serv_info);
1745 /* emit interfacesadded signal here for service path */
1746 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1747 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1749 g_variant_builder_add(inner_builder, "{sv}",
1750 "UUID", g_variant_new_string(svc_uuid));
1752 g_variant_builder_add(inner_builder, "{sv}",
1753 "Primary", g_variant_new_boolean(svc_primary));
1755 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1757 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1758 g_variant_new("ao", builder1));
1760 g_variant_builder_add(builder, "{sa{sv}}",
1761 GATT_SERV_INTERFACE, inner_builder);
1763 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1764 "org.freedesktop.Dbus.ObjectManager",
1766 g_variant_new("(oa{sa{sv}})",
1769 if (error != NULL) {
1770 /* dbus gives error cause */
1771 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1772 error->code, error->message);
1773 g_clear_error(&error);
1778 *svc_path = g_strdup(path);
1781 g_variant_builder_unref(inner_builder);
1782 g_variant_builder_unref(builder);
1783 g_variant_builder_unref(builder1);
1785 return BLUETOOTH_ERROR_NONE;
1788 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1789 const char *svc_path, const char *char_uuid,
1790 bt_gatt_permission_t permissions,
1791 bt_gatt_characteristic_property_t properties,
1795 GError *error = NULL;
1797 GDBusNodeInfo *node_info;
1799 GVariantBuilder *builder = NULL;
1800 GVariantBuilder *inner_builder = NULL;
1801 struct gatt_service_info *serv_info = NULL;
1802 struct gatt_char_info *char_info = NULL;
1803 GVariantBuilder *builder2 = NULL;
1804 GVariantBuilder *builder3 = NULL;
1805 GVariant *flags_val = NULL;
1807 char *char_flags[NUMBER_OF_FLAGS];
1812 new_service = FALSE;
1815 BT_DBG("gatt svc_path path is [%s]", svc_path);
1816 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1817 if (serv_info == NULL)
1818 return BLUETOOTH_ERROR_INVALID_PARAM;
1820 node_info = __bt_gatt_create_method_node_info(
1821 characteristics_introspection_xml);
1822 if (node_info == NULL)
1823 return BLUETOOTH_ERROR_INTERNAL;
1825 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1826 BT_DBG("gatt characteristic path is [%s]", path);
1828 object_id = g_dbus_connection_register_object(g_conn, path,
1829 node_info->interfaces[0],
1830 &char_interface_vtable,
1831 NULL, NULL, &error);
1832 g_dbus_node_info_unref(node_info);
1834 if (object_id == 0) {
1835 BT_ERR("failed to register: %s", error->message);
1836 g_error_free(error);
1839 return BLUETOOTH_ERROR_INTERNAL;
1842 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1843 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1844 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1845 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1846 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1847 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1848 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1849 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1851 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1853 char_info = g_new0(struct gatt_char_info, 1);
1855 char_info->char_path = g_strdup(path);
1856 char_info->char_id = object_id;
1857 char_info->char_uuid = g_strdup(char_uuid);
1859 for (i = 0; i < flag_count; i++)
1860 char_info->char_flags[i] = char_flags[i];
1863 char_info->flags_length = flag_count;
1865 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1867 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1868 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1870 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1871 g_variant_new("s", char_uuid));
1872 g_variant_builder_add(inner_builder, "{sv}", "Service",
1873 g_variant_new("o", svc_path));
1875 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1877 for (i = 0; i < flag_count; i++)
1878 g_variant_builder_add(builder2, "s", char_flags[i]);
1880 flags_val = g_variant_new("as", builder2);
1881 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1884 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1886 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1887 g_variant_new("ao", builder3));
1889 g_variant_builder_add(builder, "{sa{sv}}",
1890 GATT_CHAR_INTERFACE,
1893 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1894 "org.freedesktop.Dbus.ObjectManager",
1896 g_variant_new("(oa{sa{sv}})",
1900 /* dBUS gives error cause */
1901 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1902 error->code, error->message);
1903 g_clear_error(&error);
1906 *char_path = g_strdup(path);
1912 g_variant_builder_unref(inner_builder);
1913 g_variant_builder_unref(builder);
1914 g_variant_builder_unref(builder2);
1915 g_variant_builder_unref(builder3);
1917 return BLUETOOTH_ERROR_NONE;
1920 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1921 const char *characteristic, const char *char_value,
1924 gchar **line_argv = NULL;
1925 char *serv_path = NULL;
1926 struct gatt_char_info *char_info = NULL;
1927 GVariantBuilder *builder1 = NULL;
1928 GVariantBuilder *builder = NULL;
1929 GVariantBuilder *inner_builder = NULL;
1930 GVariant *char_val = NULL;
1931 GError *error = NULL;
1933 int res = BLUETOOTH_ERROR_NONE;
1935 line_argv = g_strsplit_set(characteristic, "/", 0);
1936 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1938 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1940 if (char_info == NULL) {
1941 /* Fix : RESOURCE_LEAK */
1942 res = BLUETOOTH_ERROR_INVALID_PARAM;
1946 char_info->value_length = value_length;
1948 char_info->char_value = (char *)malloc(value_length);
1949 /* Fix : NULL_RETURNS */
1950 if (char_info->char_value == NULL) {
1951 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1955 for (i = 0; i < value_length; i++)
1956 char_info->char_value[i] = char_value[i];
1958 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1959 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1961 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1963 for (i = 0; i < value_length; i++)
1964 g_variant_builder_add(builder1, "y", char_value[i]);
1966 char_val = g_variant_new("ay", builder1);
1967 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1969 g_variant_builder_add(builder, "{sa{sv}}",
1970 GATT_CHAR_INTERFACE,
1973 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1974 "org.freedesktop.Dbus.ObjectManager",
1976 g_variant_new("(oa{sa{sv}})",
1977 char_info->char_path, builder),
1981 /* dBUS gives error cause */
1982 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1983 error->code, error->message);
1984 g_clear_error(&error);
1986 g_variant_builder_unref(inner_builder);
1987 g_variant_builder_unref(builder);
1988 g_variant_builder_unref(builder1);
1990 g_strfreev(line_argv);
1996 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
1997 const char *char_path, const char *desc_uuid,
1998 bt_gatt_permission_t permissions,
2001 static int desc_id = 1;
2002 GError *error = NULL;
2004 GDBusNodeInfo *node_info;
2006 GVariantBuilder *builder = NULL;
2007 GVariantBuilder *inner_builder = NULL;
2008 struct gatt_char_info *char_info = NULL;
2009 struct gatt_desc_info *desc_info = NULL;
2010 gchar **line_argv = NULL;
2012 GVariantBuilder *builder2 = NULL;
2013 GVariant *flags_val = NULL;
2015 char *desc_flags[NUMBER_OF_FLAGS];
2023 line_argv = g_strsplit_set(char_path, "/", 0);
2024 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2026 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2027 if (char_info == NULL) {
2028 g_strfreev(line_argv);
2030 return BLUETOOTH_ERROR_INVALID_PARAM;
2033 node_info = __bt_gatt_create_method_node_info(
2034 descriptor_introspection_xml);
2035 if (node_info == NULL) {
2036 g_strfreev(line_argv);
2038 return BLUETOOTH_ERROR_INTERNAL;
2041 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2042 BT_DBG("gatt descriptor path is [%s]", path);
2044 object_id = g_dbus_connection_register_object(g_conn, path,
2045 node_info->interfaces[0],
2046 &desc_interface_vtable,
2047 NULL, NULL, &error);
2048 g_dbus_node_info_unref(node_info);
2050 if (object_id == 0) {
2051 BT_ERR("failed to register: %s", error->message);
2052 g_error_free(error);
2054 g_strfreev(line_argv);
2057 return BLUETOOTH_ERROR_INTERNAL;
2060 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2062 desc_info = g_new0(struct gatt_desc_info, 1);
2064 desc_info->desc_path = g_strdup(path);
2065 desc_info->desc_id = object_id;
2066 desc_info->desc_uuid = g_strdup(desc_uuid);
2068 for (i = 0; i < flag_count; i++)
2069 desc_info->desc_flags[i] = desc_flags[i];
2071 desc_info->flags_length = flag_count;
2073 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2075 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2076 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2078 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2079 g_variant_new("s", desc_uuid));
2080 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2081 g_variant_new("o", char_path));
2083 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2085 for (i = 0; i < flag_count; i++)
2086 g_variant_builder_add(builder2, "s", desc_flags[i]);
2088 flags_val = g_variant_new("as", builder2);
2089 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2092 g_variant_builder_add(builder, "{sa{sv}}",
2093 GATT_DESC_INTERFACE,
2096 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2097 "org.freedesktop.Dbus.ObjectManager",
2099 g_variant_new("(oa{sa{sv}})",
2103 /* dBUS gives error cause */
2104 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2105 error->code, error->message);
2106 g_clear_error(&error);
2109 *desc_path = g_strdup(path);
2113 g_strfreev(line_argv);
2114 g_variant_builder_unref(inner_builder);
2115 g_variant_builder_unref(builder);
2116 g_variant_builder_unref(builder2);
2118 return BLUETOOTH_ERROR_NONE;
2121 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2122 const char *desc_path, const char *desc_value,
2125 GError *error = NULL;
2126 GVariantBuilder *builder = NULL;
2127 GVariantBuilder *inner_builder = NULL;
2128 GVariantBuilder *builder1 = NULL;
2129 struct gatt_desc_info *desc_info = NULL;
2130 gchar **line_argv = NULL;
2132 GVariant *desc_val = NULL;
2133 char *serv_path = NULL;
2136 line_argv = g_strsplit_set(desc_path, "/", 0);
2137 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2138 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2140 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2142 /* Free the allocated memory */
2143 g_strfreev(line_argv);
2147 /* Fix : NULL_RETURNS */
2148 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2150 desc_info->desc_value = (char *)malloc(value_length);
2152 /* Fix : NULL_RETURNS */
2153 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2155 for (i = 0; i < value_length; i++)
2156 desc_info->desc_value[i] = desc_value[i];
2158 desc_info->value_length = value_length;
2160 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2161 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2163 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2165 for (i = 0; i < value_length; i++)
2166 g_variant_builder_add(builder1, "y", desc_value[i]);
2168 desc_val = g_variant_new("ay", builder1);
2169 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2171 g_variant_builder_add(builder, "{sa{sv}}",
2172 GATT_DESC_INTERFACE,
2175 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2176 "org.freedesktop.Dbus.ObjectManager",
2178 g_variant_new("(oa{sa{sv}})",
2179 desc_info->desc_path, builder),
2182 if (error != NULL) {
2183 BT_ERR("D-Bus API failure: errCode[%x], \
2185 error->code, error->message);
2186 g_clear_error(&error);
2189 g_variant_builder_unref(inner_builder);
2190 g_variant_builder_unref(builder);
2191 g_variant_builder_unref(builder1);
2193 return BLUETOOTH_ERROR_NONE;
2196 int bluetooth_gatt_get_service(const char *svc_uuid)
2198 GDBusProxy *proxy = NULL;
2201 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2202 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2204 return BLUETOOTH_ERROR_INTERNAL;
2206 uuid = g_strdup(svc_uuid);
2208 g_dbus_proxy_call(proxy,
2210 g_variant_new("(s)",
2212 G_DBUS_CALL_FLAGS_NONE, -1,
2214 (GAsyncReadyCallback) get_service_cb,
2219 return BLUETOOTH_ERROR_NONE;
2222 BT_EXPORT_API int bluetooth_gatt_register_service(const char *svc_path)
2224 struct gatt_service_info *svc_info = NULL;
2226 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2227 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2228 BT_ERR("Don't have aprivilege to use this API");
2229 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2232 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2233 if (svc_info == NULL) {
2234 BT_ERR("Cannot find service [%s]", svc_path);
2235 return BLUETOOTH_ERROR_INTERNAL;
2237 svc_info->is_svc_registered = TRUE;
2239 return BLUETOOTH_ERROR_NONE;
2242 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2244 GDBusProxy *proxy = NULL;
2246 if (!is_server_started) {
2247 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2248 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2249 BT_ERR("Don't have aprivilege to use this API");
2250 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2253 if (g_slist_length(gatt_services) == 0) {
2254 BT_ERR("There is no registered service");
2255 return BLUETOOTH_ERROR_INTERNAL;
2258 if (app_path == NULL) {
2259 BT_ERR("app_path is NULL");
2260 return BLUETOOTH_ERROR_INTERNAL;
2263 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2264 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2265 if (proxy == NULL) {
2266 BT_ERR("proxy is NULL");
2267 return BLUETOOTH_ERROR_INTERNAL;
2270 BT_INFO("RegisterApplication");
2272 if (register_cancel) {
2273 g_cancellable_cancel(register_cancel);
2274 g_object_unref(register_cancel);
2276 register_cancel = g_cancellable_new();
2278 g_dbus_proxy_call(proxy, "RegisterApplication",
2279 g_variant_new("(oa{sv})", app_path, NULL),
2280 G_DBUS_CALL_FLAGS_NONE, -1, register_cancel,
2281 (GAsyncReadyCallback)register_application_cb, NULL);
2283 is_server_started = true;
2285 return BLUETOOTH_ERROR_NONE;
2288 BT_INFO("Already RegisterApplication");
2290 return BLUETOOTH_ERROR_NONE;
2293 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2296 int ret = BLUETOOTH_ERROR_NONE;
2298 if (gatt_services == NULL) {
2299 BT_DBG("There are no registered services");
2304 for (l = gatt_services; l != NULL; ) {
2305 struct gatt_service_info *info = l->data;
2307 // In __bt_gatt_unregister_service, current node will be removed.
2308 // Go forward to next node before calling __bt_gatt_unregister_service.
2310 if (__bt_gatt_unregister_service(info) != BLUETOOTH_ERROR_NONE) {
2311 ret = BLUETOOTH_ERROR_INTERNAL;
2314 BT_INFO("All services are removed : %d", ret);
2316 g_slist_free(gatt_services);
2317 gatt_services = NULL;
2323 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2324 const char *char_path, const char* char_value,
2327 GVariantBuilder *outer_builder;
2328 GVariantBuilder *inner_builder;
2329 GVariantBuilder *invalidated_builder;
2330 GVariant *update_value = NULL;
2331 GError *error = NULL;
2332 gboolean ret = FALSE;
2333 int err = BLUETOOTH_ERROR_NONE;
2335 gchar **line_argv = NULL;
2336 gchar *serv_path = NULL;
2337 const char *value = NULL;
2339 line_argv = g_strsplit_set(char_path, "/", 0);
2340 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2342 if (!__bt_gatt_is_service_registered(serv_path)) {
2343 BT_DBG("service not registered for this characteristic");
2345 g_strfreev(line_argv);
2346 return BLUETOOTH_ERROR_INTERNAL;
2349 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2350 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2352 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2353 for (i = 0; i < value_length; i++)
2354 g_variant_builder_add(inner_builder, "y", char_value[i]);
2356 update_value = g_variant_new("ay", inner_builder);
2358 g_variant_builder_add(outer_builder, "{sv}", "Value",
2361 BT_DBG("Updating characteristic value");
2362 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2364 "org.freedesktop.DBus.Properties",
2365 "PropertiesChanged",
2366 g_variant_new("(sa{sv}as)",
2367 "org.bluez.GattCharacteristic1",
2368 outer_builder, invalidated_builder),
2372 if (error != NULL) {
2373 BT_ERR("D-Bus API failure: errCode[%x], \
2375 error->code, error->message);
2376 g_clear_error(&error);
2378 err = BLUETOOTH_ERROR_INTERNAL;
2380 struct gatt_char_info *char_info = NULL;
2382 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2383 if (char_info == NULL) {
2385 g_strfreev(line_argv);
2386 g_variant_builder_unref(inner_builder);
2387 g_variant_builder_unref(outer_builder);
2388 g_variant_builder_unref(invalidated_builder);
2390 return BLUETOOTH_ERROR_INVALID_DATA;
2393 char_info->value_length = value_length;
2395 value = (char *)realloc(char_info->char_value, value_length);
2396 if (value == NULL) {
2398 g_strfreev(line_argv);
2399 g_variant_builder_unref(inner_builder);
2400 g_variant_builder_unref(outer_builder);
2401 g_variant_builder_unref(invalidated_builder);
2403 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2406 char_info->char_value = (char*)value;
2407 if (char_info->char_value) {
2408 for (i = 0; i < value_length; i++)
2409 char_info->char_value[i] = char_value[i];
2414 g_strfreev(line_argv);
2415 g_variant_builder_unref(inner_builder);
2416 g_variant_builder_unref(outer_builder);
2417 g_variant_builder_unref(invalidated_builder);
2422 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2429 g_free(desc_info->desc_path);
2430 g_free(desc_info->desc_uuid);
2431 g_free(desc_info->desc_value);
2433 for (i = 0; i < desc_info->flags_length; i++)
2434 g_free(desc_info->desc_flags[i]);
2439 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2446 g_free(char_info->char_path);
2447 g_free(char_info->char_uuid);
2448 g_free(char_info->char_value);
2450 for (i = 0; i < char_info->flags_length; i++)
2451 g_free(char_info->char_flags[i]);
2456 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2461 g_free(svc_info->serv_path);
2462 g_free(svc_info->service_uuid);
2466 static void __desc_info_free(gpointer data, gpointer user_data)
2468 struct gatt_desc_info *desc_info = data;
2469 int *err = user_data;
2472 if (desc_info == NULL)
2475 ret = g_dbus_connection_unregister_object(g_conn, desc_info->desc_id);
2477 __bt_gatt_emit_interface_removed(desc_info->desc_path, GATT_DESC_INTERFACE);
2479 *err = BLUETOOTH_ERROR_INTERNAL;
2481 __bt_gatt_free_descriptor_info(desc_info);
2484 static void __char_info_free(gpointer data, gpointer user_data)
2486 struct gatt_char_info *char_info = data;
2487 int *err = user_data;
2490 if (char_info == NULL)
2493 g_slist_foreach(char_info->desc_data, __desc_info_free, user_data);
2494 g_slist_free(char_info->desc_data);
2495 char_info->desc_data = NULL;
2497 ret = g_dbus_connection_unregister_object(g_conn, char_info->char_id);
2499 __bt_gatt_emit_interface_removed(char_info->char_path, GATT_CHAR_INTERFACE);
2501 *err = BLUETOOTH_ERROR_INTERNAL;
2503 __bt_gatt_free_characteristic_info(char_info);
2506 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info)
2508 int ret = BLUETOOTH_ERROR_NONE;
2510 if (svc_info == NULL) {
2511 BT_ERR("svc_info is NULL");
2512 return BLUETOOTH_ERROR_NOT_FOUND;
2515 if (svc_info->is_svc_registered == FALSE) {
2516 BT_ERR("%s is not registered", svc_info->serv_path);
2517 return BLUETOOTH_ERROR_NOT_FOUND;
2520 BT_DBG("svc_path %s", svc_info->serv_path);
2522 g_slist_foreach(svc_info->char_data, __char_info_free, &ret);
2523 g_slist_free(svc_info->char_data);
2524 svc_info->char_data = NULL;
2526 if (g_dbus_connection_unregister_object(g_conn, svc_info->serv_id) == FALSE) {
2527 BT_ERR("Cannot unregister object for [%s]", svc_info->serv_path);
2528 ret = BLUETOOTH_ERROR_INTERNAL;
2530 __bt_gatt_emit_interface_removed(svc_info->serv_path, GATT_SERV_INTERFACE);
2533 gatt_services = g_slist_remove(gatt_services, svc_info);
2534 __bt_gatt_free_service_info(svc_info);
2536 new_service = FALSE;
2538 if (gatt_services == NULL) {
2540 } else if (gatt_services->next == NULL) {
2547 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2549 struct gatt_service_info *svc_info;
2550 int ret = BLUETOOTH_ERROR_NONE;
2554 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2556 ret = __bt_gatt_unregister_service(svc_info);
2557 if (ret != BLUETOOTH_ERROR_NONE) {
2558 BT_ERR("Could not unregister service [%s]", svc_path);
2565 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2566 int resp_state, int offset, char *value, int value_length)
2568 struct gatt_req_info *req_info = NULL;
2570 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2571 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2572 BT_ERR("Don't have aprivilege to use this API");
2573 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2576 req_info = __bt_gatt_find_request_info(request_id);
2577 if (req_info == NULL) {
2578 BT_ERR("Coundn't find request id [%d]", request_id);
2579 return BLUETOOTH_ERROR_INTERNAL;
2582 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2583 BT_ERR("resp_state is 0x%X", resp_state);
2584 char err_msg[20] = { 0, };
2585 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2586 g_dbus_method_invocation_return_dbus_error(req_info->context,
2587 "org.bluez.Error.Failed", err_msg);
2589 gatt_requests = g_slist_remove(gatt_requests, req_info);
2591 req_info->context = NULL;
2592 if (req_info->attr_path)
2593 g_free(req_info->attr_path);
2594 if (req_info->svc_path)
2595 g_free(req_info->svc_path);
2598 return BLUETOOTH_ERROR_NONE;
2601 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2603 GVariantBuilder *inner_builder = NULL;
2604 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2605 if (value_length > 0 && value != NULL) {
2606 for (i = 0; i < value_length; i++)
2607 g_variant_builder_add(inner_builder, "y", value[i]);
2609 g_dbus_method_invocation_return_value(req_info->context,
2610 g_variant_new("(ay)", inner_builder));
2611 g_variant_builder_unref(inner_builder);
2613 g_dbus_method_invocation_return_value(req_info->context, NULL);
2615 gatt_requests = g_slist_remove(gatt_requests, req_info);
2617 req_info->context = NULL;
2618 if (req_info->attr_path)
2619 g_free(req_info->attr_path);
2620 if (req_info->svc_path)
2621 g_free(req_info->svc_path);
2624 return BLUETOOTH_ERROR_NONE;
2627 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2628 bluetooth_device_address_t *unicast_address)
2630 GVariantBuilder *outer_builder;
2631 GVariantBuilder *invalidated_builder;
2632 GError *error = NULL;
2633 gboolean notify = TRUE;
2634 gboolean ret = TRUE;
2635 int err = BLUETOOTH_ERROR_NONE;
2636 gchar **line_argv = NULL;
2637 gchar *serv_path = NULL;
2638 char addr[20] = { 0 };
2640 line_argv = g_strsplit_set(char_path, "/", 0);
2641 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2643 if (!__bt_gatt_is_service_registered(serv_path)) {
2644 BT_DBG("service not registered for this characteristic");
2646 g_strfreev(line_argv);
2647 return BLUETOOTH_ERROR_INTERNAL;
2652 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2653 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2655 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2656 g_variant_new("b", notify));
2658 if (unicast_address) {
2659 _bt_convert_addr_type_to_string(addr,
2660 (unsigned char *)unicast_address->addr);
2662 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2663 g_variant_new("s", addr));
2665 BT_DBG("Set characteristic Notification");
2666 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2668 "org.freedesktop.DBus.Properties",
2669 "PropertiesChanged",
2670 g_variant_new("(sa{sv}as)",
2671 "org.bluez.GattCharacteristic1",
2672 outer_builder, invalidated_builder),
2676 if (error != NULL) {
2677 BT_ERR("D-Bus API failure: errCode[%x], \
2679 error->code, error->message);
2680 g_clear_error(&error);
2682 err = BLUETOOTH_ERROR_INTERNAL;
2685 g_strfreev(line_argv);
2686 g_variant_builder_unref(outer_builder);
2687 g_variant_builder_unref(invalidated_builder);
2694 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2698 if (!is_server_started) {
2700 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2701 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2702 BT_ERR("Don't have aprivilege to use this API");
2703 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2706 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2707 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2709 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2710 in_param1, in_param2, in_param3, in_param4, &out_param);
2711 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2713 if (ret != BLUETOOTH_ERROR_NONE) {
2714 BT_ERR("Register application failed");
2717 is_server_started = true;
2719 return BLUETOOTH_ERROR_NONE;
2722 BT_INFO("Already RegisterApplication");
2723 return BLUETOOTH_ERROR_NONE;
2727 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2730 int ret = BLUETOOTH_ERROR_NONE;
2733 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2735 /* Register event handler for GATT */
2736 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2738 if (ret != BLUETOOTH_ERROR_NONE &&
2739 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2740 BT_ERR("Fail to init the event handler");
2741 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2745 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2746 in_param1, in_param2, in_param3, in_param4, &out_param);
2748 /* App ID -1 is invalid */
2749 if (ret != BLUETOOTH_ERROR_NONE) {
2750 BT_INFO("GATT Server Registration failed result [%d]", ret);
2753 *instance_id = g_array_index(out_param, int, 0);
2754 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2758 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2760 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2764 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2767 BT_INFO("GATT Server Deinitialize");
2768 /* Unregister the event */
2769 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2771 if (ret != BLUETOOTH_ERROR_NONE) {
2772 BT_ERR("Fail to deinit the event handler");
2776 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2781 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2782 int instance_id, int *service_handle)
2784 BT_CHECK_ENABLED(return);
2785 BT_CHECK_PARAMETER(svc_uuid, return);
2788 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2790 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2793 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2795 g_array_append_vals(in_param1, &type, sizeof(int));
2796 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2797 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2798 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2800 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2801 in_param1, in_param2, in_param3, in_param4, &out_param);
2803 /* ATT handle 0 is reserved, hence it can not be used by app.
2804 It will be used to indicate error in regsitering attribute */
2805 if (result != BLUETOOTH_ERROR_NONE)
2806 *service_handle = 0;
2808 *service_handle = g_array_index(out_param, int, 0);
2810 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2815 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2816 const bluetooth_gatt_server_attribute_params_t *param,
2819 BT_CHECK_ENABLED(return);
2820 BT_CHECK_PARAMETER(char_uuid, return);
2821 BT_CHECK_PARAMETER(param, return);
2824 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2826 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2829 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2831 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2832 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2834 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2835 in_param1, in_param2, in_param3, in_param4, &out_param);
2837 /* ATT handle 0 is reserved, hence it can not be used by app.
2838 It will be used to indicate error in regsitering attribute */
2839 if (result != BLUETOOTH_ERROR_NONE) {
2840 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2843 *char_handle = g_array_index(out_param, int, 0);
2844 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2847 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2851 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2852 int service_handle, int instance_id, int *descriptor_handle)
2854 BT_CHECK_ENABLED(return);
2855 BT_CHECK_PARAMETER(desc_uuid, return);
2858 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2860 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2863 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2865 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2866 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2867 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2868 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2870 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2871 in_param1, in_param2, in_param3, in_param4, &out_param);
2873 /* ATT handle 0 is reserved, hence it can not be used by app.
2874 It will be used to indicate error in regsitering attribute */
2875 if (result != BLUETOOTH_ERROR_NONE) {
2876 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2877 *descriptor_handle = 0;
2879 *descriptor_handle = g_array_index(out_param, int, 0);
2880 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2883 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2888 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2890 BT_CHECK_ENABLED(return);
2894 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2896 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2897 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2899 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2900 in_param1, in_param2, in_param3, in_param4, &out_param);
2902 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2907 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2908 const bluetooth_gatt_att_data_t *value)
2910 BT_CHECK_PARAMETER(param, return);
2911 BT_CHECK_PARAMETER(value, return);
2912 BT_CHECK_ENABLED(return);
2916 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2918 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
2919 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
2921 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
2922 in_param1, in_param2, in_param3, in_param4, &out_param);
2924 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2930 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
2931 bluetooth_gatt_server_indication_params_t *param,
2932 const bluetooth_gatt_att_data_t *att_value)
2934 BT_CHECK_PARAMETER(param, return);
2935 BT_CHECK_PARAMETER(att_value, return);
2936 BT_CHECK_ENABLED(return);
2938 char addr[BLUETOOTH_ADDRESS_STRING_LENGTH] ;
2942 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2944 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
2945 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
2946 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
2948 _bt_convert_addr_type_to_string(addr, addr_hex->addr);
2949 fd = bluetooth_get_characteristic_fd(param->atrribute_handle, addr);
2952 result = bluetooth_gatt_write_characteristics_value_to_fd_(fd, att_value->data, att_value->length, NULL);
2955 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
2956 in_param1, in_param2, in_param3, in_param4, &out_param);
2959 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2964 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
2966 BT_CHECK_ENABLED(return);
2970 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2972 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2973 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2975 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
2976 in_param1, in_param2, in_param3, in_param4, &out_param);
2978 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2983 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
2985 BT_CHECK_ENABLED(return);
2989 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2991 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2992 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2994 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
2995 in_param1, in_param2, in_param3, in_param4, &out_param);
2997 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3002 /* Tizen Platform Specific */
3003 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
3004 const bluetooth_gatt_server_update_value_t *value)
3006 BT_CHECK_ENABLED(return);
3007 BT_CHECK_PARAMETER(value, return);
3011 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3013 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3014 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3016 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3017 in_param1, in_param2, in_param3, in_param4, &out_param);
3019 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3024 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3026 BT_CHECK_ENABLED(return);
3030 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3032 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3034 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3035 in_param1, in_param2, in_param3, in_param4, &out_param);
3037 if (result != BLUETOOTH_ERROR_NONE)
3038 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3040 BT_INFO("GATT Server Unregistration successful");
3042 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3047 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3048 GIOCondition cond, gpointer data)
3051 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3053 BT_DBG("FD io write data received [%s]", write_data->address);
3055 if (cond & G_IO_NVAL) {
3056 BT_ERR("Invalid channel");
3060 if (cond & (G_IO_HUP | G_IO_ERR)) {
3061 BT_ERR("Error : GIOCondition %d", cond);
3062 g_io_channel_shutdown(gio, TRUE, NULL);
3063 g_io_channel_unref(gio);
3068 if (cond & G_IO_IN) {
3069 GIOStatus status = G_IO_STATUS_NORMAL;
3071 char *buffer = NULL;
3073 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3075 buffer = g_malloc0(BUF);
3077 status = g_io_channel_read_chars(gio, buffer,
3080 if (status != G_IO_STATUS_NORMAL) {
3081 BT_ERR("IO Channel read is failed with %d", status);
3084 BT_ERR("IO Channel read error [%s]", err->message);
3085 if (status == G_IO_STATUS_ERROR) {
3086 BT_ERR("cond : %d", cond);
3088 g_io_channel_shutdown(gio, TRUE, NULL);
3089 g_io_channel_unref(gio);
3099 bluetooth_gatt_server_write_requested_info_t write_info;
3100 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3101 memcpy(write_info.data.data, buffer, len);
3103 write_info.length = len;
3104 write_info.need_resp = false;
3105 write_info.attribute_handle = write_data->attribute_handle;
3107 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->address);
3108 write_info.connection_id = write_data->connection_id;
3109 write_info.offset = write_data->offset;
3110 write_info.request_id = -2;
3112 bt_event_info_t *event_info;
3113 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3117 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3118 BLUETOOTH_ERROR_NONE, &write_info,
3119 event_info->cb, event_info->user_data);
3121 BT_ERR("eventinfo failed");
3131 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
3132 BT_ERR("Error : GIOCondition %d, ]", cond);
3133 g_io_channel_shutdown(gio, TRUE, NULL);
3134 g_io_channel_unref(gio);
3142 void bluetooth_gatt_server_send_acquire_write_response(GVariant * parameters)
3147 int pipefd[2] = {-1,};
3150 char err_msg[512] = {'\0'};
3151 GIOChannel *channel = NULL;
3155 g_variant_get(parameters, "(iiiiii&s)",
3164 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3165 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3166 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3167 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3170 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3171 strerror_r(errno, err_msg, sizeof(err_msg));
3172 BT_ERR("socketpair(): %s", err_msg);
3177 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3179 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3180 bluetooth_gatt_server_acquire_response_params_t data;
3181 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
3182 data.fd = pipefd[1];
3184 data.request_id = tran_id;
3186 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3188 write_info->attribute_handle = att_han;
3189 write_info->connection_id = tran_id;
3190 write_info->offset = offset;
3192 memcpy(write_info->address, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3194 BT_INFO("FD read %d remote address [%s ] \n", pipefd[0], addr);
3196 channel = g_io_channel_unix_new(pipefd[0]);
3197 g_io_channel_set_encoding(channel, NULL, NULL);
3198 g_io_channel_set_buffered(channel, FALSE);
3199 g_io_channel_set_close_on_unref(channel, TRUE);
3200 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3201 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3202 bluetooth_gatt_server_acquire_channel_write_cb, write_info);
3204 GUnixFDList *fd_list = g_unix_fd_list_new();
3205 GError *error = NULL;
3207 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3208 g_assert_no_error(error);
3211 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3213 BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3215 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE,
3216 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3218 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3219 g_object_unref(fd_list);
3222 void bluetooth_gatt_server_send_acquire_notify_response(GVariant * parameters, bt_event_info_t *event_info)
3227 int pipefd[2] = {-1,};
3230 char err_msg[512] = {'\0'};
3231 GIOChannel *channel = NULL;
3234 bluetooth_gatt_acquire_notify_info_t *chr_info;
3235 const char *address = NULL;
3237 g_variant_get(parameters, "(iiiiii&s)",
3246 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3247 BT_DBG("GATT Server Acquire notify att handle:[%d]", att_han);
3248 BT_DBG("GATT Server Acquire Notify Offset: [%d]", offset);
3249 BT_DBG("GATT Server Acquire Notify address: [%s]", address);
3252 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3253 strerror_r(errno, err_msg, sizeof(err_msg));
3254 BT_ERR("socketpair(): %s", err_msg);
3261 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3263 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3264 bluetooth_gatt_server_acquire_response_params_t data;
3265 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
3266 data.fd = pipefd[1];
3268 data.request_id = tran_id;
3270 BT_INFO("FD write %d", pipefd[0]);
3272 chr_info = bluetooth_get_characteristic_info_from_path(att_han);
3274 chr_info = g_malloc0(sizeof(bluetooth_gatt_acquire_notify_info_t));
3275 chr_info->write_fd = fd;
3276 chr_info->att_hand = att_han;
3278 gatt_characteristic_server_notify_list = g_slist_append(gatt_characteristic_server_notify_list, chr_info);
3280 chr_info->write_fd = fd;
3282 channel = g_io_channel_unix_new(fd);
3283 chr_info->io_channel = channel;
3284 g_io_channel_set_encoding(channel, NULL, NULL);
3285 g_io_channel_set_buffered(channel, FALSE);
3286 g_io_channel_set_close_on_unref(channel, TRUE);
3287 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3288 chr_info->watch_id =
3289 g_io_add_watch(channel,
3290 (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
3291 bluetooth_gatt_write_channel_watch_cb, chr_info);
3293 GUnixFDList *fd_list = g_unix_fd_list_new();
3294 GError *error = NULL;
3296 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3297 g_assert_no_error(error);
3300 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3302 BT_DBG("Sending event BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE file descriptor value [%d] ", data.fd);
3304 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE,
3305 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3307 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3308 g_object_unref(fd_list);
3311 if (result == BLUETOOTH_ERROR_NONE) {
3312 BT_DBG("sending gatt server notification state changed event");
3313 bluetooth_gatt_server_notification_changed_t info;
3314 bluetooth_device_address_t dev_address = { {0} };
3315 memset(&info, 0x00, sizeof(bluetooth_gatt_server_notification_changed_t));
3317 _bt_convert_addr_string_to_type(dev_address.addr, address);
3318 memcpy(info.device_address.addr,
3320 BLUETOOTH_ADDRESS_LENGTH);
3321 info.handle = att_han;
3322 info.notification = TRUE;
3324 _bt_gatt_server_event_cb(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
3326 event_info->cb, event_info->user_data);
3331 void cleanup_gatt_acquire_fd(int handle)
3333 bluetooth_gatt_acquire_notify_info_t *chr_info = NULL;
3337 chr_info = bluetooth_get_characteristic_info_from_path(handle);
3339 if (chr_info != NULL) {
3340 BT_INFO("GATT Server: acquire notification char info found [%s]", chr_info->path);
3342 if (chr_info->watch_id > 0)
3343 g_source_remove(chr_info->watch_id);
3345 if (chr_info->io_channel) {
3346 g_io_channel_shutdown(chr_info->io_channel, TRUE, NULL);
3347 g_io_channel_unref(chr_info->io_channel);
3350 BT_INFO("Removing char_info from the list");
3351 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
3352 bluetooth_characteristic_info_free(chr_info);