4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include <hardware/bluetooth.h>
23 #include <hardware/bt_gatt.h>
38 #include "bt-hal-log.h"
39 #include "bt-hal-msg.h"
40 #include "bt-hal-utils.h"
41 #include "bt-hal-dbus-common-utils.h"
43 #include "bt-hal-adapter-le.h"
44 #include "bt-hal-event-receiver.h"
46 #define NUMBER_OF_FLAGS 10
48 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
49 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
50 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
52 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
53 #define GATT_SERV_OBJECT_PATH "/service"
55 static GDBusProxy *manager_gproxy = NULL;
57 /************************************************************************************
59 ************************************************************************************/
60 extern const btgatt_callbacks_t *bt_gatt_callbacks;
62 GDBusConnection *g_conn = NULL;
63 //GDBusConnection *conn = NULL;
64 GDBusNodeInfo *manager_node_info = NULL;
67 /* Global handles which needs to be incremented during each addition */
68 static int gatt_service_handle = 10;
69 static int gatt_char_handle = 20;
70 static int gatt_desc_handle = 30;
72 struct gatt_service_info {
79 gboolean is_svc_registered;
80 gboolean is_svc_primary;
84 struct gatt_char_info {
89 gchar *char_flags[NUMBER_OF_FLAGS];
96 struct gatt_desc_info {
101 gchar *desc_flags[NUMBER_OF_FLAGS];
108 * GATT Server Request type
111 BT_HAL_GATT_REQUEST_TYPE_READ = 0x00, /* Read Requested */
112 BT_HAL_GATT_REQUEST_TYPE_WRITE = 0x01, /* Write Requested */
113 BT_HAL_GATT_REQUEST_TYPE_EXEC_WRITE = 0x02, /* Exec Write Requested */
114 } bt_gatt_request_type_e;
116 struct gatt_req_info {
121 bt_gatt_request_type_e request_type; /* Read or Write request */
122 GDBusMethodInvocation *context;
125 struct gatt_server_app {
131 /* Linked List of gatt server app's */
132 static GSList *gatt_server_apps = NULL;
134 static GSList *gatt_services = NULL;
136 static int conn_id = 0;
138 /* Linked List of connected Remote GATT clients */
139 static GSList *gatt_client_info_list = NULL;
141 /* GATT Client Info List Structure */
142 struct gatt_client_info_t {
143 int connection_id; /* This value will uniquely identify a GATT client-server connection */
144 int instance_id; /* This value unique identifies a GATT server instance */
145 char *addr; /* Remote GATT client address */
146 GSList *gatt_req_info_list; /* List of transactions per Connection*/
149 static handle_stack_msg event_cb = NULL;
152 uint32_t instance_data;
154 } hal_register_server_data;
157 uint32_t instance_data;
161 } hal_gatt_service_added;
164 uint32_t instance_data;
166 } hal_gatt_service_started;
169 uint32_t instance_data;
171 } hal_gatt_service_deleted;
174 uint32_t instance_data;
178 } hal_gatt_char_added;
181 uint32_t instance_data;
185 } hal_gatt_desc_added;
187 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
189 ERR("%s: BTGATT not initialized", __FUNCTION__);\
190 return BT_STATUS_NOT_READY;\
192 DBG("%s", __FUNCTION__);\
195 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data);
197 static void __bt_hal_gatt_deinit(char *app_path);
199 static void __bt_hal_register_application_cb(GObject *object,
200 GAsyncResult *res, gpointer user_data);
202 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
205 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
206 const gchar *path, const gchar *interface);
208 /* Introspection data for the service we are exporting */
209 static const gchar service_introspection_xml[] =
211 " <interface name='org.freedesktop.DBus.Properties'>"
212 " <property type='s' name='UUID' access='read'>"
214 " <property type='b' name='primary' access='read'>"
216 " <property type='o' name='Device' access='read'>"
218 " <property type='ao' name='Characteristics' access='read'>"
220 " <property type='s' name='Includes' access='read'>"
225 /* Introspection data for the characteristics we are exporting */
226 static const gchar characteristics_introspection_xml[] =
228 " <interface name='org.bluez.GattCharacteristic1'>"
229 " <method name='ReadValue'>"
230 " <arg type='s' name='address' direction='in'/>"
231 " <arg type='y' name='id' direction='in'/>"
232 " <arg type='q' name='offset' direction='in'/>"
233 " <arg type='ay' name='Value' direction='out'/>"
235 " <method name='WriteValue'>"
236 " <arg type='s' name='address' direction='in'/>"
237 " <arg type='u' name='id' direction='in'/>"
238 " <arg type='q' name='offset' direction='in'/>"
239 " <arg type='b' name='response_needed' direction='in'/>"
240 " <arg type='ay' name='value' direction='in'/>"
242 " <method name='StartNotify'>"
244 " <method name='StopNotify'>"
246 " <method name='IndicateConfirm'>"
247 " <arg type='s' name='address' direction='in'/>"
248 " <arg type='b' name='complete' direction='in'/>"
251 " <interface name='org.freedesktop.DBus.Properties'>"
252 " <property type='s' name='UUID' access='read'>"
254 " <property type='o' name='Service' access='read'>"
256 " <property type='ay' name='Value' access='readwrite'>"
258 " <property type='b' name='Notifying' access='read'>"
260 " <property type='as' name='Flags' access='read'>"
262 " <property type='s' name='Unicast' access='read'>"
264 " <property type='ao' name='Descriptors' access='read'>"
269 /* Introspection data for the descriptor we are exporting */
270 static const gchar descriptor_introspection_xml[] =
272 " <interface name='org.bluez.GattDescriptor1'>"
273 " <method name='ReadValue'>"
274 " <arg type='s' name='address' direction='in'/>"
275 " <arg type='u' name='id' direction='in'/>"
276 " <arg type='q' name='offset' direction='in'/>"
277 " <arg type='ay' name='Value' direction='out'/>"
279 " <method name='WriteValue'>"
280 " <arg type='s' name='address' direction='in'/>"
281 " <arg type='u' name='id' direction='in'/>"
282 " <arg type='q' name='offset' direction='in'/>"
283 " <arg type='b' name='response_needed' direction='in'/>"
284 " <arg type='ay' name='value' direction='in'/>"
287 " <interface name='org.freedesktop.DBus.Properties'>"
288 " <property type='s' name='UUID' access='read'>"
290 " <property type='o' name='Characteristic' access='read'>"
292 " <property type='ay' name='Value' access='read'>"
294 " <property type='as' name='Flags' access='read'>"
300 static const gchar manager_introspection_xml[] =
302 " <interface name='org.freedesktop.DBus.ObjectManager'>"
303 " <method name='GetManagedObjects'>"
304 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
309 GSList *_bt_get_service_list_from_server(int instance)
312 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
313 INFO("Find App with slot [%d]", instance);
315 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
316 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
318 if (app->slot == instance) {
319 INFO("App slot [%d] Found, Number of services registered [%d]",
320 app->slot, g_slist_length(app->services));
321 return app->services;
327 void _bt_remote_service_from_gatt_server(int instance, int service_handle)
332 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
333 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
335 if (app->slot == instance) {
336 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
337 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
338 if (srv->service_handle == service_handle) {
339 app->services = g_slist_remove(app->services, srv);
347 void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
350 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
351 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
353 if (app->slot == slot) {
354 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
355 serv_info->service_handle, slot);
356 app->services = g_slist_append(app->services, serv_info);
361 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
364 struct gatt_client_info_t *info = NULL;
366 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
367 info = (struct gatt_client_info_t*)l->data;
371 if (!g_strcmp0(info->addr, address)) {
372 INFO("Remote GATT client found addr[%s]", info->addr);
379 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
382 struct gatt_client_info_t *info = NULL;
384 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
385 info = (struct gatt_client_info_t*)l->data;
389 if (info->connection_id == conn_id) {
390 INFO("Remote GATT client found addr[%s]", info->addr);
397 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
402 struct gatt_client_info_t *info = NULL;
403 struct gatt_req_info *info1 = NULL;
405 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
406 info = (struct gatt_client_info_t*)l->data;
410 if (info->connection_id == conn_id) {
412 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
414 info1 = (struct gatt_req_info*)l1->data;
418 if (info1->request_id == trans_id) {
419 INFO("Remote GATT client found addr[%s]", info->addr);
428 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
430 struct hal_ev_gatt_server_connected ev;
431 struct gatt_client_info_t *conn_info = NULL;
433 memset(&ev, 0, sizeof(ev));
435 /* Find Server Instance */
436 _bt_hal_get_gatt_server_instance_initialized(&instance);
437 if (instance == -1) {
438 ERR("Not even a single GATT server is registered");
442 /* Convert address to hex */
443 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
445 /* Create Connection ID */
446 /* Check if device is already in connected list */
447 conn_info = __bt_find_remote_gatt_client_info(address);
450 /* If disconnected, and conn info found, then remove conn info */
451 if (is_connected == FALSE) {
452 DBG("GATT Disconnected");
454 INFO("Remove GATT client info from List..");
455 /* Remove info from List */
456 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
457 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
460 ERR("GATT callback not registered");
462 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
463 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
464 ev.conn_id = conn_info->connection_id;
465 ev.server_instance = conn_info->instance_id;
466 ev.connected = is_connected;
468 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
470 g_free(conn_info->addr);
473 /* If connected, and conn info NOT found, then add conn info */
476 /* Save Connection info */
477 conn_info = g_new0(struct gatt_client_info_t, 1);
478 conn_info->addr = g_strdup(address);
479 INFO("Added GATT client addr[%s]", conn_info->addr);
480 conn_info->connection_id = ++conn_id;
481 conn_info->instance_id = instance;
482 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
483 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
486 ERR("GATT callback not registered");
488 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
489 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
490 ev.conn_id = conn_info->connection_id;
491 ev.server_instance = conn_info->instance_id;
492 ev.connected = is_connected;
494 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
498 /* Send GATT connected or disconnected event */
501 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
505 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
506 struct gatt_service_info *serv_info = l1->data;
508 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
509 struct gatt_char_info *char_info = l2->data;
511 if (g_strcmp0(char_info->char_path, char_path)
513 *char_hdl = char_info->char_handle;
518 ERR("Gatt service not found");
522 char *__bt_gatt_find_char_path_from_handle(int char_hdl)
526 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
527 struct gatt_service_info *serv_info = l1->data;
529 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
530 struct gatt_char_info *char_info = l2->data;
532 if (char_info->char_handle == char_hdl)
533 return char_info->char_path;
540 struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
544 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
545 struct gatt_service_info *serv_info = l1->data;
547 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
548 struct gatt_char_info *char_info = l2->data;
550 if (char_info->char_handle == char_hdl)
558 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
560 GSList *l1, *l2, *l3;
562 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
563 struct gatt_service_info *serv_info = l1->data;
565 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
566 struct gatt_char_info *char_info = l2->data;
568 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
569 struct gatt_desc_info *desc_info = l3->data;
571 if (g_strcmp0(desc_info->desc_path, desc_path)
573 *desc_hdl = desc_info->desc_handle;
579 ERR("Gatt service not found");
583 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
585 const gchar *object_path,
586 const gchar *interface_name,
587 const gchar *method_name,
588 GVariant *parameters,
589 GDBusMethodInvocation *invocation,
594 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
595 GVariantBuilder *builder;
596 GVariantBuilder *inner_builder1 = NULL;
597 GVariant *svc_char = NULL;
599 GSList *gatt_services = NULL;
601 instance = (int*)user_data;
603 DBG("Getting values for service, chars and descriptors");
604 DBG("GATT Server App for which services are requested [%d]", *instance);
607 builder = g_variant_builder_new(
608 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
611 gatt_services = _bt_get_service_list_from_server(*instance);
613 if (g_slist_length(gatt_services) == 0) {
614 ERR("No registered GATT services!!!!");
615 g_dbus_method_invocation_return_value(invocation, NULL);
619 for (l = gatt_services; l != NULL; l = l->next) {
620 GVariantBuilder *svc_builder = NULL;
621 GVariantBuilder *inner_builder = NULL;
622 struct gatt_service_info *serv_info = l->data;
623 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
625 /* Prepare inner builder for GattService1 interface */
626 DBG("Creating builder for service");
627 svc_builder = g_variant_builder_new(
628 G_VARIANT_TYPE("a{sa{sv}}"));
629 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
631 g_variant_builder_add(inner_builder, "{sv}", "UUID",
632 g_variant_new_string(serv_info->service_uuid));
634 g_variant_builder_add(inner_builder, "{sv}", "Primary",
635 g_variant_new_boolean(serv_info->is_svc_primary));
638 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
639 DBG("Adding Charatarisitcs list");
640 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
641 struct gatt_char_info *char_info = l4->data;
642 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
643 char_info->char_handle, serv_info->service_handle);
644 g_variant_builder_add(inner_builder1, "o",
645 char_info->char_path);
646 DBG("%s", char_info->char_path);
649 svc_char = g_variant_new("ao", inner_builder1);
650 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
653 g_variant_builder_add(svc_builder, "{sa{sv}}",
657 g_variant_builder_add(builder, "{oa{sa{sv}}}",
658 serv_info->serv_path,
661 g_variant_builder_unref(inner_builder1);
663 /* Prepare inner builder for GattCharacteristic1 interface */
665 GSList *l2 = serv_info->char_data;
666 DBG("Creating builder for characteristics \n");
669 DBG("characteristic data is NULL");
671 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
673 GVariantBuilder *char_builder = NULL;
674 GVariantBuilder *inner_builder = NULL;
675 GVariantBuilder *builder1 = NULL;
676 GVariantBuilder *builder2 = NULL;
677 GVariantBuilder *builder3 = NULL;
678 GVariant *char_val = NULL;
679 GVariant *flags_val = NULL;
680 GVariant *char_desc = NULL;
681 char *unicast = NULL;
682 gboolean notify = FALSE;
685 char_builder = g_variant_builder_new(
688 inner_builder = g_variant_builder_new(
692 struct gatt_char_info *char_info = l2->data;
693 if (char_info == NULL) {
694 ERR("char_info is NULL");
699 g_variant_builder_add(inner_builder, "{sv}", "UUID",
700 g_variant_new_string(char_info->char_uuid));
702 g_variant_builder_add(inner_builder, "{sv}", "Service",
703 g_variant_new("o", serv_info->serv_path));
705 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
707 if (char_info->char_value != NULL) {
708 for (i = 0; i < char_info->value_length; i++) {
709 g_variant_builder_add(builder1, "y",
710 char_info->char_value[i]);
712 char_val = g_variant_new("ay", builder1);
713 g_variant_builder_add(inner_builder, "{sv}",
717 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
718 for (i = 0; i < char_info->flags_length; i++) {
719 g_variant_builder_add(builder2, "s",
720 char_info->char_flags[i]);
723 flags_val = g_variant_new("as", builder2);
724 g_variant_builder_add(inner_builder, "{sv}", "Flags",
728 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
729 g_variant_new("b", notify));
732 unicast = g_strdup("00:00:00:00:00:00");
733 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
734 g_variant_new("s", unicast));
737 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
738 DBG("Adding Descriptors list");
740 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
741 struct gatt_desc_info *desc_info = l4->data;
742 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
743 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
744 g_variant_builder_add(builder3, "o",
745 desc_info->desc_path);
746 DBG("%s", desc_info->desc_path);
749 char_desc = g_variant_new("ao", builder3);
750 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
753 g_variant_builder_add(char_builder, "{sa{sv}}",
754 GATT_CHAR_INTERFACE , inner_builder);
755 g_variant_builder_add(builder, "{oa{sa{sv}}}",
756 char_info->char_path, char_builder);
758 /*Prepare inner builder for GattDescriptor1 interface*/
760 GSList *l3 = char_info->desc_data;
763 DBG("descriptor data is NULL");
765 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
767 DBG("Creating builder for descriptor \n");
769 GVariantBuilder *desc_builder = NULL;
770 GVariantBuilder *inner_builder = NULL;
771 GVariantBuilder *builder1 = NULL;
772 GVariantBuilder *builder2 = NULL;
773 GVariant *desc_val = NULL;
775 desc_builder = g_variant_builder_new(
778 inner_builder = g_variant_builder_new(
782 struct gatt_desc_info *desc_info = l3->data;
783 if (desc_info == NULL) {
784 ERR("desc_info is NULL");
789 g_variant_builder_add(inner_builder,
791 g_variant_new_string(
792 desc_info->desc_uuid));
795 g_variant_builder_add(inner_builder, "{sv}",
798 char_info->char_path));
801 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
803 if (desc_info->desc_value != NULL) {
804 for (i = 0; i < desc_info->value_length; i++) {
805 g_variant_builder_add(builder1, "y",
806 desc_info->desc_value[i]);
808 desc_val = g_variant_new("ay", builder1);
809 g_variant_builder_add(inner_builder, "{sv}",
814 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
816 for (i = 0; i < desc_info->flags_length; i++) {
817 g_variant_builder_add(builder2, "s",
818 desc_info->desc_flags[i]);
821 flags_val = g_variant_new("as", builder2);
822 g_variant_builder_add(inner_builder, "{sv}", "Flags",
825 g_variant_builder_add(desc_builder, "{sa{sv}}",
829 g_variant_builder_add(builder, "{oa{sa{sv}}}",
830 desc_info->desc_path,
833 /*unref descriptor builder pointers*/
834 g_variant_builder_unref(builder1);
835 g_variant_builder_unref(builder2);
836 g_variant_builder_unref(inner_builder);
837 g_variant_builder_unref(desc_builder);
842 /*unref char builder pointers*/
843 g_variant_builder_unref(builder1);
844 g_variant_builder_unref(builder2);
845 g_variant_builder_unref(builder3);
846 g_variant_builder_unref(inner_builder);
847 g_variant_builder_unref(char_builder);
850 /*unref service builder pointers*/
851 g_variant_builder_unref(inner_builder);
852 g_variant_builder_unref(svc_builder);
855 /* Return builder as method reply */
856 DBG("Sending gatt service builder values to Bluez");
857 g_dbus_method_invocation_return_value(invocation,
867 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
869 const gchar *object_path,
870 const gchar *interface_name,
871 const gchar *method_name,
872 GVariant *parameters,
873 GDBusMethodInvocation *invocation,
877 if (g_strcmp0(method_name, "ReadValue") == 0) {
878 struct hal_ev_gatt_server_read_req ev;
883 struct gatt_client_info_t *conn_info = NULL;
884 struct gatt_req_info *req_info = NULL;
885 struct gatt_service_info *svc_info = NULL;
889 DBG("Application path = %s", object_path);
890 DBG("Sender = %s", sender);
892 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
893 if (svc_info == NULL) {
894 ERR("Coudn't find service for %s", object_path);
895 g_dbus_method_invocation_return_value(invocation, NULL);
899 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
900 DBG("Request id = %u, Offset = %u", req_id, offset);
902 /* Check if device is already in connected list */
903 conn_info = __bt_find_remote_gatt_client_info(addr);
905 if (conn_info == NULL) {
906 ERR("Coudn't find Connection info for %s", addr);
907 g_dbus_method_invocation_return_value(invocation, NULL);
912 ERR("GATT callback NOT registered");
913 g_dbus_method_invocation_return_value(invocation, NULL);
917 /* Store requests information */
918 req_info = g_new0(struct gatt_req_info, 1);
919 req_info->attr_path = g_strdup(object_path);
920 req_info->svc_path = g_strdup(svc_info->serv_path);
921 req_info->request_id = req_id;
922 req_info->offset = offset;
923 req_info->context = invocation;
925 /* Append request info in list of requests for the particular connection */
926 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
929 memset(&ev, 0, sizeof(ev));
930 ev.conn_id = conn_info->connection_id;
931 ev.trans_id = req_id;
932 ev.att_handle = desc_hdl;
934 ev.is_long = false; /* TODO*/
936 /* Convert address to hex */
937 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
939 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
941 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
943 GVariant *var = NULL;
947 gboolean response_needed = FALSE;
948 struct hal_ev_gatt_server_write_req ev;
952 struct gatt_service_info *svc_info = NULL;
953 struct gatt_client_info_t *conn_info = NULL;
954 struct gatt_req_info *req_info = NULL;
956 memset(&ev, 0, sizeof(ev));
959 DBG("Application path = %s", object_path);
960 DBG("Sender = %s", sender);
962 g_variant_get(parameters, "(&suqb@ay)",
963 &addr, &req_id, &offset, &response_needed, &var);
964 DBG("Request id = %u, Offset = %u", req_id, offset);
966 /* Check if device is already in connected list */
967 conn_info = __bt_find_remote_gatt_client_info(addr);
969 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
971 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
972 g_variant_unref(var);
974 g_dbus_method_invocation_return_value(invocation, NULL);
976 g_object_unref(invocation);
980 len = g_variant_get_size(var);
981 if (len > 0 && len < 600) {
983 data = (char *)g_variant_get_data(var);
984 memcpy(ev.value, data, len);
987 if (response_needed) {
988 /* Store request information */
989 req_info = g_new0(struct gatt_req_info, 1);
990 req_info->attr_path = g_strdup(object_path);
991 req_info->svc_path = g_strdup(svc_info->serv_path);
992 req_info->request_id = req_id;
993 req_info->offset = offset;
994 req_info->context = invocation;
996 /* Append request info in list of requests for the particular connection */
997 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
999 g_object_unref(invocation);
1002 /* Send HAL event */
1003 ev.conn_id = conn_info->connection_id;
1004 ev.trans_id = req_id;
1005 ev.att_handle = desc_hdl;
1007 ev.need_rsp = response_needed;
1010 /* Convert address to hex */
1011 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1013 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1015 g_variant_unref(var);
1020 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1021 const gchar *sender,
1022 const gchar *object_path,
1023 const gchar *interface_name,
1024 const gchar *method_name,
1025 GVariant *parameters,
1026 GDBusMethodInvocation *invocation,
1029 if (g_strcmp0(method_name, "ReadValue") == 0) {
1033 struct hal_ev_gatt_server_read_req ev;
1036 struct gatt_req_info *req_info = NULL;
1037 struct gatt_client_info_t *conn_info = NULL;
1038 struct gatt_service_info *svc_info = NULL;
1040 DBG("Application path = %s", object_path);
1041 DBG("Sender = %s", sender);
1043 /* Check if device is already in connected list */
1044 conn_info = __bt_find_remote_gatt_client_info(addr);
1046 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1048 if (svc_info == NULL || conn_info == NULL) {
1049 g_dbus_method_invocation_return_value(invocation, NULL);
1054 ERR("GATT callback NOT registered");
1055 g_dbus_method_invocation_return_value(invocation, NULL);
1059 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1060 DBG("Request id = %u, Offset = %u", req_id, offset);
1062 /* Store requets information */
1063 req_info = g_new0(struct gatt_req_info, 1);
1064 req_info->attr_path = g_strdup(object_path);
1065 req_info->svc_path = g_strdup(svc_info->serv_path);
1066 req_info->request_id = req_id;
1067 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1068 req_info->offset = offset;
1069 req_info->context = invocation;
1071 /* Append request info in list of requests for the particular connection */
1072 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1074 /* Send HAL event */
1075 memset(&ev, 0, sizeof(ev));
1076 ev.conn_id = conn_info->connection_id;
1077 ev.trans_id = req_id;
1078 ev.att_handle = char_hdl;
1080 ev.is_long = false; /* TODO*/
1082 /* Convert address to hex */
1083 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1085 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1087 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1088 GVariant *var = NULL;
1092 gboolean response_needed = FALSE;
1093 struct hal_ev_gatt_server_write_req ev;
1097 struct gatt_service_info *svc_info = NULL;
1098 struct gatt_req_info *req_info = NULL;
1099 struct gatt_client_info_t *conn_info = NULL;
1101 memset(&ev, 0, sizeof(ev));
1104 DBG("Application path = %s", object_path);
1105 DBG("Sender = %s", sender);
1107 g_variant_get(parameters, "(&suqb@ay)",
1108 &addr, &req_id, &offset, &response_needed, &var);
1109 DBG("Request id = %u, Offset = %u", req_id, offset);
1111 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1113 /* Check if device is already in connected list */
1114 conn_info = __bt_find_remote_gatt_client_info(addr);
1116 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1117 g_variant_unref(var);
1118 if (response_needed)
1119 g_dbus_method_invocation_return_value(invocation, NULL);
1121 g_object_unref(invocation);
1125 len = g_variant_get_size(var);
1126 if (len > 0 && len < 600) {
1128 data = (char *)g_variant_get_data(var);
1129 memcpy(ev.value, data, len);
1133 if (response_needed) {
1134 /* Store requets information */
1135 req_info = g_new0(struct gatt_req_info, 1);
1136 req_info->attr_path = g_strdup(object_path);
1137 req_info->svc_path = g_strdup(svc_info->serv_path);
1138 req_info->request_id = req_id;
1139 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1140 req_info->offset = offset;
1141 req_info->context = invocation;
1143 /* Append request info in list of requests for the particular connection */
1144 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1147 g_object_unref(invocation);
1150 /* Send HAL event */
1151 ev.conn_id = conn_info->connection_id;
1152 ev.trans_id = req_id;
1153 ev.att_handle = char_hdl;
1155 ev.need_rsp = response_needed;
1158 /* Convert address to hex */
1159 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1161 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1163 g_variant_unref(var);
1166 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1169 struct gatt_service_info *svc_info = NULL;
1170 struct hal_ev_gatt_server_notifcation_change ev;
1173 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1174 if (svc_info == NULL || event_cb == NULL)
1177 /* Send HAL event */
1178 memset(&ev, 0, sizeof(ev));
1179 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1180 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1181 ev.att_handle = char_hdl;
1184 /* Convert address to hex */
1185 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1187 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1190 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1193 struct gatt_service_info *svc_info = NULL;
1194 struct hal_ev_gatt_server_notifcation_change ev;
1197 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1198 if (svc_info == NULL || event_cb == NULL)
1201 /* Send HAL event */
1202 memset(&ev, 0, sizeof(ev));
1203 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1204 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1205 ev.att_handle = char_hdl;
1208 /* Convert address to hex */
1209 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1211 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1214 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1216 gboolean complete = FALSE;
1219 struct gatt_service_info *svc_info = NULL;
1220 struct gatt_client_info_t *conn_info = NULL;
1222 struct hal_ev_gatt_server_indicate_cfm ev;
1224 DBG("IndicateConfirm");
1225 DBG("Application path = %s", object_path);
1226 DBG("Sender = %s", sender);
1228 g_variant_get(parameters, "(&sb)", &addr, &complete);
1229 DBG("Remote Device address number = %s", addr);
1230 DBG("Is Indicate confirmation for last device [%d]", complete);
1232 /* Check if device is already in connected list */
1233 conn_info = __bt_find_remote_gatt_client_info(addr);
1235 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1237 if (svc_info == NULL || conn_info == NULL
1238 || event_cb == NULL) {
1242 /* Send HAL event */
1243 memset(&ev, 0, sizeof(ev));
1244 ev.conn_id = conn_info->connection_id;
1245 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1246 ev.att_handle = char_hdl;
1248 /* Convert address to hex */
1249 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1251 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1254 g_dbus_method_invocation_return_value(invocation, NULL);
1257 gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1260 GError *error = NULL;
1261 GVariantBuilder *array_builder;
1263 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1264 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1265 g_variant_builder_add(array_builder, "s", interface);
1267 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1268 "org.freedesktop.Dbus.Objectmanager",
1269 "InterfacesRemoved",
1270 g_variant_new("(oas)",
1271 object_path, array_builder),
1275 if (error != NULL) {
1276 /* dbus gives error cause */
1277 ERR("d-bus api failure: errcode[%x], message[%s]",
1278 error->code, error->message);
1279 g_clear_error(&error);
1282 g_variant_builder_unref(array_builder);
1287 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1294 g_free(desc_info->desc_path);
1295 g_free(desc_info->desc_uuid);
1296 g_free(desc_info->desc_value);
1298 for (i = 0; i < desc_info->flags_length; i++)
1299 g_free(desc_info->desc_flags[i]);
1304 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1311 g_free(char_info->char_path);
1312 g_free(char_info->char_uuid);
1313 g_free(char_info->char_value);
1315 for (i = 0; i < char_info->flags_length; i++)
1316 g_free(char_info->char_flags[i]);
1322 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1327 g_free(svc_info->serv_path);
1328 g_free(svc_info->service_uuid);
1332 static const GDBusInterfaceVTable desc_interface_vtable = {
1333 __bt_gatt_desc_method_call,
1338 static const GDBusInterfaceVTable char_interface_vtable = {
1339 __bt_gatt_char_method_call,
1344 static const GDBusInterfaceVTable serv_interface_vtable = {
1350 static const GDBusInterfaceVTable manager_interface_vtable = {
1351 __bt_gatt_manager_method_call,
1357 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1358 const gchar *introspection_data)
1361 GDBusNodeInfo *node_info = NULL;
1363 if (introspection_data == NULL)
1367 DBG("Create new node info");
1368 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1371 ERR("Unable to create node: %s", err->message);
1372 g_clear_error(&err);
1379 /* To send stack event to hal-av handler */
1380 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1385 void _bt_hal_unregister_gatt_server_handler_cb(void)
1390 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1392 struct hal_ev_gatt_desc_added ev;
1393 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1395 /* Prepare to GATT characteristic added event */
1396 memset(&ev, 0, sizeof(ev));
1397 ev.status = BT_STATUS_SUCCESS;
1398 ev.server_instance = data->instance_data;
1399 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1400 ev.service_handle = data->srvc_hdl;
1401 ev.desc_handle = data->desc_hdl;
1404 ERR("GATT Descriptor Added callback registered");
1406 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1407 data->instance_data, data->srvc_hdl, data->desc_hdl);
1409 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1416 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1418 struct hal_ev_gatt_char_added ev;
1419 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1421 /* Prepare to GATT characteristic added event */
1422 memset(&ev, 0, sizeof(ev));
1423 ev.status = BT_STATUS_SUCCESS;
1424 ev.server_instance = data->instance_data;
1425 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1426 ev.service_handle = data->srvc_hdl;
1427 ev.char_handle = data->char_hdl;
1430 ERR("GATT Characteristic Added callback registered");
1432 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1433 data->instance_data, data->srvc_hdl, data->char_hdl);
1435 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1442 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1444 struct hal_ev_gatt_service_added ev;
1445 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1447 /* Prepare to GATT Service added event */
1448 memset(&ev, 0, sizeof(ev));
1449 ev.status = BT_STATUS_SUCCESS;
1450 ev.server_instance = data->instance_data;
1451 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1452 ev.service_handle = data->srvc_hdl;
1453 ev.is_primary = data->is_primary;
1456 ERR("GATT Service Added callback registered");
1458 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1459 data->instance_data, data->srvc_hdl);
1460 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1467 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1469 struct hal_ev_gatt_service_started ev;
1470 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1472 /* Prepare to GATT Service added event */
1473 memset(&ev, 0, sizeof(ev));
1474 ev.status = BT_STATUS_SUCCESS;
1475 ev.server_instance = data->instance_data;
1476 ev.service_handle = data->srvc_hdl;
1479 ERR("GATT Service Started callback registered");
1481 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1482 data->instance_data, data->srvc_hdl);
1483 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1490 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1492 struct hal_ev_gatt_service_deleted ev;
1493 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1495 /* Prepare to GATT Service added event */
1496 memset(&ev, 0, sizeof(ev));
1497 ev.status = BT_STATUS_SUCCESS;
1498 ev.server_instance = data->instance_data;
1499 ev.service_handle = data->srvc_hdl;
1502 ERR("GATT Service Deleted callback registered");
1504 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1505 data->instance_data, data->srvc_hdl);
1506 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1513 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1515 struct hal_ev_server_instance_registered ev;
1516 hal_register_server_data *data = (hal_register_server_data*) user_data;
1518 /* Prepare to send AV connecting event */
1519 memset(&ev, 0, sizeof(ev));
1520 ev.status = BT_STATUS_SUCCESS;
1521 ev.server_instance = data->instance_data;
1522 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1525 ERR("GATT Register Server Instance Callback not registered");
1527 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1528 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1535 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1537 CHECK_BTGATT_INIT();
1538 int status = BT_STATUS_FAIL;
1540 DBG("Register server instance request");
1541 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1543 /* Check if slot available */
1544 server_if = _bt_hal_get_available_adv_slot_id(uuid);
1546 if (server_if == -1) {
1547 ERR("Allocation of server instance failed");
1551 user_data->instance_data = server_if;
1552 DBG("Allocated new Advertising slot with Stack [%d]", user_data->instance_data);
1556 * As we need to provide async callback to user from HAL, simply schedule a
1557 * callback method which will carry actual result
1559 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1560 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1562 /* If available, then return success, else return error */
1563 return BT_STATUS_SUCCESS;
1566 void _bt_hal_remove_gatt_server_from_list(int server_if)
1569 struct gatt_server_app *info = NULL;
1571 for (l = gatt_server_apps; l != NULL;) {
1572 info = (struct gatt_server_app*)l->data;
1573 l = g_slist_next(l);
1576 if (info->slot == server_if) {
1577 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1578 info->app_path, info->slot);
1580 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1581 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1582 In above case, only advertising block will be deallocated, Gatt Server will remain
1584 if (info->services == NULL) {
1585 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1586 INFO("Total gatt server apps still existing after removing above is [%d]",
1587 g_slist_length(gatt_server_apps));
1589 /* DBUS Unregister only for current app */
1590 __bt_hal_gatt_deinit(info->app_path);
1592 g_free(info->app_path);
1596 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1597 g_slist_length(info->services));
1603 static bt_status_t gatt_server_unregister_app(int server_if)
1605 CHECK_BTGATT_INIT();
1606 DBG("Un-Register server instance request [%d]", server_if);
1608 if (_bt_hal_is_advertising_in_slot(server_if) == FALSE)
1609 _bt_hal_free_server_slot(server_if);
1611 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
1612 _bt_hal_remove_gatt_server_from_list(server_if);
1613 return BT_STATUS_SUCCESS;
1616 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
1618 CHECK_BTGATT_INIT();
1619 return BT_STATUS_SUCCESS;
1622 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
1624 CHECK_BTGATT_INIT();
1625 return BT_STATUS_SUCCESS;
1628 static void __bt_gatt_close_gdbus_connection(void)
1636 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
1637 ERR("Fail to flush the connection: %s", err->message);
1642 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
1644 ERR("Fail to close the dbus connection: %s", err->message);
1649 g_object_unref(g_conn);
1654 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1656 GDBusConnection *local_system_gconn = NULL;
1660 if (g_conn == NULL) {
1661 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1662 if (address == NULL) {
1664 ERR("Failed to get bus address: %s", err->message);
1665 g_clear_error(&err);
1670 g_conn = g_dbus_connection_new_for_address_sync(address,
1671 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1672 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1673 NULL, /* GDBusAuthObserver */
1678 ERR("Unable to connect to dbus: %s", err->message);
1679 g_clear_error(&err);
1683 } else if (g_dbus_connection_is_closed(g_conn)) {
1684 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1685 if (address == NULL) {
1687 ERR("Failed to get bus address: %s", err->message);
1688 g_clear_error(&err);
1693 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1694 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1695 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1696 NULL, /* GDBusAuthObserver */
1700 if (!local_system_gconn) {
1701 ERR("Unable to connect to dbus: %s", err->message);
1702 g_clear_error(&err);
1705 g_conn = local_system_gconn;
1711 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
1716 uuid = btuuid2str(srvc_id->uu);
1717 DBG("Original UUID [%s]", uuid);
1719 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
1720 /* Extract Standard UUID string */
1721 memcpy(uuid_buf, &uuid[4], 4);
1723 DBG("Converted string [%s]", uuid_buf);
1724 return g_strdup(uuid_buf);
1726 return strdup(uuid);
1729 int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
1732 /* For GATT service specific */
1733 GDBusNodeInfo *node_info;
1736 struct gatt_service_info *serv_info = NULL;
1737 GVariantBuilder *builder = NULL;
1738 GVariantBuilder *builder1 = NULL;
1739 GVariantBuilder *inner_builder = NULL;
1740 gboolean svc_primary = TRUE;
1741 GError *error = NULL;
1742 hal_gatt_service_added *user_data = NULL;
1743 DBG("Service add to DBUS slot [%d]", slot);
1745 node_info = __bt_gatt_create_method_node_info(
1746 service_introspection_xml);
1748 if (node_info == NULL)
1749 return BT_STATUS_FAIL;
1751 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
1752 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
1753 DBG("gatt service path is [%s]", path);
1755 object_id = g_dbus_connection_register_object(g_conn, path,
1756 node_info->interfaces[0],
1757 &serv_interface_vtable,
1758 NULL, NULL, &error);
1760 if (object_id == 0) {
1761 ERR("failed to register: %s", error->message);
1762 g_error_free(error);
1764 return BT_STATUS_FAIL;
1766 /* Add object_id/gatt service information; it's required at the time of
1767 * service unregister and Getmanagedobjects
1769 serv_info = g_new0(struct gatt_service_info, 1);
1771 serv_info->serv_path = g_strdup(path);
1772 serv_info->serv_id = object_id;
1773 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
1774 serv_info->is_svc_registered = FALSE;
1775 serv_info->is_svc_primary = svc_primary;
1776 DBG("Service Handle to be added is [%d]", gatt_service_handle);
1777 serv_info->service_handle = gatt_service_handle;
1779 /* Update service in GATT Server service List */
1780 gatt_services = g_slist_append(gatt_services, serv_info);
1782 /* emit interfacesadded signal here for service path */
1783 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1784 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1786 g_variant_builder_add(inner_builder, "{sv}",
1787 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
1789 g_variant_builder_add(inner_builder, "{sv}",
1790 "Primary", g_variant_new_boolean(svc_primary));
1792 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1794 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1795 g_variant_new("ao", builder1));
1797 g_variant_builder_add(builder, "{sa{sv}}",
1798 GATT_SERV_INTERFACE, inner_builder);
1800 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1801 "org.freedesktop.Dbus.ObjectManager",
1803 g_variant_new("(oa{sa{sv}})",
1808 /* dbus gives error cause */
1809 ERR("d-bus api failure: errcode[%x], message[%s]",
1810 error->code, error->message);
1811 g_clear_error(&error);
1815 /* Send Service handle to application */
1816 user_data = g_malloc0(sizeof(hal_gatt_service_added));
1817 user_data->srvc_hdl = serv_info->service_handle;
1818 user_data->instance_data = slot;
1819 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
1820 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
1822 /* Save newly created service in GATT Server's service list */
1823 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
1827 g_variant_builder_unref(inner_builder);
1828 g_variant_builder_unref(builder);
1829 g_variant_builder_unref(builder1);
1830 return BT_STATUS_SUCCESS;
1833 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
1836 char *app_path = (char*)user_data;
1837 INFO("UnregisterApplication is completed app [%s]", app_path);
1838 GError *error = NULL;
1839 GVariant *result = NULL;
1842 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1844 if (result == NULL) {
1845 /* dBUS-RPC is failed */
1846 ERR("Dbus-RPC is failed\n");
1848 if (error != NULL) {
1849 /* dBUS gives error cause */
1850 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1851 error->code, error->message);
1852 g_clear_error(&error);
1855 g_variant_unref(result);
1860 static void __bt_hal_gatt_deinit(char *app_path)
1862 GDBusProxy *proxy = NULL;
1866 /* Step1: Remove requested App */
1867 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
1868 "/org/bluez/hci0", "org.bluez.GattManager1");
1873 INFO("UnregisterApplication : path [%s]", app_path);
1875 /* Async Call to Unregister Service */
1876 data = g_strdup(app_path);
1877 g_dbus_proxy_call(proxy,
1878 "UnregisterApplication",
1879 g_variant_new("(o)",
1881 G_DBUS_CALL_FLAGS_NONE, -1,
1883 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
1886 /* If requested app is last GATT Server app, then clean all resources */
1887 if (gatt_server_apps == NULL) {
1888 INFO("All GATT servers are removed, clean all DBUS resources");
1890 /* unregister the exported interface for object manager
1891 g_conn and manager_id are common for all GATT servers */
1892 g_dbus_connection_unregister_object(g_conn,
1895 g_bus_unown_name(owner_id);
1898 g_object_unref(manager_gproxy);
1899 manager_gproxy = NULL;
1901 /* Close the GDBUS connection */
1902 __bt_gatt_close_gdbus_connection();
1908 int __bt_hal_gatt_init(void)
1910 GDBusConnection *conn = NULL;
1912 /* Only once for ALL GATT Servers */
1913 if (owner_id == 0) {
1914 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1915 BT_GATT_SERVICE_NAME,
1916 G_BUS_NAME_OWNER_FLAGS_NONE,
1917 NULL, NULL, NULL, NULL, NULL);
1919 INFO("Owner ID [%d]", owner_id);
1921 /* Only once for ALL GATT Servers conn = g_conn(global)*/
1922 conn = __bt_gatt_get_gdbus_connection();
1924 ERR("Unable to get connection");
1925 return BT_STATUS_FAIL;
1928 /* Only once for ALL GATT Servers */
1929 if (manager_node_info == NULL) {
1930 /* Register ObjectManager interface */
1931 manager_node_info = __bt_gatt_create_method_node_info(
1932 manager_introspection_xml);
1934 if (manager_node_info == NULL) {
1935 ERR("failed to get node info");
1936 return BT_STATUS_FAIL;
1941 return BT_STATUS_SUCCESS;
1944 void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
1948 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
1949 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
1950 if (app->slot == slot) {
1951 INFO("GATT Server app found app path [%s] instance [%d]",
1952 app->app_path, app->slot);
1953 *app_path = app->app_path;
1957 /* GATT Server not found */
1961 void _bt_hal_update_gatt_server_path(int slot, char *app_path)
1963 if (app_path == NULL)
1966 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
1967 app->app_path = g_strdup(app_path);
1969 gatt_server_apps = g_slist_append(gatt_server_apps, app);
1970 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
1975 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
1978 CHECK_BTGATT_INIT();
1979 char *app_path = NULL;
1980 GError *error = NULL;
1984 int result = BT_STATUS_SUCCESS;
1986 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
1987 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
1989 /* Check if this GATT server Application is already registered with DBUS */
1990 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
1992 if (app_path != NULL) {
1993 DBG("GATT server path is already defined [%s]", app_path);
1994 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
1996 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
1997 result = __bt_hal_gatt_init();
1998 if (result != BT_STATUS_SUCCESS)
2001 /* Only once for each GATT Server */
2002 app_path = g_strdup_printf("/com/%d", server_if);
2004 app_id = g_malloc0(sizeof(int));
2005 *app_id = server_if;
2007 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2008 manager_node_info->interfaces[0],
2009 &manager_interface_vtable,
2010 (gpointer)app_id, NULL, &error);
2012 if (manager_id == 0) {
2013 ERR("failed to register: %s", error->message);
2014 g_error_free(error);
2018 /* For current GATT Server, app_path is created, save it in Table */
2019 _bt_hal_update_gatt_server_path(server_if, app_path);
2021 /* Add GATT Service to DBUS */
2022 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2028 INFO("Successfully added service");
2029 return BT_STATUS_SUCCESS;
2036 INFO("Service addition failed!!");
2037 return BT_STATUS_FAIL;
2040 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2041 int included_handle)
2043 CHECK_BTGATT_INIT();
2044 return BT_STATUS_SUCCESS;
2048 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2051 GSList *gatt_services = NULL;
2053 struct gatt_service_info *info = NULL;
2055 gatt_services = _bt_get_service_list_from_server(instance);
2057 len = g_slist_length(gatt_services);
2058 l = g_slist_nth(gatt_services, len -1);
2064 if (info->service_handle == service_handle)
2069 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2073 GSList *gatt_services = NULL;
2074 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2076 gatt_services = _bt_get_service_list_from_server(instance);
2078 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2079 struct gatt_service_info *info = l->data;
2080 INFO("Got one service with handle [%d]", info->service_handle);
2081 if (info->service_handle == service_handle)
2084 ERR("Gatt service with handle [%d] not found", service_handle);
2088 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2089 bt_uuid_t *uuid, int properties,
2093 GError *error = NULL;
2095 GDBusNodeInfo *node_info;
2097 GVariantBuilder *builder = NULL;
2098 GVariantBuilder *inner_builder = NULL;
2099 struct gatt_service_info *serv_info = NULL;
2100 struct gatt_char_info *char_info = NULL;
2101 GVariantBuilder *builder2 = NULL;
2102 GVariantBuilder *builder3 = NULL;
2103 GVariant *flags_val = NULL;
2105 char *char_flags[NUMBER_OF_FLAGS];
2107 hal_gatt_char_added *user_data = NULL;
2110 CHECK_BTGATT_INIT();
2111 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2112 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2114 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2115 if (serv_info == NULL)
2116 return BT_STATUS_FAIL;
2118 node_info = __bt_gatt_create_method_node_info(
2119 characteristics_introspection_xml);
2121 if (node_info == NULL)
2122 return BT_STATUS_FAIL;
2124 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2125 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2126 DBG("gatt characteristic path is [%s]", path);
2128 app_id = g_malloc0(sizeof(int));
2131 object_id = g_dbus_connection_register_object(g_conn, path,
2132 node_info->interfaces[0],
2133 &char_interface_vtable,
2134 (gpointer)app_id, NULL, &error);
2136 if (object_id == 0) {
2137 ERR("failed to register: %s", error->message);
2138 g_error_free(error);
2141 return BT_STATUS_FAIL;
2144 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2145 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2146 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2147 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2148 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2149 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2150 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2151 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2153 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2155 char_info = g_new0(struct gatt_char_info, 1);
2157 char_info->char_path = g_strdup(path);
2158 char_info->char_id = object_id;
2159 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2160 for (i = 0; i < flag_count; i++)
2161 char_info->char_flags[i] = char_flags[i];
2164 char_info->flags_length = flag_count;
2165 char_info->char_handle = gatt_char_handle;
2168 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2169 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2171 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2172 g_variant_new("s", char_info->char_uuid));
2173 g_variant_builder_add(inner_builder, "{sv}", "Service",
2174 g_variant_new("o", serv_info->serv_path));
2176 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2178 for (i = 0; i < flag_count; i++)
2179 g_variant_builder_add(builder2, "s", char_flags[i]);
2181 flags_val = g_variant_new("as", builder2);
2182 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2185 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2187 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2188 g_variant_new("ao", builder3));
2190 g_variant_builder_add(builder, "{sa{sv}}",
2191 GATT_CHAR_INTERFACE,
2194 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2195 "org.freedesktop.Dbus.ObjectManager",
2197 g_variant_new("(oa{sa{sv}})",
2202 /* dbus gives error cause */
2203 ERR("d-bus api failure: errcode[%x], message[%s]",
2204 error->code, error->message);
2205 g_clear_error(&error);
2209 //*char_path = g_strdup(path);
2214 /* Send Service handle to application */
2215 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2216 user_data->srvc_hdl = serv_info->service_handle;
2217 user_data->char_hdl = gatt_char_handle;
2218 user_data->instance_data = slot;
2219 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2220 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2222 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2223 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2228 g_variant_builder_unref(inner_builder);
2229 g_variant_builder_unref(builder);
2230 g_variant_builder_unref(builder2);
2231 g_variant_builder_unref(builder3);
2233 return BT_STATUS_SUCCESS;
2236 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2239 CHECK_BTGATT_INIT();
2241 // static int desc_id = 1;
2242 GError *error = NULL;
2244 GDBusNodeInfo *node_info;
2246 GVariantBuilder *builder = NULL;
2247 GVariantBuilder *inner_builder = NULL;
2249 struct gatt_char_info *char_info = NULL;
2250 struct gatt_desc_info *desc_info = NULL;
2251 struct gatt_service_info *serv_info = NULL;
2253 gchar **line_argv = NULL;
2255 char *char_path = NULL;
2258 GVariantBuilder *builder2 = NULL;
2259 GVariant *flags_val = NULL;
2261 char *desc_flags[NUMBER_OF_FLAGS];
2265 hal_gatt_desc_added *user_data = NULL;
2272 /* Fetch service data for the GATT server */
2273 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2274 if (serv_info == NULL)
2275 return BT_STATUS_FAIL;
2277 /* Fetch list of characteristics from the service info */
2278 l = serv_info->char_data;
2280 /* Fetch last char info from the characteristic list */
2281 char_info = g_slist_last(l)->data;
2282 if (char_info == NULL)
2283 return BT_STATUS_FAIL;
2285 /* Fetch characteristic path from char info */
2286 char_path = char_info->char_path;
2288 line_argv = g_strsplit_set(char_path, "/", 0);
2289 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2292 node_info = __bt_gatt_create_method_node_info(
2293 descriptor_introspection_xml);
2295 if (node_info == NULL) {
2296 g_strfreev(line_argv);
2298 return BT_STATUS_FAIL;
2301 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2303 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2304 DBG("gatt descriptor path is [%s]", path);
2306 app_id = g_malloc0(sizeof(int));
2309 object_id = g_dbus_connection_register_object(g_conn, path,
2310 node_info->interfaces[0],
2311 &desc_interface_vtable,
2312 (gpointer)app_id, NULL, &error);
2314 if (object_id == 0) {
2315 ERR("failed to register: %s", error->message);
2316 g_error_free(error);
2318 g_strfreev(line_argv);
2321 return BT_STATUS_FAIL;
2324 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2326 desc_info = g_new0(struct gatt_desc_info, 1);
2328 desc_info->desc_path = g_strdup(path);
2329 desc_info->desc_id = object_id;
2330 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2332 for (i = 0; i < flag_count; i++)
2333 desc_info->desc_flags[i] = desc_flags[i];
2335 desc_info->flags_length = flag_count;
2336 desc_info->desc_handle = gatt_desc_handle;
2339 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2340 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2342 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2343 g_variant_new("s", btuuid2str(uuid->uu)));
2344 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2345 g_variant_new("o", char_path));
2347 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2349 for (i = 0; i < flag_count; i++)
2350 g_variant_builder_add(builder2, "s", desc_flags[i]);
2352 flags_val = g_variant_new("as", builder2);
2353 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2356 g_variant_builder_add(builder, "{sa{sv}}",
2357 GATT_DESC_INTERFACE,
2360 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2361 "org.freedesktop.Dbus.ObjectManager",
2363 g_variant_new("(oa{sa{sv}})",
2367 //*desc_path = g_strdup(path);
2369 /* Save newly created descriptor to GATT server's service's characteristic */
2370 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2372 /* Send descriptor handle to application */
2373 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2374 user_data->srvc_hdl = serv_info->service_handle;
2375 user_data->desc_hdl = gatt_desc_handle;
2376 user_data->instance_data = slot;
2377 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2378 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2383 g_strfreev(line_argv);
2384 g_variant_builder_unref(inner_builder);
2385 g_variant_builder_unref(builder);
2386 return BT_STATUS_SUCCESS;
2389 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2391 GError *error = NULL;
2393 char *data = (char*) user_data;
2394 INFO("RegisterApplication is completed path [%s]", data);
2396 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2398 if (result == NULL) {
2399 /* dBUS-RPC is failed */
2400 ERR("Dbus-RPC is failed\n");
2402 if (error != NULL) {
2403 /* dBUS gives error cause */
2404 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2405 error->code, error->message);
2406 g_clear_error(&error);
2409 g_variant_unref(result);
2414 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2415 const gchar *path, const gchar *interface)
2421 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2426 ERR("Unable to connect to gdbus: %s", err->message);
2427 g_clear_error(&err);
2432 proxy = g_dbus_proxy_new_sync(g_conn,
2433 G_DBUS_PROXY_FLAGS_NONE, NULL,
2435 interface, NULL, &err);
2439 ERR("Unable to create proxy: %s", err->message);
2440 g_clear_error(&err);
2444 manager_gproxy = proxy;
2449 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2450 const gchar *path, const gchar *interface)
2452 return (manager_gproxy) ? manager_gproxy :
2453 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2457 static void __bt_register_application_to_dbus(int slot)
2459 GDBusProxy *proxy = NULL;
2460 char *app_path = NULL;
2462 DBG("RegisterApplication slot [%d]", slot);
2464 /* It is impossible that app path is still not initialized */
2465 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2467 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2468 "/org/bluez/hci0", "org.bluez.GattManager1");
2470 data = g_strdup(app_path);
2471 g_dbus_proxy_call(proxy,
2472 "RegisterApplication",
2473 g_variant_new("(oa{sv})",
2475 G_DBUS_CALL_FLAGS_NONE, -1,
2477 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2479 INFO("GATT server started");
2482 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2484 CHECK_BTGATT_INIT();
2485 struct gatt_service_info *serv_info = NULL;
2486 hal_gatt_service_started *user_data = NULL;
2487 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2489 /* Fetch service data for the GATT server */
2490 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2491 if (serv_info == NULL)
2492 return BT_STATUS_FAIL;
2494 if (serv_info->is_svc_registered)
2495 DBG("service already registered \n");
2497 serv_info->is_svc_registered = TRUE;
2499 /* Send Service handle to application */
2500 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2501 user_data->srvc_hdl = serv_info->service_handle;
2502 user_data->instance_data = server_if;
2503 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2505 /* If this is nth Service that is started, then register application at this point */
2506 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2507 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2509 __bt_register_application_to_dbus(server_if);
2512 return BT_STATUS_SUCCESS;
2515 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2517 CHECK_BTGATT_INIT();
2518 INFO("Stop service successful");
2519 return BT_STATUS_SUCCESS;
2522 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2524 CHECK_BTGATT_INIT();
2525 struct gatt_service_info *serv_info = NULL;
2526 hal_gatt_service_deleted *user_data = NULL;
2529 int err = BT_STATUS_SUCCESS;
2530 int ret = BT_STATUS_SUCCESS;
2531 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2533 /* Fetch service data for the GATT server */
2534 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2535 if (serv_info == NULL) {
2536 ERR("Could not find service info svc handle [%d] server slot [%d]",
2537 service_handle, server_if);
2538 return BT_STATUS_FAIL;
2541 if (serv_info->is_svc_registered == FALSE) {
2542 ERR("service Not registered path [%s] handle [%d]",
2543 serv_info->serv_path, service_handle);
2546 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2547 struct gatt_char_info *char_info = l->data;
2549 if (char_info == NULL)
2552 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2553 struct gatt_desc_info *desc_info = l1->data;
2555 if (desc_info == NULL)
2558 ret = g_dbus_connection_unregister_object(g_conn,
2559 desc_info->desc_id);
2561 __bt_hal_gatt_emit_interface_removed(
2562 desc_info->desc_path,
2563 GATT_DESC_INTERFACE);
2565 err = BT_STATUS_FAIL;
2568 /* list remove & free */
2569 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2570 __bt_hal_gatt_free_descriptor_info(desc_info);
2573 g_slist_free(char_info->desc_data);
2574 char_info->desc_data = NULL;
2576 ret = g_dbus_connection_unregister_object(g_conn,
2577 char_info->char_id);
2579 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2580 GATT_CHAR_INTERFACE);
2583 err = BT_STATUS_FAIL;
2586 /* list remove & free */
2587 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2588 __bt_hal_gatt_free_characteristic_info(char_info);
2591 g_slist_free(serv_info->char_data);
2592 serv_info->char_data = NULL;
2594 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2596 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2597 GATT_SERV_INTERFACE);
2600 err = BT_STATUS_FAIL;
2603 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
2605 DBG("Unregistered the service on properties interface");
2607 /* Remove from global list */
2608 gatt_services = g_slist_remove(gatt_services, serv_info);
2609 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
2611 /* Remove from GATT Server's list of services */
2612 _bt_remote_service_from_gatt_server(server_if, service_handle);
2614 if (gatt_services == NULL)
2615 INFO("All GATT Services of all GATT Servers are unregistered");
2617 if (err == BT_STATUS_SUCCESS) {
2618 INFO("Send GATT Service deleted Event");
2619 /* Send Service handle to application */
2620 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
2621 user_data->srvc_hdl = serv_info->service_handle;
2622 user_data->instance_data = server_if;
2623 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
2626 /* Free the service */
2627 __bt_hal_gatt_free_service_info(serv_info);
2631 static gboolean __bt_gatt_get_service_state(const char *service_path)
2633 struct gatt_service_info *svc_info = NULL;
2636 for (l = gatt_services; l; l = g_slist_next(l)) {
2638 svc_info = (struct gatt_service_info *)l->data;
2639 if (svc_info->serv_path == service_path) {
2640 DBG("Return the state of the gatt service %d",
2641 svc_info->is_svc_registered);
2642 return svc_info->is_svc_registered;
2646 DBG("gatt service info is NULL");
2650 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
2651 int len, int confirm, char* p_value)
2653 CHECK_BTGATT_INIT();
2656 GVariantBuilder *outer_builder;
2657 GVariantBuilder *invalidated_builder;
2659 /* For Value update via PropertyChange */
2660 GVariantBuilder *outer_builder1;
2661 GVariantBuilder *inner_builder1;
2662 GVariantBuilder *invalidated_builder1;
2663 GVariant *update_value = NULL;
2665 /* Other variables */
2666 struct gatt_client_info_t *conn_info = NULL;
2667 gchar *serv_path = NULL;
2668 char *char_path = NULL;
2669 gchar **line_argv = NULL;
2670 gboolean notify = TRUE;
2671 gboolean ret = TRUE;
2672 int err = BT_STATUS_SUCCESS;
2674 GError *error = NULL;
2677 memset(addr, 0x00, sizeof(addr));
2679 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2680 if (conn_info == NULL) {
2681 ERR("No Connection Inforamtion!!!");
2682 return BT_STATUS_FAIL;
2685 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
2687 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
2688 if (char_path == NULL)
2689 return BT_STATUS_FAIL;
2691 line_argv = g_strsplit_set(char_path, "/", 0);
2692 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2694 if (!__bt_gatt_get_service_state(serv_path)) {
2695 DBG("service not registered for this characteristic \n");
2697 g_strfreev(line_argv);
2698 return BT_STATUS_FAIL;
2701 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2702 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2704 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2705 g_variant_new("b", notify));
2707 _bt_hal_convert_addr_type_to_string(addr, (unsigned char *)conn_info->addr);
2709 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2710 g_variant_new("s", addr));
2712 DBG("Set characteristic Notification \n");
2713 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2715 "org.freedesktop.DBus.Properties",
2716 "PropertiesChanged",
2717 g_variant_new("(sa{sv}as)",
2718 "org.bluez.GattCharacteristic1",
2719 outer_builder, invalidated_builder),
2723 if (error != NULL) {
2724 ERR("D-Bus API failure: errCode[%x], \
2726 error->code, error->message);
2727 g_clear_error(&error);
2729 err = BT_STATUS_FAIL;
2732 g_variant_builder_unref(outer_builder);
2733 g_variant_builder_unref(invalidated_builder);
2736 /* Notifying Done, now update Value to Bluez via PropertyChanged */
2737 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2739 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2740 for (i = 0; i < len; i++)
2741 g_variant_builder_add(inner_builder1, "y", p_value[i]);
2743 update_value = g_variant_new("ay", inner_builder1);
2746 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2747 g_variant_builder_add(outer_builder1, "{sv}", "Value",
2750 DBG("Updating characteristic value \n");
2751 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2753 "org.freedesktop.DBus.Properties",
2754 "PropertiesChanged",
2755 g_variant_new("(sa{sv}as)",
2756 "org.bluez.GattCharacteristic1",
2757 outer_builder1, invalidated_builder1),
2761 if (error != NULL) {
2762 ERR("D-Bus API failure: errCode[%x], \
2764 error->code, error->message);
2765 g_clear_error(&error);
2767 err = BT_STATUS_FAIL;
2769 struct gatt_char_info *char_info = NULL;
2771 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
2772 if (char_info == NULL) {
2774 g_strfreev(line_argv);
2775 g_variant_builder_unref(inner_builder1);
2776 g_variant_builder_unref(outer_builder1);
2777 g_variant_builder_unref(invalidated_builder1);
2779 return BT_STATUS_FAIL;
2782 char_info->value_length = len;
2784 char_info->char_value = (char *)realloc(char_info->char_value, len);
2785 if (char_info->char_value) {
2786 for (i = 0; i < len; i++)
2787 char_info->char_value[i] = p_value[i];
2792 g_strfreev(line_argv);
2793 g_variant_builder_unref(inner_builder1);
2794 g_variant_builder_unref(outer_builder1);
2795 g_variant_builder_unref(invalidated_builder1);
2800 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
2801 int status, btgatt_response_t *response)
2803 CHECK_BTGATT_INIT();
2805 struct gatt_req_info *req_info = NULL;
2806 struct gatt_client_info_t *conn_info = NULL;
2809 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
2811 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2812 if (conn_info == NULL) {
2813 ERR("No Connection Inforamtion!!!");
2814 return BT_STATUS_FAIL;
2817 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
2818 if (req_info == NULL) {
2819 ERR("No Request Inforamtion!!!");
2820 return BT_STATUS_FAIL;
2823 if (status != BT_STATUS_SUCCESS) {
2824 ERR("resp_state is 0x%X", status);
2826 g_dbus_method_invocation_return_dbus_error(req_info->context,
2827 "org.bluez.Error.Failed", "Application Error");
2829 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
2831 req_info->context = NULL;
2832 if (req_info->attr_path)
2833 g_free(req_info->attr_path);
2834 if (req_info->svc_path)
2835 g_free(req_info->svc_path);
2838 return BT_STATUS_SUCCESS;
2841 DBG("Reponse Value length [%d]", response->attr_value.len);
2842 DBG("Request type: [%d]", req_info->request_type);
2845 for (i = 0; i < response->attr_value.len; i++)
2846 DBG("Resonse [%d] = [0x%x]", response->attr_value.value[i]);
2848 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
2849 GVariantBuilder *inner_builder = NULL;
2850 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2852 if (response->attr_value.len > 0) {
2853 for (i = 0; i < response->attr_value.len; i++)
2854 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
2856 g_dbus_method_invocation_return_value(req_info->context,
2857 g_variant_new("(ay)", inner_builder));
2859 g_variant_builder_unref(inner_builder);
2861 g_dbus_method_invocation_return_value(req_info->context, NULL);
2863 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
2865 req_info->context = NULL;
2866 if (req_info->attr_path)
2867 g_free(req_info->attr_path);
2868 if (req_info->svc_path)
2869 g_free(req_info->svc_path);
2872 return BT_STATUS_SUCCESS;
2875 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
2876 int value_length, char* att_value)
2878 CHECK_BTGATT_INIT();
2880 /* Other variables */
2881 char *char_path = NULL;
2882 gboolean ret = TRUE;
2883 GError *error = NULL;
2885 GVariantBuilder *outer_builder;
2886 GVariantBuilder *inner_builder;
2887 GVariantBuilder *invalidated_builder;
2888 GVariant *update_value = NULL;
2889 int err = BT_STATUS_SUCCESS;
2891 gchar **line_argv = NULL;
2892 gchar *serv_path = NULL;
2894 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
2895 if (char_path == NULL)
2896 return BT_STATUS_FAIL;
2898 line_argv = g_strsplit_set(char_path, "/", 0);
2899 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2901 if (!__bt_gatt_get_service_state(serv_path)) {
2902 DBG("service not registered for this characteristic \n");
2904 g_strfreev(line_argv);
2905 return BT_STATUS_FAIL;
2909 line_argv = g_strsplit_set(char_path, "/", 0);
2910 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2912 if (!__bt_gatt_get_service_state(serv_path)) {
2913 DBG("service not registered for this characteristic \n");
2915 g_strfreev(line_argv);
2916 return BT_STATUS_FAIL;
2919 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2920 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2922 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2923 for (i = 0; i < value_length; i++)
2924 g_variant_builder_add(inner_builder, "y", att_value[i]);
2926 update_value = g_variant_new("ay", inner_builder);
2928 outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2929 g_variant_builder_add(outer_builder, "{sv}", "Value",
2932 DBG("Updating characteristic value \n");
2933 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2935 "org.freedesktop.DBus.Properties",
2936 "PropertiesChanged",
2937 g_variant_new("(sa{sv}as)",
2938 "org.bluez.GattCharacteristic1",
2939 outer_builder, invalidated_builder),
2943 if (error != NULL) {
2944 ERR("D-Bus API failure: errCode[%x], \
2946 error->code, error->message);
2947 g_clear_error(&error);
2949 err = BT_STATUS_FAIL;
2951 struct gatt_char_info *char_info = NULL;
2953 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
2954 if (char_info == NULL) {
2956 g_strfreev(line_argv);
2957 g_variant_builder_unref(inner_builder);
2958 g_variant_builder_unref(outer_builder);
2959 g_variant_builder_unref(invalidated_builder);
2961 return BT_STATUS_FAIL;
2964 char_info->value_length = value_length;
2966 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
2967 if (char_info->char_value) {
2968 for (i = 0; i < value_length; i++)
2969 char_info->char_value[i] = att_value[i];
2975 g_strfreev(line_argv);
2976 g_variant_builder_unref(inner_builder);
2977 g_variant_builder_unref(outer_builder);
2978 g_variant_builder_unref(invalidated_builder);
2983 static bt_status_t gatt_server_listen(int server_if, bool start)
2985 CHECK_BTGATT_INIT();
2986 /* Send Data to LE Module */
2987 return _bt_hal_enable_advertising(server_if, start, FALSE);
2990 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
2991 bool include_txpower, int min_interval, int max_interval, int appearance,
2992 uint16_t manufacturer_len, char* manufacturer_data,
2993 uint16_t service_data_len, char* service_data,
2994 uint16_t service_uuid_len, char* service_uuid)
2996 CHECK_BTGATT_INIT();
2997 return BT_STATUS_SUCCESS;
3000 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3002 CHECK_BTGATT_INIT();
3003 /* Send Enable Advertising request to LE Module */
3004 return _bt_hal_enable_advertising(server_if, TRUE, TRUE);
3007 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3008 int chnl_map, int tx_power, int timeout_s)
3010 CHECK_BTGATT_INIT();
3012 /* Send Advertising parameters to LE Module */
3013 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3014 chnl_map, tx_power, timeout_s);
3017 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3019 CHECK_BTGATT_INIT();
3021 /* Send Data to LE Module */
3022 return _bt_hal_set_advertising_data(adv_param_setup);
3025 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3027 CHECK_BTGATT_INIT();
3028 /* Send Data to LE Module */
3029 return _bt_hal_enable_advertising(server_if, FALSE, TRUE);
3032 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3034 CHECK_BTGATT_INIT();
3035 char *object_path = NULL;
3037 GDBusProxy *device_proxy;
3038 GError *error = NULL;
3040 GVariant *tmp_value;
3041 GDBusConnection *conn;
3042 GVariant *result = NULL;
3043 int ret = BT_STATUS_SUCCESS;
3044 struct gatt_client_info_t *conn_info = NULL;
3047 if (mtu_size == NULL)
3048 return BT_STATUS_PARM_INVALID;
3050 /* GDBUS Connection Info validate */
3051 conn = _bt_hal_get_system_gconn();
3053 ERR("Could not get System DBUS Connection");
3054 return BT_STATUS_FAIL;
3057 /* Connection Info validate */
3058 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3059 if (conn_info == NULL) {
3060 ERR("No Connection Inforamtion!!!");
3061 return BT_STATUS_FAIL;
3065 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3066 if (object_path == NULL)
3067 return BT_STATUS_FAIL;
3069 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3070 NULL, BT_HAL_BLUEZ_NAME, object_path,
3071 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3073 g_free(object_path);
3074 if (device_proxy == NULL)
3075 return BT_STATUS_FAIL;
3077 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3078 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3079 G_DBUS_CALL_FLAGS_NONE,
3083 if (result == NULL) {
3084 if (error != NULL) {
3085 ERR("Error occured in Proxy call [%s]\n", error->message);
3086 g_error_free(error);
3088 g_object_unref(device_proxy);
3089 return BT_STATUS_FAIL;
3092 g_variant_get(result , "(@a{sv})", &value);
3093 g_variant_unref(result);
3095 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3096 if (tmp_value == NULL) {
3097 g_object_unref(device_proxy);
3098 g_variant_unref(value);
3099 return BT_STATUS_FAIL;
3102 mtu = g_variant_get_uint16(tmp_value);
3104 DBG("ATT MTU : [%d]", mtu);
3106 g_variant_unref(tmp_value);
3107 g_variant_unref(value);
3108 g_object_unref(device_proxy);
3110 *mtu_size = (int) mtu;
3115 const btgatt_server_interface_t btgatt_server_interface = {
3116 gatt_server_register_app,
3117 gatt_server_unregister_app,
3120 gatt_server_add_service,
3121 gatt_server_add_included_service,
3122 gatt_server_add_characteristic,
3123 gatt_server_add_descriptor,
3124 gatt_server_start_service,
3125 gatt_server_stop_service,
3126 gatt_server_delete_service,
3127 gatt_server_send_indication,
3128 gatt_server_send_response,
3129 gatt_server_update_att_value,
3131 gatt_server_set_adv_data,
3132 gatt_server_multi_adv_enable,
3133 gatt_server_multi_adv_update,
3134 gatt_server_multi_adv_set_inst_data,
3135 gatt_server_multi_adv_disable,
3136 gatt_server_get_mtu_size