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>
31 #include <gio/gunixfdlist.h>
34 #include "bt-hal-log.h"
35 #include "bt-hal-msg.h"
36 #include "bt-hal-event-receiver.h"
37 #include "bt-hal-adapter-le.h"
39 #include "bt-hal-gatt-client.h"
40 #include "bt-hal-dbus-common-utils.h"
41 #include "bt-hal-utils.h"
43 /************************************************************************************
45 ************************************************************************************/
46 extern const btgatt_callbacks_t *bt_gatt_callbacks;
47 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
49 ERR("%s: BTGATT not initialized", __FUNCTION__);\
50 return BT_STATUS_NOT_READY;\
52 DBG("%s", __FUNCTION__);\
56 int le_scan_type = BT_GATTC_LE_SCAN_TYPE_PASSIVE;
59 static handle_stack_msg event_cb = NULL;
61 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
62 #define MAX_HAL_OBJECT_PATH_LEN 100
65 HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST = 0x01,
66 HAL_GATT_CHARACTERISTIC_PROPERTY_READ = 0x02,
67 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE = 0x04,
68 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE = 0x08,
69 HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY = 0x10,
70 HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE = 0x20,
71 HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE = 0x40,
72 HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE = 0x80,
73 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES = 0x100,
74 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ = 0x200,
75 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE = 0x400,
76 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ = 0x800,
77 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE = 0x1000,
78 HAL_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS = 0xffff,
79 } bt_gatt_characteristic_property_t;
83 HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE = 1,
84 HAL_GATT_WRITE_TYPE_WRITE ,
85 } hal_gatt_write_type_t;
89 HAL_GATT_PROPERTY_BROADCAST = 0x01, /**< Broadcast property */
90 HAL_GATT_PROPERTY_READ = 0x02, /**< Read property */
91 HAL_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE = 0x04, /**< Write without response property */
92 HAL_GATT_PROPERTY_WRITE = 0x08, /**< Write property */
93 HAL_GATT_PROPERTY_NOTIFY = 0x10, /**< Notify property */
94 HAL_GATT_PROPERTY_INDICATE = 0x20, /**< Indicate property */
95 HAL_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES = 0x40, /**< Authenticated signed writes property */
96 HAL_GATT_PROPERTY_EXTENDED_PROPERTIES = 0x80, /**< Extended properties */
97 } hal_gatt_property_e;
102 gboolean auto_connect;
103 } bt_pending_le_conn_info_s;
113 unsigned int permission;
114 GSList *gatt_list_descs;
121 GSList *gatt_list_chars;
122 } hal_gattc_service_t;
125 bt_bdaddr_t bd_addr; /*remote server address*/
126 int inst_id; /*server instance id*/
127 GSList *gatt_list_services;
128 } hal_gattc_server_info_t;
130 /* Linked List of connected GATT server */
131 static GSList *hal_gattc_server_info_list = NULL;
135 bt_bdaddr_t bd_addr; /*remote server address*/
138 } hal_gattc_client_info_t;
140 /* Linked list of connected GATT client connection */
141 static GSList * hal_gattc_client_info_list = NULL;
143 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
144 static guint pending_le_conn_timer_id = 0;
145 static int bt_conn_id = 0;
146 static int bt_inst_id = 0;
148 #define BT_GATTC_CL_MAX 32
153 btgatt_srvc_id_t srvc_id;
154 btgatt_gatt_id_t char_id;
155 btgatt_gatt_id_t desc_id;
156 } hal_gatt_resp_data_t;
161 } hal_gatt_client_app;
163 static GSList * hal_gattc_client_app_list = NULL;
165 static int bt_client_if = 0;
168 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
169 gboolean auto_connect);
170 static bt_status_t _bt_hold_current_advertising();
171 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
172 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
173 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
175 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
176 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
177 const char* uuid_str, int inst_id);
178 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
179 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr);
180 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
183 /* To send stack event to hal-av handler */
184 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
189 void _bt_hal_unregister_gatt_client_handler_cb(void)
195 int _bt_hal_gatt_client_get_le_scan_type(void)
201 static gboolean __bt_hal_register_client_cb(gpointer user_data)
203 struct hal_ev_gatt_client_registered ev;
204 hal_gatt_client_app *client_info = user_data;
207 /* Prepare to send AV connecting event */
208 memset(&ev, 0, sizeof(ev));
209 ev.status = BT_STATUS_SUCCESS;
210 ev.client_if = client_info->client_if;
211 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
214 ERR("GATT Callback not registered");
216 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
217 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
224 static int __hal_generate_client_id()
226 return ++bt_client_if;
229 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
232 hal_gatt_client_app *info = NULL;
233 hal_gatt_client_app *gattc_app = NULL;
235 //check if client app is already registered
236 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
237 info = (hal_gatt_client_app*)l->data;
241 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
242 DBG("gatt client app already registered");
247 DBG("adding the gatt client app");
250 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
251 gattc_app->client_if = __hal_generate_client_id();
252 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
254 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
259 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
261 hal_gatt_client_app *gattc_app = NULL;
262 hal_gatt_client_app *client_app_info = NULL;
265 /* add gatt client in list */
266 gattc_app = __hal_gattc_add_client_app(app_uuid);
267 if (gattc_app == NULL) {
268 ERR("Failed to register gatt client app");
269 return BT_STATUS_FAIL;
273 client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
274 client_app_info->client_if = gattc_app->client_if;
275 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
276 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
278 DBG("registered client client_if [%d]", client_app_info->client_if);
280 return BT_STATUS_SUCCESS;
283 /** Registers a GATT client application with the stack */
284 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
289 return __hal_gattc_register_client_app(uuid);
292 bt_status_t __hal_gattc_unregister_client(int client_if)
295 hal_gatt_client_app *info = NULL;
297 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
299 /* remove the gatt client app */
300 for (l = hal_gattc_client_app_list; l != NULL; ) {
301 info = (hal_gatt_client_app*)l->data;
307 if (info->client_if == client_if) {
308 DBG("gatt client app found");
309 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
314 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
315 return BT_STATUS_SUCCESS;
318 /** Unregister a client application from the stack */
319 bt_status_t btif_gattc_unregister_client(int client_if)
324 return __hal_gattc_unregister_client(client_if);
327 /** Start or stop LE device scanning */
328 bt_status_t scan(int client_if, bool start)
335 ret = _bt_hal_adapter_le_start_scan();
337 ret = _bt_hal_adapter_le_stop_scan();
342 /** Create a connection to a remote LE or dual-mode device */
343 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
346 int ret = BT_STATUS_SUCCESS;
352 return BT_STATUS_PARM_INVALID;
354 ret = _bt_hold_current_advertising();
355 if (ret == BT_STATUS_SUCCESS) {
356 DBG("Current advertising is held");
357 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
358 pending_le_conn_info->client_if = client_if;
359 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
360 BT_HAL_ADDRESS_LENGTH_MAX);
361 pending_le_conn_info->auto_connect = is_direct;
363 pending_le_conn_timer_id =
364 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
366 return BT_STATUS_SUCCESS;
368 ERR("advertising is not stopped");
371 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
375 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
378 GError *g_error = NULL;
379 GVariant *reply = NULL;
380 hal_gattc_client_info_t *gatt_conn_info = user_data;
381 int result = BT_STATUS_SUCCESS;
382 struct hal_ev_gatt_client_connected ev;
386 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
387 g_object_unref(proxy);
389 ERR("Connect LE Dbus Call Error");
391 ERR("Error: %s\n", g_error->message);
392 g_clear_error(&g_error);
394 result = BT_STATUS_FAIL;
396 g_variant_unref(reply);
398 if (NULL == gatt_conn_info) {
399 ERR("server_data is NULL");
404 if (result == BT_STATUS_FAIL) {
405 memset(&ev, 0, sizeof(ev));
406 ev.conn_id = gatt_conn_info->conn_id;
408 ev.client_if = gatt_conn_info->client_if;
409 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
410 BT_HAL_ADDRESS_LENGTH_MAX);
413 ERR("gatt client callback not registered");
415 DBG("sending gatt client disconnected event");
416 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
422 g_free(gatt_conn_info);
427 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
430 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
432 GDBusProxy *device_proxy;
433 GDBusConnection *conn;
434 int ret = BT_STATUS_SUCCESS;
435 hal_gattc_client_info_t *gattc_data;
437 if (NULL == bd_addr) {
438 ERR("bd_addr is NULL");
439 return BT_STATUS_PARM_INVALID;
442 conn = _bt_hal_get_system_gconn();
444 ERR("_bt_gdbus_get_system_gconn returned NULL");
445 return BT_STATUS_FAIL;
448 _bt_hal_convert_addr_type_to_string(device_address,
449 (unsigned char *)bd_addr->address);
450 device_path = _bt_hal_get_device_object_path(device_address);
451 if (device_path == NULL) {
452 DBG("device_path NULL");
453 ret = BT_STATUS_FAIL;
457 ERR("device_path:%s", device_path);
459 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
460 NULL, BT_HAL_BLUEZ_NAME,
461 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
463 if (NULL == device_proxy) {
464 ERR("device_proxy returned NULL");
465 return BT_STATUS_FAIL;
468 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
469 memcpy(gattc_data->bd_addr.address, bd_addr->address,
470 BT_HAL_ADDRESS_LENGTH_MAX);
471 gattc_data->client_if = client_if;
472 gattc_data->conn_id = conn_id;
474 DBG("DisconnectLE [%s]", device_address);
476 g_dbus_proxy_call(device_proxy, "DisconnectLE",
478 G_DBUS_CALL_FLAGS_NONE,
479 BT_HAL_MAX_DBUS_TIMEOUT,
481 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
485 g_object_unref(device_proxy);
492 /** Disconnect a remote device or cancel a pending connection */
493 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
500 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
503 /** Clear the attribute cache for a given device */
504 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
507 return BT_STATUS_UNSUPPORTED;
510 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
515 hal_gattc_service_t *info = NULL;
517 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
518 info = (hal_gattc_service_t*)l->data;
522 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t))) {
523 INFO("Found GATT service uuid");
531 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
532 bt_gatt_characteristic_property_t prop)
537 hal_gattc_char_t *info = NULL;
539 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
540 info = (hal_gattc_char_t*)l->data;
544 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
545 (info->permission & prop)) {
546 INFO("Found GATT char uuid");
553 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
558 hal_gattc_char_t *info = NULL;
560 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
561 info = (hal_gattc_char_t*)l->data;
565 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
566 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
567 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
568 INFO("Found GATT char uuid");
575 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
580 hal_gattc_desc_t *info = NULL;
582 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
583 info = (hal_gattc_desc_t*)l->data;
587 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t))) {
588 INFO("Found GATT descriptor uuid");
596 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
597 const char *uuid_str, char *object_path, int is_primary)
600 hal_gattc_service_t *gattc_service = NULL;
602 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
603 gattc_service->svc_path = g_strdup(object_path);
604 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
605 gattc_service->is_primary = is_primary;
607 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
609 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
611 DBG("svc path {%s] svc uuid [%s]", object_path, uuid_str);
613 return gattc_service;
616 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
619 hal_gattc_char_t *gattc_char = NULL;
621 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
622 gattc_char->chr_path = g_strdup(char_handle);
624 DBG("svc path: [%s]", gatt_svc->svc_path);
625 DBG("char path: [%s]", gattc_char->chr_path);
627 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
630 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
631 const char* uuid_str, char *object_path, GPtrArray *gp_char_array)
633 hal_gattc_service_t* gatt_svc = NULL;
635 gchar *gp_char_path = NULL;
639 /* add the service */
640 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
641 if (gatt_svc == NULL) {
642 ERR("Failed to add service");
646 /* add the characteristic */
647 for (i = 0; i < gp_char_array->len; i++) {
648 gp_char_path = g_ptr_array_index(gp_char_array, i);
649 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
652 g_ptr_array_free(gp_char_array, TRUE);
655 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
657 hal_gattc_desc_t *gattc_desc = NULL;
659 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
660 gattc_desc->desc_path = g_strdup(desc_path);
662 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
664 DBG("char path: [%s]", gattc_char->chr_path);
665 DBG("desc path: [%s]", gattc_desc->desc_path);
668 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
669 GPtrArray *gp_desc_array, unsigned int char_permission)
671 gchar *gp_desc_path = NULL;
676 if (char_uuid_str == NULL) {
677 DBG("char_uuid_str is NULL");
681 //update the char uuid
682 DBG("char UUID: [%s] ", char_uuid_str);
683 DBG("char path: [%s]", gattc_char->chr_path);
685 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
687 //update char permission
688 gattc_char->permission = char_permission;
691 for (i = 0; i < gp_desc_array->len; i++) {
692 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
693 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
697 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
701 if (desc_uuid_str == NULL) {
702 DBG("char_uuid_str is NULL");
706 //update the descriptor uuid
707 DBG("desc UUID: [%s] ", desc_uuid_str);
708 DBG("desc path: [%s]", gattc_desc->desc_path);
710 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
713 static void browse_service_char(int conn_id)
715 hal_gattc_server_info_t *conn_info = NULL;
719 hal_gattc_service_t *svc_info = NULL;
720 hal_gattc_char_t *char_info = NULL;
721 hal_gattc_desc_t *desc_info = NULL;
725 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
726 if (conn_info == NULL) {
727 DBG("conn_info is NULL");
731 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
733 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
734 svc_info = (hal_gattc_service_t*)l->data;
735 if (svc_info == NULL)
738 DBG("svc path [%s]", svc_info->svc_path);
740 /* find characteristic object path */
741 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
742 char_info = (hal_gattc_char_t *)k->data;
743 if (char_info == NULL)
746 DBG("char path[%s]", char_info->chr_path);
749 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
750 desc_info = (hal_gattc_desc_t *)m->data;
751 if (desc_info == NULL)
754 DBG("desc path[%s]", desc_info->desc_path);
763 * Enumerate all GATT services on a connected device.
764 * Optionally, the results can be filtered for a given UUID.
766 static bt_status_t _gattc_client_search_service(int conn_id)
770 GVariant *result = NULL;
772 GVariantIter *svc_iter;
773 GVariantIter *interface_iter;
774 char *object_path = NULL;
775 char *interface_str = NULL;
776 const gchar *key = NULL;
777 GVariant *value = NULL;
778 GPtrArray *gp_array = NULL;
779 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
780 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
781 int ret = BT_STATUS_FAIL;
783 const gchar *uuid_str = NULL;
785 hal_gattc_server_info_t *conn_info = NULL;
786 gboolean is_primary = FALSE;
789 char *char_handle = NULL;
790 GVariantIter *char_iter = NULL;
791 GPtrArray *gp_char_array = NULL;
795 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
796 if (NULL == conn_info) {
797 DBG("Failed to get the conn_info");
798 return BT_STATUS_FAIL;
801 _bt_hal_convert_addr_type_to_string(device_address,
802 (unsigned char *)conn_info->bd_addr.address);
804 result = _bt_hal_get_managed_objects();
808 gp_array = g_ptr_array_new();
809 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
811 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
813 if (object_path == NULL)
816 _bt_hal_convert_device_path_to_address(object_path, temp_address);
818 if (g_strcmp0(temp_address, device_address) != 0)
821 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
822 &interface_str, &svc_iter)) {
823 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
826 DBG("[%d] Object Path : %s", idx++, object_path);
827 /* for characteristic */
828 gp_char_array = g_ptr_array_new();
829 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
830 if (g_strcmp0(key, "Primary") == 0) {
831 is_primary = g_variant_get_boolean(value);
834 g_ptr_array_add(gp_array, (gpointer)object_path);
837 } else if (g_strcmp0(key, "UUID") == 0) {
838 uuid_str = g_variant_get_string(value, &len);
839 DBG(" UUID: [%s]", uuid_str);
840 } else if (g_strcmp0(key, "Characteristics") == 0) {
841 g_variant_get(value, "ao", &char_iter);
842 if (char_iter != NULL) {
843 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
844 DBG("char handle : %s", char_handle);
845 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
852 DBG("send search service result event");
853 _bt_hal_send_search_service_result_event(conn_id, is_primary,
854 uuid_str, conn_info->inst_id);
856 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
861 if (gp_array->len == 0 || svc_count == 0) {
862 ERR("gp_array is NULL");
863 ret = BT_STATUS_FAIL;
865 ret = BT_STATUS_SUCCESS;
868 browse_service_char(conn_id);
869 /* send search service complete event */
870 _bt_hal_send_search_service_complete_event(conn_id, ret);
872 g_ptr_array_free(gp_array, TRUE);
873 g_variant_iter_free(iter);
874 g_variant_unref(result);
879 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
881 if (NULL == filter_uuid) {
882 DBG("Browse all the services");
883 return _gattc_client_search_service(conn_id);
885 DBG("TODO implement it");
886 return BT_STATUS_UNSUPPORTED;
890 * Enumerate included services for a given service.
891 * Set start_incl_srvc_id to NULL to get the first included service.
893 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
894 btgatt_srvc_id_t *start_incl_srvc_id)
897 return BT_STATUS_UNSUPPORTED;
900 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
901 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
903 struct hal_ev_gatt_client_char_search_result ev;
906 ERR("gatt client callback not registered");
910 DBG("sending gatt client search char result event conn_id[%d] status[%d]", conn_id, status);
912 memset(&ev, 0, sizeof(ev));
913 ev.conn_id = conn_id;
914 ev.inst_id = svc_id->id.inst_id;
915 ev.is_primary = svc_id->is_primary;
917 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
919 if (status == BT_STATUS_SUCCESS) {
920 DBG("building char uuid");
921 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
922 ev.char_prop = char_prop;
925 DBG("sending the char search event");
927 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
930 static int _hal_get_permission_flag(char *permission)
934 if (NULL == permission) {
935 ERR("gatt permission is NULL");
939 if (!g_strcmp0(permission, "broadcast"))
940 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
941 else if (!g_strcmp0(permission, "read"))
942 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
943 else if (!g_strcmp0(permission, "write-without-response"))
944 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
945 else if (!g_strcmp0(permission, "write"))
946 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
947 else if (!g_strcmp0(permission, "notify"))
948 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
949 else if (!g_strcmp0(permission, "indicate"))
950 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
951 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
952 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
953 else if (!g_strcmp0(permission, "reliable-write"))
954 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
955 else if (!g_strcmp0(permission, "writable-auxiliaries"))
956 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
957 else if (!g_strcmp0(permission, "encrypt-read"))
958 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
959 else if (!g_strcmp0(permission, "encrypt-write"))
960 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
961 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
962 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
963 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
964 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
970 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
972 GDBusProxy *properties_proxy = NULL;
973 GError *error = NULL;
974 GVariant *value = NULL;
975 GVariant *result = NULL;
976 GDBusConnection *g_conn;
978 char *char_desc_handle = NULL;
980 GVariantIter *property_iter;
981 GVariantIter *char_desc_iter;
982 char* char_handle = NULL;
983 gchar *char_uuid_str = NULL;
984 GPtrArray *gp_desc_array = NULL;
985 GVariantIter *char_perm_iter;
987 unsigned int char_permission = 0 ;
991 if (gattc_char->chr_path == NULL) {
992 DBG("char path is NULL");
993 return BT_STATUS_FAIL;
995 char_handle = gattc_char->chr_path;
997 DBG("char path:[%s]", gattc_char->chr_path);
999 g_conn = _bt_hal_get_system_gconn();
1000 if (NULL == g_conn) {
1001 ERR("_bt_gdbus_get_system_gconn returned NULL");
1002 return BT_STATUS_FAIL;
1005 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1006 G_DBUS_PROXY_FLAGS_NONE, NULL,
1009 BT_HAL_PROPERTIES_INTERFACE,
1012 if (properties_proxy == NULL) {
1013 ERR("properties_proxy returned NULL");
1014 return BT_STATUS_FAIL;
1017 result = g_dbus_proxy_call_sync(properties_proxy,
1019 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1020 G_DBUS_CALL_FLAGS_NONE,
1025 if (error != NULL) {
1026 ERR("Fail to get properties (Error: %s)", error->message);
1027 g_clear_error(&error);
1029 ERR("Fail to get properties");
1030 g_object_unref(properties_proxy);
1031 return BT_STATUS_FAIL;
1034 gp_desc_array = g_ptr_array_new();
1036 g_variant_get(result, "(a{sv})", &property_iter);
1038 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1039 if (!g_strcmp0(key, "UUID")) {
1040 char_uuid_str = g_variant_dup_string(value, &len);
1041 DBG("char UUID [%s]", char_uuid_str);
1042 } else if (!g_strcmp0(key, "Flags")) {
1043 g_variant_get(value, "as", &char_perm_iter);
1044 char_permission = 0x00;
1046 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1047 DBG("char permission: [%s]", permission);
1048 char_permission |= _hal_get_permission_flag(permission);
1050 } else if (!g_strcmp0(key, "Descriptors")) {
1051 g_variant_get(value, "ao", &char_desc_iter);
1052 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1053 DBG("char descriptor handle : %s", char_desc_handle);
1055 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1060 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1062 g_free(char_uuid_str);
1063 g_variant_iter_free(property_iter);
1064 g_variant_unref(result);
1065 g_object_unref(properties_proxy);
1066 g_ptr_array_free(gp_desc_array, TRUE);
1068 return BT_STATUS_SUCCESS;
1071 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1072 btgatt_srvc_id_t *srvc_id)
1074 hal_gattc_server_info_t * conn_info = NULL;
1075 hal_gattc_service_t *gattc_service = NULL;
1077 hal_gattc_char_t *gattc_char = NULL;
1078 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1079 int status = BT_STATUS_FAIL;
1082 DBG("conn_id[%d]", conn_id);
1084 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1085 if (NULL == conn_info) {
1086 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1087 return BT_STATUS_FAIL;
1091 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1092 if (NULL == gattc_service) {
1093 DBG("Failed to get the gatt service");
1094 return BT_STATUS_FAIL;
1097 DBG("service path [%s]", gattc_service->svc_path);
1099 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1100 DBG("service uuid [%s]", svc_uuid_str);
1102 /* find characteristic object path */
1103 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1104 gattc_char = (hal_gattc_char_t *)l->data;
1105 status = _hal_gattc_get_characteristic_info(gattc_char);
1108 if (BT_STATUS_SUCCESS == status) {
1109 DBG("Sending the success charateristics event");
1110 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1111 &gattc_char->chr_uuid, gattc_char->permission);
1115 DBG("sending final event");
1117 status = BT_STATUS_FAIL;
1118 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1120 browse_service_char(conn_id);
1121 /* retrive uuid for characteristic and object path for descriptor */
1123 return BT_STATUS_SUCCESS;
1127 * Enumerate characteristics for a given service.
1128 * Set start_char_id to NULL to get the first characteristic.
1130 bt_status_t btif_gattc_get_characteristic(int conn_id,
1131 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1134 CHECK_BTGATT_INIT();
1136 if (start_char_id == NULL) {
1137 DBG("Get all the characteristics");
1138 return _gattc_get_all_characteristic(conn_id, srvc_id);
1141 DBG("TBD Get specific characteristics");
1142 return BT_STATUS_UNSUPPORTED;
1146 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1148 GDBusProxy *properties_proxy = NULL;
1149 GError *error = NULL;
1150 GVariant *value = NULL;
1151 GVariant *result = NULL;
1152 GDBusConnection *g_conn;
1155 GVariantIter *property_iter;
1156 char* desc_handle = NULL;
1157 const gchar *desc_uuid_str = NULL;
1161 if (gattc_desc->desc_path == NULL) {
1162 DBG("desc path is NULL");
1163 return BT_STATUS_FAIL;
1165 desc_handle = gattc_desc->desc_path;
1167 DBG("desc path:[%s]", gattc_desc->desc_path);
1169 g_conn = _bt_hal_get_system_gconn();
1170 if (NULL == g_conn) {
1171 ERR("_bt_gdbus_get_system_gconn returned NULL");
1172 return BT_STATUS_FAIL;
1175 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1176 G_DBUS_PROXY_FLAGS_NONE, NULL,
1179 BT_HAL_PROPERTIES_INTERFACE,
1182 if (properties_proxy == NULL) {
1183 ERR("properties_proxy returned NULL");
1184 return BT_STATUS_FAIL;
1187 result = g_dbus_proxy_call_sync(properties_proxy,
1189 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1190 G_DBUS_CALL_FLAGS_NONE,
1195 if (error != NULL) {
1196 ERR("Fail to get properties (Error: %s)", error->message);
1197 g_clear_error(&error);
1199 ERR("Fail to get properties");
1200 g_object_unref(properties_proxy);
1201 return BT_STATUS_FAIL;
1204 g_variant_get(result, "(a{sv})", &property_iter);
1206 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1207 if (!g_strcmp0(key, "UUID")) {
1208 desc_uuid_str = g_variant_get_string(value, &len);
1209 DBG("desc UUID [%s]", desc_uuid_str);
1210 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1215 g_variant_iter_free(property_iter);
1216 g_variant_unref(result);
1217 g_object_unref(properties_proxy);
1219 return BT_STATUS_SUCCESS;
1222 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1223 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1225 struct hal_ev_gatt_client_desc_search_result ev;
1228 ERR("gatt client callback not registered");
1232 DBG("sending gatt client search desc result event conn_id[%d] status[%d]", conn_id, status);
1234 memset(&ev, 0, sizeof(ev));
1235 ev.conn_id = conn_id;
1236 ev.inst_id = svc_id->id.inst_id;
1237 ev.is_primary = svc_id->is_primary;
1240 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1241 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1243 if (status == BT_STATUS_SUCCESS) {
1244 DBG("building desc uuid");
1245 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1248 DBG("sending the desc search event");
1250 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1253 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1254 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1256 hal_gattc_server_info_t * conn_info = NULL;
1257 hal_gattc_service_t *gattc_service = NULL;
1260 hal_gattc_char_t *gattc_char = NULL;
1261 hal_gattc_desc_t *gattc_desc = NULL;
1262 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1263 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1264 int status = BT_STATUS_FAIL;
1268 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1269 if (NULL == conn_info) {
1270 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1271 return BT_STATUS_FAIL;
1275 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1276 if (NULL == gattc_service) {
1277 DBG("Failed to get the gatt service");
1278 return BT_STATUS_FAIL;
1281 DBG("service path [%s]", gattc_service->svc_path);
1282 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1283 DBG("service uuid [%s]", svc_uuid_str);
1285 /* find characteristics */
1286 /* a service can have two char with same uuid */
1287 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1288 gattc_char = (hal_gattc_char_t*)l->data;
1289 if (gattc_char == NULL)
1292 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1293 INFO("Found GATT char uuid");
1294 DBG("char path [%s]", gattc_char->chr_path);
1295 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1296 DBG("char uuid [%s]", char_uuid_str);
1298 /* get descriptor uuid */
1299 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1300 gattc_desc = (hal_gattc_desc_t *)m->data;
1301 if (gattc_desc == NULL)
1304 status = _hal_gattc_get_descriptor_info(gattc_desc);
1307 if (BT_STATUS_SUCCESS == status) {
1308 DBG("Sending the success descriptor event");
1309 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1310 char_id, &gattc_desc->desc_uuid);
1316 DBG("sending final event");
1318 status = BT_STATUS_FAIL;
1319 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1321 browse_service_char(conn_id);
1322 /* retrive uuid for characteristic and object path for descriptor */
1324 return BT_STATUS_SUCCESS;
1328 * Enumerate descriptors for a given characteristic.
1329 * Set start_descr_id to NULL to get the first descriptor.
1331 bt_status_t btif_gattc_get_descriptor(int conn_id,
1332 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1333 btgatt_gatt_id_t *start_descr_id)
1336 CHECK_BTGATT_INIT();
1338 if (start_descr_id == NULL) {
1339 DBG("Get all the descriptors");
1340 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1342 DBG("TBD Get specific descriptor");
1343 return BT_STATUS_UNSUPPORTED;
1347 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1349 struct hal_ev_gatt_client_read_data ev;
1352 ERR("gatt client callback not registered");
1356 DBG("sending gatt client charac read conn_id[%d] status[%d]", resp_data->conn_id, result);
1358 memset(&ev, 0, sizeof(ev));
1359 ev.conn_id = resp_data->conn_id;
1360 ev.inst_id = resp_data->srvc_id.id.inst_id;
1361 ev.is_primary = resp_data->srvc_id.is_primary;
1364 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1365 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1369 DBG("building the char read value [%d]", len);
1370 memcpy(ev.value, value, len);
1373 DBG("sending the gatt client read charac event");
1375 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1378 static void __hal_internal_read_char_cb(GObject *source_object,
1379 GAsyncResult *res, gpointer user_data)
1381 GError *error = NULL;
1382 GDBusConnection *system_gconn = NULL;
1385 GByteArray *gp_byte_array = NULL;
1387 hal_gatt_resp_data_t *resp_data = user_data;
1388 int result = BT_STATUS_SUCCESS;
1393 system_gconn = _bt_hal_get_system_gconn();
1394 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1397 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1400 result = BT_STATUS_FAIL;
1401 __hal_send_char_read_event(resp_data, result, NULL, 0);
1402 g_clear_error(&error);
1407 gp_byte_array = g_byte_array_new();
1408 g_variant_get(value, "(ay)", &iter);
1410 while (g_variant_iter_loop(iter, "y", &g_byte))
1411 g_byte_array_append(gp_byte_array, &g_byte, 1);
1415 for (i = 0; i < gp_byte_array->len; i++)
1416 DBG("%02x", gp_byte_array->data[i]);
1419 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1423 g_byte_array_free(gp_byte_array, TRUE);
1424 g_variant_iter_free(iter);
1425 g_variant_unref(value);
1431 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1432 btgatt_gatt_id_t *char_id, int auth_req)
1434 GDBusConnection *g_conn;
1435 hal_gatt_resp_data_t *resp_data;
1436 hal_gattc_service_t *gattc_service = NULL;
1437 GVariantBuilder *builder = NULL;
1439 hal_gattc_server_info_t * conn_info = NULL;
1440 hal_gattc_char_t *gattc_char = NULL;
1441 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1442 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1443 char* char_handle = NULL;
1447 /* get the connection info */
1448 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1449 if (NULL == conn_info) {
1450 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1451 return BT_STATUS_FAIL;
1455 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1456 if (NULL == gattc_service) {
1457 DBG("Failed to get the gatt service");
1458 return BT_STATUS_FAIL;
1461 DBG("service path [%s]", gattc_service->svc_path);
1462 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1463 DBG("service uuid [%s]", svc_uuid_str);
1466 /* find characteristic */
1467 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1468 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1469 if (NULL == gattc_char) {
1470 DBG("Failed to get the gatt char");
1471 return BT_STATUS_FAIL;
1474 DBG("char path [%s]", gattc_char->chr_path);
1475 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1476 DBG("char uuid [%s]", char_uuid_str);
1478 g_conn = _bt_hal_get_system_gconn();
1479 if (NULL == g_conn) {
1480 ERR("_bt_gdbus_get_system_gconn returned NULL");
1481 return BT_STATUS_FAIL;
1484 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1485 resp_data->conn_id = conn_id;
1486 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1487 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1489 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1492 g_variant_builder_add(builder, "{sv}", "offset",
1493 g_variant_new("q", offset));
1495 char_handle = gattc_char->chr_path;
1497 DBG("calling char read value");
1499 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1500 "ReadValue", g_variant_new("(a{sv})", builder),
1501 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1502 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1503 (gpointer)resp_data);
1504 g_variant_builder_unref(builder);
1506 return BT_STATUS_SUCCESS;
1509 /** Read a characteristic on a remote device */
1510 bt_status_t btif_read_characteristic(int conn_id,
1511 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1514 CHECK_BTGATT_INIT();
1517 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1520 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1522 struct hal_ev_gatt_client_write_result ev;
1525 ERR("gatt client callback not registered");
1529 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
1531 memset(&ev, 0, sizeof(ev));
1532 ev.conn_id = resp_data->conn_id;
1533 ev.inst_id = resp_data->srvc_id.id.inst_id;
1534 ev.is_primary = resp_data->srvc_id.is_primary;
1537 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1538 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1540 DBG("sending the gatt client write charac event");
1542 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1545 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1546 GAsyncResult *res, gpointer user_data)
1548 GError *error = NULL;
1549 GDBusConnection *system_gconn = NULL;
1551 hal_gatt_resp_data_t *resp_data = user_data;
1552 int result = BT_STATUS_SUCCESS;
1556 system_gconn = _bt_hal_get_system_gconn();
1557 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1560 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1562 result = BT_STATUS_FAIL;
1564 __hal_send_char_write_event(resp_data, result);
1565 g_clear_error(&error);
1570 //send write value event
1571 __hal_send_char_write_event(resp_data, result);
1574 g_variant_unref(value);
1579 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1582 case HAL_GATT_WRITE_TYPE_WRITE:
1583 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1585 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1586 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1589 ERR("Unknow write type : %d", type);
1590 return BT_STATUS_FAIL;
1593 return BT_STATUS_SUCCESS;
1597 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1599 GDBusConnection *conn;
1600 GVariantBuilder *builder = NULL;
1606 GUnixFDList *fd_list = NULL;
1608 conn = _bt_hal_get_system_gconn();
1610 ERR("_bt_gdbus_get_system_gconn returned NULL");
1611 return BT_STATUS_FAIL;
1614 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1615 //val = g_variant_new("ay", builder1);
1617 g_variant_builder_add(builder, "{sv}", "offset",
1618 g_variant_new("q", offset));
1620 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1621 "AcquireWrite", g_variant_new("(a{sv})", builder),
1622 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1623 NULL, &fd_list, NULL, &err);
1625 g_dbus_error_strip_remote_error(err);
1626 ERR("Error: %s", err->message);
1628 g_variant_builder_unref(builder);
1629 return BT_STATUS_FAIL;
1632 g_variant_get(value, "(hq)", &idx, &att_mtu);
1633 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1635 INFO("FD is %d index is %d mtu is %d", *fd, idx, att_mtu);
1638 g_object_unref(fd_list);
1639 g_variant_unref(value);
1640 g_variant_builder_unref(builder);
1642 return BT_STATUS_SUCCESS;
1645 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1647 GDBusConnection *conn;
1648 GVariantBuilder *builder = NULL;
1652 gint32 idx, notify_fd;
1654 GUnixFDList *fd_list = NULL;
1656 conn = _bt_hal_get_system_gconn();
1659 ERR("_bt_gdbus_get_system_gconn returned NULL");
1660 return BT_STATUS_FAIL;
1664 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1667 g_variant_builder_add(builder, "{sv}", "offset",
1668 g_variant_new("q", offset));
1670 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1671 "AcquireNotify", g_variant_new("(a{sv})", builder),
1672 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1673 NULL, &fd_list, NULL, &err);
1675 g_dbus_error_strip_remote_error(err);
1676 ERR("Error: %s", err->message);
1678 g_variant_builder_unref(builder);
1679 return BT_STATUS_FAIL;
1682 g_variant_get(value, "(hq)", &idx, &att_mtu);
1683 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1686 INFO("Acquired characteristic Notify fd %d, mtu %d", notify_fd, *mtu);
1690 g_object_unref(fd_list);
1691 g_variant_unref(value);
1692 g_variant_builder_unref(builder);
1694 return BT_STATUS_SUCCESS;
1698 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1699 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1701 GVariant *val, *options;
1702 GVariantBuilder *builder1;
1703 GVariantBuilder *builder2;
1704 GDBusConnection *g_conn;
1707 hal_gatt_resp_data_t *resp_data;
1708 hal_gattc_service_t *gattc_service = NULL;
1709 hal_gattc_server_info_t * conn_info = NULL;
1710 hal_gattc_char_t *gattc_char = NULL;
1711 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1712 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1713 char* char_handle = NULL;
1714 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1715 int ret = BT_STATUS_SUCCESS;
1719 ret = __hal_get_write_prop(write_type, &write_prop);
1720 if (BT_STATUS_FAIL == ret) {
1721 DBG("received invalid write type:[%d] ", write_type);
1722 return BT_STATUS_FAIL;
1725 /* get the connection info */
1726 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1727 if (NULL == conn_info) {
1728 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1729 return BT_STATUS_FAIL;
1733 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1734 if (NULL == gattc_service) {
1735 DBG("Failed to get the gatt service");
1736 return BT_STATUS_FAIL;
1739 DBG("service path [%s]", gattc_service->svc_path);
1740 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1741 DBG("service uuid [%s]", svc_uuid_str);
1743 /* find characteristic */
1744 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1745 if (NULL == gattc_char) {
1746 DBG("Failed to get the gatt char");
1747 return BT_STATUS_FAIL;
1750 DBG("char path [%s]", gattc_char->chr_path);
1751 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1752 DBG("char uuid [%s]", char_uuid_str);
1754 g_conn = _bt_hal_get_system_gconn();
1755 if (NULL == g_conn) {
1756 ERR("_bt_gdbus_get_system_gconn returned NULL");
1757 return BT_STATUS_FAIL;
1760 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1761 resp_data->conn_id = conn_id;
1762 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1763 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1765 char_handle = gattc_char->chr_path;
1767 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1769 for (i = 0; i < length; i++)
1770 g_variant_builder_add(builder1, "y", value[i]);
1772 val = g_variant_new("ay", builder1);
1774 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1776 g_variant_builder_add(builder2, "{sv}", "offset",
1777 g_variant_new_uint16(offset));
1779 options = g_variant_new("a{sv}", builder2);
1781 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1783 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1785 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1786 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1787 (gpointer)resp_data);
1789 g_variant_builder_unref(builder1);
1790 g_variant_builder_unref(builder2);
1792 return BT_STATUS_SUCCESS;
1795 bt_status_t btif_get_acquire_write_fd(int conn_id,
1796 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1797 int auth_req, int *fd, int*mtu)
1799 CHECK_BTGATT_INIT();
1803 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1806 hal_gattc_service_t *gattc_service = NULL;
1807 hal_gattc_server_info_t * conn_info = NULL;
1808 hal_gattc_char_t *gattc_char = NULL;
1809 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1811 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1812 int ret = BT_STATUS_SUCCESS;
1816 /* get the connection info */
1817 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1818 if (NULL == conn_info) {
1819 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1820 return BT_STATUS_FAIL;
1824 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1825 if (NULL == gattc_service) {
1826 DBG("Failed to get the gatt service");
1827 return BT_STATUS_FAIL;
1830 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1831 if (NULL == gattc_char) {
1832 DBG("Failed to get the gatt char");
1833 return BT_STATUS_FAIL;
1836 DBG("char path [%s]", gattc_char->chr_path);
1837 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1838 DBG("char uuid [%s]", char_uuid_str);
1841 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1842 if (ret != BT_STATUS_SUCCESS)
1846 ERR("Characterstics FD erite characterstics fd is %d", *fd);
1851 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1852 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1854 CHECK_BTGATT_INIT();
1858 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1861 hal_gattc_service_t *gattc_service = NULL;
1862 hal_gattc_server_info_t * conn_info = NULL;
1863 hal_gattc_char_t *gattc_char = NULL;
1864 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1866 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1867 int ret = BT_STATUS_SUCCESS;
1871 /* get the connection info */
1872 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1873 if (NULL == conn_info) {
1874 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1875 return BT_STATUS_FAIL;
1879 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1880 if (NULL == gattc_service) {
1881 DBG("Failed to get the gatt service");
1882 return BT_STATUS_FAIL;
1885 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1886 if (NULL == gattc_char) {
1887 DBG("Failed to get the gatt char");
1888 return BT_STATUS_FAIL;
1891 DBG("char path [%s]", gattc_char->chr_path);
1892 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1893 DBG("char uuid [%s]", char_uuid_str);
1896 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1897 if (ret != BT_STATUS_SUCCESS)
1901 ERR("Characterstics FD write characterstics fd is %d", *fd);
1908 /** Write a remote characteristic */
1909 bt_status_t btif_write_characteristic(int conn_id,
1910 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1911 int write_type, int len, int auth_req,
1914 CHECK_BTGATT_INIT();
1918 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1919 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1920 len, auth_req, p_value);
1923 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1925 struct hal_ev_gatt_client_read_data ev;
1928 ERR("gatt client callback not registered");
1932 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1934 memset(&ev, 0, sizeof(ev));
1935 ev.conn_id = resp_data->conn_id;
1936 ev.inst_id = resp_data->srvc_id.id.inst_id;
1937 ev.is_primary = resp_data->srvc_id.is_primary;
1940 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1941 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1942 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1946 DBG("building the desc read value [%d]", len);
1947 memcpy(ev.value, value, len);
1950 DBG("sending the gatt client read descriptor event");
1952 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1955 static void __hal_internal_read_desc_cb(GObject *source_object,
1956 GAsyncResult *res, gpointer user_data)
1958 GError *error = NULL;
1959 GDBusConnection *system_gconn = NULL;
1962 GByteArray *gp_byte_array = NULL;
1964 hal_gatt_resp_data_t *resp_data = user_data;
1965 int result = BT_STATUS_SUCCESS;
1970 system_gconn = _bt_hal_get_system_gconn();
1971 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1974 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1977 result = BT_STATUS_FAIL;
1978 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1979 g_clear_error(&error);
1984 gp_byte_array = g_byte_array_new();
1985 g_variant_get(value, "(ay)", &iter);
1987 while (g_variant_iter_loop(iter, "y", &g_byte))
1988 g_byte_array_append(gp_byte_array, &g_byte, 1);
1992 for (i = 0; i < gp_byte_array->len; i++)
1993 DBG("%02x", gp_byte_array->data[i]);
1996 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2000 g_byte_array_free(gp_byte_array, TRUE);
2001 g_variant_iter_free(iter);
2002 g_variant_unref(value);
2007 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2008 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2010 GDBusConnection *g_conn;
2011 hal_gatt_resp_data_t *resp_data;
2012 hal_gattc_service_t *gattc_service = NULL;
2013 GVariantBuilder *builder = NULL;
2015 hal_gattc_server_info_t * conn_info = NULL;
2016 hal_gattc_char_t *gattc_char = NULL;
2017 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2018 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2019 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2020 char* desc_handle = NULL;
2023 hal_gattc_desc_t *gattc_desc = NULL;
2027 /* get the connection info */
2028 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2029 if (NULL == conn_info) {
2030 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
2031 return BT_STATUS_FAIL;
2035 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2036 if (NULL == gattc_service) {
2037 DBG("Failed to get the gatt service");
2038 return BT_STATUS_FAIL;
2041 DBG("service path [%s]", gattc_service->svc_path);
2042 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2043 DBG("service uuid [%s]", svc_uuid_str);
2045 /* find characteristic */
2046 /* service can have two char with same uuid */
2047 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2048 gattc_char = (hal_gattc_char_t*)l->data;
2049 if (gattc_char == NULL)
2052 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2053 INFO("Found GATT char uuid");
2054 DBG("char path [%s]", gattc_char->chr_path);
2055 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2056 DBG("char uuid [%s]", char_uuid_str);
2058 /* find descriptor */
2059 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2061 DBG("desc path [%s]", gattc_desc->desc_path);
2062 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2063 DBG("desc uuid [%s]", desc_uuid_str);
2069 if (NULL == gattc_desc) {
2070 DBG("Failed to get the gatt desc");
2071 return BT_STATUS_FAIL;
2074 g_conn = _bt_hal_get_system_gconn();
2075 if (NULL == g_conn) {
2076 ERR("_bt_gdbus_get_system_gconn returned NULL");
2077 return BT_STATUS_FAIL;
2080 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2081 resp_data->conn_id = conn_id;
2082 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2083 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2084 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2086 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2089 g_variant_builder_add(builder, "{sv}", "offset",
2090 g_variant_new("q", offset));
2092 desc_handle = gattc_desc->desc_path;
2094 DBG("calling desc read value");
2096 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2097 "ReadValue", g_variant_new("(a{sv})", builder),
2098 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2099 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2100 (gpointer)resp_data);
2101 g_variant_builder_unref(builder);
2103 return BT_STATUS_SUCCESS;
2106 /** Read the descriptor for a given characteristic */
2107 bt_status_t btif_read_descriptor(int conn_id,
2108 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2109 btgatt_gatt_id_t *descr_id, int auth_req)
2111 CHECK_BTGATT_INIT();
2113 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2116 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2118 struct hal_ev_gatt_client_write_result ev;
2121 ERR("gatt client callback not registered");
2125 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
2127 memset(&ev, 0, sizeof(ev));
2128 ev.conn_id = resp_data->conn_id;
2129 ev.inst_id = resp_data->srvc_id.id.inst_id;
2130 ev.is_primary = resp_data->srvc_id.is_primary;
2133 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2134 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2135 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2137 DBG("sending the gatt client write charac event");
2139 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2142 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2143 GAsyncResult *res, gpointer user_data)
2145 GError *error = NULL;
2146 GDBusConnection *system_gconn = NULL;
2148 hal_gatt_resp_data_t *resp_data = user_data;
2149 int result = BT_STATUS_SUCCESS;
2153 system_gconn = _bt_hal_get_system_gconn();
2154 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2157 ERR("write descriptor dbus failed Error: [%s]", error->message);
2160 result = BT_STATUS_FAIL;
2161 __hal_send_desc_write_event(resp_data, result);
2162 g_clear_error(&error);
2167 //send write value event
2168 __hal_send_desc_write_event(resp_data, result);
2171 g_variant_unref(value);
2176 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2177 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2178 int write_type, int length, int auth_req, char* value)
2180 GVariant *val, *options;
2181 GVariantBuilder *builder1;
2182 GVariantBuilder *builder2;
2183 GDBusConnection *g_conn;
2186 hal_gatt_resp_data_t *resp_data;
2187 hal_gattc_service_t *gattc_service = NULL;
2188 hal_gattc_server_info_t * conn_info = NULL;
2189 hal_gattc_char_t *gattc_char = NULL;
2190 hal_gattc_desc_t *gattc_desc = NULL;
2191 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2192 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2193 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2194 char* desc_handle = NULL;
2195 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2196 int ret = BT_STATUS_SUCCESS;
2201 ret = __hal_get_write_prop(write_type, &write_prop);
2202 if (BT_STATUS_FAIL == ret) {
2203 DBG("received invalid write type:[%d] ", write_type);
2204 return BT_STATUS_FAIL;
2207 /* get the connection info */
2208 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2209 if (NULL == conn_info) {
2210 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
2211 return BT_STATUS_FAIL;
2215 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2216 if (NULL == gattc_service) {
2217 DBG("Failed to get the gatt service");
2218 return BT_STATUS_FAIL;
2221 DBG("service path [%s]", gattc_service->svc_path);
2222 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2223 DBG("service uuid [%s]", svc_uuid_str);
2225 /* find characteristic */
2226 /* service can have two char with same uuid */
2227 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2228 gattc_char = (hal_gattc_char_t*)l->data;
2229 if (gattc_char == NULL)
2232 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2233 INFO("Found GATT char uuid");
2234 DBG("char path [%s]", gattc_char->chr_path);
2235 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2236 DBG("char uuid [%s]", char_uuid_str);
2238 /* find descriptor */
2239 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2241 DBG("desc path [%s]", gattc_desc->desc_path);
2242 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2243 DBG("desc uuid [%s]", desc_uuid_str);
2249 if (NULL == gattc_desc) {
2250 DBG("Failed to get the gatt desc");
2251 return BT_STATUS_FAIL;
2254 g_conn = _bt_hal_get_system_gconn();
2255 if (NULL == g_conn) {
2256 ERR("_bt_gdbus_get_system_gconn returned NULL");
2257 return BT_STATUS_FAIL;
2260 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2261 resp_data->conn_id = conn_id;
2262 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2263 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2264 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2266 desc_handle = gattc_desc->desc_path;
2268 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2270 for (i = 0; i < length; i++)
2271 g_variant_builder_add(builder1, "y", value[i]);
2273 val = g_variant_new("ay", builder1);
2275 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2277 g_variant_builder_add(builder2, "{sv}", "offset",
2278 g_variant_new_uint16(offset));
2280 options = g_variant_new("a{sv}", builder2);
2282 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2284 g_variant_new("(@ay@a{sv})", val, options),
2286 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2287 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2288 (gpointer)resp_data);
2290 g_variant_builder_unref(builder1);
2291 g_variant_builder_unref(builder2);
2293 return BT_STATUS_SUCCESS;
2296 /** Write a remote descriptor for a given characteristic */
2297 bt_status_t btif_write_descriptor(int conn_id,
2298 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2299 btgatt_gatt_id_t *descr_id, int write_type, int len,
2300 int auth_req, char* p_value)
2302 CHECK_BTGATT_INIT();
2304 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2305 len, auth_req, p_value);
2308 /** Execute a prepared write operation */
2309 bt_status_t execute_write(int conn_id, int execute)
2311 CHECK_BTGATT_INIT();
2312 return BT_STATUS_UNSUPPORTED;
2315 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2317 struct hal_ev_gatt_client_watch_notification ev;
2318 hal_gatt_resp_data_t *resp_data = user_data;
2320 DBG("sending the watch register notification event");
2321 /* send the event */
2322 memset(&ev, 0, sizeof(ev));
2323 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2325 ev.status = resp_data->result;
2327 ev.is_primary = resp_data->srvc_id.is_primary;
2328 ev.inst_id = resp_data->srvc_id.id.inst_id;
2330 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2331 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2334 ERR("GATT Callback not registered");
2336 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2343 static bt_status_t _hal_register_for_notification(int client_if,
2344 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2345 btgatt_gatt_id_t *char_id)
2347 int result = BT_STATUS_SUCCESS;
2348 GError *error = NULL;
2349 GDBusConnection *g_conn;
2350 hal_gattc_client_info_t *gattc_client = NULL;
2351 hal_gattc_server_info_t * conn_info = NULL;
2352 hal_gattc_service_t *gattc_service = NULL;
2353 hal_gattc_char_t *gattc_char = NULL;
2354 char* char_handle = NULL;
2355 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2356 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2357 hal_gatt_resp_data_t *resp_data;
2361 gattc_client = __bt_find_gatt_client_info(bd_addr);
2362 if (gattc_client == NULL) {
2363 ERR("failed to get the gatt client info");
2364 return BT_STATUS_FAIL;
2367 if (gattc_client->client_if != client_if) {
2368 ERR("could not find the gatt client for client id[%d]", client_if);
2369 return BT_STATUS_FAIL;
2372 /* get the connection info */
2373 conn_info = __bt_find_gatt_conn_info(bd_addr);
2374 if (NULL == conn_info) {
2375 ERR("Failed to get the conn_info");
2376 return BT_STATUS_FAIL;
2379 if (conn_info->inst_id != gattc_client->inst_id) {
2380 ERR("could not fild the conn_info");
2381 return BT_STATUS_FAIL;
2385 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2386 if (NULL == gattc_service) {
2387 DBG("Failed to get the gatt service");
2388 return BT_STATUS_FAIL;
2391 DBG("service path [%s]", gattc_service->svc_path);
2392 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2393 DBG("service uuid [%s]", svc_uuid_str);
2396 /* find characteristic */
2397 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2398 if (NULL == gattc_char) {
2399 DBG("Failed to get the gatt char");
2400 return BT_STATUS_FAIL;
2403 DBG("char path [%s]", gattc_char->chr_path);
2404 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2405 DBG("char uuid [%s]", char_uuid_str);
2407 char_handle = gattc_char->chr_path;
2409 g_conn = _bt_hal_get_system_gconn();
2410 if (g_conn == NULL) {
2412 return BT_STATUS_FAIL;
2415 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2417 DBG("#StartNotify");
2418 g_dbus_connection_call_sync(g_conn,
2421 BT_HAL_GATT_CHAR_INTERFACE,
2425 G_DBUS_CALL_FLAGS_NONE,
2426 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2429 g_dbus_error_strip_remote_error(error);
2430 ERR("### Watch Failed: %s", error->message);
2431 if (g_strrstr(error->message, "Already notifying"))
2432 result = BT_STATUS_SUCCESS;
2433 else if (g_strrstr(error->message, "In Progress"))
2434 result = BT_STATUS_BUSY;
2435 else if (g_strrstr(error->message, "Operation is not supported"))
2436 result = BT_STATUS_UNSUPPORTED;
2437 /*failed because of either Insufficient Authorization or Write Not Permitted */
2438 else if (g_strrstr(error->message, "Write not permitted") ||
2439 g_strrstr(error->message, "Operation Not Authorized"))
2440 result = BT_STATUS_AUTH_FAILURE;
2441 /* failed because of either Insufficient Authentication,
2442 Insufficient Encryption Key Size, or Insufficient Encryption. */
2443 else if (g_strrstr(error->message, "Not paired"))
2444 result = BT_STATUS_NOT_READY;
2446 result = BT_STATUS_FAIL;
2448 g_clear_error(&error);
2451 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2452 resp_data->result = result;
2453 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2454 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2456 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2460 return BT_STATUS_SUCCESS;
2464 * Register to receive notifications or indications for a given
2467 bt_status_t btif_register_for_notification(int client_if,
2468 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2469 btgatt_gatt_id_t *char_id)
2471 CHECK_BTGATT_INIT();
2473 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2476 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2478 struct hal_ev_gatt_client_watch_notification ev;
2479 hal_gatt_resp_data_t *resp_data = user_data;
2481 DBG("sending the watch deregister notification event");
2482 /* send the event */
2483 memset(&ev, 0, sizeof(ev));
2484 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2486 ev.status = resp_data->result;
2488 ev.is_primary = resp_data->srvc_id.is_primary;
2489 ev.inst_id = resp_data->srvc_id.id.inst_id;
2491 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2492 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2495 ERR("GATT Callback not registered");
2497 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2504 static bt_status_t _hal_deregister_for_notification(int client_if,
2505 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2506 btgatt_gatt_id_t *char_id)
2508 int result = BT_STATUS_SUCCESS;
2509 GError *error = NULL;
2510 GDBusConnection *g_conn;
2511 hal_gattc_client_info_t *gattc_client = NULL;
2512 hal_gattc_server_info_t * conn_info = NULL;
2513 hal_gattc_service_t *gattc_service = NULL;
2514 hal_gattc_char_t *gattc_char = NULL;
2515 char* char_handle = NULL;
2516 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2517 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2518 hal_gatt_resp_data_t *resp_data;
2522 gattc_client = __bt_find_gatt_client_info(bd_addr);
2523 if (gattc_client == NULL) {
2524 ERR("failed to get the gatt client info");
2525 return BT_STATUS_FAIL;
2528 if (gattc_client->client_if != client_if) {
2529 ERR("could not find the gatt client for client id[%d]", client_if);
2530 return BT_STATUS_FAIL;
2533 /* get the connection info */
2534 conn_info = __bt_find_gatt_conn_info(bd_addr);
2535 if (NULL == conn_info) {
2536 ERR("Failed to get the conn_info");
2537 return BT_STATUS_FAIL;
2540 if (conn_info->inst_id != gattc_client->inst_id) {
2541 ERR("could not fild the conn_info");
2542 return BT_STATUS_FAIL;
2546 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2547 if (NULL == gattc_service) {
2548 DBG("Failed to get the gatt service");
2549 return BT_STATUS_FAIL;
2552 DBG("service path [%s]", gattc_service->svc_path);
2553 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2554 DBG("service uuid [%s]", svc_uuid_str);
2557 /* find characteristic */
2558 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2559 if (NULL == gattc_char) {
2560 DBG("Failed to get the gatt char");
2561 return BT_STATUS_FAIL;
2564 DBG("char path [%s]", gattc_char->chr_path);
2565 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2566 DBG("char uuid [%s]", char_uuid_str);
2568 char_handle = gattc_char->chr_path;
2570 g_conn = _bt_hal_get_system_gconn();
2571 if (g_conn == NULL) {
2573 return BT_STATUS_FAIL;
2576 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2578 DBG("#StartNotify");
2579 g_dbus_connection_call_sync(g_conn,
2582 BT_HAL_GATT_CHAR_INTERFACE,
2586 G_DBUS_CALL_FLAGS_NONE,
2587 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2590 ERR("### Watch Failed: %s", error->message);
2591 g_clear_error(&error);
2592 result = BT_STATUS_FAIL;
2595 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2596 resp_data->result = result;
2597 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2598 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2600 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2604 return BT_STATUS_SUCCESS;
2606 /** Deregister a previous request for notifications/indications */
2607 bt_status_t btif_deregister_for_notification(int client_if,
2608 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2609 btgatt_gatt_id_t *char_id)
2611 CHECK_BTGATT_INIT();
2612 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2615 /** Request RSSI for a given remote device */
2616 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2618 CHECK_BTGATT_INIT();
2619 return BT_STATUS_UNSUPPORTED;
2622 /** OTA firmware download */
2623 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2625 CHECK_BTGATT_INIT();
2626 return BT_STATUS_UNSUPPORTED;
2629 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2630 int get_device_type(const bt_bdaddr_t *bd_addr)
2632 CHECK_BTGATT_INIT();
2633 return BT_STATUS_UNSUPPORTED;
2636 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2637 int min_int, int max_int, int latency, int timeout)
2639 gchar *device_path = NULL;
2640 GError *error = NULL;
2641 GDBusProxy *device_proxy = NULL;
2642 GDBusConnection *conn;
2644 int ret = BT_STATUS_SUCCESS;
2645 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2647 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2648 min_int, max_int, latency, timeout);
2650 conn = _bt_hal_get_system_gconn();
2653 return BT_STATUS_FAIL;
2656 _bt_hal_convert_addr_type_to_string(device_address,
2657 (unsigned char *)bd_addr->address);
2658 device_path = _bt_hal_get_device_object_path(device_address);
2660 if (device_path == NULL) {
2661 ERR("device_path NULL : [%s]", device_address);
2662 return BT_STATUS_FAIL;
2665 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2666 NULL, BT_HAL_BLUEZ_NAME,
2667 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2669 g_free(device_path);
2670 if (NULL == device_proxy) {
2671 ERR("device_proxy returned NULL");
2672 return BT_STATUS_FAIL;
2675 INFO("### LeConnUpdate");
2676 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2677 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2678 G_DBUS_CALL_FLAGS_NONE,
2683 g_object_unref(device_proxy);
2684 if (reply == NULL) {
2686 ERR("Error %s[%s]", error->message, device_address);
2687 if (g_strrstr(error->message, "In Progress"))
2688 ret = BT_STATUS_SUCCESS;
2690 ret = BT_STATUS_FAIL;
2691 g_error_free(error);
2695 g_variant_unref(reply);
2697 INFO("LE Connection parameter Updated");
2701 /** Request a connection parameter update */
2702 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2704 CHECK_BTGATT_INIT();
2708 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2711 /** Test mode interface */
2712 bt_status_t test_command(int command, btgatt_test_params_t* params)
2714 CHECK_BTGATT_INIT();
2715 return BT_STATUS_UNSUPPORTED;
2718 /** MTU Exchange request from client */
2719 bt_status_t configure_mtu(int conn_id, int mtu)
2721 CHECK_BTGATT_INIT();
2722 return BT_STATUS_UNSUPPORTED;
2725 /** Setup scan filter params */
2726 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2727 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2728 int rssi_low_thres, int dely_mode, int found_timeout,
2729 int lost_timeout, int found_timeout_cnt)
2731 CHECK_BTGATT_INIT();
2732 return BT_STATUS_UNSUPPORTED;
2735 /** Configure a scan filter condition */
2736 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2737 int filt_index, int company_id,
2738 int company_id_mask, const bt_uuid_t *p_uuid,
2739 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2740 char addr_type, int data_len, char* p_data, int mask_len,
2743 CHECK_BTGATT_INIT();
2744 return BT_STATUS_UNSUPPORTED;
2747 /** Clear all scan filter conditions for specific filter index*/
2748 bt_status_t scan_filter_clear(int client_if, int filt_index)
2750 CHECK_BTGATT_INIT();
2751 return BT_STATUS_UNSUPPORTED;
2754 /** Enable / disable scan filter feature*/
2755 bt_status_t scan_filter_enable(int client_if, bool enable)
2757 CHECK_BTGATT_INIT();
2758 return BT_STATUS_UNSUPPORTED;
2761 /** Sets the LE scan interval and window in units of N*0.625 msec */
2763 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
2767 CHECK_BTGATT_INIT();
2769 le_scan_type = scan_type;
2770 ret = _bt_hal_adapter_le_set_scan_parameters(
2771 scan_type, scan_interval, scan_window);
2775 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
2777 CHECK_BTGATT_INIT();
2778 return BT_STATUS_UNSUPPORTED;
2782 /* Configure the batchscan storage */
2783 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
2784 int batch_scan_trunc_max, int batch_scan_notify_threshold)
2786 CHECK_BTGATT_INIT();
2787 return BT_STATUS_UNSUPPORTED;
2790 /* Enable batchscan */
2791 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
2792 int scan_interval, int scan_window, int addr_type, int discard_rule)
2794 CHECK_BTGATT_INIT();
2795 return BT_STATUS_UNSUPPORTED;
2798 /* Disable batchscan */
2799 bt_status_t batchscan_dis_batch_scan(int client_if)
2801 CHECK_BTGATT_INIT();
2802 return BT_STATUS_UNSUPPORTED;
2805 /* Read out batchscan reports */
2806 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
2808 CHECK_BTGATT_INIT();
2809 return BT_STATUS_UNSUPPORTED;
2812 const btgatt_client_interface_t btgatt_client_interface = {
2813 .register_client = btif_gattc_register_client,
2814 .unregister_client = btif_gattc_unregister_client,
2816 .connect = btif_gattc_client_connect,
2817 .disconnect = btif_gattc_client_disconnect,
2819 .search_service = btif_gattc_client_search_service,
2820 .get_included_service = get_included_service,
2821 .get_characteristic = btif_gattc_get_characteristic,
2822 .get_descriptor = btif_gattc_get_descriptor,
2823 .read_characteristic = btif_read_characteristic,
2824 .write_characteristic = btif_write_characteristic,
2825 .acquire_write = btif_get_acquire_write_fd,
2826 .acquire_notify = btif_get_acquire_notify_fd,
2827 .read_descriptor = btif_read_descriptor,
2828 .write_descriptor = btif_write_descriptor,
2829 .execute_write = execute_write,
2830 .register_for_notification = btif_register_for_notification,
2831 .deregister_for_notification = btif_deregister_for_notification,
2832 .read_remote_rssi = read_remote_rssi,
2833 .ota_fw_update = ota_fw_update,
2834 .get_device_type = get_device_type,
2835 .conn_parameter_update = btif_gattc_conn_parameter_update,
2836 .test_command = test_command,
2837 .configure_mtu = configure_mtu,
2838 .scan_filter_param_setup = scan_filter_param_setup,
2839 .scan_filter_add_remove = scan_filter_add_remove,
2840 .scan_filter_clear = scan_filter_clear,
2841 .scan_filter_enable = scan_filter_enable,
2842 .set_scan_parameters = set_scan_parameters,
2843 .batchscan_cfg_storage = batchscan_cfg_storage,
2844 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
2845 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
2846 .batchscan_read_reports = batchscan_read_reports
2849 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr)
2854 hal_gattc_server_info_t *info = NULL;
2856 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
2857 info = (hal_gattc_server_info_t*)l->data;
2861 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
2862 INFO("GATT connection found addr");
2869 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
2874 hal_gattc_client_info_t *info = NULL;
2876 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
2877 info = (hal_gattc_client_info_t*)l->data;
2881 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
2882 INFO("GATT client info found addr");
2889 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
2894 hal_gattc_client_info_t *info = NULL;
2896 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
2897 info = (hal_gattc_client_info_t*)l->data;
2901 if (info->conn_id == conn_id) {
2902 INFO("GATT client info found for conn_id [%d]", conn_id);
2909 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
2914 hal_gattc_server_info_t *info = NULL;
2915 hal_gattc_client_info_t *gattc_client = NULL;
2917 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2918 if (gattc_client == NULL) {
2919 INFO("GATT client conn info not found");
2923 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
2924 info = (hal_gattc_server_info_t*)l->data;
2928 if ((info->inst_id == gattc_client->inst_id) &&
2929 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
2930 INFO("GATT connection found for conn_id [%d]", conn_id);
2937 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
2938 gboolean auto_connect)
2940 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2941 gchar *device_path = NULL;
2942 GDBusProxy *device_proxy = NULL;
2943 GDBusConnection *conn;
2944 int ret = BT_STATUS_SUCCESS;
2945 hal_gattc_client_info_t *gattc_data;
2949 if (NULL == bd_addr) {
2950 ERR("bd_addr is NULL");
2951 return BT_STATUS_PARM_INVALID;
2954 conn = _bt_hal_get_system_gconn();
2956 ERR("_bt_gdbus_get_system_gconn returned NULL");
2957 return BT_STATUS_FAIL;
2960 _bt_hal_convert_addr_type_to_string(device_address,
2961 (unsigned char *)bd_addr->address);
2962 device_path = _bt_hal_get_device_object_path(device_address);
2963 if (device_path == NULL) {
2964 ERR("device_path NULL : [%s]", device_address);
2965 ret = BT_STATUS_FAIL;
2968 ERR("device_path:%s", device_path);
2970 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2971 NULL, BT_HAL_BLUEZ_NAME,
2972 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2973 g_free(device_path);
2974 if (NULL == device_proxy) {
2975 ERR("device_proxy returned NULL");
2976 return BT_STATUS_FAIL;
2979 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
2980 memcpy(gattc_data->bd_addr.address, bd_addr->address,
2981 BT_HAL_ADDRESS_LENGTH_MAX);
2983 DBG("Connect LE [%s]", device_address);
2985 gattc_data->client_if = client_if;
2987 g_dbus_proxy_call(device_proxy, "ConnectLE",
2988 g_variant_new("(b)", auto_connect),
2989 G_DBUS_CALL_FLAGS_NONE,
2990 BT_HAL_MAX_DBUS_TIMEOUT,
2992 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
2998 g_object_unref(device_proxy);
3005 static bt_status_t _bt_hold_current_advertising()
3007 int ret = BT_STATUS_FAIL;
3008 gboolean is_advertising = FALSE;
3011 is_advertising = _bt_hal_is_advertising_in_slot(0);
3012 if (is_advertising) {
3013 DBG("+ Stop current advertising");
3015 ret = _bt_hal_enable_advertising(0, FALSE, FALSE);
3016 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3022 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3024 DBG("+ start current advertising");
3026 _bt_hal_enable_advertising(0, TRUE, FALSE);
3031 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3033 DBG("Try to initiate pending LE connection");
3035 pending_le_conn_timer_id = 0;
3037 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3038 &pending_le_conn_info->bd_addr,
3039 pending_le_conn_info->auto_connect);
3041 g_free(pending_le_conn_info);
3042 pending_le_conn_info = NULL;
3047 static int __hal_generate_conn_id()
3049 return ++bt_conn_id;
3052 static int __hal_generate_server_instance_id()
3054 return ++bt_inst_id;
3057 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3060 GError *g_error = NULL;
3061 GVariant *reply = NULL;
3062 hal_gattc_client_info_t *gattc_data = user_data;
3063 int result = BT_STATUS_SUCCESS;
3064 struct hal_ev_gatt_client_connected ev;
3065 hal_gattc_server_info_t *gatt_conn_info = NULL;
3069 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3070 g_object_unref(proxy);
3071 if (reply == NULL) {
3072 ERR("Connect LE Dbus Call Error");
3074 ERR("Error: %s\n", g_error->message);
3075 g_clear_error(&g_error);
3077 result = BT_STATUS_FAIL;
3079 g_variant_unref(reply);
3081 if (NULL == gattc_data) {
3082 ERR("server_data is NULL");
3087 if (result == BT_STATUS_FAIL) {
3088 memset(&ev, 0, sizeof(ev));
3091 ev.client_if = gattc_data->client_if;
3092 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3093 BT_HAL_ADDRESS_LENGTH_MAX);
3096 ERR("gatt client callback not registered");
3098 DBG("sending gatt client connected event");
3099 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3105 DBG("adding the server conn info in list");
3106 gattc_data->conn_id = __hal_generate_conn_id() ;
3107 gattc_data->inst_id = __hal_generate_server_instance_id();
3109 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3111 /*add gatt server connection info*/
3112 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3113 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3114 gatt_conn_info->inst_id = gattc_data->inst_id;
3115 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3121 /*remove conn_info*/
3126 void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3128 g_free(svc_info->svc_path);
3132 void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3134 g_free(char_info->chr_path);
3138 void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3140 g_free(desc_info->desc_path);
3144 void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3149 hal_gattc_service_t *svc_info = NULL;
3150 hal_gattc_char_t *char_info = NULL;
3151 hal_gattc_desc_t *desc_info = NULL;
3155 for (l = conn_info->gatt_list_services; l != NULL;) {
3156 svc_info = (hal_gattc_service_t*)l->data;
3157 if (svc_info == NULL)
3159 l = g_slist_next(l);
3161 for (m = svc_info->gatt_list_chars; m != NULL; ) {
3162 char_info = (hal_gattc_char_t*)m->data;
3163 if (char_info == NULL)
3165 m = g_slist_next(m);
3167 for (k = char_info->gatt_list_descs; k != NULL; ) {
3168 desc_info = (hal_gattc_desc_t*)k->data;
3169 if (desc_info == NULL)
3171 k = g_slist_next(k);
3173 /*remove desc element*/
3174 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3175 __hal_gattc_free_desc_info(desc_info);
3178 /*remove desc list*/
3179 g_slist_free(char_info->gatt_list_descs);
3180 char_info->gatt_list_descs = NULL;
3182 /*remove char element*/
3183 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3184 __hal_gattc_free_char_info(char_info);
3187 /*remove char list*/
3188 g_slist_free(svc_info->gatt_list_chars);
3189 svc_info->gatt_list_chars = NULL;
3191 /*remove svc element*/
3192 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3193 __hal_gattc_free_svc_info(svc_info);
3196 /*remove svc list */
3197 g_slist_free(conn_info->gatt_list_services);
3198 conn_info->gatt_list_services = NULL;
3200 /*remove conn info*/
3204 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3206 int result = BT_STATUS_SUCCESS;
3207 struct hal_ev_gatt_client_connected ev;
3208 hal_gattc_server_info_t *conn_info = NULL;
3209 bt_bdaddr_t bd_addr;
3211 hal_gattc_client_info_t *gattc_client = NULL;
3215 DBG("+ connected device address [%s]", address);
3217 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3218 HAL_EV_GATT_CLIENT_DISCONNECTED;
3220 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3221 /* find the gatt client info */
3222 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3223 if (NULL == gattc_client) {
3224 ERR("Fail to get gatt client info");
3229 memset(&ev, 0, sizeof(ev));
3230 ev.conn_id = gattc_client->conn_id;
3232 ev.client_if = gattc_client->client_if;
3233 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3234 BT_HAL_ADDRESS_LENGTH_MAX);
3237 ERR("gatt client callback not registered");
3239 DBG("sending gatt client connected status event");
3240 event_cb(event, (void *)&ev, sizeof(ev));
3243 if (!gatt_connected) {
3244 inst_id = gattc_client->inst_id;
3246 /* remove the gatt client info from the client list also*/
3247 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3248 g_free(gattc_client);
3250 //find the connected server info
3251 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3252 if (NULL == conn_info) {
3253 ERR("Fail to get gatt server info");
3257 if (inst_id != conn_info->inst_id) {
3258 ERR("server instance is different");
3262 //remove gatt conn info from the server list
3263 DBG("remove the server conn_info from list after gatt disconnection");
3264 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3265 __hal_clean_gattc_server_info(conn_info);
3271 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3272 const char* uuid_str, int inst_id)
3274 struct hal_ev_gatt_client_search_result ev;
3277 ERR("gatt client callback not registered");
3281 DBG("sending gatt client search service result event conn_id[%d]", conn_id);
3283 memset(&ev, 0, sizeof(ev));
3284 ev.conn_id = conn_id;
3285 ev.inst_id = inst_id;
3286 ev.is_primary = is_primary;
3287 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3289 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3292 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3294 struct hal_ev_gatt_client_search_complete ev;
3297 ERR("gatt client callback not registered");
3301 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3304 memset(&ev, 0, sizeof(ev));
3305 ev.conn_id = conn_id;
3308 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3311 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3312 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3313 char *char_value, int len)
3315 struct hal_ev_gatt_client_notify_changed_value ev;
3316 hal_gattc_client_info_t *gattc_client = NULL;
3319 ERR("gatt client callback not registered");
3323 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3324 if (NULL == gattc_client) {
3325 ERR("failed to get the gatt client info");
3330 DBG("sending gatt client connected status event");
3331 memset(&ev, 0, sizeof(ev));
3333 ev.conn_id = gattc_client->conn_id;
3334 ev.inst_id = conn_info->inst_id;
3335 ev.is_primary = svc_info->is_primary;
3336 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3337 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3339 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3341 if (len > 0 && (char_value != NULL)) {
3342 memcpy(ev.value, char_value, len);
3346 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3349 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3350 char *char_value, int len)
3352 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3353 hal_gattc_server_info_t *conn_info = NULL;
3354 bt_bdaddr_t bd_addr;
3357 hal_gattc_service_t *svc_info = NULL;
3358 hal_gattc_char_t *char_info = NULL;
3362 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3363 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3364 DBG("device address:[%s]", device_address);
3365 DBG("char handle:[%s]", char_handle);
3367 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3368 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3370 if (conn_info != NULL) {
3371 //find service for notified char path
3372 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3373 svc_info = (hal_gattc_service_t*)l->data;
3374 if (svc_info == NULL)
3377 /* find characteristic object path */
3378 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3379 char_info = (hal_gattc_char_t *)k->data;
3380 if (char_info == NULL)
3383 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3384 DBG("Found char handle[%s]", char_info->chr_path);
3387 _bt_hal_send_value_changed_event(conn_info, svc_info,
3388 char_info, char_value, len);