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("Total 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;
694 uint8_t uuid[BT_HAL_STACK_UUID_SIZE];
696 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
697 gatt_svc = _gattc_find_service_from_uuid(conn_info, (bt_uuid_t *)uuid);
699 DBG("Aleady added to gatt_list_services");
703 /* add the service */
704 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
705 if (gatt_svc == NULL) {
706 ERR("Failed to add service");
710 /* add the characteristic */
711 for (i = 0; i < gp_char_array->len; i++) {
712 gp_char_path = g_ptr_array_index(gp_char_array, i);
713 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
716 g_ptr_array_free(gp_char_array, TRUE);
719 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
721 hal_gattc_desc_t *gattc_desc = NULL;
723 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
724 gattc_desc->desc_path = g_strdup(desc_path);
726 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
729 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
730 GPtrArray *gp_desc_array, unsigned int char_permission)
732 gchar *gp_desc_path = NULL;
735 if (char_uuid_str == NULL) {
736 DBG("char_uuid_str is NULL");
740 //update the char uuid
741 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
743 //update char permission
744 gattc_char->permission = char_permission;
747 for (i = 0; i < gp_desc_array->len; i++) {
748 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
749 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
753 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
755 if (desc_uuid_str == NULL) {
756 DBG("char_uuid_str is NULL");
760 //update the descriptor uuid
761 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
763 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
766 static void browse_service_char(int conn_id)
768 hal_gattc_server_info_t *conn_info = NULL;
772 hal_gattc_service_t *svc_info = NULL;
773 hal_gattc_char_t *char_info = NULL;
774 hal_gattc_desc_t *desc_info = NULL;
776 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
777 if (conn_info == NULL) {
778 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
782 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
783 svc_info = (hal_gattc_service_t*)l->data;
784 if (svc_info == NULL)
787 /* find characteristic object path */
788 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
789 char_info = (hal_gattc_char_t *)k->data;
790 if (char_info == NULL)
794 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
795 desc_info = (hal_gattc_desc_t *)m->data;
796 if (desc_info == NULL)
806 * Enumerate all GATT services on a connected device.
807 * Optionally, the results can be filtered for a given UUID.
809 static bt_status_t _gattc_client_search_service(int conn_id)
813 GVariant *result = NULL;
815 GVariantIter *svc_iter;
816 GVariantIter *interface_iter;
817 char *object_path = NULL;
818 char *interface_str = NULL;
819 const gchar *key = NULL;
820 GVariant *value = NULL;
821 GPtrArray *gp_array = NULL;
822 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
823 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
824 int ret = BT_STATUS_FAIL;
826 const gchar *uuid_str = NULL;
828 hal_gattc_server_info_t *conn_info = NULL;
829 gboolean is_primary = FALSE;
832 char *char_handle = NULL;
833 GVariantIter *char_iter = NULL;
834 GPtrArray *gp_char_array = NULL;
836 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
837 if (NULL == conn_info) {
838 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
839 return BT_STATUS_FAIL;
843 // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
844 /* Check the service info is stored */
845 if (g_slist_length(conn_info->gatt_list_services) > 0) {
847 hal_gattc_service_t *svc_info = NULL;
848 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
849 DBG("Send event from service info list");
850 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
852 if (svc_info == NULL)
854 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
855 _bt_hal_send_search_service_result_event(conn_id,
856 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
858 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
859 return BT_STATUS_SUCCESS;
861 DBG("No stored service, request to bluez");
865 _bt_hal_convert_addr_type_to_string(device_address,
866 (unsigned char *)conn_info->bd_addr.address);
868 result = _bt_hal_get_managed_objects();
872 gp_array = g_ptr_array_new();
873 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
875 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
877 if (object_path == NULL)
880 _bt_hal_convert_device_path_to_address(object_path, temp_address);
882 if (g_strcmp0(temp_address, device_address) != 0)
885 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
886 &interface_str, &svc_iter)) {
887 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
890 DBG("[%d] %s", idx++, object_path + 15);
891 /* for characteristic */
892 gp_char_array = g_ptr_array_new();
893 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
894 if (g_strcmp0(key, "Primary") == 0) {
895 is_primary = g_variant_get_boolean(value);
897 g_ptr_array_add(gp_array, (gpointer)object_path);
900 } else if (g_strcmp0(key, "UUID") == 0) {
901 uuid_str = g_variant_get_string(value, &len);
902 } else if (g_strcmp0(key, "Characteristics") == 0) {
903 g_variant_get(value, "ao", &char_iter);
904 if (char_iter != NULL) {
905 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
906 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
913 _bt_hal_send_search_service_result_event(conn_id, is_primary,
914 uuid_str, conn_info->inst_id);
916 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
921 if (gp_array->len == 0 || svc_count == 0) {
922 ERR("gp_array is NULL");
923 ret = BT_STATUS_FAIL;
925 ret = BT_STATUS_SUCCESS;
928 browse_service_char(conn_id);
929 /* send search service complete event */
930 _bt_hal_send_search_service_complete_event(conn_id, ret);
932 g_ptr_array_free(gp_array, TRUE);
933 g_variant_iter_free(iter);
934 g_variant_unref(result);
939 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
941 if (NULL == filter_uuid) {
942 DBG("Browse all the services");
943 return _gattc_client_search_service(conn_id);
945 DBG("TODO implement it");
946 return BT_STATUS_UNSUPPORTED;
950 * Enumerate included services for a given service.
951 * Set start_incl_srvc_id to NULL to get the first included service.
953 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
954 btgatt_srvc_id_t *start_incl_srvc_id)
957 return BT_STATUS_UNSUPPORTED;
960 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
961 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
963 struct hal_ev_gatt_client_char_search_result ev;
966 ERR("gatt client callback not registered");
970 memset(&ev, 0, sizeof(ev));
971 ev.conn_id = conn_id;
972 ev.inst_id = svc_id->id.inst_id;
973 ev.is_primary = svc_id->is_primary;
975 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
977 if (status == BT_STATUS_SUCCESS) {
978 /* building char uuid */
979 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
980 ev.char_prop = char_prop;
983 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
984 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
987 static int _hal_get_permission_flag(char *permission)
991 if (NULL == permission) {
992 ERR("gatt permission is NULL");
996 if (!g_strcmp0(permission, "broadcast"))
997 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
998 else if (!g_strcmp0(permission, "read"))
999 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
1000 else if (!g_strcmp0(permission, "write-without-response"))
1001 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1002 else if (!g_strcmp0(permission, "write"))
1003 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1004 else if (!g_strcmp0(permission, "notify"))
1005 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1006 else if (!g_strcmp0(permission, "indicate"))
1007 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
1008 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
1009 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
1010 else if (!g_strcmp0(permission, "reliable-write"))
1011 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
1012 else if (!g_strcmp0(permission, "writable-auxiliaries"))
1013 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1014 else if (!g_strcmp0(permission, "encrypt-read"))
1015 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1016 else if (!g_strcmp0(permission, "encrypt-write"))
1017 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1018 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1019 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1020 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1021 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1026 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1028 char perm[200] = { 0, };
1030 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1031 g_strlcat(perm, "broadcast ", sizeof(perm));
1032 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1033 g_strlcat(perm, "read ", sizeof(perm));
1034 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1035 g_strlcat(perm, "write-without-response ", sizeof(perm));
1036 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1037 g_strlcat(perm, "write ", sizeof(perm));
1038 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1039 g_strlcat(perm, "notify ", sizeof(perm));
1040 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1041 g_strlcat(perm, "indicate ", sizeof(perm));
1042 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1043 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1044 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1045 g_strlcat(perm, "reliable-write ", sizeof(perm));
1046 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1047 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1048 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1049 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1050 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1051 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1052 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1053 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1054 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1055 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1057 DBG("permission [0x%04x] : %s\n", permission, perm);
1061 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1063 GDBusProxy *properties_proxy = NULL;
1064 GError *error = NULL;
1065 GVariant *value = NULL;
1066 GVariant *result = NULL;
1067 GDBusConnection *g_conn;
1069 char *char_desc_handle = NULL;
1071 GVariantIter *property_iter;
1072 GVariantIter *char_desc_iter;
1073 char* char_handle = NULL;
1074 gchar *char_uuid_str = NULL;
1075 GPtrArray *gp_desc_array = NULL;
1076 GVariantIter *char_perm_iter;
1078 unsigned int char_permission = 0 ;
1080 if (gattc_char->chr_path == NULL) {
1081 DBG("char path is NULL");
1082 return BT_STATUS_FAIL;
1084 char_handle = gattc_char->chr_path;
1086 g_conn = _bt_hal_get_system_gconn();
1087 if (NULL == g_conn) {
1088 ERR("_bt_gdbus_get_system_gconn returned NULL");
1089 return BT_STATUS_FAIL;
1092 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1093 G_DBUS_PROXY_FLAGS_NONE, NULL,
1096 BT_HAL_PROPERTIES_INTERFACE,
1099 if (properties_proxy == NULL) {
1100 ERR("properties_proxy returned NULL");
1101 return BT_STATUS_FAIL;
1104 result = g_dbus_proxy_call_sync(properties_proxy,
1106 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1107 G_DBUS_CALL_FLAGS_NONE,
1112 if (error != NULL) {
1113 ERR("Fail to get properties (Error: %s)", error->message);
1114 g_clear_error(&error);
1116 ERR("Fail to get properties");
1117 g_object_unref(properties_proxy);
1118 return BT_STATUS_FAIL;
1121 gp_desc_array = g_ptr_array_new();
1123 g_variant_get(result, "(a{sv})", &property_iter);
1125 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1126 if (!g_strcmp0(key, "UUID")) {
1127 char_uuid_str = g_variant_dup_string(value, &len);
1128 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1129 } else if (!g_strcmp0(key, "Flags")) {
1130 g_variant_get(value, "as", &char_perm_iter);
1131 char_permission = 0x00;
1133 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1134 char_permission |= _hal_get_permission_flag(permission);
1136 __hal_convert_permission_flag_to_str(char_permission);
1137 g_variant_iter_free(char_perm_iter);
1138 } else if (!g_strcmp0(key, "Descriptors")) {
1139 g_variant_get(value, "ao", &char_desc_iter);
1140 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1141 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1143 g_variant_iter_free(char_desc_iter);
1147 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1149 g_free(char_uuid_str);
1150 g_variant_iter_free(property_iter);
1151 g_variant_unref(result);
1152 g_object_unref(properties_proxy);
1153 g_ptr_array_free(gp_desc_array, TRUE);
1155 return BT_STATUS_SUCCESS;
1158 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1159 btgatt_srvc_id_t *srvc_id)
1161 hal_gattc_server_info_t * conn_info = NULL;
1162 hal_gattc_service_t *gattc_service = NULL;
1164 hal_gattc_char_t *gattc_char = NULL;
1165 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1166 int status = BT_STATUS_FAIL;
1168 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1169 if (NULL == conn_info) {
1170 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1171 return BT_STATUS_FAIL;
1175 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1176 if (NULL == gattc_service) {
1177 ERR("Failed to get the gatt service");
1178 return BT_STATUS_FAIL;
1181 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1182 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1184 /* find characteristic object path */
1185 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1186 gattc_char = (hal_gattc_char_t *)l->data;
1187 status = _hal_gattc_get_characteristic_info(gattc_char);
1190 if (BT_STATUS_SUCCESS == status) {
1191 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1192 &gattc_char->chr_uuid, gattc_char->permission);
1196 status = BT_STATUS_FAIL;
1197 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1199 browse_service_char(conn_id);
1200 /* retrive uuid for characteristic and object path for descriptor */
1202 return BT_STATUS_SUCCESS;
1206 * Enumerate characteristics for a given service.
1207 * Set start_char_id to NULL to get the first characteristic.
1209 bt_status_t btif_gattc_get_characteristic(int conn_id,
1210 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1212 CHECK_BTGATT_INIT();
1214 if (start_char_id == NULL) {
1215 return _gattc_get_all_characteristic(conn_id, srvc_id);
1218 DBG("TBD Get specific characteristics");
1219 return BT_STATUS_UNSUPPORTED;
1223 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1225 GDBusProxy *properties_proxy = NULL;
1226 GError *error = NULL;
1227 GVariant *value = NULL;
1228 GVariant *result = NULL;
1229 GDBusConnection *g_conn;
1232 GVariantIter *property_iter;
1233 char* desc_handle = NULL;
1234 const gchar *desc_uuid_str = NULL;
1236 if (gattc_desc->desc_path == NULL) {
1237 DBG("desc path is NULL");
1238 return BT_STATUS_FAIL;
1240 desc_handle = gattc_desc->desc_path;
1242 g_conn = _bt_hal_get_system_gconn();
1243 if (NULL == g_conn) {
1244 ERR("_bt_gdbus_get_system_gconn returned NULL");
1245 return BT_STATUS_FAIL;
1248 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1249 G_DBUS_PROXY_FLAGS_NONE, NULL,
1252 BT_HAL_PROPERTIES_INTERFACE,
1255 if (properties_proxy == NULL) {
1256 ERR("properties_proxy returned NULL");
1257 return BT_STATUS_FAIL;
1260 result = g_dbus_proxy_call_sync(properties_proxy,
1262 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1263 G_DBUS_CALL_FLAGS_NONE,
1268 if (error != NULL) {
1269 ERR("Fail to get properties (Error: %s)", error->message);
1270 g_clear_error(&error);
1272 ERR("Fail to get properties");
1273 g_object_unref(properties_proxy);
1274 return BT_STATUS_FAIL;
1277 g_variant_get(result, "(a{sv})", &property_iter);
1279 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1280 if (!g_strcmp0(key, "UUID")) {
1281 desc_uuid_str = g_variant_get_string(value, &len);
1282 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1284 g_free((gchar *)key);
1285 g_variant_unref(value);
1290 g_variant_iter_free(property_iter);
1291 g_variant_unref(result);
1292 g_object_unref(properties_proxy);
1294 return BT_STATUS_SUCCESS;
1297 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1298 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1300 struct hal_ev_gatt_client_desc_search_result ev;
1303 ERR("gatt client callback not registered");
1307 memset(&ev, 0, sizeof(ev));
1308 ev.conn_id = conn_id;
1309 ev.inst_id = svc_id->id.inst_id;
1310 ev.is_primary = svc_id->is_primary;
1313 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1314 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1316 if (status == BT_STATUS_SUCCESS) {
1317 /* building desc uuid */
1318 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1321 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1323 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1326 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1327 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1329 hal_gattc_server_info_t * conn_info = NULL;
1330 hal_gattc_service_t *gattc_service = NULL;
1333 hal_gattc_char_t *gattc_char = NULL;
1334 hal_gattc_desc_t *gattc_desc = NULL;
1335 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1336 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1337 int status = BT_STATUS_FAIL;
1339 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1340 if (NULL == conn_info) {
1341 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1342 return BT_STATUS_FAIL;
1346 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1347 if (NULL == gattc_service) {
1348 ERR("Failed to get the gatt service");
1349 return BT_STATUS_FAIL;
1352 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1353 // DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1355 /* find characteristics */
1356 /* a service can have two char with same uuid */
1357 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1358 gattc_char = (hal_gattc_char_t*)l->data;
1359 if (gattc_char == NULL)
1362 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1363 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1364 // DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1366 /* get descriptor uuid */
1367 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1368 gattc_desc = (hal_gattc_desc_t *)m->data;
1369 if (gattc_desc == NULL)
1372 status = _hal_gattc_get_descriptor_info(gattc_desc);
1375 if (BT_STATUS_SUCCESS == status) {
1376 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1377 char_id, &gattc_desc->desc_uuid);
1383 status = BT_STATUS_FAIL;
1384 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1386 browse_service_char(conn_id);
1387 /* retrive uuid for characteristic and object path for descriptor */
1389 return BT_STATUS_SUCCESS;
1393 * Enumerate descriptors for a given characteristic.
1394 * Set start_descr_id to NULL to get the first descriptor.
1396 bt_status_t btif_gattc_get_descriptor(int conn_id,
1397 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1398 btgatt_gatt_id_t *start_descr_id)
1400 CHECK_BTGATT_INIT();
1402 if (start_descr_id == NULL) {
1403 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1405 DBG("TBD Get specific descriptor");
1406 return BT_STATUS_UNSUPPORTED;
1410 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1412 struct hal_ev_gatt_client_read_data ev;
1415 ERR("gatt client callback not registered");
1419 memset(&ev, 0, sizeof(ev));
1420 ev.conn_id = resp_data->conn_id;
1421 ev.inst_id = resp_data->srvc_id.id.inst_id;
1422 ev.is_primary = resp_data->srvc_id.is_primary;
1425 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1426 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1430 /* building the char read value */
1431 memcpy(ev.value, value, len);
1434 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1436 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1439 static void __hal_internal_read_char_cb(GObject *source_object,
1440 GAsyncResult *res, gpointer user_data)
1442 GError *error = NULL;
1443 GDBusConnection *system_gconn = NULL;
1446 GByteArray *gp_byte_array = NULL;
1448 hal_gatt_resp_data_t *resp_data = user_data;
1449 int result = BT_STATUS_SUCCESS;
1451 system_gconn = _bt_hal_get_system_gconn();
1452 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1455 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1458 result = BT_STATUS_FAIL;
1459 __hal_send_char_read_event(resp_data, result, NULL, 0);
1460 g_clear_error(&error);
1465 gp_byte_array = g_byte_array_new();
1466 g_variant_get(value, "(ay)", &iter);
1468 while (g_variant_iter_loop(iter, "y", &g_byte))
1469 g_byte_array_append(gp_byte_array, &g_byte, 1);
1473 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1477 g_byte_array_free(gp_byte_array, TRUE);
1478 g_variant_iter_free(iter);
1479 g_variant_unref(value);
1483 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1484 btgatt_gatt_id_t *char_id, int auth_req)
1486 GDBusConnection *g_conn;
1487 hal_gatt_resp_data_t *resp_data;
1488 hal_gattc_service_t *gattc_service = NULL;
1489 GVariantBuilder *builder = NULL;
1491 hal_gattc_server_info_t * conn_info = NULL;
1492 hal_gattc_char_t *gattc_char = NULL;
1493 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1494 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1495 char* char_handle = NULL;
1497 /* get the connection info */
1498 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1499 if (NULL == conn_info) {
1500 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1501 return BT_STATUS_FAIL;
1505 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1506 if (NULL == gattc_service) {
1507 ERR("Failed to get the gatt service");
1508 return BT_STATUS_FAIL;
1511 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1513 /* find characteristic */
1514 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1515 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1516 if (NULL == gattc_char) {
1517 ERR("Failed to get the gatt char");
1518 return BT_STATUS_FAIL;
1521 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1522 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1524 g_conn = _bt_hal_get_system_gconn();
1525 if (NULL == g_conn) {
1526 ERR("_bt_gdbus_get_system_gconn returned NULL");
1527 return BT_STATUS_FAIL;
1530 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1531 resp_data->conn_id = conn_id;
1532 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1533 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1535 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1538 g_variant_builder_add(builder, "{sv}", "offset",
1539 g_variant_new("q", offset));
1541 char_handle = gattc_char->chr_path;
1543 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1544 "ReadValue", g_variant_new("(a{sv})", builder),
1545 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1546 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1547 (gpointer)resp_data);
1548 g_variant_builder_unref(builder);
1550 return BT_STATUS_SUCCESS;
1553 /** Read a characteristic on a remote device */
1554 bt_status_t btif_read_characteristic(int conn_id,
1555 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1558 CHECK_BTGATT_INIT();
1560 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1563 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1565 struct hal_ev_gatt_client_write_result ev;
1568 ERR("gatt client callback not registered");
1572 memset(&ev, 0, sizeof(ev));
1573 ev.conn_id = resp_data->conn_id;
1574 ev.inst_id = resp_data->srvc_id.id.inst_id;
1575 ev.is_primary = resp_data->srvc_id.is_primary;
1578 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1579 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1581 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1584 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1585 GAsyncResult *res, gpointer user_data)
1587 GError *error = NULL;
1588 GDBusConnection *system_gconn = NULL;
1590 hal_gatt_resp_data_t *resp_data = user_data;
1591 int result = BT_STATUS_SUCCESS;
1593 system_gconn = _bt_hal_get_system_gconn();
1594 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1597 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1599 result = BT_STATUS_FAIL;
1601 __hal_send_char_write_event(resp_data, result);
1602 g_clear_error(&error);
1607 //send write value event
1608 __hal_send_char_write_event(resp_data, result);
1611 g_variant_unref(value);
1615 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1618 case HAL_GATT_WRITE_TYPE_WRITE:
1619 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1621 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1622 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1625 ERR("Unknow write type : %d", type);
1626 return BT_STATUS_FAIL;
1629 return BT_STATUS_SUCCESS;
1633 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1635 GDBusConnection *conn;
1636 GVariantBuilder *builder = NULL;
1642 GUnixFDList *fd_list = NULL;
1644 conn = _bt_hal_get_system_gconn();
1646 ERR("_bt_gdbus_get_system_gconn returned NULL");
1647 return BT_STATUS_FAIL;
1650 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1651 //val = g_variant_new("ay", builder1);
1653 g_variant_builder_add(builder, "{sv}", "offset",
1654 g_variant_new("q", offset));
1656 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1657 "AcquireWrite", g_variant_new("(a{sv})", builder),
1658 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1659 NULL, &fd_list, NULL, &err);
1661 g_dbus_error_strip_remote_error(err);
1662 ERR("Error: %s", err->message);
1664 g_variant_builder_unref(builder);
1665 return BT_STATUS_FAIL;
1668 g_variant_get(value, "(hq)", &idx, &att_mtu);
1669 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1671 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1674 g_object_unref(fd_list);
1675 g_variant_unref(value);
1676 g_variant_builder_unref(builder);
1678 return BT_STATUS_SUCCESS;
1681 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1683 GDBusConnection *conn;
1684 GVariantBuilder *builder = NULL;
1688 gint32 idx, notify_fd;
1690 GUnixFDList *fd_list = NULL;
1692 conn = _bt_hal_get_system_gconn();
1695 ERR("_bt_gdbus_get_system_gconn returned NULL");
1696 return BT_STATUS_FAIL;
1700 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1703 g_variant_builder_add(builder, "{sv}", "offset",
1704 g_variant_new("q", offset));
1706 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1707 "AcquireNotify", g_variant_new("(a{sv})", builder),
1708 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1709 NULL, &fd_list, NULL, &err);
1711 g_dbus_error_strip_remote_error(err);
1712 ERR("Error: %s", err->message);
1714 g_variant_builder_unref(builder);
1715 return BT_STATUS_FAIL;
1718 g_variant_get(value, "(hq)", &idx, &att_mtu);
1719 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1722 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1726 g_object_unref(fd_list);
1727 g_variant_unref(value);
1728 g_variant_builder_unref(builder);
1730 return BT_STATUS_SUCCESS;
1734 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1735 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1737 GVariant *val, *options;
1738 GVariantBuilder *builder1;
1739 GVariantBuilder *builder2;
1740 GDBusConnection *g_conn;
1743 hal_gatt_resp_data_t *resp_data;
1744 hal_gattc_service_t *gattc_service = NULL;
1745 hal_gattc_server_info_t * conn_info = NULL;
1746 hal_gattc_char_t *gattc_char = NULL;
1747 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1748 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1749 char* char_handle = NULL;
1750 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1751 int ret = BT_STATUS_SUCCESS;
1753 ret = __hal_get_write_prop(write_type, &write_prop);
1754 if (BT_STATUS_FAIL == ret) {
1755 DBG("received invalid write type:[%d] ", write_type);
1756 return BT_STATUS_FAIL;
1759 /* get the connection info */
1760 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1761 if (NULL == conn_info) {
1762 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1763 return BT_STATUS_FAIL;
1767 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1768 if (NULL == gattc_service) {
1769 ERR("Failed to get the gatt service");
1770 return BT_STATUS_FAIL;
1773 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1774 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1776 /* find characteristic */
1777 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1778 if (NULL == gattc_char) {
1779 ERR("Failed to get the gatt char");
1780 return BT_STATUS_FAIL;
1783 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1784 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1786 g_conn = _bt_hal_get_system_gconn();
1787 if (NULL == g_conn) {
1788 ERR("_bt_gdbus_get_system_gconn returned NULL");
1789 return BT_STATUS_FAIL;
1792 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1793 resp_data->conn_id = conn_id;
1794 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1795 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1797 char_handle = gattc_char->chr_path;
1799 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1801 for (i = 0; i < length; i++)
1802 g_variant_builder_add(builder1, "y", value[i]);
1804 val = g_variant_new("ay", builder1);
1806 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1808 g_variant_builder_add(builder2, "{sv}", "offset",
1809 g_variant_new_uint16(offset));
1811 options = g_variant_new("a{sv}", builder2);
1813 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1815 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1817 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1818 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1819 (gpointer)resp_data);
1821 g_variant_builder_unref(builder1);
1822 g_variant_builder_unref(builder2);
1824 return BT_STATUS_SUCCESS;
1827 bt_status_t btif_get_acquire_write_fd(int conn_id,
1828 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1829 int auth_req, int *fd, int*mtu)
1831 CHECK_BTGATT_INIT();
1833 hal_gattc_service_t *gattc_service = NULL;
1834 hal_gattc_server_info_t * conn_info = NULL;
1835 hal_gattc_char_t *gattc_char = NULL;
1836 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1838 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1839 int ret = BT_STATUS_SUCCESS;
1841 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1843 /* get the connection info */
1844 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1845 if (NULL == conn_info) {
1846 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1847 return BT_STATUS_FAIL;
1851 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1852 if (NULL == gattc_service) {
1853 ERR("Failed to get the gatt service");
1854 return BT_STATUS_FAIL;
1857 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1858 if (NULL == gattc_char) {
1859 ERR("Failed to get the gatt char");
1860 return BT_STATUS_FAIL;
1863 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1864 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1866 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1867 if (ret != BT_STATUS_SUCCESS)
1873 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1874 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1876 CHECK_BTGATT_INIT();
1878 hal_gattc_service_t *gattc_service = NULL;
1879 hal_gattc_server_info_t * conn_info = NULL;
1880 hal_gattc_char_t *gattc_char = NULL;
1881 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1883 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1884 int ret = BT_STATUS_SUCCESS;
1886 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1888 /* get the connection info */
1889 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1890 if (NULL == conn_info) {
1891 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1892 return BT_STATUS_FAIL;
1896 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1897 if (NULL == gattc_service) {
1898 ERR("Failed to get the gatt service");
1899 return BT_STATUS_FAIL;
1902 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1903 if (NULL == gattc_char) {
1904 ERR("Failed to get the gatt char");
1905 return BT_STATUS_FAIL;
1908 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1909 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1911 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1912 if (ret != BT_STATUS_SUCCESS)
1919 /** Write a remote characteristic */
1920 bt_status_t btif_write_characteristic(int conn_id,
1921 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1922 int write_type, int len, int auth_req,
1925 CHECK_BTGATT_INIT();
1927 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1928 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1929 len, auth_req, p_value);
1932 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1934 struct hal_ev_gatt_client_read_data ev;
1937 ERR("gatt client callback not registered");
1941 memset(&ev, 0, sizeof(ev));
1942 ev.conn_id = resp_data->conn_id;
1943 ev.inst_id = resp_data->srvc_id.id.inst_id;
1944 ev.is_primary = resp_data->srvc_id.is_primary;
1947 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1948 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1949 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1953 /* building the desc read value */
1954 memcpy(ev.value, value, len);
1957 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1959 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1962 static void __hal_internal_read_desc_cb(GObject *source_object,
1963 GAsyncResult *res, gpointer user_data)
1965 GError *error = NULL;
1966 GDBusConnection *system_gconn = NULL;
1969 GByteArray *gp_byte_array = NULL;
1971 hal_gatt_resp_data_t *resp_data = user_data;
1972 int result = BT_STATUS_SUCCESS;
1977 system_gconn = _bt_hal_get_system_gconn();
1978 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1981 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1984 result = BT_STATUS_FAIL;
1985 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1986 g_clear_error(&error);
1991 gp_byte_array = g_byte_array_new();
1992 g_variant_get(value, "(ay)", &iter);
1994 while (g_variant_iter_loop(iter, "y", &g_byte))
1995 g_byte_array_append(gp_byte_array, &g_byte, 1);
1999 for (i = 0; i < gp_byte_array->len; i++)
2000 DBG("%02x", gp_byte_array->data[i]);
2003 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2007 g_byte_array_free(gp_byte_array, TRUE);
2008 g_variant_iter_free(iter);
2009 g_variant_unref(value);
2014 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2015 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2017 GDBusConnection *g_conn;
2018 hal_gatt_resp_data_t *resp_data;
2019 hal_gattc_service_t *gattc_service = NULL;
2020 GVariantBuilder *builder = NULL;
2022 hal_gattc_server_info_t * conn_info = NULL;
2023 hal_gattc_char_t *gattc_char = NULL;
2024 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2025 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2026 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2027 char* desc_handle = NULL;
2030 hal_gattc_desc_t *gattc_desc = NULL;
2032 /* get the connection info */
2033 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2034 if (NULL == conn_info) {
2035 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2036 return BT_STATUS_FAIL;
2040 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2041 if (NULL == gattc_service) {
2042 ERR("Failed to get the gatt service");
2043 return BT_STATUS_FAIL;
2046 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2047 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2049 /* find characteristic */
2050 /* service can have two char with same uuid */
2051 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2052 gattc_char = (hal_gattc_char_t*)l->data;
2053 if (gattc_char == NULL)
2056 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2057 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2058 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2060 /* find descriptor */
2061 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2063 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2064 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2070 if (NULL == gattc_desc) {
2071 ERR("Failed to get the gatt desc");
2072 return BT_STATUS_FAIL;
2075 g_conn = _bt_hal_get_system_gconn();
2076 if (NULL == g_conn) {
2077 ERR("_bt_gdbus_get_system_gconn returned NULL");
2078 return BT_STATUS_FAIL;
2081 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2082 resp_data->conn_id = conn_id;
2083 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2084 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2085 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2087 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2090 g_variant_builder_add(builder, "{sv}", "offset",
2091 g_variant_new("q", offset));
2093 desc_handle = gattc_desc->desc_path;
2095 DBG("calling desc read value");
2097 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2098 "ReadValue", g_variant_new("(a{sv})", builder),
2099 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2100 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2101 (gpointer)resp_data);
2102 g_variant_builder_unref(builder);
2104 return BT_STATUS_SUCCESS;
2107 /** Read the descriptor for a given characteristic */
2108 bt_status_t btif_read_descriptor(int conn_id,
2109 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2110 btgatt_gatt_id_t *descr_id, int auth_req)
2112 CHECK_BTGATT_INIT();
2114 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2117 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2119 struct hal_ev_gatt_client_write_result ev;
2122 ERR("gatt client callback not registered");
2126 memset(&ev, 0, sizeof(ev));
2127 ev.conn_id = resp_data->conn_id;
2128 ev.inst_id = resp_data->srvc_id.id.inst_id;
2129 ev.is_primary = resp_data->srvc_id.is_primary;
2132 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2133 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2134 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2136 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2138 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2141 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2142 GAsyncResult *res, gpointer user_data)
2144 GError *error = NULL;
2145 GDBusConnection *system_gconn = NULL;
2147 hal_gatt_resp_data_t *resp_data = user_data;
2148 int result = BT_STATUS_SUCCESS;
2152 system_gconn = _bt_hal_get_system_gconn();
2153 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2156 ERR("write descriptor dbus failed Error: [%s]", error->message);
2159 result = BT_STATUS_FAIL;
2160 __hal_send_desc_write_event(resp_data, result);
2161 g_clear_error(&error);
2166 //send write value event
2167 __hal_send_desc_write_event(resp_data, result);
2170 g_variant_unref(value);
2175 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2176 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2177 int write_type, int length, int auth_req, char* value)
2179 GVariant *val, *options;
2180 GVariantBuilder *builder1;
2181 GVariantBuilder *builder2;
2182 GDBusConnection *g_conn;
2185 hal_gatt_resp_data_t *resp_data;
2186 hal_gattc_service_t *gattc_service = NULL;
2187 hal_gattc_server_info_t * conn_info = NULL;
2188 hal_gattc_char_t *gattc_char = NULL;
2189 hal_gattc_desc_t *gattc_desc = NULL;
2190 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2191 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2192 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2193 char* desc_handle = NULL;
2194 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2195 int ret = BT_STATUS_SUCCESS;
2200 ret = __hal_get_write_prop(write_type, &write_prop);
2201 if (BT_STATUS_FAIL == ret) {
2202 ERR("received invalid write type:[%d] ", write_type);
2203 return BT_STATUS_FAIL;
2206 /* get the connection info */
2207 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2208 if (NULL == conn_info) {
2209 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2210 return BT_STATUS_FAIL;
2214 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2215 if (NULL == gattc_service) {
2216 ERR("Failed to get the gatt service");
2217 return BT_STATUS_FAIL;
2220 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2221 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2223 /* find characteristic */
2224 /* service can have two char with same uuid */
2225 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2226 gattc_char = (hal_gattc_char_t*)l->data;
2227 if (gattc_char == NULL)
2230 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2231 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2232 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2234 /* find descriptor */
2235 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2237 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2238 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2244 if (NULL == gattc_desc) {
2245 ERR("Failed to get the gatt desc");
2246 return BT_STATUS_FAIL;
2249 g_conn = _bt_hal_get_system_gconn();
2250 if (NULL == g_conn) {
2251 ERR("_bt_gdbus_get_system_gconn returned NULL");
2252 return BT_STATUS_FAIL;
2255 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2256 resp_data->conn_id = conn_id;
2257 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2258 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2259 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2261 desc_handle = gattc_desc->desc_path;
2263 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2265 for (i = 0; i < length; i++)
2266 g_variant_builder_add(builder1, "y", value[i]);
2268 val = g_variant_new("ay", builder1);
2270 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2272 g_variant_builder_add(builder2, "{sv}", "offset",
2273 g_variant_new_uint16(offset));
2275 options = g_variant_new("a{sv}", builder2);
2277 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2279 g_variant_new("(@ay@a{sv})", val, options),
2281 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2282 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2283 (gpointer)resp_data);
2285 g_variant_builder_unref(builder1);
2286 g_variant_builder_unref(builder2);
2288 return BT_STATUS_SUCCESS;
2291 /** Write a remote descriptor for a given characteristic */
2292 bt_status_t btif_write_descriptor(int conn_id,
2293 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2294 btgatt_gatt_id_t *descr_id, int write_type, int len,
2295 int auth_req, char* p_value)
2297 CHECK_BTGATT_INIT();
2299 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2300 len, auth_req, p_value);
2303 /** Execute a prepared write operation */
2304 bt_status_t execute_write(int conn_id, int execute)
2306 CHECK_BTGATT_INIT();
2307 return BT_STATUS_UNSUPPORTED;
2310 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2312 struct hal_ev_gatt_client_watch_notification ev;
2313 hal_gatt_resp_data_t *resp_data = user_data;
2315 DBG("sending the watch register notification event");
2316 /* send the event */
2317 memset(&ev, 0, sizeof(ev));
2318 ev.conn_id = resp_data->conn_id;
2320 ev.status = resp_data->result;
2322 ev.is_primary = resp_data->srvc_id.is_primary;
2323 ev.inst_id = resp_data->srvc_id.id.inst_id;
2325 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2326 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2329 ERR("GATT Callback not registered");
2331 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2338 static bt_status_t _hal_register_for_notification(int conn_id,
2339 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2340 btgatt_gatt_id_t *char_id)
2342 int result = BT_STATUS_SUCCESS;
2343 GError *error = NULL;
2344 GDBusConnection *g_conn;
2345 hal_gattc_client_info_t *gattc_client = NULL;
2346 hal_gattc_server_info_t * conn_info = NULL;
2347 hal_gattc_service_t *gattc_service = NULL;
2348 hal_gattc_char_t *gattc_char = NULL;
2349 char* char_handle = NULL;
2350 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2351 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2352 hal_gatt_resp_data_t *resp_data;
2356 gattc_client = __bt_find_gatt_client_info(bd_addr);
2357 if (gattc_client == NULL) {
2358 ERR("failed to get the gatt client info");
2359 return BT_STATUS_FAIL;
2362 if (gattc_client->conn_id != conn_id) {
2363 ERR("could not find the gatt client for client id[%d]", conn_id);
2364 return BT_STATUS_FAIL;
2367 /* get the connection info */
2368 conn_info = __bt_find_gatt_conn_info(bd_addr);
2369 if (NULL == conn_info) {
2370 ERR("Failed to get the conn_info");
2371 return BT_STATUS_FAIL;
2374 if (conn_info->inst_id != gattc_client->inst_id) {
2375 ERR("could not fild the conn_info");
2376 return BT_STATUS_FAIL;
2380 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2381 if (NULL == gattc_service) {
2382 ERR("Failed to get the gatt service");
2383 return BT_STATUS_FAIL;
2386 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2387 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2390 /* find characteristic */
2391 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2392 if (NULL == gattc_char) {
2393 ERR("Failed to get the gatt char");
2394 return BT_STATUS_FAIL;
2397 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2398 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2400 char_handle = gattc_char->chr_path;
2402 g_conn = _bt_hal_get_system_gconn();
2403 if (g_conn == NULL) {
2405 return BT_STATUS_FAIL;
2408 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2410 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2412 g_dbus_connection_call_sync(g_conn,
2415 BT_HAL_GATT_CHAR_INTERFACE,
2419 G_DBUS_CALL_FLAGS_NONE,
2420 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2423 g_dbus_error_strip_remote_error(error);
2424 ERR("### StartNotify Failed: %s", error->message);
2425 if (g_strrstr(error->message, "Already notifying"))
2426 result = BT_STATUS_SUCCESS;
2427 else if (g_strrstr(error->message, "In Progress"))
2428 result = BT_STATUS_BUSY;
2429 else if (g_strrstr(error->message, "Operation is not supported"))
2430 result = BT_STATUS_UNSUPPORTED;
2431 /*failed because of either Insufficient Authorization or Write Not Permitted */
2432 else if (g_strrstr(error->message, "Write not permitted") ||
2433 g_strrstr(error->message, "Operation Not Authorized"))
2434 result = BT_STATUS_AUTH_FAILURE;
2435 /* failed because of either Insufficient Authentication,
2436 Insufficient Encryption Key Size, or Insufficient Encryption. */
2437 else if (g_strrstr(error->message, "Not paired"))
2438 result = BT_STATUS_NOT_READY;
2440 result = BT_STATUS_FAIL;
2442 g_clear_error(&error);
2445 resp_data->conn_id = gattc_client->conn_id;
2446 resp_data->result = result;
2447 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2448 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2450 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2454 return BT_STATUS_SUCCESS;
2458 * Register to receive notifications or indications for a given
2461 bt_status_t btif_register_for_notification(int conn_id,
2462 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2463 btgatt_gatt_id_t *char_id)
2465 CHECK_BTGATT_INIT();
2467 return _hal_register_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2470 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2472 struct hal_ev_gatt_client_watch_notification ev;
2473 hal_gatt_resp_data_t *resp_data = user_data;
2475 DBG("sending the watch deregister notification event");
2476 /* send the event */
2477 memset(&ev, 0, sizeof(ev));
2478 ev.conn_id = resp_data->conn_id;
2480 ev.status = resp_data->result;
2482 ev.is_primary = resp_data->srvc_id.is_primary;
2483 ev.inst_id = resp_data->srvc_id.id.inst_id;
2485 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2486 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2489 ERR("GATT Callback not registered");
2491 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2498 static bt_status_t _hal_deregister_for_notification(int conn_id,
2499 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2500 btgatt_gatt_id_t *char_id)
2502 int result = BT_STATUS_SUCCESS;
2503 GError *error = NULL;
2504 GDBusConnection *g_conn;
2505 hal_gattc_client_info_t *gattc_client = NULL;
2506 hal_gattc_server_info_t * conn_info = NULL;
2507 hal_gattc_service_t *gattc_service = NULL;
2508 hal_gattc_char_t *gattc_char = NULL;
2509 char* char_handle = NULL;
2510 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2511 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2512 hal_gatt_resp_data_t *resp_data;
2516 gattc_client = __bt_find_gatt_client_info(bd_addr);
2517 if (gattc_client == NULL) {
2518 ERR("failed to get the gatt client info");
2519 return BT_STATUS_FAIL;
2522 if (gattc_client->conn_id != conn_id) {
2523 ERR("could not find the gatt client for client id[%d]", conn_id);
2524 return BT_STATUS_FAIL;
2527 /* get the connection info */
2528 conn_info = __bt_find_gatt_conn_info(bd_addr);
2529 if (NULL == conn_info) {
2530 ERR("Failed to get the conn_info");
2531 return BT_STATUS_FAIL;
2534 if (conn_info->inst_id != gattc_client->inst_id) {
2535 ERR("could not fild the conn_info");
2536 return BT_STATUS_FAIL;
2540 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2541 if (NULL == gattc_service) {
2542 ERR("Failed to get the gatt service");
2543 return BT_STATUS_FAIL;
2546 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2547 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2550 /* find characteristic */
2551 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2552 if (NULL == gattc_char) {
2553 ERR("Failed to get the gatt char");
2554 return BT_STATUS_FAIL;
2557 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2558 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2560 char_handle = gattc_char->chr_path;
2562 g_conn = _bt_hal_get_system_gconn();
2563 if (g_conn == NULL) {
2565 return BT_STATUS_FAIL;
2568 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2570 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2571 g_dbus_connection_call_sync(g_conn,
2574 BT_HAL_GATT_CHAR_INTERFACE,
2578 G_DBUS_CALL_FLAGS_NONE,
2579 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2582 ERR("### StopNotify Failed: %s", error->message);
2583 g_clear_error(&error);
2584 result = BT_STATUS_FAIL;
2587 resp_data->conn_id = gattc_client->conn_id;
2588 resp_data->result = result;
2589 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2590 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2592 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2596 return BT_STATUS_SUCCESS;
2598 /** Deregister a previous request for notifications/indications */
2599 bt_status_t btif_deregister_for_notification(int conn_id,
2600 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2601 btgatt_gatt_id_t *char_id)
2603 CHECK_BTGATT_INIT();
2604 return _hal_deregister_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2607 /** Request RSSI for a given remote device */
2608 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2610 CHECK_BTGATT_INIT();
2611 return BT_STATUS_UNSUPPORTED;
2614 /** OTA firmware download */
2615 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2617 CHECK_BTGATT_INIT();
2618 return BT_STATUS_UNSUPPORTED;
2621 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2622 int get_device_type(const bt_bdaddr_t *bd_addr)
2624 CHECK_BTGATT_INIT();
2625 return BT_STATUS_UNSUPPORTED;
2628 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2629 int min_int, int max_int, int latency, int timeout)
2631 gchar *device_path = NULL;
2632 GError *error = NULL;
2633 GDBusProxy *device_proxy = NULL;
2634 GDBusConnection *conn;
2636 int ret = BT_STATUS_SUCCESS;
2637 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2639 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2640 min_int, max_int, latency, timeout);
2642 conn = _bt_hal_get_system_gconn();
2645 return BT_STATUS_FAIL;
2648 _bt_hal_convert_addr_type_to_string(device_address,
2649 (unsigned char *)bd_addr->address);
2650 device_path = _bt_hal_get_device_object_path(device_address);
2652 if (device_path == NULL) {
2653 ERR("device_path NULL : [%s]", device_address);
2654 return BT_STATUS_FAIL;
2657 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2658 NULL, BT_HAL_BLUEZ_NAME,
2659 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2661 g_free(device_path);
2662 if (NULL == device_proxy) {
2663 ERR("device_proxy returned NULL");
2664 return BT_STATUS_FAIL;
2667 DBG("Request LeConnUpdate");
2668 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2669 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2670 G_DBUS_CALL_FLAGS_NONE,
2675 g_object_unref(device_proxy);
2676 if (reply == NULL) {
2678 ERR("Error %s[%s]", error->message, device_address);
2679 if (g_strrstr(error->message, "In Progress"))
2680 ret = BT_STATUS_SUCCESS;
2682 ret = BT_STATUS_FAIL;
2683 g_error_free(error);
2687 g_variant_unref(reply);
2689 DBG("LE Connection parameter Updated");
2693 /** Request a connection parameter update */
2694 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2696 CHECK_BTGATT_INIT();
2698 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2701 /** Test mode interface */
2702 bt_status_t test_command(int command, btgatt_test_params_t* params)
2704 CHECK_BTGATT_INIT();
2705 return BT_STATUS_UNSUPPORTED;
2708 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2711 GError *g_error = NULL;
2712 GVariant *reply = NULL;
2713 int result = BT_STATUS_SUCCESS;
2714 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2715 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2717 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2718 g_object_unref(proxy);
2719 if (reply == NULL) {
2720 ERR("Connect LE Dbus Call Error");
2722 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2723 g_clear_error(&g_error);
2725 result = BT_STATUS_FAIL;
2727 g_variant_unref(reply);
2729 memset(&ev, 0, sizeof(ev));
2731 ev.mtu = conn_mtu->mtu;
2732 ev.conn_id = conn_mtu->conn_id;
2735 ERR("gatt client callback not registered");
2737 DBG("sending gatt client MTU exchange completed event");
2738 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2745 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2747 gchar *device_path = NULL;
2748 GDBusProxy *device_proxy = NULL;
2749 GDBusConnection *conn;
2750 hal_gattc_client_info_t *gattc_client = NULL;
2751 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2752 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2754 conn = _bt_hal_get_system_gconn();
2758 return BT_STATUS_FAIL;
2761 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2762 if (gattc_client == NULL) {
2763 INFO("GATT client conn info not found");
2765 return BT_STATUS_FAIL;
2768 _bt_hal_convert_addr_type_to_string(device_address,
2769 (unsigned char *)gattc_client->bd_addr.address);
2771 device_path = _bt_hal_get_device_object_path(device_address);
2772 if (device_path == NULL) {
2773 ERR("device_path NULL : [%s]", device_address);
2775 return BT_STATUS_FAIL;
2778 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2779 NULL, BT_HAL_BLUEZ_NAME,
2780 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2782 g_free(device_path);
2783 if (NULL == device_proxy) {
2784 ERR("device_proxy returned NULL");
2786 return BT_STATUS_FAIL;
2789 conn_mtu->conn_id = conn_id;
2790 conn_mtu->mtu = mtu;
2792 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2793 g_variant_new("(q)", mtu),
2794 G_DBUS_CALL_FLAGS_NONE,
2795 BT_HAL_MAX_DBUS_TIMEOUT,
2797 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2800 return BT_STATUS_SUCCESS;
2803 /** MTU Exchange request from client */
2804 static bt_status_t configure_mtu(int conn_id, int mtu)
2806 CHECK_BTGATT_INIT();
2808 return __hal_configure_mtu(conn_id, mtu);
2811 /** Setup scan filter params */
2812 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2813 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2814 int rssi_low_thres, int dely_mode, int found_timeout,
2815 int lost_timeout, int found_timeout_cnt)
2818 GError *error = NULL;
2819 GVariant *ret, *param;
2820 CHECK_BTGATT_INIT();
2822 proxy = _bt_hal_get_adapter_proxy();
2825 return BT_STATUS_FAIL;
2827 param = g_variant_new("(iiiiiiiiiiii)",
2840 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2841 param, G_DBUS_CALL_FLAGS_NONE,
2845 ERR("scan_filter_param_setup Fail: %s", error->message);
2846 g_clear_error(&error);
2847 return BT_STATUS_FAIL;
2851 g_variant_unref(ret);
2853 return BT_STATUS_SUCCESS;
2856 /** Configure a scan filter condition */
2857 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2858 int filt_index, int company_id,
2859 int company_id_mask, const bt_uuid_t *p_uuid,
2860 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2861 char addr_type, int data_len, char* p_data, int mask_len,
2865 GError *error = NULL;
2866 GVariant *ret, *param;
2867 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2868 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2869 GArray *arr_uuid = NULL;
2870 GArray *arr_uuid_mask = NULL;
2871 GArray *arr_data = NULL;
2872 GArray *arr_data_mask = NULL;
2873 CHECK_BTGATT_INIT();
2875 proxy = _bt_hal_get_adapter_proxy();
2878 return BT_STATUS_FAIL;
2880 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2882 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2884 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2886 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2888 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2889 NULL, 0, TRUE, NULL, NULL);
2890 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2891 NULL, 0, TRUE, NULL, NULL);
2892 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2893 NULL, 0, TRUE, NULL, NULL);
2894 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2895 NULL, 0, TRUE, NULL, NULL);
2897 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2898 client_if, // client_if
2899 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2900 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2901 filt_index, // filter_index
2902 company_id, // company_id
2903 company_id_mask, // company_id_mask
2904 arr_uuid_param, // p_uuid
2905 arr_uuid_mask_param, // p_uuid_mask
2907 addr_type, // address_type
2908 arr_data_param, // p_data
2909 arr_data_mask_param); // p_mask
2911 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2912 param, G_DBUS_CALL_FLAGS_NONE,
2916 ERR("scan_filter_add_remove Fail: %s", error->message);
2917 g_clear_error(&error);
2918 return BT_STATUS_FAIL;
2922 g_variant_unref(ret);
2924 return BT_STATUS_SUCCESS;
2927 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2929 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2930 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2931 NULL, 0, TRUE, NULL, NULL);
2932 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2933 NULL, 0, TRUE, NULL, NULL);
2934 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2935 NULL, 0, TRUE, NULL, NULL);
2936 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2937 NULL, 0, TRUE, NULL, NULL);
2939 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2940 client_if, // client_if
2941 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2942 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2943 filt_index, // filter_index
2944 company_id, // company_id
2945 company_id_mask, // company_id_mask
2946 arr_uuid_param, // p_uuid
2947 arr_uuid_mask_param, // p_uuid_mask
2949 addr_type, // address_type
2950 arr_data_param, // p_data
2951 arr_data_mask_param);
2953 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2954 param, G_DBUS_CALL_FLAGS_NONE,
2958 ERR("scan_filter_add_remove Fail: %s", error->message);
2959 g_clear_error(&error);
2960 return BT_STATUS_FAIL;
2964 g_variant_unref(ret);
2966 return BT_STATUS_SUCCESS;
2969 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2971 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2972 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2974 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2975 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2977 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2978 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2979 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2980 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2981 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2982 NULL, 0, TRUE, NULL, NULL);
2983 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2984 NULL, 0, TRUE, NULL, NULL);
2986 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2987 client_if, // client_if
2988 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2989 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
2990 filt_index, // filter_index
2991 company_id, // company_id
2992 company_id_mask, // company_id_mask
2993 arr_uuid_param, // p_uuid
2994 arr_uuid_mask_param, // p_uuid_mask
2996 addr_type, // address_type
2997 arr_data_param, // p_data
2998 arr_data_mask_param);
3000 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3001 param, G_DBUS_CALL_FLAGS_NONE,
3005 ERR("scan_filter_add_remove Fail: %s", error->message);
3006 g_clear_error(&error);
3007 return BT_STATUS_FAIL;
3011 g_variant_unref(ret);
3013 g_array_free(arr_uuid, TRUE);
3014 g_array_free(arr_uuid_mask, TRUE);
3016 return BT_STATUS_SUCCESS;
3019 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3021 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3022 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3024 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3025 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3027 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3028 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3029 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3030 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3031 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3032 NULL, 0, TRUE, NULL, NULL);
3033 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3034 NULL, 0, TRUE, NULL, NULL);
3036 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3037 client_if, // client_if
3038 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3039 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3040 filt_index, // filter_index
3041 company_id, // company_id
3042 company_id_mask, // company_id_mask
3043 arr_uuid_param, // p_uuid
3044 arr_uuid_mask_param, // p_uuid_mask
3046 addr_type, // address_type
3047 arr_data_param, // p_data
3048 arr_data_mask_param);
3050 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3051 G_DBUS_CALL_FLAGS_NONE,
3055 ERR("scan_filter_add_remove Fail: %s", error->message);
3056 g_clear_error(&error);
3057 return BT_STATUS_FAIL;
3061 g_variant_unref(ret);
3063 g_array_free(arr_uuid, TRUE);
3064 g_array_free(arr_uuid_mask, TRUE);
3066 return BT_STATUS_SUCCESS;
3069 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3071 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3072 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3074 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3075 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3077 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3078 NULL, 0, TRUE, NULL, NULL);
3079 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3080 NULL, 0, TRUE, NULL, NULL);
3081 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3082 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3083 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3084 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3086 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3087 client_if, // client_if
3088 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3089 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3090 filt_index, // filter_index
3091 company_id, // company_id
3092 company_id_mask, // company_id_mask
3093 arr_uuid_param, // p_uuid
3094 arr_uuid_mask_param, // p_uuid_mask
3096 addr_type, // address_type
3097 arr_data_param, // p_data
3098 arr_data_mask_param);
3100 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3101 G_DBUS_CALL_FLAGS_NONE,
3105 ERR("scan_filter_add_remove Fail: %s", error->message);
3106 g_clear_error(&error);
3107 return BT_STATUS_FAIL;
3111 g_variant_unref(ret);
3113 g_array_free(arr_data, TRUE);
3114 g_array_free(arr_data_mask, TRUE);
3116 return BT_STATUS_SUCCESS;
3119 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3121 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3122 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3124 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3125 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3127 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3128 NULL, 0, TRUE, NULL, NULL);
3129 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3130 NULL, 0, TRUE, NULL, NULL);
3131 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3132 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3133 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3134 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3136 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3137 client_if, // client_if
3138 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3139 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3140 filt_index, // filter_index
3141 company_id, // company_id
3142 company_id_mask, // company_id_mask
3143 arr_uuid_param, // p_uuid
3144 arr_uuid_mask_param, // p_uuid_mask
3146 addr_type, // address_type
3147 arr_data_param, // p_data
3148 arr_data_mask_param);
3150 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3151 G_DBUS_CALL_FLAGS_NONE,
3155 ERR("scan_filter_add_remove Fail: %s", error->message);
3156 g_clear_error(&error);
3157 return BT_STATUS_FAIL;
3161 g_variant_unref(ret);
3163 g_array_free(arr_data, TRUE);
3164 g_array_free(arr_data_mask, TRUE);
3166 return BT_STATUS_SUCCESS;
3169 return BT_STATUS_UNSUPPORTED;
3172 /** Clear all scan filter conditions for specific filter index*/
3173 bt_status_t scan_filter_clear(int client_if, int filt_index)
3176 GError *error = NULL;
3178 CHECK_BTGATT_INIT();
3180 proxy = _bt_hal_get_adapter_proxy();
3182 return BT_STATUS_FAIL;
3184 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3185 g_variant_new("(ii)", client_if, filt_index),
3186 G_DBUS_CALL_FLAGS_NONE,
3190 ERR("scan_filter_clear Fail: %s", error->message);
3191 g_clear_error(&error);
3192 return BT_STATUS_FAIL;
3195 g_variant_unref(ret);
3196 return BT_STATUS_SUCCESS;
3199 /** Enable / disable scan filter feature*/
3200 bt_status_t scan_filter_enable(int client_if, bool enable)
3203 GError *error = NULL;
3205 CHECK_BTGATT_INIT();
3207 proxy = _bt_hal_get_adapter_proxy();
3209 return BT_STATUS_FAIL;
3211 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3212 g_variant_new("(ib)", client_if, enable),
3213 G_DBUS_CALL_FLAGS_NONE,
3217 ERR("scan_filter_enable Fail: %s", error->message);
3218 g_clear_error(&error);
3219 return BT_STATUS_FAIL;
3221 g_variant_unref(ret);
3223 return BT_STATUS_SUCCESS;
3226 /** Sets the LE scan interval and window in units of N*0.625 msec */
3228 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3232 CHECK_BTGATT_INIT();
3234 le_scan_type = scan_type;
3235 ret = _bt_hal_adapter_le_set_scan_parameters(
3236 scan_type, scan_interval, scan_window);
3240 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3242 CHECK_BTGATT_INIT();
3243 return BT_STATUS_UNSUPPORTED;
3247 /* Configure the batchscan storage */
3248 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3249 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3251 CHECK_BTGATT_INIT();
3252 return BT_STATUS_UNSUPPORTED;
3255 /* Enable batchscan */
3256 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3257 int scan_interval, int scan_window, int addr_type, int discard_rule)
3259 CHECK_BTGATT_INIT();
3260 return BT_STATUS_UNSUPPORTED;
3263 /* Disable batchscan */
3264 bt_status_t batchscan_dis_batch_scan(int client_if)
3266 CHECK_BTGATT_INIT();
3267 return BT_STATUS_UNSUPPORTED;
3270 /* Read out batchscan reports */
3271 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3273 CHECK_BTGATT_INIT();
3274 return BT_STATUS_UNSUPPORTED;
3277 bt_status_t btif_gatt_get_data_batching_available_packets(unsigned int *available_packets)
3280 GError *error = NULL;
3282 guint32 available_pkts;
3284 CHECK_BTGATT_INIT();
3286 if (available_packets == NULL) {
3287 ERR("available_packets is NULL");
3288 return BT_STATUS_PARM_INVALID;
3291 proxy = _bt_hal_get_adapter_proxy();
3292 if (proxy == NULL) {
3293 ERR("proxy is NULL");
3294 return BT_STATUS_FAIL;
3297 ret = g_dbus_proxy_call_sync(proxy, "GetLeBatchingAvailablePkts",
3299 G_DBUS_CALL_FLAGS_NONE,
3302 int result = BT_STATUS_FAIL;
3304 ERR("SetLeBatchingParam Fail: %s", error->message);
3305 if (g_strrstr(error->message, "Operation is not supported"))
3306 result = BT_STATUS_UNSUPPORTED;
3308 g_clear_error(&error);
3311 g_variant_get(ret, "(u)", &available_pkts);
3312 g_variant_unref(ret);
3314 INFO("GATT Batching available packets: %u", available_pkts);
3315 *available_packets = available_pkts;
3316 return BT_STATUS_SUCCESS;
3319 bt_status_t btif_gatt_enable_data_batching(const bt_bdaddr_t *bd_addr, int packet_threshold, int timeout)
3321 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3323 GError *error = NULL;
3325 CHECK_BTGATT_INIT();
3327 if (bd_addr == NULL) {
3328 ERR("bd_addr is NULL");
3329 return BT_STATUS_PARM_INVALID;
3332 proxy = _bt_hal_get_adapter_proxy();
3333 if (proxy == NULL) {
3334 ERR("proxy is NULL");
3335 return BT_STATUS_FAIL;
3338 _bt_hal_convert_addr_type_to_string(device_address,
3339 (unsigned char *)bd_addr->address);
3340 ret = g_dbus_proxy_call_sync(proxy, "EnableLeBatching",
3341 g_variant_new("(sii)", device_address, packet_threshold, timeout),
3342 G_DBUS_CALL_FLAGS_NONE,
3345 int result = BT_STATUS_FAIL;
3347 ERR("SetLeBatchingParam Fail: %s", error->message);
3348 if (g_strrstr(error->message, "Operation is not supported"))
3349 result = BT_STATUS_UNSUPPORTED;
3350 else if (g_strrstr(error->message, "Invalid arguments"))
3351 result = BT_STATUS_PARM_INVALID;
3353 g_clear_error(&error);
3356 g_variant_unref(ret);
3358 INFO("GATT Batching is enabled");
3359 return BT_STATUS_SUCCESS;
3362 bt_status_t btif_gatt_disable_data_batching(const bt_bdaddr_t *bd_addr)
3364 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3366 GError *error = NULL;
3368 CHECK_BTGATT_INIT();
3370 if (bd_addr == NULL) {
3371 ERR("bd_addr is NULL");
3372 return BT_STATUS_PARM_INVALID;
3375 proxy = _bt_hal_get_adapter_proxy();
3376 if (proxy == NULL) {
3377 ERR("proxy is NULL");
3378 return BT_STATUS_FAIL;
3381 _bt_hal_convert_addr_type_to_string(device_address,
3382 (unsigned char *)bd_addr->address);
3383 ret = g_dbus_proxy_call_sync(proxy, "DisableLeBatching",
3384 g_variant_new("(s)", device_address),
3385 G_DBUS_CALL_FLAGS_NONE,
3388 int result = BT_STATUS_FAIL;
3390 ERR("SetLeBatching Fail: %s", error->message);
3391 if (g_strrstr(error->message, "Operation is not supported"))
3392 result = BT_STATUS_UNSUPPORTED;
3394 g_clear_error(&error);
3397 g_variant_unref(ret);
3399 INFO("GATT Batching is disabled");
3400 return BT_STATUS_SUCCESS;
3403 const btgatt_client_interface_t btgatt_client_interface = {
3404 .register_client = btif_gattc_register_client,
3405 .unregister_client = btif_gattc_unregister_client,
3407 .connect = btif_gattc_client_connect,
3408 .disconnect = btif_gattc_client_disconnect,
3410 .search_service = btif_gattc_client_search_service,
3411 .get_included_service = get_included_service,
3412 .get_characteristic = btif_gattc_get_characteristic,
3413 .get_descriptor = btif_gattc_get_descriptor,
3414 .read_characteristic = btif_read_characteristic,
3415 .write_characteristic = btif_write_characteristic,
3416 .acquire_write = btif_get_acquire_write_fd,
3417 .acquire_notify = btif_get_acquire_notify_fd,
3418 .read_descriptor = btif_read_descriptor,
3419 .write_descriptor = btif_write_descriptor,
3420 .execute_write = execute_write,
3421 .register_for_notification = btif_register_for_notification,
3422 .deregister_for_notification = btif_deregister_for_notification,
3423 .read_remote_rssi = read_remote_rssi,
3424 .ota_fw_update = ota_fw_update,
3425 .get_device_type = get_device_type,
3426 .conn_parameter_update = btif_gattc_conn_parameter_update,
3427 .test_command = test_command,
3428 .configure_mtu = configure_mtu,
3429 .scan_filter_param_setup = scan_filter_param_setup,
3430 .scan_filter_add_remove = scan_filter_add_remove,
3431 .scan_filter_clear = scan_filter_clear,
3432 .scan_filter_enable = scan_filter_enable,
3433 .set_scan_parameters = set_scan_parameters,
3434 .batchscan_cfg_storage = batchscan_cfg_storage,
3435 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3436 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3437 .batchscan_read_reports = batchscan_read_reports,
3438 .add_connection_info = btif_gattc_add_connection_info,
3439 .get_data_batching_available_packets = btif_gatt_get_data_batching_available_packets,
3440 .enable_data_batching = btif_gatt_enable_data_batching,
3441 .disable_data_batching = btif_gatt_disable_data_batching,
3444 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3447 hal_gattc_server_info_t *info = NULL;
3449 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3450 info = (hal_gattc_server_info_t*)l->data;
3454 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3461 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3464 hal_gattc_client_info_t *info = NULL;
3466 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3467 info = (hal_gattc_client_info_t*)l->data;
3471 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3478 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3481 hal_gattc_client_info_t *info = NULL;
3483 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3484 info = (hal_gattc_client_info_t*)l->data;
3488 if (info->conn_id == conn_id)
3495 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3498 hal_gattc_server_info_t *info = NULL;
3499 hal_gattc_client_info_t *gattc_client = NULL;
3501 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3502 if (gattc_client == NULL) {
3503 ERR("GATT client conn info not found");
3507 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3508 info = (hal_gattc_server_info_t*)l->data;
3512 if ((info->inst_id == gattc_client->inst_id) &&
3513 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3520 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3521 gboolean auto_connect)
3523 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3524 gchar *device_path = NULL;
3525 GDBusProxy *device_proxy = NULL;
3526 GDBusConnection *conn;
3527 int ret = BT_STATUS_SUCCESS;
3528 hal_gattc_client_info_t *gattc_data;
3530 if (NULL == bd_addr) {
3531 ERR("bd_addr is NULL");
3532 return BT_STATUS_PARM_INVALID;
3535 conn = _bt_hal_get_system_gconn();
3537 ERR("_bt_gdbus_get_system_gconn returned NULL");
3538 return BT_STATUS_FAIL;
3541 _bt_hal_convert_addr_type_to_string(device_address,
3542 (unsigned char *)bd_addr->address);
3543 device_path = _bt_hal_get_device_object_path(device_address);
3544 if (device_path == NULL) {
3545 ERR("device_path NULL : [%s]", device_address);
3546 ret = BT_STATUS_FAIL;
3550 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3551 NULL, BT_HAL_BLUEZ_NAME,
3552 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3553 g_free(device_path);
3554 if (NULL == device_proxy) {
3555 ERR("device_proxy returned NULL");
3556 return BT_STATUS_FAIL;
3559 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3560 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3561 BT_HAL_ADDRESS_LENGTH_MAX);
3563 DBG("ConnectLE [%s]", device_address);
3565 gattc_data->client_if = client_if;
3567 g_dbus_proxy_call(device_proxy, "ConnectLE",
3568 g_variant_new("(b)", auto_connect),
3569 G_DBUS_CALL_FLAGS_NONE,
3570 BT_HAL_MAX_DBUS_TIMEOUT,
3572 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3577 static bt_status_t _bt_hold_current_advertising()
3579 int ret = BT_STATUS_FAIL;
3580 gboolean is_advertising = FALSE;
3583 if (_bt_hal_is_support_multi_adv() == TRUE) {
3584 DBG("VSC adv used");
3585 return BT_STATUS_SUCCESS;
3588 /* Dependent on Kernel operation. Hold adv to prevent stopping adv on kernel */
3589 is_advertising = _bt_hal_is_advertising_in_slot(0);
3590 if (is_advertising) {
3591 DBG("+ Stop current advertising");
3593 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3594 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3600 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3602 DBG("+ start current advertising");
3604 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3609 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3611 DBG("Try to initiate pending LE connection");
3613 pending_le_conn_timer_id = 0;
3615 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3616 &pending_le_conn_info->bd_addr,
3617 pending_le_conn_info->auto_connect);
3619 g_free(pending_le_conn_info);
3620 pending_le_conn_info = NULL;
3625 static int __hal_generate_conn_id()
3627 return ++hal_gatt_conn_id;
3630 static int __hal_generate_server_instance_id()
3632 return ++bt_inst_id;
3635 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3638 GError *g_error = NULL;
3639 GVariant *reply = NULL;
3640 hal_gattc_client_info_t *gattc_data = user_data;
3641 int result = BT_STATUS_SUCCESS;
3642 struct hal_ev_gatt_client_connected ev;
3643 hal_gattc_server_info_t *gatt_conn_info = NULL;
3645 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3646 g_object_unref(proxy);
3647 if (reply == NULL) {
3648 ERR("Connect LE Dbus Call Error");
3650 ERR("Error: %s\n", g_error->message);
3651 g_clear_error(&g_error);
3653 result = BT_STATUS_FAIL;
3655 g_variant_unref(reply);
3657 if (NULL == gattc_data) {
3658 ERR("gattc_data is NULL");
3663 if (result == BT_STATUS_FAIL) {
3664 memset(&ev, 0, sizeof(ev));
3667 ev.client_if = gattc_data->client_if;
3668 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3669 BT_HAL_ADDRESS_LENGTH_MAX);
3672 ERR("gatt client callback not registered");
3674 DBG("sending gatt client connected event");
3675 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3681 DBG("LE connected. Adding the gattc server/client conn info in list");
3682 gattc_data->conn_id = __hal_generate_conn_id() ;
3683 gattc_data->inst_id = __hal_generate_server_instance_id();
3685 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3687 /*add gatt server connection info*/
3688 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3689 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3690 gatt_conn_info->conn_id = gattc_data->conn_id;
3691 gatt_conn_info->inst_id = gattc_data->inst_id;
3692 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3697 /*remove conn_info*/
3702 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3704 g_free(desc_info->desc_path);
3708 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3711 hal_gattc_desc_t *desc_info = NULL;
3712 for (l = char_info->gatt_list_descs; l != NULL; ) {
3713 desc_info = l->data;
3714 l = g_slist_next(l);
3715 if (desc_info == NULL)
3717 /* Remove descriptor element */
3718 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3719 __hal_gattc_free_desc_info(desc_info);
3721 g_slist_free(char_info->gatt_list_descs);
3722 g_free(char_info->chr_path);
3726 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3729 hal_gattc_char_t *char_info = NULL;
3730 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3731 char_info = l->data;
3732 l = g_slist_next(l);
3733 if (char_info == NULL)
3735 /* Remove characteristic element */
3736 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3737 __hal_gattc_free_char_info(char_info);
3739 g_slist_free(svc_info->gatt_list_chars);
3740 g_free(svc_info->svc_path);
3744 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3747 hal_gattc_service_t *svc_info = NULL;
3751 for (l = conn_info->gatt_list_services; l != NULL; ) {
3752 svc_info = (hal_gattc_service_t *)l->data;
3753 l = g_slist_next(l);
3754 if (svc_info == NULL)
3756 /* Remove service element */
3757 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3758 __hal_gattc_free_svc_info(svc_info);
3760 g_slist_free(conn_info->gatt_list_services);
3764 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3766 bt_bdaddr_t bd_addr;
3767 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3768 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3774 int _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3776 int result = BT_STATUS_SUCCESS;
3777 struct hal_ev_gatt_client_connected ev;
3778 hal_gattc_server_info_t *conn_info = NULL;
3779 bt_bdaddr_t bd_addr;
3781 hal_gattc_client_info_t *gattc_client = NULL;
3784 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3785 HAL_EV_GATT_CLIENT_DISCONNECTED;
3787 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3788 /* find the gatt client info */
3789 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3790 if (NULL == gattc_client) {
3791 ERR("Fail to get gatt client info");
3795 gattc_client->is_gatt_connected = gatt_connected;
3798 memset(&ev, 0, sizeof(ev));
3799 ev.conn_id = gattc_client->conn_id;
3801 ev.client_if = gattc_client->client_if;
3802 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3803 BT_HAL_ADDRESS_LENGTH_MAX);
3806 ERR("gatt client callback not registered");
3808 event_cb(event, (void *)&ev, sizeof(ev));
3811 if (!gatt_connected) {
3812 inst_id = gattc_client->inst_id;
3814 /* remove the gatt client info from the client list also*/
3815 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3816 g_free(gattc_client);
3818 //find the connected server info
3819 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3820 if (NULL == conn_info) {
3821 ERR("Fail to get gatt server info");
3825 if (inst_id != conn_info->inst_id) {
3826 ERR("server instance is different");
3830 //remove gatt conn info from the server list
3831 DBG("remove the server conn_info from list after gatt disconnection");
3832 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3833 __hal_clean_gattc_server_info(conn_info);
3839 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3840 const char* uuid_str, int inst_id)
3842 struct hal_ev_gatt_client_search_result ev;
3845 ERR("gatt client callback not registered");
3849 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3851 memset(&ev, 0, sizeof(ev));
3852 ev.conn_id = conn_id;
3853 ev.inst_id = inst_id;
3854 ev.is_primary = is_primary;
3855 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3857 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3860 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3862 struct hal_ev_gatt_client_search_complete ev;
3865 ERR("gatt client callback not registered");
3869 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3872 memset(&ev, 0, sizeof(ev));
3873 ev.conn_id = conn_id;
3876 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3879 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3880 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3881 char *char_value, int len)
3883 struct hal_ev_gatt_client_notify_changed_value ev;
3884 hal_gattc_client_info_t *gattc_client = NULL;
3887 ERR("gatt client callback not registered");
3891 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3892 if (NULL == gattc_client) {
3893 ERR("failed to get the gatt client info");
3898 DBG("sending gatt client connected status event");
3899 memset(&ev, 0, sizeof(ev));
3901 ev.conn_id = gattc_client->conn_id;
3902 ev.inst_id = conn_info->inst_id;
3903 ev.is_primary = svc_info->is_primary;
3904 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3905 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3907 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3909 if (len > 0 && (char_value != NULL)) {
3910 memcpy(ev.value, char_value, len);
3914 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3917 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3918 char *char_value, int len)
3920 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3921 hal_gattc_server_info_t *conn_info = NULL;
3922 bt_bdaddr_t bd_addr;
3925 hal_gattc_service_t *svc_info = NULL;
3926 hal_gattc_char_t *char_info = NULL;
3930 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3931 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3932 DBG("device address:[%s]", device_address);
3933 DBG("char handle:[%s]", char_handle);
3935 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3936 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3938 if (conn_info != NULL) {
3939 //find service for notified char path
3940 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3941 svc_info = (hal_gattc_service_t*)l->data;
3942 if (svc_info == NULL)
3945 /* find characteristic object path */
3946 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3947 char_info = (hal_gattc_char_t *)k->data;
3948 if (char_info == NULL)
3951 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3952 DBG("Found char handle[%s]", char_info->chr_path);
3955 _bt_hal_send_value_changed_event(conn_info, svc_info,
3956 char_info, char_value, len);
3964 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3966 GDBusConnection *g_conn = NULL;
3967 GDBusProxy *properties_proxy = NULL;
3968 GVariant *result = NULL;
3969 GError *error = NULL;
3970 GVariantIter *property_iter = NULL;
3971 const gchar *key = NULL;
3972 GVariant *value = NULL;
3973 const char *uuid_str = NULL;
3975 gboolean is_primary = FALSE;
3976 GVariantIter *char_iter = NULL;
3977 const char *char_handle = NULL;
3978 GPtrArray *gp_char_array = NULL;
3980 if (service_path == NULL) {
3981 ERR("service_path is NULL");
3982 return BT_STATUS_FAIL;
3985 DBG("service_path: %s", service_path);
3987 g_conn = _bt_hal_get_system_gconn();
3988 if (g_conn == NULL) {
3989 ERR("g_conn is NULL");
3990 return BT_STATUS_FAIL;
3993 properties_proxy = g_dbus_proxy_new_sync(g_conn,
3994 G_DBUS_PROXY_FLAGS_NONE, NULL,
3997 BT_HAL_PROPERTIES_INTERFACE,
3999 if (properties_proxy == NULL) {
4000 ERR("properties_proxy is NULL");
4001 return BT_STATUS_FAIL;
4004 result = g_dbus_proxy_call_sync(properties_proxy,
4006 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
4007 G_DBUS_CALL_FLAGS_NONE,
4009 if (result == NULL) {
4010 if (error != NULL) {
4011 ERR("Fail to get properties (Error: %s)", error->message);
4012 g_clear_error(&error);
4014 ERR("Fail to get properties");
4016 g_object_unref(properties_proxy);
4017 return BT_STATUS_FAIL;
4020 g_variant_get(result, "(a{sv})", &property_iter);
4022 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
4023 if (g_strcmp0(key, "UUID") == 0) {
4024 uuid_str = g_variant_get_string(value, &len);
4025 } else if (g_strcmp0(key, "Primary") == 0) {
4026 is_primary = g_variant_get_boolean(value);
4027 } else if (g_strcmp0(key, "Characteristics") == 0) {
4028 g_variant_get(value, "ao", &char_iter);
4029 if (char_iter != NULL) {
4030 if (gp_char_array == NULL)
4031 gp_char_array = g_ptr_array_new();
4033 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
4034 DBG("char_handle: %s", char_handle);
4035 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
4037 g_variant_iter_free(char_iter);
4042 if (uuid_str == NULL || gp_char_array == NULL) {
4043 ERR("uuid_str and gp_char_array should be set");
4047 /* Create new service */
4048 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
4051 g_variant_iter_free(property_iter);
4052 g_variant_unref(result);
4053 g_object_unref(properties_proxy);
4055 return BT_STATUS_SUCCESS;
4058 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
4060 GDBusConnection *conn = NULL;
4061 GDBusProxy *proxy = NULL;
4063 GVariant *ret = NULL;
4064 GVariant *value = NULL;
4066 conn = _bt_hal_get_system_gconn();
4068 ERR("_bt_gdbus_get_system_gconn returned NULL");
4072 proxy = g_dbus_proxy_new_sync(conn,
4073 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
4074 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
4075 if (proxy == NULL) {
4076 ERR("device_proxy returned NULL");
4080 ret = g_dbus_proxy_call_sync(proxy, "Get",
4081 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
4082 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
4084 ERR("DBus Error : %s", err->message);
4085 g_clear_error(&err);
4087 g_variant_get(ret, "(v)", &value);
4088 *service_uuid = g_variant_dup_string(value, NULL);
4089 g_variant_unref(value);
4090 g_variant_unref(ret);
4094 g_object_unref(proxy);
4099 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
4101 struct hal_ev_gatt_client_service_changed ev = {0, };
4102 char address[BT_HAL_ADDRESS_STRING_SIZE];
4103 hal_gattc_server_info_t *server_info = NULL;
4104 hal_gattc_client_info_t *gattc_client = NULL;
4105 hal_gattc_service_t *service = NULL;
4106 GSList *list = NULL;
4107 char *uuid_str = NULL;
4109 _bt_hal_convert_device_path_to_address(path, address);
4110 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
4111 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
4112 if (server_info == NULL) {
4113 ERR("server_info is NULL");
4117 gattc_client = __bt_find_gatt_client_info((bt_bdaddr_t *)ev.bdaddr);
4118 if (gattc_client == NULL) {
4119 ERR("gattc_client is NULL");
4123 if (server_info->is_gatt_connected == FALSE && gattc_client->is_gatt_connected == FALSE) {
4124 DBG("GattConnected signal is not received yet. Just skip [%d %d]",
4125 server_info->is_gatt_connected, gattc_client->is_gatt_connected);
4130 /* Get service UUID from path */
4131 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
4133 INFO("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
4134 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
4137 ERR("uuid_str is NULL");
4141 /* Create new service and append into the list */
4142 __hal_gattc_get_service_info(server_info, path);
4144 /* Find service UUID from path */
4145 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4146 service = (hal_gattc_service_t *)list->data;
4147 if (service == NULL)
4150 if (g_strcmp0(service->svc_path, path) == 0) {
4151 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4152 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4153 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4154 INFO("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
4156 /* Remove service info in list */
4157 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4158 __hal_gattc_free_svc_info(service);
4166 ERR("uuid_str is NULL");
4171 /* Send GATT Client service changed event */
4172 ev.change_type = is_added;
4173 ev.conn_id = server_info->conn_id;
4174 ev.inst_id = server_info->inst_id;
4175 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));