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 int _bt_get_remote_gatt_client_conn_id(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);
389 return info->connection_id;
395 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
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 (!g_strcmp0(info->addr, address)) {
406 INFO("Remote GATT client found addr[%s]", info->addr);
413 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
416 struct gatt_client_info_t *info = NULL;
418 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
419 info = (struct gatt_client_info_t*)l->data;
423 if (info->connection_id == conn_id) {
424 INFO("Remote GATT client found addr[%s]", info->addr);
431 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
436 struct gatt_client_info_t *info = NULL;
437 struct gatt_req_info *info1 = NULL;
439 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
440 info = (struct gatt_client_info_t*)l->data;
444 if (info->connection_id == conn_id) {
446 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
448 info1 = (struct gatt_req_info*)l1->data;
452 if (info1->request_id == trans_id) {
453 INFO("Remote GATT client found addr[%s]", info->addr);
462 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
464 struct hal_ev_gatt_server_connected ev;
465 struct gatt_client_info_t *conn_info = NULL;
467 memset(&ev, 0, sizeof(ev));
469 /* Find Server Instance */
470 _bt_hal_get_gatt_server_instance_initialized(&instance);
471 if (instance == -1) {
472 ERR("Not even a single GATT server is registered");
476 /* Convert address to hex */
477 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
479 /* Create Connection ID */
480 /* Check if device is already in connected list */
481 conn_info = __bt_find_remote_gatt_client_info(address);
484 /* If disconnected, and conn info found, then remove conn info */
485 if (is_connected == FALSE) {
486 DBG("GATT Disconnected");
488 INFO("Remove GATT client info from List..");
489 /* Remove info from List */
490 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
491 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
494 ERR("GATT callback not registered");
496 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
497 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
498 ev.conn_id = conn_info->connection_id;
499 ev.server_instance = conn_info->instance_id;
500 ev.connected = is_connected;
502 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
504 g_free(conn_info->addr);
507 /* If connected, and conn info NOT found, then add conn info */
510 /* Save Connection info */
511 conn_info = g_new0(struct gatt_client_info_t, 1);
512 conn_info->addr = g_strdup(address);
513 INFO("Added GATT client addr[%s]", conn_info->addr);
514 conn_info->connection_id = ++conn_id;
515 conn_info->instance_id = instance;
516 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
517 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
520 ERR("GATT callback not registered");
522 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
523 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
524 ev.conn_id = conn_info->connection_id;
525 ev.server_instance = conn_info->instance_id;
526 ev.connected = is_connected;
528 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
532 /* Send GATT connected or disconnected event */
535 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
539 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
540 struct gatt_service_info *serv_info = l1->data;
542 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
543 struct gatt_char_info *char_info = l2->data;
545 if (g_strcmp0(char_info->char_path, char_path)
547 *char_hdl = char_info->char_handle;
552 ERR("Gatt service not found");
556 static char *__bt_gatt_find_char_path_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)
567 return char_info->char_path;
574 static struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
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 if (char_info->char_handle == char_hdl)
592 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
594 GSList *l1, *l2, *l3;
596 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
597 struct gatt_service_info *serv_info = l1->data;
599 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
600 struct gatt_char_info *char_info = l2->data;
602 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
603 struct gatt_desc_info *desc_info = l3->data;
605 if (g_strcmp0(desc_info->desc_path, desc_path)
607 *desc_hdl = desc_info->desc_handle;
613 ERR("Gatt service not found");
617 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
619 const gchar *object_path,
620 const gchar *interface_name,
621 const gchar *method_name,
622 GVariant *parameters,
623 GDBusMethodInvocation *invocation,
628 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
629 GVariantBuilder *builder;
630 GVariantBuilder *inner_builder1 = NULL;
631 GVariant *svc_char = NULL;
633 GSList *gatt_services = NULL;
635 instance = (int*)user_data;
636 gboolean writeAcquired = FALSE;
637 gboolean notifyAcquired = FALSE;
639 DBG("Getting values for service, chars and descriptors");
640 DBG("GATT Server App for which services are requested [%d]", *instance);
643 builder = g_variant_builder_new(
644 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
647 gatt_services = _bt_get_service_list_from_server(*instance);
649 if (g_slist_length(gatt_services) == 0) {
650 ERR("No registered GATT services!!!!");
651 g_dbus_method_invocation_return_value(invocation, NULL);
652 g_variant_builder_unref(builder);
656 for (l = gatt_services; l != NULL; l = l->next) {
657 GVariantBuilder *svc_builder = NULL;
658 GVariantBuilder *inner_builder = NULL;
659 struct gatt_service_info *serv_info = l->data;
660 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
662 /* Prepare inner builder for GattService1 interface */
663 DBG("Creating builder for service");
664 svc_builder = g_variant_builder_new(
665 G_VARIANT_TYPE("a{sa{sv}}"));
666 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
668 g_variant_builder_add(inner_builder, "{sv}", "UUID",
669 g_variant_new_string(serv_info->service_uuid));
671 g_variant_builder_add(inner_builder, "{sv}", "Primary",
672 g_variant_new_boolean(serv_info->is_svc_primary));
675 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
676 DBG("Adding Charatarisitcs list");
677 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
678 struct gatt_char_info *char_info = l4->data;
679 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
680 char_info->char_handle, serv_info->service_handle);
681 g_variant_builder_add(inner_builder1, "o",
682 char_info->char_path);
683 DBG("%s", char_info->char_path);
686 svc_char = g_variant_new("ao", inner_builder1);
687 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
690 g_variant_builder_add(svc_builder, "{sa{sv}}",
694 g_variant_builder_add(builder, "{oa{sa{sv}}}",
695 serv_info->serv_path,
698 g_variant_builder_unref(inner_builder1);
700 /* Prepare inner builder for GattCharacteristic1 interface */
702 GSList *l2 = serv_info->char_data;
703 DBG("Creating builder for characteristics \n");
706 DBG("characteristic data is NULL");
708 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
710 GVariantBuilder *char_builder = NULL;
711 GVariantBuilder *inner_builder = NULL;
712 GVariantBuilder *builder1 = NULL;
713 GVariantBuilder *builder2 = NULL;
714 GVariantBuilder *builder3 = NULL;
715 GVariant *char_val = NULL;
716 GVariant *flags_val = NULL;
717 GVariant *char_desc = NULL;
718 char *unicast = NULL;
719 gboolean notify = FALSE;
722 char_builder = g_variant_builder_new(
725 inner_builder = g_variant_builder_new(
729 struct gatt_char_info *char_info = l2->data;
730 if (char_info == NULL) {
731 ERR("char_info is NULL");
736 g_variant_builder_add(inner_builder, "{sv}", "UUID",
737 g_variant_new_string(char_info->char_uuid));
739 g_variant_builder_add(inner_builder, "{sv}", "Service",
740 g_variant_new("o", serv_info->serv_path));
742 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
744 if (char_info->char_value != NULL) {
745 for (i = 0; i < char_info->value_length; i++) {
746 g_variant_builder_add(builder1, "y",
747 char_info->char_value[i]);
749 char_val = g_variant_new("ay", builder1);
750 g_variant_builder_add(inner_builder, "{sv}",
754 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
755 for (i = 0; i < char_info->flags_length; i++) {
756 g_variant_builder_add(builder2, "s",
757 char_info->char_flags[i]);
759 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
760 DBG("setting WriteAcquired property");
761 writeAcquired = TRUE;
764 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
765 DBG("setting NotifyAcquired property");
766 notifyAcquired = TRUE;
770 flags_val = g_variant_new("as", builder2);
771 g_variant_builder_add(inner_builder, "{sv}", "Flags",
775 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
776 g_variant_new("b", notify));
779 if (writeAcquired == TRUE) {
780 DBG("adding WriteAcquired property");
781 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
782 g_variant_new("b", writeAcquired));
786 if (notifyAcquired == TRUE) {
787 DBG("adding NotifyAcquired property");
788 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
789 g_variant_new("b", notifyAcquired));
793 unicast = g_strdup("00:00:00:00:00:00");
794 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
795 g_variant_new("s", unicast));
798 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
799 DBG("Adding Descriptors list");
801 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
802 struct gatt_desc_info *desc_info = l4->data;
803 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
804 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
805 g_variant_builder_add(builder3, "o",
806 desc_info->desc_path);
807 DBG("%s", desc_info->desc_path);
810 char_desc = g_variant_new("ao", builder3);
811 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
814 g_variant_builder_add(char_builder, "{sa{sv}}",
815 GATT_CHAR_INTERFACE , inner_builder);
816 g_variant_builder_add(builder, "{oa{sa{sv}}}",
817 char_info->char_path, char_builder);
819 /*Prepare inner builder for GattDescriptor1 interface*/
821 GSList *l3 = char_info->desc_data;
824 DBG("descriptor data is NULL");
826 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
828 DBG("Creating builder for descriptor \n");
830 GVariantBuilder *desc_builder = NULL;
831 GVariantBuilder *inner_builder = NULL;
832 GVariantBuilder *builder1 = NULL;
833 GVariantBuilder *builder2 = NULL;
834 GVariant *desc_val = NULL;
836 desc_builder = g_variant_builder_new(
839 inner_builder = g_variant_builder_new(
843 struct gatt_desc_info *desc_info = l3->data;
844 if (desc_info == NULL) {
845 ERR("desc_info is NULL");
850 g_variant_builder_add(inner_builder,
852 g_variant_new_string(
853 desc_info->desc_uuid));
856 g_variant_builder_add(inner_builder, "{sv}",
859 char_info->char_path));
862 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
864 if (desc_info->desc_value != NULL) {
865 for (i = 0; i < desc_info->value_length; i++) {
866 g_variant_builder_add(builder1, "y",
867 desc_info->desc_value[i]);
869 desc_val = g_variant_new("ay", builder1);
870 g_variant_builder_add(inner_builder, "{sv}",
875 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
877 for (i = 0; i < desc_info->flags_length; i++) {
878 g_variant_builder_add(builder2, "s",
879 desc_info->desc_flags[i]);
882 flags_val = g_variant_new("as", builder2);
883 g_variant_builder_add(inner_builder, "{sv}", "Flags",
886 g_variant_builder_add(desc_builder, "{sa{sv}}",
890 g_variant_builder_add(builder, "{oa{sa{sv}}}",
891 desc_info->desc_path,
894 /*unref descriptor builder pointers*/
895 g_variant_builder_unref(builder1);
896 g_variant_builder_unref(builder2);
897 g_variant_builder_unref(inner_builder);
898 g_variant_builder_unref(desc_builder);
903 /*unref char builder pointers*/
904 g_variant_builder_unref(builder1);
905 g_variant_builder_unref(builder2);
906 g_variant_builder_unref(builder3);
907 g_variant_builder_unref(inner_builder);
908 g_variant_builder_unref(char_builder);
911 /*unref service builder pointers*/
912 g_variant_builder_unref(inner_builder);
913 g_variant_builder_unref(svc_builder);
916 /* Return builder as method reply */
917 DBG("Sending gatt service builder values to Bluez");
918 g_dbus_method_invocation_return_value(invocation,
928 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
930 const gchar *object_path,
931 const gchar *interface_name,
932 const gchar *method_name,
933 GVariant *parameters,
934 GDBusMethodInvocation *invocation,
938 if (g_strcmp0(method_name, "ReadValue") == 0) {
939 struct hal_ev_gatt_server_read_req ev;
944 struct gatt_client_info_t *conn_info = NULL;
945 struct gatt_req_info *req_info = NULL;
946 struct gatt_service_info *svc_info = NULL;
950 DBG("Application path = %s", object_path);
951 DBG("Sender = %s", sender);
953 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
954 if (svc_info == NULL) {
955 ERR("Coudn't find service for %s", object_path);
956 g_dbus_method_invocation_return_value(invocation, NULL);
960 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
961 DBG("Request id = %u, Offset = %u", req_id, offset);
963 /* Check if device is already in connected list */
964 conn_info = __bt_find_remote_gatt_client_info(addr);
966 if (conn_info == NULL) {
967 ERR("Coudn't find Connection info for %s", addr);
968 g_dbus_method_invocation_return_value(invocation, NULL);
973 ERR("GATT callback NOT registered");
974 g_dbus_method_invocation_return_value(invocation, NULL);
978 /* Store requests information */
979 req_info = g_new0(struct gatt_req_info, 1);
980 req_info->attr_path = g_strdup(object_path);
981 req_info->svc_path = g_strdup(svc_info->serv_path);
982 req_info->request_id = req_id;
983 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
984 req_info->offset = offset;
985 req_info->context = invocation;
987 /* Append request info in list of requests for the particular connection */
988 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
991 memset(&ev, 0, sizeof(ev));
992 ev.conn_id = conn_info->connection_id;
993 ev.trans_id = req_id;
994 ev.att_handle = desc_hdl;
996 ev.is_long = false; /* TODO*/
998 /* Convert address to hex */
999 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1001 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1003 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1005 GVariant *var = NULL;
1009 gboolean response_needed = FALSE;
1010 struct hal_ev_gatt_server_write_req ev;
1014 struct gatt_service_info *svc_info = NULL;
1015 struct gatt_client_info_t *conn_info = NULL;
1016 struct gatt_req_info *req_info = NULL;
1018 memset(&ev, 0, sizeof(ev));
1021 DBG("Application path = %s", object_path);
1022 DBG("Sender = %s", sender);
1024 g_variant_get(parameters, "(&suqb@ay)",
1025 &addr, &req_id, &offset, &response_needed, &var);
1026 DBG("Request id = %u, Offset = %u", req_id, offset);
1028 /* Check if device is already in connected list */
1029 conn_info = __bt_find_remote_gatt_client_info(addr);
1031 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1033 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1034 g_variant_unref(var);
1035 if (response_needed)
1036 g_dbus_method_invocation_return_value(invocation, NULL);
1038 g_object_unref(invocation);
1042 len = g_variant_get_size(var);
1043 if (len > 0 && len < 600) {
1045 data = (char *)g_variant_get_data(var);
1046 memcpy(ev.value, data, len);
1049 if (response_needed) {
1050 /* Store request information */
1051 req_info = g_new0(struct gatt_req_info, 1);
1052 req_info->attr_path = g_strdup(object_path);
1053 req_info->svc_path = g_strdup(svc_info->serv_path);
1054 req_info->request_id = req_id;
1055 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1056 req_info->offset = offset;
1057 req_info->context = invocation;
1059 /* Append request info in list of requests for the particular connection */
1060 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1062 g_object_unref(invocation);
1065 /* Send HAL event */
1066 ev.conn_id = conn_info->connection_id;
1067 ev.trans_id = req_id;
1068 ev.att_handle = desc_hdl;
1070 ev.need_rsp = response_needed;
1073 /* Convert address to hex */
1074 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1076 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1078 g_variant_unref(var);
1083 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1084 const gchar *sender,
1085 const gchar *object_path,
1086 const gchar *interface_name,
1087 const gchar *method_name,
1088 GVariant *parameters,
1089 GDBusMethodInvocation *invocation,
1092 if (g_strcmp0(method_name, "ReadValue") == 0) {
1096 struct hal_ev_gatt_server_read_req ev;
1099 struct gatt_req_info *req_info = NULL;
1100 struct gatt_client_info_t *conn_info = NULL;
1101 struct gatt_service_info *svc_info = NULL;
1103 g_variant_get(parameters, "(&suq)",
1104 &addr, &req_id, &offset);
1106 DBG("Request id = %u, Offset = %u", req_id, offset);
1107 DBG("Application path = %s", object_path);
1108 DBG("Sender = %s", sender);
1109 DBG("Address = %s", addr);
1111 /* Check if device is already in connected list */
1112 conn_info = __bt_find_remote_gatt_client_info(addr);
1114 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1116 if (svc_info == NULL || conn_info == NULL) {
1117 g_dbus_method_invocation_return_value(invocation, NULL);
1122 ERR("GATT callback NOT registered");
1123 g_dbus_method_invocation_return_value(invocation, NULL);
1127 /* Store requets information */
1128 req_info = g_new0(struct gatt_req_info, 1);
1129 req_info->attr_path = g_strdup(object_path);
1130 req_info->svc_path = g_strdup(svc_info->serv_path);
1131 req_info->request_id = req_id;
1132 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1133 req_info->offset = offset;
1134 req_info->context = invocation;
1136 /* Append request info in list of requests for the particular connection */
1137 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1139 /* Send HAL event */
1140 memset(&ev, 0, sizeof(ev));
1141 ev.conn_id = conn_info->connection_id;
1142 ev.trans_id = req_id;
1143 ev.att_handle = char_hdl;
1145 ev.is_long = false; /* TODO*/
1147 /* Convert address to hex */
1148 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1149 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1151 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1152 GVariant *var = NULL;
1156 gboolean response_needed = FALSE;
1157 struct hal_ev_gatt_server_write_req ev;
1161 struct gatt_service_info *svc_info = NULL;
1162 struct gatt_req_info *req_info = NULL;
1163 struct gatt_client_info_t *conn_info = NULL;
1165 memset(&ev, 0, sizeof(ev));
1168 DBG("Application path = %s", object_path);
1169 DBG("Sender = %s", sender);
1171 g_variant_get(parameters, "(&suqb@ay)",
1172 &addr, &req_id, &offset, &response_needed, &var);
1173 DBG("Request id = %u, Offset = %u", req_id, offset);
1175 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1177 /* Check if device is already in connected list */
1178 conn_info = __bt_find_remote_gatt_client_info(addr);
1180 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1181 g_variant_unref(var);
1182 if (response_needed)
1183 g_dbus_method_invocation_return_value(invocation, NULL);
1185 g_object_unref(invocation);
1189 len = g_variant_get_size(var);
1190 if (len > 0 && len < 600) {
1192 data = (char *)g_variant_get_data(var);
1193 memcpy(ev.value, data, len);
1197 if (response_needed) {
1198 /* Store requets information */
1199 req_info = g_new0(struct gatt_req_info, 1);
1200 req_info->attr_path = g_strdup(object_path);
1201 req_info->svc_path = g_strdup(svc_info->serv_path);
1202 req_info->request_id = req_id;
1203 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1204 req_info->offset = offset;
1205 req_info->context = invocation;
1207 /* Append request info in list of requests for the particular connection */
1208 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1211 g_object_unref(invocation);
1214 /* Send HAL event */
1215 ev.conn_id = conn_info->connection_id;
1216 ev.trans_id = req_id;
1217 ev.att_handle = char_hdl;
1219 ev.need_rsp = response_needed;
1222 /* Convert address to hex */
1223 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1225 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1227 g_variant_unref(var);
1230 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1233 struct gatt_service_info *svc_info = NULL;
1234 struct hal_ev_gatt_server_notifcation_change ev;
1237 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1238 if (svc_info == NULL || event_cb == NULL)
1241 /* Send HAL event */
1242 memset(&ev, 0, sizeof(ev));
1243 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1244 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1245 ev.att_handle = char_hdl;
1248 /* Convert address to hex */
1249 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1251 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1254 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1257 struct gatt_service_info *svc_info = NULL;
1258 struct hal_ev_gatt_server_notifcation_change ev;
1261 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1262 if (svc_info == NULL || event_cb == NULL)
1265 /* Send HAL event */
1266 memset(&ev, 0, sizeof(ev));
1267 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1268 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1269 ev.att_handle = char_hdl;
1272 /* Convert address to hex */
1273 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1275 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1278 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1280 gboolean complete = FALSE;
1283 struct gatt_service_info *svc_info = NULL;
1284 struct gatt_client_info_t *conn_info = NULL;
1286 struct hal_ev_gatt_server_indicate_cfm ev;
1288 DBG("IndicateConfirm");
1289 DBG("Application path = %s", object_path);
1290 DBG("Sender = %s", sender);
1292 g_variant_get(parameters, "(&sb)", &addr, &complete);
1293 DBG("Remote Device address number = %s", addr);
1294 DBG("Is Indicate confirmation for last device [%d]", complete);
1296 /* Check if device is already in connected list */
1297 conn_info = __bt_find_remote_gatt_client_info(addr);
1299 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1301 if (svc_info == NULL || conn_info == NULL
1302 || event_cb == NULL) {
1306 /* Send HAL event */
1307 memset(&ev, 0, sizeof(ev));
1308 ev.conn_id = conn_info->connection_id;
1309 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1310 ev.att_handle = char_hdl;
1312 /* Convert address to hex */
1313 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1315 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1316 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1320 struct hal_ev_gatt_server_acquire_write_res ev;
1321 struct gatt_service_info *svc_info = NULL;
1322 struct gatt_req_info *req_info = NULL;
1323 struct gatt_client_info_t *conn_info = NULL;
1324 char * dev_path = NULL;
1326 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1328 DBG("AcquireWrite");
1329 DBG("Application path = %s", object_path);
1330 DBG("Sender = %s", sender);
1333 g_variant_get(parameters, "(a{sv})", &iter);
1335 GVariant* value = NULL;
1336 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1337 if (g_strcmp0(key, "MTU") == 0)
1338 g_variant_get(value, "i", &mtu);
1339 else if (g_strcmp0(key, "link") == 0)
1340 g_variant_get(value, "s", &link);
1341 else if (g_strcmp0(key, "device") == 0)
1342 g_variant_get(value, "o", &dev_path);
1345 DBG("AcquireWrite values retived");
1346 DBG(" path %s LINK = %s, MTU = %u", addr, link, mtu);
1348 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1350 _bt_hal_convert_device_path_to_address(dev_path, addr);
1352 DBG("remote address %s", addr);
1354 /* Check if device is already in connected list */
1355 conn_info = __bt_find_remote_gatt_client_info(addr);
1357 if (conn_info == NULL) {
1358 ERR("Cleint info not found\n");
1362 if (svc_info == NULL) {
1363 ERR("svc_info info not found\n");
1367 /* Store requets information */
1368 req_info = g_new0(struct gatt_req_info, 1);
1369 req_info->attr_path = g_strdup(object_path);
1370 req_info->svc_path = g_strdup(svc_info->serv_path);
1371 req_info->request_id = conn_info->connection_id;
1372 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1373 req_info->offset = mtu;
1374 req_info->context = invocation;
1376 /* Append request info in list of requests for the particular connection */
1377 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1379 /* Send HAL event */
1380 memset(&ev, 0, sizeof(ev));
1381 ev.conn_id = conn_info->connection_id;
1382 ev.char_handl = char_hdl;
1384 ev.trans_id = conn_info->connection_id;
1385 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1386 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1388 DBG("HAL_EV_GATT_ACQUIRE_WRITE_RES called");
1392 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1396 struct hal_ev_gatt_server_acquire_notify ev;
1397 struct gatt_service_info *svc_info = NULL;
1398 struct gatt_client_info_t *conn_info = NULL;
1399 struct gatt_req_info *req_info = NULL;
1401 DBG("AcquireNotify");
1402 DBG("Application path = %s", object_path);
1403 DBG("Sender = %s", sender);
1406 g_variant_get(parameters, "(a{sv})", &iter);
1408 GVariant* value = NULL;
1409 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1410 if (g_strcmp0(key, "MTU") == 0)
1411 g_variant_get(value, "q", &mtu);
1414 DBG("AcquireNotify values retived");
1415 DBG(" MTU = %u", mtu);
1417 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1419 if (svc_info == NULL) {
1420 ERR("svc_info info not found\n");
1424 /* Store requets information */
1425 req_info = g_new0(struct gatt_req_info, 1);
1426 req_info->attr_path = g_strdup(object_path);
1427 req_info->svc_path = g_strdup(svc_info->serv_path);
1428 req_info->request_id = 33;
1429 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1430 req_info->offset = mtu;
1431 req_info->context = invocation;
1433 conn_info = g_new0(struct gatt_client_info_t, 1);
1434 conn_info->addr = g_strdup(object_path);
1435 INFO("Added GATT client path[%s]", conn_info->addr);
1436 conn_info->connection_id = 33;
1437 conn_info->instance_id = 33;
1438 /* Append request info in list of requests for the particular connection */
1439 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1440 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1442 /* Send HAL event */
1443 memset(&ev, 0, sizeof(ev));
1445 ev.char_handl = char_hdl;
1449 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1451 DBG("HAL_EV_GATT_ACQUIRE_NOTIFY_RES called");
1457 g_dbus_method_invocation_return_value(invocation, NULL);
1460 static gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1463 GError *error = NULL;
1464 GVariantBuilder *array_builder;
1466 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1467 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1468 g_variant_builder_add(array_builder, "s", interface);
1470 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1471 "org.freedesktop.Dbus.Objectmanager",
1472 "InterfacesRemoved",
1473 g_variant_new("(oas)",
1474 object_path, array_builder),
1478 if (error != NULL) {
1479 /* dbus gives error cause */
1480 ERR("d-bus api failure: errcode[%x], message[%s]",
1481 error->code, error->message);
1482 g_clear_error(&error);
1485 g_variant_builder_unref(array_builder);
1490 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1497 g_free(desc_info->desc_path);
1498 g_free(desc_info->desc_uuid);
1499 g_free(desc_info->desc_value);
1501 for (i = 0; i < desc_info->flags_length; i++)
1502 g_free(desc_info->desc_flags[i]);
1507 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1514 g_free(char_info->char_path);
1515 g_free(char_info->char_uuid);
1516 g_free(char_info->char_value);
1518 for (i = 0; i < char_info->flags_length; i++)
1519 g_free(char_info->char_flags[i]);
1525 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1530 g_free(svc_info->serv_path);
1531 g_free(svc_info->service_uuid);
1535 static const GDBusInterfaceVTable desc_interface_vtable = {
1536 __bt_gatt_desc_method_call,
1541 static const GDBusInterfaceVTable char_interface_vtable = {
1542 __bt_gatt_char_method_call,
1547 static const GDBusInterfaceVTable serv_interface_vtable = {
1553 static const GDBusInterfaceVTable manager_interface_vtable = {
1554 __bt_gatt_manager_method_call,
1560 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1561 const gchar *introspection_data)
1564 GDBusNodeInfo *node_info = NULL;
1566 if (introspection_data == NULL)
1570 DBG("Create new node info");
1571 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1574 ERR("Unable to create node: %s", err->message);
1575 g_clear_error(&err);
1582 /* To send stack event to hal-av handler */
1583 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1588 void _bt_hal_unregister_gatt_server_handler_cb(void)
1593 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1595 struct hal_ev_gatt_desc_added ev;
1596 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1598 /* Prepare to GATT characteristic added event */
1599 memset(&ev, 0, sizeof(ev));
1600 ev.status = BT_STATUS_SUCCESS;
1601 ev.server_instance = data->instance_data;
1602 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1603 ev.service_handle = data->srvc_hdl;
1604 ev.desc_handle = data->desc_hdl;
1607 ERR("GATT Descriptor Added callback registered");
1609 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1610 data->instance_data, data->srvc_hdl, data->desc_hdl);
1612 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1619 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1621 struct hal_ev_gatt_char_added ev;
1622 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1624 /* Prepare to GATT characteristic added event */
1625 memset(&ev, 0, sizeof(ev));
1626 ev.status = BT_STATUS_SUCCESS;
1627 ev.server_instance = data->instance_data;
1628 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1629 ev.service_handle = data->srvc_hdl;
1630 ev.char_handle = data->char_hdl;
1633 ERR("GATT Characteristic Added callback registered");
1635 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1636 data->instance_data, data->srvc_hdl, data->char_hdl);
1638 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1645 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1647 struct hal_ev_gatt_service_added ev;
1648 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1650 /* Prepare to GATT Service added event */
1651 memset(&ev, 0, sizeof(ev));
1652 ev.status = BT_STATUS_SUCCESS;
1653 ev.server_instance = data->instance_data;
1654 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1655 ev.service_handle = data->srvc_hdl;
1656 ev.is_primary = data->is_primary;
1659 ERR("GATT Service Added callback registered");
1661 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1662 data->instance_data, data->srvc_hdl);
1663 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1670 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1672 struct hal_ev_gatt_service_started ev;
1673 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1675 /* Prepare to GATT Service added event */
1676 memset(&ev, 0, sizeof(ev));
1677 ev.status = BT_STATUS_SUCCESS;
1678 ev.server_instance = data->instance_data;
1679 ev.service_handle = data->srvc_hdl;
1682 ERR("GATT Service Started callback registered");
1684 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1685 data->instance_data, data->srvc_hdl);
1686 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1693 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1695 struct hal_ev_gatt_service_deleted ev;
1696 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1698 /* Prepare to GATT Service added event */
1699 memset(&ev, 0, sizeof(ev));
1700 ev.status = BT_STATUS_SUCCESS;
1701 ev.server_instance = data->instance_data;
1702 ev.service_handle = data->srvc_hdl;
1705 ERR("GATT Service Deleted callback registered");
1707 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1708 data->instance_data, data->srvc_hdl);
1709 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1716 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1718 struct hal_ev_server_instance_registered ev;
1719 hal_register_server_data *data = (hal_register_server_data*) user_data;
1721 /* Prepare to send AV connecting event */
1722 memset(&ev, 0, sizeof(ev));
1723 ev.status = BT_STATUS_SUCCESS;
1724 ev.server_instance = data->instance_data;
1725 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1728 ERR("GATT Register Server Instance Callback not registered");
1730 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1731 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1738 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1740 CHECK_BTGATT_INIT();
1741 int status = BT_STATUS_FAIL;
1743 DBG("Register server instance request");
1744 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1746 /* Check if slot available */
1747 server_if = _bt_hal_get_available_adv_slot_id(uuid, FALSE);
1749 if (server_if == -1) {
1750 ERR("Allocation of server instance failed");
1754 user_data->instance_data = server_if;
1755 DBG("Allocated new Advertising slot with Stack [%d]", user_data->instance_data);
1759 * As we need to provide async callback to user from HAL, simply schedule a
1760 * callback method which will carry actual result
1762 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1763 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1765 /* If available, then return success, else return error */
1766 return BT_STATUS_SUCCESS;
1769 static void _bt_hal_remove_gatt_server_from_list(int server_if)
1772 struct gatt_server_app *info = NULL;
1774 for (l = gatt_server_apps; l != NULL;) {
1775 info = (struct gatt_server_app*)l->data;
1776 l = g_slist_next(l);
1779 if (info->slot == server_if) {
1780 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1781 info->app_path, info->slot);
1783 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1784 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1785 In above case, only advertising block will be deallocated, Gatt Server will remain
1787 if (info->services == NULL) {
1788 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1789 INFO("Total gatt server apps still existing after removing above is [%d]",
1790 g_slist_length(gatt_server_apps));
1792 /* DBUS Unregister only for current app */
1793 __bt_hal_gatt_deinit(info->app_path);
1795 g_free(info->app_path);
1799 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1800 g_slist_length(info->services));
1806 static bt_status_t gatt_server_unregister_app(int server_if)
1808 CHECK_BTGATT_INIT();
1809 DBG("Un-Register server instance request [%d]", server_if);
1811 if (_bt_hal_is_advertising_in_slot(server_if) == FALSE)
1812 _bt_hal_free_server_slot(server_if);
1814 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
1815 _bt_hal_remove_gatt_server_from_list(server_if);
1816 return BT_STATUS_SUCCESS;
1819 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
1821 CHECK_BTGATT_INIT();
1822 return BT_STATUS_SUCCESS;
1825 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
1828 GError *g_error = NULL;
1829 GVariant *reply = NULL;
1833 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
1834 g_object_unref(proxy);
1835 if (reply == NULL) {
1836 ERR("Disconnect LE Dbus Call Error");
1838 ERR("Error: %s\n", g_error->message);
1839 g_clear_error(&g_error);
1842 g_variant_unref(reply);
1846 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
1848 CHECK_BTGATT_INIT();
1850 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
1852 GDBusProxy *device_proxy;
1853 GDBusConnection *g_conn;
1854 struct gatt_client_info_t *conn_info = NULL;
1858 if (NULL == bd_addr) {
1859 ERR("bd_addr is NULL");
1860 return BT_STATUS_PARM_INVALID;
1863 /* GDBUS Connection Info validate */
1864 g_conn = _bt_hal_get_system_gconn();
1865 if (g_conn == NULL) {
1866 ERR("Could not get System DBUS Connection");
1867 return BT_STATUS_FAIL;
1870 /* Connection Info validate */
1871 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
1872 if (conn_info == NULL) {
1873 ERR("No Connection Inforamtion!!!");
1874 return BT_STATUS_FAIL;
1877 _bt_hal_convert_addr_type_to_string(device_address,
1878 (unsigned char *)bd_addr->address);
1880 //check if connection has the same device address
1881 if (g_strcmp0(conn_info->addr, device_address) != 0) {
1882 ERR("device address [%s] does not match", device_address);
1883 return BT_STATUS_FAIL;
1886 device_path = _bt_hal_get_device_object_path(conn_info->addr);
1887 if (device_path == NULL) {
1888 ERR("device_path is NULL");
1889 return BT_STATUS_PARM_INVALID;
1892 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
1893 NULL, BT_HAL_BLUEZ_NAME,
1894 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
1897 g_free(device_path);
1898 if (device_proxy == NULL)
1899 return BT_STATUS_FAIL;
1901 INFO("Disconnect LE [%s]", device_address);
1903 g_dbus_proxy_call(device_proxy, "DisconnectLE",
1905 G_DBUS_CALL_FLAGS_NONE,
1906 BT_HAL_MAX_DBUS_TIMEOUT,
1908 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
1911 return BT_STATUS_SUCCESS;
1914 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
1919 uuid = btuuid2str(srvc_id->uu);
1920 DBG("Original UUID [%s]", uuid);
1922 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
1923 /* Extract Standard UUID string */
1924 memcpy(uuid_buf, &uuid[4], 4);
1926 DBG("Converted string [%s]", uuid_buf);
1927 return g_strdup(uuid_buf);
1929 return strdup(uuid);
1932 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
1935 /* For GATT service specific */
1936 GDBusNodeInfo *node_info;
1939 struct gatt_service_info *serv_info = NULL;
1940 GVariantBuilder *builder = NULL;
1941 GVariantBuilder *builder1 = NULL;
1942 GVariantBuilder *inner_builder = NULL;
1943 gboolean svc_primary = TRUE;
1944 GError *error = NULL;
1945 hal_gatt_service_added *user_data = NULL;
1946 DBG("Service add to DBUS slot [%d]", slot);
1948 node_info = __bt_gatt_create_method_node_info(
1949 service_introspection_xml);
1951 if (node_info == NULL)
1952 return BT_STATUS_FAIL;
1954 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
1955 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
1956 DBG("gatt service path is [%s]", path);
1958 object_id = g_dbus_connection_register_object(g_conn, path,
1959 node_info->interfaces[0],
1960 &serv_interface_vtable,
1961 NULL, NULL, &error);
1963 if (object_id == 0) {
1964 ERR("failed to register: %s", error->message);
1965 g_error_free(error);
1967 return BT_STATUS_FAIL;
1969 /* Add object_id/gatt service information; it's required at the time of
1970 * service unregister and Getmanagedobjects
1972 serv_info = g_new0(struct gatt_service_info, 1);
1974 serv_info->serv_path = g_strdup(path);
1975 serv_info->serv_id = object_id;
1976 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
1977 serv_info->is_svc_registered = FALSE;
1978 serv_info->is_svc_primary = svc_primary;
1979 DBG("Service Handle to be added is [%d]", gatt_service_handle);
1980 serv_info->service_handle = gatt_service_handle;
1982 /* Update service in GATT Server service List */
1983 gatt_services = g_slist_append(gatt_services, serv_info);
1985 /* emit interfacesadded signal here for service path */
1986 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1987 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1989 g_variant_builder_add(inner_builder, "{sv}",
1990 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
1992 g_variant_builder_add(inner_builder, "{sv}",
1993 "Primary", g_variant_new_boolean(svc_primary));
1995 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1997 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1998 g_variant_new("ao", builder1));
2000 g_variant_builder_add(builder, "{sa{sv}}",
2001 GATT_SERV_INTERFACE, inner_builder);
2003 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2004 "org.freedesktop.Dbus.ObjectManager",
2006 g_variant_new("(oa{sa{sv}})",
2011 /* dbus gives error cause */
2012 ERR("d-bus api failure: errcode[%x], message[%s]",
2013 error->code, error->message);
2014 g_clear_error(&error);
2018 /* Send Service handle to application */
2019 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2020 user_data->srvc_hdl = serv_info->service_handle;
2021 user_data->instance_data = slot;
2022 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2023 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2025 /* Save newly created service in GATT Server's service list */
2026 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2030 g_variant_builder_unref(inner_builder);
2031 g_variant_builder_unref(builder);
2032 g_variant_builder_unref(builder1);
2033 return BT_STATUS_SUCCESS;
2036 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2039 char *app_path = (char*)user_data;
2040 INFO("UnregisterApplication is completed app [%s]", app_path);
2041 GError *error = NULL;
2042 GVariant *result = NULL;
2045 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2047 if (result == NULL) {
2048 /* dBUS-RPC is failed */
2049 ERR("Dbus-RPC is failed\n");
2051 if (error != NULL) {
2052 /* dBUS gives error cause */
2053 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2054 error->code, error->message);
2055 g_clear_error(&error);
2058 g_variant_unref(result);
2063 static void __bt_hal_gatt_deinit(char *app_path)
2065 GDBusProxy *proxy = NULL;
2069 /* Step1: Remove requested App */
2070 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2071 "/org/bluez/hci0", "org.bluez.GattManager1");
2076 INFO("UnregisterApplication : path [%s]", app_path);
2078 /* Async Call to Unregister Service */
2079 data = g_strdup(app_path);
2080 g_dbus_proxy_call(proxy,
2081 "UnregisterApplication",
2082 g_variant_new("(o)",
2084 G_DBUS_CALL_FLAGS_NONE, -1,
2086 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2089 /* If requested app is last GATT Server app, then clean all resources */
2090 if (gatt_server_apps == NULL) {
2091 INFO("All GATT servers are removed, clean all DBUS resources");
2093 /* unregister the exported interface for object manager */
2094 g_dbus_connection_unregister_object(g_conn, manager_id);
2096 g_bus_unown_name(owner_id);
2099 g_object_unref(manager_gproxy);
2100 manager_gproxy = NULL;
2106 static int __bt_hal_gatt_init(void)
2110 /* Only once for ALL GATT Servers */
2111 if (owner_id == 0) {
2115 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2118 ERR("Unable to connect to gdbus: %s", err->message);
2119 g_clear_error(&err);
2121 return BT_STATUS_FAIL;
2124 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2125 INFO("well-known name: %s", name);
2127 owner_id = g_bus_own_name_on_connection(g_conn, name,
2128 G_BUS_NAME_OWNER_FLAGS_NONE,
2129 NULL, NULL, NULL, NULL);
2131 INFO("Owner ID [%d]", owner_id);
2133 /* Only once for ALL GATT Servers */
2134 if (manager_node_info == NULL) {
2135 /* Register ObjectManager interface */
2136 manager_node_info = __bt_gatt_create_method_node_info(
2137 manager_introspection_xml);
2139 if (manager_node_info == NULL) {
2140 ERR("failed to get node info");
2141 return BT_STATUS_FAIL;
2146 return BT_STATUS_SUCCESS;
2149 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2153 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2154 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2155 if (app->slot == slot) {
2156 INFO("GATT Server app found app path [%s] instance [%d]",
2157 app->app_path, app->slot);
2158 *app_path = app->app_path;
2162 /* GATT Server not found */
2166 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2168 if (app_path == NULL)
2171 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2172 app->app_path = g_strdup(app_path);
2174 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2175 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2180 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2183 CHECK_BTGATT_INIT();
2184 char *app_path = NULL;
2185 GError *error = NULL;
2188 int result = BT_STATUS_SUCCESS;
2190 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2191 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2193 /* Check if this GATT server Application is already registered with DBUS */
2194 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2196 if (app_path != NULL) {
2197 DBG("GATT server path is already defined [%s]", app_path);
2198 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2200 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2201 result = __bt_hal_gatt_init();
2202 if (result != BT_STATUS_SUCCESS)
2205 /* Only once for each GATT Server */
2206 app_path = g_strdup_printf("/com/%d", server_if);
2208 app_id = g_malloc0(sizeof(int));
2209 *app_id = server_if;
2211 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2212 manager_node_info->interfaces[0],
2213 &manager_interface_vtable,
2214 (gpointer)app_id, NULL, &error);
2216 if (manager_id == 0) {
2217 ERR("failed to register: %s", error->message);
2218 g_error_free(error);
2221 INFO("manager_id [%d]", manager_id);
2223 /* For current GATT Server, app_path is created, save it in Table */
2224 _bt_hal_update_gatt_server_path(server_if, app_path);
2226 /* Add GATT Service to DBUS */
2227 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2233 INFO("Successfully added service");
2234 return BT_STATUS_SUCCESS;
2241 INFO("Service addition failed!!");
2242 return BT_STATUS_FAIL;
2245 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2246 int included_handle)
2248 CHECK_BTGATT_INIT();
2249 return BT_STATUS_SUCCESS;
2253 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2256 GSList *gatt_services = NULL;
2258 struct gatt_service_info *info = NULL;
2260 gatt_services = _bt_get_service_list_from_server(instance);
2262 len = g_slist_length(gatt_services);
2263 l = g_slist_nth(gatt_services, len -1);
2269 if (info->service_handle == service_handle)
2274 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2278 GSList *gatt_services = NULL;
2279 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2281 gatt_services = _bt_get_service_list_from_server(instance);
2283 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2284 struct gatt_service_info *info = l->data;
2285 INFO("Got one service with handle [%d]", info->service_handle);
2286 if (info->service_handle == service_handle)
2289 ERR("Gatt service with handle [%d] not found", service_handle);
2293 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2294 bt_uuid_t *uuid, int properties,
2298 GError *error = NULL;
2300 GDBusNodeInfo *node_info;
2302 GVariantBuilder *builder = NULL;
2303 GVariantBuilder *inner_builder = NULL;
2304 struct gatt_service_info *serv_info = NULL;
2305 struct gatt_char_info *char_info = NULL;
2306 GVariantBuilder *builder2 = NULL;
2307 GVariantBuilder *builder3 = NULL;
2308 GVariant *flags_val = NULL;
2310 char *char_flags[NUMBER_OF_FLAGS];
2312 hal_gatt_char_added *user_data = NULL;
2315 CHECK_BTGATT_INIT();
2316 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2317 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2319 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2320 if (serv_info == NULL)
2321 return BT_STATUS_FAIL;
2323 node_info = __bt_gatt_create_method_node_info(
2324 characteristics_introspection_xml);
2326 if (node_info == NULL)
2327 return BT_STATUS_FAIL;
2329 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2330 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2331 DBG("gatt characteristic path is [%s]", path);
2333 app_id = g_malloc0(sizeof(int));
2336 object_id = g_dbus_connection_register_object(g_conn, path,
2337 node_info->interfaces[0],
2338 &char_interface_vtable,
2339 (gpointer)app_id, NULL, &error);
2341 if (object_id == 0) {
2342 ERR("failed to register: %s", error->message);
2343 g_error_free(error);
2346 return BT_STATUS_FAIL;
2349 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2350 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2351 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2352 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2353 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2354 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2355 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2356 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2358 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2360 char_info = g_new0(struct gatt_char_info, 1);
2362 char_info->char_path = g_strdup(path);
2363 char_info->char_id = object_id;
2364 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2365 for (i = 0; i < flag_count; i++)
2366 char_info->char_flags[i] = char_flags[i];
2369 char_info->flags_length = flag_count;
2370 char_info->char_handle = gatt_char_handle;
2373 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2374 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2376 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2377 g_variant_new("s", char_info->char_uuid));
2378 g_variant_builder_add(inner_builder, "{sv}", "Service",
2379 g_variant_new("o", serv_info->serv_path));
2381 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2383 for (i = 0; i < flag_count; i++)
2384 g_variant_builder_add(builder2, "s", char_flags[i]);
2386 flags_val = g_variant_new("as", builder2);
2387 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2390 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2392 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2393 g_variant_new("ao", builder3));
2395 g_variant_builder_add(builder, "{sa{sv}}",
2396 GATT_CHAR_INTERFACE,
2399 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2400 "org.freedesktop.Dbus.ObjectManager",
2402 g_variant_new("(oa{sa{sv}})",
2407 /* dbus gives error cause */
2408 ERR("d-bus api failure: errcode[%x], message[%s]",
2409 error->code, error->message);
2410 g_clear_error(&error);
2414 //*char_path = g_strdup(path);
2419 /* Send Service handle to application */
2420 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2421 user_data->srvc_hdl = serv_info->service_handle;
2422 user_data->char_hdl = gatt_char_handle;
2423 user_data->instance_data = slot;
2424 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2425 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2427 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2428 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2433 g_variant_builder_unref(inner_builder);
2434 g_variant_builder_unref(builder);
2435 g_variant_builder_unref(builder2);
2436 g_variant_builder_unref(builder3);
2438 return BT_STATUS_SUCCESS;
2441 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2444 CHECK_BTGATT_INIT();
2446 // static int desc_id = 1;
2447 GError *error = NULL;
2449 GDBusNodeInfo *node_info;
2451 GVariantBuilder *builder = NULL;
2452 GVariantBuilder *inner_builder = NULL;
2454 struct gatt_char_info *char_info = NULL;
2455 struct gatt_desc_info *desc_info = NULL;
2456 struct gatt_service_info *serv_info = NULL;
2458 gchar **line_argv = NULL;
2460 char *char_path = NULL;
2463 GVariantBuilder *builder2 = NULL;
2464 GVariant *flags_val = NULL;
2466 char *desc_flags[NUMBER_OF_FLAGS];
2470 hal_gatt_desc_added *user_data = NULL;
2477 /* Fetch service data for the GATT server */
2478 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2479 if (serv_info == NULL)
2480 return BT_STATUS_FAIL;
2482 /* Fetch list of characteristics from the service info */
2483 l = serv_info->char_data;
2485 /* Fetch last char info from the characteristic list */
2486 char_info = g_slist_last(l)->data;
2487 if (char_info == NULL)
2488 return BT_STATUS_FAIL;
2490 /* Fetch characteristic path from char info */
2491 char_path = char_info->char_path;
2493 line_argv = g_strsplit_set(char_path, "/", 0);
2494 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2497 node_info = __bt_gatt_create_method_node_info(
2498 descriptor_introspection_xml);
2500 if (node_info == NULL) {
2501 g_strfreev(line_argv);
2503 return BT_STATUS_FAIL;
2506 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2508 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2509 DBG("gatt descriptor path is [%s]", path);
2511 app_id = g_malloc0(sizeof(int));
2514 object_id = g_dbus_connection_register_object(g_conn, path,
2515 node_info->interfaces[0],
2516 &desc_interface_vtable,
2517 (gpointer)app_id, NULL, &error);
2519 if (object_id == 0) {
2520 ERR("failed to register: %s", error->message);
2521 g_error_free(error);
2523 g_strfreev(line_argv);
2526 return BT_STATUS_FAIL;
2529 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2531 desc_info = g_new0(struct gatt_desc_info, 1);
2533 desc_info->desc_path = g_strdup(path);
2534 desc_info->desc_id = object_id;
2535 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2537 for (i = 0; i < flag_count; i++)
2538 desc_info->desc_flags[i] = desc_flags[i];
2540 desc_info->flags_length = flag_count;
2541 desc_info->desc_handle = gatt_desc_handle;
2544 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2545 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2547 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2548 g_variant_new("s", btuuid2str(uuid->uu)));
2549 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2550 g_variant_new("o", char_path));
2552 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2554 for (i = 0; i < flag_count; i++)
2555 g_variant_builder_add(builder2, "s", desc_flags[i]);
2557 flags_val = g_variant_new("as", builder2);
2558 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2561 g_variant_builder_add(builder, "{sa{sv}}",
2562 GATT_DESC_INTERFACE,
2565 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2566 "org.freedesktop.Dbus.ObjectManager",
2568 g_variant_new("(oa{sa{sv}})",
2571 if (error != NULL) {
2572 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2573 error->code, error->message);
2574 g_clear_error(&error);
2577 //*desc_path = g_strdup(path);
2579 /* Save newly created descriptor to GATT server's service's characteristic */
2580 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2582 /* Send descriptor handle to application */
2583 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2584 user_data->srvc_hdl = serv_info->service_handle;
2585 user_data->desc_hdl = gatt_desc_handle;
2586 user_data->instance_data = slot;
2587 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2588 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2593 g_strfreev(line_argv);
2594 g_variant_builder_unref(inner_builder);
2595 g_variant_builder_unref(builder);
2596 return BT_STATUS_SUCCESS;
2599 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2601 GError *error = NULL;
2603 char *data = (char*) user_data;
2604 INFO("RegisterApplication is completed path [%s]", data);
2606 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2608 if (result == NULL) {
2609 /* dBUS-RPC is failed */
2610 ERR("Dbus-RPC is failed\n");
2612 if (error != NULL) {
2613 /* dBUS gives error cause */
2614 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2615 error->code, error->message);
2616 g_clear_error(&error);
2619 g_variant_unref(result);
2624 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2625 const gchar *path, const gchar *interface)
2631 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2636 ERR("Unable to connect to gdbus: %s", err->message);
2637 g_clear_error(&err);
2642 proxy = g_dbus_proxy_new_sync(g_conn,
2643 G_DBUS_PROXY_FLAGS_NONE, NULL,
2645 interface, NULL, &err);
2649 ERR("Unable to create proxy: %s", err->message);
2650 g_clear_error(&err);
2654 manager_gproxy = proxy;
2659 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2660 const gchar *path, const gchar *interface)
2662 return (manager_gproxy) ? manager_gproxy :
2663 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2667 static void __bt_register_application_to_dbus(int slot)
2669 GDBusProxy *proxy = NULL;
2670 char *app_path = NULL;
2672 DBG("RegisterApplication slot [%d]", slot);
2674 /* It is impossible that app path is still not initialized */
2675 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2677 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2678 "/org/bluez/hci0", "org.bluez.GattManager1");
2680 data = g_strdup(app_path);
2681 g_dbus_proxy_call(proxy,
2682 "RegisterApplication",
2683 g_variant_new("(oa{sv})",
2685 G_DBUS_CALL_FLAGS_NONE, -1,
2687 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2689 INFO("GATT server started");
2692 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2694 CHECK_BTGATT_INIT();
2695 struct gatt_service_info *serv_info = NULL;
2696 hal_gatt_service_started *user_data = NULL;
2697 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2699 /* Fetch service data for the GATT server */
2700 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2701 if (serv_info == NULL)
2702 return BT_STATUS_FAIL;
2704 if (serv_info->is_svc_registered)
2705 DBG("service already registered \n");
2707 serv_info->is_svc_registered = TRUE;
2709 /* Send Service handle to application */
2710 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2711 user_data->srvc_hdl = serv_info->service_handle;
2712 user_data->instance_data = server_if;
2713 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2715 /* If this is nth Service that is started, then register application at this point */
2716 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2717 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2719 __bt_register_application_to_dbus(server_if);
2722 return BT_STATUS_SUCCESS;
2725 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2727 CHECK_BTGATT_INIT();
2728 INFO("Stop service successful");
2729 return BT_STATUS_SUCCESS;
2732 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2734 CHECK_BTGATT_INIT();
2735 struct gatt_service_info *serv_info = NULL;
2736 hal_gatt_service_deleted *user_data = NULL;
2739 int err = BT_STATUS_SUCCESS;
2740 int ret = BT_STATUS_SUCCESS;
2741 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2743 /* Fetch service data for the GATT server */
2744 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2745 if (serv_info == NULL) {
2746 ERR("Could not find service info svc handle [%d] server slot [%d]",
2747 service_handle, server_if);
2748 return BT_STATUS_FAIL;
2751 if (serv_info->is_svc_registered == FALSE) {
2752 ERR("service Not registered path [%s] handle [%d]",
2753 serv_info->serv_path, service_handle);
2756 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2757 struct gatt_char_info *char_info = l->data;
2759 if (char_info == NULL)
2762 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2763 struct gatt_desc_info *desc_info = l1->data;
2765 if (desc_info == NULL)
2768 ret = g_dbus_connection_unregister_object(g_conn,
2769 desc_info->desc_id);
2771 __bt_hal_gatt_emit_interface_removed(
2772 desc_info->desc_path,
2773 GATT_DESC_INTERFACE);
2775 err = BT_STATUS_FAIL;
2778 /* list remove & free */
2779 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2780 __bt_hal_gatt_free_descriptor_info(desc_info);
2783 g_slist_free(char_info->desc_data);
2784 char_info->desc_data = NULL;
2786 ret = g_dbus_connection_unregister_object(g_conn,
2787 char_info->char_id);
2789 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2790 GATT_CHAR_INTERFACE);
2793 err = BT_STATUS_FAIL;
2796 /* list remove & free */
2797 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2798 __bt_hal_gatt_free_characteristic_info(char_info);
2801 g_slist_free(serv_info->char_data);
2802 serv_info->char_data = NULL;
2804 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2806 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2807 GATT_SERV_INTERFACE);
2810 err = BT_STATUS_FAIL;
2813 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
2815 DBG("Unregistered the service on properties interface");
2817 /* Remove from global list */
2818 gatt_services = g_slist_remove(gatt_services, serv_info);
2819 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
2821 /* Remove from GATT Server's list of services */
2822 _bt_remote_service_from_gatt_server(server_if, service_handle);
2824 if (gatt_services == NULL)
2825 INFO("All GATT Services of all GATT Servers are unregistered");
2827 if (err == BT_STATUS_SUCCESS) {
2828 INFO("Send GATT Service deleted Event");
2829 /* Send Service handle to application */
2830 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
2831 user_data->srvc_hdl = serv_info->service_handle;
2832 user_data->instance_data = server_if;
2833 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
2836 /* Free the service */
2837 __bt_hal_gatt_free_service_info(serv_info);
2841 static gboolean __bt_gatt_get_service_state(const char *service_path)
2843 struct gatt_service_info *svc_info = NULL;
2845 for (l = gatt_services; l; l = g_slist_next(l)) {
2847 svc_info = (struct gatt_service_info *)l->data;
2850 if (!g_strcmp0(svc_info->serv_path, service_path)) {
2851 DBG("Return the state of the gatt service %d",
2852 svc_info->is_svc_registered);
2853 return svc_info->is_svc_registered;
2857 DBG("gatt service info is NULL");
2861 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
2862 int len, int confirm, char* p_value)
2864 CHECK_BTGATT_INIT();
2867 GVariantBuilder *outer_builder;
2868 GVariantBuilder *invalidated_builder;
2870 /* For Value update via PropertyChange */
2871 GVariantBuilder *outer_builder1;
2872 GVariantBuilder *inner_builder1;
2873 GVariantBuilder *invalidated_builder1;
2874 GVariant *update_value = NULL;
2876 /* Other variables */
2877 struct gatt_client_info_t *conn_info = NULL;
2878 gchar *serv_path = NULL;
2879 char *char_path = NULL;
2880 gchar **line_argv = NULL;
2881 gboolean notify = TRUE;
2882 gboolean ret = TRUE;
2883 int err = BT_STATUS_SUCCESS;
2885 GError *error = NULL;
2888 memset(addr, 0x00, sizeof(addr));
2890 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2891 if (conn_info == NULL) {
2892 ERR("No Connection Inforamtion!!!");
2893 return BT_STATUS_FAIL;
2896 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
2898 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
2899 if (char_path == NULL)
2900 return BT_STATUS_FAIL;
2902 line_argv = g_strsplit_set(char_path, "/", 0);
2903 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2905 if (!__bt_gatt_get_service_state(serv_path)) {
2906 DBG("service not registered for this characteristic \n");
2908 g_strfreev(line_argv);
2909 return BT_STATUS_FAIL;
2912 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2913 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2915 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2916 g_variant_new("b", notify));
2918 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
2919 DBG("Send Indication to Unicast addr [%s]", addr);
2921 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2922 g_variant_new("s", addr));
2924 DBG("Set characteristic Notification \n");
2925 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2927 "org.freedesktop.DBus.Properties",
2928 "PropertiesChanged",
2929 g_variant_new("(sa{sv}as)",
2930 "org.bluez.GattCharacteristic1",
2931 outer_builder, invalidated_builder),
2935 if (error != NULL) {
2936 ERR("D-Bus API failure: errCode[%x], \
2938 error->code, error->message);
2939 g_clear_error(&error);
2941 err = BT_STATUS_FAIL;
2944 g_variant_builder_unref(outer_builder);
2945 g_variant_builder_unref(invalidated_builder);
2948 /* Notifying Done, now update Value to Bluez via PropertyChanged */
2949 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2951 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2952 for (i = 0; i < len; i++)
2953 g_variant_builder_add(inner_builder1, "y", p_value[i]);
2955 update_value = g_variant_new("ay", inner_builder1);
2958 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2959 g_variant_builder_add(outer_builder1, "{sv}", "Value",
2962 DBG("Updating characteristic value \n");
2963 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2965 "org.freedesktop.DBus.Properties",
2966 "PropertiesChanged",
2967 g_variant_new("(sa{sv}as)",
2968 "org.bluez.GattCharacteristic1",
2969 outer_builder1, invalidated_builder1),
2973 if (error != NULL) {
2974 ERR("D-Bus API failure: errCode[%x], \
2976 error->code, error->message);
2977 g_clear_error(&error);
2979 err = BT_STATUS_FAIL;
2981 struct gatt_char_info *char_info = NULL;
2983 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
2984 if (char_info == NULL) {
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);
2991 return BT_STATUS_FAIL;
2994 char_info->value_length = len;
2996 char_info->char_value = (char *)realloc(char_info->char_value, len);
2997 if (char_info->char_value) {
2998 for (i = 0; i < len; i++)
2999 char_info->char_value[i] = p_value[i];
3004 g_strfreev(line_argv);
3005 g_variant_builder_unref(inner_builder1);
3006 g_variant_builder_unref(outer_builder1);
3007 g_variant_builder_unref(invalidated_builder1);
3012 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3013 int status, btgatt_response_t *response)
3015 CHECK_BTGATT_INIT();
3017 struct gatt_req_info *req_info = NULL;
3018 struct gatt_client_info_t *conn_info = NULL;
3021 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3023 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3024 if (conn_info == NULL) {
3025 ERR("No Connection Inforamtion!!!");
3026 return BT_STATUS_FAIL;
3029 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3030 if (req_info == NULL) {
3031 ERR("No Request Inforamtion!!!");
3032 return BT_STATUS_FAIL;
3035 if (status != BT_STATUS_SUCCESS) {
3036 ERR("resp_state is 0x%X", status);
3038 g_dbus_method_invocation_return_dbus_error(req_info->context,
3039 "org.bluez.Error.Failed", "Application Error");
3041 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3043 req_info->context = NULL;
3044 if (req_info->attr_path)
3045 g_free(req_info->attr_path);
3046 if (req_info->svc_path)
3047 g_free(req_info->svc_path);
3050 return BT_STATUS_SUCCESS;
3053 DBG("Reponse Value length [%d]", response->attr_value.len);
3054 DBG("Request type: [%d]", req_info->request_type);
3057 for (i = 0; i < response->attr_value.len; i++)
3058 DBG("Resonse [%d] = [0x%x]", i, response->attr_value.value[i]);
3060 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3061 GVariantBuilder *inner_builder = NULL;
3062 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3064 if (response->attr_value.len > 0) {
3065 for (i = 0; i < response->attr_value.len; i++)
3066 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3068 g_dbus_method_invocation_return_value(req_info->context,
3069 g_variant_new("(ay)", inner_builder));
3071 g_variant_builder_unref(inner_builder);
3073 g_dbus_method_invocation_return_value(req_info->context, NULL);
3075 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3077 req_info->context = NULL;
3078 if (req_info->attr_path)
3079 g_free(req_info->attr_path);
3080 if (req_info->svc_path)
3081 g_free(req_info->svc_path);
3084 return BT_STATUS_SUCCESS;
3088 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3089 int status, int fd, int mtu, void *fdlist)
3091 CHECK_BTGATT_INIT();
3093 struct gatt_req_info *req_info = NULL;
3094 struct gatt_client_info_t *conn_info = NULL;
3096 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3098 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3099 if (conn_info == NULL) {
3100 ERR("No Connection Inforamtion!!!");
3101 return BT_STATUS_FAIL;
3104 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3105 if (req_info == NULL) {
3106 ERR("No Request Inforamtion!!!");
3107 return BT_STATUS_FAIL;
3110 if (status != BT_STATUS_SUCCESS) {
3111 ERR("resp_state is 0x%X", status);
3113 g_dbus_method_invocation_return_dbus_error(req_info->context,
3114 "org.bluez.Error.Failed", "Application Error");
3116 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3118 req_info->context = NULL;
3119 if (req_info->attr_path)
3120 g_free(req_info->attr_path);
3121 if (req_info->svc_path)
3122 g_free(req_info->svc_path);
3125 return BT_STATUS_SUCCESS;
3129 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3131 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3132 g_dbus_method_invocation_return_value_with_unix_fd_list(
3133 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3135 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3137 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3138 g_dbus_method_invocation_return_value_with_unix_fd_list(
3139 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3142 g_dbus_method_invocation_return_value(req_info->context, NULL);
3144 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3146 req_info->context = NULL;
3147 if (req_info->attr_path)
3148 g_free(req_info->attr_path);
3149 if (req_info->svc_path)
3150 g_free(req_info->svc_path);
3153 return BT_STATUS_SUCCESS;
3157 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3158 int value_length, char* att_value)
3160 CHECK_BTGATT_INIT();
3162 /* Other variables */
3163 char *char_path = NULL;
3164 gboolean ret = TRUE;
3165 GError *error = NULL;
3167 GVariantBuilder *outer_builder;
3168 GVariantBuilder *inner_builder;
3169 GVariantBuilder *invalidated_builder;
3170 GVariant *update_value = NULL;
3171 int err = BT_STATUS_SUCCESS;
3173 gchar **line_argv = NULL;
3174 gchar *serv_path = NULL;
3176 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3177 if (char_path == NULL)
3178 return BT_STATUS_FAIL;
3180 line_argv = g_strsplit_set(char_path, "/", 0);
3181 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3183 if (!__bt_gatt_get_service_state(serv_path)) {
3184 DBG("service not registered for this characteristic \n");
3186 g_strfreev(line_argv);
3187 return BT_STATUS_FAIL;
3191 line_argv = g_strsplit_set(char_path, "/", 0);
3192 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3194 if (!__bt_gatt_get_service_state(serv_path)) {
3195 DBG("service not registered for this characteristic \n");
3197 g_strfreev(line_argv);
3198 return BT_STATUS_FAIL;
3201 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3202 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3204 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3205 for (i = 0; i < value_length; i++)
3206 g_variant_builder_add(inner_builder, "y", att_value[i]);
3208 update_value = g_variant_new("ay", inner_builder);
3210 g_variant_builder_add(outer_builder, "{sv}", "Value",
3213 DBG("Updating characteristic value \n");
3214 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3216 "org.freedesktop.DBus.Properties",
3217 "PropertiesChanged",
3218 g_variant_new("(sa{sv}as)",
3219 "org.bluez.GattCharacteristic1",
3220 outer_builder, invalidated_builder),
3224 if (error != NULL) {
3225 ERR("D-Bus API failure: errCode[%x], \
3227 error->code, error->message);
3228 g_clear_error(&error);
3230 err = BT_STATUS_FAIL;
3232 struct gatt_char_info *char_info = NULL;
3234 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3235 if (char_info == NULL) {
3237 g_strfreev(line_argv);
3238 g_variant_builder_unref(inner_builder);
3239 g_variant_builder_unref(outer_builder);
3240 g_variant_builder_unref(invalidated_builder);
3242 return BT_STATUS_FAIL;
3245 char_info->value_length = value_length;
3247 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3248 if (char_info->char_value) {
3249 for (i = 0; i < value_length; i++)
3250 char_info->char_value[i] = att_value[i];
3256 g_strfreev(line_argv);
3257 g_variant_builder_unref(inner_builder);
3258 g_variant_builder_unref(outer_builder);
3259 g_variant_builder_unref(invalidated_builder);
3264 static bt_status_t gatt_server_listen(int server_if, bool start)
3266 CHECK_BTGATT_INIT();
3267 /* Send Data to LE Module */
3268 return _bt_hal_enable_advertising(server_if, start, FALSE);
3271 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3272 bool include_txpower, int min_interval, int max_interval, int appearance,
3273 uint16_t manufacturer_len, char* manufacturer_data,
3274 uint16_t service_data_len, char* service_data,
3275 uint16_t service_uuid_len, char* service_uuid)
3277 CHECK_BTGATT_INIT();
3278 return BT_STATUS_SUCCESS;
3281 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3283 CHECK_BTGATT_INIT();
3284 /* Send Enable Advertising request to LE Module */
3285 return _bt_hal_enable_advertising(server_if, TRUE, TRUE);
3288 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3289 int chnl_map, int tx_power, int timeout_s)
3291 CHECK_BTGATT_INIT();
3293 /* Send Advertising parameters to LE Module */
3294 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3295 chnl_map, tx_power, timeout_s);
3298 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3300 CHECK_BTGATT_INIT();
3302 /* Send Data to LE Module */
3303 return _bt_hal_set_advertising_data(adv_param_setup);
3306 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3308 CHECK_BTGATT_INIT();
3309 /* Send Data to LE Module */
3310 return _bt_hal_enable_advertising(server_if, FALSE, TRUE);
3313 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3315 CHECK_BTGATT_INIT();
3316 char *object_path = NULL;
3318 GDBusProxy *device_proxy;
3319 GError *error = NULL;
3321 GVariant *tmp_value;
3322 GDBusConnection *conn;
3323 GVariant *result = NULL;
3324 int ret = BT_STATUS_SUCCESS;
3325 struct gatt_client_info_t *conn_info = NULL;
3328 if (mtu_size == NULL)
3329 return BT_STATUS_PARM_INVALID;
3331 /* GDBUS Connection Info validate */
3332 conn = _bt_hal_get_system_gconn();
3334 ERR("Could not get System DBUS Connection");
3335 return BT_STATUS_FAIL;
3338 /* Connection Info validate */
3339 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3340 if (conn_info == NULL) {
3341 ERR("No Connection Inforamtion!!!");
3342 return BT_STATUS_FAIL;
3346 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3347 if (object_path == NULL)
3348 return BT_STATUS_FAIL;
3350 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3351 NULL, BT_HAL_BLUEZ_NAME, object_path,
3352 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3354 g_free(object_path);
3355 if (device_proxy == NULL)
3356 return BT_STATUS_FAIL;
3358 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3359 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3360 G_DBUS_CALL_FLAGS_NONE,
3364 if (result == NULL) {
3365 if (error != NULL) {
3366 ERR("Error occured in Proxy call [%s]\n", error->message);
3367 g_error_free(error);
3369 g_object_unref(device_proxy);
3370 return BT_STATUS_FAIL;
3373 g_variant_get(result , "(@a{sv})", &value);
3374 g_variant_unref(result);
3376 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3377 if (tmp_value == NULL) {
3378 g_object_unref(device_proxy);
3379 g_variant_unref(value);
3380 return BT_STATUS_FAIL;
3383 mtu = g_variant_get_uint16(tmp_value);
3385 DBG("ATT MTU : [%d]", mtu);
3387 g_variant_unref(tmp_value);
3388 g_variant_unref(value);
3389 g_object_unref(device_proxy);
3391 *mtu_size = (int) mtu;
3396 const btgatt_server_interface_t btgatt_server_interface = {
3397 .register_server = gatt_server_register_app,
3398 .unregister_server = gatt_server_unregister_app,
3399 .connect = gatt_server_open,
3400 .disconnect = gatt_server_close,
3401 .add_service = gatt_server_add_service,
3402 .add_included_service = gatt_server_add_included_service,
3403 .add_characteristic = gatt_server_add_characteristic,
3404 .add_descriptor = gatt_server_add_descriptor,
3405 .start_service = gatt_server_start_service,
3406 .stop_service = gatt_server_stop_service,
3407 .delete_service = gatt_server_delete_service,
3408 .send_indication = gatt_server_send_indication,
3409 .send_response = gatt_server_send_response,
3410 .update_att_value = gatt_server_update_att_value,
3411 .listen = gatt_server_listen,
3412 .set_adv_data = gatt_server_set_adv_data,
3413 .multi_adv_enable = gatt_server_multi_adv_enable,
3414 .multi_adv_update = gatt_server_multi_adv_update,
3415 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3416 .multi_adv_disable = gatt_server_multi_adv_disable,
3417 .get_att_mtu = gatt_server_get_mtu_size,
3418 .send_response_acquire = gatt_server_send_acquire_response