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;
65 static guint manager_id;
67 #define GATT_HANDLE_MAX_NUM 100 /* Not defined in spec, implementation dependent */
68 #define SERV_HANDLE_NUM (GATT_HANDLE_MAX_NUM)
69 #define CHAR_HANDLE_NUM (SERV_HANDLE_NUM + GATT_HANDLE_MAX_NUM)
70 #define DESC_HANDLE_NUM (CHAR_HANDLE_NUM + GATT_HANDLE_MAX_NUM)
77 static int assigned_handle[BT_GATT_TYPE_MAX];
78 static gboolean gatt_handle_used[BT_GATT_TYPE_MAX][GATT_HANDLE_MAX_NUM];
79 static int gatt_handle_base[BT_GATT_TYPE_MAX] = {SERV_HANDLE_NUM, CHAR_HANDLE_NUM, DESC_HANDLE_NUM};
81 struct gatt_service_info {
88 gboolean is_svc_registered;
89 gboolean is_svc_primary;
93 struct gatt_char_info {
98 gchar *char_flags[NUMBER_OF_FLAGS];
105 struct gatt_desc_info {
110 gchar *desc_flags[NUMBER_OF_FLAGS];
117 * GATT Server Request type
120 BT_HAL_GATT_REQUEST_TYPE_READ = 0x00, /* Read Requested */
121 BT_HAL_GATT_REQUEST_TYPE_WRITE = 0x01, /* Write Requested */
122 BT_HAL_GATT_REQUEST_TYPE_EXEC_WRITE = 0x02, /* Exec Write Requested */
123 BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE = 0x03, /* Exec Write Requested */
124 BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY = 0x04, /* Exec Write Requested */
125 } bt_gatt_request_type_e;
127 struct gatt_req_info {
132 bt_gatt_request_type_e request_type; /* Read or Write request */
133 GDBusMethodInvocation *context;
136 struct gatt_server_app {
142 /* Linked List of gatt server app's */
143 static GSList *gatt_server_apps = NULL;
145 static GSList *gatt_services = NULL;
147 extern int hal_gatt_conn_id;
149 /* Linked List of connected Remote GATT clients */
150 static GSList *gatt_client_info_list = NULL;
152 /* GATT Client Info List Structure */
153 struct gatt_client_info_t {
154 int connection_id; /* This value will uniquely identify a GATT client-server connection */
155 int instance_id; /* This value unique identifies a GATT server instance */
156 char *addr; /* Remote GATT client address */
157 GSList *gatt_req_info_list; /* List of transactions per Connection*/
160 static handle_stack_msg event_cb = NULL;
163 uint32_t instance_data;
165 } hal_register_server_data;
168 uint32_t instance_data;
172 } hal_gatt_service_added;
175 uint32_t instance_data;
177 } hal_gatt_service_started;
180 uint32_t instance_data;
182 } hal_gatt_service_deleted;
185 uint32_t instance_data;
189 } hal_gatt_char_added;
192 uint32_t instance_data;
196 } hal_gatt_desc_added;
199 struct hal_gatts_server_register_info_t {
205 static GSList * hal_gatts_server_register_list;
208 /* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
209 /* TODO: Adjust MAX Server after modifying MAX app handle logic */
210 #define BT_GATTS_MAX 11
212 static int assigned_id = 0;
214 static gboolean instance_id_used[BT_GATTS_MAX];
216 #define CHECK_BTGATT_INIT() if (_bt_hal_gatt_interface_ready() == false)\
218 ERR("%s: BTGATT not initialized", __FUNCTION__);\
219 return BT_STATUS_NOT_READY;\
221 DBG("%s", __FUNCTION__);\
224 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data);
226 static void __bt_hal_gatt_deinit(char *app_path);
228 static void __bt_hal_register_application_cb(GObject *object,
229 GAsyncResult *res, gpointer user_data);
231 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
234 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
235 const gchar *path, const gchar *interface);
237 static int bt_hal_gatts_get_gatt_server_instance();
239 /* Introspection data for the service we are exporting */
240 static const gchar service_introspection_xml[] =
242 " <interface name='org.freedesktop.DBus.Properties'>"
243 " <property type='s' name='UUID' access='read'>"
245 " <property type='b' name='primary' access='read'>"
247 " <property type='o' name='Device' access='read'>"
249 " <property type='ao' name='Characteristics' access='read'>"
251 " <property type='s' name='Includes' access='read'>"
256 /* Introspection data for the characteristics we are exporting */
257 static const gchar characteristics_introspection_xml[] =
259 " <interface name='org.bluez.GattCharacteristic1'>"
260 " <method name='ReadValue'>"
261 " <arg type='s' name='address' direction='in'/>"
262 " <arg type='u' name='id' direction='in'/>"
263 " <arg type='q' name='offset' direction='in'/>"
264 " <arg type='ay' name='Value' direction='out'/>"
266 " <method name='WriteValue'>"
267 " <arg type='s' name='address' direction='in'/>"
268 " <arg type='u' name='id' direction='in'/>"
269 " <arg type='q' name='offset' direction='in'/>"
270 " <arg type='b' name='response_needed' direction='in'/>"
271 " <arg type='b' name='prep_authorize' direction='in'/>"
272 " <arg type='ay' name='value' direction='in'/>"
274 " <method name ='AcquireWrite'>"
275 " <arg type='a{sv}' name='properties' direction='in'/>"
276 " <arg type='h' name='fd' direction='out'/>"
277 " <arg type='q' name='mtu' direction='out'/>"
279 " <method name = 'AcquireNotify'>"
280 " <arg type='a{sv}' name='properties' direction='in'/>"
281 " <arg type='h' name='fd' direction='out'/>"
282 " <arg type='q' name='mtu' direction='out'/>"
284 " <method name='StartNotify'>"
286 " <method name='StopNotify'>"
288 " <method name='IndicateConfirm'>"
289 " <arg type='s' name='address' direction='in'/>"
290 " <arg type='b' name='complete' direction='in'/>"
293 " <interface name='org.freedesktop.DBus.Properties'>"
294 " <property type='s' name='UUID' access='read'>"
296 " <property type='o' name='Service' access='read'>"
298 " <property type='ay' name='Value' access='readwrite'>"
300 " <property type='b' name='Notifying' access='read'>"
302 " <property type='as' name='Flags' access='read'>"
304 " <property type='s' name='Unicast' access='read'>"
306 " <property type='ao' name='Descriptors' access='read'>"
308 " <property type='b' name='WriteAcquired' access='read'>"
310 " <property type='b' name='NotifyAcquired' access='read'>"
315 /* Introspection data for the descriptor we are exporting */
316 static const gchar descriptor_introspection_xml[] =
318 " <interface name='org.bluez.GattDescriptor1'>"
319 " <method name='ReadValue'>"
320 " <arg type='s' name='address' direction='in'/>"
321 " <arg type='u' name='id' direction='in'/>"
322 " <arg type='q' name='offset' direction='in'/>"
323 " <arg type='ay' name='Value' direction='out'/>"
325 " <method name='WriteValue'>"
326 " <arg type='s' name='address' direction='in'/>"
327 " <arg type='u' name='id' direction='in'/>"
328 " <arg type='q' name='offset' direction='in'/>"
329 " <arg type='b' name='response_needed' direction='in'/>"
330 " <arg type='b' name='prep_authorize' direction='in'/>"
331 " <arg type='ay' name='value' direction='in'/>"
334 " <interface name='org.freedesktop.DBus.Properties'>"
335 " <property type='s' name='UUID' access='read'>"
337 " <property type='o' name='Characteristic' access='read'>"
339 " <property type='ay' name='Value' access='read'>"
341 " <property type='as' name='Flags' access='read'>"
347 static const gchar manager_introspection_xml[] =
349 " <interface name='org.freedesktop.DBus.ObjectManager'>"
350 " <method name='GetManagedObjects'>"
351 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
356 static void __bt_free_gatt_server_app(struct gatt_server_app *app)
358 g_free(app->app_path);
362 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
367 g_free(svc_info->serv_path);
368 g_free(svc_info->service_uuid);
372 void _bt_hal_gatt_server_init(void)
375 memset(instance_id_used, 0x00, sizeof(instance_id_used));
377 assigned_handle[BT_GATT_TYPE_SERV] = assigned_handle[BT_GATT_TYPE_CHAR] = assigned_handle[BT_GATT_TYPE_DESC] = -1;
378 memset(gatt_handle_used, 0x00, sizeof(gatt_handle_used));
380 g_slist_free_full(gatt_server_apps, (GDestroyNotify)__bt_free_gatt_server_app);
381 gatt_server_apps = NULL;
383 g_slist_free_full(gatt_services, (GDestroyNotify)__bt_hal_gatt_free_service_info);
384 gatt_services = NULL;
386 g_slist_free_full(hal_gatts_server_register_list, g_free);
387 hal_gatts_server_register_list = NULL;
390 static int __bt_hal_gatt_assign_id(void)
394 index = assigned_id + 1;
396 if (index >= BT_GATTS_MAX)
399 while (instance_id_used[index] == TRUE) {
400 if (index == assigned_id) {
401 /* No available ID */
402 ERR("All interface ID is used");
408 if (index >= BT_GATTS_MAX)
413 instance_id_used[index] = TRUE;
418 static void __bt_hal_gatt_delete_id(int instance_id)
420 if (instance_id >= BT_GATTS_MAX || instance_id < 0)
423 instance_id_used[instance_id] = FALSE;
426 static int __bt_hal_assign_gatt_handle(bt_gatt_type_e type)
430 index = assigned_handle[type] + 1;
432 if (index >= GATT_HANDLE_MAX_NUM)
435 while (gatt_handle_used[type][index] == TRUE) {
436 if (index == assigned_handle[type]) {
437 /* No available handle */
438 ERR("All handle is used");
444 if (index >= GATT_HANDLE_MAX_NUM)
448 assigned_handle[type] = index;
449 gatt_handle_used[type][index] = TRUE;
451 return assigned_handle[type] + gatt_handle_base[type];
454 static void __bt_hal_free_gatt_handle(bt_gatt_type_e type, int handle)
458 if (type >= BT_GATT_TYPE_MAX) {
463 index = handle - gatt_handle_base[type];
464 if (index < 0 || index >= GATT_HANDLE_MAX_NUM) {
465 ERR("Invalid handle: %d(type: %d)", handle, type);
469 gatt_handle_used[type][index] = FALSE;
472 static GSList *_bt_get_service_list_from_server(int instance)
475 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
476 INFO("Find App with slot [%d]", instance);
478 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
479 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
481 if (app->slot == instance) {
482 INFO("App slot [%d] Found, Number of services registered [%d]",
483 app->slot, g_slist_length(app->services));
484 return app->services;
490 static char *__bt_get_server_app_path_from_server(int instance)
493 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
494 INFO("Find App with slot [%d]", instance);
496 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
497 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
499 if (app->slot == instance) {
500 INFO("App slot [%d] Found, App path [%s]",
501 app->slot, app->app_path);
502 return app->app_path;
508 static void _bt_remote_service_from_gatt_server(int instance, int service_handle)
513 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
514 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
516 if (app->slot == instance) {
517 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
518 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
519 if (srv->service_handle == service_handle) {
520 app->services = g_slist_remove(app->services, srv);
528 static void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
531 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
532 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
534 if (app->slot == slot) {
535 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
536 serv_info->service_handle, slot);
537 app->services = g_slist_append(app->services, serv_info);
542 int _bt_get_remote_gatt_client_conn_id(char *address)
545 struct gatt_client_info_t *info = NULL;
547 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
548 info = (struct gatt_client_info_t*)l->data;
552 if (!g_strcmp0(info->addr, address)) {
553 INFO("Remote GATT client found addr[%s]", info->addr);
554 return info->connection_id;
560 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
563 struct gatt_client_info_t *info = NULL;
565 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
566 info = (struct gatt_client_info_t*)l->data;
570 if (!g_strcmp0(info->addr, address))
576 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
579 struct gatt_client_info_t *info = NULL;
581 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
582 info = (struct gatt_client_info_t*)l->data;
586 if (info->connection_id == conn_id)
592 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
597 struct gatt_client_info_t *info = NULL;
598 struct gatt_req_info *info1 = NULL;
600 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
601 info = (struct gatt_client_info_t*)l->data;
605 if (info->connection_id == conn_id) {
607 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
609 info1 = (struct gatt_req_info*)l1->data;
613 if (info1->request_id == trans_id)
621 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
623 struct hal_ev_gatt_server_connected ev;
624 struct gatt_client_info_t *conn_info = NULL;
625 memset(&ev, 0, sizeof(ev));
627 /* Convert address to hex */
628 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
630 /* Create Connection ID */
631 /* Check if device is already in connected list */
632 conn_info = __bt_find_remote_gatt_client_info(address);
634 /* If disconnected, and conn info found, then remove conn info */
635 if (is_connected == FALSE) {
636 DBG("GATT Disconnected");
638 INFO("Remove GATT client info from List..");
639 /* Remove info from List */
640 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
641 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
644 ERR("GATT callback not registered");
646 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
647 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
648 ev.conn_id = conn_info->connection_id;
649 ev.server_instance = conn_info->instance_id;
650 ev.connected = is_connected;
652 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
654 g_free(conn_info->addr);
657 /* If connected, and conn info NOT found, then add conn info */
661 /* Find Server Instance */
662 instance = bt_hal_gatts_get_gatt_server_instance();
663 if (instance == -1) {
664 ERR("Not even a single GATT server is registered");
665 ev.conn_id = ++hal_gatt_conn_id;
666 ev.server_instance = -1;
667 ev.connected = is_connected;
668 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
671 DBG("server instance [%d]", instance);
674 /* Save Connection info */
675 conn_info = g_new0(struct gatt_client_info_t, 1);
676 conn_info->addr = g_strdup(address);
677 DBG("Added GATT client addr[%s]", conn_info->addr);
678 conn_info->connection_id = ++hal_gatt_conn_id;
679 conn_info->instance_id = instance;
680 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
681 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
684 ERR("GATT callback not registered");
686 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
687 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
688 ev.conn_id = conn_info->connection_id;
689 ev.server_instance = conn_info->instance_id;
690 ev.connected = is_connected;
692 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
695 ERR("Abnormal case. conn_info should be NULL");
698 /* Send GATT connected or disconnected event */
701 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
705 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
706 struct gatt_service_info *serv_info = l1->data;
708 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
709 struct gatt_char_info *char_info = l2->data;
711 if (g_strcmp0(char_info->char_path, char_path)
713 *char_hdl = char_info->char_handle;
718 ERR("Gatt service not found");
722 static char *__bt_gatt_find_char_path_from_handle(int char_hdl)
726 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
727 struct gatt_service_info *serv_info = l1->data;
729 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
730 struct gatt_char_info *char_info = l2->data;
732 if (char_info->char_handle == char_hdl)
733 return char_info->char_path;
740 static struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
744 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
745 struct gatt_service_info *serv_info = l1->data;
747 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
748 struct gatt_char_info *char_info = l2->data;
750 if (char_info->char_handle == char_hdl)
758 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
760 GSList *l1, *l2, *l3;
762 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
763 struct gatt_service_info *serv_info = l1->data;
765 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
766 struct gatt_char_info *char_info = l2->data;
768 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
769 struct gatt_desc_info *desc_info = l3->data;
771 if (g_strcmp0(desc_info->desc_path, desc_path)
773 *desc_hdl = desc_info->desc_handle;
779 ERR("Gatt service not found");
783 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
785 const gchar *object_path,
786 const gchar *interface_name,
787 const gchar *method_name,
788 GVariant *parameters,
789 GDBusMethodInvocation *invocation,
794 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
795 GVariantBuilder *builder;
796 GVariantBuilder *inner_builder1 = NULL;
797 GVariant *svc_char = NULL;
799 GSList *gatt_services = NULL;
801 instance = (int*)user_data;
802 gboolean writeAcquired = FALSE;
803 gboolean notifyAcquired = FALSE;
805 DBG("Getting values for service, chars and descriptors");
806 DBG("GATT Server App for which services are requested [%d]", *instance);
809 builder = g_variant_builder_new(
810 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
813 gatt_services = _bt_get_service_list_from_server(*instance);
815 if (g_slist_length(gatt_services) == 0) {
816 ERR("No registered GATT services!!!!");
817 g_dbus_method_invocation_return_value(invocation, NULL);
818 g_variant_builder_unref(builder);
822 for (l = gatt_services; l != NULL; l = l->next) {
823 GVariantBuilder *svc_builder = NULL;
824 GVariantBuilder *inner_builder = NULL;
825 struct gatt_service_info *serv_info = l->data;
826 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
828 /* Prepare inner builder for GattService1 interface */
829 DBG("Creating builder for service");
830 svc_builder = g_variant_builder_new(
831 G_VARIANT_TYPE("a{sa{sv}}"));
832 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
834 g_variant_builder_add(inner_builder, "{sv}", "UUID",
835 g_variant_new_string(serv_info->service_uuid));
837 g_variant_builder_add(inner_builder, "{sv}", "Primary",
838 g_variant_new_boolean(serv_info->is_svc_primary));
841 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
842 DBG("Adding Charatarisitcs list");
843 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
844 struct gatt_char_info *char_info = l4->data;
845 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
846 char_info->char_handle, serv_info->service_handle);
847 g_variant_builder_add(inner_builder1, "o",
848 char_info->char_path);
849 DBG("%s", char_info->char_path);
852 svc_char = g_variant_new("ao", inner_builder1);
853 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
856 g_variant_builder_add(svc_builder, "{sa{sv}}",
860 g_variant_builder_add(builder, "{oa{sa{sv}}}",
861 serv_info->serv_path,
864 g_variant_builder_unref(inner_builder1);
866 /* Prepare inner builder for GattCharacteristic1 interface */
868 GSList *l2 = serv_info->char_data;
869 DBG("Creating builder for characteristics \n");
872 DBG("characteristic data is NULL");
874 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
876 GVariantBuilder *char_builder = NULL;
877 GVariantBuilder *inner_builder = NULL;
878 GVariantBuilder *builder1 = NULL;
879 GVariantBuilder *builder2 = NULL;
880 GVariantBuilder *builder3 = NULL;
881 GVariant *char_val = NULL;
882 GVariant *flags_val = NULL;
883 GVariant *char_desc = NULL;
884 char *unicast = NULL;
885 gboolean notify = FALSE;
888 char_builder = g_variant_builder_new(
891 inner_builder = g_variant_builder_new(
895 struct gatt_char_info *char_info = l2->data;
896 if (char_info == NULL) {
897 ERR("char_info is NULL");
902 g_variant_builder_add(inner_builder, "{sv}", "UUID",
903 g_variant_new_string(char_info->char_uuid));
905 g_variant_builder_add(inner_builder, "{sv}", "Service",
906 g_variant_new("o", serv_info->serv_path));
908 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
910 if (char_info->char_value != NULL) {
911 for (i = 0; i < char_info->value_length; i++) {
912 g_variant_builder_add(builder1, "y",
913 char_info->char_value[i]);
915 char_val = g_variant_new("ay", builder1);
916 g_variant_builder_add(inner_builder, "{sv}",
920 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
921 for (i = 0; i < char_info->flags_length; i++) {
922 g_variant_builder_add(builder2, "s",
923 char_info->char_flags[i]);
925 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
926 DBG("setting WriteAcquired property");
927 writeAcquired = TRUE;
930 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
931 DBG("setting NotifyAcquired property");
932 notifyAcquired = TRUE;
936 flags_val = g_variant_new("as", builder2);
937 g_variant_builder_add(inner_builder, "{sv}", "Flags",
941 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
942 g_variant_new("b", notify));
945 if (writeAcquired == TRUE) {
946 DBG("adding WriteAcquired property");
947 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
948 g_variant_new("b", writeAcquired));
952 if (notifyAcquired == TRUE) {
953 DBG("adding NotifyAcquired property");
954 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
955 g_variant_new("b", notifyAcquired));
959 unicast = g_strdup("00:00:00:00:00:00");
960 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
961 g_variant_new("s", unicast));
964 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
965 DBG("Adding Descriptors list");
967 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
968 struct gatt_desc_info *desc_info = l4->data;
969 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
970 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
971 g_variant_builder_add(builder3, "o",
972 desc_info->desc_path);
973 DBG("%s", desc_info->desc_path);
976 char_desc = g_variant_new("ao", builder3);
977 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
980 g_variant_builder_add(char_builder, "{sa{sv}}",
981 GATT_CHAR_INTERFACE , inner_builder);
982 g_variant_builder_add(builder, "{oa{sa{sv}}}",
983 char_info->char_path, char_builder);
985 /*Prepare inner builder for GattDescriptor1 interface*/
987 GSList *l3 = char_info->desc_data;
990 DBG("descriptor data is NULL");
992 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
994 DBG("Creating builder for descriptor \n");
996 GVariantBuilder *desc_builder = NULL;
997 GVariantBuilder *inner_builder = NULL;
998 GVariantBuilder *builder1 = NULL;
999 GVariantBuilder *builder2 = NULL;
1000 GVariant *desc_val = NULL;
1002 desc_builder = g_variant_builder_new(
1005 inner_builder = g_variant_builder_new(
1009 struct gatt_desc_info *desc_info = l3->data;
1010 if (desc_info == NULL) {
1011 ERR("desc_info is NULL");
1016 g_variant_builder_add(inner_builder,
1018 g_variant_new_string(
1019 desc_info->desc_uuid));
1022 g_variant_builder_add(inner_builder, "{sv}",
1025 char_info->char_path));
1028 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1030 if (desc_info->desc_value != NULL) {
1031 for (i = 0; i < desc_info->value_length; i++) {
1032 g_variant_builder_add(builder1, "y",
1033 desc_info->desc_value[i]);
1035 desc_val = g_variant_new("ay", builder1);
1036 g_variant_builder_add(inner_builder, "{sv}",
1041 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1043 for (i = 0; i < desc_info->flags_length; i++) {
1044 g_variant_builder_add(builder2, "s",
1045 desc_info->desc_flags[i]);
1048 flags_val = g_variant_new("as", builder2);
1049 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1052 g_variant_builder_add(desc_builder, "{sa{sv}}",
1053 GATT_DESC_INTERFACE,
1056 g_variant_builder_add(builder, "{oa{sa{sv}}}",
1057 desc_info->desc_path,
1060 /*unref descriptor builder pointers*/
1061 g_variant_builder_unref(builder1);
1062 g_variant_builder_unref(builder2);
1063 g_variant_builder_unref(inner_builder);
1064 g_variant_builder_unref(desc_builder);
1069 /*unref char builder pointers*/
1070 g_variant_builder_unref(builder1);
1071 g_variant_builder_unref(builder2);
1072 g_variant_builder_unref(builder3);
1073 g_variant_builder_unref(inner_builder);
1074 g_variant_builder_unref(char_builder);
1077 /*unref service builder pointers*/
1078 g_variant_builder_unref(inner_builder);
1079 g_variant_builder_unref(svc_builder);
1082 /* Return builder as method reply */
1083 DBG("Sending gatt service builder values to Bluez");
1084 g_dbus_method_invocation_return_value(invocation,
1090 /* Free User Data */
1094 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1095 const gchar *sender,
1096 const gchar *object_path,
1097 const gchar *interface_name,
1098 const gchar *method_name,
1099 GVariant *parameters,
1100 GDBusMethodInvocation *invocation,
1104 if (g_strcmp0(method_name, "ReadValue") == 0) {
1105 struct hal_ev_gatt_server_read_req ev;
1110 struct gatt_client_info_t *conn_info = NULL;
1111 struct gatt_req_info *req_info = NULL;
1112 struct gatt_service_info *svc_info = NULL;
1116 DBG("Application path = %s", object_path);
1117 DBG("Sender = %s", sender);
1119 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1120 if (svc_info == NULL) {
1121 ERR("Coudn't find service for %s", object_path);
1122 g_dbus_method_invocation_return_value(invocation, NULL);
1126 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1127 DBG("Request id = %u, Offset = %u", req_id, offset);
1129 /* Check if device is already in connected list */
1130 conn_info = __bt_find_remote_gatt_client_info(addr);
1132 if (conn_info == NULL) {
1133 ERR("Coudn't find Connection info for %s", addr);
1134 g_dbus_method_invocation_return_value(invocation, NULL);
1139 ERR("GATT callback NOT registered");
1140 g_dbus_method_invocation_return_value(invocation, NULL);
1144 /* Store requests information */
1145 req_info = g_new0(struct gatt_req_info, 1);
1146 req_info->attr_path = g_strdup(object_path);
1147 req_info->svc_path = g_strdup(svc_info->serv_path);
1148 req_info->request_id = req_id;
1149 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1150 req_info->offset = offset;
1151 req_info->context = invocation;
1153 /* Append request info in list of requests for the particular connection */
1154 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1156 /* Send HAL event */
1157 memset(&ev, 0, sizeof(ev));
1158 ev.conn_id = conn_info->connection_id;
1159 ev.trans_id = req_id;
1160 ev.att_handle = desc_hdl;
1162 ev.is_long = false; /* TODO*/
1164 /* Convert address to hex */
1165 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1167 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1169 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1171 GVariant *var = NULL;
1175 gboolean response_needed = FALSE;
1176 gboolean prep_authorize = FALSE;
1177 struct hal_ev_gatt_server_write_req ev;
1181 struct gatt_service_info *svc_info = NULL;
1182 struct gatt_client_info_t *conn_info = NULL;
1183 struct gatt_req_info *req_info = NULL;
1185 memset(&ev, 0, sizeof(ev));
1188 DBG("Application path = %s", object_path);
1189 DBG("Sender = %s", sender);
1191 g_variant_get(parameters, "(&suqbb@ay)",
1192 &addr, &req_id, &offset, &response_needed, &prep_authorize, &var);
1193 DBG("Request id = %u, Offset = %u", req_id, offset);
1196 DBG("prep_authorize = true");
1198 /* Check if device is already in connected list */
1199 conn_info = __bt_find_remote_gatt_client_info(addr);
1201 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1203 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1204 g_variant_unref(var);
1205 if (response_needed)
1206 g_dbus_method_invocation_return_value(invocation, NULL);
1208 g_object_unref(invocation);
1212 len = g_variant_get_size(var);
1213 if (len > 0 && len < 600) {
1215 data = (char *)g_variant_get_data(var);
1216 memcpy(ev.value, data, len);
1219 if (response_needed) {
1220 /* Store request information */
1221 req_info = g_new0(struct gatt_req_info, 1);
1222 req_info->attr_path = g_strdup(object_path);
1223 req_info->svc_path = g_strdup(svc_info->serv_path);
1224 req_info->request_id = req_id;
1225 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1226 req_info->offset = offset;
1227 req_info->context = invocation;
1229 /* Append request info in list of requests for the particular connection */
1230 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1232 g_object_unref(invocation);
1235 /* Send HAL event */
1236 ev.conn_id = conn_info->connection_id;
1237 ev.trans_id = req_id;
1238 ev.att_handle = desc_hdl;
1240 ev.need_rsp = response_needed;
1243 /* Convert address to hex */
1244 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1246 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1248 g_variant_unref(var);
1253 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1254 const gchar *sender,
1255 const gchar *object_path,
1256 const gchar *interface_name,
1257 const gchar *method_name,
1258 GVariant *parameters,
1259 GDBusMethodInvocation *invocation,
1262 if (g_strcmp0(method_name, "ReadValue") == 0) {
1266 struct hal_ev_gatt_server_read_req ev;
1269 struct gatt_req_info *req_info = NULL;
1270 struct gatt_client_info_t *conn_info = NULL;
1271 struct gatt_service_info *svc_info = NULL;
1273 g_variant_get(parameters, "(&suq)",
1274 &addr, &req_id, &offset);
1276 DBG("ReadValue : req id %u, offset %u, path %s, sender %s, %s", req_id, offset, object_path, sender, addr);
1278 /* Check if device is already in connected list */
1279 conn_info = __bt_find_remote_gatt_client_info(addr);
1281 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1283 if (svc_info == NULL || conn_info == NULL) {
1284 ERR("Invalid information %p, %p", svc_info, conn_info);
1285 g_dbus_method_invocation_return_value(invocation, NULL);
1290 ERR("GATT callback NOT registered");
1291 g_dbus_method_invocation_return_value(invocation, NULL);
1295 /* Store requets information */
1296 req_info = g_new0(struct gatt_req_info, 1);
1297 req_info->attr_path = g_strdup(object_path);
1298 req_info->svc_path = g_strdup(svc_info->serv_path);
1299 req_info->request_id = req_id;
1300 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1301 req_info->offset = offset;
1302 req_info->context = invocation;
1304 /* Append request info in list of requests for the particular connection */
1305 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1307 /* Send HAL event */
1308 memset(&ev, 0, sizeof(ev));
1309 ev.conn_id = conn_info->connection_id;
1310 ev.trans_id = req_id;
1311 ev.att_handle = char_hdl;
1313 ev.is_long = false; /* TODO*/
1315 /* Convert address to hex */
1316 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1317 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1319 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1320 GVariant *var = NULL;
1324 gboolean response_needed = FALSE;
1325 gboolean prep_authorize = FALSE;
1326 struct hal_ev_gatt_server_write_req ev;
1330 struct gatt_service_info *svc_info = NULL;
1331 struct gatt_req_info *req_info = NULL;
1332 struct gatt_client_info_t *conn_info = NULL;
1334 memset(&ev, 0, sizeof(ev));
1336 DBG("WriteValue : Application path %s, sender %s", object_path, sender);
1338 g_variant_get(parameters, "(&suqbb@ay)",
1339 &addr, &req_id, &offset, &response_needed, &prep_authorize, &var);
1340 DBG("Request id = %u, Offset = %u", req_id, offset);
1343 DBG("prep_authorize = true");
1345 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1347 /* Check if device is already in connected list */
1348 conn_info = __bt_find_remote_gatt_client_info(addr);
1350 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1351 g_variant_unref(var);
1352 if (response_needed)
1353 g_dbus_method_invocation_return_value(invocation, NULL);
1355 g_object_unref(invocation);
1359 len = g_variant_get_size(var);
1360 if (len > 0 && len < 600) {
1362 data = (char *)g_variant_get_data(var);
1363 memcpy(ev.value, data, len);
1367 if (response_needed) {
1368 /* Store requets information */
1369 req_info = g_new0(struct gatt_req_info, 1);
1370 req_info->attr_path = g_strdup(object_path);
1371 req_info->svc_path = g_strdup(svc_info->serv_path);
1372 req_info->request_id = req_id;
1373 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1374 req_info->offset = offset;
1375 req_info->context = invocation;
1377 /* Append request info in list of requests for the particular connection */
1378 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1381 g_object_unref(invocation);
1384 /* Send HAL event */
1385 ev.conn_id = conn_info->connection_id;
1386 ev.trans_id = req_id;
1387 ev.att_handle = char_hdl;
1389 ev.need_rsp = response_needed;
1392 /* Convert address to hex */
1393 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1395 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1397 g_variant_unref(var);
1400 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1403 struct gatt_service_info *svc_info = NULL;
1404 struct hal_ev_gatt_server_notifcation_change ev;
1407 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1408 if (svc_info == NULL || event_cb == NULL)
1411 /* Send HAL event */
1412 memset(&ev, 0, sizeof(ev));
1413 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1414 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1415 ev.att_handle = char_hdl;
1418 /* Convert address to hex */
1419 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1421 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1424 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1427 struct gatt_service_info *svc_info = NULL;
1428 struct hal_ev_gatt_server_notifcation_change ev;
1431 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1432 if (svc_info == NULL || event_cb == NULL)
1435 /* Send HAL event */
1436 memset(&ev, 0, sizeof(ev));
1437 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1438 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1439 ev.att_handle = char_hdl;
1442 /* Convert address to hex */
1443 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1445 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1448 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1450 gboolean complete = FALSE;
1453 struct gatt_service_info *svc_info = NULL;
1454 struct gatt_client_info_t *conn_info = NULL;
1456 struct hal_ev_gatt_server_indicate_cfm ev;
1458 DBG("IndicateConfirm : Application path %s, sender %s", object_path, sender);
1460 g_variant_get(parameters, "(&sb)", &addr, &complete);
1461 DBG("Remote Device address number = %s", addr);
1462 DBG("Is Indicate confirmation for last device [%d]", complete);
1464 /* Check if device is already in connected list */
1465 conn_info = __bt_find_remote_gatt_client_info(addr);
1467 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1469 if (svc_info == NULL || conn_info == NULL
1470 || event_cb == NULL) {
1474 /* Send HAL event */
1475 memset(&ev, 0, sizeof(ev));
1476 ev.conn_id = conn_info->connection_id;
1477 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1478 ev.att_handle = char_hdl;
1480 /* Convert address to hex */
1481 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1483 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1484 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1488 struct hal_ev_gatt_server_acquire_write_res ev;
1489 struct gatt_service_info *svc_info = NULL;
1490 struct gatt_req_info *req_info = NULL;
1491 struct gatt_client_info_t *conn_info = NULL;
1492 char *dev_path = NULL;
1494 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1496 DBG("AcquireWrite : Application path %s, sender %s", object_path, sender);
1499 g_variant_get(parameters, "(a{sv})", &iter);
1501 GVariant *value = NULL;
1502 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1503 if (g_strcmp0(key, "MTU") == 0)
1504 g_variant_get(value, "q", &mtu);
1505 else if (g_strcmp0(key, "link") == 0)
1506 g_variant_get(value, "s", &link);
1507 else if (g_strcmp0(key, "device") == 0)
1508 g_variant_get(value, "o", &dev_path);
1511 DBG(" path %s LINK = %s, MTU = %u", dev_path, link, mtu);
1513 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1515 _bt_hal_convert_device_path_to_address(dev_path, addr);
1517 DBG("remote address %s", addr);
1521 /* Check if device is already in connected list */
1522 conn_info = __bt_find_remote_gatt_client_info(addr);
1523 if (conn_info == NULL) {
1524 ERR("Cleint info not found\n");
1525 g_variant_iter_free(iter);
1529 if (svc_info == NULL) {
1530 ERR("svc_info info not found\n");
1531 g_variant_iter_free(iter);
1535 /* Store requets information */
1536 req_info = g_new0(struct gatt_req_info, 1);
1537 req_info->attr_path = g_strdup(object_path);
1538 req_info->svc_path = g_strdup(svc_info->serv_path);
1539 req_info->request_id = conn_info->connection_id;
1540 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1541 req_info->offset = mtu;
1542 req_info->context = invocation;
1544 /* Append request info in list of requests for the particular connection */
1545 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1547 /* Send HAL event */
1548 memset(&ev, 0, sizeof(ev));
1549 ev.conn_id = conn_info->connection_id;
1550 ev.char_handl = char_hdl;
1552 ev.trans_id = conn_info->connection_id;
1553 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1554 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1555 g_variant_iter_free(iter);
1557 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1561 char *dev_path = NULL;
1563 struct hal_ev_gatt_server_acquire_notify ev;
1564 struct gatt_service_info *svc_info = NULL;
1565 struct gatt_client_info_t *conn_info = NULL;
1566 struct gatt_req_info *req_info = NULL;
1567 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1569 INFO("AcquireNotify : Application path %s, sender %s", object_path, sender);
1572 g_variant_get(parameters, "(a{sv})", &iter);
1574 GVariant* value = NULL;
1575 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1576 if (g_strcmp0(key, "MTU") == 0)
1577 g_variant_get(value, "q", &mtu);
1578 else if (g_strcmp0(key, "link") == 0)
1579 g_variant_get(value, "s", &link);
1580 else if (g_strcmp0(key, "device") == 0)
1581 g_variant_get(value, "o", &dev_path);
1584 DBG("MTU = %u", mtu);
1585 INFO("Dev Path %s LINK = %s, MTU = %u", dev_path, link, mtu);
1586 _bt_hal_convert_device_path_to_address(dev_path, addr);
1587 INFO("Remote address %s", addr);
1591 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1593 /* Check if device is already in connected list */
1594 conn_info = __bt_find_remote_gatt_client_info(addr);
1595 if (conn_info == NULL) {
1596 ERR("Client info not found\n");
1597 g_variant_iter_free(iter);
1600 if (svc_info == NULL) {
1601 ERR("svc_info info not found\n");
1602 g_variant_iter_free(iter);
1606 /* Store requets information */
1607 req_info = g_new0(struct gatt_req_info, 1);
1608 req_info->attr_path = g_strdup(object_path);
1609 req_info->svc_path = g_strdup(svc_info->serv_path);
1610 req_info->request_id = -1;
1611 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1612 req_info->offset = mtu;
1613 req_info->context = invocation;
1615 INFO("AcquireNotify : Added GATT client path[%s]", conn_info->addr);
1616 /* Append request info in list of requests for the particular connection */
1617 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1619 /* Send HAL event */
1620 memset(&ev, 0, sizeof(ev));
1621 ev.conn_id = conn_info->connection_id;
1622 ev.char_handl = char_hdl;
1624 ev.trans_id = req_info->request_id;
1625 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1627 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1628 g_variant_iter_free(iter);
1633 g_dbus_method_invocation_return_value(invocation, NULL);
1636 static gboolean __bt_hal_gatt_emit_interface_removed(const char *app_path, gchar *object_path, gchar *interface)
1639 GError *error = NULL;
1640 GVariantBuilder *array_builder;
1642 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1643 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1644 g_variant_builder_add(array_builder, "s", interface);
1646 ret = g_dbus_connection_emit_signal(g_conn, NULL, app_path,
1647 "org.freedesktop.DBus.ObjectManager",
1648 "InterfacesRemoved",
1649 g_variant_new("(oas)",
1650 object_path, array_builder),
1654 if (error != NULL) {
1655 /* dbus gives error cause */
1656 ERR("d-bus api failure: errcode[%x], message[%s]",
1657 error->code, error->message);
1658 g_clear_error(&error);
1661 g_variant_builder_unref(array_builder);
1666 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1673 g_free(desc_info->desc_path);
1674 g_free(desc_info->desc_uuid);
1675 g_free(desc_info->desc_value);
1677 for (i = 0; i < desc_info->flags_length; i++)
1678 g_free(desc_info->desc_flags[i]);
1683 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1690 g_free(char_info->char_path);
1691 g_free(char_info->char_uuid);
1692 g_free(char_info->char_value);
1694 for (i = 0; i < char_info->flags_length; i++)
1695 g_free(char_info->char_flags[i]);
1700 static const GDBusInterfaceVTable desc_interface_vtable = {
1701 __bt_gatt_desc_method_call,
1706 static const GDBusInterfaceVTable char_interface_vtable = {
1707 __bt_gatt_char_method_call,
1712 static const GDBusInterfaceVTable serv_interface_vtable = {
1718 static const GDBusInterfaceVTable manager_interface_vtable = {
1719 __bt_gatt_manager_method_call,
1725 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1726 const gchar *introspection_data)
1729 GDBusNodeInfo *node_info = NULL;
1731 if (introspection_data == NULL)
1735 DBG("Create new node info");
1736 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1739 ERR("Unable to create node: %s", err->message);
1740 g_clear_error(&err);
1747 /* To send stack event to hal-av handler */
1748 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1753 void _bt_hal_unregister_gatt_server_handler_cb(void)
1758 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1760 struct hal_ev_gatt_desc_added ev;
1761 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1763 /* Prepare to GATT characteristic added event */
1764 memset(&ev, 0, sizeof(ev));
1765 ev.status = BT_STATUS_SUCCESS;
1766 ev.server_instance = data->instance_data;
1767 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1768 ev.service_handle = data->srvc_hdl;
1769 ev.desc_handle = data->desc_hdl;
1772 ERR("GATT Descriptor Added callback registered");
1774 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1775 data->instance_data, data->srvc_hdl, data->desc_hdl);
1777 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1784 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1786 struct hal_ev_gatt_char_added ev;
1787 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1789 /* Prepare to GATT characteristic added event */
1790 memset(&ev, 0, sizeof(ev));
1791 ev.status = BT_STATUS_SUCCESS;
1792 ev.server_instance = data->instance_data;
1793 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1794 ev.service_handle = data->srvc_hdl;
1795 ev.char_handle = data->char_hdl;
1798 ERR("GATT Characteristic Added callback registered");
1800 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1801 data->instance_data, data->srvc_hdl, data->char_hdl);
1803 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1810 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1812 struct hal_ev_gatt_service_added ev;
1813 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1815 /* Prepare to GATT Service added event */
1816 memset(&ev, 0, sizeof(ev));
1817 ev.status = BT_STATUS_SUCCESS;
1818 ev.server_instance = data->instance_data;
1819 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1820 ev.service_handle = data->srvc_hdl;
1821 ev.is_primary = data->is_primary;
1824 ERR("GATT Service Added callback registered");
1826 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1827 data->instance_data, data->srvc_hdl);
1828 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1835 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1837 struct hal_ev_gatt_service_started ev;
1838 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1840 /* Prepare to GATT Service added event */
1841 memset(&ev, 0, sizeof(ev));
1842 ev.status = BT_STATUS_SUCCESS;
1843 ev.server_instance = data->instance_data;
1844 ev.service_handle = data->srvc_hdl;
1847 ERR("GATT Service Started callback registered");
1849 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1850 data->instance_data, data->srvc_hdl);
1851 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1858 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1860 struct hal_ev_gatt_service_deleted ev;
1861 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1863 /* Prepare to GATT Service added event */
1864 memset(&ev, 0, sizeof(ev));
1865 ev.status = BT_STATUS_SUCCESS;
1866 ev.server_instance = data->instance_data;
1867 ev.service_handle = data->srvc_hdl;
1870 ERR("GATT Service Deleted callback registered");
1872 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1873 data->instance_data, data->srvc_hdl);
1874 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1881 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1883 struct hal_ev_server_instance_registered ev;
1884 hal_register_server_data *data = (hal_register_server_data*) user_data;
1886 /* Prepare to send AV connecting event */
1887 memset(&ev, 0, sizeof(ev));
1888 ev.status = BT_STATUS_SUCCESS;
1889 ev.server_instance = data->instance_data;
1890 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1893 ERR("GATT Register Server Instance Callback not registered");
1895 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1896 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1904 static int bt_hal_gatts_get_gatt_server_instance()
1909 struct hal_gatts_server_register_info_t *info = NULL;
1911 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1912 info = (struct hal_gatts_server_register_info_t *)l->data;
1917 return info->server_if;
1923 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_from_uuid(bt_uuid_t *app_uuid)
1928 struct hal_gatts_server_register_info_t *info = NULL;
1930 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1931 info = (struct hal_gatts_server_register_info_t *)l->data;
1936 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
1937 DBG("gatt server register found");
1945 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info(int server_if)
1948 struct hal_gatts_server_register_info_t *info = NULL;
1950 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1951 info = (struct hal_gatts_server_register_info_t *)l->data;
1956 if (info->server_if == server_if) {
1964 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_by_slot_id(int adv_slot_id)
1969 struct hal_gatts_server_register_info_t *info = NULL;
1971 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1972 info = (struct hal_gatts_server_register_info_t *)l->data;
1977 if (info->adv_slot_id == adv_slot_id) {
1978 DBG("gatt server register found");
1986 static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_uuid_t *app_uuid)
1988 struct hal_gatts_server_register_info_t * server_register_info = NULL;
1989 int instance_id = 0;
1991 server_register_info = bt_hal_gatts_find_server_register_info_from_uuid(app_uuid);
1992 if (server_register_info != NULL) {
1993 DBG("gatt server is already registered");
1994 return server_register_info;
1997 instance_id = __bt_hal_gatt_assign_id();
1998 if (instance_id == -1) {
1999 ERR("Fail to allocate the server if");
2003 server_register_info = g_malloc0(sizeof(struct hal_gatts_server_register_info_t));
2004 server_register_info->server_if = instance_id;
2006 DBG("Adding the gatt server app. server_if:[%d]", server_register_info->server_if);
2008 server_register_info->adv_slot_id = -1;
2009 memcpy(&server_register_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
2010 hal_gatts_server_register_list = g_slist_append(hal_gatts_server_register_list, server_register_info);
2012 return server_register_info;
2015 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
2017 CHECK_BTGATT_INIT();
2018 struct hal_gatts_server_register_info_t *server_register_info = NULL;
2020 DBG("Register server instance request");
2021 server_register_info = bt_hal_gatts_add_server_app(uuid);
2022 if (server_register_info == NULL) {
2023 ERR("Fail to register the server app");
2024 return BT_STATUS_FAIL;
2027 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
2028 user_data->instance_data = server_register_info->server_if;
2031 * As we need to provide async callback to user from HAL, simply schedule a
2032 * callback method which will carry actual result
2034 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
2035 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
2037 /* If available, then return success, else return error */
2038 return BT_STATUS_SUCCESS;
2041 static void _bt_hal_remove_gatt_server_from_list(int server_if)
2044 struct gatt_server_app *info = NULL;
2046 for (l = gatt_server_apps; l != NULL;) {
2047 info = (struct gatt_server_app*)l->data;
2048 l = g_slist_next(l);
2051 if (info->slot == server_if) {
2052 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
2053 info->app_path, info->slot);
2055 /* Only if all services are deleted from the GATT Server, then only Unregister it.
2056 Reason: it is possible, GATT Server app oly wants to disable multi advertising
2057 In above case, only advertising block will be deallocated, Gatt Server will remain
2059 if (info->services == NULL) {
2060 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
2061 INFO("Total gatt server apps still existing after removing above is [%d]",
2062 g_slist_length(gatt_server_apps));
2064 /* DBUS Unregister only for current app */
2065 __bt_hal_gatt_deinit(info->app_path);
2067 g_free(info->app_path);
2071 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
2072 g_slist_length(info->services));
2078 static bt_status_t gatt_server_unregister_app(int server_if)
2080 CHECK_BTGATT_INIT();
2081 DBG("Un-Register server instance request [%d]", server_if);
2082 struct hal_gatts_server_register_info_t *server_register_info = NULL;
2085 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
2086 if (server_register_info == NULL) {
2087 DBG("gatt server is not registered");
2088 return BT_STATUS_SUCCESS;
2091 /* remove the gatt server register info from the register list */
2092 hal_gatts_server_register_list = g_slist_remove(hal_gatts_server_register_list, server_register_info);
2093 g_free(server_register_info);
2095 __bt_hal_gatt_delete_id(server_if);
2097 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
2098 _bt_hal_remove_gatt_server_from_list(server_if);
2099 return BT_STATUS_SUCCESS;
2102 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
2104 CHECK_BTGATT_INIT();
2105 return BT_STATUS_SUCCESS;
2108 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
2111 GError *g_error = NULL;
2112 GVariant *reply = NULL;
2116 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2117 g_object_unref(proxy);
2118 if (reply == NULL) {
2119 ERR("Disconnect LE Dbus Call Error");
2121 ERR("Error: %s\n", g_error->message);
2122 g_clear_error(&g_error);
2125 g_variant_unref(reply);
2129 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
2131 CHECK_BTGATT_INIT();
2133 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2135 GDBusProxy *device_proxy;
2136 GDBusConnection *g_conn;
2137 struct gatt_client_info_t *conn_info = NULL;
2141 if (NULL == bd_addr) {
2142 ERR("bd_addr is NULL");
2143 return BT_STATUS_PARM_INVALID;
2146 /* GDBUS Connection Info validate */
2147 g_conn = _bt_hal_get_system_gconn();
2148 if (g_conn == NULL) {
2149 ERR("Could not get System DBUS Connection");
2150 return BT_STATUS_FAIL;
2153 /* Connection Info validate */
2154 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2155 if (conn_info == NULL) {
2156 ERR("No Connection Inforamtion!!!");
2157 return BT_STATUS_FAIL;
2160 _bt_hal_convert_addr_type_to_string(device_address,
2161 (unsigned char *)bd_addr->address);
2163 //check if connection has the same device address
2164 if (g_strcmp0(conn_info->addr, device_address) != 0) {
2165 ERR("device address [%s] does not match", device_address);
2166 return BT_STATUS_FAIL;
2169 device_path = _bt_hal_get_device_object_path(conn_info->addr);
2170 if (device_path == NULL) {
2171 ERR("device_path is NULL");
2172 return BT_STATUS_PARM_INVALID;
2175 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
2176 NULL, BT_HAL_BLUEZ_NAME,
2177 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2180 g_free(device_path);
2181 if (device_proxy == NULL)
2182 return BT_STATUS_FAIL;
2184 INFO("Disconnect LE [%s]", device_address);
2186 g_dbus_proxy_call(device_proxy, "DisconnectLE",
2188 G_DBUS_CALL_FLAGS_NONE,
2189 BT_HAL_MAX_DBUS_TIMEOUT,
2191 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
2194 return BT_STATUS_SUCCESS;
2197 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
2202 uuid = btuuid2str(srvc_id->uu);
2203 DBG("Original UUID [%s]", uuid);
2205 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
2206 /* Extract Standard UUID string */
2207 memcpy(uuid_buf, &uuid[4], 4);
2209 DBG("Converted string [%s]", uuid_buf);
2210 return g_strdup(uuid_buf);
2212 return strdup(uuid);
2215 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
2218 /* For GATT service specific */
2219 GDBusNodeInfo *node_info;
2222 struct gatt_service_info *serv_info = NULL;
2223 GVariantBuilder *builder = NULL;
2224 GVariantBuilder *builder1 = NULL;
2225 GVariantBuilder *inner_builder = NULL;
2226 gboolean svc_primary = TRUE;
2227 GError *error = NULL;
2228 hal_gatt_service_added *user_data = NULL;
2229 int service_handle = 0;
2230 DBG("Service add to DBUS slot [%d]", slot);
2232 service_handle = __bt_hal_assign_gatt_handle(BT_GATT_TYPE_SERV);
2233 if (service_handle == -1) {
2234 ERR("Too many gatt service handles are created");
2235 return BT_STATUS_FAIL;
2238 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, service_handle);
2239 DBG("gatt service path is [%s]", path);
2241 node_info = __bt_gatt_create_method_node_info(
2242 service_introspection_xml);
2243 if (node_info == NULL) {
2245 __bt_hal_free_gatt_handle(BT_GATT_TYPE_SERV, service_handle);
2246 return BT_STATUS_FAIL;
2249 object_id = g_dbus_connection_register_object(g_conn, path,
2250 node_info->interfaces[0],
2251 &serv_interface_vtable,
2252 NULL, NULL, &error);
2254 if (object_id == 0) {
2255 ERR("failed to register: %s", error->message);
2256 g_error_free(error);
2258 __bt_hal_free_gatt_handle(BT_GATT_TYPE_SERV, service_handle);
2259 return BT_STATUS_FAIL;
2261 /* Add object_id/gatt service information; it's required at the time of
2262 * service unregister and Getmanagedobjects
2264 serv_info = g_new0(struct gatt_service_info, 1);
2266 serv_info->serv_path = g_strdup(path);
2267 serv_info->serv_id = object_id;
2268 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
2269 serv_info->is_svc_registered = FALSE;
2270 serv_info->is_svc_primary = svc_primary;
2271 DBG("Service Handle to be added is [%d]", service_handle);
2272 serv_info->service_handle = service_handle;
2274 /* Update service in GATT Server service List */
2275 gatt_services = g_slist_append(gatt_services, serv_info);
2277 /* emit interfacesadded signal here for service path */
2278 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2279 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2281 g_variant_builder_add(inner_builder, "{sv}",
2282 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
2284 g_variant_builder_add(inner_builder, "{sv}",
2285 "Primary", g_variant_new_boolean(svc_primary));
2287 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2289 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
2290 g_variant_new("ao", builder1));
2292 g_variant_builder_add(builder, "{sa{sv}}",
2293 GATT_SERV_INTERFACE, inner_builder);
2295 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2296 "org.freedesktop.Dbus.ObjectManager", // TODO: need to check Dbus is working or not
2298 g_variant_new("(oa{sa{sv}})",
2303 /* dbus gives error cause */
2304 ERR("d-bus api failure: errcode[%x], message[%s]",
2305 error->code, error->message);
2306 g_clear_error(&error);
2310 /* Send Service handle to application */
2311 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2312 user_data->srvc_hdl = serv_info->service_handle;
2313 user_data->instance_data = slot;
2314 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2315 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2317 /* Save newly created service in GATT Server's service list */
2318 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2322 g_variant_builder_unref(inner_builder);
2323 g_variant_builder_unref(builder);
2324 g_variant_builder_unref(builder1);
2325 return BT_STATUS_SUCCESS;
2328 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2331 char *app_path = (char*)user_data;
2332 INFO("UnregisterApplication is completed app [%s]", app_path);
2333 GError *error = NULL;
2334 GVariant *result = NULL;
2337 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2339 if (result == NULL) {
2340 /* dBUS-RPC is failed */
2341 ERR("Dbus-RPC is failed\n");
2343 if (error != NULL) {
2344 /* dBUS gives error cause */
2345 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2346 error->code, error->message);
2347 g_clear_error(&error);
2350 g_variant_unref(result);
2355 static void __bt_hal_gatt_deinit(char *app_path)
2357 GDBusProxy *proxy = NULL;
2361 /* Step1: Remove requested App */
2362 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2363 "/org/bluez/hci0", "org.bluez.GattManager1");
2368 INFO("UnregisterApplication : path [%s]", app_path);
2370 /* Async Call to Unregister Service */
2371 data = g_strdup(app_path);
2372 g_dbus_proxy_call(proxy,
2373 "UnregisterApplication",
2374 g_variant_new("(o)",
2376 G_DBUS_CALL_FLAGS_NONE, -1,
2378 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2381 /* If requested app is last GATT Server app, then clean all resources */
2382 if (gatt_server_apps == NULL) {
2383 INFO("All GATT servers are removed, clean all DBUS resources");
2385 /* unregister the exported interface for object manager */
2386 g_dbus_connection_unregister_object(g_conn, manager_id);
2388 g_bus_unown_name(owner_id);
2391 g_object_unref(manager_gproxy);
2392 manager_gproxy = NULL;
2398 static int __bt_hal_gatt_init(void)
2402 /* Only once for ALL GATT Servers */
2403 if (owner_id == 0) {
2407 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2410 ERR("Unable to connect to gdbus: %s", err->message);
2411 g_clear_error(&err);
2413 return BT_STATUS_FAIL;
2416 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2417 INFO("well-known name: %s", name);
2419 owner_id = g_bus_own_name_on_connection(g_conn, name,
2420 G_BUS_NAME_OWNER_FLAGS_NONE,
2421 NULL, NULL, NULL, NULL);
2425 INFO("Owner ID [%d]", owner_id);
2427 /* Only once for ALL GATT Servers */
2428 if (manager_node_info == NULL) {
2429 /* Register ObjectManager interface */
2430 manager_node_info = __bt_gatt_create_method_node_info(
2431 manager_introspection_xml);
2433 if (manager_node_info == NULL) {
2434 ERR("failed to get node info");
2435 return BT_STATUS_FAIL;
2440 return BT_STATUS_SUCCESS;
2443 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2447 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2448 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2449 if (app->slot == slot) {
2450 INFO("GATT Server app found app path [%s] instance [%d]",
2451 app->app_path, app->slot);
2452 *app_path = app->app_path;
2456 /* GATT Server not found */
2460 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2462 if (app_path == NULL)
2465 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2466 app->app_path = g_strdup(app_path);
2468 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2469 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2472 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2475 CHECK_BTGATT_INIT();
2476 char *app_path = NULL;
2477 GError *error = NULL;
2480 int result = BT_STATUS_SUCCESS;
2482 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2483 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2485 /* Check if this GATT server Application is already registered with DBUS */
2486 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2488 if (app_path != NULL) {
2489 DBG("GATT server path is already defined [%s]", app_path);
2490 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2492 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2493 result = __bt_hal_gatt_init();
2494 if (result != BT_STATUS_SUCCESS)
2497 /* Only once for each GATT Server */
2498 app_path = g_strdup_printf("/com/%d", server_if);
2500 app_id = g_malloc0(sizeof(int));
2501 *app_id = server_if;
2503 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2504 manager_node_info->interfaces[0],
2505 &manager_interface_vtable,
2506 (gpointer)app_id, NULL, &error);
2508 if (manager_id == 0) {
2509 ERR("failed to register: %s", error->message);
2510 g_error_free(error);
2513 INFO("manager_id [%d]", manager_id);
2515 /* For current GATT Server, app_path is created, save it in Table */
2516 _bt_hal_update_gatt_server_path(server_if, app_path);
2518 /* Add GATT Service to DBUS */
2519 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2525 INFO("Successfully added service");
2526 return BT_STATUS_SUCCESS;
2533 INFO("Service addition failed!!");
2534 return BT_STATUS_FAIL;
2537 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2538 int included_handle)
2540 CHECK_BTGATT_INIT();
2541 return BT_STATUS_SUCCESS;
2545 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2548 GSList *gatt_services = NULL;
2550 struct gatt_service_info *info = NULL;
2552 gatt_services = _bt_get_service_list_from_server(instance);
2554 len = g_slist_length(gatt_services);
2555 l = g_slist_nth(gatt_services, len -1);
2561 if (info->service_handle == service_handle)
2566 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2570 GSList *gatt_services = NULL;
2571 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2573 gatt_services = _bt_get_service_list_from_server(instance);
2575 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2576 struct gatt_service_info *info = l->data;
2577 INFO("Got one service with handle [%d]", info->service_handle);
2578 if (info->service_handle == service_handle)
2581 ERR("Gatt service with handle [%d] not found", service_handle);
2585 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2586 bt_uuid_t *uuid, int properties,
2590 GError *error = NULL;
2592 GDBusNodeInfo *node_info;
2594 GVariantBuilder *builder = NULL;
2595 GVariantBuilder *inner_builder = NULL;
2596 struct gatt_service_info *serv_info = NULL;
2597 struct gatt_char_info *char_info = NULL;
2598 GVariantBuilder *builder2 = NULL;
2599 GVariantBuilder *builder3 = NULL;
2600 GVariant *flags_val = NULL;
2602 char *char_flags[NUMBER_OF_FLAGS];
2604 hal_gatt_char_added *user_data = NULL;
2606 int char_handle = 0;
2608 CHECK_BTGATT_INIT();
2609 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2610 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2612 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2613 if (serv_info == NULL)
2614 return BT_STATUS_FAIL;
2616 char_handle = __bt_hal_assign_gatt_handle(BT_GATT_TYPE_CHAR);
2617 if (char_handle == -1) {
2618 ERR("Too many gatt char handles are created");
2619 return BT_STATUS_FAIL;
2622 DBG("Add new GATT characteristic: Current GATT char handle [%d]", char_handle);
2623 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, char_handle);
2624 DBG("gatt characteristic path is [%s]", path);
2626 node_info = __bt_gatt_create_method_node_info(
2627 characteristics_introspection_xml);
2628 if (node_info == NULL) {
2630 __bt_hal_free_gatt_handle(BT_GATT_TYPE_CHAR, char_handle);
2631 return BT_STATUS_FAIL;
2634 app_id = g_malloc0(sizeof(int));
2637 object_id = g_dbus_connection_register_object(g_conn, path,
2638 node_info->interfaces[0],
2639 &char_interface_vtable,
2640 (gpointer)app_id, NULL, &error);
2642 if (object_id == 0) {
2643 ERR("failed to register: %s", error->message);
2644 g_error_free(error);
2647 __bt_hal_free_gatt_handle(BT_GATT_TYPE_CHAR, char_handle);
2648 return BT_STATUS_FAIL;
2651 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2652 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2653 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2654 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2655 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2656 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2657 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2658 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2660 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2662 char_info = g_new0(struct gatt_char_info, 1);
2664 char_info->char_path = g_strdup(path);
2665 char_info->char_id = object_id;
2666 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2667 for (i = 0; i < flag_count; i++)
2668 char_info->char_flags[i] = char_flags[i];
2671 char_info->flags_length = flag_count;
2672 char_info->char_handle = char_handle;
2675 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2676 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2678 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2679 g_variant_new("s", char_info->char_uuid));
2680 g_variant_builder_add(inner_builder, "{sv}", "Service",
2681 g_variant_new("o", serv_info->serv_path));
2683 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2685 for (i = 0; i < flag_count; i++)
2686 g_variant_builder_add(builder2, "s", char_flags[i]);
2688 flags_val = g_variant_new("as", builder2);
2689 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2692 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2694 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2695 g_variant_new("ao", builder3));
2697 g_variant_builder_add(builder, "{sa{sv}}",
2698 GATT_CHAR_INTERFACE,
2701 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2702 "org.freedesktop.Dbus.ObjectManager",
2704 g_variant_new("(oa{sa{sv}})",
2709 /* dbus gives error cause */
2710 ERR("d-bus api failure: errcode[%x], message[%s]",
2711 error->code, error->message);
2712 g_clear_error(&error);
2716 //*char_path = g_strdup(path);
2721 /* Send Service handle to application */
2722 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2723 user_data->srvc_hdl = serv_info->service_handle;
2724 user_data->char_hdl = char_handle;
2725 user_data->instance_data = slot;
2726 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2727 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2729 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2730 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2735 g_variant_builder_unref(inner_builder);
2736 g_variant_builder_unref(builder);
2737 g_variant_builder_unref(builder2);
2738 g_variant_builder_unref(builder3);
2740 return BT_STATUS_SUCCESS;
2743 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2746 CHECK_BTGATT_INIT();
2748 // static int desc_id = 1;
2749 GError *error = NULL;
2751 GDBusNodeInfo *node_info;
2753 GVariantBuilder *builder = NULL;
2754 GVariantBuilder *inner_builder = NULL;
2756 struct gatt_char_info *char_info = NULL;
2757 struct gatt_desc_info *desc_info = NULL;
2758 struct gatt_service_info *serv_info = NULL;
2760 gchar **line_argv = NULL;
2762 char *char_path = NULL;
2765 GVariantBuilder *builder2 = NULL;
2766 GVariant *flags_val = NULL;
2768 char *desc_flags[NUMBER_OF_FLAGS];
2771 hal_gatt_desc_added *user_data = NULL;
2772 int desc_handle = 0;
2774 /* Fetch service data for the GATT server */
2775 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2776 if (serv_info == NULL)
2777 return BT_STATUS_FAIL;
2779 /* Fetch list of characteristics from the service info */
2780 l = serv_info->char_data;
2782 /* Fetch last char info from the characteristic list */
2783 char_info = g_slist_last(l)->data;
2784 if (char_info == NULL)
2785 return BT_STATUS_FAIL;
2787 /* Fetch characteristic path from char info */
2788 char_path = char_info->char_path;
2790 line_argv = g_strsplit_set(char_path, "/", 0);
2791 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2794 node_info = __bt_gatt_create_method_node_info(
2795 descriptor_introspection_xml);
2797 if (node_info == NULL) {
2798 g_strfreev(line_argv);
2800 return BT_STATUS_FAIL;
2803 desc_handle = __bt_hal_assign_gatt_handle(BT_GATT_TYPE_DESC);
2804 if (desc_handle == -1) {
2805 ERR("Too many gatt desc handles are created");
2806 return BT_STATUS_FAIL;
2809 DBG("Add new Descriptor: Current GATT desc handle [%d]", desc_handle);
2810 path = g_strdup_printf("%s/descriptor%d", char_path, desc_handle);
2811 DBG("gatt descriptor path is [%s]", path);
2813 app_id = g_malloc0(sizeof(int));
2816 object_id = g_dbus_connection_register_object(g_conn, path,
2817 node_info->interfaces[0],
2818 &desc_interface_vtable,
2819 (gpointer)app_id, NULL, &error);
2821 if (object_id == 0) {
2822 ERR("failed to register: %s", error->message);
2823 g_error_free(error);
2825 g_strfreev(line_argv);
2828 __bt_hal_free_gatt_handle(BT_GATT_TYPE_DESC, desc_handle);
2829 return BT_STATUS_FAIL;
2832 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2834 desc_info = g_new0(struct gatt_desc_info, 1);
2836 desc_info->desc_path = g_strdup(path);
2837 desc_info->desc_id = object_id;
2838 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2840 for (i = 0; i < flag_count; i++)
2841 desc_info->desc_flags[i] = desc_flags[i];
2843 desc_info->flags_length = flag_count;
2844 desc_info->desc_handle = desc_handle;
2847 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2848 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2850 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2851 g_variant_new("s", btuuid2str(uuid->uu)));
2852 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2853 g_variant_new("o", char_path));
2855 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2857 for (i = 0; i < flag_count; i++)
2858 g_variant_builder_add(builder2, "s", desc_flags[i]);
2860 flags_val = g_variant_new("as", builder2);
2861 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2864 g_variant_builder_add(builder, "{sa{sv}}",
2865 GATT_DESC_INTERFACE,
2868 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2869 "org.freedesktop.Dbus.ObjectManager",
2871 g_variant_new("(oa{sa{sv}})",
2874 if (error != NULL) {
2875 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2876 error->code, error->message);
2877 g_clear_error(&error);
2880 //*desc_path = g_strdup(path);
2882 /* Save newly created descriptor to GATT server's service's characteristic */
2883 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2885 /* Send descriptor handle to application */
2886 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2887 user_data->srvc_hdl = serv_info->service_handle;
2888 user_data->desc_hdl = desc_handle;
2889 user_data->instance_data = slot;
2890 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2891 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2896 g_strfreev(line_argv);
2897 g_variant_builder_unref(inner_builder);
2898 g_variant_builder_unref(builder);
2899 return BT_STATUS_SUCCESS;
2902 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2904 GError *error = NULL;
2906 char *data = (char*) user_data;
2907 INFO("RegisterApplication is completed path [%s]", data);
2909 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2911 if (result == NULL) {
2912 /* dBUS-RPC is failed */
2913 ERR("Dbus-RPC is failed\n");
2915 if (error != NULL) {
2916 /* dBUS gives error cause */
2917 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2918 error->code, error->message);
2919 g_clear_error(&error);
2922 g_variant_unref(result);
2927 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2928 const gchar *path, const gchar *interface)
2934 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2939 ERR("Unable to connect to gdbus: %s", err->message);
2940 g_clear_error(&err);
2945 proxy = g_dbus_proxy_new_sync(g_conn,
2946 G_DBUS_PROXY_FLAGS_NONE, NULL,
2948 interface, NULL, &err);
2952 ERR("Unable to create proxy: %s", err->message);
2953 g_clear_error(&err);
2957 manager_gproxy = proxy;
2962 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2963 const gchar *path, const gchar *interface)
2965 return (manager_gproxy) ? manager_gproxy :
2966 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2970 static void __bt_register_application_to_dbus(int slot)
2972 GDBusProxy *proxy = NULL;
2973 char *app_path = NULL;
2975 DBG("RegisterApplication slot [%d]", slot);
2977 /* It is impossible that app path is still not initialized */
2978 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2980 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2981 "/org/bluez/hci0", "org.bluez.GattManager1");
2983 data = g_strdup(app_path);
2984 g_dbus_proxy_call(proxy,
2985 "RegisterApplication",
2986 g_variant_new("(oa{sv})",
2988 G_DBUS_CALL_FLAGS_NONE, -1,
2990 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2992 INFO("GATT server started");
2995 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2997 CHECK_BTGATT_INIT();
2998 struct gatt_service_info *serv_info = NULL;
2999 hal_gatt_service_started *user_data = NULL;
3000 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
3002 /* Fetch service data for the GATT server */
3003 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
3004 if (serv_info == NULL)
3005 return BT_STATUS_FAIL;
3007 if (serv_info->is_svc_registered)
3008 DBG("service already registered \n");
3010 serv_info->is_svc_registered = TRUE;
3012 /* Send Service handle to application */
3013 user_data = g_malloc0(sizeof(hal_gatt_service_started));
3014 user_data->srvc_hdl = serv_info->service_handle;
3015 user_data->instance_data = server_if;
3016 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
3018 /* If this is nth Service that is started, then register application at this point */
3019 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
3020 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
3022 __bt_register_application_to_dbus(server_if);
3025 return BT_STATUS_SUCCESS;
3028 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
3030 CHECK_BTGATT_INIT();
3031 INFO("Stop service successful");
3032 return BT_STATUS_SUCCESS;
3035 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
3037 CHECK_BTGATT_INIT();
3038 struct gatt_service_info *serv_info = NULL;
3039 hal_gatt_service_deleted *user_data = NULL;
3042 int err = BT_STATUS_SUCCESS;
3043 int ret = BT_STATUS_SUCCESS;
3044 char *app_path = NULL;
3045 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
3047 /* Fetch service data for the GATT server */
3048 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
3049 if (serv_info == NULL) {
3050 ERR("Could not find service info svc handle [%d] server slot [%d]",
3051 service_handle, server_if);
3052 return BT_STATUS_FAIL;
3055 app_path = __bt_get_server_app_path_from_server(server_if);
3056 if (app_path == NULL) {
3057 ERR("Could not find service info svc handle [%d] server slot [%d]",
3058 service_handle, server_if);
3059 return BT_STATUS_FAIL;
3062 if (serv_info->is_svc_registered == FALSE) {
3063 ERR("service Not registered path [%s] handle [%d]",
3064 serv_info->serv_path, service_handle);
3067 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
3068 struct gatt_char_info *char_info = l->data;
3070 if (char_info == NULL)
3073 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
3074 struct gatt_desc_info *desc_info = l1->data;
3076 if (desc_info == NULL)
3079 ret = g_dbus_connection_unregister_object(g_conn,
3080 desc_info->desc_id);
3082 __bt_hal_gatt_emit_interface_removed(
3084 desc_info->desc_path,
3085 GATT_DESC_INTERFACE);
3087 err = BT_STATUS_FAIL;
3090 /* list remove & free */
3091 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
3092 __bt_hal_free_gatt_handle(BT_GATT_TYPE_DESC, desc_info->desc_handle);
3093 __bt_hal_gatt_free_descriptor_info(desc_info);
3096 g_slist_free(char_info->desc_data);
3097 char_info->desc_data = NULL;
3099 ret = g_dbus_connection_unregister_object(g_conn,
3100 char_info->char_id);
3102 __bt_hal_gatt_emit_interface_removed(app_path, char_info->char_path,
3103 GATT_CHAR_INTERFACE);
3106 err = BT_STATUS_FAIL;
3109 /* list remove & free */
3110 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
3111 __bt_hal_free_gatt_handle(BT_GATT_TYPE_CHAR, char_info->char_handle);
3112 __bt_hal_gatt_free_characteristic_info(char_info);
3115 g_slist_free(serv_info->char_data);
3116 serv_info->char_data = NULL;
3118 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
3120 __bt_hal_gatt_emit_interface_removed(app_path, serv_info->serv_path,
3121 GATT_SERV_INTERFACE);
3124 err = BT_STATUS_FAIL;
3127 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
3129 DBG("Unregistered the service on properties interface");
3131 /* Remove from global list */
3132 gatt_services = g_slist_remove(gatt_services, serv_info);
3133 __bt_hal_free_gatt_handle(BT_GATT_TYPE_SERV, serv_info->service_handle);
3134 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
3136 /* Remove from GATT Server's list of services */
3137 _bt_remote_service_from_gatt_server(server_if, service_handle);
3139 if (gatt_services == NULL)
3140 INFO("All GATT Services of all GATT Servers are unregistered");
3142 if (err == BT_STATUS_SUCCESS) {
3143 INFO("Send GATT Service deleted Event");
3144 /* Send Service handle to application */
3145 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
3146 user_data->srvc_hdl = serv_info->service_handle;
3147 user_data->instance_data = server_if;
3148 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
3151 /* Free the service */
3152 __bt_hal_gatt_free_service_info(serv_info);
3156 static gboolean __bt_gatt_get_service_state(const char *service_path)
3158 struct gatt_service_info *svc_info = NULL;
3160 for (l = gatt_services; l; l = g_slist_next(l)) {
3162 svc_info = (struct gatt_service_info *)l->data;
3164 if (!g_strcmp0(svc_info->serv_path, service_path))
3165 return svc_info->is_svc_registered;
3168 DBG("gatt service info is NULL");
3172 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
3173 int len, int confirm, char* p_value)
3175 CHECK_BTGATT_INIT();
3178 GVariantBuilder *outer_builder;
3179 GVariantBuilder *invalidated_builder;
3181 /* For Value update via PropertyChange */
3182 GVariantBuilder *outer_builder1;
3183 GVariantBuilder *inner_builder1;
3184 GVariantBuilder *invalidated_builder1;
3185 GVariant *update_value = NULL;
3187 /* Other variables */
3188 struct gatt_client_info_t *conn_info = NULL;
3189 gchar *serv_path = NULL;
3190 char *char_path = NULL;
3191 gchar **line_argv = NULL;
3192 gboolean notify = TRUE;
3193 gboolean ret = TRUE;
3194 int err = BT_STATUS_SUCCESS;
3196 GError *error = NULL;
3199 memset(addr, 0x00, sizeof(addr));
3201 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3202 if (conn_info == NULL) {
3203 ERR("No Connection Inforamtion!!!");
3204 return BT_STATUS_FAIL;
3207 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
3209 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3210 if (char_path == NULL)
3211 return BT_STATUS_FAIL;
3213 line_argv = g_strsplit_set(char_path, "/", 0);
3214 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3216 if (!__bt_gatt_get_service_state(serv_path)) {
3217 DBG("service not registered for this characteristic \n");
3219 g_strfreev(line_argv);
3220 return BT_STATUS_FAIL;
3223 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3224 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3226 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
3227 g_variant_new("b", notify));
3229 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
3230 DBG("Send Indication to Unicast addr [%s]", addr);
3232 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
3233 g_variant_new("s", addr));
3235 DBG("Set characteristic Notification \n");
3236 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3238 "org.freedesktop.DBus.Properties",
3239 "PropertiesChanged",
3240 g_variant_new("(sa{sv}as)",
3241 "org.bluez.GattCharacteristic1",
3242 outer_builder, invalidated_builder),
3246 if (error != NULL) {
3247 ERR("D-Bus API failure: errCode[%x], \
3249 error->code, error->message);
3250 g_clear_error(&error);
3252 err = BT_STATUS_FAIL;
3255 g_variant_builder_unref(outer_builder);
3256 g_variant_builder_unref(invalidated_builder);
3259 /* Notifying Done, now update Value to Bluez via PropertyChanged */
3260 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
3262 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3263 for (i = 0; i < len; i++)
3264 g_variant_builder_add(inner_builder1, "y", p_value[i]);
3266 update_value = g_variant_new("ay", inner_builder1);
3269 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3270 g_variant_builder_add(outer_builder1, "{sv}", "Value",
3273 DBG("Updating characteristic value \n");
3274 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3276 "org.freedesktop.DBus.Properties",
3277 "PropertiesChanged",
3278 g_variant_new("(sa{sv}as)",
3279 "org.bluez.GattCharacteristic1",
3280 outer_builder1, invalidated_builder1),
3284 if (error != NULL) {
3285 ERR("D-Bus API failure: errCode[%x], \
3287 error->code, error->message);
3288 g_clear_error(&error);
3290 err = BT_STATUS_FAIL;
3292 struct gatt_char_info *char_info = NULL;
3294 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3295 if (char_info == NULL) {
3297 g_strfreev(line_argv);
3298 g_variant_builder_unref(inner_builder1);
3299 g_variant_builder_unref(outer_builder1);
3300 g_variant_builder_unref(invalidated_builder1);
3302 return BT_STATUS_FAIL;
3305 char_info->value_length = len;
3307 char_info->char_value = (char *)realloc(char_info->char_value, len);
3308 if (char_info->char_value) {
3309 for (i = 0; i < len; i++)
3310 char_info->char_value[i] = p_value[i];
3315 g_strfreev(line_argv);
3316 g_variant_builder_unref(inner_builder1);
3317 g_variant_builder_unref(outer_builder1);
3318 g_variant_builder_unref(invalidated_builder1);
3323 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3324 int status, btgatt_response_t *response)
3326 CHECK_BTGATT_INIT();
3328 struct gatt_req_info *req_info = NULL;
3329 struct gatt_client_info_t *conn_info = NULL;
3332 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3333 if (conn_info == NULL) {
3334 ERR("No Connection Inforamtion. conn_id %d", conn_id);
3335 return BT_STATUS_FAIL;
3338 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3339 if (req_info == NULL) {
3340 ERR("No Request Inforamtion. conn_id %d", conn_id);
3341 return BT_STATUS_FAIL;
3344 if (status != BT_STATUS_SUCCESS) {
3345 ERR("resp_state is 0x%X, conn_id %d", status, conn_id);
3347 g_dbus_method_invocation_return_dbus_error(req_info->context,
3348 "org.bluez.Error.Failed", "Application Error");
3350 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3352 req_info->context = NULL;
3353 if (req_info->attr_path)
3354 g_free(req_info->attr_path);
3355 if (req_info->svc_path)
3356 g_free(req_info->svc_path);
3359 return BT_STATUS_SUCCESS;
3362 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3363 GVariantBuilder *inner_builder = NULL;
3364 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3366 if (response->attr_value.len > 0) {
3367 for (i = 0; i < response->attr_value.len; i++)
3368 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3370 g_dbus_method_invocation_return_value(req_info->context,
3371 g_variant_new("(ay)", inner_builder));
3373 g_variant_builder_unref(inner_builder);
3375 g_dbus_method_invocation_return_value(req_info->context, NULL);
3377 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3379 req_info->context = NULL;
3380 if (req_info->attr_path)
3381 g_free(req_info->attr_path);
3382 if (req_info->svc_path)
3383 g_free(req_info->svc_path);
3386 return BT_STATUS_SUCCESS;
3390 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3391 int status, int fd, int mtu, void *fdlist)
3393 CHECK_BTGATT_INIT();
3395 struct gatt_req_info *req_info = NULL;
3396 struct gatt_client_info_t *conn_info = NULL;
3398 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3400 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3401 if (conn_info == NULL) {
3402 ERR("No Connection Inforamtion!!!");
3403 return BT_STATUS_FAIL;
3406 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3407 if (req_info == NULL) {
3408 ERR("No Request Inforamtion!!!");
3409 return BT_STATUS_FAIL;
3412 if (status != BT_STATUS_SUCCESS) {
3413 ERR("resp_state is 0x%X", status);
3415 g_dbus_method_invocation_return_dbus_error(req_info->context,
3416 "org.bluez.Error.Failed", "Application Error");
3418 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3420 req_info->context = NULL;
3421 if (req_info->attr_path)
3422 g_free(req_info->attr_path);
3423 if (req_info->svc_path)
3424 g_free(req_info->svc_path);
3427 return BT_STATUS_SUCCESS;
3431 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3433 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3434 g_dbus_method_invocation_return_value_with_unix_fd_list(
3435 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3437 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3439 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3440 g_dbus_method_invocation_return_value_with_unix_fd_list(
3441 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3444 g_dbus_method_invocation_return_value(req_info->context, NULL);
3446 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3448 req_info->context = NULL;
3449 if (req_info->attr_path)
3450 g_free(req_info->attr_path);
3451 if (req_info->svc_path)
3452 g_free(req_info->svc_path);
3455 return BT_STATUS_SUCCESS;
3459 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3460 int value_length, char* att_value)
3462 CHECK_BTGATT_INIT();
3464 /* Other variables */
3465 char *char_path = NULL;
3466 gboolean ret = TRUE;
3467 GError *error = NULL;
3469 GVariantBuilder *outer_builder;
3470 GVariantBuilder *inner_builder;
3471 GVariantBuilder *invalidated_builder;
3472 GVariant *update_value = NULL;
3473 int err = BT_STATUS_SUCCESS;
3475 gchar **line_argv = NULL;
3476 gchar *serv_path = NULL;
3478 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3479 if (char_path == NULL)
3480 return BT_STATUS_FAIL;
3482 line_argv = g_strsplit_set(char_path, "/", 0);
3483 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3485 if (!__bt_gatt_get_service_state(serv_path)) {
3486 DBG("service not registered for this characteristic \n");
3488 g_strfreev(line_argv);
3489 return BT_STATUS_FAIL;
3493 g_strfreev(line_argv);
3495 line_argv = g_strsplit_set(char_path, "/", 0);
3496 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3498 if (!__bt_gatt_get_service_state(serv_path)) {
3499 DBG("service not registered for this characteristic \n");
3501 g_strfreev(line_argv);
3502 return BT_STATUS_FAIL;
3505 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3506 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3508 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3509 for (i = 0; i < value_length; i++)
3510 g_variant_builder_add(inner_builder, "y", att_value[i]);
3512 update_value = g_variant_new("ay", inner_builder);
3514 g_variant_builder_add(outer_builder, "{sv}", "Value",
3517 DBG("Updating characteristic value \n");
3518 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3520 "org.freedesktop.DBus.Properties",
3521 "PropertiesChanged",
3522 g_variant_new("(sa{sv}as)",
3523 "org.bluez.GattCharacteristic1",
3524 outer_builder, invalidated_builder),
3528 if (error != NULL) {
3529 ERR("D-Bus API failure: errCode[%x], \
3531 error->code, error->message);
3532 g_clear_error(&error);
3534 err = BT_STATUS_FAIL;
3536 struct gatt_char_info *char_info = NULL;
3538 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3539 if (char_info == NULL) {
3541 g_strfreev(line_argv);
3542 g_variant_builder_unref(inner_builder);
3543 g_variant_builder_unref(outer_builder);
3544 g_variant_builder_unref(invalidated_builder);
3546 return BT_STATUS_FAIL;
3549 char_info->value_length = value_length;
3551 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3552 if (char_info->char_value) {
3553 for (i = 0; i < value_length; i++)
3554 char_info->char_value[i] = att_value[i];
3560 g_strfreev(line_argv);
3561 g_variant_builder_unref(inner_builder);
3562 g_variant_builder_unref(outer_builder);
3563 g_variant_builder_unref(invalidated_builder);
3568 static bt_status_t gatt_server_listen(int server_if, bool start)
3570 CHECK_BTGATT_INIT();
3572 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3574 DBG("server_if: [%d]", server_if);
3576 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3577 if (server_register_info == NULL) {
3578 DBG("gatt server is not registered");
3579 return BT_STATUS_FAIL;
3582 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3584 if (server_register_info->adv_slot_id < 0 ) {
3585 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3586 return BT_STATUS_FAIL;
3589 /* Send Data to LE Module */
3590 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, start, FALSE);
3593 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3594 bool include_txpower, int min_interval, int max_interval, int appearance,
3595 uint16_t manufacturer_len, char* manufacturer_data,
3596 uint16_t service_data_len, char* service_data,
3597 uint16_t service_uuid_len, char* service_uuid)
3599 CHECK_BTGATT_INIT();
3600 return BT_STATUS_SUCCESS;
3603 static int bt_hal_gatts_allocate_adv_slot(struct hal_gatts_server_register_info_t *server_register_info)
3605 int adv_slot_id = -1;
3607 /* allocate adv slot for gatt server if not assigned */
3608 if (server_register_info->adv_slot_id < 0 ) {
3609 adv_slot_id = _bt_hal_get_available_adv_slot_id(&server_register_info->app_uuid, TRUE);
3610 if (adv_slot_id < 0) {
3611 ERR("failed to get the adv_slot");
3615 server_register_info->adv_slot_id = adv_slot_id;
3618 DBG("gatt server:[%d] Assigned adv_slot [%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3623 int bt_hal_gatts_allocate_adv_slot_by_server_if(int server_if)
3625 CHECK_BTGATT_INIT();
3629 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3631 DBG("server_if: [%d]", server_if);
3633 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3634 if (server_register_info == NULL) {
3635 DBG("gatt server is not registered");
3639 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3641 if (server_register_info->adv_slot_id < 0 ) {
3642 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3644 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3646 DBG("failed to get adv_slot");
3651 return server_register_info->adv_slot_id;
3654 void bt_hal_gatts_release_adv_slot(int server_if)
3656 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3658 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3659 if (server_register_info == NULL) {
3660 ERR("failed to get server_register_info");
3664 if (server_register_info->adv_slot_id < 0) {
3665 ERR("adv_slot is not allocated");
3669 if(_bt_hal_is_advertising_in_slot(server_register_info->adv_slot_id) == FALSE) {
3670 DBG("advertising is disabled");
3671 _bt_hal_free_server_slot(server_register_info->adv_slot_id);
3672 server_register_info->adv_slot_id = -1;
3676 int bt_hal_gatts_get_adv_slot_id(int server_if)
3678 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3680 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3681 if (server_register_info == NULL) {
3682 DBG("failed to get server_register_info");
3686 return server_register_info->adv_slot_id;
3689 int bt_hal_gatts_get_server_if(int slot_id)
3691 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3693 server_register_info = bt_hal_gatts_find_server_register_info_by_slot_id(slot_id);
3694 if (server_register_info == NULL) {
3695 DBG("failed to get server_register_info");
3699 return server_register_info->server_if;
3702 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3704 CHECK_BTGATT_INIT();
3708 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3710 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3711 if (server_register_info == NULL) {
3712 ERR("gatt server is not registered");
3713 return BT_STATUS_FAIL;
3716 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3718 if (server_register_info->adv_slot_id < 0 ) {
3719 DBG("adv_slot is not assigned to server:[%d]", server_if);
3721 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3723 ERR("failed to get adv_slot");
3724 return BT_STATUS_FAIL;
3728 /* Send Enable Advertising request to LE Module */
3729 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, TRUE, TRUE);
3732 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3733 int chnl_map, int tx_power, int timeout_s)
3735 CHECK_BTGATT_INIT();
3737 /* Send Advertising parameters to LE Module */
3738 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3739 chnl_map, tx_power, timeout_s);
3742 static bt_status_t gatt_server_set_filter_policy(int filter_policy)
3744 CHECK_BTGATT_INIT();
3746 /* Send the Filter policy parameter to LE Module */
3747 _bt_hal_set_filter_policy_param(filter_policy);
3748 return BT_STATUS_SUCCESS;
3751 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3753 CHECK_BTGATT_INIT();
3755 /* Send Data to LE Module */
3756 return _bt_hal_set_advertising_data(adv_param_setup);
3759 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3761 CHECK_BTGATT_INIT();
3763 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3765 DBG("server_if: [%d]", server_if);
3767 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3768 if (server_register_info == NULL) {
3769 DBG("gatt server is not registered");
3770 return BT_STATUS_FAIL;
3773 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3775 if (server_register_info->adv_slot_id < 0 ) {
3776 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3777 return BT_STATUS_FAIL;
3780 /* Send Data to LE Module */
3781 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, FALSE, TRUE);
3784 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3786 CHECK_BTGATT_INIT();
3787 char *object_path = NULL;
3789 GDBusProxy *device_proxy;
3790 GError *error = NULL;
3792 GVariant *tmp_value;
3793 GDBusConnection *conn;
3794 GVariant *result = NULL;
3795 int ret = BT_STATUS_SUCCESS;
3796 struct gatt_client_info_t *conn_info = NULL;
3799 if (mtu_size == NULL)
3800 return BT_STATUS_PARM_INVALID;
3802 /* GDBUS Connection Info validate */
3803 conn = _bt_hal_get_system_gconn();
3805 ERR("Could not get System DBUS Connection");
3806 return BT_STATUS_FAIL;
3809 /* Connection Info validate */
3810 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3811 if (conn_info == NULL) {
3812 ERR("No Connection Inforamtion!!!");
3813 return BT_STATUS_FAIL;
3817 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3818 if (object_path == NULL)
3819 return BT_STATUS_FAIL;
3821 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3822 NULL, BT_HAL_BLUEZ_NAME, object_path,
3823 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3825 g_free(object_path);
3826 if (device_proxy == NULL)
3827 return BT_STATUS_FAIL;
3829 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3830 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3831 G_DBUS_CALL_FLAGS_NONE,
3835 if (result == NULL) {
3836 if (error != NULL) {
3837 ERR("Error occured in Proxy call [%s]\n", error->message);
3838 g_error_free(error);
3840 g_object_unref(device_proxy);
3841 return BT_STATUS_FAIL;
3844 g_variant_get(result , "(@a{sv})", &value);
3845 g_variant_unref(result);
3847 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3848 if (tmp_value == NULL) {
3849 g_object_unref(device_proxy);
3850 g_variant_unref(value);
3851 return BT_STATUS_FAIL;
3854 mtu = g_variant_get_uint16(tmp_value);
3856 DBG("ATT MTU : [%d]", mtu);
3858 g_variant_unref(tmp_value);
3859 g_variant_unref(value);
3860 g_object_unref(device_proxy);
3862 *mtu_size = (int) mtu;
3867 const btgatt_server_interface_t btgatt_server_interface = {
3868 .register_server = gatt_server_register_app,
3869 .unregister_server = gatt_server_unregister_app,
3870 .connect = gatt_server_open,
3871 .disconnect = gatt_server_close,
3872 .add_service = gatt_server_add_service,
3873 .add_included_service = gatt_server_add_included_service,
3874 .add_characteristic = gatt_server_add_characteristic,
3875 .add_descriptor = gatt_server_add_descriptor,
3876 .start_service = gatt_server_start_service,
3877 .stop_service = gatt_server_stop_service,
3878 .delete_service = gatt_server_delete_service,
3879 .send_indication = gatt_server_send_indication,
3880 .send_response = gatt_server_send_response,
3881 .update_att_value = gatt_server_update_att_value,
3882 .listen = gatt_server_listen,
3883 .set_adv_data = gatt_server_set_adv_data,
3884 .multi_adv_enable = gatt_server_multi_adv_enable,
3885 .multi_adv_update = gatt_server_multi_adv_update,
3886 .set_filter_policy = gatt_server_set_filter_policy,
3887 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3888 .multi_adv_disable = gatt_server_multi_adv_disable,
3889 .get_att_mtu = gatt_server_get_mtu_size,
3890 .send_response_acquire = gatt_server_send_acquire_response