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 /* Global handles which needs to be incremented during each addition */
68 static int gatt_service_handle = 10;
69 static int gatt_char_handle = 20;
70 static int gatt_desc_handle = 30;
72 struct gatt_service_info {
79 gboolean is_svc_registered;
80 gboolean is_svc_primary;
84 struct gatt_char_info {
89 gchar *char_flags[NUMBER_OF_FLAGS];
96 struct gatt_desc_info {
101 gchar *desc_flags[NUMBER_OF_FLAGS];
108 * GATT Server Request type
111 BT_HAL_GATT_REQUEST_TYPE_READ = 0x00, /* Read Requested */
112 BT_HAL_GATT_REQUEST_TYPE_WRITE = 0x01, /* Write Requested */
113 BT_HAL_GATT_REQUEST_TYPE_EXEC_WRITE = 0x02, /* Exec Write Requested */
114 BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE = 0x03, /* Exec Write Requested */
115 BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY = 0x04, /* Exec Write Requested */
116 } bt_gatt_request_type_e;
118 struct gatt_req_info {
123 bt_gatt_request_type_e request_type; /* Read or Write request */
124 GDBusMethodInvocation *context;
127 struct gatt_server_app {
133 /* Linked List of gatt server app's */
134 static GSList *gatt_server_apps = NULL;
136 static GSList *gatt_services = NULL;
138 extern int hal_gatt_conn_id;
140 /* Linked List of connected Remote GATT clients */
141 static GSList *gatt_client_info_list = NULL;
143 /* GATT Client Info List Structure */
144 struct gatt_client_info_t {
145 int connection_id; /* This value will uniquely identify a GATT client-server connection */
146 int instance_id; /* This value unique identifies a GATT server instance */
147 char *addr; /* Remote GATT client address */
148 GSList *gatt_req_info_list; /* List of transactions per Connection*/
151 static handle_stack_msg event_cb = NULL;
154 uint32_t instance_data;
156 } hal_register_server_data;
159 uint32_t instance_data;
163 } hal_gatt_service_added;
166 uint32_t instance_data;
168 } hal_gatt_service_started;
171 uint32_t instance_data;
173 } hal_gatt_service_deleted;
176 uint32_t instance_data;
180 } hal_gatt_char_added;
183 uint32_t instance_data;
187 } hal_gatt_desc_added;
190 struct hal_gatts_server_register_info_t {
196 static GSList * hal_gatts_server_register_list;
199 /* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
200 /* TODO: Adjust MAX Server after modifying MAX app handle logic */
201 #define BT_GATTS_MAX 11
203 static int assigned_id = 0;
205 static gboolean instance_id_used[BT_GATTS_MAX];
207 #define CHECK_BTGATT_INIT() if (_bt_hal_gatt_interface_ready() == false)\
209 ERR("%s: BTGATT not initialized", __FUNCTION__);\
210 return BT_STATUS_NOT_READY;\
212 DBG("%s", __FUNCTION__);\
215 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data);
217 static void __bt_hal_gatt_deinit(char *app_path);
219 static void __bt_hal_register_application_cb(GObject *object,
220 GAsyncResult *res, gpointer user_data);
222 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
225 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
226 const gchar *path, const gchar *interface);
228 static int bt_hal_gatts_get_gatt_server_instance();
230 /* Introspection data for the service we are exporting */
231 static const gchar service_introspection_xml[] =
233 " <interface name='org.freedesktop.DBus.Properties'>"
234 " <property type='s' name='UUID' access='read'>"
236 " <property type='b' name='primary' access='read'>"
238 " <property type='o' name='Device' access='read'>"
240 " <property type='ao' name='Characteristics' access='read'>"
242 " <property type='s' name='Includes' access='read'>"
247 /* Introspection data for the characteristics we are exporting */
248 static const gchar characteristics_introspection_xml[] =
250 " <interface name='org.bluez.GattCharacteristic1'>"
251 " <method name='ReadValue'>"
252 " <arg type='s' name='address' direction='in'/>"
253 " <arg type='u' name='id' direction='in'/>"
254 " <arg type='q' name='offset' direction='in'/>"
255 " <arg type='ay' name='Value' direction='out'/>"
257 " <method name='WriteValue'>"
258 " <arg type='s' name='address' direction='in'/>"
259 " <arg type='u' name='id' direction='in'/>"
260 " <arg type='q' name='offset' direction='in'/>"
261 " <arg type='b' name='response_needed' direction='in'/>"
262 " <arg type='ay' name='value' direction='in'/>"
264 " <method name ='AcquireWrite'>"
265 " <arg type='a{sv}' name='properties' direction='in'/>"
266 " <arg type='h' name='fd' direction='out'/>"
267 " <arg type='q' name='mtu' direction='out'/>"
269 " <method name = 'AcquireNotify'>"
270 " <arg type='a{sv}' name='properties' direction='in'/>"
271 " <arg type='h' name='fd' direction='out'/>"
272 " <arg type='q' name='mtu' direction='out'/>"
274 " <method name='StartNotify'>"
276 " <method name='StopNotify'>"
278 " <method name='IndicateConfirm'>"
279 " <arg type='s' name='address' direction='in'/>"
280 " <arg type='b' name='complete' direction='in'/>"
283 " <interface name='org.freedesktop.DBus.Properties'>"
284 " <property type='s' name='UUID' access='read'>"
286 " <property type='o' name='Service' access='read'>"
288 " <property type='ay' name='Value' access='readwrite'>"
290 " <property type='b' name='Notifying' access='read'>"
292 " <property type='as' name='Flags' access='read'>"
294 " <property type='s' name='Unicast' access='read'>"
296 " <property type='ao' name='Descriptors' access='read'>"
298 " <property type='b' name='WriteAcquired' access='read'>"
300 " <property type='b' name='NotifyAcquired' access='read'>"
305 /* Introspection data for the descriptor we are exporting */
306 static const gchar descriptor_introspection_xml[] =
308 " <interface name='org.bluez.GattDescriptor1'>"
309 " <method name='ReadValue'>"
310 " <arg type='s' name='address' direction='in'/>"
311 " <arg type='u' name='id' direction='in'/>"
312 " <arg type='q' name='offset' direction='in'/>"
313 " <arg type='ay' name='Value' direction='out'/>"
315 " <method name='WriteValue'>"
316 " <arg type='s' name='address' direction='in'/>"
317 " <arg type='u' name='id' direction='in'/>"
318 " <arg type='q' name='offset' direction='in'/>"
319 " <arg type='b' name='response_needed' direction='in'/>"
320 " <arg type='ay' name='value' direction='in'/>"
323 " <interface name='org.freedesktop.DBus.Properties'>"
324 " <property type='s' name='UUID' access='read'>"
326 " <property type='o' name='Characteristic' access='read'>"
328 " <property type='ay' name='Value' access='read'>"
330 " <property type='as' name='Flags' access='read'>"
336 static const gchar manager_introspection_xml[] =
338 " <interface name='org.freedesktop.DBus.ObjectManager'>"
339 " <method name='GetManagedObjects'>"
340 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
345 static void __bt_free_gatt_server_app(struct gatt_server_app *app)
347 g_free(app->app_path);
351 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
356 g_free(svc_info->serv_path);
357 g_free(svc_info->service_uuid);
361 void _bt_hal_gatt_server_init(void)
364 memset(instance_id_used, 0x00, sizeof(instance_id_used));
366 g_slist_free_full(gatt_server_apps, (GDestroyNotify)__bt_free_gatt_server_app);
367 gatt_server_apps = NULL;
369 g_slist_free_full(gatt_services, (GDestroyNotify)__bt_hal_gatt_free_service_info);
370 gatt_services = NULL;
372 g_slist_free_full(hal_gatts_server_register_list, g_free);
373 hal_gatts_server_register_list = NULL;
376 static int __bt_hal_gatt_assign_id(void)
380 index = assigned_id + 1;
382 if (index >= BT_GATTS_MAX)
385 while (instance_id_used[index] == TRUE) {
386 if (index == assigned_id) {
387 /* No available ID */
388 ERR("All interface ID is used");
394 if (index >= BT_GATTS_MAX)
399 instance_id_used[index] = TRUE;
404 static void __bt_hal_gatt_delete_id(int instance_id)
406 if (instance_id >= BT_GATTS_MAX || instance_id < 0)
409 instance_id_used[instance_id] = FALSE;
412 static GSList *_bt_get_service_list_from_server(int instance)
415 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
416 INFO("Find App with slot [%d]", instance);
418 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
419 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
421 if (app->slot == instance) {
422 INFO("App slot [%d] Found, Number of services registered [%d]",
423 app->slot, g_slist_length(app->services));
424 return app->services;
430 static char *__bt_get_server_app_path_from_server(int instance)
433 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
434 INFO("Find App with slot [%d]", instance);
436 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
437 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
439 if (app->slot == instance) {
440 INFO("App slot [%d] Found, App path [%s]",
441 app->slot, app->app_path);
442 return app->app_path;
448 static void _bt_remote_service_from_gatt_server(int instance, int service_handle)
453 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
454 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
456 if (app->slot == instance) {
457 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
458 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
459 if (srv->service_handle == service_handle) {
460 app->services = g_slist_remove(app->services, srv);
468 static void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
471 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
472 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
474 if (app->slot == slot) {
475 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
476 serv_info->service_handle, slot);
477 app->services = g_slist_append(app->services, serv_info);
482 int _bt_get_remote_gatt_client_conn_id(char *address)
485 struct gatt_client_info_t *info = NULL;
487 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
488 info = (struct gatt_client_info_t*)l->data;
492 if (!g_strcmp0(info->addr, address)) {
493 INFO("Remote GATT client found addr[%s]", info->addr);
494 return info->connection_id;
500 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
503 struct gatt_client_info_t *info = NULL;
505 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
506 info = (struct gatt_client_info_t*)l->data;
510 if (!g_strcmp0(info->addr, address))
516 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
519 struct gatt_client_info_t *info = NULL;
521 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
522 info = (struct gatt_client_info_t*)l->data;
526 if (info->connection_id == conn_id)
532 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
537 struct gatt_client_info_t *info = NULL;
538 struct gatt_req_info *info1 = NULL;
540 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
541 info = (struct gatt_client_info_t*)l->data;
545 if (info->connection_id == conn_id) {
547 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
549 info1 = (struct gatt_req_info*)l1->data;
553 if (info1->request_id == trans_id)
561 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
563 struct hal_ev_gatt_server_connected ev;
564 struct gatt_client_info_t *conn_info = NULL;
565 memset(&ev, 0, sizeof(ev));
567 /* Convert address to hex */
568 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
570 /* Create Connection ID */
571 /* Check if device is already in connected list */
572 conn_info = __bt_find_remote_gatt_client_info(address);
574 /* If disconnected, and conn info found, then remove conn info */
575 if (is_connected == FALSE) {
576 DBG("GATT Disconnected");
578 INFO("Remove GATT client info from List..");
579 /* Remove info from List */
580 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
581 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
584 ERR("GATT callback not registered");
586 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
587 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
588 ev.conn_id = conn_info->connection_id;
589 ev.server_instance = conn_info->instance_id;
590 ev.connected = is_connected;
592 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
594 g_free(conn_info->addr);
597 /* If connected, and conn info NOT found, then add conn info */
601 /* Find Server Instance */
602 instance = bt_hal_gatts_get_gatt_server_instance();
603 if (instance == -1) {
604 ERR("Not even a single GATT server is registered");
605 ev.conn_id = ++hal_gatt_conn_id;
606 ev.server_instance = -1;
607 ev.connected = is_connected;
608 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
611 DBG("server instance [%d]", instance);
614 /* Save Connection info */
615 conn_info = g_new0(struct gatt_client_info_t, 1);
616 conn_info->addr = g_strdup(address);
617 DBG("Added GATT client addr[%s]", conn_info->addr);
618 conn_info->connection_id = ++hal_gatt_conn_id;
619 conn_info->instance_id = instance;
620 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
621 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
624 ERR("GATT callback not registered");
626 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
627 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
628 ev.conn_id = conn_info->connection_id;
629 ev.server_instance = conn_info->instance_id;
630 ev.connected = is_connected;
632 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
635 ERR("Abnormal case. conn_info should be NULL");
638 /* Send GATT connected or disconnected event */
641 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
645 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
646 struct gatt_service_info *serv_info = l1->data;
648 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
649 struct gatt_char_info *char_info = l2->data;
651 if (g_strcmp0(char_info->char_path, char_path)
653 *char_hdl = char_info->char_handle;
658 ERR("Gatt service not found");
662 static char *__bt_gatt_find_char_path_from_handle(int char_hdl)
666 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
667 struct gatt_service_info *serv_info = l1->data;
669 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
670 struct gatt_char_info *char_info = l2->data;
672 if (char_info->char_handle == char_hdl)
673 return char_info->char_path;
680 static struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
684 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
685 struct gatt_service_info *serv_info = l1->data;
687 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
688 struct gatt_char_info *char_info = l2->data;
690 if (char_info->char_handle == char_hdl)
698 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
700 GSList *l1, *l2, *l3;
702 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
703 struct gatt_service_info *serv_info = l1->data;
705 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
706 struct gatt_char_info *char_info = l2->data;
708 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
709 struct gatt_desc_info *desc_info = l3->data;
711 if (g_strcmp0(desc_info->desc_path, desc_path)
713 *desc_hdl = desc_info->desc_handle;
719 ERR("Gatt service not found");
723 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
725 const gchar *object_path,
726 const gchar *interface_name,
727 const gchar *method_name,
728 GVariant *parameters,
729 GDBusMethodInvocation *invocation,
734 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
735 GVariantBuilder *builder;
736 GVariantBuilder *inner_builder1 = NULL;
737 GVariant *svc_char = NULL;
739 GSList *gatt_services = NULL;
741 instance = (int*)user_data;
742 gboolean writeAcquired = FALSE;
743 gboolean notifyAcquired = FALSE;
745 DBG("Getting values for service, chars and descriptors");
746 DBG("GATT Server App for which services are requested [%d]", *instance);
749 builder = g_variant_builder_new(
750 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
753 gatt_services = _bt_get_service_list_from_server(*instance);
755 if (g_slist_length(gatt_services) == 0) {
756 ERR("No registered GATT services!!!!");
757 g_dbus_method_invocation_return_value(invocation, NULL);
758 g_variant_builder_unref(builder);
762 for (l = gatt_services; l != NULL; l = l->next) {
763 GVariantBuilder *svc_builder = NULL;
764 GVariantBuilder *inner_builder = NULL;
765 struct gatt_service_info *serv_info = l->data;
766 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
768 /* Prepare inner builder for GattService1 interface */
769 DBG("Creating builder for service");
770 svc_builder = g_variant_builder_new(
771 G_VARIANT_TYPE("a{sa{sv}}"));
772 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
774 g_variant_builder_add(inner_builder, "{sv}", "UUID",
775 g_variant_new_string(serv_info->service_uuid));
777 g_variant_builder_add(inner_builder, "{sv}", "Primary",
778 g_variant_new_boolean(serv_info->is_svc_primary));
781 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
782 DBG("Adding Charatarisitcs list");
783 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
784 struct gatt_char_info *char_info = l4->data;
785 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
786 char_info->char_handle, serv_info->service_handle);
787 g_variant_builder_add(inner_builder1, "o",
788 char_info->char_path);
789 DBG("%s", char_info->char_path);
792 svc_char = g_variant_new("ao", inner_builder1);
793 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
796 g_variant_builder_add(svc_builder, "{sa{sv}}",
800 g_variant_builder_add(builder, "{oa{sa{sv}}}",
801 serv_info->serv_path,
804 g_variant_builder_unref(inner_builder1);
806 /* Prepare inner builder for GattCharacteristic1 interface */
808 GSList *l2 = serv_info->char_data;
809 DBG("Creating builder for characteristics \n");
812 DBG("characteristic data is NULL");
814 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
816 GVariantBuilder *char_builder = NULL;
817 GVariantBuilder *inner_builder = NULL;
818 GVariantBuilder *builder1 = NULL;
819 GVariantBuilder *builder2 = NULL;
820 GVariantBuilder *builder3 = NULL;
821 GVariant *char_val = NULL;
822 GVariant *flags_val = NULL;
823 GVariant *char_desc = NULL;
824 char *unicast = NULL;
825 gboolean notify = FALSE;
828 char_builder = g_variant_builder_new(
831 inner_builder = g_variant_builder_new(
835 struct gatt_char_info *char_info = l2->data;
836 if (char_info == NULL) {
837 ERR("char_info is NULL");
842 g_variant_builder_add(inner_builder, "{sv}", "UUID",
843 g_variant_new_string(char_info->char_uuid));
845 g_variant_builder_add(inner_builder, "{sv}", "Service",
846 g_variant_new("o", serv_info->serv_path));
848 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
850 if (char_info->char_value != NULL) {
851 for (i = 0; i < char_info->value_length; i++) {
852 g_variant_builder_add(builder1, "y",
853 char_info->char_value[i]);
855 char_val = g_variant_new("ay", builder1);
856 g_variant_builder_add(inner_builder, "{sv}",
860 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
861 for (i = 0; i < char_info->flags_length; i++) {
862 g_variant_builder_add(builder2, "s",
863 char_info->char_flags[i]);
865 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
866 DBG("setting WriteAcquired property");
867 writeAcquired = TRUE;
870 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
871 DBG("setting NotifyAcquired property");
872 notifyAcquired = TRUE;
876 flags_val = g_variant_new("as", builder2);
877 g_variant_builder_add(inner_builder, "{sv}", "Flags",
881 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
882 g_variant_new("b", notify));
885 if (writeAcquired == TRUE) {
886 DBG("adding WriteAcquired property");
887 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
888 g_variant_new("b", writeAcquired));
892 if (notifyAcquired == TRUE) {
893 DBG("adding NotifyAcquired property");
894 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
895 g_variant_new("b", notifyAcquired));
899 unicast = g_strdup("00:00:00:00:00:00");
900 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
901 g_variant_new("s", unicast));
904 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
905 DBG("Adding Descriptors list");
907 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
908 struct gatt_desc_info *desc_info = l4->data;
909 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
910 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
911 g_variant_builder_add(builder3, "o",
912 desc_info->desc_path);
913 DBG("%s", desc_info->desc_path);
916 char_desc = g_variant_new("ao", builder3);
917 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
920 g_variant_builder_add(char_builder, "{sa{sv}}",
921 GATT_CHAR_INTERFACE , inner_builder);
922 g_variant_builder_add(builder, "{oa{sa{sv}}}",
923 char_info->char_path, char_builder);
925 /*Prepare inner builder for GattDescriptor1 interface*/
927 GSList *l3 = char_info->desc_data;
930 DBG("descriptor data is NULL");
932 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
934 DBG("Creating builder for descriptor \n");
936 GVariantBuilder *desc_builder = NULL;
937 GVariantBuilder *inner_builder = NULL;
938 GVariantBuilder *builder1 = NULL;
939 GVariantBuilder *builder2 = NULL;
940 GVariant *desc_val = NULL;
942 desc_builder = g_variant_builder_new(
945 inner_builder = g_variant_builder_new(
949 struct gatt_desc_info *desc_info = l3->data;
950 if (desc_info == NULL) {
951 ERR("desc_info is NULL");
956 g_variant_builder_add(inner_builder,
958 g_variant_new_string(
959 desc_info->desc_uuid));
962 g_variant_builder_add(inner_builder, "{sv}",
965 char_info->char_path));
968 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
970 if (desc_info->desc_value != NULL) {
971 for (i = 0; i < desc_info->value_length; i++) {
972 g_variant_builder_add(builder1, "y",
973 desc_info->desc_value[i]);
975 desc_val = g_variant_new("ay", builder1);
976 g_variant_builder_add(inner_builder, "{sv}",
981 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
983 for (i = 0; i < desc_info->flags_length; i++) {
984 g_variant_builder_add(builder2, "s",
985 desc_info->desc_flags[i]);
988 flags_val = g_variant_new("as", builder2);
989 g_variant_builder_add(inner_builder, "{sv}", "Flags",
992 g_variant_builder_add(desc_builder, "{sa{sv}}",
996 g_variant_builder_add(builder, "{oa{sa{sv}}}",
997 desc_info->desc_path,
1000 /*unref descriptor builder pointers*/
1001 g_variant_builder_unref(builder1);
1002 g_variant_builder_unref(builder2);
1003 g_variant_builder_unref(inner_builder);
1004 g_variant_builder_unref(desc_builder);
1009 /*unref char builder pointers*/
1010 g_variant_builder_unref(builder1);
1011 g_variant_builder_unref(builder2);
1012 g_variant_builder_unref(builder3);
1013 g_variant_builder_unref(inner_builder);
1014 g_variant_builder_unref(char_builder);
1017 /*unref service builder pointers*/
1018 g_variant_builder_unref(inner_builder);
1019 g_variant_builder_unref(svc_builder);
1022 /* Return builder as method reply */
1023 DBG("Sending gatt service builder values to Bluez");
1024 g_dbus_method_invocation_return_value(invocation,
1030 /* Free User Data */
1034 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1035 const gchar *sender,
1036 const gchar *object_path,
1037 const gchar *interface_name,
1038 const gchar *method_name,
1039 GVariant *parameters,
1040 GDBusMethodInvocation *invocation,
1044 if (g_strcmp0(method_name, "ReadValue") == 0) {
1045 struct hal_ev_gatt_server_read_req ev;
1050 struct gatt_client_info_t *conn_info = NULL;
1051 struct gatt_req_info *req_info = NULL;
1052 struct gatt_service_info *svc_info = NULL;
1056 DBG("Application path = %s", object_path);
1057 DBG("Sender = %s", sender);
1059 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1060 if (svc_info == NULL) {
1061 ERR("Coudn't find service for %s", object_path);
1062 g_dbus_method_invocation_return_value(invocation, NULL);
1066 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1067 DBG("Request id = %u, Offset = %u", req_id, offset);
1069 /* Check if device is already in connected list */
1070 conn_info = __bt_find_remote_gatt_client_info(addr);
1072 if (conn_info == NULL) {
1073 ERR("Coudn't find Connection info for %s", addr);
1074 g_dbus_method_invocation_return_value(invocation, NULL);
1079 ERR("GATT callback NOT registered");
1080 g_dbus_method_invocation_return_value(invocation, NULL);
1084 /* Store requests information */
1085 req_info = g_new0(struct gatt_req_info, 1);
1086 req_info->attr_path = g_strdup(object_path);
1087 req_info->svc_path = g_strdup(svc_info->serv_path);
1088 req_info->request_id = req_id;
1089 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1090 req_info->offset = offset;
1091 req_info->context = invocation;
1093 /* Append request info in list of requests for the particular connection */
1094 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1096 /* Send HAL event */
1097 memset(&ev, 0, sizeof(ev));
1098 ev.conn_id = conn_info->connection_id;
1099 ev.trans_id = req_id;
1100 ev.att_handle = desc_hdl;
1102 ev.is_long = false; /* TODO*/
1104 /* Convert address to hex */
1105 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1107 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1109 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1111 GVariant *var = NULL;
1115 gboolean response_needed = FALSE;
1116 struct hal_ev_gatt_server_write_req ev;
1120 struct gatt_service_info *svc_info = NULL;
1121 struct gatt_client_info_t *conn_info = NULL;
1122 struct gatt_req_info *req_info = NULL;
1124 memset(&ev, 0, sizeof(ev));
1127 DBG("Application path = %s", object_path);
1128 DBG("Sender = %s", sender);
1130 g_variant_get(parameters, "(&suqb@ay)",
1131 &addr, &req_id, &offset, &response_needed, &var);
1132 DBG("Request id = %u, Offset = %u", req_id, offset);
1134 /* Check if device is already in connected list */
1135 conn_info = __bt_find_remote_gatt_client_info(addr);
1137 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1139 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1140 g_variant_unref(var);
1141 if (response_needed)
1142 g_dbus_method_invocation_return_value(invocation, NULL);
1144 g_object_unref(invocation);
1148 len = g_variant_get_size(var);
1149 if (len > 0 && len < 600) {
1151 data = (char *)g_variant_get_data(var);
1152 memcpy(ev.value, data, len);
1155 if (response_needed) {
1156 /* Store request information */
1157 req_info = g_new0(struct gatt_req_info, 1);
1158 req_info->attr_path = g_strdup(object_path);
1159 req_info->svc_path = g_strdup(svc_info->serv_path);
1160 req_info->request_id = req_id;
1161 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1162 req_info->offset = offset;
1163 req_info->context = invocation;
1165 /* Append request info in list of requests for the particular connection */
1166 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1168 g_object_unref(invocation);
1171 /* Send HAL event */
1172 ev.conn_id = conn_info->connection_id;
1173 ev.trans_id = req_id;
1174 ev.att_handle = desc_hdl;
1176 ev.need_rsp = response_needed;
1179 /* Convert address to hex */
1180 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1182 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1184 g_variant_unref(var);
1189 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1190 const gchar *sender,
1191 const gchar *object_path,
1192 const gchar *interface_name,
1193 const gchar *method_name,
1194 GVariant *parameters,
1195 GDBusMethodInvocation *invocation,
1198 if (g_strcmp0(method_name, "ReadValue") == 0) {
1202 struct hal_ev_gatt_server_read_req ev;
1205 struct gatt_req_info *req_info = NULL;
1206 struct gatt_client_info_t *conn_info = NULL;
1207 struct gatt_service_info *svc_info = NULL;
1209 g_variant_get(parameters, "(&suq)",
1210 &addr, &req_id, &offset);
1212 DBG("ReadValue : req id %u, offset %u, path %s, sender %s, %s", req_id, offset, object_path, sender, addr);
1214 /* Check if device is already in connected list */
1215 conn_info = __bt_find_remote_gatt_client_info(addr);
1217 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1219 if (svc_info == NULL || conn_info == NULL) {
1220 ERR("Invalid information %p, %p", svc_info, conn_info);
1221 g_dbus_method_invocation_return_value(invocation, NULL);
1226 ERR("GATT callback NOT registered");
1227 g_dbus_method_invocation_return_value(invocation, NULL);
1231 /* Store requets information */
1232 req_info = g_new0(struct gatt_req_info, 1);
1233 req_info->attr_path = g_strdup(object_path);
1234 req_info->svc_path = g_strdup(svc_info->serv_path);
1235 req_info->request_id = req_id;
1236 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1237 req_info->offset = offset;
1238 req_info->context = invocation;
1240 /* Append request info in list of requests for the particular connection */
1241 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1243 /* Send HAL event */
1244 memset(&ev, 0, sizeof(ev));
1245 ev.conn_id = conn_info->connection_id;
1246 ev.trans_id = req_id;
1247 ev.att_handle = char_hdl;
1249 ev.is_long = false; /* TODO*/
1251 /* Convert address to hex */
1252 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1253 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1255 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1256 GVariant *var = NULL;
1260 gboolean response_needed = FALSE;
1261 struct hal_ev_gatt_server_write_req ev;
1265 struct gatt_service_info *svc_info = NULL;
1266 struct gatt_req_info *req_info = NULL;
1267 struct gatt_client_info_t *conn_info = NULL;
1269 memset(&ev, 0, sizeof(ev));
1271 DBG("WriteValue : Application path %s, sender %s", object_path, sender);
1273 g_variant_get(parameters, "(&suqb@ay)",
1274 &addr, &req_id, &offset, &response_needed, &var);
1275 DBG("Request id = %u, Offset = %u", req_id, offset);
1277 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1279 /* Check if device is already in connected list */
1280 conn_info = __bt_find_remote_gatt_client_info(addr);
1282 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1283 g_variant_unref(var);
1284 if (response_needed)
1285 g_dbus_method_invocation_return_value(invocation, NULL);
1287 g_object_unref(invocation);
1291 len = g_variant_get_size(var);
1292 if (len > 0 && len < 600) {
1294 data = (char *)g_variant_get_data(var);
1295 memcpy(ev.value, data, len);
1299 if (response_needed) {
1300 /* Store requets information */
1301 req_info = g_new0(struct gatt_req_info, 1);
1302 req_info->attr_path = g_strdup(object_path);
1303 req_info->svc_path = g_strdup(svc_info->serv_path);
1304 req_info->request_id = req_id;
1305 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1306 req_info->offset = offset;
1307 req_info->context = invocation;
1309 /* Append request info in list of requests for the particular connection */
1310 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1313 g_object_unref(invocation);
1316 /* Send HAL event */
1317 ev.conn_id = conn_info->connection_id;
1318 ev.trans_id = req_id;
1319 ev.att_handle = char_hdl;
1321 ev.need_rsp = response_needed;
1324 /* Convert address to hex */
1325 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1327 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1329 g_variant_unref(var);
1332 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1335 struct gatt_service_info *svc_info = NULL;
1336 struct hal_ev_gatt_server_notifcation_change ev;
1339 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1340 if (svc_info == NULL || event_cb == NULL)
1343 /* Send HAL event */
1344 memset(&ev, 0, sizeof(ev));
1345 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1346 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1347 ev.att_handle = char_hdl;
1350 /* Convert address to hex */
1351 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1353 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1356 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1359 struct gatt_service_info *svc_info = NULL;
1360 struct hal_ev_gatt_server_notifcation_change ev;
1363 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1364 if (svc_info == NULL || event_cb == NULL)
1367 /* Send HAL event */
1368 memset(&ev, 0, sizeof(ev));
1369 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1370 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1371 ev.att_handle = char_hdl;
1374 /* Convert address to hex */
1375 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1377 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1380 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1382 gboolean complete = FALSE;
1385 struct gatt_service_info *svc_info = NULL;
1386 struct gatt_client_info_t *conn_info = NULL;
1388 struct hal_ev_gatt_server_indicate_cfm ev;
1390 DBG("IndicateConfirm : Application path %s, sender %s", object_path, sender);
1392 g_variant_get(parameters, "(&sb)", &addr, &complete);
1393 DBG("Remote Device address number = %s", addr);
1394 DBG("Is Indicate confirmation for last device [%d]", complete);
1396 /* Check if device is already in connected list */
1397 conn_info = __bt_find_remote_gatt_client_info(addr);
1399 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1401 if (svc_info == NULL || conn_info == NULL
1402 || event_cb == NULL) {
1406 /* Send HAL event */
1407 memset(&ev, 0, sizeof(ev));
1408 ev.conn_id = conn_info->connection_id;
1409 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1410 ev.att_handle = char_hdl;
1412 /* Convert address to hex */
1413 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1415 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1416 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1420 struct hal_ev_gatt_server_acquire_write_res ev;
1421 struct gatt_service_info *svc_info = NULL;
1422 struct gatt_req_info *req_info = NULL;
1423 struct gatt_client_info_t *conn_info = NULL;
1424 char *dev_path = NULL;
1426 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1428 DBG("AcquireWrite : Application path %s, sender %s", object_path, sender);
1431 g_variant_get(parameters, "(a{sv})", &iter);
1433 GVariant *value = NULL;
1434 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1435 if (g_strcmp0(key, "MTU") == 0)
1436 g_variant_get(value, "q", &mtu);
1437 else if (g_strcmp0(key, "link") == 0)
1438 g_variant_get(value, "s", &link);
1439 else if (g_strcmp0(key, "device") == 0)
1440 g_variant_get(value, "o", &dev_path);
1443 DBG(" path %s LINK = %s, MTU = %u", dev_path, link, mtu);
1445 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1447 _bt_hal_convert_device_path_to_address(dev_path, addr);
1449 DBG("remote address %s", addr);
1453 /* Check if device is already in connected list */
1454 conn_info = __bt_find_remote_gatt_client_info(addr);
1455 if (conn_info == NULL) {
1456 ERR("Cleint info not found\n");
1457 g_variant_iter_free(iter);
1461 if (svc_info == NULL) {
1462 ERR("svc_info info not found\n");
1463 g_variant_iter_free(iter);
1467 /* Store requets information */
1468 req_info = g_new0(struct gatt_req_info, 1);
1469 req_info->attr_path = g_strdup(object_path);
1470 req_info->svc_path = g_strdup(svc_info->serv_path);
1471 req_info->request_id = conn_info->connection_id;
1472 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1473 req_info->offset = mtu;
1474 req_info->context = invocation;
1476 /* Append request info in list of requests for the particular connection */
1477 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1479 /* Send HAL event */
1480 memset(&ev, 0, sizeof(ev));
1481 ev.conn_id = conn_info->connection_id;
1482 ev.char_handl = char_hdl;
1484 ev.trans_id = conn_info->connection_id;
1485 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1486 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1487 g_variant_iter_free(iter);
1489 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1493 struct hal_ev_gatt_server_acquire_notify ev;
1494 struct gatt_service_info *svc_info = NULL;
1495 struct gatt_client_info_t *conn_info = NULL;
1496 struct gatt_req_info *req_info = NULL;
1498 DBG("AcquireNotify : Application path %s, sender %s", object_path, sender);
1501 g_variant_get(parameters, "(a{sv})", &iter);
1503 GVariant* value = NULL;
1504 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1505 if (g_strcmp0(key, "MTU") == 0)
1506 g_variant_get(value, "q", &mtu);
1509 DBG("MTU = %u", mtu);
1511 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1513 if (svc_info == NULL) {
1514 ERR("svc_info info not found\n");
1515 g_variant_iter_free(iter);
1519 /* Store requets information */
1520 req_info = g_new0(struct gatt_req_info, 1);
1521 req_info->attr_path = g_strdup(object_path);
1522 req_info->svc_path = g_strdup(svc_info->serv_path);
1523 req_info->request_id = 33;
1524 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1525 req_info->offset = mtu;
1526 req_info->context = invocation;
1528 conn_info = g_new0(struct gatt_client_info_t, 1);
1529 conn_info->addr = g_strdup(object_path);
1530 INFO("AcquireNotify : Added GATT client path[%s]", conn_info->addr);
1531 conn_info->connection_id = 33;
1532 conn_info->instance_id = 33;
1533 /* Append request info in list of requests for the particular connection */
1534 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1535 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1537 /* Send HAL event */
1538 memset(&ev, 0, sizeof(ev));
1540 ev.char_handl = char_hdl;
1544 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1545 g_variant_iter_free(iter);
1550 g_dbus_method_invocation_return_value(invocation, NULL);
1553 static gboolean __bt_hal_gatt_emit_interface_removed(const char *app_path, gchar *object_path, gchar *interface)
1556 GError *error = NULL;
1557 GVariantBuilder *array_builder;
1559 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1560 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1561 g_variant_builder_add(array_builder, "s", interface);
1563 ret = g_dbus_connection_emit_signal(g_conn, NULL, app_path,
1564 "org.freedesktop.DBus.ObjectManager",
1565 "InterfacesRemoved",
1566 g_variant_new("(oas)",
1567 object_path, array_builder),
1571 if (error != NULL) {
1572 /* dbus gives error cause */
1573 ERR("d-bus api failure: errcode[%x], message[%s]",
1574 error->code, error->message);
1575 g_clear_error(&error);
1578 g_variant_builder_unref(array_builder);
1583 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1590 g_free(desc_info->desc_path);
1591 g_free(desc_info->desc_uuid);
1592 g_free(desc_info->desc_value);
1594 for (i = 0; i < desc_info->flags_length; i++)
1595 g_free(desc_info->desc_flags[i]);
1600 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1607 g_free(char_info->char_path);
1608 g_free(char_info->char_uuid);
1609 g_free(char_info->char_value);
1611 for (i = 0; i < char_info->flags_length; i++)
1612 g_free(char_info->char_flags[i]);
1617 static const GDBusInterfaceVTable desc_interface_vtable = {
1618 __bt_gatt_desc_method_call,
1623 static const GDBusInterfaceVTable char_interface_vtable = {
1624 __bt_gatt_char_method_call,
1629 static const GDBusInterfaceVTable serv_interface_vtable = {
1635 static const GDBusInterfaceVTable manager_interface_vtable = {
1636 __bt_gatt_manager_method_call,
1642 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1643 const gchar *introspection_data)
1646 GDBusNodeInfo *node_info = NULL;
1648 if (introspection_data == NULL)
1652 DBG("Create new node info");
1653 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1656 ERR("Unable to create node: %s", err->message);
1657 g_clear_error(&err);
1664 /* To send stack event to hal-av handler */
1665 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1670 void _bt_hal_unregister_gatt_server_handler_cb(void)
1675 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1677 struct hal_ev_gatt_desc_added ev;
1678 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1680 /* Prepare to GATT characteristic added event */
1681 memset(&ev, 0, sizeof(ev));
1682 ev.status = BT_STATUS_SUCCESS;
1683 ev.server_instance = data->instance_data;
1684 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1685 ev.service_handle = data->srvc_hdl;
1686 ev.desc_handle = data->desc_hdl;
1689 ERR("GATT Descriptor Added callback registered");
1691 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1692 data->instance_data, data->srvc_hdl, data->desc_hdl);
1694 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1701 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1703 struct hal_ev_gatt_char_added ev;
1704 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1706 /* Prepare to GATT characteristic added event */
1707 memset(&ev, 0, sizeof(ev));
1708 ev.status = BT_STATUS_SUCCESS;
1709 ev.server_instance = data->instance_data;
1710 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1711 ev.service_handle = data->srvc_hdl;
1712 ev.char_handle = data->char_hdl;
1715 ERR("GATT Characteristic Added callback registered");
1717 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1718 data->instance_data, data->srvc_hdl, data->char_hdl);
1720 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1727 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1729 struct hal_ev_gatt_service_added ev;
1730 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1732 /* Prepare to GATT Service added event */
1733 memset(&ev, 0, sizeof(ev));
1734 ev.status = BT_STATUS_SUCCESS;
1735 ev.server_instance = data->instance_data;
1736 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1737 ev.service_handle = data->srvc_hdl;
1738 ev.is_primary = data->is_primary;
1741 ERR("GATT Service Added callback registered");
1743 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1744 data->instance_data, data->srvc_hdl);
1745 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1752 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1754 struct hal_ev_gatt_service_started ev;
1755 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1757 /* Prepare to GATT Service added event */
1758 memset(&ev, 0, sizeof(ev));
1759 ev.status = BT_STATUS_SUCCESS;
1760 ev.server_instance = data->instance_data;
1761 ev.service_handle = data->srvc_hdl;
1764 ERR("GATT Service Started callback registered");
1766 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1767 data->instance_data, data->srvc_hdl);
1768 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1775 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1777 struct hal_ev_gatt_service_deleted ev;
1778 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1780 /* Prepare to GATT Service added event */
1781 memset(&ev, 0, sizeof(ev));
1782 ev.status = BT_STATUS_SUCCESS;
1783 ev.server_instance = data->instance_data;
1784 ev.service_handle = data->srvc_hdl;
1787 ERR("GATT Service Deleted callback registered");
1789 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1790 data->instance_data, data->srvc_hdl);
1791 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1798 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1800 struct hal_ev_server_instance_registered ev;
1801 hal_register_server_data *data = (hal_register_server_data*) user_data;
1803 /* Prepare to send AV connecting event */
1804 memset(&ev, 0, sizeof(ev));
1805 ev.status = BT_STATUS_SUCCESS;
1806 ev.server_instance = data->instance_data;
1807 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1810 ERR("GATT Register Server Instance Callback not registered");
1812 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1813 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1821 static int bt_hal_gatts_get_gatt_server_instance()
1826 struct hal_gatts_server_register_info_t *info = NULL;
1828 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1829 info = (struct hal_gatts_server_register_info_t *)l->data;
1834 return info->server_if;
1840 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_from_uuid(bt_uuid_t *app_uuid)
1845 struct hal_gatts_server_register_info_t *info = NULL;
1847 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1848 info = (struct hal_gatts_server_register_info_t *)l->data;
1853 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
1854 DBG("gatt server register found");
1862 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info(int server_if)
1865 struct hal_gatts_server_register_info_t *info = NULL;
1867 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1868 info = (struct hal_gatts_server_register_info_t *)l->data;
1873 if (info->server_if == server_if) {
1881 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_by_slot_id(int adv_slot_id)
1886 struct hal_gatts_server_register_info_t *info = NULL;
1888 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1889 info = (struct hal_gatts_server_register_info_t *)l->data;
1894 if (info->adv_slot_id == adv_slot_id) {
1895 DBG("gatt server register found");
1903 static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_uuid_t *app_uuid)
1905 struct hal_gatts_server_register_info_t * server_register_info = NULL;
1906 int instance_id = 0;
1908 server_register_info = bt_hal_gatts_find_server_register_info_from_uuid(app_uuid);
1909 if (server_register_info != NULL) {
1910 DBG("gatt server is already registered");
1911 return server_register_info;
1914 instance_id = __bt_hal_gatt_assign_id();
1915 if (instance_id == -1) {
1916 ERR("Fail to allocate the server if");
1920 server_register_info = g_malloc0(sizeof(struct hal_gatts_server_register_info_t));
1921 server_register_info->server_if = instance_id;
1923 DBG("Adding the gatt server app. server_if:[%d]", server_register_info->server_if);
1925 server_register_info->adv_slot_id = -1;
1926 memcpy(&server_register_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
1927 hal_gatts_server_register_list = g_slist_append(hal_gatts_server_register_list, server_register_info);
1929 return server_register_info;
1932 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1934 CHECK_BTGATT_INIT();
1935 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1937 DBG("Register server instance request");
1938 server_register_info = bt_hal_gatts_add_server_app(uuid);
1939 if (server_register_info == NULL) {
1940 ERR("Fail to register the server app");
1941 return BT_STATUS_FAIL;
1944 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1945 user_data->instance_data = server_register_info->server_if;
1948 * As we need to provide async callback to user from HAL, simply schedule a
1949 * callback method which will carry actual result
1951 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1952 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1954 /* If available, then return success, else return error */
1955 return BT_STATUS_SUCCESS;
1958 static void _bt_hal_remove_gatt_server_from_list(int server_if)
1961 struct gatt_server_app *info = NULL;
1963 for (l = gatt_server_apps; l != NULL;) {
1964 info = (struct gatt_server_app*)l->data;
1965 l = g_slist_next(l);
1968 if (info->slot == server_if) {
1969 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1970 info->app_path, info->slot);
1972 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1973 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1974 In above case, only advertising block will be deallocated, Gatt Server will remain
1976 if (info->services == NULL) {
1977 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1978 INFO("Total gatt server apps still existing after removing above is [%d]",
1979 g_slist_length(gatt_server_apps));
1981 /* DBUS Unregister only for current app */
1982 __bt_hal_gatt_deinit(info->app_path);
1984 g_free(info->app_path);
1988 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1989 g_slist_length(info->services));
1995 static bt_status_t gatt_server_unregister_app(int server_if)
1997 CHECK_BTGATT_INIT();
1998 DBG("Un-Register server instance request [%d]", server_if);
1999 struct hal_gatts_server_register_info_t *server_register_info = NULL;
2002 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
2003 if (server_register_info == NULL) {
2004 DBG("gatt server is not registered");
2005 return BT_STATUS_SUCCESS;
2008 /* remove the gatt server register info from the register list */
2009 hal_gatts_server_register_list = g_slist_remove(hal_gatts_server_register_list, server_register_info);
2010 g_free(server_register_info);
2012 __bt_hal_gatt_delete_id(server_if);
2014 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
2015 _bt_hal_remove_gatt_server_from_list(server_if);
2016 return BT_STATUS_SUCCESS;
2019 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
2021 CHECK_BTGATT_INIT();
2022 return BT_STATUS_SUCCESS;
2025 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
2028 GError *g_error = NULL;
2029 GVariant *reply = NULL;
2033 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2034 g_object_unref(proxy);
2035 if (reply == NULL) {
2036 ERR("Disconnect LE Dbus Call Error");
2038 ERR("Error: %s\n", g_error->message);
2039 g_clear_error(&g_error);
2042 g_variant_unref(reply);
2046 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
2048 CHECK_BTGATT_INIT();
2050 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2052 GDBusProxy *device_proxy;
2053 GDBusConnection *g_conn;
2054 struct gatt_client_info_t *conn_info = NULL;
2058 if (NULL == bd_addr) {
2059 ERR("bd_addr is NULL");
2060 return BT_STATUS_PARM_INVALID;
2063 /* GDBUS Connection Info validate */
2064 g_conn = _bt_hal_get_system_gconn();
2065 if (g_conn == NULL) {
2066 ERR("Could not get System DBUS Connection");
2067 return BT_STATUS_FAIL;
2070 /* Connection Info validate */
2071 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2072 if (conn_info == NULL) {
2073 ERR("No Connection Inforamtion!!!");
2074 return BT_STATUS_FAIL;
2077 _bt_hal_convert_addr_type_to_string(device_address,
2078 (unsigned char *)bd_addr->address);
2080 //check if connection has the same device address
2081 if (g_strcmp0(conn_info->addr, device_address) != 0) {
2082 ERR("device address [%s] does not match", device_address);
2083 return BT_STATUS_FAIL;
2086 device_path = _bt_hal_get_device_object_path(conn_info->addr);
2087 if (device_path == NULL) {
2088 ERR("device_path is NULL");
2089 return BT_STATUS_PARM_INVALID;
2092 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
2093 NULL, BT_HAL_BLUEZ_NAME,
2094 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2097 g_free(device_path);
2098 if (device_proxy == NULL)
2099 return BT_STATUS_FAIL;
2101 INFO("Disconnect LE [%s]", device_address);
2103 g_dbus_proxy_call(device_proxy, "DisconnectLE",
2105 G_DBUS_CALL_FLAGS_NONE,
2106 BT_HAL_MAX_DBUS_TIMEOUT,
2108 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
2111 return BT_STATUS_SUCCESS;
2114 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
2119 uuid = btuuid2str(srvc_id->uu);
2120 DBG("Original UUID [%s]", uuid);
2122 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
2123 /* Extract Standard UUID string */
2124 memcpy(uuid_buf, &uuid[4], 4);
2126 DBG("Converted string [%s]", uuid_buf);
2127 return g_strdup(uuid_buf);
2129 return strdup(uuid);
2132 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
2135 /* For GATT service specific */
2136 GDBusNodeInfo *node_info;
2139 struct gatt_service_info *serv_info = NULL;
2140 GVariantBuilder *builder = NULL;
2141 GVariantBuilder *builder1 = NULL;
2142 GVariantBuilder *inner_builder = NULL;
2143 gboolean svc_primary = TRUE;
2144 GError *error = NULL;
2145 hal_gatt_service_added *user_data = NULL;
2146 DBG("Service add to DBUS slot [%d]", slot);
2148 node_info = __bt_gatt_create_method_node_info(
2149 service_introspection_xml);
2151 if (node_info == NULL)
2152 return BT_STATUS_FAIL;
2154 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
2155 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
2156 DBG("gatt service path is [%s]", path);
2158 object_id = g_dbus_connection_register_object(g_conn, path,
2159 node_info->interfaces[0],
2160 &serv_interface_vtable,
2161 NULL, NULL, &error);
2163 if (object_id == 0) {
2164 ERR("failed to register: %s", error->message);
2165 g_error_free(error);
2167 return BT_STATUS_FAIL;
2169 /* Add object_id/gatt service information; it's required at the time of
2170 * service unregister and Getmanagedobjects
2172 serv_info = g_new0(struct gatt_service_info, 1);
2174 serv_info->serv_path = g_strdup(path);
2175 serv_info->serv_id = object_id;
2176 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
2177 serv_info->is_svc_registered = FALSE;
2178 serv_info->is_svc_primary = svc_primary;
2179 DBG("Service Handle to be added is [%d]", gatt_service_handle);
2180 serv_info->service_handle = gatt_service_handle;
2182 /* Update service in GATT Server service List */
2183 gatt_services = g_slist_append(gatt_services, serv_info);
2185 /* emit interfacesadded signal here for service path */
2186 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2187 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2189 g_variant_builder_add(inner_builder, "{sv}",
2190 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
2192 g_variant_builder_add(inner_builder, "{sv}",
2193 "Primary", g_variant_new_boolean(svc_primary));
2195 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2197 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
2198 g_variant_new("ao", builder1));
2200 g_variant_builder_add(builder, "{sa{sv}}",
2201 GATT_SERV_INTERFACE, inner_builder);
2203 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2204 "org.freedesktop.Dbus.ObjectManager", // TODO: need to check Dbus is working or not
2206 g_variant_new("(oa{sa{sv}})",
2211 /* dbus gives error cause */
2212 ERR("d-bus api failure: errcode[%x], message[%s]",
2213 error->code, error->message);
2214 g_clear_error(&error);
2218 /* Send Service handle to application */
2219 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2220 user_data->srvc_hdl = serv_info->service_handle;
2221 user_data->instance_data = slot;
2222 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2223 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2225 /* Save newly created service in GATT Server's service list */
2226 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2230 g_variant_builder_unref(inner_builder);
2231 g_variant_builder_unref(builder);
2232 g_variant_builder_unref(builder1);
2233 return BT_STATUS_SUCCESS;
2236 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2239 char *app_path = (char*)user_data;
2240 INFO("UnregisterApplication is completed app [%s]", app_path);
2241 GError *error = NULL;
2242 GVariant *result = NULL;
2245 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2247 if (result == NULL) {
2248 /* dBUS-RPC is failed */
2249 ERR("Dbus-RPC is failed\n");
2251 if (error != NULL) {
2252 /* dBUS gives error cause */
2253 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2254 error->code, error->message);
2255 g_clear_error(&error);
2258 g_variant_unref(result);
2263 static void __bt_hal_gatt_deinit(char *app_path)
2265 GDBusProxy *proxy = NULL;
2269 /* Step1: Remove requested App */
2270 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2271 "/org/bluez/hci0", "org.bluez.GattManager1");
2276 INFO("UnregisterApplication : path [%s]", app_path);
2278 /* Async Call to Unregister Service */
2279 data = g_strdup(app_path);
2280 g_dbus_proxy_call(proxy,
2281 "UnregisterApplication",
2282 g_variant_new("(o)",
2284 G_DBUS_CALL_FLAGS_NONE, -1,
2286 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2289 /* If requested app is last GATT Server app, then clean all resources */
2290 if (gatt_server_apps == NULL) {
2291 INFO("All GATT servers are removed, clean all DBUS resources");
2293 /* unregister the exported interface for object manager */
2294 g_dbus_connection_unregister_object(g_conn, manager_id);
2296 g_bus_unown_name(owner_id);
2299 g_object_unref(manager_gproxy);
2300 manager_gproxy = NULL;
2306 static int __bt_hal_gatt_init(void)
2310 /* Only once for ALL GATT Servers */
2311 if (owner_id == 0) {
2315 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2318 ERR("Unable to connect to gdbus: %s", err->message);
2319 g_clear_error(&err);
2321 return BT_STATUS_FAIL;
2324 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2325 INFO("well-known name: %s", name);
2327 owner_id = g_bus_own_name_on_connection(g_conn, name,
2328 G_BUS_NAME_OWNER_FLAGS_NONE,
2329 NULL, NULL, NULL, NULL);
2331 INFO("Owner ID [%d]", owner_id);
2333 /* Only once for ALL GATT Servers */
2334 if (manager_node_info == NULL) {
2335 /* Register ObjectManager interface */
2336 manager_node_info = __bt_gatt_create_method_node_info(
2337 manager_introspection_xml);
2339 if (manager_node_info == NULL) {
2340 ERR("failed to get node info");
2341 return BT_STATUS_FAIL;
2346 return BT_STATUS_SUCCESS;
2349 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2353 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2354 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2355 if (app->slot == slot) {
2356 INFO("GATT Server app found app path [%s] instance [%d]",
2357 app->app_path, app->slot);
2358 *app_path = app->app_path;
2362 /* GATT Server not found */
2366 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2368 if (app_path == NULL)
2371 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2372 app->app_path = g_strdup(app_path);
2374 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2375 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2378 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2381 CHECK_BTGATT_INIT();
2382 char *app_path = NULL;
2383 GError *error = NULL;
2386 int result = BT_STATUS_SUCCESS;
2388 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2389 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2391 /* Check if this GATT server Application is already registered with DBUS */
2392 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2394 if (app_path != NULL) {
2395 DBG("GATT server path is already defined [%s]", app_path);
2396 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2398 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2399 result = __bt_hal_gatt_init();
2400 if (result != BT_STATUS_SUCCESS)
2403 /* Only once for each GATT Server */
2404 app_path = g_strdup_printf("/com/%d", server_if);
2406 app_id = g_malloc0(sizeof(int));
2407 *app_id = server_if;
2409 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2410 manager_node_info->interfaces[0],
2411 &manager_interface_vtable,
2412 (gpointer)app_id, NULL, &error);
2414 if (manager_id == 0) {
2415 ERR("failed to register: %s", error->message);
2416 g_error_free(error);
2419 INFO("manager_id [%d]", manager_id);
2421 /* For current GATT Server, app_path is created, save it in Table */
2422 _bt_hal_update_gatt_server_path(server_if, app_path);
2424 /* Add GATT Service to DBUS */
2425 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2431 INFO("Successfully added service");
2432 return BT_STATUS_SUCCESS;
2439 INFO("Service addition failed!!");
2440 return BT_STATUS_FAIL;
2443 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2444 int included_handle)
2446 CHECK_BTGATT_INIT();
2447 return BT_STATUS_SUCCESS;
2451 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2454 GSList *gatt_services = NULL;
2456 struct gatt_service_info *info = NULL;
2458 gatt_services = _bt_get_service_list_from_server(instance);
2460 len = g_slist_length(gatt_services);
2461 l = g_slist_nth(gatt_services, len -1);
2467 if (info->service_handle == service_handle)
2472 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2476 GSList *gatt_services = NULL;
2477 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2479 gatt_services = _bt_get_service_list_from_server(instance);
2481 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2482 struct gatt_service_info *info = l->data;
2483 INFO("Got one service with handle [%d]", info->service_handle);
2484 if (info->service_handle == service_handle)
2487 ERR("Gatt service with handle [%d] not found", service_handle);
2491 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2492 bt_uuid_t *uuid, int properties,
2496 GError *error = NULL;
2498 GDBusNodeInfo *node_info;
2500 GVariantBuilder *builder = NULL;
2501 GVariantBuilder *inner_builder = NULL;
2502 struct gatt_service_info *serv_info = NULL;
2503 struct gatt_char_info *char_info = NULL;
2504 GVariantBuilder *builder2 = NULL;
2505 GVariantBuilder *builder3 = NULL;
2506 GVariant *flags_val = NULL;
2508 char *char_flags[NUMBER_OF_FLAGS];
2510 hal_gatt_char_added *user_data = NULL;
2513 CHECK_BTGATT_INIT();
2514 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2515 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2517 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2518 if (serv_info == NULL)
2519 return BT_STATUS_FAIL;
2521 node_info = __bt_gatt_create_method_node_info(
2522 characteristics_introspection_xml);
2524 if (node_info == NULL)
2525 return BT_STATUS_FAIL;
2527 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2528 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2529 DBG("gatt characteristic path is [%s]", path);
2531 app_id = g_malloc0(sizeof(int));
2534 object_id = g_dbus_connection_register_object(g_conn, path,
2535 node_info->interfaces[0],
2536 &char_interface_vtable,
2537 (gpointer)app_id, NULL, &error);
2539 if (object_id == 0) {
2540 ERR("failed to register: %s", error->message);
2541 g_error_free(error);
2544 return BT_STATUS_FAIL;
2547 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2548 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2549 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2550 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2551 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2552 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2553 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2554 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2556 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2558 char_info = g_new0(struct gatt_char_info, 1);
2560 char_info->char_path = g_strdup(path);
2561 char_info->char_id = object_id;
2562 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2563 for (i = 0; i < flag_count; i++)
2564 char_info->char_flags[i] = char_flags[i];
2567 char_info->flags_length = flag_count;
2568 char_info->char_handle = gatt_char_handle;
2571 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2572 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2574 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2575 g_variant_new("s", char_info->char_uuid));
2576 g_variant_builder_add(inner_builder, "{sv}", "Service",
2577 g_variant_new("o", serv_info->serv_path));
2579 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2581 for (i = 0; i < flag_count; i++)
2582 g_variant_builder_add(builder2, "s", char_flags[i]);
2584 flags_val = g_variant_new("as", builder2);
2585 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2588 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2590 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2591 g_variant_new("ao", builder3));
2593 g_variant_builder_add(builder, "{sa{sv}}",
2594 GATT_CHAR_INTERFACE,
2597 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2598 "org.freedesktop.Dbus.ObjectManager",
2600 g_variant_new("(oa{sa{sv}})",
2605 /* dbus gives error cause */
2606 ERR("d-bus api failure: errcode[%x], message[%s]",
2607 error->code, error->message);
2608 g_clear_error(&error);
2612 //*char_path = g_strdup(path);
2617 /* Send Service handle to application */
2618 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2619 user_data->srvc_hdl = serv_info->service_handle;
2620 user_data->char_hdl = gatt_char_handle;
2621 user_data->instance_data = slot;
2622 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2623 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2625 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2626 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2631 g_variant_builder_unref(inner_builder);
2632 g_variant_builder_unref(builder);
2633 g_variant_builder_unref(builder2);
2634 g_variant_builder_unref(builder3);
2636 return BT_STATUS_SUCCESS;
2639 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2642 CHECK_BTGATT_INIT();
2644 // static int desc_id = 1;
2645 GError *error = NULL;
2647 GDBusNodeInfo *node_info;
2649 GVariantBuilder *builder = NULL;
2650 GVariantBuilder *inner_builder = NULL;
2652 struct gatt_char_info *char_info = NULL;
2653 struct gatt_desc_info *desc_info = NULL;
2654 struct gatt_service_info *serv_info = NULL;
2656 gchar **line_argv = NULL;
2658 char *char_path = NULL;
2661 GVariantBuilder *builder2 = NULL;
2662 GVariant *flags_val = NULL;
2664 char *desc_flags[NUMBER_OF_FLAGS];
2667 hal_gatt_desc_added *user_data = NULL;
2669 /* Fetch service data for the GATT server */
2670 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2671 if (serv_info == NULL)
2672 return BT_STATUS_FAIL;
2674 /* Fetch list of characteristics from the service info */
2675 l = serv_info->char_data;
2677 /* Fetch last char info from the characteristic list */
2678 char_info = g_slist_last(l)->data;
2679 if (char_info == NULL)
2680 return BT_STATUS_FAIL;
2682 /* Fetch characteristic path from char info */
2683 char_path = char_info->char_path;
2685 line_argv = g_strsplit_set(char_path, "/", 0);
2686 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2689 node_info = __bt_gatt_create_method_node_info(
2690 descriptor_introspection_xml);
2692 if (node_info == NULL) {
2693 g_strfreev(line_argv);
2695 return BT_STATUS_FAIL;
2698 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2700 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2701 DBG("gatt descriptor path is [%s]", path);
2703 app_id = g_malloc0(sizeof(int));
2706 object_id = g_dbus_connection_register_object(g_conn, path,
2707 node_info->interfaces[0],
2708 &desc_interface_vtable,
2709 (gpointer)app_id, NULL, &error);
2711 if (object_id == 0) {
2712 ERR("failed to register: %s", error->message);
2713 g_error_free(error);
2715 g_strfreev(line_argv);
2718 return BT_STATUS_FAIL;
2721 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2723 desc_info = g_new0(struct gatt_desc_info, 1);
2725 desc_info->desc_path = g_strdup(path);
2726 desc_info->desc_id = object_id;
2727 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2729 for (i = 0; i < flag_count; i++)
2730 desc_info->desc_flags[i] = desc_flags[i];
2732 desc_info->flags_length = flag_count;
2733 desc_info->desc_handle = gatt_desc_handle;
2736 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2737 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2739 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2740 g_variant_new("s", btuuid2str(uuid->uu)));
2741 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2742 g_variant_new("o", char_path));
2744 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2746 for (i = 0; i < flag_count; i++)
2747 g_variant_builder_add(builder2, "s", desc_flags[i]);
2749 flags_val = g_variant_new("as", builder2);
2750 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2753 g_variant_builder_add(builder, "{sa{sv}}",
2754 GATT_DESC_INTERFACE,
2757 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2758 "org.freedesktop.Dbus.ObjectManager",
2760 g_variant_new("(oa{sa{sv}})",
2763 if (error != NULL) {
2764 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2765 error->code, error->message);
2766 g_clear_error(&error);
2769 //*desc_path = g_strdup(path);
2771 /* Save newly created descriptor to GATT server's service's characteristic */
2772 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2774 /* Send descriptor handle to application */
2775 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2776 user_data->srvc_hdl = serv_info->service_handle;
2777 user_data->desc_hdl = gatt_desc_handle;
2778 user_data->instance_data = slot;
2779 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2780 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2785 g_strfreev(line_argv);
2786 g_variant_builder_unref(inner_builder);
2787 g_variant_builder_unref(builder);
2788 return BT_STATUS_SUCCESS;
2791 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2793 GError *error = NULL;
2795 char *data = (char*) user_data;
2796 INFO("RegisterApplication is completed path [%s]", data);
2798 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2800 if (result == NULL) {
2801 /* dBUS-RPC is failed */
2802 ERR("Dbus-RPC is failed\n");
2804 if (error != NULL) {
2805 /* dBUS gives error cause */
2806 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2807 error->code, error->message);
2808 g_clear_error(&error);
2811 g_variant_unref(result);
2816 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2817 const gchar *path, const gchar *interface)
2823 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2828 ERR("Unable to connect to gdbus: %s", err->message);
2829 g_clear_error(&err);
2834 proxy = g_dbus_proxy_new_sync(g_conn,
2835 G_DBUS_PROXY_FLAGS_NONE, NULL,
2837 interface, NULL, &err);
2841 ERR("Unable to create proxy: %s", err->message);
2842 g_clear_error(&err);
2846 manager_gproxy = proxy;
2851 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2852 const gchar *path, const gchar *interface)
2854 return (manager_gproxy) ? manager_gproxy :
2855 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2859 static void __bt_register_application_to_dbus(int slot)
2861 GDBusProxy *proxy = NULL;
2862 char *app_path = NULL;
2864 DBG("RegisterApplication slot [%d]", slot);
2866 /* It is impossible that app path is still not initialized */
2867 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2869 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2870 "/org/bluez/hci0", "org.bluez.GattManager1");
2872 data = g_strdup(app_path);
2873 g_dbus_proxy_call(proxy,
2874 "RegisterApplication",
2875 g_variant_new("(oa{sv})",
2877 G_DBUS_CALL_FLAGS_NONE, -1,
2879 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2881 INFO("GATT server started");
2884 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2886 CHECK_BTGATT_INIT();
2887 struct gatt_service_info *serv_info = NULL;
2888 hal_gatt_service_started *user_data = NULL;
2889 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2891 /* Fetch service data for the GATT server */
2892 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2893 if (serv_info == NULL)
2894 return BT_STATUS_FAIL;
2896 if (serv_info->is_svc_registered)
2897 DBG("service already registered \n");
2899 serv_info->is_svc_registered = TRUE;
2901 /* Send Service handle to application */
2902 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2903 user_data->srvc_hdl = serv_info->service_handle;
2904 user_data->instance_data = server_if;
2905 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2907 /* If this is nth Service that is started, then register application at this point */
2908 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2909 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2911 __bt_register_application_to_dbus(server_if);
2914 return BT_STATUS_SUCCESS;
2917 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2919 CHECK_BTGATT_INIT();
2920 INFO("Stop service successful");
2921 return BT_STATUS_SUCCESS;
2924 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2926 CHECK_BTGATT_INIT();
2927 struct gatt_service_info *serv_info = NULL;
2928 hal_gatt_service_deleted *user_data = NULL;
2931 int err = BT_STATUS_SUCCESS;
2932 int ret = BT_STATUS_SUCCESS;
2933 char *app_path = NULL;
2934 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2936 /* Fetch service data for the GATT server */
2937 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2938 if (serv_info == NULL) {
2939 ERR("Could not find service info svc handle [%d] server slot [%d]",
2940 service_handle, server_if);
2941 return BT_STATUS_FAIL;
2944 app_path = __bt_get_server_app_path_from_server(server_if);
2945 if (app_path == NULL) {
2946 ERR("Could not find service info svc handle [%d] server slot [%d]",
2947 service_handle, server_if);
2948 return BT_STATUS_FAIL;
2951 if (serv_info->is_svc_registered == FALSE) {
2952 ERR("service Not registered path [%s] handle [%d]",
2953 serv_info->serv_path, service_handle);
2956 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2957 struct gatt_char_info *char_info = l->data;
2959 if (char_info == NULL)
2962 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2963 struct gatt_desc_info *desc_info = l1->data;
2965 if (desc_info == NULL)
2968 ret = g_dbus_connection_unregister_object(g_conn,
2969 desc_info->desc_id);
2971 __bt_hal_gatt_emit_interface_removed(
2973 desc_info->desc_path,
2974 GATT_DESC_INTERFACE);
2976 err = BT_STATUS_FAIL;
2979 /* list remove & free */
2980 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2981 __bt_hal_gatt_free_descriptor_info(desc_info);
2984 g_slist_free(char_info->desc_data);
2985 char_info->desc_data = NULL;
2987 ret = g_dbus_connection_unregister_object(g_conn,
2988 char_info->char_id);
2990 __bt_hal_gatt_emit_interface_removed(app_path, char_info->char_path,
2991 GATT_CHAR_INTERFACE);
2994 err = BT_STATUS_FAIL;
2997 /* list remove & free */
2998 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2999 __bt_hal_gatt_free_characteristic_info(char_info);
3002 g_slist_free(serv_info->char_data);
3003 serv_info->char_data = NULL;
3005 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
3007 __bt_hal_gatt_emit_interface_removed(app_path, serv_info->serv_path,
3008 GATT_SERV_INTERFACE);
3011 err = BT_STATUS_FAIL;
3014 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
3016 DBG("Unregistered the service on properties interface");
3018 /* Remove from global list */
3019 gatt_services = g_slist_remove(gatt_services, serv_info);
3020 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
3022 /* Remove from GATT Server's list of services */
3023 _bt_remote_service_from_gatt_server(server_if, service_handle);
3025 if (gatt_services == NULL)
3026 INFO("All GATT Services of all GATT Servers are unregistered");
3028 if (err == BT_STATUS_SUCCESS) {
3029 INFO("Send GATT Service deleted Event");
3030 /* Send Service handle to application */
3031 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
3032 user_data->srvc_hdl = serv_info->service_handle;
3033 user_data->instance_data = server_if;
3034 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
3037 /* Free the service */
3038 __bt_hal_gatt_free_service_info(serv_info);
3042 static gboolean __bt_gatt_get_service_state(const char *service_path)
3044 struct gatt_service_info *svc_info = NULL;
3046 for (l = gatt_services; l; l = g_slist_next(l)) {
3048 svc_info = (struct gatt_service_info *)l->data;
3050 if (!g_strcmp0(svc_info->serv_path, service_path))
3051 return svc_info->is_svc_registered;
3054 DBG("gatt service info is NULL");
3058 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
3059 int len, int confirm, char* p_value)
3061 CHECK_BTGATT_INIT();
3064 GVariantBuilder *outer_builder;
3065 GVariantBuilder *invalidated_builder;
3067 /* For Value update via PropertyChange */
3068 GVariantBuilder *outer_builder1;
3069 GVariantBuilder *inner_builder1;
3070 GVariantBuilder *invalidated_builder1;
3071 GVariant *update_value = NULL;
3073 /* Other variables */
3074 struct gatt_client_info_t *conn_info = NULL;
3075 gchar *serv_path = NULL;
3076 char *char_path = NULL;
3077 gchar **line_argv = NULL;
3078 gboolean notify = TRUE;
3079 gboolean ret = TRUE;
3080 int err = BT_STATUS_SUCCESS;
3082 GError *error = NULL;
3085 memset(addr, 0x00, sizeof(addr));
3087 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3088 if (conn_info == NULL) {
3089 ERR("No Connection Inforamtion!!!");
3090 return BT_STATUS_FAIL;
3093 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
3095 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3096 if (char_path == NULL)
3097 return BT_STATUS_FAIL;
3099 line_argv = g_strsplit_set(char_path, "/", 0);
3100 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3102 if (!__bt_gatt_get_service_state(serv_path)) {
3103 DBG("service not registered for this characteristic \n");
3105 g_strfreev(line_argv);
3106 return BT_STATUS_FAIL;
3109 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3110 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3112 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
3113 g_variant_new("b", notify));
3115 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
3116 DBG("Send Indication to Unicast addr [%s]", addr);
3118 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
3119 g_variant_new("s", addr));
3121 DBG("Set characteristic Notification \n");
3122 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3124 "org.freedesktop.DBus.Properties",
3125 "PropertiesChanged",
3126 g_variant_new("(sa{sv}as)",
3127 "org.bluez.GattCharacteristic1",
3128 outer_builder, invalidated_builder),
3132 if (error != NULL) {
3133 ERR("D-Bus API failure: errCode[%x], \
3135 error->code, error->message);
3136 g_clear_error(&error);
3138 err = BT_STATUS_FAIL;
3141 g_variant_builder_unref(outer_builder);
3142 g_variant_builder_unref(invalidated_builder);
3145 /* Notifying Done, now update Value to Bluez via PropertyChanged */
3146 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
3148 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3149 for (i = 0; i < len; i++)
3150 g_variant_builder_add(inner_builder1, "y", p_value[i]);
3152 update_value = g_variant_new("ay", inner_builder1);
3155 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3156 g_variant_builder_add(outer_builder1, "{sv}", "Value",
3159 DBG("Updating characteristic value \n");
3160 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3162 "org.freedesktop.DBus.Properties",
3163 "PropertiesChanged",
3164 g_variant_new("(sa{sv}as)",
3165 "org.bluez.GattCharacteristic1",
3166 outer_builder1, invalidated_builder1),
3170 if (error != NULL) {
3171 ERR("D-Bus API failure: errCode[%x], \
3173 error->code, error->message);
3174 g_clear_error(&error);
3176 err = BT_STATUS_FAIL;
3178 struct gatt_char_info *char_info = NULL;
3180 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3181 if (char_info == NULL) {
3183 g_strfreev(line_argv);
3184 g_variant_builder_unref(inner_builder1);
3185 g_variant_builder_unref(outer_builder1);
3186 g_variant_builder_unref(invalidated_builder1);
3188 return BT_STATUS_FAIL;
3191 char_info->value_length = len;
3193 char_info->char_value = (char *)realloc(char_info->char_value, len);
3194 if (char_info->char_value) {
3195 for (i = 0; i < len; i++)
3196 char_info->char_value[i] = p_value[i];
3201 g_strfreev(line_argv);
3202 g_variant_builder_unref(inner_builder1);
3203 g_variant_builder_unref(outer_builder1);
3204 g_variant_builder_unref(invalidated_builder1);
3209 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3210 int status, btgatt_response_t *response)
3212 CHECK_BTGATT_INIT();
3214 struct gatt_req_info *req_info = NULL;
3215 struct gatt_client_info_t *conn_info = NULL;
3218 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3219 if (conn_info == NULL) {
3220 ERR("No Connection Inforamtion. conn_id %d", conn_id);
3221 return BT_STATUS_FAIL;
3224 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3225 if (req_info == NULL) {
3226 ERR("No Request Inforamtion. conn_id %d", conn_id);
3227 return BT_STATUS_FAIL;
3230 if (status != BT_STATUS_SUCCESS) {
3231 ERR("resp_state is 0x%X, conn_id %d", status, conn_id);
3233 g_dbus_method_invocation_return_dbus_error(req_info->context,
3234 "org.bluez.Error.Failed", "Application Error");
3236 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3238 req_info->context = NULL;
3239 if (req_info->attr_path)
3240 g_free(req_info->attr_path);
3241 if (req_info->svc_path)
3242 g_free(req_info->svc_path);
3245 return BT_STATUS_SUCCESS;
3248 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3249 GVariantBuilder *inner_builder = NULL;
3250 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3252 if (response->attr_value.len > 0) {
3253 for (i = 0; i < response->attr_value.len; i++)
3254 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3256 g_dbus_method_invocation_return_value(req_info->context,
3257 g_variant_new("(ay)", inner_builder));
3259 g_variant_builder_unref(inner_builder);
3261 g_dbus_method_invocation_return_value(req_info->context, NULL);
3263 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3265 req_info->context = NULL;
3266 if (req_info->attr_path)
3267 g_free(req_info->attr_path);
3268 if (req_info->svc_path)
3269 g_free(req_info->svc_path);
3272 return BT_STATUS_SUCCESS;
3276 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3277 int status, int fd, int mtu, void *fdlist)
3279 CHECK_BTGATT_INIT();
3281 struct gatt_req_info *req_info = NULL;
3282 struct gatt_client_info_t *conn_info = NULL;
3284 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3286 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3287 if (conn_info == NULL) {
3288 ERR("No Connection Inforamtion!!!");
3289 return BT_STATUS_FAIL;
3292 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3293 if (req_info == NULL) {
3294 ERR("No Request Inforamtion!!!");
3295 return BT_STATUS_FAIL;
3298 if (status != BT_STATUS_SUCCESS) {
3299 ERR("resp_state is 0x%X", status);
3301 g_dbus_method_invocation_return_dbus_error(req_info->context,
3302 "org.bluez.Error.Failed", "Application Error");
3304 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3306 req_info->context = NULL;
3307 if (req_info->attr_path)
3308 g_free(req_info->attr_path);
3309 if (req_info->svc_path)
3310 g_free(req_info->svc_path);
3313 return BT_STATUS_SUCCESS;
3317 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3319 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3320 g_dbus_method_invocation_return_value_with_unix_fd_list(
3321 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3323 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3325 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3326 g_dbus_method_invocation_return_value_with_unix_fd_list(
3327 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3330 g_dbus_method_invocation_return_value(req_info->context, NULL);
3332 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3334 req_info->context = NULL;
3335 if (req_info->attr_path)
3336 g_free(req_info->attr_path);
3337 if (req_info->svc_path)
3338 g_free(req_info->svc_path);
3341 return BT_STATUS_SUCCESS;
3345 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3346 int value_length, char* att_value)
3348 CHECK_BTGATT_INIT();
3350 /* Other variables */
3351 char *char_path = NULL;
3352 gboolean ret = TRUE;
3353 GError *error = NULL;
3355 GVariantBuilder *outer_builder;
3356 GVariantBuilder *inner_builder;
3357 GVariantBuilder *invalidated_builder;
3358 GVariant *update_value = NULL;
3359 int err = BT_STATUS_SUCCESS;
3361 gchar **line_argv = NULL;
3362 gchar *serv_path = NULL;
3364 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3365 if (char_path == NULL)
3366 return BT_STATUS_FAIL;
3368 line_argv = g_strsplit_set(char_path, "/", 0);
3369 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3371 if (!__bt_gatt_get_service_state(serv_path)) {
3372 DBG("service not registered for this characteristic \n");
3374 g_strfreev(line_argv);
3375 return BT_STATUS_FAIL;
3379 line_argv = g_strsplit_set(char_path, "/", 0);
3380 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3382 if (!__bt_gatt_get_service_state(serv_path)) {
3383 DBG("service not registered for this characteristic \n");
3385 g_strfreev(line_argv);
3386 return BT_STATUS_FAIL;
3389 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3390 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3392 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3393 for (i = 0; i < value_length; i++)
3394 g_variant_builder_add(inner_builder, "y", att_value[i]);
3396 update_value = g_variant_new("ay", inner_builder);
3398 g_variant_builder_add(outer_builder, "{sv}", "Value",
3401 DBG("Updating characteristic value \n");
3402 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3404 "org.freedesktop.DBus.Properties",
3405 "PropertiesChanged",
3406 g_variant_new("(sa{sv}as)",
3407 "org.bluez.GattCharacteristic1",
3408 outer_builder, invalidated_builder),
3412 if (error != NULL) {
3413 ERR("D-Bus API failure: errCode[%x], \
3415 error->code, error->message);
3416 g_clear_error(&error);
3418 err = BT_STATUS_FAIL;
3420 struct gatt_char_info *char_info = NULL;
3422 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3423 if (char_info == NULL) {
3425 g_strfreev(line_argv);
3426 g_variant_builder_unref(inner_builder);
3427 g_variant_builder_unref(outer_builder);
3428 g_variant_builder_unref(invalidated_builder);
3430 return BT_STATUS_FAIL;
3433 char_info->value_length = value_length;
3435 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3436 if (char_info->char_value) {
3437 for (i = 0; i < value_length; i++)
3438 char_info->char_value[i] = att_value[i];
3444 g_strfreev(line_argv);
3445 g_variant_builder_unref(inner_builder);
3446 g_variant_builder_unref(outer_builder);
3447 g_variant_builder_unref(invalidated_builder);
3452 static bt_status_t gatt_server_listen(int server_if, bool start)
3454 CHECK_BTGATT_INIT();
3456 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3458 DBG("server_if: [%d]", server_if);
3460 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3461 if (server_register_info == NULL) {
3462 DBG("gatt server is not registered");
3463 return BT_STATUS_FAIL;
3466 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3468 if (server_register_info->adv_slot_id < 0 ) {
3469 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3470 return BT_STATUS_FAIL;
3473 /* Send Data to LE Module */
3474 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, start, FALSE);
3477 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3478 bool include_txpower, int min_interval, int max_interval, int appearance,
3479 uint16_t manufacturer_len, char* manufacturer_data,
3480 uint16_t service_data_len, char* service_data,
3481 uint16_t service_uuid_len, char* service_uuid)
3483 CHECK_BTGATT_INIT();
3484 return BT_STATUS_SUCCESS;
3487 static int bt_hal_gatts_allocate_adv_slot(struct hal_gatts_server_register_info_t *server_register_info)
3489 int adv_slot_id = -1;
3491 /* allocate adv slot for gatt server if not assigned */
3492 if (server_register_info->adv_slot_id < 0 ) {
3493 adv_slot_id = _bt_hal_get_available_adv_slot_id(&server_register_info->app_uuid, FALSE);
3494 if (adv_slot_id < 0) {
3495 ERR("failed to get the adv_slot");
3499 server_register_info->adv_slot_id = adv_slot_id;
3502 DBG("gatt server:[%d] Assigned adv_slot [%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3507 int bt_hal_gatts_allocate_adv_slot_by_server_if(int server_if)
3509 CHECK_BTGATT_INIT();
3513 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3515 DBG("server_if: [%d]", server_if);
3517 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3518 if (server_register_info == NULL) {
3519 DBG("gatt server is not registered");
3523 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3525 if (server_register_info->adv_slot_id < 0 ) {
3526 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3528 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3530 DBG("failed to get adv_slot");
3535 return server_register_info->adv_slot_id;
3538 void bt_hal_gatts_release_adv_slot(int server_if)
3540 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3542 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3543 if (server_register_info == NULL) {
3544 ERR("failed to get server_register_info");
3548 if (server_register_info->adv_slot_id < 0) {
3549 ERR("adv_slot is not allocated");
3553 if(_bt_hal_is_advertising_in_slot(server_register_info->adv_slot_id) == FALSE) {
3554 DBG("advertising is disabled");
3555 _bt_hal_free_server_slot(server_register_info->adv_slot_id);
3556 server_register_info->adv_slot_id = -1;
3560 int bt_hal_gatts_get_adv_slot_id(int server_if)
3562 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3564 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3565 if (server_register_info == NULL) {
3566 DBG("failed to get server_register_info");
3570 return server_register_info->adv_slot_id;
3573 int bt_hal_gatts_get_server_if(int slot_id)
3575 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3577 server_register_info = bt_hal_gatts_find_server_register_info_by_slot_id(slot_id);
3578 if (server_register_info == NULL) {
3579 DBG("failed to get server_register_info");
3583 return server_register_info->server_if;
3586 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3588 CHECK_BTGATT_INIT();
3592 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3594 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3595 if (server_register_info == NULL) {
3596 ERR("gatt server is not registered");
3597 return BT_STATUS_FAIL;
3600 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3602 if (server_register_info->adv_slot_id < 0 ) {
3603 DBG("adv_slot is not assigned to server:[%d]", server_if);
3605 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3607 ERR("failed to get adv_slot");
3608 return BT_STATUS_FAIL;
3612 /* Send Enable Advertising request to LE Module */
3613 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, TRUE, TRUE);
3616 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3617 int chnl_map, int tx_power, int timeout_s)
3619 CHECK_BTGATT_INIT();
3621 /* Send Advertising parameters to LE Module */
3622 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3623 chnl_map, tx_power, timeout_s);
3626 static bt_status_t gatt_server_set_filter_policy(int filter_policy)
3628 CHECK_BTGATT_INIT();
3630 /* Send the Filter policy parameter to LE Module */
3631 _bt_hal_set_filter_policy_param(filter_policy);
3632 return BT_STATUS_SUCCESS;
3635 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3637 CHECK_BTGATT_INIT();
3639 /* Send Data to LE Module */
3640 return _bt_hal_set_advertising_data(adv_param_setup);
3643 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3645 CHECK_BTGATT_INIT();
3647 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3649 DBG("server_if: [%d]", server_if);
3651 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3652 if (server_register_info == NULL) {
3653 DBG("gatt server is not registered");
3654 return BT_STATUS_FAIL;
3657 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3659 if (server_register_info->adv_slot_id < 0 ) {
3660 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3661 return BT_STATUS_FAIL;
3664 /* Send Data to LE Module */
3665 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, FALSE, TRUE);
3668 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3670 CHECK_BTGATT_INIT();
3671 char *object_path = NULL;
3673 GDBusProxy *device_proxy;
3674 GError *error = NULL;
3676 GVariant *tmp_value;
3677 GDBusConnection *conn;
3678 GVariant *result = NULL;
3679 int ret = BT_STATUS_SUCCESS;
3680 struct gatt_client_info_t *conn_info = NULL;
3683 if (mtu_size == NULL)
3684 return BT_STATUS_PARM_INVALID;
3686 /* GDBUS Connection Info validate */
3687 conn = _bt_hal_get_system_gconn();
3689 ERR("Could not get System DBUS Connection");
3690 return BT_STATUS_FAIL;
3693 /* Connection Info validate */
3694 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3695 if (conn_info == NULL) {
3696 ERR("No Connection Inforamtion!!!");
3697 return BT_STATUS_FAIL;
3701 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3702 if (object_path == NULL)
3703 return BT_STATUS_FAIL;
3705 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3706 NULL, BT_HAL_BLUEZ_NAME, object_path,
3707 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3709 g_free(object_path);
3710 if (device_proxy == NULL)
3711 return BT_STATUS_FAIL;
3713 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3714 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3715 G_DBUS_CALL_FLAGS_NONE,
3719 if (result == NULL) {
3720 if (error != NULL) {
3721 ERR("Error occured in Proxy call [%s]\n", error->message);
3722 g_error_free(error);
3724 g_object_unref(device_proxy);
3725 return BT_STATUS_FAIL;
3728 g_variant_get(result , "(@a{sv})", &value);
3729 g_variant_unref(result);
3731 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3732 if (tmp_value == NULL) {
3733 g_object_unref(device_proxy);
3734 g_variant_unref(value);
3735 return BT_STATUS_FAIL;
3738 mtu = g_variant_get_uint16(tmp_value);
3740 DBG("ATT MTU : [%d]", mtu);
3742 g_variant_unref(tmp_value);
3743 g_variant_unref(value);
3744 g_object_unref(device_proxy);
3746 *mtu_size = (int) mtu;
3751 const btgatt_server_interface_t btgatt_server_interface = {
3752 .register_server = gatt_server_register_app,
3753 .unregister_server = gatt_server_unregister_app,
3754 .connect = gatt_server_open,
3755 .disconnect = gatt_server_close,
3756 .add_service = gatt_server_add_service,
3757 .add_included_service = gatt_server_add_included_service,
3758 .add_characteristic = gatt_server_add_characteristic,
3759 .add_descriptor = gatt_server_add_descriptor,
3760 .start_service = gatt_server_start_service,
3761 .stop_service = gatt_server_stop_service,
3762 .delete_service = gatt_server_delete_service,
3763 .send_indication = gatt_server_send_indication,
3764 .send_response = gatt_server_send_response,
3765 .update_att_value = gatt_server_update_att_value,
3766 .listen = gatt_server_listen,
3767 .set_adv_data = gatt_server_set_adv_data,
3768 .multi_adv_enable = gatt_server_multi_adv_enable,
3769 .multi_adv_update = gatt_server_multi_adv_update,
3770 .set_filter_policy = gatt_server_set_filter_policy,
3771 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3772 .multi_adv_disable = gatt_server_multi_adv_disable,
3773 .get_att_mtu = gatt_server_get_mtu_size,
3774 .send_response_acquire = gatt_server_send_acquire_response