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 extern int hal_gatt_conn_id;
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))
473 static struct gatt_client_info_t *__bt_find_remote_gatt_client_info_from_conn(int conn_id)
476 struct gatt_client_info_t *info = NULL;
478 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
479 info = (struct gatt_client_info_t*)l->data;
483 if (info->connection_id == conn_id)
489 static struct gatt_req_info *__bt_find_remote_gatt_client_request_info(int conn_id, int trans_id)
494 struct gatt_client_info_t *info = NULL;
495 struct gatt_req_info *info1 = NULL;
497 for (l = gatt_client_info_list; l != NULL; l = g_slist_next(l)) {
498 info = (struct gatt_client_info_t*)l->data;
502 if (info->connection_id == conn_id) {
504 for (l1 = info->gatt_req_info_list; l1; l1 = g_slist_next(l1)) {
506 info1 = (struct gatt_req_info*)l1->data;
510 if (info1->request_id == trans_id)
518 void _bt_hal_gatt_connected_state_event(gboolean is_connected, char *address)
520 struct hal_ev_gatt_server_connected ev;
521 struct gatt_client_info_t *conn_info = NULL;
522 memset(&ev, 0, sizeof(ev));
524 /* Convert address to hex */
525 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
527 /* Create Connection ID */
528 /* Check if device is already in connected list */
529 conn_info = __bt_find_remote_gatt_client_info(address);
531 /* If disconnected, and conn info found, then remove conn info */
532 if (is_connected == FALSE) {
533 DBG("GATT Disconnected");
535 INFO("Remove GATT client info from List..");
536 /* Remove info from List */
537 gatt_client_info_list = g_slist_remove(gatt_client_info_list, conn_info);
538 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
541 ERR("GATT callback not registered");
543 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
544 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
545 ev.conn_id = conn_info->connection_id;
546 ev.server_instance = conn_info->instance_id;
547 ev.connected = is_connected;
549 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
551 g_free(conn_info->addr);
554 /* If connected, and conn info NOT found, then add conn info */
558 /* Find Server Instance */
559 instance = bt_hal_gatts_get_gatt_server_instance();
560 if (instance == -1) {
561 ERR("Not even a single GATT server is registered");
562 ev.conn_id = ++hal_gatt_conn_id;
563 ev.server_instance = -1;
564 ev.connected = is_connected;
565 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
568 DBG("server instance [%d]", instance);
571 /* Save Connection info */
572 conn_info = g_new0(struct gatt_client_info_t, 1);
573 conn_info->addr = g_strdup(address);
574 INFO("Added GATT client addr[%s]", conn_info->addr);
575 conn_info->connection_id = ++hal_gatt_conn_id;
576 conn_info->instance_id = instance;
577 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
578 INFO("Total num of connected GATT clients [%d]", g_slist_length(gatt_client_info_list));
581 ERR("GATT callback not registered");
583 DBG("GATT callback registered: server if [%d] Is Connected [%d] addr[%s] conn ID [%d]",
584 conn_info->instance_id, is_connected, conn_info->addr, conn_info->connection_id);
585 ev.conn_id = conn_info->connection_id;
586 ev.server_instance = conn_info->instance_id;
587 ev.connected = is_connected;
589 event_cb(HAL_EV_GATT_SERVER_CONNECTED, (void *)&ev, sizeof(ev));
592 ERR("Abnormal case. conn_info should be NULL");
595 /* Send GATT connected or disconnected event */
598 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_char(const char *char_path, int *char_hdl)
602 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
603 struct gatt_service_info *serv_info = l1->data;
605 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
606 struct gatt_char_info *char_info = l2->data;
608 if (g_strcmp0(char_info->char_path, char_path)
610 *char_hdl = char_info->char_handle;
615 ERR("Gatt service not found");
619 static char *__bt_gatt_find_char_path_from_handle(int char_hdl)
623 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
624 struct gatt_service_info *serv_info = l1->data;
626 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
627 struct gatt_char_info *char_info = l2->data;
629 if (char_info->char_handle == char_hdl)
630 return char_info->char_path;
637 static struct gatt_char_info *__bt_gatt_find_char_info_from_handle(int char_hdl)
641 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
642 struct gatt_service_info *serv_info = l1->data;
644 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
645 struct gatt_char_info *char_info = l2->data;
647 if (char_info->char_handle == char_hdl)
655 static struct gatt_service_info *__bt_gatt_find_gatt_service_from_desc(const char *desc_path, int *desc_hdl)
657 GSList *l1, *l2, *l3;
659 for (l1 = gatt_services; l1 != NULL; l1 = l1->next) {
660 struct gatt_service_info *serv_info = l1->data;
662 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
663 struct gatt_char_info *char_info = l2->data;
665 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
666 struct gatt_desc_info *desc_info = l3->data;
668 if (g_strcmp0(desc_info->desc_path, desc_path)
670 *desc_hdl = desc_info->desc_handle;
676 ERR("Gatt service not found");
680 static void __bt_gatt_manager_method_call(GDBusConnection *connection,
682 const gchar *object_path,
683 const gchar *interface_name,
684 const gchar *method_name,
685 GVariant *parameters,
686 GDBusMethodInvocation *invocation,
691 if (g_strcmp0(method_name, "GetManagedObjects") == 0) {
692 GVariantBuilder *builder;
693 GVariantBuilder *inner_builder1 = NULL;
694 GVariant *svc_char = NULL;
696 GSList *gatt_services = NULL;
698 instance = (int*)user_data;
699 gboolean writeAcquired = FALSE;
700 gboolean notifyAcquired = FALSE;
702 DBG("Getting values for service, chars and descriptors");
703 DBG("GATT Server App for which services are requested [%d]", *instance);
706 builder = g_variant_builder_new(
707 G_VARIANT_TYPE("a{oa{sa{sv}}}"));
710 gatt_services = _bt_get_service_list_from_server(*instance);
712 if (g_slist_length(gatt_services) == 0) {
713 ERR("No registered GATT services!!!!");
714 g_dbus_method_invocation_return_value(invocation, NULL);
715 g_variant_builder_unref(builder);
719 for (l = gatt_services; l != NULL; l = l->next) {
720 GVariantBuilder *svc_builder = NULL;
721 GVariantBuilder *inner_builder = NULL;
722 struct gatt_service_info *serv_info = l->data;
723 INFO("GATT Service fetched handle [%d]", serv_info->service_handle);
725 /* Prepare inner builder for GattService1 interface */
726 DBG("Creating builder for service");
727 svc_builder = g_variant_builder_new(
728 G_VARIANT_TYPE("a{sa{sv}}"));
729 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
731 g_variant_builder_add(inner_builder, "{sv}", "UUID",
732 g_variant_new_string(serv_info->service_uuid));
734 g_variant_builder_add(inner_builder, "{sv}", "Primary",
735 g_variant_new_boolean(serv_info->is_svc_primary));
738 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
739 DBG("Adding Charatarisitcs list");
740 for (l4 = serv_info->char_data; l4 != NULL; l4 = l4->next) {
741 struct gatt_char_info *char_info = l4->data;
742 INFO("GATT Char handle [%d] found in GATT service handle [%d]",
743 char_info->char_handle, serv_info->service_handle);
744 g_variant_builder_add(inner_builder1, "o",
745 char_info->char_path);
746 DBG("%s", char_info->char_path);
749 svc_char = g_variant_new("ao", inner_builder1);
750 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
753 g_variant_builder_add(svc_builder, "{sa{sv}}",
757 g_variant_builder_add(builder, "{oa{sa{sv}}}",
758 serv_info->serv_path,
761 g_variant_builder_unref(inner_builder1);
763 /* Prepare inner builder for GattCharacteristic1 interface */
765 GSList *l2 = serv_info->char_data;
766 DBG("Creating builder for characteristics \n");
769 DBG("characteristic data is NULL");
771 for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) {
773 GVariantBuilder *char_builder = NULL;
774 GVariantBuilder *inner_builder = NULL;
775 GVariantBuilder *builder1 = NULL;
776 GVariantBuilder *builder2 = NULL;
777 GVariantBuilder *builder3 = NULL;
778 GVariant *char_val = NULL;
779 GVariant *flags_val = NULL;
780 GVariant *char_desc = NULL;
781 char *unicast = NULL;
782 gboolean notify = FALSE;
785 char_builder = g_variant_builder_new(
788 inner_builder = g_variant_builder_new(
792 struct gatt_char_info *char_info = l2->data;
793 if (char_info == NULL) {
794 ERR("char_info is NULL");
799 g_variant_builder_add(inner_builder, "{sv}", "UUID",
800 g_variant_new_string(char_info->char_uuid));
802 g_variant_builder_add(inner_builder, "{sv}", "Service",
803 g_variant_new("o", serv_info->serv_path));
805 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
807 if (char_info->char_value != NULL) {
808 for (i = 0; i < char_info->value_length; i++) {
809 g_variant_builder_add(builder1, "y",
810 char_info->char_value[i]);
812 char_val = g_variant_new("ay", builder1);
813 g_variant_builder_add(inner_builder, "{sv}",
817 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
818 for (i = 0; i < char_info->flags_length; i++) {
819 g_variant_builder_add(builder2, "s",
820 char_info->char_flags[i]);
822 if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) {
823 DBG("setting WriteAcquired property");
824 writeAcquired = TRUE;
827 if (strncmp(char_info->char_flags[i], "notify", 4) == 0) {
828 DBG("setting NotifyAcquired property");
829 notifyAcquired = TRUE;
833 flags_val = g_variant_new("as", builder2);
834 g_variant_builder_add(inner_builder, "{sv}", "Flags",
838 g_variant_builder_add(inner_builder, "{sv}", "Notifying",
839 g_variant_new("b", notify));
842 if (writeAcquired == TRUE) {
843 DBG("adding WriteAcquired property");
844 g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired",
845 g_variant_new("b", writeAcquired));
849 if (notifyAcquired == TRUE) {
850 DBG("adding NotifyAcquired property");
851 g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired",
852 g_variant_new("b", notifyAcquired));
856 unicast = g_strdup("00:00:00:00:00:00");
857 g_variant_builder_add(inner_builder, "{sv}", "Unicast",
858 g_variant_new("s", unicast));
861 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
862 DBG("Adding Descriptors list");
864 for (l4 = char_info->desc_data; l4 != NULL; l4 = l4->next) {
865 struct gatt_desc_info *desc_info = l4->data;
866 INFO("GATT Descriptor handle [%d] found inside GATT Char handle [%d] found in GATT service handle [%d]",
867 desc_info->desc_handle, char_info->char_handle, serv_info->service_handle);
868 g_variant_builder_add(builder3, "o",
869 desc_info->desc_path);
870 DBG("%s", desc_info->desc_path);
873 char_desc = g_variant_new("ao", builder3);
874 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
877 g_variant_builder_add(char_builder, "{sa{sv}}",
878 GATT_CHAR_INTERFACE , inner_builder);
879 g_variant_builder_add(builder, "{oa{sa{sv}}}",
880 char_info->char_path, char_builder);
882 /*Prepare inner builder for GattDescriptor1 interface*/
884 GSList *l3 = char_info->desc_data;
887 DBG("descriptor data is NULL");
889 for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) {
891 DBG("Creating builder for descriptor \n");
893 GVariantBuilder *desc_builder = NULL;
894 GVariantBuilder *inner_builder = NULL;
895 GVariantBuilder *builder1 = NULL;
896 GVariantBuilder *builder2 = NULL;
897 GVariant *desc_val = NULL;
899 desc_builder = g_variant_builder_new(
902 inner_builder = g_variant_builder_new(
906 struct gatt_desc_info *desc_info = l3->data;
907 if (desc_info == NULL) {
908 ERR("desc_info is NULL");
913 g_variant_builder_add(inner_builder,
915 g_variant_new_string(
916 desc_info->desc_uuid));
919 g_variant_builder_add(inner_builder, "{sv}",
922 char_info->char_path));
925 builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
927 if (desc_info->desc_value != NULL) {
928 for (i = 0; i < desc_info->value_length; i++) {
929 g_variant_builder_add(builder1, "y",
930 desc_info->desc_value[i]);
932 desc_val = g_variant_new("ay", builder1);
933 g_variant_builder_add(inner_builder, "{sv}",
938 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
940 for (i = 0; i < desc_info->flags_length; i++) {
941 g_variant_builder_add(builder2, "s",
942 desc_info->desc_flags[i]);
945 flags_val = g_variant_new("as", builder2);
946 g_variant_builder_add(inner_builder, "{sv}", "Flags",
949 g_variant_builder_add(desc_builder, "{sa{sv}}",
953 g_variant_builder_add(builder, "{oa{sa{sv}}}",
954 desc_info->desc_path,
957 /*unref descriptor builder pointers*/
958 g_variant_builder_unref(builder1);
959 g_variant_builder_unref(builder2);
960 g_variant_builder_unref(inner_builder);
961 g_variant_builder_unref(desc_builder);
966 /*unref char builder pointers*/
967 g_variant_builder_unref(builder1);
968 g_variant_builder_unref(builder2);
969 g_variant_builder_unref(builder3);
970 g_variant_builder_unref(inner_builder);
971 g_variant_builder_unref(char_builder);
974 /*unref service builder pointers*/
975 g_variant_builder_unref(inner_builder);
976 g_variant_builder_unref(svc_builder);
979 /* Return builder as method reply */
980 DBG("Sending gatt service builder values to Bluez");
981 g_dbus_method_invocation_return_value(invocation,
991 static void __bt_gatt_desc_method_call(GDBusConnection *connection,
993 const gchar *object_path,
994 const gchar *interface_name,
995 const gchar *method_name,
996 GVariant *parameters,
997 GDBusMethodInvocation *invocation,
1001 if (g_strcmp0(method_name, "ReadValue") == 0) {
1002 struct hal_ev_gatt_server_read_req ev;
1007 struct gatt_client_info_t *conn_info = NULL;
1008 struct gatt_req_info *req_info = NULL;
1009 struct gatt_service_info *svc_info = NULL;
1013 DBG("Application path = %s", object_path);
1014 DBG("Sender = %s", sender);
1016 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1017 if (svc_info == NULL) {
1018 ERR("Coudn't find service for %s", object_path);
1019 g_dbus_method_invocation_return_value(invocation, NULL);
1023 g_variant_get(parameters, "(&suq)", &addr, &req_id, &offset);
1024 DBG("Request id = %u, Offset = %u", req_id, offset);
1026 /* Check if device is already in connected list */
1027 conn_info = __bt_find_remote_gatt_client_info(addr);
1029 if (conn_info == NULL) {
1030 ERR("Coudn't find Connection info for %s", addr);
1031 g_dbus_method_invocation_return_value(invocation, NULL);
1036 ERR("GATT callback NOT registered");
1037 g_dbus_method_invocation_return_value(invocation, NULL);
1041 /* Store requests information */
1042 req_info = g_new0(struct gatt_req_info, 1);
1043 req_info->attr_path = g_strdup(object_path);
1044 req_info->svc_path = g_strdup(svc_info->serv_path);
1045 req_info->request_id = req_id;
1046 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1047 req_info->offset = offset;
1048 req_info->context = invocation;
1050 /* Append request info in list of requests for the particular connection */
1051 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1053 /* Send HAL event */
1054 memset(&ev, 0, sizeof(ev));
1055 ev.conn_id = conn_info->connection_id;
1056 ev.trans_id = req_id;
1057 ev.att_handle = desc_hdl;
1059 ev.is_long = false; /* TODO*/
1061 /* Convert address to hex */
1062 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1064 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1066 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1068 GVariant *var = NULL;
1072 gboolean response_needed = FALSE;
1073 struct hal_ev_gatt_server_write_req ev;
1077 struct gatt_service_info *svc_info = NULL;
1078 struct gatt_client_info_t *conn_info = NULL;
1079 struct gatt_req_info *req_info = NULL;
1081 memset(&ev, 0, sizeof(ev));
1084 DBG("Application path = %s", object_path);
1085 DBG("Sender = %s", sender);
1087 g_variant_get(parameters, "(&suqb@ay)",
1088 &addr, &req_id, &offset, &response_needed, &var);
1089 DBG("Request id = %u, Offset = %u", req_id, offset);
1091 /* Check if device is already in connected list */
1092 conn_info = __bt_find_remote_gatt_client_info(addr);
1094 svc_info = __bt_gatt_find_gatt_service_from_desc(object_path, &desc_hdl);
1096 if (conn_info == NULL || svc_info == NULL || event_cb == NULL) {
1097 g_variant_unref(var);
1098 if (response_needed)
1099 g_dbus_method_invocation_return_value(invocation, NULL);
1101 g_object_unref(invocation);
1105 len = g_variant_get_size(var);
1106 if (len > 0 && len < 600) {
1108 data = (char *)g_variant_get_data(var);
1109 memcpy(ev.value, data, len);
1112 if (response_needed) {
1113 /* Store request information */
1114 req_info = g_new0(struct gatt_req_info, 1);
1115 req_info->attr_path = g_strdup(object_path);
1116 req_info->svc_path = g_strdup(svc_info->serv_path);
1117 req_info->request_id = req_id;
1118 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1119 req_info->offset = offset;
1120 req_info->context = invocation;
1122 /* Append request info in list of requests for the particular connection */
1123 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1125 g_object_unref(invocation);
1128 /* Send HAL event */
1129 ev.conn_id = conn_info->connection_id;
1130 ev.trans_id = req_id;
1131 ev.att_handle = desc_hdl;
1133 ev.need_rsp = response_needed;
1136 /* Convert address to hex */
1137 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1139 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1141 g_variant_unref(var);
1146 static void __bt_gatt_char_method_call(GDBusConnection *connection,
1147 const gchar *sender,
1148 const gchar *object_path,
1149 const gchar *interface_name,
1150 const gchar *method_name,
1151 GVariant *parameters,
1152 GDBusMethodInvocation *invocation,
1155 if (g_strcmp0(method_name, "ReadValue") == 0) {
1159 struct hal_ev_gatt_server_read_req ev;
1162 struct gatt_req_info *req_info = NULL;
1163 struct gatt_client_info_t *conn_info = NULL;
1164 struct gatt_service_info *svc_info = NULL;
1166 g_variant_get(parameters, "(&suq)",
1167 &addr, &req_id, &offset);
1169 DBG("ReadValue : req id %u, offset %u, path %s, sender %s, %s", req_id, offset, object_path, sender, addr);
1171 /* Check if device is already in connected list */
1172 conn_info = __bt_find_remote_gatt_client_info(addr);
1174 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1176 if (svc_info == NULL || conn_info == NULL) {
1177 ERR("Invalid information %p, %p", svc_info, conn_info);
1178 g_dbus_method_invocation_return_value(invocation, NULL);
1183 ERR("GATT callback NOT registered");
1184 g_dbus_method_invocation_return_value(invocation, NULL);
1188 /* Store requets information */
1189 req_info = g_new0(struct gatt_req_info, 1);
1190 req_info->attr_path = g_strdup(object_path);
1191 req_info->svc_path = g_strdup(svc_info->serv_path);
1192 req_info->request_id = req_id;
1193 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_READ;
1194 req_info->offset = offset;
1195 req_info->context = invocation;
1197 /* Append request info in list of requests for the particular connection */
1198 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1200 /* Send HAL event */
1201 memset(&ev, 0, sizeof(ev));
1202 ev.conn_id = conn_info->connection_id;
1203 ev.trans_id = req_id;
1204 ev.att_handle = char_hdl;
1206 ev.is_long = false; /* TODO*/
1208 /* Convert address to hex */
1209 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1210 event_cb(HAL_EV_GATT_READ_REQUESTED, (void *)&ev, sizeof(ev));
1212 } else if (g_strcmp0(method_name, "WriteValue") == 0) {
1213 GVariant *var = NULL;
1217 gboolean response_needed = FALSE;
1218 struct hal_ev_gatt_server_write_req ev;
1222 struct gatt_service_info *svc_info = NULL;
1223 struct gatt_req_info *req_info = NULL;
1224 struct gatt_client_info_t *conn_info = NULL;
1226 memset(&ev, 0, sizeof(ev));
1228 DBG("WriteValue : Application path %s, sender %s", object_path, sender);
1230 g_variant_get(parameters, "(&suqb@ay)",
1231 &addr, &req_id, &offset, &response_needed, &var);
1232 DBG("Request id = %u, Offset = %u", req_id, offset);
1234 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1236 /* Check if device is already in connected list */
1237 conn_info = __bt_find_remote_gatt_client_info(addr);
1239 if (svc_info == NULL || conn_info == NULL || event_cb == NULL) {
1240 g_variant_unref(var);
1241 if (response_needed)
1242 g_dbus_method_invocation_return_value(invocation, NULL);
1244 g_object_unref(invocation);
1248 len = g_variant_get_size(var);
1249 if (len > 0 && len < 600) {
1251 data = (char *)g_variant_get_data(var);
1252 memcpy(ev.value, data, len);
1256 if (response_needed) {
1257 /* Store requets information */
1258 req_info = g_new0(struct gatt_req_info, 1);
1259 req_info->attr_path = g_strdup(object_path);
1260 req_info->svc_path = g_strdup(svc_info->serv_path);
1261 req_info->request_id = req_id;
1262 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_WRITE;
1263 req_info->offset = offset;
1264 req_info->context = invocation;
1266 /* Append request info in list of requests for the particular connection */
1267 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1270 g_object_unref(invocation);
1273 /* Send HAL event */
1274 ev.conn_id = conn_info->connection_id;
1275 ev.trans_id = req_id;
1276 ev.att_handle = char_hdl;
1278 ev.need_rsp = response_needed;
1281 /* Convert address to hex */
1282 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1284 event_cb(HAL_EV_GATT_WRITE_REQUESTED, (void *)&ev, sizeof(ev));
1286 g_variant_unref(var);
1289 } else if (g_strcmp0(method_name, "StartNotify") == 0) {
1292 struct gatt_service_info *svc_info = NULL;
1293 struct hal_ev_gatt_server_notifcation_change ev;
1296 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1297 if (svc_info == NULL || event_cb == NULL)
1300 /* Send HAL event */
1301 memset(&ev, 0, sizeof(ev));
1302 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1303 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1304 ev.att_handle = char_hdl;
1307 /* Convert address to hex */
1308 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez Does not provide address of GATT client */
1310 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1313 } else if (g_strcmp0(method_name, "StopNotify") == 0) {
1316 struct gatt_service_info *svc_info = NULL;
1317 struct hal_ev_gatt_server_notifcation_change ev;
1320 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1321 if (svc_info == NULL || event_cb == NULL)
1324 /* Send HAL event */
1325 memset(&ev, 0, sizeof(ev));
1326 ev.conn_id = -1; /*TODO Bluez does not provide remote GATT client address, so no conn_id */
1327 ev.trans_id = -1; /*TODO Bluez does not provide request id or transacion ID */
1328 ev.att_handle = char_hdl;
1331 /* Convert address to hex */
1332 _bt_hal_convert_addr_string_to_type(ev.bdaddr, "00:00:00:00:00"); /* TODO Bluez DOes not provide address of GATT client */
1334 event_cb(HAL_EV_GATT_NOTIFICATION_CHANGE, (void *)&ev, sizeof(ev));
1337 } else if (g_strcmp0(method_name, "IndicateConfirm") == 0) {
1339 gboolean complete = FALSE;
1342 struct gatt_service_info *svc_info = NULL;
1343 struct gatt_client_info_t *conn_info = NULL;
1345 struct hal_ev_gatt_server_indicate_cfm ev;
1347 DBG("IndicateConfirm : Application path %s, sender %s", object_path, sender);
1349 g_variant_get(parameters, "(&sb)", &addr, &complete);
1350 DBG("Remote Device address number = %s", addr);
1351 DBG("Is Indicate confirmation for last device [%d]", complete);
1353 /* Check if device is already in connected list */
1354 conn_info = __bt_find_remote_gatt_client_info(addr);
1356 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1358 if (svc_info == NULL || conn_info == NULL
1359 || event_cb == NULL) {
1363 /* Send HAL event */
1364 memset(&ev, 0, sizeof(ev));
1365 ev.conn_id = conn_info->connection_id;
1366 ev.trans_id = -1; /*TODO Bluez does not provide Transaction ID or request ID */
1367 ev.att_handle = char_hdl;
1369 /* Convert address to hex */
1370 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1372 event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev));
1373 } else if (g_strcmp0(method_name, "AcquireWrite") == 0) {
1377 struct hal_ev_gatt_server_acquire_write_res ev;
1378 struct gatt_service_info *svc_info = NULL;
1379 struct gatt_req_info *req_info = NULL;
1380 struct gatt_client_info_t *conn_info = NULL;
1381 char * dev_path = NULL;
1383 char addr[BT_HAL_ADDRESS_STRING_SIZE];
1385 DBG("AcquireWrite : Application path %s, sender %s", object_path, sender);
1388 g_variant_get(parameters, "(a{sv})", &iter);
1390 GVariant* value = NULL;
1391 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1392 if (g_strcmp0(key, "MTU") == 0)
1393 g_variant_get(value, "i", &mtu);
1394 else if (g_strcmp0(key, "link") == 0)
1395 g_variant_get(value, "s", &link);
1396 else if (g_strcmp0(key, "device") == 0)
1397 g_variant_get(value, "o", &dev_path);
1400 DBG(" path %s LINK = %s, MTU = %u", addr, link, mtu);
1402 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1404 _bt_hal_convert_device_path_to_address(dev_path, addr);
1406 DBG("remote address %s", addr);
1408 /* Check if device is already in connected list */
1409 conn_info = __bt_find_remote_gatt_client_info(addr);
1411 if (conn_info == NULL) {
1412 ERR("Cleint info not found\n");
1416 if (svc_info == NULL) {
1417 ERR("svc_info info not found\n");
1421 /* Store requets information */
1422 req_info = g_new0(struct gatt_req_info, 1);
1423 req_info->attr_path = g_strdup(object_path);
1424 req_info->svc_path = g_strdup(svc_info->serv_path);
1425 req_info->request_id = conn_info->connection_id;
1426 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE;
1427 req_info->offset = mtu;
1428 req_info->context = invocation;
1430 /* Append request info in list of requests for the particular connection */
1431 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1433 /* Send HAL event */
1434 memset(&ev, 0, sizeof(ev));
1435 ev.conn_id = conn_info->connection_id;
1436 ev.char_handl = char_hdl;
1438 ev.trans_id = conn_info->connection_id;
1439 _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr);
1440 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev));
1442 } else if (g_strcmp0(method_name, "AcquireNotify") == 0) {
1446 struct hal_ev_gatt_server_acquire_notify ev;
1447 struct gatt_service_info *svc_info = NULL;
1448 struct gatt_client_info_t *conn_info = NULL;
1449 struct gatt_req_info *req_info = NULL;
1451 DBG("AcquireNotify : Application path %s, sender %s", object_path, sender);
1454 g_variant_get(parameters, "(a{sv})", &iter);
1456 GVariant* value = NULL;
1457 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
1458 if (g_strcmp0(key, "MTU") == 0)
1459 g_variant_get(value, "q", &mtu);
1462 DBG("MTU = %u", mtu);
1464 svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl);
1466 if (svc_info == NULL) {
1467 ERR("svc_info info not found\n");
1471 /* Store requets information */
1472 req_info = g_new0(struct gatt_req_info, 1);
1473 req_info->attr_path = g_strdup(object_path);
1474 req_info->svc_path = g_strdup(svc_info->serv_path);
1475 req_info->request_id = 33;
1476 req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY;
1477 req_info->offset = mtu;
1478 req_info->context = invocation;
1480 conn_info = g_new0(struct gatt_client_info_t, 1);
1481 conn_info->addr = g_strdup(object_path);
1482 INFO("AcquireNotify : Added GATT client path[%s]", conn_info->addr);
1483 conn_info->connection_id = 33;
1484 conn_info->instance_id = 33;
1485 /* Append request info in list of requests for the particular connection */
1486 conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info);
1487 gatt_client_info_list = g_slist_append(gatt_client_info_list, conn_info);
1489 /* Send HAL event */
1490 memset(&ev, 0, sizeof(ev));
1492 ev.char_handl = char_hdl;
1496 event_cb(HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES, (void *)&ev, sizeof(ev));
1501 g_dbus_method_invocation_return_value(invocation, NULL);
1504 static gboolean __bt_hal_gatt_emit_interface_removed(gchar *object_path, gchar *interface)
1507 GError *error = NULL;
1508 GVariantBuilder *array_builder;
1510 array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
1511 g_variant_builder_init(array_builder, G_VARIANT_TYPE("as"));
1512 g_variant_builder_add(array_builder, "s", interface);
1514 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
1515 "org.freedesktop.Dbus.Objectmanager",
1516 "InterfacesRemoved",
1517 g_variant_new("(oas)",
1518 object_path, array_builder),
1522 if (error != NULL) {
1523 /* dbus gives error cause */
1524 ERR("d-bus api failure: errcode[%x], message[%s]",
1525 error->code, error->message);
1526 g_clear_error(&error);
1529 g_variant_builder_unref(array_builder);
1534 static void __bt_hal_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
1541 g_free(desc_info->desc_path);
1542 g_free(desc_info->desc_uuid);
1543 g_free(desc_info->desc_value);
1545 for (i = 0; i < desc_info->flags_length; i++)
1546 g_free(desc_info->desc_flags[i]);
1551 static void __bt_hal_gatt_free_characteristic_info(struct gatt_char_info *char_info)
1558 g_free(char_info->char_path);
1559 g_free(char_info->char_uuid);
1560 g_free(char_info->char_value);
1562 for (i = 0; i < char_info->flags_length; i++)
1563 g_free(char_info->char_flags[i]);
1569 static void __bt_hal_gatt_free_service_info(struct gatt_service_info *svc_info)
1574 g_free(svc_info->serv_path);
1575 g_free(svc_info->service_uuid);
1579 static const GDBusInterfaceVTable desc_interface_vtable = {
1580 __bt_gatt_desc_method_call,
1585 static const GDBusInterfaceVTable char_interface_vtable = {
1586 __bt_gatt_char_method_call,
1591 static const GDBusInterfaceVTable serv_interface_vtable = {
1597 static const GDBusInterfaceVTable manager_interface_vtable = {
1598 __bt_gatt_manager_method_call,
1604 static GDBusNodeInfo *__bt_gatt_create_method_node_info(
1605 const gchar *introspection_data)
1608 GDBusNodeInfo *node_info = NULL;
1610 if (introspection_data == NULL)
1614 DBG("Create new node info");
1615 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
1618 ERR("Unable to create node: %s", err->message);
1619 g_clear_error(&err);
1626 /* To send stack event to hal-av handler */
1627 void _bt_hal_register_gatt_server_handler_cb(handle_stack_msg cb)
1632 void _bt_hal_unregister_gatt_server_handler_cb(void)
1637 static gboolean __bt_hal_gatt_desc_added_cb(gpointer user_data)
1639 struct hal_ev_gatt_desc_added ev;
1640 hal_gatt_desc_added *data = (hal_gatt_desc_added*) user_data;
1642 /* Prepare to GATT characteristic added event */
1643 memset(&ev, 0, sizeof(ev));
1644 ev.status = BT_STATUS_SUCCESS;
1645 ev.server_instance = data->instance_data;
1646 memcpy(ev.desc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1647 ev.service_handle = data->srvc_hdl;
1648 ev.desc_handle = data->desc_hdl;
1651 ERR("GATT Descriptor Added callback registered");
1653 DBG("GATT Descriptor Added: server if [%d] Service handle [%d] Descriptor Handle [%d]",
1654 data->instance_data, data->srvc_hdl, data->desc_hdl);
1656 event_cb(HAL_EV_GATT_DESC_ADDED, (void *)&ev, sizeof(ev));
1663 static gboolean __bt_hal_gatt_char_added_cb(gpointer user_data)
1665 struct hal_ev_gatt_char_added ev;
1666 hal_gatt_char_added *data = (hal_gatt_char_added*) user_data;
1668 /* Prepare to GATT characteristic added event */
1669 memset(&ev, 0, sizeof(ev));
1670 ev.status = BT_STATUS_SUCCESS;
1671 ev.server_instance = data->instance_data;
1672 memcpy(ev.char_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1673 ev.service_handle = data->srvc_hdl;
1674 ev.char_handle = data->char_hdl;
1677 ERR("GATT Characteristic Added callback registered");
1679 DBG("GATT Characteristic Added: server if [%d] Service handle [%d] Characteristic handle [%d]",
1680 data->instance_data, data->srvc_hdl, data->char_hdl);
1682 event_cb(HAL_EV_GATT_CHAR_ADDED, (void *)&ev, sizeof(ev));
1689 static gboolean __bt_hal_gatt_service_added_cb(gpointer user_data)
1691 struct hal_ev_gatt_service_added ev;
1692 hal_gatt_service_added *data = (hal_gatt_service_added*) user_data;
1694 /* Prepare to GATT Service added event */
1695 memset(&ev, 0, sizeof(ev));
1696 ev.status = BT_STATUS_SUCCESS;
1697 ev.server_instance = data->instance_data;
1698 memcpy(ev.svc_uuid, data->uuid.uu, sizeof(data->uuid.uu));
1699 ev.service_handle = data->srvc_hdl;
1700 ev.is_primary = data->is_primary;
1703 ERR("GATT Service Added callback registered");
1705 DBG("GATT Service Added: server if [%d] Service handle [%d]",
1706 data->instance_data, data->srvc_hdl);
1707 event_cb(HAL_EV_GATT_SERVICE_ADDED, (void *)&ev, sizeof(ev));
1714 static gboolean __bt_hal_gatt_service_started_cb(gpointer user_data)
1716 struct hal_ev_gatt_service_started ev;
1717 hal_gatt_service_started *data = (hal_gatt_service_started*) user_data;
1719 /* Prepare to GATT Service added event */
1720 memset(&ev, 0, sizeof(ev));
1721 ev.status = BT_STATUS_SUCCESS;
1722 ev.server_instance = data->instance_data;
1723 ev.service_handle = data->srvc_hdl;
1726 ERR("GATT Service Started callback registered");
1728 DBG("GATT Service Started: server if [%d] Service handle [%d]",
1729 data->instance_data, data->srvc_hdl);
1730 event_cb(HAL_EV_GATT_SERVICE_STARTED, (void *)&ev, sizeof(ev));
1737 static gboolean __bt_hal_gatt_service_deleted_cb(gpointer user_data)
1739 struct hal_ev_gatt_service_deleted ev;
1740 hal_gatt_service_deleted *data = (hal_gatt_service_deleted*) user_data;
1742 /* Prepare to GATT Service added event */
1743 memset(&ev, 0, sizeof(ev));
1744 ev.status = BT_STATUS_SUCCESS;
1745 ev.server_instance = data->instance_data;
1746 ev.service_handle = data->srvc_hdl;
1749 ERR("GATT Service Deleted callback registered");
1751 DBG("GATT Service Deleted: server if [%d] Service handle [%d]",
1752 data->instance_data, data->srvc_hdl);
1753 event_cb(HAL_EV_GATT_SERVICE_DELETED, (void *)&ev, sizeof(ev));
1760 static gboolean __bt_hal_register_slot_id_cb(gpointer user_data)
1762 struct hal_ev_server_instance_registered ev;
1763 hal_register_server_data *data = (hal_register_server_data*) user_data;
1765 /* Prepare to send AV connecting event */
1766 memset(&ev, 0, sizeof(ev));
1767 ev.status = BT_STATUS_SUCCESS;
1768 ev.server_instance = data->instance_data;
1769 memcpy(ev.app_uuid, data->uuid.uu, sizeof(ev.app_uuid));
1772 ERR("GATT Register Server Instance Callback not registered");
1774 DBG("Server Instance is registered!! server if [%d]", data->instance_data);
1775 event_cb(HAL_EV_SERVER_INSTANCE_INITIALIZED, (void *)&ev, sizeof(ev));
1783 static int bt_hal_gatts_get_gatt_server_instance()
1788 struct hal_gatts_server_register_info_t *info = NULL;
1790 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1791 info = (struct hal_gatts_server_register_info_t *)l->data;
1796 return info->server_if;
1802 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_from_uuid(bt_uuid_t *app_uuid)
1807 struct hal_gatts_server_register_info_t *info = NULL;
1809 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1810 info = (struct hal_gatts_server_register_info_t *)l->data;
1815 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
1816 DBG("gatt server register found");
1824 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info(int server_if)
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 (info->server_if == server_if) {
1843 static struct hal_gatts_server_register_info_t * bt_hal_gatts_find_server_register_info_by_slot_id(int adv_slot_id)
1848 struct hal_gatts_server_register_info_t *info = NULL;
1850 for (l = hal_gatts_server_register_list; l != NULL; l = g_slist_next(l)) {
1851 info = (struct hal_gatts_server_register_info_t *)l->data;
1856 if (info->adv_slot_id == adv_slot_id) {
1857 DBG("gatt server register found");
1865 static struct hal_gatts_server_register_info_t * bt_hal_gatts_add_server_app(bt_uuid_t *app_uuid)
1867 struct hal_gatts_server_register_info_t * server_register_info = NULL;
1868 int instance_id = 0;
1870 server_register_info = bt_hal_gatts_find_server_register_info_from_uuid(app_uuid);
1871 if (server_register_info != NULL) {
1872 DBG("gatt server is already registered");
1873 return server_register_info;
1876 instance_id = __bt_hal_gatt_assign_id();
1877 if (instance_id == -1) {
1878 ERR("Fail to allocate the server if");
1882 server_register_info = g_malloc0(sizeof(struct hal_gatts_server_register_info_t));
1883 server_register_info->server_if = instance_id;
1885 DBG("Adding the gatt server app. server_if:[%d]", server_register_info->server_if);
1887 server_register_info->adv_slot_id = -1;
1888 memcpy(&server_register_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
1889 hal_gatts_server_register_list = g_slist_append(hal_gatts_server_register_list, server_register_info);
1891 return server_register_info;
1894 static bt_status_t gatt_server_register_app(bt_uuid_t *uuid)
1896 CHECK_BTGATT_INIT();
1897 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1899 DBG("Register server instance request");
1900 server_register_info = bt_hal_gatts_add_server_app(uuid);
1901 if (server_register_info == NULL) {
1902 ERR("Fail to register the server app");
1903 return BT_STATUS_FAIL;
1906 hal_register_server_data *user_data = g_malloc0(sizeof(hal_register_server_data));
1907 user_data->instance_data = server_register_info->server_if;
1910 * As we need to provide async callback to user from HAL, simply schedule a
1911 * callback method which will carry actual result
1913 memcpy(user_data->uuid.uu, uuid->uu, sizeof(bt_uuid_t));
1914 g_idle_add(__bt_hal_register_slot_id_cb, (gpointer)user_data);
1916 /* If available, then return success, else return error */
1917 return BT_STATUS_SUCCESS;
1920 static void _bt_hal_remove_gatt_server_from_list(int server_if)
1923 struct gatt_server_app *info = NULL;
1925 for (l = gatt_server_apps; l != NULL;) {
1926 info = (struct gatt_server_app*)l->data;
1927 l = g_slist_next(l);
1930 if (info->slot == server_if) {
1931 INFO("Found Matching GATT Server in List path[%s] slot [%d]",
1932 info->app_path, info->slot);
1934 /* Only if all services are deleted from the GATT Server, then only Unregister it.
1935 Reason: it is possible, GATT Server app oly wants to disable multi advertising
1936 In above case, only advertising block will be deallocated, Gatt Server will remain
1938 if (info->services == NULL) {
1939 gatt_server_apps = g_slist_remove(gatt_server_apps, (gpointer)info);
1940 INFO("Total gatt server apps still existing after removing above is [%d]",
1941 g_slist_length(gatt_server_apps));
1943 /* DBUS Unregister only for current app */
1944 __bt_hal_gatt_deinit(info->app_path);
1946 g_free(info->app_path);
1950 INFO("GATT Server still has services count[%d] in it..Can not remove it!!!",
1951 g_slist_length(info->services));
1957 static bt_status_t gatt_server_unregister_app(int server_if)
1959 CHECK_BTGATT_INIT();
1960 DBG("Un-Register server instance request [%d]", server_if);
1961 struct hal_gatts_server_register_info_t *server_register_info = NULL;
1964 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
1965 if (server_register_info == NULL) {
1966 DBG("gatt server is not registered");
1967 return BT_STATUS_SUCCESS;
1970 /* remove the gatt server register info from the register list */
1971 hal_gatts_server_register_list = g_slist_remove(hal_gatts_server_register_list, server_register_info);
1972 g_free(server_register_info);
1974 __bt_hal_gatt_delete_id(server_if);
1976 /* If server_if belongs to a GATT Server, then delete the GATT server from List */
1977 _bt_hal_remove_gatt_server_from_list(server_if);
1978 return BT_STATUS_SUCCESS;
1981 static bt_status_t gatt_server_open(int server_if, const bt_bdaddr_t *bd_addr, bool is_direct)
1983 CHECK_BTGATT_INIT();
1984 return BT_STATUS_SUCCESS;
1987 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
1990 GError *g_error = NULL;
1991 GVariant *reply = NULL;
1995 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
1996 g_object_unref(proxy);
1997 if (reply == NULL) {
1998 ERR("Disconnect LE Dbus Call Error");
2000 ERR("Error: %s\n", g_error->message);
2001 g_clear_error(&g_error);
2004 g_variant_unref(reply);
2008 static bt_status_t gatt_server_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
2010 CHECK_BTGATT_INIT();
2012 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2014 GDBusProxy *device_proxy;
2015 GDBusConnection *g_conn;
2016 struct gatt_client_info_t *conn_info = NULL;
2020 if (NULL == bd_addr) {
2021 ERR("bd_addr is NULL");
2022 return BT_STATUS_PARM_INVALID;
2025 /* GDBUS Connection Info validate */
2026 g_conn = _bt_hal_get_system_gconn();
2027 if (g_conn == NULL) {
2028 ERR("Could not get System DBUS Connection");
2029 return BT_STATUS_FAIL;
2032 /* Connection Info validate */
2033 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
2034 if (conn_info == NULL) {
2035 ERR("No Connection Inforamtion!!!");
2036 return BT_STATUS_FAIL;
2039 _bt_hal_convert_addr_type_to_string(device_address,
2040 (unsigned char *)bd_addr->address);
2042 //check if connection has the same device address
2043 if (g_strcmp0(conn_info->addr, device_address) != 0) {
2044 ERR("device address [%s] does not match", device_address);
2045 return BT_STATUS_FAIL;
2048 device_path = _bt_hal_get_device_object_path(conn_info->addr);
2049 if (device_path == NULL) {
2050 ERR("device_path is NULL");
2051 return BT_STATUS_PARM_INVALID;
2054 device_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
2055 NULL, BT_HAL_BLUEZ_NAME,
2056 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2059 g_free(device_path);
2060 if (device_proxy == NULL)
2061 return BT_STATUS_FAIL;
2063 INFO("Disconnect LE [%s]", device_address);
2065 g_dbus_proxy_call(device_proxy, "DisconnectLE",
2067 G_DBUS_CALL_FLAGS_NONE,
2068 BT_HAL_MAX_DBUS_TIMEOUT,
2070 (GAsyncReadyCallback)__le_disconnection_req_cb, conn_info);
2073 return BT_STATUS_SUCCESS;
2076 static char* __bt_hal_convert_uuid_to_string(bt_uuid_t *srvc_id)
2081 uuid = btuuid2str(srvc_id->uu);
2082 DBG("Original UUID [%s]", uuid);
2084 if (_bt_hal_uuid_is_standard(srvc_id) == TRUE) {
2085 /* Extract Standard UUID string */
2086 memcpy(uuid_buf, &uuid[4], 4);
2088 DBG("Converted string [%s]", uuid_buf);
2089 return g_strdup(uuid_buf);
2091 return strdup(uuid);
2094 static int __bt_hal_add_service_to_dbus(char *app_path, int slot, btgatt_srvc_id_t *srvc_id)
2097 /* For GATT service specific */
2098 GDBusNodeInfo *node_info;
2101 struct gatt_service_info *serv_info = NULL;
2102 GVariantBuilder *builder = NULL;
2103 GVariantBuilder *builder1 = NULL;
2104 GVariantBuilder *inner_builder = NULL;
2105 gboolean svc_primary = TRUE;
2106 GError *error = NULL;
2107 hal_gatt_service_added *user_data = NULL;
2108 DBG("Service add to DBUS slot [%d]", slot);
2110 node_info = __bt_gatt_create_method_node_info(
2111 service_introspection_xml);
2113 if (node_info == NULL)
2114 return BT_STATUS_FAIL;
2116 DBG("Add new GATT Service: Current GATT Service handle [%d]", gatt_service_handle);
2117 path = g_strdup_printf("%s"GATT_SERV_OBJECT_PATH"%d", app_path, ++gatt_service_handle);
2118 DBG("gatt service path is [%s]", path);
2120 object_id = g_dbus_connection_register_object(g_conn, path,
2121 node_info->interfaces[0],
2122 &serv_interface_vtable,
2123 NULL, NULL, &error);
2125 if (object_id == 0) {
2126 ERR("failed to register: %s", error->message);
2127 g_error_free(error);
2129 return BT_STATUS_FAIL;
2131 /* Add object_id/gatt service information; it's required at the time of
2132 * service unregister and Getmanagedobjects
2134 serv_info = g_new0(struct gatt_service_info, 1);
2136 serv_info->serv_path = g_strdup(path);
2137 serv_info->serv_id = object_id;
2138 serv_info->service_uuid = __bt_hal_convert_uuid_to_string(&srvc_id->id.uuid);//g_strdup(btuuid2str(srvc_id->id.uuid.uu));
2139 serv_info->is_svc_registered = FALSE;
2140 serv_info->is_svc_primary = svc_primary;
2141 DBG("Service Handle to be added is [%d]", gatt_service_handle);
2142 serv_info->service_handle = gatt_service_handle;
2144 /* Update service in GATT Server service List */
2145 gatt_services = g_slist_append(gatt_services, serv_info);
2147 /* emit interfacesadded signal here for service path */
2148 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2149 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2151 g_variant_builder_add(inner_builder, "{sv}",
2152 "UUID", g_variant_new_string(btuuid2str(srvc_id->id.uuid.uu)));
2154 g_variant_builder_add(inner_builder, "{sv}",
2155 "Primary", g_variant_new_boolean(svc_primary));
2157 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2159 g_variant_builder_add(inner_builder, "{sv}", "Characteristics",
2160 g_variant_new("ao", builder1));
2162 g_variant_builder_add(builder, "{sa{sv}}",
2163 GATT_SERV_INTERFACE, inner_builder);
2165 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2166 "org.freedesktop.Dbus.ObjectManager",
2168 g_variant_new("(oa{sa{sv}})",
2173 /* dbus gives error cause */
2174 ERR("d-bus api failure: errcode[%x], message[%s]",
2175 error->code, error->message);
2176 g_clear_error(&error);
2180 /* Send Service handle to application */
2181 user_data = g_malloc0(sizeof(hal_gatt_service_added));
2182 user_data->srvc_hdl = serv_info->service_handle;
2183 user_data->instance_data = slot;
2184 memcpy(user_data->uuid.uu, srvc_id->id.uuid.uu, sizeof(srvc_id->id.uuid.uu));
2185 g_idle_add(__bt_hal_gatt_service_added_cb, (gpointer)user_data);
2187 /* Save newly created service in GATT Server's service list */
2188 _bt_hal_update_gatt_service_in_gatt_server(slot, serv_info);
2192 g_variant_builder_unref(inner_builder);
2193 g_variant_builder_unref(builder);
2194 g_variant_builder_unref(builder1);
2195 return BT_STATUS_SUCCESS;
2198 static void __bt_hal_unregister_application_cb(GObject *object, GAsyncResult *res,
2201 char *app_path = (char*)user_data;
2202 INFO("UnregisterApplication is completed app [%s]", app_path);
2203 GError *error = NULL;
2204 GVariant *result = NULL;
2207 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2209 if (result == NULL) {
2210 /* dBUS-RPC is failed */
2211 ERR("Dbus-RPC is failed\n");
2213 if (error != NULL) {
2214 /* dBUS gives error cause */
2215 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2216 error->code, error->message);
2217 g_clear_error(&error);
2220 g_variant_unref(result);
2225 static void __bt_hal_gatt_deinit(char *app_path)
2227 GDBusProxy *proxy = NULL;
2231 /* Step1: Remove requested App */
2232 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2233 "/org/bluez/hci0", "org.bluez.GattManager1");
2238 INFO("UnregisterApplication : path [%s]", app_path);
2240 /* Async Call to Unregister Service */
2241 data = g_strdup(app_path);
2242 g_dbus_proxy_call(proxy,
2243 "UnregisterApplication",
2244 g_variant_new("(o)",
2246 G_DBUS_CALL_FLAGS_NONE, -1,
2248 (GAsyncReadyCallback)__bt_hal_unregister_application_cb,
2251 /* If requested app is last GATT Server app, then clean all resources */
2252 if (gatt_server_apps == NULL) {
2253 INFO("All GATT servers are removed, clean all DBUS resources");
2255 /* unregister the exported interface for object manager */
2256 g_dbus_connection_unregister_object(g_conn, manager_id);
2258 g_bus_unown_name(owner_id);
2261 g_object_unref(manager_gproxy);
2262 manager_gproxy = NULL;
2268 static int __bt_hal_gatt_init(void)
2272 /* Only once for ALL GATT Servers */
2273 if (owner_id == 0) {
2277 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
2280 ERR("Unable to connect to gdbus: %s", err->message);
2281 g_clear_error(&err);
2283 return BT_STATUS_FAIL;
2286 name = g_strdup_printf("%s.p%d", BT_GATT_SERVICE_NAME, getpid());
2287 INFO("well-known name: %s", name);
2289 owner_id = g_bus_own_name_on_connection(g_conn, name,
2290 G_BUS_NAME_OWNER_FLAGS_NONE,
2291 NULL, NULL, NULL, NULL);
2293 INFO("Owner ID [%d]", owner_id);
2295 /* Only once for ALL GATT Servers */
2296 if (manager_node_info == NULL) {
2297 /* Register ObjectManager interface */
2298 manager_node_info = __bt_gatt_create_method_node_info(
2299 manager_introspection_xml);
2301 if (manager_node_info == NULL) {
2302 ERR("failed to get node info");
2303 return BT_STATUS_FAIL;
2308 return BT_STATUS_SUCCESS;
2311 static void _bt_hal_is_gatt_server_initialzed(int slot, char **app_path)
2315 for (l = gatt_server_apps; l; l = g_slist_next(l)) {
2316 struct gatt_server_app *app = (struct gatt_server_app *)l->data;
2317 if (app->slot == slot) {
2318 INFO("GATT Server app found app path [%s] instance [%d]",
2319 app->app_path, app->slot);
2320 *app_path = app->app_path;
2324 /* GATT Server not found */
2328 static void _bt_hal_update_gatt_server_path(int slot, char *app_path)
2330 if (app_path == NULL)
2333 struct gatt_server_app *app = g_malloc0(sizeof(struct gatt_server_app));
2334 app->app_path = g_strdup(app_path);
2336 gatt_server_apps = g_slist_append(gatt_server_apps, app);
2337 INFO("GATT Server: Path [%s] Slot [%d]-> Updated", app_path, slot);
2342 static bt_status_t gatt_server_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
2345 CHECK_BTGATT_INIT();
2346 char *app_path = NULL;
2347 GError *error = NULL;
2350 int result = BT_STATUS_SUCCESS;
2352 DBG("GATT Server Add service request: Instance ID[%d] Is Primary [%d] UUID [%s]",
2353 server_if, srvc_id->is_primary, btuuid2str(srvc_id->id.uuid.uu));
2355 /* Check if this GATT server Application is already registered with DBUS */
2356 _bt_hal_is_gatt_server_initialzed(server_if, &app_path);
2358 if (app_path != NULL) {
2359 DBG("GATT server path is already defined [%s]", app_path);
2360 return __bt_hal_add_service_to_dbus(app_path, server_if, srvc_id);
2362 DBG("GATT server application path for instance [%d] is not defined yet", server_if);
2363 result = __bt_hal_gatt_init();
2364 if (result != BT_STATUS_SUCCESS)
2367 /* Only once for each GATT Server */
2368 app_path = g_strdup_printf("/com/%d", server_if);
2370 app_id = g_malloc0(sizeof(int));
2371 *app_id = server_if;
2373 manager_id = g_dbus_connection_register_object(g_conn, app_path,
2374 manager_node_info->interfaces[0],
2375 &manager_interface_vtable,
2376 (gpointer)app_id, NULL, &error);
2378 if (manager_id == 0) {
2379 ERR("failed to register: %s", error->message);
2380 g_error_free(error);
2383 INFO("manager_id [%d]", manager_id);
2385 /* For current GATT Server, app_path is created, save it in Table */
2386 _bt_hal_update_gatt_server_path(server_if, app_path);
2388 /* Add GATT Service to DBUS */
2389 if (__bt_hal_add_service_to_dbus(app_path, server_if, srvc_id) != BT_STATUS_SUCCESS)
2395 INFO("Successfully added service");
2396 return BT_STATUS_SUCCESS;
2403 INFO("Service addition failed!!");
2404 return BT_STATUS_FAIL;
2407 static bt_status_t gatt_server_add_included_service(int server_if, int service_handle,
2408 int included_handle)
2410 CHECK_BTGATT_INIT();
2411 return BT_STATUS_SUCCESS;
2415 static gboolean __bt_is_service_last_in_server_list(int instance, int service_handle)
2418 GSList *gatt_services = NULL;
2420 struct gatt_service_info *info = NULL;
2422 gatt_services = _bt_get_service_list_from_server(instance);
2424 len = g_slist_length(gatt_services);
2425 l = g_slist_nth(gatt_services, len -1);
2431 if (info->service_handle == service_handle)
2436 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(int instance,
2440 GSList *gatt_services = NULL;
2441 INFO("Find Service: svc handle [%d] from GATT Server slot[%d]", service_handle, instance);
2443 gatt_services = _bt_get_service_list_from_server(instance);
2445 for (l = gatt_services; l != NULL; l = g_slist_next(l)) {
2446 struct gatt_service_info *info = l->data;
2447 INFO("Got one service with handle [%d]", info->service_handle);
2448 if (info->service_handle == service_handle)
2451 ERR("Gatt service with handle [%d] not found", service_handle);
2455 static bt_status_t gatt_server_add_characteristic(int slot, int service_handle,
2456 bt_uuid_t *uuid, int properties,
2460 GError *error = NULL;
2462 GDBusNodeInfo *node_info;
2464 GVariantBuilder *builder = NULL;
2465 GVariantBuilder *inner_builder = NULL;
2466 struct gatt_service_info *serv_info = NULL;
2467 struct gatt_char_info *char_info = NULL;
2468 GVariantBuilder *builder2 = NULL;
2469 GVariantBuilder *builder3 = NULL;
2470 GVariant *flags_val = NULL;
2472 char *char_flags[NUMBER_OF_FLAGS];
2474 hal_gatt_char_added *user_data = NULL;
2477 CHECK_BTGATT_INIT();
2478 DBG("Add new characteristic to GATT Service handle [%d]", service_handle);
2479 DBG("Properties of new charateristic [%d] Permission [%d]", properties, permissions);
2481 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2482 if (serv_info == NULL)
2483 return BT_STATUS_FAIL;
2485 node_info = __bt_gatt_create_method_node_info(
2486 characteristics_introspection_xml);
2488 if (node_info == NULL)
2489 return BT_STATUS_FAIL;
2491 DBG("Add new GATT characteristic: Current GATT char handle [%d]", gatt_char_handle);
2492 path = g_strdup_printf("%s/characteristic%d", serv_info->serv_path, ++gatt_char_handle);
2493 DBG("gatt characteristic path is [%s]", path);
2495 app_id = g_malloc0(sizeof(int));
2498 object_id = g_dbus_connection_register_object(g_conn, path,
2499 node_info->interfaces[0],
2500 &char_interface_vtable,
2501 (gpointer)app_id, NULL, &error);
2503 if (object_id == 0) {
2504 ERR("failed to register: %s", error->message);
2505 g_error_free(error);
2508 return BT_STATUS_FAIL;
2511 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_READ)
2512 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
2513 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ)
2514 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
2515 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_WRITE)
2516 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
2517 if (permissions & BT_HAL_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE)
2518 properties |= BT_HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
2520 flag_count = bt_hal_gatt_convert_prop2string(properties, char_flags);
2522 char_info = g_new0(struct gatt_char_info, 1);
2524 char_info->char_path = g_strdup(path);
2525 char_info->char_id = object_id;
2526 char_info->char_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2527 for (i = 0; i < flag_count; i++)
2528 char_info->char_flags[i] = char_flags[i];
2531 char_info->flags_length = flag_count;
2532 char_info->char_handle = gatt_char_handle;
2535 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2536 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2538 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2539 g_variant_new("s", char_info->char_uuid));
2540 g_variant_builder_add(inner_builder, "{sv}", "Service",
2541 g_variant_new("o", serv_info->serv_path));
2543 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2545 for (i = 0; i < flag_count; i++)
2546 g_variant_builder_add(builder2, "s", char_flags[i]);
2548 flags_val = g_variant_new("as", builder2);
2549 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2552 builder3 = g_variant_builder_new(G_VARIANT_TYPE("ao"));
2554 g_variant_builder_add(inner_builder, "{sv}", "Descriptors",
2555 g_variant_new("ao", builder3));
2557 g_variant_builder_add(builder, "{sa{sv}}",
2558 GATT_CHAR_INTERFACE,
2561 ret = g_dbus_connection_emit_signal(g_conn, NULL, "/",
2562 "org.freedesktop.Dbus.ObjectManager",
2564 g_variant_new("(oa{sa{sv}})",
2569 /* dbus gives error cause */
2570 ERR("d-bus api failure: errcode[%x], message[%s]",
2571 error->code, error->message);
2572 g_clear_error(&error);
2576 //*char_path = g_strdup(path);
2581 /* Send Service handle to application */
2582 user_data = g_malloc0(sizeof(hal_gatt_char_added));
2583 user_data->srvc_hdl = serv_info->service_handle;
2584 user_data->char_hdl = gatt_char_handle;
2585 user_data->instance_data = slot;
2586 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2587 g_idle_add(__bt_hal_gatt_char_added_cb, (gpointer)user_data);
2589 /* Save newly created charatcristic to GATT Server's service's characteristic list */
2590 serv_info->char_data = g_slist_append(serv_info->char_data, char_info);
2595 g_variant_builder_unref(inner_builder);
2596 g_variant_builder_unref(builder);
2597 g_variant_builder_unref(builder2);
2598 g_variant_builder_unref(builder3);
2600 return BT_STATUS_SUCCESS;
2603 static bt_status_t gatt_server_add_descriptor(int slot, int service_handle, bt_uuid_t *uuid,
2606 CHECK_BTGATT_INIT();
2608 // static int desc_id = 1;
2609 GError *error = NULL;
2611 GDBusNodeInfo *node_info;
2613 GVariantBuilder *builder = NULL;
2614 GVariantBuilder *inner_builder = NULL;
2616 struct gatt_char_info *char_info = NULL;
2617 struct gatt_desc_info *desc_info = NULL;
2618 struct gatt_service_info *serv_info = NULL;
2620 gchar **line_argv = NULL;
2622 char *char_path = NULL;
2625 GVariantBuilder *builder2 = NULL;
2626 GVariant *flags_val = NULL;
2628 char *desc_flags[NUMBER_OF_FLAGS];
2632 hal_gatt_desc_added *user_data = NULL;
2639 /* Fetch service data for the GATT server */
2640 serv_info = __bt_gatt_find_gatt_service_info(slot, service_handle);
2641 if (serv_info == NULL)
2642 return BT_STATUS_FAIL;
2644 /* Fetch list of characteristics from the service info */
2645 l = serv_info->char_data;
2647 /* Fetch last char info from the characteristic list */
2648 char_info = g_slist_last(l)->data;
2649 if (char_info == NULL)
2650 return BT_STATUS_FAIL;
2652 /* Fetch characteristic path from char info */
2653 char_path = char_info->char_path;
2655 line_argv = g_strsplit_set(char_path, "/", 0);
2656 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
2659 node_info = __bt_gatt_create_method_node_info(
2660 descriptor_introspection_xml);
2662 if (node_info == NULL) {
2663 g_strfreev(line_argv);
2665 return BT_STATUS_FAIL;
2668 DBG("Add new Descriptor: Current GATT desc handle [%d]", gatt_desc_handle);
2670 path = g_strdup_printf("%s/descriptor%d", char_path, ++gatt_desc_handle);
2671 DBG("gatt descriptor path is [%s]", path);
2673 app_id = g_malloc0(sizeof(int));
2676 object_id = g_dbus_connection_register_object(g_conn, path,
2677 node_info->interfaces[0],
2678 &desc_interface_vtable,
2679 (gpointer)app_id, NULL, &error);
2681 if (object_id == 0) {
2682 ERR("failed to register: %s", error->message);
2683 g_error_free(error);
2685 g_strfreev(line_argv);
2688 return BT_STATUS_FAIL;
2691 flag_count = bt_hal_gatt_convert_perm2string(permissions, desc_flags);
2693 desc_info = g_new0(struct gatt_desc_info, 1);
2695 desc_info->desc_path = g_strdup(path);
2696 desc_info->desc_id = object_id;
2697 desc_info->desc_uuid = __bt_hal_convert_uuid_to_string(uuid);//g_strdup(btuuid2str(uuid->uu));
2699 for (i = 0; i < flag_count; i++)
2700 desc_info->desc_flags[i] = desc_flags[i];
2702 desc_info->flags_length = flag_count;
2703 desc_info->desc_handle = gatt_desc_handle;
2706 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}"));
2707 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2709 g_variant_builder_add(inner_builder, "{sv}", "UUID",
2710 g_variant_new("s", btuuid2str(uuid->uu)));
2711 g_variant_builder_add(inner_builder, "{sv}", "Characteristic",
2712 g_variant_new("o", char_path));
2714 builder2 = g_variant_builder_new(G_VARIANT_TYPE("as"));
2716 for (i = 0; i < flag_count; i++)
2717 g_variant_builder_add(builder2, "s", desc_flags[i]);
2719 flags_val = g_variant_new("as", builder2);
2720 g_variant_builder_add(inner_builder, "{sv}", "Flags",
2723 g_variant_builder_add(builder, "{sa{sv}}",
2724 GATT_DESC_INTERFACE,
2727 g_dbus_connection_emit_signal(g_conn, NULL, "/",
2728 "org.freedesktop.Dbus.ObjectManager",
2730 g_variant_new("(oa{sa{sv}})",
2733 if (error != NULL) {
2734 ERR("g_dbus_connection_emit_signal failed: errCode[%x], message[%s]",
2735 error->code, error->message);
2736 g_clear_error(&error);
2739 //*desc_path = g_strdup(path);
2741 /* Save newly created descriptor to GATT server's service's characteristic */
2742 char_info->desc_data = g_slist_append(char_info->desc_data, desc_info);
2744 /* Send descriptor handle to application */
2745 user_data = g_malloc0(sizeof(hal_gatt_desc_added));
2746 user_data->srvc_hdl = serv_info->service_handle;
2747 user_data->desc_hdl = gatt_desc_handle;
2748 user_data->instance_data = slot;
2749 memcpy(user_data->uuid.uu, uuid->uu, sizeof(uuid->uu));
2750 g_idle_add(__bt_hal_gatt_desc_added_cb, (gpointer)user_data);
2755 g_strfreev(line_argv);
2756 g_variant_builder_unref(inner_builder);
2757 g_variant_builder_unref(builder);
2758 return BT_STATUS_SUCCESS;
2761 static void __bt_hal_register_application_cb(GObject *object, GAsyncResult *res, gpointer user_data)
2763 GError *error = NULL;
2765 char *data = (char*) user_data;
2766 INFO("RegisterApplication is completed path [%s]", data);
2768 result = g_dbus_proxy_call_finish(manager_gproxy, res, &error);
2770 if (result == NULL) {
2771 /* dBUS-RPC is failed */
2772 ERR("Dbus-RPC is failed\n");
2774 if (error != NULL) {
2775 /* dBUS gives error cause */
2776 ERR("D-Bus API failure: errCode[%x], message[%s]\n",
2777 error->code, error->message);
2778 g_clear_error(&error);
2781 g_variant_unref(result);
2786 static GDBusProxy *__bt_hal_gatt_gdbus_init_manager_proxy(const gchar *service,
2787 const gchar *path, const gchar *interface)
2793 g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
2798 ERR("Unable to connect to gdbus: %s", err->message);
2799 g_clear_error(&err);
2804 proxy = g_dbus_proxy_new_sync(g_conn,
2805 G_DBUS_PROXY_FLAGS_NONE, NULL,
2807 interface, NULL, &err);
2811 ERR("Unable to create proxy: %s", err->message);
2812 g_clear_error(&err);
2816 manager_gproxy = proxy;
2821 static GDBusProxy *__bt_gatt_gdbus_get_gatt_manager_proxy(const gchar *service,
2822 const gchar *path, const gchar *interface)
2824 return (manager_gproxy) ? manager_gproxy :
2825 __bt_hal_gatt_gdbus_init_manager_proxy(service,
2829 static void __bt_register_application_to_dbus(int slot)
2831 GDBusProxy *proxy = NULL;
2832 char *app_path = NULL;
2834 DBG("RegisterApplication slot [%d]", slot);
2836 /* It is impossible that app path is still not initialized */
2837 _bt_hal_is_gatt_server_initialzed(slot, &app_path);
2839 proxy = __bt_gatt_gdbus_get_gatt_manager_proxy("org.bluez",
2840 "/org/bluez/hci0", "org.bluez.GattManager1");
2842 data = g_strdup(app_path);
2843 g_dbus_proxy_call(proxy,
2844 "RegisterApplication",
2845 g_variant_new("(oa{sv})",
2847 G_DBUS_CALL_FLAGS_NONE, -1,
2849 (GAsyncReadyCallback)__bt_hal_register_application_cb,
2851 INFO("GATT server started");
2854 static bt_status_t gatt_server_start_service(int server_if, int service_handle, int transport)
2856 CHECK_BTGATT_INIT();
2857 struct gatt_service_info *serv_info = NULL;
2858 hal_gatt_service_started *user_data = NULL;
2859 DBG("Start GATT Service svc hdl [%d], slot [%d]", service_handle, server_if);
2861 /* Fetch service data for the GATT server */
2862 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2863 if (serv_info == NULL)
2864 return BT_STATUS_FAIL;
2866 if (serv_info->is_svc_registered)
2867 DBG("service already registered \n");
2869 serv_info->is_svc_registered = TRUE;
2871 /* Send Service handle to application */
2872 user_data = g_malloc0(sizeof(hal_gatt_service_started));
2873 user_data->srvc_hdl = serv_info->service_handle;
2874 user_data->instance_data = server_if;
2875 g_idle_add(__bt_hal_gatt_service_started_cb, (gpointer)user_data);
2877 /* If this is nth Service that is started, then register application at this point */
2878 if (__bt_is_service_last_in_server_list(server_if, service_handle)) {
2879 DBG("This is the last service started from the GATT Server's list of services handle [%d]",
2881 __bt_register_application_to_dbus(server_if);
2884 return BT_STATUS_SUCCESS;
2887 static bt_status_t gatt_server_stop_service(int server_if, int service_handle)
2889 CHECK_BTGATT_INIT();
2890 INFO("Stop service successful");
2891 return BT_STATUS_SUCCESS;
2894 static bt_status_t gatt_server_delete_service(int server_if, int service_handle)
2896 CHECK_BTGATT_INIT();
2897 struct gatt_service_info *serv_info = NULL;
2898 hal_gatt_service_deleted *user_data = NULL;
2901 int err = BT_STATUS_SUCCESS;
2902 int ret = BT_STATUS_SUCCESS;
2903 INFO("Slot [%d] service handle [%d]", server_if, service_handle);
2905 /* Fetch service data for the GATT server */
2906 serv_info = __bt_gatt_find_gatt_service_info(server_if, service_handle);
2907 if (serv_info == NULL) {
2908 ERR("Could not find service info svc handle [%d] server slot [%d]",
2909 service_handle, server_if);
2910 return BT_STATUS_FAIL;
2913 if (serv_info->is_svc_registered == FALSE) {
2914 ERR("service Not registered path [%s] handle [%d]",
2915 serv_info->serv_path, service_handle);
2918 for (l = serv_info->char_data; l != NULL; l = g_slist_next(l)) {
2919 struct gatt_char_info *char_info = l->data;
2921 if (char_info == NULL)
2924 for (l1 = char_info->desc_data; l1 != NULL; l1 = g_slist_next(l1)) {
2925 struct gatt_desc_info *desc_info = l1->data;
2927 if (desc_info == NULL)
2930 ret = g_dbus_connection_unregister_object(g_conn,
2931 desc_info->desc_id);
2933 __bt_hal_gatt_emit_interface_removed(
2934 desc_info->desc_path,
2935 GATT_DESC_INTERFACE);
2937 err = BT_STATUS_FAIL;
2940 /* list remove & free */
2941 char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
2942 __bt_hal_gatt_free_descriptor_info(desc_info);
2945 g_slist_free(char_info->desc_data);
2946 char_info->desc_data = NULL;
2948 ret = g_dbus_connection_unregister_object(g_conn,
2949 char_info->char_id);
2951 __bt_hal_gatt_emit_interface_removed(char_info->char_path,
2952 GATT_CHAR_INTERFACE);
2955 err = BT_STATUS_FAIL;
2958 /* list remove & free */
2959 serv_info->char_data = g_slist_remove(serv_info->char_data, char_info);
2960 __bt_hal_gatt_free_characteristic_info(char_info);
2963 g_slist_free(serv_info->char_data);
2964 serv_info->char_data = NULL;
2966 ret = g_dbus_connection_unregister_object(g_conn, serv_info->serv_id);
2968 __bt_hal_gatt_emit_interface_removed(serv_info->serv_path,
2969 GATT_SERV_INTERFACE);
2972 err = BT_STATUS_FAIL;
2975 ret = g_dbus_connection_unregister_object(g_conn, serv_info->prop_id);
2977 DBG("Unregistered the service on properties interface");
2979 /* Remove from global list */
2980 gatt_services = g_slist_remove(gatt_services, serv_info);
2981 INFO("After removing from global list total service dount [%d]", g_slist_length(gatt_services));
2983 /* Remove from GATT Server's list of services */
2984 _bt_remote_service_from_gatt_server(server_if, service_handle);
2986 if (gatt_services == NULL)
2987 INFO("All GATT Services of all GATT Servers are unregistered");
2989 if (err == BT_STATUS_SUCCESS) {
2990 INFO("Send GATT Service deleted Event");
2991 /* Send Service handle to application */
2992 user_data = g_malloc0(sizeof(hal_gatt_service_deleted));
2993 user_data->srvc_hdl = serv_info->service_handle;
2994 user_data->instance_data = server_if;
2995 g_idle_add(__bt_hal_gatt_service_deleted_cb, (gpointer)user_data);
2998 /* Free the service */
2999 __bt_hal_gatt_free_service_info(serv_info);
3003 static gboolean __bt_gatt_get_service_state(const char *service_path)
3005 struct gatt_service_info *svc_info = NULL;
3007 for (l = gatt_services; l; l = g_slist_next(l)) {
3009 svc_info = (struct gatt_service_info *)l->data;
3011 if (!g_strcmp0(svc_info->serv_path, service_path))
3012 return svc_info->is_svc_registered;
3015 DBG("gatt service info is NULL");
3019 static bt_status_t gatt_server_send_indication(int server_if, int attribute_handle, int conn_id,
3020 int len, int confirm, char* p_value)
3022 CHECK_BTGATT_INIT();
3025 GVariantBuilder *outer_builder;
3026 GVariantBuilder *invalidated_builder;
3028 /* For Value update via PropertyChange */
3029 GVariantBuilder *outer_builder1;
3030 GVariantBuilder *inner_builder1;
3031 GVariantBuilder *invalidated_builder1;
3032 GVariant *update_value = NULL;
3034 /* Other variables */
3035 struct gatt_client_info_t *conn_info = NULL;
3036 gchar *serv_path = NULL;
3037 char *char_path = NULL;
3038 gchar **line_argv = NULL;
3039 gboolean notify = TRUE;
3040 gboolean ret = TRUE;
3041 int err = BT_STATUS_SUCCESS;
3043 GError *error = NULL;
3046 memset(addr, 0x00, sizeof(addr));
3048 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3049 if (conn_info == NULL) {
3050 ERR("No Connection Inforamtion!!!");
3051 return BT_STATUS_FAIL;
3054 DBG("Send Indication to GATT client addr [%s]", conn_info->addr);
3056 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3057 if (char_path == NULL)
3058 return BT_STATUS_FAIL;
3060 line_argv = g_strsplit_set(char_path, "/", 0);
3061 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3063 if (!__bt_gatt_get_service_state(serv_path)) {
3064 DBG("service not registered for this characteristic \n");
3066 g_strfreev(line_argv);
3067 return BT_STATUS_FAIL;
3070 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3071 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3073 g_variant_builder_add(outer_builder, "{sv}", "Notifying",
3074 g_variant_new("b", notify));
3076 memcpy(addr, conn_info->addr, BT_HAL_ADDRESS_STRING_SIZE);
3077 DBG("Send Indication to Unicast addr [%s]", addr);
3079 g_variant_builder_add(outer_builder, "{sv}", "Unicast",
3080 g_variant_new("s", addr));
3082 DBG("Set characteristic Notification \n");
3083 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3085 "org.freedesktop.DBus.Properties",
3086 "PropertiesChanged",
3087 g_variant_new("(sa{sv}as)",
3088 "org.bluez.GattCharacteristic1",
3089 outer_builder, invalidated_builder),
3093 if (error != NULL) {
3094 ERR("D-Bus API failure: errCode[%x], \
3096 error->code, error->message);
3097 g_clear_error(&error);
3099 err = BT_STATUS_FAIL;
3102 g_variant_builder_unref(outer_builder);
3103 g_variant_builder_unref(invalidated_builder);
3106 /* Notifying Done, now update Value to Bluez via PropertyChanged */
3107 invalidated_builder1 = g_variant_builder_new(G_VARIANT_TYPE("as"));
3109 inner_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3110 for (i = 0; i < len; i++)
3111 g_variant_builder_add(inner_builder1, "y", p_value[i]);
3113 update_value = g_variant_new("ay", inner_builder1);
3116 outer_builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3117 g_variant_builder_add(outer_builder1, "{sv}", "Value",
3120 DBG("Updating characteristic value \n");
3121 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3123 "org.freedesktop.DBus.Properties",
3124 "PropertiesChanged",
3125 g_variant_new("(sa{sv}as)",
3126 "org.bluez.GattCharacteristic1",
3127 outer_builder1, invalidated_builder1),
3131 if (error != NULL) {
3132 ERR("D-Bus API failure: errCode[%x], \
3134 error->code, error->message);
3135 g_clear_error(&error);
3137 err = BT_STATUS_FAIL;
3139 struct gatt_char_info *char_info = NULL;
3141 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3142 if (char_info == NULL) {
3144 g_strfreev(line_argv);
3145 g_variant_builder_unref(inner_builder1);
3146 g_variant_builder_unref(outer_builder1);
3147 g_variant_builder_unref(invalidated_builder1);
3149 return BT_STATUS_FAIL;
3152 char_info->value_length = len;
3154 char_info->char_value = (char *)realloc(char_info->char_value, len);
3155 if (char_info->char_value) {
3156 for (i = 0; i < len; i++)
3157 char_info->char_value[i] = p_value[i];
3162 g_strfreev(line_argv);
3163 g_variant_builder_unref(inner_builder1);
3164 g_variant_builder_unref(outer_builder1);
3165 g_variant_builder_unref(invalidated_builder1);
3170 static bt_status_t gatt_server_send_response(int conn_id, int trans_id,
3171 int status, btgatt_response_t *response)
3173 CHECK_BTGATT_INIT();
3175 struct gatt_req_info *req_info = NULL;
3176 struct gatt_client_info_t *conn_info = NULL;
3179 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3180 if (conn_info == NULL) {
3181 ERR("No Connection Inforamtion. conn_id %d", conn_id);
3182 return BT_STATUS_FAIL;
3185 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3186 if (req_info == NULL) {
3187 ERR("No Request Inforamtion. conn_id %d", conn_id);
3188 return BT_STATUS_FAIL;
3191 if (status != BT_STATUS_SUCCESS) {
3192 ERR("resp_state is 0x%X, conn_id %d", status, conn_id);
3194 g_dbus_method_invocation_return_dbus_error(req_info->context,
3195 "org.bluez.Error.Failed", "Application Error");
3197 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3199 req_info->context = NULL;
3200 if (req_info->attr_path)
3201 g_free(req_info->attr_path);
3202 if (req_info->svc_path)
3203 g_free(req_info->svc_path);
3206 return BT_STATUS_SUCCESS;
3209 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_READ) {
3210 GVariantBuilder *inner_builder = NULL;
3211 inner_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
3213 if (response->attr_value.len > 0) {
3214 for (i = 0; i < response->attr_value.len; i++)
3215 g_variant_builder_add(inner_builder, "y", response->attr_value.value[i]);
3217 g_dbus_method_invocation_return_value(req_info->context,
3218 g_variant_new("(ay)", inner_builder));
3220 g_variant_builder_unref(inner_builder);
3222 g_dbus_method_invocation_return_value(req_info->context, NULL);
3224 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3226 req_info->context = NULL;
3227 if (req_info->attr_path)
3228 g_free(req_info->attr_path);
3229 if (req_info->svc_path)
3230 g_free(req_info->svc_path);
3233 return BT_STATUS_SUCCESS;
3237 static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id,
3238 int status, int fd, int mtu, void *fdlist)
3240 CHECK_BTGATT_INIT();
3242 struct gatt_req_info *req_info = NULL;
3243 struct gatt_client_info_t *conn_info = NULL;
3245 DBG("GATT Server Send Response Conn ID [%d]", conn_id);
3247 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3248 if (conn_info == NULL) {
3249 ERR("No Connection Inforamtion!!!");
3250 return BT_STATUS_FAIL;
3253 req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id);
3254 if (req_info == NULL) {
3255 ERR("No Request Inforamtion!!!");
3256 return BT_STATUS_FAIL;
3259 if (status != BT_STATUS_SUCCESS) {
3260 ERR("resp_state is 0x%X", status);
3262 g_dbus_method_invocation_return_dbus_error(req_info->context,
3263 "org.bluez.Error.Failed", "Application Error");
3265 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3267 req_info->context = NULL;
3268 if (req_info->attr_path)
3269 g_free(req_info->attr_path);
3270 if (req_info->svc_path)
3271 g_free(req_info->svc_path);
3274 return BT_STATUS_SUCCESS;
3278 if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) {
3280 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd);
3281 g_dbus_method_invocation_return_value_with_unix_fd_list(
3282 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3284 } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) {
3286 INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY to bluez %d\n", fd);
3287 g_dbus_method_invocation_return_value_with_unix_fd_list(
3288 req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist);
3291 g_dbus_method_invocation_return_value(req_info->context, NULL);
3293 conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info);
3295 req_info->context = NULL;
3296 if (req_info->attr_path)
3297 g_free(req_info->attr_path);
3298 if (req_info->svc_path)
3299 g_free(req_info->svc_path);
3302 return BT_STATUS_SUCCESS;
3306 static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle,
3307 int value_length, char* att_value)
3309 CHECK_BTGATT_INIT();
3311 /* Other variables */
3312 char *char_path = NULL;
3313 gboolean ret = TRUE;
3314 GError *error = NULL;
3316 GVariantBuilder *outer_builder;
3317 GVariantBuilder *inner_builder;
3318 GVariantBuilder *invalidated_builder;
3319 GVariant *update_value = NULL;
3320 int err = BT_STATUS_SUCCESS;
3322 gchar **line_argv = NULL;
3323 gchar *serv_path = NULL;
3325 char_path = __bt_gatt_find_char_path_from_handle(attribute_handle);
3326 if (char_path == NULL)
3327 return BT_STATUS_FAIL;
3329 line_argv = g_strsplit_set(char_path, "/", 0);
3330 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3332 if (!__bt_gatt_get_service_state(serv_path)) {
3333 DBG("service not registered for this characteristic \n");
3335 g_strfreev(line_argv);
3336 return BT_STATUS_FAIL;
3340 line_argv = g_strsplit_set(char_path, "/", 0);
3341 serv_path = g_strdup_printf("/%s/%s/%s", line_argv[1], line_argv[2], line_argv[3]);
3343 if (!__bt_gatt_get_service_state(serv_path)) {
3344 DBG("service not registered for this characteristic \n");
3346 g_strfreev(line_argv);
3347 return BT_STATUS_FAIL;
3350 outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3351 invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
3353 inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
3354 for (i = 0; i < value_length; i++)
3355 g_variant_builder_add(inner_builder, "y", att_value[i]);
3357 update_value = g_variant_new("ay", inner_builder);
3359 g_variant_builder_add(outer_builder, "{sv}", "Value",
3362 DBG("Updating characteristic value \n");
3363 ret = g_dbus_connection_emit_signal(g_conn, NULL,
3365 "org.freedesktop.DBus.Properties",
3366 "PropertiesChanged",
3367 g_variant_new("(sa{sv}as)",
3368 "org.bluez.GattCharacteristic1",
3369 outer_builder, invalidated_builder),
3373 if (error != NULL) {
3374 ERR("D-Bus API failure: errCode[%x], \
3376 error->code, error->message);
3377 g_clear_error(&error);
3379 err = BT_STATUS_FAIL;
3381 struct gatt_char_info *char_info = NULL;
3383 char_info = __bt_gatt_find_char_info_from_handle(attribute_handle);
3384 if (char_info == NULL) {
3386 g_strfreev(line_argv);
3387 g_variant_builder_unref(inner_builder);
3388 g_variant_builder_unref(outer_builder);
3389 g_variant_builder_unref(invalidated_builder);
3391 return BT_STATUS_FAIL;
3394 char_info->value_length = value_length;
3396 char_info->char_value = (char *)realloc(char_info->char_value, value_length);
3397 if (char_info->char_value) {
3398 for (i = 0; i < value_length; i++)
3399 char_info->char_value[i] = att_value[i];
3405 g_strfreev(line_argv);
3406 g_variant_builder_unref(inner_builder);
3407 g_variant_builder_unref(outer_builder);
3408 g_variant_builder_unref(invalidated_builder);
3413 static bt_status_t gatt_server_listen(int server_if, bool start)
3415 CHECK_BTGATT_INIT();
3417 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3419 DBG("server_if: [%d]", server_if);
3421 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3422 if (server_register_info == NULL) {
3423 DBG("gatt server is not registered");
3424 return BT_STATUS_FAIL;
3427 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3429 if (server_register_info->adv_slot_id < 0 ) {
3430 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3431 return BT_STATUS_FAIL;
3434 /* Send Data to LE Module */
3435 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, start, FALSE);
3438 static bt_status_t gatt_server_set_adv_data(int server_if, bool set_scan_rsp, bool include_name,
3439 bool include_txpower, int min_interval, int max_interval, int appearance,
3440 uint16_t manufacturer_len, char* manufacturer_data,
3441 uint16_t service_data_len, char* service_data,
3442 uint16_t service_uuid_len, char* service_uuid)
3444 CHECK_BTGATT_INIT();
3445 return BT_STATUS_SUCCESS;
3448 static int bt_hal_gatts_allocate_adv_slot(struct hal_gatts_server_register_info_t *server_register_info)
3450 int adv_slot_id = -1;
3452 /* allocate adv slot for gatt server if not assigned */
3453 if (server_register_info->adv_slot_id < 0 ) {
3454 adv_slot_id = _bt_hal_get_available_adv_slot_id(&server_register_info->app_uuid, FALSE);
3455 if (adv_slot_id < 0) {
3456 ERR("failed to get the adv_slot");
3460 server_register_info->adv_slot_id = adv_slot_id;
3463 DBG("gatt server:[%d] Assigned adv_slot [%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3468 int bt_hal_gatts_allocate_adv_slot_by_server_if(int server_if)
3470 CHECK_BTGATT_INIT();
3474 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3476 DBG("server_if: [%d]", server_if);
3478 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3479 if (server_register_info == NULL) {
3480 DBG("gatt server is not registered");
3484 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3486 if (server_register_info->adv_slot_id < 0 ) {
3487 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3489 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3491 DBG("failed to get adv_slot");
3496 return server_register_info->adv_slot_id;
3499 void bt_hal_gatts_release_adv_slot(int server_if)
3501 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3503 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3504 if (server_register_info == NULL) {
3505 ERR("failed to get server_register_info");
3509 if (server_register_info->adv_slot_id < 0) {
3510 ERR("adv_slot is not allocated");
3514 if(_bt_hal_is_advertising_in_slot(server_register_info->adv_slot_id) == FALSE) {
3515 DBG("advertising is disabled");
3516 _bt_hal_free_server_slot(server_register_info->adv_slot_id);
3517 server_register_info->adv_slot_id = -1;
3521 int bt_hal_gatts_get_adv_slot_id(int server_if)
3523 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3525 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3526 if (server_register_info == NULL) {
3527 DBG("failed to get server_register_info");
3531 return server_register_info->adv_slot_id;
3534 int bt_hal_gatts_get_server_if(int slot_id)
3536 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3538 server_register_info = bt_hal_gatts_find_server_register_info_by_slot_id(slot_id);
3539 if (server_register_info == NULL) {
3540 DBG("failed to get server_register_info");
3544 return server_register_info->server_if;
3547 static bt_status_t gatt_server_multi_adv_enable(int server_if)
3549 CHECK_BTGATT_INIT();
3553 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3555 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3556 if (server_register_info == NULL) {
3557 ERR("gatt server is not registered");
3558 return BT_STATUS_FAIL;
3561 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3563 if (server_register_info->adv_slot_id < 0 ) {
3564 DBG("adv_slot is not assigned to server:[%d]", server_if);
3566 ret = bt_hal_gatts_allocate_adv_slot(server_register_info);
3568 ERR("failed to get adv_slot");
3569 return BT_STATUS_FAIL;
3573 /* Send Enable Advertising request to LE Module */
3574 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, TRUE, TRUE);
3577 static bt_status_t gatt_server_multi_adv_update(int server_if, int min_interval, int max_interval, int adv_type,
3578 int chnl_map, int tx_power, int timeout_s)
3580 CHECK_BTGATT_INIT();
3582 /* Send Advertising parameters to LE Module */
3583 return _bt_hal_set_advertising_params(server_if, min_interval, max_interval, adv_type,
3584 chnl_map, tx_power, timeout_s);
3587 static bt_status_t gatt_server_set_filter_policy(int filter_policy)
3589 CHECK_BTGATT_INIT();
3591 /* Send the Filter policy parameter to LE Module */
3592 _bt_hal_set_filter_policy_param(filter_policy);
3593 return BT_STATUS_SUCCESS;
3596 static bt_status_t gatt_server_multi_adv_set_inst_data(btgatt_adv_param_setup_t adv_param_setup)
3598 CHECK_BTGATT_INIT();
3600 /* Send Data to LE Module */
3601 return _bt_hal_set_advertising_data(adv_param_setup);
3604 static bt_status_t gatt_server_multi_adv_disable(int server_if)
3606 CHECK_BTGATT_INIT();
3608 struct hal_gatts_server_register_info_t *server_register_info = NULL;
3610 DBG("server_if: [%d]", server_if);
3612 server_register_info = bt_hal_gatts_find_server_register_info(server_if);
3613 if (server_register_info == NULL) {
3614 DBG("gatt server is not registered");
3615 return BT_STATUS_FAIL;
3618 DBG("gatt server:[%d], adv_slot:[%d]", server_register_info->server_if, server_register_info->adv_slot_id);
3620 if (server_register_info->adv_slot_id < 0 ) {
3621 DBG("adv_slot is not assigned to server:[%d] \n", server_if);
3622 return BT_STATUS_FAIL;
3625 /* Send Data to LE Module */
3626 return _bt_hal_enable_advertising(server_if, server_register_info->adv_slot_id, FALSE, TRUE);
3629 static bt_status_t gatt_server_get_mtu_size(int conn_id, int *mtu_size)
3631 CHECK_BTGATT_INIT();
3632 char *object_path = NULL;
3634 GDBusProxy *device_proxy;
3635 GError *error = NULL;
3637 GVariant *tmp_value;
3638 GDBusConnection *conn;
3639 GVariant *result = NULL;
3640 int ret = BT_STATUS_SUCCESS;
3641 struct gatt_client_info_t *conn_info = NULL;
3644 if (mtu_size == NULL)
3645 return BT_STATUS_PARM_INVALID;
3647 /* GDBUS Connection Info validate */
3648 conn = _bt_hal_get_system_gconn();
3650 ERR("Could not get System DBUS Connection");
3651 return BT_STATUS_FAIL;
3654 /* Connection Info validate */
3655 conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id);
3656 if (conn_info == NULL) {
3657 ERR("No Connection Inforamtion!!!");
3658 return BT_STATUS_FAIL;
3662 object_path = _bt_hal_get_device_object_path(conn_info->addr);
3663 if (object_path == NULL)
3664 return BT_STATUS_FAIL;
3666 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3667 NULL, BT_HAL_BLUEZ_NAME, object_path,
3668 BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
3670 g_free(object_path);
3671 if (device_proxy == NULL)
3672 return BT_STATUS_FAIL;
3674 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
3675 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
3676 G_DBUS_CALL_FLAGS_NONE,
3680 if (result == NULL) {
3681 if (error != NULL) {
3682 ERR("Error occured in Proxy call [%s]\n", error->message);
3683 g_error_free(error);
3685 g_object_unref(device_proxy);
3686 return BT_STATUS_FAIL;
3689 g_variant_get(result , "(@a{sv})", &value);
3690 g_variant_unref(result);
3692 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
3693 if (tmp_value == NULL) {
3694 g_object_unref(device_proxy);
3695 g_variant_unref(value);
3696 return BT_STATUS_FAIL;
3699 mtu = g_variant_get_uint16(tmp_value);
3701 DBG("ATT MTU : [%d]", mtu);
3703 g_variant_unref(tmp_value);
3704 g_variant_unref(value);
3705 g_object_unref(device_proxy);
3707 *mtu_size = (int) mtu;
3712 const btgatt_server_interface_t btgatt_server_interface = {
3713 .register_server = gatt_server_register_app,
3714 .unregister_server = gatt_server_unregister_app,
3715 .connect = gatt_server_open,
3716 .disconnect = gatt_server_close,
3717 .add_service = gatt_server_add_service,
3718 .add_included_service = gatt_server_add_included_service,
3719 .add_characteristic = gatt_server_add_characteristic,
3720 .add_descriptor = gatt_server_add_descriptor,
3721 .start_service = gatt_server_start_service,
3722 .stop_service = gatt_server_stop_service,
3723 .delete_service = gatt_server_delete_service,
3724 .send_indication = gatt_server_send_indication,
3725 .send_response = gatt_server_send_response,
3726 .update_att_value = gatt_server_update_att_value,
3727 .listen = gatt_server_listen,
3728 .set_adv_data = gatt_server_set_adv_data,
3729 .multi_adv_enable = gatt_server_multi_adv_enable,
3730 .multi_adv_update = gatt_server_multi_adv_update,
3731 .set_filter_policy = gatt_server_set_filter_policy,
3732 .multi_adv_set_inst_data = gatt_server_multi_adv_set_inst_data,
3733 .multi_adv_disable = gatt_server_multi_adv_disable,
3734 .get_att_mtu = gatt_server_get_mtu_size,
3735 .send_response_acquire = gatt_server_send_acquire_response