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;
32 GDBusNodeInfo *obj_info;
35 static gboolean new_service = FALSE;
36 static gboolean new_char = FALSE;
37 static int serv_id = 1;
38 static int register_pending_cnt = 0;
39 static bool is_server_started = false;
41 /* Introspection data for the service we are exporting */
42 static const gchar service_introspection_xml[] =
44 " <interface name='org.freedesktop.DBus.Properties'>"
45 " <property type='s' name='UUID' access='read'>"
47 " <property type='b' name='primary' access='read'>"
49 " <property type='o' name='Device' access='read'>"
51 " <property type='ao' name='Characteristics' access='read'>"
53 " <property type='s' name='Includes' access='read'>"
58 /* Introspection data for the characteristics we are exporting */
59 static const gchar characteristics_introspection_xml[] =
61 " <interface name='org.bluez.GattCharacteristic1'>"
62 " <method name='ReadValue'>"
63 " <arg type='s' name='address' direction='in'/>"
64 " <arg type='y' name='id' direction='in'/>"
65 " <arg type='q' name='offset' direction='in'/>"
66 " <arg type='ay' name='Value' direction='out'/>"
68 " <method name='WriteValue'>"
69 " <arg type='s' name='address' direction='in'/>"
70 " <arg type='y' name='id' direction='in'/>"
71 " <arg type='q' name='offset' 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='y' 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='y' name='id' direction='in'/>"
114 " <arg type='q' name='offset' direction='in'/>"
115 " <arg type='ay' name='value' direction='in'/>"
118 " <interface name='org.freedesktop.DBus.Properties'>"
119 " <property type='s' name='UUID' access='read'>"
121 " <property type='o' name='Characteristic' access='read'>"
123 " <property type='ay' name='Value' access='read'>"
125 " <property type='as' name='Flags' access='read'>"
130 static const gchar manager_introspection_xml[] =
132 " <interface name='org.freedesktop.DBus.ObjectManager'>"
133 " <method name='GetManagedObjects'>"
134 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
139 struct gatt_service_info {
146 gboolean is_svc_registered;
147 gboolean is_svc_primary;
150 struct gatt_char_info {
155 gchar *char_flags[NUMBER_OF_FLAGS];
161 struct gatt_desc_info {
166 gchar *desc_flags[NUMBER_OF_FLAGS];
171 struct gatt_req_info {
176 GDBusMethodInvocation *context;
179 static GSList *gatt_services = NULL;
180 static GSList *gatt_requests = NULL;
181 static gchar *app_path = NULL;
183 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
184 #define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service"
186 #define GATT_SERV_OBJECT_PATH "/service"
188 #define GATT_MNGR_INTERFACE "org.bluez.GattManager1"
189 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
190 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
191 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
194 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
195 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
196 #define PROPERTIES_CHANGED "PropertiesChanged"
197 #define BT_HPS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
200 static GDBusProxy *manager_gproxy = NULL;
202 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
203 const char *service_path, const char *char_path);
204 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
205 const char *serv_path, const char *char_path,
206 const char *desc_path);
208 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
210 static void __bt_gatt_close_gdbus_connection(void)
216 ret_if(g_conn == NULL);
218 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
219 BT_ERR("Fail to flush the connection: %s", err->message);
224 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
226 BT_ERR("Fail to close the dbus connection: %s", err->message);
231 g_object_unref(g_conn);
239 static int __bt_send_event_to_hps(int event, GVariant *var)
241 GError *error = NULL;
242 GVariant *parameters;
243 GDBusMessage *msg = NULL;
247 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
249 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
250 GVariantBuilder *inner_builder;
251 GVariantBuilder *invalidated_builder;
253 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
254 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
256 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
258 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
260 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
261 g_variant_builder_unref(invalidated_builder);
262 g_variant_builder_unref(inner_builder);
263 } else if (BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
264 GVariantBuilder *inner_builder;
265 GVariantBuilder *invalidated_builder;
267 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
268 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
270 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
272 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
274 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
275 g_variant_builder_unref(invalidated_builder);
276 g_variant_builder_unref(inner_builder);
279 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
280 g_dbus_message_set_body(msg, parameters);
281 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
283 BT_ERR("D-Bus API failure: errCode[%x], \
285 error->code, error->message);
286 g_clear_error(&error);
288 return BLUETOOTH_ERROR_INTERNAL;
290 return BLUETOOTH_ERROR_NONE;
294 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
296 const gchar *object_path,
297 const gchar *interface_name,
298 const gchar *method_name,
299 GVariant *parameters,
300 GDBusMethodInvocation *invocation,
307 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
308 BT_DBG("Getting values for service, chars and descriptors");
310 GVariantBuilder *builder;
311 GVariantBuilder *inner_builder1 = NULL;
312 GVariant *svc_char = NULL;
315 builder = g_variant_builder_new(
316 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
318 /* Prepare inner builder for GattService1 interface */
320 len = g_slist_length(gatt_services);
322 for (i = 0; i <= len; i++) {
323 GVariantBuilder *svc_builder = NULL;
324 GVariantBuilder *inner_builder = NULL;
326 if (register_pending_cnt > 1) {
327 l1 = g_slist_nth(gatt_services, len - register_pending_cnt);
329 l1 = g_slist_last(gatt_services);
331 register_pending_cnt--;
333 struct gatt_service_info *serv_info = l1->data;
334 if (serv_info == NULL) {
335 BT_ERR("service info value is NULL");
336 g_dbus_method_invocation_return_value(invocation, NULL);
340 /* Prepare inner builder for GattService1 interface */
341 BT_DBG("Creating builder for service");
342 svc_builder = g_variant_builder_new(
343 G_VARIANT_TYPE("a{sa{sv}}"));
344 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
346 g_variant_builder_add(inner_builder, "{sv}", "UUID",
347 g_variant_new_string(serv_info->service_uuid));
349 g_variant_builder_add(inner_builder, "{sv}", "Primary",
350 g_variant_new_boolean(serv_info->is_svc_primary));
353 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
354 BT_DBG("Adding Charatarisitcs list");
355 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
356 struct gatt_char_info *char_info = l4->data;
357 g_variant_builder_add(inner_builder1, "o",
358 char_info->char_path);
359 BT_DBG("%s", char_info->char_path);
362 svc_char = g_variant_new("ao", inner_builder1);
363 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
366 g_variant_builder_add(svc_builder, "{sa{sv}}",
370 g_variant_builder_add(builder, "{oa{sa{sv}}}",
371 serv_info->serv_path,
374 g_variant_builder_unref(inner_builder1);
376 /* Prepare inner builder for GattCharacteristic1 interface */
378 GSList *l2 = serv_info->char_data;
379 BT_DBG("Creating builder for characteristics \n");
382 BT_DBG("characteristic data is NULL");
384 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
386 GVariantBuilder *char_builder = NULL;
387 GVariantBuilder *inner_builder = NULL;
388 GVariantBuilder *builder1 = NULL;
389 GVariantBuilder *builder2 = NULL;
390 GVariantBuilder *builder3 = NULL;
391 GVariant *char_val = NULL;
392 GVariant *flags_val = NULL;
393 GVariant *char_desc = NULL;
394 char *unicast = NULL;
395 gboolean notify = FALSE;
398 char_builder = g_variant_builder_new(
401 inner_builder = g_variant_builder_new(
405 struct gatt_char_info *char_info = l2->data;
406 if (char_info == NULL) {
407 BT_ERR("char_info is NULL");
412 g_variant_builder_add(inner_builder, "{sv}", "UUID",
413 g_variant_new_string(char_info->char_uuid));
415 g_variant_builder_add(inner_builder, "{sv}", "Service",
416 g_variant_new("o", serv_info->serv_path));
418 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
420 if (char_info->char_value != NULL) {
421 for (i = 0; i < char_info->value_length; i++) {
422 g_variant_builder_add(builder1, "y",
423 char_info->char_value[i]);
425 char_val = g_variant_new("ay", builder1);
426 g_variant_builder_add(inner_builder, "{sv}",
430 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
432 for (i = 0; i < char_info->flags_length; i++) {
433 g_variant_builder_add(builder2, "s",
434 char_info->char_flags[i]);
437 flags_val = g_variant_new("as", builder2);
438 g_variant_builder_add(inner_builder, "{sv}", "Flags",
442 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
443 g_variant_new("b", notify));
446 unicast = g_strdup("00:00:00:00:00:00");
447 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
448 g_variant_new("s", unicast));
451 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
452 BT_DBG("Adding Descriptors list");
454 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
455 struct gatt_desc_info *desc_info = l4->data;
456 g_variant_builder_add(builder3, "o",
457 desc_info->desc_path);
458 BT_DBG("%s", desc_info->desc_path);
461 char_desc = g_variant_new("ao", builder3);
462 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
465 g_variant_builder_add(char_builder, "{sa{sv}}",
466 GATT_CHAR_INTERFACE , inner_builder);
467 g_variant_builder_add(builder, "{oa{sa{sv}}}",
468 char_info->char_path, char_builder);
470 /*Prepare inner builder for GattDescriptor1 interface*/
472 GSList *l3 = char_info->desc_data;
475 BT_DBG("descriptor data is NULL");
477 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
479 BT_DBG("Creating builder for descriptor \n");
481 GVariantBuilder *desc_builder = NULL;
482 GVariantBuilder *inner_builder = NULL;
483 GVariantBuilder *builder1 = NULL;
484 GVariantBuilder *builder2 = NULL;
485 GVariant *desc_val = NULL;
487 desc_builder = g_variant_builder_new(
490 inner_builder = g_variant_builder_new(
494 struct gatt_desc_info *desc_info = l3->data;
495 if (desc_info == NULL) {
496 BT_ERR("desc_info is NULL");
501 g_variant_builder_add(inner_builder,
503 g_variant_new_string(
504 desc_info->desc_uuid));
507 g_variant_builder_add(inner_builder, "{sv}",
510 char_info->char_path));
513 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
515 if (desc_info->desc_value != NULL) {
516 for (i = 0; i < desc_info->value_length; i++) {
517 g_variant_builder_add(builder1, "y",
518 desc_info->desc_value[i]);
520 desc_val = g_variant_new("ay", builder1);
521 g_variant_builder_add(inner_builder, "{sv}",
526 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
528 for (i = 0; i < desc_info->flags_length; i++) {
529 g_variant_builder_add(builder2, "s",
530 desc_info->desc_flags[i]);
533 flags_val = g_variant_new("as", builder2);
534 g_variant_builder_add(inner_builder, "{sv}", "Flags",
537 g_variant_builder_add(desc_builder, "{sa{sv}}",
541 g_variant_builder_add(builder, "{oa{sa{sv}}}",
542 desc_info->desc_path,
545 /*unref descriptor builder pointers*/
546 g_variant_builder_unref(builder1);
547 g_variant_builder_unref(builder2);
548 g_variant_builder_unref(inner_builder);
549 g_variant_builder_unref(desc_builder);
554 /*unref char builder pointers*/
555 g_variant_builder_unref(builder1);
556 g_variant_builder_unref(builder2);
557 g_variant_builder_unref(builder3);
558 g_variant_builder_unref(inner_builder);
559 g_variant_builder_unref(char_builder);
562 /*unref service builder pointers*/
563 g_variant_builder_unref(inner_builder);
564 g_variant_builder_unref(svc_builder);
567 /* Return builder as method reply */
568 BT_DBG("Sending gatt service builder values to Bluez");
569 g_dbus_method_invocation_return_value(invocation,
576 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
580 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
581 struct gatt_service_info *serv_info = l1->data;
583 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
584 struct gatt_char_info *char_info = l2->data;
586 if (g_strcmp0(char_info->char_path, char_path)
591 BT_ERR("Gatt service not found");
595 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
597 GSList *l1, *l2, *l3;
599 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
600 struct gatt_service_info *serv_info = l1->data;
602 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
603 struct gatt_char_info *char_info = l2->data;
605 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
606 struct gatt_desc_info *desc_info = l3->data;
608 if (g_strcmp0(desc_info->desc_path, desc_path)
614 BT_ERR("Gatt service not found");
618 static void __bt_gatt_char_method_call(GDBusConnection *connection,
620 const gchar *object_path,
621 const gchar *interface_name,
622 const gchar *method_name,
623 GVariant *parameters,
624 GDBusMethodInvocation *invocation,
628 if (g_strcmp0(method_name, "ReadValue") == 0) {
632 bt_gatt_read_req_t read_req = {0, };
633 bt_user_info_t *user_info = NULL;
634 struct gatt_req_info *req_info = NULL;
635 struct gatt_service_info *svc_info = NULL;
639 g_variant_get(parameters, "(&syq)", &addr, &req_id, &offset);
641 BT_DBG("Application path = %s", object_path);
643 BT_DBG("Remote Device address number = %s", addr);
644 BT_DBG("Request id = %d, Offset = %d", req_id, offset);
646 BT_DBG("Sender = %s", sender);
648 read_req.att_handle = g_strdup(object_path);
649 read_req.address = g_strdup(addr);
650 read_req.req_id = req_id;
651 read_req.offset = offset;
652 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
653 if (svc_info != NULL) {
654 read_req.service_handle = g_strdup(svc_info->serv_path);
655 user_info = _bt_get_user_data(BT_COMMON);
657 GVariant *param = NULL;
660 /* Store requets information */
661 req_info = g_new0(struct gatt_req_info, 1);
662 req_info->attr_path = g_strdup(object_path);
663 req_info->svc_path = g_strdup(read_req.service_handle);
664 req_info->request_id = req_id;
665 req_info->offset = offset;
666 req_info->context = invocation;
667 gatt_requests = g_slist_append(gatt_requests, req_info);
669 if (user_info != NULL) {
671 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
672 BLUETOOTH_ERROR_NONE, &read_req,
673 user_info->cb, user_info->user_data);
676 param = g_variant_new("(sssyq)",
678 read_req.service_handle,
682 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
686 if (read_req.att_handle)
687 g_free(read_req.att_handle);
688 if (read_req.address)
689 g_free(read_req.address);
690 if (read_req.service_handle)
691 g_free(read_req.service_handle);
693 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
694 GVariant *var = NULL;
698 bt_gatt_value_change_t value_change = {0, };
699 bt_user_info_t *user_info = NULL;
701 struct gatt_service_info *svc_info = NULL;
702 struct gatt_req_info *req_info = NULL;
704 GVariant *param = NULL;
707 BT_DBG("WriteValue");
708 BT_DBG("Application path = %s", object_path);
709 BT_DBG("Sender = %s", sender);
711 g_variant_get(parameters, "(&syq@ay)", &addr, &req_id, &offset, &var);
713 value_change.att_handle = g_strdup(object_path);
714 value_change.address = g_strdup(addr);
715 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
716 if (svc_info == NULL) {
717 g_variant_unref(var);
718 g_dbus_method_invocation_return_value(invocation, NULL);
722 value_change.service_handle = g_strdup(svc_info->serv_path);
723 value_change.offset = offset;
724 value_change.req_id = req_id;
726 len = g_variant_get_size(var);
730 value_change.att_value = (guint8 *)malloc(len);
731 if (!value_change.att_value) {
732 BT_ERR("att_value is NULL");
733 g_variant_unref(var);
734 g_dbus_method_invocation_return_value(invocation, NULL);
738 data = (char *)g_variant_get_data(var);
739 memcpy(value_change.att_value, data, len);
742 value_change.val_len = len;
744 /* Store requets information */
745 req_info = g_new0(struct gatt_req_info, 1);
746 req_info->attr_path = g_strdup(object_path);
747 req_info->svc_path = g_strdup(value_change.service_handle);
748 req_info->request_id = req_id;
749 req_info->offset = offset;
750 req_info->context = invocation;
751 gatt_requests = g_slist_append(gatt_requests, req_info);
753 user_info = _bt_get_user_data(BT_COMMON);
754 if (user_info != NULL) {
756 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
757 BLUETOOTH_ERROR_NONE, &value_change,
758 user_info->cb, user_info->user_data);
763 svc_path = g_strdup(svc_info->serv_path);
764 param = g_variant_new("(sssyq@ay)",
771 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
776 g_variant_unref(var);
778 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
779 bt_user_info_t *user_info = NULL;
780 bt_gatt_char_notify_change_t notify_change = {0, };
781 BT_DBG("StartNotify");
782 user_info = _bt_get_user_data(BT_COMMON);
783 if (user_info != NULL) {
784 struct gatt_service_info *svc_info = NULL;
785 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
787 notify_change.service_handle = g_strdup(svc_info->serv_path);
788 notify_change.att_handle = g_strdup(object_path);
789 notify_change.att_notify = TRUE;
791 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
792 BLUETOOTH_ERROR_NONE, ¬ify_change,
793 user_info->cb, user_info->user_data);
796 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
797 bt_user_info_t *user_info = NULL;
798 bt_gatt_char_notify_change_t notify_change = {0, };
799 BT_DBG("StopNotify");
800 user_info = _bt_get_user_data(BT_COMMON);
801 if (user_info != NULL) {
802 struct gatt_service_info *svc_info = NULL;
803 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
805 notify_change.service_handle = g_strdup(svc_info->serv_path);
806 notify_change.att_handle = g_strdup(object_path);
807 notify_change.att_notify = FALSE;
809 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
810 BLUETOOTH_ERROR_NONE, ¬ify_change,
811 user_info->cb, user_info->user_data);
814 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
816 bt_gatt_indicate_confirm_t confirm = {0, };
817 bt_user_info_t *user_info = NULL;
818 gboolean complete = 0;
819 struct gatt_service_info *svc_info = NULL;
821 BT_DBG("IndicateConfirm");
822 BT_DBG("Application path = %s", object_path);
823 BT_DBG("Sender = %s", sender);
825 g_variant_get(parameters, "(&sb)", &addr, &complete);
827 BT_DBG("Remote Device address number = %s", addr);
828 confirm.att_handle = g_strdup(object_path);
829 confirm.address = g_strdup(addr);
830 confirm.complete = complete;
832 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
833 if (svc_info != NULL) {
834 confirm.service_handle = g_strdup(svc_info->serv_path);
835 user_info = _bt_get_user_data(BT_COMMON);
837 if (user_info != NULL) {
839 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
840 BLUETOOTH_ERROR_NONE, &confirm,
841 user_info->cb, user_info->user_data);
845 g_dbus_method_invocation_return_value(invocation, NULL);
848 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
850 const gchar *object_path,
851 const gchar *interface_name,
852 const gchar *method_name,
853 GVariant *parameters,
854 GDBusMethodInvocation *invocation,
857 if (g_strcmp0(method_name, "ReadValue") == 0) {
861 bt_gatt_read_req_t read_req = {0, };
862 bt_user_info_t *user_info = NULL;
863 struct gatt_req_info *req_info = NULL;
864 struct gatt_service_info *svc_info = NULL;
867 g_variant_get(parameters, "(&syq)", &addr, &req_id, &offset);
869 BT_DBG("Application path = %s", object_path);
871 BT_DBG("Remote Device address number = %s", addr);
872 BT_DBG("Request id = %d, Offset = %d", req_id, offset);
874 BT_DBG("Sender = %s", sender);
876 read_req.att_handle = g_strdup(object_path);
877 read_req.address = g_strdup(addr);
878 read_req.req_id = req_id;
879 read_req.offset = offset;
880 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
881 if (svc_info != NULL) {
882 read_req.service_handle = g_strdup(svc_info->serv_path);
883 user_info = _bt_get_user_data(BT_COMMON);
885 /* Store requets information */
886 req_info = g_new0(struct gatt_req_info, 1);
887 req_info->attr_path = g_strdup(object_path);
888 req_info->svc_path = g_strdup(read_req.service_handle);
889 req_info->request_id = req_id;
890 req_info->offset = offset;
891 req_info->context = invocation;
892 gatt_requests = g_slist_append(gatt_requests, req_info);
894 if (user_info != NULL) {
896 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
897 BLUETOOTH_ERROR_NONE, &read_req,
898 user_info->cb, user_info->user_data);
902 if (read_req.att_handle)
903 g_free(read_req.att_handle);
904 if (read_req.address)
905 g_free(read_req.address);
906 if (read_req.service_handle)
907 g_free(read_req.service_handle);
910 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
911 GVariant *var = NULL;
915 bt_gatt_value_change_t value_change = {0, };
916 bt_user_info_t *user_info = NULL;
918 struct gatt_service_info *svc_info = NULL;
919 struct gatt_req_info *req_info = NULL;
921 BT_DBG("WriteValue");
922 BT_DBG("Application path = %s", object_path);
923 BT_DBG("Sender = %s", sender);
925 g_variant_get(parameters, "(&syq@ay)", &addr, &req_id, &offset, &var);
927 value_change.att_handle = g_strdup(object_path);
928 value_change.address = g_strdup(addr);
929 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
930 if (svc_info == NULL) {
931 g_variant_unref(var);
932 g_dbus_method_invocation_return_value(invocation, NULL);
936 value_change.service_handle = g_strdup(svc_info->serv_path);
937 value_change.offset = offset;
938 value_change.req_id = req_id;
940 len = g_variant_get_size(var);
944 value_change.att_value = (guint8 *)malloc(len);
945 if (!value_change.att_value) {
946 BT_ERR("att_value is NULL");
947 g_variant_unref(var);
948 g_dbus_method_invocation_return_value(invocation, NULL);
951 data = (char *)g_variant_get_data(var);
952 memcpy(value_change.att_value, data, len);
954 g_variant_unref(var);
956 value_change.val_len = len;
958 /* Store requets information */
959 req_info = g_new0(struct gatt_req_info, 1);
960 req_info->attr_path = g_strdup(object_path);
961 req_info->svc_path = g_strdup(value_change.service_handle);
962 req_info->request_id = req_id;
963 req_info->offset = offset;
964 req_info->context = invocation;
965 gatt_requests = g_slist_append(gatt_requests, req_info);
967 user_info = _bt_get_user_data(BT_COMMON);
968 if (user_info != NULL) {
970 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
971 BLUETOOTH_ERROR_NONE, &value_change,
972 user_info->cb, user_info->user_data);
976 g_dbus_method_invocation_return_value(invocation, NULL);
979 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
982 GError *error = NULL;
983 GVariantBuilder *array_builder;
985 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
986 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
987 g_variant_builder_add(array_builder, "s", interface);
989 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
990 "org.freedesktop.Dbus.Objectmanager",
992 g_variant_new("(oas)",
993 object_path, array_builder),
998 /* dbus gives error cause */
999 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1000 error->code, error->message);
1001 g_clear_error(&error);
1004 g_variant_builder_unref(array_builder);
1009 static const GDBusInterfaceVTable desc_interface_vtable = {
1010 __bt_gatt_desc_method_call,
1015 static const GDBusInterfaceVTable char_interface_vtable = {
1016 __bt_gatt_char_method_call,
1021 static const GDBusInterfaceVTable serv_interface_vtable = {
1027 static const GDBusInterfaceVTable manager_interface_vtable = {
1028 __bt_gatt_manager_method_call,
1033 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1034 const gchar *introspection_data)
1038 if (introspection_data == NULL)
1041 if (obj_info == NULL) {
1042 BT_DBG("Create new node info");
1043 obj_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1046 BT_ERR("Unable to create node: %s", err->message);
1047 g_clear_error(&err);
1055 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1056 const char *service_path)
1060 for (l = gatt_services; l != NULL; l = l->next) {
1061 struct gatt_service_info *info = l->data;
1063 if (g_strcmp0(info->serv_path, service_path) == 0)
1066 BT_ERR("Gatt service not found");
1070 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1071 const char *service_path, const char *char_path)
1075 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1076 struct gatt_service_info *serv_info = l1->data;
1078 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1080 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1081 struct gatt_char_info *char_info = l2->data;
1083 if (g_strcmp0(char_info->char_path, char_path)
1087 BT_ERR("Gatt characteristic not found");
1091 BT_ERR("Gatt service not found");
1095 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1096 const char *serv_path, const char *char_path,
1097 const char *desc_path)
1099 GSList *l1, *l2, *l3;
1101 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1102 struct gatt_service_info *serv_info = l1->data;
1104 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1105 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1106 struct gatt_char_info *char_info = l2->data;
1108 if (g_strcmp0(char_info->char_path, char_path)
1110 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1111 struct gatt_desc_info *desc_info = l3->data;
1112 if (g_strcmp0(desc_info->desc_path,
1121 BT_ERR("Gatt descriptor not found");
1125 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1129 for (l = gatt_requests; l != NULL; l = l->next) {
1130 struct gatt_req_info *req_info = l->data;
1132 if (req_info && req_info->request_id == request_id) {
1136 BT_ERR("Gatt Request not found");
1140 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1141 const gchar *path, const gchar *interface)
1147 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1152 BT_ERR("Unable to connect to gdbus: %s", err->message);
1153 g_clear_error(&err);
1158 proxy = g_dbus_proxy_new_sync(g_conn,
1159 G_DBUS_PROXY_FLAGS_NONE, NULL,
1161 interface, NULL, &err);
1165 BT_ERR("Unable to create proxy: %s", err->message);
1166 g_clear_error(&err);
1170 manager_gproxy = proxy;
1175 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1176 const gchar *path, const gchar *interface)
1178 return (manager_gproxy) ? manager_gproxy :
1179 __bt_gatt_gdbus_init_manager_proxy(service,
1183 int bluetooth_gatt_convert_prop2string(
1184 bt_gatt_characteristic_property_t properties,
1185 char *char_properties[])
1189 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
1190 char_properties[flag_count] = g_strdup("broadcast");
1193 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
1194 char_properties[flag_count] = g_strdup("read");
1197 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
1198 char_properties[flag_count] = g_strdup("write-without-response");
1201 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
1202 char_properties[flag_count] = g_strdup("write");
1205 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
1206 char_properties[flag_count] = g_strdup("notify");
1209 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
1210 char_properties[flag_count] = g_strdup("indicate");
1213 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
1214 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
1217 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
1218 char_properties[flag_count] = g_strdup("reliable-write");
1221 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
1222 char_properties[flag_count] = g_strdup("writable-auxiliaries");
1225 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
1226 char_properties[flag_count] = g_strdup("encrypt-read");
1229 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
1230 char_properties[flag_count] = g_strdup("encrypt-write");
1233 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
1234 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1237 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
1238 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1242 if (flag_count == 0) {
1243 char_properties[flag_count] = g_strdup("read");
1250 int bluetooth_gatt_convert_perm2string(
1251 bt_gatt_permission_t properties,
1252 char *char_properties[])
1256 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
1257 char_properties[flag_count] = g_strdup("read");
1260 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
1261 char_properties[flag_count] = g_strdup("write");
1264 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
1265 char_properties[flag_count] = g_strdup("encrypt-read");
1268 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
1269 char_properties[flag_count] = g_strdup("encrypt-write");
1272 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
1273 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1276 if (properties & BLUETOOTH_GATT_PERMISSION_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 static void __bt_gatt_set_service_state(const char *service_path,
1292 struct gatt_service_info *svc_info = NULL;
1293 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1295 if (svc_info != NULL) {
1296 BT_DBG("Updating the gatt service register state %d", state);
1297 svc_info->is_svc_registered = state;
1301 BT_DBG("gatt service not found");
1304 static gboolean __bt_gatt_get_service_state(const char *service_path)
1306 struct gatt_service_info *svc_info = NULL;
1308 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1310 if (svc_info != NULL) {
1311 BT_DBG("Return the state of the gatt service %d",
1312 svc_info->is_svc_registered);
1313 return svc_info->is_svc_registered;
1316 BT_DBG("gatt service info is NULL");
1320 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1322 GError *error = NULL;
1324 GVariantIter *iter = NULL;
1325 const gchar *key = NULL;
1326 GVariant *value = NULL;
1327 const gchar *service = NULL;
1328 const gchar *characteristic = NULL;
1329 const gchar *descriptor = NULL;
1333 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1335 if (result == NULL) {
1336 /* dBUS-RPC is failed */
1337 BT_ERR("Dbus-RPC is failed\n");
1339 if (error != NULL) {
1340 /* dBUS gives error cause */
1341 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1342 error->code, error->message);
1343 g_clear_error(&error);
1346 char *char_cmp = NULL;
1347 g_variant_get(result, "(a{sv})", &iter);
1348 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1350 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1351 if (g_strcmp0(key, "Service") == 0) {
1352 service = g_variant_get_string(value, NULL);
1353 BT_DBG("Service %s", service);
1354 } else if (g_strcmp0(key, char_cmp) == 0) {
1355 characteristic = g_variant_get_string(value, NULL);
1357 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1358 BT_DBG("%s", characteristic);
1359 } else if (g_strcmp0(key, "Descriptor") == 0) {
1360 descriptor = g_variant_get_string(value, NULL);
1361 BT_DBG("Descriptor %s", descriptor);
1364 g_variant_iter_free(iter);
1366 /* TODO: Store the service informationa and
1367 * Send respponse to CAPI layer. */
1369 g_variant_unref(result);
1374 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1376 BT_INFO("RegisterApplication is completed");
1378 GError *error = NULL;
1381 register_pending_cnt = 0;
1383 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1385 if (result == NULL) {
1386 /* dBUS-RPC is failed */
1387 BT_ERR("Dbus-RPC is failed\n");
1389 if (error != NULL) {
1390 /* dBUS gives error cause */
1391 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1392 error->code, error->message);
1393 g_clear_error(&error);
1398 void unregister_application_cb(GObject *object, GAsyncResult *res,
1401 BT_INFO("UnregisterApplication is completed");
1403 GError *error = NULL;
1406 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1408 if (result == NULL) {
1409 /* dBUS-RPC is failed */
1410 BT_ERR("Dbus-RPC is failed\n");
1412 if (error != NULL) {
1413 /* dBUS gives error cause */
1414 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1415 error->code, error->message);
1416 g_clear_error(&error);
1421 static int __bt_gatt_unregister_service(const char *service_path)
1423 if (!__bt_gatt_get_service_state(service_path)) {
1424 BT_DBG("service not registered \n");
1425 return BLUETOOTH_ERROR_NOT_FOUND;
1428 return BLUETOOTH_ERROR_NONE;
1431 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1433 GDBusProxy *proxy = NULL;
1435 if (is_server_started) {
1436 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1437 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1439 if (proxy == NULL || app_path == NULL)
1440 return BLUETOOTH_ERROR_INTERNAL;
1442 BT_INFO("UnregisterApplication");
1444 /* Async Call to Unregister Service */
1445 g_dbus_proxy_call(proxy,
1446 "UnregisterApplication",
1447 g_variant_new("(o)",
1449 G_DBUS_CALL_FLAGS_NONE, -1,
1451 (GAsyncReadyCallback) unregister_application_cb,
1454 is_server_started = false;
1455 return BLUETOOTH_ERROR_NONE;
1458 BT_INFO("GATT server not started");
1459 return BLUETOOTH_ERROR_NONE;
1462 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1464 GDBusConnection *local_system_gconn = NULL;
1468 if (g_conn == NULL) {
1469 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1470 if (address == NULL) {
1472 BT_ERR("Failed to get bus address: %s", err->message);
1473 g_clear_error(&err);
1478 g_conn = g_dbus_connection_new_for_address_sync(address,
1479 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1480 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1481 NULL, /* GDBusAuthObserver */
1486 BT_ERR("Unable to connect to dbus: %s", err->message);
1487 g_clear_error(&err);
1491 } else if (g_dbus_connection_is_closed(g_conn)) {
1492 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1493 if (address == NULL) {
1495 BT_ERR("Failed to get bus address: %s", err->message);
1496 g_clear_error(&err);
1501 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1502 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1503 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1504 NULL, /* GDBusAuthObserver */
1508 if (!local_system_gconn) {
1509 BT_ERR("Unable to connect to dbus: %s", err->message);
1510 g_clear_error(&err);
1513 g_conn = local_system_gconn;
1519 BT_EXPORT_API int bluetooth_gatt_init(void)
1521 GDBusConnection *conn;
1522 GError *error = NULL;
1523 GDBusNodeInfo *node_info = NULL;
1525 if (app_path != NULL) {
1526 BT_ERR("app path already exists! initialized");
1527 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1530 if (owner_id == 0) {
1531 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1532 BT_GATT_SERVICE_NAME,
1533 G_BUS_NAME_OWNER_FLAGS_NONE,
1534 NULL, NULL, NULL, NULL, NULL);
1537 BT_DBG("owner_id is [%d]", owner_id);
1538 app_path = g_strdup_printf("/com/%d", getpid());
1542 conn = __bt_gatt_get_gdbus_connection();
1544 BT_ERR("Unable to get connection");
1548 /* Register ObjectManager interface */
1549 node_info = __bt_gatt_create_method_node_info(
1550 manager_introspection_xml);
1552 if (node_info == NULL) {
1553 BT_ERR("failed to get node info");
1557 if (manager_id == 0) {
1558 BT_INFO("manager_id does not exists");
1560 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1561 node_info->interfaces[0],
1562 &manager_interface_vtable,
1563 NULL, NULL, &error);
1566 if (manager_id == 0) {
1567 BT_ERR("failed to register: %s", error->message);
1568 g_error_free(error);
1572 return BLUETOOTH_ERROR_NONE;
1576 g_dbus_node_info_unref(obj_info);
1579 g_bus_unown_name(owner_id);
1587 __bt_gatt_close_gdbus_connection();
1589 return BLUETOOTH_ERROR_INTERNAL;
1592 BT_EXPORT_API int bluetooth_gatt_deinit()
1594 int ret = BLUETOOTH_ERROR_NONE;
1595 /* Unown gdbus bus */
1597 /* remove/unregister all services */
1598 BT_DBG("removing all registered gatt service\n");
1599 bluetooth_gatt_delete_services();
1601 /* unregister the exported interface for object manager */
1602 g_dbus_connection_unregister_object(g_conn,
1607 ret = bluetooth_gatt_unregister_application();
1608 if (ret != BLUETOOTH_ERROR_NONE)
1609 BT_ERR("Fail to unregister application\n");
1611 g_bus_unown_name(owner_id);
1617 BT_DBG("Gatt service deinitialized \n");
1619 g_slist_free(gatt_services);
1620 gatt_services = NULL;
1622 g_object_unref(manager_gproxy);
1623 manager_gproxy = NULL;
1625 /* Temperary block under codes to avoid TC blocking issue.
1626 But we should unref node info in later. */
1628 g_dbus_node_info_unref(obj_info);
1631 __bt_gatt_close_gdbus_connection();
1636 __bt_gatt_close_gdbus_connection();
1638 return BLUETOOTH_ERROR_NOT_FOUND;
1641 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1644 GError *error = NULL;
1646 GDBusNodeInfo *node_info;
1648 GVariantBuilder *builder = NULL;
1649 GVariantBuilder *builder1 = NULL;
1650 GVariantBuilder *inner_builder = NULL;
1651 gboolean svc_primary = TRUE;
1652 struct gatt_service_info *serv_info = NULL;
1654 node_info = __bt_gatt_create_method_node_info(
1655 service_introspection_xml);
1657 if (node_info == NULL)
1658 return BLUETOOTH_ERROR_INTERNAL;
1660 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1661 BT_DBG("gatt service path is [%s]", path);
1663 object_id = g_dbus_connection_register_object(g_conn, path,
1664 node_info->interfaces[0],
1665 &serv_interface_vtable,
1666 NULL, NULL, &error);
1668 if (object_id == 0) {
1669 BT_ERR("failed to register: %s", error->message);
1670 g_error_free(error);
1673 return BLUETOOTH_ERROR_INTERNAL;
1676 /* Add object_id/gatt service information; it's required at the time of
1677 * service unregister and Getmanagedobjects
1679 serv_info = g_new0(struct gatt_service_info, 1);
1681 serv_info->serv_path = g_strdup(path);
1682 serv_info->serv_id = object_id;
1683 serv_info->service_uuid = g_strdup(svc_uuid);
1684 serv_info->is_svc_registered = FALSE;
1685 serv_info->is_svc_primary = svc_primary;
1687 gatt_services = g_slist_append(gatt_services, serv_info);
1689 /* emit interfacesadded signal here for service path */
1690 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1691 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1693 g_variant_builder_add(inner_builder, "{sv}",
1694 "UUID", g_variant_new_string(svc_uuid));
1696 g_variant_builder_add(inner_builder, "{sv}",
1697 "Primary", g_variant_new_boolean(svc_primary));
1699 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1701 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1702 g_variant_new("ao", builder1));
1704 g_variant_builder_add(builder, "{sa{sv}}",
1705 GATT_SERV_INTERFACE, inner_builder);
1707 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1708 "org.freedesktop.Dbus.ObjectManager",
1710 g_variant_new("(oa{sa{sv}})",
1716 *svc_path = g_strdup(path);
1719 g_variant_builder_unref(inner_builder);
1720 g_variant_builder_unref(builder);
1721 g_variant_builder_unref(builder1);
1723 return BLUETOOTH_ERROR_NONE;
1726 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1727 const char *svc_path, const char *char_uuid,
1728 bt_gatt_permission_t permissions,
1729 bt_gatt_characteristic_property_t properties,
1733 GError *error = NULL;
1735 GDBusNodeInfo *node_info;
1737 GVariantBuilder *builder = NULL;
1738 GVariantBuilder *inner_builder = NULL;
1739 struct gatt_service_info *serv_info = NULL;
1740 struct gatt_char_info *char_info = NULL;
1741 GVariantBuilder *builder2 = NULL;
1742 GVariantBuilder *builder3 = NULL;
1743 GVariant *flags_val = NULL;
1745 char *char_flags[NUMBER_OF_FLAGS];
1750 new_service = FALSE;
1753 BT_DBG("gatt svc_path path is [%s]", svc_path);
1754 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1755 if (serv_info == NULL)
1756 return BLUETOOTH_ERROR_INVALID_PARAM;
1758 node_info = __bt_gatt_create_method_node_info(
1759 characteristics_introspection_xml);
1761 if (node_info == NULL)
1762 return BLUETOOTH_ERROR_INTERNAL;
1764 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1765 BT_DBG("gatt characteristic path is [%s]", path);
1767 object_id = g_dbus_connection_register_object(g_conn, path,
1768 node_info->interfaces[0],
1769 &char_interface_vtable,
1770 NULL, NULL, &error);
1772 if (object_id == 0) {
1773 BT_ERR("failed to register: %s", error->message);
1774 g_error_free(error);
1777 return BLUETOOTH_ERROR_INTERNAL;
1780 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1781 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1782 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1783 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1784 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1785 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1786 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1787 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1789 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1791 char_info = g_new0(struct gatt_char_info, 1);
1793 char_info->char_path = g_strdup(path);
1794 char_info->char_id = object_id;
1795 char_info->char_uuid = g_strdup(char_uuid);
1797 for (i = 0; i < flag_count; i++) {
1798 char_info->char_flags[i] = char_flags[i];
1801 char_info->flags_length = flag_count;
1803 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1805 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1806 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1808 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1809 g_variant_new("s", char_uuid));
1810 g_variant_builder_add(inner_builder, "{sv}", "Service",
1811 g_variant_new("o", svc_path));
1813 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1815 for (i = 0; i < flag_count; i++) {
1816 g_variant_builder_add(builder2, "s", char_flags[i]);
1819 flags_val = g_variant_new("as", builder2);
1820 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1823 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1825 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1826 g_variant_new("ao", builder3));
1828 g_variant_builder_add(builder, "{sa{sv}}",
1829 GATT_CHAR_INTERFACE,
1832 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1833 "org.freedesktop.Dbus.ObjectManager",
1835 g_variant_new("(oa{sa{sv}})",
1839 *char_path = g_strdup(path);
1845 g_variant_builder_unref(inner_builder);
1846 g_variant_builder_unref(builder);
1847 g_variant_builder_unref(builder2);
1848 g_variant_builder_unref(builder3);
1850 return BLUETOOTH_ERROR_NONE;
1853 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1854 const char *characteristic, const char *char_value,
1857 gchar **line_argv = NULL;
1858 char *serv_path = NULL;
1859 struct gatt_char_info *char_info = NULL;
1860 GVariantBuilder *builder1 = NULL;
1861 GVariantBuilder *builder = NULL;
1862 GVariantBuilder *inner_builder = NULL;
1863 GVariant *char_val = NULL;
1864 GError *error = NULL;
1866 int res = BLUETOOTH_ERROR_NONE;
1868 line_argv = g_strsplit_set(characteristic, "/", 0);
1869 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1871 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
1873 if (char_info == NULL) {
1874 /* Fix : RESOURCE_LEAK */
1875 res = BLUETOOTH_ERROR_INVALID_PARAM;
1879 char_info->value_length = value_length;
1881 char_info->char_value = (char *)malloc(value_length);
1882 /* Fix : NULL_RETURNS */
1883 if (char_info->char_value == NULL) {
1884 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1888 for (i = 0; i < value_length; i++)
1889 char_info->char_value[i] = char_value[i];
1891 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1892 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1894 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1896 for (i = 0; i < value_length; i++) {
1897 g_variant_builder_add(builder1, "y", char_value[i]);
1900 char_val = g_variant_new("ay", builder1);
1901 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
1903 g_variant_builder_add(builder, "{sa{sv}}",
1904 GATT_CHAR_INTERFACE,
1907 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1908 "org.freedesktop.Dbus.ObjectManager",
1910 g_variant_new("(oa{sa{sv}})",
1911 char_info->char_path, builder),
1914 g_variant_builder_unref(inner_builder);
1915 g_variant_builder_unref(builder);
1916 g_variant_builder_unref(builder1);
1918 g_strfreev(line_argv);
1924 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
1925 const char *char_path, const char *desc_uuid,
1926 bt_gatt_permission_t permissions,
1929 static int desc_id = 1;
1930 GError *error = NULL;
1932 GDBusNodeInfo *node_info;
1934 GVariantBuilder *builder = NULL;
1935 GVariantBuilder *inner_builder = NULL;
1936 struct gatt_char_info *char_info = NULL;
1937 struct gatt_desc_info *desc_info = NULL;
1938 gchar **line_argv = NULL;
1940 GVariantBuilder *builder2 = NULL;
1941 GVariant *flags_val = NULL;
1943 char *desc_flags[NUMBER_OF_FLAGS];
1951 line_argv = g_strsplit_set(char_path, "/", 0);
1952 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
1954 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
1955 if (char_info == NULL) {
1956 g_strfreev(line_argv);
1957 return BLUETOOTH_ERROR_INVALID_PARAM;
1960 node_info = __bt_gatt_create_method_node_info(
1961 descriptor_introspection_xml);
1963 if (node_info == NULL) {
1964 g_strfreev(line_argv);
1965 return BLUETOOTH_ERROR_INTERNAL;
1968 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
1969 BT_DBG("gatt descriptor path is [%s]", path);
1971 object_id = g_dbus_connection_register_object(g_conn, path,
1972 node_info->interfaces[0],
1973 &desc_interface_vtable,
1974 NULL, NULL, &error);
1976 if (object_id == 0) {
1977 BT_ERR("failed to register: %s", error->message);
1978 g_error_free(error);
1980 g_strfreev(line_argv);
1982 return BLUETOOTH_ERROR_INTERNAL;
1985 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
1987 desc_info = g_new0(struct gatt_desc_info, 1);
1989 desc_info->desc_path = g_strdup(path);
1990 desc_info->desc_id = object_id;
1991 desc_info->desc_uuid = g_strdup(desc_uuid);
1993 for (i = 0; i < flag_count; i++) {
1994 desc_info->desc_flags[i] = desc_flags[i];
1997 desc_info->flags_length = flag_count;
1999 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2001 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2002 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2004 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2005 g_variant_new("s", desc_uuid));
2006 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2007 g_variant_new("o", char_path));
2009 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2011 for (i = 0; i < flag_count; i++) {
2012 g_variant_builder_add(builder2, "s", desc_flags[i]);
2015 flags_val = g_variant_new("as", builder2);
2016 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2019 g_variant_builder_add(builder, "{sa{sv}}",
2020 GATT_DESC_INTERFACE,
2023 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2024 "org.freedesktop.Dbus.ObjectManager",
2026 g_variant_new("(oa{sa{sv}})",
2030 *desc_path = g_strdup(path);
2033 g_strfreev(line_argv);
2034 g_variant_builder_unref(inner_builder);
2035 g_variant_builder_unref(builder);
2037 return BLUETOOTH_ERROR_NONE;
2040 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2041 const char *desc_path, const char *desc_value,
2044 GError *error = NULL;
2045 GVariantBuilder *builder = NULL;
2046 GVariantBuilder *inner_builder = NULL;
2047 GVariantBuilder *builder1 = NULL;
2048 struct gatt_desc_info *desc_info = NULL;
2049 gchar **line_argv = NULL;
2051 GVariant *desc_val = NULL;
2052 char *serv_path = NULL;
2055 line_argv = g_strsplit_set(desc_path, "/", 0);
2056 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2057 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2059 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2061 /* Free the allocated memory */
2062 g_strfreev(line_argv);
2066 /* Fix : NULL_RETURNS */
2067 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2069 desc_info->desc_value = (char *)malloc(value_length);
2071 /* Fix : NULL_RETURNS */
2072 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2074 for (i = 0; i < value_length; i++)
2075 desc_info->desc_value[i] = desc_value[i];
2077 desc_info->value_length = value_length;
2079 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2080 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2082 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2084 for (i = 0; i < value_length; i++) {
2085 g_variant_builder_add(builder1, "y", desc_value[i]);
2087 desc_val = g_variant_new("ay", builder1);
2088 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2090 g_variant_builder_add(builder, "{sa{sv}}",
2091 GATT_DESC_INTERFACE,
2094 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2095 "org.freedesktop.Dbus.ObjectManager",
2097 g_variant_new("(oa{sa{sv}})",
2098 desc_info->desc_path, builder),
2101 g_variant_builder_unref(inner_builder);
2102 g_variant_builder_unref(builder);
2103 g_variant_builder_unref(builder1);
2105 return BLUETOOTH_ERROR_NONE;
2108 int bluetooth_gatt_get_service(const char *svc_uuid)
2110 GDBusProxy *proxy = NULL;
2113 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2114 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2116 return BLUETOOTH_ERROR_INTERNAL;
2118 uuid = g_strdup(svc_uuid);
2120 g_dbus_proxy_call(proxy,
2122 g_variant_new("(s)",
2124 G_DBUS_CALL_FLAGS_NONE, -1,
2126 (GAsyncReadyCallback) get_service_cb,
2131 return BLUETOOTH_ERROR_NONE;
2134 BT_EXPORT_API int bluetooth_gatt_register_service(
2135 const char *svc_path)
2137 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2138 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2139 BT_ERR("Don't have aprivilege to use this API");
2140 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2143 register_pending_cnt++;
2145 if (__bt_gatt_get_service_state(svc_path)) {
2146 BT_DBG("service already registered \n");
2147 return BLUETOOTH_ERROR_NONE;
2150 __bt_gatt_set_service_state(svc_path, TRUE);
2152 return BLUETOOTH_ERROR_NONE;
2155 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2157 GDBusProxy *proxy = NULL;
2159 if (!is_server_started) {
2161 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2162 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2163 BT_ERR("Don't have aprivilege to use this API");
2164 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2167 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2168 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2169 if (proxy == NULL || app_path == NULL)
2170 return BLUETOOTH_ERROR_INTERNAL;
2172 BT_INFO("RegisterApplication");
2174 g_dbus_proxy_call(proxy,
2175 "RegisterApplication",
2176 g_variant_new("(oa{sv})",
2178 G_DBUS_CALL_FLAGS_NONE, -1,
2180 (GAsyncReadyCallback) register_application_cb,
2183 is_server_started = true;
2185 return BLUETOOTH_ERROR_NONE;
2188 BT_INFO("Already RegisterApplication");
2190 return BLUETOOTH_ERROR_NONE;
2193 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2196 int error = BLUETOOTH_ERROR_NONE;
2200 for (l = gatt_services; l != NULL; l = l->next) {
2201 struct gatt_service_info *info = l->data;
2202 BT_DBG("svc_path is %s", info->serv_path);
2203 if (bluetooth_gatt_unregister_service(info->serv_path)
2204 != BLUETOOTH_ERROR_NONE) {
2205 error = BLUETOOTH_ERROR_INTERNAL;
2206 BT_DBG(" Error in removing service %s \n",
2210 BT_DBG(" All services removed successfully.\n ");
2212 BT_DBG(" There are no registered services.\n ");
2215 g_slist_free(gatt_services);
2216 gatt_services = NULL;
2219 if (error != BLUETOOTH_ERROR_NONE)
2222 return BLUETOOTH_ERROR_NONE;
2225 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2226 const char *char_path, const char* char_value,
2229 GVariantBuilder *outer_builder;
2230 GVariantBuilder *inner_builder;
2231 GVariantBuilder *invalidated_builder;
2232 GVariant *update_value = NULL;
2233 GError *error = NULL;
2234 gboolean ret = FALSE;
2235 int err = BLUETOOTH_ERROR_NONE;
2237 gchar **line_argv = NULL;
2238 gchar *serv_path = NULL;
2240 line_argv = g_strsplit_set(char_path, "/", 0);
2241 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2243 if (!__bt_gatt_get_service_state(serv_path)) {
2244 BT_DBG("service not registered for this characteristic \n");
2245 g_strfreev(line_argv);
2246 return BLUETOOTH_ERROR_INTERNAL;
2249 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2250 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2252 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2253 for (i = 0; i < value_length; i++) {
2254 g_variant_builder_add(inner_builder, "y", char_value[i]);
2257 update_value = g_variant_new("ay", inner_builder);
2259 outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2260 g_variant_builder_add(outer_builder, "{sv}", "Value",
2263 BT_DBG("Updating characteristic value \n");
2264 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2266 "org.freedesktop.DBus.Properties",
2267 "PropertiesChanged",
2268 g_variant_new("(sa{sv}as)",
2269 "org.bluez.GattCharacteristic1",
2270 outer_builder, invalidated_builder),
2274 if (error != NULL) {
2275 BT_ERR("D-Bus API failure: errCode[%x], \
2277 error->code, error->message);
2278 g_clear_error(&error);
2280 err = BLUETOOTH_ERROR_INTERNAL;
2282 struct gatt_char_info *char_info = NULL;
2284 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2285 if (char_info == NULL) {
2286 return BLUETOOTH_ERROR_INVALID_DATA;
2289 char_info->value_length = value_length;
2291 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
2292 if (char_info->char_value) {
2293 for (i = 0; i < value_length; i++) {
2294 char_info->char_value[i] = char_value[i];
2299 g_strfreev(line_argv);
2300 g_variant_builder_unref(inner_builder);
2301 g_variant_builder_unref(outer_builder);
2302 g_variant_builder_unref(invalidated_builder);
2307 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2314 g_free(desc_info->desc_path);
2315 g_free(desc_info->desc_uuid);
2316 g_free(desc_info->desc_value);
2318 for (i = 0; i < desc_info->flags_length; i++)
2319 g_free(desc_info->desc_flags[i]);
2324 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2331 g_free(char_info->char_path);
2332 g_free(char_info->char_uuid);
2333 g_free(char_info->char_value);
2335 for (i = 0; i < char_info->flags_length; i++)
2336 g_free(char_info->char_flags[i]);
2341 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2346 g_free(svc_info->serv_path);
2347 g_free(svc_info->service_uuid);
2351 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2354 struct gatt_service_info *svc_info;
2356 int err = BLUETOOTH_ERROR_NONE;
2358 BT_DBG("svc_path %s", svc_path);
2359 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2362 BT_ERR("Unable to find service info");
2363 return BLUETOOTH_ERROR_NOT_FOUND;
2366 err = __bt_gatt_unregister_service(svc_path);
2367 if (err != BLUETOOTH_ERROR_NONE) {
2368 BT_DBG("Could not unregister application");
2372 for (l = svc_info->char_data; l != NULL; l = l->next) {
2373 struct gatt_char_info *char_info = l->data;
2375 if (char_info == NULL)
2378 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2379 struct gatt_desc_info *desc_info = l1->data;
2381 if (desc_info == NULL)
2384 ret = g_dbus_connection_unregister_object(g_conn,
2385 desc_info->desc_id);
2387 __bt_gatt_emit_interface_removed(
2388 desc_info->desc_path,
2389 GATT_DESC_INTERFACE);
2391 err = BLUETOOTH_ERROR_INTERNAL;
2394 /* list remove & free */
2395 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2396 __bt_gatt_free_descriptor_info(desc_info);
2399 g_slist_free(char_info->desc_data);
2400 char_info->desc_data = NULL;
2402 ret = g_dbus_connection_unregister_object(g_conn,
2403 char_info->char_id);
2405 __bt_gatt_emit_interface_removed(char_info->char_path,
2406 GATT_CHAR_INTERFACE);
2408 err = BLUETOOTH_ERROR_INTERNAL;
2411 /* list remove & free */
2412 svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
2413 __bt_gatt_free_characteristic_info(char_info);
2416 g_slist_free(svc_info->char_data);
2417 svc_info->char_data = NULL;
2419 ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2421 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2422 GATT_SERV_INTERFACE);
2424 err = BLUETOOTH_ERROR_INTERNAL;
2427 ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2429 BT_DBG("Unregistered the service on properties interface");
2432 /* list remove & free */
2433 gatt_services = g_slist_remove(gatt_services, svc_info);
2434 __bt_gatt_free_service_info(svc_info);
2436 new_service = FALSE;
2438 if (gatt_services == NULL) {
2440 } else if (gatt_services->next == NULL) {
2447 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2448 int resp_state, int offset, char *value, int value_length)
2450 struct gatt_req_info *req_info = NULL;
2452 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2453 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2454 BT_ERR("Don't have aprivilege to use this API");
2455 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2458 req_info = __bt_gatt_find_request_info(request_id);
2461 if (resp_state != BLUETOOTH_ERROR_NONE) {
2463 GQuark quark = g_quark_from_string("gatt-server");
2464 GError *err = g_error_new(quark, 0, "Application Error");
2465 g_dbus_method_invocation_return_gerror(req_info->context, err);
2468 gatt_requests = g_slist_remove(gatt_requests, req_info);
2470 req_info->context = NULL;
2471 if (req_info->attr_path)
2472 g_free(req_info->attr_path);
2473 if (req_info->svc_path)
2474 g_free(req_info->svc_path);
2477 return BLUETOOTH_ERROR_NONE;
2479 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2481 GVariantBuilder *inner_builder = NULL;
2482 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2483 if (value_length > 0 && value != NULL) {
2484 for (i = 0; i < value_length; i++)
2485 g_variant_builder_add(inner_builder, "y", value[i]);
2487 g_dbus_method_invocation_return_value(req_info->context,
2488 g_variant_new("(ay)", inner_builder));
2489 g_variant_builder_unref(inner_builder);
2491 g_dbus_method_invocation_return_value(req_info->context, NULL);
2493 gatt_requests = g_slist_remove(gatt_requests, req_info);
2495 req_info->context = NULL;
2496 if (req_info->attr_path)
2497 g_free(req_info->attr_path);
2498 if (req_info->svc_path)
2499 g_free(req_info->svc_path);
2502 return BLUETOOTH_ERROR_INTERNAL;
2505 return BLUETOOTH_ERROR_NONE;
2508 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2509 bluetooth_device_address_t *unicast_address)
2511 GVariantBuilder *outer_builder;
2512 GVariantBuilder *invalidated_builder;
2513 GError *error = NULL;
2514 gboolean notify = TRUE;
2515 gboolean ret = TRUE;
2516 int err = BLUETOOTH_ERROR_NONE;
2517 gchar **line_argv = NULL;
2518 gchar *serv_path = NULL;
2519 char addr[20] = { 0 };
2521 line_argv = g_strsplit_set(char_path, "/", 0);
2522 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2524 if (!__bt_gatt_get_service_state(serv_path)) {
2525 BT_DBG("service not registered for this characteristic \n");
2526 g_strfreev(line_argv);
2527 return BLUETOOTH_ERROR_INTERNAL;
2530 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2531 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2533 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2534 g_variant_new("b", notify));
2536 if (unicast_address) {
2537 _bt_convert_addr_type_to_string(addr,
2538 (unsigned char *)unicast_address->addr);
2540 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2541 g_variant_new("s", addr));
2543 BT_DBG("Set characteristic Notification \n");
2544 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2546 "org.freedesktop.DBus.Properties",
2547 "PropertiesChanged",
2548 g_variant_new("(sa{sv}as)",
2549 "org.bluez.GattCharacteristic1",
2550 outer_builder, invalidated_builder),
2554 if (error != NULL) {
2555 BT_ERR("D-Bus API failure: errCode[%x], \
2557 error->code, error->message);
2558 g_clear_error(&error);
2560 err = BLUETOOTH_ERROR_INTERNAL;
2563 g_strfreev(line_argv);
2564 g_variant_builder_unref(outer_builder);
2565 g_variant_builder_unref(invalidated_builder);