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 int hal_gatt_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;
377 gboolean is_deleted = FALSE;
380 client_count = g_slist_length(hal_gattc_client_app_list);
382 /* remove the gatt client app */
383 for (l = hal_gattc_client_app_list; l != NULL; ) {
384 info = (hal_gatt_client_app*)l->data;
390 if (info->client_if == client_if) {
391 __bt_hal_gatt_delete_if(client_if);
393 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
399 DBG("Deleted. registered client count: [%d -> %d]", client_count, g_slist_length(hal_gattc_client_app_list));
401 ERR("Not deleted. registered client count: [%d]", client_count);
403 return BT_STATUS_SUCCESS;
406 /** Unregister a client application from the stack */
407 bt_status_t btif_gattc_unregister_client(int client_if)
411 return __hal_gattc_unregister_client(client_if);
414 /** Start or stop LE device scanning */
415 bt_status_t scan(int client_if, bool start)
422 ret = _bt_hal_adapter_le_start_scan();
424 ret = _bt_hal_adapter_le_stop_scan();
429 /** Create a connection to a remote LE or dual-mode device */
430 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
433 int ret = BT_STATUS_SUCCESS;
438 return BT_STATUS_PARM_INVALID;
440 ret = _bt_hold_current_advertising();
441 if (ret == BT_STATUS_SUCCESS) {
442 DBG("Current advertising is held");
443 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
444 pending_le_conn_info->client_if = client_if;
445 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
446 BT_HAL_ADDRESS_LENGTH_MAX);
447 pending_le_conn_info->auto_connect = is_direct;
449 pending_le_conn_timer_id =
450 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
452 return BT_STATUS_SUCCESS;
454 ERR("advertising is not stopped");
457 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
461 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
464 GError *g_error = NULL;
465 GVariant *reply = NULL;
466 hal_gattc_client_info_t *gatt_conn_info = user_data;
467 int result = BT_STATUS_SUCCESS;
468 struct hal_ev_gatt_client_connected ev;
472 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
473 g_object_unref(proxy);
475 ERR("Connect LE Dbus Call Error");
477 ERR("Error: %s\n", g_error->message);
478 g_clear_error(&g_error);
480 result = BT_STATUS_FAIL;
482 g_variant_unref(reply);
484 if (NULL == gatt_conn_info) {
485 ERR("server_data is NULL");
490 if (result == BT_STATUS_FAIL) {
491 memset(&ev, 0, sizeof(ev));
492 ev.conn_id = gatt_conn_info->conn_id;
494 ev.client_if = gatt_conn_info->client_if;
495 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
496 BT_HAL_ADDRESS_LENGTH_MAX);
499 ERR("gatt client callback not registered");
501 DBG("sending gatt client disconnected event");
502 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
508 g_free(gatt_conn_info);
513 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
516 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
518 GDBusProxy *device_proxy;
519 GDBusConnection *conn;
520 int ret = BT_STATUS_SUCCESS;
521 hal_gattc_client_info_t *gattc_data;
523 if (NULL == bd_addr) {
524 ERR("bd_addr is NULL");
525 return BT_STATUS_PARM_INVALID;
528 conn = _bt_hal_get_system_gconn();
530 ERR("_bt_gdbus_get_system_gconn returned NULL");
531 return BT_STATUS_FAIL;
534 _bt_hal_convert_addr_type_to_string(device_address,
535 (unsigned char *)bd_addr->address);
536 device_path = _bt_hal_get_device_object_path(device_address);
537 if (device_path == NULL) {
538 DBG("device_path NULL");
539 ret = BT_STATUS_FAIL;
543 ERR("device_path:%s", device_path);
545 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
546 NULL, BT_HAL_BLUEZ_NAME,
547 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
549 if (NULL == device_proxy) {
550 ERR("device_proxy returned NULL");
551 return BT_STATUS_FAIL;
554 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
555 memcpy(gattc_data->bd_addr.address, bd_addr->address,
556 BT_HAL_ADDRESS_LENGTH_MAX);
557 gattc_data->client_if = client_if;
558 gattc_data->conn_id = conn_id;
560 DBG("DisconnectLE [%s]", device_address);
562 g_dbus_proxy_call(device_proxy, "DisconnectLE",
564 G_DBUS_CALL_FLAGS_NONE,
565 BT_HAL_MAX_DBUS_TIMEOUT,
567 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
571 /** Disconnect a remote device or cancel a pending connection */
572 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
577 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
580 /** Clear the attribute cache for a given device */
581 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
584 return BT_STATUS_UNSUPPORTED;
587 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
590 hal_gattc_service_t *info = NULL;
592 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
593 info = (hal_gattc_service_t*)l->data;
597 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t)))
605 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
606 bt_gatt_characteristic_property_t prop)
609 hal_gattc_char_t *info = NULL;
611 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
612 info = (hal_gattc_char_t*)l->data;
616 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
617 (info->permission & prop)) {
624 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
627 hal_gattc_char_t *info = NULL;
629 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
630 info = (hal_gattc_char_t*)l->data;
634 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
635 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
636 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
643 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
646 hal_gattc_desc_t *info = NULL;
648 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
649 info = (hal_gattc_desc_t*)l->data;
653 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t)))
660 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
661 const char *uuid_str, const char *object_path, int is_primary)
663 hal_gattc_service_t *gattc_service = NULL;
665 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
666 gattc_service->svc_path = g_strdup(object_path);
667 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
668 gattc_service->is_primary = is_primary;
670 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
671 INFO("Toatal svc [%d] Added [%s] [%s]", g_slist_length(conn_info->gatt_list_services), object_path + 15, uuid_str);
673 return gattc_service;
676 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
678 hal_gattc_char_t *gattc_char = NULL;
680 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
681 gattc_char->chr_path = g_strdup(char_handle);
683 DBG("[%s]", gattc_char->chr_path + 15);
685 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
688 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
689 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
691 hal_gattc_service_t* gatt_svc = NULL;
693 gchar *gp_char_path = NULL;
695 /* add the service */
696 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
697 if (gatt_svc == NULL) {
698 ERR("Failed to add service");
702 /* add the characteristic */
703 for (i = 0; i < gp_char_array->len; i++) {
704 gp_char_path = g_ptr_array_index(gp_char_array, i);
705 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
708 g_ptr_array_free(gp_char_array, TRUE);
711 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
713 hal_gattc_desc_t *gattc_desc = NULL;
715 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
716 gattc_desc->desc_path = g_strdup(desc_path);
718 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
721 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
722 GPtrArray *gp_desc_array, unsigned int char_permission)
724 gchar *gp_desc_path = NULL;
727 if (char_uuid_str == NULL) {
728 DBG("char_uuid_str is NULL");
732 //update the char uuid
733 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
735 //update char permission
736 gattc_char->permission = char_permission;
739 for (i = 0; i < gp_desc_array->len; i++) {
740 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
741 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
745 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
747 if (desc_uuid_str == NULL) {
748 DBG("char_uuid_str is NULL");
752 //update the descriptor uuid
753 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
755 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
758 static void browse_service_char(int conn_id)
760 hal_gattc_server_info_t *conn_info = NULL;
764 hal_gattc_service_t *svc_info = NULL;
765 hal_gattc_char_t *char_info = NULL;
766 hal_gattc_desc_t *desc_info = NULL;
768 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
769 if (conn_info == NULL) {
770 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
774 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
775 svc_info = (hal_gattc_service_t*)l->data;
776 if (svc_info == NULL)
779 /* find characteristic object path */
780 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
781 char_info = (hal_gattc_char_t *)k->data;
782 if (char_info == NULL)
786 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
787 desc_info = (hal_gattc_desc_t *)m->data;
788 if (desc_info == NULL)
798 * Enumerate all GATT services on a connected device.
799 * Optionally, the results can be filtered for a given UUID.
801 static bt_status_t _gattc_client_search_service(int conn_id)
805 GVariant *result = NULL;
807 GVariantIter *svc_iter;
808 GVariantIter *interface_iter;
809 char *object_path = NULL;
810 char *interface_str = NULL;
811 const gchar *key = NULL;
812 GVariant *value = NULL;
813 GPtrArray *gp_array = NULL;
814 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
815 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
816 int ret = BT_STATUS_FAIL;
818 const gchar *uuid_str = NULL;
820 hal_gattc_server_info_t *conn_info = NULL;
821 gboolean is_primary = FALSE;
824 char *char_handle = NULL;
825 GVariantIter *char_iter = NULL;
826 GPtrArray *gp_char_array = NULL;
828 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
829 if (NULL == conn_info) {
830 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
831 return BT_STATUS_FAIL;
835 // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
836 /* Check the service info is stored */
837 if (g_slist_length(conn_info->gatt_list_services) > 0) {
839 hal_gattc_service_t *svc_info = NULL;
840 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
841 DBG("Send event from service info list");
842 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
844 if (svc_info == NULL)
846 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
847 _bt_hal_send_search_service_result_event(conn_id,
848 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
850 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
851 return BT_STATUS_SUCCESS;
853 DBG("No stored service, request to bluez");
857 _bt_hal_convert_addr_type_to_string(device_address,
858 (unsigned char *)conn_info->bd_addr.address);
860 result = _bt_hal_get_managed_objects();
864 gp_array = g_ptr_array_new();
865 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
867 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
869 if (object_path == NULL)
872 _bt_hal_convert_device_path_to_address(object_path, temp_address);
874 if (g_strcmp0(temp_address, device_address) != 0)
877 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
878 &interface_str, &svc_iter)) {
879 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
882 DBG("[%d] %s", idx++, object_path + 15);
883 /* for characteristic */
884 gp_char_array = g_ptr_array_new();
885 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
886 if (g_strcmp0(key, "Primary") == 0) {
887 is_primary = g_variant_get_boolean(value);
889 g_ptr_array_add(gp_array, (gpointer)object_path);
892 } else if (g_strcmp0(key, "UUID") == 0) {
893 uuid_str = g_variant_get_string(value, &len);
894 } else if (g_strcmp0(key, "Characteristics") == 0) {
895 g_variant_get(value, "ao", &char_iter);
896 if (char_iter != NULL) {
897 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
898 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
905 _bt_hal_send_search_service_result_event(conn_id, is_primary,
906 uuid_str, conn_info->inst_id);
908 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
913 if (gp_array->len == 0 || svc_count == 0) {
914 ERR("gp_array is NULL");
915 ret = BT_STATUS_FAIL;
917 ret = BT_STATUS_SUCCESS;
920 browse_service_char(conn_id);
921 /* send search service complete event */
922 _bt_hal_send_search_service_complete_event(conn_id, ret);
924 g_ptr_array_free(gp_array, TRUE);
925 g_variant_iter_free(iter);
926 g_variant_unref(result);
931 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
933 if (NULL == filter_uuid) {
934 DBG("Browse all the services");
935 return _gattc_client_search_service(conn_id);
937 DBG("TODO implement it");
938 return BT_STATUS_UNSUPPORTED;
942 * Enumerate included services for a given service.
943 * Set start_incl_srvc_id to NULL to get the first included service.
945 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
946 btgatt_srvc_id_t *start_incl_srvc_id)
949 return BT_STATUS_UNSUPPORTED;
952 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
953 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
955 struct hal_ev_gatt_client_char_search_result ev;
958 ERR("gatt client callback not registered");
962 memset(&ev, 0, sizeof(ev));
963 ev.conn_id = conn_id;
964 ev.inst_id = svc_id->id.inst_id;
965 ev.is_primary = svc_id->is_primary;
967 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
969 if (status == BT_STATUS_SUCCESS) {
970 /* building char uuid */
971 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
972 ev.char_prop = char_prop;
975 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
976 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
979 static int _hal_get_permission_flag(char *permission)
983 if (NULL == permission) {
984 ERR("gatt permission is NULL");
988 if (!g_strcmp0(permission, "broadcast"))
989 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
990 else if (!g_strcmp0(permission, "read"))
991 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
992 else if (!g_strcmp0(permission, "write-without-response"))
993 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
994 else if (!g_strcmp0(permission, "write"))
995 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
996 else if (!g_strcmp0(permission, "notify"))
997 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
998 else if (!g_strcmp0(permission, "indicate"))
999 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
1000 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
1001 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
1002 else if (!g_strcmp0(permission, "reliable-write"))
1003 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
1004 else if (!g_strcmp0(permission, "writable-auxiliaries"))
1005 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1006 else if (!g_strcmp0(permission, "encrypt-read"))
1007 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1008 else if (!g_strcmp0(permission, "encrypt-write"))
1009 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1010 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1011 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1012 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1013 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1018 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1020 char perm[200] = { 0, };
1022 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1023 g_strlcat(perm, "broadcast ", sizeof(perm));
1024 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1025 g_strlcat(perm, "read ", sizeof(perm));
1026 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1027 g_strlcat(perm, "write-without-response ", sizeof(perm));
1028 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1029 g_strlcat(perm, "write ", sizeof(perm));
1030 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1031 g_strlcat(perm, "notify ", sizeof(perm));
1032 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1033 g_strlcat(perm, "indicate ", sizeof(perm));
1034 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1035 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1036 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1037 g_strlcat(perm, "reliable-write ", sizeof(perm));
1038 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1039 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1040 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1041 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1042 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1043 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1044 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1045 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1046 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1047 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1049 DBG("permission [0x%04x] : %s\n", permission, perm);
1053 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1055 GDBusProxy *properties_proxy = NULL;
1056 GError *error = NULL;
1057 GVariant *value = NULL;
1058 GVariant *result = NULL;
1059 GDBusConnection *g_conn;
1061 char *char_desc_handle = NULL;
1063 GVariantIter *property_iter;
1064 GVariantIter *char_desc_iter;
1065 char* char_handle = NULL;
1066 gchar *char_uuid_str = NULL;
1067 GPtrArray *gp_desc_array = NULL;
1068 GVariantIter *char_perm_iter;
1070 unsigned int char_permission = 0 ;
1072 if (gattc_char->chr_path == NULL) {
1073 DBG("char path is NULL");
1074 return BT_STATUS_FAIL;
1076 char_handle = gattc_char->chr_path;
1078 g_conn = _bt_hal_get_system_gconn();
1079 if (NULL == g_conn) {
1080 ERR("_bt_gdbus_get_system_gconn returned NULL");
1081 return BT_STATUS_FAIL;
1084 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1085 G_DBUS_PROXY_FLAGS_NONE, NULL,
1088 BT_HAL_PROPERTIES_INTERFACE,
1091 if (properties_proxy == NULL) {
1092 ERR("properties_proxy returned NULL");
1093 return BT_STATUS_FAIL;
1096 result = g_dbus_proxy_call_sync(properties_proxy,
1098 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1099 G_DBUS_CALL_FLAGS_NONE,
1104 if (error != NULL) {
1105 ERR("Fail to get properties (Error: %s)", error->message);
1106 g_clear_error(&error);
1108 ERR("Fail to get properties");
1109 g_object_unref(properties_proxy);
1110 return BT_STATUS_FAIL;
1113 gp_desc_array = g_ptr_array_new();
1115 g_variant_get(result, "(a{sv})", &property_iter);
1117 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1118 if (!g_strcmp0(key, "UUID")) {
1119 char_uuid_str = g_variant_dup_string(value, &len);
1120 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1121 } else if (!g_strcmp0(key, "Flags")) {
1122 g_variant_get(value, "as", &char_perm_iter);
1123 char_permission = 0x00;
1125 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1126 char_permission |= _hal_get_permission_flag(permission);
1128 __hal_convert_permission_flag_to_str(char_permission);
1129 g_variant_iter_free(char_perm_iter);
1130 } else if (!g_strcmp0(key, "Descriptors")) {
1131 g_variant_get(value, "ao", &char_desc_iter);
1132 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1133 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1135 g_variant_iter_free(char_desc_iter);
1139 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1141 g_free(char_uuid_str);
1142 g_variant_iter_free(property_iter);
1143 g_variant_unref(result);
1144 g_object_unref(properties_proxy);
1145 g_ptr_array_free(gp_desc_array, TRUE);
1147 return BT_STATUS_SUCCESS;
1150 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1151 btgatt_srvc_id_t *srvc_id)
1153 hal_gattc_server_info_t * conn_info = NULL;
1154 hal_gattc_service_t *gattc_service = NULL;
1156 hal_gattc_char_t *gattc_char = NULL;
1157 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1158 int status = BT_STATUS_FAIL;
1160 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1161 if (NULL == conn_info) {
1162 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1163 return BT_STATUS_FAIL;
1167 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1168 if (NULL == gattc_service) {
1169 ERR("Failed to get the gatt service");
1170 return BT_STATUS_FAIL;
1173 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1174 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1176 /* find characteristic object path */
1177 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1178 gattc_char = (hal_gattc_char_t *)l->data;
1179 status = _hal_gattc_get_characteristic_info(gattc_char);
1182 if (BT_STATUS_SUCCESS == status) {
1183 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1184 &gattc_char->chr_uuid, gattc_char->permission);
1188 status = BT_STATUS_FAIL;
1189 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1191 browse_service_char(conn_id);
1192 /* retrive uuid for characteristic and object path for descriptor */
1194 return BT_STATUS_SUCCESS;
1198 * Enumerate characteristics for a given service.
1199 * Set start_char_id to NULL to get the first characteristic.
1201 bt_status_t btif_gattc_get_characteristic(int conn_id,
1202 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1204 CHECK_BTGATT_INIT();
1206 if (start_char_id == NULL) {
1207 return _gattc_get_all_characteristic(conn_id, srvc_id);
1210 DBG("TBD Get specific characteristics");
1211 return BT_STATUS_UNSUPPORTED;
1215 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1217 GDBusProxy *properties_proxy = NULL;
1218 GError *error = NULL;
1219 GVariant *value = NULL;
1220 GVariant *result = NULL;
1221 GDBusConnection *g_conn;
1224 GVariantIter *property_iter;
1225 char* desc_handle = NULL;
1226 const gchar *desc_uuid_str = NULL;
1228 if (gattc_desc->desc_path == NULL) {
1229 DBG("desc path is NULL");
1230 return BT_STATUS_FAIL;
1232 desc_handle = gattc_desc->desc_path;
1234 g_conn = _bt_hal_get_system_gconn();
1235 if (NULL == g_conn) {
1236 ERR("_bt_gdbus_get_system_gconn returned NULL");
1237 return BT_STATUS_FAIL;
1240 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1241 G_DBUS_PROXY_FLAGS_NONE, NULL,
1244 BT_HAL_PROPERTIES_INTERFACE,
1247 if (properties_proxy == NULL) {
1248 ERR("properties_proxy returned NULL");
1249 return BT_STATUS_FAIL;
1252 result = g_dbus_proxy_call_sync(properties_proxy,
1254 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1255 G_DBUS_CALL_FLAGS_NONE,
1260 if (error != NULL) {
1261 ERR("Fail to get properties (Error: %s)", error->message);
1262 g_clear_error(&error);
1264 ERR("Fail to get properties");
1265 g_object_unref(properties_proxy);
1266 return BT_STATUS_FAIL;
1269 g_variant_get(result, "(a{sv})", &property_iter);
1271 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1272 if (!g_strcmp0(key, "UUID")) {
1273 desc_uuid_str = g_variant_get_string(value, &len);
1274 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1276 g_free((gchar *)key);
1277 g_variant_unref(value);
1282 g_variant_iter_free(property_iter);
1283 g_variant_unref(result);
1284 g_object_unref(properties_proxy);
1286 return BT_STATUS_SUCCESS;
1289 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1290 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1292 struct hal_ev_gatt_client_desc_search_result ev;
1295 ERR("gatt client callback not registered");
1299 memset(&ev, 0, sizeof(ev));
1300 ev.conn_id = conn_id;
1301 ev.inst_id = svc_id->id.inst_id;
1302 ev.is_primary = svc_id->is_primary;
1305 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1306 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1308 if (status == BT_STATUS_SUCCESS) {
1309 /* building desc uuid */
1310 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1313 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1315 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1318 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1319 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1321 hal_gattc_server_info_t * conn_info = NULL;
1322 hal_gattc_service_t *gattc_service = NULL;
1325 hal_gattc_char_t *gattc_char = NULL;
1326 hal_gattc_desc_t *gattc_desc = NULL;
1327 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1328 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1329 int status = BT_STATUS_FAIL;
1331 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1332 if (NULL == conn_info) {
1333 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1334 return BT_STATUS_FAIL;
1338 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1339 if (NULL == gattc_service) {
1340 ERR("Failed to get the gatt service");
1341 return BT_STATUS_FAIL;
1344 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1345 // DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1347 /* find characteristics */
1348 /* a service can have two char with same uuid */
1349 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1350 gattc_char = (hal_gattc_char_t*)l->data;
1351 if (gattc_char == NULL)
1354 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1355 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1356 // DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1358 /* get descriptor uuid */
1359 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1360 gattc_desc = (hal_gattc_desc_t *)m->data;
1361 if (gattc_desc == NULL)
1364 status = _hal_gattc_get_descriptor_info(gattc_desc);
1367 if (BT_STATUS_SUCCESS == status) {
1368 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1369 char_id, &gattc_desc->desc_uuid);
1375 status = BT_STATUS_FAIL;
1376 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1378 browse_service_char(conn_id);
1379 /* retrive uuid for characteristic and object path for descriptor */
1381 return BT_STATUS_SUCCESS;
1385 * Enumerate descriptors for a given characteristic.
1386 * Set start_descr_id to NULL to get the first descriptor.
1388 bt_status_t btif_gattc_get_descriptor(int conn_id,
1389 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1390 btgatt_gatt_id_t *start_descr_id)
1392 CHECK_BTGATT_INIT();
1394 if (start_descr_id == NULL) {
1395 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1397 DBG("TBD Get specific descriptor");
1398 return BT_STATUS_UNSUPPORTED;
1402 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1404 struct hal_ev_gatt_client_read_data ev;
1407 ERR("gatt client callback not registered");
1411 memset(&ev, 0, sizeof(ev));
1412 ev.conn_id = resp_data->conn_id;
1413 ev.inst_id = resp_data->srvc_id.id.inst_id;
1414 ev.is_primary = resp_data->srvc_id.is_primary;
1417 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1418 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1422 /* building the char read value */
1423 memcpy(ev.value, value, len);
1426 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1428 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1431 static void __hal_internal_read_char_cb(GObject *source_object,
1432 GAsyncResult *res, gpointer user_data)
1434 GError *error = NULL;
1435 GDBusConnection *system_gconn = NULL;
1438 GByteArray *gp_byte_array = NULL;
1440 hal_gatt_resp_data_t *resp_data = user_data;
1441 int result = BT_STATUS_SUCCESS;
1443 system_gconn = _bt_hal_get_system_gconn();
1444 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1447 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1450 result = BT_STATUS_FAIL;
1451 __hal_send_char_read_event(resp_data, result, NULL, 0);
1452 g_clear_error(&error);
1457 gp_byte_array = g_byte_array_new();
1458 g_variant_get(value, "(ay)", &iter);
1460 while (g_variant_iter_loop(iter, "y", &g_byte))
1461 g_byte_array_append(gp_byte_array, &g_byte, 1);
1465 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1469 g_byte_array_free(gp_byte_array, TRUE);
1470 g_variant_iter_free(iter);
1471 g_variant_unref(value);
1475 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1476 btgatt_gatt_id_t *char_id, int auth_req)
1478 GDBusConnection *g_conn;
1479 hal_gatt_resp_data_t *resp_data;
1480 hal_gattc_service_t *gattc_service = NULL;
1481 GVariantBuilder *builder = NULL;
1483 hal_gattc_server_info_t * conn_info = NULL;
1484 hal_gattc_char_t *gattc_char = NULL;
1485 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1486 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1487 char* char_handle = NULL;
1489 /* get the connection info */
1490 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1491 if (NULL == conn_info) {
1492 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1493 return BT_STATUS_FAIL;
1497 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1498 if (NULL == gattc_service) {
1499 ERR("Failed to get the gatt service");
1500 return BT_STATUS_FAIL;
1503 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1505 /* find characteristic */
1506 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1507 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1508 if (NULL == gattc_char) {
1509 ERR("Failed to get the gatt char");
1510 return BT_STATUS_FAIL;
1513 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1514 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1516 g_conn = _bt_hal_get_system_gconn();
1517 if (NULL == g_conn) {
1518 ERR("_bt_gdbus_get_system_gconn returned NULL");
1519 return BT_STATUS_FAIL;
1522 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1523 resp_data->conn_id = conn_id;
1524 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1525 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1527 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1530 g_variant_builder_add(builder, "{sv}", "offset",
1531 g_variant_new("q", offset));
1533 char_handle = gattc_char->chr_path;
1535 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1536 "ReadValue", g_variant_new("(a{sv})", builder),
1537 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1538 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1539 (gpointer)resp_data);
1540 g_variant_builder_unref(builder);
1542 return BT_STATUS_SUCCESS;
1545 /** Read a characteristic on a remote device */
1546 bt_status_t btif_read_characteristic(int conn_id,
1547 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1550 CHECK_BTGATT_INIT();
1552 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1555 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1557 struct hal_ev_gatt_client_write_result ev;
1560 ERR("gatt client callback not registered");
1564 memset(&ev, 0, sizeof(ev));
1565 ev.conn_id = resp_data->conn_id;
1566 ev.inst_id = resp_data->srvc_id.id.inst_id;
1567 ev.is_primary = resp_data->srvc_id.is_primary;
1570 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1571 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1573 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1576 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1577 GAsyncResult *res, gpointer user_data)
1579 GError *error = NULL;
1580 GDBusConnection *system_gconn = NULL;
1582 hal_gatt_resp_data_t *resp_data = user_data;
1583 int result = BT_STATUS_SUCCESS;
1585 system_gconn = _bt_hal_get_system_gconn();
1586 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1589 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1591 result = BT_STATUS_FAIL;
1593 __hal_send_char_write_event(resp_data, result);
1594 g_clear_error(&error);
1599 //send write value event
1600 __hal_send_char_write_event(resp_data, result);
1603 g_variant_unref(value);
1607 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1610 case HAL_GATT_WRITE_TYPE_WRITE:
1611 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1613 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1614 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1617 ERR("Unknow write type : %d", type);
1618 return BT_STATUS_FAIL;
1621 return BT_STATUS_SUCCESS;
1625 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1627 GDBusConnection *conn;
1628 GVariantBuilder *builder = NULL;
1634 GUnixFDList *fd_list = NULL;
1636 conn = _bt_hal_get_system_gconn();
1638 ERR("_bt_gdbus_get_system_gconn returned NULL");
1639 return BT_STATUS_FAIL;
1642 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1643 //val = g_variant_new("ay", builder1);
1645 g_variant_builder_add(builder, "{sv}", "offset",
1646 g_variant_new("q", offset));
1648 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1649 "AcquireWrite", g_variant_new("(a{sv})", builder),
1650 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1651 NULL, &fd_list, NULL, &err);
1653 g_dbus_error_strip_remote_error(err);
1654 ERR("Error: %s", err->message);
1656 g_variant_builder_unref(builder);
1657 return BT_STATUS_FAIL;
1660 g_variant_get(value, "(hq)", &idx, &att_mtu);
1661 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1663 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1666 g_object_unref(fd_list);
1667 g_variant_unref(value);
1668 g_variant_builder_unref(builder);
1670 return BT_STATUS_SUCCESS;
1673 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1675 GDBusConnection *conn;
1676 GVariantBuilder *builder = NULL;
1680 gint32 idx, notify_fd;
1682 GUnixFDList *fd_list = NULL;
1684 conn = _bt_hal_get_system_gconn();
1687 ERR("_bt_gdbus_get_system_gconn returned NULL");
1688 return BT_STATUS_FAIL;
1692 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1695 g_variant_builder_add(builder, "{sv}", "offset",
1696 g_variant_new("q", offset));
1698 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1699 "AcquireNotify", g_variant_new("(a{sv})", builder),
1700 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1701 NULL, &fd_list, NULL, &err);
1703 g_dbus_error_strip_remote_error(err);
1704 ERR("Error: %s", err->message);
1706 g_variant_builder_unref(builder);
1707 return BT_STATUS_FAIL;
1710 g_variant_get(value, "(hq)", &idx, &att_mtu);
1711 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1714 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1718 g_object_unref(fd_list);
1719 g_variant_unref(value);
1720 g_variant_builder_unref(builder);
1722 return BT_STATUS_SUCCESS;
1726 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1727 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1729 GVariant *val, *options;
1730 GVariantBuilder *builder1;
1731 GVariantBuilder *builder2;
1732 GDBusConnection *g_conn;
1735 hal_gatt_resp_data_t *resp_data;
1736 hal_gattc_service_t *gattc_service = NULL;
1737 hal_gattc_server_info_t * conn_info = NULL;
1738 hal_gattc_char_t *gattc_char = NULL;
1739 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1740 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1741 char* char_handle = NULL;
1742 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1743 int ret = BT_STATUS_SUCCESS;
1745 ret = __hal_get_write_prop(write_type, &write_prop);
1746 if (BT_STATUS_FAIL == ret) {
1747 DBG("received invalid write type:[%d] ", write_type);
1748 return BT_STATUS_FAIL;
1751 /* get the connection info */
1752 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1753 if (NULL == conn_info) {
1754 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1755 return BT_STATUS_FAIL;
1759 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1760 if (NULL == gattc_service) {
1761 ERR("Failed to get the gatt service");
1762 return BT_STATUS_FAIL;
1765 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1766 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1768 /* find characteristic */
1769 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1770 if (NULL == gattc_char) {
1771 ERR("Failed to get the gatt char");
1772 return BT_STATUS_FAIL;
1775 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1776 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1778 g_conn = _bt_hal_get_system_gconn();
1779 if (NULL == g_conn) {
1780 ERR("_bt_gdbus_get_system_gconn returned NULL");
1781 return BT_STATUS_FAIL;
1784 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1785 resp_data->conn_id = conn_id;
1786 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1787 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1789 char_handle = gattc_char->chr_path;
1791 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1793 for (i = 0; i < length; i++)
1794 g_variant_builder_add(builder1, "y", value[i]);
1796 val = g_variant_new("ay", builder1);
1798 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1800 g_variant_builder_add(builder2, "{sv}", "offset",
1801 g_variant_new_uint16(offset));
1803 options = g_variant_new("a{sv}", builder2);
1805 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1807 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1809 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1810 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1811 (gpointer)resp_data);
1813 g_variant_builder_unref(builder1);
1814 g_variant_builder_unref(builder2);
1816 return BT_STATUS_SUCCESS;
1819 bt_status_t btif_get_acquire_write_fd(int conn_id,
1820 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1821 int auth_req, int *fd, int*mtu)
1823 CHECK_BTGATT_INIT();
1825 hal_gattc_service_t *gattc_service = NULL;
1826 hal_gattc_server_info_t * conn_info = NULL;
1827 hal_gattc_char_t *gattc_char = NULL;
1828 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1830 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1831 int ret = BT_STATUS_SUCCESS;
1833 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1835 /* get the connection info */
1836 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1837 if (NULL == conn_info) {
1838 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1839 return BT_STATUS_FAIL;
1843 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1844 if (NULL == gattc_service) {
1845 ERR("Failed to get the gatt service");
1846 return BT_STATUS_FAIL;
1849 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1850 if (NULL == gattc_char) {
1851 ERR("Failed to get the gatt char");
1852 return BT_STATUS_FAIL;
1855 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1856 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1858 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1859 if (ret != BT_STATUS_SUCCESS)
1865 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1866 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1868 CHECK_BTGATT_INIT();
1870 hal_gattc_service_t *gattc_service = NULL;
1871 hal_gattc_server_info_t * conn_info = NULL;
1872 hal_gattc_char_t *gattc_char = NULL;
1873 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1875 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1876 int ret = BT_STATUS_SUCCESS;
1878 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1880 /* get the connection info */
1881 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1882 if (NULL == conn_info) {
1883 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1884 return BT_STATUS_FAIL;
1888 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1889 if (NULL == gattc_service) {
1890 ERR("Failed to get the gatt service");
1891 return BT_STATUS_FAIL;
1894 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1895 if (NULL == gattc_char) {
1896 ERR("Failed to get the gatt char");
1897 return BT_STATUS_FAIL;
1900 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1901 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1903 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1904 if (ret != BT_STATUS_SUCCESS)
1911 /** Write a remote characteristic */
1912 bt_status_t btif_write_characteristic(int conn_id,
1913 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1914 int write_type, int len, int auth_req,
1917 CHECK_BTGATT_INIT();
1919 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1920 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1921 len, auth_req, p_value);
1924 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1926 struct hal_ev_gatt_client_read_data ev;
1929 ERR("gatt client callback not registered");
1933 memset(&ev, 0, sizeof(ev));
1934 ev.conn_id = resp_data->conn_id;
1935 ev.inst_id = resp_data->srvc_id.id.inst_id;
1936 ev.is_primary = resp_data->srvc_id.is_primary;
1939 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1940 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1941 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1945 /* building the desc read value */
1946 memcpy(ev.value, value, len);
1949 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1951 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1954 static void __hal_internal_read_desc_cb(GObject *source_object,
1955 GAsyncResult *res, gpointer user_data)
1957 GError *error = NULL;
1958 GDBusConnection *system_gconn = NULL;
1961 GByteArray *gp_byte_array = NULL;
1963 hal_gatt_resp_data_t *resp_data = user_data;
1964 int result = BT_STATUS_SUCCESS;
1969 system_gconn = _bt_hal_get_system_gconn();
1970 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1973 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1976 result = BT_STATUS_FAIL;
1977 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1978 g_clear_error(&error);
1983 gp_byte_array = g_byte_array_new();
1984 g_variant_get(value, "(ay)", &iter);
1986 while (g_variant_iter_loop(iter, "y", &g_byte))
1987 g_byte_array_append(gp_byte_array, &g_byte, 1);
1991 for (i = 0; i < gp_byte_array->len; i++)
1992 DBG("%02x", gp_byte_array->data[i]);
1995 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1999 g_byte_array_free(gp_byte_array, TRUE);
2000 g_variant_iter_free(iter);
2001 g_variant_unref(value);
2006 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2007 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2009 GDBusConnection *g_conn;
2010 hal_gatt_resp_data_t *resp_data;
2011 hal_gattc_service_t *gattc_service = NULL;
2012 GVariantBuilder *builder = NULL;
2014 hal_gattc_server_info_t * conn_info = NULL;
2015 hal_gattc_char_t *gattc_char = NULL;
2016 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2017 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2018 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2019 char* desc_handle = NULL;
2022 hal_gattc_desc_t *gattc_desc = NULL;
2024 /* get the connection info */
2025 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2026 if (NULL == conn_info) {
2027 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2028 return BT_STATUS_FAIL;
2032 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2033 if (NULL == gattc_service) {
2034 ERR("Failed to get the gatt service");
2035 return BT_STATUS_FAIL;
2038 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2039 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2041 /* find characteristic */
2042 /* service can have two char with same uuid */
2043 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2044 gattc_char = (hal_gattc_char_t*)l->data;
2045 if (gattc_char == NULL)
2048 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2049 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2050 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2052 /* find descriptor */
2053 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2055 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2056 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2062 if (NULL == gattc_desc) {
2063 ERR("Failed to get the gatt desc");
2064 return BT_STATUS_FAIL;
2067 g_conn = _bt_hal_get_system_gconn();
2068 if (NULL == g_conn) {
2069 ERR("_bt_gdbus_get_system_gconn returned NULL");
2070 return BT_STATUS_FAIL;
2073 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2074 resp_data->conn_id = conn_id;
2075 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2076 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2077 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2079 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2082 g_variant_builder_add(builder, "{sv}", "offset",
2083 g_variant_new("q", offset));
2085 desc_handle = gattc_desc->desc_path;
2087 DBG("calling desc read value");
2089 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2090 "ReadValue", g_variant_new("(a{sv})", builder),
2091 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2092 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2093 (gpointer)resp_data);
2094 g_variant_builder_unref(builder);
2096 return BT_STATUS_SUCCESS;
2099 /** Read the descriptor for a given characteristic */
2100 bt_status_t btif_read_descriptor(int conn_id,
2101 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2102 btgatt_gatt_id_t *descr_id, int auth_req)
2104 CHECK_BTGATT_INIT();
2106 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2109 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2111 struct hal_ev_gatt_client_write_result ev;
2114 ERR("gatt client callback not registered");
2118 memset(&ev, 0, sizeof(ev));
2119 ev.conn_id = resp_data->conn_id;
2120 ev.inst_id = resp_data->srvc_id.id.inst_id;
2121 ev.is_primary = resp_data->srvc_id.is_primary;
2124 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2125 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2126 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2128 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2130 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2133 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2134 GAsyncResult *res, gpointer user_data)
2136 GError *error = NULL;
2137 GDBusConnection *system_gconn = NULL;
2139 hal_gatt_resp_data_t *resp_data = user_data;
2140 int result = BT_STATUS_SUCCESS;
2144 system_gconn = _bt_hal_get_system_gconn();
2145 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2148 ERR("write descriptor dbus failed Error: [%s]", error->message);
2151 result = BT_STATUS_FAIL;
2152 __hal_send_desc_write_event(resp_data, result);
2153 g_clear_error(&error);
2158 //send write value event
2159 __hal_send_desc_write_event(resp_data, result);
2162 g_variant_unref(value);
2167 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2168 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2169 int write_type, int length, int auth_req, char* value)
2171 GVariant *val, *options;
2172 GVariantBuilder *builder1;
2173 GVariantBuilder *builder2;
2174 GDBusConnection *g_conn;
2177 hal_gatt_resp_data_t *resp_data;
2178 hal_gattc_service_t *gattc_service = NULL;
2179 hal_gattc_server_info_t * conn_info = NULL;
2180 hal_gattc_char_t *gattc_char = NULL;
2181 hal_gattc_desc_t *gattc_desc = NULL;
2182 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2183 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2184 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2185 char* desc_handle = NULL;
2186 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2187 int ret = BT_STATUS_SUCCESS;
2192 ret = __hal_get_write_prop(write_type, &write_prop);
2193 if (BT_STATUS_FAIL == ret) {
2194 ERR("received invalid write type:[%d] ", write_type);
2195 return BT_STATUS_FAIL;
2198 /* get the connection info */
2199 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2200 if (NULL == conn_info) {
2201 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2202 return BT_STATUS_FAIL;
2206 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2207 if (NULL == gattc_service) {
2208 ERR("Failed to get the gatt service");
2209 return BT_STATUS_FAIL;
2212 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2213 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2215 /* find characteristic */
2216 /* service can have two char with same uuid */
2217 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2218 gattc_char = (hal_gattc_char_t*)l->data;
2219 if (gattc_char == NULL)
2222 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2223 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2224 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2226 /* find descriptor */
2227 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2229 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2230 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2236 if (NULL == gattc_desc) {
2237 ERR("Failed to get the gatt desc");
2238 return BT_STATUS_FAIL;
2241 g_conn = _bt_hal_get_system_gconn();
2242 if (NULL == g_conn) {
2243 ERR("_bt_gdbus_get_system_gconn returned NULL");
2244 return BT_STATUS_FAIL;
2247 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2248 resp_data->conn_id = conn_id;
2249 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2250 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2251 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2253 desc_handle = gattc_desc->desc_path;
2255 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2257 for (i = 0; i < length; i++)
2258 g_variant_builder_add(builder1, "y", value[i]);
2260 val = g_variant_new("ay", builder1);
2262 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2264 g_variant_builder_add(builder2, "{sv}", "offset",
2265 g_variant_new_uint16(offset));
2267 options = g_variant_new("a{sv}", builder2);
2269 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2271 g_variant_new("(@ay@a{sv})", val, options),
2273 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2274 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2275 (gpointer)resp_data);
2277 g_variant_builder_unref(builder1);
2278 g_variant_builder_unref(builder2);
2280 return BT_STATUS_SUCCESS;
2283 /** Write a remote descriptor for a given characteristic */
2284 bt_status_t btif_write_descriptor(int conn_id,
2285 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2286 btgatt_gatt_id_t *descr_id, int write_type, int len,
2287 int auth_req, char* p_value)
2289 CHECK_BTGATT_INIT();
2291 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2292 len, auth_req, p_value);
2295 /** Execute a prepared write operation */
2296 bt_status_t execute_write(int conn_id, int execute)
2298 CHECK_BTGATT_INIT();
2299 return BT_STATUS_UNSUPPORTED;
2302 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2304 struct hal_ev_gatt_client_watch_notification ev;
2305 hal_gatt_resp_data_t *resp_data = user_data;
2307 DBG("sending the watch register notification event");
2308 /* send the event */
2309 memset(&ev, 0, sizeof(ev));
2310 ev.conn_id = resp_data->conn_id;
2312 ev.status = resp_data->result;
2314 ev.is_primary = resp_data->srvc_id.is_primary;
2315 ev.inst_id = resp_data->srvc_id.id.inst_id;
2317 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2318 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2321 ERR("GATT Callback not registered");
2323 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2330 static bt_status_t _hal_register_for_notification(int conn_id,
2331 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2332 btgatt_gatt_id_t *char_id)
2334 int result = BT_STATUS_SUCCESS;
2335 GError *error = NULL;
2336 GDBusConnection *g_conn;
2337 hal_gattc_client_info_t *gattc_client = NULL;
2338 hal_gattc_server_info_t * conn_info = NULL;
2339 hal_gattc_service_t *gattc_service = NULL;
2340 hal_gattc_char_t *gattc_char = NULL;
2341 char* char_handle = NULL;
2342 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2343 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2344 hal_gatt_resp_data_t *resp_data;
2348 gattc_client = __bt_find_gatt_client_info(bd_addr);
2349 if (gattc_client == NULL) {
2350 ERR("failed to get the gatt client info");
2351 return BT_STATUS_FAIL;
2354 if (gattc_client->conn_id != conn_id) {
2355 ERR("could not find the gatt client for client id[%d]", conn_id);
2356 return BT_STATUS_FAIL;
2359 /* get the connection info */
2360 conn_info = __bt_find_gatt_conn_info(bd_addr);
2361 if (NULL == conn_info) {
2362 ERR("Failed to get the conn_info");
2363 return BT_STATUS_FAIL;
2366 if (conn_info->inst_id != gattc_client->inst_id) {
2367 ERR("could not fild the conn_info");
2368 return BT_STATUS_FAIL;
2372 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2373 if (NULL == gattc_service) {
2374 ERR("Failed to get the gatt service");
2375 return BT_STATUS_FAIL;
2378 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2379 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2382 /* find characteristic */
2383 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2384 if (NULL == gattc_char) {
2385 ERR("Failed to get the gatt char");
2386 return BT_STATUS_FAIL;
2389 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2390 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2392 char_handle = gattc_char->chr_path;
2394 g_conn = _bt_hal_get_system_gconn();
2395 if (g_conn == NULL) {
2397 return BT_STATUS_FAIL;
2400 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2402 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2404 g_dbus_connection_call_sync(g_conn,
2407 BT_HAL_GATT_CHAR_INTERFACE,
2411 G_DBUS_CALL_FLAGS_NONE,
2412 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2415 g_dbus_error_strip_remote_error(error);
2416 ERR("### StartNotify Failed: %s", error->message);
2417 if (g_strrstr(error->message, "Already notifying"))
2418 result = BT_STATUS_SUCCESS;
2419 else if (g_strrstr(error->message, "In Progress"))
2420 result = BT_STATUS_BUSY;
2421 else if (g_strrstr(error->message, "Operation is not supported"))
2422 result = BT_STATUS_UNSUPPORTED;
2423 /*failed because of either Insufficient Authorization or Write Not Permitted */
2424 else if (g_strrstr(error->message, "Write not permitted") ||
2425 g_strrstr(error->message, "Operation Not Authorized"))
2426 result = BT_STATUS_AUTH_FAILURE;
2427 /* failed because of either Insufficient Authentication,
2428 Insufficient Encryption Key Size, or Insufficient Encryption. */
2429 else if (g_strrstr(error->message, "Not paired"))
2430 result = BT_STATUS_NOT_READY;
2432 result = BT_STATUS_FAIL;
2434 g_clear_error(&error);
2437 resp_data->conn_id = gattc_client->conn_id;
2438 resp_data->result = result;
2439 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2440 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2442 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2446 return BT_STATUS_SUCCESS;
2450 * Register to receive notifications or indications for a given
2453 bt_status_t btif_register_for_notification(int conn_id,
2454 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2455 btgatt_gatt_id_t *char_id)
2457 CHECK_BTGATT_INIT();
2459 return _hal_register_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2462 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2464 struct hal_ev_gatt_client_watch_notification ev;
2465 hal_gatt_resp_data_t *resp_data = user_data;
2467 DBG("sending the watch deregister notification event");
2468 /* send the event */
2469 memset(&ev, 0, sizeof(ev));
2470 ev.conn_id = resp_data->conn_id;
2472 ev.status = resp_data->result;
2474 ev.is_primary = resp_data->srvc_id.is_primary;
2475 ev.inst_id = resp_data->srvc_id.id.inst_id;
2477 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2478 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2481 ERR("GATT Callback not registered");
2483 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2490 static bt_status_t _hal_deregister_for_notification(int conn_id,
2491 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2492 btgatt_gatt_id_t *char_id)
2494 int result = BT_STATUS_SUCCESS;
2495 GError *error = NULL;
2496 GDBusConnection *g_conn;
2497 hal_gattc_client_info_t *gattc_client = NULL;
2498 hal_gattc_server_info_t * conn_info = NULL;
2499 hal_gattc_service_t *gattc_service = NULL;
2500 hal_gattc_char_t *gattc_char = NULL;
2501 char* char_handle = NULL;
2502 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2503 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2504 hal_gatt_resp_data_t *resp_data;
2508 gattc_client = __bt_find_gatt_client_info(bd_addr);
2509 if (gattc_client == NULL) {
2510 ERR("failed to get the gatt client info");
2511 return BT_STATUS_FAIL;
2514 if (gattc_client->conn_id != conn_id) {
2515 ERR("could not find the gatt client for client id[%d]", conn_id);
2516 return BT_STATUS_FAIL;
2519 /* get the connection info */
2520 conn_info = __bt_find_gatt_conn_info(bd_addr);
2521 if (NULL == conn_info) {
2522 ERR("Failed to get the conn_info");
2523 return BT_STATUS_FAIL;
2526 if (conn_info->inst_id != gattc_client->inst_id) {
2527 ERR("could not fild the conn_info");
2528 return BT_STATUS_FAIL;
2532 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2533 if (NULL == gattc_service) {
2534 ERR("Failed to get the gatt service");
2535 return BT_STATUS_FAIL;
2538 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2539 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2542 /* find characteristic */
2543 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2544 if (NULL == gattc_char) {
2545 ERR("Failed to get the gatt char");
2546 return BT_STATUS_FAIL;
2549 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2550 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2552 char_handle = gattc_char->chr_path;
2554 g_conn = _bt_hal_get_system_gconn();
2555 if (g_conn == NULL) {
2557 return BT_STATUS_FAIL;
2560 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2562 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2563 g_dbus_connection_call_sync(g_conn,
2566 BT_HAL_GATT_CHAR_INTERFACE,
2570 G_DBUS_CALL_FLAGS_NONE,
2571 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2574 ERR("### StopNotify Failed: %s", error->message);
2575 g_clear_error(&error);
2576 result = BT_STATUS_FAIL;
2579 resp_data->conn_id = gattc_client->conn_id;
2580 resp_data->result = result;
2581 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2582 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2584 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2588 return BT_STATUS_SUCCESS;
2590 /** Deregister a previous request for notifications/indications */
2591 bt_status_t btif_deregister_for_notification(int conn_id,
2592 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2593 btgatt_gatt_id_t *char_id)
2595 CHECK_BTGATT_INIT();
2596 return _hal_deregister_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2599 /** Request RSSI for a given remote device */
2600 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2602 CHECK_BTGATT_INIT();
2603 return BT_STATUS_UNSUPPORTED;
2606 /** OTA firmware download */
2607 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2609 CHECK_BTGATT_INIT();
2610 return BT_STATUS_UNSUPPORTED;
2613 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2614 int get_device_type(const bt_bdaddr_t *bd_addr)
2616 CHECK_BTGATT_INIT();
2617 return BT_STATUS_UNSUPPORTED;
2620 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2621 int min_int, int max_int, int latency, int timeout)
2623 gchar *device_path = NULL;
2624 GError *error = NULL;
2625 GDBusProxy *device_proxy = NULL;
2626 GDBusConnection *conn;
2628 int ret = BT_STATUS_SUCCESS;
2629 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2631 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2632 min_int, max_int, latency, timeout);
2634 conn = _bt_hal_get_system_gconn();
2637 return BT_STATUS_FAIL;
2640 _bt_hal_convert_addr_type_to_string(device_address,
2641 (unsigned char *)bd_addr->address);
2642 device_path = _bt_hal_get_device_object_path(device_address);
2644 if (device_path == NULL) {
2645 ERR("device_path NULL : [%s]", device_address);
2646 return BT_STATUS_FAIL;
2649 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2650 NULL, BT_HAL_BLUEZ_NAME,
2651 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2653 g_free(device_path);
2654 if (NULL == device_proxy) {
2655 ERR("device_proxy returned NULL");
2656 return BT_STATUS_FAIL;
2659 INFO("Request LeConnUpdate");
2660 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2661 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2662 G_DBUS_CALL_FLAGS_NONE,
2667 g_object_unref(device_proxy);
2668 if (reply == NULL) {
2670 ERR("Error %s[%s]", error->message, device_address);
2671 if (g_strrstr(error->message, "In Progress"))
2672 ret = BT_STATUS_SUCCESS;
2674 ret = BT_STATUS_FAIL;
2675 g_error_free(error);
2679 g_variant_unref(reply);
2681 DBG("LE Connection parameter Updated");
2685 /** Request a connection parameter update */
2686 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2688 CHECK_BTGATT_INIT();
2690 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2693 /** Test mode interface */
2694 bt_status_t test_command(int command, btgatt_test_params_t* params)
2696 CHECK_BTGATT_INIT();
2697 return BT_STATUS_UNSUPPORTED;
2700 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2703 GError *g_error = NULL;
2704 GVariant *reply = NULL;
2705 int result = BT_STATUS_SUCCESS;
2706 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2707 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2709 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2710 g_object_unref(proxy);
2711 if (reply == NULL) {
2712 ERR("Connect LE Dbus Call Error");
2714 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2715 g_clear_error(&g_error);
2717 result = BT_STATUS_FAIL;
2719 g_variant_unref(reply);
2721 memset(&ev, 0, sizeof(ev));
2723 ev.mtu = conn_mtu->mtu;
2724 ev.conn_id = conn_mtu->conn_id;
2727 ERR("gatt client callback not registered");
2729 DBG("sending gatt client MTU exchange completed event");
2730 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2737 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2739 gchar *device_path = NULL;
2740 GDBusProxy *device_proxy = NULL;
2741 GDBusConnection *conn;
2742 hal_gattc_client_info_t *gattc_client = NULL;
2743 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2744 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2746 conn = _bt_hal_get_system_gconn();
2750 return BT_STATUS_FAIL;
2753 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2754 if (gattc_client == NULL) {
2755 INFO("GATT client conn info not found");
2757 return BT_STATUS_FAIL;
2760 _bt_hal_convert_addr_type_to_string(device_address,
2761 (unsigned char *)gattc_client->bd_addr.address);
2763 device_path = _bt_hal_get_device_object_path(device_address);
2764 if (device_path == NULL) {
2765 ERR("device_path NULL : [%s]", device_address);
2767 return BT_STATUS_FAIL;
2770 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2771 NULL, BT_HAL_BLUEZ_NAME,
2772 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2774 g_free(device_path);
2775 if (NULL == device_proxy) {
2776 ERR("device_proxy returned NULL");
2778 return BT_STATUS_FAIL;
2781 conn_mtu->conn_id = conn_id;
2782 conn_mtu->mtu = mtu;
2784 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2785 g_variant_new("(q)", mtu),
2786 G_DBUS_CALL_FLAGS_NONE,
2787 BT_HAL_MAX_DBUS_TIMEOUT,
2789 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2792 return BT_STATUS_SUCCESS;
2795 /** MTU Exchange request from client */
2796 static bt_status_t configure_mtu(int conn_id, int mtu)
2798 CHECK_BTGATT_INIT();
2800 return __hal_configure_mtu(conn_id, mtu);
2803 /** Setup scan filter params */
2804 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2805 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2806 int rssi_low_thres, int dely_mode, int found_timeout,
2807 int lost_timeout, int found_timeout_cnt)
2810 GError *error = NULL;
2811 GVariant *ret, *param;
2812 CHECK_BTGATT_INIT();
2814 proxy = _bt_hal_get_adapter_proxy();
2817 return BT_STATUS_FAIL;
2819 param = g_variant_new("(iiiiiiiiiiii)",
2832 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2833 param, G_DBUS_CALL_FLAGS_NONE,
2837 ERR("scan_filter_param_setup Fail: %s", error->message);
2838 g_clear_error(&error);
2839 return BT_STATUS_FAIL;
2843 g_variant_unref(ret);
2845 return BT_STATUS_SUCCESS;
2848 /** Configure a scan filter condition */
2849 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2850 int filt_index, int company_id,
2851 int company_id_mask, const bt_uuid_t *p_uuid,
2852 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2853 char addr_type, int data_len, char* p_data, int mask_len,
2857 GError *error = NULL;
2858 GVariant *ret, *param;
2859 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2860 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2861 GArray *arr_uuid = NULL;
2862 GArray *arr_uuid_mask = NULL;
2863 GArray *arr_data = NULL;
2864 GArray *arr_data_mask = NULL;
2865 CHECK_BTGATT_INIT();
2867 proxy = _bt_hal_get_adapter_proxy();
2870 return BT_STATUS_FAIL;
2872 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2874 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2876 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2878 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2880 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2881 NULL, 0, TRUE, NULL, NULL);
2882 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2883 NULL, 0, TRUE, NULL, NULL);
2884 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2885 NULL, 0, TRUE, NULL, NULL);
2886 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2887 NULL, 0, TRUE, NULL, NULL);
2889 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2890 client_if, // client_if
2891 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2892 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2893 filt_index, // filter_index
2894 company_id, // company_id
2895 company_id_mask, // company_id_mask
2896 arr_uuid_param, // p_uuid
2897 arr_uuid_mask_param, // p_uuid_mask
2899 addr_type, // address_type
2900 arr_data_param, // p_data
2901 arr_data_mask_param); // p_mask
2903 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2904 param, G_DBUS_CALL_FLAGS_NONE,
2908 ERR("scan_filter_add_remove Fail: %s", error->message);
2909 g_clear_error(&error);
2910 return BT_STATUS_FAIL;
2914 g_variant_unref(ret);
2916 return BT_STATUS_SUCCESS;
2919 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2921 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2922 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2923 NULL, 0, TRUE, NULL, NULL);
2924 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2925 NULL, 0, TRUE, NULL, NULL);
2926 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2927 NULL, 0, TRUE, NULL, NULL);
2928 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2929 NULL, 0, TRUE, NULL, NULL);
2931 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2932 client_if, // client_if
2933 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2934 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2935 filt_index, // filter_index
2936 company_id, // company_id
2937 company_id_mask, // company_id_mask
2938 arr_uuid_param, // p_uuid
2939 arr_uuid_mask_param, // p_uuid_mask
2941 addr_type, // address_type
2942 arr_data_param, // p_data
2943 arr_data_mask_param);
2945 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2946 param, G_DBUS_CALL_FLAGS_NONE,
2950 ERR("scan_filter_add_remove Fail: %s", error->message);
2951 g_clear_error(&error);
2952 return BT_STATUS_FAIL;
2956 g_variant_unref(ret);
2958 return BT_STATUS_SUCCESS;
2961 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2963 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2964 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2966 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2967 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2969 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2970 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2971 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2972 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2973 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2974 NULL, 0, TRUE, NULL, NULL);
2975 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2976 NULL, 0, TRUE, NULL, NULL);
2978 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2979 client_if, // client_if
2980 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2981 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
2982 filt_index, // filter_index
2983 company_id, // company_id
2984 company_id_mask, // company_id_mask
2985 arr_uuid_param, // p_uuid
2986 arr_uuid_mask_param, // p_uuid_mask
2988 addr_type, // address_type
2989 arr_data_param, // p_data
2990 arr_data_mask_param);
2992 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2993 param, G_DBUS_CALL_FLAGS_NONE,
2997 ERR("scan_filter_add_remove Fail: %s", error->message);
2998 g_clear_error(&error);
2999 return BT_STATUS_FAIL;
3003 g_variant_unref(ret);
3005 g_array_free(arr_uuid, TRUE);
3006 g_array_free(arr_uuid_mask, TRUE);
3008 return BT_STATUS_SUCCESS;
3011 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3013 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3014 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3016 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3017 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3019 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3020 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3021 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3022 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3023 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3024 NULL, 0, TRUE, NULL, NULL);
3025 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3026 NULL, 0, TRUE, NULL, NULL);
3028 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3029 client_if, // client_if
3030 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3031 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3032 filt_index, // filter_index
3033 company_id, // company_id
3034 company_id_mask, // company_id_mask
3035 arr_uuid_param, // p_uuid
3036 arr_uuid_mask_param, // p_uuid_mask
3038 addr_type, // address_type
3039 arr_data_param, // p_data
3040 arr_data_mask_param);
3042 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3043 G_DBUS_CALL_FLAGS_NONE,
3047 ERR("scan_filter_add_remove Fail: %s", error->message);
3048 g_clear_error(&error);
3049 return BT_STATUS_FAIL;
3053 g_variant_unref(ret);
3055 g_array_free(arr_uuid, TRUE);
3056 g_array_free(arr_uuid_mask, TRUE);
3058 return BT_STATUS_SUCCESS;
3061 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3063 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3064 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3066 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3067 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3069 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3070 NULL, 0, TRUE, NULL, NULL);
3071 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3072 NULL, 0, TRUE, NULL, NULL);
3073 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3074 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3075 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3076 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3078 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3079 client_if, // client_if
3080 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3081 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3082 filt_index, // filter_index
3083 company_id, // company_id
3084 company_id_mask, // company_id_mask
3085 arr_uuid_param, // p_uuid
3086 arr_uuid_mask_param, // p_uuid_mask
3088 addr_type, // address_type
3089 arr_data_param, // p_data
3090 arr_data_mask_param);
3092 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3093 G_DBUS_CALL_FLAGS_NONE,
3097 ERR("scan_filter_add_remove Fail: %s", error->message);
3098 g_clear_error(&error);
3099 return BT_STATUS_FAIL;
3103 g_variant_unref(ret);
3105 g_array_free(arr_data, TRUE);
3106 g_array_free(arr_data_mask, TRUE);
3108 return BT_STATUS_SUCCESS;
3111 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3113 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3114 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3116 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3117 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3119 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3120 NULL, 0, TRUE, NULL, NULL);
3121 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3122 NULL, 0, TRUE, NULL, NULL);
3123 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3124 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3125 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3126 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3128 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3129 client_if, // client_if
3130 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3131 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3132 filt_index, // filter_index
3133 company_id, // company_id
3134 company_id_mask, // company_id_mask
3135 arr_uuid_param, // p_uuid
3136 arr_uuid_mask_param, // p_uuid_mask
3138 addr_type, // address_type
3139 arr_data_param, // p_data
3140 arr_data_mask_param);
3142 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3143 G_DBUS_CALL_FLAGS_NONE,
3147 ERR("scan_filter_add_remove Fail: %s", error->message);
3148 g_clear_error(&error);
3149 return BT_STATUS_FAIL;
3153 g_variant_unref(ret);
3155 g_array_free(arr_data, TRUE);
3156 g_array_free(arr_data_mask, TRUE);
3158 return BT_STATUS_SUCCESS;
3161 return BT_STATUS_UNSUPPORTED;
3164 /** Clear all scan filter conditions for specific filter index*/
3165 bt_status_t scan_filter_clear(int client_if, int filt_index)
3168 GError *error = NULL;
3170 CHECK_BTGATT_INIT();
3172 proxy = _bt_hal_get_adapter_proxy();
3174 return BT_STATUS_FAIL;
3176 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3177 g_variant_new("(ii)", client_if, filt_index),
3178 G_DBUS_CALL_FLAGS_NONE,
3182 ERR("scan_filter_clear Fail: %s", error->message);
3183 g_clear_error(&error);
3184 return BT_STATUS_FAIL;
3187 g_variant_unref(ret);
3188 return BT_STATUS_SUCCESS;
3191 /** Enable / disable scan filter feature*/
3192 bt_status_t scan_filter_enable(int client_if, bool enable)
3195 GError *error = NULL;
3197 CHECK_BTGATT_INIT();
3199 proxy = _bt_hal_get_adapter_proxy();
3201 return BT_STATUS_FAIL;
3203 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3204 g_variant_new("(ib)", client_if, enable),
3205 G_DBUS_CALL_FLAGS_NONE,
3209 ERR("scan_filter_enable Fail: %s", error->message);
3210 g_clear_error(&error);
3211 return BT_STATUS_FAIL;
3213 g_variant_unref(ret);
3215 return BT_STATUS_SUCCESS;
3218 /** Sets the LE scan interval and window in units of N*0.625 msec */
3220 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3224 CHECK_BTGATT_INIT();
3226 le_scan_type = scan_type;
3227 ret = _bt_hal_adapter_le_set_scan_parameters(
3228 scan_type, scan_interval, scan_window);
3232 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3234 CHECK_BTGATT_INIT();
3235 return BT_STATUS_UNSUPPORTED;
3239 /* Configure the batchscan storage */
3240 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3241 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3243 CHECK_BTGATT_INIT();
3244 return BT_STATUS_UNSUPPORTED;
3247 /* Enable batchscan */
3248 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3249 int scan_interval, int scan_window, int addr_type, int discard_rule)
3251 CHECK_BTGATT_INIT();
3252 return BT_STATUS_UNSUPPORTED;
3255 /* Disable batchscan */
3256 bt_status_t batchscan_dis_batch_scan(int client_if)
3258 CHECK_BTGATT_INIT();
3259 return BT_STATUS_UNSUPPORTED;
3262 /* Read out batchscan reports */
3263 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3265 CHECK_BTGATT_INIT();
3266 return BT_STATUS_UNSUPPORTED;
3269 const btgatt_client_interface_t btgatt_client_interface = {
3270 .register_client = btif_gattc_register_client,
3271 .unregister_client = btif_gattc_unregister_client,
3273 .connect = btif_gattc_client_connect,
3274 .disconnect = btif_gattc_client_disconnect,
3276 .search_service = btif_gattc_client_search_service,
3277 .get_included_service = get_included_service,
3278 .get_characteristic = btif_gattc_get_characteristic,
3279 .get_descriptor = btif_gattc_get_descriptor,
3280 .read_characteristic = btif_read_characteristic,
3281 .write_characteristic = btif_write_characteristic,
3282 .acquire_write = btif_get_acquire_write_fd,
3283 .acquire_notify = btif_get_acquire_notify_fd,
3284 .read_descriptor = btif_read_descriptor,
3285 .write_descriptor = btif_write_descriptor,
3286 .execute_write = execute_write,
3287 .register_for_notification = btif_register_for_notification,
3288 .deregister_for_notification = btif_deregister_for_notification,
3289 .read_remote_rssi = read_remote_rssi,
3290 .ota_fw_update = ota_fw_update,
3291 .get_device_type = get_device_type,
3292 .conn_parameter_update = btif_gattc_conn_parameter_update,
3293 .test_command = test_command,
3294 .configure_mtu = configure_mtu,
3295 .scan_filter_param_setup = scan_filter_param_setup,
3296 .scan_filter_add_remove = scan_filter_add_remove,
3297 .scan_filter_clear = scan_filter_clear,
3298 .scan_filter_enable = scan_filter_enable,
3299 .set_scan_parameters = set_scan_parameters,
3300 .batchscan_cfg_storage = batchscan_cfg_storage,
3301 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3302 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3303 .batchscan_read_reports = batchscan_read_reports,
3304 .add_connection_info = btif_gattc_add_connection_info,
3307 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3310 hal_gattc_server_info_t *info = NULL;
3312 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3313 info = (hal_gattc_server_info_t*)l->data;
3317 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3324 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3327 hal_gattc_client_info_t *info = NULL;
3329 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3330 info = (hal_gattc_client_info_t*)l->data;
3334 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3341 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3344 hal_gattc_client_info_t *info = NULL;
3346 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3347 info = (hal_gattc_client_info_t*)l->data;
3351 if (info->conn_id == conn_id)
3358 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3361 hal_gattc_server_info_t *info = NULL;
3362 hal_gattc_client_info_t *gattc_client = NULL;
3364 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3365 if (gattc_client == NULL) {
3366 ERR("GATT client conn info not found");
3370 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3371 info = (hal_gattc_server_info_t*)l->data;
3375 if ((info->inst_id == gattc_client->inst_id) &&
3376 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3383 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3384 gboolean auto_connect)
3386 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3387 gchar *device_path = NULL;
3388 GDBusProxy *device_proxy = NULL;
3389 GDBusConnection *conn;
3390 int ret = BT_STATUS_SUCCESS;
3391 hal_gattc_client_info_t *gattc_data;
3393 if (NULL == bd_addr) {
3394 ERR("bd_addr is NULL");
3395 return BT_STATUS_PARM_INVALID;
3398 conn = _bt_hal_get_system_gconn();
3400 ERR("_bt_gdbus_get_system_gconn returned NULL");
3401 return BT_STATUS_FAIL;
3404 _bt_hal_convert_addr_type_to_string(device_address,
3405 (unsigned char *)bd_addr->address);
3406 device_path = _bt_hal_get_device_object_path(device_address);
3407 if (device_path == NULL) {
3408 ERR("device_path NULL : [%s]", device_address);
3409 ret = BT_STATUS_FAIL;
3413 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3414 NULL, BT_HAL_BLUEZ_NAME,
3415 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3416 g_free(device_path);
3417 if (NULL == device_proxy) {
3418 ERR("device_proxy returned NULL");
3419 return BT_STATUS_FAIL;
3422 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3423 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3424 BT_HAL_ADDRESS_LENGTH_MAX);
3426 DBG("ConnectLE [%s]", device_address);
3428 gattc_data->client_if = client_if;
3430 g_dbus_proxy_call(device_proxy, "ConnectLE",
3431 g_variant_new("(b)", auto_connect),
3432 G_DBUS_CALL_FLAGS_NONE,
3433 BT_HAL_MAX_DBUS_TIMEOUT,
3435 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3440 static bt_status_t _bt_hold_current_advertising()
3442 int ret = BT_STATUS_FAIL;
3443 gboolean is_advertising = FALSE;
3446 if (_bt_hal_is_support_multi_adv() == TRUE) {
3447 DBG("VSC adv used");
3448 return BT_STATUS_SUCCESS;
3451 /* Dependent on Kernel operation. Hold adv to prevent stopping adv on kernel */
3452 is_advertising = _bt_hal_is_advertising_in_slot(0);
3453 if (is_advertising) {
3454 DBG("+ Stop current advertising");
3456 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3457 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3463 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3465 DBG("+ start current advertising");
3467 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3472 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3474 DBG("Try to initiate pending LE connection");
3476 pending_le_conn_timer_id = 0;
3478 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3479 &pending_le_conn_info->bd_addr,
3480 pending_le_conn_info->auto_connect);
3482 g_free(pending_le_conn_info);
3483 pending_le_conn_info = NULL;
3488 static int __hal_generate_conn_id()
3490 return ++hal_gatt_conn_id;
3493 static int __hal_generate_server_instance_id()
3495 return ++bt_inst_id;
3498 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3501 GError *g_error = NULL;
3502 GVariant *reply = NULL;
3503 hal_gattc_client_info_t *gattc_data = user_data;
3504 int result = BT_STATUS_SUCCESS;
3505 struct hal_ev_gatt_client_connected ev;
3506 hal_gattc_server_info_t *gatt_conn_info = NULL;
3508 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3509 g_object_unref(proxy);
3510 if (reply == NULL) {
3511 ERR("Connect LE Dbus Call Error");
3513 ERR("Error: %s\n", g_error->message);
3514 g_clear_error(&g_error);
3516 result = BT_STATUS_FAIL;
3518 g_variant_unref(reply);
3520 if (NULL == gattc_data) {
3521 ERR("gattc_data is NULL");
3526 if (result == BT_STATUS_FAIL) {
3527 memset(&ev, 0, sizeof(ev));
3530 ev.client_if = gattc_data->client_if;
3531 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3532 BT_HAL_ADDRESS_LENGTH_MAX);
3535 ERR("gatt client callback not registered");
3537 DBG("sending gatt client connected event");
3538 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3544 DBG("LE connected. Adding the gattc server/client conn info in list");
3545 gattc_data->conn_id = __hal_generate_conn_id() ;
3546 gattc_data->inst_id = __hal_generate_server_instance_id();
3548 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3550 /*add gatt server connection info*/
3551 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3552 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3553 gatt_conn_info->conn_id = gattc_data->conn_id;
3554 gatt_conn_info->inst_id = gattc_data->inst_id;
3555 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3560 /*remove conn_info*/
3565 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3567 g_free(desc_info->desc_path);
3571 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3574 hal_gattc_desc_t *desc_info = NULL;
3575 for (l = char_info->gatt_list_descs; l != NULL; ) {
3576 desc_info = l->data;
3577 l = g_slist_next(l);
3578 if (desc_info == NULL)
3580 /* Remove descriptor element */
3581 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3582 __hal_gattc_free_desc_info(desc_info);
3584 g_slist_free(char_info->gatt_list_descs);
3585 g_free(char_info->chr_path);
3589 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3592 hal_gattc_char_t *char_info = NULL;
3593 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3594 char_info = l->data;
3595 l = g_slist_next(l);
3596 if (char_info == NULL)
3598 /* Remove characteristic element */
3599 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3600 __hal_gattc_free_char_info(char_info);
3602 g_slist_free(svc_info->gatt_list_chars);
3603 g_free(svc_info->svc_path);
3607 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3610 hal_gattc_service_t *svc_info = NULL;
3614 for (l = conn_info->gatt_list_services; l != NULL; ) {
3615 svc_info = (hal_gattc_service_t *)l->data;
3616 l = g_slist_next(l);
3617 if (svc_info == NULL)
3619 /* Remove service element */
3620 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3621 __hal_gattc_free_svc_info(svc_info);
3623 g_slist_free(conn_info->gatt_list_services);
3627 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3629 bt_bdaddr_t bd_addr;
3630 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3631 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3637 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3639 int result = BT_STATUS_SUCCESS;
3640 struct hal_ev_gatt_client_connected ev;
3641 hal_gattc_server_info_t *conn_info = NULL;
3642 bt_bdaddr_t bd_addr;
3644 hal_gattc_client_info_t *gattc_client = NULL;
3647 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3648 HAL_EV_GATT_CLIENT_DISCONNECTED;
3650 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3651 /* find the gatt client info */
3652 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3653 if (NULL == gattc_client) {
3654 ERR("Fail to get gatt client info");
3658 gattc_client->is_gatt_connected = gatt_connected;
3661 memset(&ev, 0, sizeof(ev));
3662 ev.conn_id = gattc_client->conn_id;
3664 ev.client_if = gattc_client->client_if;
3665 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3666 BT_HAL_ADDRESS_LENGTH_MAX);
3669 ERR("gatt client callback not registered");
3671 event_cb(event, (void *)&ev, sizeof(ev));
3674 if (!gatt_connected) {
3675 inst_id = gattc_client->inst_id;
3677 /* remove the gatt client info from the client list also*/
3678 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3679 g_free(gattc_client);
3681 //find the connected server info
3682 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3683 if (NULL == conn_info) {
3684 ERR("Fail to get gatt server info");
3688 if (inst_id != conn_info->inst_id) {
3689 ERR("server instance is different");
3693 //remove gatt conn info from the server list
3694 DBG("remove the server conn_info from list after gatt disconnection");
3695 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3696 __hal_clean_gattc_server_info(conn_info);
3700 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3701 const char* uuid_str, int inst_id)
3703 struct hal_ev_gatt_client_search_result ev;
3706 ERR("gatt client callback not registered");
3710 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3712 memset(&ev, 0, sizeof(ev));
3713 ev.conn_id = conn_id;
3714 ev.inst_id = inst_id;
3715 ev.is_primary = is_primary;
3716 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3718 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3721 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3723 struct hal_ev_gatt_client_search_complete ev;
3726 ERR("gatt client callback not registered");
3730 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3733 memset(&ev, 0, sizeof(ev));
3734 ev.conn_id = conn_id;
3737 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3740 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3741 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3742 char *char_value, int len)
3744 struct hal_ev_gatt_client_notify_changed_value ev;
3745 hal_gattc_client_info_t *gattc_client = NULL;
3748 ERR("gatt client callback not registered");
3752 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3753 if (NULL == gattc_client) {
3754 ERR("failed to get the gatt client info");
3759 DBG("sending gatt client connected status event");
3760 memset(&ev, 0, sizeof(ev));
3762 ev.conn_id = gattc_client->conn_id;
3763 ev.inst_id = conn_info->inst_id;
3764 ev.is_primary = svc_info->is_primary;
3765 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3766 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3768 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3770 if (len > 0 && (char_value != NULL)) {
3771 memcpy(ev.value, char_value, len);
3775 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3778 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3779 char *char_value, int len)
3781 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3782 hal_gattc_server_info_t *conn_info = NULL;
3783 bt_bdaddr_t bd_addr;
3786 hal_gattc_service_t *svc_info = NULL;
3787 hal_gattc_char_t *char_info = NULL;
3791 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3792 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3793 DBG("device address:[%s]", device_address);
3794 DBG("char handle:[%s]", char_handle);
3796 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3797 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3799 if (conn_info != NULL) {
3800 //find service for notified char path
3801 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3802 svc_info = (hal_gattc_service_t*)l->data;
3803 if (svc_info == NULL)
3806 /* find characteristic object path */
3807 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3808 char_info = (hal_gattc_char_t *)k->data;
3809 if (char_info == NULL)
3812 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3813 DBG("Found char handle[%s]", char_info->chr_path);
3816 _bt_hal_send_value_changed_event(conn_info, svc_info,
3817 char_info, char_value, len);
3825 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3827 GDBusConnection *g_conn = NULL;
3828 GDBusProxy *properties_proxy = NULL;
3829 GVariant *result = NULL;
3830 GError *error = NULL;
3831 GVariantIter *property_iter = NULL;
3832 const gchar *key = NULL;
3833 GVariant *value = NULL;
3834 const char *uuid_str = NULL;
3836 gboolean is_primary = FALSE;
3837 GVariantIter *char_iter = NULL;
3838 const char *char_handle = NULL;
3839 GPtrArray *gp_char_array = NULL;
3841 if (service_path == NULL) {
3842 ERR("service_path is NULL");
3843 return BT_STATUS_FAIL;
3846 DBG("service_path: %s", service_path);
3848 g_conn = _bt_hal_get_system_gconn();
3849 if (g_conn == NULL) {
3850 ERR("g_conn is NULL");
3851 return BT_STATUS_FAIL;
3854 properties_proxy = g_dbus_proxy_new_sync(g_conn,
3855 G_DBUS_PROXY_FLAGS_NONE, NULL,
3858 BT_HAL_PROPERTIES_INTERFACE,
3860 if (properties_proxy == NULL) {
3861 ERR("properties_proxy is NULL");
3862 return BT_STATUS_FAIL;
3865 result = g_dbus_proxy_call_sync(properties_proxy,
3867 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
3868 G_DBUS_CALL_FLAGS_NONE,
3870 if (result == NULL) {
3871 if (error != NULL) {
3872 ERR("Fail to get properties (Error: %s)", error->message);
3873 g_clear_error(&error);
3875 ERR("Fail to get properties");
3877 g_object_unref(properties_proxy);
3878 return BT_STATUS_FAIL;
3881 g_variant_get(result, "(a{sv})", &property_iter);
3883 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
3884 if (g_strcmp0(key, "UUID") == 0) {
3885 uuid_str = g_variant_get_string(value, &len);
3886 } else if (g_strcmp0(key, "Primary") == 0) {
3887 is_primary = g_variant_get_boolean(value);
3888 } else if (g_strcmp0(key, "Characteristics") == 0) {
3889 g_variant_get(value, "ao", &char_iter);
3890 if (char_iter != NULL) {
3891 if (gp_char_array == NULL)
3892 gp_char_array = g_ptr_array_new();
3894 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
3895 DBG("char_handle: %s", char_handle);
3896 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
3898 g_variant_iter_free(char_iter);
3903 if (uuid_str == NULL || gp_char_array == NULL) {
3904 ERR("uuid_str and gp_char_array should be set");
3908 /* Create new service */
3909 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
3912 g_variant_iter_free(property_iter);
3913 g_variant_unref(result);
3914 g_object_unref(properties_proxy);
3916 return BT_STATUS_SUCCESS;
3919 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
3921 GDBusConnection *conn = NULL;
3922 GDBusProxy *proxy = NULL;
3924 GVariant *ret = NULL;
3925 GVariant *value = NULL;
3927 conn = _bt_hal_get_system_gconn();
3929 ERR("_bt_gdbus_get_system_gconn returned NULL");
3933 proxy = g_dbus_proxy_new_sync(conn,
3934 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
3935 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
3936 if (proxy == NULL) {
3937 ERR("device_proxy returned NULL");
3941 ret = g_dbus_proxy_call_sync(proxy, "Get",
3942 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
3943 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3945 ERR("DBus Error : %s", err->message);
3946 g_clear_error(&err);
3948 g_variant_get(ret, "(v)", &value);
3949 *service_uuid = g_variant_dup_string(value, NULL);
3950 g_variant_unref(value);
3951 g_variant_unref(ret);
3955 g_object_unref(proxy);
3960 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
3962 struct hal_ev_gatt_client_service_changed ev = {0, };
3963 char address[BT_HAL_ADDRESS_STRING_SIZE];
3964 hal_gattc_server_info_t *server_info = NULL;
3965 hal_gattc_client_info_t *gattc_client = NULL;
3966 hal_gattc_service_t *service = NULL;
3967 GSList *list = NULL;
3968 char *uuid_str = NULL;
3970 _bt_hal_convert_device_path_to_address(path, address);
3971 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
3972 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
3973 if (server_info == NULL) {
3974 ERR("server_info is NULL");
3978 gattc_client = __bt_find_gatt_client_info((bt_bdaddr_t *)ev.bdaddr);
3979 if (gattc_client == NULL) {
3980 ERR("gattc_client is NULL");
3984 if (server_info->is_gatt_connected == FALSE && gattc_client->is_gatt_connected == FALSE) {
3985 DBG("GattConnected signal is not received yet. Just skip [%d %d]",
3986 server_info->is_gatt_connected, gattc_client->is_gatt_connected);
3991 /* Get service UUID from path */
3992 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
3994 INFO("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
3995 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3998 ERR("uuid_str is NULL");
4002 /* Create new service and append into the list */
4003 __hal_gattc_get_service_info(server_info, path);
4005 /* Find service UUID from path */
4006 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4007 service = (hal_gattc_service_t *)list->data;
4008 if (service == NULL)
4011 if (g_strcmp0(service->svc_path, path) == 0) {
4012 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4013 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4014 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4015 INFO("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
4017 /* Remove service info in list */
4018 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4019 __hal_gattc_free_svc_info(service);
4027 ERR("uuid_str is NULL");
4032 /* Send GATT Client service changed event */
4033 ev.change_type = is_added;
4034 ev.conn_id = server_info->conn_id;
4035 ev.inst_id = server_info->inst_id;
4036 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));