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-gatt.h"
44 #include "bt-hal-adapter-le.h"
45 #include "bt-hal-event-receiver.h"
47 #define NUMBER_OF_FLAGS 10
49 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
50 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
51 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
53 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
54 #define GATT_SERV_OBJECT_PATH "/service"
56 static GDBusProxy *manager_gproxy = NULL;
58 /************************************************************************************
60 ************************************************************************************/
61 extern const btgatt_callbacks_t *bt_gatt_callbacks;
62 static guint owner_id;
63 static GDBusConnection *g_conn = NULL;
64 static GDBusNodeInfo *manager_node_info = NULL;
66 #define GATT_HANDLE_MAX_NUM 100 /* Not defined in spec, implementation dependent */
67 #define SERV_HANDLE_NUM (GATT_HANDLE_MAX_NUM)
68 #define CHAR_HANDLE_NUM (SERV_HANDLE_NUM + GATT_HANDLE_MAX_NUM)
69 #define DESC_HANDLE_NUM (CHAR_HANDLE_NUM + GATT_HANDLE_MAX_NUM)
76 static int assigned_handle[BT_GATT_TYPE_MAX];
77 static gboolean gatt_handle_used[BT_GATT_TYPE_MAX][GATT_HANDLE_MAX_NUM];
78 static int gatt_handle_base[BT_GATT_TYPE_MAX] = {SERV_HANDLE_NUM, CHAR_HANDLE_NUM, DESC_HANDLE_NUM};
80 struct gatt_service_info {
87 gboolean is_svc_registered;
88 gboolean is_svc_primary;
92 struct gatt_char_info {
97 gchar *char_flags[NUMBER_OF_FLAGS];
104 struct gatt_desc_info {
109 gchar *desc_flags[NUMBER_OF_FLAGS];
116 * GATT Server Request type
119 BT_HAL_GATT_REQUEST_TYPE_READ = 0x00, /* Read Requested */
120 BT_HAL_GATT_REQUEST_TYPE_WRITE = 0x01, /* Write Requested */
121 BT_HAL_GATT_REQUEST_TYPE_EXEC_WRITE = 0x02, /* Exec Write Requested */
122 BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE = 0x03, /* Exec Write Requested */
123 BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY = 0x04, /* Exec Write Requested */
124 } bt_gatt_request_type_e;
126 struct gatt_req_info {
131 bt_gatt_request_type_e request_type; /* Read or Write request */
132 GDBusMethodInvocation *context;
135 struct gatt_server_app {
141 /* Linked List of gatt server app's */
142 static GSList *gatt_server_apps = NULL;
144 static GSList *gatt_services = NULL;
146 extern int hal_gatt_conn_id;
148 /* Linked List of connected Remote GATT clients */
149 static GSList *gatt_client_info_list = NULL;
151 /* GATT Client Info List Structure */
152 struct gatt_client_info_t {
153 int connection_id; /* This value will uniquely identify a GATT client-server connection */
154 int instance_id; /* This value unique identifies a GATT server instance */
155 char *addr; /* Remote GATT client address */
156 GSList *gatt_req_info_list; /* List of transactions per Connection*/
159 static handle_stack_msg event_cb = NULL;
162 uint32_t instance_data;
164 } hal_register_server_data;
167 uint32_t instance_data;
171 } hal_gatt_service_added;
174 uint32_t instance_data;
176 } hal_gatt_service_started;
179 uint32_t instance_data;
181 } hal_gatt_service_deleted;
184 uint32_t instance_data;
188 } hal_gatt_char_added;
191 uint32_t instance_data;
195 } hal_gatt_desc_added;
198 struct hal_gatts_server_register_info_t {
204 static GSList * hal_gatts_server_register_list;
207 /* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
208 /* TODO: Adjust MAX Server after modifying MAX app handle logic */
209 #define BT_GATTS_MAX 11
211 static int assigned_id = 0;
212 static gboolean instance_id_used[BT_GATTS_MAX];
213 static guint manager_id[BT_GATTS_MAX];
215 #define CHECK_BTGATT_INIT() if (_bt_hal_gatt_interface_ready() == false)\
217 ERR("%s: BTGATT not initialized", __FUNCTION__);\
218 return BT_STATUS_NOT_READY;\
220 DBG("%s", __FUNCTION__);\
223 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data);
225 static void __bt_hal_gatt_deinit(int server_if);
227 static void __bt_hal_register_application_cb(GObject *object,
228 GAsyncResult *res, gpointer user_data);
230 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
233 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
234 const gchar *path, const gchar *interface);
236 static int bt_hal_gatts_get_gatt_server_instance();
238 /* Introspection data for the service we are exporting */
239 static const gchar service_introspection_xml[] =
241 " <interface name='org.freedesktop.DBus.Properties'>"
242 " <property type='s' name='UUID' access='read'>"
244 " <property type='b' name='primary' access='read'>"
246 " <property type='o' name='Device' access='read'>"
248 " <property type='ao' name='Characteristics' access='read'>"
250 " <property type='s' name='Includes' access='read'>"
255 /* Introspection data for the characteristics we are exporting */
256 static const gchar characteristics_introspection_xml[] =
258 " <interface name='org.bluez.GattCharacteristic1'>"
259 " <method name='ReadValue'>"
260 " <arg type='s' name='address' direction='in'/>"
261 " <arg type='u' name='id' direction='in'/>"
262 " <arg type='q' name='offset' direction='in'/>"
263 " <arg type='ay' name='Value' direction='out'/>"
265 " <method name='WriteValue'>"
266 " <arg type='s' name='address' direction='in'/>"
267 " <arg type='u' name='id' direction='in'/>"
268 " <arg type='q' name='offset' direction='in'/>"
269 " <arg type='b' name='response_needed' direction='in'/>"
270 " <arg type='b' name='prep_authorize' direction='in'/>"
271 " <arg type='ay' name='value' direction='in'/>"
273 " <method name ='AcquireWrite'>"
274 " <arg type='a{sv}' name='properties' direction='in'/>"
275 " <arg type='h' name='fd' direction='out'/>"
276 " <arg type='q' name='mtu' direction='out'/>"
278 " <method name = 'AcquireNotify'>"
279 " <arg type='a{sv}' name='properties' direction='in'/>"
280 " <arg type='h' name='fd' direction='out'/>"
281 " <arg type='q' name='mtu' direction='out'/>"
283 " <method name='StartNotify'>"
284 " <arg type='s' name='address' direction='in'/>"
286 " <method name='StopNotify'>"
287 " <arg type='s' name='address' direction='in'/>"
289 " <method name='IndicateConfirm'>"
290 " <arg type='s' name='address' direction='in'/>"
291 " <arg type='b' name='complete' direction='in'/>"
294 " <interface name='org.freedesktop.DBus.Properties'>"
295 " <property type='s' name='UUID' access='read'>"
297 " <property type='o' name='Service' access='read'>"
299 " <property type='ay' name='Value' access='readwrite'>"
301 " <property type='b' name='Notifying' access='read'>"
303 " <property type='as' name='Flags' access='read'>"
305 " <property type='s' name='Unicast' access='read'>"
307 " <property type='ao' name='Descriptors' access='read'>"
309 " <property type='b' name='WriteAcquired' access='read'>"
311 " <property type='b' name='NotifyAcquired' access='read'>"
316 /* Introspection data for the descriptor we are exporting */
317 static const gchar descriptor_introspection_xml[] =
319 " <interface name='org.bluez.GattDescriptor1'>"
320 " <method name='ReadValue'>"
321 " <arg type='s' name='address' direction='in'/>"
322 " <arg type='u' name='id' direction='in'/>"
323 " <arg type='q' name='offset' direction='in'/>"
324 " <arg type='ay' name='Value' direction='out'/>"
326 " <method name='WriteValue'>"
327 " <arg type='s' name='address' direction='in'/>"
328 " <arg type='u' name='id' direction='in'/>"
329 " <arg type='q' name='offset' direction='in'/>"
330 " <arg type='b' name='response_needed' direction='in'/>"
331 " <arg type='b' name='prep_authorize' direction='in'/>"
332 " <arg type='ay' name='value' direction='in'/>"
335 " <interface name='org.freedesktop.DBus.Properties'>"
336 " <property type='s' name='UUID' access='read'>"
338 " <property type='o' name='Characteristic' access='read'>"
340 " <property type='ay' name='Value' access='read'>"
342 " <property type='as' name='Flags' access='read'>"
348 static const gchar manager_introspection_xml[] =
350 " <interface name='org.freedesktop.DBus.ObjectManager'>"
351 " <method name='GetManagedObjects'>"
352 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
357 static void __bt_free_gatt_server_app(struct gatt_server_app *app)
359 g_free(app->app_path);
363 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
368 g_free(svc_info->serv_path);
369 g_free(svc_info->service_uuid);
373 void _bt_hal_gatt_server_init(void)
376 memset(instance_id_used, 0x00, sizeof(instance_id_used));
378 assigned_handle[BT_GATT_TYPE_SERV] = assigned_handle[BT_GATT_TYPE_CHAR] = assigned_handle[BT_GATT_TYPE_DESC] = -1;
379 memset(gatt_handle_used, 0x00, sizeof(gatt_handle_used));
381 g_slist_free_full(gatt_server_apps, (GDestroyNotify)__bt_free_gatt_server_app);
382 gatt_server_apps = NULL;
384 g_slist_free_full(gatt_services, (GDestroyNotify)__bt_hal_gatt_free_service_info);
385 gatt_services = NULL;
387 g_slist_free_full(hal_gatts_server_register_list, g_free);
388 hal_gatts_server_register_list = NULL;
391 static int __bt_hal_gatt_assign_id(void)
395 index = assigned_id + 1;
397 if (index >= BT_GATTS_MAX)
400 while (instance_id_used[index] == TRUE) {
401 if (index == assigned_id) {
402 /* No available ID */
403 ERR("All interface ID is used");
409 if (index >= BT_GATTS_MAX)
414 instance_id_used[index] = TRUE;
419 static void __bt_hal_gatt_delete_id(int instance_id)
421 if (instance_id >= BT_GATTS_MAX || instance_id < 0)
424 instance_id_used[instance_id] = FALSE;
427 static int __bt_hal_assign_gatt_handle(bt_gatt_type_e type)
431 index = assigned_handle[type] + 1;
433 if (index >= GATT_HANDLE_MAX_NUM)
436 while (gatt_handle_used[type][index] == TRUE) {
437 if (index == assigned_handle[type]) {
438 /* No available handle */
439 ERR("All handle is used");
445 if (index >= GATT_HANDLE_MAX_NUM)
449 assigned_handle[type] = index;
450 gatt_handle_used[type][index] = TRUE;
452 return assigned_handle[type] + gatt_handle_base[type];
455 static void __bt_hal_free_gatt_handle(bt_gatt_type_e type, int handle)
459 if (type >= BT_GATT_TYPE_MAX) {
464 index = handle - gatt_handle_base[type];
465 if (index < 0 || index >= GATT_HANDLE_MAX_NUM) {
466 ERR("Invalid handle: %d(type: %d)", handle, type);
470 gatt_handle_used[type][index] = FALSE;
473 static GSList *_bt_get_service_list_from_server(int instance)
476 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
477 INFO("Find App with slot [%d]", instance);
479 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
480 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
482 if (app->slot == instance) {
483 INFO("App slot [%d] Found, Number of services registered [%d]",
484 app->slot, g_slist_length(app->services));
485 return app->services;
491 static char *__bt_get_server_app_path_from_server(int instance)
494 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
495 INFO("Find App with slot [%d]", instance);
497 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
498 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
500 if (app->slot == instance) {
501 INFO("App slot [%d] Found, App path [%s]",
502 app->slot, app->app_path);
503 return app->app_path;
509 static void _bt_remote_service_from_gatt_server(int instance, int service_handle)
514 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
515 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
517 if (app->slot == instance) {
518 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
519 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
520 if (srv->service_handle == service_handle) {
521 app->services = g_slist_remove(app->services, srv);
529 static void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
532 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
533 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
535 if (app->slot == slot) {
536 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
537 serv_info->service_handle, slot);
538 app->services = g_slist_append(app->services, serv_info);
543 int _bt_get_remote_gatt_client_conn_id(char *address)
546 struct gatt_client_info_t *info = NULL;
548 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
549 info = (struct gatt_client_info_t*)l->data;
553 if (!g_strcmp0(info->addr, address)) {
554 INFO("Remote GATT client found addr[%s]", info->addr);
555 return info->connection_id;
561 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
564 struct gatt_client_info_t *info = NULL;
566 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
567 info = (struct gatt_client_info_t*)l->data;
571 if (!g_strcmp0(info->addr, address))
577 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
580 struct gatt_client_info_t *info = NULL;
582 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
583 info = (struct gatt_client_info_t*)l->data;
587 if (info->connection_id == conn_id)
593 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
598 struct gatt_client_info_t *info = NULL;
599 struct gatt_req_info *info1 = NULL;
601 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
602 info = (struct gatt_client_info_t*)l->data;
606 if (info->connection_id == conn_id) {
608 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
610 info1 = (struct gatt_req_info*)l1->data;
614 if (info1->request_id == trans_id)
622 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
624 struct hal_ev_gatt_server_connected ev;
625 struct gatt_client_info_t *conn_info = NULL;
626 memset(&ev, 0, sizeof(ev));
628 /* Convert address to hex */
629 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
631 /* Create Connection ID */
632 /* Check if device is already in connected list */
633 conn_info = __bt_find_remote_gatt_client_info(address);
635 /* If disconnected, and conn info found, then remove conn info */
636 if (is_connected == FALSE) {
637 DBG("GATT Disconnected");
639 INFO("Remove GATT client info from List..");
640 /* Remove info from List */
641 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
642 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
645 ERR("GATT callback not registered");
647 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
648 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
649 ev.conn_id = conn_info->connection_id;
650 ev.server_instance = conn_info->instance_id;
651 ev.connected = is_connected;
653 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
655 g_free(conn_info->addr);
658 /* If connected, and conn info NOT found, then add conn info */
662 /* Find Server Instance */
663 instance = bt_hal_gatts_get_gatt_server_instance();
664 if (instance == -1) {
665 ERR("Not even a single GATT server is registered");
666 ev.conn_id = ++hal_gatt_conn_id;
667 ev.server_instance = -1;
668 ev.connected = is_connected;
669 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
672 DBG("server instance [%d]", instance);
675 /* Save Connection info */
676 conn_info = g_new0(struct gatt_client_info_t, 1);
677 conn_info->addr = g_strdup(address);
678 DBG("Added GATT client addr[%s]", conn_info->addr);
679 conn_info->connection_id = ++hal_gatt_conn_id;
680 conn_info->instance_id = instance;
681 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
682 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
685 ERR("GATT callback not registered");
687 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
688 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
689 ev.conn_id = conn_info->connection_id;
690 ev.server_instance = conn_info->instance_id;
691 ev.connected = is_connected;
693 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
696 ERR("Abnormal case. conn_info should be NULL");
699 /* Send GATT connected or disconnected event */
702 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
706 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
707 struct gatt_service_info *serv_info = l1->data;
709 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
710 struct gatt_char_info *char_info = l2->data;
712 if (g_strcmp0(char_info->char_path, char_path)
714 *char_hdl = char_info->char_handle;
719 ERR("Gatt service not found");
723 static char *__bt_gatt_find_char_path_from_handle(int char_hdl)
727 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
728 struct gatt_service_info *serv_info = l1->data;
730 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
731 struct gatt_char_info *char_info = l2->data;
733 if (char_info->char_handle == char_hdl)
734 return char_info->char_path;
741 static struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
745 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
746 struct gatt_service_info *serv_info = l1->data;
748 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
749 struct gatt_char_info *char_info = l2->data;
751 if (char_info->char_handle == char_hdl)
759 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
761 GSList *l1, *l2, *l3;
763 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
764 struct gatt_service_info *serv_info = l1->data;
766 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
767 struct gatt_char_info *char_info = l2->data;
769 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
770 struct gatt_desc_info *desc_info = l3->data;
772 if (g_strcmp0(desc_info->desc_path, desc_path)
774 *desc_hdl = desc_info->desc_handle;
780 ERR("Gatt service not found");
784 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
786 const gchar *object_path,
787 const gchar *interface_name,
788 const gchar *method_name,
789 GVariant *parameters,
790 GDBusMethodInvocation *invocation,
795 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
796 GVariantBuilder *builder;
797 GVariantBuilder *inner_builder1 = NULL;
798 GVariant *svc_char = NULL;
800 GSList *gatt_services = NULL;
802 instance = (int*)user_data;
803 gboolean writeAcquired = FALSE;
804 gboolean notifyAcquired = FALSE;
806 DBG("Getting values for service, chars and descriptors");
807 DBG("GATT Server App for which services are requested [%d]", *instance);
810 builder = g_variant_builder_new(
811 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
814 gatt_services = _bt_get_service_list_from_server(*instance);
816 if (g_slist_length(gatt_services) == 0) {
817 ERR("No registered GATT services!!!!");
818 g_dbus_method_invocation_return_value(invocation, NULL);
819 g_variant_builder_unref(builder);
823 for (l = gatt_services; l != NULL; l = l->next) {
824 GVariantBuilder *svc_builder = NULL;
825 GVariantBuilder *inner_builder = NULL;
826 struct gatt_service_info *serv_info = l->data;
827 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
829 /* Prepare inner builder for GattService1 interface */
830 DBG("Creating builder for service");
831 svc_builder = g_variant_builder_new(
832 G_VARIANT_TYPE("a{sa{sv}}"));
833 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
835 g_variant_builder_add(inner_builder, "{sv}", "UUID",
836 g_variant_new_string(serv_info->service_uuid));
838 g_variant_builder_add(inner_builder, "{sv}", "Primary",
839 g_variant_new_boolean(serv_info->is_svc_primary));
842 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
843 DBG("Adding Charatarisitcs list");
844 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
845 struct gatt_char_info *char_info = l4->data;
846 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
847 char_info->char_handle, serv_info->service_handle);
848 g_variant_builder_add(inner_builder1, "o",
849 char_info->char_path);
850 DBG("%s", char_info->char_path);
853 svc_char = g_variant_new("ao", inner_builder1);
854 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
857 g_variant_builder_add(svc_builder, "{sa{sv}}",
861 g_variant_builder_add(builder, "{oa{sa{sv}}}",
862 serv_info->serv_path,
865 g_variant_builder_unref(inner_builder1);
867 /* Prepare inner builder for GattCharacteristic1 interface */
869 GSList *l2 = serv_info->char_data;
870 DBG("Creating builder for characteristics \n");
873 DBG("characteristic data is NULL");
875 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
877 GVariantBuilder *char_builder = NULL;
878 GVariantBuilder *inner_builder = NULL;
879 GVariantBuilder *builder1 = NULL;
880 GVariantBuilder *builder2 = NULL;
881 GVariantBuilder *builder3 = NULL;
882 GVariant *char_val = NULL;
883 GVariant *flags_val = NULL;
884 GVariant *char_desc = NULL;
885 char *unicast = NULL;
886 gboolean notify = FALSE;
889 char_builder = g_variant_builder_new(
892 inner_builder = g_variant_builder_new(
896 struct gatt_char_info *char_info = l2->data;
897 if (char_info == NULL) {
898 ERR("char_info is NULL");
903 g_variant_builder_add(inner_builder, "{sv}", "UUID",
904 g_variant_new_string(char_info->char_uuid));
906 g_variant_builder_add(inner_builder, "{sv}", "Service",
907 g_variant_new("o", serv_info->serv_path));
909 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
911 if (char_info->char_value != NULL) {
912 for (i = 0; i < char_info->value_length; i++) {
913 g_variant_builder_add(builder1, "y",
914 char_info->char_value[i]);
916 char_val = g_variant_new("ay", builder1);
917 g_variant_builder_add(inner_builder, "{sv}",
921 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
922 for (i = 0; i < char_info->flags_length; i++) {
923 g_variant_builder_add(builder2, "s",
924 char_info->char_flags[i]);
926 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
927 DBG("setting WriteAcquired property");
928 writeAcquired = TRUE;
931 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
932 DBG("setting NotifyAcquired property");
933 notifyAcquired = TRUE;
937 flags_val = g_variant_new("as", builder2);
938 g_variant_builder_add(inner_builder, "{sv}", "Flags",
942 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
943 g_variant_new("b", notify));
946 if (writeAcquired == TRUE) {
947 DBG("adding WriteAcquired property");
948 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
949 g_variant_new("b", writeAcquired));
953 if (notifyAcquired == TRUE) {
954 DBG("adding NotifyAcquired property");
955 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
956 g_variant_new("b", notifyAcquired));
960 unicast = g_strdup("00:00:00:00:00:00");
961 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
962 g_variant_new("s", unicast));
965 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
966 DBG("Adding Descriptors list");
968 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
969 struct gatt_desc_info *desc_info = l4->data;
970 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
971 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
972 g_variant_builder_add(builder3, "o",
973 desc_info->desc_path);
974 DBG("%s", desc_info->desc_path);
977 char_desc = g_variant_new("ao", builder3);
978 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
981 g_variant_builder_add(char_builder, "{sa{sv}}",
982 GATT_CHAR_INTERFACE , inner_builder);
983 g_variant_builder_add(builder, "{oa{sa{sv}}}",
984 char_info->char_path, char_builder);
986 /*Prepare inner builder for GattDescriptor1 interface*/
988 GSList *l3 = char_info->desc_data;
991 DBG("descriptor data is NULL");
993 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
995 DBG("Creating builder for descriptor \n");
997 GVariantBuilder *desc_builder = NULL;
998 GVariantBuilder *inner_builder = NULL;
999 GVariantBuilder *builder1 = NULL;
1000 GVariantBuilder *builder2 = NULL;
1001 GVariant *desc_val = NULL;
1003 desc_builder = g_variant_builder_new(
1006 inner_builder = g_variant_builder_new(
1010 struct gatt_desc_info *desc_info = l3->data;
1011 if (desc_info == NULL) {
1012 ERR("desc_info is NULL");
1017 g_variant_builder_add(inner_builder,
1019 g_variant_new_string(
1020 desc_info->desc_uuid));
1023 g_variant_builder_add(inner_builder, "{sv}",
1026 char_info->char_path));
1029 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1031 if (desc_info->desc_value != NULL) {
1032 for (i = 0; i < desc_info->value_length; i++) {
1033 g_variant_builder_add(builder1, "y",
1034 desc_info->desc_value[i]);
1036 desc_val = g_variant_new("ay", builder1);
1037 g_variant_builder_add(inner_builder, "{sv}",
1042 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1044 for (i = 0; i < desc_info->flags_length; i++) {
1045 g_variant_builder_add(builder2, "s",
1046 desc_info->desc_flags[i]);
1049 flags_val = g_variant_new("as", builder2);
1050 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1053 g_variant_builder_add(desc_builder, "{sa{sv}}",
1054 GATT_DESC_INTERFACE,
1057 g_variant_builder_add(builder, "{oa{sa{sv}}}",
1058 desc_info->desc_path,
1061 /*unref descriptor builder pointers*/
1062 g_variant_builder_unref(builder1);
1063 g_variant_builder_unref(builder2);
1064 g_variant_builder_unref(inner_builder);
1065 g_variant_builder_unref(desc_builder);
1070 /*unref char builder pointers*/
1071 g_variant_builder_unref(builder1);
1072 g_variant_builder_unref(builder2);
1073 g_variant_builder_unref(builder3);
1074 g_variant_builder_unref(inner_builder);
1075 g_variant_builder_unref(char_builder);
1078 /*unref service builder pointers*/
1079 g_variant_builder_unref(inner_builder);
1080 g_variant_builder_unref(svc_builder);
1083 /* Return builder as method reply */
1084 DBG("Sending gatt service builder values to Bluez");
1085 g_dbus_method_invocation_return_value(invocation,
1091 /* Free User Data */
1095 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1096 const gchar *sender,
1097 const gchar *object_path,
1098 const gchar *interface_name,
1099 const gchar *method_name,
1100 GVariant *parameters,
1101 GDBusMethodInvocation *invocation,
1105 if (g_strcmp0(method_name, "ReadValue") == 0) {
1106 struct hal_ev_gatt_server_read_req ev;
1111 struct gatt_client_info_t *conn_info = NULL;
1112 struct gatt_req_info *req_info = NULL;
1113 struct gatt_service_info *svc_info = NULL;
1117 DBG("Application path = %s", object_path);
1118 DBG("Sender = %s", sender);
1120 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1121 if (svc_info == NULL) {
1122 ERR("Coudn't find service for %s", object_path);
1123 g_dbus_method_invocation_return_value(invocation, NULL);
1127 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1128 DBG("Request id = %u, Offset = %u", req_id, offset);
1130 /* Check if device is already in connected list */
1131 conn_info = __bt_find_remote_gatt_client_info(addr);
1133 if (conn_info == NULL) {
1134 ERR("Coudn't find Connection info for %s", addr);
1135 g_dbus_method_invocation_return_value(invocation, NULL);
1140 ERR("GATT callback NOT registered");
1141 g_dbus_method_invocation_return_value(invocation, NULL);
1145 /* Store requests information */
1146 req_info = g_new0(struct gatt_req_info, 1);
1147 req_info->attr_path = g_strdup(object_path);
1148 req_info->svc_path = g_strdup(svc_info->serv_path);
1149 req_info->request_id = req_id;
1150 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1151 req_info->offset = offset;
1152 req_info->context = invocation;
1154 /* Append request info in list of requests for the particular connection */
1155 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1157 /* Send HAL event */
1158 memset(&ev, 0, sizeof(ev));
1159 ev.conn_id = conn_info->connection_id;
1160 ev.trans_id = req_id;
1161 ev.att_handle = desc_hdl;
1163 ev.is_long = false; /* TODO*/
1165 /* Convert address to hex */
1166 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1168 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1170 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1172 GVariant *var = NULL;
1176 gboolean response_needed = FALSE;
1177 gboolean prep_authorize = FALSE;
1178 struct hal_ev_gatt_server_write_req ev;
1182 struct gatt_service_info *svc_info = NULL;
1183 struct gatt_client_info_t *conn_info = NULL;
1184 struct gatt_req_info *req_info = NULL;
1186 memset(&ev, 0, sizeof(ev));
1189 DBG("Application path = %s", object_path);
1190 DBG("Sender = %s", sender);
1192 g_variant_get(parameters, "(&suqbb@ay)",
1193 &addr, &req_id, &offset, &response_needed, &prep_authorize, &var);
1194 DBG("Request id = %u, Offset = %u", req_id, offset);
1197 DBG("prep_authorize = true");
1199 /* Check if device is already in connected list */
1200 conn_info = __bt_find_remote_gatt_client_info(addr);
1202 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1204 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1205 g_variant_unref(var);
1206 g_dbus_method_invocation_return_value(invocation, NULL);
1210 len = g_variant_get_size(var);
1211 if (len > 0 && len < 600) {
1213 data = (char *)g_variant_get_data(var);
1214 memcpy(ev.value, data, len);
1217 if (response_needed) {
1218 /* Store request information */
1219 req_info = g_new0(struct gatt_req_info, 1);
1220 req_info->attr_path = g_strdup(object_path);
1221 req_info->svc_path = g_strdup(svc_info->serv_path);
1222 req_info->request_id = req_id;
1223 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1224 req_info->offset = offset;
1225 req_info->context = invocation;
1227 /* Append request info in list of requests for the particular connection */
1228 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1230 /* Send reply now */
1231 g_dbus_method_invocation_return_value(invocation, NULL);
1234 /* Send HAL event */
1235 ev.conn_id = conn_info->connection_id;
1236 ev.trans_id = req_id;
1237 ev.att_handle = desc_hdl;
1239 ev.need_rsp = response_needed;
1242 /* Convert address to hex */
1243 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1245 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1247 g_variant_unref(var);
1252 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1253 const gchar *sender,
1254 const gchar *object_path,
1255 const gchar *interface_name,
1256 const gchar *method_name,
1257 GVariant *parameters,
1258 GDBusMethodInvocation *invocation,
1261 if (g_strcmp0(method_name, "ReadValue") == 0) {
1265 struct hal_ev_gatt_server_read_req ev;
1268 struct gatt_req_info *req_info = NULL;
1269 struct gatt_client_info_t *conn_info = NULL;
1270 struct gatt_service_info *svc_info = NULL;
1272 g_variant_get(parameters, "(&suq)",
1273 &addr, &req_id, &offset);
1275 DBG("ReadValue : req id %u, offset %u, path %s, sender %s, %s", req_id, offset, object_path, sender, addr);
1277 /* Check if device is already in connected list */
1278 conn_info = __bt_find_remote_gatt_client_info(addr);
1280 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1282 if (svc_info == NULL || conn_info == NULL) {
1283 ERR("Invalid information %p, %p", svc_info, conn_info);
1284 g_dbus_method_invocation_return_value(invocation, NULL);
1289 ERR("GATT callback NOT registered");
1290 g_dbus_method_invocation_return_value(invocation, NULL);
1294 /* Store requets information */
1295 req_info = g_new0(struct gatt_req_info, 1);
1296 req_info->attr_path = g_strdup(object_path);
1297 req_info->svc_path = g_strdup(svc_info->serv_path);
1298 req_info->request_id = req_id;
1299 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1300 req_info->offset = offset;
1301 req_info->context = invocation;
1303 /* Append request info in list of requests for the particular connection */
1304 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1306 /* Send HAL event */
1307 memset(&ev, 0, sizeof(ev));
1308 ev.conn_id = conn_info->connection_id;
1309 ev.trans_id = req_id;
1310 ev.att_handle = char_hdl;
1312 ev.is_long = false; /* TODO*/
1314 /* Convert address to hex */
1315 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1316 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1318 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1319 GVariant *var = NULL;
1323 gboolean response_needed = FALSE;
1324 gboolean prep_authorize = FALSE;
1325 struct hal_ev_gatt_server_write_req ev;
1329 struct gatt_service_info *svc_info = NULL;
1330 struct gatt_req_info *req_info = NULL;
1331 struct gatt_client_info_t *conn_info = NULL;
1333 memset(&ev, 0, sizeof(ev));
1335 DBG("WriteValue : Application path %s, sender %s", object_path, sender);
1337 g_variant_get(parameters, "(&suqbb@ay)",
1338 &addr, &req_id, &offset, &response_needed, &prep_authorize, &var);
1339 DBG("Request id = %u, Offset = %u", req_id, offset);
1342 DBG("prep_authorize = true");
1344 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1346 /* Check if device is already in connected list */
1347 conn_info = __bt_find_remote_gatt_client_info(addr);
1349 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1350 g_variant_unref(var);
1351 g_dbus_method_invocation_return_value(invocation, NULL);
1355 len = g_variant_get_size(var);
1356 if (len > 0 && len < 600) {
1358 data = (char *)g_variant_get_data(var);
1359 memcpy(ev.value, data, len);
1363 if (response_needed) {
1364 /* Store requets information */
1365 req_info = g_new0(struct gatt_req_info, 1);
1366 req_info->attr_path = g_strdup(object_path);
1367 req_info->svc_path = g_strdup(svc_info->serv_path);
1368 req_info->request_id = req_id;
1369 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1370 req_info->offset = offset;
1371 req_info->context = invocation;
1373 /* Append request info in list of requests for the particular connection */
1374 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1377 /* Send reply now */
1378 g_dbus_method_invocation_return_value(invocation, NULL);
1381 /* Send HAL event */
1382 ev.conn_id = conn_info->connection_id;
1383 ev.trans_id = req_id;
1384 ev.att_handle = char_hdl;
1386 ev.need_rsp = response_needed;
1389 /* Convert address to hex */
1390 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1392 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1394 g_variant_unref(var);
1397 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1400 struct gatt_service_info *svc_info = NULL;
1401 struct gatt_client_info_t *conn_info = NULL;
1402 struct hal_ev_gatt_server_notifcation_change ev;
1406 g_variant_get(parameters, "(&s)", &addr);
1407 INFO("Remote address %s", addr);
1409 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1411 conn_info = __bt_find_remote_gatt_client_info(addr);
1413 if (svc_info == NULL || conn_info == NULL
1414 || event_cb == NULL)
1417 /* Send HAL event */
1418 memset(&ev, 0, sizeof(ev));
1419 ev.conn_id = conn_info->connection_id;
1420 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1421 ev.att_handle = char_hdl;
1424 /* Convert address to hex */
1425 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1427 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1430 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1433 struct gatt_service_info *svc_info = NULL;
1434 struct gatt_client_info_t *conn_info = NULL;
1435 struct hal_ev_gatt_server_notifcation_change ev;
1439 g_variant_get(parameters, "(&s)", &addr);
1440 INFO("Remote address %s", addr);
1442 conn_info = __bt_find_remote_gatt_client_info(addr);
1444 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1445 if (svc_info == NULL || conn_info == NULL
1446 || event_cb == NULL)
1449 /* Send HAL event */
1450 memset(&ev, 0, sizeof(ev));
1451 ev.conn_id = conn_info->connection_id;
1452 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1453 ev.att_handle = char_hdl;
1456 /* Convert address to hex */
1457 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1459 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1462 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1464 gboolean complete = FALSE;
1467 struct gatt_service_info *svc_info = NULL;
1468 struct gatt_client_info_t *conn_info = NULL;
1470 struct hal_ev_gatt_server_indicate_cfm ev;
1472 DBG("IndicateConfirm : Application path %s, sender %s", object_path, sender);
1474 g_variant_get(parameters, "(&sb)", &addr, &complete);
1475 DBG("Remote Device address number = %s", addr);
1476 DBG("Is Indicate confirmation for last device [%d]", complete);
1478 /* Check if device is already in connected list */
1479 conn_info = __bt_find_remote_gatt_client_info(addr);
1481 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1483 if (svc_info == NULL || conn_info == NULL
1484 || event_cb == NULL) {
1488 /* Send HAL event */
1489 memset(&ev, 0, sizeof(ev));
1490 ev.conn_id = conn_info->connection_id;
1491 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1492 ev.att_handle = char_hdl;
1494 /* Convert address to hex */
1495 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1497 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1498 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1502 struct hal_ev_gatt_server_acquire_write_res ev;
1503 struct gatt_service_info *svc_info = NULL;
1504 struct gatt_req_info *req_info = NULL;
1505 struct gatt_client_info_t *conn_info = NULL;
1506 char *dev_path = NULL;
1508 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1510 DBG("AcquireWrite : Application path %s, sender %s", object_path, sender);
1513 g_variant_get(parameters, "(a{sv})", &iter);
1515 GVariant *value = NULL;
1516 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1517 if (g_strcmp0(key, "MTU") == 0)
1518 g_variant_get(value, "q", &mtu);
1519 else if (g_strcmp0(key, "link") == 0)
1520 g_variant_get(value, "s", &link);
1521 else if (g_strcmp0(key, "device") == 0)
1522 g_variant_get(value, "o", &dev_path);
1525 DBG(" path %s LINK = %s, MTU = %u", dev_path, link, mtu);
1527 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1529 _bt_hal_convert_device_path_to_address(dev_path, addr);
1531 DBG("remote address %s", addr);
1535 /* Check if device is already in connected list */
1536 conn_info = __bt_find_remote_gatt_client_info(addr);
1537 if (conn_info == NULL) {
1538 ERR("Cleint info not found\n");
1539 g_variant_iter_free(iter);
1543 if (svc_info == NULL) {
1544 ERR("svc_info info not found\n");
1545 g_variant_iter_free(iter);
1549 /* Store requets information */
1550 req_info = g_new0(struct gatt_req_info, 1);
1551 req_info->attr_path = g_strdup(object_path);
1552 req_info->svc_path = g_strdup(svc_info->serv_path);
1553 req_info->request_id = conn_info->connection_id;
1554 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1555 req_info->offset = mtu;
1556 req_info->context = invocation;
1558 /* Append request info in list of requests for the particular connection */
1559 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1561 /* Send HAL event */
1562 memset(&ev, 0, sizeof(ev));
1563 ev.conn_id = conn_info->connection_id;
1564 ev.char_handl = char_hdl;
1566 ev.trans_id = conn_info->connection_id;
1567 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1568 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1569 g_variant_iter_free(iter);
1571 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1575 char *dev_path = NULL;
1577 struct hal_ev_gatt_server_acquire_notify ev;
1578 struct gatt_service_info *svc_info = NULL;
1579 struct gatt_client_info_t *conn_info = NULL;
1580 struct gatt_req_info *req_info = NULL;
1581 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1583 INFO("AcquireNotify : Application path %s, sender %s", object_path, sender);
1586 g_variant_get(parameters, "(a{sv})", &iter);
1588 GVariant* value = NULL;
1589 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1590 if (g_strcmp0(key, "MTU") == 0)
1591 g_variant_get(value, "q", &mtu);
1592 else if (g_strcmp0(key, "link") == 0)
1593 g_variant_get(value, "s", &link);
1594 else if (g_strcmp0(key, "device") == 0)
1595 g_variant_get(value, "o", &dev_path);
1598 DBG("MTU = %u", mtu);
1599 INFO("Dev Path %s LINK = %s, MTU = %u", dev_path, link, mtu);
1600 _bt_hal_convert_device_path_to_address(dev_path, addr);
1601 INFO("Remote address %s", addr);
1605 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1607 /* Check if device is already in connected list */
1608 conn_info = __bt_find_remote_gatt_client_info(addr);
1609 if (conn_info == NULL) {
1610 ERR("Client info not found\n");
1611 g_variant_iter_free(iter);
1614 if (svc_info == NULL) {
1615 ERR("svc_info info not found\n");
1616 g_variant_iter_free(iter);
1620 /* Store requets information */
1621 req_info = g_new0(struct gatt_req_info, 1);
1622 req_info->attr_path = g_strdup(object_path);
1623 req_info->svc_path = g_strdup(svc_info->serv_path);
1624 req_info->request_id = -1;
1625 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1626 req_info->offset = mtu;
1627 req_info->context = invocation;
1629 INFO("AcquireNotify : Added GATT client path[%s]", conn_info->addr);
1630 /* Append request info in list of requests for the particular connection */
1631 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1633 /* Send HAL event */
1634 memset(&ev, 0, sizeof(ev));
1635 ev.conn_id = conn_info->connection_id;
1636 ev.char_handl = char_hdl;
1638 ev.trans_id = req_info->request_id;
1639 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1641 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1642 g_variant_iter_free(iter);
1647 g_dbus_method_invocation_return_value(invocation, NULL);
1650 static gboolean __bt_hal_gatt_emit_interface_removed(const char *app_path, gchar *object_path, gchar *interface)
1653 GError *error = NULL;
1654 GVariantBuilder *array_builder;
1656 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1657 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1658 g_variant_builder_add(array_builder, "s", interface);
1660 ret = g_dbus_connection_emit_signal(g_conn, NULL, app_path,
1661 "org.freedesktop.DBus.ObjectManager",
1662 "InterfacesRemoved",
1663 g_variant_new("(oas)",
1664 object_path, array_builder),
1668 if (error != NULL) {
1669 /* dbus gives error cause */
1670 ERR("d-bus api failure: errcode[%x], message[%s]",
1671 error->code, error->message);
1672 g_clear_error(&error);
1675 g_variant_builder_unref(array_builder);
1680 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1687 g_free(desc_info->desc_path);
1688 g_free(desc_info->desc_uuid);
1689 g_free(desc_info->desc_value);
1691 for (i = 0; i < desc_info->flags_length; i++)
1692 g_free(desc_info->desc_flags[i]);
1697 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1704 g_free(char_info->char_path);
1705 g_free(char_info->char_uuid);
1706 g_free(char_info->char_value);
1708 for (i = 0; i < char_info->flags_length; i++)
1709 g_free(char_info->char_flags[i]);
1714 static const GDBusInterfaceVTable desc_interface_vtable = {
1715 __bt_gatt_desc_method_call,
1720 static const GDBusInterfaceVTable char_interface_vtable = {
1721 __bt_gatt_char_method_call,
1726 static const GDBusInterfaceVTable serv_interface_vtable = {
1732 static const GDBusInterfaceVTable manager_interface_vtable = {
1733 __bt_gatt_manager_method_call,
1739 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1740 const gchar *introspection_data)
1743 GDBusNodeInfo *node_info = NULL;
1745 if (introspection_data == NULL)
1749 DBG("Create new node info");
1750 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1753 ERR("Unable to create node: %s", err->message);
1754 g_clear_error(&err);
1761 /* To send stack event to hal-av handler */
1762 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1767 void _bt_hal_unregister_gatt_server_handler_cb(void)
1772 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1774 struct hal_ev_gatt_desc_added ev;
1775 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1777 /* Prepare to GATT characteristic added event */
1778 memset(&ev, 0, sizeof(ev));
1779 ev.status = BT_STATUS_SUCCESS;
1780 ev.server_instance = data->instance_data;
1781 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1782 ev.service_handle = data->srvc_hdl;
1783 ev.desc_handle = data->desc_hdl;
1786 ERR("GATT Descriptor Added callback registered");
1788 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1789 data->instance_data, data->srvc_hdl, data->desc_hdl);
1791 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1798 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1800 struct hal_ev_gatt_char_added ev;
1801 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1803 /* Prepare to GATT characteristic added event */
1804 memset(&ev, 0, sizeof(ev));
1805 ev.status = BT_STATUS_SUCCESS;
1806 ev.server_instance = data->instance_data;
1807 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1808 ev.service_handle = data->srvc_hdl;
1809 ev.char_handle = data->char_hdl;
1812 ERR("GATT Characteristic Added callback registered");
1814 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1815 data->instance_data, data->srvc_hdl, data->char_hdl);
1817 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1824 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1826 struct hal_ev_gatt_service_added ev;
1827 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1829 /* Prepare to GATT Service added event */
1830 memset(&ev, 0, sizeof(ev));
1831 ev.status = BT_STATUS_SUCCESS;
1832 ev.server_instance = data->instance_data;
1833 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1834 ev.service_handle = data->srvc_hdl;
1835 ev.is_primary = data->is_primary;
1838 ERR("GATT Service Added callback registered");
1840 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1841 data->instance_data, data->srvc_hdl);
1842 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1849 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1851 struct hal_ev_gatt_service_started ev;
1852 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1854 /* Prepare to GATT Service added event */
1855 memset(&ev, 0, sizeof(ev));
1856 ev.status = BT_STATUS_SUCCESS;
1857 ev.server_instance = data->instance_data;
1858 ev.service_handle = data->srvc_hdl;
1861 ERR("GATT Service Started callback registered");
1863 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1864 data->instance_data, data->srvc_hdl);
1865 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1872 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1874 struct hal_ev_gatt_service_deleted ev;
1875 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1877 /* Prepare to GATT Service added event */
1878 memset(&ev, 0, sizeof(ev));
1879 ev.status = BT_STATUS_SUCCESS;
1880 ev.server_instance = data->instance_data;
1881 ev.service_handle = data->srvc_hdl;
1884 ERR("GATT Service Deleted callback registered");
1886 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1887 data->instance_data, data->srvc_hdl);
1888 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1895 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1897 struct hal_ev_server_instance_registered ev;
1898 hal_register_server_data *data = (hal_register_server_data*) user_data;
1900 /* Prepare to send AV connecting event */
1901 memset(&ev, 0, sizeof(ev));
1902 ev.status = BT_STATUS_SUCCESS;
1903 ev.server_instance = data->instance_data;
1904 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1907 ERR("GATT Register Server Instance Callback not registered");
1909 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1910 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1918 static int bt_hal_gatts_get_gatt_server_instance()
1923 struct hal_gatts_server_register_info_t *info = NULL;
1925 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1926 info = (struct hal_gatts_server_register_info_t *)l->data;
1931 return info->server_if;
1937 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_from_uuid(bt_uuid_t *app_uuid)
1942 struct hal_gatts_server_register_info_t *info = NULL;
1944 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1945 info = (struct hal_gatts_server_register_info_t *)l->data;
1950 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
1951 DBG("gatt server register found");
1959 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info(int server_if)
1962 struct hal_gatts_server_register_info_t *info = NULL;
1964 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1965 info = (struct hal_gatts_server_register_info_t *)l->data;
1970 if (info->server_if == server_if) {
1978 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_by_slot_id(int adv_slot_id)
1983 struct hal_gatts_server_register_info_t *info = NULL;
1985 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1986 info = (struct hal_gatts_server_register_info_t *)l->data;
1991 if (info->adv_slot_id == adv_slot_id) {
1992 DBG("gatt server register found");
2000 static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_uuid_t *app_uuid)
2002 struct hal_gatts_server_register_info_t * server_register_info = NULL;
2003 int instance_id = 0;
2005 server_register_info = bt_hal_gatts_find_server_register_info_from_uuid(app_uuid);
2006 if (server_register_info != NULL) {
2007 DBG("gatt server is already registered");
2008 return server_register_info;
2011 instance_id = __bt_hal_gatt_assign_id();
2012 if (instance_id == -1) {
2013 ERR("Fail to allocate the server if");
2017 server_register_info = g_malloc0(sizeof(struct hal_gatts_server_register_info_t));
2018 server_register_info->server_if = instance_id;
2020 DBG("Adding the gatt server app. server_if:[%d]", server_register_info->server_if);
2022 server_register_info->adv_slot_id = -1;
2023 memcpy(&server_register_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
2024 hal_gatts_server_register_list = g_slist_append(hal_gatts_server_register_list, server_register_info);
2026 return server_register_info;
2029 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
2031 CHECK_BTGATT_INIT();
2032 struct hal_gatts_server_register_info_t *server_register_info = NULL;
2034 DBG("Register server instance request");
2035 server_register_info = bt_hal_gatts_add_server_app(uuid);
2036 if (server_register_info == NULL) {
2037 ERR("Fail to register the server app");
2038 return BT_STATUS_FAIL;
2041 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
2042 user_data->instance_data = server_register_info->server_if;
2045 * As we need to provide async callback to user from HAL, simply schedule a
2046 * callback method which will carry actual result
2048 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
2049 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
2051 /* If available, then return success, else return error */
2052 return BT_STATUS_SUCCESS;
2055 static void _bt_hal_remove_gatt_server_from_list(int server_if)
2058 struct gatt_server_app *info = NULL;
2060 for (l = gatt_server_apps; l != NULL;) {
2061 info = (struct gatt_server_app*)l->data;
2062 l = g_slist_next(l);
2065 if (info->slot == server_if) {
2066 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
2067 info->app_path, info->slot);
2069 /* Only if all services are deleted from the GATT Server, then only Unregister it.
2070 Reason: it is possible, GATT Server app oly wants to disable multi advertising
2071 In above case, only advertising block will be deallocated, Gatt Server will remain
2073 if (info->services == NULL) {
2074 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
2075 INFO("Total gatt server apps still existing after removing above is [%d]",
2076 g_slist_length(gatt_server_apps));
2078 /* DBUS Unregister only for current app */
2079 __bt_hal_gatt_deinit(server_if);
2081 g_free(info->app_path);
2085 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
2086 g_slist_length(info->services));
2092 static bt_status_t gatt_server_unregister_app(int server_if)
2094 CHECK_BTGATT_INIT();
2095 DBG("Un-Register server instance request [%d]", server_if);
2096 struct hal_gatts_server_register_info_t *server_register_info = NULL;
2099 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
2100 if (server_register_info == NULL) {
2101 DBG("gatt server is not registered");
2102 return BT_STATUS_SUCCESS;
2105 /* remove the gatt server register info from the register list */
2106 hal_gatts_server_register_list = g_slist_remove(hal_gatts_server_register_list, server_register_info);
2107 g_free(server_register_info);
2109 __bt_hal_gatt_delete_id(server_if);
2111 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
2112 _bt_hal_remove_gatt_server_from_list(server_if);
2113 return BT_STATUS_SUCCESS;
2116 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
2118 CHECK_BTGATT_INIT();
2119 return BT_STATUS_SUCCESS;
2122 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
2125 GError *g_error = NULL;
2126 GVariant *reply = NULL;
2130 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2131 g_object_unref(proxy);
2132 if (reply == NULL) {
2133 ERR("Disconnect LE Dbus Call Error");
2135 ERR("Error: %s\n", g_error->message);
2136 g_clear_error(&g_error);
2139 g_variant_unref(reply);
2143 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
2145 CHECK_BTGATT_INIT();
2147 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2149 GDBusProxy *device_proxy;
2150 GDBusConnection *g_conn;
2151 struct gatt_client_info_t *conn_info = NULL;
2155 if (NULL == bd_addr) {
2156 ERR("bd_addr is NULL");
2157 return BT_STATUS_PARM_INVALID;
2160 /* GDBUS Connection Info validate */
2161 g_conn = _bt_hal_get_system_gconn();
2162 if (g_conn == NULL) {
2163 ERR("Could not get System DBUS Connection");
2164 return BT_STATUS_FAIL;
2167 /* Connection Info validate */
2168 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2169 if (conn_info == NULL) {
2170 ERR("No Connection Inforamtion!!!");
2171 return BT_STATUS_FAIL;
2174 _bt_hal_convert_addr_type_to_string(device_address,
2175 (unsigned char *)bd_addr->address);
2177 //check if connection has the same device address
2178 if (g_strcmp0(conn_info->addr, device_address) != 0) {
2179 ERR("device address [%s] does not match", device_address);
2180 return BT_STATUS_FAIL;
2183 device_path = _bt_hal_get_device_object_path(conn_info->addr);
2184 if (device_path == NULL) {
2185 ERR("device_path is NULL");
2186 return BT_STATUS_PARM_INVALID;
2189 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
2190 NULL, BT_HAL_BLUEZ_NAME,
2191 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2194 g_free(device_path);
2195 if (device_proxy == NULL)
2196 return BT_STATUS_FAIL;
2198 INFO("Disconnect LE [%s]", device_address);
2200 g_dbus_proxy_call(device_proxy, "DisconnectLE",
2202 G_DBUS_CALL_FLAGS_NONE,
2203 BT_HAL_MAX_DBUS_TIMEOUT,
2205 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
2208 return BT_STATUS_SUCCESS;
2211 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
2216 uuid = btuuid2str(srvc_id->uu);
2217 DBG("Original UUID [%s]", uuid);
2219 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
2220 /* Extract Standard UUID string */
2221 memcpy(uuid_buf, &uuid[4], 4);
2223 DBG("Converted string [%s]", uuid_buf);
2224 return g_strdup(uuid_buf);
2226 return strdup(uuid);
2229 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
2232 /* For GATT service specific */
2233 GDBusNodeInfo *node_info;
2236 struct gatt_service_info *serv_info = NULL;
2237 GVariantBuilder *builder = NULL;
2238 GVariantBuilder *builder1 = NULL;
2239 GVariantBuilder *inner_builder = NULL;
2240 gboolean svc_primary = TRUE;
2241 GError *error = NULL;
2242 hal_gatt_service_added *user_data = NULL;
2243 int service_handle = 0;
2244 DBG("Service add to DBUS slot [%d]", slot);
2246 service_handle = __bt_hal_assign_gatt_handle(BT_GATT_TYPE_SERV);
2247 if (service_handle == -1) {
2248 ERR("Too many gatt service handles are created");
2249 return BT_STATUS_FAIL;
2252 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, service_handle);
2253 DBG("gatt service path is [%s]", path);
2255 node_info = __bt_gatt_create_method_node_info(
2256 service_introspection_xml);
2257 if (node_info == NULL) {
2259 __bt_hal_free_gatt_handle(BT_GATT_TYPE_SERV, service_handle);
2260 return BT_STATUS_FAIL;
2263 object_id = g_dbus_connection_register_object(g_conn, path,
2264 node_info->interfaces[0],
2265 &serv_interface_vtable,
2266 NULL, NULL, &error);
2268 if (object_id == 0) {
2269 ERR("failed to register: %s", error->message);
2270 g_error_free(error);
2272 __bt_hal_free_gatt_handle(BT_GATT_TYPE_SERV, service_handle);
2273 return BT_STATUS_FAIL;
2275 /* Add object_id/gatt service information; it's required at the time of
2276 * service unregister and Getmanagedobjects
2278 serv_info = g_new0(struct gatt_service_info, 1);
2280 serv_info->serv_path = g_strdup(path);
2281 serv_info->serv_id = object_id;
2282 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
2283 serv_info->is_svc_registered = FALSE;
2284 serv_info->is_svc_primary = svc_primary;
2285 DBG("Service Handle to be added is [%d]", service_handle);
2286 serv_info->service_handle = service_handle;
2288 /* Update service in GATT Server service List */
2289 gatt_services = g_slist_append(gatt_services, serv_info);
2291 /* emit interfacesadded signal here for service path */
2292 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2293 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2295 g_variant_builder_add(inner_builder, "{sv}",
2296 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
2298 g_variant_builder_add(inner_builder, "{sv}",
2299 "Primary", g_variant_new_boolean(svc_primary));
2301 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2303 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
2304 g_variant_new("ao", builder1));
2306 g_variant_builder_add(builder, "{sa{sv}}",
2307 GATT_SERV_INTERFACE, inner_builder);
2309 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2310 "org.freedesktop.Dbus.ObjectManager", // TODO: need to check Dbus is working or not
2312 g_variant_new("(oa{sa{sv}})",
2317 /* dbus gives error cause */
2318 ERR("d-bus api failure: errcode[%x], message[%s]",
2319 error->code, error->message);
2320 g_clear_error(&error);
2324 /* Send Service handle to application */
2325 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2326 user_data->srvc_hdl = serv_info->service_handle;
2327 user_data->instance_data = slot;
2328 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2329 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2331 /* Save newly created service in GATT Server's service list */
2332 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2336 g_variant_builder_unref(inner_builder);
2337 g_variant_builder_unref(builder);
2338 g_variant_builder_unref(builder1);
2339 return BT_STATUS_SUCCESS;
2342 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2345 char *app_path = (char*)user_data;
2346 INFO("UnregisterApplication is completed app [%s]", app_path);
2347 GError *error = NULL;
2348 GVariant *result = NULL;
2351 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2353 if (result == NULL) {
2354 /* dBUS-RPC is failed */
2355 ERR("Dbus-RPC is failed\n");
2357 if (error != NULL) {
2358 /* dBUS gives error cause */
2359 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2360 error->code, error->message);
2361 g_clear_error(&error);
2364 g_variant_unref(result);
2369 static void __bt_hal_gatt_deinit(int server_if)
2371 GDBusProxy *proxy = NULL;
2372 char *app_path, *data;
2374 /* Step1: Remove requested App */
2375 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2376 "/org/bluez/hci0", "org.bluez.GattManager1");
2381 app_path = g_strdup_printf("/com/%d", server_if);
2382 INFO("UnregisterApplication : path [%s]", app_path);
2384 /* Async Call to Unregister Service */
2385 data = g_strdup_printf("/com/%d", server_if);
2386 g_dbus_proxy_call(proxy,
2387 "UnregisterApplication",
2388 g_variant_new("(o)",
2390 G_DBUS_CALL_FLAGS_NONE, -1,
2392 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2396 /* unregister the exported interface for object manager */
2397 INFO("Unregister the interface for object with manager_id: %d", manager_id[server_if]);
2398 g_dbus_connection_unregister_object(g_conn, manager_id[server_if]);
2399 manager_id[server_if] = 0;
2401 /* If requested app is last GATT Server app, then clean all resources */
2402 if (gatt_server_apps == NULL) {
2403 INFO("All GATT servers are removed, clean all DBUS resources");
2405 g_bus_unown_name(owner_id);
2408 g_object_unref(manager_gproxy);
2409 manager_gproxy = NULL;
2414 static int __bt_hal_gatt_init(void)
2418 /* Only once for ALL GATT Servers */
2419 if (owner_id == 0) {
2423 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2426 ERR("Unable to connect to gdbus: %s", err->message);
2427 g_clear_error(&err);
2429 return BT_STATUS_FAIL;
2432 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2433 INFO("well-known name: %s", name);
2435 owner_id = g_bus_own_name_on_connection(g_conn, name,
2436 G_BUS_NAME_OWNER_FLAGS_NONE,
2437 NULL, NULL, NULL, NULL);
2441 INFO("Owner ID [%d]", owner_id);
2443 /* Only once for ALL GATT Servers */
2444 if (manager_node_info == NULL) {
2445 /* Register ObjectManager interface */
2446 manager_node_info = __bt_gatt_create_method_node_info(
2447 manager_introspection_xml);
2449 if (manager_node_info == NULL) {
2450 ERR("failed to get node info");
2451 return BT_STATUS_FAIL;
2456 return BT_STATUS_SUCCESS;
2459 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2463 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2464 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2465 if (app->slot == slot) {
2466 INFO("GATT Server app found app path [%s] instance [%d]",
2467 app->app_path, app->slot);
2468 *app_path = app->app_path;
2472 /* GATT Server not found */
2476 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2478 if (app_path == NULL)
2481 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2482 app->app_path = g_strdup(app_path);
2484 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2485 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2488 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2491 CHECK_BTGATT_INIT();
2492 char *app_path = NULL;
2493 GError *error = NULL;
2496 int result = BT_STATUS_SUCCESS;
2498 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2499 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2501 /* Check if this GATT server Application is already registered with DBUS */
2502 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2504 if (app_path != NULL) {
2505 DBG("GATT server path is already defined [%s]", app_path);
2506 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2508 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2509 result = __bt_hal_gatt_init();
2510 if (result != BT_STATUS_SUCCESS)
2513 /* Only once for each GATT Server */
2514 app_path = g_strdup_printf("/com/%d", server_if);
2516 app_id = g_malloc0(sizeof(int));
2517 *app_id = server_if;
2519 manager_id[server_if] = g_dbus_connection_register_object(g_conn, app_path,
2520 manager_node_info->interfaces[0],
2521 &manager_interface_vtable,
2522 (gpointer)app_id, NULL, &error);
2524 if (manager_id[server_if] == 0) {
2525 ERR("failed to register: %s", error->message);
2526 g_error_free(error);
2529 INFO("manager_id [%d]", manager_id[server_if]);
2531 /* For current GATT Server, app_path is created, save it in Table */
2532 _bt_hal_update_gatt_server_path(server_if, app_path);
2534 /* Add GATT Service to DBUS */
2535 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2541 INFO("Successfully added service");
2542 return BT_STATUS_SUCCESS;
2549 INFO("Service addition failed!!");
2550 return BT_STATUS_FAIL;
2553 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2554 int included_handle)
2556 CHECK_BTGATT_INIT();
2557 return BT_STATUS_SUCCESS;
2561 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2564 GSList *gatt_services = NULL;
2566 struct gatt_service_info *info = NULL;
2568 gatt_services = _bt_get_service_list_from_server(instance);
2570 len = g_slist_length(gatt_services);
2571 l = g_slist_nth(gatt_services, len -1);
2577 if (info->service_handle == service_handle)
2582 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2586 GSList *gatt_services = NULL;
2587 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2589 gatt_services = _bt_get_service_list_from_server(instance);
2591 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2592 struct gatt_service_info *info = l->data;
2593 INFO("Got one service with handle [%d]", info->service_handle);
2594 if (info->service_handle == service_handle)
2597 ERR("Gatt service with handle [%d] not found", service_handle);
2601 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2602 bt_uuid_t *uuid, int properties,
2606 GError *error = NULL;
2608 GDBusNodeInfo *node_info;
2610 GVariantBuilder *builder = NULL;
2611 GVariantBuilder *inner_builder = NULL;
2612 struct gatt_service_info *serv_info = NULL;
2613 struct gatt_char_info *char_info = NULL;
2614 GVariantBuilder *builder2 = NULL;
2615 GVariantBuilder *builder3 = NULL;
2616 GVariant *flags_val = NULL;
2618 char *char_flags[NUMBER_OF_FLAGS];
2620 hal_gatt_char_added *user_data = NULL;
2622 int char_handle = 0;
2624 CHECK_BTGATT_INIT();
2625 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2626 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2628 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2629 if (serv_info == NULL)
2630 return BT_STATUS_FAIL;
2632 char_handle = __bt_hal_assign_gatt_handle(BT_GATT_TYPE_CHAR);
2633 if (char_handle == -1) {
2634 ERR("Too many gatt char handles are created");
2635 return BT_STATUS_FAIL;
2638 DBG("Add new GATT characteristic: Current GATT char handle [%d]", char_handle);
2639 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, char_handle);
2640 DBG("gatt characteristic path is [%s]", path);
2642 node_info = __bt_gatt_create_method_node_info(
2643 characteristics_introspection_xml);
2644 if (node_info == NULL) {
2646 __bt_hal_free_gatt_handle(BT_GATT_TYPE_CHAR, char_handle);
2647 return BT_STATUS_FAIL;
2650 app_id = g_malloc0(sizeof(int));
2653 object_id = g_dbus_connection_register_object(g_conn, path,
2654 node_info->interfaces[0],
2655 &char_interface_vtable,
2656 (gpointer)app_id, NULL, &error);
2658 if (object_id == 0) {
2659 ERR("failed to register: %s", error->message);
2660 g_error_free(error);
2663 __bt_hal_free_gatt_handle(BT_GATT_TYPE_CHAR, char_handle);
2664 return BT_STATUS_FAIL;
2667 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2668 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2669 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2670 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2671 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2672 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2673 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2674 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2676 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2678 char_info = g_new0(struct gatt_char_info, 1);
2680 char_info->char_path = g_strdup(path);
2681 char_info->char_id = object_id;
2682 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2683 for (i = 0; i < flag_count; i++)
2684 char_info->char_flags[i] = char_flags[i];
2687 char_info->flags_length = flag_count;
2688 char_info->char_handle = char_handle;
2691 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2692 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2694 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2695 g_variant_new("s", char_info->char_uuid));
2696 g_variant_builder_add(inner_builder, "{sv}", "Service",
2697 g_variant_new("o", serv_info->serv_path));
2699 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2701 for (i = 0; i < flag_count; i++)
2702 g_variant_builder_add(builder2, "s", char_flags[i]);
2704 flags_val = g_variant_new("as", builder2);
2705 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2708 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2710 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2711 g_variant_new("ao", builder3));
2713 g_variant_builder_add(builder, "{sa{sv}}",
2714 GATT_CHAR_INTERFACE,
2717 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2718 "org.freedesktop.Dbus.ObjectManager",
2720 g_variant_new("(oa{sa{sv}})",
2725 /* dbus gives error cause */
2726 ERR("d-bus api failure: errcode[%x], message[%s]",
2727 error->code, error->message);
2728 g_clear_error(&error);
2732 //*char_path = g_strdup(path);
2737 /* Send Service handle to application */
2738 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2739 user_data->srvc_hdl = serv_info->service_handle;
2740 user_data->char_hdl = char_handle;
2741 user_data->instance_data = slot;
2742 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2743 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2745 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2746 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2751 g_variant_builder_unref(inner_builder);
2752 g_variant_builder_unref(builder);
2753 g_variant_builder_unref(builder2);
2754 g_variant_builder_unref(builder3);
2756 return BT_STATUS_SUCCESS;
2759 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2762 CHECK_BTGATT_INIT();
2764 // static int desc_id = 1;
2765 GError *error = NULL;
2767 GDBusNodeInfo *node_info;
2769 GVariantBuilder *builder = NULL;
2770 GVariantBuilder *inner_builder = NULL;
2772 struct gatt_char_info *char_info = NULL;
2773 struct gatt_desc_info *desc_info = NULL;
2774 struct gatt_service_info *serv_info = NULL;
2776 gchar **line_argv = NULL;
2778 char *char_path = NULL;
2781 GVariantBuilder *builder2 = NULL;
2782 GVariant *flags_val = NULL;
2784 char *desc_flags[NUMBER_OF_FLAGS];
2787 hal_gatt_desc_added *user_data = NULL;
2788 int desc_handle = 0;
2790 /* Fetch service data for the GATT server */
2791 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2792 if (serv_info == NULL)
2793 return BT_STATUS_FAIL;
2795 /* Fetch list of characteristics from the service info */
2796 l = serv_info->char_data;
2798 /* Fetch last char info from the characteristic list */
2799 char_info = g_slist_last(l)->data;
2800 if (char_info == NULL)
2801 return BT_STATUS_FAIL;
2803 /* Fetch characteristic path from char info */
2804 char_path = char_info->char_path;
2806 line_argv = g_strsplit_set(char_path, "/", 0);
2807 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2810 node_info = __bt_gatt_create_method_node_info(
2811 descriptor_introspection_xml);
2813 if (node_info == NULL) {
2814 g_strfreev(line_argv);
2816 return BT_STATUS_FAIL;
2819 desc_handle = __bt_hal_assign_gatt_handle(BT_GATT_TYPE_DESC);
2820 if (desc_handle == -1) {
2821 ERR("Too many gatt desc handles are created");
2822 g_strfreev(line_argv);
2824 return BT_STATUS_FAIL;
2827 DBG("Add new Descriptor: Current GATT desc handle [%d]", desc_handle);
2828 path = g_strdup_printf("%s/descriptor%d", char_path, desc_handle);
2829 DBG("gatt descriptor path is [%s]", path);
2831 app_id = g_malloc0(sizeof(int));
2834 object_id = g_dbus_connection_register_object(g_conn, path,
2835 node_info->interfaces[0],
2836 &desc_interface_vtable,
2837 (gpointer)app_id, NULL, &error);
2839 if (object_id == 0) {
2840 ERR("failed to register: %s", error->message);
2841 g_error_free(error);
2843 g_strfreev(line_argv);
2846 __bt_hal_free_gatt_handle(BT_GATT_TYPE_DESC, desc_handle);
2847 return BT_STATUS_FAIL;
2850 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2852 desc_info = g_new0(struct gatt_desc_info, 1);
2854 desc_info->desc_path = g_strdup(path);
2855 desc_info->desc_id = object_id;
2856 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2858 for (i = 0; i < flag_count; i++)
2859 desc_info->desc_flags[i] = desc_flags[i];
2861 desc_info->flags_length = flag_count;
2862 desc_info->desc_handle = desc_handle;
2865 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2866 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2868 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2869 g_variant_new("s", btuuid2str(uuid->uu)));
2870 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2871 g_variant_new("o", char_path));
2873 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2875 for (i = 0; i < flag_count; i++)
2876 g_variant_builder_add(builder2, "s", desc_flags[i]);
2878 flags_val = g_variant_new("as", builder2);
2879 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2882 g_variant_builder_add(builder, "{sa{sv}}",
2883 GATT_DESC_INTERFACE,
2886 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2887 "org.freedesktop.Dbus.ObjectManager",
2889 g_variant_new("(oa{sa{sv}})",
2892 if (error != NULL) {
2893 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2894 error->code, error->message);
2895 g_clear_error(&error);
2898 //*desc_path = g_strdup(path);
2900 /* Save newly created descriptor to GATT server's service's characteristic */
2901 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2903 /* Send descriptor handle to application */
2904 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2905 user_data->srvc_hdl = serv_info->service_handle;
2906 user_data->desc_hdl = desc_handle;
2907 user_data->instance_data = slot;
2908 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2909 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2914 g_strfreev(line_argv);
2915 g_variant_builder_unref(inner_builder);
2916 g_variant_builder_unref(builder);
2917 return BT_STATUS_SUCCESS;
2920 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2922 GError *error = NULL;
2924 char *data = (char*) user_data;
2925 INFO("RegisterApplication is completed path [%s]", data);
2927 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2929 if (result == NULL) {
2930 /* dBUS-RPC is failed */
2931 ERR("Dbus-RPC is failed\n");
2933 if (error != NULL) {
2934 /* dBUS gives error cause */
2935 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2936 error->code, error->message);
2937 g_clear_error(&error);
2940 g_variant_unref(result);
2945 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2946 const gchar *path, const gchar *interface)
2952 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2957 ERR("Unable to connect to gdbus: %s", err->message);
2958 g_clear_error(&err);
2963 proxy = g_dbus_proxy_new_sync(g_conn,
2964 G_DBUS_PROXY_FLAGS_NONE, NULL,
2966 interface, NULL, &err);
2970 ERR("Unable to create proxy: %s", err->message);
2971 g_clear_error(&err);
2975 manager_gproxy = proxy;
2980 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2981 const gchar *path, const gchar *interface)
2983 return (manager_gproxy) ? manager_gproxy :
2984 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2988 static void __bt_register_application_to_dbus(int slot)
2990 GDBusProxy *proxy = NULL;
2991 char *app_path = NULL;
2993 DBG("RegisterApplication slot [%d]", slot);
2995 /* It is impossible that app path is still not initialized */
2996 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2998 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2999 "/org/bluez/hci0", "org.bluez.GattManager1");
3001 data = g_strdup(app_path);
3002 g_dbus_proxy_call(proxy,
3003 "RegisterApplication",
3004 g_variant_new("(oa{sv})",
3006 G_DBUS_CALL_FLAGS_NONE, -1,
3008 (GAsyncReadyCallback)__bt_hal_register_application_cb,
3010 INFO("GATT server started");
3013 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
3015 CHECK_BTGATT_INIT();
3016 struct gatt_service_info *serv_info = NULL;
3017 hal_gatt_service_started *user_data = NULL;
3018 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
3020 /* Fetch service data for the GATT server */
3021 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
3022 if (serv_info == NULL)
3023 return BT_STATUS_FAIL;
3025 if (serv_info->is_svc_registered)
3026 DBG("service already registered \n");
3028 serv_info->is_svc_registered = TRUE;
3030 /* Send Service handle to application */
3031 user_data = g_malloc0(sizeof(hal_gatt_service_started));
3032 user_data->srvc_hdl = serv_info->service_handle;
3033 user_data->instance_data = server_if;
3034 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
3036 /* If this is nth Service that is started, then register application at this point */
3037 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
3038 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
3040 __bt_register_application_to_dbus(server_if);
3043 return BT_STATUS_SUCCESS;
3046 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
3048 CHECK_BTGATT_INIT();
3049 INFO("Stop service successful");
3050 return BT_STATUS_SUCCESS;
3053 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
3055 CHECK_BTGATT_INIT();
3056 struct gatt_service_info *serv_info = NULL;
3057 hal_gatt_service_deleted *user_data = NULL;
3060 int err = BT_STATUS_SUCCESS;
3061 int ret = BT_STATUS_SUCCESS;
3062 char *app_path = NULL;
3063 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
3065 /* Fetch service data for the GATT server */
3066 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
3067 if (serv_info == NULL) {
3068 ERR("Could not find service info svc handle [%d] server slot [%d]",
3069 service_handle, server_if);
3070 return BT_STATUS_FAIL;
3073 app_path = __bt_get_server_app_path_from_server(server_if);
3074 if (app_path == NULL) {
3075 ERR("Could not find service info svc handle [%d] server slot [%d]",
3076 service_handle, server_if);
3077 return BT_STATUS_FAIL;
3080 if (serv_info->is_svc_registered == FALSE) {
3081 ERR("service Not registered path [%s] handle [%d]",
3082 serv_info->serv_path, service_handle);
3085 for (l = serv_info->char_data; l != NULL;) {
3086 struct gatt_char_info *char_info = l->data;
3087 l = g_slist_next(l);
3089 if (char_info == NULL)
3092 for (l1 = char_info->desc_data; l1 != NULL;) {
3093 struct gatt_desc_info *desc_info = l1->data;
3094 l1 = g_slist_next(l1);
3096 if (desc_info == NULL)
3099 ret = g_dbus_connection_unregister_object(g_conn,
3100 desc_info->desc_id);
3102 __bt_hal_gatt_emit_interface_removed(
3104 desc_info->desc_path,
3105 GATT_DESC_INTERFACE);
3107 err = BT_STATUS_FAIL;
3110 /* list remove & free */
3111 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
3112 __bt_hal_free_gatt_handle(BT_GATT_TYPE_DESC, desc_info->desc_handle);
3113 INFO("desc handle(%d) removed successfully", desc_info->desc_handle);
3114 __bt_hal_gatt_free_descriptor_info(desc_info);
3117 g_slist_free(char_info->desc_data);
3118 char_info->desc_data = NULL;
3120 ret = g_dbus_connection_unregister_object(g_conn,
3121 char_info->char_id);
3123 __bt_hal_gatt_emit_interface_removed(app_path, char_info->char_path,
3124 GATT_CHAR_INTERFACE);
3127 err = BT_STATUS_FAIL;
3130 /* list remove & free */
3131 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
3132 __bt_hal_free_gatt_handle(BT_GATT_TYPE_CHAR, char_info->char_handle);
3133 INFO("char handle(%d) removed successfully", char_info->char_handle);
3134 __bt_hal_gatt_free_characteristic_info(char_info);
3137 g_slist_free(serv_info->char_data);
3138 serv_info->char_data = NULL;
3140 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
3142 __bt_hal_gatt_emit_interface_removed(app_path, serv_info->serv_path,
3143 GATT_SERV_INTERFACE);
3146 err = BT_STATUS_FAIL;
3149 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
3151 DBG("Unregistered the service on properties interface");
3153 /* Remove from global list */
3154 gatt_services = g_slist_remove(gatt_services, serv_info);
3155 __bt_hal_free_gatt_handle(BT_GATT_TYPE_SERV, serv_info->service_handle);
3156 INFO("serv handle(%d) removed successfully", serv_info->service_handle);
3157 INFO("After removing from global list total service count [%d]", g_slist_length(gatt_services));
3159 /* Remove from GATT Server's list of services */
3160 _bt_remote_service_from_gatt_server(server_if, service_handle);
3162 if (gatt_services == NULL)
3163 INFO("All GATT Services of all GATT Servers are unregistered");
3165 if (err == BT_STATUS_SUCCESS) {
3166 INFO("Send GATT Service deleted Event");
3167 /* Send Service handle to application */
3168 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
3169 user_data->srvc_hdl = serv_info->service_handle;
3170 user_data->instance_data = server_if;
3171 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
3174 /* Free the service */
3175 __bt_hal_gatt_free_service_info(serv_info);
3179 static gboolean __bt_gatt_get_service_state(const char *service_path)
3181 struct gatt_service_info *svc_info = NULL;
3183 for (l = gatt_services; l; l = g_slist_next(l)) {
3185 svc_info = (struct gatt_service_info *)l->data;
3187 if (!g_strcmp0(svc_info->serv_path, service_path))
3188 return svc_info->is_svc_registered;
3191 DBG("gatt service info is NULL");
3195 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
3196 int len, int confirm, char* p_value)
3198 CHECK_BTGATT_INIT();
3201 GVariantBuilder *outer_builder;
3202 GVariantBuilder *invalidated_builder;
3204 /* For Value update via PropertyChange */
3205 GVariantBuilder *outer_builder1;
3206 GVariantBuilder *inner_builder1;
3207 GVariantBuilder *invalidated_builder1;
3208 GVariant *update_value = NULL;
3210 /* Other variables */
3211 struct gatt_client_info_t *conn_info = NULL;
3212 gchar *serv_path = NULL;
3213 char *char_path = NULL;
3214 gchar **line_argv = NULL;
3215 gboolean notify = TRUE;
3216 gboolean ret = TRUE;
3217 int err = BT_STATUS_SUCCESS;
3219 GError *error = NULL;
3222 memset(addr, 0x00, sizeof(addr));
3224 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3225 if (conn_info == NULL) {
3226 ERR("No Connection Inforamtion!!!");
3227 return BT_STATUS_FAIL;
3230 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
3232 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3233 if (char_path == NULL)
3234 return BT_STATUS_FAIL;
3236 line_argv = g_strsplit_set(char_path, "/", 0);
3237 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3239 if (!__bt_gatt_get_service_state(serv_path)) {
3240 DBG("service not registered for this characteristic \n");
3242 g_strfreev(line_argv);
3243 return BT_STATUS_FAIL;
3246 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3247 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3249 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
3250 g_variant_new("b", notify));
3252 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
3253 DBG("Send Indication to Unicast addr [%s]", addr);
3255 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
3256 g_variant_new("s", addr));
3258 DBG("Set characteristic Notification \n");
3259 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3261 "org.freedesktop.DBus.Properties",
3262 "PropertiesChanged",
3263 g_variant_new("(sa{sv}as)",
3264 "org.bluez.GattCharacteristic1",
3265 outer_builder, invalidated_builder),
3269 if (error != NULL) {
3270 ERR("D-Bus API failure: errCode[%x], \
3272 error->code, error->message);
3273 g_clear_error(&error);
3275 err = BT_STATUS_FAIL;
3278 g_variant_builder_unref(outer_builder);
3279 g_variant_builder_unref(invalidated_builder);
3282 /* Notifying Done, now update Value to Bluez via PropertyChanged */
3283 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
3285 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3286 for (i = 0; i < len; i++)
3287 g_variant_builder_add(inner_builder1, "y", p_value[i]);
3289 update_value = g_variant_new("ay", inner_builder1);
3292 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3293 g_variant_builder_add(outer_builder1, "{sv}", "Value",
3296 DBG("Updating characteristic value \n");
3297 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3299 "org.freedesktop.DBus.Properties",
3300 "PropertiesChanged",
3301 g_variant_new("(sa{sv}as)",
3302 "org.bluez.GattCharacteristic1",
3303 outer_builder1, invalidated_builder1),
3307 if (error != NULL) {
3308 ERR("D-Bus API failure: errCode[%x], \
3310 error->code, error->message);
3311 g_clear_error(&error);
3313 err = BT_STATUS_FAIL;
3315 struct gatt_char_info *char_info = NULL;
3317 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3318 if (char_info == NULL) {
3320 g_strfreev(line_argv);
3321 g_variant_builder_unref(inner_builder1);
3322 g_variant_builder_unref(outer_builder1);
3323 g_variant_builder_unref(invalidated_builder1);
3325 return BT_STATUS_FAIL;
3328 char_info->value_length = len;
3330 char_info->char_value = (char *)realloc(char_info->char_value, len);
3331 if (char_info->char_value) {
3332 for (i = 0; i < len; i++)
3333 char_info->char_value[i] = p_value[i];
3338 g_strfreev(line_argv);
3339 g_variant_builder_unref(inner_builder1);
3340 g_variant_builder_unref(outer_builder1);
3341 g_variant_builder_unref(invalidated_builder1);
3346 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3347 int status, btgatt_response_t *response)
3349 CHECK_BTGATT_INIT();
3351 struct gatt_req_info *req_info = NULL;
3352 struct gatt_client_info_t *conn_info = NULL;
3355 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3356 if (conn_info == NULL) {
3357 ERR("No Connection Inforamtion. conn_id %d", conn_id);
3358 return BT_STATUS_FAIL;
3361 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3362 if (req_info == NULL) {
3363 ERR("No Request Inforamtion. conn_id %d", conn_id);
3364 return BT_STATUS_FAIL;
3367 if (status != BT_STATUS_SUCCESS) {
3368 ERR("resp_state is 0x%X, conn_id %d", status, conn_id);
3370 g_dbus_method_invocation_return_dbus_error(req_info->context,
3371 "org.bluez.Error.Failed", "Application Error");
3373 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3375 req_info->context = NULL;
3376 if (req_info->attr_path)
3377 g_free(req_info->attr_path);
3378 if (req_info->svc_path)
3379 g_free(req_info->svc_path);
3382 return BT_STATUS_SUCCESS;
3385 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3386 GVariantBuilder *inner_builder = NULL;
3387 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3389 if (response->attr_value.len > 0) {
3390 for (i = 0; i < response->attr_value.len; i++)
3391 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3393 g_dbus_method_invocation_return_value(req_info->context,
3394 g_variant_new("(ay)", inner_builder));
3396 g_variant_builder_unref(inner_builder);
3398 g_dbus_method_invocation_return_value(req_info->context, NULL);
3400 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3402 req_info->context = NULL;
3403 if (req_info->attr_path)
3404 g_free(req_info->attr_path);
3405 if (req_info->svc_path)
3406 g_free(req_info->svc_path);
3409 return BT_STATUS_SUCCESS;
3413 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3414 int status, int fd, int mtu, void *fdlist)
3416 CHECK_BTGATT_INIT();
3418 struct gatt_req_info *req_info = NULL;
3419 struct gatt_client_info_t *conn_info = NULL;
3421 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3423 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3424 if (conn_info == NULL) {
3425 ERR("No Connection Inforamtion!!!");
3426 return BT_STATUS_FAIL;
3429 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3430 if (req_info == NULL) {
3431 ERR("No Request Inforamtion!!!");
3432 return BT_STATUS_FAIL;
3435 if (status != BT_STATUS_SUCCESS) {
3436 ERR("resp_state is 0x%X", status);
3438 g_dbus_method_invocation_return_dbus_error(req_info->context,
3439 "org.bluez.Error.Failed", "Application Error");
3441 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3443 req_info->context = NULL;
3444 if (req_info->attr_path)
3445 g_free(req_info->attr_path);
3446 if (req_info->svc_path)
3447 g_free(req_info->svc_path);
3450 return BT_STATUS_SUCCESS;
3454 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3456 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3457 g_dbus_method_invocation_return_value_with_unix_fd_list(
3458 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3460 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3462 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3463 g_dbus_method_invocation_return_value_with_unix_fd_list(
3464 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3467 g_dbus_method_invocation_return_value(req_info->context, NULL);
3469 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3471 req_info->context = NULL;
3472 if (req_info->attr_path)
3473 g_free(req_info->attr_path);
3474 if (req_info->svc_path)
3475 g_free(req_info->svc_path);
3478 return BT_STATUS_SUCCESS;
3482 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3483 int value_length, char* att_value)
3485 CHECK_BTGATT_INIT();
3487 /* Other variables */
3488 char *char_path = NULL;
3489 gboolean ret = TRUE;
3490 GError *error = NULL;
3492 GVariantBuilder *outer_builder;
3493 GVariantBuilder *inner_builder;
3494 GVariantBuilder *invalidated_builder;
3495 GVariant *update_value = NULL;
3496 int err = BT_STATUS_SUCCESS;
3498 gchar **line_argv = NULL;
3499 gchar *serv_path = NULL;
3501 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3502 if (char_path == NULL)
3503 return BT_STATUS_FAIL;
3505 line_argv = g_strsplit_set(char_path, "/", 0);
3506 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3508 if (!__bt_gatt_get_service_state(serv_path)) {
3509 DBG("service not registered for this characteristic \n");
3511 g_strfreev(line_argv);
3512 return BT_STATUS_FAIL;
3516 g_strfreev(line_argv);
3518 line_argv = g_strsplit_set(char_path, "/", 0);
3519 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3521 if (!__bt_gatt_get_service_state(serv_path)) {
3522 DBG("service not registered for this characteristic \n");
3524 g_strfreev(line_argv);
3525 return BT_STATUS_FAIL;
3528 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3529 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3531 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3532 for (i = 0; i < value_length; i++)
3533 g_variant_builder_add(inner_builder, "y", att_value[i]);
3535 update_value = g_variant_new("ay", inner_builder);
3537 g_variant_builder_add(outer_builder, "{sv}", "Value",
3540 DBG("Updating characteristic value \n");
3541 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3543 "org.freedesktop.DBus.Properties",
3544 "PropertiesChanged",
3545 g_variant_new("(sa{sv}as)",
3546 "org.bluez.GattCharacteristic1",
3547 outer_builder, invalidated_builder),
3551 if (error != NULL) {
3552 ERR("D-Bus API failure: errCode[%x], \
3554 error->code, error->message);
3555 g_clear_error(&error);
3557 err = BT_STATUS_FAIL;
3559 struct gatt_char_info *char_info = NULL;
3561 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3562 if (char_info == NULL) {
3564 g_strfreev(line_argv);
3565 g_variant_builder_unref(inner_builder);
3566 g_variant_builder_unref(outer_builder);
3567 g_variant_builder_unref(invalidated_builder);
3569 return BT_STATUS_FAIL;
3572 char_info->value_length = value_length;
3574 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3575 if (char_info->char_value) {
3576 for (i = 0; i < value_length; i++)
3577 char_info->char_value[i] = att_value[i];
3583 g_strfreev(line_argv);
3584 g_variant_builder_unref(inner_builder);
3585 g_variant_builder_unref(outer_builder);
3586 g_variant_builder_unref(invalidated_builder);
3591 static bt_status_t gatt_server_listen(int server_if, bool start)
3593 CHECK_BTGATT_INIT();
3595 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3597 DBG("server_if: [%d]", server_if);
3599 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3600 if (server_register_info == NULL) {
3601 DBG("gatt server is not registered");
3602 return BT_STATUS_FAIL;
3605 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3607 if (server_register_info->adv_slot_id < 0 ) {
3608 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3609 return BT_STATUS_FAIL;
3612 /* Send Data to LE Module */
3613 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, start, FALSE);
3616 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3617 bool include_txpower, int min_interval, int max_interval, int appearance,
3618 uint16_t manufacturer_len, char* manufacturer_data,
3619 uint16_t service_data_len, char* service_data,
3620 uint16_t service_uuid_len, char* service_uuid)
3622 CHECK_BTGATT_INIT();
3623 return BT_STATUS_SUCCESS;
3626 static int bt_hal_gatts_allocate_adv_slot(struct hal_gatts_server_register_info_t *server_register_info)
3628 int adv_slot_id = -1;
3630 /* allocate adv slot for gatt server if not assigned */
3631 if (server_register_info->adv_slot_id < 0 ) {
3632 adv_slot_id = _bt_hal_get_available_adv_slot_id(&server_register_info->app_uuid, TRUE);
3633 if (adv_slot_id < 0) {
3634 ERR("failed to get the adv_slot");
3638 server_register_info->adv_slot_id = adv_slot_id;
3641 DBG("gatt server:[%d] Assigned adv_slot [%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3646 int bt_hal_gatts_allocate_adv_slot_by_server_if(int server_if)
3648 CHECK_BTGATT_INIT();
3652 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3654 DBG("server_if: [%d]", server_if);
3656 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3657 if (server_register_info == NULL) {
3658 DBG("gatt server is not registered");
3662 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3664 if (server_register_info->adv_slot_id < 0 ) {
3665 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3667 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3669 DBG("failed to get adv_slot");
3674 return server_register_info->adv_slot_id;
3677 void bt_hal_gatts_release_adv_slot(int server_if)
3679 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3681 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3682 if (server_register_info == NULL) {
3683 ERR("failed to get server_register_info");
3687 if (server_register_info->adv_slot_id < 0) {
3688 ERR("adv_slot is not allocated");
3692 if(_bt_hal_is_advertising_in_slot(server_register_info->adv_slot_id) == FALSE) {
3693 DBG("advertising is disabled");
3694 _bt_hal_free_server_slot(server_register_info->adv_slot_id);
3695 server_register_info->adv_slot_id = -1;
3699 int bt_hal_gatts_get_adv_slot_id(int server_if)
3701 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3703 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3704 if (server_register_info == NULL) {
3705 DBG("failed to get server_register_info");
3709 return server_register_info->adv_slot_id;
3712 int bt_hal_gatts_get_server_if(int slot_id)
3714 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3716 server_register_info = bt_hal_gatts_find_server_register_info_by_slot_id(slot_id);
3717 if (server_register_info == NULL) {
3718 DBG("failed to get server_register_info");
3722 return server_register_info->server_if;
3725 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3727 CHECK_BTGATT_INIT();
3731 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3733 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3734 if (server_register_info == NULL) {
3735 ERR("gatt server is not registered");
3736 return BT_STATUS_FAIL;
3739 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3741 if (server_register_info->adv_slot_id < 0 ) {
3742 DBG("adv_slot is not assigned to server:[%d]", server_if);
3744 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3746 ERR("failed to get adv_slot");
3747 return BT_STATUS_FAIL;
3751 /* Send Enable Advertising request to LE Module */
3752 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, TRUE, TRUE);
3755 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3756 int chnl_map, int tx_power, int timeout_s, bool is_legacy, int primary_phy, int secondary_phy)
3758 CHECK_BTGATT_INIT();
3760 /* Send Advertising parameters to LE Module */
3761 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3762 chnl_map, tx_power, timeout_s, is_legacy, primary_phy, secondary_phy);
3765 static bt_status_t gatt_server_set_filter_policy(int filter_policy)
3767 CHECK_BTGATT_INIT();
3769 /* Send the Filter policy parameter to LE Module */
3770 _bt_hal_set_filter_policy_param(filter_policy);
3771 return BT_STATUS_SUCCESS;
3774 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3776 CHECK_BTGATT_INIT();
3778 /* Send Data to LE Module */
3779 return _bt_hal_set_advertising_data(adv_param_setup);
3782 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3784 CHECK_BTGATT_INIT();
3786 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3788 DBG("server_if: [%d]", server_if);
3790 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3791 if (server_register_info == NULL) {
3792 DBG("gatt server is not registered");
3793 return BT_STATUS_FAIL;
3796 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3798 if (server_register_info->adv_slot_id < 0 ) {
3799 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3800 return BT_STATUS_FAIL;
3803 /* Send Data to LE Module */
3804 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, FALSE, TRUE);
3807 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3809 CHECK_BTGATT_INIT();
3810 char *object_path = NULL;
3812 GDBusProxy *device_proxy;
3813 GError *error = NULL;
3815 GVariant *tmp_value;
3816 GDBusConnection *conn;
3817 GVariant *result = NULL;
3818 int ret = BT_STATUS_SUCCESS;
3819 struct gatt_client_info_t *conn_info = NULL;
3822 if (mtu_size == NULL)
3823 return BT_STATUS_PARM_INVALID;
3825 /* GDBUS Connection Info validate */
3826 conn = _bt_hal_get_system_gconn();
3828 ERR("Could not get System DBUS Connection");
3829 return BT_STATUS_FAIL;
3832 /* Connection Info validate */
3833 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3834 if (conn_info == NULL) {
3835 ERR("No Connection Inforamtion!!!");
3836 return BT_STATUS_FAIL;
3840 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3841 if (object_path == NULL)
3842 return BT_STATUS_FAIL;
3844 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3845 NULL, BT_HAL_BLUEZ_NAME, object_path,
3846 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3848 g_free(object_path);
3849 if (device_proxy == NULL)
3850 return BT_STATUS_FAIL;
3852 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3853 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3854 G_DBUS_CALL_FLAGS_NONE,
3858 if (result == NULL) {
3859 if (error != NULL) {
3860 ERR("Error occured in Proxy call [%s]\n", error->message);
3861 g_error_free(error);
3863 g_object_unref(device_proxy);
3864 return BT_STATUS_FAIL;
3867 g_variant_get(result , "(@a{sv})", &value);
3868 g_variant_unref(result);
3870 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3871 if (tmp_value == NULL) {
3872 g_object_unref(device_proxy);
3873 g_variant_unref(value);
3874 return BT_STATUS_FAIL;
3877 mtu = g_variant_get_uint16(tmp_value);
3879 DBG("ATT MTU : [%d]", mtu);
3881 g_variant_unref(tmp_value);
3882 g_variant_unref(value);
3883 g_object_unref(device_proxy);
3885 *mtu_size = (int) mtu;
3890 const btgatt_server_interface_t btgatt_server_interface = {
3891 .register_server = gatt_server_register_app,
3892 .unregister_server = gatt_server_unregister_app,
3893 .connect = gatt_server_open,
3894 .disconnect = gatt_server_close,
3895 .add_service = gatt_server_add_service,
3896 .add_included_service = gatt_server_add_included_service,
3897 .add_characteristic = gatt_server_add_characteristic,
3898 .add_descriptor = gatt_server_add_descriptor,
3899 .start_service = gatt_server_start_service,
3900 .stop_service = gatt_server_stop_service,
3901 .delete_service = gatt_server_delete_service,
3902 .send_indication = gatt_server_send_indication,
3903 .send_response = gatt_server_send_response,
3904 .update_att_value = gatt_server_update_att_value,
3905 .listen = gatt_server_listen,
3906 .set_adv_data = gatt_server_set_adv_data,
3907 .multi_adv_enable = gatt_server_multi_adv_enable,
3908 .multi_adv_update = gatt_server_multi_adv_update,
3909 .set_filter_policy = gatt_server_set_filter_policy,
3910 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3911 .multi_adv_disable = gatt_server_multi_adv_disable,
3912 .get_att_mtu = gatt_server_get_mtu_size,
3913 .send_response_acquire = gatt_server_send_acquire_response