4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include <hardware/bluetooth.h>
23 #include <hardware/bt_gatt.h>
38 #include "bt-hal-log.h"
39 #include "bt-hal-msg.h"
40 #include "bt-hal-utils.h"
41 #include "bt-hal-dbus-common-utils.h"
43 #include "bt-hal-adapter-le.h"
44 #include "bt-hal-event-receiver.h"
46 #define NUMBER_OF_FLAGS 10
48 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
49 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
50 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
52 #define BT_GATT_SERVICE_NAME "org.frwk.gatt_service"
53 #define GATT_SERV_OBJECT_PATH "/service"
55 static GDBusProxy *manager_gproxy = NULL;
57 /************************************************************************************
59 ************************************************************************************/
60 extern const btgatt_callbacks_t *bt_gatt_callbacks;
62 GDBusConnection *g_conn = NULL;
63 //GDBusConnection *conn = NULL;
64 GDBusNodeInfo *manager_node_info = NULL;
67 /* Global handles which needs to be incremented during each addition */
68 static int gatt_service_handle = 10;
69 static int gatt_char_handle = 20;
70 static int gatt_desc_handle = 30;
72 struct gatt_service_info {
79 gboolean is_svc_registered;
80 gboolean is_svc_primary;
84 struct gatt_char_info {
89 gchar *char_flags[NUMBER_OF_FLAGS];
96 struct gatt_desc_info {
101 gchar *desc_flags[NUMBER_OF_FLAGS];
108 * GATT Server Request type
111 BT_HAL_GATT_REQUEST_TYPE_READ = 0x00, /* Read Requested */
112 BT_HAL_GATT_REQUEST_TYPE_WRITE = 0x01, /* Write Requested */
113 BT_HAL_GATT_REQUEST_TYPE_EXEC_WRITE = 0x02, /* Exec Write Requested */
114 BT_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_gatt_callbacks == NULL)\
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 void _bt_hal_gatt_server_init(void)
348 memset(instance_id_used, 0x00, sizeof(instance_id_used));
351 static int __bt_hal_gatt_assign_id(void)
355 index = assigned_id + 1;
357 if (index >= BT_GATTS_MAX)
360 while (instance_id_used[index] == TRUE) {
361 if (index == assigned_id) {
362 /* No available ID */
363 ERR("All interface ID is used");
369 if (index >= BT_GATTS_MAX)
374 instance_id_used[index] = TRUE;
379 static void __bt_hal_gatt_delete_id(int instance_id)
381 if (instance_id >= BT_GATTS_MAX || instance_id < 0)
384 instance_id_used[instance_id] = FALSE;
387 static GSList *_bt_get_service_list_from_server(int instance)
390 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
391 INFO("Find App with slot [%d]", instance);
393 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
394 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
396 if (app->slot == instance) {
397 INFO("App slot [%d] Found, Number of services registered [%d]",
398 app->slot, g_slist_length(app->services));
399 return app->services;
405 static char *__bt_get_server_app_path_from_server(int instance)
408 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
409 INFO("Find App with slot [%d]", instance);
411 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
412 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
414 if (app->slot == instance) {
415 INFO("App slot [%d] Found, App path [%s]",
416 app->slot, app->app_path);
417 return app->app_path;
423 static void _bt_remote_service_from_gatt_server(int instance, int service_handle)
428 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
429 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
431 if (app->slot == instance) {
432 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
433 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
434 if (srv->service_handle == service_handle) {
435 app->services = g_slist_remove(app->services, srv);
443 static void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
446 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
447 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
449 if (app->slot == slot) {
450 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
451 serv_info->service_handle, slot);
452 app->services = g_slist_append(app->services, serv_info);
457 int _bt_get_remote_gatt_client_conn_id(char *address)
460 struct gatt_client_info_t *info = NULL;
462 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
463 info = (struct gatt_client_info_t*)l->data;
467 if (!g_strcmp0(info->addr, address)) {
468 INFO("Remote GATT client found addr[%s]", info->addr);
469 return info->connection_id;
475 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
478 struct gatt_client_info_t *info = NULL;
480 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
481 info = (struct gatt_client_info_t*)l->data;
485 if (!g_strcmp0(info->addr, address))
491 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
494 struct gatt_client_info_t *info = NULL;
496 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
497 info = (struct gatt_client_info_t*)l->data;
501 if (info->connection_id == conn_id)
507 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
512 struct gatt_client_info_t *info = NULL;
513 struct gatt_req_info *info1 = NULL;
515 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
516 info = (struct gatt_client_info_t*)l->data;
520 if (info->connection_id == conn_id) {
522 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
524 info1 = (struct gatt_req_info*)l1->data;
528 if (info1->request_id == trans_id)
536 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
538 struct hal_ev_gatt_server_connected ev;
539 struct gatt_client_info_t *conn_info = NULL;
540 memset(&ev, 0, sizeof(ev));
542 /* Convert address to hex */
543 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
545 /* Create Connection ID */
546 /* Check if device is already in connected list */
547 conn_info = __bt_find_remote_gatt_client_info(address);
549 /* If disconnected, and conn info found, then remove conn info */
550 if (is_connected == FALSE) {
551 DBG("GATT Disconnected");
553 INFO("Remove GATT client info from List..");
554 /* Remove info from List */
555 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
556 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
559 ERR("GATT callback not registered");
561 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
562 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
563 ev.conn_id = conn_info->connection_id;
564 ev.server_instance = conn_info->instance_id;
565 ev.connected = is_connected;
567 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
569 g_free(conn_info->addr);
572 /* If connected, and conn info NOT found, then add conn info */
576 /* Find Server Instance */
577 instance = bt_hal_gatts_get_gatt_server_instance();
578 if (instance == -1) {
579 ERR("Not even a single GATT server is registered");
580 ev.conn_id = ++hal_gatt_conn_id;
581 ev.server_instance = -1;
582 ev.connected = is_connected;
583 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
586 DBG("server instance [%d]", instance);
589 /* Save Connection info */
590 conn_info = g_new0(struct gatt_client_info_t, 1);
591 conn_info->addr = g_strdup(address);
592 DBG("Added GATT client addr[%s]", conn_info->addr);
593 conn_info->connection_id = ++hal_gatt_conn_id;
594 conn_info->instance_id = instance;
595 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
596 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
599 ERR("GATT callback not registered");
601 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
602 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
603 ev.conn_id = conn_info->connection_id;
604 ev.server_instance = conn_info->instance_id;
605 ev.connected = is_connected;
607 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
610 ERR("Abnormal case. conn_info should be NULL");
613 /* Send GATT connected or disconnected event */
616 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
620 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
621 struct gatt_service_info *serv_info = l1->data;
623 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
624 struct gatt_char_info *char_info = l2->data;
626 if (g_strcmp0(char_info->char_path, char_path)
628 *char_hdl = char_info->char_handle;
633 ERR("Gatt service not found");
637 static char *__bt_gatt_find_char_path_from_handle(int char_hdl)
641 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
642 struct gatt_service_info *serv_info = l1->data;
644 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
645 struct gatt_char_info *char_info = l2->data;
647 if (char_info->char_handle == char_hdl)
648 return char_info->char_path;
655 static struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
659 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
660 struct gatt_service_info *serv_info = l1->data;
662 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
663 struct gatt_char_info *char_info = l2->data;
665 if (char_info->char_handle == char_hdl)
673 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
675 GSList *l1, *l2, *l3;
677 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
678 struct gatt_service_info *serv_info = l1->data;
680 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
681 struct gatt_char_info *char_info = l2->data;
683 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
684 struct gatt_desc_info *desc_info = l3->data;
686 if (g_strcmp0(desc_info->desc_path, desc_path)
688 *desc_hdl = desc_info->desc_handle;
694 ERR("Gatt service not found");
698 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
700 const gchar *object_path,
701 const gchar *interface_name,
702 const gchar *method_name,
703 GVariant *parameters,
704 GDBusMethodInvocation *invocation,
709 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
710 GVariantBuilder *builder;
711 GVariantBuilder *inner_builder1 = NULL;
712 GVariant *svc_char = NULL;
714 GSList *gatt_services = NULL;
716 instance = (int*)user_data;
717 gboolean writeAcquired = FALSE;
718 gboolean notifyAcquired = FALSE;
720 DBG("Getting values for service, chars and descriptors");
721 DBG("GATT Server App for which services are requested [%d]", *instance);
724 builder = g_variant_builder_new(
725 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
728 gatt_services = _bt_get_service_list_from_server(*instance);
730 if (g_slist_length(gatt_services) == 0) {
731 ERR("No registered GATT services!!!!");
732 g_dbus_method_invocation_return_value(invocation, NULL);
733 g_variant_builder_unref(builder);
737 for (l = gatt_services; l != NULL; l = l->next) {
738 GVariantBuilder *svc_builder = NULL;
739 GVariantBuilder *inner_builder = NULL;
740 struct gatt_service_info *serv_info = l->data;
741 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
743 /* Prepare inner builder for GattService1 interface */
744 DBG("Creating builder for service");
745 svc_builder = g_variant_builder_new(
746 G_VARIANT_TYPE("a{sa{sv}}"));
747 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
749 g_variant_builder_add(inner_builder, "{sv}", "UUID",
750 g_variant_new_string(serv_info->service_uuid));
752 g_variant_builder_add(inner_builder, "{sv}", "Primary",
753 g_variant_new_boolean(serv_info->is_svc_primary));
756 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
757 DBG("Adding Charatarisitcs list");
758 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
759 struct gatt_char_info *char_info = l4->data;
760 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
761 char_info->char_handle, serv_info->service_handle);
762 g_variant_builder_add(inner_builder1, "o",
763 char_info->char_path);
764 DBG("%s", char_info->char_path);
767 svc_char = g_variant_new("ao", inner_builder1);
768 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
771 g_variant_builder_add(svc_builder, "{sa{sv}}",
775 g_variant_builder_add(builder, "{oa{sa{sv}}}",
776 serv_info->serv_path,
779 g_variant_builder_unref(inner_builder1);
781 /* Prepare inner builder for GattCharacteristic1 interface */
783 GSList *l2 = serv_info->char_data;
784 DBG("Creating builder for characteristics \n");
787 DBG("characteristic data is NULL");
789 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
791 GVariantBuilder *char_builder = NULL;
792 GVariantBuilder *inner_builder = NULL;
793 GVariantBuilder *builder1 = NULL;
794 GVariantBuilder *builder2 = NULL;
795 GVariantBuilder *builder3 = NULL;
796 GVariant *char_val = NULL;
797 GVariant *flags_val = NULL;
798 GVariant *char_desc = NULL;
799 char *unicast = NULL;
800 gboolean notify = FALSE;
803 char_builder = g_variant_builder_new(
806 inner_builder = g_variant_builder_new(
810 struct gatt_char_info *char_info = l2->data;
811 if (char_info == NULL) {
812 ERR("char_info is NULL");
817 g_variant_builder_add(inner_builder, "{sv}", "UUID",
818 g_variant_new_string(char_info->char_uuid));
820 g_variant_builder_add(inner_builder, "{sv}", "Service",
821 g_variant_new("o", serv_info->serv_path));
823 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
825 if (char_info->char_value != NULL) {
826 for (i = 0; i < char_info->value_length; i++) {
827 g_variant_builder_add(builder1, "y",
828 char_info->char_value[i]);
830 char_val = g_variant_new("ay", builder1);
831 g_variant_builder_add(inner_builder, "{sv}",
835 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
836 for (i = 0; i < char_info->flags_length; i++) {
837 g_variant_builder_add(builder2, "s",
838 char_info->char_flags[i]);
840 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
841 DBG("setting WriteAcquired property");
842 writeAcquired = TRUE;
845 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
846 DBG("setting NotifyAcquired property");
847 notifyAcquired = TRUE;
851 flags_val = g_variant_new("as", builder2);
852 g_variant_builder_add(inner_builder, "{sv}", "Flags",
856 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
857 g_variant_new("b", notify));
860 if (writeAcquired == TRUE) {
861 DBG("adding WriteAcquired property");
862 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
863 g_variant_new("b", writeAcquired));
867 if (notifyAcquired == TRUE) {
868 DBG("adding NotifyAcquired property");
869 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
870 g_variant_new("b", notifyAcquired));
874 unicast = g_strdup("00:00:00:00:00:00");
875 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
876 g_variant_new("s", unicast));
879 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
880 DBG("Adding Descriptors list");
882 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
883 struct gatt_desc_info *desc_info = l4->data;
884 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
885 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
886 g_variant_builder_add(builder3, "o",
887 desc_info->desc_path);
888 DBG("%s", desc_info->desc_path);
891 char_desc = g_variant_new("ao", builder3);
892 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
895 g_variant_builder_add(char_builder, "{sa{sv}}",
896 GATT_CHAR_INTERFACE , inner_builder);
897 g_variant_builder_add(builder, "{oa{sa{sv}}}",
898 char_info->char_path, char_builder);
900 /*Prepare inner builder for GattDescriptor1 interface*/
902 GSList *l3 = char_info->desc_data;
905 DBG("descriptor data is NULL");
907 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
909 DBG("Creating builder for descriptor \n");
911 GVariantBuilder *desc_builder = NULL;
912 GVariantBuilder *inner_builder = NULL;
913 GVariantBuilder *builder1 = NULL;
914 GVariantBuilder *builder2 = NULL;
915 GVariant *desc_val = NULL;
917 desc_builder = g_variant_builder_new(
920 inner_builder = g_variant_builder_new(
924 struct gatt_desc_info *desc_info = l3->data;
925 if (desc_info == NULL) {
926 ERR("desc_info is NULL");
931 g_variant_builder_add(inner_builder,
933 g_variant_new_string(
934 desc_info->desc_uuid));
937 g_variant_builder_add(inner_builder, "{sv}",
940 char_info->char_path));
943 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
945 if (desc_info->desc_value != NULL) {
946 for (i = 0; i < desc_info->value_length; i++) {
947 g_variant_builder_add(builder1, "y",
948 desc_info->desc_value[i]);
950 desc_val = g_variant_new("ay", builder1);
951 g_variant_builder_add(inner_builder, "{sv}",
956 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
958 for (i = 0; i < desc_info->flags_length; i++) {
959 g_variant_builder_add(builder2, "s",
960 desc_info->desc_flags[i]);
963 flags_val = g_variant_new("as", builder2);
964 g_variant_builder_add(inner_builder, "{sv}", "Flags",
967 g_variant_builder_add(desc_builder, "{sa{sv}}",
971 g_variant_builder_add(builder, "{oa{sa{sv}}}",
972 desc_info->desc_path,
975 /*unref descriptor builder pointers*/
976 g_variant_builder_unref(builder1);
977 g_variant_builder_unref(builder2);
978 g_variant_builder_unref(inner_builder);
979 g_variant_builder_unref(desc_builder);
984 /*unref char builder pointers*/
985 g_variant_builder_unref(builder1);
986 g_variant_builder_unref(builder2);
987 g_variant_builder_unref(builder3);
988 g_variant_builder_unref(inner_builder);
989 g_variant_builder_unref(char_builder);
992 /*unref service builder pointers*/
993 g_variant_builder_unref(inner_builder);
994 g_variant_builder_unref(svc_builder);
997 /* Return builder as method reply */
998 DBG("Sending gatt service builder values to Bluez");
999 g_dbus_method_invocation_return_value(invocation,
1005 /* Free User Data */
1009 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
1010 const gchar *sender,
1011 const gchar *object_path,
1012 const gchar *interface_name,
1013 const gchar *method_name,
1014 GVariant *parameters,
1015 GDBusMethodInvocation *invocation,
1019 if (g_strcmp0(method_name, "ReadValue") == 0) {
1020 struct hal_ev_gatt_server_read_req ev;
1025 struct gatt_client_info_t *conn_info = NULL;
1026 struct gatt_req_info *req_info = NULL;
1027 struct gatt_service_info *svc_info = NULL;
1031 DBG("Application path = %s", object_path);
1032 DBG("Sender = %s", sender);
1034 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1035 if (svc_info == NULL) {
1036 ERR("Coudn't find service for %s", object_path);
1037 g_dbus_method_invocation_return_value(invocation, NULL);
1041 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1042 DBG("Request id = %u, Offset = %u", req_id, offset);
1044 /* Check if device is already in connected list */
1045 conn_info = __bt_find_remote_gatt_client_info(addr);
1047 if (conn_info == NULL) {
1048 ERR("Coudn't find Connection info for %s", addr);
1049 g_dbus_method_invocation_return_value(invocation, NULL);
1054 ERR("GATT callback NOT registered");
1055 g_dbus_method_invocation_return_value(invocation, NULL);
1059 /* Store requests information */
1060 req_info = g_new0(struct gatt_req_info, 1);
1061 req_info->attr_path = g_strdup(object_path);
1062 req_info->svc_path = g_strdup(svc_info->serv_path);
1063 req_info->request_id = req_id;
1064 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1065 req_info->offset = offset;
1066 req_info->context = invocation;
1068 /* Append request info in list of requests for the particular connection */
1069 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1071 /* Send HAL event */
1072 memset(&ev, 0, sizeof(ev));
1073 ev.conn_id = conn_info->connection_id;
1074 ev.trans_id = req_id;
1075 ev.att_handle = desc_hdl;
1077 ev.is_long = false; /* TODO*/
1079 /* Convert address to hex */
1080 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1082 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1084 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1086 GVariant *var = NULL;
1090 gboolean response_needed = FALSE;
1091 struct hal_ev_gatt_server_write_req ev;
1095 struct gatt_service_info *svc_info = NULL;
1096 struct gatt_client_info_t *conn_info = NULL;
1097 struct gatt_req_info *req_info = NULL;
1099 memset(&ev, 0, sizeof(ev));
1102 DBG("Application path = %s", object_path);
1103 DBG("Sender = %s", sender);
1105 g_variant_get(parameters, "(&suqb@ay)",
1106 &addr, &req_id, &offset, &response_needed, &var);
1107 DBG("Request id = %u, Offset = %u", req_id, offset);
1109 /* Check if device is already in connected list */
1110 conn_info = __bt_find_remote_gatt_client_info(addr);
1112 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1114 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1115 g_variant_unref(var);
1116 if (response_needed)
1117 g_dbus_method_invocation_return_value(invocation, NULL);
1119 g_object_unref(invocation);
1123 len = g_variant_get_size(var);
1124 if (len > 0 && len < 600) {
1126 data = (char *)g_variant_get_data(var);
1127 memcpy(ev.value, data, len);
1130 if (response_needed) {
1131 /* Store request information */
1132 req_info = g_new0(struct gatt_req_info, 1);
1133 req_info->attr_path = g_strdup(object_path);
1134 req_info->svc_path = g_strdup(svc_info->serv_path);
1135 req_info->request_id = req_id;
1136 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1137 req_info->offset = offset;
1138 req_info->context = invocation;
1140 /* Append request info in list of requests for the particular connection */
1141 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1143 g_object_unref(invocation);
1146 /* Send HAL event */
1147 ev.conn_id = conn_info->connection_id;
1148 ev.trans_id = req_id;
1149 ev.att_handle = desc_hdl;
1151 ev.need_rsp = response_needed;
1154 /* Convert address to hex */
1155 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1157 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1159 g_variant_unref(var);
1164 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1165 const gchar *sender,
1166 const gchar *object_path,
1167 const gchar *interface_name,
1168 const gchar *method_name,
1169 GVariant *parameters,
1170 GDBusMethodInvocation *invocation,
1173 if (g_strcmp0(method_name, "ReadValue") == 0) {
1177 struct hal_ev_gatt_server_read_req ev;
1180 struct gatt_req_info *req_info = NULL;
1181 struct gatt_client_info_t *conn_info = NULL;
1182 struct gatt_service_info *svc_info = NULL;
1184 g_variant_get(parameters, "(&suq)",
1185 &addr, &req_id, &offset);
1187 DBG("ReadValue : req id %u, offset %u, path %s, sender %s, %s", req_id, offset, object_path, sender, addr);
1189 /* Check if device is already in connected list */
1190 conn_info = __bt_find_remote_gatt_client_info(addr);
1192 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1194 if (svc_info == NULL || conn_info == NULL) {
1195 ERR("Invalid information %p, %p", svc_info, conn_info);
1196 g_dbus_method_invocation_return_value(invocation, NULL);
1201 ERR("GATT callback NOT registered");
1202 g_dbus_method_invocation_return_value(invocation, NULL);
1206 /* Store requets information */
1207 req_info = g_new0(struct gatt_req_info, 1);
1208 req_info->attr_path = g_strdup(object_path);
1209 req_info->svc_path = g_strdup(svc_info->serv_path);
1210 req_info->request_id = req_id;
1211 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1212 req_info->offset = offset;
1213 req_info->context = invocation;
1215 /* Append request info in list of requests for the particular connection */
1216 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1218 /* Send HAL event */
1219 memset(&ev, 0, sizeof(ev));
1220 ev.conn_id = conn_info->connection_id;
1221 ev.trans_id = req_id;
1222 ev.att_handle = char_hdl;
1224 ev.is_long = false; /* TODO*/
1226 /* Convert address to hex */
1227 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1228 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1230 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1231 GVariant *var = NULL;
1235 gboolean response_needed = FALSE;
1236 struct hal_ev_gatt_server_write_req ev;
1240 struct gatt_service_info *svc_info = NULL;
1241 struct gatt_req_info *req_info = NULL;
1242 struct gatt_client_info_t *conn_info = NULL;
1244 memset(&ev, 0, sizeof(ev));
1246 DBG("WriteValue : Application path %s, sender %s", object_path, sender);
1248 g_variant_get(parameters, "(&suqb@ay)",
1249 &addr, &req_id, &offset, &response_needed, &var);
1250 DBG("Request id = %u, Offset = %u", req_id, offset);
1252 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1254 /* Check if device is already in connected list */
1255 conn_info = __bt_find_remote_gatt_client_info(addr);
1257 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1258 g_variant_unref(var);
1259 if (response_needed)
1260 g_dbus_method_invocation_return_value(invocation, NULL);
1262 g_object_unref(invocation);
1266 len = g_variant_get_size(var);
1267 if (len > 0 && len < 600) {
1269 data = (char *)g_variant_get_data(var);
1270 memcpy(ev.value, data, len);
1274 if (response_needed) {
1275 /* Store requets information */
1276 req_info = g_new0(struct gatt_req_info, 1);
1277 req_info->attr_path = g_strdup(object_path);
1278 req_info->svc_path = g_strdup(svc_info->serv_path);
1279 req_info->request_id = req_id;
1280 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1281 req_info->offset = offset;
1282 req_info->context = invocation;
1284 /* Append request info in list of requests for the particular connection */
1285 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1288 g_object_unref(invocation);
1291 /* Send HAL event */
1292 ev.conn_id = conn_info->connection_id;
1293 ev.trans_id = req_id;
1294 ev.att_handle = char_hdl;
1296 ev.need_rsp = response_needed;
1299 /* Convert address to hex */
1300 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1302 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1304 g_variant_unref(var);
1307 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1310 struct gatt_service_info *svc_info = NULL;
1311 struct hal_ev_gatt_server_notifcation_change ev;
1314 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1315 if (svc_info == NULL || event_cb == NULL)
1318 /* Send HAL event */
1319 memset(&ev, 0, sizeof(ev));
1320 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1321 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1322 ev.att_handle = char_hdl;
1325 /* Convert address to hex */
1326 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1328 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1331 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1334 struct gatt_service_info *svc_info = NULL;
1335 struct hal_ev_gatt_server_notifcation_change ev;
1338 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1339 if (svc_info == NULL || event_cb == NULL)
1342 /* Send HAL event */
1343 memset(&ev, 0, sizeof(ev));
1344 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1345 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1346 ev.att_handle = char_hdl;
1349 /* Convert address to hex */
1350 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1352 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1355 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1357 gboolean complete = FALSE;
1360 struct gatt_service_info *svc_info = NULL;
1361 struct gatt_client_info_t *conn_info = NULL;
1363 struct hal_ev_gatt_server_indicate_cfm ev;
1365 DBG("IndicateConfirm : Application path %s, sender %s", object_path, sender);
1367 g_variant_get(parameters, "(&sb)", &addr, &complete);
1368 DBG("Remote Device address number = %s", addr);
1369 DBG("Is Indicate confirmation for last device [%d]", complete);
1371 /* Check if device is already in connected list */
1372 conn_info = __bt_find_remote_gatt_client_info(addr);
1374 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1376 if (svc_info == NULL || conn_info == NULL
1377 || event_cb == NULL) {
1381 /* Send HAL event */
1382 memset(&ev, 0, sizeof(ev));
1383 ev.conn_id = conn_info->connection_id;
1384 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1385 ev.att_handle = char_hdl;
1387 /* Convert address to hex */
1388 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1390 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1391 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1395 struct hal_ev_gatt_server_acquire_write_res ev;
1396 struct gatt_service_info *svc_info = NULL;
1397 struct gatt_req_info *req_info = NULL;
1398 struct gatt_client_info_t *conn_info = NULL;
1399 char *dev_path = NULL;
1401 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1403 DBG("AcquireWrite : Application path %s, sender %s", object_path, sender);
1406 g_variant_get(parameters, "(a{sv})", &iter);
1408 GVariant *value = NULL;
1409 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1410 if (g_strcmp0(key, "MTU") == 0)
1411 g_variant_get(value, "q", &mtu);
1412 else if (g_strcmp0(key, "link") == 0)
1413 g_variant_get(value, "s", &link);
1414 else if (g_strcmp0(key, "device") == 0)
1415 g_variant_get(value, "o", &dev_path);
1418 DBG(" path %s LINK = %s, MTU = %u", dev_path, link, mtu);
1420 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1422 _bt_hal_convert_device_path_to_address(dev_path, addr);
1424 DBG("remote address %s", addr);
1428 /* Check if device is already in connected list */
1429 conn_info = __bt_find_remote_gatt_client_info(addr);
1430 if (conn_info == NULL) {
1431 ERR("Cleint info not found\n");
1432 g_variant_iter_free(iter);
1436 if (svc_info == NULL) {
1437 ERR("svc_info info not found\n");
1438 g_variant_iter_free(iter);
1442 /* Store requets information */
1443 req_info = g_new0(struct gatt_req_info, 1);
1444 req_info->attr_path = g_strdup(object_path);
1445 req_info->svc_path = g_strdup(svc_info->serv_path);
1446 req_info->request_id = conn_info->connection_id;
1447 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1448 req_info->offset = mtu;
1449 req_info->context = invocation;
1451 /* Append request info in list of requests for the particular connection */
1452 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1454 /* Send HAL event */
1455 memset(&ev, 0, sizeof(ev));
1456 ev.conn_id = conn_info->connection_id;
1457 ev.char_handl = char_hdl;
1459 ev.trans_id = conn_info->connection_id;
1460 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1461 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1462 g_variant_iter_free(iter);
1464 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1468 struct hal_ev_gatt_server_acquire_notify ev;
1469 struct gatt_service_info *svc_info = NULL;
1470 struct gatt_client_info_t *conn_info = NULL;
1471 struct gatt_req_info *req_info = NULL;
1473 DBG("AcquireNotify : Application path %s, sender %s", object_path, sender);
1476 g_variant_get(parameters, "(a{sv})", &iter);
1478 GVariant* value = NULL;
1479 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1480 if (g_strcmp0(key, "MTU") == 0)
1481 g_variant_get(value, "q", &mtu);
1484 DBG("MTU = %u", mtu);
1486 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1488 if (svc_info == NULL) {
1489 ERR("svc_info info not found\n");
1490 g_variant_iter_free(iter);
1494 /* Store requets information */
1495 req_info = g_new0(struct gatt_req_info, 1);
1496 req_info->attr_path = g_strdup(object_path);
1497 req_info->svc_path = g_strdup(svc_info->serv_path);
1498 req_info->request_id = 33;
1499 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1500 req_info->offset = mtu;
1501 req_info->context = invocation;
1503 conn_info = g_new0(struct gatt_client_info_t, 1);
1504 conn_info->addr = g_strdup(object_path);
1505 INFO("AcquireNotify : Added GATT client path[%s]", conn_info->addr);
1506 conn_info->connection_id = 33;
1507 conn_info->instance_id = 33;
1508 /* Append request info in list of requests for the particular connection */
1509 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1510 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1512 /* Send HAL event */
1513 memset(&ev, 0, sizeof(ev));
1515 ev.char_handl = char_hdl;
1519 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1520 g_variant_iter_free(iter);
1525 g_dbus_method_invocation_return_value(invocation, NULL);
1528 static gboolean __bt_hal_gatt_emit_interface_removed(const char *app_path, gchar *object_path, gchar *interface)
1531 GError *error = NULL;
1532 GVariantBuilder *array_builder;
1534 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1535 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1536 g_variant_builder_add(array_builder, "s", interface);
1538 ret = g_dbus_connection_emit_signal(g_conn, NULL, app_path,
1539 "org.freedesktop.DBus.ObjectManager",
1540 "InterfacesRemoved",
1541 g_variant_new("(oas)",
1542 object_path, array_builder),
1546 if (error != NULL) {
1547 /* dbus gives error cause */
1548 ERR("d-bus api failure: errcode[%x], message[%s]",
1549 error->code, error->message);
1550 g_clear_error(&error);
1553 g_variant_builder_unref(array_builder);
1558 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1565 g_free(desc_info->desc_path);
1566 g_free(desc_info->desc_uuid);
1567 g_free(desc_info->desc_value);
1569 for (i = 0; i < desc_info->flags_length; i++)
1570 g_free(desc_info->desc_flags[i]);
1575 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1582 g_free(char_info->char_path);
1583 g_free(char_info->char_uuid);
1584 g_free(char_info->char_value);
1586 for (i = 0; i < char_info->flags_length; i++)
1587 g_free(char_info->char_flags[i]);
1593 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1598 g_free(svc_info->serv_path);
1599 g_free(svc_info->service_uuid);
1603 static const GDBusInterfaceVTable desc_interface_vtable = {
1604 __bt_gatt_desc_method_call,
1609 static const GDBusInterfaceVTable char_interface_vtable = {
1610 __bt_gatt_char_method_call,
1615 static const GDBusInterfaceVTable serv_interface_vtable = {
1621 static const GDBusInterfaceVTable manager_interface_vtable = {
1622 __bt_gatt_manager_method_call,
1628 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1629 const gchar *introspection_data)
1632 GDBusNodeInfo *node_info = NULL;
1634 if (introspection_data == NULL)
1638 DBG("Create new node info");
1639 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1642 ERR("Unable to create node: %s", err->message);
1643 g_clear_error(&err);
1650 /* To send stack event to hal-av handler */
1651 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1656 void _bt_hal_unregister_gatt_server_handler_cb(void)
1661 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1663 struct hal_ev_gatt_desc_added ev;
1664 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1666 /* Prepare to GATT characteristic added event */
1667 memset(&ev, 0, sizeof(ev));
1668 ev.status = BT_STATUS_SUCCESS;
1669 ev.server_instance = data->instance_data;
1670 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1671 ev.service_handle = data->srvc_hdl;
1672 ev.desc_handle = data->desc_hdl;
1675 ERR("GATT Descriptor Added callback registered");
1677 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1678 data->instance_data, data->srvc_hdl, data->desc_hdl);
1680 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1687 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1689 struct hal_ev_gatt_char_added ev;
1690 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1692 /* Prepare to GATT characteristic added event */
1693 memset(&ev, 0, sizeof(ev));
1694 ev.status = BT_STATUS_SUCCESS;
1695 ev.server_instance = data->instance_data;
1696 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1697 ev.service_handle = data->srvc_hdl;
1698 ev.char_handle = data->char_hdl;
1701 ERR("GATT Characteristic Added callback registered");
1703 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1704 data->instance_data, data->srvc_hdl, data->char_hdl);
1706 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1713 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1715 struct hal_ev_gatt_service_added ev;
1716 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1718 /* Prepare to GATT Service added event */
1719 memset(&ev, 0, sizeof(ev));
1720 ev.status = BT_STATUS_SUCCESS;
1721 ev.server_instance = data->instance_data;
1722 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1723 ev.service_handle = data->srvc_hdl;
1724 ev.is_primary = data->is_primary;
1727 ERR("GATT Service Added callback registered");
1729 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1730 data->instance_data, data->srvc_hdl);
1731 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1738 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1740 struct hal_ev_gatt_service_started ev;
1741 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1743 /* Prepare to GATT Service added event */
1744 memset(&ev, 0, sizeof(ev));
1745 ev.status = BT_STATUS_SUCCESS;
1746 ev.server_instance = data->instance_data;
1747 ev.service_handle = data->srvc_hdl;
1750 ERR("GATT Service Started callback registered");
1752 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1753 data->instance_data, data->srvc_hdl);
1754 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1761 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1763 struct hal_ev_gatt_service_deleted ev;
1764 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1766 /* Prepare to GATT Service added event */
1767 memset(&ev, 0, sizeof(ev));
1768 ev.status = BT_STATUS_SUCCESS;
1769 ev.server_instance = data->instance_data;
1770 ev.service_handle = data->srvc_hdl;
1773 ERR("GATT Service Deleted callback registered");
1775 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1776 data->instance_data, data->srvc_hdl);
1777 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1784 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1786 struct hal_ev_server_instance_registered ev;
1787 hal_register_server_data *data = (hal_register_server_data*) user_data;
1789 /* Prepare to send AV connecting event */
1790 memset(&ev, 0, sizeof(ev));
1791 ev.status = BT_STATUS_SUCCESS;
1792 ev.server_instance = data->instance_data;
1793 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1796 ERR("GATT Register Server Instance Callback not registered");
1798 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1799 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1807 static int bt_hal_gatts_get_gatt_server_instance()
1812 struct hal_gatts_server_register_info_t *info = NULL;
1814 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1815 info = (struct hal_gatts_server_register_info_t *)l->data;
1820 return info->server_if;
1826 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_from_uuid(bt_uuid_t *app_uuid)
1831 struct hal_gatts_server_register_info_t *info = NULL;
1833 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1834 info = (struct hal_gatts_server_register_info_t *)l->data;
1839 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
1840 DBG("gatt server register found");
1848 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info(int server_if)
1851 struct hal_gatts_server_register_info_t *info = NULL;
1853 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1854 info = (struct hal_gatts_server_register_info_t *)l->data;
1859 if (info->server_if == server_if) {
1867 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_by_slot_id(int adv_slot_id)
1872 struct hal_gatts_server_register_info_t *info = NULL;
1874 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1875 info = (struct hal_gatts_server_register_info_t *)l->data;
1880 if (info->adv_slot_id == adv_slot_id) {
1881 DBG("gatt server register found");
1889 static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_uuid_t *app_uuid)
1891 struct hal_gatts_server_register_info_t * server_register_info = NULL;
1892 int instance_id = 0;
1894 server_register_info = bt_hal_gatts_find_server_register_info_from_uuid(app_uuid);
1895 if (server_register_info != NULL) {
1896 DBG("gatt server is already registered");
1897 return server_register_info;
1900 instance_id = __bt_hal_gatt_assign_id();
1901 if (instance_id == -1) {
1902 ERR("Fail to allocate the server if");
1906 server_register_info = g_malloc0(sizeof(struct hal_gatts_server_register_info_t));
1907 server_register_info->server_if = instance_id;
1909 DBG("Adding the gatt server app. server_if:[%d]", server_register_info->server_if);
1911 server_register_info->adv_slot_id = -1;
1912 memcpy(&server_register_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
1913 hal_gatts_server_register_list = g_slist_append(hal_gatts_server_register_list, server_register_info);
1915 return server_register_info;
1918 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1920 CHECK_BTGATT_INIT();
1921 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1923 DBG("Register server instance request");
1924 server_register_info = bt_hal_gatts_add_server_app(uuid);
1925 if (server_register_info == NULL) {
1926 ERR("Fail to register the server app");
1927 return BT_STATUS_FAIL;
1930 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1931 user_data->instance_data = server_register_info->server_if;
1934 * As we need to provide async callback to user from HAL, simply schedule a
1935 * callback method which will carry actual result
1937 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1938 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1940 /* If available, then return success, else return error */
1941 return BT_STATUS_SUCCESS;
1944 static void _bt_hal_remove_gatt_server_from_list(int server_if)
1947 struct gatt_server_app *info = NULL;
1949 for (l = gatt_server_apps; l != NULL;) {
1950 info = (struct gatt_server_app*)l->data;
1951 l = g_slist_next(l);
1954 if (info->slot == server_if) {
1955 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1956 info->app_path, info->slot);
1958 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1959 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1960 In above case, only advertising block will be deallocated, Gatt Server will remain
1962 if (info->services == NULL) {
1963 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1964 INFO("Total gatt server apps still existing after removing above is [%d]",
1965 g_slist_length(gatt_server_apps));
1967 /* DBUS Unregister only for current app */
1968 __bt_hal_gatt_deinit(info->app_path);
1970 g_free(info->app_path);
1974 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1975 g_slist_length(info->services));
1981 static bt_status_t gatt_server_unregister_app(int server_if)
1983 CHECK_BTGATT_INIT();
1984 DBG("Un-Register server instance request [%d]", server_if);
1985 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1988 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
1989 if (server_register_info == NULL) {
1990 DBG("gatt server is not registered");
1991 return BT_STATUS_SUCCESS;
1994 /* remove the gatt server register info from the register list */
1995 hal_gatts_server_register_list = g_slist_remove(hal_gatts_server_register_list, server_register_info);
1996 g_free(server_register_info);
1998 __bt_hal_gatt_delete_id(server_if);
2000 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
2001 _bt_hal_remove_gatt_server_from_list(server_if);
2002 return BT_STATUS_SUCCESS;
2005 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
2007 CHECK_BTGATT_INIT();
2008 return BT_STATUS_SUCCESS;
2011 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
2014 GError *g_error = NULL;
2015 GVariant *reply = NULL;
2019 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2020 g_object_unref(proxy);
2021 if (reply == NULL) {
2022 ERR("Disconnect LE Dbus Call Error");
2024 ERR("Error: %s\n", g_error->message);
2025 g_clear_error(&g_error);
2028 g_variant_unref(reply);
2032 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
2034 CHECK_BTGATT_INIT();
2036 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2038 GDBusProxy *device_proxy;
2039 GDBusConnection *g_conn;
2040 struct gatt_client_info_t *conn_info = NULL;
2044 if (NULL == bd_addr) {
2045 ERR("bd_addr is NULL");
2046 return BT_STATUS_PARM_INVALID;
2049 /* GDBUS Connection Info validate */
2050 g_conn = _bt_hal_get_system_gconn();
2051 if (g_conn == NULL) {
2052 ERR("Could not get System DBUS Connection");
2053 return BT_STATUS_FAIL;
2056 /* Connection Info validate */
2057 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2058 if (conn_info == NULL) {
2059 ERR("No Connection Inforamtion!!!");
2060 return BT_STATUS_FAIL;
2063 _bt_hal_convert_addr_type_to_string(device_address,
2064 (unsigned char *)bd_addr->address);
2066 //check if connection has the same device address
2067 if (g_strcmp0(conn_info->addr, device_address) != 0) {
2068 ERR("device address [%s] does not match", device_address);
2069 return BT_STATUS_FAIL;
2072 device_path = _bt_hal_get_device_object_path(conn_info->addr);
2073 if (device_path == NULL) {
2074 ERR("device_path is NULL");
2075 return BT_STATUS_PARM_INVALID;
2078 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
2079 NULL, BT_HAL_BLUEZ_NAME,
2080 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2083 g_free(device_path);
2084 if (device_proxy == NULL)
2085 return BT_STATUS_FAIL;
2087 INFO("Disconnect LE [%s]", device_address);
2089 g_dbus_proxy_call(device_proxy, "DisconnectLE",
2091 G_DBUS_CALL_FLAGS_NONE,
2092 BT_HAL_MAX_DBUS_TIMEOUT,
2094 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
2097 return BT_STATUS_SUCCESS;
2100 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
2105 uuid = btuuid2str(srvc_id->uu);
2106 DBG("Original UUID [%s]", uuid);
2108 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
2109 /* Extract Standard UUID string */
2110 memcpy(uuid_buf, &uuid[4], 4);
2112 DBG("Converted string [%s]", uuid_buf);
2113 return g_strdup(uuid_buf);
2115 return strdup(uuid);
2118 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
2121 /* For GATT service specific */
2122 GDBusNodeInfo *node_info;
2125 struct gatt_service_info *serv_info = NULL;
2126 GVariantBuilder *builder = NULL;
2127 GVariantBuilder *builder1 = NULL;
2128 GVariantBuilder *inner_builder = NULL;
2129 gboolean svc_primary = TRUE;
2130 GError *error = NULL;
2131 hal_gatt_service_added *user_data = NULL;
2132 DBG("Service add to DBUS slot [%d]", slot);
2134 node_info = __bt_gatt_create_method_node_info(
2135 service_introspection_xml);
2137 if (node_info == NULL)
2138 return BT_STATUS_FAIL;
2140 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
2141 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
2142 DBG("gatt service path is [%s]", path);
2144 object_id = g_dbus_connection_register_object(g_conn, path,
2145 node_info->interfaces[0],
2146 &serv_interface_vtable,
2147 NULL, NULL, &error);
2149 if (object_id == 0) {
2150 ERR("failed to register: %s", error->message);
2151 g_error_free(error);
2153 return BT_STATUS_FAIL;
2155 /* Add object_id/gatt service information; it's required at the time of
2156 * service unregister and Getmanagedobjects
2158 serv_info = g_new0(struct gatt_service_info, 1);
2160 serv_info->serv_path = g_strdup(path);
2161 serv_info->serv_id = object_id;
2162 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
2163 serv_info->is_svc_registered = FALSE;
2164 serv_info->is_svc_primary = svc_primary;
2165 DBG("Service Handle to be added is [%d]", gatt_service_handle);
2166 serv_info->service_handle = gatt_service_handle;
2168 /* Update service in GATT Server service List */
2169 gatt_services = g_slist_append(gatt_services, serv_info);
2171 /* emit interfacesadded signal here for service path */
2172 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2173 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2175 g_variant_builder_add(inner_builder, "{sv}",
2176 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
2178 g_variant_builder_add(inner_builder, "{sv}",
2179 "Primary", g_variant_new_boolean(svc_primary));
2181 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2183 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
2184 g_variant_new("ao", builder1));
2186 g_variant_builder_add(builder, "{sa{sv}}",
2187 GATT_SERV_INTERFACE, inner_builder);
2189 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2190 "org.freedesktop.Dbus.ObjectManager", // TODO: need to check Dbus is working or not
2192 g_variant_new("(oa{sa{sv}})",
2197 /* dbus gives error cause */
2198 ERR("d-bus api failure: errcode[%x], message[%s]",
2199 error->code, error->message);
2200 g_clear_error(&error);
2204 /* Send Service handle to application */
2205 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2206 user_data->srvc_hdl = serv_info->service_handle;
2207 user_data->instance_data = slot;
2208 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2209 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2211 /* Save newly created service in GATT Server's service list */
2212 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2216 g_variant_builder_unref(inner_builder);
2217 g_variant_builder_unref(builder);
2218 g_variant_builder_unref(builder1);
2219 return BT_STATUS_SUCCESS;
2222 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2225 char *app_path = (char*)user_data;
2226 INFO("UnregisterApplication is completed app [%s]", app_path);
2227 GError *error = NULL;
2228 GVariant *result = NULL;
2231 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2233 if (result == NULL) {
2234 /* dBUS-RPC is failed */
2235 ERR("Dbus-RPC is failed\n");
2237 if (error != NULL) {
2238 /* dBUS gives error cause */
2239 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2240 error->code, error->message);
2241 g_clear_error(&error);
2244 g_variant_unref(result);
2249 static void __bt_hal_gatt_deinit(char *app_path)
2251 GDBusProxy *proxy = NULL;
2255 /* Step1: Remove requested App */
2256 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2257 "/org/bluez/hci0", "org.bluez.GattManager1");
2262 INFO("UnregisterApplication : path [%s]", app_path);
2264 /* Async Call to Unregister Service */
2265 data = g_strdup(app_path);
2266 g_dbus_proxy_call(proxy,
2267 "UnregisterApplication",
2268 g_variant_new("(o)",
2270 G_DBUS_CALL_FLAGS_NONE, -1,
2272 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2275 /* If requested app is last GATT Server app, then clean all resources */
2276 if (gatt_server_apps == NULL) {
2277 INFO("All GATT servers are removed, clean all DBUS resources");
2279 /* unregister the exported interface for object manager */
2280 g_dbus_connection_unregister_object(g_conn, manager_id);
2282 g_bus_unown_name(owner_id);
2285 g_object_unref(manager_gproxy);
2286 manager_gproxy = NULL;
2292 static int __bt_hal_gatt_init(void)
2296 /* Only once for ALL GATT Servers */
2297 if (owner_id == 0) {
2301 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2304 ERR("Unable to connect to gdbus: %s", err->message);
2305 g_clear_error(&err);
2307 return BT_STATUS_FAIL;
2310 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2311 INFO("well-known name: %s", name);
2313 owner_id = g_bus_own_name_on_connection(g_conn, name,
2314 G_BUS_NAME_OWNER_FLAGS_NONE,
2315 NULL, NULL, NULL, NULL);
2317 INFO("Owner ID [%d]", owner_id);
2319 /* Only once for ALL GATT Servers */
2320 if (manager_node_info == NULL) {
2321 /* Register ObjectManager interface */
2322 manager_node_info = __bt_gatt_create_method_node_info(
2323 manager_introspection_xml);
2325 if (manager_node_info == NULL) {
2326 ERR("failed to get node info");
2327 return BT_STATUS_FAIL;
2332 return BT_STATUS_SUCCESS;
2335 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2339 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2340 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2341 if (app->slot == slot) {
2342 INFO("GATT Server app found app path [%s] instance [%d]",
2343 app->app_path, app->slot);
2344 *app_path = app->app_path;
2348 /* GATT Server not found */
2352 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2354 if (app_path == NULL)
2357 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2358 app->app_path = g_strdup(app_path);
2360 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2361 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2364 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2367 CHECK_BTGATT_INIT();
2368 char *app_path = NULL;
2369 GError *error = NULL;
2372 int result = BT_STATUS_SUCCESS;
2374 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2375 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2377 /* Check if this GATT server Application is already registered with DBUS */
2378 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2380 if (app_path != NULL) {
2381 DBG("GATT server path is already defined [%s]", app_path);
2382 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2384 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2385 result = __bt_hal_gatt_init();
2386 if (result != BT_STATUS_SUCCESS)
2389 /* Only once for each GATT Server */
2390 app_path = g_strdup_printf("/com/%d", server_if);
2392 app_id = g_malloc0(sizeof(int));
2393 *app_id = server_if;
2395 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2396 manager_node_info->interfaces[0],
2397 &manager_interface_vtable,
2398 (gpointer)app_id, NULL, &error);
2400 if (manager_id == 0) {
2401 ERR("failed to register: %s", error->message);
2402 g_error_free(error);
2405 INFO("manager_id [%d]", manager_id);
2407 /* For current GATT Server, app_path is created, save it in Table */
2408 _bt_hal_update_gatt_server_path(server_if, app_path);
2410 /* Add GATT Service to DBUS */
2411 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2417 INFO("Successfully added service");
2418 return BT_STATUS_SUCCESS;
2425 INFO("Service addition failed!!");
2426 return BT_STATUS_FAIL;
2429 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2430 int included_handle)
2432 CHECK_BTGATT_INIT();
2433 return BT_STATUS_SUCCESS;
2437 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2440 GSList *gatt_services = NULL;
2442 struct gatt_service_info *info = NULL;
2444 gatt_services = _bt_get_service_list_from_server(instance);
2446 len = g_slist_length(gatt_services);
2447 l = g_slist_nth(gatt_services, len -1);
2453 if (info->service_handle == service_handle)
2458 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2462 GSList *gatt_services = NULL;
2463 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2465 gatt_services = _bt_get_service_list_from_server(instance);
2467 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2468 struct gatt_service_info *info = l->data;
2469 INFO("Got one service with handle [%d]", info->service_handle);
2470 if (info->service_handle == service_handle)
2473 ERR("Gatt service with handle [%d] not found", service_handle);
2477 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2478 bt_uuid_t *uuid, int properties,
2482 GError *error = NULL;
2484 GDBusNodeInfo *node_info;
2486 GVariantBuilder *builder = NULL;
2487 GVariantBuilder *inner_builder = NULL;
2488 struct gatt_service_info *serv_info = NULL;
2489 struct gatt_char_info *char_info = NULL;
2490 GVariantBuilder *builder2 = NULL;
2491 GVariantBuilder *builder3 = NULL;
2492 GVariant *flags_val = NULL;
2494 char *char_flags[NUMBER_OF_FLAGS];
2496 hal_gatt_char_added *user_data = NULL;
2499 CHECK_BTGATT_INIT();
2500 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2501 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2503 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2504 if (serv_info == NULL)
2505 return BT_STATUS_FAIL;
2507 node_info = __bt_gatt_create_method_node_info(
2508 characteristics_introspection_xml);
2510 if (node_info == NULL)
2511 return BT_STATUS_FAIL;
2513 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2514 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2515 DBG("gatt characteristic path is [%s]", path);
2517 app_id = g_malloc0(sizeof(int));
2520 object_id = g_dbus_connection_register_object(g_conn, path,
2521 node_info->interfaces[0],
2522 &char_interface_vtable,
2523 (gpointer)app_id, NULL, &error);
2525 if (object_id == 0) {
2526 ERR("failed to register: %s", error->message);
2527 g_error_free(error);
2530 return BT_STATUS_FAIL;
2533 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2534 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2535 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2536 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2537 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2538 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2539 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2540 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2542 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2544 char_info = g_new0(struct gatt_char_info, 1);
2546 char_info->char_path = g_strdup(path);
2547 char_info->char_id = object_id;
2548 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2549 for (i = 0; i < flag_count; i++)
2550 char_info->char_flags[i] = char_flags[i];
2553 char_info->flags_length = flag_count;
2554 char_info->char_handle = gatt_char_handle;
2557 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2558 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2560 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2561 g_variant_new("s", char_info->char_uuid));
2562 g_variant_builder_add(inner_builder, "{sv}", "Service",
2563 g_variant_new("o", serv_info->serv_path));
2565 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2567 for (i = 0; i < flag_count; i++)
2568 g_variant_builder_add(builder2, "s", char_flags[i]);
2570 flags_val = g_variant_new("as", builder2);
2571 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2574 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2576 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2577 g_variant_new("ao", builder3));
2579 g_variant_builder_add(builder, "{sa{sv}}",
2580 GATT_CHAR_INTERFACE,
2583 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2584 "org.freedesktop.Dbus.ObjectManager",
2586 g_variant_new("(oa{sa{sv}})",
2591 /* dbus gives error cause */
2592 ERR("d-bus api failure: errcode[%x], message[%s]",
2593 error->code, error->message);
2594 g_clear_error(&error);
2598 //*char_path = g_strdup(path);
2603 /* Send Service handle to application */
2604 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2605 user_data->srvc_hdl = serv_info->service_handle;
2606 user_data->char_hdl = gatt_char_handle;
2607 user_data->instance_data = slot;
2608 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2609 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2611 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2612 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2617 g_variant_builder_unref(inner_builder);
2618 g_variant_builder_unref(builder);
2619 g_variant_builder_unref(builder2);
2620 g_variant_builder_unref(builder3);
2622 return BT_STATUS_SUCCESS;
2625 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2628 CHECK_BTGATT_INIT();
2630 // static int desc_id = 1;
2631 GError *error = NULL;
2633 GDBusNodeInfo *node_info;
2635 GVariantBuilder *builder = NULL;
2636 GVariantBuilder *inner_builder = NULL;
2638 struct gatt_char_info *char_info = NULL;
2639 struct gatt_desc_info *desc_info = NULL;
2640 struct gatt_service_info *serv_info = NULL;
2642 gchar **line_argv = NULL;
2644 char *char_path = NULL;
2647 GVariantBuilder *builder2 = NULL;
2648 GVariant *flags_val = NULL;
2650 char *desc_flags[NUMBER_OF_FLAGS];
2654 hal_gatt_desc_added *user_data = NULL;
2661 /* Fetch service data for the GATT server */
2662 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2663 if (serv_info == NULL)
2664 return BT_STATUS_FAIL;
2666 /* Fetch list of characteristics from the service info */
2667 l = serv_info->char_data;
2669 /* Fetch last char info from the characteristic list */
2670 char_info = g_slist_last(l)->data;
2671 if (char_info == NULL)
2672 return BT_STATUS_FAIL;
2674 /* Fetch characteristic path from char info */
2675 char_path = char_info->char_path;
2677 line_argv = g_strsplit_set(char_path, "/", 0);
2678 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2681 node_info = __bt_gatt_create_method_node_info(
2682 descriptor_introspection_xml);
2684 if (node_info == NULL) {
2685 g_strfreev(line_argv);
2687 return BT_STATUS_FAIL;
2690 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2692 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2693 DBG("gatt descriptor path is [%s]", path);
2695 app_id = g_malloc0(sizeof(int));
2698 object_id = g_dbus_connection_register_object(g_conn, path,
2699 node_info->interfaces[0],
2700 &desc_interface_vtable,
2701 (gpointer)app_id, NULL, &error);
2703 if (object_id == 0) {
2704 ERR("failed to register: %s", error->message);
2705 g_error_free(error);
2707 g_strfreev(line_argv);
2710 return BT_STATUS_FAIL;
2713 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2715 desc_info = g_new0(struct gatt_desc_info, 1);
2717 desc_info->desc_path = g_strdup(path);
2718 desc_info->desc_id = object_id;
2719 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2721 for (i = 0; i < flag_count; i++)
2722 desc_info->desc_flags[i] = desc_flags[i];
2724 desc_info->flags_length = flag_count;
2725 desc_info->desc_handle = gatt_desc_handle;
2728 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2729 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2731 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2732 g_variant_new("s", btuuid2str(uuid->uu)));
2733 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2734 g_variant_new("o", char_path));
2736 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2738 for (i = 0; i < flag_count; i++)
2739 g_variant_builder_add(builder2, "s", desc_flags[i]);
2741 flags_val = g_variant_new("as", builder2);
2742 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2745 g_variant_builder_add(builder, "{sa{sv}}",
2746 GATT_DESC_INTERFACE,
2749 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2750 "org.freedesktop.Dbus.ObjectManager",
2752 g_variant_new("(oa{sa{sv}})",
2755 if (error != NULL) {
2756 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2757 error->code, error->message);
2758 g_clear_error(&error);
2761 //*desc_path = g_strdup(path);
2763 /* Save newly created descriptor to GATT server's service's characteristic */
2764 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2766 /* Send descriptor handle to application */
2767 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2768 user_data->srvc_hdl = serv_info->service_handle;
2769 user_data->desc_hdl = gatt_desc_handle;
2770 user_data->instance_data = slot;
2771 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2772 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2777 g_strfreev(line_argv);
2778 g_variant_builder_unref(inner_builder);
2779 g_variant_builder_unref(builder);
2780 return BT_STATUS_SUCCESS;
2783 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2785 GError *error = NULL;
2787 char *data = (char*) user_data;
2788 INFO("RegisterApplication is completed path [%s]", data);
2790 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2792 if (result == NULL) {
2793 /* dBUS-RPC is failed */
2794 ERR("Dbus-RPC is failed\n");
2796 if (error != NULL) {
2797 /* dBUS gives error cause */
2798 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2799 error->code, error->message);
2800 g_clear_error(&error);
2803 g_variant_unref(result);
2808 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2809 const gchar *path, const gchar *interface)
2815 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2820 ERR("Unable to connect to gdbus: %s", err->message);
2821 g_clear_error(&err);
2826 proxy = g_dbus_proxy_new_sync(g_conn,
2827 G_DBUS_PROXY_FLAGS_NONE, NULL,
2829 interface, NULL, &err);
2833 ERR("Unable to create proxy: %s", err->message);
2834 g_clear_error(&err);
2838 manager_gproxy = proxy;
2843 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2844 const gchar *path, const gchar *interface)
2846 return (manager_gproxy) ? manager_gproxy :
2847 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2851 static void __bt_register_application_to_dbus(int slot)
2853 GDBusProxy *proxy = NULL;
2854 char *app_path = NULL;
2856 DBG("RegisterApplication slot [%d]", slot);
2858 /* It is impossible that app path is still not initialized */
2859 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2861 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2862 "/org/bluez/hci0", "org.bluez.GattManager1");
2864 data = g_strdup(app_path);
2865 g_dbus_proxy_call(proxy,
2866 "RegisterApplication",
2867 g_variant_new("(oa{sv})",
2869 G_DBUS_CALL_FLAGS_NONE, -1,
2871 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2873 INFO("GATT server started");
2876 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2878 CHECK_BTGATT_INIT();
2879 struct gatt_service_info *serv_info = NULL;
2880 hal_gatt_service_started *user_data = NULL;
2881 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2883 /* Fetch service data for the GATT server */
2884 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2885 if (serv_info == NULL)
2886 return BT_STATUS_FAIL;
2888 if (serv_info->is_svc_registered)
2889 DBG("service already registered \n");
2891 serv_info->is_svc_registered = TRUE;
2893 /* Send Service handle to application */
2894 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2895 user_data->srvc_hdl = serv_info->service_handle;
2896 user_data->instance_data = server_if;
2897 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2899 /* If this is nth Service that is started, then register application at this point */
2900 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2901 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2903 __bt_register_application_to_dbus(server_if);
2906 return BT_STATUS_SUCCESS;
2909 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2911 CHECK_BTGATT_INIT();
2912 INFO("Stop service successful");
2913 return BT_STATUS_SUCCESS;
2916 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2918 CHECK_BTGATT_INIT();
2919 struct gatt_service_info *serv_info = NULL;
2920 hal_gatt_service_deleted *user_data = NULL;
2923 int err = BT_STATUS_SUCCESS;
2924 int ret = BT_STATUS_SUCCESS;
2925 char *app_path = NULL;
2926 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2928 /* Fetch service data for the GATT server */
2929 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2930 if (serv_info == NULL) {
2931 ERR("Could not find service info svc handle [%d] server slot [%d]",
2932 service_handle, server_if);
2933 return BT_STATUS_FAIL;
2936 app_path = __bt_get_server_app_path_from_server(server_if);
2937 if (app_path == NULL) {
2938 ERR("Could not find service info svc handle [%d] server slot [%d]",
2939 service_handle, server_if);
2940 return BT_STATUS_FAIL;
2943 if (serv_info->is_svc_registered == FALSE) {
2944 ERR("service Not registered path [%s] handle [%d]",
2945 serv_info->serv_path, service_handle);
2948 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2949 struct gatt_char_info *char_info = l->data;
2951 if (char_info == NULL)
2954 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2955 struct gatt_desc_info *desc_info = l1->data;
2957 if (desc_info == NULL)
2960 ret = g_dbus_connection_unregister_object(g_conn,
2961 desc_info->desc_id);
2963 __bt_hal_gatt_emit_interface_removed(
2965 desc_info->desc_path,
2966 GATT_DESC_INTERFACE);
2968 err = BT_STATUS_FAIL;
2971 /* list remove & free */
2972 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2973 __bt_hal_gatt_free_descriptor_info(desc_info);
2976 g_slist_free(char_info->desc_data);
2977 char_info->desc_data = NULL;
2979 ret = g_dbus_connection_unregister_object(g_conn,
2980 char_info->char_id);
2982 __bt_hal_gatt_emit_interface_removed(app_path, char_info->char_path,
2983 GATT_CHAR_INTERFACE);
2986 err = BT_STATUS_FAIL;
2989 /* list remove & free */
2990 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2991 __bt_hal_gatt_free_characteristic_info(char_info);
2994 g_slist_free(serv_info->char_data);
2995 serv_info->char_data = NULL;
2997 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2999 __bt_hal_gatt_emit_interface_removed(app_path, serv_info->serv_path,
3000 GATT_SERV_INTERFACE);
3003 err = BT_STATUS_FAIL;
3006 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
3008 DBG("Unregistered the service on properties interface");
3010 /* Remove from global list */
3011 gatt_services = g_slist_remove(gatt_services, serv_info);
3012 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
3014 /* Remove from GATT Server's list of services */
3015 _bt_remote_service_from_gatt_server(server_if, service_handle);
3017 if (gatt_services == NULL)
3018 INFO("All GATT Services of all GATT Servers are unregistered");
3020 if (err == BT_STATUS_SUCCESS) {
3021 INFO("Send GATT Service deleted Event");
3022 /* Send Service handle to application */
3023 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
3024 user_data->srvc_hdl = serv_info->service_handle;
3025 user_data->instance_data = server_if;
3026 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
3029 /* Free the service */
3030 __bt_hal_gatt_free_service_info(serv_info);
3034 static gboolean __bt_gatt_get_service_state(const char *service_path)
3036 struct gatt_service_info *svc_info = NULL;
3038 for (l = gatt_services; l; l = g_slist_next(l)) {
3040 svc_info = (struct gatt_service_info *)l->data;
3042 if (!g_strcmp0(svc_info->serv_path, service_path))
3043 return svc_info->is_svc_registered;
3046 DBG("gatt service info is NULL");
3050 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
3051 int len, int confirm, char* p_value)
3053 CHECK_BTGATT_INIT();
3056 GVariantBuilder *outer_builder;
3057 GVariantBuilder *invalidated_builder;
3059 /* For Value update via PropertyChange */
3060 GVariantBuilder *outer_builder1;
3061 GVariantBuilder *inner_builder1;
3062 GVariantBuilder *invalidated_builder1;
3063 GVariant *update_value = NULL;
3065 /* Other variables */
3066 struct gatt_client_info_t *conn_info = NULL;
3067 gchar *serv_path = NULL;
3068 char *char_path = NULL;
3069 gchar **line_argv = NULL;
3070 gboolean notify = TRUE;
3071 gboolean ret = TRUE;
3072 int err = BT_STATUS_SUCCESS;
3074 GError *error = NULL;
3077 memset(addr, 0x00, sizeof(addr));
3079 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3080 if (conn_info == NULL) {
3081 ERR("No Connection Inforamtion!!!");
3082 return BT_STATUS_FAIL;
3085 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
3087 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3088 if (char_path == NULL)
3089 return BT_STATUS_FAIL;
3091 line_argv = g_strsplit_set(char_path, "/", 0);
3092 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3094 if (!__bt_gatt_get_service_state(serv_path)) {
3095 DBG("service not registered for this characteristic \n");
3097 g_strfreev(line_argv);
3098 return BT_STATUS_FAIL;
3101 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3102 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3104 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
3105 g_variant_new("b", notify));
3107 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
3108 DBG("Send Indication to Unicast addr [%s]", addr);
3110 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
3111 g_variant_new("s", addr));
3113 DBG("Set characteristic Notification \n");
3114 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3116 "org.freedesktop.DBus.Properties",
3117 "PropertiesChanged",
3118 g_variant_new("(sa{sv}as)",
3119 "org.bluez.GattCharacteristic1",
3120 outer_builder, invalidated_builder),
3124 if (error != NULL) {
3125 ERR("D-Bus API failure: errCode[%x], \
3127 error->code, error->message);
3128 g_clear_error(&error);
3130 err = BT_STATUS_FAIL;
3133 g_variant_builder_unref(outer_builder);
3134 g_variant_builder_unref(invalidated_builder);
3137 /* Notifying Done, now update Value to Bluez via PropertyChanged */
3138 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
3140 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3141 for (i = 0; i < len; i++)
3142 g_variant_builder_add(inner_builder1, "y", p_value[i]);
3144 update_value = g_variant_new("ay", inner_builder1);
3147 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3148 g_variant_builder_add(outer_builder1, "{sv}", "Value",
3151 DBG("Updating characteristic value \n");
3152 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3154 "org.freedesktop.DBus.Properties",
3155 "PropertiesChanged",
3156 g_variant_new("(sa{sv}as)",
3157 "org.bluez.GattCharacteristic1",
3158 outer_builder1, invalidated_builder1),
3162 if (error != NULL) {
3163 ERR("D-Bus API failure: errCode[%x], \
3165 error->code, error->message);
3166 g_clear_error(&error);
3168 err = BT_STATUS_FAIL;
3170 struct gatt_char_info *char_info = NULL;
3172 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3173 if (char_info == NULL) {
3175 g_strfreev(line_argv);
3176 g_variant_builder_unref(inner_builder1);
3177 g_variant_builder_unref(outer_builder1);
3178 g_variant_builder_unref(invalidated_builder1);
3180 return BT_STATUS_FAIL;
3183 char_info->value_length = len;
3185 char_info->char_value = (char *)realloc(char_info->char_value, len);
3186 if (char_info->char_value) {
3187 for (i = 0; i < len; i++)
3188 char_info->char_value[i] = p_value[i];
3193 g_strfreev(line_argv);
3194 g_variant_builder_unref(inner_builder1);
3195 g_variant_builder_unref(outer_builder1);
3196 g_variant_builder_unref(invalidated_builder1);
3201 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3202 int status, btgatt_response_t *response)
3204 CHECK_BTGATT_INIT();
3206 struct gatt_req_info *req_info = NULL;
3207 struct gatt_client_info_t *conn_info = NULL;
3210 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3211 if (conn_info == NULL) {
3212 ERR("No Connection Inforamtion. conn_id %d", conn_id);
3213 return BT_STATUS_FAIL;
3216 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3217 if (req_info == NULL) {
3218 ERR("No Request Inforamtion. conn_id %d", conn_id);
3219 return BT_STATUS_FAIL;
3222 if (status != BT_STATUS_SUCCESS) {
3223 ERR("resp_state is 0x%X, conn_id %d", status, conn_id);
3225 g_dbus_method_invocation_return_dbus_error(req_info->context,
3226 "org.bluez.Error.Failed", "Application Error");
3228 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3230 req_info->context = NULL;
3231 if (req_info->attr_path)
3232 g_free(req_info->attr_path);
3233 if (req_info->svc_path)
3234 g_free(req_info->svc_path);
3237 return BT_STATUS_SUCCESS;
3240 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3241 GVariantBuilder *inner_builder = NULL;
3242 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3244 if (response->attr_value.len > 0) {
3245 for (i = 0; i < response->attr_value.len; i++)
3246 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3248 g_dbus_method_invocation_return_value(req_info->context,
3249 g_variant_new("(ay)", inner_builder));
3251 g_variant_builder_unref(inner_builder);
3253 g_dbus_method_invocation_return_value(req_info->context, NULL);
3255 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3257 req_info->context = NULL;
3258 if (req_info->attr_path)
3259 g_free(req_info->attr_path);
3260 if (req_info->svc_path)
3261 g_free(req_info->svc_path);
3264 return BT_STATUS_SUCCESS;
3268 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3269 int status, int fd, int mtu, void *fdlist)
3271 CHECK_BTGATT_INIT();
3273 struct gatt_req_info *req_info = NULL;
3274 struct gatt_client_info_t *conn_info = NULL;
3276 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3278 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3279 if (conn_info == NULL) {
3280 ERR("No Connection Inforamtion!!!");
3281 return BT_STATUS_FAIL;
3284 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3285 if (req_info == NULL) {
3286 ERR("No Request Inforamtion!!!");
3287 return BT_STATUS_FAIL;
3290 if (status != BT_STATUS_SUCCESS) {
3291 ERR("resp_state is 0x%X", status);
3293 g_dbus_method_invocation_return_dbus_error(req_info->context,
3294 "org.bluez.Error.Failed", "Application Error");
3296 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3298 req_info->context = NULL;
3299 if (req_info->attr_path)
3300 g_free(req_info->attr_path);
3301 if (req_info->svc_path)
3302 g_free(req_info->svc_path);
3305 return BT_STATUS_SUCCESS;
3309 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3311 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3312 g_dbus_method_invocation_return_value_with_unix_fd_list(
3313 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3315 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3317 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3318 g_dbus_method_invocation_return_value_with_unix_fd_list(
3319 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3322 g_dbus_method_invocation_return_value(req_info->context, NULL);
3324 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3326 req_info->context = NULL;
3327 if (req_info->attr_path)
3328 g_free(req_info->attr_path);
3329 if (req_info->svc_path)
3330 g_free(req_info->svc_path);
3333 return BT_STATUS_SUCCESS;
3337 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3338 int value_length, char* att_value)
3340 CHECK_BTGATT_INIT();
3342 /* Other variables */
3343 char *char_path = NULL;
3344 gboolean ret = TRUE;
3345 GError *error = NULL;
3347 GVariantBuilder *outer_builder;
3348 GVariantBuilder *inner_builder;
3349 GVariantBuilder *invalidated_builder;
3350 GVariant *update_value = NULL;
3351 int err = BT_STATUS_SUCCESS;
3353 gchar **line_argv = NULL;
3354 gchar *serv_path = NULL;
3356 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3357 if (char_path == NULL)
3358 return BT_STATUS_FAIL;
3360 line_argv = g_strsplit_set(char_path, "/", 0);
3361 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3363 if (!__bt_gatt_get_service_state(serv_path)) {
3364 DBG("service not registered for this characteristic \n");
3366 g_strfreev(line_argv);
3367 return BT_STATUS_FAIL;
3371 line_argv = g_strsplit_set(char_path, "/", 0);
3372 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3374 if (!__bt_gatt_get_service_state(serv_path)) {
3375 DBG("service not registered for this characteristic \n");
3377 g_strfreev(line_argv);
3378 return BT_STATUS_FAIL;
3381 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3382 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3384 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3385 for (i = 0; i < value_length; i++)
3386 g_variant_builder_add(inner_builder, "y", att_value[i]);
3388 update_value = g_variant_new("ay", inner_builder);
3390 g_variant_builder_add(outer_builder, "{sv}", "Value",
3393 DBG("Updating characteristic value \n");
3394 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3396 "org.freedesktop.DBus.Properties",
3397 "PropertiesChanged",
3398 g_variant_new("(sa{sv}as)",
3399 "org.bluez.GattCharacteristic1",
3400 outer_builder, invalidated_builder),
3404 if (error != NULL) {
3405 ERR("D-Bus API failure: errCode[%x], \
3407 error->code, error->message);
3408 g_clear_error(&error);
3410 err = BT_STATUS_FAIL;
3412 struct gatt_char_info *char_info = NULL;
3414 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3415 if (char_info == NULL) {
3417 g_strfreev(line_argv);
3418 g_variant_builder_unref(inner_builder);
3419 g_variant_builder_unref(outer_builder);
3420 g_variant_builder_unref(invalidated_builder);
3422 return BT_STATUS_FAIL;
3425 char_info->value_length = value_length;
3427 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3428 if (char_info->char_value) {
3429 for (i = 0; i < value_length; i++)
3430 char_info->char_value[i] = att_value[i];
3436 g_strfreev(line_argv);
3437 g_variant_builder_unref(inner_builder);
3438 g_variant_builder_unref(outer_builder);
3439 g_variant_builder_unref(invalidated_builder);
3444 static bt_status_t gatt_server_listen(int server_if, bool start)
3446 CHECK_BTGATT_INIT();
3448 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3450 DBG("server_if: [%d]", server_if);
3452 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3453 if (server_register_info == NULL) {
3454 DBG("gatt server is not registered");
3455 return BT_STATUS_FAIL;
3458 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3460 if (server_register_info->adv_slot_id < 0 ) {
3461 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3462 return BT_STATUS_FAIL;
3465 /* Send Data to LE Module */
3466 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, start, FALSE);
3469 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3470 bool include_txpower, int min_interval, int max_interval, int appearance,
3471 uint16_t manufacturer_len, char* manufacturer_data,
3472 uint16_t service_data_len, char* service_data,
3473 uint16_t service_uuid_len, char* service_uuid)
3475 CHECK_BTGATT_INIT();
3476 return BT_STATUS_SUCCESS;
3479 static int bt_hal_gatts_allocate_adv_slot(struct hal_gatts_server_register_info_t *server_register_info)
3481 int adv_slot_id = -1;
3483 /* allocate adv slot for gatt server if not assigned */
3484 if (server_register_info->adv_slot_id < 0 ) {
3485 adv_slot_id = _bt_hal_get_available_adv_slot_id(&server_register_info->app_uuid, FALSE);
3486 if (adv_slot_id < 0) {
3487 ERR("failed to get the adv_slot");
3491 server_register_info->adv_slot_id = adv_slot_id;
3494 DBG("gatt server:[%d] Assigned adv_slot [%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3499 int bt_hal_gatts_allocate_adv_slot_by_server_if(int server_if)
3501 CHECK_BTGATT_INIT();
3505 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3507 DBG("server_if: [%d]", server_if);
3509 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3510 if (server_register_info == NULL) {
3511 DBG("gatt server is not registered");
3515 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3517 if (server_register_info->adv_slot_id < 0 ) {
3518 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3520 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3522 DBG("failed to get adv_slot");
3527 return server_register_info->adv_slot_id;
3530 void bt_hal_gatts_release_adv_slot(int server_if)
3532 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3534 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3535 if (server_register_info == NULL) {
3536 ERR("failed to get server_register_info");
3540 if (server_register_info->adv_slot_id < 0) {
3541 ERR("adv_slot is not allocated");
3545 if(_bt_hal_is_advertising_in_slot(server_register_info->adv_slot_id) == FALSE) {
3546 DBG("advertising is disabled");
3547 _bt_hal_free_server_slot(server_register_info->adv_slot_id);
3548 server_register_info->adv_slot_id = -1;
3552 int bt_hal_gatts_get_adv_slot_id(int server_if)
3554 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3556 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3557 if (server_register_info == NULL) {
3558 DBG("failed to get server_register_info");
3562 return server_register_info->adv_slot_id;
3565 int bt_hal_gatts_get_server_if(int slot_id)
3567 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3569 server_register_info = bt_hal_gatts_find_server_register_info_by_slot_id(slot_id);
3570 if (server_register_info == NULL) {
3571 DBG("failed to get server_register_info");
3575 return server_register_info->server_if;
3578 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3580 CHECK_BTGATT_INIT();
3584 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3586 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3587 if (server_register_info == NULL) {
3588 ERR("gatt server is not registered");
3589 return BT_STATUS_FAIL;
3592 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3594 if (server_register_info->adv_slot_id < 0 ) {
3595 DBG("adv_slot is not assigned to server:[%d]", server_if);
3597 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3599 ERR("failed to get adv_slot");
3600 return BT_STATUS_FAIL;
3604 /* Send Enable Advertising request to LE Module */
3605 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, TRUE, TRUE);
3608 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3609 int chnl_map, int tx_power, int timeout_s)
3611 CHECK_BTGATT_INIT();
3613 /* Send Advertising parameters to LE Module */
3614 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3615 chnl_map, tx_power, timeout_s);
3618 static bt_status_t gatt_server_set_filter_policy(int filter_policy)
3620 CHECK_BTGATT_INIT();
3622 /* Send the Filter policy parameter to LE Module */
3623 _bt_hal_set_filter_policy_param(filter_policy);
3624 return BT_STATUS_SUCCESS;
3627 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3629 CHECK_BTGATT_INIT();
3631 /* Send Data to LE Module */
3632 return _bt_hal_set_advertising_data(adv_param_setup);
3635 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3637 CHECK_BTGATT_INIT();
3639 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3641 DBG("server_if: [%d]", server_if);
3643 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3644 if (server_register_info == NULL) {
3645 DBG("gatt server is not registered");
3646 return BT_STATUS_FAIL;
3649 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3651 if (server_register_info->adv_slot_id < 0 ) {
3652 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3653 return BT_STATUS_FAIL;
3656 /* Send Data to LE Module */
3657 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, FALSE, TRUE);
3660 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3662 CHECK_BTGATT_INIT();
3663 char *object_path = NULL;
3665 GDBusProxy *device_proxy;
3666 GError *error = NULL;
3668 GVariant *tmp_value;
3669 GDBusConnection *conn;
3670 GVariant *result = NULL;
3671 int ret = BT_STATUS_SUCCESS;
3672 struct gatt_client_info_t *conn_info = NULL;
3675 if (mtu_size == NULL)
3676 return BT_STATUS_PARM_INVALID;
3678 /* GDBUS Connection Info validate */
3679 conn = _bt_hal_get_system_gconn();
3681 ERR("Could not get System DBUS Connection");
3682 return BT_STATUS_FAIL;
3685 /* Connection Info validate */
3686 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3687 if (conn_info == NULL) {
3688 ERR("No Connection Inforamtion!!!");
3689 return BT_STATUS_FAIL;
3693 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3694 if (object_path == NULL)
3695 return BT_STATUS_FAIL;
3697 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3698 NULL, BT_HAL_BLUEZ_NAME, object_path,
3699 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3701 g_free(object_path);
3702 if (device_proxy == NULL)
3703 return BT_STATUS_FAIL;
3705 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3706 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3707 G_DBUS_CALL_FLAGS_NONE,
3711 if (result == NULL) {
3712 if (error != NULL) {
3713 ERR("Error occured in Proxy call [%s]\n", error->message);
3714 g_error_free(error);
3716 g_object_unref(device_proxy);
3717 return BT_STATUS_FAIL;
3720 g_variant_get(result , "(@a{sv})", &value);
3721 g_variant_unref(result);
3723 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3724 if (tmp_value == NULL) {
3725 g_object_unref(device_proxy);
3726 g_variant_unref(value);
3727 return BT_STATUS_FAIL;
3730 mtu = g_variant_get_uint16(tmp_value);
3732 DBG("ATT MTU : [%d]", mtu);
3734 g_variant_unref(tmp_value);
3735 g_variant_unref(value);
3736 g_object_unref(device_proxy);
3738 *mtu_size = (int) mtu;
3743 const btgatt_server_interface_t btgatt_server_interface = {
3744 .register_server = gatt_server_register_app,
3745 .unregister_server = gatt_server_unregister_app,
3746 .connect = gatt_server_open,
3747 .disconnect = gatt_server_close,
3748 .add_service = gatt_server_add_service,
3749 .add_included_service = gatt_server_add_included_service,
3750 .add_characteristic = gatt_server_add_characteristic,
3751 .add_descriptor = gatt_server_add_descriptor,
3752 .start_service = gatt_server_start_service,
3753 .stop_service = gatt_server_stop_service,
3754 .delete_service = gatt_server_delete_service,
3755 .send_indication = gatt_server_send_indication,
3756 .send_response = gatt_server_send_response,
3757 .update_att_value = gatt_server_update_att_value,
3758 .listen = gatt_server_listen,
3759 .set_adv_data = gatt_server_set_adv_data,
3760 .multi_adv_enable = gatt_server_multi_adv_enable,
3761 .multi_adv_update = gatt_server_multi_adv_update,
3762 .set_filter_policy = gatt_server_set_filter_policy,
3763 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3764 .multi_adv_disable = gatt_server_multi_adv_disable,
3765 .get_att_mtu = gatt_server_get_mtu_size,
3766 .send_response_acquire = gatt_server_send_acquire_response