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='y' name='id' direction='in'/>"
238 " <arg type='q' name='offset' direction='in'/>"
239 " <arg type='ay' name='value' direction='in'/>"
241 " <method name='StartNotify'>"
243 " <method name='StopNotify'>"
245 " <method name='IndicateConfirm'>"
246 " <arg type='s' name='address' direction='in'/>"
247 " <arg type='b' name='complete' direction='in'/>"
250 " <interface name='org.freedesktop.DBus.Properties'>"
251 " <property type='s' name='UUID' access='read'>"
253 " <property type='o' name='Service' access='read'>"
255 " <property type='ay' name='Value' access='readwrite'>"
257 " <property type='b' name='Notifying' access='read'>"
259 " <property type='as' name='Flags' access='read'>"
261 " <property type='s' name='Unicast' access='read'>"
263 " <property type='ao' name='Descriptors' access='read'>"
268 /* Introspection data for the descriptor we are exporting */
269 static const gchar descriptor_introspection_xml[] =
271 " <interface name='org.bluez.GattDescriptor1'>"
272 " <method name='ReadValue'>"
273 " <arg type='s' name='address' direction='in'/>"
274 " <arg type='u' name='id' direction='in'/>"
275 " <arg type='q' name='offset' direction='in'/>"
276 " <arg type='ay' name='Value' direction='out'/>"
278 " <method name='WriteValue'>"
279 " <arg type='s' name='address' direction='in'/>"
280 " <arg type='u' name='id' direction='in'/>"
281 " <arg type='q' name='offset' direction='in'/>"
282 " <arg type='b' name='response_needed' direction='in'/>"
283 " <arg type='ay' name='value' direction='in'/>"
286 " <interface name='org.freedesktop.DBus.Properties'>"
287 " <property type='s' name='UUID' access='read'>"
289 " <property type='o' name='Characteristic' access='read'>"
291 " <property type='ay' name='Value' access='read'>"
293 " <property type='as' name='Flags' access='read'>"
299 static const gchar manager_introspection_xml[] =
301 " <interface name='org.freedesktop.DBus.ObjectManager'>"
302 " <method name='GetManagedObjects'>"
303 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
308 GSList *_bt_get_service_list_from_server(int instance)
311 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
312 INFO("Find App with slot [%d]", instance);
314 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
315 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
317 if (app->slot == instance) {
318 INFO("App slot [%d] Found, Number of services registered [%d]",
319 app->slot, g_slist_length(app->services));
320 return app->services;
326 void _bt_remote_service_from_gatt_server(int instance, int service_handle)
331 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
332 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
334 if (app->slot == instance) {
335 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
336 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
337 if (srv->service_handle == service_handle) {
338 app->services = g_slist_remove(app->services, srv);
346 void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
349 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
350 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
352 if (app->slot == slot) {
353 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
354 serv_info->service_handle, slot);
355 app->services = g_slist_append(app->services, serv_info);
360 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
363 struct gatt_client_info_t *info = NULL;
365 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
366 info = (struct gatt_client_info_t*)l->data;
370 if (!g_strcmp0(info->addr, address)) {
371 INFO("Remote GATT client found addr[%s]", info->addr);
378 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
381 struct gatt_client_info_t *info = NULL;
383 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
384 info = (struct gatt_client_info_t*)l->data;
388 if (info->connection_id == conn_id) {
389 INFO("Remote GATT client found addr[%s]", info->addr);
396 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
401 struct gatt_client_info_t *info = NULL;
402 struct gatt_req_info *info1 = NULL;
404 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
405 info = (struct gatt_client_info_t*)l->data;
409 if (info->connection_id == conn_id) {
411 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
413 info1 = (struct gatt_req_info*)l1->data;
417 if (info1->request_id == trans_id) {
418 INFO("Remote GATT client found addr[%s]", info->addr);
427 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
429 struct hal_ev_gatt_server_connected ev;
430 struct gatt_client_info_t *conn_info = NULL;
432 memset(&ev, 0, sizeof(ev));
434 /* Find Server Instance */
435 _bt_hal_get_gatt_server_instance_initialized(&instance);
436 if (instance == -1) {
437 ERR("Not even a single GATT server is registered");
441 /* Convert address to hex */
442 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
444 /* Create Connection ID */
445 /* Check if device is already in connected list */
446 conn_info = __bt_find_remote_gatt_client_info(address);
449 /* If disconnected, and conn info found, then remove conn info */
450 if (is_connected == FALSE) {
451 DBG("GATT Disconnected");
453 INFO("Remove GATT client info from List..");
454 /* Remove info from List */
455 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
456 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
459 ERR("GATT callback not registered");
461 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
462 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
463 ev.conn_id = conn_info->connection_id;
464 ev.server_instance = conn_info->instance_id;
465 ev.connected = is_connected;
467 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
469 g_free(conn_info->addr);
472 /* If connected, and conn info NOT found, then add conn info */
475 /* Save Connection info */
476 conn_info = g_new0(struct gatt_client_info_t, 1);
477 conn_info->addr = g_strdup(address);
478 INFO("Added GATT client addr[%s]", conn_info->addr);
479 conn_info->connection_id = ++conn_id;
480 conn_info->instance_id = instance;
481 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
482 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
485 ERR("GATT callback not registered");
487 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
488 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
489 ev.conn_id = conn_info->connection_id;
490 ev.server_instance = conn_info->instance_id;
491 ev.connected = is_connected;
493 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
497 /* Send GATT connected or disconnected event */
500 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
504 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
505 struct gatt_service_info *serv_info = l1->data;
507 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
508 struct gatt_char_info *char_info = l2->data;
510 if (g_strcmp0(char_info->char_path, char_path)
512 *char_hdl = char_info->char_handle;
517 ERR("Gatt service not found");
521 char *__bt_gatt_find_char_path_from_handle(int char_hdl)
525 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
526 struct gatt_service_info *serv_info = l1->data;
528 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
529 struct gatt_char_info *char_info = l2->data;
531 if (char_info->char_handle == char_hdl)
532 return char_info->char_path;
539 struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
543 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
544 struct gatt_service_info *serv_info = l1->data;
546 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
547 struct gatt_char_info *char_info = l2->data;
549 if (char_info->char_handle == char_hdl)
557 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
559 GSList *l1, *l2, *l3;
561 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
562 struct gatt_service_info *serv_info = l1->data;
564 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
565 struct gatt_char_info *char_info = l2->data;
567 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
568 struct gatt_desc_info *desc_info = l3->data;
570 if (g_strcmp0(desc_info->desc_path, desc_path)
572 *desc_hdl = desc_info->desc_handle;
578 ERR("Gatt service not found");
582 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
584 const gchar *object_path,
585 const gchar *interface_name,
586 const gchar *method_name,
587 GVariant *parameters,
588 GDBusMethodInvocation *invocation,
593 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
594 GVariantBuilder *builder;
595 GVariantBuilder *inner_builder1 = NULL;
596 GVariant *svc_char = NULL;
598 GSList *gatt_services = NULL;
600 instance = (int*)user_data;
602 DBG("Getting values for service, chars and descriptors");
603 DBG("GATT Server App for which services are requested [%d]", *instance);
606 builder = g_variant_builder_new(
607 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
610 gatt_services = _bt_get_service_list_from_server(*instance);
612 if (g_slist_length(gatt_services) == 0) {
613 ERR("No registered GATT services!!!!");
614 g_dbus_method_invocation_return_value(invocation, NULL);
618 for (l = gatt_services; l != NULL; l = l->next) {
619 GVariantBuilder *svc_builder = NULL;
620 GVariantBuilder *inner_builder = NULL;
621 struct gatt_service_info *serv_info = l->data;
622 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
624 /* Prepare inner builder for GattService1 interface */
625 DBG("Creating builder for service");
626 svc_builder = g_variant_builder_new(
627 G_VARIANT_TYPE("a{sa{sv}}"));
628 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
630 g_variant_builder_add(inner_builder, "{sv}", "UUID",
631 g_variant_new_string(serv_info->service_uuid));
633 g_variant_builder_add(inner_builder, "{sv}", "Primary",
634 g_variant_new_boolean(serv_info->is_svc_primary));
637 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
638 DBG("Adding Charatarisitcs list");
639 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
640 struct gatt_char_info *char_info = l4->data;
641 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
642 char_info->char_handle, serv_info->service_handle);
643 g_variant_builder_add(inner_builder1, "o",
644 char_info->char_path);
645 DBG("%s", char_info->char_path);
648 svc_char = g_variant_new("ao", inner_builder1);
649 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
652 g_variant_builder_add(svc_builder, "{sa{sv}}",
656 g_variant_builder_add(builder, "{oa{sa{sv}}}",
657 serv_info->serv_path,
660 g_variant_builder_unref(inner_builder1);
662 /* Prepare inner builder for GattCharacteristic1 interface */
664 GSList *l2 = serv_info->char_data;
665 DBG("Creating builder for characteristics \n");
668 DBG("characteristic data is NULL");
670 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
672 GVariantBuilder *char_builder = NULL;
673 GVariantBuilder *inner_builder = NULL;
674 GVariantBuilder *builder1 = NULL;
675 GVariantBuilder *builder2 = NULL;
676 GVariantBuilder *builder3 = NULL;
677 GVariant *char_val = NULL;
678 GVariant *flags_val = NULL;
679 GVariant *char_desc = NULL;
680 char *unicast = NULL;
681 gboolean notify = FALSE;
684 char_builder = g_variant_builder_new(
687 inner_builder = g_variant_builder_new(
691 struct gatt_char_info *char_info = l2->data;
692 if (char_info == NULL) {
693 ERR("char_info is NULL");
698 g_variant_builder_add(inner_builder, "{sv}", "UUID",
699 g_variant_new_string(char_info->char_uuid));
701 g_variant_builder_add(inner_builder, "{sv}", "Service",
702 g_variant_new("o", serv_info->serv_path));
704 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
706 if (char_info->char_value != NULL) {
707 for (i = 0; i < char_info->value_length; i++) {
708 g_variant_builder_add(builder1, "y",
709 char_info->char_value[i]);
711 char_val = g_variant_new("ay", builder1);
712 g_variant_builder_add(inner_builder, "{sv}",
716 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
717 for (i = 0; i < char_info->flags_length; i++) {
718 g_variant_builder_add(builder2, "s",
719 char_info->char_flags[i]);
722 flags_val = g_variant_new("as", builder2);
723 g_variant_builder_add(inner_builder, "{sv}", "Flags",
727 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
728 g_variant_new("b", notify));
731 unicast = g_strdup("00:00:00:00:00:00");
732 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
733 g_variant_new("s", unicast));
736 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
737 DBG("Adding Descriptors list");
739 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
740 struct gatt_desc_info *desc_info = l4->data;
741 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
742 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
743 g_variant_builder_add(builder3, "o",
744 desc_info->desc_path);
745 DBG("%s", desc_info->desc_path);
748 char_desc = g_variant_new("ao", builder3);
749 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
752 g_variant_builder_add(char_builder, "{sa{sv}}",
753 GATT_CHAR_INTERFACE , inner_builder);
754 g_variant_builder_add(builder, "{oa{sa{sv}}}",
755 char_info->char_path, char_builder);
757 /*Prepare inner builder for GattDescriptor1 interface*/
759 GSList *l3 = char_info->desc_data;
762 DBG("descriptor data is NULL");
764 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
766 DBG("Creating builder for descriptor \n");
768 GVariantBuilder *desc_builder = NULL;
769 GVariantBuilder *inner_builder = NULL;
770 GVariantBuilder *builder1 = NULL;
771 GVariantBuilder *builder2 = NULL;
772 GVariant *desc_val = NULL;
774 desc_builder = g_variant_builder_new(
777 inner_builder = g_variant_builder_new(
781 struct gatt_desc_info *desc_info = l3->data;
782 if (desc_info == NULL) {
783 ERR("desc_info is NULL");
788 g_variant_builder_add(inner_builder,
790 g_variant_new_string(
791 desc_info->desc_uuid));
794 g_variant_builder_add(inner_builder, "{sv}",
797 char_info->char_path));
800 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
802 if (desc_info->desc_value != NULL) {
803 for (i = 0; i < desc_info->value_length; i++) {
804 g_variant_builder_add(builder1, "y",
805 desc_info->desc_value[i]);
807 desc_val = g_variant_new("ay", builder1);
808 g_variant_builder_add(inner_builder, "{sv}",
813 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
815 for (i = 0; i < desc_info->flags_length; i++) {
816 g_variant_builder_add(builder2, "s",
817 desc_info->desc_flags[i]);
820 flags_val = g_variant_new("as", builder2);
821 g_variant_builder_add(inner_builder, "{sv}", "Flags",
824 g_variant_builder_add(desc_builder, "{sa{sv}}",
828 g_variant_builder_add(builder, "{oa{sa{sv}}}",
829 desc_info->desc_path,
832 /*unref descriptor builder pointers*/
833 g_variant_builder_unref(builder1);
834 g_variant_builder_unref(builder2);
835 g_variant_builder_unref(inner_builder);
836 g_variant_builder_unref(desc_builder);
841 /*unref char builder pointers*/
842 g_variant_builder_unref(builder1);
843 g_variant_builder_unref(builder2);
844 g_variant_builder_unref(builder3);
845 g_variant_builder_unref(inner_builder);
846 g_variant_builder_unref(char_builder);
849 /*unref service builder pointers*/
850 g_variant_builder_unref(inner_builder);
851 g_variant_builder_unref(svc_builder);
854 /* Return builder as method reply */
855 DBG("Sending gatt service builder values to Bluez");
856 g_dbus_method_invocation_return_value(invocation,
866 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
868 const gchar *object_path,
869 const gchar *interface_name,
870 const gchar *method_name,
871 GVariant *parameters,
872 GDBusMethodInvocation *invocation,
876 if (g_strcmp0(method_name, "ReadValue") == 0) {
877 struct hal_ev_gatt_server_read_req ev;
882 struct gatt_client_info_t *conn_info = NULL;
883 struct gatt_req_info *req_info = NULL;
884 struct gatt_service_info *svc_info = NULL;
888 DBG("Application path = %s", object_path);
889 DBG("Sender = %s", sender);
891 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
892 if (svc_info == NULL) {
893 ERR("Coudn't find service for %s", object_path);
894 g_dbus_method_invocation_return_value(invocation, NULL);
898 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
899 DBG("Request id = %u, Offset = %u", req_id, offset);
901 /* Check if device is already in connected list */
902 conn_info = __bt_find_remote_gatt_client_info(addr);
904 if (conn_info == NULL) {
905 ERR("Coudn't find Connection info for %s", addr);
906 g_dbus_method_invocation_return_value(invocation, NULL);
911 ERR("GATT callback NOT registered");
912 g_dbus_method_invocation_return_value(invocation, NULL);
916 /* Store requests information */
917 req_info = g_new0(struct gatt_req_info, 1);
918 req_info->attr_path = g_strdup(object_path);
919 req_info->svc_path = g_strdup(svc_info->serv_path);
920 req_info->request_id = req_id;
921 req_info->offset = offset;
922 req_info->context = invocation;
924 /* Append request info in list of requests for the particular connection */
925 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
928 memset(&ev, 0, sizeof(ev));
929 ev.conn_id = conn_info->connection_id;
930 ev.trans_id = req_id;
931 ev.att_handle = desc_hdl;
933 ev.is_long = false; /* TODO*/
935 /* Convert address to hex */
936 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
938 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
940 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
942 GVariant *var = NULL;
946 gboolean response_needed = FALSE;
947 struct hal_ev_gatt_server_write_req ev;
951 struct gatt_service_info *svc_info = NULL;
952 struct gatt_client_info_t *conn_info = NULL;
953 struct gatt_req_info *req_info = NULL;
956 DBG("Application path = %s", object_path);
957 DBG("Sender = %s", sender);
959 g_variant_get(parameters, "(&suqb@ay)",
960 &addr, &req_id, &offset, &response_needed, &var);
961 DBG("Request id = %u, Offset = %u", req_id, offset);
963 /* Check if device is already in connected list */
964 conn_info = __bt_find_remote_gatt_client_info(addr);
966 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
968 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
969 g_variant_unref(var);
971 g_dbus_method_invocation_return_value(invocation, NULL);
973 g_object_unref(invocation);
977 len = g_variant_get_size(var);
980 data = (char *)g_variant_get_data(var);
981 memcpy(ev.value, data, len);
984 if (response_needed) {
985 /* Store request information */
986 req_info = g_new0(struct gatt_req_info, 1);
987 req_info->attr_path = g_strdup(object_path);
988 req_info->svc_path = g_strdup(svc_info->serv_path);
989 req_info->request_id = req_id;
990 req_info->offset = offset;
991 req_info->context = invocation;
993 /* Append request info in list of requests for the particular connection */
994 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
996 g_object_unref(invocation);
1000 memset(&ev, 0, sizeof(ev));
1001 ev.conn_id = conn_info->connection_id;
1002 ev.trans_id = req_id;
1003 ev.att_handle = desc_hdl;
1005 ev.need_rsp = response_needed;
1008 /* Convert address to hex */
1009 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1011 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1013 g_variant_unref(var);
1018 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1019 const gchar *sender,
1020 const gchar *object_path,
1021 const gchar *interface_name,
1022 const gchar *method_name,
1023 GVariant *parameters,
1024 GDBusMethodInvocation *invocation,
1027 if (g_strcmp0(method_name, "ReadValue") == 0) {
1031 struct hal_ev_gatt_server_read_req ev;
1034 struct gatt_req_info *req_info = NULL;
1035 struct gatt_client_info_t *conn_info = NULL;
1036 struct gatt_service_info *svc_info = NULL;
1038 DBG("Application path = %s", object_path);
1039 DBG("Sender = %s", sender);
1041 /* Check if device is already in connected list */
1042 conn_info = __bt_find_remote_gatt_client_info(addr);
1044 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1046 if (svc_info == NULL || conn_info == NULL) {
1047 g_dbus_method_invocation_return_value(invocation, NULL);
1052 ERR("GATT callback NOT registered");
1053 g_dbus_method_invocation_return_value(invocation, NULL);
1057 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1058 DBG("Request id = %u, Offset = %u", req_id, offset);
1060 /* Store requets information */
1061 req_info = g_new0(struct gatt_req_info, 1);
1062 req_info->attr_path = g_strdup(object_path);
1063 req_info->svc_path = g_strdup(svc_info->serv_path);
1064 req_info->request_id = req_id;
1065 req_info->offset = offset;
1066 req_info->context = invocation;
1068 /* Append request info in list of requests for the particular connection */
1069 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1071 /* Send HAL event */
1072 memset(&ev, 0, sizeof(ev));
1073 ev.conn_id = conn_info->connection_id;
1074 ev.trans_id = req_id;
1075 ev.att_handle = char_hdl;
1077 ev.is_long = false; /* TODO*/
1079 /* Convert address to hex */
1080 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1082 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1084 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1085 GVariant *var = NULL;
1089 gboolean response_needed = FALSE;
1090 struct hal_ev_gatt_server_write_req ev;
1093 struct gatt_service_info *svc_info = NULL;
1094 struct gatt_req_info *req_info = NULL;
1095 struct gatt_client_info_t *conn_info = NULL;
1098 DBG("Application path = %s", object_path);
1099 DBG("Sender = %s", sender);
1101 g_variant_get(parameters, "(&suqb@ay)",
1102 &addr, &req_id, &offset, &response_needed, &var);
1103 DBG("Request id = %u, Offset = %u", req_id, offset);
1105 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1107 /* Check if device is already in connected list */
1108 conn_info = __bt_find_remote_gatt_client_info(addr);
1110 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1111 g_variant_unref(var);
1112 if (response_needed)
1113 g_dbus_method_invocation_return_value(invocation, NULL);
1115 g_object_unref(invocation);
1119 if (response_needed) {
1120 /* Store requets information */
1121 req_info = g_new0(struct gatt_req_info, 1);
1122 req_info->attr_path = g_strdup(object_path);
1123 req_info->svc_path = g_strdup(svc_info->serv_path);
1124 req_info->request_id = req_id;
1125 req_info->offset = offset;
1126 req_info->context = invocation;
1128 /* Append request info in list of requests for the particular connection */
1129 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1132 g_object_unref(invocation);
1135 /* Send HAL event */
1136 memset(&ev, 0, sizeof(ev));
1137 ev.conn_id = conn_info->connection_id;
1138 ev.trans_id = req_id;
1139 ev.att_handle = char_hdl;
1141 ev.need_rsp = response_needed;
1144 /* Convert address to hex */
1145 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1147 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1149 g_variant_unref(var);
1152 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1155 struct gatt_service_info *svc_info = NULL;
1156 struct hal_ev_gatt_server_notifcation_change ev;
1159 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1160 if (svc_info == NULL || event_cb == NULL)
1163 /* Send HAL event */
1164 memset(&ev, 0, sizeof(ev));
1165 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1166 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1167 ev.att_handle = char_hdl;
1170 /* Convert address to hex */
1171 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1173 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1176 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1179 struct gatt_service_info *svc_info = NULL;
1180 struct hal_ev_gatt_server_notifcation_change ev;
1183 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1184 if (svc_info == NULL || event_cb == NULL)
1187 /* Send HAL event */
1188 memset(&ev, 0, sizeof(ev));
1189 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1190 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1191 ev.att_handle = char_hdl;
1194 /* Convert address to hex */
1195 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1197 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1200 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1202 gboolean complete = FALSE;
1205 struct gatt_service_info *svc_info = NULL;
1206 struct gatt_client_info_t *conn_info = NULL;
1208 struct hal_ev_gatt_server_indicate_cfm ev;
1210 DBG("IndicateConfirm");
1211 DBG("Application path = %s", object_path);
1212 DBG("Sender = %s", sender);
1214 g_variant_get(parameters, "(&sb)", &addr, &complete);
1215 DBG("Remote Device address number = %s", addr);
1216 DBG("Is Indicate confirmation for last device [%d]", complete);
1218 /* Check if device is already in connected list */
1219 conn_info = __bt_find_remote_gatt_client_info(addr);
1221 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1223 if (svc_info == NULL || conn_info == NULL
1224 || event_cb == NULL) {
1228 /* Send HAL event */
1229 memset(&ev, 0, sizeof(ev));
1230 ev.conn_id = conn_info->connection_id;
1231 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1232 ev.att_handle = char_hdl;
1234 /* Convert address to hex */
1235 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1237 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1240 g_dbus_method_invocation_return_value(invocation, NULL);
1243 gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1246 GError *error = NULL;
1247 GVariantBuilder *array_builder;
1249 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1250 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1251 g_variant_builder_add(array_builder, "s", interface);
1253 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1254 "org.freedesktop.Dbus.Objectmanager",
1255 "InterfacesRemoved",
1256 g_variant_new("(oas)",
1257 object_path, array_builder),
1261 if (error != NULL) {
1262 /* dbus gives error cause */
1263 ERR("d-bus api failure: errcode[%x], message[%s]",
1264 error->code, error->message);
1265 g_clear_error(&error);
1268 g_variant_builder_unref(array_builder);
1273 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1280 g_free(desc_info->desc_path);
1281 g_free(desc_info->desc_uuid);
1282 g_free(desc_info->desc_value);
1284 for (i = 0; i < desc_info->flags_length; i++)
1285 g_free(desc_info->desc_flags[i]);
1290 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1297 g_free(char_info->char_path);
1298 g_free(char_info->char_uuid);
1299 g_free(char_info->char_value);
1301 for (i = 0; i < char_info->flags_length; i++)
1302 g_free(char_info->char_flags[i]);
1308 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1313 g_free(svc_info->serv_path);
1314 g_free(svc_info->service_uuid);
1318 static const GDBusInterfaceVTable desc_interface_vtable = {
1319 __bt_gatt_desc_method_call,
1324 static const GDBusInterfaceVTable char_interface_vtable = {
1325 __bt_gatt_char_method_call,
1330 static const GDBusInterfaceVTable serv_interface_vtable = {
1336 static const GDBusInterfaceVTable manager_interface_vtable = {
1337 __bt_gatt_manager_method_call,
1343 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1344 const gchar *introspection_data)
1347 GDBusNodeInfo *node_info = NULL;
1349 if (introspection_data == NULL)
1353 DBG("Create new node info");
1354 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1357 ERR("Unable to create node: %s", err->message);
1358 g_clear_error(&err);
1365 /* To send stack event to hal-av handler */
1366 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1371 void _bt_hal_unregister_gatt_server_handler_cb(void)
1376 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1378 struct hal_ev_gatt_desc_added ev;
1379 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1381 /* Prepare to GATT characteristic added event */
1382 memset(&ev, 0, sizeof(ev));
1383 ev.status = BT_STATUS_SUCCESS;
1384 ev.server_instance = data->instance_data;
1385 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1386 ev.service_handle = data->srvc_hdl;
1387 ev.desc_handle = data->desc_hdl;
1390 ERR("GATT Descriptor Added callback registered");
1392 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1393 data->instance_data, data->srvc_hdl, data->desc_hdl);
1395 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1402 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1404 struct hal_ev_gatt_char_added ev;
1405 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1407 /* Prepare to GATT characteristic added event */
1408 memset(&ev, 0, sizeof(ev));
1409 ev.status = BT_STATUS_SUCCESS;
1410 ev.server_instance = data->instance_data;
1411 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1412 ev.service_handle = data->srvc_hdl;
1413 ev.char_handle = data->char_hdl;
1416 ERR("GATT Characteristic Added callback registered");
1418 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1419 data->instance_data, data->srvc_hdl, data->char_hdl);
1421 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1428 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1430 struct hal_ev_gatt_service_added ev;
1431 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1433 /* Prepare to GATT Service added event */
1434 memset(&ev, 0, sizeof(ev));
1435 ev.status = BT_STATUS_SUCCESS;
1436 ev.server_instance = data->instance_data;
1437 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1438 ev.service_handle = data->srvc_hdl;
1439 ev.is_primary = data->is_primary;
1442 ERR("GATT Service Added callback registered");
1444 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1445 data->instance_data, data->srvc_hdl);
1446 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1453 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1455 struct hal_ev_gatt_service_started ev;
1456 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1458 /* Prepare to GATT Service added event */
1459 memset(&ev, 0, sizeof(ev));
1460 ev.status = BT_STATUS_SUCCESS;
1461 ev.server_instance = data->instance_data;
1462 ev.service_handle = data->srvc_hdl;
1465 ERR("GATT Service Started callback registered");
1467 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1468 data->instance_data, data->srvc_hdl);
1469 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1476 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1478 struct hal_ev_gatt_service_deleted ev;
1479 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1481 /* Prepare to GATT Service added event */
1482 memset(&ev, 0, sizeof(ev));
1483 ev.status = BT_STATUS_SUCCESS;
1484 ev.server_instance = data->instance_data;
1485 ev.service_handle = data->srvc_hdl;
1488 ERR("GATT Service Deleted callback registered");
1490 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1491 data->instance_data, data->srvc_hdl);
1492 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1499 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1501 struct hal_ev_server_instance_registered ev;
1502 hal_register_server_data *data = (hal_register_server_data*) user_data;
1504 /* Prepare to send AV connecting event */
1505 memset(&ev, 0, sizeof(ev));
1506 ev.status = BT_STATUS_SUCCESS;
1507 ev.server_instance = data->instance_data;
1508 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1511 ERR("GATT Register Server Instance Callback not registered");
1513 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1514 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1521 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1523 CHECK_BTGATT_INIT();
1524 int status = BT_STATUS_FAIL;
1526 DBG("Register server instance request");
1527 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1529 /* Check if slot available */
1530 server_if = _bt_hal_get_available_adv_slot_id(uuid);
1532 if (server_if == -1) {
1533 ERR("Allocation of server instance failed");
1537 user_data->instance_data = server_if;
1538 DBG("Allocated new Advertising slot with Stack [%d]", user_data->instance_data);
1542 * As we need to provide async callback to user from HAL, simply schedule a
1543 * callback method which will carry actual result
1545 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1546 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1548 /* If available, then return success, else return error */
1549 return BT_STATUS_SUCCESS;
1552 void _bt_hal_remove_gatt_server_from_list(int server_if)
1555 struct gatt_server_app *info = NULL;
1557 for (l = gatt_server_apps; l != NULL;) {
1558 info = (struct gatt_server_app*)l->data;
1559 l = g_slist_next(l);
1562 if (info->slot == server_if) {
1563 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1564 info->app_path, info->slot);
1566 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1567 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1568 In above case, only advertising block will be deallocated, Gatt Server will remain
1570 if (info->services == NULL) {
1571 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1572 INFO("Total gatt server apps still existing after removing above is [%d]",
1573 g_slist_length(gatt_server_apps));
1575 /* DBUS Unregister only for current app */
1576 __bt_hal_gatt_deinit(info->app_path);
1578 g_free(info->app_path);
1582 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1583 g_slist_length(info->services));
1589 static bt_status_t gatt_server_unregister_app(int server_if)
1591 CHECK_BTGATT_INIT();
1592 DBG("Un-Register server instance request [%d]", server_if);
1594 if (_bt_hal_is_advertising_in_slot(server_if) == FALSE)
1595 _bt_hal_free_server_slot(server_if);
1597 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
1598 _bt_hal_remove_gatt_server_from_list(server_if);
1599 return BT_STATUS_SUCCESS;
1602 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
1604 CHECK_BTGATT_INIT();
1605 return BT_STATUS_SUCCESS;
1608 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
1610 CHECK_BTGATT_INIT();
1611 return BT_STATUS_SUCCESS;
1614 static void __bt_gatt_close_gdbus_connection(void)
1622 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
1623 ERR("Fail to flush the connection: %s", err->message);
1628 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
1630 ERR("Fail to close the dbus connection: %s", err->message);
1635 g_object_unref(g_conn);
1640 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1642 GDBusConnection *local_system_gconn = NULL;
1646 if (g_conn == NULL) {
1647 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1648 if (address == NULL) {
1650 ERR("Failed to get bus address: %s", err->message);
1651 g_clear_error(&err);
1656 g_conn = g_dbus_connection_new_for_address_sync(address,
1657 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1658 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1659 NULL, /* GDBusAuthObserver */
1664 ERR("Unable to connect to dbus: %s", err->message);
1665 g_clear_error(&err);
1669 } else if (g_dbus_connection_is_closed(g_conn)) {
1670 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1671 if (address == NULL) {
1673 ERR("Failed to get bus address: %s", err->message);
1674 g_clear_error(&err);
1679 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1680 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1681 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1682 NULL, /* GDBusAuthObserver */
1686 if (!local_system_gconn) {
1687 ERR("Unable to connect to dbus: %s", err->message);
1688 g_clear_error(&err);
1691 g_conn = local_system_gconn;
1697 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
1702 uuid = btuuid2str(srvc_id->uu);
1703 DBG("Original UUID [%s]", uuid);
1705 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
1706 /* Extract Standard UUID string */
1707 memcpy(uuid_buf, &uuid[4], 4);
1709 DBG("Converted string [%s]", uuid_buf);
1710 return g_strdup(uuid_buf);
1712 return strdup(uuid);
1715 int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
1717 /* For GATT service specific */
1718 GDBusNodeInfo *node_info;
1721 struct gatt_service_info *serv_info = NULL;
1722 GVariantBuilder *builder = NULL;
1723 GVariantBuilder *builder1 = NULL;
1724 GVariantBuilder *inner_builder = NULL;
1725 gboolean svc_primary = TRUE;
1726 GError *error = NULL;
1727 hal_gatt_service_added *user_data = NULL;
1728 DBG("Service add to DBUS slot [%d]", slot);
1730 node_info = __bt_gatt_create_method_node_info(
1731 service_introspection_xml);
1733 if (node_info == NULL)
1734 return BT_STATUS_FAIL;
1736 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
1737 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
1738 DBG("gatt service path is [%s]", path);
1740 object_id = g_dbus_connection_register_object(g_conn, path,
1741 node_info->interfaces[0],
1742 &serv_interface_vtable,
1743 NULL, NULL, &error);
1745 if (object_id == 0) {
1746 ERR("failed to register: %s", error->message);
1747 g_error_free(error);
1749 return BT_STATUS_FAIL;
1751 /* Add object_id/gatt service information; it's required at the time of
1752 * service unregister and Getmanagedobjects
1754 serv_info = g_new0(struct gatt_service_info, 1);
1756 serv_info->serv_path = g_strdup(path);
1757 serv_info->serv_id = object_id;
1758 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
1759 serv_info->is_svc_registered = FALSE;
1760 serv_info->is_svc_primary = svc_primary;
1761 DBG("Service Handle to be added is [%d]", gatt_service_handle);
1762 serv_info->service_handle = gatt_service_handle;
1764 /* Update service in GATT Server service List */
1765 gatt_services = g_slist_append(gatt_services, serv_info);
1767 /* emit interfacesadded signal here for service path */
1768 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1769 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1771 g_variant_builder_add(inner_builder, "{sv}",
1772 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
1774 g_variant_builder_add(inner_builder, "{sv}",
1775 "Primary", g_variant_new_boolean(svc_primary));
1777 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1779 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1780 g_variant_new("ao", builder1));
1782 g_variant_builder_add(builder, "{sa{sv}}",
1783 GATT_SERV_INTERFACE, inner_builder);
1785 g_dbus_connection_emit_signal(g_conn, NULL, "/",
1786 "org.freedesktop.Dbus.ObjectManager",
1788 g_variant_new("(oa{sa{sv}})",
1792 /* Send Service handle to application */
1793 user_data = g_malloc0(sizeof(hal_gatt_service_added));
1794 user_data->srvc_hdl = serv_info->service_handle;
1795 user_data->instance_data = slot;
1796 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
1797 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
1799 /* Save newly created service in GATT Server's service list */
1800 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
1804 g_variant_builder_unref(inner_builder);
1805 g_variant_builder_unref(builder);
1806 g_variant_builder_unref(builder1);
1807 return BT_STATUS_SUCCESS;
1810 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
1813 char *app_path = (char*)user_data;
1814 INFO("UnregisterApplication is completed app [%s]", app_path);
1815 GError *error = NULL;
1816 GVariant *result = NULL;
1819 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
1821 if (result == NULL) {
1822 /* dBUS-RPC is failed */
1823 ERR("Dbus-RPC is failed\n");
1825 if (error != NULL) {
1826 /* dBUS gives error cause */
1827 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
1828 error->code, error->message);
1829 g_clear_error(&error);
1832 g_variant_unref(result);
1837 static void __bt_hal_gatt_deinit(char *app_path)
1839 GDBusProxy *proxy = NULL;
1843 /* Step1: Remove requested App */
1844 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
1845 "/org/bluez/hci0", "org.bluez.GattManager1");
1850 INFO("UnregisterApplication : path [%s]", app_path);
1852 /* Async Call to Unregister Service */
1853 data = g_strdup(app_path);
1854 g_dbus_proxy_call(proxy,
1855 "UnregisterApplication",
1856 g_variant_new("(o)",
1858 G_DBUS_CALL_FLAGS_NONE, -1,
1860 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
1863 /* If requested app is last GATT Server app, then clean all resources */
1864 if (gatt_server_apps == NULL) {
1865 INFO("All GATT servers are removed, clean all DBUS resources");
1867 /* unregister the exported interface for object manager
1868 g_conn and manager_id are common for all GATT servers */
1869 g_dbus_connection_unregister_object(g_conn,
1872 g_bus_unown_name(owner_id);
1875 g_object_unref(manager_gproxy);
1876 manager_gproxy = NULL;
1878 /* Close the GDBUS connection */
1879 __bt_gatt_close_gdbus_connection();
1885 int __bt_hal_gatt_init(void)
1887 GDBusConnection *conn = NULL;
1889 /* Only once for ALL GATT Servers */
1890 if (owner_id == 0) {
1891 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1892 BT_GATT_SERVICE_NAME,
1893 G_BUS_NAME_OWNER_FLAGS_NONE,
1894 NULL, NULL, NULL, NULL, NULL);
1896 INFO("Owner ID [%d]", owner_id);
1898 /* Only once for ALL GATT Servers conn = g_conn(global)*/
1899 conn = __bt_gatt_get_gdbus_connection();
1901 ERR("Unable to get connection");
1902 return BT_STATUS_FAIL;
1905 /* Only once for ALL GATT Servers */
1906 if (manager_node_info == NULL) {
1907 /* Register ObjectManager interface */
1908 manager_node_info = __bt_gatt_create_method_node_info(
1909 manager_introspection_xml);
1911 if (manager_node_info == NULL) {
1912 ERR("failed to get node info");
1913 return BT_STATUS_FAIL;
1918 return BT_STATUS_SUCCESS;
1921 void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
1925 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
1926 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
1927 if (app->slot == slot) {
1928 INFO("GATT Server app found app path [%s] instance [%d]",
1929 app->app_path, app->slot);
1930 *app_path = app->app_path;
1934 /* GATT Server not found */
1938 void _bt_hal_update_gatt_server_path(int slot, char *app_path)
1940 if (app_path == NULL)
1943 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
1944 app->app_path = g_strdup(app_path);
1946 gatt_server_apps = g_slist_append(gatt_server_apps, app);
1947 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
1952 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
1955 CHECK_BTGATT_INIT();
1956 char *app_path = NULL;
1957 GError *error = NULL;
1961 int result = BT_STATUS_SUCCESS;
1963 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
1964 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
1966 /* Check if this GATT server Application is already registered with DBUS */
1967 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
1969 if (app_path != NULL) {
1970 DBG("GATT server path is already defined [%s]", app_path);
1971 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
1973 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
1974 result = __bt_hal_gatt_init();
1975 if (result != BT_STATUS_SUCCESS)
1978 /* Only once for each GATT Server */
1979 app_path = g_strdup_printf("/com/%d", server_if);
1981 app_id = g_malloc0(sizeof(int));
1982 *app_id = server_if;
1984 manager_id = g_dbus_connection_register_object(g_conn, app_path,
1985 manager_node_info->interfaces[0],
1986 &manager_interface_vtable,
1987 (gpointer)app_id, NULL, &error);
1989 if (manager_id == 0) {
1990 ERR("failed to register: %s", error->message);
1991 g_error_free(error);
1995 /* For current GATT Server, app_path is created, save it in Table */
1996 _bt_hal_update_gatt_server_path(server_if, app_path);
1998 /* Add GATT Service to DBUS */
1999 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2005 INFO("Successfully added service");
2006 return BT_STATUS_SUCCESS;
2013 INFO("Service addition failed!!");
2014 return BT_STATUS_FAIL;
2017 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2018 int included_handle)
2020 CHECK_BTGATT_INIT();
2021 return BT_STATUS_SUCCESS;
2025 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2028 GSList *gatt_services = NULL;
2030 struct gatt_service_info *info = NULL;
2032 gatt_services = _bt_get_service_list_from_server(instance);
2034 len = g_slist_length(gatt_services);
2035 l = g_slist_nth(gatt_services, len -1);
2039 if (info->service_handle == service_handle)
2044 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2048 GSList *gatt_services = NULL;
2049 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2051 gatt_services = _bt_get_service_list_from_server(instance);
2053 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2054 struct gatt_service_info *info = l->data;
2055 INFO("Got one service with handle [%d]", info->service_handle);
2056 if (info->service_handle == service_handle)
2059 ERR("Gatt service with handle [%d] not found", service_handle);
2063 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2064 bt_uuid_t *uuid, int properties,
2067 GError *error = NULL;
2069 GDBusNodeInfo *node_info;
2071 GVariantBuilder *builder = NULL;
2072 GVariantBuilder *inner_builder = NULL;
2073 struct gatt_service_info *serv_info = NULL;
2074 struct gatt_char_info *char_info = NULL;
2075 GVariantBuilder *builder2 = NULL;
2076 GVariantBuilder *builder3 = NULL;
2077 GVariant *flags_val = NULL;
2079 char *char_flags[NUMBER_OF_FLAGS];
2081 hal_gatt_char_added *user_data = NULL;
2084 CHECK_BTGATT_INIT();
2085 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2086 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2088 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2089 if (serv_info == NULL)
2090 return BT_STATUS_FAIL;
2092 node_info = __bt_gatt_create_method_node_info(
2093 characteristics_introspection_xml);
2095 if (node_info == NULL)
2096 return BT_STATUS_FAIL;
2098 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2099 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2100 DBG("gatt characteristic path is [%s]", path);
2102 app_id = g_malloc0(sizeof(int));
2105 object_id = g_dbus_connection_register_object(g_conn, path,
2106 node_info->interfaces[0],
2107 &char_interface_vtable,
2108 (gpointer)app_id, NULL, &error);
2110 if (object_id == 0) {
2111 ERR("failed to register: %s", error->message);
2112 g_error_free(error);
2115 return BT_STATUS_FAIL;
2118 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2119 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2120 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2121 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2122 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2123 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2124 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2125 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2127 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2129 char_info = g_new0(struct gatt_char_info, 1);
2131 char_info->char_path = g_strdup(path);
2132 char_info->char_id = object_id;
2133 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2134 for (i = 0; i < flag_count; i++)
2135 char_info->char_flags[i] = char_flags[i];
2138 char_info->flags_length = flag_count;
2139 char_info->char_handle = gatt_char_handle;
2142 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2143 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2145 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2146 g_variant_new("s", char_info->char_uuid));
2147 g_variant_builder_add(inner_builder, "{sv}", "Service",
2148 g_variant_new("o", serv_info->serv_path));
2150 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2152 for (i = 0; i < flag_count; i++)
2153 g_variant_builder_add(builder2, "s", char_flags[i]);
2155 flags_val = g_variant_new("as", builder2);
2156 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2159 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2161 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2162 g_variant_new("ao", builder3));
2164 g_variant_builder_add(builder, "{sa{sv}}",
2165 GATT_CHAR_INTERFACE,
2168 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2169 "org.freedesktop.Dbus.ObjectManager",
2171 g_variant_new("(oa{sa{sv}})",
2175 //*char_path = g_strdup(path);
2180 /* Send Service handle to application */
2181 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2182 user_data->srvc_hdl = serv_info->service_handle;
2183 user_data->char_hdl = gatt_char_handle;
2184 user_data->instance_data = slot;
2185 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2186 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2188 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2189 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2194 g_variant_builder_unref(inner_builder);
2195 g_variant_builder_unref(builder);
2196 g_variant_builder_unref(builder2);
2197 g_variant_builder_unref(builder3);
2199 return BT_STATUS_SUCCESS;
2202 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2205 CHECK_BTGATT_INIT();
2207 // static int desc_id = 1;
2208 GError *error = NULL;
2210 GDBusNodeInfo *node_info;
2212 GVariantBuilder *builder = NULL;
2213 GVariantBuilder *inner_builder = NULL;
2215 struct gatt_char_info *char_info = NULL;
2216 struct gatt_desc_info *desc_info = NULL;
2217 struct gatt_service_info *serv_info = NULL;
2219 gchar **line_argv = NULL;
2221 char *char_path = NULL;
2224 GVariantBuilder *builder2 = NULL;
2225 GVariant *flags_val = NULL;
2227 char *desc_flags[NUMBER_OF_FLAGS];
2231 hal_gatt_desc_added *user_data = NULL;
2238 /* Fetch service data for the GATT server */
2239 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2240 if (serv_info == NULL)
2241 return BT_STATUS_FAIL;
2243 /* Fetch list of characteristics from the service info */
2244 l = serv_info->char_data;
2246 /* Fetch last char info from the characteristic list */
2247 char_info = g_slist_last(l)->data;
2248 if (char_info == NULL)
2249 return BT_STATUS_FAIL;
2251 /* Fetch characteristic path from char info */
2252 char_path = char_info->char_path;
2254 line_argv = g_strsplit_set(char_path, "/", 0);
2255 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2258 node_info = __bt_gatt_create_method_node_info(
2259 descriptor_introspection_xml);
2261 if (node_info == NULL) {
2262 g_strfreev(line_argv);
2264 return BT_STATUS_FAIL;
2267 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2269 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2270 DBG("gatt descriptor path is [%s]", path);
2272 app_id = g_malloc0(sizeof(int));
2275 object_id = g_dbus_connection_register_object(g_conn, path,
2276 node_info->interfaces[0],
2277 &desc_interface_vtable,
2278 (gpointer)app_id, NULL, &error);
2280 if (object_id == 0) {
2281 ERR("failed to register: %s", error->message);
2282 g_error_free(error);
2284 g_strfreev(line_argv);
2287 return BT_STATUS_FAIL;
2290 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2292 desc_info = g_new0(struct gatt_desc_info, 1);
2294 desc_info->desc_path = g_strdup(path);
2295 desc_info->desc_id = object_id;
2296 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2298 for (i = 0; i < flag_count; i++)
2299 desc_info->desc_flags[i] = desc_flags[i];
2301 desc_info->flags_length = flag_count;
2302 desc_info->desc_handle = gatt_desc_handle;
2305 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2306 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2308 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2309 g_variant_new("s", btuuid2str(uuid->uu)));
2310 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2311 g_variant_new("o", char_path));
2313 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2315 for (i = 0; i < flag_count; i++)
2316 g_variant_builder_add(builder2, "s", desc_flags[i]);
2318 flags_val = g_variant_new("as", builder2);
2319 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2322 g_variant_builder_add(builder, "{sa{sv}}",
2323 GATT_DESC_INTERFACE,
2326 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2327 "org.freedesktop.Dbus.ObjectManager",
2329 g_variant_new("(oa{sa{sv}})",
2333 //*desc_path = g_strdup(path);
2335 /* Save newly created descriptor to GATT server's service's characteristic */
2336 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2338 /* Send descriptor handle to application */
2339 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2340 user_data->srvc_hdl = serv_info->service_handle;
2341 user_data->desc_hdl = gatt_desc_handle;
2342 user_data->instance_data = slot;
2343 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2344 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2349 g_strfreev(line_argv);
2350 g_variant_builder_unref(inner_builder);
2351 g_variant_builder_unref(builder);
2352 return BT_STATUS_SUCCESS;
2355 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2357 GError *error = NULL;
2359 char *data = (char*) user_data;
2360 INFO("RegisterApplication is completed path [%s]", data);
2362 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2364 if (result == NULL) {
2365 /* dBUS-RPC is failed */
2366 ERR("Dbus-RPC is failed\n");
2368 if (error != NULL) {
2369 /* dBUS gives error cause */
2370 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2371 error->code, error->message);
2372 g_clear_error(&error);
2375 g_variant_unref(result);
2380 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2381 const gchar *path, const gchar *interface)
2387 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2392 ERR("Unable to connect to gdbus: %s", err->message);
2393 g_clear_error(&err);
2398 proxy = g_dbus_proxy_new_sync(g_conn,
2399 G_DBUS_PROXY_FLAGS_NONE, NULL,
2401 interface, NULL, &err);
2405 ERR("Unable to create proxy: %s", err->message);
2406 g_clear_error(&err);
2410 manager_gproxy = proxy;
2415 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2416 const gchar *path, const gchar *interface)
2418 return (manager_gproxy) ? manager_gproxy :
2419 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2423 static void __bt_register_application_to_dbus(int slot)
2425 GDBusProxy *proxy = NULL;
2426 char *app_path = NULL;
2428 DBG("RegisterApplication slot [%d]", slot);
2430 /* It is impossible that app path is still not initialized */
2431 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2433 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2434 "/org/bluez/hci0", "org.bluez.GattManager1");
2436 data = g_strdup(app_path);
2437 g_dbus_proxy_call(proxy,
2438 "RegisterApplication",
2439 g_variant_new("(oa{sv})",
2441 G_DBUS_CALL_FLAGS_NONE, -1,
2443 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2445 INFO("GATT server started");
2448 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2450 CHECK_BTGATT_INIT();
2451 struct gatt_service_info *serv_info = NULL;
2452 hal_gatt_service_started *user_data = NULL;
2453 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2455 /* Fetch service data for the GATT server */
2456 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2457 if (serv_info == NULL)
2458 return BT_STATUS_FAIL;
2460 if (serv_info->is_svc_registered)
2461 DBG("service already registered \n");
2463 serv_info->is_svc_registered = TRUE;
2465 /* Send Service handle to application */
2466 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2467 user_data->srvc_hdl = serv_info->service_handle;
2468 user_data->instance_data = server_if;
2469 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2471 /* If this is nth Service that is started, then register application at this point */
2472 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2473 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2475 __bt_register_application_to_dbus(server_if);
2478 return BT_STATUS_SUCCESS;
2481 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2483 CHECK_BTGATT_INIT();
2484 INFO("Stop service successful");
2485 return BT_STATUS_SUCCESS;
2488 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2490 CHECK_BTGATT_INIT();
2491 struct gatt_service_info *serv_info = NULL;
2492 hal_gatt_service_deleted *user_data = NULL;
2495 int err = BT_STATUS_SUCCESS;
2496 int ret = BT_STATUS_SUCCESS;
2497 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2499 /* Fetch service data for the GATT server */
2500 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2501 if (serv_info == NULL) {
2502 ERR("Could not find service info svc handle [%d] server slot [%d]",
2503 service_handle, server_if);
2504 return BT_STATUS_FAIL;
2507 if (serv_info->is_svc_registered == FALSE) {
2508 ERR("service Not registered path [%s] handle [%d]",
2509 serv_info->serv_path, service_handle);
2512 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2513 struct gatt_char_info *char_info = l->data;
2515 if (char_info == NULL)
2518 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2519 struct gatt_desc_info *desc_info = l1->data;
2521 if (desc_info == NULL)
2524 ret = g_dbus_connection_unregister_object(g_conn,
2525 desc_info->desc_id);
2527 __bt_hal_gatt_emit_interface_removed(
2528 desc_info->desc_path,
2529 GATT_DESC_INTERFACE);
2531 err = BT_STATUS_FAIL;
2534 /* list remove & free */
2535 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2536 __bt_hal_gatt_free_descriptor_info(desc_info);
2539 g_slist_free(char_info->desc_data);
2540 char_info->desc_data = NULL;
2542 ret = g_dbus_connection_unregister_object(g_conn,
2543 char_info->char_id);
2545 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2546 GATT_CHAR_INTERFACE);
2549 err = BT_STATUS_FAIL;
2552 /* list remove & free */
2553 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2554 __bt_hal_gatt_free_characteristic_info(char_info);
2557 g_slist_free(serv_info->char_data);
2558 serv_info->char_data = NULL;
2560 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2562 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2563 GATT_SERV_INTERFACE);
2566 err = BT_STATUS_FAIL;
2569 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
2571 DBG("Unregistered the service on properties interface");
2573 /* Remove from global list */
2574 gatt_services = g_slist_remove(gatt_services, serv_info);
2575 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
2577 /* Remove from GATT Server's list of services */
2578 _bt_remote_service_from_gatt_server(server_if, service_handle);
2580 if (gatt_services == NULL)
2581 INFO("All GATT Services of all GATT Servers are unregistered");
2583 if (err == BT_STATUS_SUCCESS) {
2584 INFO("Send GATT Service deleted Event");
2585 /* Send Service handle to application */
2586 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
2587 user_data->srvc_hdl = serv_info->service_handle;
2588 user_data->instance_data = server_if;
2589 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
2592 /* Free the service */
2593 __bt_hal_gatt_free_service_info(serv_info);
2597 static gboolean __bt_gatt_get_service_state(const char *service_path)
2599 struct gatt_service_info *svc_info = NULL;
2602 for (l = gatt_services; l; l = g_slist_next(l)) {
2604 svc_info = (struct gatt_service_info *)l->data;
2605 if (svc_info->serv_path == service_path) {
2606 DBG("Return the state of the gatt service %d",
2607 svc_info->is_svc_registered);
2608 return svc_info->is_svc_registered;
2612 DBG("gatt service info is NULL");
2616 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
2617 int len, int confirm, char* p_value)
2619 CHECK_BTGATT_INIT();
2622 GVariantBuilder *outer_builder;
2623 GVariantBuilder *invalidated_builder;
2625 /* For Value update via PropertyChange */
2626 GVariantBuilder *outer_builder1;
2627 GVariantBuilder *inner_builder1;
2628 GVariantBuilder *invalidated_builder1;
2629 GVariant *update_value = NULL;
2631 /* Other variables */
2632 struct gatt_client_info_t *conn_info = NULL;
2633 gchar *serv_path = NULL;
2634 char *char_path = NULL;
2635 gchar **line_argv = NULL;
2636 gboolean notify = TRUE;
2637 gboolean ret = TRUE;
2638 int err = BT_STATUS_SUCCESS;
2640 GError *error = NULL;
2643 memset(addr, 0x00, sizeof(addr));
2645 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2646 if (conn_info == NULL) {
2647 ERR("No Connection Inforamtion!!!");
2648 return BT_STATUS_FAIL;
2651 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
2653 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
2654 if (char_path == NULL)
2655 return BT_STATUS_FAIL;
2657 line_argv = g_strsplit_set(char_path, "/", 0);
2658 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2660 if (!__bt_gatt_get_service_state(serv_path)) {
2661 DBG("service not registered for this characteristic \n");
2663 g_strfreev(line_argv);
2664 return BT_STATUS_FAIL;
2667 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2668 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2670 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2671 g_variant_new("b", notify));
2673 _bt_hal_convert_addr_type_to_string(addr, (unsigned char *)conn_info->addr);
2675 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2676 g_variant_new("s", addr));
2678 DBG("Set characteristic Notification \n");
2679 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2681 "org.freedesktop.DBus.Properties",
2682 "PropertiesChanged",
2683 g_variant_new("(sa{sv}as)",
2684 "org.bluez.GattCharacteristic1",
2685 outer_builder, invalidated_builder),
2689 if (error != NULL) {
2690 ERR("D-Bus API failure: errCode[%x], \
2692 error->code, error->message);
2693 g_clear_error(&error);
2695 err = BT_STATUS_FAIL;
2698 g_variant_builder_unref(outer_builder);
2699 g_variant_builder_unref(invalidated_builder);
2702 /* Notifying Done, now update Value to Bluez via PropertyChanged */
2703 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2705 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2706 for (i = 0; i < len; i++)
2707 g_variant_builder_add(inner_builder1, "y", p_value[i]);
2709 update_value = g_variant_new("ay", inner_builder1);
2712 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2713 g_variant_builder_add(outer_builder1, "{sv}", "Value",
2716 DBG("Updating characteristic value \n");
2717 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2719 "org.freedesktop.DBus.Properties",
2720 "PropertiesChanged",
2721 g_variant_new("(sa{sv}as)",
2722 "org.bluez.GattCharacteristic1",
2723 outer_builder1, invalidated_builder1),
2727 if (error != NULL) {
2728 ERR("D-Bus API failure: errCode[%x], \
2730 error->code, error->message);
2731 g_clear_error(&error);
2733 err = BT_STATUS_FAIL;
2735 struct gatt_char_info *char_info = NULL;
2737 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
2738 if (char_info == NULL) {
2740 g_strfreev(line_argv);
2741 g_variant_builder_unref(inner_builder1);
2742 g_variant_builder_unref(outer_builder1);
2743 g_variant_builder_unref(invalidated_builder1);
2745 return BT_STATUS_FAIL;
2748 char_info->value_length = len;
2750 char_info->char_value = (char *)realloc(char_info->char_value, len);
2751 if (char_info->char_value) {
2752 for (i = 0; i < len; i++)
2753 char_info->char_value[i] = p_value[i];
2758 g_strfreev(line_argv);
2759 g_variant_builder_unref(inner_builder1);
2760 g_variant_builder_unref(outer_builder1);
2761 g_variant_builder_unref(invalidated_builder1);
2766 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
2767 int status, btgatt_response_t *response)
2769 CHECK_BTGATT_INIT();
2771 struct gatt_req_info *req_info = NULL;
2772 struct gatt_client_info_t *conn_info = NULL;
2775 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
2777 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2778 if (conn_info == NULL) {
2779 ERR("No Connection Inforamtion!!!");
2780 return BT_STATUS_FAIL;
2783 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
2784 if (req_info == NULL) {
2785 ERR("No Request Inforamtion!!!");
2786 return BT_STATUS_FAIL;
2789 if (status != BT_STATUS_SUCCESS) {
2790 ERR("resp_state is 0x%X", status);
2792 g_dbus_method_invocation_return_dbus_error(req_info->context,
2793 "org.bluez.Error.Failed", "Application Error");
2795 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
2797 req_info->context = NULL;
2798 if (req_info->attr_path)
2799 g_free(req_info->attr_path);
2800 if (req_info->svc_path)
2801 g_free(req_info->svc_path);
2804 return BT_STATUS_SUCCESS;
2807 DBG("Reponse Value length [%d]", response->attr_value.len);
2809 for (i = 0; i < response->attr_value.len; i++)
2810 DBG("Resonse [%d] = [0x%x]", response->attr_value.value[i]);
2813 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
2814 GVariantBuilder *inner_builder = NULL;
2815 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2817 if (response->attr_value.len > 0) {
2818 for (i = 0; i < response->attr_value.len; i++)
2819 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
2821 g_dbus_method_invocation_return_value(req_info->context,
2822 g_variant_new("(ay)", inner_builder));
2824 g_variant_builder_unref(inner_builder);
2826 g_dbus_method_invocation_return_value(req_info->context, NULL);
2828 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
2830 req_info->context = NULL;
2831 if (req_info->attr_path)
2832 g_free(req_info->attr_path);
2833 if (req_info->svc_path)
2834 g_free(req_info->svc_path);
2837 return BT_STATUS_SUCCESS;
2840 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
2841 int value_length, char* att_value)
2843 CHECK_BTGATT_INIT();
2845 /* Other variables */
2846 char *char_path = NULL;
2847 gboolean ret = TRUE;
2848 GError *error = NULL;
2850 GVariantBuilder *outer_builder;
2851 GVariantBuilder *inner_builder;
2852 GVariantBuilder *invalidated_builder;
2853 GVariant *update_value = NULL;
2854 int err = BT_STATUS_SUCCESS;
2856 gchar **line_argv = NULL;
2857 gchar *serv_path = NULL;
2859 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
2860 if (char_path == NULL)
2861 return BT_STATUS_FAIL;
2863 line_argv = g_strsplit_set(char_path, "/", 0);
2864 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2866 if (!__bt_gatt_get_service_state(serv_path)) {
2867 DBG("service not registered for this characteristic \n");
2869 g_strfreev(line_argv);
2870 return BT_STATUS_FAIL;
2874 line_argv = g_strsplit_set(char_path, "/", 0);
2875 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2877 if (!__bt_gatt_get_service_state(serv_path)) {
2878 DBG("service not registered for this characteristic \n");
2880 g_strfreev(line_argv);
2881 return BT_STATUS_FAIL;
2884 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2885 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2887 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2888 for (i = 0; i < value_length; i++)
2889 g_variant_builder_add(inner_builder, "y", att_value[i]);
2891 update_value = g_variant_new("ay", inner_builder);
2893 outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2894 g_variant_builder_add(outer_builder, "{sv}", "Value",
2897 DBG("Updating characteristic value \n");
2898 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2900 "org.freedesktop.DBus.Properties",
2901 "PropertiesChanged",
2902 g_variant_new("(sa{sv}as)",
2903 "org.bluez.GattCharacteristic1",
2904 outer_builder, invalidated_builder),
2908 if (error != NULL) {
2909 ERR("D-Bus API failure: errCode[%x], \
2911 error->code, error->message);
2912 g_clear_error(&error);
2914 err = BT_STATUS_FAIL;
2916 struct gatt_char_info *char_info = NULL;
2918 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
2919 if (char_info == NULL) {
2921 g_strfreev(line_argv);
2922 g_variant_builder_unref(inner_builder);
2923 g_variant_builder_unref(outer_builder);
2924 g_variant_builder_unref(invalidated_builder);
2926 return BT_STATUS_FAIL;
2929 char_info->value_length = value_length;
2931 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
2932 if (char_info->char_value) {
2933 for (i = 0; i < value_length; i++)
2934 char_info->char_value[i] = att_value[i];
2940 g_strfreev(line_argv);
2941 g_variant_builder_unref(inner_builder);
2942 g_variant_builder_unref(outer_builder);
2943 g_variant_builder_unref(invalidated_builder);
2948 static bt_status_t gatt_server_listen(int server_if, bool start)
2950 CHECK_BTGATT_INIT();
2951 /* Send Data to LE Module */
2952 return _bt_hal_enable_advertising(server_if, start, FALSE);
2955 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
2956 bool include_txpower, int min_interval, int max_interval, int appearance,
2957 uint16_t manufacturer_len, char* manufacturer_data,
2958 uint16_t service_data_len, char* service_data,
2959 uint16_t service_uuid_len, char* service_uuid)
2961 CHECK_BTGATT_INIT();
2962 return BT_STATUS_SUCCESS;
2965 static bt_status_t gatt_server_multi_adv_enable(int server_if)
2967 CHECK_BTGATT_INIT();
2968 /* Send Enable Advertising request to LE Module */
2969 return _bt_hal_enable_advertising(server_if, TRUE, TRUE);
2972 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
2973 int chnl_map, int tx_power, int timeout_s)
2975 CHECK_BTGATT_INIT();
2977 /* Send Advertising parameters to LE Module */
2978 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
2979 chnl_map, tx_power, timeout_s);
2982 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
2984 CHECK_BTGATT_INIT();
2986 /* Send Data to LE Module */
2987 return _bt_hal_set_advertising_data(adv_param_setup);
2990 static bt_status_t gatt_server_multi_adv_disable(int server_if)
2992 CHECK_BTGATT_INIT();
2993 /* Send Data to LE Module */
2994 return _bt_hal_enable_advertising(server_if, FALSE, TRUE);
2997 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
2999 CHECK_BTGATT_INIT();
3000 char *object_path = NULL;
3002 GDBusProxy *device_proxy;
3003 GError *error = NULL;
3005 GVariant *tmp_value;
3006 GDBusConnection *conn;
3007 GVariant *result = NULL;
3008 int ret = BT_STATUS_SUCCESS;
3009 struct gatt_client_info_t *conn_info = NULL;
3012 if (mtu_size == NULL)
3013 return BT_STATUS_PARM_INVALID;
3015 /* GDBUS Connection Info validate */
3016 conn = _bt_hal_get_system_gconn();
3018 ERR("Could not get System DBUS Connection");
3019 return BT_STATUS_FAIL;
3022 /* Connection Info validate */
3023 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3024 if (conn_info == NULL) {
3025 ERR("No Connection Inforamtion!!!");
3026 return BT_STATUS_FAIL;
3030 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3031 if (object_path == NULL)
3032 return BT_STATUS_FAIL;
3034 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3035 NULL, BT_HAL_BLUEZ_NAME, object_path,
3036 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3038 g_free(object_path);
3039 if (device_proxy == NULL)
3040 return BT_STATUS_FAIL;
3042 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3043 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3044 G_DBUS_CALL_FLAGS_NONE,
3048 if (result == NULL) {
3049 if (error != NULL) {
3050 ERR("Error occured in Proxy call [%s]\n", error->message);
3051 g_error_free(error);
3053 g_object_unref(device_proxy);
3054 return BT_STATUS_FAIL;
3057 g_variant_get(result , "(@a{sv})", &value);
3058 g_variant_unref(result);
3060 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3061 if (tmp_value == NULL) {
3062 g_object_unref(device_proxy);
3063 g_variant_unref(value);
3064 return BT_STATUS_FAIL;
3067 mtu = g_variant_get_uint16(tmp_value);
3069 DBG("ATT MTU : [%d]", mtu);
3071 g_variant_unref(tmp_value);
3072 g_variant_unref(value);
3073 g_object_unref(device_proxy);
3075 *mtu_size = (int) mtu;
3080 const btgatt_server_interface_t btgatt_server_interface = {
3081 gatt_server_register_app,
3082 gatt_server_unregister_app,
3085 gatt_server_add_service,
3086 gatt_server_add_included_service,
3087 gatt_server_add_characteristic,
3088 gatt_server_add_descriptor,
3089 gatt_server_start_service,
3090 gatt_server_stop_service,
3091 gatt_server_delete_service,
3092 gatt_server_send_indication,
3093 gatt_server_send_response,
3094 gatt_server_update_att_value,
3096 gatt_server_set_adv_data,
3097 gatt_server_multi_adv_enable,
3098 gatt_server_multi_adv_update,
3099 gatt_server_multi_adv_set_inst_data,
3100 gatt_server_multi_adv_disable,
3101 gatt_server_get_mtu_size