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 static 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 static 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 static 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 static 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 static 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]);
741 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
742 DBG("setting WriteAcquired property");
743 writeAcquired = TRUE;
746 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
747 DBG("setting NotifyAcquired property");
748 notifyAcquired = TRUE;
752 flags_val = g_variant_new("as", builder2);
753 g_variant_builder_add(inner_builder, "{sv}", "Flags",
757 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
758 g_variant_new("b", notify));
761 if (writeAcquired == TRUE) {
762 DBG("adding WriteAcquired property");
763 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
764 g_variant_new("b", writeAcquired));
768 if (notifyAcquired == TRUE) {
769 DBG("adding NotifyAcquired property");
770 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
771 g_variant_new("b", notifyAcquired));
775 unicast = g_strdup("00:00:00:00:00:00");
776 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
777 g_variant_new("s", unicast));
780 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
781 DBG("Adding Descriptors list");
783 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
784 struct gatt_desc_info *desc_info = l4->data;
785 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
786 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
787 g_variant_builder_add(builder3, "o",
788 desc_info->desc_path);
789 DBG("%s", desc_info->desc_path);
792 char_desc = g_variant_new("ao", builder3);
793 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
796 g_variant_builder_add(char_builder, "{sa{sv}}",
797 GATT_CHAR_INTERFACE , inner_builder);
798 g_variant_builder_add(builder, "{oa{sa{sv}}}",
799 char_info->char_path, char_builder);
801 /*Prepare inner builder for GattDescriptor1 interface*/
803 GSList *l3 = char_info->desc_data;
806 DBG("descriptor data is NULL");
808 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
810 DBG("Creating builder for descriptor \n");
812 GVariantBuilder *desc_builder = NULL;
813 GVariantBuilder *inner_builder = NULL;
814 GVariantBuilder *builder1 = NULL;
815 GVariantBuilder *builder2 = NULL;
816 GVariant *desc_val = NULL;
818 desc_builder = g_variant_builder_new(
821 inner_builder = g_variant_builder_new(
825 struct gatt_desc_info *desc_info = l3->data;
826 if (desc_info == NULL) {
827 ERR("desc_info is NULL");
832 g_variant_builder_add(inner_builder,
834 g_variant_new_string(
835 desc_info->desc_uuid));
838 g_variant_builder_add(inner_builder, "{sv}",
841 char_info->char_path));
844 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
846 if (desc_info->desc_value != NULL) {
847 for (i = 0; i < desc_info->value_length; i++) {
848 g_variant_builder_add(builder1, "y",
849 desc_info->desc_value[i]);
851 desc_val = g_variant_new("ay", builder1);
852 g_variant_builder_add(inner_builder, "{sv}",
857 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
859 for (i = 0; i < desc_info->flags_length; i++) {
860 g_variant_builder_add(builder2, "s",
861 desc_info->desc_flags[i]);
864 flags_val = g_variant_new("as", builder2);
865 g_variant_builder_add(inner_builder, "{sv}", "Flags",
868 g_variant_builder_add(desc_builder, "{sa{sv}}",
872 g_variant_builder_add(builder, "{oa{sa{sv}}}",
873 desc_info->desc_path,
876 /*unref descriptor builder pointers*/
877 g_variant_builder_unref(builder1);
878 g_variant_builder_unref(builder2);
879 g_variant_builder_unref(inner_builder);
880 g_variant_builder_unref(desc_builder);
885 /*unref char builder pointers*/
886 g_variant_builder_unref(builder1);
887 g_variant_builder_unref(builder2);
888 g_variant_builder_unref(builder3);
889 g_variant_builder_unref(inner_builder);
890 g_variant_builder_unref(char_builder);
893 /*unref service builder pointers*/
894 g_variant_builder_unref(inner_builder);
895 g_variant_builder_unref(svc_builder);
898 /* Return builder as method reply */
899 DBG("Sending gatt service builder values to Bluez");
900 g_dbus_method_invocation_return_value(invocation,
910 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
912 const gchar *object_path,
913 const gchar *interface_name,
914 const gchar *method_name,
915 GVariant *parameters,
916 GDBusMethodInvocation *invocation,
920 if (g_strcmp0(method_name, "ReadValue") == 0) {
921 struct hal_ev_gatt_server_read_req ev;
926 struct gatt_client_info_t *conn_info = NULL;
927 struct gatt_req_info *req_info = NULL;
928 struct gatt_service_info *svc_info = NULL;
932 DBG("Application path = %s", object_path);
933 DBG("Sender = %s", sender);
935 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
936 if (svc_info == NULL) {
937 ERR("Coudn't find service for %s", object_path);
938 g_dbus_method_invocation_return_value(invocation, NULL);
942 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
943 DBG("Request id = %u, Offset = %u", req_id, offset);
945 /* Check if device is already in connected list */
946 conn_info = __bt_find_remote_gatt_client_info(addr);
948 if (conn_info == NULL) {
949 ERR("Coudn't find Connection info for %s", addr);
950 g_dbus_method_invocation_return_value(invocation, NULL);
955 ERR("GATT callback NOT registered");
956 g_dbus_method_invocation_return_value(invocation, NULL);
960 /* Store requests information */
961 req_info = g_new0(struct gatt_req_info, 1);
962 req_info->attr_path = g_strdup(object_path);
963 req_info->svc_path = g_strdup(svc_info->serv_path);
964 req_info->request_id = req_id;
965 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
966 req_info->offset = offset;
967 req_info->context = invocation;
969 /* Append request info in list of requests for the particular connection */
970 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
973 memset(&ev, 0, sizeof(ev));
974 ev.conn_id = conn_info->connection_id;
975 ev.trans_id = req_id;
976 ev.att_handle = desc_hdl;
978 ev.is_long = false; /* TODO*/
980 /* Convert address to hex */
981 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
983 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
985 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
987 GVariant *var = NULL;
991 gboolean response_needed = FALSE;
992 struct hal_ev_gatt_server_write_req ev;
996 struct gatt_service_info *svc_info = NULL;
997 struct gatt_client_info_t *conn_info = NULL;
998 struct gatt_req_info *req_info = NULL;
1000 memset(&ev, 0, sizeof(ev));
1003 DBG("Application path = %s", object_path);
1004 DBG("Sender = %s", sender);
1006 g_variant_get(parameters, "(&suqb@ay)",
1007 &addr, &req_id, &offset, &response_needed, &var);
1008 DBG("Request id = %u, Offset = %u", req_id, offset);
1010 /* Check if device is already in connected list */
1011 conn_info = __bt_find_remote_gatt_client_info(addr);
1013 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1015 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1016 g_variant_unref(var);
1017 if (response_needed)
1018 g_dbus_method_invocation_return_value(invocation, NULL);
1020 g_object_unref(invocation);
1024 len = g_variant_get_size(var);
1025 if (len > 0 && len < 600) {
1027 data = (char *)g_variant_get_data(var);
1028 memcpy(ev.value, data, len);
1031 if (response_needed) {
1032 /* Store request information */
1033 req_info = g_new0(struct gatt_req_info, 1);
1034 req_info->attr_path = g_strdup(object_path);
1035 req_info->svc_path = g_strdup(svc_info->serv_path);
1036 req_info->request_id = req_id;
1037 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1038 req_info->offset = offset;
1039 req_info->context = invocation;
1041 /* Append request info in list of requests for the particular connection */
1042 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1044 g_object_unref(invocation);
1047 /* Send HAL event */
1048 ev.conn_id = conn_info->connection_id;
1049 ev.trans_id = req_id;
1050 ev.att_handle = desc_hdl;
1052 ev.need_rsp = response_needed;
1055 /* Convert address to hex */
1056 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1058 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1060 g_variant_unref(var);
1065 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1066 const gchar *sender,
1067 const gchar *object_path,
1068 const gchar *interface_name,
1069 const gchar *method_name,
1070 GVariant *parameters,
1071 GDBusMethodInvocation *invocation,
1074 if (g_strcmp0(method_name, "ReadValue") == 0) {
1078 struct hal_ev_gatt_server_read_req ev;
1081 struct gatt_req_info *req_info = NULL;
1082 struct gatt_client_info_t *conn_info = NULL;
1083 struct gatt_service_info *svc_info = NULL;
1085 g_variant_get(parameters, "(&suq)",
1086 &addr, &req_id, &offset);
1088 DBG("Request id = %u, Offset = %u", req_id, offset);
1089 DBG("Application path = %s", object_path);
1090 DBG("Sender = %s", sender);
1091 DBG("Address = %s", addr);
1093 /* Check if device is already in connected list */
1094 conn_info = __bt_find_remote_gatt_client_info(addr);
1096 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1098 if (svc_info == NULL || conn_info == NULL) {
1099 g_dbus_method_invocation_return_value(invocation, NULL);
1104 ERR("GATT callback NOT registered");
1105 g_dbus_method_invocation_return_value(invocation, NULL);
1109 /* Store requets information */
1110 req_info = g_new0(struct gatt_req_info, 1);
1111 req_info->attr_path = g_strdup(object_path);
1112 req_info->svc_path = g_strdup(svc_info->serv_path);
1113 req_info->request_id = req_id;
1114 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1115 req_info->offset = offset;
1116 req_info->context = invocation;
1118 /* Append request info in list of requests for the particular connection */
1119 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1121 /* Send HAL event */
1122 memset(&ev, 0, sizeof(ev));
1123 ev.conn_id = conn_info->connection_id;
1124 ev.trans_id = req_id;
1125 ev.att_handle = char_hdl;
1127 ev.is_long = false; /* TODO*/
1129 /* Convert address to hex */
1130 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1131 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1133 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1134 GVariant *var = NULL;
1138 gboolean response_needed = FALSE;
1139 struct hal_ev_gatt_server_write_req ev;
1143 struct gatt_service_info *svc_info = NULL;
1144 struct gatt_req_info *req_info = NULL;
1145 struct gatt_client_info_t *conn_info = NULL;
1147 memset(&ev, 0, sizeof(ev));
1150 DBG("Application path = %s", object_path);
1151 DBG("Sender = %s", sender);
1153 g_variant_get(parameters, "(&suqb@ay)",
1154 &addr, &req_id, &offset, &response_needed, &var);
1155 DBG("Request id = %u, Offset = %u", req_id, offset);
1157 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1159 /* Check if device is already in connected list */
1160 conn_info = __bt_find_remote_gatt_client_info(addr);
1162 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1163 g_variant_unref(var);
1164 if (response_needed)
1165 g_dbus_method_invocation_return_value(invocation, NULL);
1167 g_object_unref(invocation);
1171 len = g_variant_get_size(var);
1172 if (len > 0 && len < 600) {
1174 data = (char *)g_variant_get_data(var);
1175 memcpy(ev.value, data, len);
1179 if (response_needed) {
1180 /* Store requets information */
1181 req_info = g_new0(struct gatt_req_info, 1);
1182 req_info->attr_path = g_strdup(object_path);
1183 req_info->svc_path = g_strdup(svc_info->serv_path);
1184 req_info->request_id = req_id;
1185 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1186 req_info->offset = offset;
1187 req_info->context = invocation;
1189 /* Append request info in list of requests for the particular connection */
1190 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1193 g_object_unref(invocation);
1196 /* Send HAL event */
1197 ev.conn_id = conn_info->connection_id;
1198 ev.trans_id = req_id;
1199 ev.att_handle = char_hdl;
1201 ev.need_rsp = response_needed;
1204 /* Convert address to hex */
1205 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1207 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1209 g_variant_unref(var);
1212 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1215 struct gatt_service_info *svc_info = NULL;
1216 struct hal_ev_gatt_server_notifcation_change ev;
1219 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1220 if (svc_info == NULL || event_cb == NULL)
1223 /* Send HAL event */
1224 memset(&ev, 0, sizeof(ev));
1225 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1226 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1227 ev.att_handle = char_hdl;
1230 /* Convert address to hex */
1231 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1233 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1236 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1239 struct gatt_service_info *svc_info = NULL;
1240 struct hal_ev_gatt_server_notifcation_change ev;
1243 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1244 if (svc_info == NULL || event_cb == NULL)
1247 /* Send HAL event */
1248 memset(&ev, 0, sizeof(ev));
1249 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1250 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1251 ev.att_handle = char_hdl;
1254 /* Convert address to hex */
1255 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1257 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1260 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1262 gboolean complete = FALSE;
1265 struct gatt_service_info *svc_info = NULL;
1266 struct gatt_client_info_t *conn_info = NULL;
1268 struct hal_ev_gatt_server_indicate_cfm ev;
1270 DBG("IndicateConfirm");
1271 DBG("Application path = %s", object_path);
1272 DBG("Sender = %s", sender);
1274 g_variant_get(parameters, "(&sb)", &addr, &complete);
1275 DBG("Remote Device address number = %s", addr);
1276 DBG("Is Indicate confirmation for last device [%d]", complete);
1278 /* Check if device is already in connected list */
1279 conn_info = __bt_find_remote_gatt_client_info(addr);
1281 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1283 if (svc_info == NULL || conn_info == NULL
1284 || event_cb == NULL) {
1288 /* Send HAL event */
1289 memset(&ev, 0, sizeof(ev));
1290 ev.conn_id = conn_info->connection_id;
1291 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1292 ev.att_handle = char_hdl;
1294 /* Convert address to hex */
1295 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1297 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1298 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1302 struct hal_ev_gatt_server_acquire_write_res ev;
1303 struct gatt_service_info *svc_info = NULL;
1304 struct gatt_req_info *req_info = NULL;
1305 struct gatt_client_info_t *conn_info = NULL;
1306 char * dev_path = NULL;
1308 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1310 DBG("AcquireWrite");
1311 DBG("Application path = %s", object_path);
1312 DBG("Sender = %s", sender);
1315 g_variant_get(parameters, "(a{sv})", &iter);
1317 GVariant* value = NULL;
1318 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1319 if (g_strcmp0(key, "MTU") == 0)
1320 g_variant_get(value, "i", &mtu);
1321 else if (g_strcmp0(key, "link") == 0)
1322 g_variant_get(value, "s", &link);
1323 else if (g_strcmp0(key, "device") == 0)
1324 g_variant_get(value, "o", &dev_path);
1327 DBG("AcquireWrite values retived");
1328 DBG(" path %s LINK = %s, MTU = %u", addr, link, mtu);
1330 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1332 _bt_hal_convert_device_path_to_address(dev_path, addr);
1334 DBG("remote address %s", addr);
1336 /* Check if device is already in connected list */
1337 conn_info = __bt_find_remote_gatt_client_info(addr);
1339 if (conn_info == NULL) {
1340 ERR("Cleint info not found\n");
1344 if (svc_info == NULL) {
1345 ERR("svc_info info not found\n");
1349 /* Store requets information */
1350 req_info = g_new0(struct gatt_req_info, 1);
1351 req_info->attr_path = g_strdup(object_path);
1352 req_info->svc_path = g_strdup(svc_info->serv_path);
1353 req_info->request_id = conn_info->connection_id;
1354 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1355 req_info->offset = mtu;
1356 req_info->context = invocation;
1358 /* Append request info in list of requests for the particular connection */
1359 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1361 /* Send HAL event */
1362 memset(&ev, 0, sizeof(ev));
1363 ev.conn_id = conn_info->connection_id;
1364 ev.char_handl = char_hdl;
1366 ev.trans_id = conn_info->connection_id;
1367 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1368 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1370 DBG("HAL_EV_GATT_ACQUIRE_WRITE_RES called");
1374 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1378 struct hal_ev_gatt_server_acquire_notify ev;
1379 struct gatt_service_info *svc_info = NULL;
1380 struct gatt_client_info_t *conn_info = NULL;
1381 struct gatt_req_info *req_info = NULL;
1383 DBG("AcquireNotify");
1384 DBG("Application path = %s", object_path);
1385 DBG("Sender = %s", sender);
1388 g_variant_get(parameters, "(a{sv})", &iter);
1390 GVariant* value = NULL;
1391 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1392 if (g_strcmp0(key, "MTU") == 0)
1393 g_variant_get(value, "q", &mtu);
1396 DBG("AcquireNotify values retived");
1397 DBG(" MTU = %u", mtu);
1399 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1401 if (svc_info == NULL) {
1402 ERR("svc_info info not found\n");
1406 /* Store requets information */
1407 req_info = g_new0(struct gatt_req_info, 1);
1408 req_info->attr_path = g_strdup(object_path);
1409 req_info->svc_path = g_strdup(svc_info->serv_path);
1410 req_info->request_id = 33;
1411 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1412 req_info->offset = mtu;
1413 req_info->context = invocation;
1415 conn_info = g_new0(struct gatt_client_info_t, 1);
1416 conn_info->addr = g_strdup(object_path);
1417 INFO("Added GATT client path[%s]", conn_info->addr);
1418 conn_info->connection_id = 33;
1419 conn_info->instance_id = 33;
1420 /* Append request info in list of requests for the particular connection */
1421 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1422 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1424 /* Send HAL event */
1425 memset(&ev, 0, sizeof(ev));
1427 ev.char_handl = char_hdl;
1431 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1433 DBG("HAL_EV_GATT_ACQUIRE_NOTIFY_RES called");
1439 g_dbus_method_invocation_return_value(invocation, NULL);
1442 static gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1445 GError *error = NULL;
1446 GVariantBuilder *array_builder;
1448 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1449 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1450 g_variant_builder_add(array_builder, "s", interface);
1452 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1453 "org.freedesktop.Dbus.Objectmanager",
1454 "InterfacesRemoved",
1455 g_variant_new("(oas)",
1456 object_path, array_builder),
1460 if (error != NULL) {
1461 /* dbus gives error cause */
1462 ERR("d-bus api failure: errcode[%x], message[%s]",
1463 error->code, error->message);
1464 g_clear_error(&error);
1467 g_variant_builder_unref(array_builder);
1472 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1479 g_free(desc_info->desc_path);
1480 g_free(desc_info->desc_uuid);
1481 g_free(desc_info->desc_value);
1483 for (i = 0; i < desc_info->flags_length; i++)
1484 g_free(desc_info->desc_flags[i]);
1489 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1496 g_free(char_info->char_path);
1497 g_free(char_info->char_uuid);
1498 g_free(char_info->char_value);
1500 for (i = 0; i < char_info->flags_length; i++)
1501 g_free(char_info->char_flags[i]);
1507 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1512 g_free(svc_info->serv_path);
1513 g_free(svc_info->service_uuid);
1517 static const GDBusInterfaceVTable desc_interface_vtable = {
1518 __bt_gatt_desc_method_call,
1523 static const GDBusInterfaceVTable char_interface_vtable = {
1524 __bt_gatt_char_method_call,
1529 static const GDBusInterfaceVTable serv_interface_vtable = {
1535 static const GDBusInterfaceVTable manager_interface_vtable = {
1536 __bt_gatt_manager_method_call,
1542 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1543 const gchar *introspection_data)
1546 GDBusNodeInfo *node_info = NULL;
1548 if (introspection_data == NULL)
1552 DBG("Create new node info");
1553 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1556 ERR("Unable to create node: %s", err->message);
1557 g_clear_error(&err);
1564 /* To send stack event to hal-av handler */
1565 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1570 void _bt_hal_unregister_gatt_server_handler_cb(void)
1575 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1577 struct hal_ev_gatt_desc_added ev;
1578 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1580 /* Prepare to GATT characteristic added event */
1581 memset(&ev, 0, sizeof(ev));
1582 ev.status = BT_STATUS_SUCCESS;
1583 ev.server_instance = data->instance_data;
1584 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1585 ev.service_handle = data->srvc_hdl;
1586 ev.desc_handle = data->desc_hdl;
1589 ERR("GATT Descriptor Added callback registered");
1591 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1592 data->instance_data, data->srvc_hdl, data->desc_hdl);
1594 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1601 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1603 struct hal_ev_gatt_char_added ev;
1604 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1606 /* Prepare to GATT characteristic added event */
1607 memset(&ev, 0, sizeof(ev));
1608 ev.status = BT_STATUS_SUCCESS;
1609 ev.server_instance = data->instance_data;
1610 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1611 ev.service_handle = data->srvc_hdl;
1612 ev.char_handle = data->char_hdl;
1615 ERR("GATT Characteristic Added callback registered");
1617 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1618 data->instance_data, data->srvc_hdl, data->char_hdl);
1620 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1627 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1629 struct hal_ev_gatt_service_added ev;
1630 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1632 /* Prepare to GATT Service added event */
1633 memset(&ev, 0, sizeof(ev));
1634 ev.status = BT_STATUS_SUCCESS;
1635 ev.server_instance = data->instance_data;
1636 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1637 ev.service_handle = data->srvc_hdl;
1638 ev.is_primary = data->is_primary;
1641 ERR("GATT Service Added callback registered");
1643 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1644 data->instance_data, data->srvc_hdl);
1645 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1652 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1654 struct hal_ev_gatt_service_started ev;
1655 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1657 /* Prepare to GATT Service added event */
1658 memset(&ev, 0, sizeof(ev));
1659 ev.status = BT_STATUS_SUCCESS;
1660 ev.server_instance = data->instance_data;
1661 ev.service_handle = data->srvc_hdl;
1664 ERR("GATT Service Started callback registered");
1666 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1667 data->instance_data, data->srvc_hdl);
1668 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1675 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1677 struct hal_ev_gatt_service_deleted ev;
1678 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1680 /* Prepare to GATT Service added event */
1681 memset(&ev, 0, sizeof(ev));
1682 ev.status = BT_STATUS_SUCCESS;
1683 ev.server_instance = data->instance_data;
1684 ev.service_handle = data->srvc_hdl;
1687 ERR("GATT Service Deleted callback registered");
1689 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1690 data->instance_data, data->srvc_hdl);
1691 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1698 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1700 struct hal_ev_server_instance_registered ev;
1701 hal_register_server_data *data = (hal_register_server_data*) user_data;
1703 /* Prepare to send AV connecting event */
1704 memset(&ev, 0, sizeof(ev));
1705 ev.status = BT_STATUS_SUCCESS;
1706 ev.server_instance = data->instance_data;
1707 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1710 ERR("GATT Register Server Instance Callback not registered");
1712 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1713 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1720 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1722 CHECK_BTGATT_INIT();
1723 int status = BT_STATUS_FAIL;
1725 DBG("Register server instance request");
1726 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1728 /* Check if slot available */
1729 server_if = _bt_hal_get_available_adv_slot_id(uuid);
1731 if (server_if == -1) {
1732 ERR("Allocation of server instance failed");
1736 user_data->instance_data = server_if;
1737 DBG("Allocated new Advertising slot with Stack [%d]", user_data->instance_data);
1741 * As we need to provide async callback to user from HAL, simply schedule a
1742 * callback method which will carry actual result
1744 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1745 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1747 /* If available, then return success, else return error */
1748 return BT_STATUS_SUCCESS;
1751 static void _bt_hal_remove_gatt_server_from_list(int server_if)
1754 struct gatt_server_app *info = NULL;
1756 for (l = gatt_server_apps; l != NULL;) {
1757 info = (struct gatt_server_app*)l->data;
1758 l = g_slist_next(l);
1761 if (info->slot == server_if) {
1762 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1763 info->app_path, info->slot);
1765 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1766 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1767 In above case, only advertising block will be deallocated, Gatt Server will remain
1769 if (info->services == NULL) {
1770 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1771 INFO("Total gatt server apps still existing after removing above is [%d]",
1772 g_slist_length(gatt_server_apps));
1774 /* DBUS Unregister only for current app */
1775 __bt_hal_gatt_deinit(info->app_path);
1777 g_free(info->app_path);
1781 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1782 g_slist_length(info->services));
1788 static bt_status_t gatt_server_unregister_app(int server_if)
1790 CHECK_BTGATT_INIT();
1791 DBG("Un-Register server instance request [%d]", server_if);
1793 if (_bt_hal_is_advertising_in_slot(server_if) == FALSE)
1794 _bt_hal_free_server_slot(server_if);
1796 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
1797 _bt_hal_remove_gatt_server_from_list(server_if);
1798 return BT_STATUS_SUCCESS;
1801 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
1803 CHECK_BTGATT_INIT();
1804 return BT_STATUS_SUCCESS;
1807 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
1810 GError *g_error = NULL;
1811 GVariant *reply = NULL;
1815 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
1816 g_object_unref(proxy);
1817 if (reply == NULL) {
1818 ERR("Disconnect LE Dbus Call Error");
1820 ERR("Error: %s\n", g_error->message);
1821 g_clear_error(&g_error);
1824 g_variant_unref(reply);
1828 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
1830 CHECK_BTGATT_INIT();
1832 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
1834 GDBusProxy *device_proxy;
1835 GDBusConnection *g_conn;
1836 struct gatt_client_info_t *conn_info = NULL;
1840 if (NULL == bd_addr) {
1841 ERR("bd_addr is NULL");
1842 return BT_STATUS_PARM_INVALID;
1845 /* GDBUS Connection Info validate */
1846 g_conn = _bt_hal_get_system_gconn();
1847 if (g_conn == NULL) {
1848 ERR("Could not get System DBUS Connection");
1849 return BT_STATUS_FAIL;
1852 /* Connection Info validate */
1853 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
1854 if (conn_info == NULL) {
1855 ERR("No Connection Inforamtion!!!");
1856 return BT_STATUS_FAIL;
1859 _bt_hal_convert_addr_type_to_string(device_address,
1860 (unsigned char *)bd_addr->address);
1862 //check if connection has the same device address
1863 if (g_strcmp0(conn_info->addr, device_address) != 0) {
1864 ERR("device address [%s] does not match", device_address);
1865 return BT_STATUS_FAIL;
1868 device_path = _bt_hal_get_device_object_path(conn_info->addr);
1869 if (device_path == NULL) {
1870 ERR("device_path is NULL");
1871 return BT_STATUS_PARM_INVALID;
1874 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
1875 NULL, BT_HAL_BLUEZ_NAME,
1876 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
1879 g_free(device_path);
1880 if (device_proxy == NULL)
1881 return BT_STATUS_FAIL;
1883 INFO("Disconnect LE [%s]", device_address);
1885 g_dbus_proxy_call(device_proxy, "DisconnectLE",
1887 G_DBUS_CALL_FLAGS_NONE,
1888 BT_HAL_MAX_DBUS_TIMEOUT,
1890 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
1893 return BT_STATUS_SUCCESS;
1896 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
1901 uuid = btuuid2str(srvc_id->uu);
1902 DBG("Original UUID [%s]", uuid);
1904 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
1905 /* Extract Standard UUID string */
1906 memcpy(uuid_buf, &uuid[4], 4);
1908 DBG("Converted string [%s]", uuid_buf);
1909 return g_strdup(uuid_buf);
1911 return strdup(uuid);
1914 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
1917 /* For GATT service specific */
1918 GDBusNodeInfo *node_info;
1921 struct gatt_service_info *serv_info = NULL;
1922 GVariantBuilder *builder = NULL;
1923 GVariantBuilder *builder1 = NULL;
1924 GVariantBuilder *inner_builder = NULL;
1925 gboolean svc_primary = TRUE;
1926 GError *error = NULL;
1927 hal_gatt_service_added *user_data = NULL;
1928 DBG("Service add to DBUS slot [%d]", slot);
1930 node_info = __bt_gatt_create_method_node_info(
1931 service_introspection_xml);
1933 if (node_info == NULL)
1934 return BT_STATUS_FAIL;
1936 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
1937 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
1938 DBG("gatt service path is [%s]", path);
1940 object_id = g_dbus_connection_register_object(g_conn, path,
1941 node_info->interfaces[0],
1942 &serv_interface_vtable,
1943 NULL, NULL, &error);
1945 if (object_id == 0) {
1946 ERR("failed to register: %s", error->message);
1947 g_error_free(error);
1949 return BT_STATUS_FAIL;
1951 /* Add object_id/gatt service information; it's required at the time of
1952 * service unregister and Getmanagedobjects
1954 serv_info = g_new0(struct gatt_service_info, 1);
1956 serv_info->serv_path = g_strdup(path);
1957 serv_info->serv_id = object_id;
1958 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
1959 serv_info->is_svc_registered = FALSE;
1960 serv_info->is_svc_primary = svc_primary;
1961 DBG("Service Handle to be added is [%d]", gatt_service_handle);
1962 serv_info->service_handle = gatt_service_handle;
1964 /* Update service in GATT Server service List */
1965 gatt_services = g_slist_append(gatt_services, serv_info);
1967 /* emit interfacesadded signal here for service path */
1968 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1969 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1971 g_variant_builder_add(inner_builder, "{sv}",
1972 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
1974 g_variant_builder_add(inner_builder, "{sv}",
1975 "Primary", g_variant_new_boolean(svc_primary));
1977 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1979 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1980 g_variant_new("ao", builder1));
1982 g_variant_builder_add(builder, "{sa{sv}}",
1983 GATT_SERV_INTERFACE, inner_builder);
1985 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1986 "org.freedesktop.Dbus.ObjectManager",
1988 g_variant_new("(oa{sa{sv}})",
1993 /* dbus gives error cause */
1994 ERR("d-bus api failure: errcode[%x], message[%s]",
1995 error->code, error->message);
1996 g_clear_error(&error);
2000 /* Send Service handle to application */
2001 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2002 user_data->srvc_hdl = serv_info->service_handle;
2003 user_data->instance_data = slot;
2004 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2005 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2007 /* Save newly created service in GATT Server's service list */
2008 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2012 g_variant_builder_unref(inner_builder);
2013 g_variant_builder_unref(builder);
2014 g_variant_builder_unref(builder1);
2015 return BT_STATUS_SUCCESS;
2018 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2021 char *app_path = (char*)user_data;
2022 INFO("UnregisterApplication is completed app [%s]", app_path);
2023 GError *error = NULL;
2024 GVariant *result = NULL;
2027 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2029 if (result == NULL) {
2030 /* dBUS-RPC is failed */
2031 ERR("Dbus-RPC is failed\n");
2033 if (error != NULL) {
2034 /* dBUS gives error cause */
2035 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2036 error->code, error->message);
2037 g_clear_error(&error);
2040 g_variant_unref(result);
2045 static void __bt_hal_gatt_deinit(char *app_path)
2047 GDBusProxy *proxy = NULL;
2051 /* Step1: Remove requested App */
2052 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2053 "/org/bluez/hci0", "org.bluez.GattManager1");
2058 INFO("UnregisterApplication : path [%s]", app_path);
2060 /* Async Call to Unregister Service */
2061 data = g_strdup(app_path);
2062 g_dbus_proxy_call(proxy,
2063 "UnregisterApplication",
2064 g_variant_new("(o)",
2066 G_DBUS_CALL_FLAGS_NONE, -1,
2068 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2071 /* If requested app is last GATT Server app, then clean all resources */
2072 if (gatt_server_apps == NULL) {
2073 INFO("All GATT servers are removed, clean all DBUS resources");
2075 /* unregister the exported interface for object manager */
2076 g_dbus_connection_unregister_object(g_conn, manager_id);
2078 g_bus_unown_name(owner_id);
2081 g_object_unref(manager_gproxy);
2082 manager_gproxy = NULL;
2088 static int __bt_hal_gatt_init(void)
2092 /* Only once for ALL GATT Servers */
2093 if (owner_id == 0) {
2097 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2100 ERR("Unable to connect to gdbus: %s", err->message);
2101 g_clear_error(&err);
2103 return BT_STATUS_FAIL;
2106 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2107 INFO("well-known name: %s", name);
2109 owner_id = g_bus_own_name_on_connection(g_conn, name,
2110 G_BUS_NAME_OWNER_FLAGS_NONE,
2111 NULL, NULL, NULL, NULL);
2113 INFO("Owner ID [%d]", owner_id);
2115 /* Only once for ALL GATT Servers */
2116 if (manager_node_info == NULL) {
2117 /* Register ObjectManager interface */
2118 manager_node_info = __bt_gatt_create_method_node_info(
2119 manager_introspection_xml);
2121 if (manager_node_info == NULL) {
2122 ERR("failed to get node info");
2123 return BT_STATUS_FAIL;
2128 return BT_STATUS_SUCCESS;
2131 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2135 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2136 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2137 if (app->slot == slot) {
2138 INFO("GATT Server app found app path [%s] instance [%d]",
2139 app->app_path, app->slot);
2140 *app_path = app->app_path;
2144 /* GATT Server not found */
2148 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2150 if (app_path == NULL)
2153 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2154 app->app_path = g_strdup(app_path);
2156 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2157 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2162 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2165 CHECK_BTGATT_INIT();
2166 char *app_path = NULL;
2167 GError *error = NULL;
2170 int result = BT_STATUS_SUCCESS;
2172 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2173 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2175 /* Check if this GATT server Application is already registered with DBUS */
2176 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2178 if (app_path != NULL) {
2179 DBG("GATT server path is already defined [%s]", app_path);
2180 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2182 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2183 result = __bt_hal_gatt_init();
2184 if (result != BT_STATUS_SUCCESS)
2187 /* Only once for each GATT Server */
2188 app_path = g_strdup_printf("/com/%d", server_if);
2190 app_id = g_malloc0(sizeof(int));
2191 *app_id = server_if;
2193 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2194 manager_node_info->interfaces[0],
2195 &manager_interface_vtable,
2196 (gpointer)app_id, NULL, &error);
2198 if (manager_id == 0) {
2199 ERR("failed to register: %s", error->message);
2200 g_error_free(error);
2203 INFO("manager_id [%d]", manager_id);
2205 /* For current GATT Server, app_path is created, save it in Table */
2206 _bt_hal_update_gatt_server_path(server_if, app_path);
2208 /* Add GATT Service to DBUS */
2209 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2215 INFO("Successfully added service");
2216 return BT_STATUS_SUCCESS;
2223 INFO("Service addition failed!!");
2224 return BT_STATUS_FAIL;
2227 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2228 int included_handle)
2230 CHECK_BTGATT_INIT();
2231 return BT_STATUS_SUCCESS;
2235 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2238 GSList *gatt_services = NULL;
2240 struct gatt_service_info *info = NULL;
2242 gatt_services = _bt_get_service_list_from_server(instance);
2244 len = g_slist_length(gatt_services);
2245 l = g_slist_nth(gatt_services, len -1);
2251 if (info->service_handle == service_handle)
2256 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2260 GSList *gatt_services = NULL;
2261 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2263 gatt_services = _bt_get_service_list_from_server(instance);
2265 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2266 struct gatt_service_info *info = l->data;
2267 INFO("Got one service with handle [%d]", info->service_handle);
2268 if (info->service_handle == service_handle)
2271 ERR("Gatt service with handle [%d] not found", service_handle);
2275 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2276 bt_uuid_t *uuid, int properties,
2280 GError *error = NULL;
2282 GDBusNodeInfo *node_info;
2284 GVariantBuilder *builder = NULL;
2285 GVariantBuilder *inner_builder = NULL;
2286 struct gatt_service_info *serv_info = NULL;
2287 struct gatt_char_info *char_info = NULL;
2288 GVariantBuilder *builder2 = NULL;
2289 GVariantBuilder *builder3 = NULL;
2290 GVariant *flags_val = NULL;
2292 char *char_flags[NUMBER_OF_FLAGS];
2294 hal_gatt_char_added *user_data = NULL;
2297 CHECK_BTGATT_INIT();
2298 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2299 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2301 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2302 if (serv_info == NULL)
2303 return BT_STATUS_FAIL;
2305 node_info = __bt_gatt_create_method_node_info(
2306 characteristics_introspection_xml);
2308 if (node_info == NULL)
2309 return BT_STATUS_FAIL;
2311 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2312 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2313 DBG("gatt characteristic path is [%s]", path);
2315 app_id = g_malloc0(sizeof(int));
2318 object_id = g_dbus_connection_register_object(g_conn, path,
2319 node_info->interfaces[0],
2320 &char_interface_vtable,
2321 (gpointer)app_id, NULL, &error);
2323 if (object_id == 0) {
2324 ERR("failed to register: %s", error->message);
2325 g_error_free(error);
2328 return BT_STATUS_FAIL;
2331 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2332 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2333 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2334 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2335 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2336 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2337 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2338 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2340 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2342 char_info = g_new0(struct gatt_char_info, 1);
2344 char_info->char_path = g_strdup(path);
2345 char_info->char_id = object_id;
2346 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2347 for (i = 0; i < flag_count; i++)
2348 char_info->char_flags[i] = char_flags[i];
2351 char_info->flags_length = flag_count;
2352 char_info->char_handle = gatt_char_handle;
2355 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2356 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2358 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2359 g_variant_new("s", char_info->char_uuid));
2360 g_variant_builder_add(inner_builder, "{sv}", "Service",
2361 g_variant_new("o", serv_info->serv_path));
2363 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2365 for (i = 0; i < flag_count; i++)
2366 g_variant_builder_add(builder2, "s", char_flags[i]);
2368 flags_val = g_variant_new("as", builder2);
2369 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2372 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2374 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2375 g_variant_new("ao", builder3));
2377 g_variant_builder_add(builder, "{sa{sv}}",
2378 GATT_CHAR_INTERFACE,
2381 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2382 "org.freedesktop.Dbus.ObjectManager",
2384 g_variant_new("(oa{sa{sv}})",
2389 /* dbus gives error cause */
2390 ERR("d-bus api failure: errcode[%x], message[%s]",
2391 error->code, error->message);
2392 g_clear_error(&error);
2396 //*char_path = g_strdup(path);
2401 /* Send Service handle to application */
2402 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2403 user_data->srvc_hdl = serv_info->service_handle;
2404 user_data->char_hdl = gatt_char_handle;
2405 user_data->instance_data = slot;
2406 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2407 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2409 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2410 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2415 g_variant_builder_unref(inner_builder);
2416 g_variant_builder_unref(builder);
2417 g_variant_builder_unref(builder2);
2418 g_variant_builder_unref(builder3);
2420 return BT_STATUS_SUCCESS;
2423 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2426 CHECK_BTGATT_INIT();
2428 // static int desc_id = 1;
2429 GError *error = NULL;
2431 GDBusNodeInfo *node_info;
2433 GVariantBuilder *builder = NULL;
2434 GVariantBuilder *inner_builder = NULL;
2436 struct gatt_char_info *char_info = NULL;
2437 struct gatt_desc_info *desc_info = NULL;
2438 struct gatt_service_info *serv_info = NULL;
2440 gchar **line_argv = NULL;
2442 char *char_path = NULL;
2445 GVariantBuilder *builder2 = NULL;
2446 GVariant *flags_val = NULL;
2448 char *desc_flags[NUMBER_OF_FLAGS];
2452 hal_gatt_desc_added *user_data = NULL;
2459 /* Fetch service data for the GATT server */
2460 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2461 if (serv_info == NULL)
2462 return BT_STATUS_FAIL;
2464 /* Fetch list of characteristics from the service info */
2465 l = serv_info->char_data;
2467 /* Fetch last char info from the characteristic list */
2468 char_info = g_slist_last(l)->data;
2469 if (char_info == NULL)
2470 return BT_STATUS_FAIL;
2472 /* Fetch characteristic path from char info */
2473 char_path = char_info->char_path;
2475 line_argv = g_strsplit_set(char_path, "/", 0);
2476 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2479 node_info = __bt_gatt_create_method_node_info(
2480 descriptor_introspection_xml);
2482 if (node_info == NULL) {
2483 g_strfreev(line_argv);
2485 return BT_STATUS_FAIL;
2488 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2490 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2491 DBG("gatt descriptor path is [%s]", path);
2493 app_id = g_malloc0(sizeof(int));
2496 object_id = g_dbus_connection_register_object(g_conn, path,
2497 node_info->interfaces[0],
2498 &desc_interface_vtable,
2499 (gpointer)app_id, NULL, &error);
2501 if (object_id == 0) {
2502 ERR("failed to register: %s", error->message);
2503 g_error_free(error);
2505 g_strfreev(line_argv);
2508 return BT_STATUS_FAIL;
2511 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2513 desc_info = g_new0(struct gatt_desc_info, 1);
2515 desc_info->desc_path = g_strdup(path);
2516 desc_info->desc_id = object_id;
2517 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2519 for (i = 0; i < flag_count; i++)
2520 desc_info->desc_flags[i] = desc_flags[i];
2522 desc_info->flags_length = flag_count;
2523 desc_info->desc_handle = gatt_desc_handle;
2526 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2527 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2529 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2530 g_variant_new("s", btuuid2str(uuid->uu)));
2531 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2532 g_variant_new("o", char_path));
2534 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2536 for (i = 0; i < flag_count; i++)
2537 g_variant_builder_add(builder2, "s", desc_flags[i]);
2539 flags_val = g_variant_new("as", builder2);
2540 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2543 g_variant_builder_add(builder, "{sa{sv}}",
2544 GATT_DESC_INTERFACE,
2547 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2548 "org.freedesktop.Dbus.ObjectManager",
2550 g_variant_new("(oa{sa{sv}})",
2553 if (error != NULL) {
2554 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2555 error->code, error->message);
2556 g_clear_error(&error);
2559 //*desc_path = g_strdup(path);
2561 /* Save newly created descriptor to GATT server's service's characteristic */
2562 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2564 /* Send descriptor handle to application */
2565 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2566 user_data->srvc_hdl = serv_info->service_handle;
2567 user_data->desc_hdl = gatt_desc_handle;
2568 user_data->instance_data = slot;
2569 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2570 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2575 g_strfreev(line_argv);
2576 g_variant_builder_unref(inner_builder);
2577 g_variant_builder_unref(builder);
2578 return BT_STATUS_SUCCESS;
2581 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2583 GError *error = NULL;
2585 char *data = (char*) user_data;
2586 INFO("RegisterApplication is completed path [%s]", data);
2588 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2590 if (result == NULL) {
2591 /* dBUS-RPC is failed */
2592 ERR("Dbus-RPC is failed\n");
2594 if (error != NULL) {
2595 /* dBUS gives error cause */
2596 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2597 error->code, error->message);
2598 g_clear_error(&error);
2601 g_variant_unref(result);
2606 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2607 const gchar *path, const gchar *interface)
2613 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2618 ERR("Unable to connect to gdbus: %s", err->message);
2619 g_clear_error(&err);
2624 proxy = g_dbus_proxy_new_sync(g_conn,
2625 G_DBUS_PROXY_FLAGS_NONE, NULL,
2627 interface, NULL, &err);
2631 ERR("Unable to create proxy: %s", err->message);
2632 g_clear_error(&err);
2636 manager_gproxy = proxy;
2641 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2642 const gchar *path, const gchar *interface)
2644 return (manager_gproxy) ? manager_gproxy :
2645 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2649 static void __bt_register_application_to_dbus(int slot)
2651 GDBusProxy *proxy = NULL;
2652 char *app_path = NULL;
2654 DBG("RegisterApplication slot [%d]", slot);
2656 /* It is impossible that app path is still not initialized */
2657 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2659 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2660 "/org/bluez/hci0", "org.bluez.GattManager1");
2662 data = g_strdup(app_path);
2663 g_dbus_proxy_call(proxy,
2664 "RegisterApplication",
2665 g_variant_new("(oa{sv})",
2667 G_DBUS_CALL_FLAGS_NONE, -1,
2669 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2671 INFO("GATT server started");
2674 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2676 CHECK_BTGATT_INIT();
2677 struct gatt_service_info *serv_info = NULL;
2678 hal_gatt_service_started *user_data = NULL;
2679 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2681 /* Fetch service data for the GATT server */
2682 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2683 if (serv_info == NULL)
2684 return BT_STATUS_FAIL;
2686 if (serv_info->is_svc_registered)
2687 DBG("service already registered \n");
2689 serv_info->is_svc_registered = TRUE;
2691 /* Send Service handle to application */
2692 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2693 user_data->srvc_hdl = serv_info->service_handle;
2694 user_data->instance_data = server_if;
2695 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2697 /* If this is nth Service that is started, then register application at this point */
2698 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2699 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2701 __bt_register_application_to_dbus(server_if);
2704 return BT_STATUS_SUCCESS;
2707 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2709 CHECK_BTGATT_INIT();
2710 INFO("Stop service successful");
2711 return BT_STATUS_SUCCESS;
2714 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2716 CHECK_BTGATT_INIT();
2717 struct gatt_service_info *serv_info = NULL;
2718 hal_gatt_service_deleted *user_data = NULL;
2721 int err = BT_STATUS_SUCCESS;
2722 int ret = BT_STATUS_SUCCESS;
2723 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2725 /* Fetch service data for the GATT server */
2726 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2727 if (serv_info == NULL) {
2728 ERR("Could not find service info svc handle [%d] server slot [%d]",
2729 service_handle, server_if);
2730 return BT_STATUS_FAIL;
2733 if (serv_info->is_svc_registered == FALSE) {
2734 ERR("service Not registered path [%s] handle [%d]",
2735 serv_info->serv_path, service_handle);
2738 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2739 struct gatt_char_info *char_info = l->data;
2741 if (char_info == NULL)
2744 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2745 struct gatt_desc_info *desc_info = l1->data;
2747 if (desc_info == NULL)
2750 ret = g_dbus_connection_unregister_object(g_conn,
2751 desc_info->desc_id);
2753 __bt_hal_gatt_emit_interface_removed(
2754 desc_info->desc_path,
2755 GATT_DESC_INTERFACE);
2757 err = BT_STATUS_FAIL;
2760 /* list remove & free */
2761 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2762 __bt_hal_gatt_free_descriptor_info(desc_info);
2765 g_slist_free(char_info->desc_data);
2766 char_info->desc_data = NULL;
2768 ret = g_dbus_connection_unregister_object(g_conn,
2769 char_info->char_id);
2771 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2772 GATT_CHAR_INTERFACE);
2775 err = BT_STATUS_FAIL;
2778 /* list remove & free */
2779 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2780 __bt_hal_gatt_free_characteristic_info(char_info);
2783 g_slist_free(serv_info->char_data);
2784 serv_info->char_data = NULL;
2786 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2788 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2789 GATT_SERV_INTERFACE);
2792 err = BT_STATUS_FAIL;
2795 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
2797 DBG("Unregistered the service on properties interface");
2799 /* Remove from global list */
2800 gatt_services = g_slist_remove(gatt_services, serv_info);
2801 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
2803 /* Remove from GATT Server's list of services */
2804 _bt_remote_service_from_gatt_server(server_if, service_handle);
2806 if (gatt_services == NULL)
2807 INFO("All GATT Services of all GATT Servers are unregistered");
2809 if (err == BT_STATUS_SUCCESS) {
2810 INFO("Send GATT Service deleted Event");
2811 /* Send Service handle to application */
2812 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
2813 user_data->srvc_hdl = serv_info->service_handle;
2814 user_data->instance_data = server_if;
2815 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
2818 /* Free the service */
2819 __bt_hal_gatt_free_service_info(serv_info);
2823 static gboolean __bt_gatt_get_service_state(const char *service_path)
2825 struct gatt_service_info *svc_info = NULL;
2827 for (l = gatt_services; l; l = g_slist_next(l)) {
2829 svc_info = (struct gatt_service_info *)l->data;
2832 if (!g_strcmp0(svc_info->serv_path, service_path)) {
2833 DBG("Return the state of the gatt service %d",
2834 svc_info->is_svc_registered);
2835 return svc_info->is_svc_registered;
2839 DBG("gatt service info is NULL");
2843 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
2844 int len, int confirm, char* p_value)
2846 CHECK_BTGATT_INIT();
2849 GVariantBuilder *outer_builder;
2850 GVariantBuilder *invalidated_builder;
2852 /* For Value update via PropertyChange */
2853 GVariantBuilder *outer_builder1;
2854 GVariantBuilder *inner_builder1;
2855 GVariantBuilder *invalidated_builder1;
2856 GVariant *update_value = NULL;
2858 /* Other variables */
2859 struct gatt_client_info_t *conn_info = NULL;
2860 gchar *serv_path = NULL;
2861 char *char_path = NULL;
2862 gchar **line_argv = NULL;
2863 gboolean notify = TRUE;
2864 gboolean ret = TRUE;
2865 int err = BT_STATUS_SUCCESS;
2867 GError *error = NULL;
2870 memset(addr, 0x00, sizeof(addr));
2872 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2873 if (conn_info == NULL) {
2874 ERR("No Connection Inforamtion!!!");
2875 return BT_STATUS_FAIL;
2878 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
2880 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
2881 if (char_path == NULL)
2882 return BT_STATUS_FAIL;
2884 line_argv = g_strsplit_set(char_path, "/", 0);
2885 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2887 if (!__bt_gatt_get_service_state(serv_path)) {
2888 DBG("service not registered for this characteristic \n");
2890 g_strfreev(line_argv);
2891 return BT_STATUS_FAIL;
2894 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2895 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2897 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2898 g_variant_new("b", notify));
2900 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
2901 DBG("Send Indication to Unicast addr [%s]", addr);
2903 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2904 g_variant_new("s", addr));
2906 DBG("Set characteristic Notification \n");
2907 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2909 "org.freedesktop.DBus.Properties",
2910 "PropertiesChanged",
2911 g_variant_new("(sa{sv}as)",
2912 "org.bluez.GattCharacteristic1",
2913 outer_builder, invalidated_builder),
2917 if (error != NULL) {
2918 ERR("D-Bus API failure: errCode[%x], \
2920 error->code, error->message);
2921 g_clear_error(&error);
2923 err = BT_STATUS_FAIL;
2926 g_variant_builder_unref(outer_builder);
2927 g_variant_builder_unref(invalidated_builder);
2930 /* Notifying Done, now update Value to Bluez via PropertyChanged */
2931 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2933 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2934 for (i = 0; i < len; i++)
2935 g_variant_builder_add(inner_builder1, "y", p_value[i]);
2937 update_value = g_variant_new("ay", inner_builder1);
2940 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2941 g_variant_builder_add(outer_builder1, "{sv}", "Value",
2944 DBG("Updating characteristic value \n");
2945 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2947 "org.freedesktop.DBus.Properties",
2948 "PropertiesChanged",
2949 g_variant_new("(sa{sv}as)",
2950 "org.bluez.GattCharacteristic1",
2951 outer_builder1, invalidated_builder1),
2955 if (error != NULL) {
2956 ERR("D-Bus API failure: errCode[%x], \
2958 error->code, error->message);
2959 g_clear_error(&error);
2961 err = BT_STATUS_FAIL;
2963 struct gatt_char_info *char_info = NULL;
2965 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
2966 if (char_info == NULL) {
2968 g_strfreev(line_argv);
2969 g_variant_builder_unref(inner_builder1);
2970 g_variant_builder_unref(outer_builder1);
2971 g_variant_builder_unref(invalidated_builder1);
2973 return BT_STATUS_FAIL;
2976 char_info->value_length = len;
2978 char_info->char_value = (char *)realloc(char_info->char_value, len);
2979 if (char_info->char_value) {
2980 for (i = 0; i < len; i++)
2981 char_info->char_value[i] = p_value[i];
2986 g_strfreev(line_argv);
2987 g_variant_builder_unref(inner_builder1);
2988 g_variant_builder_unref(outer_builder1);
2989 g_variant_builder_unref(invalidated_builder1);
2994 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
2995 int status, btgatt_response_t *response)
2997 CHECK_BTGATT_INIT();
2999 struct gatt_req_info *req_info = NULL;
3000 struct gatt_client_info_t *conn_info = NULL;
3003 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3005 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3006 if (conn_info == NULL) {
3007 ERR("No Connection Inforamtion!!!");
3008 return BT_STATUS_FAIL;
3011 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3012 if (req_info == NULL) {
3013 ERR("No Request Inforamtion!!!");
3014 return BT_STATUS_FAIL;
3017 if (status != BT_STATUS_SUCCESS) {
3018 ERR("resp_state is 0x%X", status);
3020 g_dbus_method_invocation_return_dbus_error(req_info->context,
3021 "org.bluez.Error.Failed", "Application Error");
3023 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3025 req_info->context = NULL;
3026 if (req_info->attr_path)
3027 g_free(req_info->attr_path);
3028 if (req_info->svc_path)
3029 g_free(req_info->svc_path);
3032 return BT_STATUS_SUCCESS;
3035 DBG("Reponse Value length [%d]", response->attr_value.len);
3036 DBG("Request type: [%d]", req_info->request_type);
3039 for (i = 0; i < response->attr_value.len; i++)
3040 DBG("Resonse [%d] = [0x%x]", i, response->attr_value.value[i]);
3042 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3043 GVariantBuilder *inner_builder = NULL;
3044 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3046 if (response->attr_value.len > 0) {
3047 for (i = 0; i < response->attr_value.len; i++)
3048 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3050 g_dbus_method_invocation_return_value(req_info->context,
3051 g_variant_new("(ay)", inner_builder));
3053 g_variant_builder_unref(inner_builder);
3055 g_dbus_method_invocation_return_value(req_info->context, NULL);
3057 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3059 req_info->context = NULL;
3060 if (req_info->attr_path)
3061 g_free(req_info->attr_path);
3062 if (req_info->svc_path)
3063 g_free(req_info->svc_path);
3066 return BT_STATUS_SUCCESS;
3070 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3071 int status, int fd, int mtu, void *fdlist)
3073 CHECK_BTGATT_INIT();
3075 struct gatt_req_info *req_info = NULL;
3076 struct gatt_client_info_t *conn_info = NULL;
3078 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3080 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3081 if (conn_info == NULL) {
3082 ERR("No Connection Inforamtion!!!");
3083 return BT_STATUS_FAIL;
3086 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3087 if (req_info == NULL) {
3088 ERR("No Request Inforamtion!!!");
3089 return BT_STATUS_FAIL;
3092 if (status != BT_STATUS_SUCCESS) {
3093 ERR("resp_state is 0x%X", status);
3095 g_dbus_method_invocation_return_dbus_error(req_info->context,
3096 "org.bluez.Error.Failed", "Application Error");
3098 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3100 req_info->context = NULL;
3101 if (req_info->attr_path)
3102 g_free(req_info->attr_path);
3103 if (req_info->svc_path)
3104 g_free(req_info->svc_path);
3107 return BT_STATUS_SUCCESS;
3111 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3113 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3114 g_dbus_method_invocation_return_value_with_unix_fd_list(
3115 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3117 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3119 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3120 g_dbus_method_invocation_return_value_with_unix_fd_list(
3121 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3124 g_dbus_method_invocation_return_value(req_info->context, NULL);
3126 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3128 req_info->context = NULL;
3129 if (req_info->attr_path)
3130 g_free(req_info->attr_path);
3131 if (req_info->svc_path)
3132 g_free(req_info->svc_path);
3135 return BT_STATUS_SUCCESS;
3139 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3140 int value_length, char* att_value)
3142 CHECK_BTGATT_INIT();
3144 /* Other variables */
3145 char *char_path = NULL;
3146 gboolean ret = TRUE;
3147 GError *error = NULL;
3149 GVariantBuilder *outer_builder;
3150 GVariantBuilder *inner_builder;
3151 GVariantBuilder *invalidated_builder;
3152 GVariant *update_value = NULL;
3153 int err = BT_STATUS_SUCCESS;
3155 gchar **line_argv = NULL;
3156 gchar *serv_path = NULL;
3158 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3159 if (char_path == NULL)
3160 return BT_STATUS_FAIL;
3162 line_argv = g_strsplit_set(char_path, "/", 0);
3163 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3165 if (!__bt_gatt_get_service_state(serv_path)) {
3166 DBG("service not registered for this characteristic \n");
3168 g_strfreev(line_argv);
3169 return BT_STATUS_FAIL;
3173 line_argv = g_strsplit_set(char_path, "/", 0);
3174 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3176 if (!__bt_gatt_get_service_state(serv_path)) {
3177 DBG("service not registered for this characteristic \n");
3179 g_strfreev(line_argv);
3180 return BT_STATUS_FAIL;
3183 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3184 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3186 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3187 for (i = 0; i < value_length; i++)
3188 g_variant_builder_add(inner_builder, "y", att_value[i]);
3190 update_value = g_variant_new("ay", inner_builder);
3192 g_variant_builder_add(outer_builder, "{sv}", "Value",
3195 DBG("Updating characteristic value \n");
3196 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3198 "org.freedesktop.DBus.Properties",
3199 "PropertiesChanged",
3200 g_variant_new("(sa{sv}as)",
3201 "org.bluez.GattCharacteristic1",
3202 outer_builder, invalidated_builder),
3206 if (error != NULL) {
3207 ERR("D-Bus API failure: errCode[%x], \
3209 error->code, error->message);
3210 g_clear_error(&error);
3212 err = BT_STATUS_FAIL;
3214 struct gatt_char_info *char_info = NULL;
3216 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3217 if (char_info == NULL) {
3219 g_strfreev(line_argv);
3220 g_variant_builder_unref(inner_builder);
3221 g_variant_builder_unref(outer_builder);
3222 g_variant_builder_unref(invalidated_builder);
3224 return BT_STATUS_FAIL;
3227 char_info->value_length = value_length;
3229 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3230 if (char_info->char_value) {
3231 for (i = 0; i < value_length; i++)
3232 char_info->char_value[i] = att_value[i];
3238 g_strfreev(line_argv);
3239 g_variant_builder_unref(inner_builder);
3240 g_variant_builder_unref(outer_builder);
3241 g_variant_builder_unref(invalidated_builder);
3246 static bt_status_t gatt_server_listen(int server_if, bool start)
3248 CHECK_BTGATT_INIT();
3249 /* Send Data to LE Module */
3250 return _bt_hal_enable_advertising(server_if, start, FALSE);
3253 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3254 bool include_txpower, int min_interval, int max_interval, int appearance,
3255 uint16_t manufacturer_len, char* manufacturer_data,
3256 uint16_t service_data_len, char* service_data,
3257 uint16_t service_uuid_len, char* service_uuid)
3259 CHECK_BTGATT_INIT();
3260 return BT_STATUS_SUCCESS;
3263 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3265 CHECK_BTGATT_INIT();
3266 /* Send Enable Advertising request to LE Module */
3267 return _bt_hal_enable_advertising(server_if, TRUE, TRUE);
3270 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3271 int chnl_map, int tx_power, int timeout_s)
3273 CHECK_BTGATT_INIT();
3275 /* Send Advertising parameters to LE Module */
3276 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3277 chnl_map, tx_power, timeout_s);
3280 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3282 CHECK_BTGATT_INIT();
3284 /* Send Data to LE Module */
3285 return _bt_hal_set_advertising_data(adv_param_setup);
3288 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3290 CHECK_BTGATT_INIT();
3291 /* Send Data to LE Module */
3292 return _bt_hal_enable_advertising(server_if, FALSE, TRUE);
3295 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3297 CHECK_BTGATT_INIT();
3298 char *object_path = NULL;
3300 GDBusProxy *device_proxy;
3301 GError *error = NULL;
3303 GVariant *tmp_value;
3304 GDBusConnection *conn;
3305 GVariant *result = NULL;
3306 int ret = BT_STATUS_SUCCESS;
3307 struct gatt_client_info_t *conn_info = NULL;
3310 if (mtu_size == NULL)
3311 return BT_STATUS_PARM_INVALID;
3313 /* GDBUS Connection Info validate */
3314 conn = _bt_hal_get_system_gconn();
3316 ERR("Could not get System DBUS Connection");
3317 return BT_STATUS_FAIL;
3320 /* Connection Info validate */
3321 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3322 if (conn_info == NULL) {
3323 ERR("No Connection Inforamtion!!!");
3324 return BT_STATUS_FAIL;
3328 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3329 if (object_path == NULL)
3330 return BT_STATUS_FAIL;
3332 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3333 NULL, BT_HAL_BLUEZ_NAME, object_path,
3334 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3336 g_free(object_path);
3337 if (device_proxy == NULL)
3338 return BT_STATUS_FAIL;
3340 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3341 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3342 G_DBUS_CALL_FLAGS_NONE,
3346 if (result == NULL) {
3347 if (error != NULL) {
3348 ERR("Error occured in Proxy call [%s]\n", error->message);
3349 g_error_free(error);
3351 g_object_unref(device_proxy);
3352 return BT_STATUS_FAIL;
3355 g_variant_get(result , "(@a{sv})", &value);
3356 g_variant_unref(result);
3358 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3359 if (tmp_value == NULL) {
3360 g_object_unref(device_proxy);
3361 g_variant_unref(value);
3362 return BT_STATUS_FAIL;
3365 mtu = g_variant_get_uint16(tmp_value);
3367 DBG("ATT MTU : [%d]", mtu);
3369 g_variant_unref(tmp_value);
3370 g_variant_unref(value);
3371 g_object_unref(device_proxy);
3373 *mtu_size = (int) mtu;
3378 const btgatt_server_interface_t btgatt_server_interface = {
3379 .register_server = gatt_server_register_app,
3380 .unregister_server = gatt_server_unregister_app,
3381 .connect = gatt_server_open,
3382 .disconnect = gatt_server_close,
3383 .add_service = gatt_server_add_service,
3384 .add_included_service = gatt_server_add_included_service,
3385 .add_characteristic = gatt_server_add_characteristic,
3386 .add_descriptor = gatt_server_add_descriptor,
3387 .start_service = gatt_server_start_service,
3388 .stop_service = gatt_server_stop_service,
3389 .delete_service = gatt_server_delete_service,
3390 .send_indication = gatt_server_send_indication,
3391 .send_response = gatt_server_send_response,
3392 .update_att_value = gatt_server_update_att_value,
3393 .listen = gatt_server_listen,
3394 .set_adv_data = gatt_server_set_adv_data,
3395 .multi_adv_enable = gatt_server_multi_adv_enable,
3396 .multi_adv_update = gatt_server_multi_adv_update,
3397 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3398 .multi_adv_disable = gatt_server_multi_adv_disable,
3399 .get_att_mtu = gatt_server_get_mtu_size,
3400 .send_response_acquire = gatt_server_send_acquire_response