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*/
127 int inst_id; /*server instance id*/
128 gboolean is_gatt_connected; /*status for GattConnected signal*/
129 GSList *gatt_list_services;
130 } hal_gattc_server_info_t;
132 /* Linked List of connected GATT server */
133 static GSList *hal_gattc_server_info_list = NULL;
137 bt_bdaddr_t bd_addr; /*remote server address*/
140 gboolean is_gatt_connected; /*status for GattConnected signal*/
141 } hal_gattc_client_info_t;
143 /* Linked list of connected GATT client connection */
144 static GSList * hal_gattc_client_info_list = NULL;
146 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
147 static guint pending_le_conn_timer_id = 0;
148 static int bt_conn_id = 0;
149 static int bt_inst_id = 0;
151 /* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
152 /* TODO: Adjust MAX Client after modifying MAX app handle logic */
153 #define BT_GATTC_CL_MAX 11
155 static int assigned_if = 0;
156 static gboolean client_if_used[BT_GATTC_CL_MAX];
161 btgatt_srvc_id_t srvc_id;
162 btgatt_gatt_id_t char_id;
163 btgatt_gatt_id_t desc_id;
164 } hal_gatt_resp_data_t;
169 } hal_gatt_client_app;
171 static GSList * hal_gattc_client_app_list = NULL;
178 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
179 gboolean auto_connect);
180 static bt_status_t _bt_hold_current_advertising();
181 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
182 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
183 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
185 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
186 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
187 const char* uuid_str, int inst_id);
188 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
189 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr);
190 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
191 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
193 void _bt_hal_gatt_client_init(void)
196 memset(client_if_used, 0x00, sizeof(client_if_used));
199 static int __bt_hal_gatt_assign_if(void)
203 index = assigned_if + 1;
205 if (index >= BT_GATTC_CL_MAX)
208 while (client_if_used[index] == TRUE) {
209 if (index == assigned_if) {
210 /* No available ID */
211 ERR("All interface ID is used");
217 if (index >= BT_GATTC_CL_MAX)
222 client_if_used[index] = TRUE;
227 static void __bt_hal_gatt_delete_if(int client_if)
229 if (client_if >= BT_GATTC_CL_MAX || client_if < 0)
232 client_if_used[client_if] = FALSE;
236 /* To send stack event to hal-av handler */
237 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
242 void _bt_hal_unregister_gatt_client_handler_cb(void)
248 int _bt_hal_gatt_client_get_le_scan_type(void)
254 static gboolean __bt_hal_register_client_cb(gpointer user_data)
256 struct hal_ev_gatt_client_registered ev;
257 hal_gatt_client_app *client_info = user_data;
259 /* Prepare to send AV connecting event */
260 memset(&ev, 0, sizeof(ev));
261 ev.status = BT_STATUS_SUCCESS;
262 ev.client_if = client_info->client_if;
263 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
266 ERR("GATT Callback not registered");
268 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
269 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
276 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
280 hal_gatt_client_app *info = NULL;
281 hal_gatt_client_app *gattc_app = NULL;
283 //check if client app is already registered
284 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
285 info = (hal_gatt_client_app*)l->data;
289 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
290 DBG("gatt client app already registered");
295 client_if = __bt_hal_gatt_assign_if();
296 if (client_if == -1) {
297 ERR("Fail to allocate the client if");
301 DBG("adding the gatt client app");
304 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
305 gattc_app->client_if = client_if;
306 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
308 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
313 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
315 hal_gatt_client_app *gattc_app = NULL;
316 hal_gatt_client_app *client_app_info = NULL;
318 /* add gatt client in list */
319 gattc_app = __hal_gattc_add_client_app(app_uuid);
320 if (gattc_app == NULL) {
321 ERR("Failed to register gatt client app");
322 return BT_STATUS_FAIL;
326 client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
327 client_app_info->client_if = gattc_app->client_if;
328 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
329 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
331 DBG("registered client client_if [%d]", client_app_info->client_if);
333 return BT_STATUS_SUCCESS;
336 /** Registers a GATT client application with the stack */
337 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
341 return __hal_gattc_register_client_app(uuid);
344 bt_status_t btif_gattc_add_connection_info(const bt_bdaddr_t *bd_addr, int conn_id, int server_inst_id)
346 hal_gattc_client_info_t *client_info = NULL;
347 hal_gattc_server_info_t *server_info = NULL;
349 /* Add client connection info in list */
350 client_info = g_malloc0(sizeof(hal_gattc_client_info_t));
351 client_info->client_if = -1;
352 memcpy(client_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
353 client_info->conn_id = conn_id;
354 client_info->inst_id = server_inst_id;
355 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, client_info);
356 DBG("Added client connection info in list");
358 /* Add server connection info in list */
359 server_info = __bt_find_gatt_conn_info(bd_addr);
360 if (server_info == NULL) {
361 server_info = g_malloc0(sizeof(hal_gattc_server_info_t));
362 memcpy(server_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
363 server_info->conn_id = conn_id;
364 server_info->inst_id = server_inst_id;
365 server_info->is_gatt_connected = TRUE;
366 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, server_info);
367 DBG("Added server connection info in list");
370 return BT_STATUS_SUCCESS;
373 bt_status_t __hal_gattc_unregister_client(int client_if)
376 hal_gatt_client_app *info = NULL;
378 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
380 /* remove the gatt client app */
381 for (l = hal_gattc_client_app_list; l != NULL; ) {
382 info = (hal_gatt_client_app*)l->data;
388 if (info->client_if == client_if) {
389 DBG("gatt client app found");
391 __bt_hal_gatt_delete_if(client_if);
393 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
398 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
399 return BT_STATUS_SUCCESS;
402 /** Unregister a client application from the stack */
403 bt_status_t btif_gattc_unregister_client(int client_if)
407 return __hal_gattc_unregister_client(client_if);
410 /** Start or stop LE device scanning */
411 bt_status_t scan(int client_if, bool start)
418 ret = _bt_hal_adapter_le_start_scan();
420 ret = _bt_hal_adapter_le_stop_scan();
425 /** Create a connection to a remote LE or dual-mode device */
426 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
429 int ret = BT_STATUS_SUCCESS;
434 return BT_STATUS_PARM_INVALID;
436 ret = _bt_hold_current_advertising();
437 if (ret == BT_STATUS_SUCCESS) {
438 DBG("Current advertising is held");
439 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
440 pending_le_conn_info->client_if = client_if;
441 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
442 BT_HAL_ADDRESS_LENGTH_MAX);
443 pending_le_conn_info->auto_connect = is_direct;
445 pending_le_conn_timer_id =
446 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
448 return BT_STATUS_SUCCESS;
450 ERR("advertising is not stopped");
453 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
457 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
460 GError *g_error = NULL;
461 GVariant *reply = NULL;
462 hal_gattc_client_info_t *gatt_conn_info = user_data;
463 int result = BT_STATUS_SUCCESS;
464 struct hal_ev_gatt_client_connected ev;
468 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
469 g_object_unref(proxy);
471 ERR("Connect LE Dbus Call Error");
473 ERR("Error: %s\n", g_error->message);
474 g_clear_error(&g_error);
476 result = BT_STATUS_FAIL;
478 g_variant_unref(reply);
480 if (NULL == gatt_conn_info) {
481 ERR("server_data is NULL");
486 if (result == BT_STATUS_FAIL) {
487 memset(&ev, 0, sizeof(ev));
488 ev.conn_id = gatt_conn_info->conn_id;
490 ev.client_if = gatt_conn_info->client_if;
491 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
492 BT_HAL_ADDRESS_LENGTH_MAX);
495 ERR("gatt client callback not registered");
497 DBG("sending gatt client disconnected event");
498 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
504 g_free(gatt_conn_info);
509 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
512 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
514 GDBusProxy *device_proxy;
515 GDBusConnection *conn;
516 int ret = BT_STATUS_SUCCESS;
517 hal_gattc_client_info_t *gattc_data;
519 if (NULL == bd_addr) {
520 ERR("bd_addr is NULL");
521 return BT_STATUS_PARM_INVALID;
524 conn = _bt_hal_get_system_gconn();
526 ERR("_bt_gdbus_get_system_gconn returned NULL");
527 return BT_STATUS_FAIL;
530 _bt_hal_convert_addr_type_to_string(device_address,
531 (unsigned char *)bd_addr->address);
532 device_path = _bt_hal_get_device_object_path(device_address);
533 if (device_path == NULL) {
534 DBG("device_path NULL");
535 ret = BT_STATUS_FAIL;
539 ERR("device_path:%s", device_path);
541 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
542 NULL, BT_HAL_BLUEZ_NAME,
543 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
545 if (NULL == device_proxy) {
546 ERR("device_proxy returned NULL");
547 return BT_STATUS_FAIL;
550 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
551 memcpy(gattc_data->bd_addr.address, bd_addr->address,
552 BT_HAL_ADDRESS_LENGTH_MAX);
553 gattc_data->client_if = client_if;
554 gattc_data->conn_id = conn_id;
556 DBG("DisconnectLE [%s]", device_address);
558 g_dbus_proxy_call(device_proxy, "DisconnectLE",
560 G_DBUS_CALL_FLAGS_NONE,
561 BT_HAL_MAX_DBUS_TIMEOUT,
563 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
567 /** Disconnect a remote device or cancel a pending connection */
568 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
573 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
576 /** Clear the attribute cache for a given device */
577 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
580 return BT_STATUS_UNSUPPORTED;
583 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
586 hal_gattc_service_t *info = NULL;
588 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
589 info = (hal_gattc_service_t*)l->data;
593 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t)))
601 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
602 bt_gatt_characteristic_property_t prop)
605 hal_gattc_char_t *info = NULL;
607 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
608 info = (hal_gattc_char_t*)l->data;
612 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
613 (info->permission & prop)) {
620 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
623 hal_gattc_char_t *info = NULL;
625 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
626 info = (hal_gattc_char_t*)l->data;
630 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
631 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
632 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
639 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
642 hal_gattc_desc_t *info = NULL;
644 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
645 info = (hal_gattc_desc_t*)l->data;
649 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t)))
656 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
657 const char *uuid_str, const char *object_path, int is_primary)
659 hal_gattc_service_t *gattc_service = NULL;
661 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
662 gattc_service->svc_path = g_strdup(object_path);
663 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
664 gattc_service->is_primary = is_primary;
666 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
667 INFO("Toatal svc [%d] Added [%s] [%s]", g_slist_length(conn_info->gatt_list_services), object_path + 15, uuid_str);
669 return gattc_service;
672 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
674 hal_gattc_char_t *gattc_char = NULL;
676 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
677 gattc_char->chr_path = g_strdup(char_handle);
679 DBG("svc path: [%s]", gatt_svc->svc_path);
680 DBG("char path: [%s]", gattc_char->chr_path);
682 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
685 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
686 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
688 hal_gattc_service_t* gatt_svc = NULL;
690 gchar *gp_char_path = NULL;
692 /* add the service */
693 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
694 if (gatt_svc == NULL) {
695 ERR("Failed to add service");
699 /* add the characteristic */
700 for (i = 0; i < gp_char_array->len; i++) {
701 gp_char_path = g_ptr_array_index(gp_char_array, i);
702 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
705 g_ptr_array_free(gp_char_array, TRUE);
708 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
710 hal_gattc_desc_t *gattc_desc = NULL;
712 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
713 gattc_desc->desc_path = g_strdup(desc_path);
715 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
718 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
719 GPtrArray *gp_desc_array, unsigned int char_permission)
721 gchar *gp_desc_path = NULL;
724 if (char_uuid_str == NULL) {
725 DBG("char_uuid_str is NULL");
729 //update the char uuid
730 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
732 //update char permission
733 gattc_char->permission = char_permission;
736 for (i = 0; i < gp_desc_array->len; i++) {
737 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
738 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
742 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
744 if (desc_uuid_str == NULL) {
745 DBG("char_uuid_str is NULL");
749 //update the descriptor uuid
750 DBG("desc UUID: [%s] ", desc_uuid_str);
751 DBG("desc path: [%s]", gattc_desc->desc_path);
753 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
756 static void browse_service_char(int conn_id)
758 hal_gattc_server_info_t *conn_info = NULL;
762 hal_gattc_service_t *svc_info = NULL;
763 hal_gattc_char_t *char_info = NULL;
764 hal_gattc_desc_t *desc_info = NULL;
766 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
767 if (conn_info == NULL) {
768 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
772 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
773 svc_info = (hal_gattc_service_t*)l->data;
774 if (svc_info == NULL)
777 /* find characteristic object path */
778 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
779 char_info = (hal_gattc_char_t *)k->data;
780 if (char_info == NULL)
784 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
785 desc_info = (hal_gattc_desc_t *)m->data;
786 if (desc_info == NULL)
796 * Enumerate all GATT services on a connected device.
797 * Optionally, the results can be filtered for a given UUID.
799 static bt_status_t _gattc_client_search_service(int conn_id)
803 GVariant *result = NULL;
805 GVariantIter *svc_iter;
806 GVariantIter *interface_iter;
807 char *object_path = NULL;
808 char *interface_str = NULL;
809 const gchar *key = NULL;
810 GVariant *value = NULL;
811 GPtrArray *gp_array = NULL;
812 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
813 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
814 int ret = BT_STATUS_FAIL;
816 const gchar *uuid_str = NULL;
818 hal_gattc_server_info_t *conn_info = NULL;
819 gboolean is_primary = FALSE;
822 char *char_handle = NULL;
823 GVariantIter *char_iter = NULL;
824 GPtrArray *gp_char_array = NULL;
826 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
827 if (NULL == conn_info) {
828 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
829 return BT_STATUS_FAIL;
833 // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
834 /* Check the service info is stored */
835 if (g_slist_length(conn_info->gatt_list_services) > 0) {
837 hal_gattc_service_t *svc_info = NULL;
838 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
839 DBG("Send event from service info list");
840 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
842 if (svc_info == NULL)
844 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
845 _bt_hal_send_search_service_result_event(conn_id,
846 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
848 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
849 return BT_STATUS_SUCCESS;
851 DBG("No stored service, request to bluez");
855 _bt_hal_convert_addr_type_to_string(device_address,
856 (unsigned char *)conn_info->bd_addr.address);
858 result = _bt_hal_get_managed_objects();
862 gp_array = g_ptr_array_new();
863 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
865 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
867 if (object_path == NULL)
870 _bt_hal_convert_device_path_to_address(object_path, temp_address);
872 if (g_strcmp0(temp_address, device_address) != 0)
875 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
876 &interface_str, &svc_iter)) {
877 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
880 DBG("[%d] Object Path : %s", idx++, object_path);
881 /* for characteristic */
882 gp_char_array = g_ptr_array_new();
883 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
884 if (g_strcmp0(key, "Primary") == 0) {
885 is_primary = g_variant_get_boolean(value);
887 g_ptr_array_add(gp_array, (gpointer)object_path);
890 } else if (g_strcmp0(key, "UUID") == 0) {
891 uuid_str = g_variant_get_string(value, &len);
892 } else if (g_strcmp0(key, "Characteristics") == 0) {
893 g_variant_get(value, "ao", &char_iter);
894 if (char_iter != NULL) {
895 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
896 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
903 _bt_hal_send_search_service_result_event(conn_id, is_primary,
904 uuid_str, conn_info->inst_id);
906 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
911 if (gp_array->len == 0 || svc_count == 0) {
912 ERR("gp_array is NULL");
913 ret = BT_STATUS_FAIL;
915 ret = BT_STATUS_SUCCESS;
918 browse_service_char(conn_id);
919 /* send search service complete event */
920 _bt_hal_send_search_service_complete_event(conn_id, ret);
922 g_ptr_array_free(gp_array, TRUE);
923 g_variant_iter_free(iter);
924 g_variant_unref(result);
929 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
931 if (NULL == filter_uuid) {
932 DBG("Browse all the services");
933 return _gattc_client_search_service(conn_id);
935 DBG("TODO implement it");
936 return BT_STATUS_UNSUPPORTED;
940 * Enumerate included services for a given service.
941 * Set start_incl_srvc_id to NULL to get the first included service.
943 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
944 btgatt_srvc_id_t *start_incl_srvc_id)
947 return BT_STATUS_UNSUPPORTED;
950 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
951 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
953 struct hal_ev_gatt_client_char_search_result ev;
956 ERR("gatt client callback not registered");
960 memset(&ev, 0, sizeof(ev));
961 ev.conn_id = conn_id;
962 ev.inst_id = svc_id->id.inst_id;
963 ev.is_primary = svc_id->is_primary;
965 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
967 if (status == BT_STATUS_SUCCESS) {
968 /* building char uuid */
969 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
970 ev.char_prop = char_prop;
973 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
974 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
977 static int _hal_get_permission_flag(char *permission)
981 if (NULL == permission) {
982 ERR("gatt permission is NULL");
986 if (!g_strcmp0(permission, "broadcast"))
987 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
988 else if (!g_strcmp0(permission, "read"))
989 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
990 else if (!g_strcmp0(permission, "write-without-response"))
991 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
992 else if (!g_strcmp0(permission, "write"))
993 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
994 else if (!g_strcmp0(permission, "notify"))
995 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
996 else if (!g_strcmp0(permission, "indicate"))
997 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
998 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
999 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
1000 else if (!g_strcmp0(permission, "reliable-write"))
1001 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
1002 else if (!g_strcmp0(permission, "writable-auxiliaries"))
1003 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1004 else if (!g_strcmp0(permission, "encrypt-read"))
1005 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1006 else if (!g_strcmp0(permission, "encrypt-write"))
1007 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1008 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1009 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1010 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1011 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1016 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1018 char perm[200] = { 0, };
1020 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1021 g_strlcat(perm, "broadcast ", sizeof(perm));
1022 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1023 g_strlcat(perm, "read ", sizeof(perm));
1024 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1025 g_strlcat(perm, "write-without-response ", sizeof(perm));
1026 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1027 g_strlcat(perm, "write ", sizeof(perm));
1028 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1029 g_strlcat(perm, "notify ", sizeof(perm));
1030 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1031 g_strlcat(perm, "indicate ", sizeof(perm));
1032 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1033 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1034 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1035 g_strlcat(perm, "reliable-write ", sizeof(perm));
1036 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1037 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1038 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1039 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1040 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1041 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1042 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1043 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1044 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1045 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1047 DBG("permission [0x%04x] : %s\n", permission, perm);
1051 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1053 GDBusProxy *properties_proxy = NULL;
1054 GError *error = NULL;
1055 GVariant *value = NULL;
1056 GVariant *result = NULL;
1057 GDBusConnection *g_conn;
1059 char *char_desc_handle = NULL;
1061 GVariantIter *property_iter;
1062 GVariantIter *char_desc_iter;
1063 char* char_handle = NULL;
1064 gchar *char_uuid_str = NULL;
1065 GPtrArray *gp_desc_array = NULL;
1066 GVariantIter *char_perm_iter;
1068 unsigned int char_permission = 0 ;
1070 if (gattc_char->chr_path == NULL) {
1071 DBG("char path is NULL");
1072 return BT_STATUS_FAIL;
1074 char_handle = gattc_char->chr_path;
1076 g_conn = _bt_hal_get_system_gconn();
1077 if (NULL == g_conn) {
1078 ERR("_bt_gdbus_get_system_gconn returned NULL");
1079 return BT_STATUS_FAIL;
1082 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1083 G_DBUS_PROXY_FLAGS_NONE, NULL,
1086 BT_HAL_PROPERTIES_INTERFACE,
1089 if (properties_proxy == NULL) {
1090 ERR("properties_proxy returned NULL");
1091 return BT_STATUS_FAIL;
1094 result = g_dbus_proxy_call_sync(properties_proxy,
1096 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1097 G_DBUS_CALL_FLAGS_NONE,
1102 if (error != NULL) {
1103 ERR("Fail to get properties (Error: %s)", error->message);
1104 g_clear_error(&error);
1106 ERR("Fail to get properties");
1107 g_object_unref(properties_proxy);
1108 return BT_STATUS_FAIL;
1111 gp_desc_array = g_ptr_array_new();
1113 g_variant_get(result, "(a{sv})", &property_iter);
1115 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1116 if (!g_strcmp0(key, "UUID")) {
1117 char_uuid_str = g_variant_dup_string(value, &len);
1118 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1119 } else if (!g_strcmp0(key, "Flags")) {
1120 g_variant_get(value, "as", &char_perm_iter);
1121 char_permission = 0x00;
1123 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1124 char_permission |= _hal_get_permission_flag(permission);
1126 __hal_convert_permission_flag_to_str(char_permission);
1127 g_variant_iter_free(char_perm_iter);
1128 } else if (!g_strcmp0(key, "Descriptors")) {
1129 g_variant_get(value, "ao", &char_desc_iter);
1130 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1131 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1133 g_variant_iter_free(char_desc_iter);
1137 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1139 g_free(char_uuid_str);
1140 g_variant_iter_free(property_iter);
1141 g_variant_unref(result);
1142 g_object_unref(properties_proxy);
1143 g_ptr_array_free(gp_desc_array, TRUE);
1145 return BT_STATUS_SUCCESS;
1148 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1149 btgatt_srvc_id_t *srvc_id)
1151 hal_gattc_server_info_t * conn_info = NULL;
1152 hal_gattc_service_t *gattc_service = NULL;
1154 hal_gattc_char_t *gattc_char = NULL;
1155 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1156 int status = BT_STATUS_FAIL;
1158 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1159 if (NULL == conn_info) {
1160 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1161 return BT_STATUS_FAIL;
1165 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1166 if (NULL == gattc_service) {
1167 ERR("Failed to get the gatt service");
1168 return BT_STATUS_FAIL;
1171 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1172 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1174 /* find characteristic object path */
1175 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1176 gattc_char = (hal_gattc_char_t *)l->data;
1177 status = _hal_gattc_get_characteristic_info(gattc_char);
1180 if (BT_STATUS_SUCCESS == status) {
1181 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1182 &gattc_char->chr_uuid, gattc_char->permission);
1186 status = BT_STATUS_FAIL;
1187 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1189 browse_service_char(conn_id);
1190 /* retrive uuid for characteristic and object path for descriptor */
1192 return BT_STATUS_SUCCESS;
1196 * Enumerate characteristics for a given service.
1197 * Set start_char_id to NULL to get the first characteristic.
1199 bt_status_t btif_gattc_get_characteristic(int conn_id,
1200 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1202 CHECK_BTGATT_INIT();
1204 if (start_char_id == NULL) {
1205 DBG("Get all the characteristics");
1206 return _gattc_get_all_characteristic(conn_id, srvc_id);
1209 DBG("TBD Get specific characteristics");
1210 return BT_STATUS_UNSUPPORTED;
1214 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1216 GDBusProxy *properties_proxy = NULL;
1217 GError *error = NULL;
1218 GVariant *value = NULL;
1219 GVariant *result = NULL;
1220 GDBusConnection *g_conn;
1223 GVariantIter *property_iter;
1224 char* desc_handle = NULL;
1225 const gchar *desc_uuid_str = NULL;
1227 if (gattc_desc->desc_path == NULL) {
1228 DBG("desc path is NULL");
1229 return BT_STATUS_FAIL;
1231 desc_handle = gattc_desc->desc_path;
1233 g_conn = _bt_hal_get_system_gconn();
1234 if (NULL == g_conn) {
1235 ERR("_bt_gdbus_get_system_gconn returned NULL");
1236 return BT_STATUS_FAIL;
1239 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1240 G_DBUS_PROXY_FLAGS_NONE, NULL,
1243 BT_HAL_PROPERTIES_INTERFACE,
1246 if (properties_proxy == NULL) {
1247 ERR("properties_proxy returned NULL");
1248 return BT_STATUS_FAIL;
1251 result = g_dbus_proxy_call_sync(properties_proxy,
1253 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1254 G_DBUS_CALL_FLAGS_NONE,
1259 if (error != NULL) {
1260 ERR("Fail to get properties (Error: %s)", error->message);
1261 g_clear_error(&error);
1263 ERR("Fail to get properties");
1264 g_object_unref(properties_proxy);
1265 return BT_STATUS_FAIL;
1268 g_variant_get(result, "(a{sv})", &property_iter);
1270 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1271 if (!g_strcmp0(key, "UUID")) {
1272 desc_uuid_str = g_variant_get_string(value, &len);
1273 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1275 g_free((gchar *)key);
1276 g_variant_unref(value);
1281 g_variant_iter_free(property_iter);
1282 g_variant_unref(result);
1283 g_object_unref(properties_proxy);
1285 return BT_STATUS_SUCCESS;
1288 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1289 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1291 struct hal_ev_gatt_client_desc_search_result ev;
1294 ERR("gatt client callback not registered");
1298 memset(&ev, 0, sizeof(ev));
1299 ev.conn_id = conn_id;
1300 ev.inst_id = svc_id->id.inst_id;
1301 ev.is_primary = svc_id->is_primary;
1304 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1305 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1307 if (status == BT_STATUS_SUCCESS) {
1308 /* building desc uuid */
1309 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1312 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1314 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1317 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1318 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1320 hal_gattc_server_info_t * conn_info = NULL;
1321 hal_gattc_service_t *gattc_service = NULL;
1324 hal_gattc_char_t *gattc_char = NULL;
1325 hal_gattc_desc_t *gattc_desc = NULL;
1326 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1327 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1328 int status = BT_STATUS_FAIL;
1330 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1331 if (NULL == conn_info) {
1332 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1333 return BT_STATUS_FAIL;
1337 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1338 if (NULL == gattc_service) {
1339 ERR("Failed to get the gatt service");
1340 return BT_STATUS_FAIL;
1343 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1344 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1346 /* find characteristics */
1347 /* a service can have two char with same uuid */
1348 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1349 gattc_char = (hal_gattc_char_t*)l->data;
1350 if (gattc_char == NULL)
1353 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1354 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1355 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1357 /* get descriptor uuid */
1358 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1359 gattc_desc = (hal_gattc_desc_t *)m->data;
1360 if (gattc_desc == NULL)
1363 status = _hal_gattc_get_descriptor_info(gattc_desc);
1366 if (BT_STATUS_SUCCESS == status) {
1367 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1368 char_id, &gattc_desc->desc_uuid);
1374 status = BT_STATUS_FAIL;
1375 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1377 browse_service_char(conn_id);
1378 /* retrive uuid for characteristic and object path for descriptor */
1380 return BT_STATUS_SUCCESS;
1384 * Enumerate descriptors for a given characteristic.
1385 * Set start_descr_id to NULL to get the first descriptor.
1387 bt_status_t btif_gattc_get_descriptor(int conn_id,
1388 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1389 btgatt_gatt_id_t *start_descr_id)
1391 CHECK_BTGATT_INIT();
1393 if (start_descr_id == NULL) {
1394 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1396 DBG("TBD Get specific descriptor");
1397 return BT_STATUS_UNSUPPORTED;
1401 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1403 struct hal_ev_gatt_client_read_data ev;
1406 ERR("gatt client callback not registered");
1410 memset(&ev, 0, sizeof(ev));
1411 ev.conn_id = resp_data->conn_id;
1412 ev.inst_id = resp_data->srvc_id.id.inst_id;
1413 ev.is_primary = resp_data->srvc_id.is_primary;
1416 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1417 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1421 /* building the char read value */
1422 memcpy(ev.value, value, len);
1425 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1427 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1430 static void __hal_internal_read_char_cb(GObject *source_object,
1431 GAsyncResult *res, gpointer user_data)
1433 GError *error = NULL;
1434 GDBusConnection *system_gconn = NULL;
1437 GByteArray *gp_byte_array = NULL;
1439 hal_gatt_resp_data_t *resp_data = user_data;
1440 int result = BT_STATUS_SUCCESS;
1442 system_gconn = _bt_hal_get_system_gconn();
1443 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1446 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1449 result = BT_STATUS_FAIL;
1450 __hal_send_char_read_event(resp_data, result, NULL, 0);
1451 g_clear_error(&error);
1456 gp_byte_array = g_byte_array_new();
1457 g_variant_get(value, "(ay)", &iter);
1459 while (g_variant_iter_loop(iter, "y", &g_byte))
1460 g_byte_array_append(gp_byte_array, &g_byte, 1);
1464 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1468 g_byte_array_free(gp_byte_array, TRUE);
1469 g_variant_iter_free(iter);
1470 g_variant_unref(value);
1474 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1475 btgatt_gatt_id_t *char_id, int auth_req)
1477 GDBusConnection *g_conn;
1478 hal_gatt_resp_data_t *resp_data;
1479 hal_gattc_service_t *gattc_service = NULL;
1480 GVariantBuilder *builder = NULL;
1482 hal_gattc_server_info_t * conn_info = NULL;
1483 hal_gattc_char_t *gattc_char = NULL;
1484 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1485 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1486 char* char_handle = NULL;
1488 /* get the connection info */
1489 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1490 if (NULL == conn_info) {
1491 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1492 return BT_STATUS_FAIL;
1496 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1497 if (NULL == gattc_service) {
1498 ERR("Failed to get the gatt service");
1499 return BT_STATUS_FAIL;
1502 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1504 /* find characteristic */
1505 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1506 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1507 if (NULL == gattc_char) {
1508 ERR("Failed to get the gatt char");
1509 return BT_STATUS_FAIL;
1512 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1513 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1515 g_conn = _bt_hal_get_system_gconn();
1516 if (NULL == g_conn) {
1517 ERR("_bt_gdbus_get_system_gconn returned NULL");
1518 return BT_STATUS_FAIL;
1521 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1522 resp_data->conn_id = conn_id;
1523 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1524 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1526 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1529 g_variant_builder_add(builder, "{sv}", "offset",
1530 g_variant_new("q", offset));
1532 char_handle = gattc_char->chr_path;
1534 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1535 "ReadValue", g_variant_new("(a{sv})", builder),
1536 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1537 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1538 (gpointer)resp_data);
1539 g_variant_builder_unref(builder);
1541 return BT_STATUS_SUCCESS;
1544 /** Read a characteristic on a remote device */
1545 bt_status_t btif_read_characteristic(int conn_id,
1546 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1549 CHECK_BTGATT_INIT();
1551 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1554 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1556 struct hal_ev_gatt_client_write_result ev;
1559 ERR("gatt client callback not registered");
1563 memset(&ev, 0, sizeof(ev));
1564 ev.conn_id = resp_data->conn_id;
1565 ev.inst_id = resp_data->srvc_id.id.inst_id;
1566 ev.is_primary = resp_data->srvc_id.is_primary;
1569 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1570 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1572 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1574 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1577 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1578 GAsyncResult *res, gpointer user_data)
1580 GError *error = NULL;
1581 GDBusConnection *system_gconn = NULL;
1583 hal_gatt_resp_data_t *resp_data = user_data;
1584 int result = BT_STATUS_SUCCESS;
1588 system_gconn = _bt_hal_get_system_gconn();
1589 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1592 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1594 result = BT_STATUS_FAIL;
1596 __hal_send_char_write_event(resp_data, result);
1597 g_clear_error(&error);
1602 //send write value event
1603 __hal_send_char_write_event(resp_data, result);
1606 g_variant_unref(value);
1611 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1614 case HAL_GATT_WRITE_TYPE_WRITE:
1615 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1617 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1618 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1621 ERR("Unknow write type : %d", type);
1622 return BT_STATUS_FAIL;
1625 return BT_STATUS_SUCCESS;
1629 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1631 GDBusConnection *conn;
1632 GVariantBuilder *builder = NULL;
1638 GUnixFDList *fd_list = NULL;
1640 conn = _bt_hal_get_system_gconn();
1642 ERR("_bt_gdbus_get_system_gconn returned NULL");
1643 return BT_STATUS_FAIL;
1646 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1647 //val = g_variant_new("ay", builder1);
1649 g_variant_builder_add(builder, "{sv}", "offset",
1650 g_variant_new("q", offset));
1652 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1653 "AcquireWrite", g_variant_new("(a{sv})", builder),
1654 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1655 NULL, &fd_list, NULL, &err);
1657 g_dbus_error_strip_remote_error(err);
1658 ERR("Error: %s", err->message);
1660 g_variant_builder_unref(builder);
1661 return BT_STATUS_FAIL;
1664 g_variant_get(value, "(hq)", &idx, &att_mtu);
1665 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1667 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1670 g_object_unref(fd_list);
1671 g_variant_unref(value);
1672 g_variant_builder_unref(builder);
1674 return BT_STATUS_SUCCESS;
1677 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1679 GDBusConnection *conn;
1680 GVariantBuilder *builder = NULL;
1684 gint32 idx, notify_fd;
1686 GUnixFDList *fd_list = NULL;
1688 conn = _bt_hal_get_system_gconn();
1691 ERR("_bt_gdbus_get_system_gconn returned NULL");
1692 return BT_STATUS_FAIL;
1696 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1699 g_variant_builder_add(builder, "{sv}", "offset",
1700 g_variant_new("q", offset));
1702 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1703 "AcquireNotify", g_variant_new("(a{sv})", builder),
1704 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1705 NULL, &fd_list, NULL, &err);
1707 g_dbus_error_strip_remote_error(err);
1708 ERR("Error: %s", err->message);
1710 g_variant_builder_unref(builder);
1711 return BT_STATUS_FAIL;
1714 g_variant_get(value, "(hq)", &idx, &att_mtu);
1715 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1718 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1722 g_object_unref(fd_list);
1723 g_variant_unref(value);
1724 g_variant_builder_unref(builder);
1726 return BT_STATUS_SUCCESS;
1730 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1731 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1733 GVariant *val, *options;
1734 GVariantBuilder *builder1;
1735 GVariantBuilder *builder2;
1736 GDBusConnection *g_conn;
1739 hal_gatt_resp_data_t *resp_data;
1740 hal_gattc_service_t *gattc_service = NULL;
1741 hal_gattc_server_info_t * conn_info = NULL;
1742 hal_gattc_char_t *gattc_char = NULL;
1743 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1744 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1745 char* char_handle = NULL;
1746 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1747 int ret = BT_STATUS_SUCCESS;
1749 ret = __hal_get_write_prop(write_type, &write_prop);
1750 if (BT_STATUS_FAIL == ret) {
1751 DBG("received invalid write type:[%d] ", write_type);
1752 return BT_STATUS_FAIL;
1755 /* get the connection info */
1756 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1757 if (NULL == conn_info) {
1758 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1759 return BT_STATUS_FAIL;
1763 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1764 if (NULL == gattc_service) {
1765 ERR("Failed to get the gatt service");
1766 return BT_STATUS_FAIL;
1769 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1770 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1772 /* find characteristic */
1773 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1774 if (NULL == gattc_char) {
1775 ERR("Failed to get the gatt char");
1776 return BT_STATUS_FAIL;
1779 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1780 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1782 g_conn = _bt_hal_get_system_gconn();
1783 if (NULL == g_conn) {
1784 ERR("_bt_gdbus_get_system_gconn returned NULL");
1785 return BT_STATUS_FAIL;
1788 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1789 resp_data->conn_id = conn_id;
1790 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1791 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1793 char_handle = gattc_char->chr_path;
1795 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1797 for (i = 0; i < length; i++)
1798 g_variant_builder_add(builder1, "y", value[i]);
1800 val = g_variant_new("ay", builder1);
1802 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1804 g_variant_builder_add(builder2, "{sv}", "offset",
1805 g_variant_new_uint16(offset));
1807 options = g_variant_new("a{sv}", builder2);
1809 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1811 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1813 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1814 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1815 (gpointer)resp_data);
1817 g_variant_builder_unref(builder1);
1818 g_variant_builder_unref(builder2);
1820 return BT_STATUS_SUCCESS;
1823 bt_status_t btif_get_acquire_write_fd(int conn_id,
1824 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1825 int auth_req, int *fd, int*mtu)
1827 CHECK_BTGATT_INIT();
1829 hal_gattc_service_t *gattc_service = NULL;
1830 hal_gattc_server_info_t * conn_info = NULL;
1831 hal_gattc_char_t *gattc_char = NULL;
1832 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1834 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1835 int ret = BT_STATUS_SUCCESS;
1837 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1839 /* get the connection info */
1840 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1841 if (NULL == conn_info) {
1842 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1843 return BT_STATUS_FAIL;
1847 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1848 if (NULL == gattc_service) {
1849 ERR("Failed to get the gatt service");
1850 return BT_STATUS_FAIL;
1853 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1854 if (NULL == gattc_char) {
1855 ERR("Failed to get the gatt char");
1856 return BT_STATUS_FAIL;
1859 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1860 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1862 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1863 if (ret != BT_STATUS_SUCCESS)
1869 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1870 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1872 CHECK_BTGATT_INIT();
1874 hal_gattc_service_t *gattc_service = NULL;
1875 hal_gattc_server_info_t * conn_info = NULL;
1876 hal_gattc_char_t *gattc_char = NULL;
1877 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1879 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1880 int ret = BT_STATUS_SUCCESS;
1882 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1884 /* get the connection info */
1885 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1886 if (NULL == conn_info) {
1887 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1888 return BT_STATUS_FAIL;
1892 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1893 if (NULL == gattc_service) {
1894 ERR("Failed to get the gatt service");
1895 return BT_STATUS_FAIL;
1898 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1899 if (NULL == gattc_char) {
1900 ERR("Failed to get the gatt char");
1901 return BT_STATUS_FAIL;
1904 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1905 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1907 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1908 if (ret != BT_STATUS_SUCCESS)
1915 /** Write a remote characteristic */
1916 bt_status_t btif_write_characteristic(int conn_id,
1917 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1918 int write_type, int len, int auth_req,
1921 CHECK_BTGATT_INIT();
1923 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1924 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1925 len, auth_req, p_value);
1928 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1930 struct hal_ev_gatt_client_read_data ev;
1933 ERR("gatt client callback not registered");
1937 memset(&ev, 0, sizeof(ev));
1938 ev.conn_id = resp_data->conn_id;
1939 ev.inst_id = resp_data->srvc_id.id.inst_id;
1940 ev.is_primary = resp_data->srvc_id.is_primary;
1943 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1944 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1945 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1949 /* building the desc read value */
1950 memcpy(ev.value, value, len);
1953 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1955 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1958 static void __hal_internal_read_desc_cb(GObject *source_object,
1959 GAsyncResult *res, gpointer user_data)
1961 GError *error = NULL;
1962 GDBusConnection *system_gconn = NULL;
1965 GByteArray *gp_byte_array = NULL;
1967 hal_gatt_resp_data_t *resp_data = user_data;
1968 int result = BT_STATUS_SUCCESS;
1973 system_gconn = _bt_hal_get_system_gconn();
1974 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1977 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1980 result = BT_STATUS_FAIL;
1981 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1982 g_clear_error(&error);
1987 gp_byte_array = g_byte_array_new();
1988 g_variant_get(value, "(ay)", &iter);
1990 while (g_variant_iter_loop(iter, "y", &g_byte))
1991 g_byte_array_append(gp_byte_array, &g_byte, 1);
1995 for (i = 0; i < gp_byte_array->len; i++)
1996 DBG("%02x", gp_byte_array->data[i]);
1999 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2003 g_byte_array_free(gp_byte_array, TRUE);
2004 g_variant_iter_free(iter);
2005 g_variant_unref(value);
2010 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2011 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2013 GDBusConnection *g_conn;
2014 hal_gatt_resp_data_t *resp_data;
2015 hal_gattc_service_t *gattc_service = NULL;
2016 GVariantBuilder *builder = NULL;
2018 hal_gattc_server_info_t * conn_info = NULL;
2019 hal_gattc_char_t *gattc_char = NULL;
2020 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2021 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2022 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2023 char* desc_handle = NULL;
2026 hal_gattc_desc_t *gattc_desc = NULL;
2028 /* get the connection info */
2029 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2030 if (NULL == conn_info) {
2031 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2032 return BT_STATUS_FAIL;
2036 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2037 if (NULL == gattc_service) {
2038 ERR("Failed to get the gatt service");
2039 return BT_STATUS_FAIL;
2042 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2043 DBG("%s %s", gattc_service->svc_path + 37, 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 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2054 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2056 /* find descriptor */
2057 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2059 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2060 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2066 if (NULL == gattc_desc) {
2067 ERR("Failed to get the gatt desc");
2068 return BT_STATUS_FAIL;
2071 g_conn = _bt_hal_get_system_gconn();
2072 if (NULL == g_conn) {
2073 ERR("_bt_gdbus_get_system_gconn returned NULL");
2074 return BT_STATUS_FAIL;
2077 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2078 resp_data->conn_id = conn_id;
2079 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2080 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2081 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2083 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2086 g_variant_builder_add(builder, "{sv}", "offset",
2087 g_variant_new("q", offset));
2089 desc_handle = gattc_desc->desc_path;
2091 DBG("calling desc read value");
2093 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2094 "ReadValue", g_variant_new("(a{sv})", builder),
2095 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2096 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2097 (gpointer)resp_data);
2098 g_variant_builder_unref(builder);
2100 return BT_STATUS_SUCCESS;
2103 /** Read the descriptor for a given characteristic */
2104 bt_status_t btif_read_descriptor(int conn_id,
2105 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2106 btgatt_gatt_id_t *descr_id, int auth_req)
2108 CHECK_BTGATT_INIT();
2110 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2113 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2115 struct hal_ev_gatt_client_write_result ev;
2118 ERR("gatt client callback not registered");
2122 memset(&ev, 0, sizeof(ev));
2123 ev.conn_id = resp_data->conn_id;
2124 ev.inst_id = resp_data->srvc_id.id.inst_id;
2125 ev.is_primary = resp_data->srvc_id.is_primary;
2128 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2129 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2130 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2132 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2134 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2137 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2138 GAsyncResult *res, gpointer user_data)
2140 GError *error = NULL;
2141 GDBusConnection *system_gconn = NULL;
2143 hal_gatt_resp_data_t *resp_data = user_data;
2144 int result = BT_STATUS_SUCCESS;
2148 system_gconn = _bt_hal_get_system_gconn();
2149 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2152 ERR("write descriptor dbus failed Error: [%s]", error->message);
2155 result = BT_STATUS_FAIL;
2156 __hal_send_desc_write_event(resp_data, result);
2157 g_clear_error(&error);
2162 //send write value event
2163 __hal_send_desc_write_event(resp_data, result);
2166 g_variant_unref(value);
2171 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2172 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2173 int write_type, int length, int auth_req, char* value)
2175 GVariant *val, *options;
2176 GVariantBuilder *builder1;
2177 GVariantBuilder *builder2;
2178 GDBusConnection *g_conn;
2181 hal_gatt_resp_data_t *resp_data;
2182 hal_gattc_service_t *gattc_service = NULL;
2183 hal_gattc_server_info_t * conn_info = NULL;
2184 hal_gattc_char_t *gattc_char = NULL;
2185 hal_gattc_desc_t *gattc_desc = NULL;
2186 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2187 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2188 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2189 char* desc_handle = NULL;
2190 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2191 int ret = BT_STATUS_SUCCESS;
2196 ret = __hal_get_write_prop(write_type, &write_prop);
2197 if (BT_STATUS_FAIL == ret) {
2198 ERR("received invalid write type:[%d] ", write_type);
2199 return BT_STATUS_FAIL;
2202 /* get the connection info */
2203 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2204 if (NULL == conn_info) {
2205 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2206 return BT_STATUS_FAIL;
2210 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2211 if (NULL == gattc_service) {
2212 ERR("Failed to get the gatt service");
2213 return BT_STATUS_FAIL;
2216 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2217 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2219 /* find characteristic */
2220 /* service can have two char with same uuid */
2221 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2222 gattc_char = (hal_gattc_char_t*)l->data;
2223 if (gattc_char == NULL)
2226 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2227 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2228 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2230 /* find descriptor */
2231 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2233 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2234 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2240 if (NULL == gattc_desc) {
2241 ERR("Failed to get the gatt desc");
2242 return BT_STATUS_FAIL;
2245 g_conn = _bt_hal_get_system_gconn();
2246 if (NULL == g_conn) {
2247 ERR("_bt_gdbus_get_system_gconn returned NULL");
2248 return BT_STATUS_FAIL;
2251 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2252 resp_data->conn_id = conn_id;
2253 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2254 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2255 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2257 desc_handle = gattc_desc->desc_path;
2259 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2261 for (i = 0; i < length; i++)
2262 g_variant_builder_add(builder1, "y", value[i]);
2264 val = g_variant_new("ay", builder1);
2266 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2268 g_variant_builder_add(builder2, "{sv}", "offset",
2269 g_variant_new_uint16(offset));
2271 options = g_variant_new("a{sv}", builder2);
2273 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2275 g_variant_new("(@ay@a{sv})", val, options),
2277 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2278 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2279 (gpointer)resp_data);
2281 g_variant_builder_unref(builder1);
2282 g_variant_builder_unref(builder2);
2284 return BT_STATUS_SUCCESS;
2287 /** Write a remote descriptor for a given characteristic */
2288 bt_status_t btif_write_descriptor(int conn_id,
2289 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2290 btgatt_gatt_id_t *descr_id, int write_type, int len,
2291 int auth_req, char* p_value)
2293 CHECK_BTGATT_INIT();
2295 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2296 len, auth_req, p_value);
2299 /** Execute a prepared write operation */
2300 bt_status_t execute_write(int conn_id, int execute)
2302 CHECK_BTGATT_INIT();
2303 return BT_STATUS_UNSUPPORTED;
2306 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2308 struct hal_ev_gatt_client_watch_notification ev;
2309 hal_gatt_resp_data_t *resp_data = user_data;
2311 DBG("sending the watch register notification event");
2312 /* send the event */
2313 memset(&ev, 0, sizeof(ev));
2314 ev.conn_id = resp_data->conn_id;
2316 ev.status = resp_data->result;
2318 ev.is_primary = resp_data->srvc_id.is_primary;
2319 ev.inst_id = resp_data->srvc_id.id.inst_id;
2321 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2322 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2325 ERR("GATT Callback not registered");
2327 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2334 static bt_status_t _hal_register_for_notification(int conn_id,
2335 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2336 btgatt_gatt_id_t *char_id)
2338 int result = BT_STATUS_SUCCESS;
2339 GError *error = NULL;
2340 GDBusConnection *g_conn;
2341 hal_gattc_client_info_t *gattc_client = NULL;
2342 hal_gattc_server_info_t * conn_info = NULL;
2343 hal_gattc_service_t *gattc_service = NULL;
2344 hal_gattc_char_t *gattc_char = NULL;
2345 char* char_handle = NULL;
2346 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2347 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2348 hal_gatt_resp_data_t *resp_data;
2352 gattc_client = __bt_find_gatt_client_info(bd_addr);
2353 if (gattc_client == NULL) {
2354 ERR("failed to get the gatt client info");
2355 return BT_STATUS_FAIL;
2358 if (gattc_client->conn_id != conn_id) {
2359 ERR("could not find the gatt client for client id[%d]", conn_id);
2360 return BT_STATUS_FAIL;
2363 /* get the connection info */
2364 conn_info = __bt_find_gatt_conn_info(bd_addr);
2365 if (NULL == conn_info) {
2366 ERR("Failed to get the conn_info");
2367 return BT_STATUS_FAIL;
2370 if (conn_info->inst_id != gattc_client->inst_id) {
2371 ERR("could not fild the conn_info");
2372 return BT_STATUS_FAIL;
2376 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2377 if (NULL == gattc_service) {
2378 ERR("Failed to get the gatt service");
2379 return BT_STATUS_FAIL;
2382 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2383 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2386 /* find characteristic */
2387 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2388 if (NULL == gattc_char) {
2389 ERR("Failed to get the gatt char");
2390 return BT_STATUS_FAIL;
2393 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2394 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2396 char_handle = gattc_char->chr_path;
2398 g_conn = _bt_hal_get_system_gconn();
2399 if (g_conn == NULL) {
2401 return BT_STATUS_FAIL;
2404 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2406 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2408 g_dbus_connection_call_sync(g_conn,
2411 BT_HAL_GATT_CHAR_INTERFACE,
2415 G_DBUS_CALL_FLAGS_NONE,
2416 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2419 g_dbus_error_strip_remote_error(error);
2420 ERR("### StartNotify Failed: %s", error->message);
2421 if (g_strrstr(error->message, "Already notifying"))
2422 result = BT_STATUS_SUCCESS;
2423 else if (g_strrstr(error->message, "In Progress"))
2424 result = BT_STATUS_BUSY;
2425 else if (g_strrstr(error->message, "Operation is not supported"))
2426 result = BT_STATUS_UNSUPPORTED;
2427 /*failed because of either Insufficient Authorization or Write Not Permitted */
2428 else if (g_strrstr(error->message, "Write not permitted") ||
2429 g_strrstr(error->message, "Operation Not Authorized"))
2430 result = BT_STATUS_AUTH_FAILURE;
2431 /* failed because of either Insufficient Authentication,
2432 Insufficient Encryption Key Size, or Insufficient Encryption. */
2433 else if (g_strrstr(error->message, "Not paired"))
2434 result = BT_STATUS_NOT_READY;
2436 result = BT_STATUS_FAIL;
2438 g_clear_error(&error);
2441 resp_data->conn_id = gattc_client->conn_id;
2442 resp_data->result = result;
2443 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2444 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2446 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2450 return BT_STATUS_SUCCESS;
2454 * Register to receive notifications or indications for a given
2457 bt_status_t btif_register_for_notification(int conn_id,
2458 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2459 btgatt_gatt_id_t *char_id)
2461 CHECK_BTGATT_INIT();
2463 return _hal_register_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2466 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2468 struct hal_ev_gatt_client_watch_notification ev;
2469 hal_gatt_resp_data_t *resp_data = user_data;
2471 DBG("sending the watch deregister notification event");
2472 /* send the event */
2473 memset(&ev, 0, sizeof(ev));
2474 ev.conn_id = resp_data->conn_id;
2476 ev.status = resp_data->result;
2478 ev.is_primary = resp_data->srvc_id.is_primary;
2479 ev.inst_id = resp_data->srvc_id.id.inst_id;
2481 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2482 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2485 ERR("GATT Callback not registered");
2487 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2494 static bt_status_t _hal_deregister_for_notification(int conn_id,
2495 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2496 btgatt_gatt_id_t *char_id)
2498 int result = BT_STATUS_SUCCESS;
2499 GError *error = NULL;
2500 GDBusConnection *g_conn;
2501 hal_gattc_client_info_t *gattc_client = NULL;
2502 hal_gattc_server_info_t * conn_info = NULL;
2503 hal_gattc_service_t *gattc_service = NULL;
2504 hal_gattc_char_t *gattc_char = NULL;
2505 char* char_handle = NULL;
2506 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2507 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2508 hal_gatt_resp_data_t *resp_data;
2512 gattc_client = __bt_find_gatt_client_info(bd_addr);
2513 if (gattc_client == NULL) {
2514 ERR("failed to get the gatt client info");
2515 return BT_STATUS_FAIL;
2518 if (gattc_client->conn_id != conn_id) {
2519 ERR("could not find the gatt client for client id[%d]", conn_id);
2520 return BT_STATUS_FAIL;
2523 /* get the connection info */
2524 conn_info = __bt_find_gatt_conn_info(bd_addr);
2525 if (NULL == conn_info) {
2526 ERR("Failed to get the conn_info");
2527 return BT_STATUS_FAIL;
2530 if (conn_info->inst_id != gattc_client->inst_id) {
2531 ERR("could not fild the conn_info");
2532 return BT_STATUS_FAIL;
2536 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2537 if (NULL == gattc_service) {
2538 ERR("Failed to get the gatt service");
2539 return BT_STATUS_FAIL;
2542 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2543 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2546 /* find characteristic */
2547 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2548 if (NULL == gattc_char) {
2549 ERR("Failed to get the gatt char");
2550 return BT_STATUS_FAIL;
2553 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2554 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2556 char_handle = gattc_char->chr_path;
2558 g_conn = _bt_hal_get_system_gconn();
2559 if (g_conn == NULL) {
2561 return BT_STATUS_FAIL;
2564 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2566 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2567 g_dbus_connection_call_sync(g_conn,
2570 BT_HAL_GATT_CHAR_INTERFACE,
2574 G_DBUS_CALL_FLAGS_NONE,
2575 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2578 ERR("### StopNotify Failed: %s", error->message);
2579 g_clear_error(&error);
2580 result = BT_STATUS_FAIL;
2583 resp_data->conn_id = gattc_client->conn_id;
2584 resp_data->result = result;
2585 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2586 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2588 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2592 return BT_STATUS_SUCCESS;
2594 /** Deregister a previous request for notifications/indications */
2595 bt_status_t btif_deregister_for_notification(int conn_id,
2596 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2597 btgatt_gatt_id_t *char_id)
2599 CHECK_BTGATT_INIT();
2600 return _hal_deregister_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2603 /** Request RSSI for a given remote device */
2604 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2606 CHECK_BTGATT_INIT();
2607 return BT_STATUS_UNSUPPORTED;
2610 /** OTA firmware download */
2611 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2613 CHECK_BTGATT_INIT();
2614 return BT_STATUS_UNSUPPORTED;
2617 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2618 int get_device_type(const bt_bdaddr_t *bd_addr)
2620 CHECK_BTGATT_INIT();
2621 return BT_STATUS_UNSUPPORTED;
2624 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2625 int min_int, int max_int, int latency, int timeout)
2627 gchar *device_path = NULL;
2628 GError *error = NULL;
2629 GDBusProxy *device_proxy = NULL;
2630 GDBusConnection *conn;
2632 int ret = BT_STATUS_SUCCESS;
2633 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2635 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2636 min_int, max_int, latency, timeout);
2638 conn = _bt_hal_get_system_gconn();
2641 return BT_STATUS_FAIL;
2644 _bt_hal_convert_addr_type_to_string(device_address,
2645 (unsigned char *)bd_addr->address);
2646 device_path = _bt_hal_get_device_object_path(device_address);
2648 if (device_path == NULL) {
2649 ERR("device_path NULL : [%s]", device_address);
2650 return BT_STATUS_FAIL;
2653 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2654 NULL, BT_HAL_BLUEZ_NAME,
2655 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2657 g_free(device_path);
2658 if (NULL == device_proxy) {
2659 ERR("device_proxy returned NULL");
2660 return BT_STATUS_FAIL;
2663 INFO("Request LeConnUpdate");
2664 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2665 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2666 G_DBUS_CALL_FLAGS_NONE,
2671 g_object_unref(device_proxy);
2672 if (reply == NULL) {
2674 ERR("Error %s[%s]", error->message, device_address);
2675 if (g_strrstr(error->message, "In Progress"))
2676 ret = BT_STATUS_SUCCESS;
2678 ret = BT_STATUS_FAIL;
2679 g_error_free(error);
2683 g_variant_unref(reply);
2685 DBG("LE Connection parameter Updated");
2689 /** Request a connection parameter update */
2690 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2692 CHECK_BTGATT_INIT();
2694 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2697 /** Test mode interface */
2698 bt_status_t test_command(int command, btgatt_test_params_t* params)
2700 CHECK_BTGATT_INIT();
2701 return BT_STATUS_UNSUPPORTED;
2704 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2707 GError *g_error = NULL;
2708 GVariant *reply = NULL;
2709 int result = BT_STATUS_SUCCESS;
2710 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2711 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2713 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2714 g_object_unref(proxy);
2715 if (reply == NULL) {
2716 ERR("Connect LE Dbus Call Error");
2718 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2719 g_clear_error(&g_error);
2721 result = BT_STATUS_FAIL;
2723 g_variant_unref(reply);
2725 memset(&ev, 0, sizeof(ev));
2727 ev.mtu = conn_mtu->mtu;
2728 ev.conn_id = conn_mtu->conn_id;
2731 ERR("gatt client callback not registered");
2733 DBG("sending gatt client MTU exchange completed event");
2734 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2741 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2743 gchar *device_path = NULL;
2744 GDBusProxy *device_proxy = NULL;
2745 GDBusConnection *conn;
2746 hal_gattc_client_info_t *gattc_client = NULL;
2747 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2748 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2750 conn = _bt_hal_get_system_gconn();
2754 return BT_STATUS_FAIL;
2757 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2758 if (gattc_client == NULL) {
2759 INFO("GATT client conn info not found");
2761 return BT_STATUS_FAIL;
2764 _bt_hal_convert_addr_type_to_string(device_address,
2765 (unsigned char *)gattc_client->bd_addr.address);
2767 device_path = _bt_hal_get_device_object_path(device_address);
2768 if (device_path == NULL) {
2769 ERR("device_path NULL : [%s]", device_address);
2771 return BT_STATUS_FAIL;
2774 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2775 NULL, BT_HAL_BLUEZ_NAME,
2776 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2778 g_free(device_path);
2779 if (NULL == device_proxy) {
2780 ERR("device_proxy returned NULL");
2782 return BT_STATUS_FAIL;
2785 conn_mtu->conn_id = conn_id;
2786 conn_mtu->mtu = mtu;
2788 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2789 g_variant_new("(q)", mtu),
2790 G_DBUS_CALL_FLAGS_NONE,
2791 BT_HAL_MAX_DBUS_TIMEOUT,
2793 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2796 return BT_STATUS_SUCCESS;
2799 /** MTU Exchange request from client */
2800 static bt_status_t configure_mtu(int conn_id, int mtu)
2802 CHECK_BTGATT_INIT();
2804 return __hal_configure_mtu(conn_id, mtu);
2807 /** Setup scan filter params */
2808 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2809 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2810 int rssi_low_thres, int dely_mode, int found_timeout,
2811 int lost_timeout, int found_timeout_cnt)
2814 GError *error = NULL;
2815 GVariant *ret, *param;
2816 CHECK_BTGATT_INIT();
2818 proxy = _bt_hal_get_adapter_proxy();
2821 return BT_STATUS_FAIL;
2823 param = g_variant_new("(iiiiiiiiiiii)",
2836 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2837 param, G_DBUS_CALL_FLAGS_NONE,
2841 ERR("scan_filter_param_setup Fail: %s", error->message);
2842 g_clear_error(&error);
2843 return BT_STATUS_FAIL;
2847 g_variant_unref(ret);
2849 return BT_STATUS_SUCCESS;
2852 /** Configure a scan filter condition */
2853 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2854 int filt_index, int company_id,
2855 int company_id_mask, const bt_uuid_t *p_uuid,
2856 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2857 char addr_type, int data_len, char* p_data, int mask_len,
2861 GError *error = NULL;
2862 GVariant *ret, *param;
2863 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2864 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2865 GArray *arr_uuid = NULL;
2866 GArray *arr_uuid_mask = NULL;
2867 GArray *arr_data = NULL;
2868 GArray *arr_data_mask = NULL;
2869 CHECK_BTGATT_INIT();
2871 proxy = _bt_hal_get_adapter_proxy();
2874 return BT_STATUS_FAIL;
2876 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2878 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2880 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2882 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2884 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2885 NULL, 0, TRUE, NULL, NULL);
2886 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2887 NULL, 0, TRUE, NULL, NULL);
2888 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2889 NULL, 0, TRUE, NULL, NULL);
2890 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2891 NULL, 0, TRUE, NULL, NULL);
2893 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2894 client_if, // client_if
2895 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2896 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2897 filt_index, // filter_index
2898 company_id, // company_id
2899 company_id_mask, // company_id_mask
2900 arr_uuid_param, // p_uuid
2901 arr_uuid_mask_param, // p_uuid_mask
2903 addr_type, // address_type
2904 arr_data_param, // p_data
2905 arr_data_mask_param); // p_mask
2907 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2908 param, G_DBUS_CALL_FLAGS_NONE,
2912 ERR("scan_filter_add_remove Fail: %s", error->message);
2913 g_clear_error(&error);
2914 return BT_STATUS_FAIL;
2918 g_variant_unref(ret);
2920 return BT_STATUS_SUCCESS;
2923 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2925 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2926 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2927 NULL, 0, TRUE, NULL, NULL);
2928 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2929 NULL, 0, TRUE, NULL, NULL);
2930 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2931 NULL, 0, TRUE, NULL, NULL);
2932 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2933 NULL, 0, TRUE, NULL, NULL);
2935 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2936 client_if, // client_if
2937 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2938 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2939 filt_index, // filter_index
2940 company_id, // company_id
2941 company_id_mask, // company_id_mask
2942 arr_uuid_param, // p_uuid
2943 arr_uuid_mask_param, // p_uuid_mask
2945 addr_type, // address_type
2946 arr_data_param, // p_data
2947 arr_data_mask_param);
2949 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2950 param, G_DBUS_CALL_FLAGS_NONE,
2954 ERR("scan_filter_add_remove Fail: %s", error->message);
2955 g_clear_error(&error);
2956 return BT_STATUS_FAIL;
2960 g_variant_unref(ret);
2962 return BT_STATUS_SUCCESS;
2965 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2967 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2968 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2970 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2971 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2973 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2974 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2975 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2976 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2977 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2978 NULL, 0, TRUE, NULL, NULL);
2979 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2980 NULL, 0, TRUE, NULL, NULL);
2982 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2983 client_if, // client_if
2984 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2985 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
2986 filt_index, // filter_index
2987 company_id, // company_id
2988 company_id_mask, // company_id_mask
2989 arr_uuid_param, // p_uuid
2990 arr_uuid_mask_param, // p_uuid_mask
2992 addr_type, // address_type
2993 arr_data_param, // p_data
2994 arr_data_mask_param);
2996 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2997 param, G_DBUS_CALL_FLAGS_NONE,
3001 ERR("scan_filter_add_remove Fail: %s", error->message);
3002 g_clear_error(&error);
3003 return BT_STATUS_FAIL;
3007 g_variant_unref(ret);
3009 g_array_free(arr_uuid, TRUE);
3010 g_array_free(arr_uuid_mask, TRUE);
3012 return BT_STATUS_SUCCESS;
3015 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3017 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3018 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3020 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3021 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3023 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3024 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3025 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3026 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3027 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3028 NULL, 0, TRUE, NULL, NULL);
3029 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3030 NULL, 0, TRUE, NULL, NULL);
3032 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3033 client_if, // client_if
3034 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3035 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3036 filt_index, // filter_index
3037 company_id, // company_id
3038 company_id_mask, // company_id_mask
3039 arr_uuid_param, // p_uuid
3040 arr_uuid_mask_param, // p_uuid_mask
3042 addr_type, // address_type
3043 arr_data_param, // p_data
3044 arr_data_mask_param);
3046 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3047 G_DBUS_CALL_FLAGS_NONE,
3051 ERR("scan_filter_add_remove Fail: %s", error->message);
3052 g_clear_error(&error);
3053 return BT_STATUS_FAIL;
3057 g_variant_unref(ret);
3059 g_array_free(arr_uuid, TRUE);
3060 g_array_free(arr_uuid_mask, TRUE);
3062 return BT_STATUS_SUCCESS;
3065 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3067 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3068 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3070 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3071 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3073 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3074 NULL, 0, TRUE, NULL, NULL);
3075 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3076 NULL, 0, TRUE, NULL, NULL);
3077 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3078 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3079 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3080 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3082 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3083 client_if, // client_if
3084 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3085 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3086 filt_index, // filter_index
3087 company_id, // company_id
3088 company_id_mask, // company_id_mask
3089 arr_uuid_param, // p_uuid
3090 arr_uuid_mask_param, // p_uuid_mask
3092 addr_type, // address_type
3093 arr_data_param, // p_data
3094 arr_data_mask_param);
3096 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3097 G_DBUS_CALL_FLAGS_NONE,
3101 ERR("scan_filter_add_remove Fail: %s", error->message);
3102 g_clear_error(&error);
3103 return BT_STATUS_FAIL;
3107 g_variant_unref(ret);
3109 g_array_free(arr_data, TRUE);
3110 g_array_free(arr_data_mask, TRUE);
3112 return BT_STATUS_SUCCESS;
3115 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3117 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3118 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3120 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3121 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3123 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3124 NULL, 0, TRUE, NULL, NULL);
3125 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3126 NULL, 0, TRUE, NULL, NULL);
3127 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3128 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3129 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3130 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3132 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3133 client_if, // client_if
3134 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3135 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3136 filt_index, // filter_index
3137 company_id, // company_id
3138 company_id_mask, // company_id_mask
3139 arr_uuid_param, // p_uuid
3140 arr_uuid_mask_param, // p_uuid_mask
3142 addr_type, // address_type
3143 arr_data_param, // p_data
3144 arr_data_mask_param);
3146 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3147 G_DBUS_CALL_FLAGS_NONE,
3151 ERR("scan_filter_add_remove Fail: %s", error->message);
3152 g_clear_error(&error);
3153 return BT_STATUS_FAIL;
3157 g_variant_unref(ret);
3159 g_array_free(arr_data, TRUE);
3160 g_array_free(arr_data_mask, TRUE);
3162 return BT_STATUS_SUCCESS;
3165 return BT_STATUS_UNSUPPORTED;
3168 /** Clear all scan filter conditions for specific filter index*/
3169 bt_status_t scan_filter_clear(int client_if, int filt_index)
3172 GError *error = NULL;
3174 CHECK_BTGATT_INIT();
3176 proxy = _bt_hal_get_adapter_proxy();
3178 return BT_STATUS_FAIL;
3180 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3181 g_variant_new("(ii)", client_if, filt_index),
3182 G_DBUS_CALL_FLAGS_NONE,
3186 ERR("scan_filter_clear Fail: %s", error->message);
3187 g_clear_error(&error);
3188 return BT_STATUS_FAIL;
3191 g_variant_unref(ret);
3192 return BT_STATUS_SUCCESS;
3195 /** Enable / disable scan filter feature*/
3196 bt_status_t scan_filter_enable(int client_if, bool enable)
3199 GError *error = NULL;
3201 CHECK_BTGATT_INIT();
3203 proxy = _bt_hal_get_adapter_proxy();
3205 return BT_STATUS_FAIL;
3207 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3208 g_variant_new("(ib)", client_if, enable),
3209 G_DBUS_CALL_FLAGS_NONE,
3213 ERR("scan_filter_enable Fail: %s", error->message);
3214 g_clear_error(&error);
3215 return BT_STATUS_FAIL;
3217 g_variant_unref(ret);
3219 return BT_STATUS_SUCCESS;
3222 /** Sets the LE scan interval and window in units of N*0.625 msec */
3224 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3228 CHECK_BTGATT_INIT();
3230 le_scan_type = scan_type;
3231 ret = _bt_hal_adapter_le_set_scan_parameters(
3232 scan_type, scan_interval, scan_window);
3236 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3238 CHECK_BTGATT_INIT();
3239 return BT_STATUS_UNSUPPORTED;
3243 /* Configure the batchscan storage */
3244 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3245 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3247 CHECK_BTGATT_INIT();
3248 return BT_STATUS_UNSUPPORTED;
3251 /* Enable batchscan */
3252 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3253 int scan_interval, int scan_window, int addr_type, int discard_rule)
3255 CHECK_BTGATT_INIT();
3256 return BT_STATUS_UNSUPPORTED;
3259 /* Disable batchscan */
3260 bt_status_t batchscan_dis_batch_scan(int client_if)
3262 CHECK_BTGATT_INIT();
3263 return BT_STATUS_UNSUPPORTED;
3266 /* Read out batchscan reports */
3267 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3269 CHECK_BTGATT_INIT();
3270 return BT_STATUS_UNSUPPORTED;
3273 const btgatt_client_interface_t btgatt_client_interface = {
3274 .register_client = btif_gattc_register_client,
3275 .unregister_client = btif_gattc_unregister_client,
3277 .connect = btif_gattc_client_connect,
3278 .disconnect = btif_gattc_client_disconnect,
3280 .search_service = btif_gattc_client_search_service,
3281 .get_included_service = get_included_service,
3282 .get_characteristic = btif_gattc_get_characteristic,
3283 .get_descriptor = btif_gattc_get_descriptor,
3284 .read_characteristic = btif_read_characteristic,
3285 .write_characteristic = btif_write_characteristic,
3286 .acquire_write = btif_get_acquire_write_fd,
3287 .acquire_notify = btif_get_acquire_notify_fd,
3288 .read_descriptor = btif_read_descriptor,
3289 .write_descriptor = btif_write_descriptor,
3290 .execute_write = execute_write,
3291 .register_for_notification = btif_register_for_notification,
3292 .deregister_for_notification = btif_deregister_for_notification,
3293 .read_remote_rssi = read_remote_rssi,
3294 .ota_fw_update = ota_fw_update,
3295 .get_device_type = get_device_type,
3296 .conn_parameter_update = btif_gattc_conn_parameter_update,
3297 .test_command = test_command,
3298 .configure_mtu = configure_mtu,
3299 .scan_filter_param_setup = scan_filter_param_setup,
3300 .scan_filter_add_remove = scan_filter_add_remove,
3301 .scan_filter_clear = scan_filter_clear,
3302 .scan_filter_enable = scan_filter_enable,
3303 .set_scan_parameters = set_scan_parameters,
3304 .batchscan_cfg_storage = batchscan_cfg_storage,
3305 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3306 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3307 .batchscan_read_reports = batchscan_read_reports,
3308 .add_connection_info = btif_gattc_add_connection_info,
3311 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3314 hal_gattc_server_info_t *info = NULL;
3316 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3317 info = (hal_gattc_server_info_t*)l->data;
3321 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3328 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3331 hal_gattc_client_info_t *info = NULL;
3333 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3334 info = (hal_gattc_client_info_t*)l->data;
3338 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3345 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3348 hal_gattc_client_info_t *info = NULL;
3350 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3351 info = (hal_gattc_client_info_t*)l->data;
3355 if (info->conn_id == conn_id)
3362 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3365 hal_gattc_server_info_t *info = NULL;
3366 hal_gattc_client_info_t *gattc_client = NULL;
3368 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3369 if (gattc_client == NULL) {
3370 ERR("GATT client conn info not found");
3374 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3375 info = (hal_gattc_server_info_t*)l->data;
3379 if ((info->inst_id == gattc_client->inst_id) &&
3380 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3387 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3388 gboolean auto_connect)
3390 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3391 gchar *device_path = NULL;
3392 GDBusProxy *device_proxy = NULL;
3393 GDBusConnection *conn;
3394 int ret = BT_STATUS_SUCCESS;
3395 hal_gattc_client_info_t *gattc_data;
3397 if (NULL == bd_addr) {
3398 ERR("bd_addr is NULL");
3399 return BT_STATUS_PARM_INVALID;
3402 conn = _bt_hal_get_system_gconn();
3404 ERR("_bt_gdbus_get_system_gconn returned NULL");
3405 return BT_STATUS_FAIL;
3408 _bt_hal_convert_addr_type_to_string(device_address,
3409 (unsigned char *)bd_addr->address);
3410 device_path = _bt_hal_get_device_object_path(device_address);
3411 if (device_path == NULL) {
3412 ERR("device_path NULL : [%s]", device_address);
3413 ret = BT_STATUS_FAIL;
3417 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3418 NULL, BT_HAL_BLUEZ_NAME,
3419 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3420 g_free(device_path);
3421 if (NULL == device_proxy) {
3422 ERR("device_proxy returned NULL");
3423 return BT_STATUS_FAIL;
3426 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3427 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3428 BT_HAL_ADDRESS_LENGTH_MAX);
3430 DBG("ConnectLE [%s]", device_address);
3432 gattc_data->client_if = client_if;
3434 g_dbus_proxy_call(device_proxy, "ConnectLE",
3435 g_variant_new("(b)", auto_connect),
3436 G_DBUS_CALL_FLAGS_NONE,
3437 BT_HAL_MAX_DBUS_TIMEOUT,
3439 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3444 static bt_status_t _bt_hold_current_advertising()
3446 int ret = BT_STATUS_FAIL;
3447 gboolean is_advertising = FALSE;
3450 is_advertising = _bt_hal_is_advertising_in_slot(0);
3451 if (is_advertising) {
3452 DBG("+ Stop current advertising");
3454 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3455 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3461 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3463 DBG("+ start current advertising");
3465 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3470 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3472 DBG("Try to initiate pending LE connection");
3474 pending_le_conn_timer_id = 0;
3476 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3477 &pending_le_conn_info->bd_addr,
3478 pending_le_conn_info->auto_connect);
3480 g_free(pending_le_conn_info);
3481 pending_le_conn_info = NULL;
3486 static int __hal_generate_conn_id()
3488 return ++bt_conn_id;
3491 static int __hal_generate_server_instance_id()
3493 return ++bt_inst_id;
3496 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3499 GError *g_error = NULL;
3500 GVariant *reply = NULL;
3501 hal_gattc_client_info_t *gattc_data = user_data;
3502 int result = BT_STATUS_SUCCESS;
3503 struct hal_ev_gatt_client_connected ev;
3504 hal_gattc_server_info_t *gatt_conn_info = NULL;
3506 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3507 g_object_unref(proxy);
3508 if (reply == NULL) {
3509 ERR("Connect LE Dbus Call Error");
3511 ERR("Error: %s\n", g_error->message);
3512 g_clear_error(&g_error);
3514 result = BT_STATUS_FAIL;
3516 g_variant_unref(reply);
3518 if (NULL == gattc_data) {
3519 ERR("gattc_data is NULL");
3524 if (result == BT_STATUS_FAIL) {
3525 memset(&ev, 0, sizeof(ev));
3528 ev.client_if = gattc_data->client_if;
3529 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3530 BT_HAL_ADDRESS_LENGTH_MAX);
3533 ERR("gatt client callback not registered");
3535 DBG("sending gatt client connected event");
3536 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3542 DBG("LE connected. Adding the gattc server/client conn info in list");
3543 gattc_data->conn_id = __hal_generate_conn_id() ;
3544 gattc_data->inst_id = __hal_generate_server_instance_id();
3546 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3548 /*add gatt server connection info*/
3549 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3550 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3551 gatt_conn_info->conn_id = gattc_data->conn_id;
3552 gatt_conn_info->inst_id = gattc_data->inst_id;
3553 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3558 /*remove conn_info*/
3563 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3565 g_free(desc_info->desc_path);
3569 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3572 hal_gattc_desc_t *desc_info = NULL;
3573 for (l = char_info->gatt_list_descs; l != NULL; ) {
3574 desc_info = l->data;
3575 l = g_slist_next(l);
3576 if (desc_info == NULL)
3578 /* Remove descriptor element */
3579 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3580 __hal_gattc_free_desc_info(desc_info);
3582 g_slist_free(char_info->gatt_list_descs);
3583 g_free(char_info->chr_path);
3587 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3590 hal_gattc_char_t *char_info = NULL;
3591 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3592 char_info = l->data;
3593 l = g_slist_next(l);
3594 if (char_info == NULL)
3596 /* Remove characteristic element */
3597 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3598 __hal_gattc_free_char_info(char_info);
3600 g_slist_free(svc_info->gatt_list_chars);
3601 g_free(svc_info->svc_path);
3605 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3608 hal_gattc_service_t *svc_info = NULL;
3612 for (l = conn_info->gatt_list_services; l != NULL; ) {
3613 svc_info = (hal_gattc_service_t *)l->data;
3614 l = g_slist_next(l);
3615 if (svc_info == NULL)
3617 /* Remove service element */
3618 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3619 __hal_gattc_free_svc_info(svc_info);
3621 g_slist_free(conn_info->gatt_list_services);
3625 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3627 bt_bdaddr_t bd_addr;
3628 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3629 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3635 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3637 int result = BT_STATUS_SUCCESS;
3638 struct hal_ev_gatt_client_connected ev;
3639 hal_gattc_server_info_t *conn_info = NULL;
3640 bt_bdaddr_t bd_addr;
3642 hal_gattc_client_info_t *gattc_client = NULL;
3645 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3646 HAL_EV_GATT_CLIENT_DISCONNECTED;
3648 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3649 /* find the gatt client info */
3650 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3651 if (NULL == gattc_client) {
3652 ERR("Fail to get gatt client info");
3656 gattc_client->is_gatt_connected = gatt_connected;
3659 memset(&ev, 0, sizeof(ev));
3660 ev.conn_id = gattc_client->conn_id;
3662 ev.client_if = gattc_client->client_if;
3663 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3664 BT_HAL_ADDRESS_LENGTH_MAX);
3667 ERR("gatt client callback not registered");
3669 event_cb(event, (void *)&ev, sizeof(ev));
3672 if (!gatt_connected) {
3673 inst_id = gattc_client->inst_id;
3675 /* remove the gatt client info from the client list also*/
3676 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3677 g_free(gattc_client);
3679 //find the connected server info
3680 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3681 if (NULL == conn_info) {
3682 ERR("Fail to get gatt server info");
3686 if (inst_id != conn_info->inst_id) {
3687 ERR("server instance is different");
3691 //remove gatt conn info from the server list
3692 DBG("remove the server conn_info from list after gatt disconnection");
3693 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3694 __hal_clean_gattc_server_info(conn_info);
3698 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3699 const char* uuid_str, int inst_id)
3701 struct hal_ev_gatt_client_search_result ev;
3704 ERR("gatt client callback not registered");
3708 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3710 memset(&ev, 0, sizeof(ev));
3711 ev.conn_id = conn_id;
3712 ev.inst_id = inst_id;
3713 ev.is_primary = is_primary;
3714 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3716 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3719 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3721 struct hal_ev_gatt_client_search_complete ev;
3724 ERR("gatt client callback not registered");
3728 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3731 memset(&ev, 0, sizeof(ev));
3732 ev.conn_id = conn_id;
3735 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3738 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3739 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3740 char *char_value, int len)
3742 struct hal_ev_gatt_client_notify_changed_value ev;
3743 hal_gattc_client_info_t *gattc_client = NULL;
3746 ERR("gatt client callback not registered");
3750 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3751 if (NULL == gattc_client) {
3752 ERR("failed to get the gatt client info");
3757 DBG("sending gatt client connected status event");
3758 memset(&ev, 0, sizeof(ev));
3760 ev.conn_id = gattc_client->conn_id;
3761 ev.inst_id = conn_info->inst_id;
3762 ev.is_primary = svc_info->is_primary;
3763 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3764 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3766 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3768 if (len > 0 && (char_value != NULL)) {
3769 memcpy(ev.value, char_value, len);
3773 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3776 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3777 char *char_value, int len)
3779 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3780 hal_gattc_server_info_t *conn_info = NULL;
3781 bt_bdaddr_t bd_addr;
3784 hal_gattc_service_t *svc_info = NULL;
3785 hal_gattc_char_t *char_info = NULL;
3789 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3790 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3791 DBG("device address:[%s]", device_address);
3792 DBG("char handle:[%s]", char_handle);
3794 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3795 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3797 if (conn_info != NULL) {
3798 //find service for notified char path
3799 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3800 svc_info = (hal_gattc_service_t*)l->data;
3801 if (svc_info == NULL)
3804 /* find characteristic object path */
3805 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3806 char_info = (hal_gattc_char_t *)k->data;
3807 if (char_info == NULL)
3810 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3811 DBG("Found char handle[%s]", char_info->chr_path);
3814 _bt_hal_send_value_changed_event(conn_info, svc_info,
3815 char_info, char_value, len);
3823 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3825 GDBusConnection *g_conn = NULL;
3826 GDBusProxy *properties_proxy = NULL;
3827 GVariant *result = NULL;
3828 GError *error = NULL;
3829 GVariantIter *property_iter = NULL;
3830 const gchar *key = NULL;
3831 GVariant *value = NULL;
3832 const char *uuid_str = NULL;
3834 gboolean is_primary = FALSE;
3835 GVariantIter *char_iter = NULL;
3836 const char *char_handle = NULL;
3837 GPtrArray *gp_char_array = NULL;
3839 if (service_path == NULL) {
3840 ERR("service_path is NULL");
3841 return BT_STATUS_FAIL;
3844 DBG("service_path: %s", service_path);
3846 g_conn = _bt_hal_get_system_gconn();
3847 if (g_conn == NULL) {
3848 ERR("g_conn is NULL");
3849 return BT_STATUS_FAIL;
3852 properties_proxy = g_dbus_proxy_new_sync(g_conn,
3853 G_DBUS_PROXY_FLAGS_NONE, NULL,
3856 BT_HAL_PROPERTIES_INTERFACE,
3858 if (properties_proxy == NULL) {
3859 ERR("properties_proxy is NULL");
3860 return BT_STATUS_FAIL;
3863 result = g_dbus_proxy_call_sync(properties_proxy,
3865 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
3866 G_DBUS_CALL_FLAGS_NONE,
3868 if (result == NULL) {
3869 if (error != NULL) {
3870 ERR("Fail to get properties (Error: %s)", error->message);
3871 g_clear_error(&error);
3873 ERR("Fail to get properties");
3875 g_object_unref(properties_proxy);
3876 return BT_STATUS_FAIL;
3879 g_variant_get(result, "(a{sv})", &property_iter);
3881 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
3882 if (g_strcmp0(key, "UUID") == 0) {
3883 uuid_str = g_variant_get_string(value, &len);
3884 } else if (g_strcmp0(key, "Primary") == 0) {
3885 is_primary = g_variant_get_boolean(value);
3886 } else if (g_strcmp0(key, "Characteristics") == 0) {
3887 g_variant_get(value, "ao", &char_iter);
3888 if (char_iter != NULL) {
3889 gp_char_array = g_ptr_array_new();
3890 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
3891 DBG("char_handle: %s", char_handle);
3892 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
3894 g_variant_iter_free(char_iter);
3899 if (uuid_str == NULL || gp_char_array == NULL) {
3900 ERR("uuid_str and gp_char_array should be set");
3904 /* Create new service */
3905 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
3908 g_variant_iter_free(property_iter);
3909 g_variant_unref(result);
3910 g_object_unref(properties_proxy);
3912 return BT_STATUS_SUCCESS;
3915 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
3917 GDBusConnection *conn = NULL;
3918 GDBusProxy *proxy = NULL;
3920 GVariant *ret = NULL;
3921 GVariant *value = NULL;
3923 conn = _bt_hal_get_system_gconn();
3925 ERR("_bt_gdbus_get_system_gconn returned NULL");
3929 proxy = g_dbus_proxy_new_sync(conn,
3930 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
3931 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
3932 if (proxy == NULL) {
3933 ERR("device_proxy returned NULL");
3937 ret = g_dbus_proxy_call_sync(proxy, "Get",
3938 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
3939 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3941 ERR("DBus Error : %s", err->message);
3942 g_clear_error(&err);
3944 g_variant_get(ret, "(v)", &value);
3945 *service_uuid = g_variant_dup_string(value, NULL);
3946 g_variant_unref(value);
3947 g_variant_unref(ret);
3951 g_object_unref(proxy);
3956 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
3958 struct hal_ev_gatt_client_service_changed ev = {0, };
3959 char address[BT_HAL_ADDRESS_STRING_SIZE];
3960 hal_gattc_server_info_t *server_info = NULL;
3961 hal_gattc_client_info_t *gattc_client = NULL;
3962 hal_gattc_service_t *service = NULL;
3963 GSList *list = NULL;
3964 char *uuid_str = NULL;
3966 _bt_hal_convert_device_path_to_address(path, address);
3967 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
3968 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
3969 if (server_info == NULL) {
3970 ERR("server_info is NULL");
3974 gattc_client = __bt_find_gatt_client_info((bt_bdaddr_t *)ev.bdaddr);
3975 if (gattc_client == NULL) {
3976 ERR("gattc_client is NULL");
3980 if (server_info->is_gatt_connected == FALSE && gattc_client->is_gatt_connected == FALSE) {
3981 DBG("GattConnected signal is not received yet. Just skip [%d %d]",
3982 server_info->is_gatt_connected, gattc_client->is_gatt_connected);
3987 /* Get service UUID from path */
3988 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
3990 DBG("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
3991 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3994 ERR("uuid_str is NULL");
3998 /* Create new service and append into the list */
3999 __hal_gattc_get_service_info(server_info, path);
4001 /* Find service UUID from path */
4002 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4003 service = (hal_gattc_service_t *)list->data;
4004 if (service == NULL)
4007 if (g_strcmp0(service->svc_path, path) == 0) {
4008 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4009 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4010 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4011 DBG("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
4013 /* Remove service info in list */
4014 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4015 __hal_gattc_free_svc_info(service);
4023 ERR("uuid_str is NULL");
4028 /* Send GATT Client service changed event */
4029 ev.change_type = is_added;
4030 ev.conn_id = server_info->conn_id;
4031 ev.inst_id = server_info->inst_id;
4032 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));