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 #ifdef TIZEN_FEATURE_BT_OTP
202 #define BT_OTP_OBJECT_PATH "/org/projectx/otp"
203 #define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
204 #define PROPERTIES_CHANGED "PropertiesChanged"
205 #define BT_OTP_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
208 static GDBusProxy *manager_gproxy = NULL;
210 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
211 const char *service_path, const char *char_path);
212 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
213 const char *serv_path, const char *char_path,
214 const char *desc_path);
216 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
218 static void __bt_gatt_close_gdbus_connection(void)
224 ret_if(g_conn == NULL);
226 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
227 BT_ERR("Fail to flush the connection: %s", err->message);
232 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
234 BT_ERR("Fail to close the dbus connection: %s", err->message);
239 g_object_unref(g_conn);
246 #ifdef TIZEN_FEATURE_BT_HPS
247 static int __bt_send_event_to_hps(int event, GVariant *var)
249 GError *error = NULL;
250 GVariant *parameters;
251 GDBusMessage *msg = NULL;
255 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
257 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
258 GVariantBuilder *inner_builder;
259 GVariantBuilder *invalidated_builder;
261 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
262 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
264 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
266 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
268 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
269 g_variant_builder_unref(invalidated_builder);
270 g_variant_builder_unref(inner_builder);
271 } else if (BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
272 GVariantBuilder *inner_builder;
273 GVariantBuilder *invalidated_builder;
275 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
276 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
278 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
280 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
282 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
283 g_variant_builder_unref(invalidated_builder);
284 g_variant_builder_unref(inner_builder);
287 msg = g_dbus_message_new_signal(BT_HPS_OBJECT_PATH, BT_HPS_INTERFACE_NAME, PROPERTIES_CHANGED);
288 g_dbus_message_set_body(msg, parameters);
289 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
291 BT_ERR("D-Bus API failure: errCode[%x], \
293 error->code, error->message);
294 g_clear_error(&error);
296 return BLUETOOTH_ERROR_INTERNAL;
298 return BLUETOOTH_ERROR_NONE;
302 #ifdef TIZEN_FEATURE_BT_OTP
303 static int __bt_send_event_to_otp(int event, GVariant *var)
305 GError *error = NULL;
306 GVariant *parameters = NULL;
307 GDBusMessage *msg = NULL;
311 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
313 if (event == BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED) {
314 GVariantBuilder *inner_builder;
315 GVariantBuilder *invalidated_builder;
317 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED");
318 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
320 g_variant_builder_add(inner_builder, "{sv}", "WriteValue", var);
322 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
324 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
325 g_variant_builder_unref(invalidated_builder);
326 g_variant_builder_unref(inner_builder);
327 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED) {
328 GVariantBuilder *inner_builder;
329 GVariantBuilder *invalidated_builder;
331 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED");
332 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
334 g_variant_builder_add(inner_builder, "{sv}", "ReadValue", var);
336 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
338 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
339 g_variant_builder_unref(invalidated_builder);
340 g_variant_builder_unref(inner_builder);
341 } else if (event == BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED) {
342 GVariantBuilder *inner_builder;
343 GVariantBuilder *invalidated_builder;
345 BT_DBG("BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED");
346 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
348 g_variant_builder_add(inner_builder, "{sv}", "NotificationStateChanged", var);
350 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
352 parameters = g_variant_new("(a{sv}as)", inner_builder, invalidated_builder);
353 g_variant_builder_unref(invalidated_builder);
354 g_variant_builder_unref(inner_builder);
357 msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, PROPERTIES_CHANGED);
358 g_dbus_message_set_body(msg, parameters);
359 if (!g_dbus_connection_send_message(g_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
361 BT_ERR("D-Bus API failure: errCode[%x], \
363 error->code, error->message);
364 g_clear_error(&error);
366 return BLUETOOTH_ERROR_INTERNAL;
368 return BLUETOOTH_ERROR_NONE;
372 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
374 const gchar *object_path,
375 const gchar *interface_name,
376 const gchar *method_name,
377 GVariant *parameters,
378 GDBusMethodInvocation *invocation,
385 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
386 BT_DBG("Getting values for service, chars and descriptors");
388 GVariantBuilder *builder;
389 GVariantBuilder *inner_builder1 = NULL;
390 GVariant *svc_char = NULL;
393 builder = g_variant_builder_new(
394 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
396 /* Prepare inner builder for GattService1 interface */
398 len = g_slist_length(gatt_services);
400 for (i = 0; i <= len; i++) {
401 GVariantBuilder *svc_builder = NULL;
402 GVariantBuilder *inner_builder = NULL;
404 if (register_pending_cnt > 1)
405 l1 = g_slist_nth(gatt_services, len - register_pending_cnt);
407 l1 = g_slist_last(gatt_services);
409 register_pending_cnt--;
412 BT_ERR("gatt service list is NULL");
413 g_dbus_method_invocation_return_value(invocation, NULL);
417 struct gatt_service_info *serv_info = l1->data;
418 if (serv_info == NULL) {
419 BT_ERR("service info value is NULL");
420 g_dbus_method_invocation_return_value(invocation, NULL);
424 /* Prepare inner builder for GattService1 interface */
425 BT_DBG("Creating builder for service");
426 svc_builder = g_variant_builder_new(
427 G_VARIANT_TYPE("a{sa{sv}}"));
428 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
430 g_variant_builder_add(inner_builder, "{sv}", "UUID",
431 g_variant_new_string(serv_info->service_uuid));
433 g_variant_builder_add(inner_builder, "{sv}", "Primary",
434 g_variant_new_boolean(serv_info->is_svc_primary));
437 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
438 BT_DBG("Adding Charatarisitcs list");
439 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
440 struct gatt_char_info *char_info = l4->data;
441 g_variant_builder_add(inner_builder1, "o",
442 char_info->char_path);
443 BT_DBG("%s", char_info->char_path);
446 svc_char = g_variant_new("ao", inner_builder1);
447 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
450 g_variant_builder_add(svc_builder, "{sa{sv}}",
454 g_variant_builder_add(builder, "{oa{sa{sv}}}",
455 serv_info->serv_path,
458 g_variant_builder_unref(inner_builder1);
460 /* Prepare inner builder for GattCharacteristic1 interface */
462 GSList *l2 = serv_info->char_data;
463 BT_DBG("Creating builder for characteristics \n");
466 BT_DBG("characteristic data is NULL");
468 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
470 GVariantBuilder *char_builder = NULL;
471 GVariantBuilder *inner_builder = NULL;
472 GVariantBuilder *builder1 = NULL;
473 GVariantBuilder *builder2 = NULL;
474 GVariantBuilder *builder3 = NULL;
475 GVariant *char_val = NULL;
476 GVariant *flags_val = NULL;
477 GVariant *char_desc = NULL;
478 char *unicast = NULL;
479 gboolean notify = FALSE;
482 char_builder = g_variant_builder_new(
485 inner_builder = g_variant_builder_new(
489 struct gatt_char_info *char_info = l2->data;
490 if (char_info == NULL) {
491 BT_ERR("char_info is NULL");
496 g_variant_builder_add(inner_builder, "{sv}", "UUID",
497 g_variant_new_string(char_info->char_uuid));
499 g_variant_builder_add(inner_builder, "{sv}", "Service",
500 g_variant_new("o", serv_info->serv_path));
502 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
504 if (char_info->char_value != NULL) {
505 for (i = 0; i < char_info->value_length; i++) {
506 g_variant_builder_add(builder1, "y",
507 char_info->char_value[i]);
509 char_val = g_variant_new("ay", builder1);
510 g_variant_builder_add(inner_builder, "{sv}",
514 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
516 for (i = 0; i < char_info->flags_length; i++) {
517 g_variant_builder_add(builder2, "s",
518 char_info->char_flags[i]);
521 flags_val = g_variant_new("as", builder2);
522 g_variant_builder_add(inner_builder, "{sv}", "Flags",
526 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
527 g_variant_new("b", notify));
530 unicast = g_strdup("00:00:00:00:00:00");
531 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
532 g_variant_new("s", unicast));
535 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
536 BT_DBG("Adding Descriptors list");
538 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
539 struct gatt_desc_info *desc_info = l4->data;
540 g_variant_builder_add(builder3, "o",
541 desc_info->desc_path);
542 BT_DBG("%s", desc_info->desc_path);
545 char_desc = g_variant_new("ao", builder3);
546 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
549 g_variant_builder_add(char_builder, "{sa{sv}}",
550 GATT_CHAR_INTERFACE , inner_builder);
551 g_variant_builder_add(builder, "{oa{sa{sv}}}",
552 char_info->char_path, char_builder);
554 /*Prepare inner builder for GattDescriptor1 interface*/
556 GSList *l3 = char_info->desc_data;
559 BT_DBG("descriptor data is NULL");
561 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
563 BT_DBG("Creating builder for descriptor \n");
565 GVariantBuilder *desc_builder = NULL;
566 GVariantBuilder *inner_builder = NULL;
567 GVariantBuilder *builder1 = NULL;
568 GVariantBuilder *builder2 = NULL;
569 GVariant *desc_val = NULL;
571 desc_builder = g_variant_builder_new(
574 inner_builder = g_variant_builder_new(
578 struct gatt_desc_info *desc_info = l3->data;
579 if (desc_info == NULL) {
580 BT_ERR("desc_info is NULL");
585 g_variant_builder_add(inner_builder,
587 g_variant_new_string(
588 desc_info->desc_uuid));
591 g_variant_builder_add(inner_builder, "{sv}",
594 char_info->char_path));
597 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
599 if (desc_info->desc_value != NULL) {
600 for (i = 0; i < desc_info->value_length; i++) {
601 g_variant_builder_add(builder1, "y",
602 desc_info->desc_value[i]);
604 desc_val = g_variant_new("ay", builder1);
605 g_variant_builder_add(inner_builder, "{sv}",
610 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
612 for (i = 0; i < desc_info->flags_length; i++) {
613 g_variant_builder_add(builder2, "s",
614 desc_info->desc_flags[i]);
617 flags_val = g_variant_new("as", builder2);
618 g_variant_builder_add(inner_builder, "{sv}", "Flags",
621 g_variant_builder_add(desc_builder, "{sa{sv}}",
625 g_variant_builder_add(builder, "{oa{sa{sv}}}",
626 desc_info->desc_path,
629 /*unref descriptor builder pointers*/
630 g_variant_builder_unref(builder1);
631 g_variant_builder_unref(builder2);
632 g_variant_builder_unref(inner_builder);
633 g_variant_builder_unref(desc_builder);
638 /*unref char builder pointers*/
639 g_variant_builder_unref(builder1);
640 g_variant_builder_unref(builder2);
641 g_variant_builder_unref(builder3);
642 g_variant_builder_unref(inner_builder);
643 g_variant_builder_unref(char_builder);
646 /*unref service builder pointers*/
647 g_variant_builder_unref(inner_builder);
648 g_variant_builder_unref(svc_builder);
651 /* Return builder as method reply */
652 BT_DBG("Sending gatt service builder values to Bluez");
653 g_dbus_method_invocation_return_value(invocation,
660 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path)
664 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
665 struct gatt_service_info *serv_info = l1->data;
667 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
668 struct gatt_char_info *char_info = l2->data;
670 if (g_strcmp0(char_info->char_path, char_path)
675 BT_ERR("Gatt service not found");
679 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path)
681 GSList *l1, *l2, *l3;
683 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
684 struct gatt_service_info *serv_info = l1->data;
686 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
687 struct gatt_char_info *char_info = l2->data;
689 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
690 struct gatt_desc_info *desc_info = l3->data;
692 if (g_strcmp0(desc_info->desc_path, desc_path)
698 BT_ERR("Gatt service not found");
702 static void __bt_gatt_char_method_call(GDBusConnection *connection,
704 const gchar *object_path,
705 const gchar *interface_name,
706 const gchar *method_name,
707 GVariant *parameters,
708 GDBusMethodInvocation *invocation,
712 if (g_strcmp0(method_name, "ReadValue") == 0) {
716 bt_gatt_read_req_t read_req = {0, };
717 bt_user_info_t *user_info = NULL;
718 struct gatt_req_info *req_info = NULL;
719 struct gatt_service_info *svc_info = NULL;
720 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
721 GVariant *param = NULL;
724 BT_DBG("Application path = %s", object_path);
725 BT_DBG("Sender = %s", sender);
727 user_info = _bt_get_user_data(BT_COMMON);
728 if (user_info == NULL) {
729 BT_INFO("No callback is set for %s", object_path);
730 g_dbus_method_invocation_return_value(invocation, NULL);
734 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
735 if (svc_info == NULL) {
736 BT_ERR("Coudn't find service for %s", object_path);
737 g_dbus_method_invocation_return_value(invocation, NULL);
741 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
742 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
744 read_req.att_handle = (char *)object_path;
745 read_req.address = addr;
746 read_req.req_id = req_id;
747 read_req.offset = offset;
748 read_req.service_handle = svc_info->serv_path;
750 /* Store requets information */
751 req_info = g_new0(struct gatt_req_info, 1);
752 req_info->attr_path = g_strdup(object_path);
753 req_info->svc_path = g_strdup(read_req.service_handle);
754 req_info->request_id = req_id;
755 req_info->offset = offset;
756 req_info->context = invocation;
757 gatt_requests = g_slist_append(gatt_requests, req_info);
759 _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
760 BLUETOOTH_ERROR_NONE, &read_req,
761 user_info->cb, user_info->user_data);
763 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
764 param = g_variant_new("(sssyq)",
766 read_req.service_handle,
770 #ifdef TIZEN_FEATURE_BT_HPS
771 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
773 #ifdef TIZEN_FEATURE_BT_OTP
774 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, param);
778 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
779 GVariant *var = NULL;
783 gboolean response_needed = FALSE;
784 bt_gatt_value_change_t value_change = {0, };
785 bt_user_info_t *user_info = NULL;
787 struct gatt_service_info *svc_info = NULL;
788 struct gatt_req_info *req_info = NULL;
789 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
790 GVariant *param = NULL;
793 BT_DBG("WriteValue");
794 BT_DBG("Application path = %s", object_path);
795 BT_DBG("Sender = %s", sender);
797 g_variant_get(parameters, "(&suqb@ay)",
798 &addr, &req_id, &offset, &response_needed, &var);
799 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
801 user_info = _bt_get_user_data(BT_COMMON);
803 BT_INFO("No callback is set for %s", object_path);
804 g_variant_unref(var);
806 g_dbus_method_invocation_return_value(invocation, NULL);
808 g_object_unref(invocation);
812 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
813 if (svc_info == NULL) {
814 BT_ERR("Coudn't find service for %s", object_path);
815 g_variant_unref(var);
817 g_dbus_method_invocation_return_value(invocation, NULL);
819 g_object_unref(invocation);
823 value_change.att_handle = (char *)object_path;
824 value_change.address = addr;
825 value_change.service_handle = svc_info->serv_path;
826 value_change.offset = offset;
827 value_change.req_id = req_id;
828 value_change.response_needed = response_needed;
830 len = g_variant_get_size(var);
834 value_change.att_value = (guint8 *)g_malloc(len);
836 data = (char *)g_variant_get_data(var);
837 memcpy(value_change.att_value, data, len);
839 value_change.val_len = len;
841 if (response_needed) {
842 /* Store requets information */
843 req_info = g_new0(struct gatt_req_info, 1);
844 req_info->attr_path = g_strdup(object_path);
845 req_info->svc_path = g_strdup(value_change.service_handle);
846 req_info->request_id = req_id;
847 req_info->offset = offset;
848 req_info->context = invocation;
849 gatt_requests = g_slist_append(gatt_requests, req_info);
851 g_object_unref(invocation);
855 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
856 BLUETOOTH_ERROR_NONE, &value_change,
857 user_info->cb, user_info->user_data);
859 #if defined(TIZEN_FEATURE_BT_HPS) || defined(TIZEN_FEATURE_BT_OTP)
862 svc_path = g_strdup(svc_info->serv_path);
863 param = g_variant_new("(sssyq@ay)",
870 #ifdef TIZEN_FEATURE_BT_HPS
871 __bt_send_event_to_hps(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
873 #ifdef TIZEN_FEATURE_BT_OTP
874 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, param);
881 g_free(value_change.att_value);
882 g_variant_unref(var);
884 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
885 bt_user_info_t *user_info = NULL;
886 bt_gatt_char_notify_change_t notify_change = {0, };
887 #if TIZEN_FEATURE_BT_OTP
888 GVariant *param = NULL;
890 BT_DBG("StartNotify");
891 user_info = _bt_get_user_data(BT_COMMON);
892 if (user_info != NULL) {
893 struct gatt_service_info *svc_info = NULL;
894 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
896 notify_change.service_handle = svc_info->serv_path;
897 notify_change.att_handle = (char *)object_path;
898 notify_change.att_notify = TRUE;
900 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
901 BLUETOOTH_ERROR_NONE, ¬ify_change,
902 user_info->cb, user_info->user_data);
903 #if TIZEN_FEATURE_BT_OTP
904 param = g_variant_new("(ssb)",
905 notify_change.att_handle,
906 notify_change.service_handle,
907 notify_change.att_notify);
908 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
912 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
913 bt_user_info_t *user_info = NULL;
914 bt_gatt_char_notify_change_t notify_change = {0, };
915 #if TIZEN_FEATURE_BT_OTP
916 GVariant *param = NULL;
918 BT_DBG("StopNotify");
919 user_info = _bt_get_user_data(BT_COMMON);
920 if (user_info != NULL) {
921 struct gatt_service_info *svc_info = NULL;
922 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
924 notify_change.service_handle = svc_info->serv_path;
925 notify_change.att_handle = (char *)object_path;
926 notify_change.att_notify = FALSE;
928 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED,
929 BLUETOOTH_ERROR_NONE, ¬ify_change,
930 user_info->cb, user_info->user_data);
931 #if TIZEN_FEATURE_BT_OTP
932 param = g_variant_new("(ssb)",
933 notify_change.att_handle,
934 notify_change.service_handle,
935 notify_change.att_notify);
936 __bt_send_event_to_otp(BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, param);
940 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
942 bt_gatt_indicate_confirm_t confirm = {0, };
943 bt_user_info_t *user_info = NULL;
944 gboolean complete = FALSE;
945 struct gatt_service_info *svc_info = NULL;
947 BT_DBG("IndicateConfirm");
948 BT_DBG("Application path = %s", object_path);
949 BT_DBG("Sender = %s", sender);
951 g_variant_get(parameters, "(&sb)", &addr, &complete);
952 BT_DBG("Remote Device address number = %s", addr);
954 confirm.att_handle = (char *)object_path;
955 confirm.address = addr;
956 confirm.complete = complete;
958 svc_info = __bt_gatt_find_gatt_service_from_char(object_path);
959 if (svc_info != NULL) {
960 confirm.service_handle = svc_info->serv_path;
962 user_info = _bt_get_user_data(BT_COMMON);
963 if (user_info != NULL) {
965 BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED,
966 BLUETOOTH_ERROR_NONE, &confirm,
967 user_info->cb, user_info->user_data);
972 g_dbus_method_invocation_return_value(invocation, NULL);
975 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
977 const gchar *object_path,
978 const gchar *interface_name,
979 const gchar *method_name,
980 GVariant *parameters,
981 GDBusMethodInvocation *invocation,
984 if (g_strcmp0(method_name, "ReadValue") == 0) {
988 bt_gatt_read_req_t read_req = {0, };
989 bt_user_info_t *user_info = NULL;
990 struct gatt_req_info *req_info = NULL;
991 struct gatt_service_info *svc_info = NULL;
994 BT_DBG("Application path = %s", object_path);
995 BT_DBG("Sender = %s", sender);
997 user_info = _bt_get_user_data(BT_COMMON);
998 if (user_info == NULL) {
999 BT_INFO("No callback is set for %s", object_path);
1000 g_dbus_method_invocation_return_value(invocation, NULL);
1004 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1005 if (svc_info == NULL) {
1006 BT_ERR("Coudn't find service for %s", object_path);
1007 g_dbus_method_invocation_return_value(invocation, NULL);
1011 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1012 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1014 read_req.att_handle = (char *)object_path;
1015 read_req.address = addr;
1016 read_req.req_id = req_id;
1017 read_req.offset = offset;
1018 read_req.service_handle = svc_info->serv_path;
1020 /* Store requets information */
1021 req_info = g_new0(struct gatt_req_info, 1);
1022 req_info->attr_path = g_strdup(object_path);
1023 req_info->svc_path = g_strdup(read_req.service_handle);
1024 req_info->request_id = req_id;
1025 req_info->offset = offset;
1026 req_info->context = invocation;
1027 gatt_requests = g_slist_append(gatt_requests, req_info);
1029 _bt_common_event_cb(
1030 BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED,
1031 BLUETOOTH_ERROR_NONE, &read_req,
1032 user_info->cb, user_info->user_data);
1035 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1036 GVariant *var = NULL;
1040 gboolean response_needed = FALSE;
1041 bt_gatt_value_change_t value_change = {0, };
1042 bt_user_info_t *user_info = NULL;
1044 struct gatt_service_info *svc_info = NULL;
1045 struct gatt_req_info *req_info = NULL;
1047 BT_DBG("WriteValue");
1048 BT_DBG("Application path = %s", object_path);
1049 BT_DBG("Sender = %s", sender);
1051 g_variant_get(parameters, "(&suqb@ay)",
1052 &addr, &req_id, &offset, &response_needed, &var);
1053 BT_DBG("Request id = %u, Offset = %u", req_id, offset);
1055 user_info = _bt_get_user_data(BT_COMMON);
1056 if (user_info == NULL) {
1057 BT_INFO("No callback is set for %s", object_path);
1058 g_variant_unref(var);
1059 if (response_needed)
1060 g_dbus_method_invocation_return_value(invocation, NULL);
1062 g_object_unref(invocation);
1066 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path);
1067 if (svc_info == NULL) {
1068 BT_ERR("Coudn't find service for %s", object_path);
1069 g_variant_unref(var);
1070 if (response_needed)
1071 g_dbus_method_invocation_return_value(invocation, NULL);
1073 g_object_unref(invocation);
1077 value_change.att_handle = (char *)object_path;
1078 value_change.address = addr;
1079 value_change.service_handle = svc_info->serv_path;
1080 value_change.offset = offset;
1081 value_change.req_id = req_id;
1082 value_change.response_needed = response_needed;
1084 len = g_variant_get_size(var);
1088 value_change.att_value = (guint8 *)g_malloc(len);
1090 data = (char *)g_variant_get_data(var);
1091 memcpy(value_change.att_value, data, len);
1093 value_change.val_len = len;
1095 if (response_needed) {
1096 /* Store requets information */
1097 req_info = g_new0(struct gatt_req_info, 1);
1098 req_info->attr_path = g_strdup(object_path);
1099 req_info->svc_path = g_strdup(value_change.service_handle);
1100 req_info->request_id = req_id;
1101 req_info->offset = offset;
1102 req_info->context = invocation;
1103 gatt_requests = g_slist_append(gatt_requests, req_info);
1105 g_object_unref(invocation);
1108 _bt_common_event_cb(
1109 BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
1110 BLUETOOTH_ERROR_NONE, &value_change,
1111 user_info->cb, user_info->user_data);
1113 g_free(value_change.att_value);
1114 g_variant_unref(var);
1119 gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1122 GError *error = NULL;
1123 GVariantBuilder *array_builder;
1125 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1126 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1127 g_variant_builder_add(array_builder, "s", interface);
1129 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1130 "org.freedesktop.Dbus.Objectmanager",
1131 "InterfacesRemoved",
1132 g_variant_new("(oas)",
1133 object_path, array_builder),
1137 if (error != NULL) {
1138 /* dbus gives error cause */
1139 BT_ERR("d-bus api failure: errcode[%x], message[%s]",
1140 error->code, error->message);
1141 g_clear_error(&error);
1144 g_variant_builder_unref(array_builder);
1149 static const GDBusInterfaceVTable desc_interface_vtable = {
1150 __bt_gatt_desc_method_call,
1155 static const GDBusInterfaceVTable char_interface_vtable = {
1156 __bt_gatt_char_method_call,
1161 static const GDBusInterfaceVTable serv_interface_vtable = {
1167 static const GDBusInterfaceVTable manager_interface_vtable = {
1168 __bt_gatt_manager_method_call,
1173 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1174 const gchar *introspection_data)
1177 GDBusNodeInfo *node_info = NULL;
1179 if (introspection_data == NULL)
1183 BT_DBG("Create new node info");
1184 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1187 BT_ERR("Unable to create node: %s", err->message);
1188 g_clear_error(&err);
1195 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
1196 const char *service_path)
1200 for (l = gatt_services; l != NULL; l = l->next) {
1201 struct gatt_service_info *info = l->data;
1203 if (g_strcmp0(info->serv_path, service_path) == 0)
1206 BT_ERR("Gatt service not found");
1210 static struct gatt_char_info *__bt_gatt_find_gatt_char_info(
1211 const char *service_path, const char *char_path)
1215 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1216 struct gatt_service_info *serv_info = l1->data;
1218 if (g_strcmp0(serv_info->serv_path, service_path) == 0) {
1220 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1221 struct gatt_char_info *char_info = l2->data;
1223 if (g_strcmp0(char_info->char_path, char_path)
1227 BT_ERR("Gatt characteristic not found");
1231 BT_ERR("Gatt service not found");
1235 static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
1236 const char *serv_path, const char *char_path,
1237 const char *desc_path)
1239 GSList *l1, *l2, *l3;
1241 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
1242 struct gatt_service_info *serv_info = l1->data;
1244 if (g_strcmp0(serv_info->serv_path, serv_path) == 0) {
1245 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
1246 struct gatt_char_info *char_info = l2->data;
1248 if (g_strcmp0(char_info->char_path, char_path)
1250 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
1251 struct gatt_desc_info *desc_info = l3->data;
1252 if (g_strcmp0(desc_info->desc_path,
1261 BT_ERR("Gatt descriptor not found");
1265 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id)
1269 for (l = gatt_requests; l != NULL; l = l->next) {
1270 struct gatt_req_info *req_info = l->data;
1272 if (req_info && req_info->request_id == request_id)
1275 BT_ERR("Gatt Request not found");
1279 static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service,
1280 const gchar *path, const gchar *interface)
1286 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
1291 BT_ERR("Unable to connect to gdbus: %s", err->message);
1292 g_clear_error(&err);
1297 proxy = g_dbus_proxy_new_sync(g_conn,
1298 G_DBUS_PROXY_FLAGS_NONE, NULL,
1300 interface, NULL, &err);
1304 BT_ERR("Unable to create proxy: %s", err->message);
1305 g_clear_error(&err);
1309 manager_gproxy = proxy;
1314 static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service,
1315 const gchar *path, const gchar *interface)
1317 return (manager_gproxy) ? manager_gproxy :
1318 __bt_gatt_gdbus_init_manager_proxy(service,
1322 int bluetooth_gatt_convert_prop2string(
1323 bt_gatt_characteristic_property_t properties,
1324 char *char_properties[])
1328 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) {
1329 char_properties[flag_count] = g_strdup("broadcast");
1332 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) {
1333 char_properties[flag_count] = g_strdup("read");
1336 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) {
1337 char_properties[flag_count] = g_strdup("write-without-response");
1340 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) {
1341 char_properties[flag_count] = g_strdup("write");
1344 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) {
1345 char_properties[flag_count] = g_strdup("notify");
1348 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) {
1349 char_properties[flag_count] = g_strdup("indicate");
1352 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) {
1353 char_properties[flag_count] = g_strdup("authenticated-signed-writes");
1356 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE) {
1357 char_properties[flag_count] = g_strdup("reliable-write");
1360 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES) {
1361 char_properties[flag_count] = g_strdup("writable-auxiliaries");
1364 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ) {
1365 char_properties[flag_count] = g_strdup("encrypt-read");
1368 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE) {
1369 char_properties[flag_count] = g_strdup("encrypt-write");
1372 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ) {
1373 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1376 if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE) {
1377 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1381 if (flag_count == 0) {
1382 char_properties[flag_count] = g_strdup("read");
1389 int bluetooth_gatt_convert_perm2string(
1390 bt_gatt_permission_t properties,
1391 char *char_properties[])
1395 if (properties & BLUETOOTH_GATT_PERMISSION_READ) {
1396 char_properties[flag_count] = g_strdup("read");
1399 if (properties & BLUETOOTH_GATT_PERMISSION_WRITE) {
1400 char_properties[flag_count] = g_strdup("write");
1403 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ) {
1404 char_properties[flag_count] = g_strdup("encrypt-read");
1407 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE) {
1408 char_properties[flag_count] = g_strdup("encrypt-write");
1411 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ) {
1412 char_properties[flag_count] = g_strdup("encrypt-authenticated-read");
1415 if (properties & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE) {
1416 char_properties[flag_count] = g_strdup("encrypt-authenticated-write");
1420 if (flag_count == 0) {
1421 char_properties[flag_count] = g_strdup("read");
1428 static void __bt_gatt_set_service_state(const char *service_path,
1431 struct gatt_service_info *svc_info = NULL;
1432 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1434 if (svc_info != NULL) {
1435 BT_DBG("Updating the gatt service register state %d", state);
1436 svc_info->is_svc_registered = state;
1440 BT_DBG("gatt service not found");
1443 static gboolean __bt_gatt_get_service_state(const char *service_path)
1445 struct gatt_service_info *svc_info = NULL;
1447 svc_info = __bt_gatt_find_gatt_service_info(service_path);
1449 if (svc_info != NULL) {
1450 BT_DBG("Return the state of the gatt service %d",
1451 svc_info->is_svc_registered);
1452 return svc_info->is_svc_registered;
1455 BT_DBG("gatt service info is NULL");
1459 void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1461 GError *error = NULL;
1463 GVariantIter *iter = NULL;
1464 const gchar *key = NULL;
1465 GVariant *value = NULL;
1466 const gchar *service = NULL;
1467 const gchar *characteristic = NULL;
1468 const gchar *descriptor = NULL;
1472 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1474 if (result == NULL) {
1475 /* dBUS-RPC is failed */
1476 BT_ERR("Dbus-RPC is failed\n");
1478 if (error != NULL) {
1479 /* dBUS gives error cause */
1480 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1481 error->code, error->message);
1482 g_clear_error(&error);
1485 char *char_cmp = NULL;
1486 g_variant_get(result, "(a{sv})", &iter);
1487 char_cmp = g_strdup_printf("Characteristic%d", n_char);
1489 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1490 if (g_strcmp0(key, "Service") == 0) {
1491 service = g_variant_get_string(value, NULL);
1492 BT_DBG("Service %s", service);
1493 } else if (g_strcmp0(key, char_cmp) == 0) {
1494 characteristic = g_variant_get_string(value, NULL);
1496 char_cmp = g_strdup_printf("Characteristic%d", ++n_char);
1497 BT_DBG("%s", characteristic);
1498 } else if (g_strcmp0(key, "Descriptor") == 0) {
1499 descriptor = g_variant_get_string(value, NULL);
1500 BT_DBG("Descriptor %s", descriptor);
1503 g_variant_iter_free(iter);
1505 /* TODO: Store the service informationa and
1506 * Send respponse to CAPI layer. */
1508 g_variant_unref(result);
1513 void register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
1515 BT_INFO("RegisterApplication is completed");
1517 GError *error = NULL;
1520 register_pending_cnt = 0;
1522 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1524 if (result == NULL) {
1525 /* dBUS-RPC is failed */
1526 BT_ERR("Dbus-RPC is failed\n");
1528 if (error != NULL) {
1529 /* dBUS gives error cause */
1530 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1531 error->code, error->message);
1532 g_clear_error(&error);
1535 g_variant_unref(result);
1539 void unregister_application_cb(GObject *object, GAsyncResult *res,
1542 BT_INFO("UnregisterApplication is completed");
1544 GError *error = NULL;
1547 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1549 if (result == NULL) {
1550 /* dBUS-RPC is failed */
1551 BT_ERR("Dbus-RPC is failed\n");
1553 if (error != NULL) {
1554 /* dBUS gives error cause */
1555 BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1556 error->code, error->message);
1557 g_clear_error(&error);
1560 g_variant_unref(result);
1564 static int __bt_gatt_unregister_service(const char *service_path)
1566 if (!__bt_gatt_get_service_state(service_path)) {
1567 BT_DBG("service not registered \n");
1568 return BLUETOOTH_ERROR_NOT_FOUND;
1571 return BLUETOOTH_ERROR_NONE;
1574 BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
1576 GDBusProxy *proxy = NULL;
1578 if (is_server_started) {
1579 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
1580 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
1582 if (proxy == NULL || app_path == NULL)
1583 return BLUETOOTH_ERROR_INTERNAL;
1585 BT_INFO("UnregisterApplication");
1587 /* Async Call to Unregister Service */
1588 g_dbus_proxy_call(proxy,
1589 "UnregisterApplication",
1590 g_variant_new("(o)",
1592 G_DBUS_CALL_FLAGS_NONE, -1,
1594 (GAsyncReadyCallback) unregister_application_cb,
1597 is_server_started = false;
1598 return BLUETOOTH_ERROR_NONE;
1601 BT_INFO("GATT server not started");
1602 return BLUETOOTH_ERROR_NONE;
1605 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1607 GDBusConnection *local_system_gconn = NULL;
1611 if (g_conn == NULL) {
1612 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1613 if (address == NULL) {
1615 BT_ERR("Failed to get bus address: %s", err->message);
1616 g_clear_error(&err);
1621 g_conn = g_dbus_connection_new_for_address_sync(address,
1622 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1623 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1624 NULL, /* GDBusAuthObserver */
1629 BT_ERR("Unable to connect to dbus: %s", err->message);
1630 g_clear_error(&err);
1634 } else if (g_dbus_connection_is_closed(g_conn)) {
1635 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1636 if (address == NULL) {
1638 BT_ERR("Failed to get bus address: %s", err->message);
1639 g_clear_error(&err);
1644 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1645 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1646 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1647 NULL, /* GDBusAuthObserver */
1651 if (!local_system_gconn) {
1652 BT_ERR("Unable to connect to dbus: %s", err->message);
1653 g_clear_error(&err);
1656 g_conn = local_system_gconn;
1662 BT_EXPORT_API int bluetooth_gatt_init(void)
1664 GDBusConnection *conn;
1665 GError *error = NULL;
1666 GDBusNodeInfo *node_info = NULL;
1668 if (app_path != NULL) {
1669 BT_ERR("app path already exists! initialized");
1670 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
1673 if (owner_id == 0) {
1674 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1675 BT_GATT_SERVICE_NAME,
1676 G_BUS_NAME_OWNER_FLAGS_NONE,
1677 NULL, NULL, NULL, NULL, NULL);
1680 BT_DBG("owner_id is [%d]", owner_id);
1681 app_path = g_strdup_printf("/com/%d", getpid());
1685 conn = __bt_gatt_get_gdbus_connection();
1687 BT_ERR("Unable to get connection");
1691 /* Register ObjectManager interface */
1692 node_info = __bt_gatt_create_method_node_info(
1693 manager_introspection_xml);
1695 if (node_info == NULL) {
1696 BT_ERR("failed to get node info");
1700 if (manager_id == 0) {
1701 BT_INFO("manager_id does not exists");
1703 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1704 node_info->interfaces[0],
1705 &manager_interface_vtable,
1706 NULL, NULL, &error);
1709 if (manager_id == 0) {
1710 BT_ERR("failed to register: %s", error->message);
1711 g_error_free(error);
1715 return BLUETOOTH_ERROR_NONE;
1719 g_bus_unown_name(owner_id);
1726 __bt_gatt_close_gdbus_connection();
1728 return BLUETOOTH_ERROR_INTERNAL;
1731 BT_EXPORT_API int bluetooth_gatt_deinit()
1733 int ret = BLUETOOTH_ERROR_NONE;
1734 /* Unown gdbus bus */
1736 /* remove/unregister all services */
1737 BT_DBG("removing all registered gatt service\n");
1738 bluetooth_gatt_delete_services();
1740 /* unregister the exported interface for object manager */
1741 g_dbus_connection_unregister_object(g_conn,
1746 ret = bluetooth_gatt_unregister_application();
1747 if (ret != BLUETOOTH_ERROR_NONE)
1748 BT_ERR("Fail to unregister application\n");
1750 g_bus_unown_name(owner_id);
1756 BT_DBG("Gatt service deinitialized \n");
1758 g_slist_free(gatt_services);
1759 gatt_services = NULL;
1761 g_object_unref(manager_gproxy);
1762 manager_gproxy = NULL;
1764 __bt_gatt_close_gdbus_connection();
1769 __bt_gatt_close_gdbus_connection();
1771 return BLUETOOTH_ERROR_NOT_FOUND;
1774 BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid,
1777 GError *error = NULL;
1779 GDBusNodeInfo *node_info;
1781 GVariantBuilder *builder = NULL;
1782 GVariantBuilder *builder1 = NULL;
1783 GVariantBuilder *inner_builder = NULL;
1784 gboolean svc_primary = TRUE;
1785 struct gatt_service_info *serv_info = NULL;
1787 node_info = __bt_gatt_create_method_node_info(
1788 service_introspection_xml);
1790 if (node_info == NULL)
1791 return BLUETOOTH_ERROR_INTERNAL;
1793 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, serv_id++);
1794 BT_DBG("gatt service path is [%s]", path);
1796 object_id = g_dbus_connection_register_object(g_conn, path,
1797 node_info->interfaces[0],
1798 &serv_interface_vtable,
1799 NULL, NULL, &error);
1801 if (object_id == 0) {
1802 BT_ERR("failed to register: %s", error->message);
1803 g_error_free(error);
1806 return BLUETOOTH_ERROR_INTERNAL;
1809 /* Add object_id/gatt service information; it's required at the time of
1810 * service unregister and Getmanagedobjects
1812 serv_info = g_new0(struct gatt_service_info, 1);
1814 serv_info->serv_path = g_strdup(path);
1815 serv_info->serv_id = object_id;
1816 serv_info->service_uuid = g_strdup(svc_uuid);
1817 serv_info->is_svc_registered = FALSE;
1818 serv_info->is_svc_primary = svc_primary;
1820 gatt_services = g_slist_append(gatt_services, serv_info);
1822 /* emit interfacesadded signal here for service path */
1823 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1824 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1826 g_variant_builder_add(inner_builder, "{sv}",
1827 "UUID", g_variant_new_string(svc_uuid));
1829 g_variant_builder_add(inner_builder, "{sv}",
1830 "Primary", g_variant_new_boolean(svc_primary));
1832 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1834 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1835 g_variant_new("ao", builder1));
1837 g_variant_builder_add(builder, "{sa{sv}}",
1838 GATT_SERV_INTERFACE, inner_builder);
1840 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1841 "org.freedesktop.Dbus.ObjectManager",
1843 g_variant_new("(oa{sa{sv}})",
1849 *svc_path = g_strdup(path);
1852 g_variant_builder_unref(inner_builder);
1853 g_variant_builder_unref(builder);
1854 g_variant_builder_unref(builder1);
1856 return BLUETOOTH_ERROR_NONE;
1859 BT_EXPORT_API int bluetooth_gatt_add_new_characteristic(
1860 const char *svc_path, const char *char_uuid,
1861 bt_gatt_permission_t permissions,
1862 bt_gatt_characteristic_property_t properties,
1866 GError *error = NULL;
1868 GDBusNodeInfo *node_info;
1870 GVariantBuilder *builder = NULL;
1871 GVariantBuilder *inner_builder = NULL;
1872 struct gatt_service_info *serv_info = NULL;
1873 struct gatt_char_info *char_info = NULL;
1874 GVariantBuilder *builder2 = NULL;
1875 GVariantBuilder *builder3 = NULL;
1876 GVariant *flags_val = NULL;
1878 char *char_flags[NUMBER_OF_FLAGS];
1883 new_service = FALSE;
1886 BT_DBG("gatt svc_path path is [%s]", svc_path);
1887 serv_info = __bt_gatt_find_gatt_service_info(svc_path);
1888 if (serv_info == NULL)
1889 return BLUETOOTH_ERROR_INVALID_PARAM;
1891 node_info = __bt_gatt_create_method_node_info(
1892 characteristics_introspection_xml);
1894 if (node_info == NULL)
1895 return BLUETOOTH_ERROR_INTERNAL;
1897 path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++);
1898 BT_DBG("gatt characteristic path is [%s]", path);
1900 object_id = g_dbus_connection_register_object(g_conn, path,
1901 node_info->interfaces[0],
1902 &char_interface_vtable,
1903 NULL, NULL, &error);
1905 if (object_id == 0) {
1906 BT_ERR("failed to register: %s", error->message);
1907 g_error_free(error);
1910 return BLUETOOTH_ERROR_INTERNAL;
1913 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_READ)
1914 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1915 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
1916 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1917 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_WRITE)
1918 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1919 if (permissions & BLUETOOTH_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
1920 properties |= BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1922 flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags);
1924 char_info = g_new0(struct gatt_char_info, 1);
1926 char_info->char_path = g_strdup(path);
1927 char_info->char_id = object_id;
1928 char_info->char_uuid = g_strdup(char_uuid);
1930 for (i = 0; i < flag_count; i++)
1931 char_info->char_flags[i] = char_flags[i];
1934 char_info->flags_length = flag_count;
1936 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
1938 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1939 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1941 g_variant_builder_add(inner_builder, "{sv}", "UUID",
1942 g_variant_new("s", char_uuid));
1943 g_variant_builder_add(inner_builder, "{sv}", "Service",
1944 g_variant_new("o", svc_path));
1946 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1948 for (i = 0; i < flag_count; i++)
1949 g_variant_builder_add(builder2, "s", char_flags[i]);
1951 flags_val = g_variant_new("as", builder2);
1952 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1955 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1957 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
1958 g_variant_new("ao", builder3));
1960 g_variant_builder_add(builder, "{sa{sv}}",
1961 GATT_CHAR_INTERFACE,
1964 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1965 "org.freedesktop.Dbus.ObjectManager",
1967 g_variant_new("(oa{sa{sv}})",
1971 *char_path = g_strdup(path);
1977 g_variant_builder_unref(inner_builder);
1978 g_variant_builder_unref(builder);
1979 g_variant_builder_unref(builder2);
1980 g_variant_builder_unref(builder3);
1982 return BLUETOOTH_ERROR_NONE;
1985 BT_EXPORT_API int bluetooth_gatt_set_characteristic_value(
1986 const char *characteristic, const char *char_value,
1989 gchar **line_argv = NULL;
1990 char *serv_path = NULL;
1991 struct gatt_char_info *char_info = NULL;
1992 GVariantBuilder *builder1 = NULL;
1993 GVariantBuilder *builder = NULL;
1994 GVariantBuilder *inner_builder = NULL;
1995 GVariant *char_val = NULL;
1996 GError *error = NULL;
1998 int res = BLUETOOTH_ERROR_NONE;
2000 line_argv = g_strsplit_set(characteristic, "/", 0);
2001 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2003 char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic);
2005 if (char_info == NULL) {
2006 /* Fix : RESOURCE_LEAK */
2007 res = BLUETOOTH_ERROR_INVALID_PARAM;
2011 char_info->value_length = value_length;
2013 char_info->char_value = (char *)malloc(value_length);
2014 /* Fix : NULL_RETURNS */
2015 if (char_info->char_value == NULL) {
2016 res = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
2020 for (i = 0; i < value_length; i++)
2021 char_info->char_value[i] = char_value[i];
2023 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2024 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2026 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2028 for (i = 0; i < value_length; i++)
2029 g_variant_builder_add(builder1, "y", char_value[i]);
2031 char_val = g_variant_new("ay", builder1);
2032 g_variant_builder_add(inner_builder, "{sv}", "Value", char_val);
2034 g_variant_builder_add(builder, "{sa{sv}}",
2035 GATT_CHAR_INTERFACE,
2038 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2039 "org.freedesktop.Dbus.ObjectManager",
2041 g_variant_new("(oa{sa{sv}})",
2042 char_info->char_path, builder),
2045 g_variant_builder_unref(inner_builder);
2046 g_variant_builder_unref(builder);
2047 g_variant_builder_unref(builder1);
2049 g_strfreev(line_argv);
2055 BT_EXPORT_API int bluetooth_gatt_add_descriptor(
2056 const char *char_path, const char *desc_uuid,
2057 bt_gatt_permission_t permissions,
2060 static int desc_id = 1;
2061 GError *error = NULL;
2063 GDBusNodeInfo *node_info;
2065 GVariantBuilder *builder = NULL;
2066 GVariantBuilder *inner_builder = NULL;
2067 struct gatt_char_info *char_info = NULL;
2068 struct gatt_desc_info *desc_info = NULL;
2069 gchar **line_argv = NULL;
2071 GVariantBuilder *builder2 = NULL;
2072 GVariant *flags_val = NULL;
2074 char *desc_flags[NUMBER_OF_FLAGS];
2082 line_argv = g_strsplit_set(char_path, "/", 0);
2083 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2085 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2086 if (char_info == NULL) {
2087 g_strfreev(line_argv);
2089 return BLUETOOTH_ERROR_INVALID_PARAM;
2092 node_info = __bt_gatt_create_method_node_info(
2093 descriptor_introspection_xml);
2095 if (node_info == NULL) {
2096 g_strfreev(line_argv);
2098 return BLUETOOTH_ERROR_INTERNAL;
2101 path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++);
2102 BT_DBG("gatt descriptor path is [%s]", path);
2104 object_id = g_dbus_connection_register_object(g_conn, path,
2105 node_info->interfaces[0],
2106 &desc_interface_vtable,
2107 NULL, NULL, &error);
2109 if (object_id == 0) {
2110 BT_ERR("failed to register: %s", error->message);
2111 g_error_free(error);
2113 g_strfreev(line_argv);
2116 return BLUETOOTH_ERROR_INTERNAL;
2119 flag_count = bluetooth_gatt_convert_perm2string(permissions, desc_flags);
2121 desc_info = g_new0(struct gatt_desc_info, 1);
2123 desc_info->desc_path = g_strdup(path);
2124 desc_info->desc_id = object_id;
2125 desc_info->desc_uuid = g_strdup(desc_uuid);
2127 for (i = 0; i < flag_count; i++)
2128 desc_info->desc_flags[i] = desc_flags[i];
2130 desc_info->flags_length = flag_count;
2132 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2134 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2135 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2137 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2138 g_variant_new("s", desc_uuid));
2139 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2140 g_variant_new("o", char_path));
2142 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2144 for (i = 0; i < flag_count; i++)
2145 g_variant_builder_add(builder2, "s", desc_flags[i]);
2147 flags_val = g_variant_new("as", builder2);
2148 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2151 g_variant_builder_add(builder, "{sa{sv}}",
2152 GATT_DESC_INTERFACE,
2155 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2156 "org.freedesktop.Dbus.ObjectManager",
2158 g_variant_new("(oa{sa{sv}})",
2162 *desc_path = g_strdup(path);
2166 g_strfreev(line_argv);
2167 g_variant_builder_unref(inner_builder);
2168 g_variant_builder_unref(builder);
2170 return BLUETOOTH_ERROR_NONE;
2173 BT_EXPORT_API int bluetooth_gatt_set_descriptor_value(
2174 const char *desc_path, const char *desc_value,
2177 GError *error = NULL;
2178 GVariantBuilder *builder = NULL;
2179 GVariantBuilder *inner_builder = NULL;
2180 GVariantBuilder *builder1 = NULL;
2181 struct gatt_desc_info *desc_info = NULL;
2182 gchar **line_argv = NULL;
2184 GVariant *desc_val = NULL;
2185 char *serv_path = NULL;
2188 line_argv = g_strsplit_set(desc_path, "/", 0);
2189 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2190 char_path = g_strdup_printf("%s/%s", serv_path, line_argv[4]);
2192 desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path);
2194 /* Free the allocated memory */
2195 g_strfreev(line_argv);
2199 /* Fix : NULL_RETURNS */
2200 retv_if(desc_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
2202 desc_info->desc_value = (char *)malloc(value_length);
2204 /* Fix : NULL_RETURNS */
2205 retv_if(desc_info->desc_value == NULL, BLUETOOTH_ERROR_MEMORY_ALLOCATION);
2207 for (i = 0; i < value_length; i++)
2208 desc_info->desc_value[i] = desc_value[i];
2210 desc_info->value_length = value_length;
2212 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2213 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2215 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2217 for (i = 0; i < value_length; i++)
2218 g_variant_builder_add(builder1, "y", desc_value[i]);
2220 desc_val = g_variant_new("ay", builder1);
2221 g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val);
2223 g_variant_builder_add(builder, "{sa{sv}}",
2224 GATT_DESC_INTERFACE,
2227 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2228 "org.freedesktop.Dbus.ObjectManager",
2230 g_variant_new("(oa{sa{sv}})",
2231 desc_info->desc_path, builder),
2234 g_variant_builder_unref(inner_builder);
2235 g_variant_builder_unref(builder);
2236 g_variant_builder_unref(builder1);
2238 return BLUETOOTH_ERROR_NONE;
2241 int bluetooth_gatt_get_service(const char *svc_uuid)
2243 GDBusProxy *proxy = NULL;
2246 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2247 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2249 return BLUETOOTH_ERROR_INTERNAL;
2251 uuid = g_strdup(svc_uuid);
2253 g_dbus_proxy_call(proxy,
2255 g_variant_new("(s)",
2257 G_DBUS_CALL_FLAGS_NONE, -1,
2259 (GAsyncReadyCallback) get_service_cb,
2264 return BLUETOOTH_ERROR_NONE;
2267 BT_EXPORT_API int bluetooth_gatt_register_service(
2268 const char *svc_path)
2270 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_SERVICE)
2271 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2272 BT_ERR("Don't have aprivilege to use this API");
2273 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2276 register_pending_cnt++;
2278 if (__bt_gatt_get_service_state(svc_path)) {
2279 BT_DBG("service already registered \n");
2280 return BLUETOOTH_ERROR_NONE;
2283 __bt_gatt_set_service_state(svc_path, TRUE);
2285 return BLUETOOTH_ERROR_NONE;
2288 BT_EXPORT_API int bluetooth_gatt_register_application(void)
2290 GDBusProxy *proxy = NULL;
2292 if (!is_server_started) {
2294 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_REGISTER_APPLICATION)
2295 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2296 BT_ERR("Don't have aprivilege to use this API");
2297 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2300 proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez",
2301 "/org/bluez/hci0", GATT_MNGR_INTERFACE);
2302 if (proxy == NULL || app_path == NULL)
2303 return BLUETOOTH_ERROR_INTERNAL;
2305 BT_INFO("RegisterApplication");
2307 g_dbus_proxy_call(proxy,
2308 "RegisterApplication",
2309 g_variant_new("(oa{sv})",
2311 G_DBUS_CALL_FLAGS_NONE, -1,
2313 (GAsyncReadyCallback) register_application_cb,
2316 is_server_started = true;
2318 return BLUETOOTH_ERROR_NONE;
2321 BT_INFO("Already RegisterApplication");
2323 return BLUETOOTH_ERROR_NONE;
2326 BT_EXPORT_API int bluetooth_gatt_delete_services(void)
2329 int error = BLUETOOTH_ERROR_NONE;
2333 for (l = gatt_services; l != NULL; l = l->next) {
2334 struct gatt_service_info *info = l->data;
2335 BT_DBG("svc_path is %s", info->serv_path);
2336 if (bluetooth_gatt_unregister_service(info->serv_path)
2337 != BLUETOOTH_ERROR_NONE) {
2338 error = BLUETOOTH_ERROR_INTERNAL;
2339 BT_ERR("Error in removing service %s \n",
2343 BT_DBG(" All services removed successfully.\n ");
2345 BT_DBG(" There are no registered services.\n ");
2348 g_slist_free(gatt_services);
2349 gatt_services = NULL;
2352 if (error != BLUETOOTH_ERROR_NONE)
2355 return BLUETOOTH_ERROR_NONE;
2358 BT_EXPORT_API int bluetooth_gatt_update_characteristic(
2359 const char *char_path, const char* char_value,
2362 GVariantBuilder *outer_builder;
2363 GVariantBuilder *inner_builder;
2364 GVariantBuilder *invalidated_builder;
2365 GVariant *update_value = NULL;
2366 GError *error = NULL;
2367 gboolean ret = FALSE;
2368 int err = BLUETOOTH_ERROR_NONE;
2370 gchar **line_argv = NULL;
2371 gchar *serv_path = NULL;
2373 line_argv = g_strsplit_set(char_path, "/", 0);
2374 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2376 if (!__bt_gatt_get_service_state(serv_path)) {
2377 BT_DBG("service not registered for this characteristic \n");
2379 g_strfreev(line_argv);
2380 return BLUETOOTH_ERROR_INTERNAL;
2383 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2384 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2386 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2387 for (i = 0; i < value_length; i++)
2388 g_variant_builder_add(inner_builder, "y", char_value[i]);
2390 update_value = g_variant_new("ay", inner_builder);
2392 outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2393 g_variant_builder_add(outer_builder, "{sv}", "Value",
2396 BT_DBG("Updating characteristic value \n");
2397 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2399 "org.freedesktop.DBus.Properties",
2400 "PropertiesChanged",
2401 g_variant_new("(sa{sv}as)",
2402 "org.bluez.GattCharacteristic1",
2403 outer_builder, invalidated_builder),
2407 if (error != NULL) {
2408 BT_ERR("D-Bus API failure: errCode[%x], \
2410 error->code, error->message);
2411 g_clear_error(&error);
2413 err = BLUETOOTH_ERROR_INTERNAL;
2415 struct gatt_char_info *char_info = NULL;
2417 char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
2418 if (char_info == NULL) {
2420 g_strfreev(line_argv);
2421 g_variant_builder_unref(inner_builder);
2422 g_variant_builder_unref(outer_builder);
2423 g_variant_builder_unref(invalidated_builder);
2425 return BLUETOOTH_ERROR_INVALID_DATA;
2428 char_info->value_length = value_length;
2430 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
2431 if (char_info->char_value) {
2432 for (i = 0; i < value_length; i++)
2433 char_info->char_value[i] = char_value[i];
2438 g_strfreev(line_argv);
2439 g_variant_builder_unref(inner_builder);
2440 g_variant_builder_unref(outer_builder);
2441 g_variant_builder_unref(invalidated_builder);
2446 static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
2453 g_free(desc_info->desc_path);
2454 g_free(desc_info->desc_uuid);
2455 g_free(desc_info->desc_value);
2457 for (i = 0; i < desc_info->flags_length; i++)
2458 g_free(desc_info->desc_flags[i]);
2463 static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
2470 g_free(char_info->char_path);
2471 g_free(char_info->char_uuid);
2472 g_free(char_info->char_value);
2474 for (i = 0; i < char_info->flags_length; i++)
2475 g_free(char_info->char_flags[i]);
2480 static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
2485 g_free(svc_info->serv_path);
2486 g_free(svc_info->service_uuid);
2490 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
2493 struct gatt_service_info *svc_info;
2495 int err = BLUETOOTH_ERROR_NONE;
2497 BT_DBG("svc_path %s", svc_path);
2498 svc_info = __bt_gatt_find_gatt_service_info(svc_path);
2501 BT_ERR("Unable to find service info");
2502 return BLUETOOTH_ERROR_NOT_FOUND;
2505 err = __bt_gatt_unregister_service(svc_path);
2506 if (err != BLUETOOTH_ERROR_NONE) {
2507 BT_ERR("Could not unregister application");
2511 for (l = svc_info->char_data; l != NULL; l = l->next) {
2512 struct gatt_char_info *char_info = l->data;
2514 if (char_info == NULL)
2517 for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
2518 struct gatt_desc_info *desc_info = l1->data;
2520 if (desc_info == NULL)
2523 ret = g_dbus_connection_unregister_object(g_conn,
2524 desc_info->desc_id);
2526 __bt_gatt_emit_interface_removed(
2527 desc_info->desc_path,
2528 GATT_DESC_INTERFACE);
2530 err = BLUETOOTH_ERROR_INTERNAL;
2533 /* list remove & free */
2534 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2535 __bt_gatt_free_descriptor_info(desc_info);
2538 g_slist_free(char_info->desc_data);
2539 char_info->desc_data = NULL;
2541 ret = g_dbus_connection_unregister_object(g_conn,
2542 char_info->char_id);
2544 __bt_gatt_emit_interface_removed(char_info->char_path,
2545 GATT_CHAR_INTERFACE);
2547 err = BLUETOOTH_ERROR_INTERNAL;
2550 /* list remove & free */
2551 svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
2552 __bt_gatt_free_characteristic_info(char_info);
2555 g_slist_free(svc_info->char_data);
2556 svc_info->char_data = NULL;
2558 ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
2560 __bt_gatt_emit_interface_removed(svc_info->serv_path,
2561 GATT_SERV_INTERFACE);
2563 err = BLUETOOTH_ERROR_INTERNAL;
2566 ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id);
2568 BT_DBG("Unregistered the service on properties interface");
2570 /* list remove & free */
2571 gatt_services = g_slist_remove(gatt_services, svc_info);
2572 __bt_gatt_free_service_info(svc_info);
2574 new_service = FALSE;
2576 if (gatt_services == NULL)
2578 else if (gatt_services->next == NULL)
2584 BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
2585 int resp_state, int offset, char *value, int value_length)
2587 struct gatt_req_info *req_info = NULL;
2589 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_GATT_SEND_RESPONSE)
2590 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
2591 BT_ERR("Don't have aprivilege to use this API");
2592 return BLUETOOTH_ERROR_PERMISSION_DEINED;
2595 req_info = __bt_gatt_find_request_info(request_id);
2596 if (req_info == NULL) {
2597 BT_ERR("Coundn't find request id [%d]", request_id);
2598 return BLUETOOTH_ERROR_INTERNAL;
2601 if (resp_state != BLUETOOTH_ERROR_NONE) {
2602 BT_ERR("resp_state is 0x%X", resp_state);
2604 switch (resp_state) {
2605 case BLUETOOTH_ERROR_WRITE_REQUEST_REJECTED:
2606 g_dbus_method_invocation_return_dbus_error(req_info->context,
2607 "org.bluez.Error.Failed", "Write Request Rejected");
2609 case BLUETOOTH_ERROR_OBJECT_NOT_SELECTED:
2610 g_dbus_method_invocation_return_dbus_error(req_info->context,
2611 "org.bluez.Error.Failed", "Object Not Selected");
2613 case BLUETOOTH_ERROR_CONCURRENCY_LIMIT_EXCEEDED:
2614 g_dbus_method_invocation_return_dbus_error(req_info->context,
2615 "org.bluez.Error.Failed", "Concurrency Limit Exceeded");
2617 case BLUETOOTH_ERROR_OBJECT_NAME_EXISITS:
2618 g_dbus_method_invocation_return_dbus_error(req_info->context,
2619 "org.bluez.Error.Failed", "Object Name Already Exists");
2621 case BLUETOOTH_ERROR_CCC_IMPROPERLY_CONFIGURED:
2622 g_dbus_method_invocation_return_dbus_error(req_info->context,
2623 "org.bluez.Error.Failed", "CCC Improperly Configured");
2626 g_dbus_method_invocation_return_dbus_error(req_info->context,
2627 "org.bluez.Error.Failed", "Application Error");
2631 gatt_requests = g_slist_remove(gatt_requests, req_info);
2633 req_info->context = NULL;
2634 if (req_info->attr_path)
2635 g_free(req_info->attr_path);
2636 if (req_info->svc_path)
2637 g_free(req_info->svc_path);
2640 return BLUETOOTH_ERROR_NONE;
2643 if (req_type == BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ) {
2645 GVariantBuilder *inner_builder = NULL;
2646 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2647 if (value_length > 0 && value != NULL) {
2648 for (i = 0; i < value_length; i++)
2649 g_variant_builder_add(inner_builder, "y", value[i]);
2651 g_dbus_method_invocation_return_value(req_info->context,
2652 g_variant_new("(ay)", inner_builder));
2653 g_variant_builder_unref(inner_builder);
2655 g_dbus_method_invocation_return_value(req_info->context, NULL);
2657 gatt_requests = g_slist_remove(gatt_requests, req_info);
2659 req_info->context = NULL;
2660 if (req_info->attr_path)
2661 g_free(req_info->attr_path);
2662 if (req_info->svc_path)
2663 g_free(req_info->svc_path);
2666 return BLUETOOTH_ERROR_NONE;
2669 BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
2670 bluetooth_device_address_t *unicast_address)
2672 GVariantBuilder *outer_builder;
2673 GVariantBuilder *invalidated_builder;
2674 GError *error = NULL;
2675 gboolean notify = TRUE;
2676 gboolean ret = TRUE;
2677 int err = BLUETOOTH_ERROR_NONE;
2678 gchar **line_argv = NULL;
2679 gchar *serv_path = NULL;
2680 char addr[20] = { 0 };
2682 line_argv = g_strsplit_set(char_path, "/", 0);
2683 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2685 if (!__bt_gatt_get_service_state(serv_path)) {
2686 BT_DBG("service not registered for this characteristic \n");
2688 g_strfreev(line_argv);
2689 return BLUETOOTH_ERROR_INTERNAL;
2694 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2695 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2697 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2698 g_variant_new("b", notify));
2700 if (unicast_address) {
2701 _bt_convert_addr_type_to_string(addr,
2702 (unsigned char *)unicast_address->addr);
2704 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2705 g_variant_new("s", addr));
2707 BT_DBG("Set characteristic Notification \n");
2708 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2710 "org.freedesktop.DBus.Properties",
2711 "PropertiesChanged",
2712 g_variant_new("(sa{sv}as)",
2713 "org.bluez.GattCharacteristic1",
2714 outer_builder, invalidated_builder),
2718 if (error != NULL) {
2719 BT_ERR("D-Bus API failure: errCode[%x], \
2721 error->code, error->message);
2722 g_clear_error(&error);
2724 err = BLUETOOTH_ERROR_INTERNAL;
2727 g_strfreev(line_argv);
2728 g_variant_builder_unref(outer_builder);
2729 g_variant_builder_unref(invalidated_builder);