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 notifyAcquired = TRUE;
750 flags_val = g_variant_new("as", builder2);
751 g_variant_builder_add(inner_builder, "{sv}", "Flags",
755 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
756 g_variant_new("b", notify));
759 if (writeAcquired == TRUE) {
760 DBG("adding writeAcquired property");
761 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
762 g_variant_new("b", writeAcquired));
766 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
767 g_variant_new("b", notifyAcquired));
770 unicast = g_strdup("00:00:00:00:00:00");
771 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
772 g_variant_new("s", unicast));
775 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
776 DBG("Adding Descriptors list");
778 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
779 struct gatt_desc_info *desc_info = l4->data;
780 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
781 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
782 g_variant_builder_add(builder3, "o",
783 desc_info->desc_path);
784 DBG("%s", desc_info->desc_path);
787 char_desc = g_variant_new("ao", builder3);
788 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
791 g_variant_builder_add(char_builder, "{sa{sv}}",
792 GATT_CHAR_INTERFACE , inner_builder);
793 g_variant_builder_add(builder, "{oa{sa{sv}}}",
794 char_info->char_path, char_builder);
796 /*Prepare inner builder for GattDescriptor1 interface*/
798 GSList *l3 = char_info->desc_data;
801 DBG("descriptor data is NULL");
803 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
805 DBG("Creating builder for descriptor \n");
807 GVariantBuilder *desc_builder = NULL;
808 GVariantBuilder *inner_builder = NULL;
809 GVariantBuilder *builder1 = NULL;
810 GVariantBuilder *builder2 = NULL;
811 GVariant *desc_val = NULL;
813 desc_builder = g_variant_builder_new(
816 inner_builder = g_variant_builder_new(
820 struct gatt_desc_info *desc_info = l3->data;
821 if (desc_info == NULL) {
822 ERR("desc_info is NULL");
827 g_variant_builder_add(inner_builder,
829 g_variant_new_string(
830 desc_info->desc_uuid));
833 g_variant_builder_add(inner_builder, "{sv}",
836 char_info->char_path));
839 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
841 if (desc_info->desc_value != NULL) {
842 for (i = 0; i < desc_info->value_length; i++) {
843 g_variant_builder_add(builder1, "y",
844 desc_info->desc_value[i]);
846 desc_val = g_variant_new("ay", builder1);
847 g_variant_builder_add(inner_builder, "{sv}",
852 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
854 for (i = 0; i < desc_info->flags_length; i++) {
855 g_variant_builder_add(builder2, "s",
856 desc_info->desc_flags[i]);
859 flags_val = g_variant_new("as", builder2);
860 g_variant_builder_add(inner_builder, "{sv}", "Flags",
863 g_variant_builder_add(desc_builder, "{sa{sv}}",
867 g_variant_builder_add(builder, "{oa{sa{sv}}}",
868 desc_info->desc_path,
871 /*unref descriptor builder pointers*/
872 g_variant_builder_unref(builder1);
873 g_variant_builder_unref(builder2);
874 g_variant_builder_unref(inner_builder);
875 g_variant_builder_unref(desc_builder);
880 /*unref char builder pointers*/
881 g_variant_builder_unref(builder1);
882 g_variant_builder_unref(builder2);
883 g_variant_builder_unref(builder3);
884 g_variant_builder_unref(inner_builder);
885 g_variant_builder_unref(char_builder);
888 /*unref service builder pointers*/
889 g_variant_builder_unref(inner_builder);
890 g_variant_builder_unref(svc_builder);
893 /* Return builder as method reply */
894 DBG("Sending gatt service builder values to Bluez");
895 g_dbus_method_invocation_return_value(invocation,
905 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
907 const gchar *object_path,
908 const gchar *interface_name,
909 const gchar *method_name,
910 GVariant *parameters,
911 GDBusMethodInvocation *invocation,
915 if (g_strcmp0(method_name, "ReadValue") == 0) {
916 struct hal_ev_gatt_server_read_req ev;
921 struct gatt_client_info_t *conn_info = NULL;
922 struct gatt_req_info *req_info = NULL;
923 struct gatt_service_info *svc_info = NULL;
927 DBG("Application path = %s", object_path);
928 DBG("Sender = %s", sender);
930 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
931 if (svc_info == NULL) {
932 ERR("Coudn't find service for %s", object_path);
933 g_dbus_method_invocation_return_value(invocation, NULL);
937 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
938 DBG("Request id = %u, Offset = %u", req_id, offset);
940 /* Check if device is already in connected list */
941 conn_info = __bt_find_remote_gatt_client_info(addr);
943 if (conn_info == NULL) {
944 ERR("Coudn't find Connection info for %s", addr);
945 g_dbus_method_invocation_return_value(invocation, NULL);
950 ERR("GATT callback NOT registered");
951 g_dbus_method_invocation_return_value(invocation, NULL);
955 /* Store requests information */
956 req_info = g_new0(struct gatt_req_info, 1);
957 req_info->attr_path = g_strdup(object_path);
958 req_info->svc_path = g_strdup(svc_info->serv_path);
959 req_info->request_id = req_id;
960 req_info->offset = offset;
961 req_info->context = invocation;
963 /* Append request info in list of requests for the particular connection */
964 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
967 memset(&ev, 0, sizeof(ev));
968 ev.conn_id = conn_info->connection_id;
969 ev.trans_id = req_id;
970 ev.att_handle = desc_hdl;
972 ev.is_long = false; /* TODO*/
974 /* Convert address to hex */
975 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
977 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
979 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
981 GVariant *var = NULL;
985 gboolean response_needed = FALSE;
986 struct hal_ev_gatt_server_write_req ev;
990 struct gatt_service_info *svc_info = NULL;
991 struct gatt_client_info_t *conn_info = NULL;
992 struct gatt_req_info *req_info = NULL;
994 memset(&ev, 0, sizeof(ev));
997 DBG("Application path = %s", object_path);
998 DBG("Sender = %s", sender);
1000 g_variant_get(parameters, "(&suqb@ay)",
1001 &addr, &req_id, &offset, &response_needed, &var);
1002 DBG("Request id = %u, Offset = %u", req_id, offset);
1004 /* Check if device is already in connected list */
1005 conn_info = __bt_find_remote_gatt_client_info(addr);
1007 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1009 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1010 g_variant_unref(var);
1011 if (response_needed)
1012 g_dbus_method_invocation_return_value(invocation, NULL);
1014 g_object_unref(invocation);
1018 len = g_variant_get_size(var);
1019 if (len > 0 && len < 600) {
1021 data = (char *)g_variant_get_data(var);
1022 memcpy(ev.value, data, len);
1025 if (response_needed) {
1026 /* Store request information */
1027 req_info = g_new0(struct gatt_req_info, 1);
1028 req_info->attr_path = g_strdup(object_path);
1029 req_info->svc_path = g_strdup(svc_info->serv_path);
1030 req_info->request_id = req_id;
1031 req_info->offset = offset;
1032 req_info->context = invocation;
1034 /* Append request info in list of requests for the particular connection */
1035 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1037 g_object_unref(invocation);
1040 /* Send HAL event */
1041 ev.conn_id = conn_info->connection_id;
1042 ev.trans_id = req_id;
1043 ev.att_handle = desc_hdl;
1045 ev.need_rsp = response_needed;
1048 /* Convert address to hex */
1049 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1051 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1053 g_variant_unref(var);
1058 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1059 const gchar *sender,
1060 const gchar *object_path,
1061 const gchar *interface_name,
1062 const gchar *method_name,
1063 GVariant *parameters,
1064 GDBusMethodInvocation *invocation,
1067 if (g_strcmp0(method_name, "ReadValue") == 0) {
1071 struct hal_ev_gatt_server_read_req ev;
1074 struct gatt_req_info *req_info = NULL;
1075 struct gatt_client_info_t *conn_info = NULL;
1076 struct gatt_service_info *svc_info = NULL;
1078 g_variant_get(parameters, "(&suq)",
1079 &addr, &req_id, &offset);
1081 DBG("Request id = %u, Offset = %u", req_id, offset);
1082 DBG("Application path = %s", object_path);
1083 DBG("Sender = %s", sender);
1084 DBG("Address = %s", addr);
1086 /* Check if device is already in connected list */
1087 conn_info = __bt_find_remote_gatt_client_info(addr);
1089 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1091 if (svc_info == NULL || conn_info == NULL) {
1092 g_dbus_method_invocation_return_value(invocation, NULL);
1097 ERR("GATT callback NOT registered");
1098 g_dbus_method_invocation_return_value(invocation, NULL);
1102 /* Store requets information */
1103 req_info = g_new0(struct gatt_req_info, 1);
1104 req_info->attr_path = g_strdup(object_path);
1105 req_info->svc_path = g_strdup(svc_info->serv_path);
1106 req_info->request_id = req_id;
1107 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1108 req_info->offset = offset;
1109 req_info->context = invocation;
1111 /* Append request info in list of requests for the particular connection */
1112 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1114 /* Send HAL event */
1115 memset(&ev, 0, sizeof(ev));
1116 ev.conn_id = conn_info->connection_id;
1117 ev.trans_id = req_id;
1118 ev.att_handle = char_hdl;
1120 ev.is_long = false; /* TODO*/
1122 /* Convert address to hex */
1123 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1124 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1126 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1127 GVariant *var = NULL;
1131 gboolean response_needed = FALSE;
1132 struct hal_ev_gatt_server_write_req ev;
1136 struct gatt_service_info *svc_info = NULL;
1137 struct gatt_req_info *req_info = NULL;
1138 struct gatt_client_info_t *conn_info = NULL;
1140 memset(&ev, 0, sizeof(ev));
1143 DBG("Application path = %s", object_path);
1144 DBG("Sender = %s", sender);
1146 g_variant_get(parameters, "(&suqb@ay)",
1147 &addr, &req_id, &offset, &response_needed, &var);
1148 DBG("Request id = %u, Offset = %u", req_id, offset);
1150 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1152 /* Check if device is already in connected list */
1153 conn_info = __bt_find_remote_gatt_client_info(addr);
1155 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1156 g_variant_unref(var);
1157 if (response_needed)
1158 g_dbus_method_invocation_return_value(invocation, NULL);
1160 g_object_unref(invocation);
1164 len = g_variant_get_size(var);
1165 if (len > 0 && len < 600) {
1167 data = (char *)g_variant_get_data(var);
1168 memcpy(ev.value, data, len);
1172 if (response_needed) {
1173 /* Store requets information */
1174 req_info = g_new0(struct gatt_req_info, 1);
1175 req_info->attr_path = g_strdup(object_path);
1176 req_info->svc_path = g_strdup(svc_info->serv_path);
1177 req_info->request_id = req_id;
1178 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1179 req_info->offset = offset;
1180 req_info->context = invocation;
1182 /* Append request info in list of requests for the particular connection */
1183 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1186 g_object_unref(invocation);
1189 /* Send HAL event */
1190 ev.conn_id = conn_info->connection_id;
1191 ev.trans_id = req_id;
1192 ev.att_handle = char_hdl;
1194 ev.need_rsp = response_needed;
1197 /* Convert address to hex */
1198 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1200 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1202 g_variant_unref(var);
1205 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1208 struct gatt_service_info *svc_info = NULL;
1209 struct hal_ev_gatt_server_notifcation_change ev;
1212 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1213 if (svc_info == NULL || event_cb == NULL)
1216 /* Send HAL event */
1217 memset(&ev, 0, sizeof(ev));
1218 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1219 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1220 ev.att_handle = char_hdl;
1223 /* Convert address to hex */
1224 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1226 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1229 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1232 struct gatt_service_info *svc_info = NULL;
1233 struct hal_ev_gatt_server_notifcation_change ev;
1236 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1237 if (svc_info == NULL || event_cb == NULL)
1240 /* Send HAL event */
1241 memset(&ev, 0, sizeof(ev));
1242 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1243 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1244 ev.att_handle = char_hdl;
1247 /* Convert address to hex */
1248 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1250 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1253 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1255 gboolean complete = FALSE;
1258 struct gatt_service_info *svc_info = NULL;
1259 struct gatt_client_info_t *conn_info = NULL;
1261 struct hal_ev_gatt_server_indicate_cfm ev;
1263 DBG("IndicateConfirm");
1264 DBG("Application path = %s", object_path);
1265 DBG("Sender = %s", sender);
1267 g_variant_get(parameters, "(&sb)", &addr, &complete);
1268 DBG("Remote Device address number = %s", addr);
1269 DBG("Is Indicate confirmation for last device [%d]", complete);
1271 /* Check if device is already in connected list */
1272 conn_info = __bt_find_remote_gatt_client_info(addr);
1274 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1276 if (svc_info == NULL || conn_info == NULL
1277 || event_cb == NULL) {
1281 /* Send HAL event */
1282 memset(&ev, 0, sizeof(ev));
1283 ev.conn_id = conn_info->connection_id;
1284 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1285 ev.att_handle = char_hdl;
1287 /* Convert address to hex */
1288 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1290 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1291 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1295 struct hal_ev_gatt_server_acquire_write_res ev;
1296 struct gatt_service_info *svc_info = NULL;
1297 struct gatt_req_info *req_info = NULL;
1298 struct gatt_client_info_t *conn_info = NULL;
1299 char * dev_path = NULL;
1301 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1303 DBG("AcquireWrite");
1304 DBG("Application path = %s", object_path);
1305 DBG("Sender = %s", sender);
1308 g_variant_get(parameters, "(a{sv})", &iter);
1310 GVariant* value = NULL;
1311 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1312 if (g_strcmp0(key, "MTU") == 0)
1313 g_variant_get(value, "i", &mtu);
1314 else if (g_strcmp0(key, "link") == 0)
1315 g_variant_get(value, "s", &link);
1316 else if (g_strcmp0(key, "device") == 0)
1317 g_variant_get(value, "o", &dev_path);
1320 DBG("AcquireWrite values retived");
1321 DBG(" path %s LINK = %s, MTU = %u", addr, link, mtu);
1323 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1325 _bt_hal_convert_device_path_to_address(dev_path, addr);
1327 DBG("remote address %s", addr);
1329 /* Check if device is already in connected list */
1330 conn_info = __bt_find_remote_gatt_client_info(addr);
1332 if (conn_info == NULL) {
1333 ERR("Cleint info not found\n");
1337 if (svc_info == NULL) {
1338 ERR("svc_info info not found\n");
1342 /* Store requets information */
1343 req_info = g_new0(struct gatt_req_info, 1);
1344 req_info->attr_path = g_strdup(object_path);
1345 req_info->svc_path = g_strdup(svc_info->serv_path);
1346 req_info->request_id = conn_info->connection_id;
1347 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1348 req_info->offset = mtu;
1349 req_info->context = invocation;
1351 /* Append request info in list of requests for the particular connection */
1352 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1354 /* Send HAL event */
1355 memset(&ev, 0, sizeof(ev));
1356 ev.conn_id = conn_info->connection_id;
1357 ev.char_handl = char_hdl;
1359 ev.trans_id = conn_info->connection_id;
1360 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1361 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1363 DBG("HAL_EV_GATT_ACQUIRE_WRITE_RES called");
1367 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1371 struct hal_ev_gatt_server_acquire_notify ev;
1372 struct gatt_service_info *svc_info = NULL;
1373 struct gatt_client_info_t *conn_info = NULL;
1374 struct gatt_req_info *req_info = NULL;
1376 DBG("AcquireNotify");
1377 DBG("Application path = %s", object_path);
1378 DBG("Sender = %s", sender);
1381 g_variant_get(parameters, "(a{sv})", &iter);
1383 GVariant* value = NULL;
1384 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1385 if (g_strcmp0(key, "MTU") == 0)
1386 g_variant_get(value, "q", &mtu);
1389 DBG("AcquireNotify values retived");
1390 DBG(" MTU = %u", mtu);
1392 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1394 if (svc_info == NULL) {
1395 ERR("svc_info info not found\n");
1399 /* Store requets information */
1400 req_info = g_new0(struct gatt_req_info, 1);
1401 req_info->attr_path = g_strdup(object_path);
1402 req_info->svc_path = g_strdup(svc_info->serv_path);
1403 req_info->request_id = 33;
1404 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1405 req_info->offset = mtu;
1406 req_info->context = invocation;
1408 conn_info = g_new0(struct gatt_client_info_t, 1);
1409 conn_info->addr = g_strdup(object_path);
1410 INFO("Added GATT client path[%s]", conn_info->addr);
1411 conn_info->connection_id = 33;
1412 conn_info->instance_id = 33;
1413 /* Append request info in list of requests for the particular connection */
1414 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1415 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1417 /* Send HAL event */
1418 memset(&ev, 0, sizeof(ev));
1420 ev.char_handl = char_hdl;
1424 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1426 DBG("HAL_EV_GATT_ACQUIRE_NOTIFY_RES called");
1432 g_dbus_method_invocation_return_value(invocation, NULL);
1435 static gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1438 GError *error = NULL;
1439 GVariantBuilder *array_builder;
1441 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1442 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1443 g_variant_builder_add(array_builder, "s", interface);
1445 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1446 "org.freedesktop.Dbus.Objectmanager",
1447 "InterfacesRemoved",
1448 g_variant_new("(oas)",
1449 object_path, array_builder),
1453 if (error != NULL) {
1454 /* dbus gives error cause */
1455 ERR("d-bus api failure: errcode[%x], message[%s]",
1456 error->code, error->message);
1457 g_clear_error(&error);
1460 g_variant_builder_unref(array_builder);
1465 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1472 g_free(desc_info->desc_path);
1473 g_free(desc_info->desc_uuid);
1474 g_free(desc_info->desc_value);
1476 for (i = 0; i < desc_info->flags_length; i++)
1477 g_free(desc_info->desc_flags[i]);
1482 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1489 g_free(char_info->char_path);
1490 g_free(char_info->char_uuid);
1491 g_free(char_info->char_value);
1493 for (i = 0; i < char_info->flags_length; i++)
1494 g_free(char_info->char_flags[i]);
1500 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1505 g_free(svc_info->serv_path);
1506 g_free(svc_info->service_uuid);
1510 static const GDBusInterfaceVTable desc_interface_vtable = {
1511 __bt_gatt_desc_method_call,
1516 static const GDBusInterfaceVTable char_interface_vtable = {
1517 __bt_gatt_char_method_call,
1522 static const GDBusInterfaceVTable serv_interface_vtable = {
1528 static const GDBusInterfaceVTable manager_interface_vtable = {
1529 __bt_gatt_manager_method_call,
1535 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1536 const gchar *introspection_data)
1539 GDBusNodeInfo *node_info = NULL;
1541 if (introspection_data == NULL)
1545 DBG("Create new node info");
1546 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1549 ERR("Unable to create node: %s", err->message);
1550 g_clear_error(&err);
1557 /* To send stack event to hal-av handler */
1558 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1563 void _bt_hal_unregister_gatt_server_handler_cb(void)
1568 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1570 struct hal_ev_gatt_desc_added ev;
1571 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1573 /* Prepare to GATT characteristic added event */
1574 memset(&ev, 0, sizeof(ev));
1575 ev.status = BT_STATUS_SUCCESS;
1576 ev.server_instance = data->instance_data;
1577 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1578 ev.service_handle = data->srvc_hdl;
1579 ev.desc_handle = data->desc_hdl;
1582 ERR("GATT Descriptor Added callback registered");
1584 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1585 data->instance_data, data->srvc_hdl, data->desc_hdl);
1587 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1594 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1596 struct hal_ev_gatt_char_added ev;
1597 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1599 /* Prepare to GATT characteristic added event */
1600 memset(&ev, 0, sizeof(ev));
1601 ev.status = BT_STATUS_SUCCESS;
1602 ev.server_instance = data->instance_data;
1603 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1604 ev.service_handle = data->srvc_hdl;
1605 ev.char_handle = data->char_hdl;
1608 ERR("GATT Characteristic Added callback registered");
1610 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1611 data->instance_data, data->srvc_hdl, data->char_hdl);
1613 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1620 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1622 struct hal_ev_gatt_service_added ev;
1623 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1625 /* Prepare to GATT Service added event */
1626 memset(&ev, 0, sizeof(ev));
1627 ev.status = BT_STATUS_SUCCESS;
1628 ev.server_instance = data->instance_data;
1629 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1630 ev.service_handle = data->srvc_hdl;
1631 ev.is_primary = data->is_primary;
1634 ERR("GATT Service Added callback registered");
1636 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1637 data->instance_data, data->srvc_hdl);
1638 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1645 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1647 struct hal_ev_gatt_service_started ev;
1648 hal_gatt_service_started *data = (hal_gatt_service_started*) 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 ev.service_handle = data->srvc_hdl;
1657 ERR("GATT Service Started callback registered");
1659 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1660 data->instance_data, data->srvc_hdl);
1661 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1668 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1670 struct hal_ev_gatt_service_deleted ev;
1671 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1673 /* Prepare to GATT Service added event */
1674 memset(&ev, 0, sizeof(ev));
1675 ev.status = BT_STATUS_SUCCESS;
1676 ev.server_instance = data->instance_data;
1677 ev.service_handle = data->srvc_hdl;
1680 ERR("GATT Service Deleted callback registered");
1682 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1683 data->instance_data, data->srvc_hdl);
1684 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1691 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1693 struct hal_ev_server_instance_registered ev;
1694 hal_register_server_data *data = (hal_register_server_data*) user_data;
1696 /* Prepare to send AV connecting event */
1697 memset(&ev, 0, sizeof(ev));
1698 ev.status = BT_STATUS_SUCCESS;
1699 ev.server_instance = data->instance_data;
1700 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1703 ERR("GATT Register Server Instance Callback not registered");
1705 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1706 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1713 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1715 CHECK_BTGATT_INIT();
1716 int status = BT_STATUS_FAIL;
1718 DBG("Register server instance request");
1719 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1721 /* Check if slot available */
1722 server_if = _bt_hal_get_available_adv_slot_id(uuid);
1724 if (server_if == -1) {
1725 ERR("Allocation of server instance failed");
1729 user_data->instance_data = server_if;
1730 DBG("Allocated new Advertising slot with Stack [%d]", user_data->instance_data);
1734 * As we need to provide async callback to user from HAL, simply schedule a
1735 * callback method which will carry actual result
1737 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1738 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1740 /* If available, then return success, else return error */
1741 return BT_STATUS_SUCCESS;
1744 static void _bt_hal_remove_gatt_server_from_list(int server_if)
1747 struct gatt_server_app *info = NULL;
1749 for (l = gatt_server_apps; l != NULL;) {
1750 info = (struct gatt_server_app*)l->data;
1751 l = g_slist_next(l);
1754 if (info->slot == server_if) {
1755 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1756 info->app_path, info->slot);
1758 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1759 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1760 In above case, only advertising block will be deallocated, Gatt Server will remain
1762 if (info->services == NULL) {
1763 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1764 INFO("Total gatt server apps still existing after removing above is [%d]",
1765 g_slist_length(gatt_server_apps));
1767 /* DBUS Unregister only for current app */
1768 __bt_hal_gatt_deinit(info->app_path);
1770 g_free(info->app_path);
1774 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1775 g_slist_length(info->services));
1781 static bt_status_t gatt_server_unregister_app(int server_if)
1783 CHECK_BTGATT_INIT();
1784 DBG("Un-Register server instance request [%d]", server_if);
1786 if (_bt_hal_is_advertising_in_slot(server_if) == FALSE)
1787 _bt_hal_free_server_slot(server_if);
1789 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
1790 _bt_hal_remove_gatt_server_from_list(server_if);
1791 return BT_STATUS_SUCCESS;
1794 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
1796 CHECK_BTGATT_INIT();
1797 return BT_STATUS_SUCCESS;
1800 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
1803 GError *g_error = NULL;
1804 GVariant *reply = NULL;
1808 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
1809 g_object_unref(proxy);
1810 if (reply == NULL) {
1811 ERR("Disconnect LE Dbus Call Error");
1813 ERR("Error: %s\n", g_error->message);
1814 g_clear_error(&g_error);
1817 g_variant_unref(reply);
1821 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
1823 CHECK_BTGATT_INIT();
1825 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
1827 GDBusProxy *device_proxy;
1828 GDBusConnection *g_conn;
1829 struct gatt_client_info_t *conn_info = NULL;
1833 if (NULL == bd_addr) {
1834 ERR("bd_addr is NULL");
1835 return BT_STATUS_PARM_INVALID;
1838 /* GDBUS Connection Info validate */
1839 g_conn = _bt_hal_get_system_gconn();
1840 if (g_conn == NULL) {
1841 ERR("Could not get System DBUS Connection");
1842 return BT_STATUS_FAIL;
1845 /* Connection Info validate */
1846 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
1847 if (conn_info == NULL) {
1848 ERR("No Connection Inforamtion!!!");
1849 return BT_STATUS_FAIL;
1852 _bt_hal_convert_addr_type_to_string(device_address,
1853 (unsigned char *)bd_addr->address);
1855 //check if connection has the same device address
1856 if (g_strcmp0(conn_info->addr, device_address) != 0) {
1857 ERR("device address [%s] does not match", device_address);
1858 return BT_STATUS_FAIL;
1861 device_path = _bt_hal_get_device_object_path(conn_info->addr);
1862 if (device_path == NULL) {
1863 ERR("device_path is NULL");
1864 return BT_STATUS_PARM_INVALID;
1867 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
1868 NULL, BT_HAL_BLUEZ_NAME,
1869 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
1872 g_free(device_path);
1873 if (device_proxy == NULL)
1874 return BT_STATUS_FAIL;
1876 INFO("Disconnect LE [%s]", device_address);
1878 g_dbus_proxy_call(device_proxy, "DisconnectLE",
1880 G_DBUS_CALL_FLAGS_NONE,
1881 BT_HAL_MAX_DBUS_TIMEOUT,
1883 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
1886 return BT_STATUS_SUCCESS;
1889 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
1894 uuid = btuuid2str(srvc_id->uu);
1895 DBG("Original UUID [%s]", uuid);
1897 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
1898 /* Extract Standard UUID string */
1899 memcpy(uuid_buf, &uuid[4], 4);
1901 DBG("Converted string [%s]", uuid_buf);
1902 return g_strdup(uuid_buf);
1904 return strdup(uuid);
1907 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
1910 /* For GATT service specific */
1911 GDBusNodeInfo *node_info;
1914 struct gatt_service_info *serv_info = NULL;
1915 GVariantBuilder *builder = NULL;
1916 GVariantBuilder *builder1 = NULL;
1917 GVariantBuilder *inner_builder = NULL;
1918 gboolean svc_primary = TRUE;
1919 GError *error = NULL;
1920 hal_gatt_service_added *user_data = NULL;
1921 DBG("Service add to DBUS slot [%d]", slot);
1923 node_info = __bt_gatt_create_method_node_info(
1924 service_introspection_xml);
1926 if (node_info == NULL)
1927 return BT_STATUS_FAIL;
1929 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
1930 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
1931 DBG("gatt service path is [%s]", path);
1933 object_id = g_dbus_connection_register_object(g_conn, path,
1934 node_info->interfaces[0],
1935 &serv_interface_vtable,
1936 NULL, NULL, &error);
1938 if (object_id == 0) {
1939 ERR("failed to register: %s", error->message);
1940 g_error_free(error);
1942 return BT_STATUS_FAIL;
1944 /* Add object_id/gatt service information; it's required at the time of
1945 * service unregister and Getmanagedobjects
1947 serv_info = g_new0(struct gatt_service_info, 1);
1949 serv_info->serv_path = g_strdup(path);
1950 serv_info->serv_id = object_id;
1951 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
1952 serv_info->is_svc_registered = FALSE;
1953 serv_info->is_svc_primary = svc_primary;
1954 DBG("Service Handle to be added is [%d]", gatt_service_handle);
1955 serv_info->service_handle = gatt_service_handle;
1957 /* Update service in GATT Server service List */
1958 gatt_services = g_slist_append(gatt_services, serv_info);
1960 /* emit interfacesadded signal here for service path */
1961 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
1962 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1964 g_variant_builder_add(inner_builder, "{sv}",
1965 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
1967 g_variant_builder_add(inner_builder, "{sv}",
1968 "Primary", g_variant_new_boolean(svc_primary));
1970 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
1972 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
1973 g_variant_new("ao", builder1));
1975 g_variant_builder_add(builder, "{sa{sv}}",
1976 GATT_SERV_INTERFACE, inner_builder);
1978 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1979 "org.freedesktop.Dbus.ObjectManager",
1981 g_variant_new("(oa{sa{sv}})",
1986 /* dbus gives error cause */
1987 ERR("d-bus api failure: errcode[%x], message[%s]",
1988 error->code, error->message);
1989 g_clear_error(&error);
1993 /* Send Service handle to application */
1994 user_data = g_malloc0(sizeof(hal_gatt_service_added));
1995 user_data->srvc_hdl = serv_info->service_handle;
1996 user_data->instance_data = slot;
1997 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
1998 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2000 /* Save newly created service in GATT Server's service list */
2001 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2005 g_variant_builder_unref(inner_builder);
2006 g_variant_builder_unref(builder);
2007 g_variant_builder_unref(builder1);
2008 return BT_STATUS_SUCCESS;
2011 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2014 char *app_path = (char*)user_data;
2015 INFO("UnregisterApplication is completed app [%s]", app_path);
2016 GError *error = NULL;
2017 GVariant *result = NULL;
2020 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2022 if (result == NULL) {
2023 /* dBUS-RPC is failed */
2024 ERR("Dbus-RPC is failed\n");
2026 if (error != NULL) {
2027 /* dBUS gives error cause */
2028 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2029 error->code, error->message);
2030 g_clear_error(&error);
2033 g_variant_unref(result);
2038 static void __bt_hal_gatt_deinit(char *app_path)
2040 GDBusProxy *proxy = NULL;
2044 /* Step1: Remove requested App */
2045 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2046 "/org/bluez/hci0", "org.bluez.GattManager1");
2051 INFO("UnregisterApplication : path [%s]", app_path);
2053 /* Async Call to Unregister Service */
2054 data = g_strdup(app_path);
2055 g_dbus_proxy_call(proxy,
2056 "UnregisterApplication",
2057 g_variant_new("(o)",
2059 G_DBUS_CALL_FLAGS_NONE, -1,
2061 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2064 /* If requested app is last GATT Server app, then clean all resources */
2065 if (gatt_server_apps == NULL) {
2066 INFO("All GATT servers are removed, clean all DBUS resources");
2068 /* unregister the exported interface for object manager */
2069 g_dbus_connection_unregister_object(g_conn, manager_id);
2071 g_bus_unown_name(owner_id);
2074 g_object_unref(manager_gproxy);
2075 manager_gproxy = NULL;
2081 static int __bt_hal_gatt_init(void)
2085 /* Only once for ALL GATT Servers */
2086 if (owner_id == 0) {
2090 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2093 ERR("Unable to connect to gdbus: %s", err->message);
2094 g_clear_error(&err);
2096 return BT_STATUS_FAIL;
2099 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2100 INFO("well-known name: %s", name);
2102 owner_id = g_bus_own_name_on_connection(g_conn, name,
2103 G_BUS_NAME_OWNER_FLAGS_NONE,
2104 NULL, NULL, NULL, NULL);
2106 INFO("Owner ID [%d]", owner_id);
2108 /* Only once for ALL GATT Servers */
2109 if (manager_node_info == NULL) {
2110 /* Register ObjectManager interface */
2111 manager_node_info = __bt_gatt_create_method_node_info(
2112 manager_introspection_xml);
2114 if (manager_node_info == NULL) {
2115 ERR("failed to get node info");
2116 return BT_STATUS_FAIL;
2121 return BT_STATUS_SUCCESS;
2124 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2128 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2129 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2130 if (app->slot == slot) {
2131 INFO("GATT Server app found app path [%s] instance [%d]",
2132 app->app_path, app->slot);
2133 *app_path = app->app_path;
2137 /* GATT Server not found */
2141 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2143 if (app_path == NULL)
2146 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2147 app->app_path = g_strdup(app_path);
2149 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2150 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2155 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2158 CHECK_BTGATT_INIT();
2159 char *app_path = NULL;
2160 GError *error = NULL;
2163 int result = BT_STATUS_SUCCESS;
2165 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2166 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2168 /* Check if this GATT server Application is already registered with DBUS */
2169 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2171 if (app_path != NULL) {
2172 DBG("GATT server path is already defined [%s]", app_path);
2173 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2175 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2176 result = __bt_hal_gatt_init();
2177 if (result != BT_STATUS_SUCCESS)
2180 /* Only once for each GATT Server */
2181 app_path = g_strdup_printf("/com/%d", server_if);
2183 app_id = g_malloc0(sizeof(int));
2184 *app_id = server_if;
2186 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2187 manager_node_info->interfaces[0],
2188 &manager_interface_vtable,
2189 (gpointer)app_id, NULL, &error);
2191 if (manager_id == 0) {
2192 ERR("failed to register: %s", error->message);
2193 g_error_free(error);
2196 INFO("manager_id [%d]", manager_id);
2198 /* For current GATT Server, app_path is created, save it in Table */
2199 _bt_hal_update_gatt_server_path(server_if, app_path);
2201 /* Add GATT Service to DBUS */
2202 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2208 INFO("Successfully added service");
2209 return BT_STATUS_SUCCESS;
2216 INFO("Service addition failed!!");
2217 return BT_STATUS_FAIL;
2220 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2221 int included_handle)
2223 CHECK_BTGATT_INIT();
2224 return BT_STATUS_SUCCESS;
2228 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2231 GSList *gatt_services = NULL;
2233 struct gatt_service_info *info = NULL;
2235 gatt_services = _bt_get_service_list_from_server(instance);
2237 len = g_slist_length(gatt_services);
2238 l = g_slist_nth(gatt_services, len -1);
2244 if (info->service_handle == service_handle)
2249 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2253 GSList *gatt_services = NULL;
2254 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2256 gatt_services = _bt_get_service_list_from_server(instance);
2258 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2259 struct gatt_service_info *info = l->data;
2260 INFO("Got one service with handle [%d]", info->service_handle);
2261 if (info->service_handle == service_handle)
2264 ERR("Gatt service with handle [%d] not found", service_handle);
2268 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2269 bt_uuid_t *uuid, int properties,
2273 GError *error = NULL;
2275 GDBusNodeInfo *node_info;
2277 GVariantBuilder *builder = NULL;
2278 GVariantBuilder *inner_builder = NULL;
2279 struct gatt_service_info *serv_info = NULL;
2280 struct gatt_char_info *char_info = NULL;
2281 GVariantBuilder *builder2 = NULL;
2282 GVariantBuilder *builder3 = NULL;
2283 GVariant *flags_val = NULL;
2285 char *char_flags[NUMBER_OF_FLAGS];
2287 hal_gatt_char_added *user_data = NULL;
2290 CHECK_BTGATT_INIT();
2291 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2292 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2294 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2295 if (serv_info == NULL)
2296 return BT_STATUS_FAIL;
2298 node_info = __bt_gatt_create_method_node_info(
2299 characteristics_introspection_xml);
2301 if (node_info == NULL)
2302 return BT_STATUS_FAIL;
2304 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2305 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2306 DBG("gatt characteristic path is [%s]", path);
2308 app_id = g_malloc0(sizeof(int));
2311 object_id = g_dbus_connection_register_object(g_conn, path,
2312 node_info->interfaces[0],
2313 &char_interface_vtable,
2314 (gpointer)app_id, NULL, &error);
2316 if (object_id == 0) {
2317 ERR("failed to register: %s", error->message);
2318 g_error_free(error);
2321 return BT_STATUS_FAIL;
2324 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2325 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2326 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2327 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2328 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2329 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2330 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2331 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2333 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2335 char_info = g_new0(struct gatt_char_info, 1);
2337 char_info->char_path = g_strdup(path);
2338 char_info->char_id = object_id;
2339 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2340 for (i = 0; i < flag_count; i++)
2341 char_info->char_flags[i] = char_flags[i];
2344 char_info->flags_length = flag_count;
2345 char_info->char_handle = gatt_char_handle;
2348 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2349 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2351 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2352 g_variant_new("s", char_info->char_uuid));
2353 g_variant_builder_add(inner_builder, "{sv}", "Service",
2354 g_variant_new("o", serv_info->serv_path));
2356 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2358 for (i = 0; i < flag_count; i++)
2359 g_variant_builder_add(builder2, "s", char_flags[i]);
2361 flags_val = g_variant_new("as", builder2);
2362 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2365 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2367 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2368 g_variant_new("ao", builder3));
2370 g_variant_builder_add(builder, "{sa{sv}}",
2371 GATT_CHAR_INTERFACE,
2374 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2375 "org.freedesktop.Dbus.ObjectManager",
2377 g_variant_new("(oa{sa{sv}})",
2382 /* dbus gives error cause */
2383 ERR("d-bus api failure: errcode[%x], message[%s]",
2384 error->code, error->message);
2385 g_clear_error(&error);
2389 //*char_path = g_strdup(path);
2394 /* Send Service handle to application */
2395 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2396 user_data->srvc_hdl = serv_info->service_handle;
2397 user_data->char_hdl = gatt_char_handle;
2398 user_data->instance_data = slot;
2399 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2400 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2402 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2403 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2408 g_variant_builder_unref(inner_builder);
2409 g_variant_builder_unref(builder);
2410 g_variant_builder_unref(builder2);
2411 g_variant_builder_unref(builder3);
2413 return BT_STATUS_SUCCESS;
2416 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2419 CHECK_BTGATT_INIT();
2421 // static int desc_id = 1;
2422 GError *error = NULL;
2424 GDBusNodeInfo *node_info;
2426 GVariantBuilder *builder = NULL;
2427 GVariantBuilder *inner_builder = NULL;
2429 struct gatt_char_info *char_info = NULL;
2430 struct gatt_desc_info *desc_info = NULL;
2431 struct gatt_service_info *serv_info = NULL;
2433 gchar **line_argv = NULL;
2435 char *char_path = NULL;
2438 GVariantBuilder *builder2 = NULL;
2439 GVariant *flags_val = NULL;
2441 char *desc_flags[NUMBER_OF_FLAGS];
2445 hal_gatt_desc_added *user_data = NULL;
2452 /* Fetch service data for the GATT server */
2453 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2454 if (serv_info == NULL)
2455 return BT_STATUS_FAIL;
2457 /* Fetch list of characteristics from the service info */
2458 l = serv_info->char_data;
2460 /* Fetch last char info from the characteristic list */
2461 char_info = g_slist_last(l)->data;
2462 if (char_info == NULL)
2463 return BT_STATUS_FAIL;
2465 /* Fetch characteristic path from char info */
2466 char_path = char_info->char_path;
2468 line_argv = g_strsplit_set(char_path, "/", 0);
2469 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2472 node_info = __bt_gatt_create_method_node_info(
2473 descriptor_introspection_xml);
2475 if (node_info == NULL) {
2476 g_strfreev(line_argv);
2478 return BT_STATUS_FAIL;
2481 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2483 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2484 DBG("gatt descriptor path is [%s]", path);
2486 app_id = g_malloc0(sizeof(int));
2489 object_id = g_dbus_connection_register_object(g_conn, path,
2490 node_info->interfaces[0],
2491 &desc_interface_vtable,
2492 (gpointer)app_id, NULL, &error);
2494 if (object_id == 0) {
2495 ERR("failed to register: %s", error->message);
2496 g_error_free(error);
2498 g_strfreev(line_argv);
2501 return BT_STATUS_FAIL;
2504 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2506 desc_info = g_new0(struct gatt_desc_info, 1);
2508 desc_info->desc_path = g_strdup(path);
2509 desc_info->desc_id = object_id;
2510 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2512 for (i = 0; i < flag_count; i++)
2513 desc_info->desc_flags[i] = desc_flags[i];
2515 desc_info->flags_length = flag_count;
2516 desc_info->desc_handle = gatt_desc_handle;
2519 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2520 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2522 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2523 g_variant_new("s", btuuid2str(uuid->uu)));
2524 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2525 g_variant_new("o", char_path));
2527 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2529 for (i = 0; i < flag_count; i++)
2530 g_variant_builder_add(builder2, "s", desc_flags[i]);
2532 flags_val = g_variant_new("as", builder2);
2533 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2536 g_variant_builder_add(builder, "{sa{sv}}",
2537 GATT_DESC_INTERFACE,
2540 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2541 "org.freedesktop.Dbus.ObjectManager",
2543 g_variant_new("(oa{sa{sv}})",
2546 if (error != NULL) {
2547 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2548 error->code, error->message);
2549 g_clear_error(&error);
2552 //*desc_path = g_strdup(path);
2554 /* Save newly created descriptor to GATT server's service's characteristic */
2555 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2557 /* Send descriptor handle to application */
2558 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2559 user_data->srvc_hdl = serv_info->service_handle;
2560 user_data->desc_hdl = gatt_desc_handle;
2561 user_data->instance_data = slot;
2562 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2563 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2568 g_strfreev(line_argv);
2569 g_variant_builder_unref(inner_builder);
2570 g_variant_builder_unref(builder);
2571 return BT_STATUS_SUCCESS;
2574 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2576 GError *error = NULL;
2578 char *data = (char*) user_data;
2579 INFO("RegisterApplication is completed path [%s]", data);
2581 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2583 if (result == NULL) {
2584 /* dBUS-RPC is failed */
2585 ERR("Dbus-RPC is failed\n");
2587 if (error != NULL) {
2588 /* dBUS gives error cause */
2589 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2590 error->code, error->message);
2591 g_clear_error(&error);
2594 g_variant_unref(result);
2599 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2600 const gchar *path, const gchar *interface)
2606 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2611 ERR("Unable to connect to gdbus: %s", err->message);
2612 g_clear_error(&err);
2617 proxy = g_dbus_proxy_new_sync(g_conn,
2618 G_DBUS_PROXY_FLAGS_NONE, NULL,
2620 interface, NULL, &err);
2624 ERR("Unable to create proxy: %s", err->message);
2625 g_clear_error(&err);
2629 manager_gproxy = proxy;
2634 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2635 const gchar *path, const gchar *interface)
2637 return (manager_gproxy) ? manager_gproxy :
2638 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2642 static void __bt_register_application_to_dbus(int slot)
2644 GDBusProxy *proxy = NULL;
2645 char *app_path = NULL;
2647 DBG("RegisterApplication slot [%d]", slot);
2649 /* It is impossible that app path is still not initialized */
2650 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2652 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2653 "/org/bluez/hci0", "org.bluez.GattManager1");
2655 data = g_strdup(app_path);
2656 g_dbus_proxy_call(proxy,
2657 "RegisterApplication",
2658 g_variant_new("(oa{sv})",
2660 G_DBUS_CALL_FLAGS_NONE, -1,
2662 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2664 INFO("GATT server started");
2667 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2669 CHECK_BTGATT_INIT();
2670 struct gatt_service_info *serv_info = NULL;
2671 hal_gatt_service_started *user_data = NULL;
2672 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2674 /* Fetch service data for the GATT server */
2675 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2676 if (serv_info == NULL)
2677 return BT_STATUS_FAIL;
2679 if (serv_info->is_svc_registered)
2680 DBG("service already registered \n");
2682 serv_info->is_svc_registered = TRUE;
2684 /* Send Service handle to application */
2685 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2686 user_data->srvc_hdl = serv_info->service_handle;
2687 user_data->instance_data = server_if;
2688 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2690 /* If this is nth Service that is started, then register application at this point */
2691 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2692 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2694 __bt_register_application_to_dbus(server_if);
2697 return BT_STATUS_SUCCESS;
2700 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2702 CHECK_BTGATT_INIT();
2703 INFO("Stop service successful");
2704 return BT_STATUS_SUCCESS;
2707 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2709 CHECK_BTGATT_INIT();
2710 struct gatt_service_info *serv_info = NULL;
2711 hal_gatt_service_deleted *user_data = NULL;
2714 int err = BT_STATUS_SUCCESS;
2715 int ret = BT_STATUS_SUCCESS;
2716 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2718 /* Fetch service data for the GATT server */
2719 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2720 if (serv_info == NULL) {
2721 ERR("Could not find service info svc handle [%d] server slot [%d]",
2722 service_handle, server_if);
2723 return BT_STATUS_FAIL;
2726 if (serv_info->is_svc_registered == FALSE) {
2727 ERR("service Not registered path [%s] handle [%d]",
2728 serv_info->serv_path, service_handle);
2731 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2732 struct gatt_char_info *char_info = l->data;
2734 if (char_info == NULL)
2737 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2738 struct gatt_desc_info *desc_info = l1->data;
2740 if (desc_info == NULL)
2743 ret = g_dbus_connection_unregister_object(g_conn,
2744 desc_info->desc_id);
2746 __bt_hal_gatt_emit_interface_removed(
2747 desc_info->desc_path,
2748 GATT_DESC_INTERFACE);
2750 err = BT_STATUS_FAIL;
2753 /* list remove & free */
2754 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2755 __bt_hal_gatt_free_descriptor_info(desc_info);
2758 g_slist_free(char_info->desc_data);
2759 char_info->desc_data = NULL;
2761 ret = g_dbus_connection_unregister_object(g_conn,
2762 char_info->char_id);
2764 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2765 GATT_CHAR_INTERFACE);
2768 err = BT_STATUS_FAIL;
2771 /* list remove & free */
2772 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2773 __bt_hal_gatt_free_characteristic_info(char_info);
2776 g_slist_free(serv_info->char_data);
2777 serv_info->char_data = NULL;
2779 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2781 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2782 GATT_SERV_INTERFACE);
2785 err = BT_STATUS_FAIL;
2788 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
2790 DBG("Unregistered the service on properties interface");
2792 /* Remove from global list */
2793 gatt_services = g_slist_remove(gatt_services, serv_info);
2794 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
2796 /* Remove from GATT Server's list of services */
2797 _bt_remote_service_from_gatt_server(server_if, service_handle);
2799 if (gatt_services == NULL)
2800 INFO("All GATT Services of all GATT Servers are unregistered");
2802 if (err == BT_STATUS_SUCCESS) {
2803 INFO("Send GATT Service deleted Event");
2804 /* Send Service handle to application */
2805 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
2806 user_data->srvc_hdl = serv_info->service_handle;
2807 user_data->instance_data = server_if;
2808 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
2811 /* Free the service */
2812 __bt_hal_gatt_free_service_info(serv_info);
2816 static gboolean __bt_gatt_get_service_state(const char *service_path)
2818 struct gatt_service_info *svc_info = NULL;
2820 for (l = gatt_services; l; l = g_slist_next(l)) {
2822 svc_info = (struct gatt_service_info *)l->data;
2825 if (!g_strcmp0(svc_info->serv_path, service_path)) {
2826 DBG("Return the state of the gatt service %d",
2827 svc_info->is_svc_registered);
2828 return svc_info->is_svc_registered;
2832 DBG("gatt service info is NULL");
2836 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
2837 int len, int confirm, char* p_value)
2839 CHECK_BTGATT_INIT();
2842 GVariantBuilder *outer_builder;
2843 GVariantBuilder *invalidated_builder;
2845 /* For Value update via PropertyChange */
2846 GVariantBuilder *outer_builder1;
2847 GVariantBuilder *inner_builder1;
2848 GVariantBuilder *invalidated_builder1;
2849 GVariant *update_value = NULL;
2851 /* Other variables */
2852 struct gatt_client_info_t *conn_info = NULL;
2853 gchar *serv_path = NULL;
2854 char *char_path = NULL;
2855 gchar **line_argv = NULL;
2856 gboolean notify = TRUE;
2857 gboolean ret = TRUE;
2858 int err = BT_STATUS_SUCCESS;
2860 GError *error = NULL;
2863 memset(addr, 0x00, sizeof(addr));
2865 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2866 if (conn_info == NULL) {
2867 ERR("No Connection Inforamtion!!!");
2868 return BT_STATUS_FAIL;
2871 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
2873 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
2874 if (char_path == NULL)
2875 return BT_STATUS_FAIL;
2877 line_argv = g_strsplit_set(char_path, "/", 0);
2878 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2880 if (!__bt_gatt_get_service_state(serv_path)) {
2881 DBG("service not registered for this characteristic \n");
2883 g_strfreev(line_argv);
2884 return BT_STATUS_FAIL;
2887 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2888 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
2890 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
2891 g_variant_new("b", notify));
2893 _bt_hal_convert_addr_type_to_string(addr, (unsigned char *)conn_info->addr);
2895 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
2896 g_variant_new("s", addr));
2898 DBG("Set characteristic Notification \n");
2899 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2901 "org.freedesktop.DBus.Properties",
2902 "PropertiesChanged",
2903 g_variant_new("(sa{sv}as)",
2904 "org.bluez.GattCharacteristic1",
2905 outer_builder, invalidated_builder),
2909 if (error != NULL) {
2910 ERR("D-Bus API failure: errCode[%x], \
2912 error->code, error->message);
2913 g_clear_error(&error);
2915 err = BT_STATUS_FAIL;
2918 g_variant_builder_unref(outer_builder);
2919 g_variant_builder_unref(invalidated_builder);
2922 /* Notifying Done, now update Value to Bluez via PropertyChanged */
2923 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2925 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2926 for (i = 0; i < len; i++)
2927 g_variant_builder_add(inner_builder1, "y", p_value[i]);
2929 update_value = g_variant_new("ay", inner_builder1);
2932 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
2933 g_variant_builder_add(outer_builder1, "{sv}", "Value",
2936 DBG("Updating characteristic value \n");
2937 ret = g_dbus_connection_emit_signal(g_conn, NULL,
2939 "org.freedesktop.DBus.Properties",
2940 "PropertiesChanged",
2941 g_variant_new("(sa{sv}as)",
2942 "org.bluez.GattCharacteristic1",
2943 outer_builder1, invalidated_builder1),
2947 if (error != NULL) {
2948 ERR("D-Bus API failure: errCode[%x], \
2950 error->code, error->message);
2951 g_clear_error(&error);
2953 err = BT_STATUS_FAIL;
2955 struct gatt_char_info *char_info = NULL;
2957 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
2958 if (char_info == NULL) {
2960 g_strfreev(line_argv);
2961 g_variant_builder_unref(inner_builder1);
2962 g_variant_builder_unref(outer_builder1);
2963 g_variant_builder_unref(invalidated_builder1);
2965 return BT_STATUS_FAIL;
2968 char_info->value_length = len;
2970 char_info->char_value = (char *)realloc(char_info->char_value, len);
2971 if (char_info->char_value) {
2972 for (i = 0; i < len; i++)
2973 char_info->char_value[i] = p_value[i];
2978 g_strfreev(line_argv);
2979 g_variant_builder_unref(inner_builder1);
2980 g_variant_builder_unref(outer_builder1);
2981 g_variant_builder_unref(invalidated_builder1);
2986 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
2987 int status, btgatt_response_t *response)
2989 CHECK_BTGATT_INIT();
2991 struct gatt_req_info *req_info = NULL;
2992 struct gatt_client_info_t *conn_info = NULL;
2995 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
2997 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2998 if (conn_info == NULL) {
2999 ERR("No Connection Inforamtion!!!");
3000 return BT_STATUS_FAIL;
3003 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3004 if (req_info == NULL) {
3005 ERR("No Request Inforamtion!!!");
3006 return BT_STATUS_FAIL;
3009 if (status != BT_STATUS_SUCCESS) {
3010 ERR("resp_state is 0x%X", status);
3012 g_dbus_method_invocation_return_dbus_error(req_info->context,
3013 "org.bluez.Error.Failed", "Application Error");
3015 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3017 req_info->context = NULL;
3018 if (req_info->attr_path)
3019 g_free(req_info->attr_path);
3020 if (req_info->svc_path)
3021 g_free(req_info->svc_path);
3024 return BT_STATUS_SUCCESS;
3027 DBG("Reponse Value length [%d]", response->attr_value.len);
3028 DBG("Request type: [%d]", req_info->request_type);
3031 for (i = 0; i < response->attr_value.len; i++)
3032 DBG("Resonse [%d] = [0x%x]", i, response->attr_value.value[i]);
3034 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3035 GVariantBuilder *inner_builder = NULL;
3036 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3038 if (response->attr_value.len > 0) {
3039 for (i = 0; i < response->attr_value.len; i++)
3040 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3042 g_dbus_method_invocation_return_value(req_info->context,
3043 g_variant_new("(ay)", inner_builder));
3045 g_variant_builder_unref(inner_builder);
3047 g_dbus_method_invocation_return_value(req_info->context, NULL);
3049 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3051 req_info->context = NULL;
3052 if (req_info->attr_path)
3053 g_free(req_info->attr_path);
3054 if (req_info->svc_path)
3055 g_free(req_info->svc_path);
3058 return BT_STATUS_SUCCESS;
3062 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3063 int status, int fd, int mtu, void *fdlist)
3065 CHECK_BTGATT_INIT();
3067 struct gatt_req_info *req_info = NULL;
3068 struct gatt_client_info_t *conn_info = NULL;
3070 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3072 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3073 if (conn_info == NULL) {
3074 ERR("No Connection Inforamtion!!!");
3075 return BT_STATUS_FAIL;
3078 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3079 if (req_info == NULL) {
3080 ERR("No Request Inforamtion!!!");
3081 return BT_STATUS_FAIL;
3084 if (status != BT_STATUS_SUCCESS) {
3085 ERR("resp_state is 0x%X", status);
3087 g_dbus_method_invocation_return_dbus_error(req_info->context,
3088 "org.bluez.Error.Failed", "Application Error");
3090 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3092 req_info->context = NULL;
3093 if (req_info->attr_path)
3094 g_free(req_info->attr_path);
3095 if (req_info->svc_path)
3096 g_free(req_info->svc_path);
3099 return BT_STATUS_SUCCESS;
3103 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3105 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3106 g_dbus_method_invocation_return_value_with_unix_fd_list(
3107 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3109 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3111 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY 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);
3116 g_dbus_method_invocation_return_value(req_info->context, NULL);
3118 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3120 req_info->context = NULL;
3121 if (req_info->attr_path)
3122 g_free(req_info->attr_path);
3123 if (req_info->svc_path)
3124 g_free(req_info->svc_path);
3127 return BT_STATUS_SUCCESS;
3131 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3132 int value_length, char* att_value)
3134 CHECK_BTGATT_INIT();
3136 /* Other variables */
3137 char *char_path = NULL;
3138 gboolean ret = TRUE;
3139 GError *error = NULL;
3141 GVariantBuilder *outer_builder;
3142 GVariantBuilder *inner_builder;
3143 GVariantBuilder *invalidated_builder;
3144 GVariant *update_value = NULL;
3145 int err = BT_STATUS_SUCCESS;
3147 gchar **line_argv = NULL;
3148 gchar *serv_path = NULL;
3150 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3151 if (char_path == NULL)
3152 return BT_STATUS_FAIL;
3154 line_argv = g_strsplit_set(char_path, "/", 0);
3155 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3157 if (!__bt_gatt_get_service_state(serv_path)) {
3158 DBG("service not registered for this characteristic \n");
3160 g_strfreev(line_argv);
3161 return BT_STATUS_FAIL;
3165 line_argv = g_strsplit_set(char_path, "/", 0);
3166 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3168 if (!__bt_gatt_get_service_state(serv_path)) {
3169 DBG("service not registered for this characteristic \n");
3171 g_strfreev(line_argv);
3172 return BT_STATUS_FAIL;
3175 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3176 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3178 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3179 for (i = 0; i < value_length; i++)
3180 g_variant_builder_add(inner_builder, "y", att_value[i]);
3182 update_value = g_variant_new("ay", inner_builder);
3184 g_variant_builder_add(outer_builder, "{sv}", "Value",
3187 DBG("Updating characteristic value \n");
3188 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3190 "org.freedesktop.DBus.Properties",
3191 "PropertiesChanged",
3192 g_variant_new("(sa{sv}as)",
3193 "org.bluez.GattCharacteristic1",
3194 outer_builder, invalidated_builder),
3198 if (error != NULL) {
3199 ERR("D-Bus API failure: errCode[%x], \
3201 error->code, error->message);
3202 g_clear_error(&error);
3204 err = BT_STATUS_FAIL;
3206 struct gatt_char_info *char_info = NULL;
3208 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3209 if (char_info == NULL) {
3211 g_strfreev(line_argv);
3212 g_variant_builder_unref(inner_builder);
3213 g_variant_builder_unref(outer_builder);
3214 g_variant_builder_unref(invalidated_builder);
3216 return BT_STATUS_FAIL;
3219 char_info->value_length = value_length;
3221 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3222 if (char_info->char_value) {
3223 for (i = 0; i < value_length; i++)
3224 char_info->char_value[i] = att_value[i];
3230 g_strfreev(line_argv);
3231 g_variant_builder_unref(inner_builder);
3232 g_variant_builder_unref(outer_builder);
3233 g_variant_builder_unref(invalidated_builder);
3238 static bt_status_t gatt_server_listen(int server_if, bool start)
3240 CHECK_BTGATT_INIT();
3241 /* Send Data to LE Module */
3242 return _bt_hal_enable_advertising(server_if, start, FALSE);
3245 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3246 bool include_txpower, int min_interval, int max_interval, int appearance,
3247 uint16_t manufacturer_len, char* manufacturer_data,
3248 uint16_t service_data_len, char* service_data,
3249 uint16_t service_uuid_len, char* service_uuid)
3251 CHECK_BTGATT_INIT();
3252 return BT_STATUS_SUCCESS;
3255 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3257 CHECK_BTGATT_INIT();
3258 /* Send Enable Advertising request to LE Module */
3259 return _bt_hal_enable_advertising(server_if, TRUE, TRUE);
3262 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3263 int chnl_map, int tx_power, int timeout_s)
3265 CHECK_BTGATT_INIT();
3267 /* Send Advertising parameters to LE Module */
3268 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3269 chnl_map, tx_power, timeout_s);
3272 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3274 CHECK_BTGATT_INIT();
3276 /* Send Data to LE Module */
3277 return _bt_hal_set_advertising_data(adv_param_setup);
3280 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3282 CHECK_BTGATT_INIT();
3283 /* Send Data to LE Module */
3284 return _bt_hal_enable_advertising(server_if, FALSE, TRUE);
3287 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3289 CHECK_BTGATT_INIT();
3290 char *object_path = NULL;
3292 GDBusProxy *device_proxy;
3293 GError *error = NULL;
3295 GVariant *tmp_value;
3296 GDBusConnection *conn;
3297 GVariant *result = NULL;
3298 int ret = BT_STATUS_SUCCESS;
3299 struct gatt_client_info_t *conn_info = NULL;
3302 if (mtu_size == NULL)
3303 return BT_STATUS_PARM_INVALID;
3305 /* GDBUS Connection Info validate */
3306 conn = _bt_hal_get_system_gconn();
3308 ERR("Could not get System DBUS Connection");
3309 return BT_STATUS_FAIL;
3312 /* Connection Info validate */
3313 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3314 if (conn_info == NULL) {
3315 ERR("No Connection Inforamtion!!!");
3316 return BT_STATUS_FAIL;
3320 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3321 if (object_path == NULL)
3322 return BT_STATUS_FAIL;
3324 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3325 NULL, BT_HAL_BLUEZ_NAME, object_path,
3326 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3328 g_free(object_path);
3329 if (device_proxy == NULL)
3330 return BT_STATUS_FAIL;
3332 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3333 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3334 G_DBUS_CALL_FLAGS_NONE,
3338 if (result == NULL) {
3339 if (error != NULL) {
3340 ERR("Error occured in Proxy call [%s]\n", error->message);
3341 g_error_free(error);
3343 g_object_unref(device_proxy);
3344 return BT_STATUS_FAIL;
3347 g_variant_get(result , "(@a{sv})", &value);
3348 g_variant_unref(result);
3350 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3351 if (tmp_value == NULL) {
3352 g_object_unref(device_proxy);
3353 g_variant_unref(value);
3354 return BT_STATUS_FAIL;
3357 mtu = g_variant_get_uint16(tmp_value);
3359 DBG("ATT MTU : [%d]", mtu);
3361 g_variant_unref(tmp_value);
3362 g_variant_unref(value);
3363 g_object_unref(device_proxy);
3365 *mtu_size = (int) mtu;
3370 const btgatt_server_interface_t btgatt_server_interface = {
3371 .register_server = gatt_server_register_app,
3372 .unregister_server = gatt_server_unregister_app,
3373 .connect = gatt_server_open,
3374 .disconnect = gatt_server_close,
3375 .add_service = gatt_server_add_service,
3376 .add_included_service = gatt_server_add_included_service,
3377 .add_characteristic = gatt_server_add_characteristic,
3378 .add_descriptor = gatt_server_add_descriptor,
3379 .start_service = gatt_server_start_service,
3380 .stop_service = gatt_server_stop_service,
3381 .delete_service = gatt_server_delete_service,
3382 .send_indication = gatt_server_send_indication,
3383 .send_response = gatt_server_send_response,
3384 .update_att_value = gatt_server_update_att_value,
3385 .listen = gatt_server_listen,
3386 .set_adv_data = gatt_server_set_adv_data,
3387 .multi_adv_enable = gatt_server_multi_adv_enable,
3388 .multi_adv_update = gatt_server_multi_adv_update,
3389 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3390 .multi_adv_disable = gatt_server_multi_adv_disable,
3391 .get_att_mtu = gatt_server_get_mtu_size,
3392 .send_response_acquire = gatt_server_send_acquire_response