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)
350 BT_DBG("Find FD for address [%s] att_handle [ %d]", address, att_handle);
352 /* Check for NULL address */
353 if (g_strcmp0(address, "00:00:00:00:00:00") != 0) {
354 BT_INFO("Unicast address: Use DBUS send indication");
358 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
359 bluetooth_gatt_acquire_notify_info_t *info = l->data;
361 if (info->att_hand == att_handle) {
362 BT_INFO("ATT handle Matched: AquireNotify Set: Remote addr[%s]", info->address);
363 return info->write_fd;
369 static bluetooth_gatt_acquire_notify_info_t * bluetooth_get_characteristic_info_from_path(int att_handle)
373 BT_DBG("request found att_handle [ %d]", att_handle);
374 for (l = gatt_characteristic_server_notify_list; l != NULL; l = l->next) {
375 bluetooth_gatt_acquire_notify_info_t *info = l->data;
376 BT_DBG(" sid [ %d]" , info->att_hand);
377 if (info->att_hand == att_handle)
384 static void bluetooth_characteristic_info_free(bluetooth_gatt_acquire_notify_info_t *chr_info)
389 static gboolean bluetooth_gatt_write_channel_watch_cb(GIOChannel *gio,
390 GIOCondition cond, gpointer data)
394 bluetooth_gatt_acquire_notify_info_t *chr_info = (bluetooth_gatt_acquire_notify_info_t *)data;
397 BT_INFO("chr_info is NULL");
401 if (cond & G_IO_NVAL) {
402 BT_ERR("Invalid channel");
406 if (cond & (G_IO_HUP | G_IO_ERR)) {
407 BT_ERR("Error : GIOCondition %d", cond);
408 g_io_channel_shutdown(gio, TRUE, NULL);
409 g_io_channel_unref(gio);
411 if (g_slist_find(gatt_characteristic_server_notify_list, chr_info)) {
412 BT_INFO("found char_info in the list");
413 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
414 bluetooth_characteristic_info_free(chr_info);
420 if (g_slist_find(gatt_characteristic_server_notify_list, chr_info) == NULL) {
421 BT_INFO("chr_info is not in the list");
428 static int bluetooth_gatt_write_characteristics_value_to_fd_(
429 int fd, const guint8 *value, int length,
434 int att_result = BLUETOOTH_ERROR_NONE;
436 BT_CHECK_PARAMETER(value, return);
438 written = write(fd, value, length);
439 if (written != length) {
440 att_result = BLUETOOTH_ERROR_INTERNAL;
441 BT_ERR("write data failed %d is ", written);
447 #ifdef TIZEN_FEATURE_BT_HPS
448 static int __bt_send_event_to_hps(int event, GVariant *var)
450 GError *error = NULL;
451 GVariant *parameters;
452 GDBusMessage *msg = NULL;
456 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
458 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
459 GVariantBuilder *inner_builder;
460 GVariantBuilder *invalidated_builder;
462 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
463 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
465 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
467 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
469 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
470 g_variant_builder_unref(invalidated_builder);
471 g_variant_builder_unref(inner_builder);
472 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
473 GVariantBuilder *inner_builder;
474 GVariantBuilder *invalidated_builder;
476 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
477 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
479 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
481 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
483 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
484 g_variant_builder_unref(invalidated_builder);
485 g_variant_builder_unref(inner_builder);
487 g_varaiant_unref(var);
490 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
491 g_dbus_message_set_body(msg, parameters);
492 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
494 BT_ERR("D-Bus API failure: errCode[%x], \
496 error->code, error->message);
497 g_clear_error(&error);
499 return BLUETOOTH_ERROR_INTERNAL;
501 return BLUETOOTH_ERROR_NONE;
505 #ifdef TIZEN_FEATURE_BT_OTP
506 static int __bt_send_event_to_otp(int event, GVariant *var)
508 GError *error = NULL;
509 GVariant *parameters = NULL;
510 GDBusMessage *msg = NULL;
514 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
516 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
517 GVariantBuilder *inner_builder;
518 GVariantBuilder *invalidated_builder;
520 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
521 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
523 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
525 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
527 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
528 g_variant_builder_unref(invalidated_builder);
529 g_variant_builder_unref(inner_builder);
530 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
531 GVariantBuilder *inner_builder;
532 GVariantBuilder *invalidated_builder;
534 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
535 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
537 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
539 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
541 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
542 g_variant_builder_unref(invalidated_builder);
543 g_variant_builder_unref(inner_builder);
544 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
545 GVariantBuilder *inner_builder;
546 GVariantBuilder *invalidated_builder;
548 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
549 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
551 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
553 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
555 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
556 g_variant_builder_unref(invalidated_builder);
557 g_variant_builder_unref(inner_builder);
560 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
561 g_dbus_message_set_body(msg, parameters);
562 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
564 BT_ERR("D-Bus API failure: errCode[%x], \
566 error->code, error->message);
567 g_clear_error(&error);
569 return BLUETOOTH_ERROR_INTERNAL;
571 return BLUETOOTH_ERROR_NONE;
575 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
577 const gchar *object_path,
578 const gchar *interface_name,
579 const gchar *method_name,
580 GVariant *parameters,
581 GDBusMethodInvocation *invocation,
584 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
585 BT_DBG("Getting values for service, chars and descriptors");
588 GVariantBuilder *builder = NULL;
589 GVariantBuilder *inner_builder1 = NULL;
590 GVariant *svc_char = NULL;
591 GSList *char_list = NULL;
592 GSList *desc_list = NULL;
595 builder = g_variant_builder_new(G_VARIANT_TYPE("a{oa{sa{sv}}}"));
597 /* Prepare inner builder for GattService1 interface */
598 svc_index = g_slist_length(gatt_services) - 1;
599 for (; svc_index >= 0; svc_index--) {
600 GVariantBuilder *svc_builder = NULL;
601 GVariantBuilder *inner_builder = NULL;
602 struct gatt_service_info *serv_info = NULL;
604 serv_info = g_slist_nth_data(gatt_services, svc_index);
605 if (serv_info == NULL) {
606 BT_ERR("serv_info is NULL");
610 /* Prepare inner builder for GattService1 interface */
611 BT_DBG("Creating builder for service : %s", serv_info->service_uuid);
612 svc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
613 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
615 g_variant_builder_add(inner_builder, "{sv}", "UUID",
616 g_variant_new_string(serv_info->service_uuid));
617 g_variant_builder_add(inner_builder, "{sv}", "Primary",
618 g_variant_new_boolean(serv_info->is_svc_primary));
620 /* Characteristics */
621 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
623 BT_DBG("Adding Charatarisitcs list");
624 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
625 struct gatt_char_info *char_info = char_list->data;
626 g_variant_builder_add(inner_builder1, "o", char_info->char_path);
627 BT_DBG("%s", char_info->char_path);
630 svc_char = g_variant_new("ao", inner_builder1);
631 g_variant_builder_add(inner_builder, "{sv}", "Characteristics", svc_char);
632 g_variant_builder_add(svc_builder, "{sa{sv}}", GATT_SERV_INTERFACE, inner_builder);
633 g_variant_builder_add(builder, "{oa{sa{sv}}}", serv_info->serv_path, svc_builder);
634 g_variant_builder_unref(inner_builder1);
636 /* Prepare inner builder for GattCharacteristic1 interface */
637 for (char_list = serv_info->char_data; char_list != NULL; char_list = char_list->next) {
638 GVariantBuilder *char_builder = NULL;
639 GVariantBuilder *inner_builder = NULL;
640 GVariantBuilder *builder1 = NULL;
641 GVariantBuilder *builder2 = NULL;
642 GVariantBuilder *builder3 = NULL;
643 GVariant *char_val = NULL;
644 GVariant *flags_val = NULL;
645 GVariant *char_desc = NULL;
646 char *unicast = NULL;
647 gboolean notify = FALSE;
649 struct gatt_char_info *char_info = char_list->data;
651 if (char_info == NULL) {
652 BT_ERR("char_info is NULL");
656 BT_DBG("Creating builder for characteristic : %s", char_info->char_uuid);
657 char_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
658 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
661 g_variant_builder_add(inner_builder, "{sv}", "UUID",
662 g_variant_new_string(char_info->char_uuid));
665 g_variant_builder_add(inner_builder, "{sv}", "Service",
666 g_variant_new("o", serv_info->serv_path));
669 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
670 if (char_info->char_value != NULL) {
671 for (i = 0; i < char_info->value_length; i++) {
672 g_variant_builder_add(builder1, "y", char_info->char_value[i]);
674 char_val = g_variant_new("ay", builder1);
675 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
679 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
680 for (i = 0; i < char_info->flags_length; i++) {
681 g_variant_builder_add(builder2, "s", char_info->char_flags[i]);
683 flags_val = g_variant_new("as", builder2);
684 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
687 g_variant_builder_add(inner_builder, "{sv}", "Notifying", g_variant_new("b", notify));
690 unicast = g_strdup("00:00:00:00:00:00");
691 g_variant_builder_add(inner_builder, "{sv}", "Unicast", g_variant_new("s", unicast));
694 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
695 BT_DBG("Adding Descriptors list");
696 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
697 struct gatt_desc_info *desc_info = desc_list->data;
698 g_variant_builder_add(builder3, "o", desc_info->desc_path);
699 BT_DBG("%s", desc_info->desc_path);
702 char_desc = g_variant_new("ao", builder3);
703 g_variant_builder_add(inner_builder, "{sv}", "Descriptors", char_desc);
704 g_variant_builder_add(char_builder, "{sa{sv}}", GATT_CHAR_INTERFACE , inner_builder);
705 g_variant_builder_add(builder, "{oa{sa{sv}}}", char_info->char_path, char_builder);
707 /*Prepare inner builder for GattDescriptor1 interface*/
708 for (desc_list = char_info->desc_data; desc_list != NULL; desc_list = desc_list->next) {
709 GVariantBuilder *desc_builder = NULL;
710 GVariantBuilder *inner_builder = NULL;
711 GVariantBuilder *builder1 = NULL;
712 GVariantBuilder *builder2 = NULL;
713 GVariant *desc_val = NULL;
714 struct gatt_desc_info *desc_info = desc_list->data;
716 if (desc_info == NULL) {
717 BT_ERR("desc_info is NULL");
721 BT_DBG("Creating builder for descriptor : %s", desc_info->desc_uuid);
722 desc_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
723 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
726 g_variant_builder_add(inner_builder, "{sv}", "UUID",
727 g_variant_new_string(desc_info->desc_uuid));
730 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
731 g_variant_new("o", char_info->char_path));
734 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
735 if (desc_info->desc_value != NULL) {
736 for (i = 0; i < desc_info->value_length; i++) {
737 g_variant_builder_add(builder1, "y", desc_info->desc_value[i]);
739 desc_val = g_variant_new("ay", builder1);
740 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
744 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
745 for (i = 0; i < desc_info->flags_length; i++) {
746 g_variant_builder_add(builder2, "s", desc_info->desc_flags[i]);
748 flags_val = g_variant_new("as", builder2);
749 g_variant_builder_add(inner_builder, "{sv}", "Flags", flags_val);
751 g_variant_builder_add(desc_builder, "{sa{sv}}", GATT_DESC_INTERFACE,
753 g_variant_builder_add(builder, "{oa{sa{sv}}}", desc_info->desc_path,
756 /* unref descriptor builder pointers */
757 g_variant_builder_unref(builder1);
758 g_variant_builder_unref(builder2);
759 g_variant_builder_unref(inner_builder);
760 g_variant_builder_unref(desc_builder);
766 /* unref char builder pointers */
767 g_variant_builder_unref(builder1);
768 g_variant_builder_unref(builder2);
769 g_variant_builder_unref(builder3);
770 g_variant_builder_unref(inner_builder);
771 g_variant_builder_unref(char_builder);
774 /* unref service builder pointers */
775 g_variant_builder_unref(inner_builder);
776 g_variant_builder_unref(svc_builder);
779 /* Return builder as method reply */
780 BT_DBG("Sending gatt service builder values to Bluez");
781 g_dbus_method_invocation_return_value(invocation,
782 g_variant_new("(a{oa{sa{sv}}})", builder));
783 g_variant_builder_unref(builder);
787 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
791 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
792 struct gatt_service_info *serv_info = l1->data;
794 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
795 struct gatt_char_info *char_info = l2->data;
797 if (g_strcmp0(char_info->char_path, char_path) == 0)
801 BT_ERR("Gatt service not found");
805 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
807 GSList *l1, *l2, *l3;
809 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
810 struct gatt_service_info *serv_info = l1->data;
812 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
813 struct gatt_char_info *char_info = l2->data;
815 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
816 struct gatt_desc_info *desc_info = l3->data;
818 if (g_strcmp0(desc_info->desc_path, desc_path) == 0)
823 BT_ERR("Gatt service not found");
827 static void __bt_gatt_char_method_call(GDBusConnection *connection,
829 const gchar *object_path,
830 const gchar *interface_name,
831 const gchar *method_name,
832 GVariant *parameters,
833 GDBusMethodInvocation *invocation,
837 if (g_strcmp0(method_name, "ReadValue") == 0) {
841 bt_gatt_read_req_t read_req = {0, };
842 bt_user_info_t *user_info = NULL;
843 struct gatt_req_info *req_info = NULL;
844 struct gatt_service_info *svc_info = NULL;
845 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
846 GVariant *param = NULL;
849 BT_DBG("Application path = %s", object_path);
850 BT_DBG("Sender = %s", sender);
852 user_info = _bt_get_user_data(BT_COMMON);
853 if (user_info == NULL) {
854 BT_INFO("No callback is set for %s", object_path);
855 g_dbus_method_invocation_return_value(invocation, NULL);
859 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
860 if (svc_info == NULL) {
861 BT_ERR("Coudn't find service for %s", object_path);
862 g_dbus_method_invocation_return_value(invocation, NULL);
866 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
867 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
869 read_req.att_handle = (char *)object_path;
870 read_req.address = addr;
871 read_req.req_id = req_id;
872 read_req.offset = offset;
873 read_req.service_handle = svc_info->serv_path;
875 /* Store requets information */
876 req_info = g_new0(struct gatt_req_info, 1);
877 req_info->attr_path = g_strdup(object_path);
878 req_info->svc_path = g_strdup(read_req.service_handle);
879 req_info->request_id = req_id;
880 req_info->offset = offset;
881 req_info->context = invocation;
882 gatt_requests = g_slist_append(gatt_requests, req_info);
884 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
885 param = g_variant_new("(sssyq)",
887 read_req.service_handle,
891 #ifdef TIZEN_FEATURE_BT_HPS
892 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
894 #ifdef TIZEN_FEATURE_BT_OTP
895 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
899 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
900 BLUETOOTH_ERROR_NONE, &read_req,
901 user_info->cb, user_info->user_data);
903 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
904 GVariant *var = NULL;
908 gboolean response_needed = FALSE;
909 bt_gatt_value_change_t value_change = {0, };
910 bt_user_info_t *user_info = NULL;
912 struct gatt_service_info *svc_info = NULL;
913 struct gatt_req_info *req_info = NULL;
914 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
915 GVariant *param = NULL;
918 BT_DBG("WriteValue");
919 BT_DBG("Application path = %s", object_path);
920 BT_DBG("Sender = %s", sender);
922 g_variant_get(parameters, "(&suqb@ay)",
923 &addr, &req_id, &offset, &response_needed, &var);
924 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
926 user_info = _bt_get_user_data(BT_COMMON);
928 BT_INFO("No callback is set for %s", object_path);
929 g_variant_unref(var);
931 g_dbus_method_invocation_return_value(invocation, NULL);
933 g_object_unref(invocation);
937 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
938 if (svc_info == NULL) {
939 BT_ERR("Coudn't find service for %s", object_path);
940 g_variant_unref(var);
942 g_dbus_method_invocation_return_value(invocation, NULL);
944 g_object_unref(invocation);
948 value_change.att_handle = (char *)object_path;
949 value_change.address = addr;
950 value_change.service_handle = svc_info->serv_path;
951 value_change.offset = offset;
952 value_change.req_id = req_id;
953 value_change.response_needed = response_needed;
955 len = g_variant_get_size(var);
959 value_change.att_value = (guint8 *)g_malloc(len);
961 data = (char *)g_variant_get_data(var);
962 memcpy(value_change.att_value, data, len);
964 value_change.val_len = len;
966 if (response_needed) {
967 /* Store requets information */
968 req_info = g_new0(struct gatt_req_info, 1);
969 req_info->attr_path = g_strdup(object_path);
970 req_info->svc_path = g_strdup(value_change.service_handle);
971 req_info->request_id = req_id;
972 req_info->offset = offset;
973 req_info->context = invocation;
974 gatt_requests = g_slist_append(gatt_requests, req_info);
976 g_object_unref(invocation);
979 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
982 svc_path = g_strdup(svc_info->serv_path);
983 param = g_variant_new("(sssyq@ay)",
990 #ifdef TIZEN_FEATURE_BT_HPS
991 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
993 #ifdef TIZEN_FEATURE_BT_OTP
994 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1001 _bt_common_event_cb(
1002 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1003 BLUETOOTH_ERROR_NONE, &value_change,
1004 user_info->cb, user_info->user_data);
1006 g_free(value_change.att_value);
1007 g_variant_unref(var);
1009 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1010 bt_user_info_t *user_info = NULL;
1011 bt_gatt_char_notify_change_t notify_change = {0, };
1012 #if TIZEN_FEATURE_BT_OTP
1013 GVariant *param = NULL;
1015 BT_DBG("StartNotify");
1016 user_info = _bt_get_user_data(BT_COMMON);
1017 if (user_info != NULL) {
1018 struct gatt_service_info *svc_info = NULL;
1019 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1021 notify_change.service_handle = svc_info->serv_path;
1022 notify_change.att_handle = (char *)object_path;
1023 notify_change.att_notify = TRUE;
1024 #if TIZEN_FEATURE_BT_OTP
1025 param = g_variant_new("(ssb)",
1026 notify_change.att_handle,
1027 notify_change.service_handle,
1028 notify_change.att_notify);
1029 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1031 _bt_common_event_cb(
1032 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1033 BLUETOOTH_ERROR_NONE, ¬ify_change,
1034 user_info->cb, user_info->user_data);
1037 g_object_unref(invocation);
1039 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1040 bt_user_info_t *user_info = NULL;
1041 bt_gatt_char_notify_change_t notify_change = {0, };
1042 #if TIZEN_FEATURE_BT_OTP
1043 GVariant *param = NULL;
1045 BT_DBG("StopNotify");
1046 user_info = _bt_get_user_data(BT_COMMON);
1047 if (user_info != NULL) {
1048 struct gatt_service_info *svc_info = NULL;
1049 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1051 notify_change.service_handle = svc_info->serv_path;
1052 notify_change.att_handle = (char *)object_path;
1053 notify_change.att_notify = FALSE;
1054 #if TIZEN_FEATURE_BT_OTP
1055 param = g_variant_new("(ssb)",
1056 notify_change.att_handle,
1057 notify_change.service_handle,
1058 notify_change.att_notify);
1059 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1061 _bt_common_event_cb(
1062 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1063 BLUETOOTH_ERROR_NONE, ¬ify_change,
1064 user_info->cb, user_info->user_data);
1067 g_object_unref(invocation);
1069 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1071 bt_gatt_indicate_confirm_t confirm = {0, };
1072 bt_user_info_t *user_info = NULL;
1073 gboolean complete = FALSE;
1074 struct gatt_service_info *svc_info = NULL;
1076 BT_DBG("IndicateConfirm");
1077 BT_DBG("Application path = %s", object_path);
1078 BT_DBG("Sender = %s", sender);
1080 g_variant_get(parameters, "(&sb)", &addr, &complete);
1081 BT_DBG("Remote Device address number = %s", addr);
1083 confirm.att_handle = (char *)object_path;
1084 confirm.address = addr;
1085 confirm.complete = complete;
1087 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1088 if (svc_info != NULL) {
1089 confirm.service_handle = svc_info->serv_path;
1091 user_info = _bt_get_user_data(BT_COMMON);
1092 if (user_info != NULL) {
1093 _bt_common_event_cb(
1094 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1095 BLUETOOTH_ERROR_NONE, &confirm,
1096 user_info->cb, user_info->user_data);
1101 g_dbus_method_invocation_return_value(invocation, NULL);
1104 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1105 const gchar *sender,
1106 const gchar *object_path,
1107 const gchar *interface_name,
1108 const gchar *method_name,
1109 GVariant *parameters,
1110 GDBusMethodInvocation *invocation,
1113 if (g_strcmp0(method_name, "ReadValue") == 0) {
1117 bt_gatt_read_req_t read_req = {0, };
1118 bt_user_info_t *user_info = NULL;
1119 struct gatt_req_info *req_info = NULL;
1120 struct gatt_service_info *svc_info = NULL;
1122 BT_DBG("ReadValue");
1123 BT_DBG("Application path = %s", object_path);
1124 BT_DBG("Sender = %s", sender);
1126 user_info = _bt_get_user_data(BT_COMMON);
1127 if (user_info == NULL) {
1128 BT_INFO("No callback is set for %s", object_path);
1129 g_dbus_method_invocation_return_value(invocation, NULL);
1133 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1134 if (svc_info == NULL) {
1135 BT_ERR("Coudn't find service for %s", object_path);
1136 g_dbus_method_invocation_return_value(invocation, NULL);
1140 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1141 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1143 read_req.att_handle = (char *)object_path;
1144 read_req.address = addr;
1145 read_req.req_id = req_id;
1146 read_req.offset = offset;
1147 read_req.service_handle = svc_info->serv_path;
1149 /* Store requets information */
1150 req_info = g_new0(struct gatt_req_info, 1);
1151 req_info->attr_path = g_strdup(object_path);
1152 req_info->svc_path = g_strdup(read_req.service_handle);
1153 req_info->request_id = req_id;
1154 req_info->offset = offset;
1155 req_info->context = invocation;
1156 gatt_requests = g_slist_append(gatt_requests, req_info);
1158 _bt_common_event_cb(
1159 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1160 BLUETOOTH_ERROR_NONE, &read_req,
1161 user_info->cb, user_info->user_data);
1164 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1165 GVariant *var = NULL;
1169 gboolean response_needed = FALSE;
1170 bt_gatt_value_change_t value_change = {0, };
1171 bt_user_info_t *user_info = NULL;
1173 struct gatt_service_info *svc_info = NULL;
1174 struct gatt_req_info *req_info = NULL;
1176 BT_DBG("WriteValue");
1177 BT_DBG("Application path = %s", object_path);
1178 BT_DBG("Sender = %s", sender);
1180 g_variant_get(parameters, "(&suqb@ay)",
1181 &addr, &req_id, &offset, &response_needed, &var);
1182 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1184 user_info = _bt_get_user_data(BT_COMMON);
1185 if (user_info == NULL) {
1186 BT_INFO("No callback is set for %s", object_path);
1187 g_variant_unref(var);
1188 if (response_needed)
1189 g_dbus_method_invocation_return_value(invocation, NULL);
1191 g_object_unref(invocation);
1195 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1196 if (svc_info == NULL) {
1197 BT_ERR("Coudn't find service for %s", object_path);
1198 g_variant_unref(var);
1199 if (response_needed)
1200 g_dbus_method_invocation_return_value(invocation, NULL);
1202 g_object_unref(invocation);
1206 value_change.att_handle = (char *)object_path;
1207 value_change.address = addr;
1208 value_change.service_handle = svc_info->serv_path;
1209 value_change.offset = offset;
1210 value_change.req_id = req_id;
1211 value_change.response_needed = response_needed;
1213 len = g_variant_get_size(var);
1217 value_change.att_value = (guint8 *)g_malloc(len);
1219 data = (char *)g_variant_get_data(var);
1220 memcpy(value_change.att_value, data, len);
1222 value_change.val_len = len;
1224 if (response_needed) {
1225 /* Store requets information */
1226 req_info = g_new0(struct gatt_req_info, 1);
1227 req_info->attr_path = g_strdup(object_path);
1228 req_info->svc_path = g_strdup(value_change.service_handle);
1229 req_info->request_id = req_id;
1230 req_info->offset = offset;
1231 req_info->context = invocation;
1232 gatt_requests = g_slist_append(gatt_requests, req_info);
1234 g_object_unref(invocation);
1237 _bt_common_event_cb(
1238 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1239 BLUETOOTH_ERROR_NONE, &value_change,
1240 user_info->cb, user_info->user_data);
1242 g_free(value_change.att_value);
1243 g_variant_unref(var);
1248 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1251 GError *error = NULL;
1252 GVariantBuilder *array_builder;
1254 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1255 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1256 g_variant_builder_add(array_builder, "s", interface);
1258 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1259 "org.freedesktop.Dbus.Objectmanager",
1260 "InterfacesRemoved",
1261 g_variant_new("(oas)",
1262 object_path, array_builder),
1266 if (error != NULL) {
1267 /* dbus gives error cause */
1268 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1269 error->code, error->message);
1270 g_clear_error(&error);
1273 g_variant_builder_unref(array_builder);
1278 static const GDBusInterfaceVTable desc_interface_vtable = {
1279 __bt_gatt_desc_method_call,
1285 static const GDBusInterfaceVTable char_interface_vtable = {
1286 __bt_gatt_char_method_call,
1292 static const GDBusInterfaceVTable serv_interface_vtable = {
1299 static const GDBusInterfaceVTable manager_interface_vtable = {
1300 __bt_gatt_manager_method_call,
1306 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1307 const gchar *introspection_data)
1310 GDBusNodeInfo *node_info = NULL;
1312 if (introspection_data == NULL)
1316 BT_DBG("Create new node info");
1317 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1320 BT_ERR("Unable to create node: %s", err->message);
1321 g_clear_error(&err);
1328 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1329 const char *service_path)
1333 for (l = gatt_services; l != NULL; l = l->next) {
1334 struct gatt_service_info *info = l->data;
1336 if (g_strcmp0(info->serv_path, service_path) == 0)
1339 BT_ERR("Gatt service not found");
1343 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1344 const char *service_path, const char *char_path)
1348 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1349 struct gatt_service_info *serv_info = l1->data;
1351 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1353 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1354 struct gatt_char_info *char_info = l2->data;
1356 if (g_strcmp0(char_info->char_path, char_path) == 0)
1359 BT_ERR("Gatt characteristic not found");
1363 BT_ERR("Gatt service not found");
1367 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1368 const char *serv_path, const char *char_path,
1369 const char *desc_path)
1371 GSList *l1, *l2, *l3;
1373 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1374 struct gatt_service_info *serv_info = l1->data;
1376 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1377 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1378 struct gatt_char_info *char_info = l2->data;
1380 if (g_strcmp0(char_info->char_path, char_path) == 0) {
1381 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1382 struct gatt_desc_info *desc_info = l3->data;
1383 if (g_strcmp0(desc_info->desc_path,
1392 BT_ERR("Gatt descriptor not found");
1396 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1400 for (l = gatt_requests; l != NULL; l = l->next) {
1401 struct gatt_req_info *req_info = l->data;
1403 if (req_info && req_info->request_id == request_id)
1406 BT_ERR("Gatt Request not found");
1410 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1411 const gchar *path, const gchar *interface)
1416 g_conn = _bt_get_system_shared_conn();
1418 BT_ERR("Unable to get connection");
1422 proxy = g_dbus_proxy_new_sync(g_conn,
1423 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1425 interface, NULL, &err);
1429 BT_ERR("Unable to create proxy: %s", err->message);
1430 g_clear_error(&err);
1434 manager_gproxy = proxy;
1439 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1440 const gchar *path, const gchar *interface)
1442 return (manager_gproxy) ? manager_gproxy :
1443 __bt_gatt_gdbus_init_manager_proxy(service,
1447 static gboolean __bt_gatt_is_service_registered(const char *service_path)
1449 struct gatt_service_info *svc_info = NULL;
1451 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1453 if (svc_info != NULL) {
1454 BT_DBG("Return the state of the gatt service %d",
1455 svc_info->is_svc_registered);
1456 return svc_info->is_svc_registered;
1459 BT_DBG("gatt service info is NULL");
1463 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1465 GError *error = NULL;
1467 GVariantIter *iter = NULL;
1468 const gchar *key = NULL;
1469 GVariant *value = NULL;
1470 const gchar *service = NULL;
1471 const gchar *characteristic = NULL;
1472 const gchar *descriptor = NULL;
1476 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1478 if (result == NULL) {
1479 BT_ERR("Dbus-RPC is failed");
1480 if (error != NULL) {
1481 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1482 error->code, error->message);
1483 g_clear_error(&error);
1486 char *char_cmp = NULL;
1487 g_variant_get(result, "(a{sv})", &iter);
1488 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1490 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1491 if (g_strcmp0(key, "Service") == 0) {
1492 service = g_variant_get_string(value, NULL);
1493 BT_DBG("Service %s", service);
1494 } else if (g_strcmp0(key, char_cmp) == 0) {
1495 characteristic = g_variant_get_string(value, NULL);
1497 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1498 BT_DBG("%s", characteristic);
1499 } else if (g_strcmp0(key, "Descriptor") == 0) {
1500 descriptor = g_variant_get_string(value, NULL);
1501 BT_DBG("Descriptor %s", descriptor);
1504 g_variant_iter_free(iter);
1506 /* TODO: Store the service informationa and
1507 * Send respponse to CAPI layer. */
1509 g_variant_unref(result);
1514 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1516 BT_INFO("RegisterApplication is completed");
1518 GError *error = NULL;
1521 if (register_cancel) {
1522 g_object_unref(register_cancel);
1523 register_cancel = NULL;
1526 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1527 if (result == NULL) {
1528 BT_ERR("Dbus-RPC is failed");
1529 if (error != NULL) {
1530 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1531 error->code, error->message);
1532 g_clear_error(&error);
1534 is_server_started = false;
1536 g_variant_unref(result);
1540 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1542 GDBusProxy *proxy = NULL;
1544 if (is_server_started) {
1548 if (app_path == NULL) {
1549 BT_ERR("app_path is NULL");
1550 return BLUETOOTH_ERROR_INTERNAL;
1553 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1554 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1555 if (proxy == NULL) {
1556 BT_ERR("proxy is NULL");
1557 return BLUETOOTH_ERROR_INTERNAL;
1560 BT_INFO("UnregisterApplication");
1562 /* Async Call to Unregister Service */
1563 ret = g_dbus_proxy_call_sync(proxy, "UnregisterApplication",
1564 g_variant_new("(o)", app_path), G_DBUS_CALL_FLAGS_NONE, -1,
1567 BT_ERR("dBUS-RPC is failed");
1569 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1570 err->code, err->message);
1571 if (err->code == G_DBUS_ERROR_SERVICE_UNKNOWN ||
1572 g_strrstr(err->message, BT_ERROR_DOES_NOT_EXIST)) {
1573 g_clear_error(&err);
1576 g_clear_error(&err);
1578 return BLUETOOTH_ERROR_INTERNAL;
1580 g_variant_unref(ret);
1583 is_server_started = false;
1585 BT_INFO("UnregisterApplication is completed");
1587 return BLUETOOTH_ERROR_NONE;
1590 BT_INFO("GATT server not started");
1591 return BLUETOOTH_ERROR_NONE;
1594 BT_EXPORT_API int bluetooth_gatt_init(void)
1596 GError *error = NULL;
1597 GDBusNodeInfo *node_info = NULL;
1599 if (app_path != NULL) {
1600 BT_ERR("app path already exists! initialized");
1601 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1604 g_conn = _bt_get_system_shared_conn();
1606 BT_ERR("Unable to get connection");
1610 if (owner_id == 0) {
1611 gchar *name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
1612 BT_DBG("well-known name: %s", name);
1614 owner_id = g_bus_own_name_on_connection(g_conn, name,
1615 G_BUS_NAME_OWNER_FLAGS_NONE,
1616 NULL, NULL, NULL, NULL);
1619 BT_DBG("owner_id is [%d]", owner_id);
1621 app_path = g_strdup_printf("/com/%d", getpid());
1625 /* Register ObjectManager interface */
1626 node_info = __bt_gatt_create_method_node_info(
1627 manager_introspection_xml);
1628 if (node_info == NULL) {
1629 BT_ERR("failed to get node info");
1633 if (manager_id == 0) {
1634 BT_INFO("manager_id does not exists");
1636 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1637 node_info->interfaces[0],
1638 &manager_interface_vtable,
1639 NULL, NULL, &error);
1641 g_dbus_node_info_unref(node_info);
1642 if (manager_id == 0) {
1643 BT_ERR("failed to register: %s", error->message);
1644 g_error_free(error);
1648 return BLUETOOTH_ERROR_NONE;
1652 g_bus_unown_name(owner_id);
1659 return BLUETOOTH_ERROR_INTERNAL;
1662 BT_EXPORT_API int bluetooth_gatt_deinit()
1664 int ret = BLUETOOTH_ERROR_NONE;
1666 if (register_cancel) {
1667 g_cancellable_cancel(register_cancel);
1668 g_object_unref(register_cancel);
1669 register_cancel = NULL;
1672 if (owner_id == 0) {
1673 BT_ERR("owner_id is zero");
1674 return BLUETOOTH_ERROR_NOT_FOUND;
1677 BT_DBG("Removing all registered gatt services");
1678 bluetooth_gatt_delete_services();
1680 /* Unregister the exported interface for object manager */
1682 g_dbus_connection_unregister_object(g_conn, manager_id);
1686 ret = bluetooth_gatt_unregister_application();
1687 if (ret != BLUETOOTH_ERROR_NONE) {
1688 BT_ERR("Fail to unregister application");
1691 g_bus_unown_name(owner_id);
1697 if (manager_gproxy) {
1698 g_object_unref(manager_gproxy);
1699 manager_gproxy = NULL;
1706 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1709 GError *error = NULL;
1711 GDBusNodeInfo *node_info;
1713 GVariantBuilder *builder = NULL;
1714 GVariantBuilder *builder1 = NULL;
1715 GVariantBuilder *inner_builder = NULL;
1716 gboolean svc_primary = TRUE;
1717 struct gatt_service_info *serv_info = NULL;
1719 node_info = __bt_gatt_create_method_node_info(
1720 service_introspection_xml);
1721 if (node_info == NULL)
1722 return BLUETOOTH_ERROR_INTERNAL;
1724 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1725 BT_DBG("gatt service path is [%s]", path);
1727 object_id = g_dbus_connection_register_object(g_conn, path,
1728 node_info->interfaces[0],
1729 &serv_interface_vtable,
1730 NULL, NULL, &error);
1731 g_dbus_node_info_unref(node_info);
1733 if (object_id == 0) {
1734 BT_ERR("failed to register: %s", error->message);
1735 g_error_free(error);
1738 return BLUETOOTH_ERROR_INTERNAL;
1741 /* Add object_id/gatt service information; it's required at the time of
1742 * service unregister and Getmanagedobjects
1744 serv_info = g_new0(struct gatt_service_info, 1);
1746 serv_info->serv_path = g_strdup(path);
1747 serv_info->serv_id = object_id;
1748 serv_info->service_uuid = g_strdup(svc_uuid);
1749 serv_info->is_svc_registered = FALSE;
1750 serv_info->is_svc_primary = svc_primary;
1752 gatt_services = g_slist_append(gatt_services, serv_info);
1754 /* emit interfacesadded signal here for service path */
1755 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1756 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1758 g_variant_builder_add(inner_builder, "{sv}",
1759 "UUID", g_variant_new_string(svc_uuid));
1761 g_variant_builder_add(inner_builder, "{sv}",
1762 "Primary", g_variant_new_boolean(svc_primary));
1764 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1766 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1767 g_variant_new("ao", builder1));
1769 g_variant_builder_add(builder, "{sa{sv}}",
1770 GATT_SERV_INTERFACE, inner_builder);
1772 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1773 "org.freedesktop.Dbus.ObjectManager",
1775 g_variant_new("(oa{sa{sv}})",
1778 if (error != NULL) {
1779 /* dbus gives error cause */
1780 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1781 error->code, error->message);
1782 g_clear_error(&error);
1787 *svc_path = g_strdup(path);
1790 g_variant_builder_unref(inner_builder);
1791 g_variant_builder_unref(builder);
1792 g_variant_builder_unref(builder1);
1794 return BLUETOOTH_ERROR_NONE;
1797 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1798 const char *svc_path, const char *char_uuid,
1799 bt_gatt_permission_t permissions,
1800 bt_gatt_characteristic_property_t properties,
1804 GError *error = NULL;
1806 GDBusNodeInfo *node_info;
1808 GVariantBuilder *builder = NULL;
1809 GVariantBuilder *inner_builder = NULL;
1810 struct gatt_service_info *serv_info = NULL;
1811 struct gatt_char_info *char_info = NULL;
1812 GVariantBuilder *builder2 = NULL;
1813 GVariantBuilder *builder3 = NULL;
1814 GVariant *flags_val = NULL;
1816 char *char_flags[NUMBER_OF_FLAGS];
1821 new_service = FALSE;
1824 BT_DBG("gatt svc_path path is [%s]", svc_path);
1825 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1826 if (serv_info == NULL)
1827 return BLUETOOTH_ERROR_INVALID_PARAM;
1829 node_info = __bt_gatt_create_method_node_info(
1830 characteristics_introspection_xml);
1831 if (node_info == NULL)
1832 return BLUETOOTH_ERROR_INTERNAL;
1834 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1835 BT_DBG("gatt characteristic path is [%s]", path);
1837 object_id = g_dbus_connection_register_object(g_conn, path,
1838 node_info->interfaces[0],
1839 &char_interface_vtable,
1840 NULL, NULL, &error);
1841 g_dbus_node_info_unref(node_info);
1843 if (object_id == 0) {
1844 BT_ERR("failed to register: %s", error->message);
1845 g_error_free(error);
1848 return BLUETOOTH_ERROR_INTERNAL;
1851 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1852 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1853 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1854 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1855 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1856 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1857 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1858 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1860 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1862 char_info = g_new0(struct gatt_char_info, 1);
1864 char_info->char_path = g_strdup(path);
1865 char_info->char_id = object_id;
1866 char_info->char_uuid = g_strdup(char_uuid);
1868 for (i = 0; i < flag_count; i++)
1869 char_info->char_flags[i] = char_flags[i];
1872 char_info->flags_length = flag_count;
1874 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1876 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1877 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1879 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1880 g_variant_new("s", char_uuid));
1881 g_variant_builder_add(inner_builder, "{sv}", "Service",
1882 g_variant_new("o", svc_path));
1884 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1886 for (i = 0; i < flag_count; i++)
1887 g_variant_builder_add(builder2, "s", char_flags[i]);
1889 flags_val = g_variant_new("as", builder2);
1890 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1893 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1895 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1896 g_variant_new("ao", builder3));
1898 g_variant_builder_add(builder, "{sa{sv}}",
1899 GATT_CHAR_INTERFACE,
1902 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1903 "org.freedesktop.Dbus.ObjectManager",
1905 g_variant_new("(oa{sa{sv}})",
1909 /* dBUS gives error cause */
1910 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1911 error->code, error->message);
1912 g_clear_error(&error);
1915 *char_path = g_strdup(path);
1921 g_variant_builder_unref(inner_builder);
1922 g_variant_builder_unref(builder);
1923 g_variant_builder_unref(builder2);
1924 g_variant_builder_unref(builder3);
1926 return BLUETOOTH_ERROR_NONE;
1929 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1930 const char *characteristic, const char *char_value,
1933 gchar **line_argv = NULL;
1934 char *serv_path = NULL;
1935 struct gatt_char_info *char_info = NULL;
1936 GVariantBuilder *builder1 = NULL;
1937 GVariantBuilder *builder = NULL;
1938 GVariantBuilder *inner_builder = NULL;
1939 GVariant *char_val = NULL;
1940 GError *error = NULL;
1942 int res = BLUETOOTH_ERROR_NONE;
1944 line_argv = g_strsplit_set(characteristic, "/", 0);
1945 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1947 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1949 if (char_info == NULL) {
1950 /* Fix : RESOURCE_LEAK */
1951 res = BLUETOOTH_ERROR_INVALID_PARAM;
1955 char_info->value_length = value_length;
1957 char_info->char_value = (char *)malloc(value_length);
1958 /* Fix : NULL_RETURNS */
1959 if (char_info->char_value == NULL) {
1960 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1964 for (i = 0; i < value_length; i++)
1965 char_info->char_value[i] = char_value[i];
1967 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1968 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1970 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1972 for (i = 0; i < value_length; i++)
1973 g_variant_builder_add(builder1, "y", char_value[i]);
1975 char_val = g_variant_new("ay", builder1);
1976 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1978 g_variant_builder_add(builder, "{sa{sv}}",
1979 GATT_CHAR_INTERFACE,
1982 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1983 "org.freedesktop.Dbus.ObjectManager",
1985 g_variant_new("(oa{sa{sv}})",
1986 char_info->char_path, builder),
1990 /* dBUS gives error cause */
1991 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
1992 error->code, error->message);
1993 g_clear_error(&error);
1995 g_variant_builder_unref(inner_builder);
1996 g_variant_builder_unref(builder);
1997 g_variant_builder_unref(builder1);
1999 g_strfreev(line_argv);
2005 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2006 const char *char_path, const char *desc_uuid,
2007 bt_gatt_permission_t permissions,
2010 static int desc_id = 1;
2011 GError *error = NULL;
2013 GDBusNodeInfo *node_info;
2015 GVariantBuilder *builder = NULL;
2016 GVariantBuilder *inner_builder = NULL;
2017 struct gatt_char_info *char_info = NULL;
2018 struct gatt_desc_info *desc_info = NULL;
2019 gchar **line_argv = NULL;
2021 GVariantBuilder *builder2 = NULL;
2022 GVariant *flags_val = NULL;
2024 char *desc_flags[NUMBER_OF_FLAGS];
2032 line_argv = g_strsplit_set(char_path, "/", 0);
2033 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2035 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2036 if (char_info == NULL) {
2037 g_strfreev(line_argv);
2039 return BLUETOOTH_ERROR_INVALID_PARAM;
2042 node_info = __bt_gatt_create_method_node_info(
2043 descriptor_introspection_xml);
2044 if (node_info == NULL) {
2045 g_strfreev(line_argv);
2047 return BLUETOOTH_ERROR_INTERNAL;
2050 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2051 BT_DBG("gatt descriptor path is [%s]", path);
2053 object_id = g_dbus_connection_register_object(g_conn, path,
2054 node_info->interfaces[0],
2055 &desc_interface_vtable,
2056 NULL, NULL, &error);
2057 g_dbus_node_info_unref(node_info);
2059 if (object_id == 0) {
2060 BT_ERR("failed to register: %s", error->message);
2061 g_error_free(error);
2063 g_strfreev(line_argv);
2066 return BLUETOOTH_ERROR_INTERNAL;
2069 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2071 desc_info = g_new0(struct gatt_desc_info, 1);
2073 desc_info->desc_path = g_strdup(path);
2074 desc_info->desc_id = object_id;
2075 desc_info->desc_uuid = g_strdup(desc_uuid);
2077 for (i = 0; i < flag_count; i++)
2078 desc_info->desc_flags[i] = desc_flags[i];
2080 desc_info->flags_length = flag_count;
2082 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2084 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2085 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2087 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2088 g_variant_new("s", desc_uuid));
2089 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2090 g_variant_new("o", char_path));
2092 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2094 for (i = 0; i < flag_count; i++)
2095 g_variant_builder_add(builder2, "s", desc_flags[i]);
2097 flags_val = g_variant_new("as", builder2);
2098 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2101 g_variant_builder_add(builder, "{sa{sv}}",
2102 GATT_DESC_INTERFACE,
2105 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2106 "org.freedesktop.Dbus.ObjectManager",
2108 g_variant_new("(oa{sa{sv}})",
2112 /* dBUS gives error cause */
2113 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2114 error->code, error->message);
2115 g_clear_error(&error);
2118 *desc_path = g_strdup(path);
2122 g_strfreev(line_argv);
2123 g_variant_builder_unref(inner_builder);
2124 g_variant_builder_unref(builder);
2125 g_variant_builder_unref(builder2);
2127 return BLUETOOTH_ERROR_NONE;
2130 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2131 const char *desc_path, const char *desc_value,
2134 GError *error = NULL;
2135 GVariantBuilder *builder = NULL;
2136 GVariantBuilder *inner_builder = NULL;
2137 GVariantBuilder *builder1 = NULL;
2138 struct gatt_desc_info *desc_info = NULL;
2139 gchar **line_argv = NULL;
2141 GVariant *desc_val = NULL;
2142 char *serv_path = NULL;
2145 line_argv = g_strsplit_set(desc_path, "/", 0);
2146 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2147 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2149 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2151 /* Free the allocated memory */
2152 g_strfreev(line_argv);
2156 /* Fix : NULL_RETURNS */
2157 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2159 desc_info->desc_value = (char *)malloc(value_length);
2161 /* Fix : NULL_RETURNS */
2162 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2164 for (i = 0; i < value_length; i++)
2165 desc_info->desc_value[i] = desc_value[i];
2167 desc_info->value_length = value_length;
2169 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2170 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2172 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2174 for (i = 0; i < value_length; i++)
2175 g_variant_builder_add(builder1, "y", desc_value[i]);
2177 desc_val = g_variant_new("ay", builder1);
2178 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2180 g_variant_builder_add(builder, "{sa{sv}}",
2181 GATT_DESC_INTERFACE,
2184 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2185 "org.freedesktop.Dbus.ObjectManager",
2187 g_variant_new("(oa{sa{sv}})",
2188 desc_info->desc_path, builder),
2191 if (error != NULL) {
2192 BT_ERR("D-Bus API failure: errCode[%x], \
2194 error->code, error->message);
2195 g_clear_error(&error);
2198 g_variant_builder_unref(inner_builder);
2199 g_variant_builder_unref(builder);
2200 g_variant_builder_unref(builder1);
2202 return BLUETOOTH_ERROR_NONE;
2205 int bluetooth_gatt_get_service(const char *svc_uuid)
2207 GDBusProxy *proxy = NULL;
2210 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2211 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2213 return BLUETOOTH_ERROR_INTERNAL;
2215 uuid = g_strdup(svc_uuid);
2217 g_dbus_proxy_call(proxy,
2219 g_variant_new("(s)",
2221 G_DBUS_CALL_FLAGS_NONE, -1,
2223 (GAsyncReadyCallback) get_service_cb,
2228 return BLUETOOTH_ERROR_NONE;
2231 BT_EXPORT_API int bluetooth_gatt_register_service(const char *svc_path)
2233 struct gatt_service_info *svc_info = NULL;
2235 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2236 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2237 BT_ERR("Don't have aprivilege to use this API");
2238 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2241 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2242 if (svc_info == NULL) {
2243 BT_ERR("Cannot find service [%s]", svc_path);
2244 return BLUETOOTH_ERROR_INTERNAL;
2246 svc_info->is_svc_registered = TRUE;
2248 return BLUETOOTH_ERROR_NONE;
2251 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2253 GDBusProxy *proxy = NULL;
2255 if (!is_server_started) {
2256 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2257 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2258 BT_ERR("Don't have aprivilege to use this API");
2259 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2262 if (g_slist_length(gatt_services) == 0) {
2263 BT_ERR("There is no registered service");
2264 return BLUETOOTH_ERROR_INTERNAL;
2267 if (app_path == NULL) {
2268 BT_ERR("app_path is NULL");
2269 return BLUETOOTH_ERROR_INTERNAL;
2272 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2273 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2274 if (proxy == NULL) {
2275 BT_ERR("proxy is NULL");
2276 return BLUETOOTH_ERROR_INTERNAL;
2279 BT_INFO("RegisterApplication");
2281 if (register_cancel) {
2282 g_cancellable_cancel(register_cancel);
2283 g_object_unref(register_cancel);
2285 register_cancel = g_cancellable_new();
2287 g_dbus_proxy_call(proxy, "RegisterApplication",
2288 g_variant_new("(oa{sv})", app_path, NULL),
2289 G_DBUS_CALL_FLAGS_NONE, -1, register_cancel,
2290 (GAsyncReadyCallback)register_application_cb, NULL);
2292 is_server_started = true;
2294 return BLUETOOTH_ERROR_NONE;
2297 BT_INFO("Already RegisterApplication");
2299 return BLUETOOTH_ERROR_NONE;
2302 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2305 int ret = BLUETOOTH_ERROR_NONE;
2307 if (gatt_services == NULL) {
2308 BT_DBG("There are no registered services");
2313 for (l = gatt_services; l != NULL; ) {
2314 struct gatt_service_info *info = l->data;
2316 // In __bt_gatt_unregister_service, current node will be removed.
2317 // Go forward to next node before calling __bt_gatt_unregister_service.
2319 if (__bt_gatt_unregister_service(info) != BLUETOOTH_ERROR_NONE) {
2320 ret = BLUETOOTH_ERROR_INTERNAL;
2323 BT_INFO("All services are removed : %d", ret);
2325 g_slist_free(gatt_services);
2326 gatt_services = NULL;
2332 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2333 const char *char_path, const char* char_value,
2336 GVariantBuilder *outer_builder;
2337 GVariantBuilder *inner_builder;
2338 GVariantBuilder *invalidated_builder;
2339 GVariant *update_value = NULL;
2340 GError *error = NULL;
2341 gboolean ret = FALSE;
2342 int err = BLUETOOTH_ERROR_NONE;
2344 gchar **line_argv = NULL;
2345 gchar *serv_path = NULL;
2346 const char *value = NULL;
2348 line_argv = g_strsplit_set(char_path, "/", 0);
2349 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2351 if (!__bt_gatt_is_service_registered(serv_path)) {
2352 BT_DBG("service not registered for this characteristic");
2354 g_strfreev(line_argv);
2355 return BLUETOOTH_ERROR_INTERNAL;
2358 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2359 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2361 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2362 for (i = 0; i < value_length; i++)
2363 g_variant_builder_add(inner_builder, "y", char_value[i]);
2365 update_value = g_variant_new("ay", inner_builder);
2367 g_variant_builder_add(outer_builder, "{sv}", "Value",
2370 BT_DBG("Updating characteristic value");
2371 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2373 "org.freedesktop.DBus.Properties",
2374 "PropertiesChanged",
2375 g_variant_new("(sa{sv}as)",
2376 "org.bluez.GattCharacteristic1",
2377 outer_builder, invalidated_builder),
2381 if (error != NULL) {
2382 BT_ERR("D-Bus API failure: errCode[%x], \
2384 error->code, error->message);
2385 g_clear_error(&error);
2387 err = BLUETOOTH_ERROR_INTERNAL;
2389 struct gatt_char_info *char_info = NULL;
2391 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2392 if (char_info == NULL) {
2394 g_strfreev(line_argv);
2395 g_variant_builder_unref(inner_builder);
2396 g_variant_builder_unref(outer_builder);
2397 g_variant_builder_unref(invalidated_builder);
2399 return BLUETOOTH_ERROR_INVALID_DATA;
2402 char_info->value_length = value_length;
2404 value = (char *)realloc(char_info->char_value, value_length);
2405 if (value == NULL) {
2407 g_strfreev(line_argv);
2408 g_variant_builder_unref(inner_builder);
2409 g_variant_builder_unref(outer_builder);
2410 g_variant_builder_unref(invalidated_builder);
2412 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2415 char_info->char_value = (char*)value;
2416 if (char_info->char_value) {
2417 for (i = 0; i < value_length; i++)
2418 char_info->char_value[i] = char_value[i];
2423 g_strfreev(line_argv);
2424 g_variant_builder_unref(inner_builder);
2425 g_variant_builder_unref(outer_builder);
2426 g_variant_builder_unref(invalidated_builder);
2431 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2438 g_free(desc_info->desc_path);
2439 g_free(desc_info->desc_uuid);
2440 g_free(desc_info->desc_value);
2442 for (i = 0; i < desc_info->flags_length; i++)
2443 g_free(desc_info->desc_flags[i]);
2448 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2455 g_free(char_info->char_path);
2456 g_free(char_info->char_uuid);
2457 g_free(char_info->char_value);
2459 for (i = 0; i < char_info->flags_length; i++)
2460 g_free(char_info->char_flags[i]);
2465 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2470 g_free(svc_info->serv_path);
2471 g_free(svc_info->service_uuid);
2475 static void __desc_info_free(gpointer data, gpointer user_data)
2477 struct gatt_desc_info *desc_info = data;
2478 int *err = user_data;
2481 if (desc_info == NULL)
2484 ret = g_dbus_connection_unregister_object(g_conn, desc_info->desc_id);
2486 __bt_gatt_emit_interface_removed(desc_info->desc_path, GATT_DESC_INTERFACE);
2488 *err = BLUETOOTH_ERROR_INTERNAL;
2490 __bt_gatt_free_descriptor_info(desc_info);
2493 static void __char_info_free(gpointer data, gpointer user_data)
2495 struct gatt_char_info *char_info = data;
2496 int *err = user_data;
2499 if (char_info == NULL)
2502 g_slist_foreach(char_info->desc_data, __desc_info_free, user_data);
2503 g_slist_free(char_info->desc_data);
2504 char_info->desc_data = NULL;
2506 ret = g_dbus_connection_unregister_object(g_conn, char_info->char_id);
2508 __bt_gatt_emit_interface_removed(char_info->char_path, GATT_CHAR_INTERFACE);
2510 *err = BLUETOOTH_ERROR_INTERNAL;
2512 __bt_gatt_free_characteristic_info(char_info);
2515 static int __bt_gatt_unregister_service(struct gatt_service_info *svc_info)
2517 int ret = BLUETOOTH_ERROR_NONE;
2519 if (svc_info == NULL) {
2520 BT_ERR("svc_info is NULL");
2521 return BLUETOOTH_ERROR_NOT_FOUND;
2524 if (svc_info->is_svc_registered == FALSE) {
2525 BT_ERR("%s is not registered", svc_info->serv_path);
2526 return BLUETOOTH_ERROR_NOT_FOUND;
2529 BT_DBG("svc_path %s", svc_info->serv_path);
2531 g_slist_foreach(svc_info->char_data, __char_info_free, &ret);
2532 g_slist_free(svc_info->char_data);
2533 svc_info->char_data = NULL;
2535 if (g_dbus_connection_unregister_object(g_conn, svc_info->serv_id) == FALSE) {
2536 BT_ERR("Cannot unregister object for [%s]", svc_info->serv_path);
2537 ret = BLUETOOTH_ERROR_INTERNAL;
2539 __bt_gatt_emit_interface_removed(svc_info->serv_path, GATT_SERV_INTERFACE);
2542 gatt_services = g_slist_remove(gatt_services, svc_info);
2543 __bt_gatt_free_service_info(svc_info);
2545 new_service = FALSE;
2547 if (gatt_services == NULL) {
2549 } else if (gatt_services->next == NULL) {
2556 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2558 struct gatt_service_info *svc_info;
2559 int ret = BLUETOOTH_ERROR_NONE;
2563 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2565 ret = __bt_gatt_unregister_service(svc_info);
2566 if (ret != BLUETOOTH_ERROR_NONE) {
2567 BT_ERR("Could not unregister service [%s]", svc_path);
2574 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2575 int resp_state, int offset, char *value, int value_length)
2577 struct gatt_req_info *req_info = NULL;
2579 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2580 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2581 BT_ERR("Don't have aprivilege to use this API");
2582 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2585 req_info = __bt_gatt_find_request_info(request_id);
2586 if (req_info == NULL) {
2587 BT_ERR("Coundn't find request id [%d]", request_id);
2588 return BLUETOOTH_ERROR_INTERNAL;
2591 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2592 BT_ERR("resp_state is 0x%X", resp_state);
2593 char err_msg[20] = { 0, };
2594 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2595 g_dbus_method_invocation_return_dbus_error(req_info->context,
2596 "org.bluez.Error.Failed", err_msg);
2598 gatt_requests = g_slist_remove(gatt_requests, req_info);
2600 req_info->context = NULL;
2601 if (req_info->attr_path)
2602 g_free(req_info->attr_path);
2603 if (req_info->svc_path)
2604 g_free(req_info->svc_path);
2607 return BLUETOOTH_ERROR_NONE;
2610 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2612 GVariantBuilder *inner_builder = NULL;
2613 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2614 if (value_length > 0 && value != NULL) {
2615 for (i = 0; i < value_length; i++)
2616 g_variant_builder_add(inner_builder, "y", value[i]);
2618 g_dbus_method_invocation_return_value(req_info->context,
2619 g_variant_new("(ay)", inner_builder));
2620 g_variant_builder_unref(inner_builder);
2622 g_dbus_method_invocation_return_value(req_info->context, NULL);
2624 gatt_requests = g_slist_remove(gatt_requests, req_info);
2626 req_info->context = NULL;
2627 if (req_info->attr_path)
2628 g_free(req_info->attr_path);
2629 if (req_info->svc_path)
2630 g_free(req_info->svc_path);
2633 return BLUETOOTH_ERROR_NONE;
2636 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2637 bluetooth_device_address_t *unicast_address)
2639 GVariantBuilder *outer_builder;
2640 GVariantBuilder *invalidated_builder;
2641 GError *error = NULL;
2642 gboolean notify = TRUE;
2643 gboolean ret = TRUE;
2644 int err = BLUETOOTH_ERROR_NONE;
2645 gchar **line_argv = NULL;
2646 gchar *serv_path = NULL;
2647 char addr[20] = { 0 };
2649 line_argv = g_strsplit_set(char_path, "/", 0);
2650 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2652 if (!__bt_gatt_is_service_registered(serv_path)) {
2653 BT_DBG("service not registered for this characteristic");
2655 g_strfreev(line_argv);
2656 return BLUETOOTH_ERROR_INTERNAL;
2661 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2662 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2664 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2665 g_variant_new("b", notify));
2667 if (unicast_address) {
2668 _bt_convert_addr_type_to_string(addr,
2669 (unsigned char *)unicast_address->addr);
2671 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2672 g_variant_new("s", addr));
2674 BT_DBG("Set characteristic Notification");
2675 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2677 "org.freedesktop.DBus.Properties",
2678 "PropertiesChanged",
2679 g_variant_new("(sa{sv}as)",
2680 "org.bluez.GattCharacteristic1",
2681 outer_builder, invalidated_builder),
2685 if (error != NULL) {
2686 BT_ERR("D-Bus API failure: errCode[%x], \
2688 error->code, error->message);
2689 g_clear_error(&error);
2691 err = BLUETOOTH_ERROR_INTERNAL;
2694 g_strfreev(line_argv);
2695 g_variant_builder_unref(outer_builder);
2696 g_variant_builder_unref(invalidated_builder);
2701 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2704 int ret = BLUETOOTH_ERROR_NONE;
2707 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2709 /* Register event handler for GATT */
2710 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2712 if (ret != BLUETOOTH_ERROR_NONE &&
2713 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2714 BT_ERR("Fail to init the event handler");
2715 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2719 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2720 in_param1, in_param2, in_param3, in_param4, &out_param);
2722 /* App ID -1 is invalid */
2723 if (ret != BLUETOOTH_ERROR_NONE) {
2724 BT_INFO("GATT Server Registration failed result [%d]", ret);
2727 *instance_id = g_array_index(out_param, int, 0);
2728 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2732 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2734 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2738 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2741 BT_INFO("GATT Server Deinitialize");
2742 /* Unregister the event */
2743 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2745 if (ret != BLUETOOTH_ERROR_NONE) {
2746 BT_ERR("Fail to deinit the event handler");
2750 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2755 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2756 int instance_id, int *service_handle)
2758 BT_CHECK_ENABLED(return);
2759 BT_CHECK_PARAMETER(svc_uuid, return);
2762 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2764 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2767 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2769 g_array_append_vals(in_param1, &type, sizeof(int));
2770 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2771 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2772 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2774 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2775 in_param1, in_param2, in_param3, in_param4, &out_param);
2777 /* ATT handle 0 is reserved, hence it can not be used by app.
2778 It will be used to indicate error in regsitering attribute */
2779 if (result != BLUETOOTH_ERROR_NONE)
2780 *service_handle = 0;
2782 *service_handle = g_array_index(out_param, int, 0);
2784 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2789 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2790 const bluetooth_gatt_server_attribute_params_t *param,
2793 BT_CHECK_ENABLED(return);
2794 BT_CHECK_PARAMETER(char_uuid, return);
2795 BT_CHECK_PARAMETER(param, return);
2798 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2800 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2803 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2805 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2806 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2808 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2809 in_param1, in_param2, in_param3, in_param4, &out_param);
2811 /* ATT handle 0 is reserved, hence it can not be used by app.
2812 It will be used to indicate error in regsitering attribute */
2813 if (result != BLUETOOTH_ERROR_NONE) {
2814 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2817 *char_handle = g_array_index(out_param, int, 0);
2818 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2821 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2825 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2826 int service_handle, int instance_id, int *descriptor_handle)
2828 BT_CHECK_ENABLED(return);
2829 BT_CHECK_PARAMETER(desc_uuid, return);
2832 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2834 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2837 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2839 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2840 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2841 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2842 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2844 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2845 in_param1, in_param2, in_param3, in_param4, &out_param);
2847 /* ATT handle 0 is reserved, hence it can not be used by app.
2848 It will be used to indicate error in regsitering attribute */
2849 if (result != BLUETOOTH_ERROR_NONE) {
2850 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2851 *descriptor_handle = 0;
2853 *descriptor_handle = g_array_index(out_param, int, 0);
2854 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2857 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2862 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
2864 BT_CHECK_ENABLED(return);
2868 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2870 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2871 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2873 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
2874 in_param1, in_param2, in_param3, in_param4, &out_param);
2876 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2881 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
2882 const bluetooth_gatt_att_data_t *value)
2884 BT_CHECK_PARAMETER(param, return);
2885 BT_CHECK_PARAMETER(value, return);
2886 BT_CHECK_ENABLED(return);
2890 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2892 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
2893 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
2895 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
2896 in_param1, in_param2, in_param3, in_param4, &out_param);
2898 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2904 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
2905 bluetooth_gatt_server_indication_params_t *param,
2906 const bluetooth_gatt_att_data_t *att_value)
2908 BT_CHECK_PARAMETER(param, return);
2909 BT_CHECK_PARAMETER(att_value, return);
2910 BT_CHECK_ENABLED(return);
2912 char addr[BLUETOOTH_ADDRESS_STRING_LENGTH] ;
2916 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2918 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
2919 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
2920 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
2922 _bt_convert_addr_type_to_string(addr, addr_hex->addr);
2923 BT_INFO("Send Indication to address [%s]", addr);
2924 fd = bluetooth_get_characteristic_fd(param->atrribute_handle, addr);
2927 BT_INFO("Send Multicast");
2928 result = bluetooth_gatt_write_characteristics_value_to_fd_(fd, att_value->data, att_value->length, NULL);
2930 } else if (fd == -2) {
2931 BT_ERR("Acquire Notify FD not found for charatcristic handle");
2932 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2933 return BLUETOOTH_ERROR_INVALID_PARAM;
2934 } else if (fd == -1) {
2935 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
2936 in_param1, in_param2, in_param3, in_param4, &out_param);
2939 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2944 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
2946 BT_CHECK_ENABLED(return);
2950 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2952 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2953 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2955 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
2956 in_param1, in_param2, in_param3, in_param4, &out_param);
2958 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2963 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
2965 BT_CHECK_ENABLED(return);
2969 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2971 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2972 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2974 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
2975 in_param1, in_param2, in_param3, in_param4, &out_param);
2977 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2982 /* Tizen Platform Specific */
2983 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
2984 const bluetooth_gatt_server_update_value_t *value)
2986 BT_CHECK_ENABLED(return);
2987 BT_CHECK_PARAMETER(value, return);
2991 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2993 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2994 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
2996 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
2997 in_param1, in_param2, in_param3, in_param4, &out_param);
2999 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3004 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3006 BT_CHECK_ENABLED(return);
3010 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3012 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3014 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3015 in_param1, in_param2, in_param3, in_param4, &out_param);
3017 if (result != BLUETOOTH_ERROR_NONE)
3018 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3020 BT_INFO("GATT Server Unregistration successful");
3022 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3027 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3028 GIOCondition cond, gpointer data)
3031 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3033 BT_DBG("FD io write data received [%s]", write_data->address);
3035 if (cond & G_IO_NVAL) {
3036 BT_ERR("Invalid channel");
3040 if (cond & (G_IO_HUP | G_IO_ERR)) {
3041 BT_ERR("Error : GIOCondition %d", cond);
3042 g_io_channel_shutdown(gio, TRUE, NULL);
3043 g_io_channel_unref(gio);
3048 if (cond & G_IO_IN) {
3049 GIOStatus status = G_IO_STATUS_NORMAL;
3051 char *buffer = NULL;
3053 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3055 buffer = g_malloc0(BUF);
3057 status = g_io_channel_read_chars(gio, buffer,
3060 if (status != G_IO_STATUS_NORMAL) {
3061 BT_ERR("IO Channel read is failed with %d", status);
3064 BT_ERR("IO Channel read error [%s]", err->message);
3065 if (status == G_IO_STATUS_ERROR) {
3066 BT_ERR("cond : %d", cond);
3068 g_io_channel_shutdown(gio, TRUE, NULL);
3069 g_io_channel_unref(gio);
3079 bluetooth_gatt_server_write_requested_info_t write_info;
3080 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3081 memcpy(write_info.data.data, buffer, len);
3083 write_info.length = len;
3084 write_info.need_resp = false;
3085 write_info.attribute_handle = write_data->attribute_handle;
3087 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->address);
3088 write_info.connection_id = write_data->connection_id;
3089 write_info.offset = write_data->offset;
3090 write_info.request_id = -2;
3092 bt_event_info_t *event_info;
3093 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3097 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3098 BLUETOOTH_ERROR_NONE, &write_info,
3099 event_info->cb, event_info->user_data);
3101 BT_ERR("eventinfo failed");
3112 void bluetooth_gatt_server_send_acquire_write_response(GVariant * parameters)
3117 int pipefd[2] = {-1,};
3120 char err_msg[512] = {'\0'};
3121 GIOChannel *channel = NULL;
3125 g_variant_get(parameters, "(iiiiii&s)",
3134 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3135 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3136 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3137 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3140 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3141 strerror_r(errno, err_msg, sizeof(err_msg));
3142 BT_ERR("socketpair(): %s", err_msg);
3147 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3149 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3150 bluetooth_gatt_server_acquire_response_params_t data;
3151 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
3152 data.fd = pipefd[1];
3154 data.request_id = tran_id;
3156 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3158 write_info->attribute_handle = att_han;
3159 write_info->connection_id = tran_id;
3160 write_info->offset = offset;
3162 memcpy(write_info->address, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3164 BT_INFO("FD read %d remote address [%s ] \n", pipefd[0], addr);
3166 channel = g_io_channel_unix_new(pipefd[0]);
3167 g_io_channel_set_encoding(channel, NULL, NULL);
3168 g_io_channel_set_buffered(channel, FALSE);
3169 g_io_channel_set_close_on_unref(channel, TRUE);
3170 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3171 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3172 bluetooth_gatt_server_acquire_channel_write_cb, write_info);
3174 GUnixFDList *fd_list = g_unix_fd_list_new();
3175 GError *error = NULL;
3177 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3178 g_assert_no_error(error);
3181 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3183 BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3185 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE,
3186 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3188 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3189 g_object_unref(fd_list);
3192 void bluetooth_gatt_server_send_acquire_notify_response(GVariant * parameters, bt_event_info_t *event_info)
3197 int pipefd[2] = {-1,};
3200 char err_msg[512] = {'\0'};
3201 GIOChannel *channel = NULL;
3204 bluetooth_gatt_acquire_notify_info_t *chr_info;
3205 const char *address = NULL;
3207 g_variant_get(parameters, "(iiiiii&s)",
3216 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3217 BT_DBG("GATT Server Acquire notify att handle:[%d]", att_han);
3218 BT_DBG("GATT Server Acquire Notify Offset: [%d]", offset);
3219 BT_DBG("GATT Server Acquire Notify address: [%s]", address);
3222 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3223 strerror_r(errno, err_msg, sizeof(err_msg));
3224 BT_ERR("socketpair(): %s", err_msg);
3231 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3233 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3234 bluetooth_gatt_server_acquire_response_params_t data;
3235 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
3236 data.fd = pipefd[1];
3238 data.request_id = tran_id;
3240 BT_INFO("FD write %d", pipefd[0]);
3242 chr_info = bluetooth_get_characteristic_info_from_path(att_han);
3244 BT_INFO("char info not found for ATT handle [%u]", att_han);
3245 chr_info = g_malloc0(sizeof(bluetooth_gatt_acquire_notify_info_t));
3246 chr_info->write_fd = fd;
3247 chr_info->att_hand = att_han;
3248 memcpy(chr_info->address, address, BLUETOOTH_ADDRESS_STRING_LENGTH);
3250 gatt_characteristic_server_notify_list = g_slist_append(gatt_characteristic_server_notify_list, chr_info);
3252 BT_INFO("Already AcquireNotify Set for this attribute handle by remote Client [%s]", chr_info->address);
3253 chr_info->write_fd = fd;
3256 channel = g_io_channel_unix_new(fd);
3257 chr_info->io_channel = channel;
3258 g_io_channel_set_encoding(channel, NULL, NULL);
3259 g_io_channel_set_buffered(channel, FALSE);
3260 g_io_channel_set_close_on_unref(channel, TRUE);
3261 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3262 chr_info->watch_id =
3263 g_io_add_watch(channel,
3264 (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
3265 bluetooth_gatt_write_channel_watch_cb, chr_info);
3267 GUnixFDList *fd_list = g_unix_fd_list_new();
3268 GError *error = NULL;
3270 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3271 g_assert_no_error(error);
3274 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3276 BT_DBG("Sending event BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE file descriptor value [%d] ", data.fd);
3278 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQUIRE_NOTIFY_RESPONSE,
3279 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3281 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3282 g_object_unref(fd_list);
3285 if (result == BLUETOOTH_ERROR_NONE) {
3286 BT_DBG("sending gatt server notification state changed event");
3287 bluetooth_gatt_server_notification_changed_t info;
3288 bluetooth_device_address_t dev_address = { {0} };
3289 memset(&info, 0x00, sizeof(bluetooth_gatt_server_notification_changed_t));
3291 _bt_convert_addr_string_to_type(dev_address.addr, address);
3292 memcpy(info.device_address.addr,
3294 BLUETOOTH_ADDRESS_LENGTH);
3295 info.handle = att_han;
3296 info.notification = TRUE;
3298 _bt_gatt_server_event_cb(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
3300 event_info->cb, event_info->user_data);
3305 void cleanup_gatt_acquire_fd(int handle)
3307 bluetooth_gatt_acquire_notify_info_t *chr_info = NULL;
3311 chr_info = bluetooth_get_characteristic_info_from_path(handle);
3313 if (chr_info != NULL) {
3314 BT_INFO("GATT Server: acquire notification char info found [%s]", chr_info->path);
3316 if (chr_info->watch_id > 0)
3317 g_source_remove(chr_info->watch_id);
3319 if (chr_info->io_channel) {
3320 g_io_channel_shutdown(chr_info->io_channel, TRUE, NULL);
3321 g_io_channel_unref(chr_info->io_channel);
3324 BT_INFO("Removing char_info from the list");
3325 gatt_characteristic_server_notify_list = g_slist_remove(gatt_characteristic_server_notify_list, chr_info);
3326 bluetooth_characteristic_info_free(chr_info);