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);
937 g_variant_iter_free(char_iter);
943 _bt_hal_send_search_service_result_event(conn_id, is_primary,
944 uuid_str, conn_info->inst_id);
946 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
951 if (gp_array->len == 0 || svc_count == 0) {
952 ERR("gp_array is NULL");
953 ret = BT_STATUS_FAIL;
955 ret = BT_STATUS_SUCCESS;
958 browse_service_char(conn_id);
959 /* send search service complete event */
960 _bt_hal_send_search_service_complete_event(conn_id, ret);
962 g_ptr_array_free(gp_array, TRUE);
963 g_variant_iter_free(iter);
964 g_variant_unref(result);
969 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
971 if (NULL == filter_uuid) {
972 DBG("Browse all the services");
973 return _gattc_client_search_service(conn_id);
975 DBG("TODO implement it");
976 return BT_STATUS_UNSUPPORTED;
980 * Enumerate included services for a given service.
981 * Set start_incl_srvc_id to NULL to get the first included service.
983 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
984 btgatt_srvc_id_t *start_incl_srvc_id)
987 return BT_STATUS_UNSUPPORTED;
990 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
991 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
993 struct hal_ev_gatt_client_char_search_result ev;
996 ERR("gatt client callback not registered");
1000 memset(&ev, 0, sizeof(ev));
1001 ev.conn_id = conn_id;
1002 ev.inst_id = svc_id->id.inst_id;
1003 ev.is_primary = svc_id->is_primary;
1005 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1007 if (status == BT_STATUS_SUCCESS) {
1008 /* building char uuid */
1009 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
1010 ev.char_prop = char_prop;
1013 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
1014 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1017 static int _hal_get_permission_flag(char *permission)
1021 if (NULL == permission) {
1022 ERR("gatt permission is NULL");
1026 if (!g_strcmp0(permission, "broadcast"))
1027 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
1028 else if (!g_strcmp0(permission, "read"))
1029 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
1030 else if (!g_strcmp0(permission, "write-without-response"))
1031 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1032 else if (!g_strcmp0(permission, "write"))
1033 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1034 else if (!g_strcmp0(permission, "notify"))
1035 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1036 else if (!g_strcmp0(permission, "indicate"))
1037 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
1038 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
1039 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
1040 else if (!g_strcmp0(permission, "reliable-write"))
1041 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
1042 else if (!g_strcmp0(permission, "writable-auxiliaries"))
1043 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1044 else if (!g_strcmp0(permission, "encrypt-read"))
1045 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1046 else if (!g_strcmp0(permission, "encrypt-write"))
1047 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1048 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1049 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1050 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1051 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1056 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1058 char perm[200] = { 0, };
1060 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1061 g_strlcat(perm, "broadcast ", sizeof(perm));
1062 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1063 g_strlcat(perm, "read ", sizeof(perm));
1064 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1065 g_strlcat(perm, "write-without-response ", sizeof(perm));
1066 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1067 g_strlcat(perm, "write ", sizeof(perm));
1068 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1069 g_strlcat(perm, "notify ", sizeof(perm));
1070 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1071 g_strlcat(perm, "indicate ", sizeof(perm));
1072 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1073 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1074 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1075 g_strlcat(perm, "reliable-write ", sizeof(perm));
1076 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1077 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1078 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1079 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1080 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1081 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1082 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1083 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1084 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1085 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1087 DBG("permission [0x%04x] : %s\n", permission, perm);
1091 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1093 GDBusProxy *properties_proxy = NULL;
1094 GError *error = NULL;
1095 GVariant *value = NULL;
1096 GVariant *result = NULL;
1097 GDBusConnection *g_conn;
1099 char *char_desc_handle = NULL;
1101 GVariantIter *property_iter;
1102 GVariantIter *char_desc_iter;
1103 char* char_handle = NULL;
1104 gchar *char_uuid_str = NULL;
1105 GPtrArray *gp_desc_array = NULL;
1106 GVariantIter *char_perm_iter;
1108 unsigned int char_permission = 0 ;
1110 if (gattc_char->chr_path == NULL) {
1111 DBG("char path is NULL");
1112 return BT_STATUS_FAIL;
1114 char_handle = gattc_char->chr_path;
1116 g_conn = _bt_hal_get_system_gconn();
1117 if (NULL == g_conn) {
1118 ERR("_bt_gdbus_get_system_gconn returned NULL");
1119 return BT_STATUS_FAIL;
1122 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1123 G_DBUS_PROXY_FLAGS_NONE, NULL,
1126 BT_HAL_PROPERTIES_INTERFACE,
1129 if (properties_proxy == NULL) {
1130 ERR("properties_proxy returned NULL");
1131 return BT_STATUS_FAIL;
1134 result = g_dbus_proxy_call_sync(properties_proxy,
1136 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1137 G_DBUS_CALL_FLAGS_NONE,
1142 if (error != NULL) {
1143 ERR("Fail to get properties (Error: %s)", error->message);
1144 g_clear_error(&error);
1146 ERR("Fail to get properties");
1147 g_object_unref(properties_proxy);
1148 return BT_STATUS_FAIL;
1151 gp_desc_array = g_ptr_array_new();
1153 g_variant_get(result, "(a{sv})", &property_iter);
1155 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1156 if (!g_strcmp0(key, "UUID")) {
1157 char_uuid_str = g_variant_dup_string(value, &len);
1158 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1159 } else if (!g_strcmp0(key, "Flags")) {
1160 g_variant_get(value, "as", &char_perm_iter);
1161 char_permission = 0x00;
1163 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1164 char_permission |= _hal_get_permission_flag(permission);
1166 __hal_convert_permission_flag_to_str(char_permission);
1167 g_variant_iter_free(char_perm_iter);
1168 } else if (!g_strcmp0(key, "Descriptors")) {
1169 g_variant_get(value, "ao", &char_desc_iter);
1170 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1171 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1173 g_variant_iter_free(char_desc_iter);
1177 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1179 g_free(char_uuid_str);
1180 g_variant_iter_free(property_iter);
1181 g_variant_unref(result);
1182 g_object_unref(properties_proxy);
1183 g_ptr_array_free(gp_desc_array, TRUE);
1185 return BT_STATUS_SUCCESS;
1188 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1189 btgatt_srvc_id_t *srvc_id)
1191 hal_gattc_server_info_t * conn_info = NULL;
1192 hal_gattc_service_t *gattc_service = NULL;
1194 hal_gattc_char_t *gattc_char = NULL;
1195 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1196 int status = BT_STATUS_FAIL;
1198 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1199 if (NULL == conn_info) {
1200 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1201 return BT_STATUS_FAIL;
1205 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1206 if (NULL == gattc_service) {
1207 ERR("Failed to get the gatt service");
1208 return BT_STATUS_FAIL;
1211 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1212 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1214 /* find characteristic object path */
1215 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1216 gattc_char = (hal_gattc_char_t *)l->data;
1217 status = _hal_gattc_get_characteristic_info(gattc_char);
1220 if (BT_STATUS_SUCCESS == status) {
1221 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1222 &gattc_char->chr_uuid, gattc_char->permission);
1226 status = BT_STATUS_FAIL;
1227 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1229 browse_service_char(conn_id);
1230 /* retrive uuid for characteristic and object path for descriptor */
1232 return BT_STATUS_SUCCESS;
1236 * Enumerate characteristics for a given service.
1237 * Set start_char_id to NULL to get the first characteristic.
1239 bt_status_t btif_gattc_get_characteristic(int conn_id,
1240 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1242 CHECK_BTGATT_INIT();
1244 if (start_char_id == NULL) {
1245 return _gattc_get_all_characteristic(conn_id, srvc_id);
1248 DBG("TBD Get specific characteristics");
1249 return BT_STATUS_UNSUPPORTED;
1253 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1255 GDBusProxy *properties_proxy = NULL;
1256 GError *error = NULL;
1257 GVariant *value = NULL;
1258 GVariant *result = NULL;
1259 GDBusConnection *g_conn;
1262 GVariantIter *property_iter;
1263 char* desc_handle = NULL;
1264 const gchar *desc_uuid_str = NULL;
1266 if (gattc_desc->desc_path == NULL) {
1267 DBG("desc path is NULL");
1268 return BT_STATUS_FAIL;
1270 desc_handle = gattc_desc->desc_path;
1272 g_conn = _bt_hal_get_system_gconn();
1273 if (NULL == g_conn) {
1274 ERR("_bt_gdbus_get_system_gconn returned NULL");
1275 return BT_STATUS_FAIL;
1278 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1279 G_DBUS_PROXY_FLAGS_NONE, NULL,
1282 BT_HAL_PROPERTIES_INTERFACE,
1285 if (properties_proxy == NULL) {
1286 ERR("properties_proxy returned NULL");
1287 return BT_STATUS_FAIL;
1290 result = g_dbus_proxy_call_sync(properties_proxy,
1292 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1293 G_DBUS_CALL_FLAGS_NONE,
1298 if (error != NULL) {
1299 ERR("Fail to get properties (Error: %s)", error->message);
1300 g_clear_error(&error);
1302 ERR("Fail to get properties");
1303 g_object_unref(properties_proxy);
1304 return BT_STATUS_FAIL;
1307 g_variant_get(result, "(a{sv})", &property_iter);
1309 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1310 if (!g_strcmp0(key, "UUID")) {
1311 desc_uuid_str = g_variant_get_string(value, &len);
1312 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1314 g_free((gchar *)key);
1315 g_variant_unref(value);
1320 g_variant_iter_free(property_iter);
1321 g_variant_unref(result);
1322 g_object_unref(properties_proxy);
1324 return BT_STATUS_SUCCESS;
1327 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1328 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1330 struct hal_ev_gatt_client_desc_search_result ev;
1333 ERR("gatt client callback not registered");
1337 memset(&ev, 0, sizeof(ev));
1338 ev.conn_id = conn_id;
1339 ev.inst_id = svc_id->id.inst_id;
1340 ev.is_primary = svc_id->is_primary;
1343 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1344 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1346 if (status == BT_STATUS_SUCCESS) {
1347 /* building desc uuid */
1348 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1351 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1353 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1356 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1357 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1359 hal_gattc_server_info_t * conn_info = NULL;
1360 hal_gattc_service_t *gattc_service = NULL;
1363 hal_gattc_char_t *gattc_char = NULL;
1364 hal_gattc_desc_t *gattc_desc = NULL;
1365 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1366 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1367 int status = BT_STATUS_FAIL;
1369 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1370 if (NULL == conn_info) {
1371 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1372 return BT_STATUS_FAIL;
1376 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1377 if (NULL == gattc_service) {
1378 ERR("Failed to get the gatt service");
1379 return BT_STATUS_FAIL;
1382 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1383 // DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1385 /* find characteristics */
1386 /* a service can have two char with same uuid */
1387 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1388 gattc_char = (hal_gattc_char_t*)l->data;
1389 if (gattc_char == NULL)
1392 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1393 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1394 // DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1396 /* get descriptor uuid */
1397 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1398 gattc_desc = (hal_gattc_desc_t *)m->data;
1399 if (gattc_desc == NULL)
1402 status = _hal_gattc_get_descriptor_info(gattc_desc);
1405 if (BT_STATUS_SUCCESS == status) {
1406 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1407 char_id, &gattc_desc->desc_uuid);
1413 status = BT_STATUS_FAIL;
1414 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1416 browse_service_char(conn_id);
1417 /* retrive uuid for characteristic and object path for descriptor */
1419 return BT_STATUS_SUCCESS;
1423 * Enumerate descriptors for a given characteristic.
1424 * Set start_descr_id to NULL to get the first descriptor.
1426 bt_status_t btif_gattc_get_descriptor(int conn_id,
1427 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1428 btgatt_gatt_id_t *start_descr_id)
1430 CHECK_BTGATT_INIT();
1432 if (start_descr_id == NULL) {
1433 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1435 DBG("TBD Get specific descriptor");
1436 return BT_STATUS_UNSUPPORTED;
1440 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1442 struct hal_ev_gatt_client_read_data ev;
1445 ERR("gatt client callback not registered");
1449 memset(&ev, 0, sizeof(ev));
1450 ev.conn_id = resp_data->conn_id;
1451 ev.inst_id = resp_data->srvc_id.id.inst_id;
1452 ev.is_primary = resp_data->srvc_id.is_primary;
1455 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1456 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1460 /* building the char read value */
1461 memcpy(ev.value, value, len);
1464 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1466 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1469 static void __hal_internal_read_char_cb(GObject *source_object,
1470 GAsyncResult *res, gpointer user_data)
1472 GError *error = NULL;
1473 GDBusConnection *system_gconn = NULL;
1476 GByteArray *gp_byte_array = NULL;
1478 hal_gatt_resp_data_t *resp_data = user_data;
1479 int result = BT_STATUS_SUCCESS;
1481 system_gconn = _bt_hal_get_system_gconn();
1482 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1485 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1488 result = BT_STATUS_FAIL;
1489 __hal_send_char_read_event(resp_data, result, NULL, 0);
1490 g_clear_error(&error);
1495 gp_byte_array = g_byte_array_new();
1496 g_variant_get(value, "(ay)", &iter);
1498 while (g_variant_iter_loop(iter, "y", &g_byte))
1499 g_byte_array_append(gp_byte_array, &g_byte, 1);
1503 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1507 g_byte_array_free(gp_byte_array, TRUE);
1508 g_variant_iter_free(iter);
1509 g_variant_unref(value);
1513 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1514 btgatt_gatt_id_t *char_id, int auth_req)
1516 GDBusConnection *g_conn;
1517 hal_gatt_resp_data_t *resp_data;
1518 hal_gattc_service_t *gattc_service = NULL;
1519 GVariantBuilder *builder = NULL;
1521 hal_gattc_server_info_t * conn_info = NULL;
1522 hal_gattc_char_t *gattc_char = NULL;
1523 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1524 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1525 char* char_handle = NULL;
1527 /* get the connection info */
1528 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1529 if (NULL == conn_info) {
1530 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1531 return BT_STATUS_FAIL;
1535 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1536 if (NULL == gattc_service) {
1537 ERR("Failed to get the gatt service");
1538 return BT_STATUS_FAIL;
1541 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1543 /* find characteristic */
1544 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1545 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1546 if (NULL == gattc_char) {
1547 ERR("Failed to get the gatt char");
1548 return BT_STATUS_FAIL;
1551 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1552 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1554 g_conn = _bt_hal_get_system_gconn();
1555 if (NULL == g_conn) {
1556 ERR("_bt_gdbus_get_system_gconn returned NULL");
1557 return BT_STATUS_FAIL;
1560 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1561 resp_data->conn_id = conn_id;
1562 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1563 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1565 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1568 g_variant_builder_add(builder, "{sv}", "offset",
1569 g_variant_new("q", offset));
1571 char_handle = gattc_char->chr_path;
1573 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1574 "ReadValue", g_variant_new("(a{sv})", builder),
1575 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1576 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1577 (gpointer)resp_data);
1578 g_variant_builder_unref(builder);
1580 return BT_STATUS_SUCCESS;
1583 /** Read a characteristic on a remote device */
1584 bt_status_t btif_read_characteristic(int conn_id,
1585 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1588 CHECK_BTGATT_INIT();
1590 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1593 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1595 struct hal_ev_gatt_client_write_result ev;
1598 ERR("gatt client callback not registered");
1602 memset(&ev, 0, sizeof(ev));
1603 ev.conn_id = resp_data->conn_id;
1604 ev.inst_id = resp_data->srvc_id.id.inst_id;
1605 ev.is_primary = resp_data->srvc_id.is_primary;
1608 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1609 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1611 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1614 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1615 GAsyncResult *res, gpointer user_data)
1617 GError *error = NULL;
1618 GDBusConnection *system_gconn = NULL;
1620 hal_gatt_resp_data_t *resp_data = user_data;
1621 int result = BT_STATUS_SUCCESS;
1623 system_gconn = _bt_hal_get_system_gconn();
1624 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1627 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1629 result = BT_STATUS_FAIL;
1631 __hal_send_char_write_event(resp_data, result);
1632 g_clear_error(&error);
1637 //send write value event
1638 __hal_send_char_write_event(resp_data, result);
1641 g_variant_unref(value);
1645 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1648 case HAL_GATT_WRITE_TYPE_WRITE:
1649 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1651 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1652 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1655 ERR("Unknow write type : %d", type);
1656 return BT_STATUS_FAIL;
1659 return BT_STATUS_SUCCESS;
1663 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1665 GDBusConnection *conn;
1666 GVariantBuilder *builder = NULL;
1672 GUnixFDList *fd_list = NULL;
1674 conn = _bt_hal_get_system_gconn();
1676 ERR("_bt_gdbus_get_system_gconn returned NULL");
1677 return BT_STATUS_FAIL;
1680 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1681 //val = g_variant_new("ay", builder1);
1683 g_variant_builder_add(builder, "{sv}", "offset",
1684 g_variant_new("q", offset));
1686 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1687 "AcquireWrite", g_variant_new("(a{sv})", builder),
1688 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1689 NULL, &fd_list, NULL, &err);
1691 g_dbus_error_strip_remote_error(err);
1692 ERR("Error: %s", err->message);
1694 g_variant_builder_unref(builder);
1695 return BT_STATUS_FAIL;
1698 g_variant_get(value, "(hq)", &idx, &att_mtu);
1699 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1701 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1704 g_object_unref(fd_list);
1705 g_variant_unref(value);
1706 g_variant_builder_unref(builder);
1708 return BT_STATUS_SUCCESS;
1711 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1713 GDBusConnection *conn;
1714 GVariantBuilder *builder = NULL;
1718 gint32 idx, notify_fd;
1720 GUnixFDList *fd_list = NULL;
1722 conn = _bt_hal_get_system_gconn();
1725 ERR("_bt_gdbus_get_system_gconn returned NULL");
1726 return BT_STATUS_FAIL;
1730 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1733 g_variant_builder_add(builder, "{sv}", "offset",
1734 g_variant_new("q", offset));
1736 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1737 "AcquireNotify", g_variant_new("(a{sv})", builder),
1738 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1739 NULL, &fd_list, NULL, &err);
1741 g_dbus_error_strip_remote_error(err);
1742 ERR("Error: %s", err->message);
1744 g_variant_builder_unref(builder);
1745 return BT_STATUS_FAIL;
1748 g_variant_get(value, "(hq)", &idx, &att_mtu);
1749 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1752 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1756 g_object_unref(fd_list);
1757 g_variant_unref(value);
1758 g_variant_builder_unref(builder);
1760 return BT_STATUS_SUCCESS;
1764 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1765 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1767 GVariant *val, *options;
1768 GVariantBuilder *builder1;
1769 GVariantBuilder *builder2;
1770 GDBusConnection *g_conn;
1773 hal_gatt_resp_data_t *resp_data;
1774 hal_gattc_service_t *gattc_service = NULL;
1775 hal_gattc_server_info_t * conn_info = NULL;
1776 hal_gattc_char_t *gattc_char = NULL;
1777 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1778 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1779 char* char_handle = NULL;
1780 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1781 int ret = BT_STATUS_SUCCESS;
1783 ret = __hal_get_write_prop(write_type, &write_prop);
1784 if (BT_STATUS_FAIL == ret) {
1785 DBG("received invalid write type:[%d] ", write_type);
1786 return BT_STATUS_FAIL;
1789 /* get the connection info */
1790 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1791 if (NULL == conn_info) {
1792 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1793 return BT_STATUS_FAIL;
1797 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1798 if (NULL == gattc_service) {
1799 ERR("Failed to get the gatt service");
1800 return BT_STATUS_FAIL;
1803 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1804 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1806 /* find characteristic */
1807 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1808 if (NULL == gattc_char) {
1809 ERR("Failed to get the gatt char");
1810 return BT_STATUS_FAIL;
1813 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1814 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1816 g_conn = _bt_hal_get_system_gconn();
1817 if (NULL == g_conn) {
1818 ERR("_bt_gdbus_get_system_gconn returned NULL");
1819 return BT_STATUS_FAIL;
1822 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1823 resp_data->conn_id = conn_id;
1824 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1825 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1827 char_handle = gattc_char->chr_path;
1829 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1831 for (i = 0; i < length; i++)
1832 g_variant_builder_add(builder1, "y", value[i]);
1834 val = g_variant_new("ay", builder1);
1836 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1838 g_variant_builder_add(builder2, "{sv}", "offset",
1839 g_variant_new_uint16(offset));
1841 options = g_variant_new("a{sv}", builder2);
1843 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1845 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1847 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1848 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1849 (gpointer)resp_data);
1851 g_variant_builder_unref(builder1);
1852 g_variant_builder_unref(builder2);
1854 return BT_STATUS_SUCCESS;
1857 bt_status_t btif_get_acquire_write_fd(int conn_id,
1858 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1859 int auth_req, int *fd, int*mtu)
1861 CHECK_BTGATT_INIT();
1863 hal_gattc_service_t *gattc_service = NULL;
1864 hal_gattc_server_info_t * conn_info = NULL;
1865 hal_gattc_char_t *gattc_char = NULL;
1866 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1868 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1869 int ret = BT_STATUS_SUCCESS;
1871 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1873 /* get the connection info */
1874 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1875 if (NULL == conn_info) {
1876 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1877 return BT_STATUS_FAIL;
1881 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1882 if (NULL == gattc_service) {
1883 ERR("Failed to get the gatt service");
1884 return BT_STATUS_FAIL;
1887 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1888 if (NULL == gattc_char) {
1889 ERR("Failed to get the gatt char");
1890 return BT_STATUS_FAIL;
1893 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1894 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1896 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1897 if (ret != BT_STATUS_SUCCESS)
1903 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1904 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1906 CHECK_BTGATT_INIT();
1908 hal_gattc_service_t *gattc_service = NULL;
1909 hal_gattc_server_info_t * conn_info = NULL;
1910 hal_gattc_char_t *gattc_char = NULL;
1911 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1913 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1914 int ret = BT_STATUS_SUCCESS;
1916 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1918 /* get the connection info */
1919 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1920 if (NULL == conn_info) {
1921 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1922 return BT_STATUS_FAIL;
1926 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1927 if (NULL == gattc_service) {
1928 ERR("Failed to get the gatt service");
1929 return BT_STATUS_FAIL;
1932 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1933 if (NULL == gattc_char) {
1934 ERR("Failed to get the gatt char");
1935 return BT_STATUS_FAIL;
1938 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1939 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1941 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1942 if (ret != BT_STATUS_SUCCESS)
1949 /** Write a remote characteristic */
1950 bt_status_t btif_write_characteristic(int conn_id,
1951 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1952 int write_type, int len, int auth_req,
1955 CHECK_BTGATT_INIT();
1957 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1958 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1959 len, auth_req, p_value);
1962 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1964 struct hal_ev_gatt_client_read_data ev;
1967 ERR("gatt client callback not registered");
1971 memset(&ev, 0, sizeof(ev));
1972 ev.conn_id = resp_data->conn_id;
1973 ev.inst_id = resp_data->srvc_id.id.inst_id;
1974 ev.is_primary = resp_data->srvc_id.is_primary;
1977 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1978 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1979 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1983 /* building the desc read value */
1984 memcpy(ev.value, value, len);
1987 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1989 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1992 static void __hal_internal_read_desc_cb(GObject *source_object,
1993 GAsyncResult *res, gpointer user_data)
1995 GError *error = NULL;
1996 GDBusConnection *system_gconn = NULL;
1999 GByteArray *gp_byte_array = NULL;
2001 hal_gatt_resp_data_t *resp_data = user_data;
2002 int result = BT_STATUS_SUCCESS;
2007 system_gconn = _bt_hal_get_system_gconn();
2008 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2011 ERR("Read descriptor dbus failed Error:[%s]", error->message);
2014 result = BT_STATUS_FAIL;
2015 __hal_send_desc_read_event(resp_data, result, NULL, 0);
2016 g_clear_error(&error);
2021 gp_byte_array = g_byte_array_new();
2022 g_variant_get(value, "(ay)", &iter);
2024 while (g_variant_iter_loop(iter, "y", &g_byte))
2025 g_byte_array_append(gp_byte_array, &g_byte, 1);
2029 for (i = 0; i < gp_byte_array->len; i++)
2030 DBG("%02x", gp_byte_array->data[i]);
2033 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2037 g_byte_array_free(gp_byte_array, TRUE);
2038 g_variant_iter_free(iter);
2039 g_variant_unref(value);
2044 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2045 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2047 GDBusConnection *g_conn;
2048 hal_gatt_resp_data_t *resp_data;
2049 hal_gattc_service_t *gattc_service = NULL;
2050 GVariantBuilder *builder = NULL;
2052 hal_gattc_server_info_t * conn_info = NULL;
2053 hal_gattc_char_t *gattc_char = NULL;
2054 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2055 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2056 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2057 char* desc_handle = NULL;
2060 hal_gattc_desc_t *gattc_desc = NULL;
2062 /* get the connection info */
2063 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2064 if (NULL == conn_info) {
2065 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2066 return BT_STATUS_FAIL;
2070 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2071 if (NULL == gattc_service) {
2072 ERR("Failed to get the gatt service");
2073 return BT_STATUS_FAIL;
2076 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2077 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2079 /* find characteristic */
2080 /* service can have two char with same uuid */
2081 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2082 gattc_char = (hal_gattc_char_t*)l->data;
2083 if (gattc_char == NULL)
2086 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2087 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2088 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2090 /* find descriptor */
2091 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2093 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2094 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2100 if (NULL == gattc_desc) {
2101 ERR("Failed to get the gatt desc");
2102 return BT_STATUS_FAIL;
2105 g_conn = _bt_hal_get_system_gconn();
2106 if (NULL == g_conn) {
2107 ERR("_bt_gdbus_get_system_gconn returned NULL");
2108 return BT_STATUS_FAIL;
2111 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2112 resp_data->conn_id = conn_id;
2113 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2114 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2115 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2117 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2120 g_variant_builder_add(builder, "{sv}", "offset",
2121 g_variant_new("q", offset));
2123 desc_handle = gattc_desc->desc_path;
2125 DBG("calling desc read value");
2127 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2128 "ReadValue", g_variant_new("(a{sv})", builder),
2129 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2130 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2131 (gpointer)resp_data);
2132 g_variant_builder_unref(builder);
2134 return BT_STATUS_SUCCESS;
2137 /** Read the descriptor for a given characteristic */
2138 bt_status_t btif_read_descriptor(int conn_id,
2139 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2140 btgatt_gatt_id_t *descr_id, int auth_req)
2142 CHECK_BTGATT_INIT();
2144 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2147 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2149 struct hal_ev_gatt_client_write_result ev;
2152 ERR("gatt client callback not registered");
2156 memset(&ev, 0, sizeof(ev));
2157 ev.conn_id = resp_data->conn_id;
2158 ev.inst_id = resp_data->srvc_id.id.inst_id;
2159 ev.is_primary = resp_data->srvc_id.is_primary;
2162 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2163 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2164 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2166 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2168 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2171 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2172 GAsyncResult *res, gpointer user_data)
2174 GError *error = NULL;
2175 GDBusConnection *system_gconn = NULL;
2177 hal_gatt_resp_data_t *resp_data = user_data;
2178 int result = BT_STATUS_SUCCESS;
2182 system_gconn = _bt_hal_get_system_gconn();
2183 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2186 ERR("write descriptor dbus failed Error: [%s]", error->message);
2189 result = BT_STATUS_FAIL;
2190 __hal_send_desc_write_event(resp_data, result);
2191 g_clear_error(&error);
2196 //send write value event
2197 __hal_send_desc_write_event(resp_data, result);
2200 g_variant_unref(value);
2205 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2206 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2207 int write_type, int length, int auth_req, char* value)
2209 GVariant *val, *options;
2210 GVariantBuilder *builder1;
2211 GVariantBuilder *builder2;
2212 GDBusConnection *g_conn;
2215 hal_gatt_resp_data_t *resp_data;
2216 hal_gattc_service_t *gattc_service = NULL;
2217 hal_gattc_server_info_t * conn_info = NULL;
2218 hal_gattc_char_t *gattc_char = NULL;
2219 hal_gattc_desc_t *gattc_desc = NULL;
2220 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2221 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2222 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2223 char* desc_handle = NULL;
2224 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2225 int ret = BT_STATUS_SUCCESS;
2230 ret = __hal_get_write_prop(write_type, &write_prop);
2231 if (BT_STATUS_FAIL == ret) {
2232 ERR("received invalid write type:[%d] ", write_type);
2233 return BT_STATUS_FAIL;
2236 /* get the connection info */
2237 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2238 if (NULL == conn_info) {
2239 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2240 return BT_STATUS_FAIL;
2244 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2245 if (NULL == gattc_service) {
2246 ERR("Failed to get the gatt service");
2247 return BT_STATUS_FAIL;
2250 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2251 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2253 /* find characteristic */
2254 /* service can have two char with same uuid */
2255 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2256 gattc_char = (hal_gattc_char_t*)l->data;
2257 if (gattc_char == NULL)
2260 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2261 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2262 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2264 /* find descriptor */
2265 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2267 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2268 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2274 if (NULL == gattc_desc) {
2275 ERR("Failed to get the gatt desc");
2276 return BT_STATUS_FAIL;
2279 g_conn = _bt_hal_get_system_gconn();
2280 if (NULL == g_conn) {
2281 ERR("_bt_gdbus_get_system_gconn returned NULL");
2282 return BT_STATUS_FAIL;
2285 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2286 resp_data->conn_id = conn_id;
2287 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2288 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2289 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2291 desc_handle = gattc_desc->desc_path;
2293 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2295 for (i = 0; i < length; i++)
2296 g_variant_builder_add(builder1, "y", value[i]);
2298 val = g_variant_new("ay", builder1);
2300 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2302 g_variant_builder_add(builder2, "{sv}", "offset",
2303 g_variant_new_uint16(offset));
2305 options = g_variant_new("a{sv}", builder2);
2307 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2309 g_variant_new("(@ay@a{sv})", val, options),
2311 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2312 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2313 (gpointer)resp_data);
2315 g_variant_builder_unref(builder1);
2316 g_variant_builder_unref(builder2);
2318 return BT_STATUS_SUCCESS;
2321 /** Write a remote descriptor for a given characteristic */
2322 bt_status_t btif_write_descriptor(int conn_id,
2323 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2324 btgatt_gatt_id_t *descr_id, int write_type, int len,
2325 int auth_req, char* p_value)
2327 CHECK_BTGATT_INIT();
2329 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2330 len, auth_req, p_value);
2333 /** Execute a prepared write operation */
2334 bt_status_t execute_write(int conn_id, int execute)
2336 CHECK_BTGATT_INIT();
2337 return BT_STATUS_UNSUPPORTED;
2340 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2342 struct hal_ev_gatt_client_watch_notification ev;
2343 hal_gatt_resp_data_t *resp_data = user_data;
2345 DBG("sending the watch register notification event");
2346 /* send the event */
2347 memset(&ev, 0, sizeof(ev));
2348 ev.conn_id = resp_data->conn_id;
2350 ev.status = resp_data->result;
2352 ev.is_primary = resp_data->srvc_id.is_primary;
2353 ev.inst_id = resp_data->srvc_id.id.inst_id;
2355 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2356 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2359 ERR("GATT Callback not registered");
2361 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2368 static bt_status_t _hal_register_for_notification(int conn_id,
2369 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2370 btgatt_gatt_id_t *char_id)
2372 int result = BT_STATUS_SUCCESS;
2373 GError *error = NULL;
2374 GDBusConnection *g_conn;
2375 hal_gattc_client_info_t *gattc_client = NULL;
2376 hal_gattc_server_info_t * conn_info = NULL;
2377 hal_gattc_service_t *gattc_service = NULL;
2378 hal_gattc_char_t *gattc_char = NULL;
2379 char* char_handle = NULL;
2380 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2381 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2382 hal_gatt_resp_data_t *resp_data;
2386 gattc_client = __bt_find_gatt_client_info(bd_addr);
2387 if (gattc_client == NULL) {
2388 ERR("failed to get the gatt client info");
2389 return BT_STATUS_FAIL;
2392 if (gattc_client->conn_id != conn_id) {
2393 ERR("could not find the gatt client for client id[%d]", conn_id);
2394 return BT_STATUS_FAIL;
2397 /* get the connection info */
2398 conn_info = __bt_find_gatt_conn_info(bd_addr);
2399 if (NULL == conn_info) {
2400 ERR("Failed to get the conn_info");
2401 return BT_STATUS_FAIL;
2404 if (conn_info->inst_id != gattc_client->inst_id) {
2405 ERR("could not fild the conn_info");
2406 return BT_STATUS_FAIL;
2410 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2411 if (NULL == gattc_service) {
2412 ERR("Failed to get the gatt service");
2413 return BT_STATUS_FAIL;
2416 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2417 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2420 /* find characteristic */
2421 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2422 if (NULL == gattc_char) {
2423 ERR("Failed to get the gatt char");
2424 return BT_STATUS_FAIL;
2427 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2428 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2430 char_handle = gattc_char->chr_path;
2432 g_conn = _bt_hal_get_system_gconn();
2433 if (g_conn == NULL) {
2435 return BT_STATUS_FAIL;
2438 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2440 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2442 g_dbus_connection_call_sync(g_conn,
2445 BT_HAL_GATT_CHAR_INTERFACE,
2449 G_DBUS_CALL_FLAGS_NONE,
2450 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2453 g_dbus_error_strip_remote_error(error);
2454 ERR("### StartNotify Failed: %s", error->message);
2455 if (g_strrstr(error->message, "Already notifying"))
2456 result = BT_STATUS_SUCCESS;
2457 else if (g_strrstr(error->message, "In Progress"))
2458 result = BT_STATUS_BUSY;
2459 else if (g_strrstr(error->message, "Operation is not supported"))
2460 result = BT_STATUS_UNSUPPORTED;
2461 /*failed because of either Insufficient Authorization or Write Not Permitted */
2462 else if (g_strrstr(error->message, "Write not permitted") ||
2463 g_strrstr(error->message, "Operation Not Authorized"))
2464 result = BT_STATUS_AUTH_FAILURE;
2465 /* failed because of either Insufficient Authentication,
2466 Insufficient Encryption Key Size, or Insufficient Encryption. */
2467 else if (g_strrstr(error->message, "Not paired"))
2468 result = BT_STATUS_NOT_READY;
2470 result = BT_STATUS_FAIL;
2472 g_clear_error(&error);
2475 resp_data->conn_id = gattc_client->conn_id;
2476 resp_data->result = result;
2477 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2478 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2480 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2484 return BT_STATUS_SUCCESS;
2488 * Register to receive notifications or indications for a given
2491 bt_status_t btif_register_for_notification(int conn_id,
2492 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2493 btgatt_gatt_id_t *char_id)
2495 CHECK_BTGATT_INIT();
2497 return _hal_register_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2500 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2502 struct hal_ev_gatt_client_watch_notification ev;
2503 hal_gatt_resp_data_t *resp_data = user_data;
2505 DBG("sending the watch deregister notification event");
2506 /* send the event */
2507 memset(&ev, 0, sizeof(ev));
2508 ev.conn_id = resp_data->conn_id;
2510 ev.status = resp_data->result;
2512 ev.is_primary = resp_data->srvc_id.is_primary;
2513 ev.inst_id = resp_data->srvc_id.id.inst_id;
2515 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2516 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2519 ERR("GATT Callback not registered");
2521 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2528 static bt_status_t _hal_deregister_for_notification(int conn_id,
2529 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2530 btgatt_gatt_id_t *char_id)
2532 int result = BT_STATUS_SUCCESS;
2533 GError *error = NULL;
2534 GDBusConnection *g_conn;
2535 hal_gattc_client_info_t *gattc_client = NULL;
2536 hal_gattc_server_info_t * conn_info = NULL;
2537 hal_gattc_service_t *gattc_service = NULL;
2538 hal_gattc_char_t *gattc_char = NULL;
2539 char* char_handle = NULL;
2540 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2541 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2542 hal_gatt_resp_data_t *resp_data;
2546 gattc_client = __bt_find_gatt_client_info(bd_addr);
2547 if (gattc_client == NULL) {
2548 ERR("failed to get the gatt client info");
2549 return BT_STATUS_FAIL;
2552 if (gattc_client->conn_id != conn_id) {
2553 ERR("could not find the gatt client for client id[%d]", conn_id);
2554 return BT_STATUS_FAIL;
2557 /* get the connection info */
2558 conn_info = __bt_find_gatt_conn_info(bd_addr);
2559 if (NULL == conn_info) {
2560 ERR("Failed to get the conn_info");
2561 return BT_STATUS_FAIL;
2564 if (conn_info->inst_id != gattc_client->inst_id) {
2565 ERR("could not fild the conn_info");
2566 return BT_STATUS_FAIL;
2570 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2571 if (NULL == gattc_service) {
2572 ERR("Failed to get the gatt service");
2573 return BT_STATUS_FAIL;
2576 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2577 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2580 /* find characteristic */
2581 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2582 if (NULL == gattc_char) {
2583 ERR("Failed to get the gatt char");
2584 return BT_STATUS_FAIL;
2587 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2588 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2590 char_handle = gattc_char->chr_path;
2592 g_conn = _bt_hal_get_system_gconn();
2593 if (g_conn == NULL) {
2595 return BT_STATUS_FAIL;
2598 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2600 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2601 g_dbus_connection_call_sync(g_conn,
2604 BT_HAL_GATT_CHAR_INTERFACE,
2608 G_DBUS_CALL_FLAGS_NONE,
2609 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2612 ERR("### StopNotify Failed: %s", error->message);
2613 g_clear_error(&error);
2614 result = BT_STATUS_FAIL;
2617 resp_data->conn_id = gattc_client->conn_id;
2618 resp_data->result = result;
2619 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2620 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2622 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2626 return BT_STATUS_SUCCESS;
2628 /** Deregister a previous request for notifications/indications */
2629 bt_status_t btif_deregister_for_notification(int conn_id,
2630 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2631 btgatt_gatt_id_t *char_id)
2633 CHECK_BTGATT_INIT();
2634 return _hal_deregister_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2637 /** Request RSSI for a given remote device */
2638 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2640 CHECK_BTGATT_INIT();
2641 return BT_STATUS_UNSUPPORTED;
2644 /** OTA firmware download */
2645 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2647 CHECK_BTGATT_INIT();
2648 return BT_STATUS_UNSUPPORTED;
2651 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2652 int get_device_type(const bt_bdaddr_t *bd_addr)
2654 CHECK_BTGATT_INIT();
2655 return BT_STATUS_UNSUPPORTED;
2658 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2659 int min_int, int max_int, int latency, int timeout)
2661 gchar *device_path = NULL;
2662 GError *error = NULL;
2663 GDBusProxy *device_proxy = NULL;
2664 GDBusConnection *conn;
2666 int ret = BT_STATUS_SUCCESS;
2667 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2669 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2670 min_int, max_int, latency, timeout);
2672 conn = _bt_hal_get_system_gconn();
2675 return BT_STATUS_FAIL;
2678 _bt_hal_convert_addr_type_to_string(device_address,
2679 (unsigned char *)bd_addr->address);
2680 device_path = _bt_hal_get_device_object_path(device_address);
2682 if (device_path == NULL) {
2683 ERR("device_path NULL : [%s]", device_address);
2684 return BT_STATUS_FAIL;
2687 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2688 NULL, BT_HAL_BLUEZ_NAME,
2689 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2691 g_free(device_path);
2692 if (NULL == device_proxy) {
2693 ERR("device_proxy returned NULL");
2694 return BT_STATUS_FAIL;
2697 DBG("Request LeConnUpdate");
2698 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2699 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2700 G_DBUS_CALL_FLAGS_NONE,
2705 g_object_unref(device_proxy);
2706 if (reply == NULL) {
2708 ERR("Error %s[%s]", error->message, device_address);
2709 if (g_strrstr(error->message, "In Progress"))
2710 ret = BT_STATUS_SUCCESS;
2712 ret = BT_STATUS_FAIL;
2713 g_error_free(error);
2717 g_variant_unref(reply);
2719 DBG("LE Connection parameter Updated");
2723 /** Request a connection parameter update */
2724 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2726 CHECK_BTGATT_INIT();
2728 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2731 /** Test mode interface */
2732 bt_status_t test_command(int command, btgatt_test_params_t* params)
2734 CHECK_BTGATT_INIT();
2735 return BT_STATUS_UNSUPPORTED;
2738 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2741 GError *g_error = NULL;
2742 GVariant *reply = NULL;
2743 int result = BT_STATUS_SUCCESS;
2744 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2745 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2747 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2748 g_object_unref(proxy);
2749 if (reply == NULL) {
2750 ERR("Connect LE Dbus Call Error");
2752 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2753 g_clear_error(&g_error);
2755 result = BT_STATUS_FAIL;
2757 g_variant_unref(reply);
2759 memset(&ev, 0, sizeof(ev));
2761 ev.mtu = conn_mtu->mtu;
2762 ev.conn_id = conn_mtu->conn_id;
2765 ERR("gatt client callback not registered");
2767 DBG("sending gatt client MTU exchange completed event");
2768 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2775 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2777 gchar *device_path = NULL;
2778 GDBusProxy *device_proxy = NULL;
2779 GDBusConnection *conn;
2780 hal_gattc_client_info_t *gattc_client = NULL;
2781 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2782 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2784 conn = _bt_hal_get_system_gconn();
2788 return BT_STATUS_FAIL;
2791 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2792 if (gattc_client == NULL) {
2793 INFO("GATT client conn info not found");
2795 return BT_STATUS_FAIL;
2798 _bt_hal_convert_addr_type_to_string(device_address,
2799 (unsigned char *)gattc_client->bd_addr.address);
2801 device_path = _bt_hal_get_device_object_path(device_address);
2802 if (device_path == NULL) {
2803 ERR("device_path NULL : [%s]", device_address);
2805 return BT_STATUS_FAIL;
2808 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2809 NULL, BT_HAL_BLUEZ_NAME,
2810 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2812 g_free(device_path);
2813 if (NULL == device_proxy) {
2814 ERR("device_proxy returned NULL");
2816 return BT_STATUS_FAIL;
2819 conn_mtu->conn_id = conn_id;
2820 conn_mtu->mtu = mtu;
2822 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2823 g_variant_new("(q)", mtu),
2824 G_DBUS_CALL_FLAGS_NONE,
2825 BT_HAL_MAX_DBUS_TIMEOUT,
2827 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2830 return BT_STATUS_SUCCESS;
2833 /** MTU Exchange request from client */
2834 static bt_status_t configure_mtu(int conn_id, int mtu)
2836 CHECK_BTGATT_INIT();
2838 return __hal_configure_mtu(conn_id, mtu);
2841 /** Setup scan filter params */
2842 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2843 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2844 int rssi_low_thres, int dely_mode, int found_timeout,
2845 int lost_timeout, int found_timeout_cnt)
2848 GError *error = NULL;
2849 GVariant *ret, *param;
2850 CHECK_BTGATT_INIT();
2852 proxy = _bt_hal_get_adapter_proxy();
2855 return BT_STATUS_FAIL;
2857 param = g_variant_new("(iiiiiiiiiiii)",
2870 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2871 param, G_DBUS_CALL_FLAGS_NONE,
2875 ERR("scan_filter_param_setup Fail: %s", error->message);
2876 g_clear_error(&error);
2877 return BT_STATUS_FAIL;
2881 g_variant_unref(ret);
2883 return BT_STATUS_SUCCESS;
2886 /** Configure a scan filter condition */
2887 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2888 int filt_index, int company_id,
2889 int company_id_mask, const bt_uuid_t *p_uuid,
2890 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2891 char addr_type, int data_len, char* p_data, int mask_len,
2895 GError *error = NULL;
2896 GVariant *ret, *param;
2897 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2898 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2899 GArray *arr_uuid = NULL;
2900 GArray *arr_uuid_mask = NULL;
2901 GArray *arr_data = NULL;
2902 GArray *arr_data_mask = NULL;
2903 CHECK_BTGATT_INIT();
2905 proxy = _bt_hal_get_adapter_proxy();
2908 return BT_STATUS_FAIL;
2910 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2912 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2914 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2916 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2918 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2919 NULL, 0, TRUE, NULL, NULL);
2920 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2921 NULL, 0, TRUE, NULL, NULL);
2922 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2923 NULL, 0, TRUE, NULL, NULL);
2924 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2925 NULL, 0, TRUE, NULL, NULL);
2927 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2928 client_if, // client_if
2929 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2930 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2931 filt_index, // filter_index
2932 company_id, // company_id
2933 company_id_mask, // company_id_mask
2934 arr_uuid_param, // p_uuid
2935 arr_uuid_mask_param, // p_uuid_mask
2937 addr_type, // address_type
2938 arr_data_param, // p_data
2939 arr_data_mask_param); // p_mask
2941 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2942 param, G_DBUS_CALL_FLAGS_NONE,
2946 ERR("scan_filter_add_remove Fail: %s", error->message);
2947 g_clear_error(&error);
2948 return BT_STATUS_FAIL;
2952 g_variant_unref(ret);
2954 return BT_STATUS_SUCCESS;
2957 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2959 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2960 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2961 NULL, 0, TRUE, NULL, NULL);
2962 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2963 NULL, 0, TRUE, NULL, NULL);
2964 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2965 NULL, 0, TRUE, NULL, NULL);
2966 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2967 NULL, 0, TRUE, NULL, NULL);
2969 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2970 client_if, // client_if
2971 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2972 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2973 filt_index, // filter_index
2974 company_id, // company_id
2975 company_id_mask, // company_id_mask
2976 arr_uuid_param, // p_uuid
2977 arr_uuid_mask_param, // p_uuid_mask
2979 addr_type, // address_type
2980 arr_data_param, // p_data
2981 arr_data_mask_param);
2983 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2984 param, G_DBUS_CALL_FLAGS_NONE,
2988 ERR("scan_filter_add_remove Fail: %s", error->message);
2989 g_clear_error(&error);
2990 return BT_STATUS_FAIL;
2994 g_variant_unref(ret);
2996 return BT_STATUS_SUCCESS;
2999 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
3001 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3002 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3004 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3005 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3007 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3008 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3009 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3010 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3011 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3012 NULL, 0, TRUE, NULL, NULL);
3013 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3014 NULL, 0, TRUE, NULL, NULL);
3016 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3017 client_if, // client_if
3018 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3019 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
3020 filt_index, // filter_index
3021 company_id, // company_id
3022 company_id_mask, // company_id_mask
3023 arr_uuid_param, // p_uuid
3024 arr_uuid_mask_param, // p_uuid_mask
3026 addr_type, // address_type
3027 arr_data_param, // p_data
3028 arr_data_mask_param);
3030 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3031 param, G_DBUS_CALL_FLAGS_NONE,
3035 ERR("scan_filter_add_remove Fail: %s", error->message);
3036 g_clear_error(&error);
3037 return BT_STATUS_FAIL;
3041 g_variant_unref(ret);
3043 g_array_free(arr_uuid, TRUE);
3044 g_array_free(arr_uuid_mask, TRUE);
3046 return BT_STATUS_SUCCESS;
3049 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3051 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3052 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3054 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3055 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3057 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3058 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3059 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3060 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3061 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3062 NULL, 0, TRUE, NULL, NULL);
3063 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3064 NULL, 0, TRUE, NULL, NULL);
3066 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3067 client_if, // client_if
3068 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3069 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3070 filt_index, // filter_index
3071 company_id, // company_id
3072 company_id_mask, // company_id_mask
3073 arr_uuid_param, // p_uuid
3074 arr_uuid_mask_param, // p_uuid_mask
3076 addr_type, // address_type
3077 arr_data_param, // p_data
3078 arr_data_mask_param);
3080 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3081 G_DBUS_CALL_FLAGS_NONE,
3085 ERR("scan_filter_add_remove Fail: %s", error->message);
3086 g_clear_error(&error);
3087 return BT_STATUS_FAIL;
3091 g_variant_unref(ret);
3093 g_array_free(arr_uuid, TRUE);
3094 g_array_free(arr_uuid_mask, TRUE);
3096 return BT_STATUS_SUCCESS;
3099 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3101 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3102 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3104 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3105 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3107 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3108 NULL, 0, TRUE, NULL, NULL);
3109 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3110 NULL, 0, TRUE, NULL, NULL);
3111 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3112 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3113 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3114 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3116 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3117 client_if, // client_if
3118 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3119 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3120 filt_index, // filter_index
3121 company_id, // company_id
3122 company_id_mask, // company_id_mask
3123 arr_uuid_param, // p_uuid
3124 arr_uuid_mask_param, // p_uuid_mask
3126 addr_type, // address_type
3127 arr_data_param, // p_data
3128 arr_data_mask_param);
3130 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3131 G_DBUS_CALL_FLAGS_NONE,
3135 ERR("scan_filter_add_remove Fail: %s", error->message);
3136 g_clear_error(&error);
3137 return BT_STATUS_FAIL;
3141 g_variant_unref(ret);
3143 g_array_free(arr_data, TRUE);
3144 g_array_free(arr_data_mask, TRUE);
3146 return BT_STATUS_SUCCESS;
3149 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3151 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3152 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3154 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3155 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3157 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3158 NULL, 0, TRUE, NULL, NULL);
3159 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3160 NULL, 0, TRUE, NULL, NULL);
3161 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3162 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3163 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3164 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3166 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3167 client_if, // client_if
3168 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3169 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3170 filt_index, // filter_index
3171 company_id, // company_id
3172 company_id_mask, // company_id_mask
3173 arr_uuid_param, // p_uuid
3174 arr_uuid_mask_param, // p_uuid_mask
3176 addr_type, // address_type
3177 arr_data_param, // p_data
3178 arr_data_mask_param);
3180 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3181 G_DBUS_CALL_FLAGS_NONE,
3185 ERR("scan_filter_add_remove Fail: %s", error->message);
3186 g_clear_error(&error);
3187 return BT_STATUS_FAIL;
3191 g_variant_unref(ret);
3193 g_array_free(arr_data, TRUE);
3194 g_array_free(arr_data_mask, TRUE);
3196 return BT_STATUS_SUCCESS;
3199 return BT_STATUS_UNSUPPORTED;
3202 /** Clear all scan filter conditions for specific filter index*/
3203 bt_status_t scan_filter_clear(int client_if, int filt_index)
3206 GError *error = NULL;
3208 CHECK_BTGATT_INIT();
3210 proxy = _bt_hal_get_adapter_proxy();
3212 return BT_STATUS_FAIL;
3214 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3215 g_variant_new("(ii)", client_if, filt_index),
3216 G_DBUS_CALL_FLAGS_NONE,
3220 ERR("scan_filter_clear Fail: %s", error->message);
3221 g_clear_error(&error);
3222 return BT_STATUS_FAIL;
3225 g_variant_unref(ret);
3226 return BT_STATUS_SUCCESS;
3229 /** Enable / disable scan filter feature*/
3230 bt_status_t scan_filter_enable(int client_if, bool enable)
3233 GError *error = NULL;
3235 CHECK_BTGATT_INIT();
3237 proxy = _bt_hal_get_adapter_proxy();
3239 return BT_STATUS_FAIL;
3241 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3242 g_variant_new("(ib)", client_if, enable),
3243 G_DBUS_CALL_FLAGS_NONE,
3247 ERR("scan_filter_enable Fail: %s", error->message);
3248 g_clear_error(&error);
3249 return BT_STATUS_FAIL;
3251 g_variant_unref(ret);
3253 return BT_STATUS_SUCCESS;
3256 /** Sets the LE scan interval and window in units of N*0.625 msec */
3258 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3262 CHECK_BTGATT_INIT();
3264 le_scan_type = scan_type;
3265 ret = _bt_hal_adapter_le_set_scan_parameters(
3266 scan_type, scan_interval, scan_window);
3270 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3272 CHECK_BTGATT_INIT();
3273 return BT_STATUS_UNSUPPORTED;
3277 /* Configure the batchscan storage */
3278 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3279 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3281 CHECK_BTGATT_INIT();
3282 return BT_STATUS_UNSUPPORTED;
3285 /* Enable batchscan */
3286 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3287 int scan_interval, int scan_window, int addr_type, int discard_rule)
3289 CHECK_BTGATT_INIT();
3290 return BT_STATUS_UNSUPPORTED;
3293 /* Disable batchscan */
3294 bt_status_t batchscan_dis_batch_scan(int client_if)
3296 CHECK_BTGATT_INIT();
3297 return BT_STATUS_UNSUPPORTED;
3300 /* Read out batchscan reports */
3301 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3303 CHECK_BTGATT_INIT();
3304 return BT_STATUS_UNSUPPORTED;
3307 bt_status_t btif_gatt_get_data_batching_available_packets(unsigned int *available_packets)
3310 GError *error = NULL;
3312 guint32 available_pkts;
3314 CHECK_BTGATT_INIT();
3316 if (available_packets == NULL) {
3317 ERR("available_packets is NULL");
3318 return BT_STATUS_PARM_INVALID;
3321 proxy = _bt_hal_get_adapter_proxy();
3322 if (proxy == NULL) {
3323 ERR("proxy is NULL");
3324 return BT_STATUS_FAIL;
3327 ret = g_dbus_proxy_call_sync(proxy, "GetLeBatchingAvailablePkts",
3329 G_DBUS_CALL_FLAGS_NONE,
3332 int result = BT_STATUS_FAIL;
3334 ERR("SetLeBatchingParam Fail: %s", error->message);
3335 if (g_strrstr(error->message, "Operation is not supported"))
3336 result = BT_STATUS_UNSUPPORTED;
3338 g_clear_error(&error);
3341 g_variant_get(ret, "(u)", &available_pkts);
3342 g_variant_unref(ret);
3344 INFO("GATT Batching available packets: %u", available_pkts);
3345 *available_packets = available_pkts;
3346 return BT_STATUS_SUCCESS;
3349 bt_status_t btif_gatt_enable_data_batching(const bt_bdaddr_t *bd_addr, int packet_threshold, int timeout)
3351 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3353 GError *error = NULL;
3355 CHECK_BTGATT_INIT();
3357 if (bd_addr == NULL) {
3358 ERR("bd_addr is NULL");
3359 return BT_STATUS_PARM_INVALID;
3362 proxy = _bt_hal_get_adapter_proxy();
3363 if (proxy == NULL) {
3364 ERR("proxy is NULL");
3365 return BT_STATUS_FAIL;
3368 _bt_hal_convert_addr_type_to_string(device_address,
3369 (unsigned char *)bd_addr->address);
3370 ret = g_dbus_proxy_call_sync(proxy, "EnableLeBatching",
3371 g_variant_new("(sii)", device_address, packet_threshold, timeout),
3372 G_DBUS_CALL_FLAGS_NONE,
3375 int result = BT_STATUS_FAIL;
3377 ERR("SetLeBatchingParam Fail: %s", error->message);
3378 if (g_strrstr(error->message, "Operation is not supported"))
3379 result = BT_STATUS_UNSUPPORTED;
3380 else if (g_strrstr(error->message, "Invalid arguments"))
3381 result = BT_STATUS_PARM_INVALID;
3383 g_clear_error(&error);
3386 g_variant_unref(ret);
3388 INFO("GATT Batching is enabled");
3389 return BT_STATUS_SUCCESS;
3392 bt_status_t btif_gatt_disable_data_batching(const bt_bdaddr_t *bd_addr)
3394 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3396 GError *error = NULL;
3398 CHECK_BTGATT_INIT();
3400 if (bd_addr == NULL) {
3401 ERR("bd_addr is NULL");
3402 return BT_STATUS_PARM_INVALID;
3405 proxy = _bt_hal_get_adapter_proxy();
3406 if (proxy == NULL) {
3407 ERR("proxy is NULL");
3408 return BT_STATUS_FAIL;
3411 _bt_hal_convert_addr_type_to_string(device_address,
3412 (unsigned char *)bd_addr->address);
3413 ret = g_dbus_proxy_call_sync(proxy, "DisableLeBatching",
3414 g_variant_new("(s)", device_address),
3415 G_DBUS_CALL_FLAGS_NONE,
3418 int result = BT_STATUS_FAIL;
3420 ERR("SetLeBatching Fail: %s", error->message);
3421 if (g_strrstr(error->message, "Operation is not supported"))
3422 result = BT_STATUS_UNSUPPORTED;
3424 g_clear_error(&error);
3427 g_variant_unref(ret);
3429 INFO("GATT Batching is disabled");
3430 return BT_STATUS_SUCCESS;
3433 const btgatt_client_interface_t btgatt_client_interface = {
3434 .register_client = btif_gattc_register_client,
3435 .unregister_client = btif_gattc_unregister_client,
3437 .connect = btif_gattc_client_connect,
3438 .disconnect = btif_gattc_client_disconnect,
3440 .search_service = btif_gattc_client_search_service,
3441 .get_included_service = get_included_service,
3442 .get_characteristic = btif_gattc_get_characteristic,
3443 .get_descriptor = btif_gattc_get_descriptor,
3444 .read_characteristic = btif_read_characteristic,
3445 .write_characteristic = btif_write_characteristic,
3446 .acquire_write = btif_get_acquire_write_fd,
3447 .acquire_notify = btif_get_acquire_notify_fd,
3448 .read_descriptor = btif_read_descriptor,
3449 .write_descriptor = btif_write_descriptor,
3450 .execute_write = execute_write,
3451 .register_for_notification = btif_register_for_notification,
3452 .deregister_for_notification = btif_deregister_for_notification,
3453 .read_remote_rssi = read_remote_rssi,
3454 .ota_fw_update = ota_fw_update,
3455 .get_device_type = get_device_type,
3456 .conn_parameter_update = btif_gattc_conn_parameter_update,
3457 .test_command = test_command,
3458 .configure_mtu = configure_mtu,
3459 .scan_filter_param_setup = scan_filter_param_setup,
3460 .scan_filter_add_remove = scan_filter_add_remove,
3461 .scan_filter_clear = scan_filter_clear,
3462 .scan_filter_enable = scan_filter_enable,
3463 .set_scan_parameters = set_scan_parameters,
3464 .batchscan_cfg_storage = batchscan_cfg_storage,
3465 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3466 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3467 .batchscan_read_reports = batchscan_read_reports,
3468 .add_connection_info = btif_gattc_add_connection_info,
3469 .get_data_batching_available_packets = btif_gatt_get_data_batching_available_packets,
3470 .enable_data_batching = btif_gatt_enable_data_batching,
3471 .disable_data_batching = btif_gatt_disable_data_batching,
3474 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3477 hal_gattc_server_info_t *info = NULL;
3479 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3480 info = (hal_gattc_server_info_t*)l->data;
3484 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3491 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3494 hal_gattc_client_info_t *info = NULL;
3496 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3497 info = (hal_gattc_client_info_t*)l->data;
3501 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3508 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3511 hal_gattc_client_info_t *info = NULL;
3513 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3514 info = (hal_gattc_client_info_t*)l->data;
3518 if (info->conn_id == conn_id)
3525 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3528 hal_gattc_server_info_t *info = NULL;
3529 hal_gattc_client_info_t *gattc_client = NULL;
3531 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3532 if (gattc_client == NULL) {
3533 ERR("GATT client conn info not found");
3537 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3538 info = (hal_gattc_server_info_t*)l->data;
3542 if ((info->inst_id == gattc_client->inst_id) &&
3543 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3550 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3551 gboolean auto_connect)
3553 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3554 gchar *device_path = NULL;
3555 GDBusProxy *device_proxy = NULL;
3556 GDBusConnection *conn;
3557 int ret = BT_STATUS_SUCCESS;
3558 hal_gattc_client_info_t *gattc_data;
3560 if (NULL == bd_addr) {
3561 ERR("bd_addr is NULL");
3562 return BT_STATUS_PARM_INVALID;
3565 conn = _bt_hal_get_system_gconn();
3567 ERR("_bt_gdbus_get_system_gconn returned NULL");
3568 return BT_STATUS_FAIL;
3571 _bt_hal_convert_addr_type_to_string(device_address,
3572 (unsigned char *)bd_addr->address);
3573 device_path = _bt_hal_get_device_object_path(device_address);
3574 if (device_path == NULL) {
3575 ERR("device_path NULL : [%s]", device_address);
3576 ret = BT_STATUS_FAIL;
3580 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3581 NULL, BT_HAL_BLUEZ_NAME,
3582 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3583 g_free(device_path);
3584 if (NULL == device_proxy) {
3585 ERR("device_proxy returned NULL");
3586 return BT_STATUS_FAIL;
3589 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3590 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3591 BT_HAL_ADDRESS_LENGTH_MAX);
3593 DBG("ConnectLE [%s]", device_address);
3595 gattc_data->client_if = client_if;
3597 g_dbus_proxy_call(device_proxy, "ConnectLE",
3598 g_variant_new("(b)", auto_connect),
3599 G_DBUS_CALL_FLAGS_NONE,
3600 BT_HAL_MAX_DBUS_TIMEOUT,
3602 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3607 static bt_status_t _bt_hold_current_advertising()
3609 int ret = BT_STATUS_FAIL;
3610 gboolean is_advertising = FALSE;
3613 if (_bt_hal_is_support_multi_adv() == TRUE) {
3614 DBG("VSC adv used");
3615 return BT_STATUS_SUCCESS;
3618 /* Dependent on Kernel operation. Hold adv to prevent stopping adv on kernel */
3619 is_advertising = _bt_hal_is_advertising_in_slot(0);
3620 if (is_advertising) {
3621 DBG("+ Stop current advertising");
3623 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3624 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3630 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3632 DBG("+ start current advertising");
3634 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3639 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3641 DBG("Try to initiate pending LE connection");
3643 pending_le_conn_timer_id = 0;
3645 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3646 &pending_le_conn_info->bd_addr,
3647 pending_le_conn_info->auto_connect);
3649 g_free(pending_le_conn_info);
3650 pending_le_conn_info = NULL;
3655 static int __hal_generate_conn_id()
3657 return ++hal_gatt_conn_id;
3660 static int __hal_generate_server_instance_id()
3662 return ++bt_inst_id;
3665 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3668 GError *g_error = NULL;
3669 GVariant *reply = NULL;
3670 hal_gattc_client_info_t *gattc_data = user_data;
3671 int result = BT_STATUS_SUCCESS;
3672 struct hal_ev_gatt_client_connected ev;
3673 hal_gattc_server_info_t *gatt_conn_info = NULL;
3675 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3676 g_object_unref(proxy);
3677 if (reply == NULL) {
3678 ERR("Connect LE Dbus Call Error");
3680 ERR("Error: %s\n", g_error->message);
3681 g_clear_error(&g_error);
3683 result = BT_STATUS_FAIL;
3685 g_variant_unref(reply);
3687 if (NULL == gattc_data) {
3688 ERR("gattc_data is NULL");
3693 if (result == BT_STATUS_FAIL) {
3694 memset(&ev, 0, sizeof(ev));
3697 ev.client_if = gattc_data->client_if;
3698 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3699 BT_HAL_ADDRESS_LENGTH_MAX);
3702 ERR("gatt client callback not registered");
3704 DBG("sending gatt client connected event");
3705 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3711 DBG("LE connected. Adding the gattc server/client conn info in list");
3712 gattc_data->conn_id = __hal_generate_conn_id() ;
3713 gattc_data->inst_id = __hal_generate_server_instance_id();
3715 #ifndef __INTEGRATE_HAL_GATT_INFO__
3716 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3719 /*add gatt server connection info*/
3720 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3721 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3722 gatt_conn_info->conn_id = gattc_data->conn_id;
3723 gatt_conn_info->inst_id = gattc_data->inst_id;
3724 #ifdef __INTEGRATE_HAL_GATT_INFO__
3725 gatt_conn_info->client_if = gattc_data->client_if;
3727 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3732 /*remove conn_info*/
3737 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3739 g_free(desc_info->desc_path);
3743 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3746 hal_gattc_desc_t *desc_info = NULL;
3747 for (l = char_info->gatt_list_descs; l != NULL; ) {
3748 desc_info = l->data;
3749 l = g_slist_next(l);
3750 if (desc_info == NULL)
3752 /* Remove descriptor element */
3753 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3754 __hal_gattc_free_desc_info(desc_info);
3756 g_slist_free(char_info->gatt_list_descs);
3757 g_free(char_info->chr_path);
3761 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3764 hal_gattc_char_t *char_info = NULL;
3765 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3766 char_info = l->data;
3767 l = g_slist_next(l);
3768 if (char_info == NULL)
3770 /* Remove characteristic element */
3771 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3772 __hal_gattc_free_char_info(char_info);
3774 g_slist_free(svc_info->gatt_list_chars);
3775 g_free(svc_info->svc_path);
3779 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3782 hal_gattc_service_t *svc_info = NULL;
3786 for (l = conn_info->gatt_list_services; l != NULL; ) {
3787 svc_info = (hal_gattc_service_t *)l->data;
3788 l = g_slist_next(l);
3789 if (svc_info == NULL)
3791 /* Remove service element */
3792 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3793 __hal_gattc_free_svc_info(svc_info);
3795 g_slist_free(conn_info->gatt_list_services);
3799 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3801 bt_bdaddr_t bd_addr;
3802 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3803 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3809 int _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3811 int result = BT_STATUS_SUCCESS;
3812 struct hal_ev_gatt_client_connected ev;
3813 hal_gattc_server_info_t *conn_info = NULL;
3814 bt_bdaddr_t bd_addr;
3816 hal_gattc_client_info_t *gattc_client = NULL;
3817 #ifndef __INTEGRATE_HAL_GATT_INFO__
3821 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3822 HAL_EV_GATT_CLIENT_DISCONNECTED;
3824 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3825 /* find the gatt client info */
3826 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3827 if (NULL == gattc_client) {
3828 ERR("Fail to get gatt client info");
3832 gattc_client->is_gatt_connected = gatt_connected;
3835 memset(&ev, 0, sizeof(ev));
3836 ev.conn_id = gattc_client->conn_id;
3838 ev.client_if = gattc_client->client_if;
3839 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3840 BT_HAL_ADDRESS_LENGTH_MAX);
3843 ERR("gatt client callback not registered");
3845 event_cb(event, (void *)&ev, sizeof(ev));
3848 if (!gatt_connected) {
3849 #ifndef __INTEGRATE_HAL_GATT_INFO__
3850 inst_id = gattc_client->inst_id;
3852 /* remove the gatt client info from the client list also*/
3853 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3854 g_free(gattc_client);
3857 //find the connected server info
3858 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3859 if (NULL == conn_info) {
3860 ERR("Fail to get gatt server info");
3864 #ifndef __INTEGRATE_HAL_GATT_INFO__
3865 if (inst_id != conn_info->inst_id) {
3866 ERR("server instance is different");
3871 //remove gatt conn info from the server list
3872 DBG("remove the server conn_info from list after gatt disconnection");
3873 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3874 __hal_clean_gattc_server_info(conn_info);
3880 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3881 const char* uuid_str, int inst_id)
3883 struct hal_ev_gatt_client_search_result ev;
3886 ERR("gatt client callback not registered");
3890 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3892 memset(&ev, 0, sizeof(ev));
3893 ev.conn_id = conn_id;
3894 ev.inst_id = inst_id;
3895 ev.is_primary = is_primary;
3896 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3898 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3901 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3903 struct hal_ev_gatt_client_search_complete ev;
3906 ERR("gatt client callback not registered");
3910 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3913 memset(&ev, 0, sizeof(ev));
3914 ev.conn_id = conn_id;
3917 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3920 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3921 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3922 char *char_value, int len)
3924 struct hal_ev_gatt_client_notify_changed_value ev;
3925 hal_gattc_client_info_t *gattc_client = NULL;
3928 ERR("gatt client callback not registered");
3932 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3933 if (NULL == gattc_client) {
3934 ERR("failed to get the gatt client info");
3939 DBG("sending gatt client connected status event");
3940 memset(&ev, 0, sizeof(ev));
3942 ev.conn_id = gattc_client->conn_id;
3943 ev.inst_id = conn_info->inst_id;
3944 ev.is_primary = svc_info->is_primary;
3945 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3946 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3948 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3950 if (len > 0 && (char_value != NULL)) {
3951 memcpy(ev.value, char_value, len);
3955 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3958 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3959 char *char_value, int len)
3961 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3962 hal_gattc_server_info_t *conn_info = NULL;
3963 bt_bdaddr_t bd_addr;
3966 hal_gattc_service_t *svc_info = NULL;
3967 hal_gattc_char_t *char_info = NULL;
3971 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3972 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3973 DBG("device address:[%s]", device_address);
3974 DBG("char handle:[%s]", char_handle);
3976 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3977 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3979 if (conn_info != NULL) {
3980 //find service for notified char path
3981 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3982 svc_info = (hal_gattc_service_t*)l->data;
3983 if (svc_info == NULL)
3986 /* find characteristic object path */
3987 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3988 char_info = (hal_gattc_char_t *)k->data;
3989 if (char_info == NULL)
3992 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3993 DBG("Found char handle[%s]", char_info->chr_path);
3996 _bt_hal_send_value_changed_event(conn_info, svc_info,
3997 char_info, char_value, len);
4005 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
4007 GDBusConnection *g_conn = NULL;
4008 GDBusProxy *properties_proxy = NULL;
4009 GVariant *result = NULL;
4010 GError *error = NULL;
4011 GVariantIter *property_iter = NULL;
4012 const gchar *key = NULL;
4013 GVariant *value = NULL;
4014 const char *uuid_str = NULL;
4016 gboolean is_primary = FALSE;
4017 GVariantIter *char_iter = NULL;
4018 const char *char_handle = NULL;
4019 GPtrArray *gp_char_array = NULL;
4021 if (service_path == NULL) {
4022 ERR("service_path is NULL");
4023 return BT_STATUS_FAIL;
4026 DBG("service_path: %s", service_path);
4028 g_conn = _bt_hal_get_system_gconn();
4029 if (g_conn == NULL) {
4030 ERR("g_conn is NULL");
4031 return BT_STATUS_FAIL;
4034 properties_proxy = g_dbus_proxy_new_sync(g_conn,
4035 G_DBUS_PROXY_FLAGS_NONE, NULL,
4038 BT_HAL_PROPERTIES_INTERFACE,
4040 if (properties_proxy == NULL) {
4041 ERR("properties_proxy is NULL");
4042 return BT_STATUS_FAIL;
4045 result = g_dbus_proxy_call_sync(properties_proxy,
4047 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
4048 G_DBUS_CALL_FLAGS_NONE,
4050 if (result == NULL) {
4051 if (error != NULL) {
4052 ERR("Fail to get properties (Error: %s)", error->message);
4053 g_clear_error(&error);
4055 ERR("Fail to get properties");
4057 g_object_unref(properties_proxy);
4058 return BT_STATUS_FAIL;
4061 g_variant_get(result, "(a{sv})", &property_iter);
4063 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
4064 if (g_strcmp0(key, "UUID") == 0) {
4065 uuid_str = g_variant_get_string(value, &len);
4066 } else if (g_strcmp0(key, "Primary") == 0) {
4067 is_primary = g_variant_get_boolean(value);
4068 } else if (g_strcmp0(key, "Characteristics") == 0) {
4069 g_variant_get(value, "ao", &char_iter);
4070 if (char_iter != NULL) {
4071 if (gp_char_array == NULL)
4072 gp_char_array = g_ptr_array_new();
4074 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
4075 DBG("char_handle: %s", char_handle);
4076 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
4078 g_variant_iter_free(char_iter);
4083 if (uuid_str == NULL || gp_char_array == NULL) {
4084 ERR("uuid_str and gp_char_array should be set");
4088 /* Create new service */
4089 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
4092 g_variant_iter_free(property_iter);
4093 g_variant_unref(result);
4094 g_object_unref(properties_proxy);
4096 return BT_STATUS_SUCCESS;
4099 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
4101 GDBusConnection *conn = NULL;
4102 GDBusProxy *proxy = NULL;
4104 GVariant *ret = NULL;
4105 GVariant *value = NULL;
4107 conn = _bt_hal_get_system_gconn();
4109 ERR("_bt_gdbus_get_system_gconn returned NULL");
4113 proxy = g_dbus_proxy_new_sync(conn,
4114 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
4115 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
4116 if (proxy == NULL) {
4117 ERR("device_proxy returned NULL");
4121 ret = g_dbus_proxy_call_sync(proxy, "Get",
4122 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
4123 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
4125 ERR("DBus Error : %s", err->message);
4126 g_clear_error(&err);
4128 g_variant_get(ret, "(v)", &value);
4129 *service_uuid = g_variant_dup_string(value, NULL);
4130 g_variant_unref(value);
4131 g_variant_unref(ret);
4135 g_object_unref(proxy);
4140 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
4142 struct hal_ev_gatt_client_service_changed ev = {0, };
4143 char address[BT_HAL_ADDRESS_STRING_SIZE];
4144 hal_gattc_server_info_t *server_info = NULL;
4145 hal_gattc_client_info_t *gattc_client = NULL;
4146 hal_gattc_service_t *service = NULL;
4147 GSList *list = NULL;
4148 char *uuid_str = NULL;
4150 _bt_hal_convert_device_path_to_address(path, address);
4151 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
4152 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
4153 if (server_info == NULL) {
4154 ERR("server_info is NULL");
4158 gattc_client = __bt_find_gatt_client_info((bt_bdaddr_t *)ev.bdaddr);
4159 if (gattc_client == NULL) {
4160 ERR("gattc_client is NULL");
4164 if (server_info->is_gatt_connected == FALSE && gattc_client->is_gatt_connected == FALSE) {
4165 DBG("GattConnected signal is not received yet. Just skip [%d %d]",
4166 server_info->is_gatt_connected, gattc_client->is_gatt_connected);
4171 /* Get service UUID from path */
4172 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
4174 INFO("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
4175 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
4178 ERR("uuid_str is NULL");
4182 /* Create new service and append into the list */
4183 __hal_gattc_get_service_info(server_info, path);
4185 /* Find service UUID from path */
4186 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4187 service = (hal_gattc_service_t *)list->data;
4188 if (service == NULL)
4191 if (g_strcmp0(service->svc_path, path) == 0) {
4192 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4193 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4194 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4195 INFO("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
4197 /* Remove service info in list */
4198 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4199 __hal_gattc_free_svc_info(service);
4207 ERR("uuid_str is NULL");
4212 /* Send GATT Client service changed event */
4213 ev.change_type = is_added;
4214 ev.conn_id = server_info->conn_id;
4215 ev.inst_id = server_info->inst_id;
4216 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));