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 static int conn_id = 0;
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;
189 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
191 ERR("%s: BTGATT not initialized", __FUNCTION__);\
192 return BT_STATUS_NOT_READY;\
194 DBG("%s", __FUNCTION__);\
197 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data);
199 static void __bt_hal_gatt_deinit(char *app_path);
201 static void __bt_hal_register_application_cb(GObject *object,
202 GAsyncResult *res, gpointer user_data);
204 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
207 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
208 const gchar *path, const gchar *interface);
210 /* Introspection data for the service we are exporting */
211 static const gchar service_introspection_xml[] =
213 " <interface name='org.freedesktop.DBus.Properties'>"
214 " <property type='s' name='UUID' access='read'>"
216 " <property type='b' name='primary' access='read'>"
218 " <property type='o' name='Device' access='read'>"
220 " <property type='ao' name='Characteristics' access='read'>"
222 " <property type='s' name='Includes' access='read'>"
227 /* Introspection data for the characteristics we are exporting */
228 static const gchar characteristics_introspection_xml[] =
230 " <interface name='org.bluez.GattCharacteristic1'>"
231 " <method name='ReadValue'>"
232 " <arg type='s' name='address' direction='in'/>"
233 " <arg type='u' name='id' direction='in'/>"
234 " <arg type='q' name='offset' direction='in'/>"
235 " <arg type='ay' name='Value' direction='out'/>"
237 " <method name='WriteValue'>"
238 " <arg type='s' name='address' direction='in'/>"
239 " <arg type='u' name='id' direction='in'/>"
240 " <arg type='q' name='offset' direction='in'/>"
241 " <arg type='b' name='response_needed' direction='in'/>"
242 " <arg type='ay' name='value' direction='in'/>"
244 " <method name ='AcquireWrite'>"
245 " <arg type='a{sv}' name='properties' direction='in'/>"
246 " <arg type='h' name='fd' direction='out'/>"
247 " <arg type='q' name='mtu' direction='out'/>"
249 " <method name = 'AcquireNotify'>"
250 " <arg type='a{sv}' name='properties' direction='in'/>"
251 " <arg type='h' name='fd' direction='out'/>"
252 " <arg type='q' name='mtu' direction='out'/>"
254 " <method name='StartNotify'>"
256 " <method name='StopNotify'>"
258 " <method name='IndicateConfirm'>"
259 " <arg type='s' name='address' direction='in'/>"
260 " <arg type='b' name='complete' direction='in'/>"
263 " <interface name='org.freedesktop.DBus.Properties'>"
264 " <property type='s' name='UUID' access='read'>"
266 " <property type='o' name='Service' access='read'>"
268 " <property type='ay' name='Value' access='readwrite'>"
270 " <property type='b' name='Notifying' access='read'>"
272 " <property type='as' name='Flags' access='read'>"
274 " <property type='s' name='Unicast' access='read'>"
276 " <property type='ao' name='Descriptors' access='read'>"
278 " <property type='b' name='WriteAcquired' access='read'>"
280 " <property type='b' name='NotifyAcquired' access='read'>"
285 /* Introspection data for the descriptor we are exporting */
286 static const gchar descriptor_introspection_xml[] =
288 " <interface name='org.bluez.GattDescriptor1'>"
289 " <method name='ReadValue'>"
290 " <arg type='s' name='address' direction='in'/>"
291 " <arg type='u' name='id' direction='in'/>"
292 " <arg type='q' name='offset' direction='in'/>"
293 " <arg type='ay' name='Value' direction='out'/>"
295 " <method name='WriteValue'>"
296 " <arg type='s' name='address' direction='in'/>"
297 " <arg type='u' name='id' direction='in'/>"
298 " <arg type='q' name='offset' direction='in'/>"
299 " <arg type='b' name='response_needed' direction='in'/>"
300 " <arg type='ay' name='value' direction='in'/>"
303 " <interface name='org.freedesktop.DBus.Properties'>"
304 " <property type='s' name='UUID' access='read'>"
306 " <property type='o' name='Characteristic' access='read'>"
308 " <property type='ay' name='Value' access='read'>"
310 " <property type='as' name='Flags' access='read'>"
316 static const gchar manager_introspection_xml[] =
318 " <interface name='org.freedesktop.DBus.ObjectManager'>"
319 " <method name='GetManagedObjects'>"
320 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
325 GSList *_bt_get_service_list_from_server(int instance)
328 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
329 INFO("Find App with slot [%d]", instance);
331 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
332 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
334 if (app->slot == instance) {
335 INFO("App slot [%d] Found, Number of services registered [%d]",
336 app->slot, g_slist_length(app->services));
337 return app->services;
343 void _bt_remote_service_from_gatt_server(int instance, int service_handle)
348 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
349 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
351 if (app->slot == instance) {
352 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
353 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
354 if (srv->service_handle == service_handle) {
355 app->services = g_slist_remove(app->services, srv);
363 void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
366 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
367 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
369 if (app->slot == slot) {
370 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
371 serv_info->service_handle, slot);
372 app->services = g_slist_append(app->services, serv_info);
377 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
380 struct gatt_client_info_t *info = NULL;
382 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
383 info = (struct gatt_client_info_t*)l->data;
387 if (!g_strcmp0(info->addr, address)) {
388 INFO("Remote GATT client found addr[%s]", info->addr);
395 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
398 struct gatt_client_info_t *info = NULL;
400 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
401 info = (struct gatt_client_info_t*)l->data;
405 if (info->connection_id == conn_id) {
406 INFO("Remote GATT client found addr[%s]", info->addr);
413 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
418 struct gatt_client_info_t *info = NULL;
419 struct gatt_req_info *info1 = NULL;
421 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
422 info = (struct gatt_client_info_t*)l->data;
426 if (info->connection_id == conn_id) {
428 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
430 info1 = (struct gatt_req_info*)l1->data;
434 if (info1->request_id == trans_id) {
435 INFO("Remote GATT client found addr[%s]", info->addr);
444 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
446 struct hal_ev_gatt_server_connected ev;
447 struct gatt_client_info_t *conn_info = NULL;
449 memset(&ev, 0, sizeof(ev));
451 /* Find Server Instance */
452 _bt_hal_get_gatt_server_instance_initialized(&instance);
453 if (instance == -1) {
454 ERR("Not even a single GATT server is registered");
458 /* Convert address to hex */
459 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
461 /* Create Connection ID */
462 /* Check if device is already in connected list */
463 conn_info = __bt_find_remote_gatt_client_info(address);
466 /* If disconnected, and conn info found, then remove conn info */
467 if (is_connected == FALSE) {
468 DBG("GATT Disconnected");
470 INFO("Remove GATT client info from List..");
471 /* Remove info from List */
472 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
473 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
476 ERR("GATT callback not registered");
478 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
479 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
480 ev.conn_id = conn_info->connection_id;
481 ev.server_instance = conn_info->instance_id;
482 ev.connected = is_connected;
484 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
486 g_free(conn_info->addr);
489 /* If connected, and conn info NOT found, then add conn info */
492 /* Save Connection info */
493 conn_info = g_new0(struct gatt_client_info_t, 1);
494 conn_info->addr = g_strdup(address);
495 INFO("Added GATT client addr[%s]", conn_info->addr);
496 conn_info->connection_id = ++conn_id;
497 conn_info->instance_id = instance;
498 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
499 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
502 ERR("GATT callback not registered");
504 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
505 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
506 ev.conn_id = conn_info->connection_id;
507 ev.server_instance = conn_info->instance_id;
508 ev.connected = is_connected;
510 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
514 /* Send GATT connected or disconnected event */
517 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
521 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
522 struct gatt_service_info *serv_info = l1->data;
524 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
525 struct gatt_char_info *char_info = l2->data;
527 if (g_strcmp0(char_info->char_path, char_path)
529 *char_hdl = char_info->char_handle;
534 ERR("Gatt service not found");
538 char *__bt_gatt_find_char_path_from_handle(int char_hdl)
542 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
543 struct gatt_service_info *serv_info = l1->data;
545 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
546 struct gatt_char_info *char_info = l2->data;
548 if (char_info->char_handle == char_hdl)
549 return char_info->char_path;
556 struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
560 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
561 struct gatt_service_info *serv_info = l1->data;
563 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
564 struct gatt_char_info *char_info = l2->data;
566 if (char_info->char_handle == char_hdl)
574 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
576 GSList *l1, *l2, *l3;
578 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
579 struct gatt_service_info *serv_info = l1->data;
581 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
582 struct gatt_char_info *char_info = l2->data;
584 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
585 struct gatt_desc_info *desc_info = l3->data;
587 if (g_strcmp0(desc_info->desc_path, desc_path)
589 *desc_hdl = desc_info->desc_handle;
595 ERR("Gatt service not found");
599 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
601 const gchar *object_path,
602 const gchar *interface_name,
603 const gchar *method_name,
604 GVariant *parameters,
605 GDBusMethodInvocation *invocation,
610 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
611 GVariantBuilder *builder;
612 GVariantBuilder *inner_builder1 = NULL;
613 GVariant *svc_char = NULL;
615 GSList *gatt_services = NULL;
617 instance = (int*)user_data;
618 gboolean writeAcquired = FALSE;
619 gboolean notifyAcquired = FALSE;
621 DBG("Getting values for service, chars and descriptors");
622 DBG("GATT Server App for which services are requested [%d]", *instance);
625 builder = g_variant_builder_new(
626 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
629 gatt_services = _bt_get_service_list_from_server(*instance);
631 if (g_slist_length(gatt_services) == 0) {
632 ERR("No registered GATT services!!!!");
633 g_dbus_method_invocation_return_value(invocation, NULL);
634 g_variant_builder_unref(builder);
638 for (l = gatt_services; l != NULL; l = l->next) {
639 GVariantBuilder *svc_builder = NULL;
640 GVariantBuilder *inner_builder = NULL;
641 struct gatt_service_info *serv_info = l->data;
642 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
644 /* Prepare inner builder for GattService1 interface */
645 DBG("Creating builder for service");
646 svc_builder = g_variant_builder_new(
647 G_VARIANT_TYPE("a{sa{sv}}"));
648 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
650 g_variant_builder_add(inner_builder, "{sv}", "UUID",
651 g_variant_new_string(serv_info->service_uuid));
653 g_variant_builder_add(inner_builder, "{sv}", "Primary",
654 g_variant_new_boolean(serv_info->is_svc_primary));
657 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
658 DBG("Adding Charatarisitcs list");
659 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
660 struct gatt_char_info *char_info = l4->data;
661 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
662 char_info->char_handle, serv_info->service_handle);
663 g_variant_builder_add(inner_builder1, "o",
664 char_info->char_path);
665 DBG("%s", char_info->char_path);
668 svc_char = g_variant_new("ao", inner_builder1);
669 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
672 g_variant_builder_add(svc_builder, "{sa{sv}}",
676 g_variant_builder_add(builder, "{oa{sa{sv}}}",
677 serv_info->serv_path,
680 g_variant_builder_unref(inner_builder1);
682 /* Prepare inner builder for GattCharacteristic1 interface */
684 GSList *l2 = serv_info->char_data;
685 DBG("Creating builder for characteristics \n");
688 DBG("characteristic data is NULL");
690 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
692 GVariantBuilder *char_builder = NULL;
693 GVariantBuilder *inner_builder = NULL;
694 GVariantBuilder *builder1 = NULL;
695 GVariantBuilder *builder2 = NULL;
696 GVariantBuilder *builder3 = NULL;
697 GVariant *char_val = NULL;
698 GVariant *flags_val = NULL;
699 GVariant *char_desc = NULL;
700 char *unicast = NULL;
701 gboolean notify = FALSE;
704 char_builder = g_variant_builder_new(
707 inner_builder = g_variant_builder_new(
711 struct gatt_char_info *char_info = l2->data;
712 if (char_info == NULL) {
713 ERR("char_info is NULL");
718 g_variant_builder_add(inner_builder, "{sv}", "UUID",
719 g_variant_new_string(char_info->char_uuid));
721 g_variant_builder_add(inner_builder, "{sv}", "Service",
722 g_variant_new("o", serv_info->serv_path));
724 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
726 if (char_info->char_value != NULL) {
727 for (i = 0; i < char_info->value_length; i++) {
728 g_variant_builder_add(builder1, "y",
729 char_info->char_value[i]);
731 char_val = g_variant_new("ay", builder1);
732 g_variant_builder_add(inner_builder, "{sv}",
736 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
737 for (i = 0; i < char_info->flags_length; i++) {
738 g_variant_builder_add(builder2, "s",
739 char_info->char_flags[i]);
740 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0)
741 writeAcquired = TRUE;
743 if (strncmp(char_info->char_flags[i], "notify", 4) == 0)
744 notifyAcquired = TRUE;
747 flags_val = g_variant_new("as", builder2);
748 g_variant_builder_add(inner_builder, "{sv}", "Flags",
752 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
753 g_variant_new("b", notify));
756 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
757 g_variant_new("b", writeAcquired));
760 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
761 g_variant_new("b", notifyAcquired));
764 unicast = g_strdup("00:00:00:00:00:00");
765 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
766 g_variant_new("s", unicast));
769 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
770 DBG("Adding Descriptors list");
772 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
773 struct gatt_desc_info *desc_info = l4->data;
774 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
775 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
776 g_variant_builder_add(builder3, "o",
777 desc_info->desc_path);
778 DBG("%s", desc_info->desc_path);
781 char_desc = g_variant_new("ao", builder3);
782 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
785 g_variant_builder_add(char_builder, "{sa{sv}}",
786 GATT_CHAR_INTERFACE , inner_builder);
787 g_variant_builder_add(builder, "{oa{sa{sv}}}",
788 char_info->char_path, char_builder);
790 /*Prepare inner builder for GattDescriptor1 interface*/
792 GSList *l3 = char_info->desc_data;
795 DBG("descriptor data is NULL");
797 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
799 DBG("Creating builder for descriptor \n");
801 GVariantBuilder *desc_builder = NULL;
802 GVariantBuilder *inner_builder = NULL;
803 GVariantBuilder *builder1 = NULL;
804 GVariantBuilder *builder2 = NULL;
805 GVariant *desc_val = NULL;
807 desc_builder = g_variant_builder_new(
810 inner_builder = g_variant_builder_new(
814 struct gatt_desc_info *desc_info = l3->data;
815 if (desc_info == NULL) {
816 ERR("desc_info is NULL");
821 g_variant_builder_add(inner_builder,
823 g_variant_new_string(
824 desc_info->desc_uuid));
827 g_variant_builder_add(inner_builder, "{sv}",
830 char_info->char_path));
833 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
835 if (desc_info->desc_value != NULL) {
836 for (i = 0; i < desc_info->value_length; i++) {
837 g_variant_builder_add(builder1, "y",
838 desc_info->desc_value[i]);
840 desc_val = g_variant_new("ay", builder1);
841 g_variant_builder_add(inner_builder, "{sv}",
846 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
848 for (i = 0; i < desc_info->flags_length; i++) {
849 g_variant_builder_add(builder2, "s",
850 desc_info->desc_flags[i]);
853 flags_val = g_variant_new("as", builder2);
854 g_variant_builder_add(inner_builder, "{sv}", "Flags",
857 g_variant_builder_add(desc_builder, "{sa{sv}}",
861 g_variant_builder_add(builder, "{oa{sa{sv}}}",
862 desc_info->desc_path,
865 /*unref descriptor builder pointers*/
866 g_variant_builder_unref(builder1);
867 g_variant_builder_unref(builder2);
868 g_variant_builder_unref(inner_builder);
869 g_variant_builder_unref(desc_builder);
874 /*unref char builder pointers*/
875 g_variant_builder_unref(builder1);
876 g_variant_builder_unref(builder2);
877 g_variant_builder_unref(builder3);
878 g_variant_builder_unref(inner_builder);
879 g_variant_builder_unref(char_builder);
882 /*unref service builder pointers*/
883 g_variant_builder_unref(inner_builder);
884 g_variant_builder_unref(svc_builder);
887 /* Return builder as method reply */
888 DBG("Sending gatt service builder values to Bluez");
889 g_dbus_method_invocation_return_value(invocation,
899 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
901 const gchar *object_path,
902 const gchar *interface_name,
903 const gchar *method_name,
904 GVariant *parameters,
905 GDBusMethodInvocation *invocation,
909 if (g_strcmp0(method_name, "ReadValue") == 0) {
910 struct hal_ev_gatt_server_read_req ev;
915 struct gatt_client_info_t *conn_info = NULL;
916 struct gatt_req_info *req_info = NULL;
917 struct gatt_service_info *svc_info = NULL;
921 DBG("Application path = %s", object_path);
922 DBG("Sender = %s", sender);
924 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
925 if (svc_info == NULL) {
926 ERR("Coudn't find service for %s", object_path);
927 g_dbus_method_invocation_return_value(invocation, NULL);
931 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
932 DBG("Request id = %u, Offset = %u", req_id, offset);
934 /* Check if device is already in connected list */
935 conn_info = __bt_find_remote_gatt_client_info(addr);
937 if (conn_info == NULL) {
938 ERR("Coudn't find Connection info for %s", addr);
939 g_dbus_method_invocation_return_value(invocation, NULL);
944 ERR("GATT callback NOT registered");
945 g_dbus_method_invocation_return_value(invocation, NULL);
949 /* Store requests information */
950 req_info = g_new0(struct gatt_req_info, 1);
951 req_info->attr_path = g_strdup(object_path);
952 req_info->svc_path = g_strdup(svc_info->serv_path);
953 req_info->request_id = req_id;
954 req_info->offset = offset;
955 req_info->context = invocation;
957 /* Append request info in list of requests for the particular connection */
958 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
961 memset(&ev, 0, sizeof(ev));
962 ev.conn_id = conn_info->connection_id;
963 ev.trans_id = req_id;
964 ev.att_handle = desc_hdl;
966 ev.is_long = false; /* TODO*/
968 /* Convert address to hex */
969 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
971 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
973 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
975 GVariant *var = NULL;
979 gboolean response_needed = FALSE;
980 struct hal_ev_gatt_server_write_req ev;
984 struct gatt_service_info *svc_info = NULL;
985 struct gatt_client_info_t *conn_info = NULL;
986 struct gatt_req_info *req_info = NULL;
988 memset(&ev, 0, sizeof(ev));
991 DBG("Application path = %s", object_path);
992 DBG("Sender = %s", sender);
994 g_variant_get(parameters, "(&suqb@ay)",
995 &addr, &req_id, &offset, &response_needed, &var);
996 DBG("Request id = %u, Offset = %u", req_id, offset);
998 /* Check if device is already in connected list */
999 conn_info = __bt_find_remote_gatt_client_info(addr);
1001 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1003 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1004 g_variant_unref(var);
1005 if (response_needed)
1006 g_dbus_method_invocation_return_value(invocation, NULL);
1008 g_object_unref(invocation);
1012 len = g_variant_get_size(var);
1013 if (len > 0 && len < 600) {
1015 data = (char *)g_variant_get_data(var);
1016 memcpy(ev.value, data, len);
1019 if (response_needed) {
1020 /* Store request information */
1021 req_info = g_new0(struct gatt_req_info, 1);
1022 req_info->attr_path = g_strdup(object_path);
1023 req_info->svc_path = g_strdup(svc_info->serv_path);
1024 req_info->request_id = req_id;
1025 req_info->offset = offset;
1026 req_info->context = invocation;
1028 /* Append request info in list of requests for the particular connection */
1029 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1031 g_object_unref(invocation);
1034 /* Send HAL event */
1035 ev.conn_id = conn_info->connection_id;
1036 ev.trans_id = req_id;
1037 ev.att_handle = desc_hdl;
1039 ev.need_rsp = response_needed;
1042 /* Convert address to hex */
1043 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1045 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1047 g_variant_unref(var);
1052 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1053 const gchar *sender,
1054 const gchar *object_path,
1055 const gchar *interface_name,
1056 const gchar *method_name,
1057 GVariant *parameters,
1058 GDBusMethodInvocation *invocation,
1061 if (g_strcmp0(method_name, "ReadValue") == 0) {
1065 struct hal_ev_gatt_server_read_req ev;
1068 struct gatt_req_info *req_info = NULL;
1069 struct gatt_client_info_t *conn_info = NULL;
1070 struct gatt_service_info *svc_info = NULL;
1072 g_variant_get(parameters, "(&suq)",
1073 &addr, &req_id, &offset);
1075 DBG("Request id = %u, Offset = %u", req_id, offset);
1076 DBG("Application path = %s", object_path);
1077 DBG("Sender = %s", sender);
1078 DBG("Address = %s", addr);
1080 /* Check if device is already in connected list */
1081 conn_info = __bt_find_remote_gatt_client_info(addr);
1083 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1085 if (svc_info == NULL || conn_info == NULL) {
1086 g_dbus_method_invocation_return_value(invocation, NULL);
1091 ERR("GATT callback NOT registered");
1092 g_dbus_method_invocation_return_value(invocation, NULL);
1096 /* Store requets information */
1097 req_info = g_new0(struct gatt_req_info, 1);
1098 req_info->attr_path = g_strdup(object_path);
1099 req_info->svc_path = g_strdup(svc_info->serv_path);
1100 req_info->request_id = req_id;
1101 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1102 req_info->offset = offset;
1103 req_info->context = invocation;
1105 /* Append request info in list of requests for the particular connection */
1106 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1108 /* Send HAL event */
1109 memset(&ev, 0, sizeof(ev));
1110 ev.conn_id = conn_info->connection_id;
1111 ev.trans_id = req_id;
1112 ev.att_handle = char_hdl;
1114 ev.is_long = false; /* TODO*/
1116 /* Convert address to hex */
1117 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1118 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1120 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1121 GVariant *var = NULL;
1125 gboolean response_needed = FALSE;
1126 struct hal_ev_gatt_server_write_req ev;
1130 struct gatt_service_info *svc_info = NULL;
1131 struct gatt_req_info *req_info = NULL;
1132 struct gatt_client_info_t *conn_info = NULL;
1134 memset(&ev, 0, sizeof(ev));
1137 DBG("Application path = %s", object_path);
1138 DBG("Sender = %s", sender);
1140 g_variant_get(parameters, "(&suqb@ay)",
1141 &addr, &req_id, &offset, &response_needed, &var);
1142 DBG("Request id = %u, Offset = %u", req_id, offset);
1144 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1146 /* Check if device is already in connected list */
1147 conn_info = __bt_find_remote_gatt_client_info(addr);
1149 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1150 g_variant_unref(var);
1151 if (response_needed)
1152 g_dbus_method_invocation_return_value(invocation, NULL);
1154 g_object_unref(invocation);
1158 len = g_variant_get_size(var);
1159 if (len > 0 && len < 600) {
1161 data = (char *)g_variant_get_data(var);
1162 memcpy(ev.value, data, len);
1166 if (response_needed) {
1167 /* Store requets information */
1168 req_info = g_new0(struct gatt_req_info, 1);
1169 req_info->attr_path = g_strdup(object_path);
1170 req_info->svc_path = g_strdup(svc_info->serv_path);
1171 req_info->request_id = req_id;
1172 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1173 req_info->offset = offset;
1174 req_info->context = invocation;
1176 /* Append request info in list of requests for the particular connection */
1177 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1180 g_object_unref(invocation);
1183 /* Send HAL event */
1184 ev.conn_id = conn_info->connection_id;
1185 ev.trans_id = req_id;
1186 ev.att_handle = char_hdl;
1188 ev.need_rsp = response_needed;
1191 /* Convert address to hex */
1192 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1194 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1196 g_variant_unref(var);
1199 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1202 struct gatt_service_info *svc_info = NULL;
1203 struct hal_ev_gatt_server_notifcation_change ev;
1206 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1207 if (svc_info == NULL || event_cb == NULL)
1210 /* Send HAL event */
1211 memset(&ev, 0, sizeof(ev));
1212 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1213 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1214 ev.att_handle = char_hdl;
1217 /* Convert address to hex */
1218 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1220 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1223 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1226 struct gatt_service_info *svc_info = NULL;
1227 struct hal_ev_gatt_server_notifcation_change ev;
1230 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1231 if (svc_info == NULL || event_cb == NULL)
1234 /* Send HAL event */
1235 memset(&ev, 0, sizeof(ev));
1236 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1237 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1238 ev.att_handle = char_hdl;
1241 /* Convert address to hex */
1242 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1244 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1247 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1249 gboolean complete = FALSE;
1252 struct gatt_service_info *svc_info = NULL;
1253 struct gatt_client_info_t *conn_info = NULL;
1255 struct hal_ev_gatt_server_indicate_cfm ev;
1257 DBG("IndicateConfirm");
1258 DBG("Application path = %s", object_path);
1259 DBG("Sender = %s", sender);
1261 g_variant_get(parameters, "(&sb)", &addr, &complete);
1262 DBG("Remote Device address number = %s", addr);
1263 DBG("Is Indicate confirmation for last device [%d]", complete);
1265 /* Check if device is already in connected list */
1266 conn_info = __bt_find_remote_gatt_client_info(addr);
1268 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1270 if (svc_info == NULL || conn_info == NULL
1271 || event_cb == NULL) {
1275 /* Send HAL event */
1276 memset(&ev, 0, sizeof(ev));
1277 ev.conn_id = conn_info->connection_id;
1278 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1279 ev.att_handle = char_hdl;
1281 /* Convert address to hex */
1282 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1284 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1285 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1289 struct hal_ev_gatt_server_acquire_write_res ev;
1290 struct gatt_service_info *svc_info = NULL;
1291 struct gatt_req_info *req_info = NULL;
1292 struct gatt_client_info_t *conn_info = NULL;
1293 char * dev_path = NULL;
1295 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1297 DBG("AcquireWrite");
1298 DBG("Application path = %s", object_path);
1299 DBG("Sender = %s", sender);
1302 g_variant_get(parameters, "(a{sv})", &iter);
1304 GVariant* value = NULL;
1305 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1306 if (g_strcmp0(key, "MTU") == 0)
1307 g_variant_get(value, "i", &mtu);
1308 else if (g_strcmp0(key, "link") == 0)
1309 g_variant_get(value, "s", &link);
1310 else if (g_strcmp0(key, "device") == 0)
1311 g_variant_get(value, "o", &dev_path);
1314 DBG("AcquireWrite values retived");
1315 DBG(" path %s LINK = %s, MTU = %u", addr, link, mtu);
1317 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1319 _bt_hal_convert_device_path_to_address(dev_path, addr);
1321 DBG("remote address %s", addr);
1323 /* Check if device is already in connected list */
1324 conn_info = __bt_find_remote_gatt_client_info(addr);
1326 if (conn_info == NULL) {
1327 ERR("Cleint info not found\n");
1331 if (svc_info == NULL) {
1332 ERR("svc_info info not found\n");
1336 /* Store requets information */
1337 req_info = g_new0(struct gatt_req_info, 1);
1338 req_info->attr_path = g_strdup(object_path);
1339 req_info->svc_path = g_strdup(svc_info->serv_path);
1340 req_info->request_id = conn_info->connection_id;
1341 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1342 req_info->offset = mtu;
1343 req_info->context = invocation;
1345 /* Append request info in list of requests for the particular connection */
1346 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1348 /* Send HAL event */
1349 memset(&ev, 0, sizeof(ev));
1350 ev.conn_id = conn_info->connection_id;
1351 ev.char_handl = char_hdl;
1353 ev.trans_id = conn_info->connection_id;
1354 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1355 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1357 DBG("HAL_EV_GATT_ACQUIRE_WRITE_RES called");
1361 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1365 struct hal_ev_gatt_server_acquire_notify ev;
1366 struct gatt_service_info *svc_info = NULL;
1367 struct gatt_client_info_t *conn_info = NULL;
1368 struct gatt_req_info *req_info = NULL;
1370 DBG("AcquireNotify");
1371 DBG("Application path = %s", object_path);
1372 DBG("Sender = %s", sender);
1375 g_variant_get(parameters, "(a{sv})", &iter);
1377 GVariant* value = NULL;
1378 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1379 if (g_strcmp0(key, "MTU") == 0)
1380 g_variant_get(value, "q", &mtu);
1383 DBG("AcquireNotify values retived");
1384 DBG(" MTU = %u", mtu);
1386 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1388 if (svc_info == NULL) {
1389 ERR("svc_info info not found\n");
1393 /* Store requets information */
1394 req_info = g_new0(struct gatt_req_info, 1);
1395 req_info->attr_path = g_strdup(object_path);
1396 req_info->svc_path = g_strdup(svc_info->serv_path);
1397 req_info->request_id = 33;
1398 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1399 req_info->offset = mtu;
1400 req_info->context = invocation;
1402 conn_info = g_new0(struct gatt_client_info_t, 1);
1403 conn_info->addr = g_strdup(object_path);
1404 INFO("Added GATT client path[%s]", conn_info->addr);
1405 conn_info->connection_id = 33;
1406 conn_info->instance_id = 33;
1407 /* Append request info in list of requests for the particular connection */
1408 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1409 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1411 /* Send HAL event */
1412 memset(&ev, 0, sizeof(ev));
1414 ev.char_handl = char_hdl;
1418 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1420 DBG("HAL_EV_GATT_ACQUIRE_NOTIFY_RES called");
1426 g_dbus_method_invocation_return_value(invocation, NULL);
1429 gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1432 GError *error = NULL;
1433 GVariantBuilder *array_builder;
1435 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1436 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1437 g_variant_builder_add(array_builder, "s", interface);
1439 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1440 "org.freedesktop.Dbus.Objectmanager",
1441 "InterfacesRemoved",
1442 g_variant_new("(oas)",
1443 object_path, array_builder),
1447 if (error != NULL) {
1448 /* dbus gives error cause */
1449 ERR("d-bus api failure: errcode[%x], message[%s]",
1450 error->code, error->message);
1451 g_clear_error(&error);
1454 g_variant_builder_unref(array_builder);
1459 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1466 g_free(desc_info->desc_path);
1467 g_free(desc_info->desc_uuid);
1468 g_free(desc_info->desc_value);
1470 for (i = 0; i < desc_info->flags_length; i++)
1471 g_free(desc_info->desc_flags[i]);
1476 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1483 g_free(char_info->char_path);
1484 g_free(char_info->char_uuid);
1485 g_free(char_info->char_value);
1487 for (i = 0; i < char_info->flags_length; i++)
1488 g_free(char_info->char_flags[i]);
1494 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1499 g_free(svc_info->serv_path);
1500 g_free(svc_info->service_uuid);
1504 static const GDBusInterfaceVTable desc_interface_vtable = {
1505 __bt_gatt_desc_method_call,
1510 static const GDBusInterfaceVTable char_interface_vtable = {
1511 __bt_gatt_char_method_call,
1516 static const GDBusInterfaceVTable serv_interface_vtable = {
1522 static const GDBusInterfaceVTable manager_interface_vtable = {
1523 __bt_gatt_manager_method_call,
1529 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1530 const gchar *introspection_data)
1533 GDBusNodeInfo *node_info = NULL;
1535 if (introspection_data == NULL)
1539 DBG("Create new node info");
1540 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1543 ERR("Unable to create node: %s", err->message);
1544 g_clear_error(&err);
1551 /* To send stack event to hal-av handler */
1552 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1557 void _bt_hal_unregister_gatt_server_handler_cb(void)
1562 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1564 struct hal_ev_gatt_desc_added ev;
1565 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1567 /* Prepare to GATT characteristic added event */
1568 memset(&ev, 0, sizeof(ev));
1569 ev.status = BT_STATUS_SUCCESS;
1570 ev.server_instance = data->instance_data;
1571 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1572 ev.service_handle = data->srvc_hdl;
1573 ev.desc_handle = data->desc_hdl;
1576 ERR("GATT Descriptor Added callback registered");
1578 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1579 data->instance_data, data->srvc_hdl, data->desc_hdl);
1581 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1588 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1590 struct hal_ev_gatt_char_added ev;
1591 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1593 /* Prepare to GATT characteristic added event */
1594 memset(&ev, 0, sizeof(ev));
1595 ev.status = BT_STATUS_SUCCESS;
1596 ev.server_instance = data->instance_data;
1597 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1598 ev.service_handle = data->srvc_hdl;
1599 ev.char_handle = data->char_hdl;
1602 ERR("GATT Characteristic Added callback registered");
1604 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1605 data->instance_data, data->srvc_hdl, data->char_hdl);
1607 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1614 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1616 struct hal_ev_gatt_service_added ev;
1617 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1619 /* Prepare to GATT Service added event */
1620 memset(&ev, 0, sizeof(ev));
1621 ev.status = BT_STATUS_SUCCESS;
1622 ev.server_instance = data->instance_data;
1623 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1624 ev.service_handle = data->srvc_hdl;
1625 ev.is_primary = data->is_primary;
1628 ERR("GATT Service Added callback registered");
1630 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1631 data->instance_data, data->srvc_hdl);
1632 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1639 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1641 struct hal_ev_gatt_service_started ev;
1642 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1644 /* Prepare to GATT Service added event */
1645 memset(&ev, 0, sizeof(ev));
1646 ev.status = BT_STATUS_SUCCESS;
1647 ev.server_instance = data->instance_data;
1648 ev.service_handle = data->srvc_hdl;
1651 ERR("GATT Service Started callback registered");
1653 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1654 data->instance_data, data->srvc_hdl);
1655 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1662 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1664 struct hal_ev_gatt_service_deleted ev;
1665 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1667 /* Prepare to GATT Service added event */
1668 memset(&ev, 0, sizeof(ev));
1669 ev.status = BT_STATUS_SUCCESS;
1670 ev.server_instance = data->instance_data;
1671 ev.service_handle = data->srvc_hdl;
1674 ERR("GATT Service Deleted callback registered");
1676 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1677 data->instance_data, data->srvc_hdl);
1678 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1685 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1687 struct hal_ev_server_instance_registered ev;
1688 hal_register_server_data *data = (hal_register_server_data*) user_data;
1690 /* Prepare to send AV connecting event */
1691 memset(&ev, 0, sizeof(ev));
1692 ev.status = BT_STATUS_SUCCESS;
1693 ev.server_instance = data->instance_data;
1694 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1697 ERR("GATT Register Server Instance Callback not registered");
1699 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1700 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1707 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1709 CHECK_BTGATT_INIT();
1710 int status = BT_STATUS_FAIL;
1712 DBG("Register server instance request");
1713 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1715 /* Check if slot available */
1716 server_if = _bt_hal_get_available_adv_slot_id(uuid);
1718 if (server_if == -1) {
1719 ERR("Allocation of server instance failed");
1723 user_data->instance_data = server_if;
1724 DBG("Allocated new Advertising slot with Stack [%d]", user_data->instance_data);
1728 * As we need to provide async callback to user from HAL, simply schedule a
1729 * callback method which will carry actual result
1731 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1732 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1734 /* If available, then return success, else return error */
1735 return BT_STATUS_SUCCESS;
1738 void _bt_hal_remove_gatt_server_from_list(int server_if)
1741 struct gatt_server_app *info = NULL;
1743 for (l = gatt_server_apps; l != NULL;) {
1744 info = (struct gatt_server_app*)l->data;
1745 l = g_slist_next(l);
1748 if (info->slot == server_if) {
1749 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1750 info->app_path, info->slot);
1752 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1753 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1754 In above case, only advertising block will be deallocated, Gatt Server will remain
1756 if (info->services == NULL) {
1757 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1758 INFO("Total gatt server apps still existing after removing above is [%d]",
1759 g_slist_length(gatt_server_apps));
1761 /* DBUS Unregister only for current app */
1762 __bt_hal_gatt_deinit(info->app_path);
1764 g_free(info->app_path);
1768 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1769 g_slist_length(info->services));
1775 static bt_status_t gatt_server_unregister_app(int server_if)
1777 CHECK_BTGATT_INIT();
1778 DBG("Un-Register server instance request [%d]", server_if);
1780 if (_bt_hal_is_advertising_in_slot(server_if) == FALSE)
1781 _bt_hal_free_server_slot(server_if);
1783 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
1784 _bt_hal_remove_gatt_server_from_list(server_if);
1785 return BT_STATUS_SUCCESS;
1788 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
1790 CHECK_BTGATT_INIT();
1791 return BT_STATUS_SUCCESS;
1794 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
1797 GError *g_error = NULL;
1798 GVariant *reply = NULL;
1802 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
1803 g_object_unref(proxy);
1804 if (reply == NULL) {
1805 ERR("Disconnect LE Dbus Call Error");
1807 ERR("Error: %s\n", g_error->message);
1808 g_clear_error(&g_error);
1811 g_variant_unref(reply);
1815 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
1817 CHECK_BTGATT_INIT();
1819 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
1821 GDBusProxy *device_proxy;
1822 GDBusConnection *g_conn;
1823 struct gatt_client_info_t *conn_info = NULL;
1827 if (NULL == bd_addr) {
1828 ERR("bd_addr is NULL");
1829 return BT_STATUS_PARM_INVALID;
1832 /* GDBUS Connection Info validate */
1833 g_conn = _bt_hal_get_system_gconn();
1834 if (g_conn == NULL) {
1835 ERR("Could not get System DBUS Connection");
1836 return BT_STATUS_FAIL;
1839 /* Connection Info validate */
1840 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
1841 if (conn_info == NULL) {
1842 ERR("No Connection Inforamtion!!!");
1843 return BT_STATUS_FAIL;
1846 _bt_hal_convert_addr_type_to_string(device_address,
1847 (unsigned char *)bd_addr->address);
1849 //check if connection has the same device address
1850 if (g_strcmp0(conn_info->addr, device_address) != 0) {
1851 ERR("device address [%s] does not match", device_address);
1852 return BT_STATUS_FAIL;
1855 device_path = _bt_hal_get_device_object_path(conn_info->addr);
1856 if (device_path == NULL) {
1857 ERR("device_path is NULL");
1858 return BT_STATUS_PARM_INVALID;
1861 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
1862 NULL, BT_HAL_BLUEZ_NAME,
1863 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
1866 g_free(device_path);
1867 if (device_proxy == NULL)
1868 return BT_STATUS_FAIL;
1870 INFO("Disconnect LE [%s]", device_address);
1872 g_dbus_proxy_call(device_proxy, "DisconnectLE",
1874 G_DBUS_CALL_FLAGS_NONE,
1875 BT_HAL_MAX_DBUS_TIMEOUT,
1877 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
1880 return BT_STATUS_SUCCESS;
1883 static void __bt_gatt_close_gdbus_connection(void)
1891 if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
1892 ERR("Fail to flush the connection: %s", err->message);
1897 if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
1899 ERR("Fail to close the dbus connection: %s", err->message);
1904 g_object_unref(g_conn);
1909 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
1911 GDBusConnection *local_system_gconn = NULL;
1915 if (g_conn == NULL) {
1916 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1917 if (address == NULL) {
1919 ERR("Failed to get bus address: %s", err->message);
1920 g_clear_error(&err);
1925 g_conn = g_dbus_connection_new_for_address_sync(address,
1926 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1927 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1928 NULL, /* GDBusAuthObserver */
1933 ERR("Unable to connect to dbus: %s", err->message);
1934 g_clear_error(&err);
1938 } else if (g_dbus_connection_is_closed(g_conn)) {
1939 address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1940 if (address == NULL) {
1942 ERR("Failed to get bus address: %s", err->message);
1943 g_clear_error(&err);
1948 local_system_gconn = g_dbus_connection_new_for_address_sync(address,
1949 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1950 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
1951 NULL, /* GDBusAuthObserver */
1955 if (!local_system_gconn) {
1956 ERR("Unable to connect to dbus: %s", err->message);
1957 g_clear_error(&err);
1960 g_conn = local_system_gconn;
1966 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
1971 uuid = btuuid2str(srvc_id->uu);
1972 DBG("Original UUID [%s]", uuid);
1974 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
1975 /* Extract Standard UUID string */
1976 memcpy(uuid_buf, &uuid[4], 4);
1978 DBG("Converted string [%s]", uuid_buf);
1979 return g_strdup(uuid_buf);
1981 return strdup(uuid);
1984 int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
1987 /* For GATT service specific */
1988 GDBusNodeInfo *node_info;
1991 struct gatt_service_info *serv_info = NULL;
1992 GVariantBuilder *builder = NULL;
1993 GVariantBuilder *builder1 = NULL;
1994 GVariantBuilder *inner_builder = NULL;
1995 gboolean svc_primary = TRUE;
1996 GError *error = NULL;
1997 hal_gatt_service_added *user_data = NULL;
1998 DBG("Service add to DBUS slot [%d]", slot);
2000 node_info = __bt_gatt_create_method_node_info(
2001 service_introspection_xml);
2003 if (node_info == NULL)
2004 return BT_STATUS_FAIL;
2006 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
2007 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
2008 DBG("gatt service path is [%s]", path);
2010 object_id = g_dbus_connection_register_object(g_conn, path,
2011 node_info->interfaces[0],
2012 &serv_interface_vtable,
2013 NULL, NULL, &error);
2015 if (object_id == 0) {
2016 ERR("failed to register: %s", error->message);
2017 g_error_free(error);
2019 return BT_STATUS_FAIL;
2021 /* Add object_id/gatt service information; it's required at the time of
2022 * service unregister and Getmanagedobjects
2024 serv_info = g_new0(struct gatt_service_info, 1);
2026 serv_info->serv_path = g_strdup(path);
2027 serv_info->serv_id = object_id;
2028 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
2029 serv_info->is_svc_registered = FALSE;
2030 serv_info->is_svc_primary = svc_primary;
2031 DBG("Service Handle to be added is [%d]", gatt_service_handle);
2032 serv_info->service_handle = gatt_service_handle;
2034 /* Update service in GATT Server service List */
2035 gatt_services = g_slist_append(gatt_services, serv_info);
2037 /* emit interfacesadded signal here for service path */
2038 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2039 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2041 g_variant_builder_add(inner_builder, "{sv}",
2042 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
2044 g_variant_builder_add(inner_builder, "{sv}",
2045 "Primary", g_variant_new_boolean(svc_primary));
2047 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2049 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
2050 g_variant_new("ao", builder1));
2052 g_variant_builder_add(builder, "{sa{sv}}",
2053 GATT_SERV_INTERFACE, inner_builder);
2055 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2056 "org.freedesktop.Dbus.ObjectManager",
2058 g_variant_new("(oa{sa{sv}})",
2063 /* dbus gives error cause */
2064 ERR("d-bus api failure: errcode[%x], message[%s]",
2065 error->code, error->message);
2066 g_clear_error(&error);
2070 /* Send Service handle to application */
2071 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2072 user_data->srvc_hdl = serv_info->service_handle;
2073 user_data->instance_data = slot;
2074 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2075 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2077 /* Save newly created service in GATT Server's service list */
2078 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2082 g_variant_builder_unref(inner_builder);
2083 g_variant_builder_unref(builder);
2084 g_variant_builder_unref(builder1);
2085 return BT_STATUS_SUCCESS;
2088 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2091 char *app_path = (char*)user_data;
2092 INFO("UnregisterApplication is completed app [%s]", app_path);
2093 GError *error = NULL;
2094 GVariant *result = NULL;
2097 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2099 if (result == NULL) {
2100 /* dBUS-RPC is failed */
2101 ERR("Dbus-RPC is failed\n");
2103 if (error != NULL) {
2104 /* dBUS gives error cause */
2105 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2106 error->code, error->message);
2107 g_clear_error(&error);
2110 g_variant_unref(result);
2115 static void __bt_hal_gatt_deinit(char *app_path)
2117 GDBusProxy *proxy = NULL;
2121 /* Step1: Remove requested App */
2122 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2123 "/org/bluez/hci0", "org.bluez.GattManager1");
2128 INFO("UnregisterApplication : path [%s]", app_path);
2130 /* Async Call to Unregister Service */
2131 data = g_strdup(app_path);
2132 g_dbus_proxy_call(proxy,
2133 "UnregisterApplication",
2134 g_variant_new("(o)",
2136 G_DBUS_CALL_FLAGS_NONE, -1,
2138 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2141 /* If requested app is last GATT Server app, then clean all resources */
2142 if (gatt_server_apps == NULL) {
2143 INFO("All GATT servers are removed, clean all DBUS resources");
2145 /* unregister the exported interface for object manager
2146 g_conn and manager_id are common for all GATT servers */
2147 g_dbus_connection_unregister_object(g_conn,
2150 g_bus_unown_name(owner_id);
2153 g_object_unref(manager_gproxy);
2154 manager_gproxy = NULL;
2156 /* Close the GDBUS connection */
2157 __bt_gatt_close_gdbus_connection();
2163 int __bt_hal_gatt_init(void)
2165 GDBusConnection *conn = NULL;
2167 /* Only once for ALL GATT Servers */
2168 if (owner_id == 0) {
2169 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
2170 BT_GATT_SERVICE_NAME,
2171 G_BUS_NAME_OWNER_FLAGS_NONE,
2172 NULL, NULL, NULL, NULL, NULL);
2174 INFO("Owner ID [%d]", owner_id);
2176 /* Only once for ALL GATT Servers conn = g_conn(global)*/
2177 conn = __bt_gatt_get_gdbus_connection();
2179 ERR("Unable to get connection");
2180 return BT_STATUS_FAIL;
2183 /* Only once for ALL GATT Servers */
2184 if (manager_node_info == NULL) {
2185 /* Register ObjectManager interface */
2186 manager_node_info = __bt_gatt_create_method_node_info(
2187 manager_introspection_xml);
2189 if (manager_node_info == NULL) {
2190 ERR("failed to get node info");
2191 return BT_STATUS_FAIL;
2196 return BT_STATUS_SUCCESS;
2199 void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2203 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2204 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2205 if (app->slot == slot) {
2206 INFO("GATT Server app found app path [%s] instance [%d]",
2207 app->app_path, app->slot);
2208 *app_path = app->app_path;
2212 /* GATT Server not found */
2216 void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2218 if (app_path == NULL)
2221 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2222 app->app_path = g_strdup(app_path);
2224 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2225 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2230 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2233 CHECK_BTGATT_INIT();
2234 char *app_path = NULL;
2235 GError *error = NULL;
2239 int result = BT_STATUS_SUCCESS;
2241 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2242 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2244 /* Check if this GATT server Application is already registered with DBUS */
2245 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2247 if (app_path != NULL) {
2248 DBG("GATT server path is already defined [%s]", app_path);
2249 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2251 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2252 result = __bt_hal_gatt_init();
2253 if (result != BT_STATUS_SUCCESS)
2256 /* Only once for each GATT Server */
2257 app_path = g_strdup_printf("/com/%d", server_if);
2259 app_id = g_malloc0(sizeof(int));
2260 *app_id = server_if;
2262 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2263 manager_node_info->interfaces[0],
2264 &manager_interface_vtable,
2265 (gpointer)app_id, NULL, &error);
2267 if (manager_id == 0) {
2268 ERR("failed to register: %s", error->message);
2269 g_error_free(error);
2273 /* For current GATT Server, app_path is created, save it in Table */
2274 _bt_hal_update_gatt_server_path(server_if, app_path);
2276 /* Add GATT Service to DBUS */
2277 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2283 INFO("Successfully added service");
2284 return BT_STATUS_SUCCESS;
2291 INFO("Service addition failed!!");
2292 return BT_STATUS_FAIL;
2295 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2296 int included_handle)
2298 CHECK_BTGATT_INIT();
2299 return BT_STATUS_SUCCESS;
2303 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2306 GSList *gatt_services = NULL;
2308 struct gatt_service_info *info = NULL;
2310 gatt_services = _bt_get_service_list_from_server(instance);
2312 len = g_slist_length(gatt_services);
2313 l = g_slist_nth(gatt_services, len -1);
2319 if (info->service_handle == service_handle)
2324 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2328 GSList *gatt_services = NULL;
2329 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2331 gatt_services = _bt_get_service_list_from_server(instance);
2333 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2334 struct gatt_service_info *info = l->data;
2335 INFO("Got one service with handle [%d]", info->service_handle);
2336 if (info->service_handle == service_handle)
2339 ERR("Gatt service with handle [%d] not found", service_handle);
2343 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2344 bt_uuid_t *uuid, int properties,
2348 GError *error = NULL;
2350 GDBusNodeInfo *node_info;
2352 GVariantBuilder *builder = NULL;
2353 GVariantBuilder *inner_builder = NULL;
2354 struct gatt_service_info *serv_info = NULL;
2355 struct gatt_char_info *char_info = NULL;
2356 GVariantBuilder *builder2 = NULL;
2357 GVariantBuilder *builder3 = NULL;
2358 GVariant *flags_val = NULL;
2360 char *char_flags[NUMBER_OF_FLAGS];
2362 hal_gatt_char_added *user_data = NULL;
2365 CHECK_BTGATT_INIT();
2366 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2367 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2369 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2370 if (serv_info == NULL)
2371 return BT_STATUS_FAIL;
2373 node_info = __bt_gatt_create_method_node_info(
2374 characteristics_introspection_xml);
2376 if (node_info == NULL)
2377 return BT_STATUS_FAIL;
2379 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2380 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2381 DBG("gatt characteristic path is [%s]", path);
2383 app_id = g_malloc0(sizeof(int));
2386 object_id = g_dbus_connection_register_object(g_conn, path,
2387 node_info->interfaces[0],
2388 &char_interface_vtable,
2389 (gpointer)app_id, NULL, &error);
2391 if (object_id == 0) {
2392 ERR("failed to register: %s", error->message);
2393 g_error_free(error);
2396 return BT_STATUS_FAIL;
2399 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2400 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2401 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2402 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2403 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2404 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2405 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2406 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2408 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2410 char_info = g_new0(struct gatt_char_info, 1);
2412 char_info->char_path = g_strdup(path);
2413 char_info->char_id = object_id;
2414 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2415 for (i = 0; i < flag_count; i++)
2416 char_info->char_flags[i] = char_flags[i];
2419 char_info->flags_length = flag_count;
2420 char_info->char_handle = gatt_char_handle;
2423 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2424 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2426 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2427 g_variant_new("s", char_info->char_uuid));
2428 g_variant_builder_add(inner_builder, "{sv}", "Service",
2429 g_variant_new("o", serv_info->serv_path));
2431 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2433 for (i = 0; i < flag_count; i++)
2434 g_variant_builder_add(builder2, "s", char_flags[i]);
2436 flags_val = g_variant_new("as", builder2);
2437 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2440 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2442 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2443 g_variant_new("ao", builder3));
2445 g_variant_builder_add(builder, "{sa{sv}}",
2446 GATT_CHAR_INTERFACE,
2449 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2450 "org.freedesktop.Dbus.ObjectManager",
2452 g_variant_new("(oa{sa{sv}})",
2457 /* dbus gives error cause */
2458 ERR("d-bus api failure: errcode[%x], message[%s]",
2459 error->code, error->message);
2460 g_clear_error(&error);
2464 //*char_path = g_strdup(path);
2469 /* Send Service handle to application */
2470 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2471 user_data->srvc_hdl = serv_info->service_handle;
2472 user_data->char_hdl = gatt_char_handle;
2473 user_data->instance_data = slot;
2474 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2475 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2477 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2478 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2483 g_variant_builder_unref(inner_builder);
2484 g_variant_builder_unref(builder);
2485 g_variant_builder_unref(builder2);
2486 g_variant_builder_unref(builder3);
2488 return BT_STATUS_SUCCESS;
2491 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2494 CHECK_BTGATT_INIT();
2496 // static int desc_id = 1;
2497 GError *error = NULL;
2499 GDBusNodeInfo *node_info;
2501 GVariantBuilder *builder = NULL;
2502 GVariantBuilder *inner_builder = NULL;
2504 struct gatt_char_info *char_info = NULL;
2505 struct gatt_desc_info *desc_info = NULL;
2506 struct gatt_service_info *serv_info = NULL;
2508 gchar **line_argv = NULL;
2510 char *char_path = NULL;
2513 GVariantBuilder *builder2 = NULL;
2514 GVariant *flags_val = NULL;
2516 char *desc_flags[NUMBER_OF_FLAGS];
2520 hal_gatt_desc_added *user_data = NULL;
2527 /* Fetch service data for the GATT server */
2528 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2529 if (serv_info == NULL)
2530 return BT_STATUS_FAIL;
2532 /* Fetch list of characteristics from the service info */
2533 l = serv_info->char_data;
2535 /* Fetch last char info from the characteristic list */
2536 char_info = g_slist_last(l)->data;
2537 if (char_info == NULL)
2538 return BT_STATUS_FAIL;
2540 /* Fetch characteristic path from char info */
2541 char_path = char_info->char_path;
2543 line_argv = g_strsplit_set(char_path, "/", 0);
2544 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2547 node_info = __bt_gatt_create_method_node_info(
2548 descriptor_introspection_xml);
2550 if (node_info == NULL) {
2551 g_strfreev(line_argv);
2553 return BT_STATUS_FAIL;
2556 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2558 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2559 DBG("gatt descriptor path is [%s]", path);
2561 app_id = g_malloc0(sizeof(int));
2564 object_id = g_dbus_connection_register_object(g_conn, path,
2565 node_info->interfaces[0],
2566 &desc_interface_vtable,
2567 (gpointer)app_id, NULL, &error);
2569 if (object_id == 0) {
2570 ERR("failed to register: %s", error->message);
2571 g_error_free(error);
2573 g_strfreev(line_argv);
2576 return BT_STATUS_FAIL;
2579 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2581 desc_info = g_new0(struct gatt_desc_info, 1);
2583 desc_info->desc_path = g_strdup(path);
2584 desc_info->desc_id = object_id;
2585 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2587 for (i = 0; i < flag_count; i++)
2588 desc_info->desc_flags[i] = desc_flags[i];
2590 desc_info->flags_length = flag_count;
2591 desc_info->desc_handle = gatt_desc_handle;
2594 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2595 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2597 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2598 g_variant_new("s", btuuid2str(uuid->uu)));
2599 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2600 g_variant_new("o", char_path));
2602 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2604 for (i = 0; i < flag_count; i++)
2605 g_variant_builder_add(builder2, "s", desc_flags[i]);
2607 flags_val = g_variant_new("as", builder2);
2608 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2611 g_variant_builder_add(builder, "{sa{sv}}",
2612 GATT_DESC_INTERFACE,
2615 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2616 "org.freedesktop.Dbus.ObjectManager",
2618 g_variant_new("(oa{sa{sv}})",
2621 if (error != NULL) {
2622 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2623 error->code, error->message);
2624 g_clear_error(&error);
2627 //*desc_path = g_strdup(path);
2629 /* Save newly created descriptor to GATT server's service's characteristic */
2630 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2632 /* Send descriptor handle to application */
2633 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2634 user_data->srvc_hdl = serv_info->service_handle;
2635 user_data->desc_hdl = gatt_desc_handle;
2636 user_data->instance_data = slot;
2637 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2638 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2643 g_strfreev(line_argv);
2644 g_variant_builder_unref(inner_builder);
2645 g_variant_builder_unref(builder);
2646 return BT_STATUS_SUCCESS;
2649 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2651 GError *error = NULL;
2653 char *data = (char*) user_data;
2654 INFO("RegisterApplication is completed path [%s]", data);
2656 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2658 if (result == NULL) {
2659 /* dBUS-RPC is failed */
2660 ERR("Dbus-RPC is failed\n");
2662 if (error != NULL) {
2663 /* dBUS gives error cause */
2664 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2665 error->code, error->message);
2666 g_clear_error(&error);
2669 g_variant_unref(result);
2674 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2675 const gchar *path, const gchar *interface)
2681 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2686 ERR("Unable to connect to gdbus: %s", err->message);
2687 g_clear_error(&err);
2692 proxy = g_dbus_proxy_new_sync(g_conn,
2693 G_DBUS_PROXY_FLAGS_NONE, NULL,
2695 interface, NULL, &err);
2699 ERR("Unable to create proxy: %s", err->message);
2700 g_clear_error(&err);
2704 manager_gproxy = proxy;
2709 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2710 const gchar *path, const gchar *interface)
2712 return (manager_gproxy) ? manager_gproxy :
2713 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2717 static void __bt_register_application_to_dbus(int slot)
2719 GDBusProxy *proxy = NULL;
2720 char *app_path = NULL;
2722 DBG("RegisterApplication slot [%d]", slot);
2724 /* It is impossible that app path is still not initialized */
2725 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2727 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2728 "/org/bluez/hci0", "org.bluez.GattManager1");
2730 data = g_strdup(app_path);
2731 g_dbus_proxy_call(proxy,
2732 "RegisterApplication",
2733 g_variant_new("(oa{sv})",
2735 G_DBUS_CALL_FLAGS_NONE, -1,
2737 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2739 INFO("GATT server started");
2742 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2744 CHECK_BTGATT_INIT();
2745 struct gatt_service_info *serv_info = NULL;
2746 hal_gatt_service_started *user_data = NULL;
2747 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2749 /* Fetch service data for the GATT server */
2750 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2751 if (serv_info == NULL)
2752 return BT_STATUS_FAIL;
2754 if (serv_info->is_svc_registered)
2755 DBG("service already registered \n");
2757 serv_info->is_svc_registered = TRUE;
2759 /* Send Service handle to application */
2760 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2761 user_data->srvc_hdl = serv_info->service_handle;
2762 user_data->instance_data = server_if;
2763 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2765 /* If this is nth Service that is started, then register application at this point */
2766 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2767 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2769 __bt_register_application_to_dbus(server_if);
2772 return BT_STATUS_SUCCESS;
2775 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2777 CHECK_BTGATT_INIT();
2778 INFO("Stop service successful");
2779 return BT_STATUS_SUCCESS;
2782 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2784 CHECK_BTGATT_INIT();
2785 struct gatt_service_info *serv_info = NULL;
2786 hal_gatt_service_deleted *user_data = NULL;
2789 int err = BT_STATUS_SUCCESS;
2790 int ret = BT_STATUS_SUCCESS;
2791 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2793 /* Fetch service data for the GATT server */
2794 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2795 if (serv_info == NULL) {
2796 ERR("Could not find service info svc handle [%d] server slot [%d]",
2797 service_handle, server_if);
2798 return BT_STATUS_FAIL;
2801 if (serv_info->is_svc_registered == FALSE) {
2802 ERR("service Not registered path [%s] handle [%d]",
2803 serv_info->serv_path, service_handle);
2806 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2807 struct gatt_char_info *char_info = l->data;
2809 if (char_info == NULL)
2812 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2813 struct gatt_desc_info *desc_info = l1->data;
2815 if (desc_info == NULL)
2818 ret = g_dbus_connection_unregister_object(g_conn,
2819 desc_info->desc_id);
2821 __bt_hal_gatt_emit_interface_removed(
2822 desc_info->desc_path,
2823 GATT_DESC_INTERFACE);
2825 err = BT_STATUS_FAIL;
2828 /* list remove & free */
2829 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2830 __bt_hal_gatt_free_descriptor_info(desc_info);
2833 g_slist_free(char_info->desc_data);
2834 char_info->desc_data = NULL;
2836 ret = g_dbus_connection_unregister_object(g_conn,
2837 char_info->char_id);
2839 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2840 GATT_CHAR_INTERFACE);
2843 err = BT_STATUS_FAIL;
2846 /* list remove & free */
2847 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2848 __bt_hal_gatt_free_characteristic_info(char_info);
2851 g_slist_free(serv_info->char_data);
2852 serv_info->char_data = NULL;
2854 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2856 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2857 GATT_SERV_INTERFACE);
2860 err = BT_STATUS_FAIL;
2863 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
2865 DBG("Unregistered the service on properties interface");
2867 /* Remove from global list */
2868 gatt_services = g_slist_remove(gatt_services, serv_info);
2869 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
2871 /* Remove from GATT Server's list of services */
2872 _bt_remote_service_from_gatt_server(server_if, service_handle);
2874 if (gatt_services == NULL)
2875 INFO("All GATT Services of all GATT Servers are unregistered");
2877 if (err == BT_STATUS_SUCCESS) {
2878 INFO("Send GATT Service deleted Event");
2879 /* Send Service handle to application */
2880 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
2881 user_data->srvc_hdl = serv_info->service_handle;
2882 user_data->instance_data = server_if;
2883 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
2886 /* Free the service */
2887 __bt_hal_gatt_free_service_info(serv_info);
2891 static gboolean __bt_gatt_get_service_state(const char *service_path)
2893 struct gatt_service_info *svc_info = NULL;
2895 for (l = gatt_services; l; l = g_slist_next(l)) {
2897 svc_info = (struct gatt_service_info *)l->data;
2900 if (!g_strcmp0(svc_info->serv_path, service_path)) {
2901 DBG("Return the state of the gatt service %d",
2902 svc_info->is_svc_registered);
2903 return svc_info->is_svc_registered;
2907 DBG("gatt service info is NULL");
2911 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
2912 int len, int confirm, char* p_value)
2914 CHECK_BTGATT_INIT();
2917 GVariantBuilder *outer_builder;
2918 GVariantBuilder *invalidated_builder;
2920 /* For Value update via PropertyChange */
2921 GVariantBuilder *outer_builder1;
2922 GVariantBuilder *inner_builder1;
2923 GVariantBuilder *invalidated_builder1;
2924 GVariant *update_value = NULL;
2926 /* Other variables */
2927 struct gatt_client_info_t *conn_info = NULL;
2928 gchar *serv_path = NULL;
2929 char *char_path = NULL;
2930 gchar **line_argv = NULL;
2931 gboolean notify = TRUE;
2932 gboolean ret = TRUE;
2933 int err = BT_STATUS_SUCCESS;
2935 GError *error = NULL;
2938 memset(addr, 0x00, sizeof(addr));
2940 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2941 if (conn_info == NULL) {
2942 ERR("No Connection Inforamtion!!!");
2943 return BT_STATUS_FAIL;
2946 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
2948 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
2949 if (char_path == NULL)
2950 return BT_STATUS_FAIL;
2952 line_argv = g_strsplit_set(char_path, "/", 0);
2953 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2955 if (!__bt_gatt_get_service_state(serv_path)) {
2956 DBG("service not registered for this characteristic \n");
2958 g_strfreev(line_argv);
2959 return BT_STATUS_FAIL;
2962 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2963 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2965 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2966 g_variant_new("b", notify));
2968 _bt_hal_convert_addr_type_to_string(addr, (unsigned char *)conn_info->addr);
2970 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2971 g_variant_new("s", addr));
2973 DBG("Set characteristic Notification \n");
2974 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2976 "org.freedesktop.DBus.Properties",
2977 "PropertiesChanged",
2978 g_variant_new("(sa{sv}as)",
2979 "org.bluez.GattCharacteristic1",
2980 outer_builder, invalidated_builder),
2984 if (error != NULL) {
2985 ERR("D-Bus API failure: errCode[%x], \
2987 error->code, error->message);
2988 g_clear_error(&error);
2990 err = BT_STATUS_FAIL;
2993 g_variant_builder_unref(outer_builder);
2994 g_variant_builder_unref(invalidated_builder);
2997 /* Notifying Done, now update Value to Bluez via PropertyChanged */
2998 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
3000 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3001 for (i = 0; i < len; i++)
3002 g_variant_builder_add(inner_builder1, "y", p_value[i]);
3004 update_value = g_variant_new("ay", inner_builder1);
3007 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3008 g_variant_builder_add(outer_builder1, "{sv}", "Value",
3011 DBG("Updating characteristic value \n");
3012 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3014 "org.freedesktop.DBus.Properties",
3015 "PropertiesChanged",
3016 g_variant_new("(sa{sv}as)",
3017 "org.bluez.GattCharacteristic1",
3018 outer_builder1, invalidated_builder1),
3022 if (error != NULL) {
3023 ERR("D-Bus API failure: errCode[%x], \
3025 error->code, error->message);
3026 g_clear_error(&error);
3028 err = BT_STATUS_FAIL;
3030 struct gatt_char_info *char_info = NULL;
3032 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3033 if (char_info == NULL) {
3035 g_strfreev(line_argv);
3036 g_variant_builder_unref(inner_builder1);
3037 g_variant_builder_unref(outer_builder1);
3038 g_variant_builder_unref(invalidated_builder1);
3040 return BT_STATUS_FAIL;
3043 char_info->value_length = len;
3045 char_info->char_value = (char *)realloc(char_info->char_value, len);
3046 if (char_info->char_value) {
3047 for (i = 0; i < len; i++)
3048 char_info->char_value[i] = p_value[i];
3053 g_strfreev(line_argv);
3054 g_variant_builder_unref(inner_builder1);
3055 g_variant_builder_unref(outer_builder1);
3056 g_variant_builder_unref(invalidated_builder1);
3061 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3062 int status, btgatt_response_t *response)
3064 CHECK_BTGATT_INIT();
3066 struct gatt_req_info *req_info = NULL;
3067 struct gatt_client_info_t *conn_info = NULL;
3070 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3072 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3073 if (conn_info == NULL) {
3074 ERR("No Connection Inforamtion!!!");
3075 return BT_STATUS_FAIL;
3078 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3079 if (req_info == NULL) {
3080 ERR("No Request Inforamtion!!!");
3081 return BT_STATUS_FAIL;
3084 if (status != BT_STATUS_SUCCESS) {
3085 ERR("resp_state is 0x%X", status);
3087 g_dbus_method_invocation_return_dbus_error(req_info->context,
3088 "org.bluez.Error.Failed", "Application Error");
3090 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3092 req_info->context = NULL;
3093 if (req_info->attr_path)
3094 g_free(req_info->attr_path);
3095 if (req_info->svc_path)
3096 g_free(req_info->svc_path);
3099 return BT_STATUS_SUCCESS;
3102 DBG("Reponse Value length [%d]", response->attr_value.len);
3103 DBG("Request type: [%d]", req_info->request_type);
3106 for (i = 0; i < response->attr_value.len; i++)
3107 DBG("Resonse [%d] = [0x%x]", i, response->attr_value.value[i]);
3109 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3110 GVariantBuilder *inner_builder = NULL;
3111 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3113 if (response->attr_value.len > 0) {
3114 for (i = 0; i < response->attr_value.len; i++)
3115 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3117 g_dbus_method_invocation_return_value(req_info->context,
3118 g_variant_new("(ay)", inner_builder));
3120 g_variant_builder_unref(inner_builder);
3122 g_dbus_method_invocation_return_value(req_info->context, NULL);
3124 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3126 req_info->context = NULL;
3127 if (req_info->attr_path)
3128 g_free(req_info->attr_path);
3129 if (req_info->svc_path)
3130 g_free(req_info->svc_path);
3133 return BT_STATUS_SUCCESS;
3137 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3138 int status, int fd, int mtu, void *fdlist)
3140 CHECK_BTGATT_INIT();
3142 struct gatt_req_info *req_info = NULL;
3143 struct gatt_client_info_t *conn_info = NULL;
3145 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3147 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3148 if (conn_info == NULL) {
3149 ERR("No Connection Inforamtion!!!");
3150 return BT_STATUS_FAIL;
3153 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3154 if (req_info == NULL) {
3155 ERR("No Request Inforamtion!!!");
3156 return BT_STATUS_FAIL;
3159 if (status != BT_STATUS_SUCCESS) {
3160 ERR("resp_state is 0x%X", status);
3162 g_dbus_method_invocation_return_dbus_error(req_info->context,
3163 "org.bluez.Error.Failed", "Application Error");
3165 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3167 req_info->context = NULL;
3168 if (req_info->attr_path)
3169 g_free(req_info->attr_path);
3170 if (req_info->svc_path)
3171 g_free(req_info->svc_path);
3174 return BT_STATUS_SUCCESS;
3178 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3180 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3181 g_dbus_method_invocation_return_value_with_unix_fd_list(
3182 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3184 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3186 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3187 g_dbus_method_invocation_return_value_with_unix_fd_list(
3188 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3191 g_dbus_method_invocation_return_value(req_info->context, NULL);
3193 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3195 req_info->context = NULL;
3196 if (req_info->attr_path)
3197 g_free(req_info->attr_path);
3198 if (req_info->svc_path)
3199 g_free(req_info->svc_path);
3202 return BT_STATUS_SUCCESS;
3206 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3207 int value_length, char* att_value)
3209 CHECK_BTGATT_INIT();
3211 /* Other variables */
3212 char *char_path = NULL;
3213 gboolean ret = TRUE;
3214 GError *error = NULL;
3216 GVariantBuilder *outer_builder;
3217 GVariantBuilder *inner_builder;
3218 GVariantBuilder *invalidated_builder;
3219 GVariant *update_value = NULL;
3220 int err = BT_STATUS_SUCCESS;
3222 gchar **line_argv = NULL;
3223 gchar *serv_path = NULL;
3225 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3226 if (char_path == NULL)
3227 return BT_STATUS_FAIL;
3229 line_argv = g_strsplit_set(char_path, "/", 0);
3230 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3232 if (!__bt_gatt_get_service_state(serv_path)) {
3233 DBG("service not registered for this characteristic \n");
3235 g_strfreev(line_argv);
3236 return BT_STATUS_FAIL;
3240 line_argv = g_strsplit_set(char_path, "/", 0);
3241 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3243 if (!__bt_gatt_get_service_state(serv_path)) {
3244 DBG("service not registered for this characteristic \n");
3246 g_strfreev(line_argv);
3247 return BT_STATUS_FAIL;
3250 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3251 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3253 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3254 for (i = 0; i < value_length; i++)
3255 g_variant_builder_add(inner_builder, "y", att_value[i]);
3257 update_value = g_variant_new("ay", inner_builder);
3259 g_variant_builder_add(outer_builder, "{sv}", "Value",
3262 DBG("Updating characteristic value \n");
3263 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3265 "org.freedesktop.DBus.Properties",
3266 "PropertiesChanged",
3267 g_variant_new("(sa{sv}as)",
3268 "org.bluez.GattCharacteristic1",
3269 outer_builder, invalidated_builder),
3273 if (error != NULL) {
3274 ERR("D-Bus API failure: errCode[%x], \
3276 error->code, error->message);
3277 g_clear_error(&error);
3279 err = BT_STATUS_FAIL;
3281 struct gatt_char_info *char_info = NULL;
3283 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3284 if (char_info == NULL) {
3286 g_strfreev(line_argv);
3287 g_variant_builder_unref(inner_builder);
3288 g_variant_builder_unref(outer_builder);
3289 g_variant_builder_unref(invalidated_builder);
3291 return BT_STATUS_FAIL;
3294 char_info->value_length = value_length;
3296 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3297 if (char_info->char_value) {
3298 for (i = 0; i < value_length; i++)
3299 char_info->char_value[i] = att_value[i];
3305 g_strfreev(line_argv);
3306 g_variant_builder_unref(inner_builder);
3307 g_variant_builder_unref(outer_builder);
3308 g_variant_builder_unref(invalidated_builder);
3313 static bt_status_t gatt_server_listen(int server_if, bool start)
3315 CHECK_BTGATT_INIT();
3316 /* Send Data to LE Module */
3317 return _bt_hal_enable_advertising(server_if, start, FALSE);
3320 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3321 bool include_txpower, int min_interval, int max_interval, int appearance,
3322 uint16_t manufacturer_len, char* manufacturer_data,
3323 uint16_t service_data_len, char* service_data,
3324 uint16_t service_uuid_len, char* service_uuid)
3326 CHECK_BTGATT_INIT();
3327 return BT_STATUS_SUCCESS;
3330 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3332 CHECK_BTGATT_INIT();
3333 /* Send Enable Advertising request to LE Module */
3334 return _bt_hal_enable_advertising(server_if, TRUE, TRUE);
3337 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3338 int chnl_map, int tx_power, int timeout_s)
3340 CHECK_BTGATT_INIT();
3342 /* Send Advertising parameters to LE Module */
3343 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3344 chnl_map, tx_power, timeout_s);
3347 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3349 CHECK_BTGATT_INIT();
3351 /* Send Data to LE Module */
3352 return _bt_hal_set_advertising_data(adv_param_setup);
3355 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3357 CHECK_BTGATT_INIT();
3358 /* Send Data to LE Module */
3359 return _bt_hal_enable_advertising(server_if, FALSE, TRUE);
3362 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3364 CHECK_BTGATT_INIT();
3365 char *object_path = NULL;
3367 GDBusProxy *device_proxy;
3368 GError *error = NULL;
3370 GVariant *tmp_value;
3371 GDBusConnection *conn;
3372 GVariant *result = NULL;
3373 int ret = BT_STATUS_SUCCESS;
3374 struct gatt_client_info_t *conn_info = NULL;
3377 if (mtu_size == NULL)
3378 return BT_STATUS_PARM_INVALID;
3380 /* GDBUS Connection Info validate */
3381 conn = _bt_hal_get_system_gconn();
3383 ERR("Could not get System DBUS Connection");
3384 return BT_STATUS_FAIL;
3387 /* Connection Info validate */
3388 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3389 if (conn_info == NULL) {
3390 ERR("No Connection Inforamtion!!!");
3391 return BT_STATUS_FAIL;
3395 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3396 if (object_path == NULL)
3397 return BT_STATUS_FAIL;
3399 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3400 NULL, BT_HAL_BLUEZ_NAME, object_path,
3401 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3403 g_free(object_path);
3404 if (device_proxy == NULL)
3405 return BT_STATUS_FAIL;
3407 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3408 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3409 G_DBUS_CALL_FLAGS_NONE,
3413 if (result == NULL) {
3414 if (error != NULL) {
3415 ERR("Error occured in Proxy call [%s]\n", error->message);
3416 g_error_free(error);
3418 g_object_unref(device_proxy);
3419 return BT_STATUS_FAIL;
3422 g_variant_get(result , "(@a{sv})", &value);
3423 g_variant_unref(result);
3425 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3426 if (tmp_value == NULL) {
3427 g_object_unref(device_proxy);
3428 g_variant_unref(value);
3429 return BT_STATUS_FAIL;
3432 mtu = g_variant_get_uint16(tmp_value);
3434 DBG("ATT MTU : [%d]", mtu);
3436 g_variant_unref(tmp_value);
3437 g_variant_unref(value);
3438 g_object_unref(device_proxy);
3440 *mtu_size = (int) mtu;
3445 const btgatt_server_interface_t btgatt_server_interface = {
3446 .register_server = gatt_server_register_app,
3447 .unregister_server = gatt_server_unregister_app,
3448 .connect = gatt_server_open,
3449 .disconnect = gatt_server_close,
3450 .add_service = gatt_server_add_service,
3451 .add_included_service = gatt_server_add_included_service,
3452 .add_characteristic = gatt_server_add_characteristic,
3453 .add_descriptor = gatt_server_add_descriptor,
3454 .start_service = gatt_server_start_service,
3455 .stop_service = gatt_server_stop_service,
3456 .delete_service = gatt_server_delete_service,
3457 .send_indication = gatt_server_send_indication,
3458 .send_response = gatt_server_send_response,
3459 .update_att_value = gatt_server_update_att_value,
3460 .listen = gatt_server_listen,
3461 .set_adv_data = gatt_server_set_adv_data,
3462 .multi_adv_enable = gatt_server_multi_adv_enable,
3463 .multi_adv_update = gatt_server_multi_adv_update,
3464 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3465 .multi_adv_disable = gatt_server_multi_adv_disable,
3466 .get_att_mtu = gatt_server_get_mtu_size,
3467 .send_response_acquire = gatt_server_send_acquire_response