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'>"
285 " <arg type='s' name='address' direction='in'/>"
287 " <method name='StopNotify'>"
288 " <arg type='s' name='address' direction='in'/>"
290 " <method name='IndicateConfirm'>"
291 " <arg type='s' name='address' direction='in'/>"
292 " <arg type='b' name='complete' direction='in'/>"
295 " <interface name='org.freedesktop.DBus.Properties'>"
296 " <property type='s' name='UUID' access='read'>"
298 " <property type='o' name='Service' access='read'>"
300 " <property type='ay' name='Value' access='readwrite'>"
302 " <property type='b' name='Notifying' access='read'>"
304 " <property type='as' name='Flags' access='read'>"
306 " <property type='s' name='Unicast' access='read'>"
308 " <property type='ao' name='Descriptors' access='read'>"
310 " <property type='b' name='WriteAcquired' access='read'>"
312 " <property type='b' name='NotifyAcquired' access='read'>"
317 /* Introspection data for the descriptor we are exporting */
318 static const gchar descriptor_introspection_xml[] =
320 " <interface name='org.bluez.GattDescriptor1'>"
321 " <method name='ReadValue'>"
322 " <arg type='s' name='address' direction='in'/>"
323 " <arg type='u' name='id' direction='in'/>"
324 " <arg type='q' name='offset' direction='in'/>"
325 " <arg type='ay' name='Value' direction='out'/>"
327 " <method name='WriteValue'>"
328 " <arg type='s' name='address' direction='in'/>"
329 " <arg type='u' name='id' direction='in'/>"
330 " <arg type='q' name='offset' direction='in'/>"
331 " <arg type='b' name='response_needed' direction='in'/>"
332 " <arg type='b' name='prep_authorize' direction='in'/>"
333 " <arg type='ay' name='value' direction='in'/>"
336 " <interface name='org.freedesktop.DBus.Properties'>"
337 " <property type='s' name='UUID' access='read'>"
339 " <property type='o' name='Characteristic' access='read'>"
341 " <property type='ay' name='Value' access='read'>"
343 " <property type='as' name='Flags' access='read'>"
349 static const gchar manager_introspection_xml[] =
351 " <interface name='org.freedesktop.DBus.ObjectManager'>"
352 " <method name='GetManagedObjects'>"
353 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
358 static void __bt_free_gatt_server_app(struct gatt_server_app *app)
360 g_free(app->app_path);
364 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
369 g_free(svc_info->serv_path);
370 g_free(svc_info->service_uuid);
374 void _bt_hal_gatt_server_init(void)
377 memset(instance_id_used, 0x00, sizeof(instance_id_used));
379 assigned_handle[BT_GATT_TYPE_SERV] = assigned_handle[BT_GATT_TYPE_CHAR] = assigned_handle[BT_GATT_TYPE_DESC] = -1;
380 memset(gatt_handle_used, 0x00, sizeof(gatt_handle_used));
382 g_slist_free_full(gatt_server_apps, (GDestroyNotify)__bt_free_gatt_server_app);
383 gatt_server_apps = NULL;
385 g_slist_free_full(gatt_services, (GDestroyNotify)__bt_hal_gatt_free_service_info);
386 gatt_services = NULL;
388 g_slist_free_full(hal_gatts_server_register_list, g_free);
389 hal_gatts_server_register_list = NULL;
392 static int __bt_hal_gatt_assign_id(void)
396 index = assigned_id + 1;
398 if (index >= BT_GATTS_MAX)
401 while (instance_id_used[index] == TRUE) {
402 if (index == assigned_id) {
403 /* No available ID */
404 ERR("All interface ID is used");
410 if (index >= BT_GATTS_MAX)
415 instance_id_used[index] = TRUE;
420 static void __bt_hal_gatt_delete_id(int instance_id)
422 if (instance_id >= BT_GATTS_MAX || instance_id < 0)
425 instance_id_used[instance_id] = FALSE;
428 static int __bt_hal_assign_gatt_handle(bt_gatt_type_e type)
432 index = assigned_handle[type] + 1;
434 if (index >= GATT_HANDLE_MAX_NUM)
437 while (gatt_handle_used[type][index] == TRUE) {
438 if (index == assigned_handle[type]) {
439 /* No available handle */
440 ERR("All handle is used");
446 if (index >= GATT_HANDLE_MAX_NUM)
450 assigned_handle[type] = index;
451 gatt_handle_used[type][index] = TRUE;
453 return assigned_handle[type] + gatt_handle_base[type];
456 static void __bt_hal_free_gatt_handle(bt_gatt_type_e type, int handle)
460 if (type >= BT_GATT_TYPE_MAX) {
465 index = handle - gatt_handle_base[type];
466 if (index < 0 || index >= GATT_HANDLE_MAX_NUM) {
467 ERR("Invalid handle: %d(type: %d)", handle, type);
471 gatt_handle_used[type][index] = FALSE;
474 static GSList *_bt_get_service_list_from_server(int instance)
477 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
478 INFO("Find App with slot [%d]", instance);
480 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
481 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
483 if (app->slot == instance) {
484 INFO("App slot [%d] Found, Number of services registered [%d]",
485 app->slot, g_slist_length(app->services));
486 return app->services;
492 static char *__bt_get_server_app_path_from_server(int instance)
495 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
496 INFO("Find App with slot [%d]", instance);
498 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
499 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
501 if (app->slot == instance) {
502 INFO("App slot [%d] Found, App path [%s]",
503 app->slot, app->app_path);
504 return app->app_path;
510 static void _bt_remote_service_from_gatt_server(int instance, int service_handle)
515 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
516 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
518 if (app->slot == instance) {
519 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
520 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
521 if (srv->service_handle == service_handle) {
522 app->services = g_slist_remove(app->services, srv);
530 static void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
533 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
534 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
536 if (app->slot == slot) {
537 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
538 serv_info->service_handle, slot);
539 app->services = g_slist_append(app->services, serv_info);
544 int _bt_get_remote_gatt_client_conn_id(char *address)
547 struct gatt_client_info_t *info = NULL;
549 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
550 info = (struct gatt_client_info_t*)l->data;
554 if (!g_strcmp0(info->addr, address)) {
555 INFO("Remote GATT client found addr[%s]", info->addr);
556 return info->connection_id;
562 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
565 struct gatt_client_info_t *info = NULL;
567 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
568 info = (struct gatt_client_info_t*)l->data;
572 if (!g_strcmp0(info->addr, address))
578 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
581 struct gatt_client_info_t *info = NULL;
583 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
584 info = (struct gatt_client_info_t*)l->data;
588 if (info->connection_id == conn_id)
594 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
599 struct gatt_client_info_t *info = NULL;
600 struct gatt_req_info *info1 = NULL;
602 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
603 info = (struct gatt_client_info_t*)l->data;
607 if (info->connection_id == conn_id) {
609 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
611 info1 = (struct gatt_req_info*)l1->data;
615 if (info1->request_id == trans_id)
623 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
625 struct hal_ev_gatt_server_connected ev;
626 struct gatt_client_info_t *conn_info = NULL;
627 memset(&ev, 0, sizeof(ev));
629 /* Convert address to hex */
630 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
632 /* Create Connection ID */
633 /* Check if device is already in connected list */
634 conn_info = __bt_find_remote_gatt_client_info(address);
636 /* If disconnected, and conn info found, then remove conn info */
637 if (is_connected == FALSE) {
638 DBG("GATT Disconnected");
640 INFO("Remove GATT client info from List..");
641 /* Remove info from List */
642 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
643 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
646 ERR("GATT callback not registered");
648 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
649 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
650 ev.conn_id = conn_info->connection_id;
651 ev.server_instance = conn_info->instance_id;
652 ev.connected = is_connected;
654 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
656 g_free(conn_info->addr);
659 /* If connected, and conn info NOT found, then add conn info */
663 /* Find Server Instance */
664 instance = bt_hal_gatts_get_gatt_server_instance();
665 if (instance == -1) {
666 ERR("Not even a single GATT server is registered");
667 ev.conn_id = ++hal_gatt_conn_id;
668 ev.server_instance = -1;
669 ev.connected = is_connected;
670 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
673 DBG("server instance [%d]", instance);
676 /* Save Connection info */
677 conn_info = g_new0(struct gatt_client_info_t, 1);
678 conn_info->addr = g_strdup(address);
679 DBG("Added GATT client addr[%s]", conn_info->addr);
680 conn_info->connection_id = ++hal_gatt_conn_id;
681 conn_info->instance_id = instance;
682 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
683 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
686 ERR("GATT callback not registered");
688 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
689 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
690 ev.conn_id = conn_info->connection_id;
691 ev.server_instance = conn_info->instance_id;
692 ev.connected = is_connected;
694 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
697 ERR("Abnormal case. conn_info should be NULL");
700 /* Send GATT connected or disconnected event */
703 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
707 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
708 struct gatt_service_info *serv_info = l1->data;
710 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
711 struct gatt_char_info *char_info = l2->data;
713 if (g_strcmp0(char_info->char_path, char_path)
715 *char_hdl = char_info->char_handle;
720 ERR("Gatt service not found");
724 static char *__bt_gatt_find_char_path_from_handle(int char_hdl)
728 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
729 struct gatt_service_info *serv_info = l1->data;
731 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
732 struct gatt_char_info *char_info = l2->data;
734 if (char_info->char_handle == char_hdl)
735 return char_info->char_path;
742 static struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
746 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
747 struct gatt_service_info *serv_info = l1->data;
749 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
750 struct gatt_char_info *char_info = l2->data;
752 if (char_info->char_handle == char_hdl)
760 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
762 GSList *l1, *l2, *l3;
764 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
765 struct gatt_service_info *serv_info = l1->data;
767 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
768 struct gatt_char_info *char_info = l2->data;
770 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
771 struct gatt_desc_info *desc_info = l3->data;
773 if (g_strcmp0(desc_info->desc_path, desc_path)
775 *desc_hdl = desc_info->desc_handle;
781 ERR("Gatt service not found");
785 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
787 const gchar *object_path,
788 const gchar *interface_name,
789 const gchar *method_name,
790 GVariant *parameters,
791 GDBusMethodInvocation *invocation,
796 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
797 GVariantBuilder *builder;
798 GVariantBuilder *inner_builder1 = NULL;
799 GVariant *svc_char = NULL;
801 GSList *gatt_services = NULL;
803 instance = (int*)user_data;
804 gboolean writeAcquired = FALSE;
805 gboolean notifyAcquired = FALSE;
807 DBG("Getting values for service, chars and descriptors");
808 DBG("GATT Server App for which services are requested [%d]", *instance);
811 builder = g_variant_builder_new(
812 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
815 gatt_services = _bt_get_service_list_from_server(*instance);
817 if (g_slist_length(gatt_services) == 0) {
818 ERR("No registered GATT services!!!!");
819 g_dbus_method_invocation_return_value(invocation, NULL);
820 g_variant_builder_unref(builder);
824 for (l = gatt_services; l != NULL; l = l->next) {
825 GVariantBuilder *svc_builder = NULL;
826 GVariantBuilder *inner_builder = NULL;
827 struct gatt_service_info *serv_info = l->data;
828 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
830 /* Prepare inner builder for GattService1 interface */
831 DBG("Creating builder for service");
832 svc_builder = g_variant_builder_new(
833 G_VARIANT_TYPE("a{sa{sv}}"));
834 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
836 g_variant_builder_add(inner_builder, "{sv}", "UUID",
837 g_variant_new_string(serv_info->service_uuid));
839 g_variant_builder_add(inner_builder, "{sv}", "Primary",
840 g_variant_new_boolean(serv_info->is_svc_primary));
843 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
844 DBG("Adding Charatarisitcs list");
845 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
846 struct gatt_char_info *char_info = l4->data;
847 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
848 char_info->char_handle, serv_info->service_handle);
849 g_variant_builder_add(inner_builder1, "o",
850 char_info->char_path);
851 DBG("%s", char_info->char_path);
854 svc_char = g_variant_new("ao", inner_builder1);
855 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
858 g_variant_builder_add(svc_builder, "{sa{sv}}",
862 g_variant_builder_add(builder, "{oa{sa{sv}}}",
863 serv_info->serv_path,
866 g_variant_builder_unref(inner_builder1);
868 /* Prepare inner builder for GattCharacteristic1 interface */
870 GSList *l2 = serv_info->char_data;
871 DBG("Creating builder for characteristics \n");
874 DBG("characteristic data is NULL");
876 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
878 GVariantBuilder *char_builder = NULL;
879 GVariantBuilder *inner_builder = NULL;
880 GVariantBuilder *builder1 = NULL;
881 GVariantBuilder *builder2 = NULL;
882 GVariantBuilder *builder3 = NULL;
883 GVariant *char_val = NULL;
884 GVariant *flags_val = NULL;
885 GVariant *char_desc = NULL;
886 char *unicast = NULL;
887 gboolean notify = FALSE;
890 char_builder = g_variant_builder_new(
893 inner_builder = g_variant_builder_new(
897 struct gatt_char_info *char_info = l2->data;
898 if (char_info == NULL) {
899 ERR("char_info is NULL");
904 g_variant_builder_add(inner_builder, "{sv}", "UUID",
905 g_variant_new_string(char_info->char_uuid));
907 g_variant_builder_add(inner_builder, "{sv}", "Service",
908 g_variant_new("o", serv_info->serv_path));
910 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
912 if (char_info->char_value != NULL) {
913 for (i = 0; i < char_info->value_length; i++) {
914 g_variant_builder_add(builder1, "y",
915 char_info->char_value[i]);
917 char_val = g_variant_new("ay", builder1);
918 g_variant_builder_add(inner_builder, "{sv}",
922 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
923 for (i = 0; i < char_info->flags_length; i++) {
924 g_variant_builder_add(builder2, "s",
925 char_info->char_flags[i]);
927 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
928 DBG("setting WriteAcquired property");
929 writeAcquired = TRUE;
932 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
933 DBG("setting NotifyAcquired property");
934 notifyAcquired = TRUE;
938 flags_val = g_variant_new("as", builder2);
939 g_variant_builder_add(inner_builder, "{sv}", "Flags",
943 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
944 g_variant_new("b", notify));
947 if (writeAcquired == TRUE) {
948 DBG("adding WriteAcquired property");
949 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
950 g_variant_new("b", writeAcquired));
954 if (notifyAcquired == TRUE) {
955 DBG("adding NotifyAcquired property");
956 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
957 g_variant_new("b", notifyAcquired));
961 unicast = g_strdup("00:00:00:00:00:00");
962 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
963 g_variant_new("s", unicast));
966 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
967 DBG("Adding Descriptors list");
969 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
970 struct gatt_desc_info *desc_info = l4->data;
971 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
972 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
973 g_variant_builder_add(builder3, "o",
974 desc_info->desc_path);
975 DBG("%s", desc_info->desc_path);
978 char_desc = g_variant_new("ao", builder3);
979 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
982 g_variant_builder_add(char_builder, "{sa{sv}}",
983 GATT_CHAR_INTERFACE , inner_builder);
984 g_variant_builder_add(builder, "{oa{sa{sv}}}",
985 char_info->char_path, char_builder);
987 /*Prepare inner builder for GattDescriptor1 interface*/
989 GSList *l3 = char_info->desc_data;
992 DBG("descriptor data is NULL");
994 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
996 DBG("Creating builder for descriptor \n");
998 GVariantBuilder *desc_builder = NULL;
999 GVariantBuilder *inner_builder = NULL;
1000 GVariantBuilder *builder1 = NULL;
1001 GVariantBuilder *builder2 = NULL;
1002 GVariant *desc_val = NULL;
1004 desc_builder = g_variant_builder_new(
1007 inner_builder = g_variant_builder_new(
1011 struct gatt_desc_info *desc_info = l3->data;
1012 if (desc_info == NULL) {
1013 ERR("desc_info is NULL");
1018 g_variant_builder_add(inner_builder,
1020 g_variant_new_string(
1021 desc_info->desc_uuid));
1024 g_variant_builder_add(inner_builder, "{sv}",
1027 char_info->char_path));
1030 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1032 if (desc_info->desc_value != NULL) {
1033 for (i = 0; i < desc_info->value_length; i++) {
1034 g_variant_builder_add(builder1, "y",
1035 desc_info->desc_value[i]);
1037 desc_val = g_variant_new("ay", builder1);
1038 g_variant_builder_add(inner_builder, "{sv}",
1043 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
1045 for (i = 0; i < desc_info->flags_length; i++) {
1046 g_variant_builder_add(builder2, "s",
1047 desc_info->desc_flags[i]);
1050 flags_val = g_variant_new("as", builder2);
1051 g_variant_builder_add(inner_builder, "{sv}", "Flags",
1054 g_variant_builder_add(desc_builder, "{sa{sv}}",
1055 GATT_DESC_INTERFACE,
1058 g_variant_builder_add(builder, "{oa{sa{sv}}}",
1059 desc_info->desc_path,
1062 /*unref descriptor builder pointers*/
1063 g_variant_builder_unref(builder1);
1064 g_variant_builder_unref(builder2);
1065 g_variant_builder_unref(inner_builder);
1066 g_variant_builder_unref(desc_builder);
1071 /*unref char builder pointers*/
1072 g_variant_builder_unref(builder1);
1073 g_variant_builder_unref(builder2);
1074 g_variant_builder_unref(builder3);
1075 g_variant_builder_unref(inner_builder);
1076 g_variant_builder_unref(char_builder);
1079 /*unref service builder pointers*/
1080 g_variant_builder_unref(inner_builder);
1081 g_variant_builder_unref(svc_builder);
1084 /* Return builder as method reply */
1085 DBG("Sending gatt service builder values to Bluez");
1086 g_dbus_method_invocation_return_value(invocation,
1092 /* Free User Data */
1096 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1097 const gchar *sender,
1098 const gchar *object_path,
1099 const gchar *interface_name,
1100 const gchar *method_name,
1101 GVariant *parameters,
1102 GDBusMethodInvocation *invocation,
1106 if (g_strcmp0(method_name, "ReadValue") == 0) {
1107 struct hal_ev_gatt_server_read_req ev;
1112 struct gatt_client_info_t *conn_info = NULL;
1113 struct gatt_req_info *req_info = NULL;
1114 struct gatt_service_info *svc_info = NULL;
1118 DBG("Application path = %s", object_path);
1119 DBG("Sender = %s", sender);
1121 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1122 if (svc_info == NULL) {
1123 ERR("Coudn't find service for %s", object_path);
1124 g_dbus_method_invocation_return_value(invocation, NULL);
1128 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1129 DBG("Request id = %u, Offset = %u", req_id, offset);
1131 /* Check if device is already in connected list */
1132 conn_info = __bt_find_remote_gatt_client_info(addr);
1134 if (conn_info == NULL) {
1135 ERR("Coudn't find Connection info for %s", addr);
1136 g_dbus_method_invocation_return_value(invocation, NULL);
1141 ERR("GATT callback NOT registered");
1142 g_dbus_method_invocation_return_value(invocation, NULL);
1146 /* Store requests information */
1147 req_info = g_new0(struct gatt_req_info, 1);
1148 req_info->attr_path = g_strdup(object_path);
1149 req_info->svc_path = g_strdup(svc_info->serv_path);
1150 req_info->request_id = req_id;
1151 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1152 req_info->offset = offset;
1153 req_info->context = invocation;
1155 /* Append request info in list of requests for the particular connection */
1156 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1158 /* Send HAL event */
1159 memset(&ev, 0, sizeof(ev));
1160 ev.conn_id = conn_info->connection_id;
1161 ev.trans_id = req_id;
1162 ev.att_handle = desc_hdl;
1164 ev.is_long = false; /* TODO*/
1166 /* Convert address to hex */
1167 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1169 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1171 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1173 GVariant *var = NULL;
1177 gboolean response_needed = FALSE;
1178 gboolean prep_authorize = FALSE;
1179 struct hal_ev_gatt_server_write_req ev;
1183 struct gatt_service_info *svc_info = NULL;
1184 struct gatt_client_info_t *conn_info = NULL;
1185 struct gatt_req_info *req_info = NULL;
1187 memset(&ev, 0, sizeof(ev));
1190 DBG("Application path = %s", object_path);
1191 DBG("Sender = %s", sender);
1193 g_variant_get(parameters, "(&suqbb@ay)",
1194 &addr, &req_id, &offset, &response_needed, &prep_authorize, &var);
1195 DBG("Request id = %u, Offset = %u", req_id, offset);
1198 DBG("prep_authorize = true");
1200 /* Check if device is already in connected list */
1201 conn_info = __bt_find_remote_gatt_client_info(addr);
1203 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1205 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1206 g_variant_unref(var);
1207 g_dbus_method_invocation_return_value(invocation, NULL);
1211 len = g_variant_get_size(var);
1212 if (len > 0 && len < 600) {
1214 data = (char *)g_variant_get_data(var);
1215 memcpy(ev.value, data, len);
1218 if (response_needed) {
1219 /* Store request information */
1220 req_info = g_new0(struct gatt_req_info, 1);
1221 req_info->attr_path = g_strdup(object_path);
1222 req_info->svc_path = g_strdup(svc_info->serv_path);
1223 req_info->request_id = req_id;
1224 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1225 req_info->offset = offset;
1226 req_info->context = invocation;
1228 /* Append request info in list of requests for the particular connection */
1229 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1231 /* Send reply now */
1232 g_dbus_method_invocation_return_value(invocation, NULL);
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 g_dbus_method_invocation_return_value(invocation, NULL);
1356 len = g_variant_get_size(var);
1357 if (len > 0 && len < 600) {
1359 data = (char *)g_variant_get_data(var);
1360 memcpy(ev.value, data, len);
1364 if (response_needed) {
1365 /* Store requets information */
1366 req_info = g_new0(struct gatt_req_info, 1);
1367 req_info->attr_path = g_strdup(object_path);
1368 req_info->svc_path = g_strdup(svc_info->serv_path);
1369 req_info->request_id = req_id;
1370 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1371 req_info->offset = offset;
1372 req_info->context = invocation;
1374 /* Append request info in list of requests for the particular connection */
1375 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1378 /* Send reply now */
1379 g_dbus_method_invocation_return_value(invocation, NULL);
1382 /* Send HAL event */
1383 ev.conn_id = conn_info->connection_id;
1384 ev.trans_id = req_id;
1385 ev.att_handle = char_hdl;
1387 ev.need_rsp = response_needed;
1390 /* Convert address to hex */
1391 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1393 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1395 g_variant_unref(var);
1398 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1401 struct gatt_service_info *svc_info = NULL;
1402 struct gatt_client_info_t *conn_info = NULL;
1403 struct hal_ev_gatt_server_notifcation_change ev;
1407 g_variant_get(parameters, "(&s)", &addr);
1408 INFO("Remote address %s", addr);
1410 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1412 conn_info = __bt_find_remote_gatt_client_info(addr);
1414 if (svc_info == NULL || conn_info == NULL
1415 || event_cb == NULL)
1418 /* Send HAL event */
1419 memset(&ev, 0, sizeof(ev));
1420 ev.conn_id = conn_info->connection_id;
1421 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1422 ev.att_handle = char_hdl;
1425 /* Convert address to hex */
1426 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1428 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1431 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1434 struct gatt_service_info *svc_info = NULL;
1435 struct gatt_client_info_t *conn_info = NULL;
1436 struct hal_ev_gatt_server_notifcation_change ev;
1440 g_variant_get(parameters, "(&s)", &addr);
1441 INFO("Remote address %s", addr);
1443 conn_info = __bt_find_remote_gatt_client_info(addr);
1445 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1446 if (svc_info == NULL || conn_info == NULL
1447 || event_cb == NULL)
1450 /* Send HAL event */
1451 memset(&ev, 0, sizeof(ev));
1452 ev.conn_id = conn_info->connection_id;
1453 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1454 ev.att_handle = char_hdl;
1457 /* Convert address to hex */
1458 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1460 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1463 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1465 gboolean complete = FALSE;
1468 struct gatt_service_info *svc_info = NULL;
1469 struct gatt_client_info_t *conn_info = NULL;
1471 struct hal_ev_gatt_server_indicate_cfm ev;
1473 DBG("IndicateConfirm : Application path %s, sender %s", object_path, sender);
1475 g_variant_get(parameters, "(&sb)", &addr, &complete);
1476 DBG("Remote Device address number = %s", addr);
1477 DBG("Is Indicate confirmation for last device [%d]", complete);
1479 /* Check if device is already in connected list */
1480 conn_info = __bt_find_remote_gatt_client_info(addr);
1482 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1484 if (svc_info == NULL || conn_info == NULL
1485 || event_cb == NULL) {
1489 /* Send HAL event */
1490 memset(&ev, 0, sizeof(ev));
1491 ev.conn_id = conn_info->connection_id;
1492 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1493 ev.att_handle = char_hdl;
1495 /* Convert address to hex */
1496 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1498 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1499 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1503 struct hal_ev_gatt_server_acquire_write_res ev;
1504 struct gatt_service_info *svc_info = NULL;
1505 struct gatt_req_info *req_info = NULL;
1506 struct gatt_client_info_t *conn_info = NULL;
1507 char *dev_path = NULL;
1509 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1511 DBG("AcquireWrite : Application path %s, sender %s", object_path, sender);
1514 g_variant_get(parameters, "(a{sv})", &iter);
1516 GVariant *value = NULL;
1517 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1518 if (g_strcmp0(key, "MTU") == 0)
1519 g_variant_get(value, "q", &mtu);
1520 else if (g_strcmp0(key, "link") == 0)
1521 g_variant_get(value, "s", &link);
1522 else if (g_strcmp0(key, "device") == 0)
1523 g_variant_get(value, "o", &dev_path);
1526 DBG(" path %s LINK = %s, MTU = %u", dev_path, link, mtu);
1528 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1530 _bt_hal_convert_device_path_to_address(dev_path, addr);
1532 DBG("remote address %s", addr);
1536 /* Check if device is already in connected list */
1537 conn_info = __bt_find_remote_gatt_client_info(addr);
1538 if (conn_info == NULL) {
1539 ERR("Cleint info not found\n");
1540 g_variant_iter_free(iter);
1544 if (svc_info == NULL) {
1545 ERR("svc_info info not found\n");
1546 g_variant_iter_free(iter);
1550 /* Store requets information */
1551 req_info = g_new0(struct gatt_req_info, 1);
1552 req_info->attr_path = g_strdup(object_path);
1553 req_info->svc_path = g_strdup(svc_info->serv_path);
1554 req_info->request_id = conn_info->connection_id;
1555 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1556 req_info->offset = mtu;
1557 req_info->context = invocation;
1559 /* Append request info in list of requests for the particular connection */
1560 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1562 /* Send HAL event */
1563 memset(&ev, 0, sizeof(ev));
1564 ev.conn_id = conn_info->connection_id;
1565 ev.char_handl = char_hdl;
1567 ev.trans_id = conn_info->connection_id;
1568 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1569 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1570 g_variant_iter_free(iter);
1572 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1576 char *dev_path = NULL;
1578 struct hal_ev_gatt_server_acquire_notify ev;
1579 struct gatt_service_info *svc_info = NULL;
1580 struct gatt_client_info_t *conn_info = NULL;
1581 struct gatt_req_info *req_info = NULL;
1582 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1584 INFO("AcquireNotify : Application path %s, sender %s", object_path, sender);
1587 g_variant_get(parameters, "(a{sv})", &iter);
1589 GVariant* value = NULL;
1590 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1591 if (g_strcmp0(key, "MTU") == 0)
1592 g_variant_get(value, "q", &mtu);
1593 else if (g_strcmp0(key, "link") == 0)
1594 g_variant_get(value, "s", &link);
1595 else if (g_strcmp0(key, "device") == 0)
1596 g_variant_get(value, "o", &dev_path);
1599 DBG("MTU = %u", mtu);
1600 INFO("Dev Path %s LINK = %s, MTU = %u", dev_path, link, mtu);
1601 _bt_hal_convert_device_path_to_address(dev_path, addr);
1602 INFO("Remote address %s", addr);
1606 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1608 /* Check if device is already in connected list */
1609 conn_info = __bt_find_remote_gatt_client_info(addr);
1610 if (conn_info == NULL) {
1611 ERR("Client info not found\n");
1612 g_variant_iter_free(iter);
1615 if (svc_info == NULL) {
1616 ERR("svc_info info not found\n");
1617 g_variant_iter_free(iter);
1621 /* Store requets information */
1622 req_info = g_new0(struct gatt_req_info, 1);
1623 req_info->attr_path = g_strdup(object_path);
1624 req_info->svc_path = g_strdup(svc_info->serv_path);
1625 req_info->request_id = -1;
1626 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1627 req_info->offset = mtu;
1628 req_info->context = invocation;
1630 INFO("AcquireNotify : Added GATT client path[%s]", conn_info->addr);
1631 /* Append request info in list of requests for the particular connection */
1632 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1634 /* Send HAL event */
1635 memset(&ev, 0, sizeof(ev));
1636 ev.conn_id = conn_info->connection_id;
1637 ev.char_handl = char_hdl;
1639 ev.trans_id = req_info->request_id;
1640 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1642 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1643 g_variant_iter_free(iter);
1648 g_dbus_method_invocation_return_value(invocation, NULL);
1651 static gboolean __bt_hal_gatt_emit_interface_removed(const char *app_path, gchar *object_path, gchar *interface)
1654 GError *error = NULL;
1655 GVariantBuilder *array_builder;
1657 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1658 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1659 g_variant_builder_add(array_builder, "s", interface);
1661 ret = g_dbus_connection_emit_signal(g_conn, NULL, app_path,
1662 "org.freedesktop.DBus.ObjectManager",
1663 "InterfacesRemoved",
1664 g_variant_new("(oas)",
1665 object_path, array_builder),
1669 if (error != NULL) {
1670 /* dbus gives error cause */
1671 ERR("d-bus api failure: errcode[%x], message[%s]",
1672 error->code, error->message);
1673 g_clear_error(&error);
1676 g_variant_builder_unref(array_builder);
1681 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1688 g_free(desc_info->desc_path);
1689 g_free(desc_info->desc_uuid);
1690 g_free(desc_info->desc_value);
1692 for (i = 0; i < desc_info->flags_length; i++)
1693 g_free(desc_info->desc_flags[i]);
1698 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1705 g_free(char_info->char_path);
1706 g_free(char_info->char_uuid);
1707 g_free(char_info->char_value);
1709 for (i = 0; i < char_info->flags_length; i++)
1710 g_free(char_info->char_flags[i]);
1715 static const GDBusInterfaceVTable desc_interface_vtable = {
1716 __bt_gatt_desc_method_call,
1721 static const GDBusInterfaceVTable char_interface_vtable = {
1722 __bt_gatt_char_method_call,
1727 static const GDBusInterfaceVTable serv_interface_vtable = {
1733 static const GDBusInterfaceVTable manager_interface_vtable = {
1734 __bt_gatt_manager_method_call,
1740 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1741 const gchar *introspection_data)
1744 GDBusNodeInfo *node_info = NULL;
1746 if (introspection_data == NULL)
1750 DBG("Create new node info");
1751 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1754 ERR("Unable to create node: %s", err->message);
1755 g_clear_error(&err);
1762 /* To send stack event to hal-av handler */
1763 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1768 void _bt_hal_unregister_gatt_server_handler_cb(void)
1773 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1775 struct hal_ev_gatt_desc_added ev;
1776 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1778 /* Prepare to GATT characteristic added event */
1779 memset(&ev, 0, sizeof(ev));
1780 ev.status = BT_STATUS_SUCCESS;
1781 ev.server_instance = data->instance_data;
1782 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1783 ev.service_handle = data->srvc_hdl;
1784 ev.desc_handle = data->desc_hdl;
1787 ERR("GATT Descriptor Added callback registered");
1789 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1790 data->instance_data, data->srvc_hdl, data->desc_hdl);
1792 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1799 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1801 struct hal_ev_gatt_char_added ev;
1802 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1804 /* Prepare to GATT characteristic added event */
1805 memset(&ev, 0, sizeof(ev));
1806 ev.status = BT_STATUS_SUCCESS;
1807 ev.server_instance = data->instance_data;
1808 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1809 ev.service_handle = data->srvc_hdl;
1810 ev.char_handle = data->char_hdl;
1813 ERR("GATT Characteristic Added callback registered");
1815 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1816 data->instance_data, data->srvc_hdl, data->char_hdl);
1818 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1825 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1827 struct hal_ev_gatt_service_added ev;
1828 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1830 /* Prepare to GATT Service added event */
1831 memset(&ev, 0, sizeof(ev));
1832 ev.status = BT_STATUS_SUCCESS;
1833 ev.server_instance = data->instance_data;
1834 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1835 ev.service_handle = data->srvc_hdl;
1836 ev.is_primary = data->is_primary;
1839 ERR("GATT Service Added callback registered");
1841 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1842 data->instance_data, data->srvc_hdl);
1843 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1850 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1852 struct hal_ev_gatt_service_started ev;
1853 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1855 /* Prepare to GATT Service added event */
1856 memset(&ev, 0, sizeof(ev));
1857 ev.status = BT_STATUS_SUCCESS;
1858 ev.server_instance = data->instance_data;
1859 ev.service_handle = data->srvc_hdl;
1862 ERR("GATT Service Started callback registered");
1864 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1865 data->instance_data, data->srvc_hdl);
1866 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1873 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1875 struct hal_ev_gatt_service_deleted ev;
1876 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1878 /* Prepare to GATT Service added event */
1879 memset(&ev, 0, sizeof(ev));
1880 ev.status = BT_STATUS_SUCCESS;
1881 ev.server_instance = data->instance_data;
1882 ev.service_handle = data->srvc_hdl;
1885 ERR("GATT Service Deleted callback registered");
1887 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1888 data->instance_data, data->srvc_hdl);
1889 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1896 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1898 struct hal_ev_server_instance_registered ev;
1899 hal_register_server_data *data = (hal_register_server_data*) user_data;
1901 /* Prepare to send AV connecting event */
1902 memset(&ev, 0, sizeof(ev));
1903 ev.status = BT_STATUS_SUCCESS;
1904 ev.server_instance = data->instance_data;
1905 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1908 ERR("GATT Register Server Instance Callback not registered");
1910 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1911 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1919 static int bt_hal_gatts_get_gatt_server_instance()
1924 struct hal_gatts_server_register_info_t *info = NULL;
1926 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1927 info = (struct hal_gatts_server_register_info_t *)l->data;
1932 return info->server_if;
1938 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_from_uuid(bt_uuid_t *app_uuid)
1943 struct hal_gatts_server_register_info_t *info = NULL;
1945 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1946 info = (struct hal_gatts_server_register_info_t *)l->data;
1951 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
1952 DBG("gatt server register found");
1960 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info(int server_if)
1963 struct hal_gatts_server_register_info_t *info = NULL;
1965 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1966 info = (struct hal_gatts_server_register_info_t *)l->data;
1971 if (info->server_if == server_if) {
1979 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_by_slot_id(int adv_slot_id)
1984 struct hal_gatts_server_register_info_t *info = NULL;
1986 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1987 info = (struct hal_gatts_server_register_info_t *)l->data;
1992 if (info->adv_slot_id == adv_slot_id) {
1993 DBG("gatt server register found");
2001 static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_uuid_t *app_uuid)
2003 struct hal_gatts_server_register_info_t * server_register_info = NULL;
2004 int instance_id = 0;
2006 server_register_info = bt_hal_gatts_find_server_register_info_from_uuid(app_uuid);
2007 if (server_register_info != NULL) {
2008 DBG("gatt server is already registered");
2009 return server_register_info;
2012 instance_id = __bt_hal_gatt_assign_id();
2013 if (instance_id == -1) {
2014 ERR("Fail to allocate the server if");
2018 server_register_info = g_malloc0(sizeof(struct hal_gatts_server_register_info_t));
2019 server_register_info->server_if = instance_id;
2021 DBG("Adding the gatt server app. server_if:[%d]", server_register_info->server_if);
2023 server_register_info->adv_slot_id = -1;
2024 memcpy(&server_register_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
2025 hal_gatts_server_register_list = g_slist_append(hal_gatts_server_register_list, server_register_info);
2027 return server_register_info;
2030 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
2032 CHECK_BTGATT_INIT();
2033 struct hal_gatts_server_register_info_t *server_register_info = NULL;
2035 DBG("Register server instance request");
2036 server_register_info = bt_hal_gatts_add_server_app(uuid);
2037 if (server_register_info == NULL) {
2038 ERR("Fail to register the server app");
2039 return BT_STATUS_FAIL;
2042 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
2043 user_data->instance_data = server_register_info->server_if;
2046 * As we need to provide async callback to user from HAL, simply schedule a
2047 * callback method which will carry actual result
2049 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
2050 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
2052 /* If available, then return success, else return error */
2053 return BT_STATUS_SUCCESS;
2056 static void _bt_hal_remove_gatt_server_from_list(int server_if)
2059 struct gatt_server_app *info = NULL;
2061 for (l = gatt_server_apps; l != NULL;) {
2062 info = (struct gatt_server_app*)l->data;
2063 l = g_slist_next(l);
2066 if (info->slot == server_if) {
2067 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
2068 info->app_path, info->slot);
2070 /* Only if all services are deleted from the GATT Server, then only Unregister it.
2071 Reason: it is possible, GATT Server app oly wants to disable multi advertising
2072 In above case, only advertising block will be deallocated, Gatt Server will remain
2074 if (info->services == NULL) {
2075 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
2076 INFO("Total gatt server apps still existing after removing above is [%d]",
2077 g_slist_length(gatt_server_apps));
2079 /* DBUS Unregister only for current app */
2080 __bt_hal_gatt_deinit(info->app_path);
2082 g_free(info->app_path);
2086 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
2087 g_slist_length(info->services));
2093 static bt_status_t gatt_server_unregister_app(int server_if)
2095 CHECK_BTGATT_INIT();
2096 DBG("Un-Register server instance request [%d]", server_if);
2097 struct hal_gatts_server_register_info_t *server_register_info = NULL;
2100 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
2101 if (server_register_info == NULL) {
2102 DBG("gatt server is not registered");
2103 return BT_STATUS_SUCCESS;
2106 /* remove the gatt server register info from the register list */
2107 hal_gatts_server_register_list = g_slist_remove(hal_gatts_server_register_list, server_register_info);
2108 g_free(server_register_info);
2110 __bt_hal_gatt_delete_id(server_if);
2112 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
2113 _bt_hal_remove_gatt_server_from_list(server_if);
2114 return BT_STATUS_SUCCESS;
2117 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
2119 CHECK_BTGATT_INIT();
2120 return BT_STATUS_SUCCESS;
2123 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
2126 GError *g_error = NULL;
2127 GVariant *reply = NULL;
2131 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2132 g_object_unref(proxy);
2133 if (reply == NULL) {
2134 ERR("Disconnect LE Dbus Call Error");
2136 ERR("Error: %s\n", g_error->message);
2137 g_clear_error(&g_error);
2140 g_variant_unref(reply);
2144 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
2146 CHECK_BTGATT_INIT();
2148 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2150 GDBusProxy *device_proxy;
2151 GDBusConnection *g_conn;
2152 struct gatt_client_info_t *conn_info = NULL;
2156 if (NULL == bd_addr) {
2157 ERR("bd_addr is NULL");
2158 return BT_STATUS_PARM_INVALID;
2161 /* GDBUS Connection Info validate */
2162 g_conn = _bt_hal_get_system_gconn();
2163 if (g_conn == NULL) {
2164 ERR("Could not get System DBUS Connection");
2165 return BT_STATUS_FAIL;
2168 /* Connection Info validate */
2169 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2170 if (conn_info == NULL) {
2171 ERR("No Connection Inforamtion!!!");
2172 return BT_STATUS_FAIL;
2175 _bt_hal_convert_addr_type_to_string(device_address,
2176 (unsigned char *)bd_addr->address);
2178 //check if connection has the same device address
2179 if (g_strcmp0(conn_info->addr, device_address) != 0) {
2180 ERR("device address [%s] does not match", device_address);
2181 return BT_STATUS_FAIL;
2184 device_path = _bt_hal_get_device_object_path(conn_info->addr);
2185 if (device_path == NULL) {
2186 ERR("device_path is NULL");
2187 return BT_STATUS_PARM_INVALID;
2190 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
2191 NULL, BT_HAL_BLUEZ_NAME,
2192 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2195 g_free(device_path);
2196 if (device_proxy == NULL)
2197 return BT_STATUS_FAIL;
2199 INFO("Disconnect LE [%s]", device_address);
2201 g_dbus_proxy_call(device_proxy, "DisconnectLE",
2203 G_DBUS_CALL_FLAGS_NONE,
2204 BT_HAL_MAX_DBUS_TIMEOUT,
2206 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
2209 return BT_STATUS_SUCCESS;
2212 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
2217 uuid = btuuid2str(srvc_id->uu);
2218 DBG("Original UUID [%s]", uuid);
2220 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
2221 /* Extract Standard UUID string */
2222 memcpy(uuid_buf, &uuid[4], 4);
2224 DBG("Converted string [%s]", uuid_buf);
2225 return g_strdup(uuid_buf);
2227 return strdup(uuid);
2230 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
2233 /* For GATT service specific */
2234 GDBusNodeInfo *node_info;
2237 struct gatt_service_info *serv_info = NULL;
2238 GVariantBuilder *builder = NULL;
2239 GVariantBuilder *builder1 = NULL;
2240 GVariantBuilder *inner_builder = NULL;
2241 gboolean svc_primary = TRUE;
2242 GError *error = NULL;
2243 hal_gatt_service_added *user_data = NULL;
2244 int service_handle = 0;
2245 DBG("Service add to DBUS slot [%d]", slot);
2247 service_handle = __bt_hal_assign_gatt_handle(BT_GATT_TYPE_SERV);
2248 if (service_handle == -1) {
2249 ERR("Too many gatt service handles are created");
2250 return BT_STATUS_FAIL;
2253 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, service_handle);
2254 DBG("gatt service path is [%s]", path);
2256 node_info = __bt_gatt_create_method_node_info(
2257 service_introspection_xml);
2258 if (node_info == NULL) {
2260 __bt_hal_free_gatt_handle(BT_GATT_TYPE_SERV, service_handle);
2261 return BT_STATUS_FAIL;
2264 object_id = g_dbus_connection_register_object(g_conn, path,
2265 node_info->interfaces[0],
2266 &serv_interface_vtable,
2267 NULL, NULL, &error);
2269 if (object_id == 0) {
2270 ERR("failed to register: %s", error->message);
2271 g_error_free(error);
2273 __bt_hal_free_gatt_handle(BT_GATT_TYPE_SERV, service_handle);
2274 return BT_STATUS_FAIL;
2276 /* Add object_id/gatt service information; it's required at the time of
2277 * service unregister and Getmanagedobjects
2279 serv_info = g_new0(struct gatt_service_info, 1);
2281 serv_info->serv_path = g_strdup(path);
2282 serv_info->serv_id = object_id;
2283 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
2284 serv_info->is_svc_registered = FALSE;
2285 serv_info->is_svc_primary = svc_primary;
2286 DBG("Service Handle to be added is [%d]", service_handle);
2287 serv_info->service_handle = service_handle;
2289 /* Update service in GATT Server service List */
2290 gatt_services = g_slist_append(gatt_services, serv_info);
2292 /* emit interfacesadded signal here for service path */
2293 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2294 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2296 g_variant_builder_add(inner_builder, "{sv}",
2297 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
2299 g_variant_builder_add(inner_builder, "{sv}",
2300 "Primary", g_variant_new_boolean(svc_primary));
2302 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2304 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
2305 g_variant_new("ao", builder1));
2307 g_variant_builder_add(builder, "{sa{sv}}",
2308 GATT_SERV_INTERFACE, inner_builder);
2310 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2311 "org.freedesktop.Dbus.ObjectManager", // TODO: need to check Dbus is working or not
2313 g_variant_new("(oa{sa{sv}})",
2318 /* dbus gives error cause */
2319 ERR("d-bus api failure: errcode[%x], message[%s]",
2320 error->code, error->message);
2321 g_clear_error(&error);
2325 /* Send Service handle to application */
2326 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2327 user_data->srvc_hdl = serv_info->service_handle;
2328 user_data->instance_data = slot;
2329 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2330 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2332 /* Save newly created service in GATT Server's service list */
2333 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2337 g_variant_builder_unref(inner_builder);
2338 g_variant_builder_unref(builder);
2339 g_variant_builder_unref(builder1);
2340 return BT_STATUS_SUCCESS;
2343 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2346 char *app_path = (char*)user_data;
2347 INFO("UnregisterApplication is completed app [%s]", app_path);
2348 GError *error = NULL;
2349 GVariant *result = NULL;
2352 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2354 if (result == NULL) {
2355 /* dBUS-RPC is failed */
2356 ERR("Dbus-RPC is failed\n");
2358 if (error != NULL) {
2359 /* dBUS gives error cause */
2360 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2361 error->code, error->message);
2362 g_clear_error(&error);
2365 g_variant_unref(result);
2370 static void __bt_hal_gatt_deinit(char *app_path)
2372 GDBusProxy *proxy = NULL;
2376 /* Step1: Remove requested App */
2377 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2378 "/org/bluez/hci0", "org.bluez.GattManager1");
2383 INFO("UnregisterApplication : path [%s]", app_path);
2385 /* Async Call to Unregister Service */
2386 data = g_strdup(app_path);
2387 g_dbus_proxy_call(proxy,
2388 "UnregisterApplication",
2389 g_variant_new("(o)",
2391 G_DBUS_CALL_FLAGS_NONE, -1,
2393 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2396 /* If requested app is last GATT Server app, then clean all resources */
2397 if (gatt_server_apps == NULL) {
2398 INFO("All GATT servers are removed, clean all DBUS resources");
2400 /* unregister the exported interface for object manager */
2401 g_dbus_connection_unregister_object(g_conn, manager_id);
2403 g_bus_unown_name(owner_id);
2406 g_object_unref(manager_gproxy);
2407 manager_gproxy = NULL;
2413 static int __bt_hal_gatt_init(void)
2417 /* Only once for ALL GATT Servers */
2418 if (owner_id == 0) {
2422 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2425 ERR("Unable to connect to gdbus: %s", err->message);
2426 g_clear_error(&err);
2428 return BT_STATUS_FAIL;
2431 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2432 INFO("well-known name: %s", name);
2434 owner_id = g_bus_own_name_on_connection(g_conn, name,
2435 G_BUS_NAME_OWNER_FLAGS_NONE,
2436 NULL, NULL, NULL, NULL);
2440 INFO("Owner ID [%d]", owner_id);
2442 /* Only once for ALL GATT Servers */
2443 if (manager_node_info == NULL) {
2444 /* Register ObjectManager interface */
2445 manager_node_info = __bt_gatt_create_method_node_info(
2446 manager_introspection_xml);
2448 if (manager_node_info == NULL) {
2449 ERR("failed to get node info");
2450 return BT_STATUS_FAIL;
2455 return BT_STATUS_SUCCESS;
2458 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2462 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2463 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2464 if (app->slot == slot) {
2465 INFO("GATT Server app found app path [%s] instance [%d]",
2466 app->app_path, app->slot);
2467 *app_path = app->app_path;
2471 /* GATT Server not found */
2475 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2477 if (app_path == NULL)
2480 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2481 app->app_path = g_strdup(app_path);
2483 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2484 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2487 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2490 CHECK_BTGATT_INIT();
2491 char *app_path = NULL;
2492 GError *error = NULL;
2495 int result = BT_STATUS_SUCCESS;
2497 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2498 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2500 /* Check if this GATT server Application is already registered with DBUS */
2501 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2503 if (app_path != NULL) {
2504 DBG("GATT server path is already defined [%s]", app_path);
2505 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2507 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2508 result = __bt_hal_gatt_init();
2509 if (result != BT_STATUS_SUCCESS)
2512 /* Only once for each GATT Server */
2513 app_path = g_strdup_printf("/com/%d", server_if);
2515 app_id = g_malloc0(sizeof(int));
2516 *app_id = server_if;
2518 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2519 manager_node_info->interfaces[0],
2520 &manager_interface_vtable,
2521 (gpointer)app_id, NULL, &error);
2523 if (manager_id == 0) {
2524 ERR("failed to register: %s", error->message);
2525 g_error_free(error);
2528 INFO("manager_id [%d]", manager_id);
2530 /* For current GATT Server, app_path is created, save it in Table */
2531 _bt_hal_update_gatt_server_path(server_if, app_path);
2533 /* Add GATT Service to DBUS */
2534 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2540 INFO("Successfully added service");
2541 return BT_STATUS_SUCCESS;
2548 INFO("Service addition failed!!");
2549 return BT_STATUS_FAIL;
2552 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2553 int included_handle)
2555 CHECK_BTGATT_INIT();
2556 return BT_STATUS_SUCCESS;
2560 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2563 GSList *gatt_services = NULL;
2565 struct gatt_service_info *info = NULL;
2567 gatt_services = _bt_get_service_list_from_server(instance);
2569 len = g_slist_length(gatt_services);
2570 l = g_slist_nth(gatt_services, len -1);
2576 if (info->service_handle == service_handle)
2581 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2585 GSList *gatt_services = NULL;
2586 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2588 gatt_services = _bt_get_service_list_from_server(instance);
2590 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2591 struct gatt_service_info *info = l->data;
2592 INFO("Got one service with handle [%d]", info->service_handle);
2593 if (info->service_handle == service_handle)
2596 ERR("Gatt service with handle [%d] not found", service_handle);
2600 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2601 bt_uuid_t *uuid, int properties,
2605 GError *error = NULL;
2607 GDBusNodeInfo *node_info;
2609 GVariantBuilder *builder = NULL;
2610 GVariantBuilder *inner_builder = NULL;
2611 struct gatt_service_info *serv_info = NULL;
2612 struct gatt_char_info *char_info = NULL;
2613 GVariantBuilder *builder2 = NULL;
2614 GVariantBuilder *builder3 = NULL;
2615 GVariant *flags_val = NULL;
2617 char *char_flags[NUMBER_OF_FLAGS];
2619 hal_gatt_char_added *user_data = NULL;
2621 int char_handle = 0;
2623 CHECK_BTGATT_INIT();
2624 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2625 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2627 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2628 if (serv_info == NULL)
2629 return BT_STATUS_FAIL;
2631 char_handle = __bt_hal_assign_gatt_handle(BT_GATT_TYPE_CHAR);
2632 if (char_handle == -1) {
2633 ERR("Too many gatt char handles are created");
2634 return BT_STATUS_FAIL;
2637 DBG("Add new GATT characteristic: Current GATT char handle [%d]", char_handle);
2638 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, char_handle);
2639 DBG("gatt characteristic path is [%s]", path);
2641 node_info = __bt_gatt_create_method_node_info(
2642 characteristics_introspection_xml);
2643 if (node_info == NULL) {
2645 __bt_hal_free_gatt_handle(BT_GATT_TYPE_CHAR, char_handle);
2646 return BT_STATUS_FAIL;
2649 app_id = g_malloc0(sizeof(int));
2652 object_id = g_dbus_connection_register_object(g_conn, path,
2653 node_info->interfaces[0],
2654 &char_interface_vtable,
2655 (gpointer)app_id, NULL, &error);
2657 if (object_id == 0) {
2658 ERR("failed to register: %s", error->message);
2659 g_error_free(error);
2662 __bt_hal_free_gatt_handle(BT_GATT_TYPE_CHAR, char_handle);
2663 return BT_STATUS_FAIL;
2666 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2667 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2668 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2669 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2670 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2671 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2672 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2673 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2675 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2677 char_info = g_new0(struct gatt_char_info, 1);
2679 char_info->char_path = g_strdup(path);
2680 char_info->char_id = object_id;
2681 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2682 for (i = 0; i < flag_count; i++)
2683 char_info->char_flags[i] = char_flags[i];
2686 char_info->flags_length = flag_count;
2687 char_info->char_handle = char_handle;
2690 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2691 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2693 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2694 g_variant_new("s", char_info->char_uuid));
2695 g_variant_builder_add(inner_builder, "{sv}", "Service",
2696 g_variant_new("o", serv_info->serv_path));
2698 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2700 for (i = 0; i < flag_count; i++)
2701 g_variant_builder_add(builder2, "s", char_flags[i]);
2703 flags_val = g_variant_new("as", builder2);
2704 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2707 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2709 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2710 g_variant_new("ao", builder3));
2712 g_variant_builder_add(builder, "{sa{sv}}",
2713 GATT_CHAR_INTERFACE,
2716 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2717 "org.freedesktop.Dbus.ObjectManager",
2719 g_variant_new("(oa{sa{sv}})",
2724 /* dbus gives error cause */
2725 ERR("d-bus api failure: errcode[%x], message[%s]",
2726 error->code, error->message);
2727 g_clear_error(&error);
2731 //*char_path = g_strdup(path);
2736 /* Send Service handle to application */
2737 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2738 user_data->srvc_hdl = serv_info->service_handle;
2739 user_data->char_hdl = char_handle;
2740 user_data->instance_data = slot;
2741 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2742 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2744 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2745 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2750 g_variant_builder_unref(inner_builder);
2751 g_variant_builder_unref(builder);
2752 g_variant_builder_unref(builder2);
2753 g_variant_builder_unref(builder3);
2755 return BT_STATUS_SUCCESS;
2758 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2761 CHECK_BTGATT_INIT();
2763 // static int desc_id = 1;
2764 GError *error = NULL;
2766 GDBusNodeInfo *node_info;
2768 GVariantBuilder *builder = NULL;
2769 GVariantBuilder *inner_builder = NULL;
2771 struct gatt_char_info *char_info = NULL;
2772 struct gatt_desc_info *desc_info = NULL;
2773 struct gatt_service_info *serv_info = NULL;
2775 gchar **line_argv = NULL;
2777 char *char_path = NULL;
2780 GVariantBuilder *builder2 = NULL;
2781 GVariant *flags_val = NULL;
2783 char *desc_flags[NUMBER_OF_FLAGS];
2786 hal_gatt_desc_added *user_data = NULL;
2787 int desc_handle = 0;
2789 /* Fetch service data for the GATT server */
2790 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2791 if (serv_info == NULL)
2792 return BT_STATUS_FAIL;
2794 /* Fetch list of characteristics from the service info */
2795 l = serv_info->char_data;
2797 /* Fetch last char info from the characteristic list */
2798 char_info = g_slist_last(l)->data;
2799 if (char_info == NULL)
2800 return BT_STATUS_FAIL;
2802 /* Fetch characteristic path from char info */
2803 char_path = char_info->char_path;
2805 line_argv = g_strsplit_set(char_path, "/", 0);
2806 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2809 node_info = __bt_gatt_create_method_node_info(
2810 descriptor_introspection_xml);
2812 if (node_info == NULL) {
2813 g_strfreev(line_argv);
2815 return BT_STATUS_FAIL;
2818 desc_handle = __bt_hal_assign_gatt_handle(BT_GATT_TYPE_DESC);
2819 if (desc_handle == -1) {
2820 ERR("Too many gatt desc handles are created");
2821 g_strfreev(line_argv);
2823 return BT_STATUS_FAIL;
2826 DBG("Add new Descriptor: Current GATT desc handle [%d]", desc_handle);
2827 path = g_strdup_printf("%s/descriptor%d", char_path, desc_handle);
2828 DBG("gatt descriptor path is [%s]", path);
2830 app_id = g_malloc0(sizeof(int));
2833 object_id = g_dbus_connection_register_object(g_conn, path,
2834 node_info->interfaces[0],
2835 &desc_interface_vtable,
2836 (gpointer)app_id, NULL, &error);
2838 if (object_id == 0) {
2839 ERR("failed to register: %s", error->message);
2840 g_error_free(error);
2842 g_strfreev(line_argv);
2845 __bt_hal_free_gatt_handle(BT_GATT_TYPE_DESC, desc_handle);
2846 return BT_STATUS_FAIL;
2849 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2851 desc_info = g_new0(struct gatt_desc_info, 1);
2853 desc_info->desc_path = g_strdup(path);
2854 desc_info->desc_id = object_id;
2855 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2857 for (i = 0; i < flag_count; i++)
2858 desc_info->desc_flags[i] = desc_flags[i];
2860 desc_info->flags_length = flag_count;
2861 desc_info->desc_handle = desc_handle;
2864 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2865 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2867 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2868 g_variant_new("s", btuuid2str(uuid->uu)));
2869 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2870 g_variant_new("o", char_path));
2872 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2874 for (i = 0; i < flag_count; i++)
2875 g_variant_builder_add(builder2, "s", desc_flags[i]);
2877 flags_val = g_variant_new("as", builder2);
2878 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2881 g_variant_builder_add(builder, "{sa{sv}}",
2882 GATT_DESC_INTERFACE,
2885 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2886 "org.freedesktop.Dbus.ObjectManager",
2888 g_variant_new("(oa{sa{sv}})",
2891 if (error != NULL) {
2892 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2893 error->code, error->message);
2894 g_clear_error(&error);
2897 //*desc_path = g_strdup(path);
2899 /* Save newly created descriptor to GATT server's service's characteristic */
2900 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2902 /* Send descriptor handle to application */
2903 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2904 user_data->srvc_hdl = serv_info->service_handle;
2905 user_data->desc_hdl = desc_handle;
2906 user_data->instance_data = slot;
2907 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2908 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2913 g_strfreev(line_argv);
2914 g_variant_builder_unref(inner_builder);
2915 g_variant_builder_unref(builder);
2916 return BT_STATUS_SUCCESS;
2919 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2921 GError *error = NULL;
2923 char *data = (char*) user_data;
2924 INFO("RegisterApplication is completed path [%s]", data);
2926 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2928 if (result == NULL) {
2929 /* dBUS-RPC is failed */
2930 ERR("Dbus-RPC is failed\n");
2932 if (error != NULL) {
2933 /* dBUS gives error cause */
2934 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2935 error->code, error->message);
2936 g_clear_error(&error);
2939 g_variant_unref(result);
2944 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2945 const gchar *path, const gchar *interface)
2951 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2956 ERR("Unable to connect to gdbus: %s", err->message);
2957 g_clear_error(&err);
2962 proxy = g_dbus_proxy_new_sync(g_conn,
2963 G_DBUS_PROXY_FLAGS_NONE, NULL,
2965 interface, NULL, &err);
2969 ERR("Unable to create proxy: %s", err->message);
2970 g_clear_error(&err);
2974 manager_gproxy = proxy;
2979 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2980 const gchar *path, const gchar *interface)
2982 return (manager_gproxy) ? manager_gproxy :
2983 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2987 static void __bt_register_application_to_dbus(int slot)
2989 GDBusProxy *proxy = NULL;
2990 char *app_path = NULL;
2992 DBG("RegisterApplication slot [%d]", slot);
2994 /* It is impossible that app path is still not initialized */
2995 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2997 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2998 "/org/bluez/hci0", "org.bluez.GattManager1");
3000 data = g_strdup(app_path);
3001 g_dbus_proxy_call(proxy,
3002 "RegisterApplication",
3003 g_variant_new("(oa{sv})",
3005 G_DBUS_CALL_FLAGS_NONE, -1,
3007 (GAsyncReadyCallback)__bt_hal_register_application_cb,
3009 INFO("GATT server started");
3012 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
3014 CHECK_BTGATT_INIT();
3015 struct gatt_service_info *serv_info = NULL;
3016 hal_gatt_service_started *user_data = NULL;
3017 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
3019 /* Fetch service data for the GATT server */
3020 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
3021 if (serv_info == NULL)
3022 return BT_STATUS_FAIL;
3024 if (serv_info->is_svc_registered)
3025 DBG("service already registered \n");
3027 serv_info->is_svc_registered = TRUE;
3029 /* Send Service handle to application */
3030 user_data = g_malloc0(sizeof(hal_gatt_service_started));
3031 user_data->srvc_hdl = serv_info->service_handle;
3032 user_data->instance_data = server_if;
3033 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
3035 /* If this is nth Service that is started, then register application at this point */
3036 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
3037 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
3039 __bt_register_application_to_dbus(server_if);
3042 return BT_STATUS_SUCCESS;
3045 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
3047 CHECK_BTGATT_INIT();
3048 INFO("Stop service successful");
3049 return BT_STATUS_SUCCESS;
3052 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
3054 CHECK_BTGATT_INIT();
3055 struct gatt_service_info *serv_info = NULL;
3056 hal_gatt_service_deleted *user_data = NULL;
3059 int err = BT_STATUS_SUCCESS;
3060 int ret = BT_STATUS_SUCCESS;
3061 char *app_path = NULL;
3062 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
3064 /* Fetch service data for the GATT server */
3065 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
3066 if (serv_info == NULL) {
3067 ERR("Could not find service info svc handle [%d] server slot [%d]",
3068 service_handle, server_if);
3069 return BT_STATUS_FAIL;
3072 app_path = __bt_get_server_app_path_from_server(server_if);
3073 if (app_path == NULL) {
3074 ERR("Could not find service info svc handle [%d] server slot [%d]",
3075 service_handle, server_if);
3076 return BT_STATUS_FAIL;
3079 if (serv_info->is_svc_registered == FALSE) {
3080 ERR("service Not registered path [%s] handle [%d]",
3081 serv_info->serv_path, service_handle);
3084 for (l = serv_info->char_data; l != NULL;) {
3085 struct gatt_char_info *char_info = l->data;
3086 l = g_slist_next(l);
3088 if (char_info == NULL)
3091 for (l1 = char_info->desc_data; l1 != NULL;) {
3092 struct gatt_desc_info *desc_info = l1->data;
3093 l1 = g_slist_next(l1);
3095 if (desc_info == NULL)
3098 ret = g_dbus_connection_unregister_object(g_conn,
3099 desc_info->desc_id);
3101 __bt_hal_gatt_emit_interface_removed(
3103 desc_info->desc_path,
3104 GATT_DESC_INTERFACE);
3106 err = BT_STATUS_FAIL;
3109 /* list remove & free */
3110 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
3111 __bt_hal_free_gatt_handle(BT_GATT_TYPE_DESC, desc_info->desc_handle);
3112 INFO("desc handle(%d) removed successfully", desc_info->desc_handle);
3113 __bt_hal_gatt_free_descriptor_info(desc_info);
3116 g_slist_free(char_info->desc_data);
3117 char_info->desc_data = NULL;
3119 ret = g_dbus_connection_unregister_object(g_conn,
3120 char_info->char_id);
3122 __bt_hal_gatt_emit_interface_removed(app_path, char_info->char_path,
3123 GATT_CHAR_INTERFACE);
3126 err = BT_STATUS_FAIL;
3129 /* list remove & free */
3130 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
3131 __bt_hal_free_gatt_handle(BT_GATT_TYPE_CHAR, char_info->char_handle);
3132 INFO("char handle(%d) removed successfully", char_info->char_handle);
3133 __bt_hal_gatt_free_characteristic_info(char_info);
3136 g_slist_free(serv_info->char_data);
3137 serv_info->char_data = NULL;
3139 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
3141 __bt_hal_gatt_emit_interface_removed(app_path, serv_info->serv_path,
3142 GATT_SERV_INTERFACE);
3145 err = BT_STATUS_FAIL;
3148 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
3150 DBG("Unregistered the service on properties interface");
3152 /* Remove from global list */
3153 gatt_services = g_slist_remove(gatt_services, serv_info);
3154 __bt_hal_free_gatt_handle(BT_GATT_TYPE_SERV, serv_info->service_handle);
3155 INFO("serv handle(%d) removed successfully", serv_info->service_handle);
3156 INFO("After removing from global list total service count [%d]", g_slist_length(gatt_services));
3158 /* Remove from GATT Server's list of services */
3159 _bt_remote_service_from_gatt_server(server_if, service_handle);
3161 if (gatt_services == NULL)
3162 INFO("All GATT Services of all GATT Servers are unregistered");
3164 if (err == BT_STATUS_SUCCESS) {
3165 INFO("Send GATT Service deleted Event");
3166 /* Send Service handle to application */
3167 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
3168 user_data->srvc_hdl = serv_info->service_handle;
3169 user_data->instance_data = server_if;
3170 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
3173 /* Free the service */
3174 __bt_hal_gatt_free_service_info(serv_info);
3178 static gboolean __bt_gatt_get_service_state(const char *service_path)
3180 struct gatt_service_info *svc_info = NULL;
3182 for (l = gatt_services; l; l = g_slist_next(l)) {
3184 svc_info = (struct gatt_service_info *)l->data;
3186 if (!g_strcmp0(svc_info->serv_path, service_path))
3187 return svc_info->is_svc_registered;
3190 DBG("gatt service info is NULL");
3194 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
3195 int len, int confirm, char* p_value)
3197 CHECK_BTGATT_INIT();
3200 GVariantBuilder *outer_builder;
3201 GVariantBuilder *invalidated_builder;
3203 /* For Value update via PropertyChange */
3204 GVariantBuilder *outer_builder1;
3205 GVariantBuilder *inner_builder1;
3206 GVariantBuilder *invalidated_builder1;
3207 GVariant *update_value = NULL;
3209 /* Other variables */
3210 struct gatt_client_info_t *conn_info = NULL;
3211 gchar *serv_path = NULL;
3212 char *char_path = NULL;
3213 gchar **line_argv = NULL;
3214 gboolean notify = TRUE;
3215 gboolean ret = TRUE;
3216 int err = BT_STATUS_SUCCESS;
3218 GError *error = NULL;
3221 memset(addr, 0x00, sizeof(addr));
3223 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3224 if (conn_info == NULL) {
3225 ERR("No Connection Inforamtion!!!");
3226 return BT_STATUS_FAIL;
3229 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
3231 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3232 if (char_path == NULL)
3233 return BT_STATUS_FAIL;
3235 line_argv = g_strsplit_set(char_path, "/", 0);
3236 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3238 if (!__bt_gatt_get_service_state(serv_path)) {
3239 DBG("service not registered for this characteristic \n");
3241 g_strfreev(line_argv);
3242 return BT_STATUS_FAIL;
3245 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3246 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3248 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
3249 g_variant_new("b", notify));
3251 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
3252 DBG("Send Indication to Unicast addr [%s]", addr);
3254 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
3255 g_variant_new("s", addr));
3257 DBG("Set characteristic Notification \n");
3258 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3260 "org.freedesktop.DBus.Properties",
3261 "PropertiesChanged",
3262 g_variant_new("(sa{sv}as)",
3263 "org.bluez.GattCharacteristic1",
3264 outer_builder, invalidated_builder),
3268 if (error != NULL) {
3269 ERR("D-Bus API failure: errCode[%x], \
3271 error->code, error->message);
3272 g_clear_error(&error);
3274 err = BT_STATUS_FAIL;
3277 g_variant_builder_unref(outer_builder);
3278 g_variant_builder_unref(invalidated_builder);
3281 /* Notifying Done, now update Value to Bluez via PropertyChanged */
3282 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
3284 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3285 for (i = 0; i < len; i++)
3286 g_variant_builder_add(inner_builder1, "y", p_value[i]);
3288 update_value = g_variant_new("ay", inner_builder1);
3291 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3292 g_variant_builder_add(outer_builder1, "{sv}", "Value",
3295 DBG("Updating characteristic value \n");
3296 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3298 "org.freedesktop.DBus.Properties",
3299 "PropertiesChanged",
3300 g_variant_new("(sa{sv}as)",
3301 "org.bluez.GattCharacteristic1",
3302 outer_builder1, invalidated_builder1),
3306 if (error != NULL) {
3307 ERR("D-Bus API failure: errCode[%x], \
3309 error->code, error->message);
3310 g_clear_error(&error);
3312 err = BT_STATUS_FAIL;
3314 struct gatt_char_info *char_info = NULL;
3316 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3317 if (char_info == NULL) {
3319 g_strfreev(line_argv);
3320 g_variant_builder_unref(inner_builder1);
3321 g_variant_builder_unref(outer_builder1);
3322 g_variant_builder_unref(invalidated_builder1);
3324 return BT_STATUS_FAIL;
3327 char_info->value_length = len;
3329 char_info->char_value = (char *)realloc(char_info->char_value, len);
3330 if (char_info->char_value) {
3331 for (i = 0; i < len; i++)
3332 char_info->char_value[i] = p_value[i];
3337 g_strfreev(line_argv);
3338 g_variant_builder_unref(inner_builder1);
3339 g_variant_builder_unref(outer_builder1);
3340 g_variant_builder_unref(invalidated_builder1);
3345 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3346 int status, btgatt_response_t *response)
3348 CHECK_BTGATT_INIT();
3350 struct gatt_req_info *req_info = NULL;
3351 struct gatt_client_info_t *conn_info = NULL;
3354 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3355 if (conn_info == NULL) {
3356 ERR("No Connection Inforamtion. conn_id %d", conn_id);
3357 return BT_STATUS_FAIL;
3360 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3361 if (req_info == NULL) {
3362 ERR("No Request Inforamtion. conn_id %d", conn_id);
3363 return BT_STATUS_FAIL;
3366 if (status != BT_STATUS_SUCCESS) {
3367 ERR("resp_state is 0x%X, conn_id %d", status, conn_id);
3369 g_dbus_method_invocation_return_dbus_error(req_info->context,
3370 "org.bluez.Error.Failed", "Application Error");
3372 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3374 req_info->context = NULL;
3375 if (req_info->attr_path)
3376 g_free(req_info->attr_path);
3377 if (req_info->svc_path)
3378 g_free(req_info->svc_path);
3381 return BT_STATUS_SUCCESS;
3384 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3385 GVariantBuilder *inner_builder = NULL;
3386 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3388 if (response->attr_value.len > 0) {
3389 for (i = 0; i < response->attr_value.len; i++)
3390 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3392 g_dbus_method_invocation_return_value(req_info->context,
3393 g_variant_new("(ay)", inner_builder));
3395 g_variant_builder_unref(inner_builder);
3397 g_dbus_method_invocation_return_value(req_info->context, NULL);
3399 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3401 req_info->context = NULL;
3402 if (req_info->attr_path)
3403 g_free(req_info->attr_path);
3404 if (req_info->svc_path)
3405 g_free(req_info->svc_path);
3408 return BT_STATUS_SUCCESS;
3412 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3413 int status, int fd, int mtu, void *fdlist)
3415 CHECK_BTGATT_INIT();
3417 struct gatt_req_info *req_info = NULL;
3418 struct gatt_client_info_t *conn_info = NULL;
3420 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3422 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3423 if (conn_info == NULL) {
3424 ERR("No Connection Inforamtion!!!");
3425 return BT_STATUS_FAIL;
3428 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3429 if (req_info == NULL) {
3430 ERR("No Request Inforamtion!!!");
3431 return BT_STATUS_FAIL;
3434 if (status != BT_STATUS_SUCCESS) {
3435 ERR("resp_state is 0x%X", status);
3437 g_dbus_method_invocation_return_dbus_error(req_info->context,
3438 "org.bluez.Error.Failed", "Application Error");
3440 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3442 req_info->context = NULL;
3443 if (req_info->attr_path)
3444 g_free(req_info->attr_path);
3445 if (req_info->svc_path)
3446 g_free(req_info->svc_path);
3449 return BT_STATUS_SUCCESS;
3453 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3455 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3456 g_dbus_method_invocation_return_value_with_unix_fd_list(
3457 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3459 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3461 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3462 g_dbus_method_invocation_return_value_with_unix_fd_list(
3463 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3466 g_dbus_method_invocation_return_value(req_info->context, NULL);
3468 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3470 req_info->context = NULL;
3471 if (req_info->attr_path)
3472 g_free(req_info->attr_path);
3473 if (req_info->svc_path)
3474 g_free(req_info->svc_path);
3477 return BT_STATUS_SUCCESS;
3481 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3482 int value_length, char* att_value)
3484 CHECK_BTGATT_INIT();
3486 /* Other variables */
3487 char *char_path = NULL;
3488 gboolean ret = TRUE;
3489 GError *error = NULL;
3491 GVariantBuilder *outer_builder;
3492 GVariantBuilder *inner_builder;
3493 GVariantBuilder *invalidated_builder;
3494 GVariant *update_value = NULL;
3495 int err = BT_STATUS_SUCCESS;
3497 gchar **line_argv = NULL;
3498 gchar *serv_path = NULL;
3500 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3501 if (char_path == NULL)
3502 return BT_STATUS_FAIL;
3504 line_argv = g_strsplit_set(char_path, "/", 0);
3505 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3507 if (!__bt_gatt_get_service_state(serv_path)) {
3508 DBG("service not registered for this characteristic \n");
3510 g_strfreev(line_argv);
3511 return BT_STATUS_FAIL;
3515 g_strfreev(line_argv);
3517 line_argv = g_strsplit_set(char_path, "/", 0);
3518 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3520 if (!__bt_gatt_get_service_state(serv_path)) {
3521 DBG("service not registered for this characteristic \n");
3523 g_strfreev(line_argv);
3524 return BT_STATUS_FAIL;
3527 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3528 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3530 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3531 for (i = 0; i < value_length; i++)
3532 g_variant_builder_add(inner_builder, "y", att_value[i]);
3534 update_value = g_variant_new("ay", inner_builder);
3536 g_variant_builder_add(outer_builder, "{sv}", "Value",
3539 DBG("Updating characteristic value \n");
3540 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3542 "org.freedesktop.DBus.Properties",
3543 "PropertiesChanged",
3544 g_variant_new("(sa{sv}as)",
3545 "org.bluez.GattCharacteristic1",
3546 outer_builder, invalidated_builder),
3550 if (error != NULL) {
3551 ERR("D-Bus API failure: errCode[%x], \
3553 error->code, error->message);
3554 g_clear_error(&error);
3556 err = BT_STATUS_FAIL;
3558 struct gatt_char_info *char_info = NULL;
3560 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3561 if (char_info == NULL) {
3563 g_strfreev(line_argv);
3564 g_variant_builder_unref(inner_builder);
3565 g_variant_builder_unref(outer_builder);
3566 g_variant_builder_unref(invalidated_builder);
3568 return BT_STATUS_FAIL;
3571 char_info->value_length = value_length;
3573 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3574 if (char_info->char_value) {
3575 for (i = 0; i < value_length; i++)
3576 char_info->char_value[i] = att_value[i];
3582 g_strfreev(line_argv);
3583 g_variant_builder_unref(inner_builder);
3584 g_variant_builder_unref(outer_builder);
3585 g_variant_builder_unref(invalidated_builder);
3590 static bt_status_t gatt_server_listen(int server_if, bool start)
3592 CHECK_BTGATT_INIT();
3594 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3596 DBG("server_if: [%d]", server_if);
3598 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3599 if (server_register_info == NULL) {
3600 DBG("gatt server is not registered");
3601 return BT_STATUS_FAIL;
3604 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3606 if (server_register_info->adv_slot_id < 0 ) {
3607 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3608 return BT_STATUS_FAIL;
3611 /* Send Data to LE Module */
3612 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, start, FALSE);
3615 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3616 bool include_txpower, int min_interval, int max_interval, int appearance,
3617 uint16_t manufacturer_len, char* manufacturer_data,
3618 uint16_t service_data_len, char* service_data,
3619 uint16_t service_uuid_len, char* service_uuid)
3621 CHECK_BTGATT_INIT();
3622 return BT_STATUS_SUCCESS;
3625 static int bt_hal_gatts_allocate_adv_slot(struct hal_gatts_server_register_info_t *server_register_info)
3627 int adv_slot_id = -1;
3629 /* allocate adv slot for gatt server if not assigned */
3630 if (server_register_info->adv_slot_id < 0 ) {
3631 adv_slot_id = _bt_hal_get_available_adv_slot_id(&server_register_info->app_uuid, TRUE);
3632 if (adv_slot_id < 0) {
3633 ERR("failed to get the adv_slot");
3637 server_register_info->adv_slot_id = adv_slot_id;
3640 DBG("gatt server:[%d] Assigned adv_slot [%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3645 int bt_hal_gatts_allocate_adv_slot_by_server_if(int server_if)
3647 CHECK_BTGATT_INIT();
3651 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3653 DBG("server_if: [%d]", server_if);
3655 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3656 if (server_register_info == NULL) {
3657 DBG("gatt server is not registered");
3661 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3663 if (server_register_info->adv_slot_id < 0 ) {
3664 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3666 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3668 DBG("failed to get adv_slot");
3673 return server_register_info->adv_slot_id;
3676 void bt_hal_gatts_release_adv_slot(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 ERR("failed to get server_register_info");
3686 if (server_register_info->adv_slot_id < 0) {
3687 ERR("adv_slot is not allocated");
3691 if(_bt_hal_is_advertising_in_slot(server_register_info->adv_slot_id) == FALSE) {
3692 DBG("advertising is disabled");
3693 _bt_hal_free_server_slot(server_register_info->adv_slot_id);
3694 server_register_info->adv_slot_id = -1;
3698 int bt_hal_gatts_get_adv_slot_id(int server_if)
3700 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3702 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3703 if (server_register_info == NULL) {
3704 DBG("failed to get server_register_info");
3708 return server_register_info->adv_slot_id;
3711 int bt_hal_gatts_get_server_if(int slot_id)
3713 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3715 server_register_info = bt_hal_gatts_find_server_register_info_by_slot_id(slot_id);
3716 if (server_register_info == NULL) {
3717 DBG("failed to get server_register_info");
3721 return server_register_info->server_if;
3724 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3726 CHECK_BTGATT_INIT();
3730 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3732 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3733 if (server_register_info == NULL) {
3734 ERR("gatt server is not registered");
3735 return BT_STATUS_FAIL;
3738 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3740 if (server_register_info->adv_slot_id < 0 ) {
3741 DBG("adv_slot is not assigned to server:[%d]", server_if);
3743 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3745 ERR("failed to get adv_slot");
3746 return BT_STATUS_FAIL;
3750 /* Send Enable Advertising request to LE Module */
3751 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, TRUE, TRUE);
3754 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3755 int chnl_map, int tx_power, int timeout_s, bool is_legacy, int primary_phy, int secondary_phy)
3757 CHECK_BTGATT_INIT();
3759 /* Send Advertising parameters to LE Module */
3760 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3761 chnl_map, tx_power, timeout_s, is_legacy, primary_phy, secondary_phy);
3764 static bt_status_t gatt_server_set_filter_policy(int filter_policy)
3766 CHECK_BTGATT_INIT();
3768 /* Send the Filter policy parameter to LE Module */
3769 _bt_hal_set_filter_policy_param(filter_policy);
3770 return BT_STATUS_SUCCESS;
3773 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3775 CHECK_BTGATT_INIT();
3777 /* Send Data to LE Module */
3778 return _bt_hal_set_advertising_data(adv_param_setup);
3781 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3783 CHECK_BTGATT_INIT();
3785 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3787 DBG("server_if: [%d]", server_if);
3789 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3790 if (server_register_info == NULL) {
3791 DBG("gatt server is not registered");
3792 return BT_STATUS_FAIL;
3795 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3797 if (server_register_info->adv_slot_id < 0 ) {
3798 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3799 return BT_STATUS_FAIL;
3802 /* Send Data to LE Module */
3803 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, FALSE, TRUE);
3806 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3808 CHECK_BTGATT_INIT();
3809 char *object_path = NULL;
3811 GDBusProxy *device_proxy;
3812 GError *error = NULL;
3814 GVariant *tmp_value;
3815 GDBusConnection *conn;
3816 GVariant *result = NULL;
3817 int ret = BT_STATUS_SUCCESS;
3818 struct gatt_client_info_t *conn_info = NULL;
3821 if (mtu_size == NULL)
3822 return BT_STATUS_PARM_INVALID;
3824 /* GDBUS Connection Info validate */
3825 conn = _bt_hal_get_system_gconn();
3827 ERR("Could not get System DBUS Connection");
3828 return BT_STATUS_FAIL;
3831 /* Connection Info validate */
3832 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3833 if (conn_info == NULL) {
3834 ERR("No Connection Inforamtion!!!");
3835 return BT_STATUS_FAIL;
3839 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3840 if (object_path == NULL)
3841 return BT_STATUS_FAIL;
3843 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3844 NULL, BT_HAL_BLUEZ_NAME, object_path,
3845 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3847 g_free(object_path);
3848 if (device_proxy == NULL)
3849 return BT_STATUS_FAIL;
3851 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3852 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3853 G_DBUS_CALL_FLAGS_NONE,
3857 if (result == NULL) {
3858 if (error != NULL) {
3859 ERR("Error occured in Proxy call [%s]\n", error->message);
3860 g_error_free(error);
3862 g_object_unref(device_proxy);
3863 return BT_STATUS_FAIL;
3866 g_variant_get(result , "(@a{sv})", &value);
3867 g_variant_unref(result);
3869 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3870 if (tmp_value == NULL) {
3871 g_object_unref(device_proxy);
3872 g_variant_unref(value);
3873 return BT_STATUS_FAIL;
3876 mtu = g_variant_get_uint16(tmp_value);
3878 DBG("ATT MTU : [%d]", mtu);
3880 g_variant_unref(tmp_value);
3881 g_variant_unref(value);
3882 g_object_unref(device_proxy);
3884 *mtu_size = (int) mtu;
3889 const btgatt_server_interface_t btgatt_server_interface = {
3890 .register_server = gatt_server_register_app,
3891 .unregister_server = gatt_server_unregister_app,
3892 .connect = gatt_server_open,
3893 .disconnect = gatt_server_close,
3894 .add_service = gatt_server_add_service,
3895 .add_included_service = gatt_server_add_included_service,
3896 .add_characteristic = gatt_server_add_characteristic,
3897 .add_descriptor = gatt_server_add_descriptor,
3898 .start_service = gatt_server_start_service,
3899 .stop_service = gatt_server_stop_service,
3900 .delete_service = gatt_server_delete_service,
3901 .send_indication = gatt_server_send_indication,
3902 .send_response = gatt_server_send_response,
3903 .update_att_value = gatt_server_update_att_value,
3904 .listen = gatt_server_listen,
3905 .set_adv_data = gatt_server_set_adv_data,
3906 .multi_adv_enable = gatt_server_multi_adv_enable,
3907 .multi_adv_update = gatt_server_multi_adv_update,
3908 .set_filter_policy = gatt_server_set_filter_policy,
3909 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3910 .multi_adv_disable = gatt_server_multi_adv_disable,
3911 .get_att_mtu = gatt_server_get_mtu_size,
3912 .send_response_acquire = gatt_server_send_acquire_response