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 void _bt_remote_service_from_gatt_server(int instance, int service_handle)
410 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
411 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
413 if (app->slot == instance) {
414 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
415 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
416 if (srv->service_handle == service_handle) {
417 app->services = g_slist_remove(app->services, srv);
425 static void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
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 == slot) {
432 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
433 serv_info->service_handle, slot);
434 app->services = g_slist_append(app->services, serv_info);
439 int _bt_get_remote_gatt_client_conn_id(char *address)
442 struct gatt_client_info_t *info = NULL;
444 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
445 info = (struct gatt_client_info_t*)l->data;
449 if (!g_strcmp0(info->addr, address)) {
450 INFO("Remote GATT client found addr[%s]", info->addr);
451 return info->connection_id;
457 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(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);
475 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
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 (info->connection_id == conn_id) {
486 INFO("Remote GATT client found addr[%s]", info->addr);
493 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
498 struct gatt_client_info_t *info = NULL;
499 struct gatt_req_info *info1 = NULL;
501 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
502 info = (struct gatt_client_info_t*)l->data;
506 if (info->connection_id == conn_id) {
508 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
510 info1 = (struct gatt_req_info*)l1->data;
514 if (info1->request_id == trans_id) {
515 INFO("Remote GATT client found addr[%s]", info->addr);
524 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
526 struct hal_ev_gatt_server_connected ev;
527 struct gatt_client_info_t *conn_info = NULL;
528 memset(&ev, 0, sizeof(ev));
530 /* Convert address to hex */
531 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
533 /* Create Connection ID */
534 /* Check if device is already in connected list */
535 conn_info = __bt_find_remote_gatt_client_info(address);
537 /* If disconnected, and conn info found, then remove conn info */
538 if (is_connected == FALSE) {
539 DBG("GATT Disconnected");
541 INFO("Remove GATT client info from List..");
542 /* Remove info from List */
543 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
544 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
547 ERR("GATT callback not registered");
549 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
550 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
551 ev.conn_id = conn_info->connection_id;
552 ev.server_instance = conn_info->instance_id;
553 ev.connected = is_connected;
555 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
557 g_free(conn_info->addr);
560 /* If connected, and conn info NOT found, then add conn info */
564 /* Find Server Instance */
565 instance = bt_hal_gatts_get_gatt_server_instance();
566 if (instance == -1) {
567 ERR("Not even a single GATT server is registered");
568 ev.conn_id = ++hal_gatt_conn_id;
569 ev.server_instance = -1;
570 ev.connected = is_connected;
571 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
574 DBG("server instance [%d]", instance);
577 /* Save Connection info */
578 conn_info = g_new0(struct gatt_client_info_t, 1);
579 conn_info->addr = g_strdup(address);
580 INFO("Added GATT client addr[%s]", conn_info->addr);
581 conn_info->connection_id = ++hal_gatt_conn_id;
582 conn_info->instance_id = instance;
583 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
584 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
587 ERR("GATT callback not registered");
589 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
590 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
591 ev.conn_id = conn_info->connection_id;
592 ev.server_instance = conn_info->instance_id;
593 ev.connected = is_connected;
595 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
598 ERR("Abnormal case. conn_info should be NULL");
601 /* Send GATT connected or disconnected event */
604 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
608 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
609 struct gatt_service_info *serv_info = l1->data;
611 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
612 struct gatt_char_info *char_info = l2->data;
614 if (g_strcmp0(char_info->char_path, char_path)
616 *char_hdl = char_info->char_handle;
621 ERR("Gatt service not found");
625 static char *__bt_gatt_find_char_path_from_handle(int char_hdl)
629 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
630 struct gatt_service_info *serv_info = l1->data;
632 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
633 struct gatt_char_info *char_info = l2->data;
635 if (char_info->char_handle == char_hdl)
636 return char_info->char_path;
643 static struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
647 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
648 struct gatt_service_info *serv_info = l1->data;
650 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
651 struct gatt_char_info *char_info = l2->data;
653 if (char_info->char_handle == char_hdl)
661 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
663 GSList *l1, *l2, *l3;
665 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
666 struct gatt_service_info *serv_info = l1->data;
668 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
669 struct gatt_char_info *char_info = l2->data;
671 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
672 struct gatt_desc_info *desc_info = l3->data;
674 if (g_strcmp0(desc_info->desc_path, desc_path)
676 *desc_hdl = desc_info->desc_handle;
682 ERR("Gatt service not found");
686 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
688 const gchar *object_path,
689 const gchar *interface_name,
690 const gchar *method_name,
691 GVariant *parameters,
692 GDBusMethodInvocation *invocation,
697 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
698 GVariantBuilder *builder;
699 GVariantBuilder *inner_builder1 = NULL;
700 GVariant *svc_char = NULL;
702 GSList *gatt_services = NULL;
704 instance = (int*)user_data;
705 gboolean writeAcquired = FALSE;
706 gboolean notifyAcquired = FALSE;
708 DBG("Getting values for service, chars and descriptors");
709 DBG("GATT Server App for which services are requested [%d]", *instance);
712 builder = g_variant_builder_new(
713 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
716 gatt_services = _bt_get_service_list_from_server(*instance);
718 if (g_slist_length(gatt_services) == 0) {
719 ERR("No registered GATT services!!!!");
720 g_dbus_method_invocation_return_value(invocation, NULL);
721 g_variant_builder_unref(builder);
725 for (l = gatt_services; l != NULL; l = l->next) {
726 GVariantBuilder *svc_builder = NULL;
727 GVariantBuilder *inner_builder = NULL;
728 struct gatt_service_info *serv_info = l->data;
729 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
731 /* Prepare inner builder for GattService1 interface */
732 DBG("Creating builder for service");
733 svc_builder = g_variant_builder_new(
734 G_VARIANT_TYPE("a{sa{sv}}"));
735 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
737 g_variant_builder_add(inner_builder, "{sv}", "UUID",
738 g_variant_new_string(serv_info->service_uuid));
740 g_variant_builder_add(inner_builder, "{sv}", "Primary",
741 g_variant_new_boolean(serv_info->is_svc_primary));
744 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
745 DBG("Adding Charatarisitcs list");
746 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
747 struct gatt_char_info *char_info = l4->data;
748 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
749 char_info->char_handle, serv_info->service_handle);
750 g_variant_builder_add(inner_builder1, "o",
751 char_info->char_path);
752 DBG("%s", char_info->char_path);
755 svc_char = g_variant_new("ao", inner_builder1);
756 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
759 g_variant_builder_add(svc_builder, "{sa{sv}}",
763 g_variant_builder_add(builder, "{oa{sa{sv}}}",
764 serv_info->serv_path,
767 g_variant_builder_unref(inner_builder1);
769 /* Prepare inner builder for GattCharacteristic1 interface */
771 GSList *l2 = serv_info->char_data;
772 DBG("Creating builder for characteristics \n");
775 DBG("characteristic data is NULL");
777 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
779 GVariantBuilder *char_builder = NULL;
780 GVariantBuilder *inner_builder = NULL;
781 GVariantBuilder *builder1 = NULL;
782 GVariantBuilder *builder2 = NULL;
783 GVariantBuilder *builder3 = NULL;
784 GVariant *char_val = NULL;
785 GVariant *flags_val = NULL;
786 GVariant *char_desc = NULL;
787 char *unicast = NULL;
788 gboolean notify = FALSE;
791 char_builder = g_variant_builder_new(
794 inner_builder = g_variant_builder_new(
798 struct gatt_char_info *char_info = l2->data;
799 if (char_info == NULL) {
800 ERR("char_info is NULL");
805 g_variant_builder_add(inner_builder, "{sv}", "UUID",
806 g_variant_new_string(char_info->char_uuid));
808 g_variant_builder_add(inner_builder, "{sv}", "Service",
809 g_variant_new("o", serv_info->serv_path));
811 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
813 if (char_info->char_value != NULL) {
814 for (i = 0; i < char_info->value_length; i++) {
815 g_variant_builder_add(builder1, "y",
816 char_info->char_value[i]);
818 char_val = g_variant_new("ay", builder1);
819 g_variant_builder_add(inner_builder, "{sv}",
823 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
824 for (i = 0; i < char_info->flags_length; i++) {
825 g_variant_builder_add(builder2, "s",
826 char_info->char_flags[i]);
828 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
829 DBG("setting WriteAcquired property");
830 writeAcquired = TRUE;
833 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
834 DBG("setting NotifyAcquired property");
835 notifyAcquired = TRUE;
839 flags_val = g_variant_new("as", builder2);
840 g_variant_builder_add(inner_builder, "{sv}", "Flags",
844 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
845 g_variant_new("b", notify));
848 if (writeAcquired == TRUE) {
849 DBG("adding WriteAcquired property");
850 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
851 g_variant_new("b", writeAcquired));
855 if (notifyAcquired == TRUE) {
856 DBG("adding NotifyAcquired property");
857 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
858 g_variant_new("b", notifyAcquired));
862 unicast = g_strdup("00:00:00:00:00:00");
863 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
864 g_variant_new("s", unicast));
867 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
868 DBG("Adding Descriptors list");
870 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
871 struct gatt_desc_info *desc_info = l4->data;
872 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
873 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
874 g_variant_builder_add(builder3, "o",
875 desc_info->desc_path);
876 DBG("%s", desc_info->desc_path);
879 char_desc = g_variant_new("ao", builder3);
880 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
883 g_variant_builder_add(char_builder, "{sa{sv}}",
884 GATT_CHAR_INTERFACE , inner_builder);
885 g_variant_builder_add(builder, "{oa{sa{sv}}}",
886 char_info->char_path, char_builder);
888 /*Prepare inner builder for GattDescriptor1 interface*/
890 GSList *l3 = char_info->desc_data;
893 DBG("descriptor data is NULL");
895 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
897 DBG("Creating builder for descriptor \n");
899 GVariantBuilder *desc_builder = NULL;
900 GVariantBuilder *inner_builder = NULL;
901 GVariantBuilder *builder1 = NULL;
902 GVariantBuilder *builder2 = NULL;
903 GVariant *desc_val = NULL;
905 desc_builder = g_variant_builder_new(
908 inner_builder = g_variant_builder_new(
912 struct gatt_desc_info *desc_info = l3->data;
913 if (desc_info == NULL) {
914 ERR("desc_info is NULL");
919 g_variant_builder_add(inner_builder,
921 g_variant_new_string(
922 desc_info->desc_uuid));
925 g_variant_builder_add(inner_builder, "{sv}",
928 char_info->char_path));
931 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
933 if (desc_info->desc_value != NULL) {
934 for (i = 0; i < desc_info->value_length; i++) {
935 g_variant_builder_add(builder1, "y",
936 desc_info->desc_value[i]);
938 desc_val = g_variant_new("ay", builder1);
939 g_variant_builder_add(inner_builder, "{sv}",
944 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
946 for (i = 0; i < desc_info->flags_length; i++) {
947 g_variant_builder_add(builder2, "s",
948 desc_info->desc_flags[i]);
951 flags_val = g_variant_new("as", builder2);
952 g_variant_builder_add(inner_builder, "{sv}", "Flags",
955 g_variant_builder_add(desc_builder, "{sa{sv}}",
959 g_variant_builder_add(builder, "{oa{sa{sv}}}",
960 desc_info->desc_path,
963 /*unref descriptor builder pointers*/
964 g_variant_builder_unref(builder1);
965 g_variant_builder_unref(builder2);
966 g_variant_builder_unref(inner_builder);
967 g_variant_builder_unref(desc_builder);
972 /*unref char builder pointers*/
973 g_variant_builder_unref(builder1);
974 g_variant_builder_unref(builder2);
975 g_variant_builder_unref(builder3);
976 g_variant_builder_unref(inner_builder);
977 g_variant_builder_unref(char_builder);
980 /*unref service builder pointers*/
981 g_variant_builder_unref(inner_builder);
982 g_variant_builder_unref(svc_builder);
985 /* Return builder as method reply */
986 DBG("Sending gatt service builder values to Bluez");
987 g_dbus_method_invocation_return_value(invocation,
997 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
999 const gchar *object_path,
1000 const gchar *interface_name,
1001 const gchar *method_name,
1002 GVariant *parameters,
1003 GDBusMethodInvocation *invocation,
1007 if (g_strcmp0(method_name, "ReadValue") == 0) {
1008 struct hal_ev_gatt_server_read_req ev;
1013 struct gatt_client_info_t *conn_info = NULL;
1014 struct gatt_req_info *req_info = NULL;
1015 struct gatt_service_info *svc_info = NULL;
1019 DBG("Application path = %s", object_path);
1020 DBG("Sender = %s", sender);
1022 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1023 if (svc_info == NULL) {
1024 ERR("Coudn't find service for %s", object_path);
1025 g_dbus_method_invocation_return_value(invocation, NULL);
1029 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1030 DBG("Request id = %u, Offset = %u", req_id, offset);
1032 /* Check if device is already in connected list */
1033 conn_info = __bt_find_remote_gatt_client_info(addr);
1035 if (conn_info == NULL) {
1036 ERR("Coudn't find Connection info for %s", addr);
1037 g_dbus_method_invocation_return_value(invocation, NULL);
1042 ERR("GATT callback NOT registered");
1043 g_dbus_method_invocation_return_value(invocation, NULL);
1047 /* Store requests information */
1048 req_info = g_new0(struct gatt_req_info, 1);
1049 req_info->attr_path = g_strdup(object_path);
1050 req_info->svc_path = g_strdup(svc_info->serv_path);
1051 req_info->request_id = req_id;
1052 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1053 req_info->offset = offset;
1054 req_info->context = invocation;
1056 /* Append request info in list of requests for the particular connection */
1057 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1059 /* Send HAL event */
1060 memset(&ev, 0, sizeof(ev));
1061 ev.conn_id = conn_info->connection_id;
1062 ev.trans_id = req_id;
1063 ev.att_handle = desc_hdl;
1065 ev.is_long = false; /* TODO*/
1067 /* Convert address to hex */
1068 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1070 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1072 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1074 GVariant *var = NULL;
1078 gboolean response_needed = FALSE;
1079 struct hal_ev_gatt_server_write_req ev;
1083 struct gatt_service_info *svc_info = NULL;
1084 struct gatt_client_info_t *conn_info = NULL;
1085 struct gatt_req_info *req_info = NULL;
1087 memset(&ev, 0, sizeof(ev));
1090 DBG("Application path = %s", object_path);
1091 DBG("Sender = %s", sender);
1093 g_variant_get(parameters, "(&suqb@ay)",
1094 &addr, &req_id, &offset, &response_needed, &var);
1095 DBG("Request id = %u, Offset = %u", req_id, offset);
1097 /* Check if device is already in connected list */
1098 conn_info = __bt_find_remote_gatt_client_info(addr);
1100 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1102 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1103 g_variant_unref(var);
1104 if (response_needed)
1105 g_dbus_method_invocation_return_value(invocation, NULL);
1107 g_object_unref(invocation);
1111 len = g_variant_get_size(var);
1112 if (len > 0 && len < 600) {
1114 data = (char *)g_variant_get_data(var);
1115 memcpy(ev.value, data, len);
1118 if (response_needed) {
1119 /* Store request information */
1120 req_info = g_new0(struct gatt_req_info, 1);
1121 req_info->attr_path = g_strdup(object_path);
1122 req_info->svc_path = g_strdup(svc_info->serv_path);
1123 req_info->request_id = req_id;
1124 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1125 req_info->offset = offset;
1126 req_info->context = invocation;
1128 /* Append request info in list of requests for the particular connection */
1129 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1131 g_object_unref(invocation);
1134 /* Send HAL event */
1135 ev.conn_id = conn_info->connection_id;
1136 ev.trans_id = req_id;
1137 ev.att_handle = desc_hdl;
1139 ev.need_rsp = response_needed;
1142 /* Convert address to hex */
1143 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1145 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1147 g_variant_unref(var);
1152 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1153 const gchar *sender,
1154 const gchar *object_path,
1155 const gchar *interface_name,
1156 const gchar *method_name,
1157 GVariant *parameters,
1158 GDBusMethodInvocation *invocation,
1161 if (g_strcmp0(method_name, "ReadValue") == 0) {
1165 struct hal_ev_gatt_server_read_req ev;
1168 struct gatt_req_info *req_info = NULL;
1169 struct gatt_client_info_t *conn_info = NULL;
1170 struct gatt_service_info *svc_info = NULL;
1172 g_variant_get(parameters, "(&suq)",
1173 &addr, &req_id, &offset);
1175 DBG("Request id = %u, Offset = %u", req_id, offset);
1176 DBG("Application path = %s", object_path);
1177 DBG("Sender = %s", sender);
1178 DBG("Address = %s", addr);
1180 /* Check if device is already in connected list */
1181 conn_info = __bt_find_remote_gatt_client_info(addr);
1183 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1185 if (svc_info == NULL || conn_info == NULL) {
1186 g_dbus_method_invocation_return_value(invocation, NULL);
1191 ERR("GATT callback NOT registered");
1192 g_dbus_method_invocation_return_value(invocation, NULL);
1196 /* Store requets information */
1197 req_info = g_new0(struct gatt_req_info, 1);
1198 req_info->attr_path = g_strdup(object_path);
1199 req_info->svc_path = g_strdup(svc_info->serv_path);
1200 req_info->request_id = req_id;
1201 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1202 req_info->offset = offset;
1203 req_info->context = invocation;
1205 /* Append request info in list of requests for the particular connection */
1206 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1208 /* Send HAL event */
1209 memset(&ev, 0, sizeof(ev));
1210 ev.conn_id = conn_info->connection_id;
1211 ev.trans_id = req_id;
1212 ev.att_handle = char_hdl;
1214 ev.is_long = false; /* TODO*/
1216 /* Convert address to hex */
1217 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1218 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1220 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1221 GVariant *var = NULL;
1225 gboolean response_needed = FALSE;
1226 struct hal_ev_gatt_server_write_req ev;
1230 struct gatt_service_info *svc_info = NULL;
1231 struct gatt_req_info *req_info = NULL;
1232 struct gatt_client_info_t *conn_info = NULL;
1234 memset(&ev, 0, sizeof(ev));
1237 DBG("Application path = %s", object_path);
1238 DBG("Sender = %s", sender);
1240 g_variant_get(parameters, "(&suqb@ay)",
1241 &addr, &req_id, &offset, &response_needed, &var);
1242 DBG("Request id = %u, Offset = %u", req_id, offset);
1244 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1246 /* Check if device is already in connected list */
1247 conn_info = __bt_find_remote_gatt_client_info(addr);
1249 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1250 g_variant_unref(var);
1251 if (response_needed)
1252 g_dbus_method_invocation_return_value(invocation, NULL);
1254 g_object_unref(invocation);
1258 len = g_variant_get_size(var);
1259 if (len > 0 && len < 600) {
1261 data = (char *)g_variant_get_data(var);
1262 memcpy(ev.value, data, len);
1266 if (response_needed) {
1267 /* Store requets information */
1268 req_info = g_new0(struct gatt_req_info, 1);
1269 req_info->attr_path = g_strdup(object_path);
1270 req_info->svc_path = g_strdup(svc_info->serv_path);
1271 req_info->request_id = req_id;
1272 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1273 req_info->offset = offset;
1274 req_info->context = invocation;
1276 /* Append request info in list of requests for the particular connection */
1277 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1280 g_object_unref(invocation);
1283 /* Send HAL event */
1284 ev.conn_id = conn_info->connection_id;
1285 ev.trans_id = req_id;
1286 ev.att_handle = char_hdl;
1288 ev.need_rsp = response_needed;
1291 /* Convert address to hex */
1292 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1294 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1296 g_variant_unref(var);
1299 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1302 struct gatt_service_info *svc_info = NULL;
1303 struct hal_ev_gatt_server_notifcation_change ev;
1306 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1307 if (svc_info == NULL || event_cb == NULL)
1310 /* Send HAL event */
1311 memset(&ev, 0, sizeof(ev));
1312 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1313 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1314 ev.att_handle = char_hdl;
1317 /* Convert address to hex */
1318 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1320 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1323 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1326 struct gatt_service_info *svc_info = NULL;
1327 struct hal_ev_gatt_server_notifcation_change ev;
1330 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1331 if (svc_info == NULL || event_cb == NULL)
1334 /* Send HAL event */
1335 memset(&ev, 0, sizeof(ev));
1336 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1337 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1338 ev.att_handle = char_hdl;
1341 /* Convert address to hex */
1342 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1344 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1347 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1349 gboolean complete = FALSE;
1352 struct gatt_service_info *svc_info = NULL;
1353 struct gatt_client_info_t *conn_info = NULL;
1355 struct hal_ev_gatt_server_indicate_cfm ev;
1357 DBG("IndicateConfirm");
1358 DBG("Application path = %s", object_path);
1359 DBG("Sender = %s", sender);
1361 g_variant_get(parameters, "(&sb)", &addr, &complete);
1362 DBG("Remote Device address number = %s", addr);
1363 DBG("Is Indicate confirmation for last device [%d]", complete);
1365 /* Check if device is already in connected list */
1366 conn_info = __bt_find_remote_gatt_client_info(addr);
1368 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1370 if (svc_info == NULL || conn_info == NULL
1371 || event_cb == NULL) {
1375 /* Send HAL event */
1376 memset(&ev, 0, sizeof(ev));
1377 ev.conn_id = conn_info->connection_id;
1378 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1379 ev.att_handle = char_hdl;
1381 /* Convert address to hex */
1382 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1384 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1385 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1389 struct hal_ev_gatt_server_acquire_write_res ev;
1390 struct gatt_service_info *svc_info = NULL;
1391 struct gatt_req_info *req_info = NULL;
1392 struct gatt_client_info_t *conn_info = NULL;
1393 char * dev_path = NULL;
1395 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1397 DBG("AcquireWrite");
1398 DBG("Application path = %s", object_path);
1399 DBG("Sender = %s", sender);
1402 g_variant_get(parameters, "(a{sv})", &iter);
1404 GVariant* value = NULL;
1405 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1406 if (g_strcmp0(key, "MTU") == 0)
1407 g_variant_get(value, "i", &mtu);
1408 else if (g_strcmp0(key, "link") == 0)
1409 g_variant_get(value, "s", &link);
1410 else if (g_strcmp0(key, "device") == 0)
1411 g_variant_get(value, "o", &dev_path);
1414 DBG("AcquireWrite values retived");
1415 DBG(" path %s LINK = %s, MTU = %u", addr, link, mtu);
1417 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1419 _bt_hal_convert_device_path_to_address(dev_path, addr);
1421 DBG("remote address %s", addr);
1423 /* Check if device is already in connected list */
1424 conn_info = __bt_find_remote_gatt_client_info(addr);
1426 if (conn_info == NULL) {
1427 ERR("Cleint info not found\n");
1431 if (svc_info == NULL) {
1432 ERR("svc_info info not found\n");
1436 /* Store requets information */
1437 req_info = g_new0(struct gatt_req_info, 1);
1438 req_info->attr_path = g_strdup(object_path);
1439 req_info->svc_path = g_strdup(svc_info->serv_path);
1440 req_info->request_id = conn_info->connection_id;
1441 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1442 req_info->offset = mtu;
1443 req_info->context = invocation;
1445 /* Append request info in list of requests for the particular connection */
1446 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1448 /* Send HAL event */
1449 memset(&ev, 0, sizeof(ev));
1450 ev.conn_id = conn_info->connection_id;
1451 ev.char_handl = char_hdl;
1453 ev.trans_id = conn_info->connection_id;
1454 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1455 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1457 DBG("HAL_EV_GATT_ACQUIRE_WRITE_RES called");
1461 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1465 struct hal_ev_gatt_server_acquire_notify ev;
1466 struct gatt_service_info *svc_info = NULL;
1467 struct gatt_client_info_t *conn_info = NULL;
1468 struct gatt_req_info *req_info = NULL;
1470 DBG("AcquireNotify");
1471 DBG("Application path = %s", object_path);
1472 DBG("Sender = %s", sender);
1475 g_variant_get(parameters, "(a{sv})", &iter);
1477 GVariant* value = NULL;
1478 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1479 if (g_strcmp0(key, "MTU") == 0)
1480 g_variant_get(value, "q", &mtu);
1483 DBG("AcquireNotify values retived");
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");
1493 /* Store requets information */
1494 req_info = g_new0(struct gatt_req_info, 1);
1495 req_info->attr_path = g_strdup(object_path);
1496 req_info->svc_path = g_strdup(svc_info->serv_path);
1497 req_info->request_id = 33;
1498 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1499 req_info->offset = mtu;
1500 req_info->context = invocation;
1502 conn_info = g_new0(struct gatt_client_info_t, 1);
1503 conn_info->addr = g_strdup(object_path);
1504 INFO("Added GATT client path[%s]", conn_info->addr);
1505 conn_info->connection_id = 33;
1506 conn_info->instance_id = 33;
1507 /* Append request info in list of requests for the particular connection */
1508 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1509 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1511 /* Send HAL event */
1512 memset(&ev, 0, sizeof(ev));
1514 ev.char_handl = char_hdl;
1518 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1520 DBG("HAL_EV_GATT_ACQUIRE_NOTIFY_RES called");
1526 g_dbus_method_invocation_return_value(invocation, NULL);
1529 static gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1532 GError *error = NULL;
1533 GVariantBuilder *array_builder;
1535 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1536 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1537 g_variant_builder_add(array_builder, "s", interface);
1539 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1540 "org.freedesktop.Dbus.Objectmanager",
1541 "InterfacesRemoved",
1542 g_variant_new("(oas)",
1543 object_path, array_builder),
1547 if (error != NULL) {
1548 /* dbus gives error cause */
1549 ERR("d-bus api failure: errcode[%x], message[%s]",
1550 error->code, error->message);
1551 g_clear_error(&error);
1554 g_variant_builder_unref(array_builder);
1559 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1566 g_free(desc_info->desc_path);
1567 g_free(desc_info->desc_uuid);
1568 g_free(desc_info->desc_value);
1570 for (i = 0; i < desc_info->flags_length; i++)
1571 g_free(desc_info->desc_flags[i]);
1576 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1583 g_free(char_info->char_path);
1584 g_free(char_info->char_uuid);
1585 g_free(char_info->char_value);
1587 for (i = 0; i < char_info->flags_length; i++)
1588 g_free(char_info->char_flags[i]);
1594 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1599 g_free(svc_info->serv_path);
1600 g_free(svc_info->service_uuid);
1604 static const GDBusInterfaceVTable desc_interface_vtable = {
1605 __bt_gatt_desc_method_call,
1610 static const GDBusInterfaceVTable char_interface_vtable = {
1611 __bt_gatt_char_method_call,
1616 static const GDBusInterfaceVTable serv_interface_vtable = {
1622 static const GDBusInterfaceVTable manager_interface_vtable = {
1623 __bt_gatt_manager_method_call,
1629 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1630 const gchar *introspection_data)
1633 GDBusNodeInfo *node_info = NULL;
1635 if (introspection_data == NULL)
1639 DBG("Create new node info");
1640 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1643 ERR("Unable to create node: %s", err->message);
1644 g_clear_error(&err);
1651 /* To send stack event to hal-av handler */
1652 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1657 void _bt_hal_unregister_gatt_server_handler_cb(void)
1662 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1664 struct hal_ev_gatt_desc_added ev;
1665 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1667 /* Prepare to GATT characteristic added event */
1668 memset(&ev, 0, sizeof(ev));
1669 ev.status = BT_STATUS_SUCCESS;
1670 ev.server_instance = data->instance_data;
1671 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1672 ev.service_handle = data->srvc_hdl;
1673 ev.desc_handle = data->desc_hdl;
1676 ERR("GATT Descriptor Added callback registered");
1678 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1679 data->instance_data, data->srvc_hdl, data->desc_hdl);
1681 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1688 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1690 struct hal_ev_gatt_char_added ev;
1691 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1693 /* Prepare to GATT characteristic added event */
1694 memset(&ev, 0, sizeof(ev));
1695 ev.status = BT_STATUS_SUCCESS;
1696 ev.server_instance = data->instance_data;
1697 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1698 ev.service_handle = data->srvc_hdl;
1699 ev.char_handle = data->char_hdl;
1702 ERR("GATT Characteristic Added callback registered");
1704 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1705 data->instance_data, data->srvc_hdl, data->char_hdl);
1707 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1714 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1716 struct hal_ev_gatt_service_added ev;
1717 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1719 /* Prepare to GATT Service added event */
1720 memset(&ev, 0, sizeof(ev));
1721 ev.status = BT_STATUS_SUCCESS;
1722 ev.server_instance = data->instance_data;
1723 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1724 ev.service_handle = data->srvc_hdl;
1725 ev.is_primary = data->is_primary;
1728 ERR("GATT Service Added callback registered");
1730 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1731 data->instance_data, data->srvc_hdl);
1732 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1739 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1741 struct hal_ev_gatt_service_started ev;
1742 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1744 /* Prepare to GATT Service added event */
1745 memset(&ev, 0, sizeof(ev));
1746 ev.status = BT_STATUS_SUCCESS;
1747 ev.server_instance = data->instance_data;
1748 ev.service_handle = data->srvc_hdl;
1751 ERR("GATT Service Started callback registered");
1753 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1754 data->instance_data, data->srvc_hdl);
1755 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1762 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1764 struct hal_ev_gatt_service_deleted ev;
1765 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1767 /* Prepare to GATT Service added event */
1768 memset(&ev, 0, sizeof(ev));
1769 ev.status = BT_STATUS_SUCCESS;
1770 ev.server_instance = data->instance_data;
1771 ev.service_handle = data->srvc_hdl;
1774 ERR("GATT Service Deleted callback registered");
1776 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1777 data->instance_data, data->srvc_hdl);
1778 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1785 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1787 struct hal_ev_server_instance_registered ev;
1788 hal_register_server_data *data = (hal_register_server_data*) user_data;
1790 /* Prepare to send AV connecting event */
1791 memset(&ev, 0, sizeof(ev));
1792 ev.status = BT_STATUS_SUCCESS;
1793 ev.server_instance = data->instance_data;
1794 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1797 ERR("GATT Register Server Instance Callback not registered");
1799 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1800 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1808 static int bt_hal_gatts_get_gatt_server_instance()
1813 struct hal_gatts_server_register_info_t *info = NULL;
1815 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1816 info = (struct hal_gatts_server_register_info_t *)l->data;
1821 return info->server_if;
1827 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_from_uuid(bt_uuid_t *app_uuid)
1832 struct hal_gatts_server_register_info_t *info = NULL;
1834 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1835 info = (struct hal_gatts_server_register_info_t *)l->data;
1840 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
1841 DBG("gatt server register found");
1849 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info(int server_if)
1852 struct hal_gatts_server_register_info_t *info = NULL;
1854 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1855 info = (struct hal_gatts_server_register_info_t *)l->data;
1860 if (info->server_if == server_if) {
1868 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_by_slot_id(int adv_slot_id)
1873 struct hal_gatts_server_register_info_t *info = NULL;
1875 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1876 info = (struct hal_gatts_server_register_info_t *)l->data;
1881 if (info->adv_slot_id == adv_slot_id) {
1882 DBG("gatt server register found");
1890 static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_uuid_t *app_uuid)
1892 struct hal_gatts_server_register_info_t * server_register_info = NULL;
1893 int instance_id = 0;
1895 server_register_info = bt_hal_gatts_find_server_register_info_from_uuid(app_uuid);
1896 if (server_register_info != NULL) {
1897 DBG("gatt server is already registered");
1898 return server_register_info;
1901 instance_id = __bt_hal_gatt_assign_id();
1902 if (instance_id == -1) {
1903 ERR("Fail to allocate the server if");
1907 server_register_info = g_malloc0(sizeof(struct hal_gatts_server_register_info_t));
1908 server_register_info->server_if = instance_id;
1910 DBG("Adding the gatt server app. server_if:[%d]", server_register_info->server_if);
1912 server_register_info->adv_slot_id = -1;
1913 memcpy(&server_register_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
1914 hal_gatts_server_register_list = g_slist_append(hal_gatts_server_register_list, server_register_info);
1916 return server_register_info;
1919 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1921 CHECK_BTGATT_INIT();
1922 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1924 DBG("Register server instance request");
1925 server_register_info = bt_hal_gatts_add_server_app(uuid);
1926 if (server_register_info == NULL) {
1927 ERR("Fail to register the server app");
1928 return BT_STATUS_FAIL;
1931 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1932 user_data->instance_data = server_register_info->server_if;
1935 * As we need to provide async callback to user from HAL, simply schedule a
1936 * callback method which will carry actual result
1938 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1939 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1941 /* If available, then return success, else return error */
1942 return BT_STATUS_SUCCESS;
1945 static void _bt_hal_remove_gatt_server_from_list(int server_if)
1948 struct gatt_server_app *info = NULL;
1950 for (l = gatt_server_apps; l != NULL;) {
1951 info = (struct gatt_server_app*)l->data;
1952 l = g_slist_next(l);
1955 if (info->slot == server_if) {
1956 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1957 info->app_path, info->slot);
1959 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1960 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1961 In above case, only advertising block will be deallocated, Gatt Server will remain
1963 if (info->services == NULL) {
1964 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1965 INFO("Total gatt server apps still existing after removing above is [%d]",
1966 g_slist_length(gatt_server_apps));
1968 /* DBUS Unregister only for current app */
1969 __bt_hal_gatt_deinit(info->app_path);
1971 g_free(info->app_path);
1975 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1976 g_slist_length(info->services));
1982 static bt_status_t gatt_server_unregister_app(int server_if)
1984 CHECK_BTGATT_INIT();
1985 DBG("Un-Register server instance request [%d]", server_if);
1986 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1989 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
1990 if (server_register_info == NULL) {
1991 DBG("gatt server is not registered");
1992 return BT_STATUS_SUCCESS;
1995 /* remove the gatt server register info from the register list */
1996 hal_gatts_server_register_list = g_slist_remove(hal_gatts_server_register_list, server_register_info);
1997 g_free(server_register_info);
1999 __bt_hal_gatt_delete_id(server_if);
2001 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
2002 _bt_hal_remove_gatt_server_from_list(server_if);
2003 return BT_STATUS_SUCCESS;
2006 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
2008 CHECK_BTGATT_INIT();
2009 return BT_STATUS_SUCCESS;
2012 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
2015 GError *g_error = NULL;
2016 GVariant *reply = NULL;
2020 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2021 g_object_unref(proxy);
2022 if (reply == NULL) {
2023 ERR("Disconnect LE Dbus Call Error");
2025 ERR("Error: %s\n", g_error->message);
2026 g_clear_error(&g_error);
2029 g_variant_unref(reply);
2033 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
2035 CHECK_BTGATT_INIT();
2037 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2039 GDBusProxy *device_proxy;
2040 GDBusConnection *g_conn;
2041 struct gatt_client_info_t *conn_info = NULL;
2045 if (NULL == bd_addr) {
2046 ERR("bd_addr is NULL");
2047 return BT_STATUS_PARM_INVALID;
2050 /* GDBUS Connection Info validate */
2051 g_conn = _bt_hal_get_system_gconn();
2052 if (g_conn == NULL) {
2053 ERR("Could not get System DBUS Connection");
2054 return BT_STATUS_FAIL;
2057 /* Connection Info validate */
2058 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2059 if (conn_info == NULL) {
2060 ERR("No Connection Inforamtion!!!");
2061 return BT_STATUS_FAIL;
2064 _bt_hal_convert_addr_type_to_string(device_address,
2065 (unsigned char *)bd_addr->address);
2067 //check if connection has the same device address
2068 if (g_strcmp0(conn_info->addr, device_address) != 0) {
2069 ERR("device address [%s] does not match", device_address);
2070 return BT_STATUS_FAIL;
2073 device_path = _bt_hal_get_device_object_path(conn_info->addr);
2074 if (device_path == NULL) {
2075 ERR("device_path is NULL");
2076 return BT_STATUS_PARM_INVALID;
2079 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
2080 NULL, BT_HAL_BLUEZ_NAME,
2081 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2084 g_free(device_path);
2085 if (device_proxy == NULL)
2086 return BT_STATUS_FAIL;
2088 INFO("Disconnect LE [%s]", device_address);
2090 g_dbus_proxy_call(device_proxy, "DisconnectLE",
2092 G_DBUS_CALL_FLAGS_NONE,
2093 BT_HAL_MAX_DBUS_TIMEOUT,
2095 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
2098 return BT_STATUS_SUCCESS;
2101 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
2106 uuid = btuuid2str(srvc_id->uu);
2107 DBG("Original UUID [%s]", uuid);
2109 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
2110 /* Extract Standard UUID string */
2111 memcpy(uuid_buf, &uuid[4], 4);
2113 DBG("Converted string [%s]", uuid_buf);
2114 return g_strdup(uuid_buf);
2116 return strdup(uuid);
2119 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
2122 /* For GATT service specific */
2123 GDBusNodeInfo *node_info;
2126 struct gatt_service_info *serv_info = NULL;
2127 GVariantBuilder *builder = NULL;
2128 GVariantBuilder *builder1 = NULL;
2129 GVariantBuilder *inner_builder = NULL;
2130 gboolean svc_primary = TRUE;
2131 GError *error = NULL;
2132 hal_gatt_service_added *user_data = NULL;
2133 DBG("Service add to DBUS slot [%d]", slot);
2135 node_info = __bt_gatt_create_method_node_info(
2136 service_introspection_xml);
2138 if (node_info == NULL)
2139 return BT_STATUS_FAIL;
2141 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
2142 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
2143 DBG("gatt service path is [%s]", path);
2145 object_id = g_dbus_connection_register_object(g_conn, path,
2146 node_info->interfaces[0],
2147 &serv_interface_vtable,
2148 NULL, NULL, &error);
2150 if (object_id == 0) {
2151 ERR("failed to register: %s", error->message);
2152 g_error_free(error);
2154 return BT_STATUS_FAIL;
2156 /* Add object_id/gatt service information; it's required at the time of
2157 * service unregister and Getmanagedobjects
2159 serv_info = g_new0(struct gatt_service_info, 1);
2161 serv_info->serv_path = g_strdup(path);
2162 serv_info->serv_id = object_id;
2163 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
2164 serv_info->is_svc_registered = FALSE;
2165 serv_info->is_svc_primary = svc_primary;
2166 DBG("Service Handle to be added is [%d]", gatt_service_handle);
2167 serv_info->service_handle = gatt_service_handle;
2169 /* Update service in GATT Server service List */
2170 gatt_services = g_slist_append(gatt_services, serv_info);
2172 /* emit interfacesadded signal here for service path */
2173 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2174 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2176 g_variant_builder_add(inner_builder, "{sv}",
2177 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
2179 g_variant_builder_add(inner_builder, "{sv}",
2180 "Primary", g_variant_new_boolean(svc_primary));
2182 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2184 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
2185 g_variant_new("ao", builder1));
2187 g_variant_builder_add(builder, "{sa{sv}}",
2188 GATT_SERV_INTERFACE, inner_builder);
2190 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2191 "org.freedesktop.Dbus.ObjectManager",
2193 g_variant_new("(oa{sa{sv}})",
2198 /* dbus gives error cause */
2199 ERR("d-bus api failure: errcode[%x], message[%s]",
2200 error->code, error->message);
2201 g_clear_error(&error);
2205 /* Send Service handle to application */
2206 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2207 user_data->srvc_hdl = serv_info->service_handle;
2208 user_data->instance_data = slot;
2209 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2210 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2212 /* Save newly created service in GATT Server's service list */
2213 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2217 g_variant_builder_unref(inner_builder);
2218 g_variant_builder_unref(builder);
2219 g_variant_builder_unref(builder1);
2220 return BT_STATUS_SUCCESS;
2223 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2226 char *app_path = (char*)user_data;
2227 INFO("UnregisterApplication is completed app [%s]", app_path);
2228 GError *error = NULL;
2229 GVariant *result = NULL;
2232 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2234 if (result == NULL) {
2235 /* dBUS-RPC is failed */
2236 ERR("Dbus-RPC is failed\n");
2238 if (error != NULL) {
2239 /* dBUS gives error cause */
2240 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2241 error->code, error->message);
2242 g_clear_error(&error);
2245 g_variant_unref(result);
2250 static void __bt_hal_gatt_deinit(char *app_path)
2252 GDBusProxy *proxy = NULL;
2256 /* Step1: Remove requested App */
2257 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2258 "/org/bluez/hci0", "org.bluez.GattManager1");
2263 INFO("UnregisterApplication : path [%s]", app_path);
2265 /* Async Call to Unregister Service */
2266 data = g_strdup(app_path);
2267 g_dbus_proxy_call(proxy,
2268 "UnregisterApplication",
2269 g_variant_new("(o)",
2271 G_DBUS_CALL_FLAGS_NONE, -1,
2273 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2276 /* If requested app is last GATT Server app, then clean all resources */
2277 if (gatt_server_apps == NULL) {
2278 INFO("All GATT servers are removed, clean all DBUS resources");
2280 /* unregister the exported interface for object manager */
2281 g_dbus_connection_unregister_object(g_conn, manager_id);
2283 g_bus_unown_name(owner_id);
2286 g_object_unref(manager_gproxy);
2287 manager_gproxy = NULL;
2293 static int __bt_hal_gatt_init(void)
2297 /* Only once for ALL GATT Servers */
2298 if (owner_id == 0) {
2302 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2305 ERR("Unable to connect to gdbus: %s", err->message);
2306 g_clear_error(&err);
2308 return BT_STATUS_FAIL;
2311 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2312 INFO("well-known name: %s", name);
2314 owner_id = g_bus_own_name_on_connection(g_conn, name,
2315 G_BUS_NAME_OWNER_FLAGS_NONE,
2316 NULL, NULL, NULL, NULL);
2318 INFO("Owner ID [%d]", owner_id);
2320 /* Only once for ALL GATT Servers */
2321 if (manager_node_info == NULL) {
2322 /* Register ObjectManager interface */
2323 manager_node_info = __bt_gatt_create_method_node_info(
2324 manager_introspection_xml);
2326 if (manager_node_info == NULL) {
2327 ERR("failed to get node info");
2328 return BT_STATUS_FAIL;
2333 return BT_STATUS_SUCCESS;
2336 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2340 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2341 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2342 if (app->slot == slot) {
2343 INFO("GATT Server app found app path [%s] instance [%d]",
2344 app->app_path, app->slot);
2345 *app_path = app->app_path;
2349 /* GATT Server not found */
2353 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2355 if (app_path == NULL)
2358 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2359 app->app_path = g_strdup(app_path);
2361 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2362 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2367 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2370 CHECK_BTGATT_INIT();
2371 char *app_path = NULL;
2372 GError *error = NULL;
2375 int result = BT_STATUS_SUCCESS;
2377 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2378 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2380 /* Check if this GATT server Application is already registered with DBUS */
2381 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2383 if (app_path != NULL) {
2384 DBG("GATT server path is already defined [%s]", app_path);
2385 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2387 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2388 result = __bt_hal_gatt_init();
2389 if (result != BT_STATUS_SUCCESS)
2392 /* Only once for each GATT Server */
2393 app_path = g_strdup_printf("/com/%d", server_if);
2395 app_id = g_malloc0(sizeof(int));
2396 *app_id = server_if;
2398 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2399 manager_node_info->interfaces[0],
2400 &manager_interface_vtable,
2401 (gpointer)app_id, NULL, &error);
2403 if (manager_id == 0) {
2404 ERR("failed to register: %s", error->message);
2405 g_error_free(error);
2408 INFO("manager_id [%d]", manager_id);
2410 /* For current GATT Server, app_path is created, save it in Table */
2411 _bt_hal_update_gatt_server_path(server_if, app_path);
2413 /* Add GATT Service to DBUS */
2414 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2420 INFO("Successfully added service");
2421 return BT_STATUS_SUCCESS;
2428 INFO("Service addition failed!!");
2429 return BT_STATUS_FAIL;
2432 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2433 int included_handle)
2435 CHECK_BTGATT_INIT();
2436 return BT_STATUS_SUCCESS;
2440 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2443 GSList *gatt_services = NULL;
2445 struct gatt_service_info *info = NULL;
2447 gatt_services = _bt_get_service_list_from_server(instance);
2449 len = g_slist_length(gatt_services);
2450 l = g_slist_nth(gatt_services, len -1);
2456 if (info->service_handle == service_handle)
2461 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2465 GSList *gatt_services = NULL;
2466 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2468 gatt_services = _bt_get_service_list_from_server(instance);
2470 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2471 struct gatt_service_info *info = l->data;
2472 INFO("Got one service with handle [%d]", info->service_handle);
2473 if (info->service_handle == service_handle)
2476 ERR("Gatt service with handle [%d] not found", service_handle);
2480 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2481 bt_uuid_t *uuid, int properties,
2485 GError *error = NULL;
2487 GDBusNodeInfo *node_info;
2489 GVariantBuilder *builder = NULL;
2490 GVariantBuilder *inner_builder = NULL;
2491 struct gatt_service_info *serv_info = NULL;
2492 struct gatt_char_info *char_info = NULL;
2493 GVariantBuilder *builder2 = NULL;
2494 GVariantBuilder *builder3 = NULL;
2495 GVariant *flags_val = NULL;
2497 char *char_flags[NUMBER_OF_FLAGS];
2499 hal_gatt_char_added *user_data = NULL;
2502 CHECK_BTGATT_INIT();
2503 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2504 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2506 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2507 if (serv_info == NULL)
2508 return BT_STATUS_FAIL;
2510 node_info = __bt_gatt_create_method_node_info(
2511 characteristics_introspection_xml);
2513 if (node_info == NULL)
2514 return BT_STATUS_FAIL;
2516 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2517 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2518 DBG("gatt characteristic path is [%s]", path);
2520 app_id = g_malloc0(sizeof(int));
2523 object_id = g_dbus_connection_register_object(g_conn, path,
2524 node_info->interfaces[0],
2525 &char_interface_vtable,
2526 (gpointer)app_id, NULL, &error);
2528 if (object_id == 0) {
2529 ERR("failed to register: %s", error->message);
2530 g_error_free(error);
2533 return BT_STATUS_FAIL;
2536 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2537 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2538 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2539 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2540 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2541 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2542 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2543 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2545 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2547 char_info = g_new0(struct gatt_char_info, 1);
2549 char_info->char_path = g_strdup(path);
2550 char_info->char_id = object_id;
2551 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2552 for (i = 0; i < flag_count; i++)
2553 char_info->char_flags[i] = char_flags[i];
2556 char_info->flags_length = flag_count;
2557 char_info->char_handle = gatt_char_handle;
2560 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2561 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2563 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2564 g_variant_new("s", char_info->char_uuid));
2565 g_variant_builder_add(inner_builder, "{sv}", "Service",
2566 g_variant_new("o", serv_info->serv_path));
2568 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2570 for (i = 0; i < flag_count; i++)
2571 g_variant_builder_add(builder2, "s", char_flags[i]);
2573 flags_val = g_variant_new("as", builder2);
2574 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2577 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2579 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2580 g_variant_new("ao", builder3));
2582 g_variant_builder_add(builder, "{sa{sv}}",
2583 GATT_CHAR_INTERFACE,
2586 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2587 "org.freedesktop.Dbus.ObjectManager",
2589 g_variant_new("(oa{sa{sv}})",
2594 /* dbus gives error cause */
2595 ERR("d-bus api failure: errcode[%x], message[%s]",
2596 error->code, error->message);
2597 g_clear_error(&error);
2601 //*char_path = g_strdup(path);
2606 /* Send Service handle to application */
2607 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2608 user_data->srvc_hdl = serv_info->service_handle;
2609 user_data->char_hdl = gatt_char_handle;
2610 user_data->instance_data = slot;
2611 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2612 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2614 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2615 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2620 g_variant_builder_unref(inner_builder);
2621 g_variant_builder_unref(builder);
2622 g_variant_builder_unref(builder2);
2623 g_variant_builder_unref(builder3);
2625 return BT_STATUS_SUCCESS;
2628 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2631 CHECK_BTGATT_INIT();
2633 // static int desc_id = 1;
2634 GError *error = NULL;
2636 GDBusNodeInfo *node_info;
2638 GVariantBuilder *builder = NULL;
2639 GVariantBuilder *inner_builder = NULL;
2641 struct gatt_char_info *char_info = NULL;
2642 struct gatt_desc_info *desc_info = NULL;
2643 struct gatt_service_info *serv_info = NULL;
2645 gchar **line_argv = NULL;
2647 char *char_path = NULL;
2650 GVariantBuilder *builder2 = NULL;
2651 GVariant *flags_val = NULL;
2653 char *desc_flags[NUMBER_OF_FLAGS];
2657 hal_gatt_desc_added *user_data = NULL;
2664 /* Fetch service data for the GATT server */
2665 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2666 if (serv_info == NULL)
2667 return BT_STATUS_FAIL;
2669 /* Fetch list of characteristics from the service info */
2670 l = serv_info->char_data;
2672 /* Fetch last char info from the characteristic list */
2673 char_info = g_slist_last(l)->data;
2674 if (char_info == NULL)
2675 return BT_STATUS_FAIL;
2677 /* Fetch characteristic path from char info */
2678 char_path = char_info->char_path;
2680 line_argv = g_strsplit_set(char_path, "/", 0);
2681 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2684 node_info = __bt_gatt_create_method_node_info(
2685 descriptor_introspection_xml);
2687 if (node_info == NULL) {
2688 g_strfreev(line_argv);
2690 return BT_STATUS_FAIL;
2693 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2695 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2696 DBG("gatt descriptor path is [%s]", path);
2698 app_id = g_malloc0(sizeof(int));
2701 object_id = g_dbus_connection_register_object(g_conn, path,
2702 node_info->interfaces[0],
2703 &desc_interface_vtable,
2704 (gpointer)app_id, NULL, &error);
2706 if (object_id == 0) {
2707 ERR("failed to register: %s", error->message);
2708 g_error_free(error);
2710 g_strfreev(line_argv);
2713 return BT_STATUS_FAIL;
2716 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2718 desc_info = g_new0(struct gatt_desc_info, 1);
2720 desc_info->desc_path = g_strdup(path);
2721 desc_info->desc_id = object_id;
2722 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2724 for (i = 0; i < flag_count; i++)
2725 desc_info->desc_flags[i] = desc_flags[i];
2727 desc_info->flags_length = flag_count;
2728 desc_info->desc_handle = gatt_desc_handle;
2731 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2732 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2734 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2735 g_variant_new("s", btuuid2str(uuid->uu)));
2736 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2737 g_variant_new("o", char_path));
2739 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2741 for (i = 0; i < flag_count; i++)
2742 g_variant_builder_add(builder2, "s", desc_flags[i]);
2744 flags_val = g_variant_new("as", builder2);
2745 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2748 g_variant_builder_add(builder, "{sa{sv}}",
2749 GATT_DESC_INTERFACE,
2752 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2753 "org.freedesktop.Dbus.ObjectManager",
2755 g_variant_new("(oa{sa{sv}})",
2758 if (error != NULL) {
2759 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2760 error->code, error->message);
2761 g_clear_error(&error);
2764 //*desc_path = g_strdup(path);
2766 /* Save newly created descriptor to GATT server's service's characteristic */
2767 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2769 /* Send descriptor handle to application */
2770 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2771 user_data->srvc_hdl = serv_info->service_handle;
2772 user_data->desc_hdl = gatt_desc_handle;
2773 user_data->instance_data = slot;
2774 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2775 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2780 g_strfreev(line_argv);
2781 g_variant_builder_unref(inner_builder);
2782 g_variant_builder_unref(builder);
2783 return BT_STATUS_SUCCESS;
2786 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2788 GError *error = NULL;
2790 char *data = (char*) user_data;
2791 INFO("RegisterApplication is completed path [%s]", data);
2793 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2795 if (result == NULL) {
2796 /* dBUS-RPC is failed */
2797 ERR("Dbus-RPC is failed\n");
2799 if (error != NULL) {
2800 /* dBUS gives error cause */
2801 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2802 error->code, error->message);
2803 g_clear_error(&error);
2806 g_variant_unref(result);
2811 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2812 const gchar *path, const gchar *interface)
2818 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2823 ERR("Unable to connect to gdbus: %s", err->message);
2824 g_clear_error(&err);
2829 proxy = g_dbus_proxy_new_sync(g_conn,
2830 G_DBUS_PROXY_FLAGS_NONE, NULL,
2832 interface, NULL, &err);
2836 ERR("Unable to create proxy: %s", err->message);
2837 g_clear_error(&err);
2841 manager_gproxy = proxy;
2846 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2847 const gchar *path, const gchar *interface)
2849 return (manager_gproxy) ? manager_gproxy :
2850 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2854 static void __bt_register_application_to_dbus(int slot)
2856 GDBusProxy *proxy = NULL;
2857 char *app_path = NULL;
2859 DBG("RegisterApplication slot [%d]", slot);
2861 /* It is impossible that app path is still not initialized */
2862 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2864 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2865 "/org/bluez/hci0", "org.bluez.GattManager1");
2867 data = g_strdup(app_path);
2868 g_dbus_proxy_call(proxy,
2869 "RegisterApplication",
2870 g_variant_new("(oa{sv})",
2872 G_DBUS_CALL_FLAGS_NONE, -1,
2874 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2876 INFO("GATT server started");
2879 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2881 CHECK_BTGATT_INIT();
2882 struct gatt_service_info *serv_info = NULL;
2883 hal_gatt_service_started *user_data = NULL;
2884 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2886 /* Fetch service data for the GATT server */
2887 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2888 if (serv_info == NULL)
2889 return BT_STATUS_FAIL;
2891 if (serv_info->is_svc_registered)
2892 DBG("service already registered \n");
2894 serv_info->is_svc_registered = TRUE;
2896 /* Send Service handle to application */
2897 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2898 user_data->srvc_hdl = serv_info->service_handle;
2899 user_data->instance_data = server_if;
2900 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2902 /* If this is nth Service that is started, then register application at this point */
2903 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2904 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2906 __bt_register_application_to_dbus(server_if);
2909 return BT_STATUS_SUCCESS;
2912 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2914 CHECK_BTGATT_INIT();
2915 INFO("Stop service successful");
2916 return BT_STATUS_SUCCESS;
2919 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2921 CHECK_BTGATT_INIT();
2922 struct gatt_service_info *serv_info = NULL;
2923 hal_gatt_service_deleted *user_data = NULL;
2926 int err = BT_STATUS_SUCCESS;
2927 int ret = BT_STATUS_SUCCESS;
2928 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2930 /* Fetch service data for the GATT server */
2931 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2932 if (serv_info == NULL) {
2933 ERR("Could not find service info svc handle [%d] server slot [%d]",
2934 service_handle, server_if);
2935 return BT_STATUS_FAIL;
2938 if (serv_info->is_svc_registered == FALSE) {
2939 ERR("service Not registered path [%s] handle [%d]",
2940 serv_info->serv_path, service_handle);
2943 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2944 struct gatt_char_info *char_info = l->data;
2946 if (char_info == NULL)
2949 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2950 struct gatt_desc_info *desc_info = l1->data;
2952 if (desc_info == NULL)
2955 ret = g_dbus_connection_unregister_object(g_conn,
2956 desc_info->desc_id);
2958 __bt_hal_gatt_emit_interface_removed(
2959 desc_info->desc_path,
2960 GATT_DESC_INTERFACE);
2962 err = BT_STATUS_FAIL;
2965 /* list remove & free */
2966 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2967 __bt_hal_gatt_free_descriptor_info(desc_info);
2970 g_slist_free(char_info->desc_data);
2971 char_info->desc_data = NULL;
2973 ret = g_dbus_connection_unregister_object(g_conn,
2974 char_info->char_id);
2976 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2977 GATT_CHAR_INTERFACE);
2980 err = BT_STATUS_FAIL;
2983 /* list remove & free */
2984 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2985 __bt_hal_gatt_free_characteristic_info(char_info);
2988 g_slist_free(serv_info->char_data);
2989 serv_info->char_data = NULL;
2991 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2993 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2994 GATT_SERV_INTERFACE);
2997 err = BT_STATUS_FAIL;
3000 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
3002 DBG("Unregistered the service on properties interface");
3004 /* Remove from global list */
3005 gatt_services = g_slist_remove(gatt_services, serv_info);
3006 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
3008 /* Remove from GATT Server's list of services */
3009 _bt_remote_service_from_gatt_server(server_if, service_handle);
3011 if (gatt_services == NULL)
3012 INFO("All GATT Services of all GATT Servers are unregistered");
3014 if (err == BT_STATUS_SUCCESS) {
3015 INFO("Send GATT Service deleted Event");
3016 /* Send Service handle to application */
3017 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
3018 user_data->srvc_hdl = serv_info->service_handle;
3019 user_data->instance_data = server_if;
3020 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
3023 /* Free the service */
3024 __bt_hal_gatt_free_service_info(serv_info);
3028 static gboolean __bt_gatt_get_service_state(const char *service_path)
3030 struct gatt_service_info *svc_info = NULL;
3032 for (l = gatt_services; l; l = g_slist_next(l)) {
3034 svc_info = (struct gatt_service_info *)l->data;
3037 if (!g_strcmp0(svc_info->serv_path, service_path)) {
3038 DBG("Return the state of the gatt service %d",
3039 svc_info->is_svc_registered);
3040 return svc_info->is_svc_registered;
3044 DBG("gatt service info is NULL");
3048 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
3049 int len, int confirm, char* p_value)
3051 CHECK_BTGATT_INIT();
3054 GVariantBuilder *outer_builder;
3055 GVariantBuilder *invalidated_builder;
3057 /* For Value update via PropertyChange */
3058 GVariantBuilder *outer_builder1;
3059 GVariantBuilder *inner_builder1;
3060 GVariantBuilder *invalidated_builder1;
3061 GVariant *update_value = NULL;
3063 /* Other variables */
3064 struct gatt_client_info_t *conn_info = NULL;
3065 gchar *serv_path = NULL;
3066 char *char_path = NULL;
3067 gchar **line_argv = NULL;
3068 gboolean notify = TRUE;
3069 gboolean ret = TRUE;
3070 int err = BT_STATUS_SUCCESS;
3072 GError *error = NULL;
3075 memset(addr, 0x00, sizeof(addr));
3077 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3078 if (conn_info == NULL) {
3079 ERR("No Connection Inforamtion!!!");
3080 return BT_STATUS_FAIL;
3083 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
3085 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3086 if (char_path == NULL)
3087 return BT_STATUS_FAIL;
3089 line_argv = g_strsplit_set(char_path, "/", 0);
3090 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3092 if (!__bt_gatt_get_service_state(serv_path)) {
3093 DBG("service not registered for this characteristic \n");
3095 g_strfreev(line_argv);
3096 return BT_STATUS_FAIL;
3099 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3100 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3102 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
3103 g_variant_new("b", notify));
3105 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
3106 DBG("Send Indication to Unicast addr [%s]", addr);
3108 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
3109 g_variant_new("s", addr));
3111 DBG("Set characteristic Notification \n");
3112 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3114 "org.freedesktop.DBus.Properties",
3115 "PropertiesChanged",
3116 g_variant_new("(sa{sv}as)",
3117 "org.bluez.GattCharacteristic1",
3118 outer_builder, invalidated_builder),
3122 if (error != NULL) {
3123 ERR("D-Bus API failure: errCode[%x], \
3125 error->code, error->message);
3126 g_clear_error(&error);
3128 err = BT_STATUS_FAIL;
3131 g_variant_builder_unref(outer_builder);
3132 g_variant_builder_unref(invalidated_builder);
3135 /* Notifying Done, now update Value to Bluez via PropertyChanged */
3136 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
3138 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3139 for (i = 0; i < len; i++)
3140 g_variant_builder_add(inner_builder1, "y", p_value[i]);
3142 update_value = g_variant_new("ay", inner_builder1);
3145 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3146 g_variant_builder_add(outer_builder1, "{sv}", "Value",
3149 DBG("Updating characteristic value \n");
3150 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3152 "org.freedesktop.DBus.Properties",
3153 "PropertiesChanged",
3154 g_variant_new("(sa{sv}as)",
3155 "org.bluez.GattCharacteristic1",
3156 outer_builder1, invalidated_builder1),
3160 if (error != NULL) {
3161 ERR("D-Bus API failure: errCode[%x], \
3163 error->code, error->message);
3164 g_clear_error(&error);
3166 err = BT_STATUS_FAIL;
3168 struct gatt_char_info *char_info = NULL;
3170 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3171 if (char_info == NULL) {
3173 g_strfreev(line_argv);
3174 g_variant_builder_unref(inner_builder1);
3175 g_variant_builder_unref(outer_builder1);
3176 g_variant_builder_unref(invalidated_builder1);
3178 return BT_STATUS_FAIL;
3181 char_info->value_length = len;
3183 char_info->char_value = (char *)realloc(char_info->char_value, len);
3184 if (char_info->char_value) {
3185 for (i = 0; i < len; i++)
3186 char_info->char_value[i] = p_value[i];
3191 g_strfreev(line_argv);
3192 g_variant_builder_unref(inner_builder1);
3193 g_variant_builder_unref(outer_builder1);
3194 g_variant_builder_unref(invalidated_builder1);
3199 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3200 int status, btgatt_response_t *response)
3202 CHECK_BTGATT_INIT();
3204 struct gatt_req_info *req_info = NULL;
3205 struct gatt_client_info_t *conn_info = NULL;
3208 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3210 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3211 if (conn_info == NULL) {
3212 ERR("No Connection Inforamtion!!!");
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!!!");
3219 return BT_STATUS_FAIL;
3222 if (status != BT_STATUS_SUCCESS) {
3223 ERR("resp_state is 0x%X", status);
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 DBG("Reponse Value length [%d]", response->attr_value.len);
3241 DBG("Request type: [%d]", req_info->request_type);
3244 for (i = 0; i < response->attr_value.len; i++)
3245 DBG("Resonse [%d] = [0x%x]", i, response->attr_value.value[i]);
3247 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3248 GVariantBuilder *inner_builder = NULL;
3249 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3251 if (response->attr_value.len > 0) {
3252 for (i = 0; i < response->attr_value.len; i++)
3253 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3255 g_dbus_method_invocation_return_value(req_info->context,
3256 g_variant_new("(ay)", inner_builder));
3258 g_variant_builder_unref(inner_builder);
3260 g_dbus_method_invocation_return_value(req_info->context, NULL);
3262 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3264 req_info->context = NULL;
3265 if (req_info->attr_path)
3266 g_free(req_info->attr_path);
3267 if (req_info->svc_path)
3268 g_free(req_info->svc_path);
3271 return BT_STATUS_SUCCESS;
3275 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3276 int status, int fd, int mtu, void *fdlist)
3278 CHECK_BTGATT_INIT();
3280 struct gatt_req_info *req_info = NULL;
3281 struct gatt_client_info_t *conn_info = NULL;
3283 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3285 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3286 if (conn_info == NULL) {
3287 ERR("No Connection Inforamtion!!!");
3288 return BT_STATUS_FAIL;
3291 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3292 if (req_info == NULL) {
3293 ERR("No Request Inforamtion!!!");
3294 return BT_STATUS_FAIL;
3297 if (status != BT_STATUS_SUCCESS) {
3298 ERR("resp_state is 0x%X", status);
3300 g_dbus_method_invocation_return_dbus_error(req_info->context,
3301 "org.bluez.Error.Failed", "Application Error");
3303 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3305 req_info->context = NULL;
3306 if (req_info->attr_path)
3307 g_free(req_info->attr_path);
3308 if (req_info->svc_path)
3309 g_free(req_info->svc_path);
3312 return BT_STATUS_SUCCESS;
3316 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3318 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3319 g_dbus_method_invocation_return_value_with_unix_fd_list(
3320 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3322 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3324 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3325 g_dbus_method_invocation_return_value_with_unix_fd_list(
3326 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3329 g_dbus_method_invocation_return_value(req_info->context, NULL);
3331 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3333 req_info->context = NULL;
3334 if (req_info->attr_path)
3335 g_free(req_info->attr_path);
3336 if (req_info->svc_path)
3337 g_free(req_info->svc_path);
3340 return BT_STATUS_SUCCESS;
3344 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3345 int value_length, char* att_value)
3347 CHECK_BTGATT_INIT();
3349 /* Other variables */
3350 char *char_path = NULL;
3351 gboolean ret = TRUE;
3352 GError *error = NULL;
3354 GVariantBuilder *outer_builder;
3355 GVariantBuilder *inner_builder;
3356 GVariantBuilder *invalidated_builder;
3357 GVariant *update_value = NULL;
3358 int err = BT_STATUS_SUCCESS;
3360 gchar **line_argv = NULL;
3361 gchar *serv_path = NULL;
3363 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3364 if (char_path == NULL)
3365 return BT_STATUS_FAIL;
3367 line_argv = g_strsplit_set(char_path, "/", 0);
3368 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3370 if (!__bt_gatt_get_service_state(serv_path)) {
3371 DBG("service not registered for this characteristic \n");
3373 g_strfreev(line_argv);
3374 return BT_STATUS_FAIL;
3378 line_argv = g_strsplit_set(char_path, "/", 0);
3379 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3381 if (!__bt_gatt_get_service_state(serv_path)) {
3382 DBG("service not registered for this characteristic \n");
3384 g_strfreev(line_argv);
3385 return BT_STATUS_FAIL;
3388 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3389 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3391 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3392 for (i = 0; i < value_length; i++)
3393 g_variant_builder_add(inner_builder, "y", att_value[i]);
3395 update_value = g_variant_new("ay", inner_builder);
3397 g_variant_builder_add(outer_builder, "{sv}", "Value",
3400 DBG("Updating characteristic value \n");
3401 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3403 "org.freedesktop.DBus.Properties",
3404 "PropertiesChanged",
3405 g_variant_new("(sa{sv}as)",
3406 "org.bluez.GattCharacteristic1",
3407 outer_builder, invalidated_builder),
3411 if (error != NULL) {
3412 ERR("D-Bus API failure: errCode[%x], \
3414 error->code, error->message);
3415 g_clear_error(&error);
3417 err = BT_STATUS_FAIL;
3419 struct gatt_char_info *char_info = NULL;
3421 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3422 if (char_info == NULL) {
3424 g_strfreev(line_argv);
3425 g_variant_builder_unref(inner_builder);
3426 g_variant_builder_unref(outer_builder);
3427 g_variant_builder_unref(invalidated_builder);
3429 return BT_STATUS_FAIL;
3432 char_info->value_length = value_length;
3434 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3435 if (char_info->char_value) {
3436 for (i = 0; i < value_length; i++)
3437 char_info->char_value[i] = att_value[i];
3443 g_strfreev(line_argv);
3444 g_variant_builder_unref(inner_builder);
3445 g_variant_builder_unref(outer_builder);
3446 g_variant_builder_unref(invalidated_builder);
3451 static bt_status_t gatt_server_listen(int server_if, bool start)
3453 CHECK_BTGATT_INIT();
3455 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3457 DBG("server_if: [%d]", server_if);
3459 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3460 if (server_register_info == NULL) {
3461 DBG("gatt server is not registered");
3462 return BT_STATUS_FAIL;
3465 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3467 if (server_register_info->adv_slot_id < 0 ) {
3468 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3469 return BT_STATUS_FAIL;
3472 /* Send Data to LE Module */
3473 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, start, FALSE);
3476 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3477 bool include_txpower, int min_interval, int max_interval, int appearance,
3478 uint16_t manufacturer_len, char* manufacturer_data,
3479 uint16_t service_data_len, char* service_data,
3480 uint16_t service_uuid_len, char* service_uuid)
3482 CHECK_BTGATT_INIT();
3483 return BT_STATUS_SUCCESS;
3486 static int bt_hal_gatts_allocate_adv_slot(struct hal_gatts_server_register_info_t *server_register_info)
3488 int adv_slot_id = -1;
3490 /* allocate adv slot for gatt server if not assigned */
3491 if (server_register_info->adv_slot_id < 0 ) {
3492 adv_slot_id = _bt_hal_get_available_adv_slot_id(&server_register_info->app_uuid, FALSE);
3493 if (adv_slot_id < 0) {
3494 ERR("failed to get the adv_slot");
3498 server_register_info->adv_slot_id = adv_slot_id;
3501 DBG("gatt server:[%d] Assigned adv_slot [%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3506 int bt_hal_gatts_allocate_adv_slot_by_server_if(int server_if)
3508 CHECK_BTGATT_INIT();
3512 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3514 DBG("server_if: [%d]", server_if);
3516 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3517 if (server_register_info == NULL) {
3518 DBG("gatt server is not registered");
3522 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3524 if (server_register_info->adv_slot_id < 0 ) {
3525 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3527 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3529 DBG("failed to get adv_slot");
3534 return server_register_info->adv_slot_id;
3537 void bt_hal_gatts_release_adv_slot(int server_if)
3539 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3541 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3542 if (server_register_info == NULL) {
3543 ERR("failed to get server_register_info");
3547 if (server_register_info->adv_slot_id < 0) {
3548 ERR("adv_slot is not allocated");
3552 if(_bt_hal_is_advertising_in_slot(server_register_info->adv_slot_id) == FALSE) {
3553 DBG("advertising is disabled");
3554 _bt_hal_free_server_slot(server_register_info->adv_slot_id);
3555 server_register_info->adv_slot_id = -1;
3559 int bt_hal_gatts_get_adv_slot_id(int server_if)
3561 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3563 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3564 if (server_register_info == NULL) {
3565 DBG("failed to get server_register_info");
3569 return server_register_info->adv_slot_id;
3572 int bt_hal_gatts_get_server_if(int slot_id)
3574 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3576 server_register_info = bt_hal_gatts_find_server_register_info_by_slot_id(slot_id);
3577 if (server_register_info == NULL) {
3578 DBG("failed to get server_register_info");
3582 return server_register_info->server_if;
3585 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3587 CHECK_BTGATT_INIT();
3591 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3593 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3594 if (server_register_info == NULL) {
3595 ERR("gatt server is not registered");
3596 return BT_STATUS_FAIL;
3599 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3601 if (server_register_info->adv_slot_id < 0 ) {
3602 DBG("adv_slot is not assigned to server:[%d]", server_if);
3604 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3606 ERR("failed to get adv_slot");
3607 return BT_STATUS_FAIL;
3611 /* Send Enable Advertising request to LE Module */
3612 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, TRUE, TRUE);
3615 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3616 int chnl_map, int tx_power, int timeout_s)
3618 CHECK_BTGATT_INIT();
3620 /* Send Advertising parameters to LE Module */
3621 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3622 chnl_map, tx_power, timeout_s);
3625 static bt_status_t gatt_server_set_filter_policy(int filter_policy)
3627 CHECK_BTGATT_INIT();
3629 /* Send the Filter policy parameter to LE Module */
3630 _bt_hal_set_filter_policy_param(filter_policy);
3631 return BT_STATUS_SUCCESS;
3634 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3636 CHECK_BTGATT_INIT();
3638 /* Send Data to LE Module */
3639 return _bt_hal_set_advertising_data(adv_param_setup);
3642 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3644 CHECK_BTGATT_INIT();
3646 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3648 DBG("server_if: [%d]", server_if);
3650 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3651 if (server_register_info == NULL) {
3652 DBG("gatt server is not registered");
3653 return BT_STATUS_FAIL;
3656 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3658 if (server_register_info->adv_slot_id < 0 ) {
3659 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3660 return BT_STATUS_FAIL;
3663 /* Send Data to LE Module */
3664 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, FALSE, TRUE);
3667 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3669 CHECK_BTGATT_INIT();
3670 char *object_path = NULL;
3672 GDBusProxy *device_proxy;
3673 GError *error = NULL;
3675 GVariant *tmp_value;
3676 GDBusConnection *conn;
3677 GVariant *result = NULL;
3678 int ret = BT_STATUS_SUCCESS;
3679 struct gatt_client_info_t *conn_info = NULL;
3682 if (mtu_size == NULL)
3683 return BT_STATUS_PARM_INVALID;
3685 /* GDBUS Connection Info validate */
3686 conn = _bt_hal_get_system_gconn();
3688 ERR("Could not get System DBUS Connection");
3689 return BT_STATUS_FAIL;
3692 /* Connection Info validate */
3693 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3694 if (conn_info == NULL) {
3695 ERR("No Connection Inforamtion!!!");
3696 return BT_STATUS_FAIL;
3700 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3701 if (object_path == NULL)
3702 return BT_STATUS_FAIL;
3704 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3705 NULL, BT_HAL_BLUEZ_NAME, object_path,
3706 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3708 g_free(object_path);
3709 if (device_proxy == NULL)
3710 return BT_STATUS_FAIL;
3712 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3713 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3714 G_DBUS_CALL_FLAGS_NONE,
3718 if (result == NULL) {
3719 if (error != NULL) {
3720 ERR("Error occured in Proxy call [%s]\n", error->message);
3721 g_error_free(error);
3723 g_object_unref(device_proxy);
3724 return BT_STATUS_FAIL;
3727 g_variant_get(result , "(@a{sv})", &value);
3728 g_variant_unref(result);
3730 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3731 if (tmp_value == NULL) {
3732 g_object_unref(device_proxy);
3733 g_variant_unref(value);
3734 return BT_STATUS_FAIL;
3737 mtu = g_variant_get_uint16(tmp_value);
3739 DBG("ATT MTU : [%d]", mtu);
3741 g_variant_unref(tmp_value);
3742 g_variant_unref(value);
3743 g_object_unref(device_proxy);
3745 *mtu_size = (int) mtu;
3750 const btgatt_server_interface_t btgatt_server_interface = {
3751 .register_server = gatt_server_register_app,
3752 .unregister_server = gatt_server_unregister_app,
3753 .connect = gatt_server_open,
3754 .disconnect = gatt_server_close,
3755 .add_service = gatt_server_add_service,
3756 .add_included_service = gatt_server_add_included_service,
3757 .add_characteristic = gatt_server_add_characteristic,
3758 .add_descriptor = gatt_server_add_descriptor,
3759 .start_service = gatt_server_start_service,
3760 .stop_service = gatt_server_stop_service,
3761 .delete_service = gatt_server_delete_service,
3762 .send_indication = gatt_server_send_indication,
3763 .send_response = gatt_server_send_response,
3764 .update_att_value = gatt_server_update_att_value,
3765 .listen = gatt_server_listen,
3766 .set_adv_data = gatt_server_set_adv_data,
3767 .multi_adv_enable = gatt_server_multi_adv_enable,
3768 .multi_adv_update = gatt_server_multi_adv_update,
3769 .set_filter_policy = gatt_server_set_filter_policy,
3770 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3771 .multi_adv_disable = gatt_server_multi_adv_disable,
3772 .get_att_mtu = gatt_server_get_mtu_size,
3773 .send_response_acquire = gatt_server_send_acquire_response