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;
190 struct hal_gatts_server_register_info_t {
196 static GSList * hal_gatts_server_register_list;
198 static int g_server_inst_id = 0;
200 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
202 ERR("%s: BTGATT not initialized", __FUNCTION__);\
203 return BT_STATUS_NOT_READY;\
205 DBG("%s", __FUNCTION__);\
208 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data);
210 static void __bt_hal_gatt_deinit(char *app_path);
212 static void __bt_hal_register_application_cb(GObject *object,
213 GAsyncResult *res, gpointer user_data);
215 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
218 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
219 const gchar *path, const gchar *interface);
221 static int bt_hal_gatts_get_gatt_server_instance();
223 /* Introspection data for the service we are exporting */
224 static const gchar service_introspection_xml[] =
226 " <interface name='org.freedesktop.DBus.Properties'>"
227 " <property type='s' name='UUID' access='read'>"
229 " <property type='b' name='primary' access='read'>"
231 " <property type='o' name='Device' access='read'>"
233 " <property type='ao' name='Characteristics' access='read'>"
235 " <property type='s' name='Includes' access='read'>"
240 /* Introspection data for the characteristics we are exporting */
241 static const gchar characteristics_introspection_xml[] =
243 " <interface name='org.bluez.GattCharacteristic1'>"
244 " <method name='ReadValue'>"
245 " <arg type='s' name='address' direction='in'/>"
246 " <arg type='u' name='id' direction='in'/>"
247 " <arg type='q' name='offset' direction='in'/>"
248 " <arg type='ay' name='Value' direction='out'/>"
250 " <method name='WriteValue'>"
251 " <arg type='s' name='address' direction='in'/>"
252 " <arg type='u' name='id' direction='in'/>"
253 " <arg type='q' name='offset' direction='in'/>"
254 " <arg type='b' name='response_needed' direction='in'/>"
255 " <arg type='ay' name='value' direction='in'/>"
257 " <method name ='AcquireWrite'>"
258 " <arg type='a{sv}' name='properties' direction='in'/>"
259 " <arg type='h' name='fd' direction='out'/>"
260 " <arg type='q' name='mtu' direction='out'/>"
262 " <method name = 'AcquireNotify'>"
263 " <arg type='a{sv}' name='properties' direction='in'/>"
264 " <arg type='h' name='fd' direction='out'/>"
265 " <arg type='q' name='mtu' direction='out'/>"
267 " <method name='StartNotify'>"
269 " <method name='StopNotify'>"
271 " <method name='IndicateConfirm'>"
272 " <arg type='s' name='address' direction='in'/>"
273 " <arg type='b' name='complete' direction='in'/>"
276 " <interface name='org.freedesktop.DBus.Properties'>"
277 " <property type='s' name='UUID' access='read'>"
279 " <property type='o' name='Service' access='read'>"
281 " <property type='ay' name='Value' access='readwrite'>"
283 " <property type='b' name='Notifying' access='read'>"
285 " <property type='as' name='Flags' access='read'>"
287 " <property type='s' name='Unicast' access='read'>"
289 " <property type='ao' name='Descriptors' access='read'>"
291 " <property type='b' name='WriteAcquired' access='read'>"
293 " <property type='b' name='NotifyAcquired' access='read'>"
298 /* Introspection data for the descriptor we are exporting */
299 static const gchar descriptor_introspection_xml[] =
301 " <interface name='org.bluez.GattDescriptor1'>"
302 " <method name='ReadValue'>"
303 " <arg type='s' name='address' direction='in'/>"
304 " <arg type='u' name='id' direction='in'/>"
305 " <arg type='q' name='offset' direction='in'/>"
306 " <arg type='ay' name='Value' direction='out'/>"
308 " <method name='WriteValue'>"
309 " <arg type='s' name='address' direction='in'/>"
310 " <arg type='u' name='id' direction='in'/>"
311 " <arg type='q' name='offset' direction='in'/>"
312 " <arg type='b' name='response_needed' direction='in'/>"
313 " <arg type='ay' name='value' direction='in'/>"
316 " <interface name='org.freedesktop.DBus.Properties'>"
317 " <property type='s' name='UUID' access='read'>"
319 " <property type='o' name='Characteristic' access='read'>"
321 " <property type='ay' name='Value' access='read'>"
323 " <property type='as' name='Flags' access='read'>"
329 static const gchar manager_introspection_xml[] =
331 " <interface name='org.freedesktop.DBus.ObjectManager'>"
332 " <method name='GetManagedObjects'>"
333 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
338 static GSList *_bt_get_service_list_from_server(int instance)
341 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
342 INFO("Find App with slot [%d]", instance);
344 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
345 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
347 if (app->slot == instance) {
348 INFO("App slot [%d] Found, Number of services registered [%d]",
349 app->slot, g_slist_length(app->services));
350 return app->services;
356 static void _bt_remote_service_from_gatt_server(int instance, int service_handle)
361 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
362 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
364 if (app->slot == instance) {
365 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
366 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
367 if (srv->service_handle == service_handle) {
368 app->services = g_slist_remove(app->services, srv);
376 static void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
379 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
380 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
382 if (app->slot == slot) {
383 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
384 serv_info->service_handle, slot);
385 app->services = g_slist_append(app->services, serv_info);
390 int _bt_get_remote_gatt_client_conn_id(char *address)
393 struct gatt_client_info_t *info = NULL;
395 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
396 info = (struct gatt_client_info_t*)l->data;
400 if (!g_strcmp0(info->addr, address)) {
401 INFO("Remote GATT client found addr[%s]", info->addr);
402 return info->connection_id;
408 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
411 struct gatt_client_info_t *info = NULL;
413 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
414 info = (struct gatt_client_info_t*)l->data;
418 if (!g_strcmp0(info->addr, address)) {
419 INFO("Remote GATT client found addr[%s]", info->addr);
426 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
429 struct gatt_client_info_t *info = NULL;
431 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
432 info = (struct gatt_client_info_t*)l->data;
436 if (info->connection_id == conn_id) {
437 INFO("Remote GATT client found addr[%s]", info->addr);
444 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
449 struct gatt_client_info_t *info = NULL;
450 struct gatt_req_info *info1 = NULL;
452 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
453 info = (struct gatt_client_info_t*)l->data;
457 if (info->connection_id == conn_id) {
459 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
461 info1 = (struct gatt_req_info*)l1->data;
465 if (info1->request_id == trans_id) {
466 INFO("Remote GATT client found addr[%s]", info->addr);
475 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
477 struct hal_ev_gatt_server_connected ev;
478 struct gatt_client_info_t *conn_info = NULL;
480 memset(&ev, 0, sizeof(ev));
482 /* Find Server Instance */
483 instance = bt_hal_gatts_get_gatt_server_instance();
484 if (instance == -1) {
485 ERR("Not even a single GATT server is registered");
489 DBG("server instance [%d]", instance);
491 /* Convert address to hex */
492 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
494 /* Create Connection ID */
495 /* Check if device is already in connected list */
496 conn_info = __bt_find_remote_gatt_client_info(address);
499 /* If disconnected, and conn info found, then remove conn info */
500 if (is_connected == FALSE) {
501 DBG("GATT Disconnected");
503 INFO("Remove GATT client info from List..");
504 /* Remove info from List */
505 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
506 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
509 ERR("GATT callback not registered");
511 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
512 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
513 ev.conn_id = conn_info->connection_id;
514 ev.server_instance = conn_info->instance_id;
515 ev.connected = is_connected;
517 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
519 g_free(conn_info->addr);
522 /* If connected, and conn info NOT found, then add conn info */
525 /* Save Connection info */
526 conn_info = g_new0(struct gatt_client_info_t, 1);
527 conn_info->addr = g_strdup(address);
528 INFO("Added GATT client addr[%s]", conn_info->addr);
529 conn_info->connection_id = ++conn_id;
530 conn_info->instance_id = instance;
531 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
532 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
535 ERR("GATT callback not registered");
537 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
538 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
539 ev.conn_id = conn_info->connection_id;
540 ev.server_instance = conn_info->instance_id;
541 ev.connected = is_connected;
543 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
547 /* Send GATT connected or disconnected event */
550 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
554 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
555 struct gatt_service_info *serv_info = l1->data;
557 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
558 struct gatt_char_info *char_info = l2->data;
560 if (g_strcmp0(char_info->char_path, char_path)
562 *char_hdl = char_info->char_handle;
567 ERR("Gatt service not found");
571 static char *__bt_gatt_find_char_path_from_handle(int char_hdl)
575 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
576 struct gatt_service_info *serv_info = l1->data;
578 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
579 struct gatt_char_info *char_info = l2->data;
581 if (char_info->char_handle == char_hdl)
582 return char_info->char_path;
589 static struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
593 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
594 struct gatt_service_info *serv_info = l1->data;
596 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
597 struct gatt_char_info *char_info = l2->data;
599 if (char_info->char_handle == char_hdl)
607 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
609 GSList *l1, *l2, *l3;
611 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
612 struct gatt_service_info *serv_info = l1->data;
614 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
615 struct gatt_char_info *char_info = l2->data;
617 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
618 struct gatt_desc_info *desc_info = l3->data;
620 if (g_strcmp0(desc_info->desc_path, desc_path)
622 *desc_hdl = desc_info->desc_handle;
628 ERR("Gatt service not found");
632 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
634 const gchar *object_path,
635 const gchar *interface_name,
636 const gchar *method_name,
637 GVariant *parameters,
638 GDBusMethodInvocation *invocation,
643 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
644 GVariantBuilder *builder;
645 GVariantBuilder *inner_builder1 = NULL;
646 GVariant *svc_char = NULL;
648 GSList *gatt_services = NULL;
650 instance = (int*)user_data;
651 gboolean writeAcquired = FALSE;
652 gboolean notifyAcquired = FALSE;
654 DBG("Getting values for service, chars and descriptors");
655 DBG("GATT Server App for which services are requested [%d]", *instance);
658 builder = g_variant_builder_new(
659 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
662 gatt_services = _bt_get_service_list_from_server(*instance);
664 if (g_slist_length(gatt_services) == 0) {
665 ERR("No registered GATT services!!!!");
666 g_dbus_method_invocation_return_value(invocation, NULL);
667 g_variant_builder_unref(builder);
671 for (l = gatt_services; l != NULL; l = l->next) {
672 GVariantBuilder *svc_builder = NULL;
673 GVariantBuilder *inner_builder = NULL;
674 struct gatt_service_info *serv_info = l->data;
675 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
677 /* Prepare inner builder for GattService1 interface */
678 DBG("Creating builder for service");
679 svc_builder = g_variant_builder_new(
680 G_VARIANT_TYPE("a{sa{sv}}"));
681 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
683 g_variant_builder_add(inner_builder, "{sv}", "UUID",
684 g_variant_new_string(serv_info->service_uuid));
686 g_variant_builder_add(inner_builder, "{sv}", "Primary",
687 g_variant_new_boolean(serv_info->is_svc_primary));
690 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
691 DBG("Adding Charatarisitcs list");
692 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
693 struct gatt_char_info *char_info = l4->data;
694 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
695 char_info->char_handle, serv_info->service_handle);
696 g_variant_builder_add(inner_builder1, "o",
697 char_info->char_path);
698 DBG("%s", char_info->char_path);
701 svc_char = g_variant_new("ao", inner_builder1);
702 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
705 g_variant_builder_add(svc_builder, "{sa{sv}}",
709 g_variant_builder_add(builder, "{oa{sa{sv}}}",
710 serv_info->serv_path,
713 g_variant_builder_unref(inner_builder1);
715 /* Prepare inner builder for GattCharacteristic1 interface */
717 GSList *l2 = serv_info->char_data;
718 DBG("Creating builder for characteristics \n");
721 DBG("characteristic data is NULL");
723 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
725 GVariantBuilder *char_builder = NULL;
726 GVariantBuilder *inner_builder = NULL;
727 GVariantBuilder *builder1 = NULL;
728 GVariantBuilder *builder2 = NULL;
729 GVariantBuilder *builder3 = NULL;
730 GVariant *char_val = NULL;
731 GVariant *flags_val = NULL;
732 GVariant *char_desc = NULL;
733 char *unicast = NULL;
734 gboolean notify = FALSE;
737 char_builder = g_variant_builder_new(
740 inner_builder = g_variant_builder_new(
744 struct gatt_char_info *char_info = l2->data;
745 if (char_info == NULL) {
746 ERR("char_info is NULL");
751 g_variant_builder_add(inner_builder, "{sv}", "UUID",
752 g_variant_new_string(char_info->char_uuid));
754 g_variant_builder_add(inner_builder, "{sv}", "Service",
755 g_variant_new("o", serv_info->serv_path));
757 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
759 if (char_info->char_value != NULL) {
760 for (i = 0; i < char_info->value_length; i++) {
761 g_variant_builder_add(builder1, "y",
762 char_info->char_value[i]);
764 char_val = g_variant_new("ay", builder1);
765 g_variant_builder_add(inner_builder, "{sv}",
769 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
770 for (i = 0; i < char_info->flags_length; i++) {
771 g_variant_builder_add(builder2, "s",
772 char_info->char_flags[i]);
774 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
775 DBG("setting WriteAcquired property");
776 writeAcquired = TRUE;
779 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
780 DBG("setting NotifyAcquired property");
781 notifyAcquired = TRUE;
785 flags_val = g_variant_new("as", builder2);
786 g_variant_builder_add(inner_builder, "{sv}", "Flags",
790 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
791 g_variant_new("b", notify));
794 if (writeAcquired == TRUE) {
795 DBG("adding WriteAcquired property");
796 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
797 g_variant_new("b", writeAcquired));
801 if (notifyAcquired == TRUE) {
802 DBG("adding NotifyAcquired property");
803 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
804 g_variant_new("b", notifyAcquired));
808 unicast = g_strdup("00:00:00:00:00:00");
809 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
810 g_variant_new("s", unicast));
813 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
814 DBG("Adding Descriptors list");
816 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
817 struct gatt_desc_info *desc_info = l4->data;
818 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
819 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
820 g_variant_builder_add(builder3, "o",
821 desc_info->desc_path);
822 DBG("%s", desc_info->desc_path);
825 char_desc = g_variant_new("ao", builder3);
826 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
829 g_variant_builder_add(char_builder, "{sa{sv}}",
830 GATT_CHAR_INTERFACE , inner_builder);
831 g_variant_builder_add(builder, "{oa{sa{sv}}}",
832 char_info->char_path, char_builder);
834 /*Prepare inner builder for GattDescriptor1 interface*/
836 GSList *l3 = char_info->desc_data;
839 DBG("descriptor data is NULL");
841 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
843 DBG("Creating builder for descriptor \n");
845 GVariantBuilder *desc_builder = NULL;
846 GVariantBuilder *inner_builder = NULL;
847 GVariantBuilder *builder1 = NULL;
848 GVariantBuilder *builder2 = NULL;
849 GVariant *desc_val = NULL;
851 desc_builder = g_variant_builder_new(
854 inner_builder = g_variant_builder_new(
858 struct gatt_desc_info *desc_info = l3->data;
859 if (desc_info == NULL) {
860 ERR("desc_info is NULL");
865 g_variant_builder_add(inner_builder,
867 g_variant_new_string(
868 desc_info->desc_uuid));
871 g_variant_builder_add(inner_builder, "{sv}",
874 char_info->char_path));
877 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
879 if (desc_info->desc_value != NULL) {
880 for (i = 0; i < desc_info->value_length; i++) {
881 g_variant_builder_add(builder1, "y",
882 desc_info->desc_value[i]);
884 desc_val = g_variant_new("ay", builder1);
885 g_variant_builder_add(inner_builder, "{sv}",
890 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
892 for (i = 0; i < desc_info->flags_length; i++) {
893 g_variant_builder_add(builder2, "s",
894 desc_info->desc_flags[i]);
897 flags_val = g_variant_new("as", builder2);
898 g_variant_builder_add(inner_builder, "{sv}", "Flags",
901 g_variant_builder_add(desc_builder, "{sa{sv}}",
905 g_variant_builder_add(builder, "{oa{sa{sv}}}",
906 desc_info->desc_path,
909 /*unref descriptor builder pointers*/
910 g_variant_builder_unref(builder1);
911 g_variant_builder_unref(builder2);
912 g_variant_builder_unref(inner_builder);
913 g_variant_builder_unref(desc_builder);
918 /*unref char builder pointers*/
919 g_variant_builder_unref(builder1);
920 g_variant_builder_unref(builder2);
921 g_variant_builder_unref(builder3);
922 g_variant_builder_unref(inner_builder);
923 g_variant_builder_unref(char_builder);
926 /*unref service builder pointers*/
927 g_variant_builder_unref(inner_builder);
928 g_variant_builder_unref(svc_builder);
931 /* Return builder as method reply */
932 DBG("Sending gatt service builder values to Bluez");
933 g_dbus_method_invocation_return_value(invocation,
943 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
945 const gchar *object_path,
946 const gchar *interface_name,
947 const gchar *method_name,
948 GVariant *parameters,
949 GDBusMethodInvocation *invocation,
953 if (g_strcmp0(method_name, "ReadValue") == 0) {
954 struct hal_ev_gatt_server_read_req ev;
959 struct gatt_client_info_t *conn_info = NULL;
960 struct gatt_req_info *req_info = NULL;
961 struct gatt_service_info *svc_info = NULL;
965 DBG("Application path = %s", object_path);
966 DBG("Sender = %s", sender);
968 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
969 if (svc_info == NULL) {
970 ERR("Coudn't find service for %s", object_path);
971 g_dbus_method_invocation_return_value(invocation, NULL);
975 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
976 DBG("Request id = %u, Offset = %u", req_id, offset);
978 /* Check if device is already in connected list */
979 conn_info = __bt_find_remote_gatt_client_info(addr);
981 if (conn_info == NULL) {
982 ERR("Coudn't find Connection info for %s", addr);
983 g_dbus_method_invocation_return_value(invocation, NULL);
988 ERR("GATT callback NOT registered");
989 g_dbus_method_invocation_return_value(invocation, NULL);
993 /* Store requests information */
994 req_info = g_new0(struct gatt_req_info, 1);
995 req_info->attr_path = g_strdup(object_path);
996 req_info->svc_path = g_strdup(svc_info->serv_path);
997 req_info->request_id = req_id;
998 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
999 req_info->offset = offset;
1000 req_info->context = invocation;
1002 /* Append request info in list of requests for the particular connection */
1003 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1005 /* Send HAL event */
1006 memset(&ev, 0, sizeof(ev));
1007 ev.conn_id = conn_info->connection_id;
1008 ev.trans_id = req_id;
1009 ev.att_handle = desc_hdl;
1011 ev.is_long = false; /* TODO*/
1013 /* Convert address to hex */
1014 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1016 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1018 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1020 GVariant *var = NULL;
1024 gboolean response_needed = FALSE;
1025 struct hal_ev_gatt_server_write_req ev;
1029 struct gatt_service_info *svc_info = NULL;
1030 struct gatt_client_info_t *conn_info = NULL;
1031 struct gatt_req_info *req_info = NULL;
1033 memset(&ev, 0, sizeof(ev));
1036 DBG("Application path = %s", object_path);
1037 DBG("Sender = %s", sender);
1039 g_variant_get(parameters, "(&suqb@ay)",
1040 &addr, &req_id, &offset, &response_needed, &var);
1041 DBG("Request id = %u, Offset = %u", req_id, offset);
1043 /* Check if device is already in connected list */
1044 conn_info = __bt_find_remote_gatt_client_info(addr);
1046 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1048 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1049 g_variant_unref(var);
1050 if (response_needed)
1051 g_dbus_method_invocation_return_value(invocation, NULL);
1053 g_object_unref(invocation);
1057 len = g_variant_get_size(var);
1058 if (len > 0 && len < 600) {
1060 data = (char *)g_variant_get_data(var);
1061 memcpy(ev.value, data, len);
1064 if (response_needed) {
1065 /* Store request information */
1066 req_info = g_new0(struct gatt_req_info, 1);
1067 req_info->attr_path = g_strdup(object_path);
1068 req_info->svc_path = g_strdup(svc_info->serv_path);
1069 req_info->request_id = req_id;
1070 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1071 req_info->offset = offset;
1072 req_info->context = invocation;
1074 /* Append request info in list of requests for the particular connection */
1075 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1077 g_object_unref(invocation);
1080 /* Send HAL event */
1081 ev.conn_id = conn_info->connection_id;
1082 ev.trans_id = req_id;
1083 ev.att_handle = desc_hdl;
1085 ev.need_rsp = response_needed;
1088 /* Convert address to hex */
1089 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1091 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1093 g_variant_unref(var);
1098 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1099 const gchar *sender,
1100 const gchar *object_path,
1101 const gchar *interface_name,
1102 const gchar *method_name,
1103 GVariant *parameters,
1104 GDBusMethodInvocation *invocation,
1107 if (g_strcmp0(method_name, "ReadValue") == 0) {
1111 struct hal_ev_gatt_server_read_req ev;
1114 struct gatt_req_info *req_info = NULL;
1115 struct gatt_client_info_t *conn_info = NULL;
1116 struct gatt_service_info *svc_info = NULL;
1118 g_variant_get(parameters, "(&suq)",
1119 &addr, &req_id, &offset);
1121 DBG("Request id = %u, Offset = %u", req_id, offset);
1122 DBG("Application path = %s", object_path);
1123 DBG("Sender = %s", sender);
1124 DBG("Address = %s", addr);
1126 /* Check if device is already in connected list */
1127 conn_info = __bt_find_remote_gatt_client_info(addr);
1129 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1131 if (svc_info == NULL || conn_info == NULL) {
1132 g_dbus_method_invocation_return_value(invocation, NULL);
1137 ERR("GATT callback NOT registered");
1138 g_dbus_method_invocation_return_value(invocation, NULL);
1142 /* Store requets information */
1143 req_info = g_new0(struct gatt_req_info, 1);
1144 req_info->attr_path = g_strdup(object_path);
1145 req_info->svc_path = g_strdup(svc_info->serv_path);
1146 req_info->request_id = req_id;
1147 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1148 req_info->offset = offset;
1149 req_info->context = invocation;
1151 /* Append request info in list of requests for the particular connection */
1152 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1154 /* Send HAL event */
1155 memset(&ev, 0, sizeof(ev));
1156 ev.conn_id = conn_info->connection_id;
1157 ev.trans_id = req_id;
1158 ev.att_handle = char_hdl;
1160 ev.is_long = false; /* TODO*/
1162 /* Convert address to hex */
1163 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1164 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1166 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1167 GVariant *var = NULL;
1171 gboolean response_needed = FALSE;
1172 struct hal_ev_gatt_server_write_req ev;
1176 struct gatt_service_info *svc_info = NULL;
1177 struct gatt_req_info *req_info = NULL;
1178 struct gatt_client_info_t *conn_info = NULL;
1180 memset(&ev, 0, sizeof(ev));
1183 DBG("Application path = %s", object_path);
1184 DBG("Sender = %s", sender);
1186 g_variant_get(parameters, "(&suqb@ay)",
1187 &addr, &req_id, &offset, &response_needed, &var);
1188 DBG("Request id = %u, Offset = %u", req_id, offset);
1190 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1192 /* Check if device is already in connected list */
1193 conn_info = __bt_find_remote_gatt_client_info(addr);
1195 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1196 g_variant_unref(var);
1197 if (response_needed)
1198 g_dbus_method_invocation_return_value(invocation, NULL);
1200 g_object_unref(invocation);
1204 len = g_variant_get_size(var);
1205 if (len > 0 && len < 600) {
1207 data = (char *)g_variant_get_data(var);
1208 memcpy(ev.value, data, len);
1212 if (response_needed) {
1213 /* Store requets information */
1214 req_info = g_new0(struct gatt_req_info, 1);
1215 req_info->attr_path = g_strdup(object_path);
1216 req_info->svc_path = g_strdup(svc_info->serv_path);
1217 req_info->request_id = req_id;
1218 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1219 req_info->offset = offset;
1220 req_info->context = invocation;
1222 /* Append request info in list of requests for the particular connection */
1223 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1226 g_object_unref(invocation);
1229 /* Send HAL event */
1230 ev.conn_id = conn_info->connection_id;
1231 ev.trans_id = req_id;
1232 ev.att_handle = char_hdl;
1234 ev.need_rsp = response_needed;
1237 /* Convert address to hex */
1238 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1240 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1242 g_variant_unref(var);
1245 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1248 struct gatt_service_info *svc_info = NULL;
1249 struct hal_ev_gatt_server_notifcation_change ev;
1252 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1253 if (svc_info == NULL || event_cb == NULL)
1256 /* Send HAL event */
1257 memset(&ev, 0, sizeof(ev));
1258 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1259 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1260 ev.att_handle = char_hdl;
1263 /* Convert address to hex */
1264 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1266 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1269 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1272 struct gatt_service_info *svc_info = NULL;
1273 struct hal_ev_gatt_server_notifcation_change ev;
1276 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1277 if (svc_info == NULL || event_cb == NULL)
1280 /* Send HAL event */
1281 memset(&ev, 0, sizeof(ev));
1282 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1283 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1284 ev.att_handle = char_hdl;
1287 /* Convert address to hex */
1288 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1290 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1293 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1295 gboolean complete = FALSE;
1298 struct gatt_service_info *svc_info = NULL;
1299 struct gatt_client_info_t *conn_info = NULL;
1301 struct hal_ev_gatt_server_indicate_cfm ev;
1303 DBG("IndicateConfirm");
1304 DBG("Application path = %s", object_path);
1305 DBG("Sender = %s", sender);
1307 g_variant_get(parameters, "(&sb)", &addr, &complete);
1308 DBG("Remote Device address number = %s", addr);
1309 DBG("Is Indicate confirmation for last device [%d]", complete);
1311 /* Check if device is already in connected list */
1312 conn_info = __bt_find_remote_gatt_client_info(addr);
1314 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1316 if (svc_info == NULL || conn_info == NULL
1317 || event_cb == NULL) {
1321 /* Send HAL event */
1322 memset(&ev, 0, sizeof(ev));
1323 ev.conn_id = conn_info->connection_id;
1324 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1325 ev.att_handle = char_hdl;
1327 /* Convert address to hex */
1328 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1330 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1331 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1335 struct hal_ev_gatt_server_acquire_write_res ev;
1336 struct gatt_service_info *svc_info = NULL;
1337 struct gatt_req_info *req_info = NULL;
1338 struct gatt_client_info_t *conn_info = NULL;
1339 char * dev_path = NULL;
1341 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1343 DBG("AcquireWrite");
1344 DBG("Application path = %s", object_path);
1345 DBG("Sender = %s", sender);
1348 g_variant_get(parameters, "(a{sv})", &iter);
1350 GVariant* value = NULL;
1351 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1352 if (g_strcmp0(key, "MTU") == 0)
1353 g_variant_get(value, "i", &mtu);
1354 else if (g_strcmp0(key, "link") == 0)
1355 g_variant_get(value, "s", &link);
1356 else if (g_strcmp0(key, "device") == 0)
1357 g_variant_get(value, "o", &dev_path);
1360 DBG("AcquireWrite values retived");
1361 DBG(" path %s LINK = %s, MTU = %u", addr, link, mtu);
1363 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1365 _bt_hal_convert_device_path_to_address(dev_path, addr);
1367 DBG("remote address %s", addr);
1369 /* Check if device is already in connected list */
1370 conn_info = __bt_find_remote_gatt_client_info(addr);
1372 if (conn_info == NULL) {
1373 ERR("Cleint info not found\n");
1377 if (svc_info == NULL) {
1378 ERR("svc_info info not found\n");
1382 /* Store requets information */
1383 req_info = g_new0(struct gatt_req_info, 1);
1384 req_info->attr_path = g_strdup(object_path);
1385 req_info->svc_path = g_strdup(svc_info->serv_path);
1386 req_info->request_id = conn_info->connection_id;
1387 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1388 req_info->offset = mtu;
1389 req_info->context = invocation;
1391 /* Append request info in list of requests for the particular connection */
1392 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1394 /* Send HAL event */
1395 memset(&ev, 0, sizeof(ev));
1396 ev.conn_id = conn_info->connection_id;
1397 ev.char_handl = char_hdl;
1399 ev.trans_id = conn_info->connection_id;
1400 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1401 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1403 DBG("HAL_EV_GATT_ACQUIRE_WRITE_RES called");
1407 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1411 struct hal_ev_gatt_server_acquire_notify ev;
1412 struct gatt_service_info *svc_info = NULL;
1413 struct gatt_client_info_t *conn_info = NULL;
1414 struct gatt_req_info *req_info = NULL;
1416 DBG("AcquireNotify");
1417 DBG("Application path = %s", object_path);
1418 DBG("Sender = %s", sender);
1421 g_variant_get(parameters, "(a{sv})", &iter);
1423 GVariant* value = NULL;
1424 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1425 if (g_strcmp0(key, "MTU") == 0)
1426 g_variant_get(value, "q", &mtu);
1429 DBG("AcquireNotify values retived");
1430 DBG(" MTU = %u", mtu);
1432 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1434 if (svc_info == NULL) {
1435 ERR("svc_info info not found\n");
1439 /* Store requets information */
1440 req_info = g_new0(struct gatt_req_info, 1);
1441 req_info->attr_path = g_strdup(object_path);
1442 req_info->svc_path = g_strdup(svc_info->serv_path);
1443 req_info->request_id = 33;
1444 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1445 req_info->offset = mtu;
1446 req_info->context = invocation;
1448 conn_info = g_new0(struct gatt_client_info_t, 1);
1449 conn_info->addr = g_strdup(object_path);
1450 INFO("Added GATT client path[%s]", conn_info->addr);
1451 conn_info->connection_id = 33;
1452 conn_info->instance_id = 33;
1453 /* Append request info in list of requests for the particular connection */
1454 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1455 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1457 /* Send HAL event */
1458 memset(&ev, 0, sizeof(ev));
1460 ev.char_handl = char_hdl;
1464 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1466 DBG("HAL_EV_GATT_ACQUIRE_NOTIFY_RES called");
1472 g_dbus_method_invocation_return_value(invocation, NULL);
1475 static gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1478 GError *error = NULL;
1479 GVariantBuilder *array_builder;
1481 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1482 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1483 g_variant_builder_add(array_builder, "s", interface);
1485 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1486 "org.freedesktop.Dbus.Objectmanager",
1487 "InterfacesRemoved",
1488 g_variant_new("(oas)",
1489 object_path, array_builder),
1493 if (error != NULL) {
1494 /* dbus gives error cause */
1495 ERR("d-bus api failure: errcode[%x], message[%s]",
1496 error->code, error->message);
1497 g_clear_error(&error);
1500 g_variant_builder_unref(array_builder);
1505 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1512 g_free(desc_info->desc_path);
1513 g_free(desc_info->desc_uuid);
1514 g_free(desc_info->desc_value);
1516 for (i = 0; i < desc_info->flags_length; i++)
1517 g_free(desc_info->desc_flags[i]);
1522 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1529 g_free(char_info->char_path);
1530 g_free(char_info->char_uuid);
1531 g_free(char_info->char_value);
1533 for (i = 0; i < char_info->flags_length; i++)
1534 g_free(char_info->char_flags[i]);
1540 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1545 g_free(svc_info->serv_path);
1546 g_free(svc_info->service_uuid);
1550 static const GDBusInterfaceVTable desc_interface_vtable = {
1551 __bt_gatt_desc_method_call,
1556 static const GDBusInterfaceVTable char_interface_vtable = {
1557 __bt_gatt_char_method_call,
1562 static const GDBusInterfaceVTable serv_interface_vtable = {
1568 static const GDBusInterfaceVTable manager_interface_vtable = {
1569 __bt_gatt_manager_method_call,
1575 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1576 const gchar *introspection_data)
1579 GDBusNodeInfo *node_info = NULL;
1581 if (introspection_data == NULL)
1585 DBG("Create new node info");
1586 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1589 ERR("Unable to create node: %s", err->message);
1590 g_clear_error(&err);
1597 /* To send stack event to hal-av handler */
1598 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1603 void _bt_hal_unregister_gatt_server_handler_cb(void)
1608 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1610 struct hal_ev_gatt_desc_added ev;
1611 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1613 /* Prepare to GATT characteristic added event */
1614 memset(&ev, 0, sizeof(ev));
1615 ev.status = BT_STATUS_SUCCESS;
1616 ev.server_instance = data->instance_data;
1617 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1618 ev.service_handle = data->srvc_hdl;
1619 ev.desc_handle = data->desc_hdl;
1622 ERR("GATT Descriptor Added callback registered");
1624 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1625 data->instance_data, data->srvc_hdl, data->desc_hdl);
1627 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1634 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1636 struct hal_ev_gatt_char_added ev;
1637 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1639 /* Prepare to GATT characteristic added event */
1640 memset(&ev, 0, sizeof(ev));
1641 ev.status = BT_STATUS_SUCCESS;
1642 ev.server_instance = data->instance_data;
1643 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1644 ev.service_handle = data->srvc_hdl;
1645 ev.char_handle = data->char_hdl;
1648 ERR("GATT Characteristic Added callback registered");
1650 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1651 data->instance_data, data->srvc_hdl, data->char_hdl);
1653 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1660 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1662 struct hal_ev_gatt_service_added ev;
1663 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1665 /* Prepare to GATT Service added event */
1666 memset(&ev, 0, sizeof(ev));
1667 ev.status = BT_STATUS_SUCCESS;
1668 ev.server_instance = data->instance_data;
1669 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1670 ev.service_handle = data->srvc_hdl;
1671 ev.is_primary = data->is_primary;
1674 ERR("GATT Service Added callback registered");
1676 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1677 data->instance_data, data->srvc_hdl);
1678 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1685 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1687 struct hal_ev_gatt_service_started ev;
1688 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1690 /* Prepare to GATT Service added event */
1691 memset(&ev, 0, sizeof(ev));
1692 ev.status = BT_STATUS_SUCCESS;
1693 ev.server_instance = data->instance_data;
1694 ev.service_handle = data->srvc_hdl;
1697 ERR("GATT Service Started callback registered");
1699 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1700 data->instance_data, data->srvc_hdl);
1701 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1708 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1710 struct hal_ev_gatt_service_deleted ev;
1711 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1713 /* Prepare to GATT Service added event */
1714 memset(&ev, 0, sizeof(ev));
1715 ev.status = BT_STATUS_SUCCESS;
1716 ev.server_instance = data->instance_data;
1717 ev.service_handle = data->srvc_hdl;
1720 ERR("GATT Service Deleted callback registered");
1722 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1723 data->instance_data, data->srvc_hdl);
1724 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1731 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1733 struct hal_ev_server_instance_registered ev;
1734 hal_register_server_data *data = (hal_register_server_data*) user_data;
1736 /* Prepare to send AV connecting event */
1737 memset(&ev, 0, sizeof(ev));
1738 ev.status = BT_STATUS_SUCCESS;
1739 ev.server_instance = data->instance_data;
1740 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1743 ERR("GATT Register Server Instance Callback not registered");
1745 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1746 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1754 static int bt_hal_gatts_get_gatt_server_instance()
1759 struct hal_gatts_server_register_info_t *info = NULL;
1761 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1762 info = (struct hal_gatts_server_register_info_t *)l->data;
1767 return info->server_if;
1773 int bt_hal_gatts_generate_server_id()
1775 return ++g_server_inst_id;
1778 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_from_uuid(bt_uuid_t *app_uuid)
1783 struct hal_gatts_server_register_info_t *info = NULL;
1785 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1786 info = (struct hal_gatts_server_register_info_t *)l->data;
1791 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
1792 DBG("gatt server register found");
1800 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info(int server_if)
1803 struct hal_gatts_server_register_info_t *info = NULL;
1805 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1806 info = (struct hal_gatts_server_register_info_t *)l->data;
1811 if (info->server_if == server_if) {
1819 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_by_slot_id(int adv_slot_id)
1824 struct hal_gatts_server_register_info_t *info = NULL;
1826 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1827 info = (struct hal_gatts_server_register_info_t *)l->data;
1832 if (info->adv_slot_id == adv_slot_id) {
1833 DBG("gatt server register found");
1841 static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_uuid_t *app_uuid)
1843 struct hal_gatts_server_register_info_t * server_register_info = NULL;
1845 server_register_info = bt_hal_gatts_find_server_register_info_from_uuid(app_uuid);
1846 if (server_register_info != NULL) {
1847 DBG("gatt server is already registered");
1848 return server_register_info;
1851 server_register_info = g_malloc0(sizeof(struct hal_gatts_server_register_info_t));
1852 server_register_info->server_if = bt_hal_gatts_generate_server_id();
1854 DBG("Adding the gatt server app. server_if:[%d]", server_register_info->server_if);
1856 server_register_info->adv_slot_id = -1;
1857 memcpy(&server_register_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
1858 hal_gatts_server_register_list = g_slist_append(hal_gatts_server_register_list, server_register_info);
1860 return server_register_info;
1863 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1865 CHECK_BTGATT_INIT();
1866 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1868 DBG("Register server instance request");
1869 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1871 server_register_info = bt_hal_gatts_add_server_app(uuid);
1872 user_data->instance_data = server_register_info->server_if;
1875 * As we need to provide async callback to user from HAL, simply schedule a
1876 * callback method which will carry actual result
1878 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1879 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1881 /* If available, then return success, else return error */
1882 return BT_STATUS_SUCCESS;
1885 static void _bt_hal_remove_gatt_server_from_list(int server_if)
1888 struct gatt_server_app *info = NULL;
1890 for (l = gatt_server_apps; l != NULL;) {
1891 info = (struct gatt_server_app*)l->data;
1892 l = g_slist_next(l);
1895 if (info->slot == server_if) {
1896 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1897 info->app_path, info->slot);
1899 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1900 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1901 In above case, only advertising block will be deallocated, Gatt Server will remain
1903 if (info->services == NULL) {
1904 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1905 INFO("Total gatt server apps still existing after removing above is [%d]",
1906 g_slist_length(gatt_server_apps));
1908 /* DBUS Unregister only for current app */
1909 __bt_hal_gatt_deinit(info->app_path);
1911 g_free(info->app_path);
1915 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1916 g_slist_length(info->services));
1922 static bt_status_t gatt_server_unregister_app(int server_if)
1924 CHECK_BTGATT_INIT();
1925 DBG("Un-Register server instance request [%d]", server_if);
1926 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1929 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
1930 if (server_register_info == NULL) {
1931 DBG("gatt server is not registered");
1932 return BT_STATUS_SUCCESS;
1935 /* remove the gatt server register info from the register list */
1936 hal_gatts_server_register_list = g_slist_remove(hal_gatts_server_register_list, server_register_info);
1937 g_free(server_register_info);
1939 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
1940 _bt_hal_remove_gatt_server_from_list(server_if);
1941 return BT_STATUS_SUCCESS;
1944 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
1946 CHECK_BTGATT_INIT();
1947 return BT_STATUS_SUCCESS;
1950 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
1953 GError *g_error = NULL;
1954 GVariant *reply = NULL;
1958 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
1959 g_object_unref(proxy);
1960 if (reply == NULL) {
1961 ERR("Disconnect LE Dbus Call Error");
1963 ERR("Error: %s\n", g_error->message);
1964 g_clear_error(&g_error);
1967 g_variant_unref(reply);
1971 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
1973 CHECK_BTGATT_INIT();
1975 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
1977 GDBusProxy *device_proxy;
1978 GDBusConnection *g_conn;
1979 struct gatt_client_info_t *conn_info = NULL;
1983 if (NULL == bd_addr) {
1984 ERR("bd_addr is NULL");
1985 return BT_STATUS_PARM_INVALID;
1988 /* GDBUS Connection Info validate */
1989 g_conn = _bt_hal_get_system_gconn();
1990 if (g_conn == NULL) {
1991 ERR("Could not get System DBUS Connection");
1992 return BT_STATUS_FAIL;
1995 /* Connection Info validate */
1996 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
1997 if (conn_info == NULL) {
1998 ERR("No Connection Inforamtion!!!");
1999 return BT_STATUS_FAIL;
2002 _bt_hal_convert_addr_type_to_string(device_address,
2003 (unsigned char *)bd_addr->address);
2005 //check if connection has the same device address
2006 if (g_strcmp0(conn_info->addr, device_address) != 0) {
2007 ERR("device address [%s] does not match", device_address);
2008 return BT_STATUS_FAIL;
2011 device_path = _bt_hal_get_device_object_path(conn_info->addr);
2012 if (device_path == NULL) {
2013 ERR("device_path is NULL");
2014 return BT_STATUS_PARM_INVALID;
2017 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
2018 NULL, BT_HAL_BLUEZ_NAME,
2019 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2022 g_free(device_path);
2023 if (device_proxy == NULL)
2024 return BT_STATUS_FAIL;
2026 INFO("Disconnect LE [%s]", device_address);
2028 g_dbus_proxy_call(device_proxy, "DisconnectLE",
2030 G_DBUS_CALL_FLAGS_NONE,
2031 BT_HAL_MAX_DBUS_TIMEOUT,
2033 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
2036 return BT_STATUS_SUCCESS;
2039 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
2044 uuid = btuuid2str(srvc_id->uu);
2045 DBG("Original UUID [%s]", uuid);
2047 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
2048 /* Extract Standard UUID string */
2049 memcpy(uuid_buf, &uuid[4], 4);
2051 DBG("Converted string [%s]", uuid_buf);
2052 return g_strdup(uuid_buf);
2054 return strdup(uuid);
2057 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
2060 /* For GATT service specific */
2061 GDBusNodeInfo *node_info;
2064 struct gatt_service_info *serv_info = NULL;
2065 GVariantBuilder *builder = NULL;
2066 GVariantBuilder *builder1 = NULL;
2067 GVariantBuilder *inner_builder = NULL;
2068 gboolean svc_primary = TRUE;
2069 GError *error = NULL;
2070 hal_gatt_service_added *user_data = NULL;
2071 DBG("Service add to DBUS slot [%d]", slot);
2073 node_info = __bt_gatt_create_method_node_info(
2074 service_introspection_xml);
2076 if (node_info == NULL)
2077 return BT_STATUS_FAIL;
2079 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
2080 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
2081 DBG("gatt service path is [%s]", path);
2083 object_id = g_dbus_connection_register_object(g_conn, path,
2084 node_info->interfaces[0],
2085 &serv_interface_vtable,
2086 NULL, NULL, &error);
2088 if (object_id == 0) {
2089 ERR("failed to register: %s", error->message);
2090 g_error_free(error);
2092 return BT_STATUS_FAIL;
2094 /* Add object_id/gatt service information; it's required at the time of
2095 * service unregister and Getmanagedobjects
2097 serv_info = g_new0(struct gatt_service_info, 1);
2099 serv_info->serv_path = g_strdup(path);
2100 serv_info->serv_id = object_id;
2101 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
2102 serv_info->is_svc_registered = FALSE;
2103 serv_info->is_svc_primary = svc_primary;
2104 DBG("Service Handle to be added is [%d]", gatt_service_handle);
2105 serv_info->service_handle = gatt_service_handle;
2107 /* Update service in GATT Server service List */
2108 gatt_services = g_slist_append(gatt_services, serv_info);
2110 /* emit interfacesadded signal here for service path */
2111 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2112 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2114 g_variant_builder_add(inner_builder, "{sv}",
2115 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
2117 g_variant_builder_add(inner_builder, "{sv}",
2118 "Primary", g_variant_new_boolean(svc_primary));
2120 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2122 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
2123 g_variant_new("ao", builder1));
2125 g_variant_builder_add(builder, "{sa{sv}}",
2126 GATT_SERV_INTERFACE, inner_builder);
2128 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2129 "org.freedesktop.Dbus.ObjectManager",
2131 g_variant_new("(oa{sa{sv}})",
2136 /* dbus gives error cause */
2137 ERR("d-bus api failure: errcode[%x], message[%s]",
2138 error->code, error->message);
2139 g_clear_error(&error);
2143 /* Send Service handle to application */
2144 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2145 user_data->srvc_hdl = serv_info->service_handle;
2146 user_data->instance_data = slot;
2147 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2148 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2150 /* Save newly created service in GATT Server's service list */
2151 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2155 g_variant_builder_unref(inner_builder);
2156 g_variant_builder_unref(builder);
2157 g_variant_builder_unref(builder1);
2158 return BT_STATUS_SUCCESS;
2161 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2164 char *app_path = (char*)user_data;
2165 INFO("UnregisterApplication is completed app [%s]", app_path);
2166 GError *error = NULL;
2167 GVariant *result = NULL;
2170 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2172 if (result == NULL) {
2173 /* dBUS-RPC is failed */
2174 ERR("Dbus-RPC is failed\n");
2176 if (error != NULL) {
2177 /* dBUS gives error cause */
2178 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2179 error->code, error->message);
2180 g_clear_error(&error);
2183 g_variant_unref(result);
2188 static void __bt_hal_gatt_deinit(char *app_path)
2190 GDBusProxy *proxy = NULL;
2194 /* Step1: Remove requested App */
2195 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2196 "/org/bluez/hci0", "org.bluez.GattManager1");
2201 INFO("UnregisterApplication : path [%s]", app_path);
2203 /* Async Call to Unregister Service */
2204 data = g_strdup(app_path);
2205 g_dbus_proxy_call(proxy,
2206 "UnregisterApplication",
2207 g_variant_new("(o)",
2209 G_DBUS_CALL_FLAGS_NONE, -1,
2211 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2214 /* If requested app is last GATT Server app, then clean all resources */
2215 if (gatt_server_apps == NULL) {
2216 INFO("All GATT servers are removed, clean all DBUS resources");
2218 /* unregister the exported interface for object manager */
2219 g_dbus_connection_unregister_object(g_conn, manager_id);
2221 g_bus_unown_name(owner_id);
2224 g_object_unref(manager_gproxy);
2225 manager_gproxy = NULL;
2231 static int __bt_hal_gatt_init(void)
2235 /* Only once for ALL GATT Servers */
2236 if (owner_id == 0) {
2240 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2243 ERR("Unable to connect to gdbus: %s", err->message);
2244 g_clear_error(&err);
2246 return BT_STATUS_FAIL;
2249 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2250 INFO("well-known name: %s", name);
2252 owner_id = g_bus_own_name_on_connection(g_conn, name,
2253 G_BUS_NAME_OWNER_FLAGS_NONE,
2254 NULL, NULL, NULL, NULL);
2256 INFO("Owner ID [%d]", owner_id);
2258 /* Only once for ALL GATT Servers */
2259 if (manager_node_info == NULL) {
2260 /* Register ObjectManager interface */
2261 manager_node_info = __bt_gatt_create_method_node_info(
2262 manager_introspection_xml);
2264 if (manager_node_info == NULL) {
2265 ERR("failed to get node info");
2266 return BT_STATUS_FAIL;
2271 return BT_STATUS_SUCCESS;
2274 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2278 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2279 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2280 if (app->slot == slot) {
2281 INFO("GATT Server app found app path [%s] instance [%d]",
2282 app->app_path, app->slot);
2283 *app_path = app->app_path;
2287 /* GATT Server not found */
2291 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2293 if (app_path == NULL)
2296 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2297 app->app_path = g_strdup(app_path);
2299 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2300 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2305 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2308 CHECK_BTGATT_INIT();
2309 char *app_path = NULL;
2310 GError *error = NULL;
2313 int result = BT_STATUS_SUCCESS;
2315 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2316 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2318 /* Check if this GATT server Application is already registered with DBUS */
2319 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2321 if (app_path != NULL) {
2322 DBG("GATT server path is already defined [%s]", app_path);
2323 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2325 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2326 result = __bt_hal_gatt_init();
2327 if (result != BT_STATUS_SUCCESS)
2330 /* Only once for each GATT Server */
2331 app_path = g_strdup_printf("/com/%d", server_if);
2333 app_id = g_malloc0(sizeof(int));
2334 *app_id = server_if;
2336 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2337 manager_node_info->interfaces[0],
2338 &manager_interface_vtable,
2339 (gpointer)app_id, NULL, &error);
2341 if (manager_id == 0) {
2342 ERR("failed to register: %s", error->message);
2343 g_error_free(error);
2346 INFO("manager_id [%d]", manager_id);
2348 /* For current GATT Server, app_path is created, save it in Table */
2349 _bt_hal_update_gatt_server_path(server_if, app_path);
2351 /* Add GATT Service to DBUS */
2352 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2358 INFO("Successfully added service");
2359 return BT_STATUS_SUCCESS;
2366 INFO("Service addition failed!!");
2367 return BT_STATUS_FAIL;
2370 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2371 int included_handle)
2373 CHECK_BTGATT_INIT();
2374 return BT_STATUS_SUCCESS;
2378 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2381 GSList *gatt_services = NULL;
2383 struct gatt_service_info *info = NULL;
2385 gatt_services = _bt_get_service_list_from_server(instance);
2387 len = g_slist_length(gatt_services);
2388 l = g_slist_nth(gatt_services, len -1);
2394 if (info->service_handle == service_handle)
2399 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2403 GSList *gatt_services = NULL;
2404 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2406 gatt_services = _bt_get_service_list_from_server(instance);
2408 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2409 struct gatt_service_info *info = l->data;
2410 INFO("Got one service with handle [%d]", info->service_handle);
2411 if (info->service_handle == service_handle)
2414 ERR("Gatt service with handle [%d] not found", service_handle);
2418 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2419 bt_uuid_t *uuid, int properties,
2423 GError *error = NULL;
2425 GDBusNodeInfo *node_info;
2427 GVariantBuilder *builder = NULL;
2428 GVariantBuilder *inner_builder = NULL;
2429 struct gatt_service_info *serv_info = NULL;
2430 struct gatt_char_info *char_info = NULL;
2431 GVariantBuilder *builder2 = NULL;
2432 GVariantBuilder *builder3 = NULL;
2433 GVariant *flags_val = NULL;
2435 char *char_flags[NUMBER_OF_FLAGS];
2437 hal_gatt_char_added *user_data = NULL;
2440 CHECK_BTGATT_INIT();
2441 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2442 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2444 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2445 if (serv_info == NULL)
2446 return BT_STATUS_FAIL;
2448 node_info = __bt_gatt_create_method_node_info(
2449 characteristics_introspection_xml);
2451 if (node_info == NULL)
2452 return BT_STATUS_FAIL;
2454 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2455 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2456 DBG("gatt characteristic path is [%s]", path);
2458 app_id = g_malloc0(sizeof(int));
2461 object_id = g_dbus_connection_register_object(g_conn, path,
2462 node_info->interfaces[0],
2463 &char_interface_vtable,
2464 (gpointer)app_id, NULL, &error);
2466 if (object_id == 0) {
2467 ERR("failed to register: %s", error->message);
2468 g_error_free(error);
2471 return BT_STATUS_FAIL;
2474 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2475 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2476 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2477 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2478 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2479 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2480 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2481 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2483 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2485 char_info = g_new0(struct gatt_char_info, 1);
2487 char_info->char_path = g_strdup(path);
2488 char_info->char_id = object_id;
2489 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2490 for (i = 0; i < flag_count; i++)
2491 char_info->char_flags[i] = char_flags[i];
2494 char_info->flags_length = flag_count;
2495 char_info->char_handle = gatt_char_handle;
2498 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2499 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2501 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2502 g_variant_new("s", char_info->char_uuid));
2503 g_variant_builder_add(inner_builder, "{sv}", "Service",
2504 g_variant_new("o", serv_info->serv_path));
2506 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2508 for (i = 0; i < flag_count; i++)
2509 g_variant_builder_add(builder2, "s", char_flags[i]);
2511 flags_val = g_variant_new("as", builder2);
2512 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2515 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2517 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2518 g_variant_new("ao", builder3));
2520 g_variant_builder_add(builder, "{sa{sv}}",
2521 GATT_CHAR_INTERFACE,
2524 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2525 "org.freedesktop.Dbus.ObjectManager",
2527 g_variant_new("(oa{sa{sv}})",
2532 /* dbus gives error cause */
2533 ERR("d-bus api failure: errcode[%x], message[%s]",
2534 error->code, error->message);
2535 g_clear_error(&error);
2539 //*char_path = g_strdup(path);
2544 /* Send Service handle to application */
2545 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2546 user_data->srvc_hdl = serv_info->service_handle;
2547 user_data->char_hdl = gatt_char_handle;
2548 user_data->instance_data = slot;
2549 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2550 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2552 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2553 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2558 g_variant_builder_unref(inner_builder);
2559 g_variant_builder_unref(builder);
2560 g_variant_builder_unref(builder2);
2561 g_variant_builder_unref(builder3);
2563 return BT_STATUS_SUCCESS;
2566 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2569 CHECK_BTGATT_INIT();
2571 // static int desc_id = 1;
2572 GError *error = NULL;
2574 GDBusNodeInfo *node_info;
2576 GVariantBuilder *builder = NULL;
2577 GVariantBuilder *inner_builder = NULL;
2579 struct gatt_char_info *char_info = NULL;
2580 struct gatt_desc_info *desc_info = NULL;
2581 struct gatt_service_info *serv_info = NULL;
2583 gchar **line_argv = NULL;
2585 char *char_path = NULL;
2588 GVariantBuilder *builder2 = NULL;
2589 GVariant *flags_val = NULL;
2591 char *desc_flags[NUMBER_OF_FLAGS];
2595 hal_gatt_desc_added *user_data = NULL;
2602 /* Fetch service data for the GATT server */
2603 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2604 if (serv_info == NULL)
2605 return BT_STATUS_FAIL;
2607 /* Fetch list of characteristics from the service info */
2608 l = serv_info->char_data;
2610 /* Fetch last char info from the characteristic list */
2611 char_info = g_slist_last(l)->data;
2612 if (char_info == NULL)
2613 return BT_STATUS_FAIL;
2615 /* Fetch characteristic path from char info */
2616 char_path = char_info->char_path;
2618 line_argv = g_strsplit_set(char_path, "/", 0);
2619 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2622 node_info = __bt_gatt_create_method_node_info(
2623 descriptor_introspection_xml);
2625 if (node_info == NULL) {
2626 g_strfreev(line_argv);
2628 return BT_STATUS_FAIL;
2631 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2633 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2634 DBG("gatt descriptor path is [%s]", path);
2636 app_id = g_malloc0(sizeof(int));
2639 object_id = g_dbus_connection_register_object(g_conn, path,
2640 node_info->interfaces[0],
2641 &desc_interface_vtable,
2642 (gpointer)app_id, NULL, &error);
2644 if (object_id == 0) {
2645 ERR("failed to register: %s", error->message);
2646 g_error_free(error);
2648 g_strfreev(line_argv);
2651 return BT_STATUS_FAIL;
2654 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2656 desc_info = g_new0(struct gatt_desc_info, 1);
2658 desc_info->desc_path = g_strdup(path);
2659 desc_info->desc_id = object_id;
2660 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2662 for (i = 0; i < flag_count; i++)
2663 desc_info->desc_flags[i] = desc_flags[i];
2665 desc_info->flags_length = flag_count;
2666 desc_info->desc_handle = gatt_desc_handle;
2669 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2670 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2672 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2673 g_variant_new("s", btuuid2str(uuid->uu)));
2674 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2675 g_variant_new("o", char_path));
2677 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2679 for (i = 0; i < flag_count; i++)
2680 g_variant_builder_add(builder2, "s", desc_flags[i]);
2682 flags_val = g_variant_new("as", builder2);
2683 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2686 g_variant_builder_add(builder, "{sa{sv}}",
2687 GATT_DESC_INTERFACE,
2690 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2691 "org.freedesktop.Dbus.ObjectManager",
2693 g_variant_new("(oa{sa{sv}})",
2696 if (error != NULL) {
2697 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2698 error->code, error->message);
2699 g_clear_error(&error);
2702 //*desc_path = g_strdup(path);
2704 /* Save newly created descriptor to GATT server's service's characteristic */
2705 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2707 /* Send descriptor handle to application */
2708 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2709 user_data->srvc_hdl = serv_info->service_handle;
2710 user_data->desc_hdl = gatt_desc_handle;
2711 user_data->instance_data = slot;
2712 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2713 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2718 g_strfreev(line_argv);
2719 g_variant_builder_unref(inner_builder);
2720 g_variant_builder_unref(builder);
2721 return BT_STATUS_SUCCESS;
2724 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2726 GError *error = NULL;
2728 char *data = (char*) user_data;
2729 INFO("RegisterApplication is completed path [%s]", data);
2731 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2733 if (result == NULL) {
2734 /* dBUS-RPC is failed */
2735 ERR("Dbus-RPC is failed\n");
2737 if (error != NULL) {
2738 /* dBUS gives error cause */
2739 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2740 error->code, error->message);
2741 g_clear_error(&error);
2744 g_variant_unref(result);
2749 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2750 const gchar *path, const gchar *interface)
2756 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2761 ERR("Unable to connect to gdbus: %s", err->message);
2762 g_clear_error(&err);
2767 proxy = g_dbus_proxy_new_sync(g_conn,
2768 G_DBUS_PROXY_FLAGS_NONE, NULL,
2770 interface, NULL, &err);
2774 ERR("Unable to create proxy: %s", err->message);
2775 g_clear_error(&err);
2779 manager_gproxy = proxy;
2784 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2785 const gchar *path, const gchar *interface)
2787 return (manager_gproxy) ? manager_gproxy :
2788 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2792 static void __bt_register_application_to_dbus(int slot)
2794 GDBusProxy *proxy = NULL;
2795 char *app_path = NULL;
2797 DBG("RegisterApplication slot [%d]", slot);
2799 /* It is impossible that app path is still not initialized */
2800 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2802 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2803 "/org/bluez/hci0", "org.bluez.GattManager1");
2805 data = g_strdup(app_path);
2806 g_dbus_proxy_call(proxy,
2807 "RegisterApplication",
2808 g_variant_new("(oa{sv})",
2810 G_DBUS_CALL_FLAGS_NONE, -1,
2812 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2814 INFO("GATT server started");
2817 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2819 CHECK_BTGATT_INIT();
2820 struct gatt_service_info *serv_info = NULL;
2821 hal_gatt_service_started *user_data = NULL;
2822 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2824 /* Fetch service data for the GATT server */
2825 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2826 if (serv_info == NULL)
2827 return BT_STATUS_FAIL;
2829 if (serv_info->is_svc_registered)
2830 DBG("service already registered \n");
2832 serv_info->is_svc_registered = TRUE;
2834 /* Send Service handle to application */
2835 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2836 user_data->srvc_hdl = serv_info->service_handle;
2837 user_data->instance_data = server_if;
2838 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2840 /* If this is nth Service that is started, then register application at this point */
2841 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2842 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2844 __bt_register_application_to_dbus(server_if);
2847 return BT_STATUS_SUCCESS;
2850 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2852 CHECK_BTGATT_INIT();
2853 INFO("Stop service successful");
2854 return BT_STATUS_SUCCESS;
2857 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2859 CHECK_BTGATT_INIT();
2860 struct gatt_service_info *serv_info = NULL;
2861 hal_gatt_service_deleted *user_data = NULL;
2864 int err = BT_STATUS_SUCCESS;
2865 int ret = BT_STATUS_SUCCESS;
2866 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2868 /* Fetch service data for the GATT server */
2869 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2870 if (serv_info == NULL) {
2871 ERR("Could not find service info svc handle [%d] server slot [%d]",
2872 service_handle, server_if);
2873 return BT_STATUS_FAIL;
2876 if (serv_info->is_svc_registered == FALSE) {
2877 ERR("service Not registered path [%s] handle [%d]",
2878 serv_info->serv_path, service_handle);
2881 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2882 struct gatt_char_info *char_info = l->data;
2884 if (char_info == NULL)
2887 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2888 struct gatt_desc_info *desc_info = l1->data;
2890 if (desc_info == NULL)
2893 ret = g_dbus_connection_unregister_object(g_conn,
2894 desc_info->desc_id);
2896 __bt_hal_gatt_emit_interface_removed(
2897 desc_info->desc_path,
2898 GATT_DESC_INTERFACE);
2900 err = BT_STATUS_FAIL;
2903 /* list remove & free */
2904 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2905 __bt_hal_gatt_free_descriptor_info(desc_info);
2908 g_slist_free(char_info->desc_data);
2909 char_info->desc_data = NULL;
2911 ret = g_dbus_connection_unregister_object(g_conn,
2912 char_info->char_id);
2914 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2915 GATT_CHAR_INTERFACE);
2918 err = BT_STATUS_FAIL;
2921 /* list remove & free */
2922 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2923 __bt_hal_gatt_free_characteristic_info(char_info);
2926 g_slist_free(serv_info->char_data);
2927 serv_info->char_data = NULL;
2929 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2931 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2932 GATT_SERV_INTERFACE);
2935 err = BT_STATUS_FAIL;
2938 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
2940 DBG("Unregistered the service on properties interface");
2942 /* Remove from global list */
2943 gatt_services = g_slist_remove(gatt_services, serv_info);
2944 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
2946 /* Remove from GATT Server's list of services */
2947 _bt_remote_service_from_gatt_server(server_if, service_handle);
2949 if (gatt_services == NULL)
2950 INFO("All GATT Services of all GATT Servers are unregistered");
2952 if (err == BT_STATUS_SUCCESS) {
2953 INFO("Send GATT Service deleted Event");
2954 /* Send Service handle to application */
2955 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
2956 user_data->srvc_hdl = serv_info->service_handle;
2957 user_data->instance_data = server_if;
2958 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
2961 /* Free the service */
2962 __bt_hal_gatt_free_service_info(serv_info);
2966 static gboolean __bt_gatt_get_service_state(const char *service_path)
2968 struct gatt_service_info *svc_info = NULL;
2970 for (l = gatt_services; l; l = g_slist_next(l)) {
2972 svc_info = (struct gatt_service_info *)l->data;
2975 if (!g_strcmp0(svc_info->serv_path, service_path)) {
2976 DBG("Return the state of the gatt service %d",
2977 svc_info->is_svc_registered);
2978 return svc_info->is_svc_registered;
2982 DBG("gatt service info is NULL");
2986 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
2987 int len, int confirm, char* p_value)
2989 CHECK_BTGATT_INIT();
2992 GVariantBuilder *outer_builder;
2993 GVariantBuilder *invalidated_builder;
2995 /* For Value update via PropertyChange */
2996 GVariantBuilder *outer_builder1;
2997 GVariantBuilder *inner_builder1;
2998 GVariantBuilder *invalidated_builder1;
2999 GVariant *update_value = NULL;
3001 /* Other variables */
3002 struct gatt_client_info_t *conn_info = NULL;
3003 gchar *serv_path = NULL;
3004 char *char_path = NULL;
3005 gchar **line_argv = NULL;
3006 gboolean notify = TRUE;
3007 gboolean ret = TRUE;
3008 int err = BT_STATUS_SUCCESS;
3010 GError *error = NULL;
3013 memset(addr, 0x00, sizeof(addr));
3015 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3016 if (conn_info == NULL) {
3017 ERR("No Connection Inforamtion!!!");
3018 return BT_STATUS_FAIL;
3021 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
3023 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3024 if (char_path == NULL)
3025 return BT_STATUS_FAIL;
3027 line_argv = g_strsplit_set(char_path, "/", 0);
3028 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3030 if (!__bt_gatt_get_service_state(serv_path)) {
3031 DBG("service not registered for this characteristic \n");
3033 g_strfreev(line_argv);
3034 return BT_STATUS_FAIL;
3037 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3038 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3040 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
3041 g_variant_new("b", notify));
3043 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
3044 DBG("Send Indication to Unicast addr [%s]", addr);
3046 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
3047 g_variant_new("s", addr));
3049 DBG("Set characteristic Notification \n");
3050 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3052 "org.freedesktop.DBus.Properties",
3053 "PropertiesChanged",
3054 g_variant_new("(sa{sv}as)",
3055 "org.bluez.GattCharacteristic1",
3056 outer_builder, invalidated_builder),
3060 if (error != NULL) {
3061 ERR("D-Bus API failure: errCode[%x], \
3063 error->code, error->message);
3064 g_clear_error(&error);
3066 err = BT_STATUS_FAIL;
3069 g_variant_builder_unref(outer_builder);
3070 g_variant_builder_unref(invalidated_builder);
3073 /* Notifying Done, now update Value to Bluez via PropertyChanged */
3074 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
3076 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3077 for (i = 0; i < len; i++)
3078 g_variant_builder_add(inner_builder1, "y", p_value[i]);
3080 update_value = g_variant_new("ay", inner_builder1);
3083 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3084 g_variant_builder_add(outer_builder1, "{sv}", "Value",
3087 DBG("Updating characteristic value \n");
3088 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3090 "org.freedesktop.DBus.Properties",
3091 "PropertiesChanged",
3092 g_variant_new("(sa{sv}as)",
3093 "org.bluez.GattCharacteristic1",
3094 outer_builder1, invalidated_builder1),
3098 if (error != NULL) {
3099 ERR("D-Bus API failure: errCode[%x], \
3101 error->code, error->message);
3102 g_clear_error(&error);
3104 err = BT_STATUS_FAIL;
3106 struct gatt_char_info *char_info = NULL;
3108 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3109 if (char_info == NULL) {
3111 g_strfreev(line_argv);
3112 g_variant_builder_unref(inner_builder1);
3113 g_variant_builder_unref(outer_builder1);
3114 g_variant_builder_unref(invalidated_builder1);
3116 return BT_STATUS_FAIL;
3119 char_info->value_length = len;
3121 char_info->char_value = (char *)realloc(char_info->char_value, len);
3122 if (char_info->char_value) {
3123 for (i = 0; i < len; i++)
3124 char_info->char_value[i] = p_value[i];
3129 g_strfreev(line_argv);
3130 g_variant_builder_unref(inner_builder1);
3131 g_variant_builder_unref(outer_builder1);
3132 g_variant_builder_unref(invalidated_builder1);
3137 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3138 int status, btgatt_response_t *response)
3140 CHECK_BTGATT_INIT();
3142 struct gatt_req_info *req_info = NULL;
3143 struct gatt_client_info_t *conn_info = NULL;
3146 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3148 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3149 if (conn_info == NULL) {
3150 ERR("No Connection Inforamtion!!!");
3151 return BT_STATUS_FAIL;
3154 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3155 if (req_info == NULL) {
3156 ERR("No Request Inforamtion!!!");
3157 return BT_STATUS_FAIL;
3160 if (status != BT_STATUS_SUCCESS) {
3161 ERR("resp_state is 0x%X", status);
3163 g_dbus_method_invocation_return_dbus_error(req_info->context,
3164 "org.bluez.Error.Failed", "Application Error");
3166 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3168 req_info->context = NULL;
3169 if (req_info->attr_path)
3170 g_free(req_info->attr_path);
3171 if (req_info->svc_path)
3172 g_free(req_info->svc_path);
3175 return BT_STATUS_SUCCESS;
3178 DBG("Reponse Value length [%d]", response->attr_value.len);
3179 DBG("Request type: [%d]", req_info->request_type);
3182 for (i = 0; i < response->attr_value.len; i++)
3183 DBG("Resonse [%d] = [0x%x]", i, response->attr_value.value[i]);
3185 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3186 GVariantBuilder *inner_builder = NULL;
3187 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3189 if (response->attr_value.len > 0) {
3190 for (i = 0; i < response->attr_value.len; i++)
3191 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3193 g_dbus_method_invocation_return_value(req_info->context,
3194 g_variant_new("(ay)", inner_builder));
3196 g_variant_builder_unref(inner_builder);
3198 g_dbus_method_invocation_return_value(req_info->context, NULL);
3200 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3202 req_info->context = NULL;
3203 if (req_info->attr_path)
3204 g_free(req_info->attr_path);
3205 if (req_info->svc_path)
3206 g_free(req_info->svc_path);
3209 return BT_STATUS_SUCCESS;
3213 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3214 int status, int fd, int mtu, void *fdlist)
3216 CHECK_BTGATT_INIT();
3218 struct gatt_req_info *req_info = NULL;
3219 struct gatt_client_info_t *conn_info = NULL;
3221 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3223 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3224 if (conn_info == NULL) {
3225 ERR("No Connection Inforamtion!!!");
3226 return BT_STATUS_FAIL;
3229 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3230 if (req_info == NULL) {
3231 ERR("No Request Inforamtion!!!");
3232 return BT_STATUS_FAIL;
3235 if (status != BT_STATUS_SUCCESS) {
3236 ERR("resp_state is 0x%X", status);
3238 g_dbus_method_invocation_return_dbus_error(req_info->context,
3239 "org.bluez.Error.Failed", "Application Error");
3241 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3243 req_info->context = NULL;
3244 if (req_info->attr_path)
3245 g_free(req_info->attr_path);
3246 if (req_info->svc_path)
3247 g_free(req_info->svc_path);
3250 return BT_STATUS_SUCCESS;
3254 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3256 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3257 g_dbus_method_invocation_return_value_with_unix_fd_list(
3258 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3260 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3262 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3263 g_dbus_method_invocation_return_value_with_unix_fd_list(
3264 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3267 g_dbus_method_invocation_return_value(req_info->context, NULL);
3269 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3271 req_info->context = NULL;
3272 if (req_info->attr_path)
3273 g_free(req_info->attr_path);
3274 if (req_info->svc_path)
3275 g_free(req_info->svc_path);
3278 return BT_STATUS_SUCCESS;
3282 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3283 int value_length, char* att_value)
3285 CHECK_BTGATT_INIT();
3287 /* Other variables */
3288 char *char_path = NULL;
3289 gboolean ret = TRUE;
3290 GError *error = NULL;
3292 GVariantBuilder *outer_builder;
3293 GVariantBuilder *inner_builder;
3294 GVariantBuilder *invalidated_builder;
3295 GVariant *update_value = NULL;
3296 int err = BT_STATUS_SUCCESS;
3298 gchar **line_argv = NULL;
3299 gchar *serv_path = NULL;
3301 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3302 if (char_path == NULL)
3303 return BT_STATUS_FAIL;
3305 line_argv = g_strsplit_set(char_path, "/", 0);
3306 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3308 if (!__bt_gatt_get_service_state(serv_path)) {
3309 DBG("service not registered for this characteristic \n");
3311 g_strfreev(line_argv);
3312 return BT_STATUS_FAIL;
3316 line_argv = g_strsplit_set(char_path, "/", 0);
3317 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3319 if (!__bt_gatt_get_service_state(serv_path)) {
3320 DBG("service not registered for this characteristic \n");
3322 g_strfreev(line_argv);
3323 return BT_STATUS_FAIL;
3326 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3327 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3329 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3330 for (i = 0; i < value_length; i++)
3331 g_variant_builder_add(inner_builder, "y", att_value[i]);
3333 update_value = g_variant_new("ay", inner_builder);
3335 g_variant_builder_add(outer_builder, "{sv}", "Value",
3338 DBG("Updating characteristic value \n");
3339 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3341 "org.freedesktop.DBus.Properties",
3342 "PropertiesChanged",
3343 g_variant_new("(sa{sv}as)",
3344 "org.bluez.GattCharacteristic1",
3345 outer_builder, invalidated_builder),
3349 if (error != NULL) {
3350 ERR("D-Bus API failure: errCode[%x], \
3352 error->code, error->message);
3353 g_clear_error(&error);
3355 err = BT_STATUS_FAIL;
3357 struct gatt_char_info *char_info = NULL;
3359 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3360 if (char_info == NULL) {
3362 g_strfreev(line_argv);
3363 g_variant_builder_unref(inner_builder);
3364 g_variant_builder_unref(outer_builder);
3365 g_variant_builder_unref(invalidated_builder);
3367 return BT_STATUS_FAIL;
3370 char_info->value_length = value_length;
3372 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3373 if (char_info->char_value) {
3374 for (i = 0; i < value_length; i++)
3375 char_info->char_value[i] = att_value[i];
3381 g_strfreev(line_argv);
3382 g_variant_builder_unref(inner_builder);
3383 g_variant_builder_unref(outer_builder);
3384 g_variant_builder_unref(invalidated_builder);
3389 static bt_status_t gatt_server_listen(int server_if, bool start)
3391 CHECK_BTGATT_INIT();
3393 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3395 DBG("server_if: [%d]", server_if);
3397 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3398 if (server_register_info == NULL) {
3399 DBG("gatt server is not registered");
3400 return BT_STATUS_FAIL;
3403 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3405 if (server_register_info->adv_slot_id < 0 ) {
3406 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3407 return BT_STATUS_FAIL;
3410 /* Send Data to LE Module */
3411 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, start, FALSE);
3414 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3415 bool include_txpower, int min_interval, int max_interval, int appearance,
3416 uint16_t manufacturer_len, char* manufacturer_data,
3417 uint16_t service_data_len, char* service_data,
3418 uint16_t service_uuid_len, char* service_uuid)
3420 CHECK_BTGATT_INIT();
3421 return BT_STATUS_SUCCESS;
3424 static int bt_hal_gatts_allocate_adv_slot(struct hal_gatts_server_register_info_t *server_register_info)
3426 int adv_slot_id = -1;
3428 /* allocate adv slot for gatt server if not assigned */
3429 if (server_register_info->adv_slot_id < 0 ) {
3430 adv_slot_id = _bt_hal_get_available_adv_slot_id(&server_register_info->app_uuid, FALSE);
3431 if (adv_slot_id < 0) {
3432 ERR("failed to get the adv_slot");
3436 server_register_info->adv_slot_id = adv_slot_id;
3439 DBG("gatt server:[%d] Assigned adv_slot [%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3444 int bt_hal_gatts_allocate_adv_slot_by_server_if(int server_if)
3446 CHECK_BTGATT_INIT();
3450 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3452 DBG("server_if: [%d]", server_if);
3454 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3455 if (server_register_info == NULL) {
3456 DBG("gatt server is not registered");
3460 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3462 if (server_register_info->adv_slot_id < 0 ) {
3463 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3465 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3467 DBG("failed to get adv_slot");
3472 return server_register_info->adv_slot_id;
3475 void bt_hal_gatts_release_adv_slot(int server_if)
3477 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3479 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3480 if (server_register_info == NULL) {
3481 ERR("failed to get server_register_info");
3485 if (server_register_info->adv_slot_id < 0) {
3486 ERR("adv_slot is not allocated");
3490 if(_bt_hal_is_advertising_in_slot(server_register_info->adv_slot_id) == FALSE) {
3491 DBG("advertising is disabled");
3492 _bt_hal_free_server_slot(server_register_info->adv_slot_id);
3493 server_register_info->adv_slot_id = -1;
3497 int bt_hal_gatts_get_adv_slot_id(int server_if)
3499 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3501 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3502 if (server_register_info == NULL) {
3503 DBG("failed to get server_register_info");
3507 return server_register_info->adv_slot_id;
3510 int bt_hal_gatts_get_server_if(int slot_id)
3512 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3514 server_register_info = bt_hal_gatts_find_server_register_info_by_slot_id(slot_id);
3515 if (server_register_info == NULL) {
3516 DBG("failed to get server_register_info");
3520 return server_register_info->server_if;
3523 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3525 CHECK_BTGATT_INIT();
3529 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3531 DBG("server_if: [%d]", server_if);
3533 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3534 if (server_register_info == NULL) {
3535 ERR("gatt server is not registered");
3536 return BT_STATUS_FAIL;
3539 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3541 if (server_register_info->adv_slot_id < 0 ) {
3542 DBG("adv_slot is not assigned to server:[%d]", server_if);
3544 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3546 ERR("failed to get adv_slot");
3547 return BT_STATUS_FAIL;
3551 /* Send Enable Advertising request to LE Module */
3552 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, TRUE, TRUE);
3555 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3556 int chnl_map, int tx_power, int timeout_s)
3558 CHECK_BTGATT_INIT();
3560 /* Send Advertising parameters to LE Module */
3561 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3562 chnl_map, tx_power, timeout_s);
3565 static bt_status_t gatt_server_set_filter_policy(int filter_policy)
3567 CHECK_BTGATT_INIT();
3569 /* Send the Filter policy parameter to LE Module */
3570 _bt_hal_set_filter_policy_param(filter_policy);
3571 return BT_STATUS_SUCCESS;
3574 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3576 CHECK_BTGATT_INIT();
3578 /* Send Data to LE Module */
3579 return _bt_hal_set_advertising_data(adv_param_setup);
3582 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3584 CHECK_BTGATT_INIT();
3586 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3588 DBG("server_if: [%d]", server_if);
3590 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3591 if (server_register_info == NULL) {
3592 DBG("gatt server is not registered");
3593 return BT_STATUS_FAIL;
3596 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3598 if (server_register_info->adv_slot_id < 0 ) {
3599 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3600 return BT_STATUS_FAIL;
3603 /* Send Data to LE Module */
3604 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, FALSE, TRUE);
3607 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3609 CHECK_BTGATT_INIT();
3610 char *object_path = NULL;
3612 GDBusProxy *device_proxy;
3613 GError *error = NULL;
3615 GVariant *tmp_value;
3616 GDBusConnection *conn;
3617 GVariant *result = NULL;
3618 int ret = BT_STATUS_SUCCESS;
3619 struct gatt_client_info_t *conn_info = NULL;
3622 if (mtu_size == NULL)
3623 return BT_STATUS_PARM_INVALID;
3625 /* GDBUS Connection Info validate */
3626 conn = _bt_hal_get_system_gconn();
3628 ERR("Could not get System DBUS Connection");
3629 return BT_STATUS_FAIL;
3632 /* Connection Info validate */
3633 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3634 if (conn_info == NULL) {
3635 ERR("No Connection Inforamtion!!!");
3636 return BT_STATUS_FAIL;
3640 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3641 if (object_path == NULL)
3642 return BT_STATUS_FAIL;
3644 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3645 NULL, BT_HAL_BLUEZ_NAME, object_path,
3646 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3648 g_free(object_path);
3649 if (device_proxy == NULL)
3650 return BT_STATUS_FAIL;
3652 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3653 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3654 G_DBUS_CALL_FLAGS_NONE,
3658 if (result == NULL) {
3659 if (error != NULL) {
3660 ERR("Error occured in Proxy call [%s]\n", error->message);
3661 g_error_free(error);
3663 g_object_unref(device_proxy);
3664 return BT_STATUS_FAIL;
3667 g_variant_get(result , "(@a{sv})", &value);
3668 g_variant_unref(result);
3670 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3671 if (tmp_value == NULL) {
3672 g_object_unref(device_proxy);
3673 g_variant_unref(value);
3674 return BT_STATUS_FAIL;
3677 mtu = g_variant_get_uint16(tmp_value);
3679 DBG("ATT MTU : [%d]", mtu);
3681 g_variant_unref(tmp_value);
3682 g_variant_unref(value);
3683 g_object_unref(device_proxy);
3685 *mtu_size = (int) mtu;
3690 const btgatt_server_interface_t btgatt_server_interface = {
3691 .register_server = gatt_server_register_app,
3692 .unregister_server = gatt_server_unregister_app,
3693 .connect = gatt_server_open,
3694 .disconnect = gatt_server_close,
3695 .add_service = gatt_server_add_service,
3696 .add_included_service = gatt_server_add_included_service,
3697 .add_characteristic = gatt_server_add_characteristic,
3698 .add_descriptor = gatt_server_add_descriptor,
3699 .start_service = gatt_server_start_service,
3700 .stop_service = gatt_server_stop_service,
3701 .delete_service = gatt_server_delete_service,
3702 .send_indication = gatt_server_send_indication,
3703 .send_response = gatt_server_send_response,
3704 .update_att_value = gatt_server_update_att_value,
3705 .listen = gatt_server_listen,
3706 .set_adv_data = gatt_server_set_adv_data,
3707 .multi_adv_enable = gatt_server_multi_adv_enable,
3708 .multi_adv_update = gatt_server_multi_adv_update,
3709 .set_filter_policy = gatt_server_set_filter_policy,
3710 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3711 .multi_adv_disable = gatt_server_multi_adv_disable,
3712 .get_att_mtu = gatt_server_get_mtu_size,
3713 .send_response_acquire = gatt_server_send_acquire_response