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 (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);
280 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
281 g_dbus_message_set_body(msg, parameters);
282 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
284 BT_ERR("D-Bus API failure: errCode[%x], \
286 error->code, error->message);
287 g_clear_error(&error);
289 return BLUETOOTH_ERROR_INTERNAL;
291 return BLUETOOTH_ERROR_NONE;
295 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
297 const gchar *object_path,
298 const gchar *interface_name,
299 const gchar *method_name,
300 GVariant *parameters,
301 GDBusMethodInvocation *invocation,
308 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
309 BT_DBG("Getting values for service, chars and descriptors");
311 GVariantBuilder *builder;
312 GVariantBuilder *inner_builder1 = NULL;
313 GVariant *svc_char = NULL;
316 builder = g_variant_builder_new(
317 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
319 /* Prepare inner builder for GattService1 interface */
321 len = g_slist_length(gatt_services);
323 for (i = 0; i <= len; i++) {
324 GVariantBuilder *svc_builder = NULL;
325 GVariantBuilder *inner_builder = NULL;
327 if (register_pending_cnt > 1)
328 l1 = g_slist_nth(gatt_services, len - register_pending_cnt);
330 l1 = g_slist_last(gatt_services);
332 register_pending_cnt--;
335 BT_ERR("gatt service list is NULL");
336 g_dbus_method_invocation_return_value(invocation, NULL);
340 struct gatt_service_info *serv_info = l1->data;
341 if (serv_info == NULL) {
342 BT_ERR("service info value is NULL");
343 g_dbus_method_invocation_return_value(invocation, NULL);
347 /* Prepare inner builder for GattService1 interface */
348 BT_DBG("Creating builder for service");
349 svc_builder = g_variant_builder_new(
350 G_VARIANT_TYPE("a{sa{sv}}"));
351 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
353 g_variant_builder_add(inner_builder, "{sv}", "UUID",
354 g_variant_new_string(serv_info->service_uuid));
356 g_variant_builder_add(inner_builder, "{sv}", "Primary",
357 g_variant_new_boolean(serv_info->is_svc_primary));
360 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
361 BT_DBG("Adding Charatarisitcs list");
362 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
363 struct gatt_char_info *char_info = l4->data;
364 g_variant_builder_add(inner_builder1, "o",
365 char_info->char_path);
366 BT_DBG("%s", char_info->char_path);
369 svc_char = g_variant_new("ao", inner_builder1);
370 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
373 g_variant_builder_add(svc_builder, "{sa{sv}}",
377 g_variant_builder_add(builder, "{oa{sa{sv}}}",
378 serv_info->serv_path,
381 g_variant_builder_unref(inner_builder1);
383 /* Prepare inner builder for GattCharacteristic1 interface */
385 GSList *l2 = serv_info->char_data;
386 BT_DBG("Creating builder for characteristics \n");
389 BT_DBG("characteristic data is NULL");
391 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
393 GVariantBuilder *char_builder = NULL;
394 GVariantBuilder *inner_builder = NULL;
395 GVariantBuilder *builder1 = NULL;
396 GVariantBuilder *builder2 = NULL;
397 GVariantBuilder *builder3 = NULL;
398 GVariant *char_val = NULL;
399 GVariant *flags_val = NULL;
400 GVariant *char_desc = NULL;
401 char *unicast = NULL;
402 gboolean notify = FALSE;
405 char_builder = g_variant_builder_new(
408 inner_builder = g_variant_builder_new(
412 struct gatt_char_info *char_info = l2->data;
413 if (char_info == NULL) {
414 BT_ERR("char_info is NULL");
419 g_variant_builder_add(inner_builder, "{sv}", "UUID",
420 g_variant_new_string(char_info->char_uuid));
422 g_variant_builder_add(inner_builder, "{sv}", "Service",
423 g_variant_new("o", serv_info->serv_path));
425 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
427 if (char_info->char_value != NULL) {
428 for (i = 0; i < char_info->value_length; i++) {
429 g_variant_builder_add(builder1, "y",
430 char_info->char_value[i]);
432 char_val = g_variant_new("ay", builder1);
433 g_variant_builder_add(inner_builder, "{sv}",
437 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
439 for (i = 0; i < char_info->flags_length; i++) {
440 g_variant_builder_add(builder2, "s",
441 char_info->char_flags[i]);
444 flags_val = g_variant_new("as", builder2);
445 g_variant_builder_add(inner_builder, "{sv}", "Flags",
449 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
450 g_variant_new("b", notify));
453 unicast = g_strdup("00:00:00:00:00:00");
454 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
455 g_variant_new("s", unicast));
458 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
459 BT_DBG("Adding Descriptors list");
461 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
462 struct gatt_desc_info *desc_info = l4->data;
463 g_variant_builder_add(builder3, "o",
464 desc_info->desc_path);
465 BT_DBG("%s", desc_info->desc_path);
468 char_desc = g_variant_new("ao", builder3);
469 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
472 g_variant_builder_add(char_builder, "{sa{sv}}",
473 GATT_CHAR_INTERFACE , inner_builder);
474 g_variant_builder_add(builder, "{oa{sa{sv}}}",
475 char_info->char_path, char_builder);
477 /*Prepare inner builder for GattDescriptor1 interface*/
479 GSList *l3 = char_info->desc_data;
482 BT_DBG("descriptor data is NULL");
484 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
486 BT_DBG("Creating builder for descriptor \n");
488 GVariantBuilder *desc_builder = NULL;
489 GVariantBuilder *inner_builder = NULL;
490 GVariantBuilder *builder1 = NULL;
491 GVariantBuilder *builder2 = NULL;
492 GVariant *desc_val = NULL;
494 desc_builder = g_variant_builder_new(
497 inner_builder = g_variant_builder_new(
501 struct gatt_desc_info *desc_info = l3->data;
502 if (desc_info == NULL) {
503 BT_ERR("desc_info is NULL");
508 g_variant_builder_add(inner_builder,
510 g_variant_new_string(
511 desc_info->desc_uuid));
514 g_variant_builder_add(inner_builder, "{sv}",
517 char_info->char_path));
520 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
522 if (desc_info->desc_value != NULL) {
523 for (i = 0; i < desc_info->value_length; i++) {
524 g_variant_builder_add(builder1, "y",
525 desc_info->desc_value[i]);
527 desc_val = g_variant_new("ay", builder1);
528 g_variant_builder_add(inner_builder, "{sv}",
533 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
535 for (i = 0; i < desc_info->flags_length; i++) {
536 g_variant_builder_add(builder2, "s",
537 desc_info->desc_flags[i]);
540 flags_val = g_variant_new("as", builder2);
541 g_variant_builder_add(inner_builder, "{sv}", "Flags",
544 g_variant_builder_add(desc_builder, "{sa{sv}}",
548 g_variant_builder_add(builder, "{oa{sa{sv}}}",
549 desc_info->desc_path,
552 /*unref descriptor builder pointers*/
553 g_variant_builder_unref(builder1);
554 g_variant_builder_unref(builder2);
555 g_variant_builder_unref(inner_builder);
556 g_variant_builder_unref(desc_builder);
561 /*unref char builder pointers*/
562 g_variant_builder_unref(builder1);
563 g_variant_builder_unref(builder2);
564 g_variant_builder_unref(builder3);
565 g_variant_builder_unref(inner_builder);
566 g_variant_builder_unref(char_builder);
569 /*unref service builder pointers*/
570 g_variant_builder_unref(inner_builder);
571 g_variant_builder_unref(svc_builder);
574 /* Return builder as method reply */
575 BT_DBG("Sending gatt service builder values to Bluez");
576 g_dbus_method_invocation_return_value(invocation,
583 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
587 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
588 struct gatt_service_info *serv_info = l1->data;
590 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
591 struct gatt_char_info *char_info = l2->data;
593 if (g_strcmp0(char_info->char_path, char_path)
598 BT_ERR("Gatt service not found");
602 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
604 GSList *l1, *l2, *l3;
606 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
607 struct gatt_service_info *serv_info = l1->data;
609 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
610 struct gatt_char_info *char_info = l2->data;
612 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
613 struct gatt_desc_info *desc_info = l3->data;
615 if (g_strcmp0(desc_info->desc_path, desc_path)
621 BT_ERR("Gatt service not found");
625 static void __bt_gatt_char_method_call(GDBusConnection *connection,
627 const gchar *object_path,
628 const gchar *interface_name,
629 const gchar *method_name,
630 GVariant *parameters,
631 GDBusMethodInvocation *invocation,
635 if (g_strcmp0(method_name, "ReadValue") == 0) {
639 bt_gatt_read_req_t read_req = {0, };
640 bt_user_info_t *user_info = NULL;
641 struct gatt_req_info *req_info = NULL;
642 struct gatt_service_info *svc_info = NULL;
643 #ifdef TIZEN_FEATURE_BT_HPS
644 GVariant *param = NULL;
647 BT_DBG("Application path = %s", object_path);
648 BT_DBG("Sender = %s", sender);
650 user_info = _bt_get_user_data(BT_COMMON);
651 if (user_info == NULL) {
652 BT_INFO("No callback is set for %s", object_path);
653 g_dbus_method_invocation_return_value(invocation, NULL);
657 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
658 if (svc_info == NULL) {
659 BT_ERR("Coudn't find service for %s", object_path);
660 g_dbus_method_invocation_return_value(invocation, NULL);
664 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
665 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
667 read_req.att_handle = (char *)object_path;
668 read_req.address = addr;
669 read_req.req_id = req_id;
670 read_req.offset = offset;
671 read_req.service_handle = svc_info->serv_path;
673 /* Store requets information */
674 req_info = g_new0(struct gatt_req_info, 1);
675 req_info->attr_path = g_strdup(object_path);
676 req_info->svc_path = g_strdup(read_req.service_handle);
677 req_info->request_id = req_id;
678 req_info->offset = offset;
679 req_info->context = invocation;
680 gatt_requests = g_slist_append(gatt_requests, req_info);
682 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
683 BLUETOOTH_ERROR_NONE, &read_req,
684 user_info->cb, user_info->user_data);
686 #ifdef TIZEN_FEATURE_BT_HPS
687 param = g_variant_new("(sssyq)",
689 read_req.service_handle,
693 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
697 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
698 GVariant *var = NULL;
702 gboolean response_needed = FALSE;
703 bt_gatt_value_change_t value_change = {0, };
704 bt_user_info_t *user_info = NULL;
706 struct gatt_service_info *svc_info = NULL;
707 struct gatt_req_info *req_info = NULL;
708 #ifdef TIZEN_FEATURE_BT_HPS
709 GVariant *param = NULL;
712 BT_DBG("WriteValue");
713 BT_DBG("Application path = %s", object_path);
714 BT_DBG("Sender = %s", sender);
716 g_variant_get(parameters, "(&suqb@ay)",
717 &addr, &req_id, &offset, &response_needed, &var);
718 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
720 user_info = _bt_get_user_data(BT_COMMON);
722 BT_INFO("No callback is set for %s", object_path);
723 g_variant_unref(var);
725 g_dbus_method_invocation_return_value(invocation, NULL);
727 g_object_unref(invocation);
731 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
732 if (svc_info == NULL) {
733 BT_ERR("Coudn't find service for %s", object_path);
734 g_variant_unref(var);
736 g_dbus_method_invocation_return_value(invocation, NULL);
738 g_object_unref(invocation);
742 value_change.att_handle = (char *)object_path;
743 value_change.address = addr;
744 value_change.service_handle = svc_info->serv_path;
745 value_change.offset = offset;
746 value_change.req_id = req_id;
747 value_change.response_needed = response_needed;
749 len = g_variant_get_size(var);
753 value_change.att_value = (guint8 *)g_malloc(len);
755 data = (char *)g_variant_get_data(var);
756 memcpy(value_change.att_value, data, len);
758 value_change.val_len = len;
760 if (response_needed) {
761 /* Store requets information */
762 req_info = g_new0(struct gatt_req_info, 1);
763 req_info->attr_path = g_strdup(object_path);
764 req_info->svc_path = g_strdup(value_change.service_handle);
765 req_info->request_id = req_id;
766 req_info->offset = offset;
767 req_info->context = invocation;
768 gatt_requests = g_slist_append(gatt_requests, req_info);
770 g_object_unref(invocation);
774 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
775 BLUETOOTH_ERROR_NONE, &value_change,
776 user_info->cb, user_info->user_data);
778 #ifdef TIZEN_FEATURE_BT_HPS
781 svc_path = g_strdup(svc_info->serv_path);
782 param = g_variant_new("(sssyq@ay)",
789 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
795 g_free(value_change.att_value);
796 g_variant_unref(var);
798 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
799 bt_user_info_t *user_info = NULL;
800 bt_gatt_char_notify_change_t notify_change = {0, };
801 BT_DBG("StartNotify");
802 user_info = _bt_get_user_data(BT_COMMON);
803 if (user_info != NULL) {
804 struct gatt_service_info *svc_info = NULL;
805 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
807 notify_change.service_handle = svc_info->serv_path;
808 notify_change.att_handle = (char *)object_path;
809 notify_change.att_notify = TRUE;
811 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
812 BLUETOOTH_ERROR_NONE, ¬ify_change,
813 user_info->cb, user_info->user_data);
816 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
817 bt_user_info_t *user_info = NULL;
818 bt_gatt_char_notify_change_t notify_change = {0, };
819 BT_DBG("StopNotify");
820 user_info = _bt_get_user_data(BT_COMMON);
821 if (user_info != NULL) {
822 struct gatt_service_info *svc_info = NULL;
823 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
825 notify_change.service_handle = svc_info->serv_path;
826 notify_change.att_handle = (char *)object_path;
827 notify_change.att_notify = FALSE;
829 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
830 BLUETOOTH_ERROR_NONE, ¬ify_change,
831 user_info->cb, user_info->user_data);
834 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
836 bt_gatt_indicate_confirm_t confirm = {0, };
837 bt_user_info_t *user_info = NULL;
838 gboolean complete = FALSE;
839 struct gatt_service_info *svc_info = NULL;
841 BT_DBG("IndicateConfirm");
842 BT_DBG("Application path = %s", object_path);
843 BT_DBG("Sender = %s", sender);
845 g_variant_get(parameters, "(&sb)", &addr, &complete);
846 BT_DBG("Remote Device address number = %s", addr);
848 confirm.att_handle = (char *)object_path;
849 confirm.address = addr;
850 confirm.complete = complete;
852 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
853 if (svc_info != NULL) {
854 confirm.service_handle = svc_info->serv_path;
856 user_info = _bt_get_user_data(BT_COMMON);
857 if (user_info != NULL) {
859 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
860 BLUETOOTH_ERROR_NONE, &confirm,
861 user_info->cb, user_info->user_data);
866 g_dbus_method_invocation_return_value(invocation, NULL);
869 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
871 const gchar *object_path,
872 const gchar *interface_name,
873 const gchar *method_name,
874 GVariant *parameters,
875 GDBusMethodInvocation *invocation,
878 if (g_strcmp0(method_name, "ReadValue") == 0) {
882 bt_gatt_read_req_t read_req = {0, };
883 bt_user_info_t *user_info = NULL;
884 struct gatt_req_info *req_info = NULL;
885 struct gatt_service_info *svc_info = NULL;
888 BT_DBG("Application path = %s", object_path);
889 BT_DBG("Sender = %s", sender);
891 user_info = _bt_get_user_data(BT_COMMON);
892 if (user_info == NULL) {
893 BT_INFO("No callback is set for %s", object_path);
894 g_dbus_method_invocation_return_value(invocation, NULL);
898 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
899 if (svc_info == NULL) {
900 BT_ERR("Coudn't find service for %s", object_path);
901 g_dbus_method_invocation_return_value(invocation, NULL);
905 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
906 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
908 read_req.att_handle = (char *)object_path;
909 read_req.address = addr;
910 read_req.req_id = req_id;
911 read_req.offset = offset;
912 read_req.service_handle = svc_info->serv_path;
914 /* Store requets information */
915 req_info = g_new0(struct gatt_req_info, 1);
916 req_info->attr_path = g_strdup(object_path);
917 req_info->svc_path = g_strdup(read_req.service_handle);
918 req_info->request_id = req_id;
919 req_info->offset = offset;
920 req_info->context = invocation;
921 gatt_requests = g_slist_append(gatt_requests, req_info);
924 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
925 BLUETOOTH_ERROR_NONE, &read_req,
926 user_info->cb, user_info->user_data);
929 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
930 GVariant *var = NULL;
934 gboolean response_needed = FALSE;
935 bt_gatt_value_change_t value_change = {0, };
936 bt_user_info_t *user_info = NULL;
938 struct gatt_service_info *svc_info = NULL;
939 struct gatt_req_info *req_info = NULL;
941 BT_DBG("WriteValue");
942 BT_DBG("Application path = %s", object_path);
943 BT_DBG("Sender = %s", sender);
945 g_variant_get(parameters, "(&suqb@ay)",
946 &addr, &req_id, &offset, &response_needed, &var);
947 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
949 user_info = _bt_get_user_data(BT_COMMON);
950 if (user_info == NULL) {
951 BT_INFO("No callback is set for %s", object_path);
952 g_variant_unref(var);
954 g_dbus_method_invocation_return_value(invocation, NULL);
956 g_object_unref(invocation);
960 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
961 if (svc_info == NULL) {
962 BT_ERR("Coudn't find service for %s", object_path);
963 g_variant_unref(var);
965 g_dbus_method_invocation_return_value(invocation, NULL);
967 g_object_unref(invocation);
971 value_change.att_handle = (char *)object_path;
972 value_change.address = addr;
973 value_change.service_handle = svc_info->serv_path;
974 value_change.offset = offset;
975 value_change.req_id = req_id;
976 value_change.response_needed = response_needed;
978 len = g_variant_get_size(var);
982 value_change.att_value = (guint8 *)g_malloc(len);
984 data = (char *)g_variant_get_data(var);
985 memcpy(value_change.att_value, data, len);
987 value_change.val_len = len;
989 if (response_needed) {
990 /* Store requets information */
991 req_info = g_new0(struct gatt_req_info, 1);
992 req_info->attr_path = g_strdup(object_path);
993 req_info->svc_path = g_strdup(value_change.service_handle);
994 req_info->request_id = req_id;
995 req_info->offset = offset;
996 req_info->context = invocation;
997 gatt_requests = g_slist_append(gatt_requests, req_info);
999 g_object_unref(invocation);
1002 _bt_common_event_cb(
1003 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1004 BLUETOOTH_ERROR_NONE, &value_change,
1005 user_info->cb, user_info->user_data);
1007 g_free(value_change.att_value);
1008 g_variant_unref(var);
1013 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1016 GError *error = NULL;
1017 GVariantBuilder *array_builder;
1019 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1020 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1021 g_variant_builder_add(array_builder, "s", interface);
1023 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1024 "org.freedesktop.Dbus.Objectmanager",
1025 "InterfacesRemoved",
1026 g_variant_new("(oas)",
1027 object_path, array_builder),
1031 if (error != NULL) {
1032 /* dbus gives error cause */
1033 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1034 error->code, error->message);
1035 g_clear_error(&error);
1038 g_variant_builder_unref(array_builder);
1043 static const GDBusInterfaceVTable desc_interface_vtable = {
1044 __bt_gatt_desc_method_call,
1049 static const GDBusInterfaceVTable char_interface_vtable = {
1050 __bt_gatt_char_method_call,
1055 static const GDBusInterfaceVTable serv_interface_vtable = {
1061 static const GDBusInterfaceVTable manager_interface_vtable = {
1062 __bt_gatt_manager_method_call,
1067 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1068 const gchar *introspection_data)
1071 GDBusNodeInfo *node_info = NULL;
1073 if (introspection_data == NULL)
1077 BT_DBG("Create new node info");
1078 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1081 BT_ERR("Unable to create node: %s", err->message);
1082 g_clear_error(&err);
1089 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1090 const char *service_path)
1094 for (l = gatt_services; l != NULL; l = l->next) {
1095 struct gatt_service_info *info = l->data;
1097 if (g_strcmp0(info->serv_path, service_path) == 0)
1100 BT_ERR("Gatt service not found");
1104 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1105 const char *service_path, const char *char_path)
1109 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1110 struct gatt_service_info *serv_info = l1->data;
1112 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1114 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1115 struct gatt_char_info *char_info = l2->data;
1117 if (g_strcmp0(char_info->char_path, char_path)
1121 BT_ERR("Gatt characteristic not found");
1125 BT_ERR("Gatt service not found");
1129 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1130 const char *serv_path, const char *char_path,
1131 const char *desc_path)
1133 GSList *l1, *l2, *l3;
1135 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1136 struct gatt_service_info *serv_info = l1->data;
1138 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1139 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1140 struct gatt_char_info *char_info = l2->data;
1142 if (g_strcmp0(char_info->char_path, char_path)
1144 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1145 struct gatt_desc_info *desc_info = l3->data;
1146 if (g_strcmp0(desc_info->desc_path,
1155 BT_ERR("Gatt descriptor not found");
1159 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1163 for (l = gatt_requests; l != NULL; l = l->next) {
1164 struct gatt_req_info *req_info = l->data;
1166 if (req_info && req_info->request_id == request_id)
1169 BT_ERR("Gatt Request not found");
1173 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1174 const gchar *path, const gchar *interface)
1180 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1185 BT_ERR("Unable to connect to gdbus: %s", err->message);
1186 g_clear_error(&err);
1191 proxy = g_dbus_proxy_new_sync(g_conn,
1192 G_DBUS_PROXY_FLAGS_NONE, NULL,
1194 interface, NULL, &err);
1198 BT_ERR("Unable to create proxy: %s", err->message);
1199 g_clear_error(&err);
1203 manager_gproxy = proxy;
1208 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1209 const gchar *path, const gchar *interface)
1211 return (manager_gproxy) ? manager_gproxy :
1212 __bt_gatt_gdbus_init_manager_proxy(service,
1216 int bluetooth_gatt_convert_prop2string(
1217 bt_gatt_characteristic_property_t properties,
1218 char *char_properties[])
1222 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
1223 char_properties[flag_count] = g_strdup("broadcast");
1226 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
1227 char_properties[flag_count] = g_strdup("read");
1230 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
1231 char_properties[flag_count] = g_strdup("write-without-response");
1234 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
1235 char_properties[flag_count] = g_strdup("write");
1238 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
1239 char_properties[flag_count] = g_strdup("notify");
1242 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
1243 char_properties[flag_count] = g_strdup("indicate");
1246 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
1247 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
1250 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
1251 char_properties[flag_count] = g_strdup("reliable-write");
1254 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
1255 char_properties[flag_count] = g_strdup("writable-auxiliaries");
1258 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
1259 char_properties[flag_count] = g_strdup("encrypt-read");
1262 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
1263 char_properties[flag_count] = g_strdup("encrypt-write");
1266 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
1267 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1270 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
1271 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1275 if (flag_count == 0) {
1276 char_properties[flag_count] = g_strdup("read");
1283 int bluetooth_gatt_convert_perm2string(
1284 bt_gatt_permission_t properties,
1285 char *char_properties[])
1289 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
1290 char_properties[flag_count] = g_strdup("read");
1293 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
1294 char_properties[flag_count] = g_strdup("write");
1297 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
1298 char_properties[flag_count] = g_strdup("encrypt-read");
1301 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
1302 char_properties[flag_count] = g_strdup("encrypt-write");
1305 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
1306 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1309 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
1310 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1314 if (flag_count == 0) {
1315 char_properties[flag_count] = g_strdup("read");
1322 static void __bt_gatt_set_service_state(const char *service_path,
1325 struct gatt_service_info *svc_info = NULL;
1326 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1328 if (svc_info != NULL) {
1329 BT_DBG("Updating the gatt service register state %d", state);
1330 svc_info->is_svc_registered = state;
1334 BT_DBG("gatt service not found");
1337 static gboolean __bt_gatt_get_service_state(const char *service_path)
1339 struct gatt_service_info *svc_info = NULL;
1341 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1343 if (svc_info != NULL) {
1344 BT_DBG("Return the state of the gatt service %d",
1345 svc_info->is_svc_registered);
1346 return svc_info->is_svc_registered;
1349 BT_DBG("gatt service info is NULL");
1353 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1355 GError *error = NULL;
1357 GVariantIter *iter = NULL;
1358 const gchar *key = NULL;
1359 GVariant *value = NULL;
1360 const gchar *service = NULL;
1361 const gchar *characteristic = NULL;
1362 const gchar *descriptor = NULL;
1366 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1368 if (result == NULL) {
1369 /* dBUS-RPC is failed */
1370 BT_ERR("Dbus-RPC is failed\n");
1372 if (error != NULL) {
1373 /* dBUS gives error cause */
1374 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1375 error->code, error->message);
1376 g_clear_error(&error);
1379 char *char_cmp = NULL;
1380 g_variant_get(result, "(a{sv})", &iter);
1381 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1383 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1384 if (g_strcmp0(key, "Service") == 0) {
1385 service = g_variant_get_string(value, NULL);
1386 BT_DBG("Service %s", service);
1387 } else if (g_strcmp0(key, char_cmp) == 0) {
1388 characteristic = g_variant_get_string(value, NULL);
1390 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1391 BT_DBG("%s", characteristic);
1392 } else if (g_strcmp0(key, "Descriptor") == 0) {
1393 descriptor = g_variant_get_string(value, NULL);
1394 BT_DBG("Descriptor %s", descriptor);
1397 g_variant_iter_free(iter);
1399 /* TODO: Store the service informationa and
1400 * Send respponse to CAPI layer. */
1402 g_variant_unref(result);
1407 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1409 BT_INFO("RegisterApplication is completed");
1411 GError *error = NULL;
1414 register_pending_cnt = 0;
1416 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1418 if (result == NULL) {
1419 /* dBUS-RPC is failed */
1420 BT_ERR("Dbus-RPC is failed\n");
1422 if (error != NULL) {
1423 /* dBUS gives error cause */
1424 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1425 error->code, error->message);
1426 g_clear_error(&error);
1429 g_variant_unref(result);
1433 void unregister_application_cb(GObject *object, GAsyncResult *res,
1436 BT_INFO("UnregisterApplication is completed");
1438 GError *error = NULL;
1441 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1443 if (result == NULL) {
1444 /* dBUS-RPC is failed */
1445 BT_ERR("Dbus-RPC is failed\n");
1447 if (error != NULL) {
1448 /* dBUS gives error cause */
1449 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1450 error->code, error->message);
1451 g_clear_error(&error);
1454 g_variant_unref(result);
1458 static int __bt_gatt_unregister_service(const char *service_path)
1460 if (!__bt_gatt_get_service_state(service_path)) {
1461 BT_DBG("service not registered \n");
1462 return BLUETOOTH_ERROR_NOT_FOUND;
1465 return BLUETOOTH_ERROR_NONE;
1468 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1470 GDBusProxy *proxy = NULL;
1472 if (is_server_started) {
1473 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1474 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1476 if (proxy == NULL || app_path == NULL)
1477 return BLUETOOTH_ERROR_INTERNAL;
1479 BT_INFO("UnregisterApplication");
1481 /* Async Call to Unregister Service */
1482 g_dbus_proxy_call(proxy,
1483 "UnregisterApplication",
1484 g_variant_new("(o)",
1486 G_DBUS_CALL_FLAGS_NONE, -1,
1488 (GAsyncReadyCallback) unregister_application_cb,
1491 is_server_started = false;
1492 return BLUETOOTH_ERROR_NONE;
1495 BT_INFO("GATT server not started");
1496 return BLUETOOTH_ERROR_NONE;
1499 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1501 GDBusConnection *local_system_gconn = NULL;
1505 if (g_conn == NULL) {
1506 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1507 if (address == NULL) {
1509 BT_ERR("Failed to get bus address: %s", err->message);
1510 g_clear_error(&err);
1515 g_conn = g_dbus_connection_new_for_address_sync(address,
1516 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1517 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1518 NULL, /* GDBusAuthObserver */
1524 BT_ERR("Unable to connect to dbus: %s", err->message);
1525 g_clear_error(&err);
1529 } else if (g_dbus_connection_is_closed(g_conn)) {
1530 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1531 if (address == NULL) {
1533 BT_ERR("Failed to get bus address: %s", err->message);
1534 g_clear_error(&err);
1539 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1540 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1541 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1542 NULL, /* GDBusAuthObserver */
1546 if (!local_system_gconn) {
1547 BT_ERR("Unable to connect to dbus: %s", err->message);
1548 g_clear_error(&err);
1551 g_conn = local_system_gconn;
1557 BT_EXPORT_API int bluetooth_gatt_init(void)
1559 GDBusConnection *conn;
1560 GError *error = NULL;
1561 GDBusNodeInfo *node_info = NULL;
1563 if (app_path != NULL) {
1564 BT_ERR("app path already exists! initialized");
1565 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1568 if (owner_id == 0) {
1569 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1570 BT_GATT_SERVICE_NAME,
1571 G_BUS_NAME_OWNER_FLAGS_NONE,
1572 NULL, NULL, NULL, NULL, NULL);
1575 BT_DBG("owner_id is [%d]", owner_id);
1576 app_path = g_strdup_printf("/com/%d", getpid());
1580 conn = __bt_gatt_get_gdbus_connection();
1582 BT_ERR("Unable to get connection");
1586 /* Register ObjectManager interface */
1587 node_info = __bt_gatt_create_method_node_info(
1588 manager_introspection_xml);
1589 if (node_info == NULL) {
1590 BT_ERR("failed to get node info");
1594 if (manager_id == 0) {
1595 BT_INFO("manager_id does not exists");
1597 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1598 node_info->interfaces[0],
1599 &manager_interface_vtable,
1600 NULL, NULL, &error);
1602 g_dbus_node_info_unref(node_info);
1603 if (manager_id == 0) {
1604 BT_ERR("failed to register: %s", error->message);
1605 g_error_free(error);
1609 return BLUETOOTH_ERROR_NONE;
1613 g_bus_unown_name(owner_id);
1620 __bt_gatt_close_gdbus_connection();
1622 return BLUETOOTH_ERROR_INTERNAL;
1625 BT_EXPORT_API int bluetooth_gatt_deinit()
1627 int ret = BLUETOOTH_ERROR_NONE;
1628 /* Unown gdbus bus */
1630 /* remove/unregister all services */
1631 BT_DBG("removing all registered gatt service\n");
1632 bluetooth_gatt_delete_services();
1634 /* unregister the exported interface for object manager */
1635 g_dbus_connection_unregister_object(g_conn,
1640 ret = bluetooth_gatt_unregister_application();
1641 if (ret != BLUETOOTH_ERROR_NONE)
1642 BT_ERR("Fail to unregister application\n");
1644 g_bus_unown_name(owner_id);
1650 BT_DBG("Gatt service deinitialized \n");
1652 g_slist_free(gatt_services);
1653 gatt_services = NULL;
1655 g_object_unref(manager_gproxy);
1656 manager_gproxy = NULL;
1658 __bt_gatt_close_gdbus_connection();
1663 __bt_gatt_close_gdbus_connection();
1665 return BLUETOOTH_ERROR_NOT_FOUND;
1668 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1671 GError *error = NULL;
1673 GDBusNodeInfo *node_info;
1675 GVariantBuilder *builder = NULL;
1676 GVariantBuilder *builder1 = NULL;
1677 GVariantBuilder *inner_builder = NULL;
1678 gboolean svc_primary = TRUE;
1679 struct gatt_service_info *serv_info = NULL;
1681 node_info = __bt_gatt_create_method_node_info(
1682 service_introspection_xml);
1683 if (node_info == NULL)
1684 return BLUETOOTH_ERROR_INTERNAL;
1686 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1687 BT_DBG("gatt service path is [%s]", path);
1689 object_id = g_dbus_connection_register_object(g_conn, path,
1690 node_info->interfaces[0],
1691 &serv_interface_vtable,
1692 NULL, NULL, &error);
1693 g_dbus_node_info_unref(node_info);
1695 if (object_id == 0) {
1696 BT_ERR("failed to register: %s", error->message);
1697 g_error_free(error);
1700 return BLUETOOTH_ERROR_INTERNAL;
1703 /* Add object_id/gatt service information; it's required at the time of
1704 * service unregister and Getmanagedobjects
1706 serv_info = g_new0(struct gatt_service_info, 1);
1708 serv_info->serv_path = g_strdup(path);
1709 serv_info->serv_id = object_id;
1710 serv_info->service_uuid = g_strdup(svc_uuid);
1711 serv_info->is_svc_registered = FALSE;
1712 serv_info->is_svc_primary = svc_primary;
1714 gatt_services = g_slist_append(gatt_services, serv_info);
1716 /* emit interfacesadded signal here for service path */
1717 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1718 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1720 g_variant_builder_add(inner_builder, "{sv}",
1721 "UUID", g_variant_new_string(svc_uuid));
1723 g_variant_builder_add(inner_builder, "{sv}",
1724 "Primary", g_variant_new_boolean(svc_primary));
1726 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1728 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1729 g_variant_new("ao", builder1));
1731 g_variant_builder_add(builder, "{sa{sv}}",
1732 GATT_SERV_INTERFACE, inner_builder);
1734 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1735 "org.freedesktop.Dbus.ObjectManager",
1737 g_variant_new("(oa{sa{sv}})",
1743 *svc_path = g_strdup(path);
1746 g_variant_builder_unref(inner_builder);
1747 g_variant_builder_unref(builder);
1748 g_variant_builder_unref(builder1);
1750 return BLUETOOTH_ERROR_NONE;
1753 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1754 const char *svc_path, const char *char_uuid,
1755 bt_gatt_permission_t permissions,
1756 bt_gatt_characteristic_property_t properties,
1760 GError *error = NULL;
1762 GDBusNodeInfo *node_info;
1764 GVariantBuilder *builder = NULL;
1765 GVariantBuilder *inner_builder = NULL;
1766 struct gatt_service_info *serv_info = NULL;
1767 struct gatt_char_info *char_info = NULL;
1768 GVariantBuilder *builder2 = NULL;
1769 GVariantBuilder *builder3 = NULL;
1770 GVariant *flags_val = NULL;
1772 char *char_flags[NUMBER_OF_FLAGS];
1777 new_service = FALSE;
1780 BT_DBG("gatt svc_path path is [%s]", svc_path);
1781 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1782 if (serv_info == NULL)
1783 return BLUETOOTH_ERROR_INVALID_PARAM;
1785 node_info = __bt_gatt_create_method_node_info(
1786 characteristics_introspection_xml);
1787 if (node_info == NULL)
1788 return BLUETOOTH_ERROR_INTERNAL;
1790 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1791 BT_DBG("gatt characteristic path is [%s]", path);
1793 object_id = g_dbus_connection_register_object(g_conn, path,
1794 node_info->interfaces[0],
1795 &char_interface_vtable,
1796 NULL, NULL, &error);
1797 g_dbus_node_info_unref(node_info);
1799 if (object_id == 0) {
1800 BT_ERR("failed to register: %s", error->message);
1801 g_error_free(error);
1804 return BLUETOOTH_ERROR_INTERNAL;
1807 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1808 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1809 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1810 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1811 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1812 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1813 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1814 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1816 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1818 char_info = g_new0(struct gatt_char_info, 1);
1820 char_info->char_path = g_strdup(path);
1821 char_info->char_id = object_id;
1822 char_info->char_uuid = g_strdup(char_uuid);
1824 for (i = 0; i < flag_count; i++)
1825 char_info->char_flags[i] = char_flags[i];
1828 char_info->flags_length = flag_count;
1830 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1832 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1833 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1835 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1836 g_variant_new("s", char_uuid));
1837 g_variant_builder_add(inner_builder, "{sv}", "Service",
1838 g_variant_new("o", svc_path));
1840 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1842 for (i = 0; i < flag_count; i++)
1843 g_variant_builder_add(builder2, "s", char_flags[i]);
1845 flags_val = g_variant_new("as", builder2);
1846 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1849 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1851 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1852 g_variant_new("ao", builder3));
1854 g_variant_builder_add(builder, "{sa{sv}}",
1855 GATT_CHAR_INTERFACE,
1858 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1859 "org.freedesktop.Dbus.ObjectManager",
1861 g_variant_new("(oa{sa{sv}})",
1865 *char_path = g_strdup(path);
1871 g_variant_builder_unref(inner_builder);
1872 g_variant_builder_unref(builder);
1873 g_variant_builder_unref(builder2);
1874 g_variant_builder_unref(builder3);
1876 return BLUETOOTH_ERROR_NONE;
1879 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1880 const char *characteristic, const char *char_value,
1883 gchar **line_argv = NULL;
1884 char *serv_path = NULL;
1885 struct gatt_char_info *char_info = NULL;
1886 GVariantBuilder *builder1 = NULL;
1887 GVariantBuilder *builder = NULL;
1888 GVariantBuilder *inner_builder = NULL;
1889 GVariant *char_val = NULL;
1890 GError *error = NULL;
1892 int res = BLUETOOTH_ERROR_NONE;
1894 line_argv = g_strsplit_set(characteristic, "/", 0);
1895 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1897 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1899 if (char_info == NULL) {
1900 /* Fix : RESOURCE_LEAK */
1901 res = BLUETOOTH_ERROR_INVALID_PARAM;
1905 char_info->value_length = value_length;
1907 char_info->char_value = (char *)malloc(value_length);
1908 /* Fix : NULL_RETURNS */
1909 if (char_info->char_value == NULL) {
1910 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1914 for (i = 0; i < value_length; i++)
1915 char_info->char_value[i] = char_value[i];
1917 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1918 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1920 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1922 for (i = 0; i < value_length; i++)
1923 g_variant_builder_add(builder1, "y", char_value[i]);
1925 char_val = g_variant_new("ay", builder1);
1926 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1928 g_variant_builder_add(builder, "{sa{sv}}",
1929 GATT_CHAR_INTERFACE,
1932 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1933 "org.freedesktop.Dbus.ObjectManager",
1935 g_variant_new("(oa{sa{sv}})",
1936 char_info->char_path, builder),
1939 g_variant_builder_unref(inner_builder);
1940 g_variant_builder_unref(builder);
1941 g_variant_builder_unref(builder1);
1943 g_strfreev(line_argv);
1949 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
1950 const char *char_path, const char *desc_uuid,
1951 bt_gatt_permission_t permissions,
1954 static int desc_id = 1;
1955 GError *error = NULL;
1957 GDBusNodeInfo *node_info;
1959 GVariantBuilder *builder = NULL;
1960 GVariantBuilder *inner_builder = NULL;
1961 struct gatt_char_info *char_info = NULL;
1962 struct gatt_desc_info *desc_info = NULL;
1963 gchar **line_argv = NULL;
1965 GVariantBuilder *builder2 = NULL;
1966 GVariant *flags_val = NULL;
1968 char *desc_flags[NUMBER_OF_FLAGS];
1976 line_argv = g_strsplit_set(char_path, "/", 0);
1977 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1979 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
1980 if (char_info == NULL) {
1981 g_strfreev(line_argv);
1983 return BLUETOOTH_ERROR_INVALID_PARAM;
1986 node_info = __bt_gatt_create_method_node_info(
1987 descriptor_introspection_xml);
1988 if (node_info == NULL) {
1989 g_strfreev(line_argv);
1991 return BLUETOOTH_ERROR_INTERNAL;
1994 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
1995 BT_DBG("gatt descriptor path is [%s]", path);
1997 object_id = g_dbus_connection_register_object(g_conn, path,
1998 node_info->interfaces[0],
1999 &desc_interface_vtable,
2000 NULL, NULL, &error);
2001 g_dbus_node_info_unref(node_info);
2003 if (object_id == 0) {
2004 BT_ERR("failed to register: %s", error->message);
2005 g_error_free(error);
2007 g_strfreev(line_argv);
2010 return BLUETOOTH_ERROR_INTERNAL;
2013 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2015 desc_info = g_new0(struct gatt_desc_info, 1);
2017 desc_info->desc_path = g_strdup(path);
2018 desc_info->desc_id = object_id;
2019 desc_info->desc_uuid = g_strdup(desc_uuid);
2021 for (i = 0; i < flag_count; i++)
2022 desc_info->desc_flags[i] = desc_flags[i];
2024 desc_info->flags_length = flag_count;
2026 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2028 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2029 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2031 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2032 g_variant_new("s", desc_uuid));
2033 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2034 g_variant_new("o", char_path));
2036 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2038 for (i = 0; i < flag_count; i++)
2039 g_variant_builder_add(builder2, "s", desc_flags[i]);
2041 flags_val = g_variant_new("as", builder2);
2042 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2045 g_variant_builder_add(builder, "{sa{sv}}",
2046 GATT_DESC_INTERFACE,
2049 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2050 "org.freedesktop.Dbus.ObjectManager",
2052 g_variant_new("(oa{sa{sv}})",
2056 *desc_path = g_strdup(path);
2060 g_strfreev(line_argv);
2061 g_variant_builder_unref(inner_builder);
2062 g_variant_builder_unref(builder);
2063 g_variant_builder_unref(builder2);
2065 return BLUETOOTH_ERROR_NONE;
2068 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2069 const char *desc_path, const char *desc_value,
2072 GError *error = NULL;
2073 GVariantBuilder *builder = NULL;
2074 GVariantBuilder *inner_builder = NULL;
2075 GVariantBuilder *builder1 = NULL;
2076 struct gatt_desc_info *desc_info = NULL;
2077 gchar **line_argv = NULL;
2079 GVariant *desc_val = NULL;
2080 char *serv_path = NULL;
2083 line_argv = g_strsplit_set(desc_path, "/", 0);
2084 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2085 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2087 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2089 /* Free the allocated memory */
2090 g_strfreev(line_argv);
2094 /* Fix : NULL_RETURNS */
2095 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2097 desc_info->desc_value = (char *)malloc(value_length);
2099 /* Fix : NULL_RETURNS */
2100 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2102 for (i = 0; i < value_length; i++)
2103 desc_info->desc_value[i] = desc_value[i];
2105 desc_info->value_length = value_length;
2107 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2108 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2110 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2112 for (i = 0; i < value_length; i++)
2113 g_variant_builder_add(builder1, "y", desc_value[i]);
2115 desc_val = g_variant_new("ay", builder1);
2116 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2118 g_variant_builder_add(builder, "{sa{sv}}",
2119 GATT_DESC_INTERFACE,
2122 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2123 "org.freedesktop.Dbus.ObjectManager",
2125 g_variant_new("(oa{sa{sv}})",
2126 desc_info->desc_path, builder),
2129 g_variant_builder_unref(inner_builder);
2130 g_variant_builder_unref(builder);
2131 g_variant_builder_unref(builder1);
2133 return BLUETOOTH_ERROR_NONE;
2136 int bluetooth_gatt_get_service(const char *svc_uuid)
2138 GDBusProxy *proxy = NULL;
2141 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2142 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2144 return BLUETOOTH_ERROR_INTERNAL;
2146 uuid = g_strdup(svc_uuid);
2148 g_dbus_proxy_call(proxy,
2150 g_variant_new("(s)",
2152 G_DBUS_CALL_FLAGS_NONE, -1,
2154 (GAsyncReadyCallback) get_service_cb,
2159 return BLUETOOTH_ERROR_NONE;
2162 BT_EXPORT_API int bluetooth_gatt_register_service(
2163 const char *svc_path)
2165 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2166 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2167 BT_ERR("Don't have aprivilege to use this API");
2168 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2171 register_pending_cnt++;
2173 if (__bt_gatt_get_service_state(svc_path)) {
2174 BT_DBG("service already registered \n");
2175 return BLUETOOTH_ERROR_NONE;
2178 __bt_gatt_set_service_state(svc_path, TRUE);
2180 return BLUETOOTH_ERROR_NONE;
2183 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2185 GDBusProxy *proxy = NULL;
2187 if (!is_server_started) {
2189 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2190 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2191 BT_ERR("Don't have aprivilege to use this API");
2192 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2195 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2196 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2197 if (proxy == NULL || app_path == NULL)
2198 return BLUETOOTH_ERROR_INTERNAL;
2200 BT_INFO("RegisterApplication");
2202 g_dbus_proxy_call(proxy,
2203 "RegisterApplication",
2204 g_variant_new("(oa{sv})",
2206 G_DBUS_CALL_FLAGS_NONE, -1,
2208 (GAsyncReadyCallback) register_application_cb,
2211 is_server_started = true;
2213 return BLUETOOTH_ERROR_NONE;
2216 BT_INFO("Already RegisterApplication");
2218 return BLUETOOTH_ERROR_NONE;
2221 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2224 int error = BLUETOOTH_ERROR_NONE;
2228 for (l = gatt_services; l != NULL; l = l->next) {
2229 struct gatt_service_info *info = l->data;
2230 BT_DBG("svc_path is %s", info->serv_path);
2231 if (bluetooth_gatt_unregister_service(info->serv_path)
2232 != BLUETOOTH_ERROR_NONE) {
2233 error = BLUETOOTH_ERROR_INTERNAL;
2234 BT_ERR("Error in removing service %s \n",
2238 BT_DBG(" All services removed successfully.\n ");
2240 BT_DBG(" There are no registered services.\n ");
2243 g_slist_free(gatt_services);
2244 gatt_services = NULL;
2247 if (error != BLUETOOTH_ERROR_NONE)
2250 return BLUETOOTH_ERROR_NONE;
2253 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2254 const char *char_path, const char* char_value,
2257 GVariantBuilder *outer_builder;
2258 GVariantBuilder *inner_builder;
2259 GVariantBuilder *invalidated_builder;
2260 GVariant *update_value = NULL;
2261 GError *error = NULL;
2262 gboolean ret = FALSE;
2263 int err = BLUETOOTH_ERROR_NONE;
2265 gchar **line_argv = NULL;
2266 gchar *serv_path = NULL;
2268 line_argv = g_strsplit_set(char_path, "/", 0);
2269 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2271 if (!__bt_gatt_get_service_state(serv_path)) {
2272 BT_DBG("service not registered for this characteristic \n");
2274 g_strfreev(line_argv);
2275 return BLUETOOTH_ERROR_INTERNAL;
2278 /* Fix the svace issue : 185689
2279 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2281 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2283 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2284 for (i = 0; i < value_length; i++)
2285 g_variant_builder_add(inner_builder, "y", char_value[i]);
2287 update_value = g_variant_new("ay", inner_builder);
2290 outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2291 g_variant_builder_add(outer_builder, "{sv}", "Value",
2294 BT_DBG("Updating characteristic value \n");
2295 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2297 "org.freedesktop.DBus.Properties",
2298 "PropertiesChanged",
2299 g_variant_new("(sa{sv}as)",
2300 "org.bluez.GattCharacteristic1",
2301 outer_builder, invalidated_builder),
2305 if (error != NULL) {
2306 BT_ERR("D-Bus API failure: errCode[%x], \
2308 error->code, error->message);
2309 g_clear_error(&error);
2311 err = BLUETOOTH_ERROR_INTERNAL;
2313 struct gatt_char_info *char_info = NULL;
2315 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2316 if (char_info == NULL) {
2318 g_strfreev(line_argv);
2319 g_variant_builder_unref(inner_builder);
2320 g_variant_builder_unref(outer_builder);
2321 g_variant_builder_unref(invalidated_builder);
2323 return BLUETOOTH_ERROR_INVALID_DATA;
2326 char_info->value_length = value_length;
2328 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
2329 if (char_info->char_value) {
2330 for (i = 0; i < value_length; i++)
2331 char_info->char_value[i] = char_value[i];
2336 g_strfreev(line_argv);
2337 g_variant_builder_unref(inner_builder);
2338 g_variant_builder_unref(outer_builder);
2339 g_variant_builder_unref(invalidated_builder);
2344 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2351 g_free(desc_info->desc_path);
2352 g_free(desc_info->desc_uuid);
2353 g_free(desc_info->desc_value);
2355 for (i = 0; i < desc_info->flags_length; i++)
2356 g_free(desc_info->desc_flags[i]);
2361 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2368 g_free(char_info->char_path);
2369 g_free(char_info->char_uuid);
2370 g_free(char_info->char_value);
2372 for (i = 0; i < char_info->flags_length; i++)
2373 g_free(char_info->char_flags[i]);
2378 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2383 g_free(svc_info->serv_path);
2384 g_free(svc_info->service_uuid);
2388 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2391 struct gatt_service_info *svc_info;
2393 int err = BLUETOOTH_ERROR_NONE;
2395 BT_DBG("svc_path %s", svc_path);
2396 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2399 BT_ERR("Unable to find service info");
2400 return BLUETOOTH_ERROR_NOT_FOUND;
2403 err = __bt_gatt_unregister_service(svc_path);
2404 if (err != BLUETOOTH_ERROR_NONE) {
2405 BT_ERR("Could not unregister application");
2409 for (l = svc_info->char_data; l != NULL; l = l->next) {
2410 struct gatt_char_info *char_info = l->data;
2412 if (char_info == NULL)
2415 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2416 struct gatt_desc_info *desc_info = l1->data;
2418 if (desc_info == NULL)
2421 ret = g_dbus_connection_unregister_object(g_conn,
2422 desc_info->desc_id);
2424 __bt_gatt_emit_interface_removed(
2425 desc_info->desc_path,
2426 GATT_DESC_INTERFACE);
2428 err = BLUETOOTH_ERROR_INTERNAL;
2431 /* list remove & free */
2432 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2433 __bt_gatt_free_descriptor_info(desc_info);
2436 g_slist_free(char_info->desc_data);
2437 char_info->desc_data = NULL;
2439 ret = g_dbus_connection_unregister_object(g_conn,
2440 char_info->char_id);
2442 __bt_gatt_emit_interface_removed(char_info->char_path,
2443 GATT_CHAR_INTERFACE);
2445 err = BLUETOOTH_ERROR_INTERNAL;
2448 /* list remove & free */
2449 svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
2450 __bt_gatt_free_characteristic_info(char_info);
2453 g_slist_free(svc_info->char_data);
2454 svc_info->char_data = NULL;
2456 ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2458 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2459 GATT_SERV_INTERFACE);
2461 err = BLUETOOTH_ERROR_INTERNAL;
2464 ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2466 BT_DBG("Unregistered the service on properties interface");
2468 /* list remove & free */
2469 gatt_services = g_slist_remove(gatt_services, svc_info);
2470 __bt_gatt_free_service_info(svc_info);
2472 new_service = FALSE;
2474 if (gatt_services == NULL)
2476 else if (gatt_services->next == NULL)
2482 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2483 int resp_state, int offset, char *value, int value_length)
2485 struct gatt_req_info *req_info = NULL;
2487 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2488 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2489 BT_ERR("Don't have aprivilege to use this API");
2490 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2493 req_info = __bt_gatt_find_request_info(request_id);
2494 if (req_info == NULL) {
2495 BT_ERR("Coundn't find request id [%d]", request_id);
2496 return BLUETOOTH_ERROR_INTERNAL;
2499 if (resp_state != BLUETOOTH_ERROR_NONE) {
2500 BT_ERR("resp_state is 0x%X", resp_state);
2502 g_dbus_method_invocation_return_dbus_error(req_info->context,
2503 "org.bluez.Error.Failed", "Application Error");
2505 gatt_requests = g_slist_remove(gatt_requests, req_info);
2507 req_info->context = NULL;
2508 if (req_info->attr_path)
2509 g_free(req_info->attr_path);
2510 if (req_info->svc_path)
2511 g_free(req_info->svc_path);
2514 return BLUETOOTH_ERROR_NONE;
2517 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2519 GVariantBuilder *inner_builder = NULL;
2520 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2521 if (value_length > 0 && value != NULL) {
2522 for (i = 0; i < value_length; i++)
2523 g_variant_builder_add(inner_builder, "y", value[i]);
2525 g_dbus_method_invocation_return_value(req_info->context,
2526 g_variant_new("(ay)", inner_builder));
2527 g_variant_builder_unref(inner_builder);
2529 g_dbus_method_invocation_return_value(req_info->context, NULL);
2531 gatt_requests = g_slist_remove(gatt_requests, req_info);
2533 req_info->context = NULL;
2534 if (req_info->attr_path)
2535 g_free(req_info->attr_path);
2536 if (req_info->svc_path)
2537 g_free(req_info->svc_path);
2540 return BLUETOOTH_ERROR_NONE;
2543 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2544 bluetooth_device_address_t *unicast_address)
2546 GVariantBuilder *outer_builder;
2547 GVariantBuilder *invalidated_builder;
2548 GError *error = NULL;
2549 gboolean notify = TRUE;
2550 gboolean ret = TRUE;
2551 int err = BLUETOOTH_ERROR_NONE;
2552 gchar **line_argv = NULL;
2553 gchar *serv_path = NULL;
2554 char addr[20] = { 0 };
2556 line_argv = g_strsplit_set(char_path, "/", 0);
2557 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2559 if (!__bt_gatt_get_service_state(serv_path)) {
2560 BT_DBG("service not registered for this characteristic \n");
2562 g_strfreev(line_argv);
2563 return BLUETOOTH_ERROR_INTERNAL;
2568 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2569 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2571 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2572 g_variant_new("b", notify));
2574 if (unicast_address) {
2575 _bt_convert_addr_type_to_string(addr,
2576 (unsigned char *)unicast_address->addr);
2578 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2579 g_variant_new("s", addr));
2581 BT_DBG("Set characteristic Notification \n");
2582 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2584 "org.freedesktop.DBus.Properties",
2585 "PropertiesChanged",
2586 g_variant_new("(sa{sv}as)",
2587 "org.bluez.GattCharacteristic1",
2588 outer_builder, invalidated_builder),
2592 if (error != NULL) {
2593 BT_ERR("D-Bus API failure: errCode[%x], \
2595 error->code, error->message);
2596 g_clear_error(&error);
2598 err = BLUETOOTH_ERROR_INTERNAL;
2601 g_strfreev(line_argv);
2602 g_variant_builder_unref(outer_builder);
2603 g_variant_builder_unref(invalidated_builder);