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;
134 bt_bdaddr_t bd_addr; /*remote server address*/
137 gboolean is_gatt_connected; /*status for GattConnected signal*/
138 } hal_gattc_client_info_t;
141 bt_bdaddr_t bd_addr; /* remote server address */
142 int conn_id; /* connection id */
143 int inst_id; /* server instance id */
144 gboolean is_gatt_connected; /* status for GattConnected signal */
145 int client_if; /* client id */
146 GSList *gatt_list_services;
147 } hal_gattc_conn_info_t;
150 * Remove this feature after verified.
151 * Remove hal_gattc_client/server_info_t and use hal_gattc_conn_info_t
152 * Remove hal_gattc_client/server_info_list and use hal_gattc_conn_info_list
154 #define __INTEGRATE_HAL_GATT_INFO__
155 #ifndef __INTEGRATE_HAL_GATT_INFO__
156 /* Linked List of connected GATT server */
157 static GSList *hal_gattc_server_info_list = NULL;
158 /* Linked list of connected GATT client connection */
159 static GSList *hal_gattc_client_info_list = NULL;
161 static GSList *hal_gattc_conn_info_list = NULL;
162 #define hal_gattc_server_info_t hal_gattc_conn_info_t
163 #define hal_gattc_client_info_t hal_gattc_conn_info_t
164 #define hal_gattc_server_info_list hal_gattc_conn_info_list
165 #define hal_gattc_client_info_list hal_gattc_conn_info_list
168 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
169 static guint pending_le_conn_timer_id = 0;
170 int hal_gatt_conn_id = 0;
171 static int bt_inst_id = 0;
173 /* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
174 /* TODO: Adjust MAX Client after modifying MAX app handle logic */
175 #define BT_GATTC_CL_MAX 11
177 static int assigned_if = 0;
178 static gboolean client_if_used[BT_GATTC_CL_MAX];
183 btgatt_srvc_id_t srvc_id;
184 btgatt_gatt_id_t char_id;
185 btgatt_gatt_id_t desc_id;
186 } hal_gatt_resp_data_t;
191 } hal_gatt_client_app;
193 static GSList * hal_gattc_client_app_list = NULL;
200 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
201 gboolean auto_connect);
202 static bt_status_t _bt_hold_current_advertising();
203 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
204 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
205 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
207 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
208 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
209 const char* uuid_str, int inst_id);
210 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
211 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr);
212 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
213 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
215 void _bt_hal_gatt_client_init(void)
218 memset(client_if_used, 0x00, sizeof(client_if_used));
221 static int __bt_hal_gatt_assign_if(void)
225 index = assigned_if + 1;
227 if (index >= BT_GATTC_CL_MAX)
230 while (client_if_used[index] == TRUE) {
231 if (index == assigned_if) {
232 /* No available ID */
233 ERR("All interface ID is used");
239 if (index >= BT_GATTC_CL_MAX)
244 client_if_used[index] = TRUE;
249 static void __bt_hal_gatt_delete_if(int client_if)
251 if (client_if >= BT_GATTC_CL_MAX || client_if < 0)
254 client_if_used[client_if] = FALSE;
258 /* To send stack event to hal-av handler */
259 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
264 void _bt_hal_unregister_gatt_client_handler_cb(void)
270 int _bt_hal_gatt_client_get_le_scan_type(void)
276 static gboolean __bt_hal_register_client_cb(gpointer user_data)
278 struct hal_ev_gatt_client_registered ev;
279 hal_gatt_client_app *client_info = user_data;
281 /* Prepare to send AV connecting event */
282 memset(&ev, 0, sizeof(ev));
283 ev.status = BT_STATUS_SUCCESS;
284 ev.client_if = client_info->client_if;
285 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
288 ERR("GATT Callback not registered");
290 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
291 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
298 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
302 hal_gatt_client_app *info = NULL;
303 hal_gatt_client_app *gattc_app = NULL;
305 //check if client app is already registered
306 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
307 info = (hal_gatt_client_app*)l->data;
311 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
312 DBG("gatt client app already registered");
317 client_if = __bt_hal_gatt_assign_if();
318 if (client_if == -1) {
319 ERR("Fail to allocate the client if");
323 DBG("adding the gatt client app");
326 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
327 gattc_app->client_if = client_if;
328 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
330 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
335 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
337 hal_gatt_client_app *gattc_app = NULL;
338 hal_gatt_client_app *client_app_info = NULL;
340 /* add gatt client in list */
341 gattc_app = __hal_gattc_add_client_app(app_uuid);
342 if (gattc_app == NULL) {
343 ERR("Failed to register gatt client app");
344 return BT_STATUS_FAIL;
348 client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
349 client_app_info->client_if = gattc_app->client_if;
350 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
351 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
353 DBG("registered client client_if [%d]", client_app_info->client_if);
355 return BT_STATUS_SUCCESS;
358 /** Registers a GATT client application with the stack */
359 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
363 return __hal_gattc_register_client_app(uuid);
366 bt_status_t btif_gattc_add_connection_info(const bt_bdaddr_t *bd_addr, int conn_id, int server_inst_id)
368 #ifndef __INTEGRATE_HAL_GATT_INFO__
369 hal_gattc_client_info_t *client_info = NULL;
371 hal_gattc_server_info_t *server_info = NULL;
373 #ifndef __INTEGRATE_HAL_GATT_INFO__
374 /* Add client connection info in list */
375 client_info = g_malloc0(sizeof(hal_gattc_client_info_t));
376 client_info->client_if = -1;
377 memcpy(client_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
378 client_info->conn_id = conn_id;
379 client_info->inst_id = server_inst_id;
380 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, client_info);
381 DBG("Added client connection info in list");
384 /* Add server connection info in list */
385 server_info = __bt_find_gatt_conn_info(bd_addr);
386 if (server_info == NULL) {
387 server_info = g_malloc0(sizeof(hal_gattc_server_info_t));
388 memcpy(server_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
389 server_info->conn_id = conn_id;
390 server_info->inst_id = server_inst_id;
391 server_info->is_gatt_connected = TRUE;
392 #ifdef __INTEGRATE_HAL_GATT_INFO__
393 server_info->client_if = -1;
395 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, server_info);
396 DBG("Added server connection info in list");
399 return BT_STATUS_SUCCESS;
402 bt_status_t __hal_gattc_unregister_client(int client_if)
405 hal_gatt_client_app *info = NULL;
406 gboolean is_deleted = FALSE;
409 client_count = g_slist_length(hal_gattc_client_app_list);
411 /* remove the gatt client app */
412 for (l = hal_gattc_client_app_list; l != NULL; ) {
413 info = (hal_gatt_client_app*)l->data;
419 if (info->client_if == client_if) {
420 __bt_hal_gatt_delete_if(client_if);
422 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
428 DBG("Deleted. registered client count: [%d -> %d]", client_count, g_slist_length(hal_gattc_client_app_list));
430 ERR("Not deleted. registered client count: [%d]", client_count);
432 return BT_STATUS_SUCCESS;
435 /** Unregister a client application from the stack */
436 bt_status_t btif_gattc_unregister_client(int client_if)
440 return __hal_gattc_unregister_client(client_if);
443 /** Start or stop LE device scanning */
444 bt_status_t scan(int client_if, bool start)
451 ret = _bt_hal_adapter_le_start_scan();
453 ret = _bt_hal_adapter_le_stop_scan();
458 /** Create a connection to a remote LE or dual-mode device */
459 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
462 int ret = BT_STATUS_SUCCESS;
467 return BT_STATUS_PARM_INVALID;
469 ret = _bt_hold_current_advertising();
470 if (ret == BT_STATUS_SUCCESS) {
471 DBG("Current advertising is held");
472 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
473 pending_le_conn_info->client_if = client_if;
474 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
475 BT_HAL_ADDRESS_LENGTH_MAX);
476 pending_le_conn_info->auto_connect = is_direct;
478 pending_le_conn_timer_id =
479 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
481 return BT_STATUS_SUCCESS;
483 ERR("advertising is not stopped");
486 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
490 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
493 GError *g_error = NULL;
494 GVariant *reply = NULL;
495 hal_gattc_client_info_t *gatt_conn_info = user_data;
496 int result = BT_STATUS_SUCCESS;
497 struct hal_ev_gatt_client_connected ev;
501 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
502 g_object_unref(proxy);
504 ERR("Connect LE Dbus Call Error");
506 ERR("Error: %s\n", g_error->message);
507 g_clear_error(&g_error);
509 result = BT_STATUS_FAIL;
511 g_variant_unref(reply);
513 if (NULL == gatt_conn_info) {
514 ERR("server_data is NULL");
519 if (result == BT_STATUS_FAIL) {
520 memset(&ev, 0, sizeof(ev));
521 ev.conn_id = gatt_conn_info->conn_id;
523 ev.client_if = gatt_conn_info->client_if;
524 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
525 BT_HAL_ADDRESS_LENGTH_MAX);
528 ERR("gatt client callback not registered");
530 DBG("sending gatt client disconnected event");
531 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
537 g_free(gatt_conn_info);
542 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
545 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
547 GDBusProxy *device_proxy;
548 GDBusConnection *conn;
549 int ret = BT_STATUS_SUCCESS;
550 hal_gattc_client_info_t *gattc_data;
552 if (NULL == bd_addr) {
553 ERR("bd_addr is NULL");
554 return BT_STATUS_PARM_INVALID;
557 conn = _bt_hal_get_system_gconn();
559 ERR("_bt_gdbus_get_system_gconn returned NULL");
560 return BT_STATUS_FAIL;
563 _bt_hal_convert_addr_type_to_string(device_address,
564 (unsigned char *)bd_addr->address);
565 device_path = _bt_hal_get_device_object_path(device_address);
566 if (device_path == NULL) {
567 DBG("device_path NULL");
568 ret = BT_STATUS_FAIL;
572 ERR("device_path:%s", device_path);
574 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
575 NULL, BT_HAL_BLUEZ_NAME,
576 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
578 if (NULL == device_proxy) {
579 ERR("device_proxy returned NULL");
580 return BT_STATUS_FAIL;
583 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
584 memcpy(gattc_data->bd_addr.address, bd_addr->address,
585 BT_HAL_ADDRESS_LENGTH_MAX);
586 gattc_data->client_if = client_if;
587 gattc_data->conn_id = conn_id;
589 DBG("DisconnectLE [%s]", device_address);
591 g_dbus_proxy_call(device_proxy, "DisconnectLE",
593 G_DBUS_CALL_FLAGS_NONE,
594 BT_HAL_MAX_DBUS_TIMEOUT,
596 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
600 /** Disconnect a remote device or cancel a pending connection */
601 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
606 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
609 /** Clear the attribute cache for a given device */
610 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
613 return BT_STATUS_UNSUPPORTED;
616 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
619 hal_gattc_service_t *info = NULL;
621 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
622 info = (hal_gattc_service_t*)l->data;
626 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t)))
634 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
635 bt_gatt_characteristic_property_t prop)
638 hal_gattc_char_t *info = NULL;
640 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
641 info = (hal_gattc_char_t*)l->data;
645 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
646 (info->permission & prop)) {
653 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
656 hal_gattc_char_t *info = NULL;
658 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
659 info = (hal_gattc_char_t*)l->data;
663 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
664 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
665 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
672 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
675 hal_gattc_desc_t *info = NULL;
677 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
678 info = (hal_gattc_desc_t*)l->data;
682 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t)))
689 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
690 const char *uuid_str, const char *object_path, int is_primary)
692 hal_gattc_service_t *gattc_service = NULL;
694 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
695 gattc_service->svc_path = g_strdup(object_path);
696 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
697 gattc_service->is_primary = is_primary;
699 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
700 INFO("Total svc [%d] Added [%s] [%s]", g_slist_length(conn_info->gatt_list_services), object_path + 15, uuid_str);
702 return gattc_service;
705 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
707 hal_gattc_char_t *gattc_char = NULL;
709 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
710 gattc_char->chr_path = g_strdup(char_handle);
712 DBG("[%s]", gattc_char->chr_path + 15);
714 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
717 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
718 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
720 hal_gattc_service_t* gatt_svc = NULL;
722 gchar *gp_char_path = NULL;
723 uint8_t uuid[BT_HAL_STACK_UUID_SIZE];
725 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
726 gatt_svc = _gattc_find_service_from_uuid(conn_info, (bt_uuid_t *)uuid);
728 DBG("Aleady added to gatt_list_services");
732 /* add the service */
733 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
734 if (gatt_svc == NULL) {
735 ERR("Failed to add service");
739 /* add the characteristic */
740 for (i = 0; i < gp_char_array->len; i++) {
741 gp_char_path = g_ptr_array_index(gp_char_array, i);
742 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
745 g_ptr_array_free(gp_char_array, TRUE);
748 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
750 hal_gattc_desc_t *gattc_desc = NULL;
752 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
753 gattc_desc->desc_path = g_strdup(desc_path);
755 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
758 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
759 GPtrArray *gp_desc_array, unsigned int char_permission)
761 gchar *gp_desc_path = NULL;
764 if (char_uuid_str == NULL) {
765 DBG("char_uuid_str is NULL");
769 //update the char uuid
770 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
772 //update char permission
773 gattc_char->permission = char_permission;
776 for (i = 0; i < gp_desc_array->len; i++) {
777 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
778 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
782 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
784 if (desc_uuid_str == NULL) {
785 DBG("char_uuid_str is NULL");
789 //update the descriptor uuid
790 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
792 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
795 static void browse_service_char(int conn_id)
797 hal_gattc_server_info_t *conn_info = NULL;
801 hal_gattc_service_t *svc_info = NULL;
802 hal_gattc_char_t *char_info = NULL;
803 hal_gattc_desc_t *desc_info = NULL;
805 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
806 if (conn_info == NULL) {
807 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
811 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
812 svc_info = (hal_gattc_service_t*)l->data;
813 if (svc_info == NULL)
816 /* find characteristic object path */
817 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
818 char_info = (hal_gattc_char_t *)k->data;
819 if (char_info == NULL)
823 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
824 desc_info = (hal_gattc_desc_t *)m->data;
825 if (desc_info == NULL)
835 * Enumerate all GATT services on a connected device.
836 * Optionally, the results can be filtered for a given UUID.
838 static bt_status_t _gattc_client_search_service(int conn_id)
842 GVariant *result = NULL;
844 GVariantIter *svc_iter;
845 GVariantIter *interface_iter;
846 char *object_path = NULL;
847 char *interface_str = NULL;
848 const gchar *key = NULL;
849 GVariant *value = NULL;
850 GPtrArray *gp_array = NULL;
851 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
852 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
853 int ret = BT_STATUS_FAIL;
855 const gchar *uuid_str = NULL;
857 hal_gattc_server_info_t *conn_info = NULL;
858 gboolean is_primary = FALSE;
861 char *char_handle = NULL;
862 GVariantIter *char_iter = NULL;
863 GPtrArray *gp_char_array = NULL;
865 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
866 if (NULL == conn_info) {
867 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
868 return BT_STATUS_FAIL;
872 // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
873 /* Check the service info is stored */
874 if (g_slist_length(conn_info->gatt_list_services) > 0) {
876 hal_gattc_service_t *svc_info = NULL;
877 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
878 DBG("Send event from service info list");
879 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
881 if (svc_info == NULL)
883 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
884 _bt_hal_send_search_service_result_event(conn_id,
885 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
887 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
888 return BT_STATUS_SUCCESS;
890 DBG("No stored service, request to bluez");
894 _bt_hal_convert_addr_type_to_string(device_address,
895 (unsigned char *)conn_info->bd_addr.address);
897 result = _bt_hal_get_managed_objects();
901 gp_array = g_ptr_array_new();
902 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
904 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
906 if (object_path == NULL)
909 _bt_hal_convert_device_path_to_address(object_path, temp_address);
911 if (g_strcmp0(temp_address, device_address) != 0)
914 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
915 &interface_str, &svc_iter)) {
916 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
919 DBG("[%d] %s", idx++, object_path + 15);
920 /* for characteristic */
921 gp_char_array = g_ptr_array_new();
922 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
923 if (g_strcmp0(key, "Primary") == 0) {
924 is_primary = g_variant_get_boolean(value);
926 g_ptr_array_add(gp_array, (gpointer)object_path);
929 } else if (g_strcmp0(key, "UUID") == 0) {
930 uuid_str = g_variant_get_string(value, &len);
931 } else if (g_strcmp0(key, "Characteristics") == 0) {
932 g_variant_get(value, "ao", &char_iter);
933 if (char_iter != NULL) {
934 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
935 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
942 _bt_hal_send_search_service_result_event(conn_id, is_primary,
943 uuid_str, conn_info->inst_id);
945 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
950 if (gp_array->len == 0 || svc_count == 0) {
951 ERR("gp_array is NULL");
952 ret = BT_STATUS_FAIL;
954 ret = BT_STATUS_SUCCESS;
957 browse_service_char(conn_id);
958 /* send search service complete event */
959 _bt_hal_send_search_service_complete_event(conn_id, ret);
961 g_ptr_array_free(gp_array, TRUE);
962 g_variant_iter_free(iter);
963 g_variant_unref(result);
968 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
970 if (NULL == filter_uuid) {
971 DBG("Browse all the services");
972 return _gattc_client_search_service(conn_id);
974 DBG("TODO implement it");
975 return BT_STATUS_UNSUPPORTED;
979 * Enumerate included services for a given service.
980 * Set start_incl_srvc_id to NULL to get the first included service.
982 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
983 btgatt_srvc_id_t *start_incl_srvc_id)
986 return BT_STATUS_UNSUPPORTED;
989 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
990 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
992 struct hal_ev_gatt_client_char_search_result ev;
995 ERR("gatt client callback not registered");
999 memset(&ev, 0, sizeof(ev));
1000 ev.conn_id = conn_id;
1001 ev.inst_id = svc_id->id.inst_id;
1002 ev.is_primary = svc_id->is_primary;
1004 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1006 if (status == BT_STATUS_SUCCESS) {
1007 /* building char uuid */
1008 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
1009 ev.char_prop = char_prop;
1012 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
1013 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1016 static int _hal_get_permission_flag(char *permission)
1020 if (NULL == permission) {
1021 ERR("gatt permission is NULL");
1025 if (!g_strcmp0(permission, "broadcast"))
1026 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
1027 else if (!g_strcmp0(permission, "read"))
1028 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
1029 else if (!g_strcmp0(permission, "write-without-response"))
1030 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1031 else if (!g_strcmp0(permission, "write"))
1032 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1033 else if (!g_strcmp0(permission, "notify"))
1034 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1035 else if (!g_strcmp0(permission, "indicate"))
1036 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
1037 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
1038 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
1039 else if (!g_strcmp0(permission, "reliable-write"))
1040 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
1041 else if (!g_strcmp0(permission, "writable-auxiliaries"))
1042 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1043 else if (!g_strcmp0(permission, "encrypt-read"))
1044 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1045 else if (!g_strcmp0(permission, "encrypt-write"))
1046 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1047 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1048 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1049 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1050 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1055 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1057 char perm[200] = { 0, };
1059 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1060 g_strlcat(perm, "broadcast ", sizeof(perm));
1061 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1062 g_strlcat(perm, "read ", sizeof(perm));
1063 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1064 g_strlcat(perm, "write-without-response ", sizeof(perm));
1065 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1066 g_strlcat(perm, "write ", sizeof(perm));
1067 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1068 g_strlcat(perm, "notify ", sizeof(perm));
1069 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1070 g_strlcat(perm, "indicate ", sizeof(perm));
1071 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1072 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1073 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1074 g_strlcat(perm, "reliable-write ", sizeof(perm));
1075 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1076 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1077 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1078 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1079 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1080 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1081 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1082 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1083 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1084 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1086 DBG("permission [0x%04x] : %s\n", permission, perm);
1090 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1092 GDBusProxy *properties_proxy = NULL;
1093 GError *error = NULL;
1094 GVariant *value = NULL;
1095 GVariant *result = NULL;
1096 GDBusConnection *g_conn;
1098 char *char_desc_handle = NULL;
1100 GVariantIter *property_iter;
1101 GVariantIter *char_desc_iter;
1102 char* char_handle = NULL;
1103 gchar *char_uuid_str = NULL;
1104 GPtrArray *gp_desc_array = NULL;
1105 GVariantIter *char_perm_iter;
1107 unsigned int char_permission = 0 ;
1109 if (gattc_char->chr_path == NULL) {
1110 DBG("char path is NULL");
1111 return BT_STATUS_FAIL;
1113 char_handle = gattc_char->chr_path;
1115 g_conn = _bt_hal_get_system_gconn();
1116 if (NULL == g_conn) {
1117 ERR("_bt_gdbus_get_system_gconn returned NULL");
1118 return BT_STATUS_FAIL;
1121 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1122 G_DBUS_PROXY_FLAGS_NONE, NULL,
1125 BT_HAL_PROPERTIES_INTERFACE,
1128 if (properties_proxy == NULL) {
1129 ERR("properties_proxy returned NULL");
1130 return BT_STATUS_FAIL;
1133 result = g_dbus_proxy_call_sync(properties_proxy,
1135 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1136 G_DBUS_CALL_FLAGS_NONE,
1141 if (error != NULL) {
1142 ERR("Fail to get properties (Error: %s)", error->message);
1143 g_clear_error(&error);
1145 ERR("Fail to get properties");
1146 g_object_unref(properties_proxy);
1147 return BT_STATUS_FAIL;
1150 gp_desc_array = g_ptr_array_new();
1152 g_variant_get(result, "(a{sv})", &property_iter);
1154 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1155 if (!g_strcmp0(key, "UUID")) {
1156 char_uuid_str = g_variant_dup_string(value, &len);
1157 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1158 } else if (!g_strcmp0(key, "Flags")) {
1159 g_variant_get(value, "as", &char_perm_iter);
1160 char_permission = 0x00;
1162 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1163 char_permission |= _hal_get_permission_flag(permission);
1165 __hal_convert_permission_flag_to_str(char_permission);
1166 g_variant_iter_free(char_perm_iter);
1167 } else if (!g_strcmp0(key, "Descriptors")) {
1168 g_variant_get(value, "ao", &char_desc_iter);
1169 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1170 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1172 g_variant_iter_free(char_desc_iter);
1176 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1178 g_free(char_uuid_str);
1179 g_variant_iter_free(property_iter);
1180 g_variant_unref(result);
1181 g_object_unref(properties_proxy);
1182 g_ptr_array_free(gp_desc_array, TRUE);
1184 return BT_STATUS_SUCCESS;
1187 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1188 btgatt_srvc_id_t *srvc_id)
1190 hal_gattc_server_info_t * conn_info = NULL;
1191 hal_gattc_service_t *gattc_service = NULL;
1193 hal_gattc_char_t *gattc_char = NULL;
1194 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1195 int status = BT_STATUS_FAIL;
1197 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1198 if (NULL == conn_info) {
1199 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1200 return BT_STATUS_FAIL;
1204 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1205 if (NULL == gattc_service) {
1206 ERR("Failed to get the gatt service");
1207 return BT_STATUS_FAIL;
1210 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1211 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1213 /* find characteristic object path */
1214 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1215 gattc_char = (hal_gattc_char_t *)l->data;
1216 status = _hal_gattc_get_characteristic_info(gattc_char);
1219 if (BT_STATUS_SUCCESS == status) {
1220 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1221 &gattc_char->chr_uuid, gattc_char->permission);
1225 status = BT_STATUS_FAIL;
1226 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1228 browse_service_char(conn_id);
1229 /* retrive uuid for characteristic and object path for descriptor */
1231 return BT_STATUS_SUCCESS;
1235 * Enumerate characteristics for a given service.
1236 * Set start_char_id to NULL to get the first characteristic.
1238 bt_status_t btif_gattc_get_characteristic(int conn_id,
1239 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1241 CHECK_BTGATT_INIT();
1243 if (start_char_id == NULL) {
1244 return _gattc_get_all_characteristic(conn_id, srvc_id);
1247 DBG("TBD Get specific characteristics");
1248 return BT_STATUS_UNSUPPORTED;
1252 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1254 GDBusProxy *properties_proxy = NULL;
1255 GError *error = NULL;
1256 GVariant *value = NULL;
1257 GVariant *result = NULL;
1258 GDBusConnection *g_conn;
1261 GVariantIter *property_iter;
1262 char* desc_handle = NULL;
1263 const gchar *desc_uuid_str = NULL;
1265 if (gattc_desc->desc_path == NULL) {
1266 DBG("desc path is NULL");
1267 return BT_STATUS_FAIL;
1269 desc_handle = gattc_desc->desc_path;
1271 g_conn = _bt_hal_get_system_gconn();
1272 if (NULL == g_conn) {
1273 ERR("_bt_gdbus_get_system_gconn returned NULL");
1274 return BT_STATUS_FAIL;
1277 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1278 G_DBUS_PROXY_FLAGS_NONE, NULL,
1281 BT_HAL_PROPERTIES_INTERFACE,
1284 if (properties_proxy == NULL) {
1285 ERR("properties_proxy returned NULL");
1286 return BT_STATUS_FAIL;
1289 result = g_dbus_proxy_call_sync(properties_proxy,
1291 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1292 G_DBUS_CALL_FLAGS_NONE,
1297 if (error != NULL) {
1298 ERR("Fail to get properties (Error: %s)", error->message);
1299 g_clear_error(&error);
1301 ERR("Fail to get properties");
1302 g_object_unref(properties_proxy);
1303 return BT_STATUS_FAIL;
1306 g_variant_get(result, "(a{sv})", &property_iter);
1308 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1309 if (!g_strcmp0(key, "UUID")) {
1310 desc_uuid_str = g_variant_get_string(value, &len);
1311 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1313 g_free((gchar *)key);
1314 g_variant_unref(value);
1319 g_variant_iter_free(property_iter);
1320 g_variant_unref(result);
1321 g_object_unref(properties_proxy);
1323 return BT_STATUS_SUCCESS;
1326 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1327 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1329 struct hal_ev_gatt_client_desc_search_result ev;
1332 ERR("gatt client callback not registered");
1336 memset(&ev, 0, sizeof(ev));
1337 ev.conn_id = conn_id;
1338 ev.inst_id = svc_id->id.inst_id;
1339 ev.is_primary = svc_id->is_primary;
1342 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1343 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1345 if (status == BT_STATUS_SUCCESS) {
1346 /* building desc uuid */
1347 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1350 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1352 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1355 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1356 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1358 hal_gattc_server_info_t * conn_info = NULL;
1359 hal_gattc_service_t *gattc_service = NULL;
1362 hal_gattc_char_t *gattc_char = NULL;
1363 hal_gattc_desc_t *gattc_desc = NULL;
1364 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1365 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1366 int status = BT_STATUS_FAIL;
1368 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1369 if (NULL == conn_info) {
1370 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1371 return BT_STATUS_FAIL;
1375 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1376 if (NULL == gattc_service) {
1377 ERR("Failed to get the gatt service");
1378 return BT_STATUS_FAIL;
1381 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1382 // DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1384 /* find characteristics */
1385 /* a service can have two char with same uuid */
1386 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1387 gattc_char = (hal_gattc_char_t*)l->data;
1388 if (gattc_char == NULL)
1391 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1392 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1393 // DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1395 /* get descriptor uuid */
1396 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1397 gattc_desc = (hal_gattc_desc_t *)m->data;
1398 if (gattc_desc == NULL)
1401 status = _hal_gattc_get_descriptor_info(gattc_desc);
1404 if (BT_STATUS_SUCCESS == status) {
1405 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1406 char_id, &gattc_desc->desc_uuid);
1412 status = BT_STATUS_FAIL;
1413 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1415 browse_service_char(conn_id);
1416 /* retrive uuid for characteristic and object path for descriptor */
1418 return BT_STATUS_SUCCESS;
1422 * Enumerate descriptors for a given characteristic.
1423 * Set start_descr_id to NULL to get the first descriptor.
1425 bt_status_t btif_gattc_get_descriptor(int conn_id,
1426 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1427 btgatt_gatt_id_t *start_descr_id)
1429 CHECK_BTGATT_INIT();
1431 if (start_descr_id == NULL) {
1432 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1434 DBG("TBD Get specific descriptor");
1435 return BT_STATUS_UNSUPPORTED;
1439 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1441 struct hal_ev_gatt_client_read_data ev;
1444 ERR("gatt client callback not registered");
1448 memset(&ev, 0, sizeof(ev));
1449 ev.conn_id = resp_data->conn_id;
1450 ev.inst_id = resp_data->srvc_id.id.inst_id;
1451 ev.is_primary = resp_data->srvc_id.is_primary;
1454 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1455 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1459 /* building the char read value */
1460 memcpy(ev.value, value, len);
1463 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1465 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1468 static void __hal_internal_read_char_cb(GObject *source_object,
1469 GAsyncResult *res, gpointer user_data)
1471 GError *error = NULL;
1472 GDBusConnection *system_gconn = NULL;
1475 GByteArray *gp_byte_array = NULL;
1477 hal_gatt_resp_data_t *resp_data = user_data;
1478 int result = BT_STATUS_SUCCESS;
1480 system_gconn = _bt_hal_get_system_gconn();
1481 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1484 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1487 result = BT_STATUS_FAIL;
1488 __hal_send_char_read_event(resp_data, result, NULL, 0);
1489 g_clear_error(&error);
1494 gp_byte_array = g_byte_array_new();
1495 g_variant_get(value, "(ay)", &iter);
1497 while (g_variant_iter_loop(iter, "y", &g_byte))
1498 g_byte_array_append(gp_byte_array, &g_byte, 1);
1502 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1506 g_byte_array_free(gp_byte_array, TRUE);
1507 g_variant_iter_free(iter);
1508 g_variant_unref(value);
1512 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1513 btgatt_gatt_id_t *char_id, int auth_req)
1515 GDBusConnection *g_conn;
1516 hal_gatt_resp_data_t *resp_data;
1517 hal_gattc_service_t *gattc_service = NULL;
1518 GVariantBuilder *builder = NULL;
1520 hal_gattc_server_info_t * conn_info = NULL;
1521 hal_gattc_char_t *gattc_char = NULL;
1522 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1523 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1524 char* char_handle = NULL;
1526 /* get the connection info */
1527 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1528 if (NULL == conn_info) {
1529 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1530 return BT_STATUS_FAIL;
1534 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1535 if (NULL == gattc_service) {
1536 ERR("Failed to get the gatt service");
1537 return BT_STATUS_FAIL;
1540 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1542 /* find characteristic */
1543 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1544 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1545 if (NULL == gattc_char) {
1546 ERR("Failed to get the gatt char");
1547 return BT_STATUS_FAIL;
1550 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1551 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1553 g_conn = _bt_hal_get_system_gconn();
1554 if (NULL == g_conn) {
1555 ERR("_bt_gdbus_get_system_gconn returned NULL");
1556 return BT_STATUS_FAIL;
1559 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1560 resp_data->conn_id = conn_id;
1561 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1562 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1564 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1567 g_variant_builder_add(builder, "{sv}", "offset",
1568 g_variant_new("q", offset));
1570 char_handle = gattc_char->chr_path;
1572 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1573 "ReadValue", g_variant_new("(a{sv})", builder),
1574 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1575 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1576 (gpointer)resp_data);
1577 g_variant_builder_unref(builder);
1579 return BT_STATUS_SUCCESS;
1582 /** Read a characteristic on a remote device */
1583 bt_status_t btif_read_characteristic(int conn_id,
1584 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1587 CHECK_BTGATT_INIT();
1589 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1592 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1594 struct hal_ev_gatt_client_write_result ev;
1597 ERR("gatt client callback not registered");
1601 memset(&ev, 0, sizeof(ev));
1602 ev.conn_id = resp_data->conn_id;
1603 ev.inst_id = resp_data->srvc_id.id.inst_id;
1604 ev.is_primary = resp_data->srvc_id.is_primary;
1607 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1608 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1610 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1613 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1614 GAsyncResult *res, gpointer user_data)
1616 GError *error = NULL;
1617 GDBusConnection *system_gconn = NULL;
1619 hal_gatt_resp_data_t *resp_data = user_data;
1620 int result = BT_STATUS_SUCCESS;
1622 system_gconn = _bt_hal_get_system_gconn();
1623 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1626 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1628 result = BT_STATUS_FAIL;
1630 __hal_send_char_write_event(resp_data, result);
1631 g_clear_error(&error);
1636 //send write value event
1637 __hal_send_char_write_event(resp_data, result);
1640 g_variant_unref(value);
1644 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1647 case HAL_GATT_WRITE_TYPE_WRITE:
1648 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1650 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1651 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1654 ERR("Unknow write type : %d", type);
1655 return BT_STATUS_FAIL;
1658 return BT_STATUS_SUCCESS;
1662 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1664 GDBusConnection *conn;
1665 GVariantBuilder *builder = NULL;
1671 GUnixFDList *fd_list = NULL;
1673 conn = _bt_hal_get_system_gconn();
1675 ERR("_bt_gdbus_get_system_gconn returned NULL");
1676 return BT_STATUS_FAIL;
1679 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1680 //val = g_variant_new("ay", builder1);
1682 g_variant_builder_add(builder, "{sv}", "offset",
1683 g_variant_new("q", offset));
1685 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1686 "AcquireWrite", g_variant_new("(a{sv})", builder),
1687 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1688 NULL, &fd_list, NULL, &err);
1690 g_dbus_error_strip_remote_error(err);
1691 ERR("Error: %s", err->message);
1693 g_variant_builder_unref(builder);
1694 return BT_STATUS_FAIL;
1697 g_variant_get(value, "(hq)", &idx, &att_mtu);
1698 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1700 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1703 g_object_unref(fd_list);
1704 g_variant_unref(value);
1705 g_variant_builder_unref(builder);
1707 return BT_STATUS_SUCCESS;
1710 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1712 GDBusConnection *conn;
1713 GVariantBuilder *builder = NULL;
1717 gint32 idx, notify_fd;
1719 GUnixFDList *fd_list = NULL;
1721 conn = _bt_hal_get_system_gconn();
1724 ERR("_bt_gdbus_get_system_gconn returned NULL");
1725 return BT_STATUS_FAIL;
1729 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1732 g_variant_builder_add(builder, "{sv}", "offset",
1733 g_variant_new("q", offset));
1735 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1736 "AcquireNotify", g_variant_new("(a{sv})", builder),
1737 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1738 NULL, &fd_list, NULL, &err);
1740 g_dbus_error_strip_remote_error(err);
1741 ERR("Error: %s", err->message);
1743 g_variant_builder_unref(builder);
1744 return BT_STATUS_FAIL;
1747 g_variant_get(value, "(hq)", &idx, &att_mtu);
1748 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1751 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1755 g_object_unref(fd_list);
1756 g_variant_unref(value);
1757 g_variant_builder_unref(builder);
1759 return BT_STATUS_SUCCESS;
1763 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1764 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1766 GVariant *val, *options;
1767 GVariantBuilder *builder1;
1768 GVariantBuilder *builder2;
1769 GDBusConnection *g_conn;
1772 hal_gatt_resp_data_t *resp_data;
1773 hal_gattc_service_t *gattc_service = NULL;
1774 hal_gattc_server_info_t * conn_info = NULL;
1775 hal_gattc_char_t *gattc_char = NULL;
1776 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1777 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1778 char* char_handle = NULL;
1779 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1780 int ret = BT_STATUS_SUCCESS;
1782 ret = __hal_get_write_prop(write_type, &write_prop);
1783 if (BT_STATUS_FAIL == ret) {
1784 DBG("received invalid write type:[%d] ", write_type);
1785 return BT_STATUS_FAIL;
1788 /* get the connection info */
1789 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1790 if (NULL == conn_info) {
1791 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1792 return BT_STATUS_FAIL;
1796 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1797 if (NULL == gattc_service) {
1798 ERR("Failed to get the gatt service");
1799 return BT_STATUS_FAIL;
1802 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1803 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1805 /* find characteristic */
1806 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1807 if (NULL == gattc_char) {
1808 ERR("Failed to get the gatt char");
1809 return BT_STATUS_FAIL;
1812 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1813 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1815 g_conn = _bt_hal_get_system_gconn();
1816 if (NULL == g_conn) {
1817 ERR("_bt_gdbus_get_system_gconn returned NULL");
1818 return BT_STATUS_FAIL;
1821 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1822 resp_data->conn_id = conn_id;
1823 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1824 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1826 char_handle = gattc_char->chr_path;
1828 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1830 for (i = 0; i < length; i++)
1831 g_variant_builder_add(builder1, "y", value[i]);
1833 val = g_variant_new("ay", builder1);
1835 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1837 g_variant_builder_add(builder2, "{sv}", "offset",
1838 g_variant_new_uint16(offset));
1840 options = g_variant_new("a{sv}", builder2);
1842 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1844 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1846 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1847 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1848 (gpointer)resp_data);
1850 g_variant_builder_unref(builder1);
1851 g_variant_builder_unref(builder2);
1853 return BT_STATUS_SUCCESS;
1856 bt_status_t btif_get_acquire_write_fd(int conn_id,
1857 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1858 int auth_req, int *fd, int*mtu)
1860 CHECK_BTGATT_INIT();
1862 hal_gattc_service_t *gattc_service = NULL;
1863 hal_gattc_server_info_t * conn_info = NULL;
1864 hal_gattc_char_t *gattc_char = NULL;
1865 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1867 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1868 int ret = BT_STATUS_SUCCESS;
1870 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1872 /* get the connection info */
1873 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1874 if (NULL == conn_info) {
1875 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1876 return BT_STATUS_FAIL;
1880 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1881 if (NULL == gattc_service) {
1882 ERR("Failed to get the gatt service");
1883 return BT_STATUS_FAIL;
1886 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1887 if (NULL == gattc_char) {
1888 ERR("Failed to get the gatt char");
1889 return BT_STATUS_FAIL;
1892 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1893 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1895 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1896 if (ret != BT_STATUS_SUCCESS)
1902 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1903 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1905 CHECK_BTGATT_INIT();
1907 hal_gattc_service_t *gattc_service = NULL;
1908 hal_gattc_server_info_t * conn_info = NULL;
1909 hal_gattc_char_t *gattc_char = NULL;
1910 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1912 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1913 int ret = BT_STATUS_SUCCESS;
1915 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1917 /* get the connection info */
1918 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1919 if (NULL == conn_info) {
1920 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1921 return BT_STATUS_FAIL;
1925 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1926 if (NULL == gattc_service) {
1927 ERR("Failed to get the gatt service");
1928 return BT_STATUS_FAIL;
1931 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1932 if (NULL == gattc_char) {
1933 ERR("Failed to get the gatt char");
1934 return BT_STATUS_FAIL;
1937 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1938 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1940 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1941 if (ret != BT_STATUS_SUCCESS)
1948 /** Write a remote characteristic */
1949 bt_status_t btif_write_characteristic(int conn_id,
1950 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1951 int write_type, int len, int auth_req,
1954 CHECK_BTGATT_INIT();
1956 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1957 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1958 len, auth_req, p_value);
1961 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1963 struct hal_ev_gatt_client_read_data ev;
1966 ERR("gatt client callback not registered");
1970 memset(&ev, 0, sizeof(ev));
1971 ev.conn_id = resp_data->conn_id;
1972 ev.inst_id = resp_data->srvc_id.id.inst_id;
1973 ev.is_primary = resp_data->srvc_id.is_primary;
1976 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1977 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1978 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1982 /* building the desc read value */
1983 memcpy(ev.value, value, len);
1986 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1988 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1991 static void __hal_internal_read_desc_cb(GObject *source_object,
1992 GAsyncResult *res, gpointer user_data)
1994 GError *error = NULL;
1995 GDBusConnection *system_gconn = NULL;
1998 GByteArray *gp_byte_array = NULL;
2000 hal_gatt_resp_data_t *resp_data = user_data;
2001 int result = BT_STATUS_SUCCESS;
2006 system_gconn = _bt_hal_get_system_gconn();
2007 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2010 ERR("Read descriptor dbus failed Error:[%s]", error->message);
2013 result = BT_STATUS_FAIL;
2014 __hal_send_desc_read_event(resp_data, result, NULL, 0);
2015 g_clear_error(&error);
2020 gp_byte_array = g_byte_array_new();
2021 g_variant_get(value, "(ay)", &iter);
2023 while (g_variant_iter_loop(iter, "y", &g_byte))
2024 g_byte_array_append(gp_byte_array, &g_byte, 1);
2028 for (i = 0; i < gp_byte_array->len; i++)
2029 DBG("%02x", gp_byte_array->data[i]);
2032 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2036 g_byte_array_free(gp_byte_array, TRUE);
2037 g_variant_iter_free(iter);
2038 g_variant_unref(value);
2043 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2044 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2046 GDBusConnection *g_conn;
2047 hal_gatt_resp_data_t *resp_data;
2048 hal_gattc_service_t *gattc_service = NULL;
2049 GVariantBuilder *builder = NULL;
2051 hal_gattc_server_info_t * conn_info = NULL;
2052 hal_gattc_char_t *gattc_char = NULL;
2053 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2054 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2055 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2056 char* desc_handle = NULL;
2059 hal_gattc_desc_t *gattc_desc = NULL;
2061 /* get the connection info */
2062 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2063 if (NULL == conn_info) {
2064 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2065 return BT_STATUS_FAIL;
2069 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2070 if (NULL == gattc_service) {
2071 ERR("Failed to get the gatt service");
2072 return BT_STATUS_FAIL;
2075 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2076 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2078 /* find characteristic */
2079 /* service can have two char with same uuid */
2080 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2081 gattc_char = (hal_gattc_char_t*)l->data;
2082 if (gattc_char == NULL)
2085 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2086 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2087 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2089 /* find descriptor */
2090 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2092 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2093 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2099 if (NULL == gattc_desc) {
2100 ERR("Failed to get the gatt desc");
2101 return BT_STATUS_FAIL;
2104 g_conn = _bt_hal_get_system_gconn();
2105 if (NULL == g_conn) {
2106 ERR("_bt_gdbus_get_system_gconn returned NULL");
2107 return BT_STATUS_FAIL;
2110 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2111 resp_data->conn_id = conn_id;
2112 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2113 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2114 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2116 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2119 g_variant_builder_add(builder, "{sv}", "offset",
2120 g_variant_new("q", offset));
2122 desc_handle = gattc_desc->desc_path;
2124 DBG("calling desc read value");
2126 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2127 "ReadValue", g_variant_new("(a{sv})", builder),
2128 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2129 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2130 (gpointer)resp_data);
2131 g_variant_builder_unref(builder);
2133 return BT_STATUS_SUCCESS;
2136 /** Read the descriptor for a given characteristic */
2137 bt_status_t btif_read_descriptor(int conn_id,
2138 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2139 btgatt_gatt_id_t *descr_id, int auth_req)
2141 CHECK_BTGATT_INIT();
2143 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2146 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2148 struct hal_ev_gatt_client_write_result ev;
2151 ERR("gatt client callback not registered");
2155 memset(&ev, 0, sizeof(ev));
2156 ev.conn_id = resp_data->conn_id;
2157 ev.inst_id = resp_data->srvc_id.id.inst_id;
2158 ev.is_primary = resp_data->srvc_id.is_primary;
2161 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2162 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2163 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2165 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2167 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2170 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2171 GAsyncResult *res, gpointer user_data)
2173 GError *error = NULL;
2174 GDBusConnection *system_gconn = NULL;
2176 hal_gatt_resp_data_t *resp_data = user_data;
2177 int result = BT_STATUS_SUCCESS;
2181 system_gconn = _bt_hal_get_system_gconn();
2182 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2185 ERR("write descriptor dbus failed Error: [%s]", error->message);
2188 result = BT_STATUS_FAIL;
2189 __hal_send_desc_write_event(resp_data, result);
2190 g_clear_error(&error);
2195 //send write value event
2196 __hal_send_desc_write_event(resp_data, result);
2199 g_variant_unref(value);
2204 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2205 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2206 int write_type, int length, int auth_req, char* value)
2208 GVariant *val, *options;
2209 GVariantBuilder *builder1;
2210 GVariantBuilder *builder2;
2211 GDBusConnection *g_conn;
2214 hal_gatt_resp_data_t *resp_data;
2215 hal_gattc_service_t *gattc_service = NULL;
2216 hal_gattc_server_info_t * conn_info = NULL;
2217 hal_gattc_char_t *gattc_char = NULL;
2218 hal_gattc_desc_t *gattc_desc = NULL;
2219 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2220 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2221 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2222 char* desc_handle = NULL;
2223 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2224 int ret = BT_STATUS_SUCCESS;
2229 ret = __hal_get_write_prop(write_type, &write_prop);
2230 if (BT_STATUS_FAIL == ret) {
2231 ERR("received invalid write type:[%d] ", write_type);
2232 return BT_STATUS_FAIL;
2235 /* get the connection info */
2236 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2237 if (NULL == conn_info) {
2238 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2239 return BT_STATUS_FAIL;
2243 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2244 if (NULL == gattc_service) {
2245 ERR("Failed to get the gatt service");
2246 return BT_STATUS_FAIL;
2249 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2250 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2252 /* find characteristic */
2253 /* service can have two char with same uuid */
2254 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2255 gattc_char = (hal_gattc_char_t*)l->data;
2256 if (gattc_char == NULL)
2259 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2260 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2261 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2263 /* find descriptor */
2264 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2266 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2267 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2273 if (NULL == gattc_desc) {
2274 ERR("Failed to get the gatt desc");
2275 return BT_STATUS_FAIL;
2278 g_conn = _bt_hal_get_system_gconn();
2279 if (NULL == g_conn) {
2280 ERR("_bt_gdbus_get_system_gconn returned NULL");
2281 return BT_STATUS_FAIL;
2284 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2285 resp_data->conn_id = conn_id;
2286 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2287 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2288 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2290 desc_handle = gattc_desc->desc_path;
2292 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2294 for (i = 0; i < length; i++)
2295 g_variant_builder_add(builder1, "y", value[i]);
2297 val = g_variant_new("ay", builder1);
2299 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2301 g_variant_builder_add(builder2, "{sv}", "offset",
2302 g_variant_new_uint16(offset));
2304 options = g_variant_new("a{sv}", builder2);
2306 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2308 g_variant_new("(@ay@a{sv})", val, options),
2310 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2311 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2312 (gpointer)resp_data);
2314 g_variant_builder_unref(builder1);
2315 g_variant_builder_unref(builder2);
2317 return BT_STATUS_SUCCESS;
2320 /** Write a remote descriptor for a given characteristic */
2321 bt_status_t btif_write_descriptor(int conn_id,
2322 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2323 btgatt_gatt_id_t *descr_id, int write_type, int len,
2324 int auth_req, char* p_value)
2326 CHECK_BTGATT_INIT();
2328 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2329 len, auth_req, p_value);
2332 /** Execute a prepared write operation */
2333 bt_status_t execute_write(int conn_id, int execute)
2335 CHECK_BTGATT_INIT();
2336 return BT_STATUS_UNSUPPORTED;
2339 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2341 struct hal_ev_gatt_client_watch_notification ev;
2342 hal_gatt_resp_data_t *resp_data = user_data;
2344 DBG("sending the watch register notification event");
2345 /* send the event */
2346 memset(&ev, 0, sizeof(ev));
2347 ev.conn_id = resp_data->conn_id;
2349 ev.status = resp_data->result;
2351 ev.is_primary = resp_data->srvc_id.is_primary;
2352 ev.inst_id = resp_data->srvc_id.id.inst_id;
2354 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2355 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2358 ERR("GATT Callback not registered");
2360 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2367 static bt_status_t _hal_register_for_notification(int conn_id,
2368 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2369 btgatt_gatt_id_t *char_id)
2371 int result = BT_STATUS_SUCCESS;
2372 GError *error = NULL;
2373 GDBusConnection *g_conn;
2374 hal_gattc_client_info_t *gattc_client = NULL;
2375 hal_gattc_server_info_t * conn_info = NULL;
2376 hal_gattc_service_t *gattc_service = NULL;
2377 hal_gattc_char_t *gattc_char = NULL;
2378 char* char_handle = NULL;
2379 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2380 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2381 hal_gatt_resp_data_t *resp_data;
2385 gattc_client = __bt_find_gatt_client_info(bd_addr);
2386 if (gattc_client == NULL) {
2387 ERR("failed to get the gatt client info");
2388 return BT_STATUS_FAIL;
2391 if (gattc_client->conn_id != conn_id) {
2392 ERR("could not find the gatt client for client id[%d]", conn_id);
2393 return BT_STATUS_FAIL;
2396 /* get the connection info */
2397 conn_info = __bt_find_gatt_conn_info(bd_addr);
2398 if (NULL == conn_info) {
2399 ERR("Failed to get the conn_info");
2400 return BT_STATUS_FAIL;
2403 if (conn_info->inst_id != gattc_client->inst_id) {
2404 ERR("could not fild the conn_info");
2405 return BT_STATUS_FAIL;
2409 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2410 if (NULL == gattc_service) {
2411 ERR("Failed to get the gatt service");
2412 return BT_STATUS_FAIL;
2415 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2416 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2419 /* find characteristic */
2420 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2421 if (NULL == gattc_char) {
2422 ERR("Failed to get the gatt char");
2423 return BT_STATUS_FAIL;
2426 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2427 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2429 char_handle = gattc_char->chr_path;
2431 g_conn = _bt_hal_get_system_gconn();
2432 if (g_conn == NULL) {
2434 return BT_STATUS_FAIL;
2437 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2439 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2441 g_dbus_connection_call_sync(g_conn,
2444 BT_HAL_GATT_CHAR_INTERFACE,
2448 G_DBUS_CALL_FLAGS_NONE,
2449 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2452 g_dbus_error_strip_remote_error(error);
2453 ERR("### StartNotify Failed: %s", error->message);
2454 if (g_strrstr(error->message, "Already notifying"))
2455 result = BT_STATUS_SUCCESS;
2456 else if (g_strrstr(error->message, "In Progress"))
2457 result = BT_STATUS_BUSY;
2458 else if (g_strrstr(error->message, "Operation is not supported"))
2459 result = BT_STATUS_UNSUPPORTED;
2460 /*failed because of either Insufficient Authorization or Write Not Permitted */
2461 else if (g_strrstr(error->message, "Write not permitted") ||
2462 g_strrstr(error->message, "Operation Not Authorized"))
2463 result = BT_STATUS_AUTH_FAILURE;
2464 /* failed because of either Insufficient Authentication,
2465 Insufficient Encryption Key Size, or Insufficient Encryption. */
2466 else if (g_strrstr(error->message, "Not paired"))
2467 result = BT_STATUS_NOT_READY;
2469 result = BT_STATUS_FAIL;
2471 g_clear_error(&error);
2474 resp_data->conn_id = gattc_client->conn_id;
2475 resp_data->result = result;
2476 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2477 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2479 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2483 return BT_STATUS_SUCCESS;
2487 * Register to receive notifications or indications for a given
2490 bt_status_t btif_register_for_notification(int conn_id,
2491 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2492 btgatt_gatt_id_t *char_id)
2494 CHECK_BTGATT_INIT();
2496 return _hal_register_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2499 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2501 struct hal_ev_gatt_client_watch_notification ev;
2502 hal_gatt_resp_data_t *resp_data = user_data;
2504 DBG("sending the watch deregister notification event");
2505 /* send the event */
2506 memset(&ev, 0, sizeof(ev));
2507 ev.conn_id = resp_data->conn_id;
2509 ev.status = resp_data->result;
2511 ev.is_primary = resp_data->srvc_id.is_primary;
2512 ev.inst_id = resp_data->srvc_id.id.inst_id;
2514 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2515 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2518 ERR("GATT Callback not registered");
2520 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2527 static bt_status_t _hal_deregister_for_notification(int conn_id,
2528 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2529 btgatt_gatt_id_t *char_id)
2531 int result = BT_STATUS_SUCCESS;
2532 GError *error = NULL;
2533 GDBusConnection *g_conn;
2534 hal_gattc_client_info_t *gattc_client = NULL;
2535 hal_gattc_server_info_t * conn_info = NULL;
2536 hal_gattc_service_t *gattc_service = NULL;
2537 hal_gattc_char_t *gattc_char = NULL;
2538 char* char_handle = NULL;
2539 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2540 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2541 hal_gatt_resp_data_t *resp_data;
2545 gattc_client = __bt_find_gatt_client_info(bd_addr);
2546 if (gattc_client == NULL) {
2547 ERR("failed to get the gatt client info");
2548 return BT_STATUS_FAIL;
2551 if (gattc_client->conn_id != conn_id) {
2552 ERR("could not find the gatt client for client id[%d]", conn_id);
2553 return BT_STATUS_FAIL;
2556 /* get the connection info */
2557 conn_info = __bt_find_gatt_conn_info(bd_addr);
2558 if (NULL == conn_info) {
2559 ERR("Failed to get the conn_info");
2560 return BT_STATUS_FAIL;
2563 if (conn_info->inst_id != gattc_client->inst_id) {
2564 ERR("could not fild the conn_info");
2565 return BT_STATUS_FAIL;
2569 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2570 if (NULL == gattc_service) {
2571 ERR("Failed to get the gatt service");
2572 return BT_STATUS_FAIL;
2575 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2576 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2579 /* find characteristic */
2580 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2581 if (NULL == gattc_char) {
2582 ERR("Failed to get the gatt char");
2583 return BT_STATUS_FAIL;
2586 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2587 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2589 char_handle = gattc_char->chr_path;
2591 g_conn = _bt_hal_get_system_gconn();
2592 if (g_conn == NULL) {
2594 return BT_STATUS_FAIL;
2597 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2599 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2600 g_dbus_connection_call_sync(g_conn,
2603 BT_HAL_GATT_CHAR_INTERFACE,
2607 G_DBUS_CALL_FLAGS_NONE,
2608 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2611 ERR("### StopNotify Failed: %s", error->message);
2612 g_clear_error(&error);
2613 result = BT_STATUS_FAIL;
2616 resp_data->conn_id = gattc_client->conn_id;
2617 resp_data->result = result;
2618 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2619 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2621 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2625 return BT_STATUS_SUCCESS;
2627 /** Deregister a previous request for notifications/indications */
2628 bt_status_t btif_deregister_for_notification(int conn_id,
2629 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2630 btgatt_gatt_id_t *char_id)
2632 CHECK_BTGATT_INIT();
2633 return _hal_deregister_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2636 /** Request RSSI for a given remote device */
2637 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2639 CHECK_BTGATT_INIT();
2640 return BT_STATUS_UNSUPPORTED;
2643 /** OTA firmware download */
2644 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2646 CHECK_BTGATT_INIT();
2647 return BT_STATUS_UNSUPPORTED;
2650 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2651 int get_device_type(const bt_bdaddr_t *bd_addr)
2653 CHECK_BTGATT_INIT();
2654 return BT_STATUS_UNSUPPORTED;
2657 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2658 int min_int, int max_int, int latency, int timeout)
2660 gchar *device_path = NULL;
2661 GError *error = NULL;
2662 GDBusProxy *device_proxy = NULL;
2663 GDBusConnection *conn;
2665 int ret = BT_STATUS_SUCCESS;
2666 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2668 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2669 min_int, max_int, latency, timeout);
2671 conn = _bt_hal_get_system_gconn();
2674 return BT_STATUS_FAIL;
2677 _bt_hal_convert_addr_type_to_string(device_address,
2678 (unsigned char *)bd_addr->address);
2679 device_path = _bt_hal_get_device_object_path(device_address);
2681 if (device_path == NULL) {
2682 ERR("device_path NULL : [%s]", device_address);
2683 return BT_STATUS_FAIL;
2686 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2687 NULL, BT_HAL_BLUEZ_NAME,
2688 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2690 g_free(device_path);
2691 if (NULL == device_proxy) {
2692 ERR("device_proxy returned NULL");
2693 return BT_STATUS_FAIL;
2696 DBG("Request LeConnUpdate");
2697 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2698 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2699 G_DBUS_CALL_FLAGS_NONE,
2704 g_object_unref(device_proxy);
2705 if (reply == NULL) {
2707 ERR("Error %s[%s]", error->message, device_address);
2708 if (g_strrstr(error->message, "In Progress"))
2709 ret = BT_STATUS_SUCCESS;
2711 ret = BT_STATUS_FAIL;
2712 g_error_free(error);
2716 g_variant_unref(reply);
2718 DBG("LE Connection parameter Updated");
2722 /** Request a connection parameter update */
2723 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2725 CHECK_BTGATT_INIT();
2727 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2730 /** Test mode interface */
2731 bt_status_t test_command(int command, btgatt_test_params_t* params)
2733 CHECK_BTGATT_INIT();
2734 return BT_STATUS_UNSUPPORTED;
2737 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2740 GError *g_error = NULL;
2741 GVariant *reply = NULL;
2742 int result = BT_STATUS_SUCCESS;
2743 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2744 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2746 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2747 g_object_unref(proxy);
2748 if (reply == NULL) {
2749 ERR("Connect LE Dbus Call Error");
2751 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2752 g_clear_error(&g_error);
2754 result = BT_STATUS_FAIL;
2756 g_variant_unref(reply);
2758 memset(&ev, 0, sizeof(ev));
2760 ev.mtu = conn_mtu->mtu;
2761 ev.conn_id = conn_mtu->conn_id;
2764 ERR("gatt client callback not registered");
2766 DBG("sending gatt client MTU exchange completed event");
2767 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2774 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2776 gchar *device_path = NULL;
2777 GDBusProxy *device_proxy = NULL;
2778 GDBusConnection *conn;
2779 hal_gattc_client_info_t *gattc_client = NULL;
2780 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2781 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2783 conn = _bt_hal_get_system_gconn();
2787 return BT_STATUS_FAIL;
2790 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2791 if (gattc_client == NULL) {
2792 INFO("GATT client conn info not found");
2794 return BT_STATUS_FAIL;
2797 _bt_hal_convert_addr_type_to_string(device_address,
2798 (unsigned char *)gattc_client->bd_addr.address);
2800 device_path = _bt_hal_get_device_object_path(device_address);
2801 if (device_path == NULL) {
2802 ERR("device_path NULL : [%s]", device_address);
2804 return BT_STATUS_FAIL;
2807 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2808 NULL, BT_HAL_BLUEZ_NAME,
2809 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2811 g_free(device_path);
2812 if (NULL == device_proxy) {
2813 ERR("device_proxy returned NULL");
2815 return BT_STATUS_FAIL;
2818 conn_mtu->conn_id = conn_id;
2819 conn_mtu->mtu = mtu;
2821 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2822 g_variant_new("(q)", mtu),
2823 G_DBUS_CALL_FLAGS_NONE,
2824 BT_HAL_MAX_DBUS_TIMEOUT,
2826 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2829 return BT_STATUS_SUCCESS;
2832 /** MTU Exchange request from client */
2833 static bt_status_t configure_mtu(int conn_id, int mtu)
2835 CHECK_BTGATT_INIT();
2837 return __hal_configure_mtu(conn_id, mtu);
2840 /** Setup scan filter params */
2841 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2842 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2843 int rssi_low_thres, int dely_mode, int found_timeout,
2844 int lost_timeout, int found_timeout_cnt)
2847 GError *error = NULL;
2848 GVariant *ret, *param;
2849 CHECK_BTGATT_INIT();
2851 proxy = _bt_hal_get_adapter_proxy();
2854 return BT_STATUS_FAIL;
2856 param = g_variant_new("(iiiiiiiiiiii)",
2869 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2870 param, G_DBUS_CALL_FLAGS_NONE,
2874 ERR("scan_filter_param_setup Fail: %s", error->message);
2875 g_clear_error(&error);
2876 return BT_STATUS_FAIL;
2880 g_variant_unref(ret);
2882 return BT_STATUS_SUCCESS;
2885 /** Configure a scan filter condition */
2886 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2887 int filt_index, int company_id,
2888 int company_id_mask, const bt_uuid_t *p_uuid,
2889 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2890 char addr_type, int data_len, char* p_data, int mask_len,
2894 GError *error = NULL;
2895 GVariant *ret, *param;
2896 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2897 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2898 GArray *arr_uuid = NULL;
2899 GArray *arr_uuid_mask = NULL;
2900 GArray *arr_data = NULL;
2901 GArray *arr_data_mask = NULL;
2902 CHECK_BTGATT_INIT();
2904 proxy = _bt_hal_get_adapter_proxy();
2907 return BT_STATUS_FAIL;
2909 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2911 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2913 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2915 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2917 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2918 NULL, 0, TRUE, NULL, NULL);
2919 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2920 NULL, 0, TRUE, NULL, NULL);
2921 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2922 NULL, 0, TRUE, NULL, NULL);
2923 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2924 NULL, 0, TRUE, NULL, NULL);
2926 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2927 client_if, // client_if
2928 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2929 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2930 filt_index, // filter_index
2931 company_id, // company_id
2932 company_id_mask, // company_id_mask
2933 arr_uuid_param, // p_uuid
2934 arr_uuid_mask_param, // p_uuid_mask
2936 addr_type, // address_type
2937 arr_data_param, // p_data
2938 arr_data_mask_param); // p_mask
2940 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2941 param, G_DBUS_CALL_FLAGS_NONE,
2945 ERR("scan_filter_add_remove Fail: %s", error->message);
2946 g_clear_error(&error);
2947 return BT_STATUS_FAIL;
2951 g_variant_unref(ret);
2953 return BT_STATUS_SUCCESS;
2956 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2958 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2959 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2960 NULL, 0, TRUE, NULL, NULL);
2961 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2962 NULL, 0, TRUE, NULL, NULL);
2963 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2964 NULL, 0, TRUE, NULL, NULL);
2965 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2966 NULL, 0, TRUE, NULL, NULL);
2968 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2969 client_if, // client_if
2970 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2971 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2972 filt_index, // filter_index
2973 company_id, // company_id
2974 company_id_mask, // company_id_mask
2975 arr_uuid_param, // p_uuid
2976 arr_uuid_mask_param, // p_uuid_mask
2978 addr_type, // address_type
2979 arr_data_param, // p_data
2980 arr_data_mask_param);
2982 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2983 param, G_DBUS_CALL_FLAGS_NONE,
2987 ERR("scan_filter_add_remove Fail: %s", error->message);
2988 g_clear_error(&error);
2989 return BT_STATUS_FAIL;
2993 g_variant_unref(ret);
2995 return BT_STATUS_SUCCESS;
2998 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
3000 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3001 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3003 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3004 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3006 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3007 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3008 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3009 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3010 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3011 NULL, 0, TRUE, NULL, NULL);
3012 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3013 NULL, 0, TRUE, NULL, NULL);
3015 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3016 client_if, // client_if
3017 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3018 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
3019 filt_index, // filter_index
3020 company_id, // company_id
3021 company_id_mask, // company_id_mask
3022 arr_uuid_param, // p_uuid
3023 arr_uuid_mask_param, // p_uuid_mask
3025 addr_type, // address_type
3026 arr_data_param, // p_data
3027 arr_data_mask_param);
3029 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3030 param, G_DBUS_CALL_FLAGS_NONE,
3034 ERR("scan_filter_add_remove Fail: %s", error->message);
3035 g_clear_error(&error);
3036 return BT_STATUS_FAIL;
3040 g_variant_unref(ret);
3042 g_array_free(arr_uuid, TRUE);
3043 g_array_free(arr_uuid_mask, TRUE);
3045 return BT_STATUS_SUCCESS;
3048 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3050 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3051 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3053 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3054 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3056 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3057 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3058 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3059 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3060 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3061 NULL, 0, TRUE, NULL, NULL);
3062 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3063 NULL, 0, TRUE, NULL, NULL);
3065 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3066 client_if, // client_if
3067 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3068 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3069 filt_index, // filter_index
3070 company_id, // company_id
3071 company_id_mask, // company_id_mask
3072 arr_uuid_param, // p_uuid
3073 arr_uuid_mask_param, // p_uuid_mask
3075 addr_type, // address_type
3076 arr_data_param, // p_data
3077 arr_data_mask_param);
3079 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3080 G_DBUS_CALL_FLAGS_NONE,
3084 ERR("scan_filter_add_remove Fail: %s", error->message);
3085 g_clear_error(&error);
3086 return BT_STATUS_FAIL;
3090 g_variant_unref(ret);
3092 g_array_free(arr_uuid, TRUE);
3093 g_array_free(arr_uuid_mask, TRUE);
3095 return BT_STATUS_SUCCESS;
3098 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3100 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3101 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3103 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3104 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3106 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3107 NULL, 0, TRUE, NULL, NULL);
3108 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3109 NULL, 0, TRUE, NULL, NULL);
3110 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3111 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3112 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3113 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3115 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3116 client_if, // client_if
3117 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3118 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3119 filt_index, // filter_index
3120 company_id, // company_id
3121 company_id_mask, // company_id_mask
3122 arr_uuid_param, // p_uuid
3123 arr_uuid_mask_param, // p_uuid_mask
3125 addr_type, // address_type
3126 arr_data_param, // p_data
3127 arr_data_mask_param);
3129 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3130 G_DBUS_CALL_FLAGS_NONE,
3134 ERR("scan_filter_add_remove Fail: %s", error->message);
3135 g_clear_error(&error);
3136 return BT_STATUS_FAIL;
3140 g_variant_unref(ret);
3142 g_array_free(arr_data, TRUE);
3143 g_array_free(arr_data_mask, TRUE);
3145 return BT_STATUS_SUCCESS;
3148 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3150 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3151 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3153 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3154 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3156 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3157 NULL, 0, TRUE, NULL, NULL);
3158 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3159 NULL, 0, TRUE, NULL, NULL);
3160 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3161 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3162 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3163 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3165 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3166 client_if, // client_if
3167 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3168 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3169 filt_index, // filter_index
3170 company_id, // company_id
3171 company_id_mask, // company_id_mask
3172 arr_uuid_param, // p_uuid
3173 arr_uuid_mask_param, // p_uuid_mask
3175 addr_type, // address_type
3176 arr_data_param, // p_data
3177 arr_data_mask_param);
3179 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3180 G_DBUS_CALL_FLAGS_NONE,
3184 ERR("scan_filter_add_remove Fail: %s", error->message);
3185 g_clear_error(&error);
3186 return BT_STATUS_FAIL;
3190 g_variant_unref(ret);
3192 g_array_free(arr_data, TRUE);
3193 g_array_free(arr_data_mask, TRUE);
3195 return BT_STATUS_SUCCESS;
3198 return BT_STATUS_UNSUPPORTED;
3201 /** Clear all scan filter conditions for specific filter index*/
3202 bt_status_t scan_filter_clear(int client_if, int filt_index)
3205 GError *error = NULL;
3207 CHECK_BTGATT_INIT();
3209 proxy = _bt_hal_get_adapter_proxy();
3211 return BT_STATUS_FAIL;
3213 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3214 g_variant_new("(ii)", client_if, filt_index),
3215 G_DBUS_CALL_FLAGS_NONE,
3219 ERR("scan_filter_clear Fail: %s", error->message);
3220 g_clear_error(&error);
3221 return BT_STATUS_FAIL;
3224 g_variant_unref(ret);
3225 return BT_STATUS_SUCCESS;
3228 /** Enable / disable scan filter feature*/
3229 bt_status_t scan_filter_enable(int client_if, bool enable)
3232 GError *error = NULL;
3234 CHECK_BTGATT_INIT();
3236 proxy = _bt_hal_get_adapter_proxy();
3238 return BT_STATUS_FAIL;
3240 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3241 g_variant_new("(ib)", client_if, enable),
3242 G_DBUS_CALL_FLAGS_NONE,
3246 ERR("scan_filter_enable Fail: %s", error->message);
3247 g_clear_error(&error);
3248 return BT_STATUS_FAIL;
3250 g_variant_unref(ret);
3252 return BT_STATUS_SUCCESS;
3255 /** Sets the LE scan interval and window in units of N*0.625 msec */
3257 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3261 CHECK_BTGATT_INIT();
3263 le_scan_type = scan_type;
3264 ret = _bt_hal_adapter_le_set_scan_parameters(
3265 scan_type, scan_interval, scan_window);
3269 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3271 CHECK_BTGATT_INIT();
3272 return BT_STATUS_UNSUPPORTED;
3276 /* Configure the batchscan storage */
3277 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3278 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3280 CHECK_BTGATT_INIT();
3281 return BT_STATUS_UNSUPPORTED;
3284 /* Enable batchscan */
3285 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3286 int scan_interval, int scan_window, int addr_type, int discard_rule)
3288 CHECK_BTGATT_INIT();
3289 return BT_STATUS_UNSUPPORTED;
3292 /* Disable batchscan */
3293 bt_status_t batchscan_dis_batch_scan(int client_if)
3295 CHECK_BTGATT_INIT();
3296 return BT_STATUS_UNSUPPORTED;
3299 /* Read out batchscan reports */
3300 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3302 CHECK_BTGATT_INIT();
3303 return BT_STATUS_UNSUPPORTED;
3306 bt_status_t btif_gatt_get_data_batching_available_packets(unsigned int *available_packets)
3309 GError *error = NULL;
3311 guint32 available_pkts;
3313 CHECK_BTGATT_INIT();
3315 if (available_packets == NULL) {
3316 ERR("available_packets is NULL");
3317 return BT_STATUS_PARM_INVALID;
3320 proxy = _bt_hal_get_adapter_proxy();
3321 if (proxy == NULL) {
3322 ERR("proxy is NULL");
3323 return BT_STATUS_FAIL;
3326 ret = g_dbus_proxy_call_sync(proxy, "GetLeBatchingAvailablePkts",
3328 G_DBUS_CALL_FLAGS_NONE,
3331 int result = BT_STATUS_FAIL;
3333 ERR("SetLeBatchingParam Fail: %s", error->message);
3334 if (g_strrstr(error->message, "Operation is not supported"))
3335 result = BT_STATUS_UNSUPPORTED;
3337 g_clear_error(&error);
3340 g_variant_get(ret, "(u)", &available_pkts);
3341 g_variant_unref(ret);
3343 INFO("GATT Batching available packets: %u", available_pkts);
3344 *available_packets = available_pkts;
3345 return BT_STATUS_SUCCESS;
3348 bt_status_t btif_gatt_enable_data_batching(const bt_bdaddr_t *bd_addr, int packet_threshold, int timeout)
3350 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3352 GError *error = NULL;
3354 CHECK_BTGATT_INIT();
3356 if (bd_addr == NULL) {
3357 ERR("bd_addr is NULL");
3358 return BT_STATUS_PARM_INVALID;
3361 proxy = _bt_hal_get_adapter_proxy();
3362 if (proxy == NULL) {
3363 ERR("proxy is NULL");
3364 return BT_STATUS_FAIL;
3367 _bt_hal_convert_addr_type_to_string(device_address,
3368 (unsigned char *)bd_addr->address);
3369 ret = g_dbus_proxy_call_sync(proxy, "EnableLeBatching",
3370 g_variant_new("(sii)", device_address, packet_threshold, timeout),
3371 G_DBUS_CALL_FLAGS_NONE,
3374 int result = BT_STATUS_FAIL;
3376 ERR("SetLeBatchingParam Fail: %s", error->message);
3377 if (g_strrstr(error->message, "Operation is not supported"))
3378 result = BT_STATUS_UNSUPPORTED;
3379 else if (g_strrstr(error->message, "Invalid arguments"))
3380 result = BT_STATUS_PARM_INVALID;
3382 g_clear_error(&error);
3385 g_variant_unref(ret);
3387 INFO("GATT Batching is enabled");
3388 return BT_STATUS_SUCCESS;
3391 bt_status_t btif_gatt_disable_data_batching(const bt_bdaddr_t *bd_addr)
3393 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3395 GError *error = NULL;
3397 CHECK_BTGATT_INIT();
3399 if (bd_addr == NULL) {
3400 ERR("bd_addr is NULL");
3401 return BT_STATUS_PARM_INVALID;
3404 proxy = _bt_hal_get_adapter_proxy();
3405 if (proxy == NULL) {
3406 ERR("proxy is NULL");
3407 return BT_STATUS_FAIL;
3410 _bt_hal_convert_addr_type_to_string(device_address,
3411 (unsigned char *)bd_addr->address);
3412 ret = g_dbus_proxy_call_sync(proxy, "DisableLeBatching",
3413 g_variant_new("(s)", device_address),
3414 G_DBUS_CALL_FLAGS_NONE,
3417 int result = BT_STATUS_FAIL;
3419 ERR("SetLeBatching Fail: %s", error->message);
3420 if (g_strrstr(error->message, "Operation is not supported"))
3421 result = BT_STATUS_UNSUPPORTED;
3423 g_clear_error(&error);
3426 g_variant_unref(ret);
3428 INFO("GATT Batching is disabled");
3429 return BT_STATUS_SUCCESS;
3432 const btgatt_client_interface_t btgatt_client_interface = {
3433 .register_client = btif_gattc_register_client,
3434 .unregister_client = btif_gattc_unregister_client,
3436 .connect = btif_gattc_client_connect,
3437 .disconnect = btif_gattc_client_disconnect,
3439 .search_service = btif_gattc_client_search_service,
3440 .get_included_service = get_included_service,
3441 .get_characteristic = btif_gattc_get_characteristic,
3442 .get_descriptor = btif_gattc_get_descriptor,
3443 .read_characteristic = btif_read_characteristic,
3444 .write_characteristic = btif_write_characteristic,
3445 .acquire_write = btif_get_acquire_write_fd,
3446 .acquire_notify = btif_get_acquire_notify_fd,
3447 .read_descriptor = btif_read_descriptor,
3448 .write_descriptor = btif_write_descriptor,
3449 .execute_write = execute_write,
3450 .register_for_notification = btif_register_for_notification,
3451 .deregister_for_notification = btif_deregister_for_notification,
3452 .read_remote_rssi = read_remote_rssi,
3453 .ota_fw_update = ota_fw_update,
3454 .get_device_type = get_device_type,
3455 .conn_parameter_update = btif_gattc_conn_parameter_update,
3456 .test_command = test_command,
3457 .configure_mtu = configure_mtu,
3458 .scan_filter_param_setup = scan_filter_param_setup,
3459 .scan_filter_add_remove = scan_filter_add_remove,
3460 .scan_filter_clear = scan_filter_clear,
3461 .scan_filter_enable = scan_filter_enable,
3462 .set_scan_parameters = set_scan_parameters,
3463 .batchscan_cfg_storage = batchscan_cfg_storage,
3464 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3465 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3466 .batchscan_read_reports = batchscan_read_reports,
3467 .add_connection_info = btif_gattc_add_connection_info,
3468 .get_data_batching_available_packets = btif_gatt_get_data_batching_available_packets,
3469 .enable_data_batching = btif_gatt_enable_data_batching,
3470 .disable_data_batching = btif_gatt_disable_data_batching,
3473 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3476 hal_gattc_server_info_t *info = NULL;
3478 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3479 info = (hal_gattc_server_info_t*)l->data;
3483 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3490 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3493 hal_gattc_client_info_t *info = NULL;
3495 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3496 info = (hal_gattc_client_info_t*)l->data;
3500 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3507 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3510 hal_gattc_client_info_t *info = NULL;
3512 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3513 info = (hal_gattc_client_info_t*)l->data;
3517 if (info->conn_id == conn_id)
3524 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3527 hal_gattc_server_info_t *info = NULL;
3528 hal_gattc_client_info_t *gattc_client = NULL;
3530 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3531 if (gattc_client == NULL) {
3532 ERR("GATT client conn info not found");
3536 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3537 info = (hal_gattc_server_info_t*)l->data;
3541 if ((info->inst_id == gattc_client->inst_id) &&
3542 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3549 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3550 gboolean auto_connect)
3552 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3553 gchar *device_path = NULL;
3554 GDBusProxy *device_proxy = NULL;
3555 GDBusConnection *conn;
3556 int ret = BT_STATUS_SUCCESS;
3557 hal_gattc_client_info_t *gattc_data;
3559 if (NULL == bd_addr) {
3560 ERR("bd_addr is NULL");
3561 return BT_STATUS_PARM_INVALID;
3564 conn = _bt_hal_get_system_gconn();
3566 ERR("_bt_gdbus_get_system_gconn returned NULL");
3567 return BT_STATUS_FAIL;
3570 _bt_hal_convert_addr_type_to_string(device_address,
3571 (unsigned char *)bd_addr->address);
3572 device_path = _bt_hal_get_device_object_path(device_address);
3573 if (device_path == NULL) {
3574 ERR("device_path NULL : [%s]", device_address);
3575 ret = BT_STATUS_FAIL;
3579 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3580 NULL, BT_HAL_BLUEZ_NAME,
3581 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3582 g_free(device_path);
3583 if (NULL == device_proxy) {
3584 ERR("device_proxy returned NULL");
3585 return BT_STATUS_FAIL;
3588 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3589 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3590 BT_HAL_ADDRESS_LENGTH_MAX);
3592 DBG("ConnectLE [%s]", device_address);
3594 gattc_data->client_if = client_if;
3596 g_dbus_proxy_call(device_proxy, "ConnectLE",
3597 g_variant_new("(b)", auto_connect),
3598 G_DBUS_CALL_FLAGS_NONE,
3599 BT_HAL_MAX_DBUS_TIMEOUT,
3601 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3606 static bt_status_t _bt_hold_current_advertising()
3608 int ret = BT_STATUS_FAIL;
3609 gboolean is_advertising = FALSE;
3612 if (_bt_hal_is_support_multi_adv() == TRUE) {
3613 DBG("VSC adv used");
3614 return BT_STATUS_SUCCESS;
3617 /* Dependent on Kernel operation. Hold adv to prevent stopping adv on kernel */
3618 is_advertising = _bt_hal_is_advertising_in_slot(0);
3619 if (is_advertising) {
3620 DBG("+ Stop current advertising");
3622 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3623 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3629 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3631 DBG("+ start current advertising");
3633 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3638 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3640 DBG("Try to initiate pending LE connection");
3642 pending_le_conn_timer_id = 0;
3644 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3645 &pending_le_conn_info->bd_addr,
3646 pending_le_conn_info->auto_connect);
3648 g_free(pending_le_conn_info);
3649 pending_le_conn_info = NULL;
3654 static int __hal_generate_conn_id()
3656 return ++hal_gatt_conn_id;
3659 static int __hal_generate_server_instance_id()
3661 return ++bt_inst_id;
3664 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3667 GError *g_error = NULL;
3668 GVariant *reply = NULL;
3669 hal_gattc_client_info_t *gattc_data = user_data;
3670 int result = BT_STATUS_SUCCESS;
3671 struct hal_ev_gatt_client_connected ev;
3672 hal_gattc_server_info_t *gatt_conn_info = NULL;
3674 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3675 g_object_unref(proxy);
3676 if (reply == NULL) {
3677 ERR("Connect LE Dbus Call Error");
3679 ERR("Error: %s\n", g_error->message);
3680 g_clear_error(&g_error);
3682 result = BT_STATUS_FAIL;
3684 g_variant_unref(reply);
3686 if (NULL == gattc_data) {
3687 ERR("gattc_data is NULL");
3692 if (result == BT_STATUS_FAIL) {
3693 memset(&ev, 0, sizeof(ev));
3696 ev.client_if = gattc_data->client_if;
3697 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3698 BT_HAL_ADDRESS_LENGTH_MAX);
3701 ERR("gatt client callback not registered");
3703 DBG("sending gatt client connected event");
3704 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3710 DBG("LE connected. Adding the gattc server/client conn info in list");
3711 gattc_data->conn_id = __hal_generate_conn_id() ;
3712 gattc_data->inst_id = __hal_generate_server_instance_id();
3714 #ifndef __INTEGRATE_HAL_GATT_INFO__
3715 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3718 /*add gatt server connection info*/
3719 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3720 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3721 gatt_conn_info->conn_id = gattc_data->conn_id;
3722 gatt_conn_info->inst_id = gattc_data->inst_id;
3723 #ifdef __INTEGRATE_HAL_GATT_INFO__
3724 gatt_conn_info->client_if = gattc_data->client_if;
3726 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3731 /*remove conn_info*/
3736 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3738 g_free(desc_info->desc_path);
3742 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3745 hal_gattc_desc_t *desc_info = NULL;
3746 for (l = char_info->gatt_list_descs; l != NULL; ) {
3747 desc_info = l->data;
3748 l = g_slist_next(l);
3749 if (desc_info == NULL)
3751 /* Remove descriptor element */
3752 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3753 __hal_gattc_free_desc_info(desc_info);
3755 g_slist_free(char_info->gatt_list_descs);
3756 g_free(char_info->chr_path);
3760 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3763 hal_gattc_char_t *char_info = NULL;
3764 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3765 char_info = l->data;
3766 l = g_slist_next(l);
3767 if (char_info == NULL)
3769 /* Remove characteristic element */
3770 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3771 __hal_gattc_free_char_info(char_info);
3773 g_slist_free(svc_info->gatt_list_chars);
3774 g_free(svc_info->svc_path);
3778 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3781 hal_gattc_service_t *svc_info = NULL;
3785 for (l = conn_info->gatt_list_services; l != NULL; ) {
3786 svc_info = (hal_gattc_service_t *)l->data;
3787 l = g_slist_next(l);
3788 if (svc_info == NULL)
3790 /* Remove service element */
3791 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3792 __hal_gattc_free_svc_info(svc_info);
3794 g_slist_free(conn_info->gatt_list_services);
3798 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3800 bt_bdaddr_t bd_addr;
3801 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3802 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3808 int _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3810 int result = BT_STATUS_SUCCESS;
3811 struct hal_ev_gatt_client_connected ev;
3812 hal_gattc_server_info_t *conn_info = NULL;
3813 bt_bdaddr_t bd_addr;
3815 hal_gattc_client_info_t *gattc_client = NULL;
3816 #ifndef __INTEGRATE_HAL_GATT_INFO__
3820 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3821 HAL_EV_GATT_CLIENT_DISCONNECTED;
3823 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3824 /* find the gatt client info */
3825 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3826 if (NULL == gattc_client) {
3827 ERR("Fail to get gatt client info");
3831 gattc_client->is_gatt_connected = gatt_connected;
3834 memset(&ev, 0, sizeof(ev));
3835 ev.conn_id = gattc_client->conn_id;
3837 ev.client_if = gattc_client->client_if;
3838 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3839 BT_HAL_ADDRESS_LENGTH_MAX);
3842 ERR("gatt client callback not registered");
3844 event_cb(event, (void *)&ev, sizeof(ev));
3847 if (!gatt_connected) {
3848 #ifndef __INTEGRATE_HAL_GATT_INFO__
3849 inst_id = gattc_client->inst_id;
3851 /* remove the gatt client info from the client list also*/
3852 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3853 g_free(gattc_client);
3856 //find the connected server info
3857 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3858 if (NULL == conn_info) {
3859 ERR("Fail to get gatt server info");
3863 #ifndef __INTEGRATE_HAL_GATT_INFO__
3864 if (inst_id != conn_info->inst_id) {
3865 ERR("server instance is different");
3870 //remove gatt conn info from the server list
3871 DBG("remove the server conn_info from list after gatt disconnection");
3872 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3873 __hal_clean_gattc_server_info(conn_info);
3879 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3880 const char* uuid_str, int inst_id)
3882 struct hal_ev_gatt_client_search_result ev;
3885 ERR("gatt client callback not registered");
3889 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3891 memset(&ev, 0, sizeof(ev));
3892 ev.conn_id = conn_id;
3893 ev.inst_id = inst_id;
3894 ev.is_primary = is_primary;
3895 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3897 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3900 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3902 struct hal_ev_gatt_client_search_complete ev;
3905 ERR("gatt client callback not registered");
3909 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3912 memset(&ev, 0, sizeof(ev));
3913 ev.conn_id = conn_id;
3916 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3919 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3920 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3921 char *char_value, int len)
3923 struct hal_ev_gatt_client_notify_changed_value ev;
3924 hal_gattc_client_info_t *gattc_client = NULL;
3927 ERR("gatt client callback not registered");
3931 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3932 if (NULL == gattc_client) {
3933 ERR("failed to get the gatt client info");
3938 DBG("sending gatt client connected status event");
3939 memset(&ev, 0, sizeof(ev));
3941 ev.conn_id = gattc_client->conn_id;
3942 ev.inst_id = conn_info->inst_id;
3943 ev.is_primary = svc_info->is_primary;
3944 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3945 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3947 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3949 if (len > 0 && (char_value != NULL)) {
3950 memcpy(ev.value, char_value, len);
3954 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3957 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3958 char *char_value, int len)
3960 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3961 hal_gattc_server_info_t *conn_info = NULL;
3962 bt_bdaddr_t bd_addr;
3965 hal_gattc_service_t *svc_info = NULL;
3966 hal_gattc_char_t *char_info = NULL;
3970 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3971 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3972 DBG("device address:[%s]", device_address);
3973 DBG("char handle:[%s]", char_handle);
3975 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3976 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3978 if (conn_info != NULL) {
3979 //find service for notified char path
3980 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3981 svc_info = (hal_gattc_service_t*)l->data;
3982 if (svc_info == NULL)
3985 /* find characteristic object path */
3986 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3987 char_info = (hal_gattc_char_t *)k->data;
3988 if (char_info == NULL)
3991 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3992 DBG("Found char handle[%s]", char_info->chr_path);
3995 _bt_hal_send_value_changed_event(conn_info, svc_info,
3996 char_info, char_value, len);
4004 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
4006 GDBusConnection *g_conn = NULL;
4007 GDBusProxy *properties_proxy = NULL;
4008 GVariant *result = NULL;
4009 GError *error = NULL;
4010 GVariantIter *property_iter = NULL;
4011 const gchar *key = NULL;
4012 GVariant *value = NULL;
4013 const char *uuid_str = NULL;
4015 gboolean is_primary = FALSE;
4016 GVariantIter *char_iter = NULL;
4017 const char *char_handle = NULL;
4018 GPtrArray *gp_char_array = NULL;
4020 if (service_path == NULL) {
4021 ERR("service_path is NULL");
4022 return BT_STATUS_FAIL;
4025 DBG("service_path: %s", service_path);
4027 g_conn = _bt_hal_get_system_gconn();
4028 if (g_conn == NULL) {
4029 ERR("g_conn is NULL");
4030 return BT_STATUS_FAIL;
4033 properties_proxy = g_dbus_proxy_new_sync(g_conn,
4034 G_DBUS_PROXY_FLAGS_NONE, NULL,
4037 BT_HAL_PROPERTIES_INTERFACE,
4039 if (properties_proxy == NULL) {
4040 ERR("properties_proxy is NULL");
4041 return BT_STATUS_FAIL;
4044 result = g_dbus_proxy_call_sync(properties_proxy,
4046 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
4047 G_DBUS_CALL_FLAGS_NONE,
4049 if (result == NULL) {
4050 if (error != NULL) {
4051 ERR("Fail to get properties (Error: %s)", error->message);
4052 g_clear_error(&error);
4054 ERR("Fail to get properties");
4056 g_object_unref(properties_proxy);
4057 return BT_STATUS_FAIL;
4060 g_variant_get(result, "(a{sv})", &property_iter);
4062 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
4063 if (g_strcmp0(key, "UUID") == 0) {
4064 uuid_str = g_variant_get_string(value, &len);
4065 } else if (g_strcmp0(key, "Primary") == 0) {
4066 is_primary = g_variant_get_boolean(value);
4067 } else if (g_strcmp0(key, "Characteristics") == 0) {
4068 g_variant_get(value, "ao", &char_iter);
4069 if (char_iter != NULL) {
4070 if (gp_char_array == NULL)
4071 gp_char_array = g_ptr_array_new();
4073 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
4074 DBG("char_handle: %s", char_handle);
4075 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
4077 g_variant_iter_free(char_iter);
4082 if (uuid_str == NULL || gp_char_array == NULL) {
4083 ERR("uuid_str and gp_char_array should be set");
4087 /* Create new service */
4088 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
4091 g_variant_iter_free(property_iter);
4092 g_variant_unref(result);
4093 g_object_unref(properties_proxy);
4095 return BT_STATUS_SUCCESS;
4098 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
4100 GDBusConnection *conn = NULL;
4101 GDBusProxy *proxy = NULL;
4103 GVariant *ret = NULL;
4104 GVariant *value = NULL;
4106 conn = _bt_hal_get_system_gconn();
4108 ERR("_bt_gdbus_get_system_gconn returned NULL");
4112 proxy = g_dbus_proxy_new_sync(conn,
4113 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
4114 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
4115 if (proxy == NULL) {
4116 ERR("device_proxy returned NULL");
4120 ret = g_dbus_proxy_call_sync(proxy, "Get",
4121 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
4122 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
4124 ERR("DBus Error : %s", err->message);
4125 g_clear_error(&err);
4127 g_variant_get(ret, "(v)", &value);
4128 *service_uuid = g_variant_dup_string(value, NULL);
4129 g_variant_unref(value);
4130 g_variant_unref(ret);
4134 g_object_unref(proxy);
4139 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
4141 struct hal_ev_gatt_client_service_changed ev = {0, };
4142 char address[BT_HAL_ADDRESS_STRING_SIZE];
4143 hal_gattc_server_info_t *server_info = NULL;
4144 hal_gattc_client_info_t *gattc_client = NULL;
4145 hal_gattc_service_t *service = NULL;
4146 GSList *list = NULL;
4147 char *uuid_str = NULL;
4149 _bt_hal_convert_device_path_to_address(path, address);
4150 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
4151 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
4152 if (server_info == NULL) {
4153 ERR("server_info is NULL");
4157 gattc_client = __bt_find_gatt_client_info((bt_bdaddr_t *)ev.bdaddr);
4158 if (gattc_client == NULL) {
4159 ERR("gattc_client is NULL");
4163 if (server_info->is_gatt_connected == FALSE && gattc_client->is_gatt_connected == FALSE) {
4164 DBG("GattConnected signal is not received yet. Just skip [%d %d]",
4165 server_info->is_gatt_connected, gattc_client->is_gatt_connected);
4170 /* Get service UUID from path */
4171 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
4173 INFO("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
4174 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
4177 ERR("uuid_str is NULL");
4181 /* Create new service and append into the list */
4182 __hal_gattc_get_service_info(server_info, path);
4184 /* Find service UUID from path */
4185 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4186 service = (hal_gattc_service_t *)list->data;
4187 if (service == NULL)
4190 if (g_strcmp0(service->svc_path, path) == 0) {
4191 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4192 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4193 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4194 INFO("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
4196 /* Remove service info in list */
4197 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4198 __hal_gattc_free_svc_info(service);
4206 ERR("uuid_str is NULL");
4211 /* Send GATT Client service changed event */
4212 ev.change_type = is_added;
4213 ev.conn_id = server_info->conn_id;
4214 ev.inst_id = server_info->inst_id;
4215 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));