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->offset = offset;
966 req_info->context = invocation;
968 /* Append request info in list of requests for the particular connection */
969 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
972 memset(&ev, 0, sizeof(ev));
973 ev.conn_id = conn_info->connection_id;
974 ev.trans_id = req_id;
975 ev.att_handle = desc_hdl;
977 ev.is_long = false; /* TODO*/
979 /* Convert address to hex */
980 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
982 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
984 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
986 GVariant *var = NULL;
990 gboolean response_needed = FALSE;
991 struct hal_ev_gatt_server_write_req ev;
995 struct gatt_service_info *svc_info = NULL;
996 struct gatt_client_info_t *conn_info = NULL;
997 struct gatt_req_info *req_info = NULL;
999 memset(&ev, 0, sizeof(ev));
1002 DBG("Application path = %s", object_path);
1003 DBG("Sender = %s", sender);
1005 g_variant_get(parameters, "(&suqb@ay)",
1006 &addr, &req_id, &offset, &response_needed, &var);
1007 DBG("Request id = %u, Offset = %u", req_id, offset);
1009 /* Check if device is already in connected list */
1010 conn_info = __bt_find_remote_gatt_client_info(addr);
1012 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1014 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1015 g_variant_unref(var);
1016 if (response_needed)
1017 g_dbus_method_invocation_return_value(invocation, NULL);
1019 g_object_unref(invocation);
1023 len = g_variant_get_size(var);
1024 if (len > 0 && len < 600) {
1026 data = (char *)g_variant_get_data(var);
1027 memcpy(ev.value, data, len);
1030 if (response_needed) {
1031 /* Store request information */
1032 req_info = g_new0(struct gatt_req_info, 1);
1033 req_info->attr_path = g_strdup(object_path);
1034 req_info->svc_path = g_strdup(svc_info->serv_path);
1035 req_info->request_id = req_id;
1036 req_info->offset = offset;
1037 req_info->context = invocation;
1039 /* Append request info in list of requests for the particular connection */
1040 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1042 g_object_unref(invocation);
1045 /* Send HAL event */
1046 ev.conn_id = conn_info->connection_id;
1047 ev.trans_id = req_id;
1048 ev.att_handle = desc_hdl;
1050 ev.need_rsp = response_needed;
1053 /* Convert address to hex */
1054 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1056 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1058 g_variant_unref(var);
1063 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1064 const gchar *sender,
1065 const gchar *object_path,
1066 const gchar *interface_name,
1067 const gchar *method_name,
1068 GVariant *parameters,
1069 GDBusMethodInvocation *invocation,
1072 if (g_strcmp0(method_name, "ReadValue") == 0) {
1076 struct hal_ev_gatt_server_read_req ev;
1079 struct gatt_req_info *req_info = NULL;
1080 struct gatt_client_info_t *conn_info = NULL;
1081 struct gatt_service_info *svc_info = NULL;
1083 g_variant_get(parameters, "(&suq)",
1084 &addr, &req_id, &offset);
1086 DBG("Request id = %u, Offset = %u", req_id, offset);
1087 DBG("Application path = %s", object_path);
1088 DBG("Sender = %s", sender);
1089 DBG("Address = %s", addr);
1091 /* Check if device is already in connected list */
1092 conn_info = __bt_find_remote_gatt_client_info(addr);
1094 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1096 if (svc_info == NULL || conn_info == NULL) {
1097 g_dbus_method_invocation_return_value(invocation, NULL);
1102 ERR("GATT callback NOT registered");
1103 g_dbus_method_invocation_return_value(invocation, NULL);
1107 /* Store requets information */
1108 req_info = g_new0(struct gatt_req_info, 1);
1109 req_info->attr_path = g_strdup(object_path);
1110 req_info->svc_path = g_strdup(svc_info->serv_path);
1111 req_info->request_id = req_id;
1112 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1113 req_info->offset = offset;
1114 req_info->context = invocation;
1116 /* Append request info in list of requests for the particular connection */
1117 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1119 /* Send HAL event */
1120 memset(&ev, 0, sizeof(ev));
1121 ev.conn_id = conn_info->connection_id;
1122 ev.trans_id = req_id;
1123 ev.att_handle = char_hdl;
1125 ev.is_long = false; /* TODO*/
1127 /* Convert address to hex */
1128 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1129 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1131 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1132 GVariant *var = NULL;
1136 gboolean response_needed = FALSE;
1137 struct hal_ev_gatt_server_write_req ev;
1141 struct gatt_service_info *svc_info = NULL;
1142 struct gatt_req_info *req_info = NULL;
1143 struct gatt_client_info_t *conn_info = NULL;
1145 memset(&ev, 0, sizeof(ev));
1148 DBG("Application path = %s", object_path);
1149 DBG("Sender = %s", sender);
1151 g_variant_get(parameters, "(&suqb@ay)",
1152 &addr, &req_id, &offset, &response_needed, &var);
1153 DBG("Request id = %u, Offset = %u", req_id, offset);
1155 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1157 /* Check if device is already in connected list */
1158 conn_info = __bt_find_remote_gatt_client_info(addr);
1160 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1161 g_variant_unref(var);
1162 if (response_needed)
1163 g_dbus_method_invocation_return_value(invocation, NULL);
1165 g_object_unref(invocation);
1169 len = g_variant_get_size(var);
1170 if (len > 0 && len < 600) {
1172 data = (char *)g_variant_get_data(var);
1173 memcpy(ev.value, data, len);
1177 if (response_needed) {
1178 /* Store requets information */
1179 req_info = g_new0(struct gatt_req_info, 1);
1180 req_info->attr_path = g_strdup(object_path);
1181 req_info->svc_path = g_strdup(svc_info->serv_path);
1182 req_info->request_id = req_id;
1183 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1184 req_info->offset = offset;
1185 req_info->context = invocation;
1187 /* Append request info in list of requests for the particular connection */
1188 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1191 g_object_unref(invocation);
1194 /* Send HAL event */
1195 ev.conn_id = conn_info->connection_id;
1196 ev.trans_id = req_id;
1197 ev.att_handle = char_hdl;
1199 ev.need_rsp = response_needed;
1202 /* Convert address to hex */
1203 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1205 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1207 g_variant_unref(var);
1210 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1213 struct gatt_service_info *svc_info = NULL;
1214 struct hal_ev_gatt_server_notifcation_change ev;
1217 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1218 if (svc_info == NULL || event_cb == NULL)
1221 /* Send HAL event */
1222 memset(&ev, 0, sizeof(ev));
1223 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1224 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1225 ev.att_handle = char_hdl;
1228 /* Convert address to hex */
1229 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1231 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1234 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1237 struct gatt_service_info *svc_info = NULL;
1238 struct hal_ev_gatt_server_notifcation_change ev;
1241 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1242 if (svc_info == NULL || event_cb == NULL)
1245 /* Send HAL event */
1246 memset(&ev, 0, sizeof(ev));
1247 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1248 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1249 ev.att_handle = char_hdl;
1252 /* Convert address to hex */
1253 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1255 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1258 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1260 gboolean complete = FALSE;
1263 struct gatt_service_info *svc_info = NULL;
1264 struct gatt_client_info_t *conn_info = NULL;
1266 struct hal_ev_gatt_server_indicate_cfm ev;
1268 DBG("IndicateConfirm");
1269 DBG("Application path = %s", object_path);
1270 DBG("Sender = %s", sender);
1272 g_variant_get(parameters, "(&sb)", &addr, &complete);
1273 DBG("Remote Device address number = %s", addr);
1274 DBG("Is Indicate confirmation for last device [%d]", complete);
1276 /* Check if device is already in connected list */
1277 conn_info = __bt_find_remote_gatt_client_info(addr);
1279 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1281 if (svc_info == NULL || conn_info == NULL
1282 || event_cb == NULL) {
1286 /* Send HAL event */
1287 memset(&ev, 0, sizeof(ev));
1288 ev.conn_id = conn_info->connection_id;
1289 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1290 ev.att_handle = char_hdl;
1292 /* Convert address to hex */
1293 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1295 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1296 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1300 struct hal_ev_gatt_server_acquire_write_res ev;
1301 struct gatt_service_info *svc_info = NULL;
1302 struct gatt_req_info *req_info = NULL;
1303 struct gatt_client_info_t *conn_info = NULL;
1304 char * dev_path = NULL;
1306 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1308 DBG("AcquireWrite");
1309 DBG("Application path = %s", object_path);
1310 DBG("Sender = %s", sender);
1313 g_variant_get(parameters, "(a{sv})", &iter);
1315 GVariant* value = NULL;
1316 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1317 if (g_strcmp0(key, "MTU") == 0)
1318 g_variant_get(value, "i", &mtu);
1319 else if (g_strcmp0(key, "link") == 0)
1320 g_variant_get(value, "s", &link);
1321 else if (g_strcmp0(key, "device") == 0)
1322 g_variant_get(value, "o", &dev_path);
1325 DBG("AcquireWrite values retived");
1326 DBG(" path %s LINK = %s, MTU = %u", addr, link, mtu);
1328 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1330 _bt_hal_convert_device_path_to_address(dev_path, addr);
1332 DBG("remote address %s", addr);
1334 /* Check if device is already in connected list */
1335 conn_info = __bt_find_remote_gatt_client_info(addr);
1337 if (conn_info == NULL) {
1338 ERR("Cleint info not found\n");
1342 if (svc_info == NULL) {
1343 ERR("svc_info info not found\n");
1347 /* Store requets information */
1348 req_info = g_new0(struct gatt_req_info, 1);
1349 req_info->attr_path = g_strdup(object_path);
1350 req_info->svc_path = g_strdup(svc_info->serv_path);
1351 req_info->request_id = conn_info->connection_id;
1352 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1353 req_info->offset = mtu;
1354 req_info->context = invocation;
1356 /* Append request info in list of requests for the particular connection */
1357 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1359 /* Send HAL event */
1360 memset(&ev, 0, sizeof(ev));
1361 ev.conn_id = conn_info->connection_id;
1362 ev.char_handl = char_hdl;
1364 ev.trans_id = conn_info->connection_id;
1365 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1366 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1368 DBG("HAL_EV_GATT_ACQUIRE_WRITE_RES called");
1372 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1376 struct hal_ev_gatt_server_acquire_notify ev;
1377 struct gatt_service_info *svc_info = NULL;
1378 struct gatt_client_info_t *conn_info = NULL;
1379 struct gatt_req_info *req_info = NULL;
1381 DBG("AcquireNotify");
1382 DBG("Application path = %s", object_path);
1383 DBG("Sender = %s", sender);
1386 g_variant_get(parameters, "(a{sv})", &iter);
1388 GVariant* value = NULL;
1389 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1390 if (g_strcmp0(key, "MTU") == 0)
1391 g_variant_get(value, "q", &mtu);
1394 DBG("AcquireNotify values retived");
1395 DBG(" MTU = %u", mtu);
1397 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1399 if (svc_info == NULL) {
1400 ERR("svc_info info not found\n");
1404 /* Store requets information */
1405 req_info = g_new0(struct gatt_req_info, 1);
1406 req_info->attr_path = g_strdup(object_path);
1407 req_info->svc_path = g_strdup(svc_info->serv_path);
1408 req_info->request_id = 33;
1409 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1410 req_info->offset = mtu;
1411 req_info->context = invocation;
1413 conn_info = g_new0(struct gatt_client_info_t, 1);
1414 conn_info->addr = g_strdup(object_path);
1415 INFO("Added GATT client path[%s]", conn_info->addr);
1416 conn_info->connection_id = 33;
1417 conn_info->instance_id = 33;
1418 /* Append request info in list of requests for the particular connection */
1419 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1420 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1422 /* Send HAL event */
1423 memset(&ev, 0, sizeof(ev));
1425 ev.char_handl = char_hdl;
1429 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1431 DBG("HAL_EV_GATT_ACQUIRE_NOTIFY_RES called");
1437 g_dbus_method_invocation_return_value(invocation, NULL);
1440 static gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1443 GError *error = NULL;
1444 GVariantBuilder *array_builder;
1446 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1447 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1448 g_variant_builder_add(array_builder, "s", interface);
1450 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1451 "org.freedesktop.Dbus.Objectmanager",
1452 "InterfacesRemoved",
1453 g_variant_new("(oas)",
1454 object_path, array_builder),
1458 if (error != NULL) {
1459 /* dbus gives error cause */
1460 ERR("d-bus api failure: errcode[%x], message[%s]",
1461 error->code, error->message);
1462 g_clear_error(&error);
1465 g_variant_builder_unref(array_builder);
1470 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1477 g_free(desc_info->desc_path);
1478 g_free(desc_info->desc_uuid);
1479 g_free(desc_info->desc_value);
1481 for (i = 0; i < desc_info->flags_length; i++)
1482 g_free(desc_info->desc_flags[i]);
1487 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1494 g_free(char_info->char_path);
1495 g_free(char_info->char_uuid);
1496 g_free(char_info->char_value);
1498 for (i = 0; i < char_info->flags_length; i++)
1499 g_free(char_info->char_flags[i]);
1505 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1510 g_free(svc_info->serv_path);
1511 g_free(svc_info->service_uuid);
1515 static const GDBusInterfaceVTable desc_interface_vtable = {
1516 __bt_gatt_desc_method_call,
1521 static const GDBusInterfaceVTable char_interface_vtable = {
1522 __bt_gatt_char_method_call,
1527 static const GDBusInterfaceVTable serv_interface_vtable = {
1533 static const GDBusInterfaceVTable manager_interface_vtable = {
1534 __bt_gatt_manager_method_call,
1540 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1541 const gchar *introspection_data)
1544 GDBusNodeInfo *node_info = NULL;
1546 if (introspection_data == NULL)
1550 DBG("Create new node info");
1551 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1554 ERR("Unable to create node: %s", err->message);
1555 g_clear_error(&err);
1562 /* To send stack event to hal-av handler */
1563 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1568 void _bt_hal_unregister_gatt_server_handler_cb(void)
1573 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1575 struct hal_ev_gatt_desc_added ev;
1576 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1578 /* Prepare to GATT characteristic added event */
1579 memset(&ev, 0, sizeof(ev));
1580 ev.status = BT_STATUS_SUCCESS;
1581 ev.server_instance = data->instance_data;
1582 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1583 ev.service_handle = data->srvc_hdl;
1584 ev.desc_handle = data->desc_hdl;
1587 ERR("GATT Descriptor Added callback registered");
1589 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1590 data->instance_data, data->srvc_hdl, data->desc_hdl);
1592 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1599 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1601 struct hal_ev_gatt_char_added ev;
1602 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1604 /* Prepare to GATT characteristic added event */
1605 memset(&ev, 0, sizeof(ev));
1606 ev.status = BT_STATUS_SUCCESS;
1607 ev.server_instance = data->instance_data;
1608 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1609 ev.service_handle = data->srvc_hdl;
1610 ev.char_handle = data->char_hdl;
1613 ERR("GATT Characteristic Added callback registered");
1615 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1616 data->instance_data, data->srvc_hdl, data->char_hdl);
1618 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1625 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1627 struct hal_ev_gatt_service_added ev;
1628 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1630 /* Prepare to GATT Service added event */
1631 memset(&ev, 0, sizeof(ev));
1632 ev.status = BT_STATUS_SUCCESS;
1633 ev.server_instance = data->instance_data;
1634 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1635 ev.service_handle = data->srvc_hdl;
1636 ev.is_primary = data->is_primary;
1639 ERR("GATT Service Added callback registered");
1641 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1642 data->instance_data, data->srvc_hdl);
1643 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1650 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1652 struct hal_ev_gatt_service_started ev;
1653 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1655 /* Prepare to GATT Service added event */
1656 memset(&ev, 0, sizeof(ev));
1657 ev.status = BT_STATUS_SUCCESS;
1658 ev.server_instance = data->instance_data;
1659 ev.service_handle = data->srvc_hdl;
1662 ERR("GATT Service Started callback registered");
1664 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1665 data->instance_data, data->srvc_hdl);
1666 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1673 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1675 struct hal_ev_gatt_service_deleted ev;
1676 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1678 /* Prepare to GATT Service added event */
1679 memset(&ev, 0, sizeof(ev));
1680 ev.status = BT_STATUS_SUCCESS;
1681 ev.server_instance = data->instance_data;
1682 ev.service_handle = data->srvc_hdl;
1685 ERR("GATT Service Deleted callback registered");
1687 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1688 data->instance_data, data->srvc_hdl);
1689 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1696 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1698 struct hal_ev_server_instance_registered ev;
1699 hal_register_server_data *data = (hal_register_server_data*) user_data;
1701 /* Prepare to send AV connecting event */
1702 memset(&ev, 0, sizeof(ev));
1703 ev.status = BT_STATUS_SUCCESS;
1704 ev.server_instance = data->instance_data;
1705 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1708 ERR("GATT Register Server Instance Callback not registered");
1710 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1711 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1718 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1720 CHECK_BTGATT_INIT();
1721 int status = BT_STATUS_FAIL;
1723 DBG("Register server instance request");
1724 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1726 /* Check if slot available */
1727 server_if = _bt_hal_get_available_adv_slot_id(uuid);
1729 if (server_if == -1) {
1730 ERR("Allocation of server instance failed");
1734 user_data->instance_data = server_if;
1735 DBG("Allocated new Advertising slot with Stack [%d]", user_data->instance_data);
1739 * As we need to provide async callback to user from HAL, simply schedule a
1740 * callback method which will carry actual result
1742 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1743 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1745 /* If available, then return success, else return error */
1746 return BT_STATUS_SUCCESS;
1749 static void _bt_hal_remove_gatt_server_from_list(int server_if)
1752 struct gatt_server_app *info = NULL;
1754 for (l = gatt_server_apps; l != NULL;) {
1755 info = (struct gatt_server_app*)l->data;
1756 l = g_slist_next(l);
1759 if (info->slot == server_if) {
1760 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1761 info->app_path, info->slot);
1763 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1764 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1765 In above case, only advertising block will be deallocated, Gatt Server will remain
1767 if (info->services == NULL) {
1768 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1769 INFO("Total gatt server apps still existing after removing above is [%d]",
1770 g_slist_length(gatt_server_apps));
1772 /* DBUS Unregister only for current app */
1773 __bt_hal_gatt_deinit(info->app_path);
1775 g_free(info->app_path);
1779 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1780 g_slist_length(info->services));
1786 static bt_status_t gatt_server_unregister_app(int server_if)
1788 CHECK_BTGATT_INIT();
1789 DBG("Un-Register server instance request [%d]", server_if);
1791 if (_bt_hal_is_advertising_in_slot(server_if) == FALSE)
1792 _bt_hal_free_server_slot(server_if);
1794 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
1795 _bt_hal_remove_gatt_server_from_list(server_if);
1796 return BT_STATUS_SUCCESS;
1799 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
1801 CHECK_BTGATT_INIT();
1802 return BT_STATUS_SUCCESS;
1805 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
1808 GError *g_error = NULL;
1809 GVariant *reply = NULL;
1813 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
1814 g_object_unref(proxy);
1815 if (reply == NULL) {
1816 ERR("Disconnect LE Dbus Call Error");
1818 ERR("Error: %s\n", g_error->message);
1819 g_clear_error(&g_error);
1822 g_variant_unref(reply);
1826 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
1828 CHECK_BTGATT_INIT();
1830 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
1832 GDBusProxy *device_proxy;
1833 GDBusConnection *g_conn;
1834 struct gatt_client_info_t *conn_info = NULL;
1838 if (NULL == bd_addr) {
1839 ERR("bd_addr is NULL");
1840 return BT_STATUS_PARM_INVALID;
1843 /* GDBUS Connection Info validate */
1844 g_conn = _bt_hal_get_system_gconn();
1845 if (g_conn == NULL) {
1846 ERR("Could not get System DBUS Connection");
1847 return BT_STATUS_FAIL;
1850 /* Connection Info validate */
1851 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
1852 if (conn_info == NULL) {
1853 ERR("No Connection Inforamtion!!!");
1854 return BT_STATUS_FAIL;
1857 _bt_hal_convert_addr_type_to_string(device_address,
1858 (unsigned char *)bd_addr->address);
1860 //check if connection has the same device address
1861 if (g_strcmp0(conn_info->addr, device_address) != 0) {
1862 ERR("device address [%s] does not match", device_address);
1863 return BT_STATUS_FAIL;
1866 device_path = _bt_hal_get_device_object_path(conn_info->addr);
1867 if (device_path == NULL) {
1868 ERR("device_path is NULL");
1869 return BT_STATUS_PARM_INVALID;
1872 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
1873 NULL, BT_HAL_BLUEZ_NAME,
1874 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
1877 g_free(device_path);
1878 if (device_proxy == NULL)
1879 return BT_STATUS_FAIL;
1881 INFO("Disconnect LE [%s]", device_address);
1883 g_dbus_proxy_call(device_proxy, "DisconnectLE",
1885 G_DBUS_CALL_FLAGS_NONE,
1886 BT_HAL_MAX_DBUS_TIMEOUT,
1888 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
1891 return BT_STATUS_SUCCESS;
1894 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
1899 uuid = btuuid2str(srvc_id->uu);
1900 DBG("Original UUID [%s]", uuid);
1902 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
1903 /* Extract Standard UUID string */
1904 memcpy(uuid_buf, &uuid[4], 4);
1906 DBG("Converted string [%s]", uuid_buf);
1907 return g_strdup(uuid_buf);
1909 return strdup(uuid);
1912 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
1915 /* For GATT service specific */
1916 GDBusNodeInfo *node_info;
1919 struct gatt_service_info *serv_info = NULL;
1920 GVariantBuilder *builder = NULL;
1921 GVariantBuilder *builder1 = NULL;
1922 GVariantBuilder *inner_builder = NULL;
1923 gboolean svc_primary = TRUE;
1924 GError *error = NULL;
1925 hal_gatt_service_added *user_data = NULL;
1926 DBG("Service add to DBUS slot [%d]", slot);
1928 node_info = __bt_gatt_create_method_node_info(
1929 service_introspection_xml);
1931 if (node_info == NULL)
1932 return BT_STATUS_FAIL;
1934 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
1935 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
1936 DBG("gatt service path is [%s]", path);
1938 object_id = g_dbus_connection_register_object(g_conn, path,
1939 node_info->interfaces[0],
1940 &serv_interface_vtable,
1941 NULL, NULL, &error);
1943 if (object_id == 0) {
1944 ERR("failed to register: %s", error->message);
1945 g_error_free(error);
1947 return BT_STATUS_FAIL;
1949 /* Add object_id/gatt service information; it's required at the time of
1950 * service unregister and Getmanagedobjects
1952 serv_info = g_new0(struct gatt_service_info, 1);
1954 serv_info->serv_path = g_strdup(path);
1955 serv_info->serv_id = object_id;
1956 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
1957 serv_info->is_svc_registered = FALSE;
1958 serv_info->is_svc_primary = svc_primary;
1959 DBG("Service Handle to be added is [%d]", gatt_service_handle);
1960 serv_info->service_handle = gatt_service_handle;
1962 /* Update service in GATT Server service List */
1963 gatt_services = g_slist_append(gatt_services, serv_info);
1965 /* emit interfacesadded signal here for service path */
1966 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1967 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1969 g_variant_builder_add(inner_builder, "{sv}",
1970 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
1972 g_variant_builder_add(inner_builder, "{sv}",
1973 "Primary", g_variant_new_boolean(svc_primary));
1975 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1977 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1978 g_variant_new("ao", builder1));
1980 g_variant_builder_add(builder, "{sa{sv}}",
1981 GATT_SERV_INTERFACE, inner_builder);
1983 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1984 "org.freedesktop.Dbus.ObjectManager",
1986 g_variant_new("(oa{sa{sv}})",
1991 /* dbus gives error cause */
1992 ERR("d-bus api failure: errcode[%x], message[%s]",
1993 error->code, error->message);
1994 g_clear_error(&error);
1998 /* Send Service handle to application */
1999 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2000 user_data->srvc_hdl = serv_info->service_handle;
2001 user_data->instance_data = slot;
2002 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2003 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2005 /* Save newly created service in GATT Server's service list */
2006 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2010 g_variant_builder_unref(inner_builder);
2011 g_variant_builder_unref(builder);
2012 g_variant_builder_unref(builder1);
2013 return BT_STATUS_SUCCESS;
2016 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2019 char *app_path = (char*)user_data;
2020 INFO("UnregisterApplication is completed app [%s]", app_path);
2021 GError *error = NULL;
2022 GVariant *result = NULL;
2025 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2027 if (result == NULL) {
2028 /* dBUS-RPC is failed */
2029 ERR("Dbus-RPC is failed\n");
2031 if (error != NULL) {
2032 /* dBUS gives error cause */
2033 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2034 error->code, error->message);
2035 g_clear_error(&error);
2038 g_variant_unref(result);
2043 static void __bt_hal_gatt_deinit(char *app_path)
2045 GDBusProxy *proxy = NULL;
2049 /* Step1: Remove requested App */
2050 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2051 "/org/bluez/hci0", "org.bluez.GattManager1");
2056 INFO("UnregisterApplication : path [%s]", app_path);
2058 /* Async Call to Unregister Service */
2059 data = g_strdup(app_path);
2060 g_dbus_proxy_call(proxy,
2061 "UnregisterApplication",
2062 g_variant_new("(o)",
2064 G_DBUS_CALL_FLAGS_NONE, -1,
2066 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2069 /* If requested app is last GATT Server app, then clean all resources */
2070 if (gatt_server_apps == NULL) {
2071 INFO("All GATT servers are removed, clean all DBUS resources");
2073 /* unregister the exported interface for object manager */
2074 g_dbus_connection_unregister_object(g_conn, manager_id);
2076 g_bus_unown_name(owner_id);
2079 g_object_unref(manager_gproxy);
2080 manager_gproxy = NULL;
2086 static int __bt_hal_gatt_init(void)
2090 /* Only once for ALL GATT Servers */
2091 if (owner_id == 0) {
2095 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2098 ERR("Unable to connect to gdbus: %s", err->message);
2099 g_clear_error(&err);
2101 return BT_STATUS_FAIL;
2104 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2105 INFO("well-known name: %s", name);
2107 owner_id = g_bus_own_name_on_connection(g_conn, name,
2108 G_BUS_NAME_OWNER_FLAGS_NONE,
2109 NULL, NULL, NULL, NULL);
2111 INFO("Owner ID [%d]", owner_id);
2113 /* Only once for ALL GATT Servers */
2114 if (manager_node_info == NULL) {
2115 /* Register ObjectManager interface */
2116 manager_node_info = __bt_gatt_create_method_node_info(
2117 manager_introspection_xml);
2119 if (manager_node_info == NULL) {
2120 ERR("failed to get node info");
2121 return BT_STATUS_FAIL;
2126 return BT_STATUS_SUCCESS;
2129 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2133 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2134 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2135 if (app->slot == slot) {
2136 INFO("GATT Server app found app path [%s] instance [%d]",
2137 app->app_path, app->slot);
2138 *app_path = app->app_path;
2142 /* GATT Server not found */
2146 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2148 if (app_path == NULL)
2151 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2152 app->app_path = g_strdup(app_path);
2154 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2155 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2160 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2163 CHECK_BTGATT_INIT();
2164 char *app_path = NULL;
2165 GError *error = NULL;
2168 int result = BT_STATUS_SUCCESS;
2170 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2171 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2173 /* Check if this GATT server Application is already registered with DBUS */
2174 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2176 if (app_path != NULL) {
2177 DBG("GATT server path is already defined [%s]", app_path);
2178 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2180 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2181 result = __bt_hal_gatt_init();
2182 if (result != BT_STATUS_SUCCESS)
2185 /* Only once for each GATT Server */
2186 app_path = g_strdup_printf("/com/%d", server_if);
2188 app_id = g_malloc0(sizeof(int));
2189 *app_id = server_if;
2191 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2192 manager_node_info->interfaces[0],
2193 &manager_interface_vtable,
2194 (gpointer)app_id, NULL, &error);
2196 if (manager_id == 0) {
2197 ERR("failed to register: %s", error->message);
2198 g_error_free(error);
2201 INFO("manager_id [%d]", manager_id);
2203 /* For current GATT Server, app_path is created, save it in Table */
2204 _bt_hal_update_gatt_server_path(server_if, app_path);
2206 /* Add GATT Service to DBUS */
2207 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2213 INFO("Successfully added service");
2214 return BT_STATUS_SUCCESS;
2221 INFO("Service addition failed!!");
2222 return BT_STATUS_FAIL;
2225 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2226 int included_handle)
2228 CHECK_BTGATT_INIT();
2229 return BT_STATUS_SUCCESS;
2233 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2236 GSList *gatt_services = NULL;
2238 struct gatt_service_info *info = NULL;
2240 gatt_services = _bt_get_service_list_from_server(instance);
2242 len = g_slist_length(gatt_services);
2243 l = g_slist_nth(gatt_services, len -1);
2249 if (info->service_handle == service_handle)
2254 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2258 GSList *gatt_services = NULL;
2259 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2261 gatt_services = _bt_get_service_list_from_server(instance);
2263 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2264 struct gatt_service_info *info = l->data;
2265 INFO("Got one service with handle [%d]", info->service_handle);
2266 if (info->service_handle == service_handle)
2269 ERR("Gatt service with handle [%d] not found", service_handle);
2273 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2274 bt_uuid_t *uuid, int properties,
2278 GError *error = NULL;
2280 GDBusNodeInfo *node_info;
2282 GVariantBuilder *builder = NULL;
2283 GVariantBuilder *inner_builder = NULL;
2284 struct gatt_service_info *serv_info = NULL;
2285 struct gatt_char_info *char_info = NULL;
2286 GVariantBuilder *builder2 = NULL;
2287 GVariantBuilder *builder3 = NULL;
2288 GVariant *flags_val = NULL;
2290 char *char_flags[NUMBER_OF_FLAGS];
2292 hal_gatt_char_added *user_data = NULL;
2295 CHECK_BTGATT_INIT();
2296 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2297 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2299 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2300 if (serv_info == NULL)
2301 return BT_STATUS_FAIL;
2303 node_info = __bt_gatt_create_method_node_info(
2304 characteristics_introspection_xml);
2306 if (node_info == NULL)
2307 return BT_STATUS_FAIL;
2309 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2310 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2311 DBG("gatt characteristic path is [%s]", path);
2313 app_id = g_malloc0(sizeof(int));
2316 object_id = g_dbus_connection_register_object(g_conn, path,
2317 node_info->interfaces[0],
2318 &char_interface_vtable,
2319 (gpointer)app_id, NULL, &error);
2321 if (object_id == 0) {
2322 ERR("failed to register: %s", error->message);
2323 g_error_free(error);
2326 return BT_STATUS_FAIL;
2329 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2330 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2331 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2332 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2333 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2334 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2335 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2336 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2338 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2340 char_info = g_new0(struct gatt_char_info, 1);
2342 char_info->char_path = g_strdup(path);
2343 char_info->char_id = object_id;
2344 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2345 for (i = 0; i < flag_count; i++)
2346 char_info->char_flags[i] = char_flags[i];
2349 char_info->flags_length = flag_count;
2350 char_info->char_handle = gatt_char_handle;
2353 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2354 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2356 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2357 g_variant_new("s", char_info->char_uuid));
2358 g_variant_builder_add(inner_builder, "{sv}", "Service",
2359 g_variant_new("o", serv_info->serv_path));
2361 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2363 for (i = 0; i < flag_count; i++)
2364 g_variant_builder_add(builder2, "s", char_flags[i]);
2366 flags_val = g_variant_new("as", builder2);
2367 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2370 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2372 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2373 g_variant_new("ao", builder3));
2375 g_variant_builder_add(builder, "{sa{sv}}",
2376 GATT_CHAR_INTERFACE,
2379 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2380 "org.freedesktop.Dbus.ObjectManager",
2382 g_variant_new("(oa{sa{sv}})",
2387 /* dbus gives error cause */
2388 ERR("d-bus api failure: errcode[%x], message[%s]",
2389 error->code, error->message);
2390 g_clear_error(&error);
2394 //*char_path = g_strdup(path);
2399 /* Send Service handle to application */
2400 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2401 user_data->srvc_hdl = serv_info->service_handle;
2402 user_data->char_hdl = gatt_char_handle;
2403 user_data->instance_data = slot;
2404 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2405 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2407 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2408 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2413 g_variant_builder_unref(inner_builder);
2414 g_variant_builder_unref(builder);
2415 g_variant_builder_unref(builder2);
2416 g_variant_builder_unref(builder3);
2418 return BT_STATUS_SUCCESS;
2421 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2424 CHECK_BTGATT_INIT();
2426 // static int desc_id = 1;
2427 GError *error = NULL;
2429 GDBusNodeInfo *node_info;
2431 GVariantBuilder *builder = NULL;
2432 GVariantBuilder *inner_builder = NULL;
2434 struct gatt_char_info *char_info = NULL;
2435 struct gatt_desc_info *desc_info = NULL;
2436 struct gatt_service_info *serv_info = NULL;
2438 gchar **line_argv = NULL;
2440 char *char_path = NULL;
2443 GVariantBuilder *builder2 = NULL;
2444 GVariant *flags_val = NULL;
2446 char *desc_flags[NUMBER_OF_FLAGS];
2450 hal_gatt_desc_added *user_data = NULL;
2457 /* Fetch service data for the GATT server */
2458 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2459 if (serv_info == NULL)
2460 return BT_STATUS_FAIL;
2462 /* Fetch list of characteristics from the service info */
2463 l = serv_info->char_data;
2465 /* Fetch last char info from the characteristic list */
2466 char_info = g_slist_last(l)->data;
2467 if (char_info == NULL)
2468 return BT_STATUS_FAIL;
2470 /* Fetch characteristic path from char info */
2471 char_path = char_info->char_path;
2473 line_argv = g_strsplit_set(char_path, "/", 0);
2474 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2477 node_info = __bt_gatt_create_method_node_info(
2478 descriptor_introspection_xml);
2480 if (node_info == NULL) {
2481 g_strfreev(line_argv);
2483 return BT_STATUS_FAIL;
2486 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2488 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2489 DBG("gatt descriptor path is [%s]", path);
2491 app_id = g_malloc0(sizeof(int));
2494 object_id = g_dbus_connection_register_object(g_conn, path,
2495 node_info->interfaces[0],
2496 &desc_interface_vtable,
2497 (gpointer)app_id, NULL, &error);
2499 if (object_id == 0) {
2500 ERR("failed to register: %s", error->message);
2501 g_error_free(error);
2503 g_strfreev(line_argv);
2506 return BT_STATUS_FAIL;
2509 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2511 desc_info = g_new0(struct gatt_desc_info, 1);
2513 desc_info->desc_path = g_strdup(path);
2514 desc_info->desc_id = object_id;
2515 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2517 for (i = 0; i < flag_count; i++)
2518 desc_info->desc_flags[i] = desc_flags[i];
2520 desc_info->flags_length = flag_count;
2521 desc_info->desc_handle = gatt_desc_handle;
2524 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2525 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2527 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2528 g_variant_new("s", btuuid2str(uuid->uu)));
2529 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2530 g_variant_new("o", char_path));
2532 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2534 for (i = 0; i < flag_count; i++)
2535 g_variant_builder_add(builder2, "s", desc_flags[i]);
2537 flags_val = g_variant_new("as", builder2);
2538 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2541 g_variant_builder_add(builder, "{sa{sv}}",
2542 GATT_DESC_INTERFACE,
2545 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2546 "org.freedesktop.Dbus.ObjectManager",
2548 g_variant_new("(oa{sa{sv}})",
2551 if (error != NULL) {
2552 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2553 error->code, error->message);
2554 g_clear_error(&error);
2557 //*desc_path = g_strdup(path);
2559 /* Save newly created descriptor to GATT server's service's characteristic */
2560 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2562 /* Send descriptor handle to application */
2563 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2564 user_data->srvc_hdl = serv_info->service_handle;
2565 user_data->desc_hdl = gatt_desc_handle;
2566 user_data->instance_data = slot;
2567 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2568 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2573 g_strfreev(line_argv);
2574 g_variant_builder_unref(inner_builder);
2575 g_variant_builder_unref(builder);
2576 return BT_STATUS_SUCCESS;
2579 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2581 GError *error = NULL;
2583 char *data = (char*) user_data;
2584 INFO("RegisterApplication is completed path [%s]", data);
2586 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2588 if (result == NULL) {
2589 /* dBUS-RPC is failed */
2590 ERR("Dbus-RPC is failed\n");
2592 if (error != NULL) {
2593 /* dBUS gives error cause */
2594 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2595 error->code, error->message);
2596 g_clear_error(&error);
2599 g_variant_unref(result);
2604 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2605 const gchar *path, const gchar *interface)
2611 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2616 ERR("Unable to connect to gdbus: %s", err->message);
2617 g_clear_error(&err);
2622 proxy = g_dbus_proxy_new_sync(g_conn,
2623 G_DBUS_PROXY_FLAGS_NONE, NULL,
2625 interface, NULL, &err);
2629 ERR("Unable to create proxy: %s", err->message);
2630 g_clear_error(&err);
2634 manager_gproxy = proxy;
2639 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2640 const gchar *path, const gchar *interface)
2642 return (manager_gproxy) ? manager_gproxy :
2643 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2647 static void __bt_register_application_to_dbus(int slot)
2649 GDBusProxy *proxy = NULL;
2650 char *app_path = NULL;
2652 DBG("RegisterApplication slot [%d]", slot);
2654 /* It is impossible that app path is still not initialized */
2655 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2657 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2658 "/org/bluez/hci0", "org.bluez.GattManager1");
2660 data = g_strdup(app_path);
2661 g_dbus_proxy_call(proxy,
2662 "RegisterApplication",
2663 g_variant_new("(oa{sv})",
2665 G_DBUS_CALL_FLAGS_NONE, -1,
2667 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2669 INFO("GATT server started");
2672 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2674 CHECK_BTGATT_INIT();
2675 struct gatt_service_info *serv_info = NULL;
2676 hal_gatt_service_started *user_data = NULL;
2677 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2679 /* Fetch service data for the GATT server */
2680 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2681 if (serv_info == NULL)
2682 return BT_STATUS_FAIL;
2684 if (serv_info->is_svc_registered)
2685 DBG("service already registered \n");
2687 serv_info->is_svc_registered = TRUE;
2689 /* Send Service handle to application */
2690 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2691 user_data->srvc_hdl = serv_info->service_handle;
2692 user_data->instance_data = server_if;
2693 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2695 /* If this is nth Service that is started, then register application at this point */
2696 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2697 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2699 __bt_register_application_to_dbus(server_if);
2702 return BT_STATUS_SUCCESS;
2705 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2707 CHECK_BTGATT_INIT();
2708 INFO("Stop service successful");
2709 return BT_STATUS_SUCCESS;
2712 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2714 CHECK_BTGATT_INIT();
2715 struct gatt_service_info *serv_info = NULL;
2716 hal_gatt_service_deleted *user_data = NULL;
2719 int err = BT_STATUS_SUCCESS;
2720 int ret = BT_STATUS_SUCCESS;
2721 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2723 /* Fetch service data for the GATT server */
2724 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2725 if (serv_info == NULL) {
2726 ERR("Could not find service info svc handle [%d] server slot [%d]",
2727 service_handle, server_if);
2728 return BT_STATUS_FAIL;
2731 if (serv_info->is_svc_registered == FALSE) {
2732 ERR("service Not registered path [%s] handle [%d]",
2733 serv_info->serv_path, service_handle);
2736 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2737 struct gatt_char_info *char_info = l->data;
2739 if (char_info == NULL)
2742 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2743 struct gatt_desc_info *desc_info = l1->data;
2745 if (desc_info == NULL)
2748 ret = g_dbus_connection_unregister_object(g_conn,
2749 desc_info->desc_id);
2751 __bt_hal_gatt_emit_interface_removed(
2752 desc_info->desc_path,
2753 GATT_DESC_INTERFACE);
2755 err = BT_STATUS_FAIL;
2758 /* list remove & free */
2759 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2760 __bt_hal_gatt_free_descriptor_info(desc_info);
2763 g_slist_free(char_info->desc_data);
2764 char_info->desc_data = NULL;
2766 ret = g_dbus_connection_unregister_object(g_conn,
2767 char_info->char_id);
2769 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2770 GATT_CHAR_INTERFACE);
2773 err = BT_STATUS_FAIL;
2776 /* list remove & free */
2777 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2778 __bt_hal_gatt_free_characteristic_info(char_info);
2781 g_slist_free(serv_info->char_data);
2782 serv_info->char_data = NULL;
2784 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2786 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2787 GATT_SERV_INTERFACE);
2790 err = BT_STATUS_FAIL;
2793 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
2795 DBG("Unregistered the service on properties interface");
2797 /* Remove from global list */
2798 gatt_services = g_slist_remove(gatt_services, serv_info);
2799 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
2801 /* Remove from GATT Server's list of services */
2802 _bt_remote_service_from_gatt_server(server_if, service_handle);
2804 if (gatt_services == NULL)
2805 INFO("All GATT Services of all GATT Servers are unregistered");
2807 if (err == BT_STATUS_SUCCESS) {
2808 INFO("Send GATT Service deleted Event");
2809 /* Send Service handle to application */
2810 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
2811 user_data->srvc_hdl = serv_info->service_handle;
2812 user_data->instance_data = server_if;
2813 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
2816 /* Free the service */
2817 __bt_hal_gatt_free_service_info(serv_info);
2821 static gboolean __bt_gatt_get_service_state(const char *service_path)
2823 struct gatt_service_info *svc_info = NULL;
2825 for (l = gatt_services; l; l = g_slist_next(l)) {
2827 svc_info = (struct gatt_service_info *)l->data;
2830 if (!g_strcmp0(svc_info->serv_path, service_path)) {
2831 DBG("Return the state of the gatt service %d",
2832 svc_info->is_svc_registered);
2833 return svc_info->is_svc_registered;
2837 DBG("gatt service info is NULL");
2841 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
2842 int len, int confirm, char* p_value)
2844 CHECK_BTGATT_INIT();
2847 GVariantBuilder *outer_builder;
2848 GVariantBuilder *invalidated_builder;
2850 /* For Value update via PropertyChange */
2851 GVariantBuilder *outer_builder1;
2852 GVariantBuilder *inner_builder1;
2853 GVariantBuilder *invalidated_builder1;
2854 GVariant *update_value = NULL;
2856 /* Other variables */
2857 struct gatt_client_info_t *conn_info = NULL;
2858 gchar *serv_path = NULL;
2859 char *char_path = NULL;
2860 gchar **line_argv = NULL;
2861 gboolean notify = TRUE;
2862 gboolean ret = TRUE;
2863 int err = BT_STATUS_SUCCESS;
2865 GError *error = NULL;
2868 memset(addr, 0x00, sizeof(addr));
2870 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2871 if (conn_info == NULL) {
2872 ERR("No Connection Inforamtion!!!");
2873 return BT_STATUS_FAIL;
2876 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
2878 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
2879 if (char_path == NULL)
2880 return BT_STATUS_FAIL;
2882 line_argv = g_strsplit_set(char_path, "/", 0);
2883 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2885 if (!__bt_gatt_get_service_state(serv_path)) {
2886 DBG("service not registered for this characteristic \n");
2888 g_strfreev(line_argv);
2889 return BT_STATUS_FAIL;
2892 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2893 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2895 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2896 g_variant_new("b", notify));
2898 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
2899 DBG("Send Indication to Unicast addr [%s]", addr);
2901 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2902 g_variant_new("s", addr));
2904 DBG("Set characteristic Notification \n");
2905 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2907 "org.freedesktop.DBus.Properties",
2908 "PropertiesChanged",
2909 g_variant_new("(sa{sv}as)",
2910 "org.bluez.GattCharacteristic1",
2911 outer_builder, invalidated_builder),
2915 if (error != NULL) {
2916 ERR("D-Bus API failure: errCode[%x], \
2918 error->code, error->message);
2919 g_clear_error(&error);
2921 err = BT_STATUS_FAIL;
2924 g_variant_builder_unref(outer_builder);
2925 g_variant_builder_unref(invalidated_builder);
2928 /* Notifying Done, now update Value to Bluez via PropertyChanged */
2929 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2931 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2932 for (i = 0; i < len; i++)
2933 g_variant_builder_add(inner_builder1, "y", p_value[i]);
2935 update_value = g_variant_new("ay", inner_builder1);
2938 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2939 g_variant_builder_add(outer_builder1, "{sv}", "Value",
2942 DBG("Updating characteristic value \n");
2943 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2945 "org.freedesktop.DBus.Properties",
2946 "PropertiesChanged",
2947 g_variant_new("(sa{sv}as)",
2948 "org.bluez.GattCharacteristic1",
2949 outer_builder1, invalidated_builder1),
2953 if (error != NULL) {
2954 ERR("D-Bus API failure: errCode[%x], \
2956 error->code, error->message);
2957 g_clear_error(&error);
2959 err = BT_STATUS_FAIL;
2961 struct gatt_char_info *char_info = NULL;
2963 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
2964 if (char_info == NULL) {
2966 g_strfreev(line_argv);
2967 g_variant_builder_unref(inner_builder1);
2968 g_variant_builder_unref(outer_builder1);
2969 g_variant_builder_unref(invalidated_builder1);
2971 return BT_STATUS_FAIL;
2974 char_info->value_length = len;
2976 char_info->char_value = (char *)realloc(char_info->char_value, len);
2977 if (char_info->char_value) {
2978 for (i = 0; i < len; i++)
2979 char_info->char_value[i] = p_value[i];
2984 g_strfreev(line_argv);
2985 g_variant_builder_unref(inner_builder1);
2986 g_variant_builder_unref(outer_builder1);
2987 g_variant_builder_unref(invalidated_builder1);
2992 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
2993 int status, btgatt_response_t *response)
2995 CHECK_BTGATT_INIT();
2997 struct gatt_req_info *req_info = NULL;
2998 struct gatt_client_info_t *conn_info = NULL;
3001 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3003 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3004 if (conn_info == NULL) {
3005 ERR("No Connection Inforamtion!!!");
3006 return BT_STATUS_FAIL;
3009 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3010 if (req_info == NULL) {
3011 ERR("No Request Inforamtion!!!");
3012 return BT_STATUS_FAIL;
3015 if (status != BT_STATUS_SUCCESS) {
3016 ERR("resp_state is 0x%X", status);
3018 g_dbus_method_invocation_return_dbus_error(req_info->context,
3019 "org.bluez.Error.Failed", "Application Error");
3021 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3023 req_info->context = NULL;
3024 if (req_info->attr_path)
3025 g_free(req_info->attr_path);
3026 if (req_info->svc_path)
3027 g_free(req_info->svc_path);
3030 return BT_STATUS_SUCCESS;
3033 DBG("Reponse Value length [%d]", response->attr_value.len);
3034 DBG("Request type: [%d]", req_info->request_type);
3037 for (i = 0; i < response->attr_value.len; i++)
3038 DBG("Resonse [%d] = [0x%x]", i, response->attr_value.value[i]);
3040 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3041 GVariantBuilder *inner_builder = NULL;
3042 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3044 if (response->attr_value.len > 0) {
3045 for (i = 0; i < response->attr_value.len; i++)
3046 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3048 g_dbus_method_invocation_return_value(req_info->context,
3049 g_variant_new("(ay)", inner_builder));
3051 g_variant_builder_unref(inner_builder);
3053 g_dbus_method_invocation_return_value(req_info->context, NULL);
3055 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3057 req_info->context = NULL;
3058 if (req_info->attr_path)
3059 g_free(req_info->attr_path);
3060 if (req_info->svc_path)
3061 g_free(req_info->svc_path);
3064 return BT_STATUS_SUCCESS;
3068 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3069 int status, int fd, int mtu, void *fdlist)
3071 CHECK_BTGATT_INIT();
3073 struct gatt_req_info *req_info = NULL;
3074 struct gatt_client_info_t *conn_info = NULL;
3076 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3078 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3079 if (conn_info == NULL) {
3080 ERR("No Connection Inforamtion!!!");
3081 return BT_STATUS_FAIL;
3084 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3085 if (req_info == NULL) {
3086 ERR("No Request Inforamtion!!!");
3087 return BT_STATUS_FAIL;
3090 if (status != BT_STATUS_SUCCESS) {
3091 ERR("resp_state is 0x%X", status);
3093 g_dbus_method_invocation_return_dbus_error(req_info->context,
3094 "org.bluez.Error.Failed", "Application Error");
3096 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3098 req_info->context = NULL;
3099 if (req_info->attr_path)
3100 g_free(req_info->attr_path);
3101 if (req_info->svc_path)
3102 g_free(req_info->svc_path);
3105 return BT_STATUS_SUCCESS;
3109 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3111 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3112 g_dbus_method_invocation_return_value_with_unix_fd_list(
3113 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3115 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3117 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3118 g_dbus_method_invocation_return_value_with_unix_fd_list(
3119 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
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_update_att_value(int server_if, int attribute_handle,
3138 int value_length, char* att_value)
3140 CHECK_BTGATT_INIT();
3142 /* Other variables */
3143 char *char_path = NULL;
3144 gboolean ret = TRUE;
3145 GError *error = NULL;
3147 GVariantBuilder *outer_builder;
3148 GVariantBuilder *inner_builder;
3149 GVariantBuilder *invalidated_builder;
3150 GVariant *update_value = NULL;
3151 int err = BT_STATUS_SUCCESS;
3153 gchar **line_argv = NULL;
3154 gchar *serv_path = NULL;
3156 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3157 if (char_path == NULL)
3158 return BT_STATUS_FAIL;
3160 line_argv = g_strsplit_set(char_path, "/", 0);
3161 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3163 if (!__bt_gatt_get_service_state(serv_path)) {
3164 DBG("service not registered for this characteristic \n");
3166 g_strfreev(line_argv);
3167 return BT_STATUS_FAIL;
3171 line_argv = g_strsplit_set(char_path, "/", 0);
3172 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3174 if (!__bt_gatt_get_service_state(serv_path)) {
3175 DBG("service not registered for this characteristic \n");
3177 g_strfreev(line_argv);
3178 return BT_STATUS_FAIL;
3181 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3182 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3184 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3185 for (i = 0; i < value_length; i++)
3186 g_variant_builder_add(inner_builder, "y", att_value[i]);
3188 update_value = g_variant_new("ay", inner_builder);
3190 g_variant_builder_add(outer_builder, "{sv}", "Value",
3193 DBG("Updating characteristic value \n");
3194 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3196 "org.freedesktop.DBus.Properties",
3197 "PropertiesChanged",
3198 g_variant_new("(sa{sv}as)",
3199 "org.bluez.GattCharacteristic1",
3200 outer_builder, invalidated_builder),
3204 if (error != NULL) {
3205 ERR("D-Bus API failure: errCode[%x], \
3207 error->code, error->message);
3208 g_clear_error(&error);
3210 err = BT_STATUS_FAIL;
3212 struct gatt_char_info *char_info = NULL;
3214 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3215 if (char_info == NULL) {
3217 g_strfreev(line_argv);
3218 g_variant_builder_unref(inner_builder);
3219 g_variant_builder_unref(outer_builder);
3220 g_variant_builder_unref(invalidated_builder);
3222 return BT_STATUS_FAIL;
3225 char_info->value_length = value_length;
3227 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3228 if (char_info->char_value) {
3229 for (i = 0; i < value_length; i++)
3230 char_info->char_value[i] = att_value[i];
3236 g_strfreev(line_argv);
3237 g_variant_builder_unref(inner_builder);
3238 g_variant_builder_unref(outer_builder);
3239 g_variant_builder_unref(invalidated_builder);
3244 static bt_status_t gatt_server_listen(int server_if, bool start)
3246 CHECK_BTGATT_INIT();
3247 /* Send Data to LE Module */
3248 return _bt_hal_enable_advertising(server_if, start, FALSE);
3251 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3252 bool include_txpower, int min_interval, int max_interval, int appearance,
3253 uint16_t manufacturer_len, char* manufacturer_data,
3254 uint16_t service_data_len, char* service_data,
3255 uint16_t service_uuid_len, char* service_uuid)
3257 CHECK_BTGATT_INIT();
3258 return BT_STATUS_SUCCESS;
3261 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3263 CHECK_BTGATT_INIT();
3264 /* Send Enable Advertising request to LE Module */
3265 return _bt_hal_enable_advertising(server_if, TRUE, TRUE);
3268 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3269 int chnl_map, int tx_power, int timeout_s)
3271 CHECK_BTGATT_INIT();
3273 /* Send Advertising parameters to LE Module */
3274 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3275 chnl_map, tx_power, timeout_s);
3278 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3280 CHECK_BTGATT_INIT();
3282 /* Send Data to LE Module */
3283 return _bt_hal_set_advertising_data(adv_param_setup);
3286 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3288 CHECK_BTGATT_INIT();
3289 /* Send Data to LE Module */
3290 return _bt_hal_enable_advertising(server_if, FALSE, TRUE);
3293 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3295 CHECK_BTGATT_INIT();
3296 char *object_path = NULL;
3298 GDBusProxy *device_proxy;
3299 GError *error = NULL;
3301 GVariant *tmp_value;
3302 GDBusConnection *conn;
3303 GVariant *result = NULL;
3304 int ret = BT_STATUS_SUCCESS;
3305 struct gatt_client_info_t *conn_info = NULL;
3308 if (mtu_size == NULL)
3309 return BT_STATUS_PARM_INVALID;
3311 /* GDBUS Connection Info validate */
3312 conn = _bt_hal_get_system_gconn();
3314 ERR("Could not get System DBUS Connection");
3315 return BT_STATUS_FAIL;
3318 /* Connection Info validate */
3319 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3320 if (conn_info == NULL) {
3321 ERR("No Connection Inforamtion!!!");
3322 return BT_STATUS_FAIL;
3326 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3327 if (object_path == NULL)
3328 return BT_STATUS_FAIL;
3330 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3331 NULL, BT_HAL_BLUEZ_NAME, object_path,
3332 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3334 g_free(object_path);
3335 if (device_proxy == NULL)
3336 return BT_STATUS_FAIL;
3338 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3339 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3340 G_DBUS_CALL_FLAGS_NONE,
3344 if (result == NULL) {
3345 if (error != NULL) {
3346 ERR("Error occured in Proxy call [%s]\n", error->message);
3347 g_error_free(error);
3349 g_object_unref(device_proxy);
3350 return BT_STATUS_FAIL;
3353 g_variant_get(result , "(@a{sv})", &value);
3354 g_variant_unref(result);
3356 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3357 if (tmp_value == NULL) {
3358 g_object_unref(device_proxy);
3359 g_variant_unref(value);
3360 return BT_STATUS_FAIL;
3363 mtu = g_variant_get_uint16(tmp_value);
3365 DBG("ATT MTU : [%d]", mtu);
3367 g_variant_unref(tmp_value);
3368 g_variant_unref(value);
3369 g_object_unref(device_proxy);
3371 *mtu_size = (int) mtu;
3376 const btgatt_server_interface_t btgatt_server_interface = {
3377 .register_server = gatt_server_register_app,
3378 .unregister_server = gatt_server_unregister_app,
3379 .connect = gatt_server_open,
3380 .disconnect = gatt_server_close,
3381 .add_service = gatt_server_add_service,
3382 .add_included_service = gatt_server_add_included_service,
3383 .add_characteristic = gatt_server_add_characteristic,
3384 .add_descriptor = gatt_server_add_descriptor,
3385 .start_service = gatt_server_start_service,
3386 .stop_service = gatt_server_stop_service,
3387 .delete_service = gatt_server_delete_service,
3388 .send_indication = gatt_server_send_indication,
3389 .send_response = gatt_server_send_response,
3390 .update_att_value = gatt_server_update_att_value,
3391 .listen = gatt_server_listen,
3392 .set_adv_data = gatt_server_set_adv_data,
3393 .multi_adv_enable = gatt_server_multi_adv_enable,
3394 .multi_adv_update = gatt_server_multi_adv_update,
3395 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3396 .multi_adv_disable = gatt_server_multi_adv_disable,
3397 .get_att_mtu = gatt_server_get_mtu_size,
3398 .send_response_acquire = gatt_server_send_acquire_response