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;
199 /* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
200 /* TODO: Adjust MAX Server after modifying MAX app handle logic */
201 #define BT_GATTS_MAX 11
203 static int assigned_id = 0;
205 static gboolean instance_id_used[BT_GATTS_MAX];
207 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
209 ERR("%s: BTGATT not initialized", __FUNCTION__);\
210 return BT_STATUS_NOT_READY;\
212 DBG("%s", __FUNCTION__);\
215 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data);
217 static void __bt_hal_gatt_deinit(char *app_path);
219 static void __bt_hal_register_application_cb(GObject *object,
220 GAsyncResult *res, gpointer user_data);
222 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
225 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
226 const gchar *path, const gchar *interface);
228 static int bt_hal_gatts_get_gatt_server_instance();
230 /* Introspection data for the service we are exporting */
231 static const gchar service_introspection_xml[] =
233 " <interface name='org.freedesktop.DBus.Properties'>"
234 " <property type='s' name='UUID' access='read'>"
236 " <property type='b' name='primary' access='read'>"
238 " <property type='o' name='Device' access='read'>"
240 " <property type='ao' name='Characteristics' access='read'>"
242 " <property type='s' name='Includes' access='read'>"
247 /* Introspection data for the characteristics we are exporting */
248 static const gchar characteristics_introspection_xml[] =
250 " <interface name='org.bluez.GattCharacteristic1'>"
251 " <method name='ReadValue'>"
252 " <arg type='s' name='address' direction='in'/>"
253 " <arg type='u' name='id' direction='in'/>"
254 " <arg type='q' name='offset' direction='in'/>"
255 " <arg type='ay' name='Value' direction='out'/>"
257 " <method name='WriteValue'>"
258 " <arg type='s' name='address' direction='in'/>"
259 " <arg type='u' name='id' direction='in'/>"
260 " <arg type='q' name='offset' direction='in'/>"
261 " <arg type='b' name='response_needed' direction='in'/>"
262 " <arg type='ay' name='value' direction='in'/>"
264 " <method name ='AcquireWrite'>"
265 " <arg type='a{sv}' name='properties' direction='in'/>"
266 " <arg type='h' name='fd' direction='out'/>"
267 " <arg type='q' name='mtu' direction='out'/>"
269 " <method name = 'AcquireNotify'>"
270 " <arg type='a{sv}' name='properties' direction='in'/>"
271 " <arg type='h' name='fd' direction='out'/>"
272 " <arg type='q' name='mtu' direction='out'/>"
274 " <method name='StartNotify'>"
276 " <method name='StopNotify'>"
278 " <method name='IndicateConfirm'>"
279 " <arg type='s' name='address' direction='in'/>"
280 " <arg type='b' name='complete' direction='in'/>"
283 " <interface name='org.freedesktop.DBus.Properties'>"
284 " <property type='s' name='UUID' access='read'>"
286 " <property type='o' name='Service' access='read'>"
288 " <property type='ay' name='Value' access='readwrite'>"
290 " <property type='b' name='Notifying' access='read'>"
292 " <property type='as' name='Flags' access='read'>"
294 " <property type='s' name='Unicast' access='read'>"
296 " <property type='ao' name='Descriptors' access='read'>"
298 " <property type='b' name='WriteAcquired' access='read'>"
300 " <property type='b' name='NotifyAcquired' access='read'>"
305 /* Introspection data for the descriptor we are exporting */
306 static const gchar descriptor_introspection_xml[] =
308 " <interface name='org.bluez.GattDescriptor1'>"
309 " <method name='ReadValue'>"
310 " <arg type='s' name='address' direction='in'/>"
311 " <arg type='u' name='id' direction='in'/>"
312 " <arg type='q' name='offset' direction='in'/>"
313 " <arg type='ay' name='Value' direction='out'/>"
315 " <method name='WriteValue'>"
316 " <arg type='s' name='address' direction='in'/>"
317 " <arg type='u' name='id' direction='in'/>"
318 " <arg type='q' name='offset' direction='in'/>"
319 " <arg type='b' name='response_needed' direction='in'/>"
320 " <arg type='ay' name='value' direction='in'/>"
323 " <interface name='org.freedesktop.DBus.Properties'>"
324 " <property type='s' name='UUID' access='read'>"
326 " <property type='o' name='Characteristic' access='read'>"
328 " <property type='ay' name='Value' access='read'>"
330 " <property type='as' name='Flags' access='read'>"
336 static const gchar manager_introspection_xml[] =
338 " <interface name='org.freedesktop.DBus.ObjectManager'>"
339 " <method name='GetManagedObjects'>"
340 " <arg type='a{oa{sa{sv}}}' name='object_paths_interfaces_and_properties' direction='out'/>"
345 void _bt_hal_gatt_server_init(void)
348 memset(instance_id_used, 0x00, sizeof(instance_id_used));
351 static int __bt_hal_gatt_assign_id(void)
355 index = assigned_id + 1;
357 if (index >= BT_GATTS_MAX)
360 while (instance_id_used[index] == TRUE) {
361 if (index == assigned_id) {
362 /* No available ID */
363 ERR("All interface ID is used");
369 if (index >= BT_GATTS_MAX)
374 instance_id_used[index] = TRUE;
379 static void __bt_hal_gatt_delete_id(int instance_id)
381 if (instance_id >= BT_GATTS_MAX || instance_id < 0)
384 instance_id_used[instance_id] = FALSE;
387 static GSList *_bt_get_service_list_from_server(int instance)
390 INFO("Number of GATT Server apps [%d]", g_slist_length(gatt_server_apps));
391 INFO("Find App with slot [%d]", instance);
393 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
394 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
396 if (app->slot == instance) {
397 INFO("App slot [%d] Found, Number of services registered [%d]",
398 app->slot, g_slist_length(app->services));
399 return app->services;
405 static void _bt_remote_service_from_gatt_server(int instance, int service_handle)
410 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
411 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
413 if (app->slot == instance) {
414 for (l1 = app->services; l1; l1 = g_slist_next(l1)) {
415 struct gatt_service_info *srv = (struct gatt_service_info *)l1->data;
416 if (srv->service_handle == service_handle) {
417 app->services = g_slist_remove(app->services, srv);
425 static void _bt_hal_update_gatt_service_in_gatt_server(int slot, struct gatt_service_info *serv_info)
428 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
429 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
431 if (app->slot == slot) {
432 INFO("Updating service in GATT server's service list service handle [%d] slot [%d]",
433 serv_info->service_handle, slot);
434 app->services = g_slist_append(app->services, serv_info);
439 int _bt_get_remote_gatt_client_conn_id(char *address)
442 struct gatt_client_info_t *info = NULL;
444 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
445 info = (struct gatt_client_info_t*)l->data;
449 if (!g_strcmp0(info->addr, address)) {
450 INFO("Remote GATT client found addr[%s]", info->addr);
451 return info->connection_id;
457 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info(char *address)
460 struct gatt_client_info_t *info = NULL;
462 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
463 info = (struct gatt_client_info_t*)l->data;
467 if (!g_strcmp0(info->addr, address)) {
468 INFO("Remote GATT client found addr[%s]", info->addr);
475 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
478 struct gatt_client_info_t *info = NULL;
480 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
481 info = (struct gatt_client_info_t*)l->data;
485 if (info->connection_id == conn_id) {
486 INFO("Remote GATT client found addr[%s]", info->addr);
493 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
498 struct gatt_client_info_t *info = NULL;
499 struct gatt_req_info *info1 = NULL;
501 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
502 info = (struct gatt_client_info_t*)l->data;
506 if (info->connection_id == conn_id) {
508 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
510 info1 = (struct gatt_req_info*)l1->data;
514 if (info1->request_id == trans_id) {
515 INFO("Remote GATT client found addr[%s]", info->addr);
524 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
526 struct hal_ev_gatt_server_connected ev;
527 struct gatt_client_info_t *conn_info = NULL;
529 memset(&ev, 0, sizeof(ev));
531 /* Find Server Instance */
532 instance = bt_hal_gatts_get_gatt_server_instance();
533 if (instance == -1) {
534 ERR("Not even a single GATT server is registered");
538 DBG("server instance [%d]", instance);
540 /* Convert address to hex */
541 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
543 /* Create Connection ID */
544 /* Check if device is already in connected list */
545 conn_info = __bt_find_remote_gatt_client_info(address);
548 /* If disconnected, and conn info found, then remove conn info */
549 if (is_connected == FALSE) {
550 DBG("GATT Disconnected");
552 INFO("Remove GATT client info from List..");
553 /* Remove info from List */
554 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
555 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
558 ERR("GATT callback not registered");
560 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
561 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
562 ev.conn_id = conn_info->connection_id;
563 ev.server_instance = conn_info->instance_id;
564 ev.connected = is_connected;
566 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
568 g_free(conn_info->addr);
571 /* If connected, and conn info NOT found, then add conn info */
574 /* Save Connection info */
575 conn_info = g_new0(struct gatt_client_info_t, 1);
576 conn_info->addr = g_strdup(address);
577 INFO("Added GATT client addr[%s]", conn_info->addr);
578 conn_info->connection_id = ++conn_id;
579 conn_info->instance_id = instance;
580 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
581 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
584 ERR("GATT callback not registered");
586 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
587 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
588 ev.conn_id = conn_info->connection_id;
589 ev.server_instance = conn_info->instance_id;
590 ev.connected = is_connected;
592 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
596 /* Send GATT connected or disconnected event */
599 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
603 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
604 struct gatt_service_info *serv_info = l1->data;
606 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
607 struct gatt_char_info *char_info = l2->data;
609 if (g_strcmp0(char_info->char_path, char_path)
611 *char_hdl = char_info->char_handle;
616 ERR("Gatt service not found");
620 static char *__bt_gatt_find_char_path_from_handle(int char_hdl)
624 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
625 struct gatt_service_info *serv_info = l1->data;
627 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
628 struct gatt_char_info *char_info = l2->data;
630 if (char_info->char_handle == char_hdl)
631 return char_info->char_path;
638 static struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
642 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
643 struct gatt_service_info *serv_info = l1->data;
645 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
646 struct gatt_char_info *char_info = l2->data;
648 if (char_info->char_handle == char_hdl)
656 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
658 GSList *l1, *l2, *l3;
660 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
661 struct gatt_service_info *serv_info = l1->data;
663 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
664 struct gatt_char_info *char_info = l2->data;
666 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
667 struct gatt_desc_info *desc_info = l3->data;
669 if (g_strcmp0(desc_info->desc_path, desc_path)
671 *desc_hdl = desc_info->desc_handle;
677 ERR("Gatt service not found");
681 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
683 const gchar *object_path,
684 const gchar *interface_name,
685 const gchar *method_name,
686 GVariant *parameters,
687 GDBusMethodInvocation *invocation,
692 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
693 GVariantBuilder *builder;
694 GVariantBuilder *inner_builder1 = NULL;
695 GVariant *svc_char = NULL;
697 GSList *gatt_services = NULL;
699 instance = (int*)user_data;
700 gboolean writeAcquired = FALSE;
701 gboolean notifyAcquired = FALSE;
703 DBG("Getting values for service, chars and descriptors");
704 DBG("GATT Server App for which services are requested [%d]", *instance);
707 builder = g_variant_builder_new(
708 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
711 gatt_services = _bt_get_service_list_from_server(*instance);
713 if (g_slist_length(gatt_services) == 0) {
714 ERR("No registered GATT services!!!!");
715 g_dbus_method_invocation_return_value(invocation, NULL);
716 g_variant_builder_unref(builder);
720 for (l = gatt_services; l != NULL; l = l->next) {
721 GVariantBuilder *svc_builder = NULL;
722 GVariantBuilder *inner_builder = NULL;
723 struct gatt_service_info *serv_info = l->data;
724 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
726 /* Prepare inner builder for GattService1 interface */
727 DBG("Creating builder for service");
728 svc_builder = g_variant_builder_new(
729 G_VARIANT_TYPE("a{sa{sv}}"));
730 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
732 g_variant_builder_add(inner_builder, "{sv}", "UUID",
733 g_variant_new_string(serv_info->service_uuid));
735 g_variant_builder_add(inner_builder, "{sv}", "Primary",
736 g_variant_new_boolean(serv_info->is_svc_primary));
739 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
740 DBG("Adding Charatarisitcs list");
741 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
742 struct gatt_char_info *char_info = l4->data;
743 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
744 char_info->char_handle, serv_info->service_handle);
745 g_variant_builder_add(inner_builder1, "o",
746 char_info->char_path);
747 DBG("%s", char_info->char_path);
750 svc_char = g_variant_new("ao", inner_builder1);
751 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
754 g_variant_builder_add(svc_builder, "{sa{sv}}",
758 g_variant_builder_add(builder, "{oa{sa{sv}}}",
759 serv_info->serv_path,
762 g_variant_builder_unref(inner_builder1);
764 /* Prepare inner builder for GattCharacteristic1 interface */
766 GSList *l2 = serv_info->char_data;
767 DBG("Creating builder for characteristics \n");
770 DBG("characteristic data is NULL");
772 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
774 GVariantBuilder *char_builder = NULL;
775 GVariantBuilder *inner_builder = NULL;
776 GVariantBuilder *builder1 = NULL;
777 GVariantBuilder *builder2 = NULL;
778 GVariantBuilder *builder3 = NULL;
779 GVariant *char_val = NULL;
780 GVariant *flags_val = NULL;
781 GVariant *char_desc = NULL;
782 char *unicast = NULL;
783 gboolean notify = FALSE;
786 char_builder = g_variant_builder_new(
789 inner_builder = g_variant_builder_new(
793 struct gatt_char_info *char_info = l2->data;
794 if (char_info == NULL) {
795 ERR("char_info is NULL");
800 g_variant_builder_add(inner_builder, "{sv}", "UUID",
801 g_variant_new_string(char_info->char_uuid));
803 g_variant_builder_add(inner_builder, "{sv}", "Service",
804 g_variant_new("o", serv_info->serv_path));
806 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
808 if (char_info->char_value != NULL) {
809 for (i = 0; i < char_info->value_length; i++) {
810 g_variant_builder_add(builder1, "y",
811 char_info->char_value[i]);
813 char_val = g_variant_new("ay", builder1);
814 g_variant_builder_add(inner_builder, "{sv}",
818 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
819 for (i = 0; i < char_info->flags_length; i++) {
820 g_variant_builder_add(builder2, "s",
821 char_info->char_flags[i]);
823 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
824 DBG("setting WriteAcquired property");
825 writeAcquired = TRUE;
828 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
829 DBG("setting NotifyAcquired property");
830 notifyAcquired = TRUE;
834 flags_val = g_variant_new("as", builder2);
835 g_variant_builder_add(inner_builder, "{sv}", "Flags",
839 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
840 g_variant_new("b", notify));
843 if (writeAcquired == TRUE) {
844 DBG("adding WriteAcquired property");
845 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
846 g_variant_new("b", writeAcquired));
850 if (notifyAcquired == TRUE) {
851 DBG("adding NotifyAcquired property");
852 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
853 g_variant_new("b", notifyAcquired));
857 unicast = g_strdup("00:00:00:00:00:00");
858 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
859 g_variant_new("s", unicast));
862 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
863 DBG("Adding Descriptors list");
865 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
866 struct gatt_desc_info *desc_info = l4->data;
867 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
868 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
869 g_variant_builder_add(builder3, "o",
870 desc_info->desc_path);
871 DBG("%s", desc_info->desc_path);
874 char_desc = g_variant_new("ao", builder3);
875 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
878 g_variant_builder_add(char_builder, "{sa{sv}}",
879 GATT_CHAR_INTERFACE , inner_builder);
880 g_variant_builder_add(builder, "{oa{sa{sv}}}",
881 char_info->char_path, char_builder);
883 /*Prepare inner builder for GattDescriptor1 interface*/
885 GSList *l3 = char_info->desc_data;
888 DBG("descriptor data is NULL");
890 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
892 DBG("Creating builder for descriptor \n");
894 GVariantBuilder *desc_builder = NULL;
895 GVariantBuilder *inner_builder = NULL;
896 GVariantBuilder *builder1 = NULL;
897 GVariantBuilder *builder2 = NULL;
898 GVariant *desc_val = NULL;
900 desc_builder = g_variant_builder_new(
903 inner_builder = g_variant_builder_new(
907 struct gatt_desc_info *desc_info = l3->data;
908 if (desc_info == NULL) {
909 ERR("desc_info is NULL");
914 g_variant_builder_add(inner_builder,
916 g_variant_new_string(
917 desc_info->desc_uuid));
920 g_variant_builder_add(inner_builder, "{sv}",
923 char_info->char_path));
926 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
928 if (desc_info->desc_value != NULL) {
929 for (i = 0; i < desc_info->value_length; i++) {
930 g_variant_builder_add(builder1, "y",
931 desc_info->desc_value[i]);
933 desc_val = g_variant_new("ay", builder1);
934 g_variant_builder_add(inner_builder, "{sv}",
939 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
941 for (i = 0; i < desc_info->flags_length; i++) {
942 g_variant_builder_add(builder2, "s",
943 desc_info->desc_flags[i]);
946 flags_val = g_variant_new("as", builder2);
947 g_variant_builder_add(inner_builder, "{sv}", "Flags",
950 g_variant_builder_add(desc_builder, "{sa{sv}}",
954 g_variant_builder_add(builder, "{oa{sa{sv}}}",
955 desc_info->desc_path,
958 /*unref descriptor builder pointers*/
959 g_variant_builder_unref(builder1);
960 g_variant_builder_unref(builder2);
961 g_variant_builder_unref(inner_builder);
962 g_variant_builder_unref(desc_builder);
967 /*unref char builder pointers*/
968 g_variant_builder_unref(builder1);
969 g_variant_builder_unref(builder2);
970 g_variant_builder_unref(builder3);
971 g_variant_builder_unref(inner_builder);
972 g_variant_builder_unref(char_builder);
975 /*unref service builder pointers*/
976 g_variant_builder_unref(inner_builder);
977 g_variant_builder_unref(svc_builder);
980 /* Return builder as method reply */
981 DBG("Sending gatt service builder values to Bluez");
982 g_dbus_method_invocation_return_value(invocation,
992 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
994 const gchar *object_path,
995 const gchar *interface_name,
996 const gchar *method_name,
997 GVariant *parameters,
998 GDBusMethodInvocation *invocation,
1002 if (g_strcmp0(method_name, "ReadValue") == 0) {
1003 struct hal_ev_gatt_server_read_req ev;
1008 struct gatt_client_info_t *conn_info = NULL;
1009 struct gatt_req_info *req_info = NULL;
1010 struct gatt_service_info *svc_info = NULL;
1014 DBG("Application path = %s", object_path);
1015 DBG("Sender = %s", sender);
1017 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1018 if (svc_info == NULL) {
1019 ERR("Coudn't find service for %s", object_path);
1020 g_dbus_method_invocation_return_value(invocation, NULL);
1024 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1025 DBG("Request id = %u, Offset = %u", req_id, offset);
1027 /* Check if device is already in connected list */
1028 conn_info = __bt_find_remote_gatt_client_info(addr);
1030 if (conn_info == NULL) {
1031 ERR("Coudn't find Connection info for %s", addr);
1032 g_dbus_method_invocation_return_value(invocation, NULL);
1037 ERR("GATT callback NOT registered");
1038 g_dbus_method_invocation_return_value(invocation, NULL);
1042 /* Store requests information */
1043 req_info = g_new0(struct gatt_req_info, 1);
1044 req_info->attr_path = g_strdup(object_path);
1045 req_info->svc_path = g_strdup(svc_info->serv_path);
1046 req_info->request_id = req_id;
1047 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1048 req_info->offset = offset;
1049 req_info->context = invocation;
1051 /* Append request info in list of requests for the particular connection */
1052 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1054 /* Send HAL event */
1055 memset(&ev, 0, sizeof(ev));
1056 ev.conn_id = conn_info->connection_id;
1057 ev.trans_id = req_id;
1058 ev.att_handle = desc_hdl;
1060 ev.is_long = false; /* TODO*/
1062 /* Convert address to hex */
1063 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1065 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1067 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1069 GVariant *var = NULL;
1073 gboolean response_needed = FALSE;
1074 struct hal_ev_gatt_server_write_req ev;
1078 struct gatt_service_info *svc_info = NULL;
1079 struct gatt_client_info_t *conn_info = NULL;
1080 struct gatt_req_info *req_info = NULL;
1082 memset(&ev, 0, sizeof(ev));
1085 DBG("Application path = %s", object_path);
1086 DBG("Sender = %s", sender);
1088 g_variant_get(parameters, "(&suqb@ay)",
1089 &addr, &req_id, &offset, &response_needed, &var);
1090 DBG("Request id = %u, Offset = %u", req_id, offset);
1092 /* Check if device is already in connected list */
1093 conn_info = __bt_find_remote_gatt_client_info(addr);
1095 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1097 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1098 g_variant_unref(var);
1099 if (response_needed)
1100 g_dbus_method_invocation_return_value(invocation, NULL);
1102 g_object_unref(invocation);
1106 len = g_variant_get_size(var);
1107 if (len > 0 && len < 600) {
1109 data = (char *)g_variant_get_data(var);
1110 memcpy(ev.value, data, len);
1113 if (response_needed) {
1114 /* Store request information */
1115 req_info = g_new0(struct gatt_req_info, 1);
1116 req_info->attr_path = g_strdup(object_path);
1117 req_info->svc_path = g_strdup(svc_info->serv_path);
1118 req_info->request_id = req_id;
1119 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1120 req_info->offset = offset;
1121 req_info->context = invocation;
1123 /* Append request info in list of requests for the particular connection */
1124 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1126 g_object_unref(invocation);
1129 /* Send HAL event */
1130 ev.conn_id = conn_info->connection_id;
1131 ev.trans_id = req_id;
1132 ev.att_handle = desc_hdl;
1134 ev.need_rsp = response_needed;
1137 /* Convert address to hex */
1138 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1140 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1142 g_variant_unref(var);
1147 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1148 const gchar *sender,
1149 const gchar *object_path,
1150 const gchar *interface_name,
1151 const gchar *method_name,
1152 GVariant *parameters,
1153 GDBusMethodInvocation *invocation,
1156 if (g_strcmp0(method_name, "ReadValue") == 0) {
1160 struct hal_ev_gatt_server_read_req ev;
1163 struct gatt_req_info *req_info = NULL;
1164 struct gatt_client_info_t *conn_info = NULL;
1165 struct gatt_service_info *svc_info = NULL;
1167 g_variant_get(parameters, "(&suq)",
1168 &addr, &req_id, &offset);
1170 DBG("Request id = %u, Offset = %u", req_id, offset);
1171 DBG("Application path = %s", object_path);
1172 DBG("Sender = %s", sender);
1173 DBG("Address = %s", addr);
1175 /* Check if device is already in connected list */
1176 conn_info = __bt_find_remote_gatt_client_info(addr);
1178 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1180 if (svc_info == NULL || conn_info == NULL) {
1181 g_dbus_method_invocation_return_value(invocation, NULL);
1186 ERR("GATT callback NOT registered");
1187 g_dbus_method_invocation_return_value(invocation, NULL);
1191 /* Store requets information */
1192 req_info = g_new0(struct gatt_req_info, 1);
1193 req_info->attr_path = g_strdup(object_path);
1194 req_info->svc_path = g_strdup(svc_info->serv_path);
1195 req_info->request_id = req_id;
1196 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1197 req_info->offset = offset;
1198 req_info->context = invocation;
1200 /* Append request info in list of requests for the particular connection */
1201 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1203 /* Send HAL event */
1204 memset(&ev, 0, sizeof(ev));
1205 ev.conn_id = conn_info->connection_id;
1206 ev.trans_id = req_id;
1207 ev.att_handle = char_hdl;
1209 ev.is_long = false; /* TODO*/
1211 /* Convert address to hex */
1212 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1213 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1215 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1216 GVariant *var = NULL;
1220 gboolean response_needed = FALSE;
1221 struct hal_ev_gatt_server_write_req ev;
1225 struct gatt_service_info *svc_info = NULL;
1226 struct gatt_req_info *req_info = NULL;
1227 struct gatt_client_info_t *conn_info = NULL;
1229 memset(&ev, 0, sizeof(ev));
1232 DBG("Application path = %s", object_path);
1233 DBG("Sender = %s", sender);
1235 g_variant_get(parameters, "(&suqb@ay)",
1236 &addr, &req_id, &offset, &response_needed, &var);
1237 DBG("Request id = %u, Offset = %u", req_id, offset);
1239 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1241 /* Check if device is already in connected list */
1242 conn_info = __bt_find_remote_gatt_client_info(addr);
1244 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1245 g_variant_unref(var);
1246 if (response_needed)
1247 g_dbus_method_invocation_return_value(invocation, NULL);
1249 g_object_unref(invocation);
1253 len = g_variant_get_size(var);
1254 if (len > 0 && len < 600) {
1256 data = (char *)g_variant_get_data(var);
1257 memcpy(ev.value, data, len);
1261 if (response_needed) {
1262 /* Store requets information */
1263 req_info = g_new0(struct gatt_req_info, 1);
1264 req_info->attr_path = g_strdup(object_path);
1265 req_info->svc_path = g_strdup(svc_info->serv_path);
1266 req_info->request_id = req_id;
1267 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1268 req_info->offset = offset;
1269 req_info->context = invocation;
1271 /* Append request info in list of requests for the particular connection */
1272 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1275 g_object_unref(invocation);
1278 /* Send HAL event */
1279 ev.conn_id = conn_info->connection_id;
1280 ev.trans_id = req_id;
1281 ev.att_handle = char_hdl;
1283 ev.need_rsp = response_needed;
1286 /* Convert address to hex */
1287 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1289 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1291 g_variant_unref(var);
1294 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1297 struct gatt_service_info *svc_info = NULL;
1298 struct hal_ev_gatt_server_notifcation_change ev;
1301 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1302 if (svc_info == NULL || event_cb == NULL)
1305 /* Send HAL event */
1306 memset(&ev, 0, sizeof(ev));
1307 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1308 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1309 ev.att_handle = char_hdl;
1312 /* Convert address to hex */
1313 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1315 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1318 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1321 struct gatt_service_info *svc_info = NULL;
1322 struct hal_ev_gatt_server_notifcation_change ev;
1325 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1326 if (svc_info == NULL || event_cb == NULL)
1329 /* Send HAL event */
1330 memset(&ev, 0, sizeof(ev));
1331 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1332 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1333 ev.att_handle = char_hdl;
1336 /* Convert address to hex */
1337 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1339 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1342 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1344 gboolean complete = FALSE;
1347 struct gatt_service_info *svc_info = NULL;
1348 struct gatt_client_info_t *conn_info = NULL;
1350 struct hal_ev_gatt_server_indicate_cfm ev;
1352 DBG("IndicateConfirm");
1353 DBG("Application path = %s", object_path);
1354 DBG("Sender = %s", sender);
1356 g_variant_get(parameters, "(&sb)", &addr, &complete);
1357 DBG("Remote Device address number = %s", addr);
1358 DBG("Is Indicate confirmation for last device [%d]", complete);
1360 /* Check if device is already in connected list */
1361 conn_info = __bt_find_remote_gatt_client_info(addr);
1363 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1365 if (svc_info == NULL || conn_info == NULL
1366 || event_cb == NULL) {
1370 /* Send HAL event */
1371 memset(&ev, 0, sizeof(ev));
1372 ev.conn_id = conn_info->connection_id;
1373 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1374 ev.att_handle = char_hdl;
1376 /* Convert address to hex */
1377 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1379 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1380 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1384 struct hal_ev_gatt_server_acquire_write_res ev;
1385 struct gatt_service_info *svc_info = NULL;
1386 struct gatt_req_info *req_info = NULL;
1387 struct gatt_client_info_t *conn_info = NULL;
1388 char * dev_path = NULL;
1390 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1392 DBG("AcquireWrite");
1393 DBG("Application path = %s", object_path);
1394 DBG("Sender = %s", sender);
1397 g_variant_get(parameters, "(a{sv})", &iter);
1399 GVariant* value = NULL;
1400 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1401 if (g_strcmp0(key, "MTU") == 0)
1402 g_variant_get(value, "i", &mtu);
1403 else if (g_strcmp0(key, "link") == 0)
1404 g_variant_get(value, "s", &link);
1405 else if (g_strcmp0(key, "device") == 0)
1406 g_variant_get(value, "o", &dev_path);
1409 DBG("AcquireWrite values retived");
1410 DBG(" path %s LINK = %s, MTU = %u", addr, link, mtu);
1412 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1414 _bt_hal_convert_device_path_to_address(dev_path, addr);
1416 DBG("remote address %s", addr);
1418 /* Check if device is already in connected list */
1419 conn_info = __bt_find_remote_gatt_client_info(addr);
1421 if (conn_info == NULL) {
1422 ERR("Cleint info not found\n");
1426 if (svc_info == NULL) {
1427 ERR("svc_info info not found\n");
1431 /* Store requets information */
1432 req_info = g_new0(struct gatt_req_info, 1);
1433 req_info->attr_path = g_strdup(object_path);
1434 req_info->svc_path = g_strdup(svc_info->serv_path);
1435 req_info->request_id = conn_info->connection_id;
1436 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1437 req_info->offset = mtu;
1438 req_info->context = invocation;
1440 /* Append request info in list of requests for the particular connection */
1441 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1443 /* Send HAL event */
1444 memset(&ev, 0, sizeof(ev));
1445 ev.conn_id = conn_info->connection_id;
1446 ev.char_handl = char_hdl;
1448 ev.trans_id = conn_info->connection_id;
1449 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1450 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1452 DBG("HAL_EV_GATT_ACQUIRE_WRITE_RES called");
1456 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1460 struct hal_ev_gatt_server_acquire_notify ev;
1461 struct gatt_service_info *svc_info = NULL;
1462 struct gatt_client_info_t *conn_info = NULL;
1463 struct gatt_req_info *req_info = NULL;
1465 DBG("AcquireNotify");
1466 DBG("Application path = %s", object_path);
1467 DBG("Sender = %s", sender);
1470 g_variant_get(parameters, "(a{sv})", &iter);
1472 GVariant* value = NULL;
1473 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1474 if (g_strcmp0(key, "MTU") == 0)
1475 g_variant_get(value, "q", &mtu);
1478 DBG("AcquireNotify values retived");
1479 DBG(" MTU = %u", mtu);
1481 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1483 if (svc_info == NULL) {
1484 ERR("svc_info info not found\n");
1488 /* Store requets information */
1489 req_info = g_new0(struct gatt_req_info, 1);
1490 req_info->attr_path = g_strdup(object_path);
1491 req_info->svc_path = g_strdup(svc_info->serv_path);
1492 req_info->request_id = 33;
1493 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1494 req_info->offset = mtu;
1495 req_info->context = invocation;
1497 conn_info = g_new0(struct gatt_client_info_t, 1);
1498 conn_info->addr = g_strdup(object_path);
1499 INFO("Added GATT client path[%s]", conn_info->addr);
1500 conn_info->connection_id = 33;
1501 conn_info->instance_id = 33;
1502 /* Append request info in list of requests for the particular connection */
1503 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1504 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1506 /* Send HAL event */
1507 memset(&ev, 0, sizeof(ev));
1509 ev.char_handl = char_hdl;
1513 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1515 DBG("HAL_EV_GATT_ACQUIRE_NOTIFY_RES called");
1521 g_dbus_method_invocation_return_value(invocation, NULL);
1524 static gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1527 GError *error = NULL;
1528 GVariantBuilder *array_builder;
1530 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1531 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1532 g_variant_builder_add(array_builder, "s", interface);
1534 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1535 "org.freedesktop.Dbus.Objectmanager",
1536 "InterfacesRemoved",
1537 g_variant_new("(oas)",
1538 object_path, array_builder),
1542 if (error != NULL) {
1543 /* dbus gives error cause */
1544 ERR("d-bus api failure: errcode[%x], message[%s]",
1545 error->code, error->message);
1546 g_clear_error(&error);
1549 g_variant_builder_unref(array_builder);
1554 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1561 g_free(desc_info->desc_path);
1562 g_free(desc_info->desc_uuid);
1563 g_free(desc_info->desc_value);
1565 for (i = 0; i < desc_info->flags_length; i++)
1566 g_free(desc_info->desc_flags[i]);
1571 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1578 g_free(char_info->char_path);
1579 g_free(char_info->char_uuid);
1580 g_free(char_info->char_value);
1582 for (i = 0; i < char_info->flags_length; i++)
1583 g_free(char_info->char_flags[i]);
1589 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1594 g_free(svc_info->serv_path);
1595 g_free(svc_info->service_uuid);
1599 static const GDBusInterfaceVTable desc_interface_vtable = {
1600 __bt_gatt_desc_method_call,
1605 static const GDBusInterfaceVTable char_interface_vtable = {
1606 __bt_gatt_char_method_call,
1611 static const GDBusInterfaceVTable serv_interface_vtable = {
1617 static const GDBusInterfaceVTable manager_interface_vtable = {
1618 __bt_gatt_manager_method_call,
1624 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1625 const gchar *introspection_data)
1628 GDBusNodeInfo *node_info = NULL;
1630 if (introspection_data == NULL)
1634 DBG("Create new node info");
1635 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1638 ERR("Unable to create node: %s", err->message);
1639 g_clear_error(&err);
1646 /* To send stack event to hal-av handler */
1647 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1652 void _bt_hal_unregister_gatt_server_handler_cb(void)
1657 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1659 struct hal_ev_gatt_desc_added ev;
1660 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1662 /* Prepare to GATT characteristic added event */
1663 memset(&ev, 0, sizeof(ev));
1664 ev.status = BT_STATUS_SUCCESS;
1665 ev.server_instance = data->instance_data;
1666 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1667 ev.service_handle = data->srvc_hdl;
1668 ev.desc_handle = data->desc_hdl;
1671 ERR("GATT Descriptor Added callback registered");
1673 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1674 data->instance_data, data->srvc_hdl, data->desc_hdl);
1676 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1683 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1685 struct hal_ev_gatt_char_added ev;
1686 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1688 /* Prepare to GATT characteristic added event */
1689 memset(&ev, 0, sizeof(ev));
1690 ev.status = BT_STATUS_SUCCESS;
1691 ev.server_instance = data->instance_data;
1692 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1693 ev.service_handle = data->srvc_hdl;
1694 ev.char_handle = data->char_hdl;
1697 ERR("GATT Characteristic Added callback registered");
1699 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1700 data->instance_data, data->srvc_hdl, data->char_hdl);
1702 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1709 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1711 struct hal_ev_gatt_service_added ev;
1712 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1714 /* Prepare to GATT Service added event */
1715 memset(&ev, 0, sizeof(ev));
1716 ev.status = BT_STATUS_SUCCESS;
1717 ev.server_instance = data->instance_data;
1718 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1719 ev.service_handle = data->srvc_hdl;
1720 ev.is_primary = data->is_primary;
1723 ERR("GATT Service Added callback registered");
1725 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1726 data->instance_data, data->srvc_hdl);
1727 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1734 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1736 struct hal_ev_gatt_service_started ev;
1737 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1739 /* Prepare to GATT Service added event */
1740 memset(&ev, 0, sizeof(ev));
1741 ev.status = BT_STATUS_SUCCESS;
1742 ev.server_instance = data->instance_data;
1743 ev.service_handle = data->srvc_hdl;
1746 ERR("GATT Service Started callback registered");
1748 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1749 data->instance_data, data->srvc_hdl);
1750 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1757 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1759 struct hal_ev_gatt_service_deleted ev;
1760 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1762 /* Prepare to GATT Service added event */
1763 memset(&ev, 0, sizeof(ev));
1764 ev.status = BT_STATUS_SUCCESS;
1765 ev.server_instance = data->instance_data;
1766 ev.service_handle = data->srvc_hdl;
1769 ERR("GATT Service Deleted callback registered");
1771 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1772 data->instance_data, data->srvc_hdl);
1773 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1780 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1782 struct hal_ev_server_instance_registered ev;
1783 hal_register_server_data *data = (hal_register_server_data*) user_data;
1785 /* Prepare to send AV connecting event */
1786 memset(&ev, 0, sizeof(ev));
1787 ev.status = BT_STATUS_SUCCESS;
1788 ev.server_instance = data->instance_data;
1789 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1792 ERR("GATT Register Server Instance Callback not registered");
1794 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1795 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1803 static int bt_hal_gatts_get_gatt_server_instance()
1808 struct hal_gatts_server_register_info_t *info = NULL;
1810 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1811 info = (struct hal_gatts_server_register_info_t *)l->data;
1816 return info->server_if;
1822 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_from_uuid(bt_uuid_t *app_uuid)
1827 struct hal_gatts_server_register_info_t *info = NULL;
1829 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1830 info = (struct hal_gatts_server_register_info_t *)l->data;
1835 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
1836 DBG("gatt server register found");
1844 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info(int server_if)
1847 struct hal_gatts_server_register_info_t *info = NULL;
1849 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1850 info = (struct hal_gatts_server_register_info_t *)l->data;
1855 if (info->server_if == server_if) {
1863 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_by_slot_id(int adv_slot_id)
1868 struct hal_gatts_server_register_info_t *info = NULL;
1870 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1871 info = (struct hal_gatts_server_register_info_t *)l->data;
1876 if (info->adv_slot_id == adv_slot_id) {
1877 DBG("gatt server register found");
1885 static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_uuid_t *app_uuid)
1887 struct hal_gatts_server_register_info_t * server_register_info = NULL;
1888 int instance_id = 0;
1890 server_register_info = bt_hal_gatts_find_server_register_info_from_uuid(app_uuid);
1891 if (server_register_info != NULL) {
1892 DBG("gatt server is already registered");
1893 return server_register_info;
1896 instance_id = __bt_hal_gatt_assign_id();
1897 if (instance_id == -1) {
1898 ERR("Fail to allocate the server if");
1902 server_register_info = g_malloc0(sizeof(struct hal_gatts_server_register_info_t));
1903 server_register_info->server_if = instance_id;
1905 DBG("Adding the gatt server app. server_if:[%d]", server_register_info->server_if);
1907 server_register_info->adv_slot_id = -1;
1908 memcpy(&server_register_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
1909 hal_gatts_server_register_list = g_slist_append(hal_gatts_server_register_list, server_register_info);
1911 return server_register_info;
1914 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1916 CHECK_BTGATT_INIT();
1917 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1919 DBG("Register server instance request");
1920 server_register_info = bt_hal_gatts_add_server_app(uuid);
1921 if (server_register_info == NULL) {
1922 ERR("Fail to register the server app");
1923 return BT_STATUS_FAIL;
1926 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1927 user_data->instance_data = server_register_info->server_if;
1930 * As we need to provide async callback to user from HAL, simply schedule a
1931 * callback method which will carry actual result
1933 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1934 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1936 /* If available, then return success, else return error */
1937 return BT_STATUS_SUCCESS;
1940 static void _bt_hal_remove_gatt_server_from_list(int server_if)
1943 struct gatt_server_app *info = NULL;
1945 for (l = gatt_server_apps; l != NULL;) {
1946 info = (struct gatt_server_app*)l->data;
1947 l = g_slist_next(l);
1950 if (info->slot == server_if) {
1951 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1952 info->app_path, info->slot);
1954 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1955 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1956 In above case, only advertising block will be deallocated, Gatt Server will remain
1958 if (info->services == NULL) {
1959 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1960 INFO("Total gatt server apps still existing after removing above is [%d]",
1961 g_slist_length(gatt_server_apps));
1963 /* DBUS Unregister only for current app */
1964 __bt_hal_gatt_deinit(info->app_path);
1966 g_free(info->app_path);
1970 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1971 g_slist_length(info->services));
1977 static bt_status_t gatt_server_unregister_app(int server_if)
1979 CHECK_BTGATT_INIT();
1980 DBG("Un-Register server instance request [%d]", server_if);
1981 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1984 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
1985 if (server_register_info == NULL) {
1986 DBG("gatt server is not registered");
1987 return BT_STATUS_SUCCESS;
1990 /* remove the gatt server register info from the register list */
1991 hal_gatts_server_register_list = g_slist_remove(hal_gatts_server_register_list, server_register_info);
1992 g_free(server_register_info);
1994 __bt_hal_gatt_delete_id(server_if);
1996 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
1997 _bt_hal_remove_gatt_server_from_list(server_if);
1998 return BT_STATUS_SUCCESS;
2001 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
2003 CHECK_BTGATT_INIT();
2004 return BT_STATUS_SUCCESS;
2007 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
2010 GError *g_error = NULL;
2011 GVariant *reply = NULL;
2015 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2016 g_object_unref(proxy);
2017 if (reply == NULL) {
2018 ERR("Disconnect LE Dbus Call Error");
2020 ERR("Error: %s\n", g_error->message);
2021 g_clear_error(&g_error);
2024 g_variant_unref(reply);
2028 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
2030 CHECK_BTGATT_INIT();
2032 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2034 GDBusProxy *device_proxy;
2035 GDBusConnection *g_conn;
2036 struct gatt_client_info_t *conn_info = NULL;
2040 if (NULL == bd_addr) {
2041 ERR("bd_addr is NULL");
2042 return BT_STATUS_PARM_INVALID;
2045 /* GDBUS Connection Info validate */
2046 g_conn = _bt_hal_get_system_gconn();
2047 if (g_conn == NULL) {
2048 ERR("Could not get System DBUS Connection");
2049 return BT_STATUS_FAIL;
2052 /* Connection Info validate */
2053 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2054 if (conn_info == NULL) {
2055 ERR("No Connection Inforamtion!!!");
2056 return BT_STATUS_FAIL;
2059 _bt_hal_convert_addr_type_to_string(device_address,
2060 (unsigned char *)bd_addr->address);
2062 //check if connection has the same device address
2063 if (g_strcmp0(conn_info->addr, device_address) != 0) {
2064 ERR("device address [%s] does not match", device_address);
2065 return BT_STATUS_FAIL;
2068 device_path = _bt_hal_get_device_object_path(conn_info->addr);
2069 if (device_path == NULL) {
2070 ERR("device_path is NULL");
2071 return BT_STATUS_PARM_INVALID;
2074 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
2075 NULL, BT_HAL_BLUEZ_NAME,
2076 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2079 g_free(device_path);
2080 if (device_proxy == NULL)
2081 return BT_STATUS_FAIL;
2083 INFO("Disconnect LE [%s]", device_address);
2085 g_dbus_proxy_call(device_proxy, "DisconnectLE",
2087 G_DBUS_CALL_FLAGS_NONE,
2088 BT_HAL_MAX_DBUS_TIMEOUT,
2090 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
2093 return BT_STATUS_SUCCESS;
2096 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
2101 uuid = btuuid2str(srvc_id->uu);
2102 DBG("Original UUID [%s]", uuid);
2104 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
2105 /* Extract Standard UUID string */
2106 memcpy(uuid_buf, &uuid[4], 4);
2108 DBG("Converted string [%s]", uuid_buf);
2109 return g_strdup(uuid_buf);
2111 return strdup(uuid);
2114 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
2117 /* For GATT service specific */
2118 GDBusNodeInfo *node_info;
2121 struct gatt_service_info *serv_info = NULL;
2122 GVariantBuilder *builder = NULL;
2123 GVariantBuilder *builder1 = NULL;
2124 GVariantBuilder *inner_builder = NULL;
2125 gboolean svc_primary = TRUE;
2126 GError *error = NULL;
2127 hal_gatt_service_added *user_data = NULL;
2128 DBG("Service add to DBUS slot [%d]", slot);
2130 node_info = __bt_gatt_create_method_node_info(
2131 service_introspection_xml);
2133 if (node_info == NULL)
2134 return BT_STATUS_FAIL;
2136 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
2137 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
2138 DBG("gatt service path is [%s]", path);
2140 object_id = g_dbus_connection_register_object(g_conn, path,
2141 node_info->interfaces[0],
2142 &serv_interface_vtable,
2143 NULL, NULL, &error);
2145 if (object_id == 0) {
2146 ERR("failed to register: %s", error->message);
2147 g_error_free(error);
2149 return BT_STATUS_FAIL;
2151 /* Add object_id/gatt service information; it's required at the time of
2152 * service unregister and Getmanagedobjects
2154 serv_info = g_new0(struct gatt_service_info, 1);
2156 serv_info->serv_path = g_strdup(path);
2157 serv_info->serv_id = object_id;
2158 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
2159 serv_info->is_svc_registered = FALSE;
2160 serv_info->is_svc_primary = svc_primary;
2161 DBG("Service Handle to be added is [%d]", gatt_service_handle);
2162 serv_info->service_handle = gatt_service_handle;
2164 /* Update service in GATT Server service List */
2165 gatt_services = g_slist_append(gatt_services, serv_info);
2167 /* emit interfacesadded signal here for service path */
2168 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2169 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2171 g_variant_builder_add(inner_builder, "{sv}",
2172 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
2174 g_variant_builder_add(inner_builder, "{sv}",
2175 "Primary", g_variant_new_boolean(svc_primary));
2177 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2179 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
2180 g_variant_new("ao", builder1));
2182 g_variant_builder_add(builder, "{sa{sv}}",
2183 GATT_SERV_INTERFACE, inner_builder);
2185 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2186 "org.freedesktop.Dbus.ObjectManager",
2188 g_variant_new("(oa{sa{sv}})",
2193 /* dbus gives error cause */
2194 ERR("d-bus api failure: errcode[%x], message[%s]",
2195 error->code, error->message);
2196 g_clear_error(&error);
2200 /* Send Service handle to application */
2201 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2202 user_data->srvc_hdl = serv_info->service_handle;
2203 user_data->instance_data = slot;
2204 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2205 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2207 /* Save newly created service in GATT Server's service list */
2208 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2212 g_variant_builder_unref(inner_builder);
2213 g_variant_builder_unref(builder);
2214 g_variant_builder_unref(builder1);
2215 return BT_STATUS_SUCCESS;
2218 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2221 char *app_path = (char*)user_data;
2222 INFO("UnregisterApplication is completed app [%s]", app_path);
2223 GError *error = NULL;
2224 GVariant *result = NULL;
2227 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2229 if (result == NULL) {
2230 /* dBUS-RPC is failed */
2231 ERR("Dbus-RPC is failed\n");
2233 if (error != NULL) {
2234 /* dBUS gives error cause */
2235 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2236 error->code, error->message);
2237 g_clear_error(&error);
2240 g_variant_unref(result);
2245 static void __bt_hal_gatt_deinit(char *app_path)
2247 GDBusProxy *proxy = NULL;
2251 /* Step1: Remove requested App */
2252 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2253 "/org/bluez/hci0", "org.bluez.GattManager1");
2258 INFO("UnregisterApplication : path [%s]", app_path);
2260 /* Async Call to Unregister Service */
2261 data = g_strdup(app_path);
2262 g_dbus_proxy_call(proxy,
2263 "UnregisterApplication",
2264 g_variant_new("(o)",
2266 G_DBUS_CALL_FLAGS_NONE, -1,
2268 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2271 /* If requested app is last GATT Server app, then clean all resources */
2272 if (gatt_server_apps == NULL) {
2273 INFO("All GATT servers are removed, clean all DBUS resources");
2275 /* unregister the exported interface for object manager */
2276 g_dbus_connection_unregister_object(g_conn, manager_id);
2278 g_bus_unown_name(owner_id);
2281 g_object_unref(manager_gproxy);
2282 manager_gproxy = NULL;
2288 static int __bt_hal_gatt_init(void)
2292 /* Only once for ALL GATT Servers */
2293 if (owner_id == 0) {
2297 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2300 ERR("Unable to connect to gdbus: %s", err->message);
2301 g_clear_error(&err);
2303 return BT_STATUS_FAIL;
2306 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2307 INFO("well-known name: %s", name);
2309 owner_id = g_bus_own_name_on_connection(g_conn, name,
2310 G_BUS_NAME_OWNER_FLAGS_NONE,
2311 NULL, NULL, NULL, NULL);
2313 INFO("Owner ID [%d]", owner_id);
2315 /* Only once for ALL GATT Servers */
2316 if (manager_node_info == NULL) {
2317 /* Register ObjectManager interface */
2318 manager_node_info = __bt_gatt_create_method_node_info(
2319 manager_introspection_xml);
2321 if (manager_node_info == NULL) {
2322 ERR("failed to get node info");
2323 return BT_STATUS_FAIL;
2328 return BT_STATUS_SUCCESS;
2331 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2335 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2336 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2337 if (app->slot == slot) {
2338 INFO("GATT Server app found app path [%s] instance [%d]",
2339 app->app_path, app->slot);
2340 *app_path = app->app_path;
2344 /* GATT Server not found */
2348 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2350 if (app_path == NULL)
2353 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2354 app->app_path = g_strdup(app_path);
2356 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2357 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2362 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2365 CHECK_BTGATT_INIT();
2366 char *app_path = NULL;
2367 GError *error = NULL;
2370 int result = BT_STATUS_SUCCESS;
2372 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2373 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2375 /* Check if this GATT server Application is already registered with DBUS */
2376 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2378 if (app_path != NULL) {
2379 DBG("GATT server path is already defined [%s]", app_path);
2380 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2382 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2383 result = __bt_hal_gatt_init();
2384 if (result != BT_STATUS_SUCCESS)
2387 /* Only once for each GATT Server */
2388 app_path = g_strdup_printf("/com/%d", server_if);
2390 app_id = g_malloc0(sizeof(int));
2391 *app_id = server_if;
2393 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2394 manager_node_info->interfaces[0],
2395 &manager_interface_vtable,
2396 (gpointer)app_id, NULL, &error);
2398 if (manager_id == 0) {
2399 ERR("failed to register: %s", error->message);
2400 g_error_free(error);
2403 INFO("manager_id [%d]", manager_id);
2405 /* For current GATT Server, app_path is created, save it in Table */
2406 _bt_hal_update_gatt_server_path(server_if, app_path);
2408 /* Add GATT Service to DBUS */
2409 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2415 INFO("Successfully added service");
2416 return BT_STATUS_SUCCESS;
2423 INFO("Service addition failed!!");
2424 return BT_STATUS_FAIL;
2427 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2428 int included_handle)
2430 CHECK_BTGATT_INIT();
2431 return BT_STATUS_SUCCESS;
2435 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2438 GSList *gatt_services = NULL;
2440 struct gatt_service_info *info = NULL;
2442 gatt_services = _bt_get_service_list_from_server(instance);
2444 len = g_slist_length(gatt_services);
2445 l = g_slist_nth(gatt_services, len -1);
2451 if (info->service_handle == service_handle)
2456 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2460 GSList *gatt_services = NULL;
2461 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2463 gatt_services = _bt_get_service_list_from_server(instance);
2465 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2466 struct gatt_service_info *info = l->data;
2467 INFO("Got one service with handle [%d]", info->service_handle);
2468 if (info->service_handle == service_handle)
2471 ERR("Gatt service with handle [%d] not found", service_handle);
2475 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2476 bt_uuid_t *uuid, int properties,
2480 GError *error = NULL;
2482 GDBusNodeInfo *node_info;
2484 GVariantBuilder *builder = NULL;
2485 GVariantBuilder *inner_builder = NULL;
2486 struct gatt_service_info *serv_info = NULL;
2487 struct gatt_char_info *char_info = NULL;
2488 GVariantBuilder *builder2 = NULL;
2489 GVariantBuilder *builder3 = NULL;
2490 GVariant *flags_val = NULL;
2492 char *char_flags[NUMBER_OF_FLAGS];
2494 hal_gatt_char_added *user_data = NULL;
2497 CHECK_BTGATT_INIT();
2498 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2499 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2501 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2502 if (serv_info == NULL)
2503 return BT_STATUS_FAIL;
2505 node_info = __bt_gatt_create_method_node_info(
2506 characteristics_introspection_xml);
2508 if (node_info == NULL)
2509 return BT_STATUS_FAIL;
2511 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2512 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2513 DBG("gatt characteristic path is [%s]", path);
2515 app_id = g_malloc0(sizeof(int));
2518 object_id = g_dbus_connection_register_object(g_conn, path,
2519 node_info->interfaces[0],
2520 &char_interface_vtable,
2521 (gpointer)app_id, NULL, &error);
2523 if (object_id == 0) {
2524 ERR("failed to register: %s", error->message);
2525 g_error_free(error);
2528 return BT_STATUS_FAIL;
2531 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2532 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2533 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2534 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2535 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2536 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2537 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2538 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2540 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2542 char_info = g_new0(struct gatt_char_info, 1);
2544 char_info->char_path = g_strdup(path);
2545 char_info->char_id = object_id;
2546 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2547 for (i = 0; i < flag_count; i++)
2548 char_info->char_flags[i] = char_flags[i];
2551 char_info->flags_length = flag_count;
2552 char_info->char_handle = gatt_char_handle;
2555 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2556 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2558 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2559 g_variant_new("s", char_info->char_uuid));
2560 g_variant_builder_add(inner_builder, "{sv}", "Service",
2561 g_variant_new("o", serv_info->serv_path));
2563 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2565 for (i = 0; i < flag_count; i++)
2566 g_variant_builder_add(builder2, "s", char_flags[i]);
2568 flags_val = g_variant_new("as", builder2);
2569 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2572 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2574 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2575 g_variant_new("ao", builder3));
2577 g_variant_builder_add(builder, "{sa{sv}}",
2578 GATT_CHAR_INTERFACE,
2581 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2582 "org.freedesktop.Dbus.ObjectManager",
2584 g_variant_new("(oa{sa{sv}})",
2589 /* dbus gives error cause */
2590 ERR("d-bus api failure: errcode[%x], message[%s]",
2591 error->code, error->message);
2592 g_clear_error(&error);
2596 //*char_path = g_strdup(path);
2601 /* Send Service handle to application */
2602 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2603 user_data->srvc_hdl = serv_info->service_handle;
2604 user_data->char_hdl = gatt_char_handle;
2605 user_data->instance_data = slot;
2606 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2607 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2609 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2610 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2615 g_variant_builder_unref(inner_builder);
2616 g_variant_builder_unref(builder);
2617 g_variant_builder_unref(builder2);
2618 g_variant_builder_unref(builder3);
2620 return BT_STATUS_SUCCESS;
2623 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2626 CHECK_BTGATT_INIT();
2628 // static int desc_id = 1;
2629 GError *error = NULL;
2631 GDBusNodeInfo *node_info;
2633 GVariantBuilder *builder = NULL;
2634 GVariantBuilder *inner_builder = NULL;
2636 struct gatt_char_info *char_info = NULL;
2637 struct gatt_desc_info *desc_info = NULL;
2638 struct gatt_service_info *serv_info = NULL;
2640 gchar **line_argv = NULL;
2642 char *char_path = NULL;
2645 GVariantBuilder *builder2 = NULL;
2646 GVariant *flags_val = NULL;
2648 char *desc_flags[NUMBER_OF_FLAGS];
2652 hal_gatt_desc_added *user_data = NULL;
2659 /* Fetch service data for the GATT server */
2660 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2661 if (serv_info == NULL)
2662 return BT_STATUS_FAIL;
2664 /* Fetch list of characteristics from the service info */
2665 l = serv_info->char_data;
2667 /* Fetch last char info from the characteristic list */
2668 char_info = g_slist_last(l)->data;
2669 if (char_info == NULL)
2670 return BT_STATUS_FAIL;
2672 /* Fetch characteristic path from char info */
2673 char_path = char_info->char_path;
2675 line_argv = g_strsplit_set(char_path, "/", 0);
2676 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2679 node_info = __bt_gatt_create_method_node_info(
2680 descriptor_introspection_xml);
2682 if (node_info == NULL) {
2683 g_strfreev(line_argv);
2685 return BT_STATUS_FAIL;
2688 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2690 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2691 DBG("gatt descriptor path is [%s]", path);
2693 app_id = g_malloc0(sizeof(int));
2696 object_id = g_dbus_connection_register_object(g_conn, path,
2697 node_info->interfaces[0],
2698 &desc_interface_vtable,
2699 (gpointer)app_id, NULL, &error);
2701 if (object_id == 0) {
2702 ERR("failed to register: %s", error->message);
2703 g_error_free(error);
2705 g_strfreev(line_argv);
2708 return BT_STATUS_FAIL;
2711 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2713 desc_info = g_new0(struct gatt_desc_info, 1);
2715 desc_info->desc_path = g_strdup(path);
2716 desc_info->desc_id = object_id;
2717 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2719 for (i = 0; i < flag_count; i++)
2720 desc_info->desc_flags[i] = desc_flags[i];
2722 desc_info->flags_length = flag_count;
2723 desc_info->desc_handle = gatt_desc_handle;
2726 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2727 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2729 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2730 g_variant_new("s", btuuid2str(uuid->uu)));
2731 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2732 g_variant_new("o", char_path));
2734 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2736 for (i = 0; i < flag_count; i++)
2737 g_variant_builder_add(builder2, "s", desc_flags[i]);
2739 flags_val = g_variant_new("as", builder2);
2740 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2743 g_variant_builder_add(builder, "{sa{sv}}",
2744 GATT_DESC_INTERFACE,
2747 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2748 "org.freedesktop.Dbus.ObjectManager",
2750 g_variant_new("(oa{sa{sv}})",
2753 if (error != NULL) {
2754 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2755 error->code, error->message);
2756 g_clear_error(&error);
2759 //*desc_path = g_strdup(path);
2761 /* Save newly created descriptor to GATT server's service's characteristic */
2762 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2764 /* Send descriptor handle to application */
2765 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2766 user_data->srvc_hdl = serv_info->service_handle;
2767 user_data->desc_hdl = gatt_desc_handle;
2768 user_data->instance_data = slot;
2769 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2770 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2775 g_strfreev(line_argv);
2776 g_variant_builder_unref(inner_builder);
2777 g_variant_builder_unref(builder);
2778 return BT_STATUS_SUCCESS;
2781 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2783 GError *error = NULL;
2785 char *data = (char*) user_data;
2786 INFO("RegisterApplication is completed path [%s]", data);
2788 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2790 if (result == NULL) {
2791 /* dBUS-RPC is failed */
2792 ERR("Dbus-RPC is failed\n");
2794 if (error != NULL) {
2795 /* dBUS gives error cause */
2796 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2797 error->code, error->message);
2798 g_clear_error(&error);
2801 g_variant_unref(result);
2806 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2807 const gchar *path, const gchar *interface)
2813 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2818 ERR("Unable to connect to gdbus: %s", err->message);
2819 g_clear_error(&err);
2824 proxy = g_dbus_proxy_new_sync(g_conn,
2825 G_DBUS_PROXY_FLAGS_NONE, NULL,
2827 interface, NULL, &err);
2831 ERR("Unable to create proxy: %s", err->message);
2832 g_clear_error(&err);
2836 manager_gproxy = proxy;
2841 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2842 const gchar *path, const gchar *interface)
2844 return (manager_gproxy) ? manager_gproxy :
2845 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2849 static void __bt_register_application_to_dbus(int slot)
2851 GDBusProxy *proxy = NULL;
2852 char *app_path = NULL;
2854 DBG("RegisterApplication slot [%d]", slot);
2856 /* It is impossible that app path is still not initialized */
2857 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2859 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2860 "/org/bluez/hci0", "org.bluez.GattManager1");
2862 data = g_strdup(app_path);
2863 g_dbus_proxy_call(proxy,
2864 "RegisterApplication",
2865 g_variant_new("(oa{sv})",
2867 G_DBUS_CALL_FLAGS_NONE, -1,
2869 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2871 INFO("GATT server started");
2874 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2876 CHECK_BTGATT_INIT();
2877 struct gatt_service_info *serv_info = NULL;
2878 hal_gatt_service_started *user_data = NULL;
2879 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2881 /* Fetch service data for the GATT server */
2882 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2883 if (serv_info == NULL)
2884 return BT_STATUS_FAIL;
2886 if (serv_info->is_svc_registered)
2887 DBG("service already registered \n");
2889 serv_info->is_svc_registered = TRUE;
2891 /* Send Service handle to application */
2892 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2893 user_data->srvc_hdl = serv_info->service_handle;
2894 user_data->instance_data = server_if;
2895 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2897 /* If this is nth Service that is started, then register application at this point */
2898 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2899 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2901 __bt_register_application_to_dbus(server_if);
2904 return BT_STATUS_SUCCESS;
2907 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2909 CHECK_BTGATT_INIT();
2910 INFO("Stop service successful");
2911 return BT_STATUS_SUCCESS;
2914 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2916 CHECK_BTGATT_INIT();
2917 struct gatt_service_info *serv_info = NULL;
2918 hal_gatt_service_deleted *user_data = NULL;
2921 int err = BT_STATUS_SUCCESS;
2922 int ret = BT_STATUS_SUCCESS;
2923 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2925 /* Fetch service data for the GATT server */
2926 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2927 if (serv_info == NULL) {
2928 ERR("Could not find service info svc handle [%d] server slot [%d]",
2929 service_handle, server_if);
2930 return BT_STATUS_FAIL;
2933 if (serv_info->is_svc_registered == FALSE) {
2934 ERR("service Not registered path [%s] handle [%d]",
2935 serv_info->serv_path, service_handle);
2938 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2939 struct gatt_char_info *char_info = l->data;
2941 if (char_info == NULL)
2944 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2945 struct gatt_desc_info *desc_info = l1->data;
2947 if (desc_info == NULL)
2950 ret = g_dbus_connection_unregister_object(g_conn,
2951 desc_info->desc_id);
2953 __bt_hal_gatt_emit_interface_removed(
2954 desc_info->desc_path,
2955 GATT_DESC_INTERFACE);
2957 err = BT_STATUS_FAIL;
2960 /* list remove & free */
2961 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2962 __bt_hal_gatt_free_descriptor_info(desc_info);
2965 g_slist_free(char_info->desc_data);
2966 char_info->desc_data = NULL;
2968 ret = g_dbus_connection_unregister_object(g_conn,
2969 char_info->char_id);
2971 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2972 GATT_CHAR_INTERFACE);
2975 err = BT_STATUS_FAIL;
2978 /* list remove & free */
2979 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2980 __bt_hal_gatt_free_characteristic_info(char_info);
2983 g_slist_free(serv_info->char_data);
2984 serv_info->char_data = NULL;
2986 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2988 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2989 GATT_SERV_INTERFACE);
2992 err = BT_STATUS_FAIL;
2995 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
2997 DBG("Unregistered the service on properties interface");
2999 /* Remove from global list */
3000 gatt_services = g_slist_remove(gatt_services, serv_info);
3001 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
3003 /* Remove from GATT Server's list of services */
3004 _bt_remote_service_from_gatt_server(server_if, service_handle);
3006 if (gatt_services == NULL)
3007 INFO("All GATT Services of all GATT Servers are unregistered");
3009 if (err == BT_STATUS_SUCCESS) {
3010 INFO("Send GATT Service deleted Event");
3011 /* Send Service handle to application */
3012 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
3013 user_data->srvc_hdl = serv_info->service_handle;
3014 user_data->instance_data = server_if;
3015 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
3018 /* Free the service */
3019 __bt_hal_gatt_free_service_info(serv_info);
3023 static gboolean __bt_gatt_get_service_state(const char *service_path)
3025 struct gatt_service_info *svc_info = NULL;
3027 for (l = gatt_services; l; l = g_slist_next(l)) {
3029 svc_info = (struct gatt_service_info *)l->data;
3032 if (!g_strcmp0(svc_info->serv_path, service_path)) {
3033 DBG("Return the state of the gatt service %d",
3034 svc_info->is_svc_registered);
3035 return svc_info->is_svc_registered;
3039 DBG("gatt service info is NULL");
3043 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
3044 int len, int confirm, char* p_value)
3046 CHECK_BTGATT_INIT();
3049 GVariantBuilder *outer_builder;
3050 GVariantBuilder *invalidated_builder;
3052 /* For Value update via PropertyChange */
3053 GVariantBuilder *outer_builder1;
3054 GVariantBuilder *inner_builder1;
3055 GVariantBuilder *invalidated_builder1;
3056 GVariant *update_value = NULL;
3058 /* Other variables */
3059 struct gatt_client_info_t *conn_info = NULL;
3060 gchar *serv_path = NULL;
3061 char *char_path = NULL;
3062 gchar **line_argv = NULL;
3063 gboolean notify = TRUE;
3064 gboolean ret = TRUE;
3065 int err = BT_STATUS_SUCCESS;
3067 GError *error = NULL;
3070 memset(addr, 0x00, sizeof(addr));
3072 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3073 if (conn_info == NULL) {
3074 ERR("No Connection Inforamtion!!!");
3075 return BT_STATUS_FAIL;
3078 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
3080 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3081 if (char_path == NULL)
3082 return BT_STATUS_FAIL;
3084 line_argv = g_strsplit_set(char_path, "/", 0);
3085 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3087 if (!__bt_gatt_get_service_state(serv_path)) {
3088 DBG("service not registered for this characteristic \n");
3090 g_strfreev(line_argv);
3091 return BT_STATUS_FAIL;
3094 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3095 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3097 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
3098 g_variant_new("b", notify));
3100 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
3101 DBG("Send Indication to Unicast addr [%s]", addr);
3103 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
3104 g_variant_new("s", addr));
3106 DBG("Set characteristic Notification \n");
3107 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3109 "org.freedesktop.DBus.Properties",
3110 "PropertiesChanged",
3111 g_variant_new("(sa{sv}as)",
3112 "org.bluez.GattCharacteristic1",
3113 outer_builder, invalidated_builder),
3117 if (error != NULL) {
3118 ERR("D-Bus API failure: errCode[%x], \
3120 error->code, error->message);
3121 g_clear_error(&error);
3123 err = BT_STATUS_FAIL;
3126 g_variant_builder_unref(outer_builder);
3127 g_variant_builder_unref(invalidated_builder);
3130 /* Notifying Done, now update Value to Bluez via PropertyChanged */
3131 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
3133 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3134 for (i = 0; i < len; i++)
3135 g_variant_builder_add(inner_builder1, "y", p_value[i]);
3137 update_value = g_variant_new("ay", inner_builder1);
3140 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3141 g_variant_builder_add(outer_builder1, "{sv}", "Value",
3144 DBG("Updating characteristic value \n");
3145 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3147 "org.freedesktop.DBus.Properties",
3148 "PropertiesChanged",
3149 g_variant_new("(sa{sv}as)",
3150 "org.bluez.GattCharacteristic1",
3151 outer_builder1, invalidated_builder1),
3155 if (error != NULL) {
3156 ERR("D-Bus API failure: errCode[%x], \
3158 error->code, error->message);
3159 g_clear_error(&error);
3161 err = BT_STATUS_FAIL;
3163 struct gatt_char_info *char_info = NULL;
3165 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3166 if (char_info == NULL) {
3168 g_strfreev(line_argv);
3169 g_variant_builder_unref(inner_builder1);
3170 g_variant_builder_unref(outer_builder1);
3171 g_variant_builder_unref(invalidated_builder1);
3173 return BT_STATUS_FAIL;
3176 char_info->value_length = len;
3178 char_info->char_value = (char *)realloc(char_info->char_value, len);
3179 if (char_info->char_value) {
3180 for (i = 0; i < len; i++)
3181 char_info->char_value[i] = p_value[i];
3186 g_strfreev(line_argv);
3187 g_variant_builder_unref(inner_builder1);
3188 g_variant_builder_unref(outer_builder1);
3189 g_variant_builder_unref(invalidated_builder1);
3194 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3195 int status, btgatt_response_t *response)
3197 CHECK_BTGATT_INIT();
3199 struct gatt_req_info *req_info = NULL;
3200 struct gatt_client_info_t *conn_info = NULL;
3203 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3205 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3206 if (conn_info == NULL) {
3207 ERR("No Connection Inforamtion!!!");
3208 return BT_STATUS_FAIL;
3211 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3212 if (req_info == NULL) {
3213 ERR("No Request Inforamtion!!!");
3214 return BT_STATUS_FAIL;
3217 if (status != BT_STATUS_SUCCESS) {
3218 ERR("resp_state is 0x%X", status);
3220 g_dbus_method_invocation_return_dbus_error(req_info->context,
3221 "org.bluez.Error.Failed", "Application Error");
3223 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3225 req_info->context = NULL;
3226 if (req_info->attr_path)
3227 g_free(req_info->attr_path);
3228 if (req_info->svc_path)
3229 g_free(req_info->svc_path);
3232 return BT_STATUS_SUCCESS;
3235 DBG("Reponse Value length [%d]", response->attr_value.len);
3236 DBG("Request type: [%d]", req_info->request_type);
3239 for (i = 0; i < response->attr_value.len; i++)
3240 DBG("Resonse [%d] = [0x%x]", i, response->attr_value.value[i]);
3242 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3243 GVariantBuilder *inner_builder = NULL;
3244 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3246 if (response->attr_value.len > 0) {
3247 for (i = 0; i < response->attr_value.len; i++)
3248 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3250 g_dbus_method_invocation_return_value(req_info->context,
3251 g_variant_new("(ay)", inner_builder));
3253 g_variant_builder_unref(inner_builder);
3255 g_dbus_method_invocation_return_value(req_info->context, NULL);
3257 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3259 req_info->context = NULL;
3260 if (req_info->attr_path)
3261 g_free(req_info->attr_path);
3262 if (req_info->svc_path)
3263 g_free(req_info->svc_path);
3266 return BT_STATUS_SUCCESS;
3270 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3271 int status, int fd, int mtu, void *fdlist)
3273 CHECK_BTGATT_INIT();
3275 struct gatt_req_info *req_info = NULL;
3276 struct gatt_client_info_t *conn_info = NULL;
3278 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3280 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3281 if (conn_info == NULL) {
3282 ERR("No Connection Inforamtion!!!");
3283 return BT_STATUS_FAIL;
3286 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3287 if (req_info == NULL) {
3288 ERR("No Request Inforamtion!!!");
3289 return BT_STATUS_FAIL;
3292 if (status != BT_STATUS_SUCCESS) {
3293 ERR("resp_state is 0x%X", status);
3295 g_dbus_method_invocation_return_dbus_error(req_info->context,
3296 "org.bluez.Error.Failed", "Application Error");
3298 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3300 req_info->context = NULL;
3301 if (req_info->attr_path)
3302 g_free(req_info->attr_path);
3303 if (req_info->svc_path)
3304 g_free(req_info->svc_path);
3307 return BT_STATUS_SUCCESS;
3311 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3313 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3314 g_dbus_method_invocation_return_value_with_unix_fd_list(
3315 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3317 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3319 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3320 g_dbus_method_invocation_return_value_with_unix_fd_list(
3321 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3324 g_dbus_method_invocation_return_value(req_info->context, NULL);
3326 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3328 req_info->context = NULL;
3329 if (req_info->attr_path)
3330 g_free(req_info->attr_path);
3331 if (req_info->svc_path)
3332 g_free(req_info->svc_path);
3335 return BT_STATUS_SUCCESS;
3339 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3340 int value_length, char* att_value)
3342 CHECK_BTGATT_INIT();
3344 /* Other variables */
3345 char *char_path = NULL;
3346 gboolean ret = TRUE;
3347 GError *error = NULL;
3349 GVariantBuilder *outer_builder;
3350 GVariantBuilder *inner_builder;
3351 GVariantBuilder *invalidated_builder;
3352 GVariant *update_value = NULL;
3353 int err = BT_STATUS_SUCCESS;
3355 gchar **line_argv = NULL;
3356 gchar *serv_path = NULL;
3358 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3359 if (char_path == NULL)
3360 return BT_STATUS_FAIL;
3362 line_argv = g_strsplit_set(char_path, "/", 0);
3363 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3365 if (!__bt_gatt_get_service_state(serv_path)) {
3366 DBG("service not registered for this characteristic \n");
3368 g_strfreev(line_argv);
3369 return BT_STATUS_FAIL;
3373 line_argv = g_strsplit_set(char_path, "/", 0);
3374 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3376 if (!__bt_gatt_get_service_state(serv_path)) {
3377 DBG("service not registered for this characteristic \n");
3379 g_strfreev(line_argv);
3380 return BT_STATUS_FAIL;
3383 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3384 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3386 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3387 for (i = 0; i < value_length; i++)
3388 g_variant_builder_add(inner_builder, "y", att_value[i]);
3390 update_value = g_variant_new("ay", inner_builder);
3392 g_variant_builder_add(outer_builder, "{sv}", "Value",
3395 DBG("Updating characteristic value \n");
3396 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3398 "org.freedesktop.DBus.Properties",
3399 "PropertiesChanged",
3400 g_variant_new("(sa{sv}as)",
3401 "org.bluez.GattCharacteristic1",
3402 outer_builder, invalidated_builder),
3406 if (error != NULL) {
3407 ERR("D-Bus API failure: errCode[%x], \
3409 error->code, error->message);
3410 g_clear_error(&error);
3412 err = BT_STATUS_FAIL;
3414 struct gatt_char_info *char_info = NULL;
3416 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3417 if (char_info == NULL) {
3419 g_strfreev(line_argv);
3420 g_variant_builder_unref(inner_builder);
3421 g_variant_builder_unref(outer_builder);
3422 g_variant_builder_unref(invalidated_builder);
3424 return BT_STATUS_FAIL;
3427 char_info->value_length = value_length;
3429 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3430 if (char_info->char_value) {
3431 for (i = 0; i < value_length; i++)
3432 char_info->char_value[i] = att_value[i];
3438 g_strfreev(line_argv);
3439 g_variant_builder_unref(inner_builder);
3440 g_variant_builder_unref(outer_builder);
3441 g_variant_builder_unref(invalidated_builder);
3446 static bt_status_t gatt_server_listen(int server_if, bool start)
3448 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");
3457 return BT_STATUS_FAIL;
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);
3464 return BT_STATUS_FAIL;
3467 /* Send Data to LE Module */
3468 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, start, FALSE);
3471 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3472 bool include_txpower, int min_interval, int max_interval, int appearance,
3473 uint16_t manufacturer_len, char* manufacturer_data,
3474 uint16_t service_data_len, char* service_data,
3475 uint16_t service_uuid_len, char* service_uuid)
3477 CHECK_BTGATT_INIT();
3478 return BT_STATUS_SUCCESS;
3481 static int bt_hal_gatts_allocate_adv_slot(struct hal_gatts_server_register_info_t *server_register_info)
3483 int adv_slot_id = -1;
3485 /* allocate adv slot for gatt server if not assigned */
3486 if (server_register_info->adv_slot_id < 0 ) {
3487 adv_slot_id = _bt_hal_get_available_adv_slot_id(&server_register_info->app_uuid, FALSE);
3488 if (adv_slot_id < 0) {
3489 ERR("failed to get the adv_slot");
3493 server_register_info->adv_slot_id = adv_slot_id;
3496 DBG("gatt server:[%d] Assigned adv_slot [%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3501 int bt_hal_gatts_allocate_adv_slot_by_server_if(int server_if)
3503 CHECK_BTGATT_INIT();
3507 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3509 DBG("server_if: [%d]", server_if);
3511 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3512 if (server_register_info == NULL) {
3513 DBG("gatt server is not registered");
3517 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3519 if (server_register_info->adv_slot_id < 0 ) {
3520 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3522 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3524 DBG("failed to get adv_slot");
3529 return server_register_info->adv_slot_id;
3532 void bt_hal_gatts_release_adv_slot(int server_if)
3534 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3536 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3537 if (server_register_info == NULL) {
3538 ERR("failed to get server_register_info");
3542 if (server_register_info->adv_slot_id < 0) {
3543 ERR("adv_slot is not allocated");
3547 if(_bt_hal_is_advertising_in_slot(server_register_info->adv_slot_id) == FALSE) {
3548 DBG("advertising is disabled");
3549 _bt_hal_free_server_slot(server_register_info->adv_slot_id);
3550 server_register_info->adv_slot_id = -1;
3554 int bt_hal_gatts_get_adv_slot_id(int server_if)
3556 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3558 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3559 if (server_register_info == NULL) {
3560 DBG("failed to get server_register_info");
3564 return server_register_info->adv_slot_id;
3567 int bt_hal_gatts_get_server_if(int slot_id)
3569 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3571 server_register_info = bt_hal_gatts_find_server_register_info_by_slot_id(slot_id);
3572 if (server_register_info == NULL) {
3573 DBG("failed to get server_register_info");
3577 return server_register_info->server_if;
3580 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3582 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 ERR("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]", server_if);
3601 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3603 ERR("failed to get adv_slot");
3604 return BT_STATUS_FAIL;
3608 /* Send Enable Advertising request to LE Module */
3609 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, TRUE, TRUE);
3612 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3613 int chnl_map, int tx_power, int timeout_s)
3615 CHECK_BTGATT_INIT();
3617 /* Send Advertising parameters to LE Module */
3618 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3619 chnl_map, tx_power, timeout_s);
3622 static bt_status_t gatt_server_set_filter_policy(int filter_policy)
3624 CHECK_BTGATT_INIT();
3626 /* Send the Filter policy parameter to LE Module */
3627 _bt_hal_set_filter_policy_param(filter_policy);
3628 return BT_STATUS_SUCCESS;
3631 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3633 CHECK_BTGATT_INIT();
3635 /* Send Data to LE Module */
3636 return _bt_hal_set_advertising_data(adv_param_setup);
3639 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3641 CHECK_BTGATT_INIT();
3643 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3645 DBG("server_if: [%d]", server_if);
3647 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3648 if (server_register_info == NULL) {
3649 DBG("gatt server is not registered");
3650 return BT_STATUS_FAIL;
3653 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3655 if (server_register_info->adv_slot_id < 0 ) {
3656 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3657 return BT_STATUS_FAIL;
3660 /* Send Data to LE Module */
3661 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, FALSE, TRUE);
3664 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3666 CHECK_BTGATT_INIT();
3667 char *object_path = NULL;
3669 GDBusProxy *device_proxy;
3670 GError *error = NULL;
3672 GVariant *tmp_value;
3673 GDBusConnection *conn;
3674 GVariant *result = NULL;
3675 int ret = BT_STATUS_SUCCESS;
3676 struct gatt_client_info_t *conn_info = NULL;
3679 if (mtu_size == NULL)
3680 return BT_STATUS_PARM_INVALID;
3682 /* GDBUS Connection Info validate */
3683 conn = _bt_hal_get_system_gconn();
3685 ERR("Could not get System DBUS Connection");
3686 return BT_STATUS_FAIL;
3689 /* Connection Info validate */
3690 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3691 if (conn_info == NULL) {
3692 ERR("No Connection Inforamtion!!!");
3693 return BT_STATUS_FAIL;
3697 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3698 if (object_path == NULL)
3699 return BT_STATUS_FAIL;
3701 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3702 NULL, BT_HAL_BLUEZ_NAME, object_path,
3703 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3705 g_free(object_path);
3706 if (device_proxy == NULL)
3707 return BT_STATUS_FAIL;
3709 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3710 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3711 G_DBUS_CALL_FLAGS_NONE,
3715 if (result == NULL) {
3716 if (error != NULL) {
3717 ERR("Error occured in Proxy call [%s]\n", error->message);
3718 g_error_free(error);
3720 g_object_unref(device_proxy);
3721 return BT_STATUS_FAIL;
3724 g_variant_get(result , "(@a{sv})", &value);
3725 g_variant_unref(result);
3727 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3728 if (tmp_value == NULL) {
3729 g_object_unref(device_proxy);
3730 g_variant_unref(value);
3731 return BT_STATUS_FAIL;
3734 mtu = g_variant_get_uint16(tmp_value);
3736 DBG("ATT MTU : [%d]", mtu);
3738 g_variant_unref(tmp_value);
3739 g_variant_unref(value);
3740 g_object_unref(device_proxy);
3742 *mtu_size = (int) mtu;
3747 const btgatt_server_interface_t btgatt_server_interface = {
3748 .register_server = gatt_server_register_app,
3749 .unregister_server = gatt_server_unregister_app,
3750 .connect = gatt_server_open,
3751 .disconnect = gatt_server_close,
3752 .add_service = gatt_server_add_service,
3753 .add_included_service = gatt_server_add_included_service,
3754 .add_characteristic = gatt_server_add_characteristic,
3755 .add_descriptor = gatt_server_add_descriptor,
3756 .start_service = gatt_server_start_service,
3757 .stop_service = gatt_server_stop_service,
3758 .delete_service = gatt_server_delete_service,
3759 .send_indication = gatt_server_send_indication,
3760 .send_response = gatt_server_send_response,
3761 .update_att_value = gatt_server_update_att_value,
3762 .listen = gatt_server_listen,
3763 .set_adv_data = gatt_server_set_adv_data,
3764 .multi_adv_enable = gatt_server_multi_adv_enable,
3765 .multi_adv_update = gatt_server_multi_adv_update,
3766 .set_filter_policy = gatt_server_set_filter_policy,
3767 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3768 .multi_adv_disable = gatt_server_multi_adv_disable,
3769 .get_att_mtu = gatt_server_get_mtu_size,
3770 .send_response_acquire = gatt_server_send_acquire_response