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>
26 #include "bt-common.h"
27 #include "bt-internal-types.h"
29 #define NUMBER_OF_FLAGS 10
31 GDBusConnection *g_conn;
34 static gboolean new_service = FALSE;
35 static gboolean new_char = FALSE;
36 static int serv_id = 1;
37 static int register_pending_cnt = 0;
38 static bool is_server_started = false;
40 /* Introspection data for the service we are exporting */
41 static const gchar service_introspection_xml[] =
43 " <interface name='org.freedesktop.DBus.Properties'>"
44 " <property type='s' name='UUID' access='read'>"
46 " <property type='b' name='primary' access='read'>"
48 " <property type='o' name='Device' access='read'>"
50 " <property type='ao' name='Characteristics' access='read'>"
52 " <property type='s' name='Includes' access='read'>"
57 /* Introspection data for the characteristics we are exporting */
58 static const gchar characteristics_introspection_xml[] =
60 " <interface name='org.bluez.GattCharacteristic1'>"
61 " <method name='ReadValue'>"
62 " <arg type='s' name='address' direction='in'/>"
63 " <arg type='u' name='id' direction='in'/>"
64 " <arg type='q' name='offset' direction='in'/>"
65 " <arg type='ay' name='Value' direction='out'/>"
67 " <method name='WriteValue'>"
68 " <arg type='s' name='address' direction='in'/>"
69 " <arg type='u' name='id' direction='in'/>"
70 " <arg type='q' name='offset' direction='in'/>"
71 " <arg type='b' name='response_needed' direction='in'/>"
72 " <arg type='ay' name='value' direction='in'/>"
74 " <method name='StartNotify'>"
76 " <method name='StopNotify'>"
78 " <method name='IndicateConfirm'>"
79 " <arg type='s' name='address' direction='in'/>"
80 " <arg type='b' name='complete' direction='in'/>"
83 " <interface name='org.freedesktop.DBus.Properties'>"
84 " <property type='s' name='UUID' access='read'>"
86 " <property type='o' name='Service' access='read'>"
88 " <property type='ay' name='Value' access='readwrite'>"
90 " <property type='b' name='Notifying' access='read'>"
92 " <property type='as' name='Flags' access='read'>"
94 " <property type='s' name='Unicast' access='read'>"
96 " <property type='ao' name='Descriptors' access='read'>"
101 /* Introspection data for the descriptor we are exporting */
102 static const gchar descriptor_introspection_xml[] =
104 " <interface name='org.bluez.GattDescriptor1'>"
105 " <method name='ReadValue'>"
106 " <arg type='s' name='address' direction='in'/>"
107 " <arg type='u' name='id' direction='in'/>"
108 " <arg type='q' name='offset' direction='in'/>"
109 " <arg type='ay' name='Value' direction='out'/>"
111 " <method name='WriteValue'>"
112 " <arg type='s' name='address' direction='in'/>"
113 " <arg type='u' name='id' direction='in'/>"
114 " <arg type='q' name='offset' direction='in'/>"
115 " <arg type='b' name='response_needed' direction='in'/>"
116 " <arg type='ay' name='value' direction='in'/>"
119 " <interface name='org.freedesktop.DBus.Properties'>"
120 " <property type='s' name='UUID' access='read'>"
122 " <property type='o' name='Characteristic' access='read'>"
124 " <property type='ay' name='Value' access='read'>"
126 " <property type='as' name='Flags' access='read'>"
131 static const gchar manager_introspection_xml[] =
133 " <interface name='org.freedesktop.DBus.ObjectManager'>"
134 " <method name='GetManagedObjects'>"
135 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
140 struct gatt_service_info {
147 gboolean is_svc_registered;
148 gboolean is_svc_primary;
151 struct gatt_char_info {
156 gchar *char_flags[NUMBER_OF_FLAGS];
162 struct gatt_desc_info {
167 gchar *desc_flags[NUMBER_OF_FLAGS];
172 struct gatt_req_info {
177 GDBusMethodInvocation *context;
180 static GSList *gatt_services = NULL;
181 static GSList *gatt_requests = NULL;
182 static gchar *app_path = NULL;
184 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
185 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
187 #define GATT_SERV_OBJECT_PATH "/service"
189 #define GATT_MNGR_INTERFACE "org.bluez.GattManager1"
190 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
191 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
192 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
194 #ifdef TIZEN_FEATURE_BT_HPS
195 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
196 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
197 #define PROPERTIES_CHANGED "PropertiesChanged"
198 #define BT_HPS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
201 static GDBusProxy *manager_gproxy = NULL;
203 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
204 const char *service_path, const char *char_path);
205 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
206 const char *serv_path, const char *char_path,
207 const char *desc_path);
209 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
211 static void __bt_gatt_close_gdbus_connection(void)
217 ret_if(g_conn == NULL);
219 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
220 BT_ERR("Fail to flush the connection: %s", err->message);
225 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
227 BT_ERR("Fail to close the dbus connection: %s", err->message);
232 g_object_unref(g_conn);
239 #ifdef TIZEN_FEATURE_BT_HPS
240 static int __bt_send_event_to_hps(int event, GVariant *var)
242 GError *error = NULL;
243 GVariant *parameters;
244 GDBusMessage *msg = NULL;
248 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
250 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
251 GVariantBuilder *inner_builder;
252 GVariantBuilder *invalidated_builder;
254 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
255 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
257 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
259 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
261 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
262 g_variant_builder_unref(invalidated_builder);
263 g_variant_builder_unref(inner_builder);
264 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
265 GVariantBuilder *inner_builder;
266 GVariantBuilder *invalidated_builder;
268 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
269 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
271 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
273 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
275 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
276 g_variant_builder_unref(invalidated_builder);
277 g_variant_builder_unref(inner_builder);
279 g_varaiant_unref(var);
282 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
283 g_dbus_message_set_body(msg, parameters);
284 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
286 BT_ERR("D-Bus API failure: errCode[%x], \
288 error->code, error->message);
289 g_clear_error(&error);
291 return BLUETOOTH_ERROR_INTERNAL;
293 return BLUETOOTH_ERROR_NONE;
297 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
299 const gchar *object_path,
300 const gchar *interface_name,
301 const gchar *method_name,
302 GVariant *parameters,
303 GDBusMethodInvocation *invocation,
310 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
311 BT_DBG("Getting values for service, chars and descriptors");
313 GVariantBuilder *builder;
314 GVariantBuilder *inner_builder1 = NULL;
315 GVariant *svc_char = NULL;
318 builder = g_variant_builder_new(
319 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
321 /* Prepare inner builder for GattService1 interface */
323 len = g_slist_length(gatt_services);
325 for (i = 0; i <= len; i++) {
326 GVariantBuilder *svc_builder = NULL;
327 GVariantBuilder *inner_builder = NULL;
329 if (register_pending_cnt > 1)
330 l1 = g_slist_nth(gatt_services, len - register_pending_cnt);
332 l1 = g_slist_last(gatt_services);
334 register_pending_cnt--;
337 BT_ERR("gatt service list is NULL");
338 g_dbus_method_invocation_return_value(invocation, NULL);
342 struct gatt_service_info *serv_info = l1->data;
343 if (serv_info == NULL) {
344 BT_ERR("service info value is NULL");
345 g_dbus_method_invocation_return_value(invocation, NULL);
349 /* Prepare inner builder for GattService1 interface */
350 BT_DBG("Creating builder for service");
351 svc_builder = g_variant_builder_new(
352 G_VARIANT_TYPE("a{sa{sv}}"));
353 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
355 g_variant_builder_add(inner_builder, "{sv}", "UUID",
356 g_variant_new_string(serv_info->service_uuid));
358 g_variant_builder_add(inner_builder, "{sv}", "Primary",
359 g_variant_new_boolean(serv_info->is_svc_primary));
362 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
363 BT_DBG("Adding Charatarisitcs list");
364 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
365 struct gatt_char_info *char_info = l4->data;
366 g_variant_builder_add(inner_builder1, "o",
367 char_info->char_path);
368 BT_DBG("%s", char_info->char_path);
371 svc_char = g_variant_new("ao", inner_builder1);
372 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
375 g_variant_builder_add(svc_builder, "{sa{sv}}",
379 g_variant_builder_add(builder, "{oa{sa{sv}}}",
380 serv_info->serv_path,
383 g_variant_builder_unref(inner_builder1);
385 /* Prepare inner builder for GattCharacteristic1 interface */
387 GSList *l2 = serv_info->char_data;
388 BT_DBG("Creating builder for characteristics \n");
391 BT_DBG("characteristic data is NULL");
393 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
395 GVariantBuilder *char_builder = NULL;
396 GVariantBuilder *inner_builder = NULL;
397 GVariantBuilder *builder1 = NULL;
398 GVariantBuilder *builder2 = NULL;
399 GVariantBuilder *builder3 = NULL;
400 GVariant *char_val = NULL;
401 GVariant *flags_val = NULL;
402 GVariant *char_desc = NULL;
403 char *unicast = NULL;
404 gboolean notify = FALSE;
407 char_builder = g_variant_builder_new(
410 inner_builder = g_variant_builder_new(
414 struct gatt_char_info *char_info = l2->data;
415 if (char_info == NULL) {
416 BT_ERR("char_info is NULL");
421 g_variant_builder_add(inner_builder, "{sv}", "UUID",
422 g_variant_new_string(char_info->char_uuid));
424 g_variant_builder_add(inner_builder, "{sv}", "Service",
425 g_variant_new("o", serv_info->serv_path));
427 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
429 if (char_info->char_value != NULL) {
430 for (i = 0; i < char_info->value_length; i++) {
431 g_variant_builder_add(builder1, "y",
432 char_info->char_value[i]);
434 char_val = g_variant_new("ay", builder1);
435 g_variant_builder_add(inner_builder, "{sv}",
439 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
441 for (i = 0; i < char_info->flags_length; i++) {
442 g_variant_builder_add(builder2, "s",
443 char_info->char_flags[i]);
446 flags_val = g_variant_new("as", builder2);
447 g_variant_builder_add(inner_builder, "{sv}", "Flags",
451 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
452 g_variant_new("b", notify));
455 unicast = g_strdup("00:00:00:00:00:00");
456 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
457 g_variant_new("s", unicast));
460 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
461 BT_DBG("Adding Descriptors list");
463 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
464 struct gatt_desc_info *desc_info = l4->data;
465 g_variant_builder_add(builder3, "o",
466 desc_info->desc_path);
467 BT_DBG("%s", desc_info->desc_path);
470 char_desc = g_variant_new("ao", builder3);
471 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
474 g_variant_builder_add(char_builder, "{sa{sv}}",
475 GATT_CHAR_INTERFACE , inner_builder);
476 g_variant_builder_add(builder, "{oa{sa{sv}}}",
477 char_info->char_path, char_builder);
479 /*Prepare inner builder for GattDescriptor1 interface*/
481 GSList *l3 = char_info->desc_data;
484 BT_DBG("descriptor data is NULL");
486 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
488 BT_DBG("Creating builder for descriptor \n");
490 GVariantBuilder *desc_builder = NULL;
491 GVariantBuilder *inner_builder = NULL;
492 GVariantBuilder *builder1 = NULL;
493 GVariantBuilder *builder2 = NULL;
494 GVariant *desc_val = NULL;
496 desc_builder = g_variant_builder_new(
499 inner_builder = g_variant_builder_new(
503 struct gatt_desc_info *desc_info = l3->data;
504 if (desc_info == NULL) {
505 BT_ERR("desc_info is NULL");
510 g_variant_builder_add(inner_builder,
512 g_variant_new_string(
513 desc_info->desc_uuid));
516 g_variant_builder_add(inner_builder, "{sv}",
519 char_info->char_path));
522 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
524 if (desc_info->desc_value != NULL) {
525 for (i = 0; i < desc_info->value_length; i++) {
526 g_variant_builder_add(builder1, "y",
527 desc_info->desc_value[i]);
529 desc_val = g_variant_new("ay", builder1);
530 g_variant_builder_add(inner_builder, "{sv}",
535 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
537 for (i = 0; i < desc_info->flags_length; i++) {
538 g_variant_builder_add(builder2, "s",
539 desc_info->desc_flags[i]);
542 flags_val = g_variant_new("as", builder2);
543 g_variant_builder_add(inner_builder, "{sv}", "Flags",
546 g_variant_builder_add(desc_builder, "{sa{sv}}",
550 g_variant_builder_add(builder, "{oa{sa{sv}}}",
551 desc_info->desc_path,
554 /*unref descriptor builder pointers*/
555 g_variant_builder_unref(builder1);
556 g_variant_builder_unref(builder2);
557 g_variant_builder_unref(inner_builder);
558 g_variant_builder_unref(desc_builder);
563 /*unref char builder pointers*/
564 g_variant_builder_unref(builder1);
565 g_variant_builder_unref(builder2);
566 g_variant_builder_unref(builder3);
567 g_variant_builder_unref(inner_builder);
568 g_variant_builder_unref(char_builder);
571 /*unref service builder pointers*/
572 g_variant_builder_unref(inner_builder);
573 g_variant_builder_unref(svc_builder);
576 /* Return builder as method reply */
577 BT_DBG("Sending gatt service builder values to Bluez");
578 g_dbus_method_invocation_return_value(invocation,
585 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
589 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
590 struct gatt_service_info *serv_info = l1->data;
592 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
593 struct gatt_char_info *char_info = l2->data;
595 if (g_strcmp0(char_info->char_path, char_path)
600 BT_ERR("Gatt service not found");
604 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
606 GSList *l1, *l2, *l3;
608 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
609 struct gatt_service_info *serv_info = l1->data;
611 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
612 struct gatt_char_info *char_info = l2->data;
614 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
615 struct gatt_desc_info *desc_info = l3->data;
617 if (g_strcmp0(desc_info->desc_path, desc_path)
623 BT_ERR("Gatt service not found");
627 static void __bt_gatt_char_method_call(GDBusConnection *connection,
629 const gchar *object_path,
630 const gchar *interface_name,
631 const gchar *method_name,
632 GVariant *parameters,
633 GDBusMethodInvocation *invocation,
637 if (g_strcmp0(method_name, "ReadValue") == 0) {
641 bt_gatt_read_req_t read_req = {0, };
642 bt_user_info_t *user_info = NULL;
643 struct gatt_req_info *req_info = NULL;
644 struct gatt_service_info *svc_info = NULL;
645 #ifdef TIZEN_FEATURE_BT_HPS
646 GVariant *param = NULL;
649 BT_DBG("Application path = %s", object_path);
650 BT_DBG("Sender = %s", sender);
652 user_info = _bt_get_user_data(BT_COMMON);
653 if (user_info == NULL) {
654 BT_INFO("No callback is set for %s", object_path);
655 g_dbus_method_invocation_return_value(invocation, NULL);
659 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
660 if (svc_info == NULL) {
661 BT_ERR("Coudn't find service for %s", object_path);
662 g_dbus_method_invocation_return_value(invocation, NULL);
666 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
667 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
669 read_req.att_handle = (char *)object_path;
670 read_req.address = addr;
671 read_req.req_id = req_id;
672 read_req.offset = offset;
673 read_req.service_handle = svc_info->serv_path;
675 /* Store requets information */
676 req_info = g_new0(struct gatt_req_info, 1);
677 req_info->attr_path = g_strdup(object_path);
678 req_info->svc_path = g_strdup(read_req.service_handle);
679 req_info->request_id = req_id;
680 req_info->offset = offset;
681 req_info->context = invocation;
682 gatt_requests = g_slist_append(gatt_requests, req_info);
684 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
685 BLUETOOTH_ERROR_NONE, &read_req,
686 user_info->cb, user_info->user_data);
688 #ifdef TIZEN_FEATURE_BT_HPS
689 param = g_variant_new("(sssyq)",
691 read_req.service_handle,
695 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
699 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
700 GVariant *var = NULL;
704 gboolean response_needed = FALSE;
705 bt_gatt_value_change_t value_change = {0, };
706 bt_user_info_t *user_info = NULL;
708 struct gatt_service_info *svc_info = NULL;
709 struct gatt_req_info *req_info = NULL;
710 #ifdef TIZEN_FEATURE_BT_HPS
711 GVariant *param = NULL;
714 BT_DBG("WriteValue");
715 BT_DBG("Application path = %s", object_path);
716 BT_DBG("Sender = %s", sender);
718 g_variant_get(parameters, "(&suqb@ay)",
719 &addr, &req_id, &offset, &response_needed, &var);
720 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
722 user_info = _bt_get_user_data(BT_COMMON);
724 BT_INFO("No callback is set for %s", object_path);
725 g_variant_unref(var);
727 g_dbus_method_invocation_return_value(invocation, NULL);
729 g_object_unref(invocation);
733 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
734 if (svc_info == NULL) {
735 BT_ERR("Coudn't find service for %s", object_path);
736 g_variant_unref(var);
738 g_dbus_method_invocation_return_value(invocation, NULL);
740 g_object_unref(invocation);
744 value_change.att_handle = (char *)object_path;
745 value_change.address = addr;
746 value_change.service_handle = svc_info->serv_path;
747 value_change.offset = offset;
748 value_change.req_id = req_id;
749 value_change.response_needed = response_needed;
751 len = g_variant_get_size(var);
755 value_change.att_value = (guint8 *)g_malloc(len);
757 data = (char *)g_variant_get_data(var);
758 memcpy(value_change.att_value, data, len);
760 value_change.val_len = len;
762 if (response_needed) {
763 /* Store requets information */
764 req_info = g_new0(struct gatt_req_info, 1);
765 req_info->attr_path = g_strdup(object_path);
766 req_info->svc_path = g_strdup(value_change.service_handle);
767 req_info->request_id = req_id;
768 req_info->offset = offset;
769 req_info->context = invocation;
770 gatt_requests = g_slist_append(gatt_requests, req_info);
772 g_object_unref(invocation);
776 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
777 BLUETOOTH_ERROR_NONE, &value_change,
778 user_info->cb, user_info->user_data);
780 #ifdef TIZEN_FEATURE_BT_HPS
783 svc_path = g_strdup(svc_info->serv_path);
784 param = g_variant_new("(sssyq@ay)",
791 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
797 g_free(value_change.att_value);
798 g_variant_unref(var);
800 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
801 bt_user_info_t *user_info = NULL;
802 bt_gatt_char_notify_change_t notify_change = {0, };
803 BT_DBG("StartNotify");
804 user_info = _bt_get_user_data(BT_COMMON);
805 if (user_info != NULL) {
806 struct gatt_service_info *svc_info = NULL;
807 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
809 notify_change.service_handle = svc_info->serv_path;
810 notify_change.att_handle = (char *)object_path;
811 notify_change.att_notify = TRUE;
813 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
814 BLUETOOTH_ERROR_NONE, ¬ify_change,
815 user_info->cb, user_info->user_data);
818 g_object_unref(invocation);
820 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
821 bt_user_info_t *user_info = NULL;
822 bt_gatt_char_notify_change_t notify_change = {0, };
823 BT_DBG("StopNotify");
824 user_info = _bt_get_user_data(BT_COMMON);
825 if (user_info != NULL) {
826 struct gatt_service_info *svc_info = NULL;
827 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
829 notify_change.service_handle = svc_info->serv_path;
830 notify_change.att_handle = (char *)object_path;
831 notify_change.att_notify = FALSE;
833 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
834 BLUETOOTH_ERROR_NONE, ¬ify_change,
835 user_info->cb, user_info->user_data);
838 g_object_unref(invocation);
840 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
842 bt_gatt_indicate_confirm_t confirm = {0, };
843 bt_user_info_t *user_info = NULL;
844 gboolean complete = FALSE;
845 struct gatt_service_info *svc_info = NULL;
847 BT_DBG("IndicateConfirm");
848 BT_DBG("Application path = %s", object_path);
849 BT_DBG("Sender = %s", sender);
851 g_variant_get(parameters, "(&sb)", &addr, &complete);
852 BT_DBG("Remote Device address number = %s", addr);
854 confirm.att_handle = (char *)object_path;
855 confirm.address = addr;
856 confirm.complete = complete;
858 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
859 if (svc_info != NULL) {
860 confirm.service_handle = svc_info->serv_path;
862 user_info = _bt_get_user_data(BT_COMMON);
863 if (user_info != NULL) {
865 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
866 BLUETOOTH_ERROR_NONE, &confirm,
867 user_info->cb, user_info->user_data);
872 g_dbus_method_invocation_return_value(invocation, NULL);
875 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
877 const gchar *object_path,
878 const gchar *interface_name,
879 const gchar *method_name,
880 GVariant *parameters,
881 GDBusMethodInvocation *invocation,
884 if (g_strcmp0(method_name, "ReadValue") == 0) {
888 bt_gatt_read_req_t read_req = {0, };
889 bt_user_info_t *user_info = NULL;
890 struct gatt_req_info *req_info = NULL;
891 struct gatt_service_info *svc_info = NULL;
894 BT_DBG("Application path = %s", object_path);
895 BT_DBG("Sender = %s", sender);
897 user_info = _bt_get_user_data(BT_COMMON);
898 if (user_info == NULL) {
899 BT_INFO("No callback is set for %s", object_path);
900 g_dbus_method_invocation_return_value(invocation, NULL);
904 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
905 if (svc_info == NULL) {
906 BT_ERR("Coudn't find service for %s", object_path);
907 g_dbus_method_invocation_return_value(invocation, NULL);
911 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
912 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
914 read_req.att_handle = (char *)object_path;
915 read_req.address = addr;
916 read_req.req_id = req_id;
917 read_req.offset = offset;
918 read_req.service_handle = svc_info->serv_path;
920 /* Store requets information */
921 req_info = g_new0(struct gatt_req_info, 1);
922 req_info->attr_path = g_strdup(object_path);
923 req_info->svc_path = g_strdup(read_req.service_handle);
924 req_info->request_id = req_id;
925 req_info->offset = offset;
926 req_info->context = invocation;
927 gatt_requests = g_slist_append(gatt_requests, req_info);
930 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
931 BLUETOOTH_ERROR_NONE, &read_req,
932 user_info->cb, user_info->user_data);
935 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
936 GVariant *var = NULL;
940 gboolean response_needed = FALSE;
941 bt_gatt_value_change_t value_change = {0, };
942 bt_user_info_t *user_info = NULL;
944 struct gatt_service_info *svc_info = NULL;
945 struct gatt_req_info *req_info = NULL;
947 BT_DBG("WriteValue");
948 BT_DBG("Application path = %s", object_path);
949 BT_DBG("Sender = %s", sender);
951 g_variant_get(parameters, "(&suqb@ay)",
952 &addr, &req_id, &offset, &response_needed, &var);
953 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
955 user_info = _bt_get_user_data(BT_COMMON);
956 if (user_info == NULL) {
957 BT_INFO("No callback is set for %s", object_path);
958 g_variant_unref(var);
960 g_dbus_method_invocation_return_value(invocation, NULL);
962 g_object_unref(invocation);
966 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
967 if (svc_info == NULL) {
968 BT_ERR("Coudn't find service for %s", object_path);
969 g_variant_unref(var);
971 g_dbus_method_invocation_return_value(invocation, NULL);
973 g_object_unref(invocation);
977 value_change.att_handle = (char *)object_path;
978 value_change.address = addr;
979 value_change.service_handle = svc_info->serv_path;
980 value_change.offset = offset;
981 value_change.req_id = req_id;
982 value_change.response_needed = response_needed;
984 len = g_variant_get_size(var);
988 value_change.att_value = (guint8 *)g_malloc(len);
990 data = (char *)g_variant_get_data(var);
991 memcpy(value_change.att_value, data, len);
993 value_change.val_len = len;
995 if (response_needed) {
996 /* Store requets information */
997 req_info = g_new0(struct gatt_req_info, 1);
998 req_info->attr_path = g_strdup(object_path);
999 req_info->svc_path = g_strdup(value_change.service_handle);
1000 req_info->request_id = req_id;
1001 req_info->offset = offset;
1002 req_info->context = invocation;
1003 gatt_requests = g_slist_append(gatt_requests, req_info);
1005 g_object_unref(invocation);
1008 _bt_common_event_cb(
1009 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1010 BLUETOOTH_ERROR_NONE, &value_change,
1011 user_info->cb, user_info->user_data);
1013 g_free(value_change.att_value);
1014 g_variant_unref(var);
1019 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1022 GError *error = NULL;
1023 GVariantBuilder *array_builder;
1025 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1026 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1027 g_variant_builder_add(array_builder, "s", interface);
1029 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1030 "org.freedesktop.Dbus.Objectmanager",
1031 "InterfacesRemoved",
1032 g_variant_new("(oas)",
1033 object_path, array_builder),
1037 if (error != NULL) {
1038 /* dbus gives error cause */
1039 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1040 error->code, error->message);
1041 g_clear_error(&error);
1044 g_variant_builder_unref(array_builder);
1049 static const GDBusInterfaceVTable desc_interface_vtable = {
1050 __bt_gatt_desc_method_call,
1055 static const GDBusInterfaceVTable char_interface_vtable = {
1056 __bt_gatt_char_method_call,
1061 static const GDBusInterfaceVTable serv_interface_vtable = {
1067 static const GDBusInterfaceVTable manager_interface_vtable = {
1068 __bt_gatt_manager_method_call,
1073 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1074 const gchar *introspection_data)
1077 GDBusNodeInfo *node_info = NULL;
1079 if (introspection_data == NULL)
1083 BT_DBG("Create new node info");
1084 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1087 BT_ERR("Unable to create node: %s", err->message);
1088 g_clear_error(&err);
1095 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1096 const char *service_path)
1100 for (l = gatt_services; l != NULL; l = l->next) {
1101 struct gatt_service_info *info = l->data;
1103 if (g_strcmp0(info->serv_path, service_path) == 0)
1106 BT_ERR("Gatt service not found");
1110 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1111 const char *service_path, const char *char_path)
1115 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1116 struct gatt_service_info *serv_info = l1->data;
1118 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1120 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1121 struct gatt_char_info *char_info = l2->data;
1123 if (g_strcmp0(char_info->char_path, char_path)
1127 BT_ERR("Gatt characteristic not found");
1131 BT_ERR("Gatt service not found");
1135 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1136 const char *serv_path, const char *char_path,
1137 const char *desc_path)
1139 GSList *l1, *l2, *l3;
1141 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1142 struct gatt_service_info *serv_info = l1->data;
1144 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1145 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1146 struct gatt_char_info *char_info = l2->data;
1148 if (g_strcmp0(char_info->char_path, char_path)
1150 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1151 struct gatt_desc_info *desc_info = l3->data;
1152 if (g_strcmp0(desc_info->desc_path,
1161 BT_ERR("Gatt descriptor not found");
1165 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1169 for (l = gatt_requests; l != NULL; l = l->next) {
1170 struct gatt_req_info *req_info = l->data;
1172 if (req_info && req_info->request_id == request_id)
1175 BT_ERR("Gatt Request not found");
1179 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1180 const gchar *path, const gchar *interface)
1186 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1191 BT_ERR("Unable to connect to gdbus: %s", err->message);
1192 g_clear_error(&err);
1197 proxy = g_dbus_proxy_new_sync(g_conn,
1198 G_DBUS_PROXY_FLAGS_NONE, NULL,
1200 interface, NULL, &err);
1204 BT_ERR("Unable to create proxy: %s", err->message);
1205 g_clear_error(&err);
1209 manager_gproxy = proxy;
1214 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1215 const gchar *path, const gchar *interface)
1217 return (manager_gproxy) ? manager_gproxy :
1218 __bt_gatt_gdbus_init_manager_proxy(service,
1222 int bluetooth_gatt_convert_prop2string(
1223 bt_gatt_characteristic_property_t properties,
1224 char *char_properties[])
1228 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
1229 char_properties[flag_count] = g_strdup("broadcast");
1232 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
1233 char_properties[flag_count] = g_strdup("read");
1236 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
1237 char_properties[flag_count] = g_strdup("write-without-response");
1240 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
1241 char_properties[flag_count] = g_strdup("write");
1244 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
1245 char_properties[flag_count] = g_strdup("notify");
1248 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
1249 char_properties[flag_count] = g_strdup("indicate");
1252 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
1253 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
1256 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
1257 char_properties[flag_count] = g_strdup("reliable-write");
1260 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
1261 char_properties[flag_count] = g_strdup("writable-auxiliaries");
1264 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
1265 char_properties[flag_count] = g_strdup("encrypt-read");
1268 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
1269 char_properties[flag_count] = g_strdup("encrypt-write");
1272 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
1273 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1276 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
1277 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1281 if (flag_count == 0) {
1282 char_properties[flag_count] = g_strdup("read");
1289 int bluetooth_gatt_convert_perm2string(
1290 bt_gatt_permission_t properties,
1291 char *char_properties[])
1295 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
1296 char_properties[flag_count] = g_strdup("read");
1299 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
1300 char_properties[flag_count] = g_strdup("write");
1303 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
1304 char_properties[flag_count] = g_strdup("encrypt-read");
1307 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
1308 char_properties[flag_count] = g_strdup("encrypt-write");
1311 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
1312 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1315 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
1316 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1320 if (flag_count == 0) {
1321 char_properties[flag_count] = g_strdup("read");
1328 static void __bt_gatt_set_service_state(const char *service_path,
1331 struct gatt_service_info *svc_info = NULL;
1332 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1334 if (svc_info != NULL) {
1335 BT_DBG("Updating the gatt service register state %d", state);
1336 svc_info->is_svc_registered = state;
1340 BT_DBG("gatt service not found");
1343 static gboolean __bt_gatt_get_service_state(const char *service_path)
1345 struct gatt_service_info *svc_info = NULL;
1347 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1349 if (svc_info != NULL) {
1350 BT_DBG("Return the state of the gatt service %d",
1351 svc_info->is_svc_registered);
1352 return svc_info->is_svc_registered;
1355 BT_DBG("gatt service info is NULL");
1359 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1361 GError *error = NULL;
1363 GVariantIter *iter = NULL;
1364 const gchar *key = NULL;
1365 GVariant *value = NULL;
1366 const gchar *service = NULL;
1367 const gchar *characteristic = NULL;
1368 const gchar *descriptor = NULL;
1372 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1374 if (result == NULL) {
1375 /* dBUS-RPC is failed */
1376 BT_ERR("Dbus-RPC is failed\n");
1378 if (error != NULL) {
1379 /* dBUS gives error cause */
1380 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1381 error->code, error->message);
1382 g_clear_error(&error);
1385 char *char_cmp = NULL;
1386 g_variant_get(result, "(a{sv})", &iter);
1387 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1389 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1390 if (g_strcmp0(key, "Service") == 0) {
1391 service = g_variant_get_string(value, NULL);
1392 BT_DBG("Service %s", service);
1393 } else if (g_strcmp0(key, char_cmp) == 0) {
1394 characteristic = g_variant_get_string(value, NULL);
1396 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1397 BT_DBG("%s", characteristic);
1398 } else if (g_strcmp0(key, "Descriptor") == 0) {
1399 descriptor = g_variant_get_string(value, NULL);
1400 BT_DBG("Descriptor %s", descriptor);
1403 g_variant_iter_free(iter);
1405 /* TODO: Store the service informationa and
1406 * Send respponse to CAPI layer. */
1408 g_variant_unref(result);
1413 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1415 BT_INFO("RegisterApplication is completed");
1417 GError *error = NULL;
1420 register_pending_cnt = 0;
1422 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1424 if (result == NULL) {
1425 /* dBUS-RPC is failed */
1426 BT_ERR("Dbus-RPC is failed\n");
1428 if (error != NULL) {
1429 /* dBUS gives error cause */
1430 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1431 error->code, error->message);
1432 g_clear_error(&error);
1435 g_variant_unref(result);
1439 void unregister_application_cb(GObject *object, GAsyncResult *res,
1442 BT_INFO("UnregisterApplication is completed");
1444 GError *error = NULL;
1447 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1449 if (result == NULL) {
1450 /* dBUS-RPC is failed */
1451 BT_ERR("Dbus-RPC is failed\n");
1453 if (error != NULL) {
1454 /* dBUS gives error cause */
1455 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1456 error->code, error->message);
1457 g_clear_error(&error);
1460 g_variant_unref(result);
1464 static int __bt_gatt_unregister_service(const char *service_path)
1466 if (!__bt_gatt_get_service_state(service_path)) {
1467 BT_DBG("service not registered \n");
1468 return BLUETOOTH_ERROR_NOT_FOUND;
1471 return BLUETOOTH_ERROR_NONE;
1474 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1476 GDBusProxy *proxy = NULL;
1478 if (is_server_started) {
1479 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1480 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1482 if (proxy == NULL || app_path == NULL)
1483 return BLUETOOTH_ERROR_INTERNAL;
1485 BT_INFO("UnregisterApplication");
1487 /* Async Call to Unregister Service */
1488 g_dbus_proxy_call(proxy,
1489 "UnregisterApplication",
1490 g_variant_new("(o)",
1492 G_DBUS_CALL_FLAGS_NONE, -1,
1494 (GAsyncReadyCallback) unregister_application_cb,
1497 is_server_started = false;
1498 return BLUETOOTH_ERROR_NONE;
1501 BT_INFO("GATT server not started");
1502 return BLUETOOTH_ERROR_NONE;
1505 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1507 GDBusConnection *local_system_gconn = NULL;
1511 if (g_conn == NULL) {
1512 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1513 if (address == NULL) {
1515 BT_ERR("Failed to get bus address: %s", err->message);
1516 g_clear_error(&err);
1521 g_conn = g_dbus_connection_new_for_address_sync(address,
1522 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1523 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1524 NULL, /* GDBusAuthObserver */
1530 BT_ERR("Unable to connect to dbus: %s", err->message);
1531 g_clear_error(&err);
1535 } else if (g_dbus_connection_is_closed(g_conn)) {
1536 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1537 if (address == NULL) {
1539 BT_ERR("Failed to get bus address: %s", err->message);
1540 g_clear_error(&err);
1545 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1546 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1547 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1548 NULL, /* GDBusAuthObserver */
1552 if (!local_system_gconn) {
1553 BT_ERR("Unable to connect to dbus: %s", err->message);
1554 g_clear_error(&err);
1557 g_conn = local_system_gconn;
1563 BT_EXPORT_API int bluetooth_gatt_init(void)
1565 GDBusConnection *conn;
1566 GError *error = NULL;
1567 GDBusNodeInfo *node_info = NULL;
1569 if (app_path != NULL) {
1570 BT_ERR("app path already exists! initialized");
1571 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1574 if (owner_id == 0) {
1575 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1576 BT_GATT_SERVICE_NAME,
1577 G_BUS_NAME_OWNER_FLAGS_NONE,
1578 NULL, NULL, NULL, NULL, NULL);
1581 BT_DBG("owner_id is [%d]", owner_id);
1582 app_path = g_strdup_printf("/com/%d", getpid());
1586 conn = __bt_gatt_get_gdbus_connection();
1588 BT_ERR("Unable to get connection");
1592 /* Register ObjectManager interface */
1593 node_info = __bt_gatt_create_method_node_info(
1594 manager_introspection_xml);
1595 if (node_info == NULL) {
1596 BT_ERR("failed to get node info");
1600 if (manager_id == 0) {
1601 BT_INFO("manager_id does not exists");
1603 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1604 node_info->interfaces[0],
1605 &manager_interface_vtable,
1606 NULL, NULL, &error);
1608 g_dbus_node_info_unref(node_info);
1609 if (manager_id == 0) {
1610 BT_ERR("failed to register: %s", error->message);
1611 g_error_free(error);
1615 return BLUETOOTH_ERROR_NONE;
1619 g_bus_unown_name(owner_id);
1626 __bt_gatt_close_gdbus_connection();
1628 return BLUETOOTH_ERROR_INTERNAL;
1631 BT_EXPORT_API int bluetooth_gatt_deinit()
1633 int ret = BLUETOOTH_ERROR_NONE;
1634 /* Unown gdbus bus */
1636 /* remove/unregister all services */
1637 BT_DBG("removing all registered gatt service\n");
1638 bluetooth_gatt_delete_services();
1640 /* unregister the exported interface for object manager */
1641 g_dbus_connection_unregister_object(g_conn,
1646 ret = bluetooth_gatt_unregister_application();
1647 if (ret != BLUETOOTH_ERROR_NONE)
1648 BT_ERR("Fail to unregister application\n");
1650 g_bus_unown_name(owner_id);
1656 BT_DBG("Gatt service deinitialized \n");
1658 g_slist_free(gatt_services);
1659 gatt_services = NULL;
1661 g_object_unref(manager_gproxy);
1662 manager_gproxy = NULL;
1664 __bt_gatt_close_gdbus_connection();
1669 __bt_gatt_close_gdbus_connection();
1671 return BLUETOOTH_ERROR_NOT_FOUND;
1674 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1677 GError *error = NULL;
1679 GDBusNodeInfo *node_info;
1681 GVariantBuilder *builder = NULL;
1682 GVariantBuilder *builder1 = NULL;
1683 GVariantBuilder *inner_builder = NULL;
1684 gboolean svc_primary = TRUE;
1685 struct gatt_service_info *serv_info = NULL;
1687 node_info = __bt_gatt_create_method_node_info(
1688 service_introspection_xml);
1689 if (node_info == NULL)
1690 return BLUETOOTH_ERROR_INTERNAL;
1692 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1693 BT_DBG("gatt service path is [%s]", path);
1695 object_id = g_dbus_connection_register_object(g_conn, path,
1696 node_info->interfaces[0],
1697 &serv_interface_vtable,
1698 NULL, NULL, &error);
1699 g_dbus_node_info_unref(node_info);
1701 if (object_id == 0) {
1702 BT_ERR("failed to register: %s", error->message);
1703 g_error_free(error);
1706 return BLUETOOTH_ERROR_INTERNAL;
1709 /* Add object_id/gatt service information; it's required at the time of
1710 * service unregister and Getmanagedobjects
1712 serv_info = g_new0(struct gatt_service_info, 1);
1714 serv_info->serv_path = g_strdup(path);
1715 serv_info->serv_id = object_id;
1716 serv_info->service_uuid = g_strdup(svc_uuid);
1717 serv_info->is_svc_registered = FALSE;
1718 serv_info->is_svc_primary = svc_primary;
1720 gatt_services = g_slist_append(gatt_services, serv_info);
1722 /* emit interfacesadded signal here for service path */
1723 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1724 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1726 g_variant_builder_add(inner_builder, "{sv}",
1727 "UUID", g_variant_new_string(svc_uuid));
1729 g_variant_builder_add(inner_builder, "{sv}",
1730 "Primary", g_variant_new_boolean(svc_primary));
1732 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1734 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1735 g_variant_new("ao", builder1));
1737 g_variant_builder_add(builder, "{sa{sv}}",
1738 GATT_SERV_INTERFACE, inner_builder);
1740 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1741 "org.freedesktop.Dbus.ObjectManager",
1743 g_variant_new("(oa{sa{sv}})",
1749 *svc_path = g_strdup(path);
1752 g_variant_builder_unref(inner_builder);
1753 g_variant_builder_unref(builder);
1754 g_variant_builder_unref(builder1);
1756 return BLUETOOTH_ERROR_NONE;
1759 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1760 const char *svc_path, const char *char_uuid,
1761 bt_gatt_permission_t permissions,
1762 bt_gatt_characteristic_property_t properties,
1766 GError *error = NULL;
1768 GDBusNodeInfo *node_info;
1770 GVariantBuilder *builder = NULL;
1771 GVariantBuilder *inner_builder = NULL;
1772 struct gatt_service_info *serv_info = NULL;
1773 struct gatt_char_info *char_info = NULL;
1774 GVariantBuilder *builder2 = NULL;
1775 GVariantBuilder *builder3 = NULL;
1776 GVariant *flags_val = NULL;
1778 char *char_flags[NUMBER_OF_FLAGS];
1783 new_service = FALSE;
1786 BT_DBG("gatt svc_path path is [%s]", svc_path);
1787 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1788 if (serv_info == NULL)
1789 return BLUETOOTH_ERROR_INVALID_PARAM;
1791 node_info = __bt_gatt_create_method_node_info(
1792 characteristics_introspection_xml);
1793 if (node_info == NULL)
1794 return BLUETOOTH_ERROR_INTERNAL;
1796 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1797 BT_DBG("gatt characteristic path is [%s]", path);
1799 object_id = g_dbus_connection_register_object(g_conn, path,
1800 node_info->interfaces[0],
1801 &char_interface_vtable,
1802 NULL, NULL, &error);
1803 g_dbus_node_info_unref(node_info);
1805 if (object_id == 0) {
1806 BT_ERR("failed to register: %s", error->message);
1807 g_error_free(error);
1810 return BLUETOOTH_ERROR_INTERNAL;
1813 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1814 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1815 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1816 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1817 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1818 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1819 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1820 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1822 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1824 char_info = g_new0(struct gatt_char_info, 1);
1826 char_info->char_path = g_strdup(path);
1827 char_info->char_id = object_id;
1828 char_info->char_uuid = g_strdup(char_uuid);
1830 for (i = 0; i < flag_count; i++)
1831 char_info->char_flags[i] = char_flags[i];
1834 char_info->flags_length = flag_count;
1836 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1838 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1839 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1841 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1842 g_variant_new("s", char_uuid));
1843 g_variant_builder_add(inner_builder, "{sv}", "Service",
1844 g_variant_new("o", svc_path));
1846 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1848 for (i = 0; i < flag_count; i++)
1849 g_variant_builder_add(builder2, "s", char_flags[i]);
1851 flags_val = g_variant_new("as", builder2);
1852 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1855 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1857 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1858 g_variant_new("ao", builder3));
1860 g_variant_builder_add(builder, "{sa{sv}}",
1861 GATT_CHAR_INTERFACE,
1864 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1865 "org.freedesktop.Dbus.ObjectManager",
1867 g_variant_new("(oa{sa{sv}})",
1871 *char_path = g_strdup(path);
1877 g_variant_builder_unref(inner_builder);
1878 g_variant_builder_unref(builder);
1879 g_variant_builder_unref(builder2);
1880 g_variant_builder_unref(builder3);
1882 return BLUETOOTH_ERROR_NONE;
1885 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1886 const char *characteristic, const char *char_value,
1889 gchar **line_argv = NULL;
1890 char *serv_path = NULL;
1891 struct gatt_char_info *char_info = NULL;
1892 GVariantBuilder *builder1 = NULL;
1893 GVariantBuilder *builder = NULL;
1894 GVariantBuilder *inner_builder = NULL;
1895 GVariant *char_val = NULL;
1896 GError *error = NULL;
1898 int res = BLUETOOTH_ERROR_NONE;
1900 line_argv = g_strsplit_set(characteristic, "/", 0);
1901 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1903 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1905 if (char_info == NULL) {
1906 /* Fix : RESOURCE_LEAK */
1907 res = BLUETOOTH_ERROR_INVALID_PARAM;
1911 char_info->value_length = value_length;
1913 char_info->char_value = (char *)malloc(value_length);
1914 /* Fix : NULL_RETURNS */
1915 if (char_info->char_value == NULL) {
1916 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1920 for (i = 0; i < value_length; i++)
1921 char_info->char_value[i] = char_value[i];
1923 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1924 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1926 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1928 for (i = 0; i < value_length; i++)
1929 g_variant_builder_add(builder1, "y", char_value[i]);
1931 char_val = g_variant_new("ay", builder1);
1932 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1934 g_variant_builder_add(builder, "{sa{sv}}",
1935 GATT_CHAR_INTERFACE,
1938 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1939 "org.freedesktop.Dbus.ObjectManager",
1941 g_variant_new("(oa{sa{sv}})",
1942 char_info->char_path, builder),
1945 g_variant_builder_unref(inner_builder);
1946 g_variant_builder_unref(builder);
1947 g_variant_builder_unref(builder1);
1949 g_strfreev(line_argv);
1955 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
1956 const char *char_path, const char *desc_uuid,
1957 bt_gatt_permission_t permissions,
1960 static int desc_id = 1;
1961 GError *error = NULL;
1963 GDBusNodeInfo *node_info;
1965 GVariantBuilder *builder = NULL;
1966 GVariantBuilder *inner_builder = NULL;
1967 struct gatt_char_info *char_info = NULL;
1968 struct gatt_desc_info *desc_info = NULL;
1969 gchar **line_argv = NULL;
1971 GVariantBuilder *builder2 = NULL;
1972 GVariant *flags_val = NULL;
1974 char *desc_flags[NUMBER_OF_FLAGS];
1982 line_argv = g_strsplit_set(char_path, "/", 0);
1983 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1985 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
1986 if (char_info == NULL) {
1987 g_strfreev(line_argv);
1989 return BLUETOOTH_ERROR_INVALID_PARAM;
1992 node_info = __bt_gatt_create_method_node_info(
1993 descriptor_introspection_xml);
1994 if (node_info == NULL) {
1995 g_strfreev(line_argv);
1997 return BLUETOOTH_ERROR_INTERNAL;
2000 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2001 BT_DBG("gatt descriptor path is [%s]", path);
2003 object_id = g_dbus_connection_register_object(g_conn, path,
2004 node_info->interfaces[0],
2005 &desc_interface_vtable,
2006 NULL, NULL, &error);
2007 g_dbus_node_info_unref(node_info);
2009 if (object_id == 0) {
2010 BT_ERR("failed to register: %s", error->message);
2011 g_error_free(error);
2013 g_strfreev(line_argv);
2016 return BLUETOOTH_ERROR_INTERNAL;
2019 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2021 desc_info = g_new0(struct gatt_desc_info, 1);
2023 desc_info->desc_path = g_strdup(path);
2024 desc_info->desc_id = object_id;
2025 desc_info->desc_uuid = g_strdup(desc_uuid);
2027 for (i = 0; i < flag_count; i++)
2028 desc_info->desc_flags[i] = desc_flags[i];
2030 desc_info->flags_length = flag_count;
2032 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2034 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2035 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2037 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2038 g_variant_new("s", desc_uuid));
2039 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2040 g_variant_new("o", char_path));
2042 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2044 for (i = 0; i < flag_count; i++)
2045 g_variant_builder_add(builder2, "s", desc_flags[i]);
2047 flags_val = g_variant_new("as", builder2);
2048 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2051 g_variant_builder_add(builder, "{sa{sv}}",
2052 GATT_DESC_INTERFACE,
2055 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2056 "org.freedesktop.Dbus.ObjectManager",
2058 g_variant_new("(oa{sa{sv}})",
2062 *desc_path = g_strdup(path);
2066 g_strfreev(line_argv);
2067 g_variant_builder_unref(inner_builder);
2068 g_variant_builder_unref(builder);
2069 g_variant_builder_unref(builder2);
2071 return BLUETOOTH_ERROR_NONE;
2074 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2075 const char *desc_path, const char *desc_value,
2078 GError *error = NULL;
2079 GVariantBuilder *builder = NULL;
2080 GVariantBuilder *inner_builder = NULL;
2081 GVariantBuilder *builder1 = NULL;
2082 struct gatt_desc_info *desc_info = NULL;
2083 gchar **line_argv = NULL;
2085 GVariant *desc_val = NULL;
2086 char *serv_path = NULL;
2089 line_argv = g_strsplit_set(desc_path, "/", 0);
2090 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2091 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2093 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2095 /* Free the allocated memory */
2096 g_strfreev(line_argv);
2100 /* Fix : NULL_RETURNS */
2101 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2103 desc_info->desc_value = (char *)malloc(value_length);
2105 /* Fix : NULL_RETURNS */
2106 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2108 for (i = 0; i < value_length; i++)
2109 desc_info->desc_value[i] = desc_value[i];
2111 desc_info->value_length = value_length;
2113 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2114 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2116 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2118 for (i = 0; i < value_length; i++)
2119 g_variant_builder_add(builder1, "y", desc_value[i]);
2121 desc_val = g_variant_new("ay", builder1);
2122 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2124 g_variant_builder_add(builder, "{sa{sv}}",
2125 GATT_DESC_INTERFACE,
2128 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2129 "org.freedesktop.Dbus.ObjectManager",
2131 g_variant_new("(oa{sa{sv}})",
2132 desc_info->desc_path, builder),
2135 g_variant_builder_unref(inner_builder);
2136 g_variant_builder_unref(builder);
2137 g_variant_builder_unref(builder1);
2139 return BLUETOOTH_ERROR_NONE;
2142 int bluetooth_gatt_get_service(const char *svc_uuid)
2144 GDBusProxy *proxy = NULL;
2147 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2148 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2150 return BLUETOOTH_ERROR_INTERNAL;
2152 uuid = g_strdup(svc_uuid);
2154 g_dbus_proxy_call(proxy,
2156 g_variant_new("(s)",
2158 G_DBUS_CALL_FLAGS_NONE, -1,
2160 (GAsyncReadyCallback) get_service_cb,
2165 return BLUETOOTH_ERROR_NONE;
2168 BT_EXPORT_API int bluetooth_gatt_register_service(
2169 const char *svc_path)
2171 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2172 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2173 BT_ERR("Don't have aprivilege to use this API");
2174 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2177 register_pending_cnt++;
2179 if (__bt_gatt_get_service_state(svc_path)) {
2180 BT_DBG("service already registered \n");
2181 return BLUETOOTH_ERROR_NONE;
2184 __bt_gatt_set_service_state(svc_path, TRUE);
2186 return BLUETOOTH_ERROR_NONE;
2189 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2191 GDBusProxy *proxy = NULL;
2193 if (!is_server_started) {
2195 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2196 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2197 BT_ERR("Don't have aprivilege to use this API");
2198 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2201 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2202 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2203 if (proxy == NULL || app_path == NULL)
2204 return BLUETOOTH_ERROR_INTERNAL;
2206 BT_INFO("RegisterApplication");
2208 g_dbus_proxy_call(proxy,
2209 "RegisterApplication",
2210 g_variant_new("(oa{sv})",
2212 G_DBUS_CALL_FLAGS_NONE, -1,
2214 (GAsyncReadyCallback) register_application_cb,
2217 is_server_started = true;
2219 return BLUETOOTH_ERROR_NONE;
2222 BT_INFO("Already RegisterApplication");
2224 return BLUETOOTH_ERROR_NONE;
2227 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2230 int error = BLUETOOTH_ERROR_NONE;
2234 for (l = gatt_services; l != NULL; l = l->next) {
2235 struct gatt_service_info *info = l->data;
2236 BT_DBG("svc_path is %s", info->serv_path);
2237 if (bluetooth_gatt_unregister_service(info->serv_path)
2238 != BLUETOOTH_ERROR_NONE) {
2239 error = BLUETOOTH_ERROR_INTERNAL;
2240 BT_ERR("Error in removing service %s \n",
2244 BT_DBG(" All services removed successfully.\n ");
2246 BT_DBG(" There are no registered services.\n ");
2249 g_slist_free(gatt_services);
2250 gatt_services = NULL;
2253 if (error != BLUETOOTH_ERROR_NONE)
2256 return BLUETOOTH_ERROR_NONE;
2259 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2260 const char *char_path, const char* char_value,
2263 GVariantBuilder *outer_builder;
2264 GVariantBuilder *inner_builder;
2265 GVariantBuilder *invalidated_builder;
2266 GVariant *update_value = NULL;
2267 GError *error = NULL;
2268 gboolean ret = FALSE;
2269 int err = BLUETOOTH_ERROR_NONE;
2271 gchar **line_argv = NULL;
2272 gchar *serv_path = NULL;
2274 line_argv = g_strsplit_set(char_path, "/", 0);
2275 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2277 if (!__bt_gatt_get_service_state(serv_path)) {
2278 BT_DBG("service not registered for this characteristic \n");
2280 g_strfreev(line_argv);
2281 return BLUETOOTH_ERROR_INTERNAL;
2284 /* Fix the svace issue : 185689
2285 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2287 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2289 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2290 for (i = 0; i < value_length; i++)
2291 g_variant_builder_add(inner_builder, "y", char_value[i]);
2293 update_value = g_variant_new("ay", inner_builder);
2296 outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2297 g_variant_builder_add(outer_builder, "{sv}", "Value",
2300 BT_DBG("Updating characteristic value \n");
2301 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2303 "org.freedesktop.DBus.Properties",
2304 "PropertiesChanged",
2305 g_variant_new("(sa{sv}as)",
2306 "org.bluez.GattCharacteristic1",
2307 outer_builder, invalidated_builder),
2311 if (error != NULL) {
2312 BT_ERR("D-Bus API failure: errCode[%x], \
2314 error->code, error->message);
2315 g_clear_error(&error);
2317 err = BLUETOOTH_ERROR_INTERNAL;
2319 struct gatt_char_info *char_info = NULL;
2321 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2322 if (char_info == NULL) {
2324 g_strfreev(line_argv);
2325 g_variant_builder_unref(inner_builder);
2326 g_variant_builder_unref(outer_builder);
2327 g_variant_builder_unref(invalidated_builder);
2329 return BLUETOOTH_ERROR_INVALID_DATA;
2332 char_info->value_length = value_length;
2334 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
2335 if (char_info->char_value) {
2336 for (i = 0; i < value_length; i++)
2337 char_info->char_value[i] = char_value[i];
2342 g_strfreev(line_argv);
2343 g_variant_builder_unref(inner_builder);
2344 g_variant_builder_unref(outer_builder);
2345 g_variant_builder_unref(invalidated_builder);
2350 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2357 g_free(desc_info->desc_path);
2358 g_free(desc_info->desc_uuid);
2359 g_free(desc_info->desc_value);
2361 for (i = 0; i < desc_info->flags_length; i++)
2362 g_free(desc_info->desc_flags[i]);
2367 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2374 g_free(char_info->char_path);
2375 g_free(char_info->char_uuid);
2376 g_free(char_info->char_value);
2378 for (i = 0; i < char_info->flags_length; i++)
2379 g_free(char_info->char_flags[i]);
2384 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2389 g_free(svc_info->serv_path);
2390 g_free(svc_info->service_uuid);
2394 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2397 struct gatt_service_info *svc_info;
2399 int err = BLUETOOTH_ERROR_NONE;
2401 BT_DBG("svc_path %s", svc_path);
2402 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2405 BT_ERR("Unable to find service info");
2406 return BLUETOOTH_ERROR_NOT_FOUND;
2409 err = __bt_gatt_unregister_service(svc_path);
2410 if (err != BLUETOOTH_ERROR_NONE) {
2411 BT_ERR("Could not unregister application");
2415 for (l = svc_info->char_data; l != NULL; l = l->next) {
2416 struct gatt_char_info *char_info = l->data;
2418 if (char_info == NULL)
2421 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2422 struct gatt_desc_info *desc_info = l1->data;
2424 if (desc_info == NULL)
2427 ret = g_dbus_connection_unregister_object(g_conn,
2428 desc_info->desc_id);
2430 __bt_gatt_emit_interface_removed(
2431 desc_info->desc_path,
2432 GATT_DESC_INTERFACE);
2434 err = BLUETOOTH_ERROR_INTERNAL;
2437 /* list remove & free */
2438 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2439 __bt_gatt_free_descriptor_info(desc_info);
2442 g_slist_free(char_info->desc_data);
2443 char_info->desc_data = NULL;
2445 ret = g_dbus_connection_unregister_object(g_conn,
2446 char_info->char_id);
2448 __bt_gatt_emit_interface_removed(char_info->char_path,
2449 GATT_CHAR_INTERFACE);
2451 err = BLUETOOTH_ERROR_INTERNAL;
2454 /* list remove & free */
2455 svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
2456 __bt_gatt_free_characteristic_info(char_info);
2459 g_slist_free(svc_info->char_data);
2460 svc_info->char_data = NULL;
2462 ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2464 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2465 GATT_SERV_INTERFACE);
2467 err = BLUETOOTH_ERROR_INTERNAL;
2470 ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2472 BT_DBG("Unregistered the service on properties interface");
2474 /* list remove & free */
2475 gatt_services = g_slist_remove(gatt_services, svc_info);
2476 __bt_gatt_free_service_info(svc_info);
2478 new_service = FALSE;
2480 if (gatt_services == NULL)
2482 else if (gatt_services->next == NULL)
2488 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2489 int resp_state, int offset, char *value, int value_length)
2491 struct gatt_req_info *req_info = NULL;
2493 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2494 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2495 BT_ERR("Don't have aprivilege to use this API");
2496 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2499 req_info = __bt_gatt_find_request_info(request_id);
2500 if (req_info == NULL) {
2501 BT_ERR("Coundn't find request id [%d]", request_id);
2502 return BLUETOOTH_ERROR_INTERNAL;
2505 if (resp_state != BLUETOOTH_ERROR_NONE) {
2506 BT_ERR("resp_state is 0x%X", resp_state);
2508 g_dbus_method_invocation_return_dbus_error(req_info->context,
2509 "org.bluez.Error.Failed", "Application Error");
2511 gatt_requests = g_slist_remove(gatt_requests, req_info);
2513 req_info->context = NULL;
2514 if (req_info->attr_path)
2515 g_free(req_info->attr_path);
2516 if (req_info->svc_path)
2517 g_free(req_info->svc_path);
2520 return BLUETOOTH_ERROR_NONE;
2523 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2525 GVariantBuilder *inner_builder = NULL;
2526 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2527 if (value_length > 0 && value != NULL) {
2528 for (i = 0; i < value_length; i++)
2529 g_variant_builder_add(inner_builder, "y", value[i]);
2531 g_dbus_method_invocation_return_value(req_info->context,
2532 g_variant_new("(ay)", inner_builder));
2533 g_variant_builder_unref(inner_builder);
2535 g_dbus_method_invocation_return_value(req_info->context, NULL);
2537 gatt_requests = g_slist_remove(gatt_requests, req_info);
2539 req_info->context = NULL;
2540 if (req_info->attr_path)
2541 g_free(req_info->attr_path);
2542 if (req_info->svc_path)
2543 g_free(req_info->svc_path);
2546 return BLUETOOTH_ERROR_NONE;
2549 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2550 bluetooth_device_address_t *unicast_address)
2552 GVariantBuilder *outer_builder;
2553 GVariantBuilder *invalidated_builder;
2554 GError *error = NULL;
2555 gboolean notify = TRUE;
2556 gboolean ret = TRUE;
2557 int err = BLUETOOTH_ERROR_NONE;
2558 gchar **line_argv = NULL;
2559 gchar *serv_path = NULL;
2560 char addr[20] = { 0 };
2562 line_argv = g_strsplit_set(char_path, "/", 0);
2563 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2565 if (!__bt_gatt_get_service_state(serv_path)) {
2566 BT_DBG("service not registered for this characteristic \n");
2568 g_strfreev(line_argv);
2569 return BLUETOOTH_ERROR_INTERNAL;
2574 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2575 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2577 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2578 g_variant_new("b", notify));
2580 if (unicast_address) {
2581 _bt_convert_addr_type_to_string(addr,
2582 (unsigned char *)unicast_address->addr);
2584 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2585 g_variant_new("s", addr));
2587 BT_DBG("Set characteristic Notification \n");
2588 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2590 "org.freedesktop.DBus.Properties",
2591 "PropertiesChanged",
2592 g_variant_new("(sa{sv}as)",
2593 "org.bluez.GattCharacteristic1",
2594 outer_builder, invalidated_builder),
2598 if (error != NULL) {
2599 BT_ERR("D-Bus API failure: errCode[%x], \
2601 error->code, error->message);
2602 g_clear_error(&error);
2604 err = BLUETOOTH_ERROR_INTERNAL;
2607 g_strfreev(line_argv);
2608 g_variant_builder_unref(outer_builder);
2609 g_variant_builder_unref(invalidated_builder);