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
41 /* Common defintions to follow , applicable for both
42 GATT_DIRECT and RELAY */
45 #define NUMBER_OF_FLAGS 10
46 int bluetooth_gatt_convert_prop2string(
47 bt_gatt_characteristic_property_t properties,
48 char *char_properties[])
52 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
53 char_properties[flag_count] = g_strdup("broadcast");
56 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
57 char_properties[flag_count] = g_strdup("read");
60 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
61 char_properties[flag_count] = g_strdup("write-without-response");
64 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
65 char_properties[flag_count] = g_strdup("write");
68 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
69 char_properties[flag_count] = g_strdup("notify");
72 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
73 char_properties[flag_count] = g_strdup("indicate");
76 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
77 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
80 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
81 char_properties[flag_count] = g_strdup("reliable-write");
84 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
85 char_properties[flag_count] = g_strdup("writable-auxiliaries");
88 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
89 char_properties[flag_count] = g_strdup("encrypt-read");
92 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
93 char_properties[flag_count] = g_strdup("encrypt-write");
96 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
97 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
100 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
101 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
105 if (flag_count == 0) {
106 char_properties[flag_count] = g_strdup("read");
113 int bluetooth_gatt_convert_perm2string(
114 bt_gatt_permission_t properties,
115 char *char_properties[])
119 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
120 char_properties[flag_count] = g_strdup("read");
123 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
124 char_properties[flag_count] = g_strdup("write");
127 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
128 char_properties[flag_count] = g_strdup("encrypt-read");
131 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
132 char_properties[flag_count] = g_strdup("encrypt-write");
135 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
136 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
139 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
140 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
144 if (flag_count == 0) {
145 char_properties[flag_count] = g_strdup("read");
153 #define NUMBER_OF_FLAGS 10
155 GDBusConnection *g_conn;
158 static gboolean new_service = FALSE;
159 static gboolean new_char = FALSE;
160 static int serv_id = 1;
161 static int register_pending_cnt = 0;
162 static bool is_server_started = false;
164 GCancellable *register_cancel;
166 /* Introspection data for the service we are exporting */
167 static const gchar service_introspection_xml[] =
169 " <interface name='org.freedesktop.DBus.Properties'>"
170 " <property type='s' name='UUID' access='read'>"
172 " <property type='b' name='primary' access='read'>"
174 " <property type='o' name='Device' access='read'>"
176 " <property type='ao' name='Characteristics' access='read'>"
178 " <property type='s' name='Includes' access='read'>"
183 /* Introspection data for the characteristics we are exporting */
184 static const gchar characteristics_introspection_xml[] =
186 " <interface name='org.bluez.GattCharacteristic1'>"
187 " <method name='ReadValue'>"
188 " <arg type='s' name='address' direction='in'/>"
189 " <arg type='u' name='id' direction='in'/>"
190 " <arg type='q' name='offset' direction='in'/>"
191 " <arg type='ay' name='Value' direction='out'/>"
193 " <method name='WriteValue'>"
194 " <arg type='s' name='address' direction='in'/>"
195 " <arg type='u' name='id' direction='in'/>"
196 " <arg type='q' name='offset' direction='in'/>"
197 " <arg type='b' name='response_needed' direction='in'/>"
198 " <arg type='ay' name='value' direction='in'/>"
200 " <method name='StartNotify'>"
202 " <method name='StopNotify'>"
204 " <method name='IndicateConfirm'>"
205 " <arg type='s' name='address' direction='in'/>"
206 " <arg type='b' name='complete' direction='in'/>"
209 " <interface name='org.freedesktop.DBus.Properties'>"
210 " <property type='s' name='UUID' access='read'>"
212 " <property type='o' name='Service' access='read'>"
214 " <property type='ay' name='Value' access='readwrite'>"
216 " <property type='b' name='Notifying' access='read'>"
218 " <property type='as' name='Flags' access='read'>"
220 " <property type='s' name='Unicast' access='read'>"
222 " <property type='ao' name='Descriptors' access='read'>"
227 /* Introspection data for the descriptor we are exporting */
228 static const gchar descriptor_introspection_xml[] =
230 " <interface name='org.bluez.GattDescriptor1'>"
231 " <method name='ReadValue'>"
232 " <arg type='s' name='address' direction='in'/>"
233 " <arg type='u' name='id' direction='in'/>"
234 " <arg type='q' name='offset' direction='in'/>"
235 " <arg type='ay' name='Value' direction='out'/>"
237 " <method name='WriteValue'>"
238 " <arg type='s' name='address' direction='in'/>"
239 " <arg type='u' name='id' direction='in'/>"
240 " <arg type='q' name='offset' direction='in'/>"
241 " <arg type='b' name='response_needed' direction='in'/>"
242 " <arg type='ay' name='value' direction='in'/>"
245 " <interface name='org.freedesktop.DBus.Properties'>"
246 " <property type='s' name='UUID' access='read'>"
248 " <property type='o' name='Characteristic' access='read'>"
250 " <property type='ay' name='Value' access='read'>"
252 " <property type='as' name='Flags' access='read'>"
257 static const gchar manager_introspection_xml[] =
259 " <interface name='org.freedesktop.DBus.ObjectManager'>"
260 " <method name='GetManagedObjects'>"
261 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
266 struct gatt_service_info {
273 gboolean is_svc_registered;
274 gboolean is_svc_primary;
277 struct gatt_char_info {
282 gchar *char_flags[NUMBER_OF_FLAGS];
288 struct gatt_desc_info {
293 gchar *desc_flags[NUMBER_OF_FLAGS];
298 struct gatt_req_info {
303 GDBusMethodInvocation *context;
306 static GSList *gatt_services = NULL;
307 static GSList *gatt_requests = NULL;
308 static gchar *app_path = NULL;
310 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
311 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
313 #define GATT_SERV_OBJECT_PATH "/service"
315 #define GATT_MNGR_INTERFACE "org.bluez.GattManager1"
316 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
317 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
318 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
320 #ifdef TIZEN_FEATURE_BT_HPS
321 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
322 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
323 #define PROPERTIES_CHANGED "PropertiesChanged"
324 #define BT_HPS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
327 #ifdef TIZEN_FEATURE_BT_OTP
328 #define BT_OTP_OBJECT_PATH "/org/projectx/otp"
329 #define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
330 #define PROPERTIES_CHANGED "PropertiesChanged"
331 #define BT_OTP_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
334 static GDBusProxy *manager_gproxy = NULL;
336 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
337 const char *service_path, const char *char_path);
338 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
339 const char *serv_path, const char *char_path,
340 const char *desc_path);
342 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
344 static void __bt_gatt_close_gdbus_connection(void)
350 ret_if(g_conn == NULL);
352 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
353 BT_ERR("Fail to flush the connection: %s", err->message);
358 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
360 BT_ERR("Fail to close the dbus connection: %s", err->message);
365 g_object_unref(g_conn);
372 #ifdef TIZEN_FEATURE_BT_HPS
373 static int __bt_send_event_to_hps(int event, GVariant *var)
375 GError *error = NULL;
376 GVariant *parameters;
377 GDBusMessage *msg = NULL;
381 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
383 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
384 GVariantBuilder *inner_builder;
385 GVariantBuilder *invalidated_builder;
387 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
388 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
390 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
392 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
394 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
395 g_variant_builder_unref(invalidated_builder);
396 g_variant_builder_unref(inner_builder);
397 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
398 GVariantBuilder *inner_builder;
399 GVariantBuilder *invalidated_builder;
401 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
402 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
404 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
406 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
408 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
409 g_variant_builder_unref(invalidated_builder);
410 g_variant_builder_unref(inner_builder);
412 g_varaiant_unref(var);
415 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
416 g_dbus_message_set_body(msg, parameters);
417 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
419 BT_ERR("D-Bus API failure: errCode[%x], \
421 error->code, error->message);
422 g_clear_error(&error);
424 return BLUETOOTH_ERROR_INTERNAL;
426 return BLUETOOTH_ERROR_NONE;
430 #ifdef TIZEN_FEATURE_BT_OTP
431 static int __bt_send_event_to_otp(int event, GVariant *var)
433 GError *error = NULL;
434 GVariant *parameters = NULL;
435 GDBusMessage *msg = NULL;
439 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
441 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
442 GVariantBuilder *inner_builder;
443 GVariantBuilder *invalidated_builder;
445 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
446 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
448 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
450 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
452 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
453 g_variant_builder_unref(invalidated_builder);
454 g_variant_builder_unref(inner_builder);
455 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
456 GVariantBuilder *inner_builder;
457 GVariantBuilder *invalidated_builder;
459 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
460 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
462 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
464 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
466 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
467 g_variant_builder_unref(invalidated_builder);
468 g_variant_builder_unref(inner_builder);
469 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
470 GVariantBuilder *inner_builder;
471 GVariantBuilder *invalidated_builder;
473 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
474 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
476 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
478 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
480 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
481 g_variant_builder_unref(invalidated_builder);
482 g_variant_builder_unref(inner_builder);
485 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
486 g_dbus_message_set_body(msg, parameters);
487 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
489 BT_ERR("D-Bus API failure: errCode[%x], \
491 error->code, error->message);
492 g_clear_error(&error);
494 return BLUETOOTH_ERROR_INTERNAL;
496 return BLUETOOTH_ERROR_NONE;
500 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
502 const gchar *object_path,
503 const gchar *interface_name,
504 const gchar *method_name,
505 GVariant *parameters,
506 GDBusMethodInvocation *invocation,
513 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
514 BT_DBG("Getting values for service, chars and descriptors");
516 GVariantBuilder *builder;
517 GVariantBuilder *inner_builder1 = NULL;
518 GVariant *svc_char = NULL;
521 builder = g_variant_builder_new(
522 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
524 /* Prepare inner builder for GattService1 interface */
526 len = g_slist_length(gatt_services);
528 for (i = 0; i <= len; i++) {
529 GVariantBuilder *svc_builder = NULL;
530 GVariantBuilder *inner_builder = NULL;
532 if (register_pending_cnt > 1)
533 l1 = g_slist_nth(gatt_services, len - register_pending_cnt);
535 l1 = g_slist_last(gatt_services);
537 register_pending_cnt--;
540 BT_ERR("gatt service list is NULL");
541 g_dbus_method_invocation_return_value(invocation, NULL);
542 g_variant_builder_unref(builder);
546 struct gatt_service_info *serv_info = l1->data;
547 if (serv_info == NULL) {
548 BT_ERR("service info value is NULL");
549 g_dbus_method_invocation_return_value(invocation, NULL);
550 g_variant_builder_unref(builder);
554 /* Prepare inner builder for GattService1 interface */
555 BT_DBG("Creating builder for service");
556 svc_builder = g_variant_builder_new(
557 G_VARIANT_TYPE("a{sa{sv}}"));
558 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
560 g_variant_builder_add(inner_builder, "{sv}", "UUID",
561 g_variant_new_string(serv_info->service_uuid));
563 g_variant_builder_add(inner_builder, "{sv}", "Primary",
564 g_variant_new_boolean(serv_info->is_svc_primary));
567 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
568 BT_DBG("Adding Charatarisitcs list");
569 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
570 struct gatt_char_info *char_info = l4->data;
571 g_variant_builder_add(inner_builder1, "o",
572 char_info->char_path);
573 BT_DBG("%s", char_info->char_path);
576 svc_char = g_variant_new("ao", inner_builder1);
577 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
580 g_variant_builder_add(svc_builder, "{sa{sv}}",
584 g_variant_builder_add(builder, "{oa{sa{sv}}}",
585 serv_info->serv_path,
588 g_variant_builder_unref(inner_builder1);
590 /* Prepare inner builder for GattCharacteristic1 interface */
592 GSList *l2 = serv_info->char_data;
593 BT_DBG("Creating builder for characteristics \n");
596 BT_DBG("characteristic data is NULL");
598 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
600 GVariantBuilder *char_builder = NULL;
601 GVariantBuilder *inner_builder = NULL;
602 GVariantBuilder *builder1 = NULL;
603 GVariantBuilder *builder2 = NULL;
604 GVariantBuilder *builder3 = NULL;
605 GVariant *char_val = NULL;
606 GVariant *flags_val = NULL;
607 GVariant *char_desc = NULL;
608 char *unicast = NULL;
609 gboolean notify = FALSE;
612 char_builder = g_variant_builder_new(
615 inner_builder = g_variant_builder_new(
619 struct gatt_char_info *char_info = l2->data;
620 if (char_info == NULL) {
621 BT_ERR("char_info is NULL");
626 g_variant_builder_add(inner_builder, "{sv}", "UUID",
627 g_variant_new_string(char_info->char_uuid));
629 g_variant_builder_add(inner_builder, "{sv}", "Service",
630 g_variant_new("o", serv_info->serv_path));
632 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
634 if (char_info->char_value != NULL) {
635 for (i = 0; i < char_info->value_length; i++) {
636 g_variant_builder_add(builder1, "y",
637 char_info->char_value[i]);
639 char_val = g_variant_new("ay", builder1);
640 g_variant_builder_add(inner_builder, "{sv}",
644 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
646 for (i = 0; i < char_info->flags_length; i++) {
647 g_variant_builder_add(builder2, "s",
648 char_info->char_flags[i]);
651 flags_val = g_variant_new("as", builder2);
652 g_variant_builder_add(inner_builder, "{sv}", "Flags",
656 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
657 g_variant_new("b", notify));
660 unicast = g_strdup("00:00:00:00:00:00");
661 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
662 g_variant_new("s", unicast));
665 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
666 BT_DBG("Adding Descriptors list");
668 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
669 struct gatt_desc_info *desc_info = l4->data;
670 g_variant_builder_add(builder3, "o",
671 desc_info->desc_path);
672 BT_DBG("%s", desc_info->desc_path);
675 char_desc = g_variant_new("ao", builder3);
676 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
679 g_variant_builder_add(char_builder, "{sa{sv}}",
680 GATT_CHAR_INTERFACE , inner_builder);
681 g_variant_builder_add(builder, "{oa{sa{sv}}}",
682 char_info->char_path, char_builder);
684 /*Prepare inner builder for GattDescriptor1 interface*/
686 GSList *l3 = char_info->desc_data;
689 BT_DBG("descriptor data is NULL");
691 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
693 BT_DBG("Creating builder for descriptor \n");
695 GVariantBuilder *desc_builder = NULL;
696 GVariantBuilder *inner_builder = NULL;
697 GVariantBuilder *builder1 = NULL;
698 GVariantBuilder *builder2 = NULL;
699 GVariant *desc_val = NULL;
701 desc_builder = g_variant_builder_new(
704 inner_builder = g_variant_builder_new(
708 struct gatt_desc_info *desc_info = l3->data;
709 if (desc_info == NULL) {
710 BT_ERR("desc_info is NULL");
715 g_variant_builder_add(inner_builder,
717 g_variant_new_string(
718 desc_info->desc_uuid));
721 g_variant_builder_add(inner_builder, "{sv}",
724 char_info->char_path));
727 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
729 if (desc_info->desc_value != NULL) {
730 for (i = 0; i < desc_info->value_length; i++) {
731 g_variant_builder_add(builder1, "y",
732 desc_info->desc_value[i]);
734 desc_val = g_variant_new("ay", builder1);
735 g_variant_builder_add(inner_builder, "{sv}",
740 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
742 for (i = 0; i < desc_info->flags_length; i++) {
743 g_variant_builder_add(builder2, "s",
744 desc_info->desc_flags[i]);
747 flags_val = g_variant_new("as", builder2);
748 g_variant_builder_add(inner_builder, "{sv}", "Flags",
751 g_variant_builder_add(desc_builder, "{sa{sv}}",
755 g_variant_builder_add(builder, "{oa{sa{sv}}}",
756 desc_info->desc_path,
759 /*unref descriptor builder pointers*/
760 g_variant_builder_unref(builder1);
761 g_variant_builder_unref(builder2);
762 g_variant_builder_unref(inner_builder);
763 g_variant_builder_unref(desc_builder);
768 /*unref char builder pointers*/
769 g_variant_builder_unref(builder1);
770 g_variant_builder_unref(builder2);
771 g_variant_builder_unref(builder3);
772 g_variant_builder_unref(inner_builder);
773 g_variant_builder_unref(char_builder);
776 /*unref service builder pointers*/
777 g_variant_builder_unref(inner_builder);
778 g_variant_builder_unref(svc_builder);
781 /* Return builder as method reply */
782 BT_DBG("Sending gatt service builder values to Bluez");
783 g_dbus_method_invocation_return_value(invocation,
787 g_variant_builder_unref(builder);
791 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
795 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
796 struct gatt_service_info *serv_info = l1->data;
798 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
799 struct gatt_char_info *char_info = l2->data;
801 if (g_strcmp0(char_info->char_path, char_path)
806 BT_ERR("Gatt service not found");
810 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
812 GSList *l1, *l2, *l3;
814 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
815 struct gatt_service_info *serv_info = l1->data;
817 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
818 struct gatt_char_info *char_info = l2->data;
820 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
821 struct gatt_desc_info *desc_info = l3->data;
823 if (g_strcmp0(desc_info->desc_path, desc_path)
829 BT_ERR("Gatt service not found");
833 static void __bt_gatt_char_method_call(GDBusConnection *connection,
835 const gchar *object_path,
836 const gchar *interface_name,
837 const gchar *method_name,
838 GVariant *parameters,
839 GDBusMethodInvocation *invocation,
843 if (g_strcmp0(method_name, "ReadValue") == 0) {
847 bt_gatt_read_req_t read_req = {0, };
848 bt_user_info_t *user_info = NULL;
849 struct gatt_req_info *req_info = NULL;
850 struct gatt_service_info *svc_info = NULL;
851 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
852 GVariant *param = NULL;
855 BT_DBG("Application path = %s", object_path);
856 BT_DBG("Sender = %s", sender);
858 user_info = _bt_get_user_data(BT_COMMON);
859 if (user_info == NULL) {
860 BT_INFO("No callback is set for %s", object_path);
861 g_dbus_method_invocation_return_value(invocation, NULL);
865 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
866 if (svc_info == NULL) {
867 BT_ERR("Coudn't find service for %s", object_path);
868 g_dbus_method_invocation_return_value(invocation, NULL);
872 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
873 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
875 read_req.att_handle = (char *)object_path;
876 read_req.address = addr;
877 read_req.req_id = req_id;
878 read_req.offset = offset;
879 read_req.service_handle = svc_info->serv_path;
881 /* Store requets information */
882 req_info = g_new0(struct gatt_req_info, 1);
883 req_info->attr_path = g_strdup(object_path);
884 req_info->svc_path = g_strdup(read_req.service_handle);
885 req_info->request_id = req_id;
886 req_info->offset = offset;
887 req_info->context = invocation;
888 gatt_requests = g_slist_append(gatt_requests, req_info);
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 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
895 param = g_variant_new("(sssyq)",
897 read_req.service_handle,
901 #ifdef TIZEN_FEATURE_BT_HPS
902 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
904 #ifdef TIZEN_FEATURE_BT_OTP
905 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
909 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
910 GVariant *var = NULL;
914 gboolean response_needed = FALSE;
915 bt_gatt_value_change_t value_change = {0, };
916 bt_user_info_t *user_info = NULL;
918 struct gatt_service_info *svc_info = NULL;
919 struct gatt_req_info *req_info = NULL;
920 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
921 GVariant *param = NULL;
924 BT_DBG("WriteValue");
925 BT_DBG("Application path = %s", object_path);
926 BT_DBG("Sender = %s", sender);
928 g_variant_get(parameters, "(&suqb@ay)",
929 &addr, &req_id, &offset, &response_needed, &var);
930 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
932 user_info = _bt_get_user_data(BT_COMMON);
934 BT_INFO("No callback is set for %s", object_path);
935 g_variant_unref(var);
937 g_dbus_method_invocation_return_value(invocation, NULL);
939 g_object_unref(invocation);
943 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
944 if (svc_info == NULL) {
945 BT_ERR("Coudn't find service for %s", object_path);
946 g_variant_unref(var);
948 g_dbus_method_invocation_return_value(invocation, NULL);
950 g_object_unref(invocation);
954 value_change.att_handle = (char *)object_path;
955 value_change.address = addr;
956 value_change.service_handle = svc_info->serv_path;
957 value_change.offset = offset;
958 value_change.req_id = req_id;
959 value_change.response_needed = response_needed;
961 len = g_variant_get_size(var);
965 value_change.att_value = (guint8 *)g_malloc(len);
967 data = (char *)g_variant_get_data(var);
968 memcpy(value_change.att_value, data, len);
970 value_change.val_len = len;
972 if (response_needed) {
973 /* Store requets information */
974 req_info = g_new0(struct gatt_req_info, 1);
975 req_info->attr_path = g_strdup(object_path);
976 req_info->svc_path = g_strdup(value_change.service_handle);
977 req_info->request_id = req_id;
978 req_info->offset = offset;
979 req_info->context = invocation;
980 gatt_requests = g_slist_append(gatt_requests, req_info);
982 g_object_unref(invocation);
986 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
987 BLUETOOTH_ERROR_NONE, &value_change,
988 user_info->cb, user_info->user_data);
990 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
993 svc_path = g_strdup(svc_info->serv_path);
994 param = g_variant_new("(sssyq@ay)",
1001 #ifdef TIZEN_FEATURE_BT_HPS
1002 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1004 #ifdef TIZEN_FEATURE_BT_OTP
1005 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
1012 g_free(value_change.att_value);
1013 g_variant_unref(var);
1015 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1016 bt_user_info_t *user_info = NULL;
1017 bt_gatt_char_notify_change_t notify_change = {0, };
1018 #if TIZEN_FEATURE_BT_OTP
1019 GVariant *param = NULL;
1021 BT_DBG("StartNotify");
1022 user_info = _bt_get_user_data(BT_COMMON);
1023 if (user_info != NULL) {
1024 struct gatt_service_info *svc_info = NULL;
1025 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1027 notify_change.service_handle = svc_info->serv_path;
1028 notify_change.att_handle = (char *)object_path;
1029 notify_change.att_notify = TRUE;
1030 _bt_common_event_cb(
1031 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1032 BLUETOOTH_ERROR_NONE, ¬ify_change,
1033 user_info->cb, user_info->user_data);
1034 #if TIZEN_FEATURE_BT_OTP
1035 param = g_variant_new("(ssb)",
1036 notify_change.att_handle,
1037 notify_change.service_handle,
1038 notify_change.att_notify);
1039 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1043 g_object_unref(invocation);
1045 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1046 bt_user_info_t *user_info = NULL;
1047 bt_gatt_char_notify_change_t notify_change = {0, };
1048 #if TIZEN_FEATURE_BT_OTP
1049 GVariant *param = NULL;
1051 BT_DBG("StopNotify");
1052 user_info = _bt_get_user_data(BT_COMMON);
1053 if (user_info != NULL) {
1054 struct gatt_service_info *svc_info = NULL;
1055 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1057 notify_change.service_handle = svc_info->serv_path;
1058 notify_change.att_handle = (char *)object_path;
1059 notify_change.att_notify = FALSE;
1060 _bt_common_event_cb(
1061 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
1062 BLUETOOTH_ERROR_NONE, ¬ify_change,
1063 user_info->cb, user_info->user_data);
1064 #if TIZEN_FEATURE_BT_OTP
1065 param = g_variant_new("(ssb)",
1066 notify_change.att_handle,
1067 notify_change.service_handle,
1068 notify_change.att_notify);
1069 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
1073 g_object_unref(invocation);
1075 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1077 bt_gatt_indicate_confirm_t confirm = {0, };
1078 bt_user_info_t *user_info = NULL;
1079 gboolean complete = FALSE;
1080 struct gatt_service_info *svc_info = NULL;
1082 BT_DBG("IndicateConfirm");
1083 BT_DBG("Application path = %s", object_path);
1084 BT_DBG("Sender = %s", sender);
1086 g_variant_get(parameters, "(&sb)", &addr, &complete);
1087 BT_DBG("Remote Device address number = %s", addr);
1089 confirm.att_handle = (char *)object_path;
1090 confirm.address = addr;
1091 confirm.complete = complete;
1093 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
1094 if (svc_info != NULL) {
1095 confirm.service_handle = svc_info->serv_path;
1097 user_info = _bt_get_user_data(BT_COMMON);
1098 if (user_info != NULL) {
1099 _bt_common_event_cb(
1100 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
1101 BLUETOOTH_ERROR_NONE, &confirm,
1102 user_info->cb, user_info->user_data);
1107 g_dbus_method_invocation_return_value(invocation, NULL);
1110 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1111 const gchar *sender,
1112 const gchar *object_path,
1113 const gchar *interface_name,
1114 const gchar *method_name,
1115 GVariant *parameters,
1116 GDBusMethodInvocation *invocation,
1119 if (g_strcmp0(method_name, "ReadValue") == 0) {
1123 bt_gatt_read_req_t read_req = {0, };
1124 bt_user_info_t *user_info = NULL;
1125 struct gatt_req_info *req_info = NULL;
1126 struct gatt_service_info *svc_info = NULL;
1128 BT_DBG("ReadValue");
1129 BT_DBG("Application path = %s", object_path);
1130 BT_DBG("Sender = %s", sender);
1132 user_info = _bt_get_user_data(BT_COMMON);
1133 if (user_info == NULL) {
1134 BT_INFO("No callback is set for %s", object_path);
1135 g_dbus_method_invocation_return_value(invocation, NULL);
1139 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1140 if (svc_info == NULL) {
1141 BT_ERR("Coudn't find service for %s", object_path);
1142 g_dbus_method_invocation_return_value(invocation, NULL);
1146 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1147 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1149 read_req.att_handle = (char *)object_path;
1150 read_req.address = addr;
1151 read_req.req_id = req_id;
1152 read_req.offset = offset;
1153 read_req.service_handle = svc_info->serv_path;
1155 /* Store requets information */
1156 req_info = g_new0(struct gatt_req_info, 1);
1157 req_info->attr_path = g_strdup(object_path);
1158 req_info->svc_path = g_strdup(read_req.service_handle);
1159 req_info->request_id = req_id;
1160 req_info->offset = offset;
1161 req_info->context = invocation;
1162 gatt_requests = g_slist_append(gatt_requests, req_info);
1164 _bt_common_event_cb(
1165 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1166 BLUETOOTH_ERROR_NONE, &read_req,
1167 user_info->cb, user_info->user_data);
1170 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1171 GVariant *var = NULL;
1175 gboolean response_needed = FALSE;
1176 bt_gatt_value_change_t value_change = {0, };
1177 bt_user_info_t *user_info = NULL;
1179 struct gatt_service_info *svc_info = NULL;
1180 struct gatt_req_info *req_info = NULL;
1182 BT_DBG("WriteValue");
1183 BT_DBG("Application path = %s", object_path);
1184 BT_DBG("Sender = %s", sender);
1186 g_variant_get(parameters, "(&suqb@ay)",
1187 &addr, &req_id, &offset, &response_needed, &var);
1188 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1190 user_info = _bt_get_user_data(BT_COMMON);
1191 if (user_info == NULL) {
1192 BT_INFO("No callback is set for %s", object_path);
1193 g_variant_unref(var);
1194 if (response_needed)
1195 g_dbus_method_invocation_return_value(invocation, NULL);
1197 g_object_unref(invocation);
1201 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1202 if (svc_info == NULL) {
1203 BT_ERR("Coudn't find service for %s", object_path);
1204 g_variant_unref(var);
1205 if (response_needed)
1206 g_dbus_method_invocation_return_value(invocation, NULL);
1208 g_object_unref(invocation);
1212 value_change.att_handle = (char *)object_path;
1213 value_change.address = addr;
1214 value_change.service_handle = svc_info->serv_path;
1215 value_change.offset = offset;
1216 value_change.req_id = req_id;
1217 value_change.response_needed = response_needed;
1219 len = g_variant_get_size(var);
1223 value_change.att_value = (guint8 *)g_malloc(len);
1225 data = (char *)g_variant_get_data(var);
1226 memcpy(value_change.att_value, data, len);
1228 value_change.val_len = len;
1230 if (response_needed) {
1231 /* Store requets information */
1232 req_info = g_new0(struct gatt_req_info, 1);
1233 req_info->attr_path = g_strdup(object_path);
1234 req_info->svc_path = g_strdup(value_change.service_handle);
1235 req_info->request_id = req_id;
1236 req_info->offset = offset;
1237 req_info->context = invocation;
1238 gatt_requests = g_slist_append(gatt_requests, req_info);
1240 g_object_unref(invocation);
1243 _bt_common_event_cb(
1244 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1245 BLUETOOTH_ERROR_NONE, &value_change,
1246 user_info->cb, user_info->user_data);
1248 g_free(value_change.att_value);
1249 g_variant_unref(var);
1254 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1257 GError *error = NULL;
1258 GVariantBuilder *array_builder;
1260 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1261 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1262 g_variant_builder_add(array_builder, "s", interface);
1264 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1265 "org.freedesktop.Dbus.Objectmanager",
1266 "InterfacesRemoved",
1267 g_variant_new("(oas)",
1268 object_path, array_builder),
1272 if (error != NULL) {
1273 /* dbus gives error cause */
1274 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1275 error->code, error->message);
1276 g_clear_error(&error);
1279 g_variant_builder_unref(array_builder);
1284 static const GDBusInterfaceVTable desc_interface_vtable = {
1285 __bt_gatt_desc_method_call,
1291 static const GDBusInterfaceVTable char_interface_vtable = {
1292 __bt_gatt_char_method_call,
1298 static const GDBusInterfaceVTable serv_interface_vtable = {
1305 static const GDBusInterfaceVTable manager_interface_vtable = {
1306 __bt_gatt_manager_method_call,
1312 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1313 const gchar *introspection_data)
1316 GDBusNodeInfo *node_info = NULL;
1318 if (introspection_data == NULL)
1322 BT_DBG("Create new node info");
1323 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1326 BT_ERR("Unable to create node: %s", err->message);
1327 g_clear_error(&err);
1334 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1335 const char *service_path)
1339 for (l = gatt_services; l != NULL; l = l->next) {
1340 struct gatt_service_info *info = l->data;
1342 if (g_strcmp0(info->serv_path, service_path) == 0)
1345 BT_ERR("Gatt service not found");
1349 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1350 const char *service_path, const char *char_path)
1354 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1355 struct gatt_service_info *serv_info = l1->data;
1357 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1359 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1360 struct gatt_char_info *char_info = l2->data;
1362 if (g_strcmp0(char_info->char_path, char_path)
1366 BT_ERR("Gatt characteristic not found");
1370 BT_ERR("Gatt service not found");
1374 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1375 const char *serv_path, const char *char_path,
1376 const char *desc_path)
1378 GSList *l1, *l2, *l3;
1380 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1381 struct gatt_service_info *serv_info = l1->data;
1383 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1384 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1385 struct gatt_char_info *char_info = l2->data;
1387 if (g_strcmp0(char_info->char_path, char_path)
1389 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1390 struct gatt_desc_info *desc_info = l3->data;
1391 if (g_strcmp0(desc_info->desc_path,
1400 BT_ERR("Gatt descriptor not found");
1404 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1408 for (l = gatt_requests; l != NULL; l = l->next) {
1409 struct gatt_req_info *req_info = l->data;
1411 if (req_info && req_info->request_id == request_id)
1414 BT_ERR("Gatt Request not found");
1418 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1419 const gchar *path, const gchar *interface)
1425 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1430 BT_ERR("Unable to connect to gdbus: %s", err->message);
1431 g_clear_error(&err);
1436 proxy = g_dbus_proxy_new_sync(g_conn,
1437 G_DBUS_PROXY_FLAGS_NONE, NULL,
1439 interface, NULL, &err);
1443 BT_ERR("Unable to create proxy: %s", err->message);
1444 g_clear_error(&err);
1448 manager_gproxy = proxy;
1453 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1454 const gchar *path, const gchar *interface)
1456 return (manager_gproxy) ? manager_gproxy :
1457 __bt_gatt_gdbus_init_manager_proxy(service,
1462 static void __bt_gatt_set_service_state(const char *service_path,
1465 struct gatt_service_info *svc_info = NULL;
1466 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1468 if (svc_info != NULL) {
1469 BT_DBG("Updating the gatt service register state %d", state);
1470 svc_info->is_svc_registered = state;
1474 BT_DBG("gatt service not found");
1477 static gboolean __bt_gatt_get_service_state(const char *service_path)
1479 struct gatt_service_info *svc_info = NULL;
1481 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1483 if (svc_info != NULL) {
1484 BT_DBG("Return the state of the gatt service %d",
1485 svc_info->is_svc_registered);
1486 return svc_info->is_svc_registered;
1489 BT_DBG("gatt service info is NULL");
1493 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1495 GError *error = NULL;
1497 GVariantIter *iter = NULL;
1498 const gchar *key = NULL;
1499 GVariant *value = NULL;
1500 const gchar *service = NULL;
1501 const gchar *characteristic = NULL;
1502 const gchar *descriptor = NULL;
1506 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1508 if (result == NULL) {
1509 /* dBUS-RPC is failed */
1510 BT_ERR("Dbus-RPC is failed\n");
1512 if (error != NULL) {
1513 /* dBUS gives error cause */
1514 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1515 error->code, error->message);
1516 g_clear_error(&error);
1519 char *char_cmp = NULL;
1520 g_variant_get(result, "(a{sv})", &iter);
1521 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1523 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1524 if (g_strcmp0(key, "Service") == 0) {
1525 service = g_variant_get_string(value, NULL);
1526 BT_DBG("Service %s", service);
1527 } else if (g_strcmp0(key, char_cmp) == 0) {
1528 characteristic = g_variant_get_string(value, NULL);
1530 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1531 BT_DBG("%s", characteristic);
1532 } else if (g_strcmp0(key, "Descriptor") == 0) {
1533 descriptor = g_variant_get_string(value, NULL);
1534 BT_DBG("Descriptor %s", descriptor);
1537 g_variant_iter_free(iter);
1539 /* TODO: Store the service informationa and
1540 * Send respponse to CAPI layer. */
1542 g_variant_unref(result);
1547 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1549 BT_INFO("RegisterApplication is completed");
1551 GError *error = NULL;
1554 register_pending_cnt = 0;
1556 if (register_cancel) {
1557 g_object_unref(register_cancel);
1558 register_cancel = NULL;
1561 result = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
1563 if (result == NULL) {
1564 /* dBUS-RPC is failed */
1565 BT_ERR("Dbus-RPC is failed\n");
1567 if (error != NULL) {
1568 /* dBUS gives error cause */
1569 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1570 error->code, error->message);
1571 g_clear_error(&error);
1574 g_variant_unref(result);
1578 static int __bt_gatt_unregister_service(const char *service_path)
1580 if (!__bt_gatt_get_service_state(service_path)) {
1581 BT_DBG("service not registered \n");
1582 return BLUETOOTH_ERROR_NOT_FOUND;
1585 return BLUETOOTH_ERROR_NONE;
1588 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1590 GDBusProxy *proxy = NULL;
1592 if (is_server_started) {
1596 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1597 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1599 if (proxy == NULL || app_path == NULL)
1600 return BLUETOOTH_ERROR_INTERNAL;
1602 BT_INFO("UnregisterApplication");
1604 is_server_started = false;
1606 /* Async Call to Unregister Service */
1607 ret = g_dbus_proxy_call_sync(proxy,
1608 "UnregisterApplication",
1609 g_variant_new("(o)",
1611 G_DBUS_CALL_FLAGS_NONE, -1,
1615 /* dBUS-RPC is failed */
1616 BT_ERR("dBUS-RPC is failed");
1618 /* dBUS gives error cause */
1619 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
1620 err->code, err->message);
1622 g_clear_error(&err);
1624 return BLUETOOTH_ERROR_INTERNAL;
1626 g_variant_unref(ret);
1628 BT_INFO("UnregisterApplication is completed");
1630 return BLUETOOTH_ERROR_NONE;
1633 BT_INFO("GATT server not started");
1634 return BLUETOOTH_ERROR_NONE;
1637 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1639 GDBusConnection *local_system_gconn = NULL;
1643 if (g_conn == NULL) {
1644 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1645 if (address == NULL) {
1647 BT_ERR("Failed to get bus address: %s", err->message);
1648 g_clear_error(&err);
1653 g_conn = g_dbus_connection_new_for_address_sync(address,
1654 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1655 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1656 NULL, /* GDBusAuthObserver */
1662 BT_ERR("Unable to connect to dbus: %s", err->message);
1663 g_clear_error(&err);
1667 } else if (g_dbus_connection_is_closed(g_conn)) {
1668 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1669 if (address == NULL) {
1671 BT_ERR("Failed to get bus address: %s", err->message);
1672 g_clear_error(&err);
1677 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1678 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1679 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1680 NULL, /* GDBusAuthObserver */
1684 if (!local_system_gconn) {
1685 BT_ERR("Unable to connect to dbus: %s", err->message);
1686 g_clear_error(&err);
1689 g_conn = local_system_gconn;
1695 BT_EXPORT_API int bluetooth_gatt_init(void)
1697 GDBusConnection *conn;
1698 GError *error = NULL;
1699 GDBusNodeInfo *node_info = NULL;
1701 if (app_path != NULL) {
1702 BT_ERR("app path already exists! initialized");
1703 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1706 if (owner_id == 0) {
1707 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1708 BT_GATT_SERVICE_NAME,
1709 G_BUS_NAME_OWNER_FLAGS_NONE,
1710 NULL, NULL, NULL, NULL, NULL);
1713 BT_DBG("owner_id is [%d]", owner_id);
1714 app_path = g_strdup_printf("/com/%d", getpid());
1718 conn = __bt_gatt_get_gdbus_connection();
1720 BT_ERR("Unable to get connection");
1724 /* Register ObjectManager interface */
1725 node_info = __bt_gatt_create_method_node_info(
1726 manager_introspection_xml);
1727 if (node_info == NULL) {
1728 BT_ERR("failed to get node info");
1732 if (manager_id == 0) {
1733 BT_INFO("manager_id does not exists");
1735 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1736 node_info->interfaces[0],
1737 &manager_interface_vtable,
1738 NULL, NULL, &error);
1740 g_dbus_node_info_unref(node_info);
1741 if (manager_id == 0) {
1742 BT_ERR("failed to register: %s", error->message);
1743 g_error_free(error);
1747 return BLUETOOTH_ERROR_NONE;
1751 g_bus_unown_name(owner_id);
1758 __bt_gatt_close_gdbus_connection();
1760 return BLUETOOTH_ERROR_INTERNAL;
1763 BT_EXPORT_API int bluetooth_gatt_deinit()
1765 int ret = BLUETOOTH_ERROR_NONE;
1767 if (register_cancel) {
1768 g_cancellable_cancel(register_cancel);
1769 g_object_unref(register_cancel);
1770 register_cancel = NULL;
1773 /* Unown gdbus bus */
1775 /* remove/unregister all services */
1776 BT_DBG("removing all registered gatt service\n");
1777 bluetooth_gatt_delete_services();
1779 /* unregister the exported interface for object manager */
1780 g_dbus_connection_unregister_object(g_conn,
1785 ret = bluetooth_gatt_unregister_application();
1786 if (ret != BLUETOOTH_ERROR_NONE)
1787 BT_ERR("Fail to unregister application\n");
1789 g_bus_unown_name(owner_id);
1795 BT_DBG("Gatt service deinitialized \n");
1797 g_slist_free(gatt_services);
1798 gatt_services = NULL;
1800 g_object_unref(manager_gproxy);
1801 manager_gproxy = NULL;
1803 __bt_gatt_close_gdbus_connection();
1808 __bt_gatt_close_gdbus_connection();
1810 return BLUETOOTH_ERROR_NOT_FOUND;
1813 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1816 GError *error = NULL;
1818 GDBusNodeInfo *node_info;
1820 GVariantBuilder *builder = NULL;
1821 GVariantBuilder *builder1 = NULL;
1822 GVariantBuilder *inner_builder = NULL;
1823 gboolean svc_primary = TRUE;
1824 struct gatt_service_info *serv_info = NULL;
1826 node_info = __bt_gatt_create_method_node_info(
1827 service_introspection_xml);
1828 if (node_info == NULL)
1829 return BLUETOOTH_ERROR_INTERNAL;
1831 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1832 BT_DBG("gatt service path is [%s]", path);
1834 object_id = g_dbus_connection_register_object(g_conn, path,
1835 node_info->interfaces[0],
1836 &serv_interface_vtable,
1837 NULL, NULL, &error);
1838 g_dbus_node_info_unref(node_info);
1840 if (object_id == 0) {
1841 BT_ERR("failed to register: %s", error->message);
1842 g_error_free(error);
1845 return BLUETOOTH_ERROR_INTERNAL;
1848 /* Add object_id/gatt service information; it's required at the time of
1849 * service unregister and Getmanagedobjects
1851 serv_info = g_new0(struct gatt_service_info, 1);
1853 serv_info->serv_path = g_strdup(path);
1854 serv_info->serv_id = object_id;
1855 serv_info->service_uuid = g_strdup(svc_uuid);
1856 serv_info->is_svc_registered = FALSE;
1857 serv_info->is_svc_primary = svc_primary;
1859 gatt_services = g_slist_append(gatt_services, serv_info);
1861 /* emit interfacesadded signal here for service path */
1862 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1863 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1865 g_variant_builder_add(inner_builder, "{sv}",
1866 "UUID", g_variant_new_string(svc_uuid));
1868 g_variant_builder_add(inner_builder, "{sv}",
1869 "Primary", g_variant_new_boolean(svc_primary));
1871 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1873 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1874 g_variant_new("ao", builder1));
1876 g_variant_builder_add(builder, "{sa{sv}}",
1877 GATT_SERV_INTERFACE, inner_builder);
1879 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1880 "org.freedesktop.Dbus.ObjectManager",
1882 g_variant_new("(oa{sa{sv}})",
1885 if (error != NULL) {
1886 /* dbus gives error cause */
1887 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1888 error->code, error->message);
1889 g_clear_error(&error);
1894 *svc_path = g_strdup(path);
1897 g_variant_builder_unref(inner_builder);
1898 g_variant_builder_unref(builder);
1899 g_variant_builder_unref(builder1);
1901 return BLUETOOTH_ERROR_NONE;
1904 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1905 const char *svc_path, const char *char_uuid,
1906 bt_gatt_permission_t permissions,
1907 bt_gatt_characteristic_property_t properties,
1911 GError *error = NULL;
1913 GDBusNodeInfo *node_info;
1915 GVariantBuilder *builder = NULL;
1916 GVariantBuilder *inner_builder = NULL;
1917 struct gatt_service_info *serv_info = NULL;
1918 struct gatt_char_info *char_info = NULL;
1919 GVariantBuilder *builder2 = NULL;
1920 GVariantBuilder *builder3 = NULL;
1921 GVariant *flags_val = NULL;
1923 char *char_flags[NUMBER_OF_FLAGS];
1928 new_service = FALSE;
1931 BT_DBG("gatt svc_path path is [%s]", svc_path);
1932 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1933 if (serv_info == NULL)
1934 return BLUETOOTH_ERROR_INVALID_PARAM;
1936 node_info = __bt_gatt_create_method_node_info(
1937 characteristics_introspection_xml);
1938 if (node_info == NULL)
1939 return BLUETOOTH_ERROR_INTERNAL;
1941 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1942 BT_DBG("gatt characteristic path is [%s]", path);
1944 object_id = g_dbus_connection_register_object(g_conn, path,
1945 node_info->interfaces[0],
1946 &char_interface_vtable,
1947 NULL, NULL, &error);
1948 g_dbus_node_info_unref(node_info);
1950 if (object_id == 0) {
1951 BT_ERR("failed to register: %s", error->message);
1952 g_error_free(error);
1955 return BLUETOOTH_ERROR_INTERNAL;
1958 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1959 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1960 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1961 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1962 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1963 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1964 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1965 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1967 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1969 char_info = g_new0(struct gatt_char_info, 1);
1971 char_info->char_path = g_strdup(path);
1972 char_info->char_id = object_id;
1973 char_info->char_uuid = g_strdup(char_uuid);
1975 for (i = 0; i < flag_count; i++)
1976 char_info->char_flags[i] = char_flags[i];
1979 char_info->flags_length = flag_count;
1981 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1983 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1984 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1986 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1987 g_variant_new("s", char_uuid));
1988 g_variant_builder_add(inner_builder, "{sv}", "Service",
1989 g_variant_new("o", svc_path));
1991 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1993 for (i = 0; i < flag_count; i++)
1994 g_variant_builder_add(builder2, "s", char_flags[i]);
1996 flags_val = g_variant_new("as", builder2);
1997 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2000 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2002 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2003 g_variant_new("ao", builder3));
2005 g_variant_builder_add(builder, "{sa{sv}}",
2006 GATT_CHAR_INTERFACE,
2009 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2010 "org.freedesktop.Dbus.ObjectManager",
2012 g_variant_new("(oa{sa{sv}})",
2017 /* dBUS gives error cause */
2018 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2019 error->code, error->message);
2020 g_clear_error(&error);
2023 *char_path = g_strdup(path);
2029 g_variant_builder_unref(inner_builder);
2030 g_variant_builder_unref(builder);
2031 g_variant_builder_unref(builder2);
2032 g_variant_builder_unref(builder3);
2034 return BLUETOOTH_ERROR_NONE;
2037 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
2038 const char *characteristic, const char *char_value,
2041 gchar **line_argv = NULL;
2042 char *serv_path = NULL;
2043 struct gatt_char_info *char_info = NULL;
2044 GVariantBuilder *builder1 = NULL;
2045 GVariantBuilder *builder = NULL;
2046 GVariantBuilder *inner_builder = NULL;
2047 GVariant *char_val = NULL;
2048 GError *error = NULL;
2050 int res = BLUETOOTH_ERROR_NONE;
2052 line_argv = g_strsplit_set(characteristic, "/", 0);
2053 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2055 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
2057 if (char_info == NULL) {
2058 /* Fix : RESOURCE_LEAK */
2059 res = BLUETOOTH_ERROR_INVALID_PARAM;
2063 char_info->value_length = value_length;
2065 char_info->char_value = (char *)malloc(value_length);
2066 /* Fix : NULL_RETURNS */
2067 if (char_info->char_value == NULL) {
2068 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2072 for (i = 0; i < value_length; i++)
2073 char_info->char_value[i] = char_value[i];
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 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2080 for (i = 0; i < value_length; i++)
2081 g_variant_builder_add(builder1, "y", char_value[i]);
2083 char_val = g_variant_new("ay", builder1);
2084 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
2086 g_variant_builder_add(builder, "{sa{sv}}",
2087 GATT_CHAR_INTERFACE,
2090 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2091 "org.freedesktop.Dbus.ObjectManager",
2093 g_variant_new("(oa{sa{sv}})",
2094 char_info->char_path, builder),
2098 /* dBUS gives error cause */
2099 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2100 error->code, error->message);
2101 g_clear_error(&error);
2103 g_variant_builder_unref(inner_builder);
2104 g_variant_builder_unref(builder);
2105 g_variant_builder_unref(builder1);
2107 g_strfreev(line_argv);
2113 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2114 const char *char_path, const char *desc_uuid,
2115 bt_gatt_permission_t permissions,
2118 static int desc_id = 1;
2119 GError *error = NULL;
2121 GDBusNodeInfo *node_info;
2123 GVariantBuilder *builder = NULL;
2124 GVariantBuilder *inner_builder = NULL;
2125 struct gatt_char_info *char_info = NULL;
2126 struct gatt_desc_info *desc_info = NULL;
2127 gchar **line_argv = NULL;
2129 GVariantBuilder *builder2 = NULL;
2130 GVariant *flags_val = NULL;
2132 char *desc_flags[NUMBER_OF_FLAGS];
2140 line_argv = g_strsplit_set(char_path, "/", 0);
2141 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2143 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2144 if (char_info == NULL) {
2145 g_strfreev(line_argv);
2147 return BLUETOOTH_ERROR_INVALID_PARAM;
2150 node_info = __bt_gatt_create_method_node_info(
2151 descriptor_introspection_xml);
2152 if (node_info == NULL) {
2153 g_strfreev(line_argv);
2155 return BLUETOOTH_ERROR_INTERNAL;
2158 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2159 BT_DBG("gatt descriptor path is [%s]", path);
2161 object_id = g_dbus_connection_register_object(g_conn, path,
2162 node_info->interfaces[0],
2163 &desc_interface_vtable,
2164 NULL, NULL, &error);
2165 g_dbus_node_info_unref(node_info);
2167 if (object_id == 0) {
2168 BT_ERR("failed to register: %s", error->message);
2169 g_error_free(error);
2171 g_strfreev(line_argv);
2174 return BLUETOOTH_ERROR_INTERNAL;
2177 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2179 desc_info = g_new0(struct gatt_desc_info, 1);
2181 desc_info->desc_path = g_strdup(path);
2182 desc_info->desc_id = object_id;
2183 desc_info->desc_uuid = g_strdup(desc_uuid);
2185 for (i = 0; i < flag_count; i++)
2186 desc_info->desc_flags[i] = desc_flags[i];
2188 desc_info->flags_length = flag_count;
2190 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2192 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2193 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2195 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2196 g_variant_new("s", desc_uuid));
2197 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2198 g_variant_new("o", char_path));
2200 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2202 for (i = 0; i < flag_count; i++)
2203 g_variant_builder_add(builder2, "s", desc_flags[i]);
2205 flags_val = g_variant_new("as", builder2);
2206 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2209 g_variant_builder_add(builder, "{sa{sv}}",
2210 GATT_DESC_INTERFACE,
2213 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2214 "org.freedesktop.Dbus.ObjectManager",
2216 g_variant_new("(oa{sa{sv}})",
2220 /* dBUS gives error cause */
2221 BT_ERR("Could not Emit Signal: errCode[%x], message[%s]",
2222 error->code, error->message);
2223 g_clear_error(&error);
2226 *desc_path = g_strdup(path);
2230 g_strfreev(line_argv);
2231 g_variant_builder_unref(inner_builder);
2232 g_variant_builder_unref(builder);
2233 g_variant_builder_unref(builder2);
2235 return BLUETOOTH_ERROR_NONE;
2238 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2239 const char *desc_path, const char *desc_value,
2242 GError *error = NULL;
2243 GVariantBuilder *builder = NULL;
2244 GVariantBuilder *inner_builder = NULL;
2245 GVariantBuilder *builder1 = NULL;
2246 struct gatt_desc_info *desc_info = NULL;
2247 gchar **line_argv = NULL;
2249 GVariant *desc_val = NULL;
2250 char *serv_path = NULL;
2253 line_argv = g_strsplit_set(desc_path, "/", 0);
2254 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2255 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2257 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2259 /* Free the allocated memory */
2260 g_strfreev(line_argv);
2264 /* Fix : NULL_RETURNS */
2265 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2267 desc_info->desc_value = (char *)malloc(value_length);
2269 /* Fix : NULL_RETURNS */
2270 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2272 for (i = 0; i < value_length; i++)
2273 desc_info->desc_value[i] = desc_value[i];
2275 desc_info->value_length = value_length;
2277 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2278 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2280 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2282 for (i = 0; i < value_length; i++)
2283 g_variant_builder_add(builder1, "y", desc_value[i]);
2285 desc_val = g_variant_new("ay", builder1);
2286 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2288 g_variant_builder_add(builder, "{sa{sv}}",
2289 GATT_DESC_INTERFACE,
2292 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2293 "org.freedesktop.Dbus.ObjectManager",
2295 g_variant_new("(oa{sa{sv}})",
2296 desc_info->desc_path, builder),
2299 if (error != NULL) {
2300 BT_ERR("D-Bus API failure: errCode[%x], \
2302 error->code, error->message);
2303 g_clear_error(&error);
2306 g_variant_builder_unref(inner_builder);
2307 g_variant_builder_unref(builder);
2308 g_variant_builder_unref(builder1);
2310 return BLUETOOTH_ERROR_NONE;
2313 int bluetooth_gatt_get_service(const char *svc_uuid)
2315 GDBusProxy *proxy = NULL;
2318 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2319 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2321 return BLUETOOTH_ERROR_INTERNAL;
2323 uuid = g_strdup(svc_uuid);
2325 g_dbus_proxy_call(proxy,
2327 g_variant_new("(s)",
2329 G_DBUS_CALL_FLAGS_NONE, -1,
2331 (GAsyncReadyCallback) get_service_cb,
2336 return BLUETOOTH_ERROR_NONE;
2339 BT_EXPORT_API int bluetooth_gatt_register_service(
2340 const char *svc_path)
2342 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2343 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2344 BT_ERR("Don't have aprivilege to use this API");
2345 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2348 register_pending_cnt++;
2350 if (__bt_gatt_get_service_state(svc_path)) {
2351 BT_DBG("service already registered \n");
2352 return BLUETOOTH_ERROR_NONE;
2355 __bt_gatt_set_service_state(svc_path, TRUE);
2357 return BLUETOOTH_ERROR_NONE;
2360 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2362 GDBusProxy *proxy = NULL;
2364 if (!is_server_started) {
2366 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2367 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2368 BT_ERR("Don't have aprivilege to use this API");
2369 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2372 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2373 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2374 if (proxy == NULL || app_path == NULL)
2375 return BLUETOOTH_ERROR_INTERNAL;
2377 BT_INFO("RegisterApplication");
2379 if (register_cancel) {
2380 g_cancellable_cancel(register_cancel);
2381 g_object_unref(register_cancel);
2384 register_cancel = g_cancellable_new();
2386 g_dbus_proxy_call(proxy,
2387 "RegisterApplication",
2388 g_variant_new("(oa{sv})",
2390 G_DBUS_CALL_FLAGS_NONE, -1,
2392 (GAsyncReadyCallback) register_application_cb,
2395 is_server_started = true;
2397 return BLUETOOTH_ERROR_NONE;
2400 BT_INFO("Already RegisterApplication");
2402 return BLUETOOTH_ERROR_NONE;
2405 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2408 int error = BLUETOOTH_ERROR_NONE;
2412 for (l = gatt_services; l != NULL; l = l->next) {
2413 struct gatt_service_info *info = l->data;
2414 BT_DBG("svc_path is %s", info->serv_path);
2415 if (bluetooth_gatt_unregister_service(info->serv_path)
2416 != BLUETOOTH_ERROR_NONE) {
2417 error = BLUETOOTH_ERROR_INTERNAL;
2418 BT_ERR("Error in removing service %s \n",
2422 BT_DBG(" All services removed successfully.\n ");
2424 BT_DBG(" There are no registered services.\n ");
2427 g_slist_free(gatt_services);
2428 gatt_services = NULL;
2431 if (error != BLUETOOTH_ERROR_NONE)
2434 return BLUETOOTH_ERROR_NONE;
2437 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2438 const char *char_path, const char* char_value,
2441 GVariantBuilder *outer_builder;
2442 GVariantBuilder *inner_builder;
2443 GVariantBuilder *invalidated_builder;
2444 GVariant *update_value = NULL;
2445 GError *error = NULL;
2446 gboolean ret = FALSE;
2447 int err = BLUETOOTH_ERROR_NONE;
2449 gchar **line_argv = NULL;
2450 gchar *serv_path = NULL;
2451 const char *value = NULL;
2453 line_argv = g_strsplit_set(char_path, "/", 0);
2454 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2456 if (!__bt_gatt_get_service_state(serv_path)) {
2457 BT_DBG("service not registered for this characteristic \n");
2459 g_strfreev(line_argv);
2460 return BLUETOOTH_ERROR_INTERNAL;
2463 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2464 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2466 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2467 for (i = 0; i < value_length; i++)
2468 g_variant_builder_add(inner_builder, "y", char_value[i]);
2470 update_value = g_variant_new("ay", inner_builder);
2472 g_variant_builder_add(outer_builder, "{sv}", "Value",
2475 BT_DBG("Updating characteristic value \n");
2476 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2478 "org.freedesktop.DBus.Properties",
2479 "PropertiesChanged",
2480 g_variant_new("(sa{sv}as)",
2481 "org.bluez.GattCharacteristic1",
2482 outer_builder, invalidated_builder),
2486 if (error != NULL) {
2487 BT_ERR("D-Bus API failure: errCode[%x], \
2489 error->code, error->message);
2490 g_clear_error(&error);
2492 err = BLUETOOTH_ERROR_INTERNAL;
2494 struct gatt_char_info *char_info = NULL;
2496 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2497 if (char_info == NULL) {
2499 g_strfreev(line_argv);
2500 g_variant_builder_unref(inner_builder);
2501 g_variant_builder_unref(outer_builder);
2502 g_variant_builder_unref(invalidated_builder);
2504 return BLUETOOTH_ERROR_INVALID_DATA;
2507 char_info->value_length = value_length;
2509 value = (char *)realloc(char_info->char_value, value_length);
2510 if (value == NULL) {
2512 g_strfreev(line_argv);
2513 g_variant_builder_unref(inner_builder);
2514 g_variant_builder_unref(outer_builder);
2515 g_variant_builder_unref(invalidated_builder);
2517 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2520 char_info->char_value = (char*)value;
2521 if (char_info->char_value) {
2522 for (i = 0; i < value_length; i++)
2523 char_info->char_value[i] = char_value[i];
2528 g_strfreev(line_argv);
2529 g_variant_builder_unref(inner_builder);
2530 g_variant_builder_unref(outer_builder);
2531 g_variant_builder_unref(invalidated_builder);
2536 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2543 g_free(desc_info->desc_path);
2544 g_free(desc_info->desc_uuid);
2545 g_free(desc_info->desc_value);
2547 for (i = 0; i < desc_info->flags_length; i++)
2548 g_free(desc_info->desc_flags[i]);
2553 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2560 g_free(char_info->char_path);
2561 g_free(char_info->char_uuid);
2562 g_free(char_info->char_value);
2564 for (i = 0; i < char_info->flags_length; i++)
2565 g_free(char_info->char_flags[i]);
2570 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2575 g_free(svc_info->serv_path);
2576 g_free(svc_info->service_uuid);
2580 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2583 struct gatt_service_info *svc_info;
2585 int err = BLUETOOTH_ERROR_NONE;
2587 BT_DBG("svc_path %s", svc_path);
2588 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2591 BT_ERR("Unable to find service info");
2592 return BLUETOOTH_ERROR_NOT_FOUND;
2595 err = __bt_gatt_unregister_service(svc_path);
2596 if (err != BLUETOOTH_ERROR_NONE) {
2597 BT_ERR("Could not unregister application");
2601 for (l = svc_info->char_data; l != NULL; l = l->next) {
2602 struct gatt_char_info *char_info = l->data;
2604 if (char_info == NULL)
2607 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2608 struct gatt_desc_info *desc_info = l1->data;
2610 if (desc_info == NULL)
2613 ret = g_dbus_connection_unregister_object(g_conn,
2614 desc_info->desc_id);
2616 __bt_gatt_emit_interface_removed(
2617 desc_info->desc_path,
2618 GATT_DESC_INTERFACE);
2620 err = BLUETOOTH_ERROR_INTERNAL;
2623 /* list remove & free */
2624 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2625 __bt_gatt_free_descriptor_info(desc_info);
2628 g_slist_free(char_info->desc_data);
2629 char_info->desc_data = NULL;
2631 ret = g_dbus_connection_unregister_object(g_conn,
2632 char_info->char_id);
2634 __bt_gatt_emit_interface_removed(char_info->char_path,
2635 GATT_CHAR_INTERFACE);
2637 err = BLUETOOTH_ERROR_INTERNAL;
2640 /* list remove & free */
2641 svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
2642 __bt_gatt_free_characteristic_info(char_info);
2645 g_slist_free(svc_info->char_data);
2646 svc_info->char_data = NULL;
2648 ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2650 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2651 GATT_SERV_INTERFACE);
2653 err = BLUETOOTH_ERROR_INTERNAL;
2656 ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2658 BT_DBG("Unregistered the service on properties interface");
2660 /* list remove & free */
2661 gatt_services = g_slist_remove(gatt_services, svc_info);
2662 __bt_gatt_free_service_info(svc_info);
2664 new_service = FALSE;
2666 if (gatt_services == NULL)
2668 else if (gatt_services->next == NULL)
2674 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2675 int resp_state, int offset, char *value, int value_length)
2677 struct gatt_req_info *req_info = NULL;
2679 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2680 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2681 BT_ERR("Don't have aprivilege to use this API");
2682 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2685 req_info = __bt_gatt_find_request_info(request_id);
2686 if (req_info == NULL) {
2687 BT_ERR("Coundn't find request id [%d]", request_id);
2688 return BLUETOOTH_ERROR_INTERNAL;
2691 if (resp_state != BLUETOOTH_ATT_ERROR_NONE) {
2692 BT_ERR("resp_state is 0x%X", resp_state);
2693 char err_msg[20] = { 0, };
2694 g_snprintf(err_msg, sizeof(err_msg), "ATT error: 0x%02x", resp_state);
2695 g_dbus_method_invocation_return_dbus_error(req_info->context,
2696 "org.bluez.Error.Failed", err_msg);
2698 gatt_requests = g_slist_remove(gatt_requests, req_info);
2700 req_info->context = NULL;
2701 if (req_info->attr_path)
2702 g_free(req_info->attr_path);
2703 if (req_info->svc_path)
2704 g_free(req_info->svc_path);
2707 return BLUETOOTH_ERROR_NONE;
2710 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2712 GVariantBuilder *inner_builder = NULL;
2713 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2714 if (value_length > 0 && value != NULL) {
2715 for (i = 0; i < value_length; i++)
2716 g_variant_builder_add(inner_builder, "y", value[i]);
2718 g_dbus_method_invocation_return_value(req_info->context,
2719 g_variant_new("(ay)", inner_builder));
2720 g_variant_builder_unref(inner_builder);
2722 g_dbus_method_invocation_return_value(req_info->context, NULL);
2724 gatt_requests = g_slist_remove(gatt_requests, req_info);
2726 req_info->context = NULL;
2727 if (req_info->attr_path)
2728 g_free(req_info->attr_path);
2729 if (req_info->svc_path)
2730 g_free(req_info->svc_path);
2733 return BLUETOOTH_ERROR_NONE;
2736 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2737 bluetooth_device_address_t *unicast_address)
2739 GVariantBuilder *outer_builder;
2740 GVariantBuilder *invalidated_builder;
2741 GError *error = NULL;
2742 gboolean notify = TRUE;
2743 gboolean ret = TRUE;
2744 int err = BLUETOOTH_ERROR_NONE;
2745 gchar **line_argv = NULL;
2746 gchar *serv_path = NULL;
2747 char addr[20] = { 0 };
2749 line_argv = g_strsplit_set(char_path, "/", 0);
2750 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2752 if (!__bt_gatt_get_service_state(serv_path)) {
2753 BT_DBG("service not registered for this characteristic \n");
2755 g_strfreev(line_argv);
2756 return BLUETOOTH_ERROR_INTERNAL;
2761 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2762 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2764 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2765 g_variant_new("b", notify));
2767 if (unicast_address) {
2768 _bt_convert_addr_type_to_string(addr,
2769 (unsigned char *)unicast_address->addr);
2771 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2772 g_variant_new("s", addr));
2774 BT_DBG("Set characteristic Notification \n");
2775 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2777 "org.freedesktop.DBus.Properties",
2778 "PropertiesChanged",
2779 g_variant_new("(sa{sv}as)",
2780 "org.bluez.GattCharacteristic1",
2781 outer_builder, invalidated_builder),
2785 if (error != NULL) {
2786 BT_ERR("D-Bus API failure: errCode[%x], \
2788 error->code, error->message);
2789 g_clear_error(&error);
2791 err = BLUETOOTH_ERROR_INTERNAL;
2794 g_strfreev(line_argv);
2795 g_variant_builder_unref(outer_builder);
2796 g_variant_builder_unref(invalidated_builder);
2803 BT_EXPORT_API int bluetooth_gatt_register_application(int instance_id)
2807 if (!is_server_started) {
2809 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2810 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2811 BT_ERR("Don't have aprivilege to use this API");
2812 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2815 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2816 g_array_append_vals(in_param1, &instance_id, sizeof(int));
2818 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_REGISTER_APPLICATION,
2819 in_param1, in_param2, in_param3, in_param4, &out_param);
2820 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2822 if (ret != BLUETOOTH_ERROR_NONE) {
2823 BT_ERR("Register application failed");
2826 is_server_started = true;
2828 return BLUETOOTH_ERROR_NONE;
2831 BT_INFO("Already RegisterApplication");
2832 return BLUETOOTH_ERROR_NONE;
2836 BT_EXPORT_API int bluetooth_gatt_server_init(int *instance_id, gatt_server_cb_func_ptr callback_ptr,
2839 int ret = BLUETOOTH_ERROR_NONE;
2842 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2844 /* Register event handler for GATT */
2845 ret = _bt_register_event(BT_GATT_SERVER_EVENT, (void *)callback_ptr, user_data);
2847 if (ret != BLUETOOTH_ERROR_NONE &&
2848 ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) {
2849 BT_ERR("Fail to init the event handler");
2850 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2854 ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_REGISTER,
2855 in_param1, in_param2, in_param3, in_param4, &out_param);
2857 /* App ID -1 is invalid */
2858 if (ret != BLUETOOTH_ERROR_NONE) {
2859 BT_INFO("GATT Server Registration failed result [%d]", ret);
2862 *instance_id = g_array_index(out_param, int, 0);
2863 BT_INFO("GATT Server Registered successfully: App Instance ID [%d]", *instance_id);
2867 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2869 BT_INFO("GATT Server instance ID obtained [%d]", *instance_id);
2873 BT_EXPORT_API int bluetooth_gatt_server_deinit(void)
2876 BT_INFO("GATT Server Deinitialize");
2877 /* Unregister the event */
2878 ret = _bt_unregister_event(BT_GATT_SERVER_EVENT);
2880 if (ret != BLUETOOTH_ERROR_NONE) {
2881 BT_ERR("Fail to deinit the event handler");
2885 _bt_set_user_data(BT_GATT_SERVER, NULL, NULL);
2890 BT_EXPORT_API int bluetooth_gatt_server_add_service(const char *svc_uuid, int type, int numhandles,
2891 int instance_id, int *service_handle)
2893 BT_CHECK_ENABLED(return);
2894 BT_CHECK_PARAMETER(svc_uuid, return);
2897 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2899 g_strlcpy(uuid, svc_uuid, sizeof(uuid));
2902 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2904 g_array_append_vals(in_param1, &type, sizeof(int));
2905 g_array_append_vals(in_param2, &numhandles, sizeof(int));
2906 g_array_append_vals(in_param3, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2907 g_array_append_vals(in_param4, &instance_id, sizeof(int));
2909 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_SERVICE,
2910 in_param1, in_param2, in_param3, in_param4, &out_param);
2912 /* ATT handle 0 is reserved, hence it can not be used by app.
2913 It will be used to indicate error in regsitering attribute */
2914 if (result != BLUETOOTH_ERROR_NONE)
2915 *service_handle = 0;
2917 *service_handle = g_array_index(out_param, int, 0);
2919 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2924 BT_EXPORT_API int bluetooth_gatt_server_add_new_characteristic(const char *char_uuid,
2925 const bluetooth_gatt_server_attribute_params_t *param,
2928 BT_CHECK_ENABLED(return);
2929 BT_CHECK_PARAMETER(char_uuid, return);
2930 BT_CHECK_PARAMETER(param, return);
2933 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2935 char *char_flags[NUMBER_OF_FLAGS];
2937 g_strlcpy(uuid, char_uuid, sizeof(uuid));
2938 flag_count = bluetooth_gatt_convert_prop2string(param->properties, char_flags);
2939 BT_INFO("Flag count [%d]", flag_count);
2942 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2944 g_array_append_vals(in_param1, param, sizeof(bluetooth_gatt_server_attribute_params_t));
2945 g_array_append_vals(in_param2, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2947 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_CHARACTERISTIC,
2948 in_param1, in_param2, in_param3, in_param4, &out_param);
2950 /* ATT handle 0 is reserved, hence it can not be used by app.
2951 It will be used to indicate error in regsitering attribute */
2952 if (result != BLUETOOTH_ERROR_NONE) {
2953 BT_ERR("GATT Server Add characteristic failed.. result [%d]", result);
2956 *char_handle = g_array_index(out_param, int, 0);
2957 BT_DBG("GATT Server Add characteristic success result [%d] char chandle [%d]", result, *char_handle);
2960 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2964 BT_EXPORT_API int bluetooth_gatt_server_add_descriptor(const char *desc_uuid, bt_gatt_permission_t permissions,
2965 int service_handle, int instance_id, int *descriptor_handle)
2967 BT_CHECK_ENABLED(return);
2968 BT_CHECK_PARAMETER(desc_uuid, return);
2971 char uuid[BT_GATT_ATT_UUID_LEN_MAX + 1];
2973 g_strlcpy(uuid, desc_uuid, sizeof(uuid));
2976 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
2978 g_array_append_vals(in_param1, &service_handle, sizeof(int));
2979 g_array_append_vals(in_param2, &instance_id, sizeof(int));
2980 g_array_append_vals(in_param3, &permissions, sizeof(bt_gatt_permission_t));
2981 g_array_append_vals(in_param4, uuid, BT_GATT_ATT_UUID_LEN_MAX + 1);
2983 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ADD_DESCRIPTOR,
2984 in_param1, in_param2, in_param3, in_param4, &out_param);
2986 /* ATT handle 0 is reserved, hence it can not be used by app.
2987 It will be used to indicate error in regsitering attribute */
2988 if (result != BLUETOOTH_ERROR_NONE) {
2989 BT_ERR("GATT Server Add Descriptor failed.. result [%d] desc handle [%d]", result, *descriptor_handle);
2990 *descriptor_handle = 0;
2992 *descriptor_handle = g_array_index(out_param, int, 0);
2993 BT_INFO("GATT Server Add Descriptor Successful.. result [%d] desc handle [%d]", result, *descriptor_handle);
2996 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3001 BT_EXPORT_API int bluetooth_gatt_server_start_service(int service_handle, int instance_id)
3003 BT_CHECK_ENABLED(return);
3007 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3009 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3010 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3012 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_START_SERVICE,
3013 in_param1, in_param2, in_param3, in_param4, &out_param);
3015 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3020 BT_EXPORT_API int bluetooth_gatt_server_send_response(const bluetooth_gatt_server_response_params_t *param,
3021 const bluetooth_gatt_att_data_t *value)
3023 BT_CHECK_PARAMETER(param, return);
3024 BT_CHECK_PARAMETER(value, return);
3025 BT_CHECK_ENABLED(return);
3029 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3031 g_array_append_vals(in_param1, value, sizeof(bluetooth_gatt_att_data_t));
3032 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_response_params_t));
3034 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_RESPONSE,
3035 in_param1, in_param2, in_param3, in_param4, &out_param);
3037 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3043 BT_EXPORT_API int bluetooth_gatt_server_send_indication(bluetooth_device_address_t *addr_hex,
3044 const bluetooth_gatt_server_indication_params_t *param,
3045 const bluetooth_gatt_att_data_t *att_value)
3047 BT_CHECK_PARAMETER(param, return);
3048 BT_CHECK_PARAMETER(att_value, return);
3049 BT_CHECK_ENABLED(return);
3053 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3055 g_array_append_vals(in_param1, att_value, sizeof(bluetooth_gatt_att_data_t));
3056 g_array_append_vals(in_param2, param, sizeof(bluetooth_gatt_server_indication_params_t));
3057 g_array_append_vals(in_param3, addr_hex, sizeof(bluetooth_device_address_t));
3059 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_SEND_INDICATION,
3060 in_param1, in_param2, in_param3, in_param4, &out_param);
3062 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3067 BT_EXPORT_API int bluetooth_gatt_server_stop_service(int service_handle, int instance_id)
3069 BT_CHECK_ENABLED(return);
3073 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3075 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3076 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3078 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_STOP_SERVICE,
3079 in_param1, in_param2, in_param3, in_param4, &out_param);
3081 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3086 BT_EXPORT_API int bluetooth_gatt_server_delete_service(int service_handle, int instance_id)
3088 BT_CHECK_ENABLED(return);
3092 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3094 g_array_append_vals(in_param1, &service_handle, sizeof(int));
3095 g_array_append_vals(in_param2, &instance_id, sizeof(int));
3097 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DELETE_SERVICE,
3098 in_param1, in_param2, in_param3, in_param4, &out_param);
3100 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3105 /* Tizen Platform Specific */
3106 BT_EXPORT_API int bluetooth_gatt_server_update_characteristic(int instance_id,
3107 const bluetooth_gatt_server_update_value_t *value)
3109 BT_CHECK_ENABLED(return);
3110 BT_CHECK_PARAMETER(value, return);
3114 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3116 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3117 g_array_append_vals(in_param2, value, sizeof(bluetooth_gatt_server_update_value_t));
3119 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_UPDATE_VALUE,
3120 in_param1, in_param2, in_param3, in_param4, &out_param);
3122 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3127 BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id)
3129 BT_CHECK_ENABLED(return);
3133 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3135 g_array_append_vals(in_param1, &instance_id, sizeof(int));
3137 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GATT_SERVER_DEREGISTER,
3138 in_param1, in_param2, in_param3, in_param4, &out_param);
3140 if (result != BLUETOOTH_ERROR_NONE)
3141 BT_INFO("GATT Server Unregistration failed result [%d]", result);
3143 BT_INFO("GATT Server Unregistration successful");
3145 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3150 static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio,
3151 GIOCondition cond, gpointer data)
3154 bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data;
3156 BT_INFO("FD io write data received remote adress [%s]\n", write_data->adress);
3158 if (cond & G_IO_IN) {
3159 GIOStatus status = G_IO_STATUS_NORMAL;
3161 char *buffer = NULL;
3163 int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX;
3165 buffer = g_malloc0(BUF);
3167 status = g_io_channel_read_chars(gio, buffer,
3170 if (status != G_IO_STATUS_NORMAL) {
3171 BT_ERR("IO Channel read is failed with %d", status);
3174 BT_ERR("IO Channel read error [%s]", err->message);
3175 if (status == G_IO_STATUS_ERROR) {
3176 BT_ERR("cond : %d", cond);
3178 g_io_channel_shutdown(gio, TRUE, NULL);
3179 g_io_channel_unref(gio);
3190 BT_INFO(" FD io sending value changed %s %d \n", buffer, len);
3193 bluetooth_gatt_server_write_requested_info_t write_info;
3194 if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX)
3195 memcpy(write_info.data.data, buffer, len);
3197 write_info.length = len;
3198 write_info.need_resp = false;
3199 write_info.attribute_handle = write_data->attribute_handle;
3201 _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->adress);
3202 write_info.connection_id = write_data->connection_id;
3203 write_info.offset = write_data->offset;
3204 write_info.request_id = -2;
3206 BT_INFO("ACQUIRING EVENT \n");
3208 bt_event_info_t *event_info;
3209 event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT);
3213 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
3214 BLUETOOTH_ERROR_NONE, &write_info,
3215 event_info->cb, event_info->user_data);
3217 BT_ERR("eventinfo failed");
3227 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
3228 BT_ERR("Error : GIOCondition %d, ]", cond);
3229 g_io_channel_shutdown(gio, TRUE, NULL);
3230 g_io_channel_unref(gio);
3238 void bluetooth_gatt_server_send_acquire_response(GVariant * parameters)
3243 int pipefd[2] = {-1,};
3246 char err_msg[512] = {'\0'};
3247 GIOChannel *channel = NULL;
3251 g_variant_get(parameters, "(iiiiii&s)",
3260 BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr);
3261 BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id);
3262 BT_DBG("GATT Server Acquire write att handle:[%d]", att_han);
3263 BT_DBG("GATT Server Acquire Write Offset: [%d]", offset);
3266 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) {
3267 strerror_r(errno, err_msg, sizeof(err_msg));
3268 BT_ERR("socketpair(): %s", err_msg);
3273 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
3275 //param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
3276 bluetooth_gatt_server_acquire_response_params_t data;
3277 data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
3278 data.fd = pipefd[1];
3280 data.request_id = tran_id;
3282 bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ;
3284 write_info->attribute_handle = att_han;
3285 write_info->connection_id = tran_id;
3286 write_info->offset = offset;
3288 memcpy(write_info->adress, addr , BLUETOOTH_ADDRESS_STRING_LENGTH);
3290 BT_INFO("FD read %d remote adress [%s ] \n", pipefd[0], addr);
3293 channel = g_io_channel_unix_new(pipefd[0]);
3294 g_io_channel_set_encoding(channel, NULL, NULL);
3295 g_io_channel_set_buffered(channel, FALSE);
3296 g_io_channel_set_close_on_unref(channel, TRUE);
3297 g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
3298 g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP),
3299 bluetooth_gatt_server_acquire_channel_write_cb, write_info);
3302 GUnixFDList *fd_list = g_unix_fd_list_new();
3303 GError *error = NULL;
3305 g_unix_fd_list_append(fd_list, pipefd[1], &error);
3306 g_assert_no_error(error);
3309 g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t));
3311 BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr);
3313 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE,
3314 in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL);
3316 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);