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.h"
40 #include "bt-hal-gatt-client.h"
41 #include "bt-hal-dbus-common-utils.h"
42 #include "bt-hal-utils.h"
44 /************************************************************************************
46 ************************************************************************************/
47 #define CHECK_BTGATT_INIT() if (_bt_hal_gatt_interface_ready() == false)\
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 if (pending_le_conn_timer_id > 0) {
473 DBG("Connecting timer is existing. return busy");
474 return BT_STATUS_BUSY;
476 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
477 pending_le_conn_info->client_if = client_if;
478 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
479 BT_HAL_ADDRESS_LENGTH_MAX);
480 pending_le_conn_info->auto_connect = is_direct;
482 pending_le_conn_timer_id =
483 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
485 return BT_STATUS_SUCCESS;
487 ERR("advertising is not stopped");
490 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
494 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
497 GError *g_error = NULL;
498 GVariant *reply = NULL;
499 hal_gattc_client_info_t *gatt_conn_info = user_data;
500 int result = BT_STATUS_SUCCESS;
501 struct hal_ev_gatt_client_connected ev;
505 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
506 g_object_unref(proxy);
508 ERR("Connect LE Dbus Call Error");
510 ERR("Error: %s\n", g_error->message);
511 g_clear_error(&g_error);
513 result = BT_STATUS_FAIL;
515 g_variant_unref(reply);
517 if (NULL == gatt_conn_info) {
518 ERR("server_data is NULL");
523 if (result == BT_STATUS_FAIL) {
524 memset(&ev, 0, sizeof(ev));
525 ev.conn_id = gatt_conn_info->conn_id;
527 ev.client_if = gatt_conn_info->client_if;
528 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
529 BT_HAL_ADDRESS_LENGTH_MAX);
532 ERR("gatt client callback not registered");
534 DBG("sending gatt client disconnected event");
535 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
541 g_free(gatt_conn_info);
546 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
549 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
551 GDBusProxy *device_proxy;
552 GDBusConnection *conn;
553 int ret = BT_STATUS_SUCCESS;
554 hal_gattc_client_info_t *gattc_data;
556 if (NULL == bd_addr) {
557 ERR("bd_addr is NULL");
558 return BT_STATUS_PARM_INVALID;
561 conn = _bt_hal_get_system_gconn();
563 ERR("_bt_gdbus_get_system_gconn returned NULL");
564 return BT_STATUS_FAIL;
567 _bt_hal_convert_addr_type_to_string(device_address,
568 (unsigned char *)bd_addr->address);
569 device_path = _bt_hal_get_device_object_path(device_address);
570 if (device_path == NULL) {
571 DBG("device_path NULL");
572 ret = BT_STATUS_FAIL;
576 ERR("device_path:%s", device_path);
578 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
579 NULL, BT_HAL_BLUEZ_NAME,
580 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
582 if (NULL == device_proxy) {
583 ERR("device_proxy returned NULL");
584 return BT_STATUS_FAIL;
587 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
588 memcpy(gattc_data->bd_addr.address, bd_addr->address,
589 BT_HAL_ADDRESS_LENGTH_MAX);
590 gattc_data->client_if = client_if;
591 gattc_data->conn_id = conn_id;
593 DBG("DisconnectLE [%s]", device_address);
595 g_dbus_proxy_call(device_proxy, "DisconnectLE",
597 G_DBUS_CALL_FLAGS_NONE,
598 BT_HAL_MAX_DBUS_TIMEOUT,
600 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
604 /** Disconnect a remote device or cancel a pending connection */
605 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
610 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
613 /** Clear the attribute cache for a given device */
614 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
617 return BT_STATUS_UNSUPPORTED;
620 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
623 hal_gattc_service_t *info = NULL;
625 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
626 info = (hal_gattc_service_t*)l->data;
630 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t)))
638 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
639 bt_gatt_characteristic_property_t prop)
642 hal_gattc_char_t *info = NULL;
644 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
645 info = (hal_gattc_char_t*)l->data;
649 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
650 (info->permission & prop)) {
657 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
660 hal_gattc_char_t *info = NULL;
662 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
663 info = (hal_gattc_char_t*)l->data;
667 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
668 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
669 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
676 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
679 hal_gattc_desc_t *info = NULL;
681 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
682 info = (hal_gattc_desc_t*)l->data;
686 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t)))
693 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
694 const char *uuid_str, const char *object_path, int is_primary)
696 hal_gattc_service_t *gattc_service = NULL;
698 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
699 gattc_service->svc_path = g_strdup(object_path);
700 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
701 gattc_service->is_primary = is_primary;
703 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
704 INFO("Total svc [%d] Added [%s] [%s]", g_slist_length(conn_info->gatt_list_services), object_path + 15, uuid_str);
706 return gattc_service;
709 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
711 hal_gattc_char_t *gattc_char = NULL;
713 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
714 gattc_char->chr_path = g_strdup(char_handle);
716 DBG("[%s]", gattc_char->chr_path + 15);
718 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
721 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
722 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
724 hal_gattc_service_t* gatt_svc = NULL;
726 gchar *gp_char_path = NULL;
727 uint8_t uuid[BT_HAL_STACK_UUID_SIZE];
729 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
730 gatt_svc = _gattc_find_service_from_uuid(conn_info, (bt_uuid_t *)uuid);
732 DBG("Aleady added to gatt_list_services");
736 /* add the service */
737 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
738 if (gatt_svc == NULL) {
739 ERR("Failed to add service");
743 /* add the characteristic */
744 for (i = 0; i < gp_char_array->len; i++) {
745 gp_char_path = g_ptr_array_index(gp_char_array, i);
746 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
749 g_ptr_array_free(gp_char_array, TRUE);
752 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
754 hal_gattc_desc_t *gattc_desc = NULL;
757 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
758 gattc_desc = (hal_gattc_desc_t *)l->data;
759 if (gattc_desc == NULL)
762 if (g_strcmp0(gattc_desc->desc_path, desc_path) == 0)
766 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
767 gattc_desc->desc_path = g_strdup(desc_path);
769 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
772 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
773 GPtrArray *gp_desc_array, unsigned int char_permission)
775 gchar *gp_desc_path = NULL;
778 if (char_uuid_str == NULL) {
779 DBG("char_uuid_str is NULL");
783 //update the char uuid
784 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
786 //update char permission
787 gattc_char->permission = char_permission;
790 for (i = 0; i < gp_desc_array->len; i++) {
791 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
792 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
796 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
798 if (desc_uuid_str == NULL) {
799 DBG("char_uuid_str is NULL");
803 //update the descriptor uuid
804 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
806 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
809 static void browse_service_char(int conn_id)
811 hal_gattc_server_info_t *conn_info = NULL;
815 hal_gattc_service_t *svc_info = NULL;
816 hal_gattc_char_t *char_info = NULL;
817 hal_gattc_desc_t *desc_info = NULL;
819 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
820 if (conn_info == NULL) {
821 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
825 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
826 svc_info = (hal_gattc_service_t*)l->data;
827 if (svc_info == NULL)
830 /* find characteristic object path */
831 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
832 char_info = (hal_gattc_char_t *)k->data;
833 if (char_info == NULL)
837 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
838 desc_info = (hal_gattc_desc_t *)m->data;
839 if (desc_info == NULL)
849 * Enumerate all GATT services on a connected device.
850 * Optionally, the results can be filtered for a given UUID.
852 static bt_status_t _gattc_client_search_service(int conn_id)
856 GVariant *result = NULL;
858 GVariantIter *svc_iter;
859 GVariantIter *interface_iter;
860 char *object_path = NULL;
861 char *interface_str = NULL;
862 const gchar *key = NULL;
863 GVariant *value = NULL;
864 GPtrArray *gp_array = NULL;
865 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
866 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
867 int ret = BT_STATUS_FAIL;
869 const gchar *uuid_str = NULL;
871 hal_gattc_server_info_t *conn_info = NULL;
872 gboolean is_primary = FALSE;
875 char *char_handle = NULL;
876 GVariantIter *char_iter = NULL;
877 GPtrArray *gp_char_array = NULL;
879 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
880 if (NULL == conn_info) {
881 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
882 return BT_STATUS_FAIL;
886 // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
887 // Check the service info is stored
888 if (g_slist_length(conn_info->gatt_list_services) > 0) {
890 hal_gattc_service_t *svc_info = NULL;
891 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
892 DBG("Send event from service info list");
893 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
895 if (svc_info == NULL)
897 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
898 _bt_hal_send_search_service_result_event(conn_id,
899 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
901 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
902 return BT_STATUS_SUCCESS;
904 DBG("No stored service, request to bluez");
907 _bt_hal_convert_addr_type_to_string(device_address,
908 (unsigned char *)conn_info->bd_addr.address);
910 result = _bt_hal_get_managed_objects();
914 gp_array = g_ptr_array_new();
915 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
917 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
919 if (object_path == NULL)
922 _bt_hal_convert_device_path_to_address(object_path, temp_address);
924 if (g_strcmp0(temp_address, device_address) != 0)
927 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
928 &interface_str, &svc_iter)) {
929 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
932 DBG("[%d] %s", idx++, object_path + 15);
933 /* for characteristic */
934 gp_char_array = g_ptr_array_new();
935 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
936 if (g_strcmp0(key, "Primary") == 0) {
937 is_primary = g_variant_get_boolean(value);
939 g_ptr_array_add(gp_array, (gpointer)object_path);
942 } else if (g_strcmp0(key, "UUID") == 0) {
943 uuid_str = g_variant_get_string(value, &len);
944 } else if (g_strcmp0(key, "Characteristics") == 0) {
945 g_variant_get(value, "ao", &char_iter);
946 if (char_iter != NULL) {
947 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
948 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
950 g_variant_iter_free(char_iter);
956 _bt_hal_send_search_service_result_event(conn_id, is_primary,
957 uuid_str, conn_info->inst_id);
959 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
964 if (gp_array->len == 0 || svc_count == 0) {
965 ERR("gp_array is NULL");
966 ret = BT_STATUS_FAIL;
968 ret = BT_STATUS_SUCCESS;
971 browse_service_char(conn_id);
972 /* send search service complete event */
973 _bt_hal_send_search_service_complete_event(conn_id, ret);
975 g_ptr_array_free(gp_array, TRUE);
976 g_variant_iter_free(iter);
977 g_variant_unref(result);
982 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
984 if (NULL == filter_uuid) {
985 DBG("Browse all the services");
986 return _gattc_client_search_service(conn_id);
988 DBG("TODO implement it");
989 return BT_STATUS_UNSUPPORTED;
993 * Enumerate included services for a given service.
994 * Set start_incl_srvc_id to NULL to get the first included service.
996 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
997 btgatt_srvc_id_t *start_incl_srvc_id)
1000 return BT_STATUS_UNSUPPORTED;
1003 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
1004 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
1006 struct hal_ev_gatt_client_char_search_result ev;
1009 ERR("gatt client callback not registered");
1013 memset(&ev, 0, sizeof(ev));
1014 ev.conn_id = conn_id;
1015 ev.inst_id = svc_id->id.inst_id;
1016 ev.is_primary = svc_id->is_primary;
1018 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1020 if (status == BT_STATUS_SUCCESS) {
1021 /* building char uuid */
1022 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
1023 ev.char_prop = char_prop;
1026 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
1027 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1030 static int _hal_get_permission_flag(char *permission)
1034 if (NULL == permission) {
1035 ERR("gatt permission is NULL");
1039 if (!g_strcmp0(permission, "broadcast"))
1040 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
1041 else if (!g_strcmp0(permission, "read"))
1042 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
1043 else if (!g_strcmp0(permission, "write-without-response"))
1044 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1045 else if (!g_strcmp0(permission, "write"))
1046 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1047 else if (!g_strcmp0(permission, "notify"))
1048 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1049 else if (!g_strcmp0(permission, "indicate"))
1050 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
1051 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
1052 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
1053 else if (!g_strcmp0(permission, "reliable-write"))
1054 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
1055 else if (!g_strcmp0(permission, "writable-auxiliaries"))
1056 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1057 else if (!g_strcmp0(permission, "encrypt-read"))
1058 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1059 else if (!g_strcmp0(permission, "encrypt-write"))
1060 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1061 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1062 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1063 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1064 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1069 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1071 char perm[200] = { 0, };
1073 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1074 g_strlcat(perm, "broadcast ", sizeof(perm));
1075 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1076 g_strlcat(perm, "read ", sizeof(perm));
1077 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1078 g_strlcat(perm, "write-without-response ", sizeof(perm));
1079 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1080 g_strlcat(perm, "write ", sizeof(perm));
1081 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1082 g_strlcat(perm, "notify ", sizeof(perm));
1083 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1084 g_strlcat(perm, "indicate ", sizeof(perm));
1085 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1086 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1087 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1088 g_strlcat(perm, "reliable-write ", sizeof(perm));
1089 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1090 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1091 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1092 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1093 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1094 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1095 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1096 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1097 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1098 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1100 DBG("permission [0x%04x] : %s\n", permission, perm);
1104 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1106 GDBusProxy *properties_proxy = NULL;
1107 GError *error = NULL;
1108 GVariant *value = NULL;
1109 GVariant *result = NULL;
1110 GDBusConnection *g_conn;
1112 char *char_desc_handle = NULL;
1114 GVariantIter *property_iter;
1115 GVariantIter *char_desc_iter;
1116 char* char_handle = NULL;
1117 gchar *char_uuid_str = NULL;
1118 GPtrArray *gp_desc_array = NULL;
1119 GVariantIter *char_perm_iter;
1121 unsigned int char_permission = 0 ;
1123 if (gattc_char->chr_path == NULL) {
1124 DBG("char path is NULL");
1125 return BT_STATUS_FAIL;
1127 char_handle = gattc_char->chr_path;
1129 g_conn = _bt_hal_get_system_gconn();
1130 if (NULL == g_conn) {
1131 ERR("_bt_gdbus_get_system_gconn returned NULL");
1132 return BT_STATUS_FAIL;
1135 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1136 G_DBUS_PROXY_FLAGS_NONE, NULL,
1139 BT_HAL_PROPERTIES_INTERFACE,
1142 if (properties_proxy == NULL) {
1143 ERR("properties_proxy returned NULL");
1144 return BT_STATUS_FAIL;
1147 result = g_dbus_proxy_call_sync(properties_proxy,
1149 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1150 G_DBUS_CALL_FLAGS_NONE,
1155 if (error != NULL) {
1156 ERR("Fail to get properties (Error: %s)", error->message);
1157 g_clear_error(&error);
1159 ERR("Fail to get properties");
1160 g_object_unref(properties_proxy);
1161 return BT_STATUS_FAIL;
1164 gp_desc_array = g_ptr_array_new();
1166 g_variant_get(result, "(a{sv})", &property_iter);
1168 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1169 if (!g_strcmp0(key, "UUID")) {
1170 char_uuid_str = g_variant_dup_string(value, &len);
1171 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1172 } else if (!g_strcmp0(key, "Flags")) {
1173 g_variant_get(value, "as", &char_perm_iter);
1174 char_permission = 0x00;
1176 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1177 char_permission |= _hal_get_permission_flag(permission);
1179 __hal_convert_permission_flag_to_str(char_permission);
1180 g_variant_iter_free(char_perm_iter);
1181 } else if (!g_strcmp0(key, "Descriptors")) {
1182 g_variant_get(value, "ao", &char_desc_iter);
1183 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1184 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1186 g_variant_iter_free(char_desc_iter);
1190 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1192 g_free(char_uuid_str);
1193 g_variant_iter_free(property_iter);
1194 g_variant_unref(result);
1195 g_object_unref(properties_proxy);
1196 g_ptr_array_free(gp_desc_array, TRUE);
1198 return BT_STATUS_SUCCESS;
1201 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1202 btgatt_srvc_id_t *srvc_id)
1204 hal_gattc_server_info_t * conn_info = NULL;
1205 hal_gattc_service_t *gattc_service = NULL;
1207 hal_gattc_char_t *gattc_char = NULL;
1208 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1209 int status = BT_STATUS_FAIL;
1211 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1212 if (NULL == conn_info) {
1213 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1214 return BT_STATUS_FAIL;
1218 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1219 if (NULL == gattc_service) {
1220 ERR("Failed to get the gatt service");
1221 return BT_STATUS_FAIL;
1224 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1225 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1227 /* find characteristic object path */
1228 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1229 gattc_char = (hal_gattc_char_t *)l->data;
1230 status = _hal_gattc_get_characteristic_info(gattc_char);
1233 if (BT_STATUS_SUCCESS == status) {
1234 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1235 &gattc_char->chr_uuid, gattc_char->permission);
1239 status = BT_STATUS_FAIL;
1240 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1242 browse_service_char(conn_id);
1243 /* retrive uuid for characteristic and object path for descriptor */
1245 return BT_STATUS_SUCCESS;
1249 * Enumerate characteristics for a given service.
1250 * Set start_char_id to NULL to get the first characteristic.
1252 bt_status_t btif_gattc_get_characteristic(int conn_id,
1253 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1255 CHECK_BTGATT_INIT();
1257 if (start_char_id == NULL) {
1258 return _gattc_get_all_characteristic(conn_id, srvc_id);
1261 DBG("TBD Get specific characteristics");
1262 return BT_STATUS_UNSUPPORTED;
1266 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1268 GDBusProxy *properties_proxy = NULL;
1269 GError *error = NULL;
1270 GVariant *value = NULL;
1271 GVariant *result = NULL;
1272 GDBusConnection *g_conn;
1275 GVariantIter *property_iter;
1276 char* desc_handle = NULL;
1277 const gchar *desc_uuid_str = NULL;
1279 if (gattc_desc->desc_path == NULL) {
1280 DBG("desc path is NULL");
1281 return BT_STATUS_FAIL;
1283 desc_handle = gattc_desc->desc_path;
1285 g_conn = _bt_hal_get_system_gconn();
1286 if (NULL == g_conn) {
1287 ERR("_bt_gdbus_get_system_gconn returned NULL");
1288 return BT_STATUS_FAIL;
1291 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1292 G_DBUS_PROXY_FLAGS_NONE, NULL,
1295 BT_HAL_PROPERTIES_INTERFACE,
1298 if (properties_proxy == NULL) {
1299 ERR("properties_proxy returned NULL");
1300 return BT_STATUS_FAIL;
1303 result = g_dbus_proxy_call_sync(properties_proxy,
1305 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1306 G_DBUS_CALL_FLAGS_NONE,
1311 if (error != NULL) {
1312 ERR("Fail to get properties (Error: %s)", error->message);
1313 g_clear_error(&error);
1315 ERR("Fail to get properties");
1316 g_object_unref(properties_proxy);
1317 return BT_STATUS_FAIL;
1320 g_variant_get(result, "(a{sv})", &property_iter);
1322 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1323 if (!g_strcmp0(key, "UUID")) {
1324 desc_uuid_str = g_variant_get_string(value, &len);
1325 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1327 g_free((gchar *)key);
1328 g_variant_unref(value);
1333 g_variant_iter_free(property_iter);
1334 g_variant_unref(result);
1335 g_object_unref(properties_proxy);
1337 return BT_STATUS_SUCCESS;
1340 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1341 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1343 struct hal_ev_gatt_client_desc_search_result ev;
1346 ERR("gatt client callback not registered");
1350 memset(&ev, 0, sizeof(ev));
1351 ev.conn_id = conn_id;
1352 ev.inst_id = svc_id->id.inst_id;
1353 ev.is_primary = svc_id->is_primary;
1356 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1357 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1359 if (status == BT_STATUS_SUCCESS) {
1360 /* building desc uuid */
1361 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1364 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1366 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1369 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1370 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1372 hal_gattc_server_info_t * conn_info = NULL;
1373 hal_gattc_service_t *gattc_service = NULL;
1376 hal_gattc_char_t *gattc_char = NULL;
1377 hal_gattc_desc_t *gattc_desc = NULL;
1378 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1379 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1380 int status = BT_STATUS_FAIL;
1382 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1383 if (NULL == conn_info) {
1384 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1385 return BT_STATUS_FAIL;
1389 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1390 if (NULL == gattc_service) {
1391 ERR("Failed to get the gatt service");
1392 return BT_STATUS_FAIL;
1395 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1396 // DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1398 /* find characteristics */
1399 /* a service can have two char with same uuid */
1400 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1401 gattc_char = (hal_gattc_char_t*)l->data;
1402 if (gattc_char == NULL)
1405 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1406 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1407 // DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1409 /* get descriptor uuid */
1410 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1411 gattc_desc = (hal_gattc_desc_t *)m->data;
1412 if (gattc_desc == NULL)
1415 status = _hal_gattc_get_descriptor_info(gattc_desc);
1418 if (BT_STATUS_SUCCESS == status) {
1419 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1420 char_id, &gattc_desc->desc_uuid);
1426 status = BT_STATUS_FAIL;
1427 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1429 browse_service_char(conn_id);
1430 /* retrive uuid for characteristic and object path for descriptor */
1432 return BT_STATUS_SUCCESS;
1436 * Enumerate descriptors for a given characteristic.
1437 * Set start_descr_id to NULL to get the first descriptor.
1439 bt_status_t btif_gattc_get_descriptor(int conn_id,
1440 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1441 btgatt_gatt_id_t *start_descr_id)
1443 CHECK_BTGATT_INIT();
1445 if (start_descr_id == NULL) {
1446 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1448 DBG("TBD Get specific descriptor");
1449 return BT_STATUS_UNSUPPORTED;
1453 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1455 struct hal_ev_gatt_client_read_data ev;
1458 ERR("gatt client callback not registered");
1462 memset(&ev, 0, sizeof(ev));
1463 ev.conn_id = resp_data->conn_id;
1464 ev.inst_id = resp_data->srvc_id.id.inst_id;
1465 ev.is_primary = resp_data->srvc_id.is_primary;
1468 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1469 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1473 /* building the char read value */
1474 memcpy(ev.value, value, len);
1477 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1479 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1482 static void __hal_internal_read_char_cb(GObject *source_object,
1483 GAsyncResult *res, gpointer user_data)
1485 GError *error = NULL;
1486 GDBusConnection *system_gconn = NULL;
1489 GByteArray *gp_byte_array = NULL;
1491 hal_gatt_resp_data_t *resp_data = user_data;
1492 int result = BT_STATUS_SUCCESS;
1494 system_gconn = _bt_hal_get_system_gconn();
1495 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1498 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1501 result = BT_STATUS_FAIL;
1502 __hal_send_char_read_event(resp_data, result, NULL, 0);
1503 g_clear_error(&error);
1508 gp_byte_array = g_byte_array_new();
1509 g_variant_get(value, "(ay)", &iter);
1511 while (g_variant_iter_loop(iter, "y", &g_byte))
1512 g_byte_array_append(gp_byte_array, &g_byte, 1);
1516 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1520 g_byte_array_free(gp_byte_array, TRUE);
1521 g_variant_iter_free(iter);
1522 g_variant_unref(value);
1526 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1527 btgatt_gatt_id_t *char_id, int auth_req)
1529 GDBusConnection *g_conn;
1530 hal_gatt_resp_data_t *resp_data;
1531 hal_gattc_service_t *gattc_service = NULL;
1532 GVariantBuilder *builder = NULL;
1534 hal_gattc_server_info_t * conn_info = NULL;
1535 hal_gattc_char_t *gattc_char = NULL;
1536 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1537 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1538 char* char_handle = NULL;
1540 /* get the connection info */
1541 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1542 if (NULL == conn_info) {
1543 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1544 return BT_STATUS_FAIL;
1548 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1549 if (NULL == gattc_service) {
1550 ERR("Failed to get the gatt service");
1551 return BT_STATUS_FAIL;
1554 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1556 /* find characteristic */
1557 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1558 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1559 if (NULL == gattc_char) {
1560 ERR("Failed to get the gatt char");
1561 return BT_STATUS_FAIL;
1564 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1565 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1567 g_conn = _bt_hal_get_system_gconn();
1568 if (NULL == g_conn) {
1569 ERR("_bt_gdbus_get_system_gconn returned NULL");
1570 return BT_STATUS_FAIL;
1573 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1574 resp_data->conn_id = conn_id;
1575 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1576 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1578 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1581 g_variant_builder_add(builder, "{sv}", "offset",
1582 g_variant_new("q", offset));
1584 char_handle = gattc_char->chr_path;
1586 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1587 "ReadValue", g_variant_new("(a{sv})", builder),
1588 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1589 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1590 (gpointer)resp_data);
1591 g_variant_builder_unref(builder);
1593 return BT_STATUS_SUCCESS;
1596 /** Read a characteristic on a remote device */
1597 bt_status_t btif_read_characteristic(int conn_id,
1598 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1601 CHECK_BTGATT_INIT();
1603 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1606 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1608 struct hal_ev_gatt_client_write_result ev;
1611 ERR("gatt client callback not registered");
1615 memset(&ev, 0, sizeof(ev));
1616 ev.conn_id = resp_data->conn_id;
1617 ev.inst_id = resp_data->srvc_id.id.inst_id;
1618 ev.is_primary = resp_data->srvc_id.is_primary;
1621 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1622 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1624 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1627 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1628 GAsyncResult *res, gpointer user_data)
1630 GError *error = NULL;
1631 GDBusConnection *system_gconn = NULL;
1633 hal_gatt_resp_data_t *resp_data = user_data;
1634 int result = BT_STATUS_SUCCESS;
1636 system_gconn = _bt_hal_get_system_gconn();
1637 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1640 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1642 result = BT_STATUS_FAIL;
1644 __hal_send_char_write_event(resp_data, result);
1645 g_clear_error(&error);
1650 //send write value event
1651 __hal_send_char_write_event(resp_data, result);
1654 g_variant_unref(value);
1658 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1661 case HAL_GATT_WRITE_TYPE_WRITE:
1662 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1664 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1665 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1668 ERR("Unknow write type : %d", type);
1669 return BT_STATUS_FAIL;
1672 return BT_STATUS_SUCCESS;
1676 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1678 GDBusConnection *conn;
1679 GVariantBuilder *builder = NULL;
1685 GUnixFDList *fd_list = NULL;
1687 conn = _bt_hal_get_system_gconn();
1689 ERR("_bt_gdbus_get_system_gconn returned NULL");
1690 return BT_STATUS_FAIL;
1693 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1694 //val = g_variant_new("ay", builder1);
1696 g_variant_builder_add(builder, "{sv}", "offset",
1697 g_variant_new("q", offset));
1699 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1700 "AcquireWrite", g_variant_new("(a{sv})", builder),
1701 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1702 NULL, &fd_list, NULL, &err);
1704 g_dbus_error_strip_remote_error(err);
1705 ERR("Error: %s", err->message);
1707 g_variant_builder_unref(builder);
1708 return BT_STATUS_FAIL;
1711 g_variant_get(value, "(hq)", &idx, &att_mtu);
1712 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1714 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1717 g_object_unref(fd_list);
1718 g_variant_unref(value);
1719 g_variant_builder_unref(builder);
1721 return BT_STATUS_SUCCESS;
1724 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1726 GDBusConnection *conn;
1727 GVariantBuilder *builder = NULL;
1731 gint32 idx, notify_fd;
1733 GUnixFDList *fd_list = NULL;
1735 conn = _bt_hal_get_system_gconn();
1738 ERR("_bt_gdbus_get_system_gconn returned NULL");
1739 return BT_STATUS_FAIL;
1743 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1746 g_variant_builder_add(builder, "{sv}", "offset",
1747 g_variant_new("q", offset));
1749 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1750 "AcquireNotify", g_variant_new("(a{sv})", builder),
1751 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1752 NULL, &fd_list, NULL, &err);
1754 g_dbus_error_strip_remote_error(err);
1755 ERR("Error: %s", err->message);
1757 g_variant_builder_unref(builder);
1758 return BT_STATUS_FAIL;
1761 g_variant_get(value, "(hq)", &idx, &att_mtu);
1762 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1765 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1769 g_object_unref(fd_list);
1770 g_variant_unref(value);
1771 g_variant_builder_unref(builder);
1773 return BT_STATUS_SUCCESS;
1777 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1778 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1780 GVariant *val, *options;
1781 GVariantBuilder *builder1;
1782 GVariantBuilder *builder2;
1783 GDBusConnection *g_conn;
1786 hal_gatt_resp_data_t *resp_data;
1787 hal_gattc_service_t *gattc_service = NULL;
1788 hal_gattc_server_info_t * conn_info = NULL;
1789 hal_gattc_char_t *gattc_char = NULL;
1790 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1791 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1792 char* char_handle = NULL;
1793 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1794 int ret = BT_STATUS_SUCCESS;
1796 ret = __hal_get_write_prop(write_type, &write_prop);
1797 if (BT_STATUS_FAIL == ret) {
1798 DBG("received invalid write type:[%d] ", write_type);
1799 return BT_STATUS_FAIL;
1802 /* get the connection info */
1803 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1804 if (NULL == conn_info) {
1805 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1806 return BT_STATUS_FAIL;
1810 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1811 if (NULL == gattc_service) {
1812 ERR("Failed to get the gatt service");
1813 return BT_STATUS_FAIL;
1816 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1817 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1819 /* find characteristic */
1820 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1821 if (NULL == gattc_char) {
1822 ERR("Failed to get the gatt char");
1823 return BT_STATUS_FAIL;
1826 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1827 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1829 g_conn = _bt_hal_get_system_gconn();
1830 if (NULL == g_conn) {
1831 ERR("_bt_gdbus_get_system_gconn returned NULL");
1832 return BT_STATUS_FAIL;
1835 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1836 resp_data->conn_id = conn_id;
1837 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1838 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1840 char_handle = gattc_char->chr_path;
1842 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1844 for (i = 0; i < length; i++)
1845 g_variant_builder_add(builder1, "y", value[i]);
1847 val = g_variant_new("ay", builder1);
1849 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1851 g_variant_builder_add(builder2, "{sv}", "offset",
1852 g_variant_new_uint16(offset));
1854 options = g_variant_new("a{sv}", builder2);
1856 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1858 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1860 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1861 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1862 (gpointer)resp_data);
1864 g_variant_builder_unref(builder1);
1865 g_variant_builder_unref(builder2);
1867 return BT_STATUS_SUCCESS;
1870 bt_status_t btif_get_acquire_write_fd(int conn_id,
1871 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1872 int auth_req, int *fd, int*mtu)
1874 CHECK_BTGATT_INIT();
1876 hal_gattc_service_t *gattc_service = NULL;
1877 hal_gattc_server_info_t * conn_info = NULL;
1878 hal_gattc_char_t *gattc_char = NULL;
1879 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1881 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1882 int ret = BT_STATUS_SUCCESS;
1884 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1886 /* get the connection info */
1887 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1888 if (NULL == conn_info) {
1889 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1890 return BT_STATUS_FAIL;
1894 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1895 if (NULL == gattc_service) {
1896 ERR("Failed to get the gatt service");
1897 return BT_STATUS_FAIL;
1900 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1901 if (NULL == gattc_char) {
1902 ERR("Failed to get the gatt char");
1903 return BT_STATUS_FAIL;
1906 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1907 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1909 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1910 if (ret != BT_STATUS_SUCCESS)
1916 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1917 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1919 CHECK_BTGATT_INIT();
1921 hal_gattc_service_t *gattc_service = NULL;
1922 hal_gattc_server_info_t * conn_info = NULL;
1923 hal_gattc_char_t *gattc_char = NULL;
1924 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1926 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1927 int ret = BT_STATUS_SUCCESS;
1929 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1931 /* get the connection info */
1932 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1933 if (NULL == conn_info) {
1934 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1935 return BT_STATUS_FAIL;
1939 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1940 if (NULL == gattc_service) {
1941 ERR("Failed to get the gatt service");
1942 return BT_STATUS_FAIL;
1945 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1946 if (NULL == gattc_char) {
1947 ERR("Failed to get the gatt char");
1948 return BT_STATUS_FAIL;
1951 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1952 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1954 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1955 if (ret != BT_STATUS_SUCCESS)
1962 /** Write a remote characteristic */
1963 bt_status_t btif_write_characteristic(int conn_id,
1964 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1965 int write_type, int len, int auth_req,
1968 CHECK_BTGATT_INIT();
1970 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1971 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1972 len, auth_req, p_value);
1975 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1977 struct hal_ev_gatt_client_read_data ev;
1980 ERR("gatt client callback not registered");
1984 memset(&ev, 0, sizeof(ev));
1985 ev.conn_id = resp_data->conn_id;
1986 ev.inst_id = resp_data->srvc_id.id.inst_id;
1987 ev.is_primary = resp_data->srvc_id.is_primary;
1990 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1991 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1992 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1996 /* building the desc read value */
1997 memcpy(ev.value, value, len);
2000 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
2002 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
2005 static void __hal_internal_read_desc_cb(GObject *source_object,
2006 GAsyncResult *res, gpointer user_data)
2008 GError *error = NULL;
2009 GDBusConnection *system_gconn = NULL;
2012 GByteArray *gp_byte_array = NULL;
2014 hal_gatt_resp_data_t *resp_data = user_data;
2015 int result = BT_STATUS_SUCCESS;
2020 system_gconn = _bt_hal_get_system_gconn();
2021 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2024 ERR("Read descriptor dbus failed Error:[%s]", error->message);
2027 result = BT_STATUS_FAIL;
2028 __hal_send_desc_read_event(resp_data, result, NULL, 0);
2029 g_clear_error(&error);
2034 gp_byte_array = g_byte_array_new();
2035 g_variant_get(value, "(ay)", &iter);
2037 while (g_variant_iter_loop(iter, "y", &g_byte))
2038 g_byte_array_append(gp_byte_array, &g_byte, 1);
2042 for (i = 0; i < gp_byte_array->len; i++)
2043 DBG("%02x", gp_byte_array->data[i]);
2046 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2050 g_byte_array_free(gp_byte_array, TRUE);
2051 g_variant_iter_free(iter);
2052 g_variant_unref(value);
2057 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2058 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2060 GDBusConnection *g_conn;
2061 hal_gatt_resp_data_t *resp_data;
2062 hal_gattc_service_t *gattc_service = NULL;
2063 GVariantBuilder *builder = NULL;
2065 hal_gattc_server_info_t * conn_info = NULL;
2066 hal_gattc_char_t *gattc_char = NULL;
2067 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2068 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2069 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2070 char* desc_handle = NULL;
2073 hal_gattc_desc_t *gattc_desc = NULL;
2075 /* get the connection info */
2076 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2077 if (NULL == conn_info) {
2078 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2079 return BT_STATUS_FAIL;
2083 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2084 if (NULL == gattc_service) {
2085 ERR("Failed to get the gatt service");
2086 return BT_STATUS_FAIL;
2089 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2090 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2092 /* find characteristic */
2093 /* service can have two char with same uuid */
2094 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2095 gattc_char = (hal_gattc_char_t*)l->data;
2096 if (gattc_char == NULL)
2099 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2100 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2101 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2103 /* find descriptor */
2104 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2106 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2107 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2113 if (NULL == gattc_desc) {
2114 ERR("Failed to get the gatt desc");
2115 return BT_STATUS_FAIL;
2118 g_conn = _bt_hal_get_system_gconn();
2119 if (NULL == g_conn) {
2120 ERR("_bt_gdbus_get_system_gconn returned NULL");
2121 return BT_STATUS_FAIL;
2124 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2125 resp_data->conn_id = conn_id;
2126 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2127 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2128 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2130 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2133 g_variant_builder_add(builder, "{sv}", "offset",
2134 g_variant_new("q", offset));
2136 desc_handle = gattc_desc->desc_path;
2138 DBG("calling desc read value");
2140 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2141 "ReadValue", g_variant_new("(a{sv})", builder),
2142 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2143 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2144 (gpointer)resp_data);
2145 g_variant_builder_unref(builder);
2147 return BT_STATUS_SUCCESS;
2150 /** Read the descriptor for a given characteristic */
2151 bt_status_t btif_read_descriptor(int conn_id,
2152 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2153 btgatt_gatt_id_t *descr_id, int auth_req)
2155 CHECK_BTGATT_INIT();
2157 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2160 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2162 struct hal_ev_gatt_client_write_result ev;
2165 ERR("gatt client callback not registered");
2169 memset(&ev, 0, sizeof(ev));
2170 ev.conn_id = resp_data->conn_id;
2171 ev.inst_id = resp_data->srvc_id.id.inst_id;
2172 ev.is_primary = resp_data->srvc_id.is_primary;
2175 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2176 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2177 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2179 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2181 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2184 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2185 GAsyncResult *res, gpointer user_data)
2187 GError *error = NULL;
2188 GDBusConnection *system_gconn = NULL;
2190 hal_gatt_resp_data_t *resp_data = user_data;
2191 int result = BT_STATUS_SUCCESS;
2195 system_gconn = _bt_hal_get_system_gconn();
2196 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2199 ERR("write descriptor dbus failed Error: [%s]", error->message);
2202 result = BT_STATUS_FAIL;
2203 __hal_send_desc_write_event(resp_data, result);
2204 g_clear_error(&error);
2209 //send write value event
2210 __hal_send_desc_write_event(resp_data, result);
2213 g_variant_unref(value);
2218 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2219 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2220 int write_type, int length, int auth_req, char* value)
2222 GVariant *val, *options;
2223 GVariantBuilder *builder1;
2224 GVariantBuilder *builder2;
2225 GDBusConnection *g_conn;
2228 hal_gatt_resp_data_t *resp_data;
2229 hal_gattc_service_t *gattc_service = NULL;
2230 hal_gattc_server_info_t * conn_info = NULL;
2231 hal_gattc_char_t *gattc_char = NULL;
2232 hal_gattc_desc_t *gattc_desc = NULL;
2233 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2234 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2235 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2236 char* desc_handle = NULL;
2237 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2238 int ret = BT_STATUS_SUCCESS;
2243 ret = __hal_get_write_prop(write_type, &write_prop);
2244 if (BT_STATUS_FAIL == ret) {
2245 ERR("received invalid write type:[%d] ", write_type);
2246 return BT_STATUS_FAIL;
2249 /* get the connection info */
2250 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2251 if (NULL == conn_info) {
2252 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2253 return BT_STATUS_FAIL;
2257 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2258 if (NULL == gattc_service) {
2259 ERR("Failed to get the gatt service");
2260 return BT_STATUS_FAIL;
2263 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2264 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2266 /* find characteristic */
2267 /* service can have two char with same uuid */
2268 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2269 gattc_char = (hal_gattc_char_t*)l->data;
2270 if (gattc_char == NULL)
2273 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2274 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2275 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2277 /* find descriptor */
2278 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2280 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2281 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2287 if (NULL == gattc_desc) {
2288 ERR("Failed to get the gatt desc");
2289 return BT_STATUS_FAIL;
2292 g_conn = _bt_hal_get_system_gconn();
2293 if (NULL == g_conn) {
2294 ERR("_bt_gdbus_get_system_gconn returned NULL");
2295 return BT_STATUS_FAIL;
2298 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2299 resp_data->conn_id = conn_id;
2300 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2301 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2302 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2304 desc_handle = gattc_desc->desc_path;
2306 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2308 for (i = 0; i < length; i++)
2309 g_variant_builder_add(builder1, "y", value[i]);
2311 val = g_variant_new("ay", builder1);
2313 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2315 g_variant_builder_add(builder2, "{sv}", "offset",
2316 g_variant_new_uint16(offset));
2318 options = g_variant_new("a{sv}", builder2);
2320 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2322 g_variant_new("(@ay@a{sv})", val, options),
2324 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2325 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2326 (gpointer)resp_data);
2328 g_variant_builder_unref(builder1);
2329 g_variant_builder_unref(builder2);
2331 return BT_STATUS_SUCCESS;
2334 /** Write a remote descriptor for a given characteristic */
2335 bt_status_t btif_write_descriptor(int conn_id,
2336 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2337 btgatt_gatt_id_t *descr_id, int write_type, int len,
2338 int auth_req, char* p_value)
2340 CHECK_BTGATT_INIT();
2342 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2343 len, auth_req, p_value);
2346 /** Execute a prepared write operation */
2347 bt_status_t execute_write(int conn_id, int execute)
2349 CHECK_BTGATT_INIT();
2350 return BT_STATUS_UNSUPPORTED;
2353 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2355 struct hal_ev_gatt_client_watch_notification ev;
2356 hal_gatt_resp_data_t *resp_data = user_data;
2358 DBG("sending the watch register notification event");
2359 /* send the event */
2360 memset(&ev, 0, sizeof(ev));
2361 ev.conn_id = resp_data->conn_id;
2363 ev.status = resp_data->result;
2365 ev.is_primary = resp_data->srvc_id.is_primary;
2366 ev.inst_id = resp_data->srvc_id.id.inst_id;
2368 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2369 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2372 ERR("GATT Callback not registered");
2374 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2381 static bt_status_t _hal_register_for_notification(int conn_id,
2382 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2383 btgatt_gatt_id_t *char_id)
2385 int result = BT_STATUS_SUCCESS;
2386 GError *error = NULL;
2387 GDBusConnection *g_conn;
2388 hal_gattc_client_info_t *gattc_client = NULL;
2389 hal_gattc_server_info_t * conn_info = NULL;
2390 hal_gattc_service_t *gattc_service = NULL;
2391 hal_gattc_char_t *gattc_char = NULL;
2392 char* char_handle = NULL;
2393 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2394 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2395 hal_gatt_resp_data_t *resp_data;
2399 gattc_client = __bt_find_gatt_client_info(bd_addr);
2400 if (gattc_client == NULL) {
2401 ERR("failed to get the gatt client info");
2402 return BT_STATUS_FAIL;
2405 if (gattc_client->conn_id != conn_id) {
2406 ERR("could not find the gatt client for client id[%d]", conn_id);
2407 return BT_STATUS_FAIL;
2410 /* get the connection info */
2411 conn_info = __bt_find_gatt_conn_info(bd_addr);
2412 if (NULL == conn_info) {
2413 ERR("Failed to get the conn_info");
2414 return BT_STATUS_FAIL;
2417 if (conn_info->inst_id != gattc_client->inst_id) {
2418 ERR("could not fild the conn_info");
2419 return BT_STATUS_FAIL;
2423 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2424 if (NULL == gattc_service) {
2425 ERR("Failed to get the gatt service");
2426 return BT_STATUS_FAIL;
2429 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2430 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2433 /* find characteristic */
2434 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2435 if (NULL == gattc_char) {
2436 ERR("Failed to get the gatt char");
2437 return BT_STATUS_FAIL;
2440 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2441 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2443 char_handle = gattc_char->chr_path;
2445 g_conn = _bt_hal_get_system_gconn();
2446 if (g_conn == NULL) {
2448 return BT_STATUS_FAIL;
2451 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2453 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2455 g_dbus_connection_call_sync(g_conn,
2458 BT_HAL_GATT_CHAR_INTERFACE,
2462 G_DBUS_CALL_FLAGS_NONE,
2463 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2466 g_dbus_error_strip_remote_error(error);
2467 ERR("### StartNotify Failed: %s", error->message);
2468 if (g_strrstr(error->message, "Already notifying"))
2469 result = BT_STATUS_SUCCESS;
2470 else if (g_strrstr(error->message, "In Progress"))
2471 result = BT_STATUS_BUSY;
2472 else if (g_strrstr(error->message, "Operation is not supported"))
2473 result = BT_STATUS_UNSUPPORTED;
2474 /*failed because of either Insufficient Authorization or Write Not Permitted */
2475 else if (g_strrstr(error->message, "Write not permitted") ||
2476 g_strrstr(error->message, "Operation Not Authorized"))
2477 result = BT_STATUS_AUTH_FAILURE;
2478 /* failed because of either Insufficient Authentication,
2479 Insufficient Encryption Key Size, or Insufficient Encryption. */
2480 else if (g_strrstr(error->message, "Not paired"))
2481 result = BT_STATUS_NOT_READY;
2483 result = BT_STATUS_FAIL;
2485 g_clear_error(&error);
2488 resp_data->conn_id = gattc_client->conn_id;
2489 resp_data->result = result;
2490 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2491 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2493 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2497 return BT_STATUS_SUCCESS;
2501 * Register to receive notifications or indications for a given
2504 bt_status_t btif_register_for_notification(int conn_id,
2505 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2506 btgatt_gatt_id_t *char_id)
2508 CHECK_BTGATT_INIT();
2510 return _hal_register_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2513 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2515 struct hal_ev_gatt_client_watch_notification ev;
2516 hal_gatt_resp_data_t *resp_data = user_data;
2518 DBG("sending the watch deregister notification event");
2519 /* send the event */
2520 memset(&ev, 0, sizeof(ev));
2521 ev.conn_id = resp_data->conn_id;
2523 ev.status = resp_data->result;
2525 ev.is_primary = resp_data->srvc_id.is_primary;
2526 ev.inst_id = resp_data->srvc_id.id.inst_id;
2528 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2529 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2532 ERR("GATT Callback not registered");
2534 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2541 static bt_status_t _hal_deregister_for_notification(int conn_id,
2542 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2543 btgatt_gatt_id_t *char_id)
2545 int result = BT_STATUS_SUCCESS;
2546 GError *error = NULL;
2547 GDBusConnection *g_conn;
2548 hal_gattc_client_info_t *gattc_client = NULL;
2549 hal_gattc_server_info_t * conn_info = NULL;
2550 hal_gattc_service_t *gattc_service = NULL;
2551 hal_gattc_char_t *gattc_char = NULL;
2552 char* char_handle = NULL;
2553 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2554 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2555 hal_gatt_resp_data_t *resp_data;
2559 gattc_client = __bt_find_gatt_client_info(bd_addr);
2560 if (gattc_client == NULL) {
2561 ERR("failed to get the gatt client info");
2562 return BT_STATUS_FAIL;
2565 if (gattc_client->conn_id != conn_id) {
2566 ERR("could not find the gatt client for client id[%d]", conn_id);
2567 return BT_STATUS_FAIL;
2570 /* get the connection info */
2571 conn_info = __bt_find_gatt_conn_info(bd_addr);
2572 if (NULL == conn_info) {
2573 ERR("Failed to get the conn_info");
2574 return BT_STATUS_FAIL;
2577 if (conn_info->inst_id != gattc_client->inst_id) {
2578 ERR("could not fild the conn_info");
2579 return BT_STATUS_FAIL;
2583 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2584 if (NULL == gattc_service) {
2585 ERR("Failed to get the gatt service");
2586 return BT_STATUS_FAIL;
2589 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2590 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2593 /* find characteristic */
2594 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2595 if (NULL == gattc_char) {
2596 ERR("Failed to get the gatt char");
2597 return BT_STATUS_FAIL;
2600 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2601 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2603 char_handle = gattc_char->chr_path;
2605 g_conn = _bt_hal_get_system_gconn();
2606 if (g_conn == NULL) {
2608 return BT_STATUS_FAIL;
2611 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2613 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2614 g_dbus_connection_call_sync(g_conn,
2617 BT_HAL_GATT_CHAR_INTERFACE,
2621 G_DBUS_CALL_FLAGS_NONE,
2622 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2625 ERR("### StopNotify Failed: %s", error->message);
2626 g_clear_error(&error);
2627 result = BT_STATUS_FAIL;
2630 resp_data->conn_id = gattc_client->conn_id;
2631 resp_data->result = result;
2632 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2633 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2635 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2639 return BT_STATUS_SUCCESS;
2641 /** Deregister a previous request for notifications/indications */
2642 bt_status_t btif_deregister_for_notification(int conn_id,
2643 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2644 btgatt_gatt_id_t *char_id)
2646 CHECK_BTGATT_INIT();
2647 return _hal_deregister_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2650 /** Request RSSI for a given remote device */
2651 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2653 CHECK_BTGATT_INIT();
2654 return BT_STATUS_UNSUPPORTED;
2657 /** OTA firmware download */
2658 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2660 CHECK_BTGATT_INIT();
2661 return BT_STATUS_UNSUPPORTED;
2664 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2665 int get_device_type(const bt_bdaddr_t *bd_addr)
2667 CHECK_BTGATT_INIT();
2668 return BT_STATUS_UNSUPPORTED;
2671 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2672 int min_int, int max_int, int latency, int timeout)
2674 gchar *device_path = NULL;
2675 GError *error = NULL;
2676 GDBusProxy *device_proxy = NULL;
2677 GDBusConnection *conn;
2679 int ret = BT_STATUS_SUCCESS;
2680 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2682 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2683 min_int, max_int, latency, timeout);
2685 conn = _bt_hal_get_system_gconn();
2688 return BT_STATUS_FAIL;
2691 _bt_hal_convert_addr_type_to_string(device_address,
2692 (unsigned char *)bd_addr->address);
2693 device_path = _bt_hal_get_device_object_path(device_address);
2695 if (device_path == NULL) {
2696 ERR("device_path NULL : [%s]", device_address);
2697 return BT_STATUS_FAIL;
2700 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2701 NULL, BT_HAL_BLUEZ_NAME,
2702 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2704 g_free(device_path);
2705 if (NULL == device_proxy) {
2706 ERR("device_proxy returned NULL");
2707 return BT_STATUS_FAIL;
2710 DBG("Request LeConnUpdate");
2711 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2712 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2713 G_DBUS_CALL_FLAGS_NONE,
2718 g_object_unref(device_proxy);
2719 if (reply == NULL) {
2721 ERR("Error %s[%s]", error->message, device_address);
2722 if (g_strrstr(error->message, "In Progress"))
2723 ret = BT_STATUS_SUCCESS;
2725 ret = BT_STATUS_FAIL;
2726 g_error_free(error);
2730 g_variant_unref(reply);
2732 DBG("LE Connection parameter Updated");
2736 /** Request a connection parameter update */
2737 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2739 CHECK_BTGATT_INIT();
2741 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2744 /** Test mode interface */
2745 bt_status_t test_command(int command, btgatt_test_params_t* params)
2747 CHECK_BTGATT_INIT();
2748 return BT_STATUS_UNSUPPORTED;
2751 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2754 GError *g_error = NULL;
2755 GVariant *reply = NULL;
2756 int result = BT_STATUS_SUCCESS;
2757 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2758 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2760 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2761 g_object_unref(proxy);
2762 if (reply == NULL) {
2763 ERR("Connect LE Dbus Call Error");
2765 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2766 g_clear_error(&g_error);
2768 result = BT_STATUS_FAIL;
2770 g_variant_unref(reply);
2772 memset(&ev, 0, sizeof(ev));
2774 ev.mtu = conn_mtu->mtu;
2775 ev.conn_id = conn_mtu->conn_id;
2778 ERR("gatt client callback not registered");
2780 DBG("sending gatt client MTU exchange completed event");
2781 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2787 static bt_status_t get_att_mtu(int conn_id, int *mtu_size)
2789 CHECK_BTGATT_INIT();
2790 GDBusProxy *device_proxy;
2791 gchar *device_path = NULL;
2792 GError *error = NULL;
2794 GVariant *tmp_value;
2795 GDBusConnection *conn;
2796 GVariant *result = NULL;
2797 int ret = BT_STATUS_SUCCESS;
2798 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2799 hal_gattc_client_info_t *gattc_client = NULL;
2802 if (mtu_size == NULL)
2803 return BT_STATUS_PARM_INVALID;
2805 conn = _bt_hal_get_system_gconn();
2808 return BT_STATUS_FAIL;
2811 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2812 if (gattc_client == NULL) {
2813 INFO("GATT client conn info not found");
2814 return BT_STATUS_FAIL;
2817 _bt_hal_convert_addr_type_to_string(device_address,
2818 (unsigned char *)gattc_client->bd_addr.address);
2820 device_path = _bt_hal_get_device_object_path(device_address);
2821 if (device_path == NULL) {
2822 ERR("device_path NULL : [%s]", device_address);
2823 return BT_STATUS_FAIL;
2826 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2827 NULL, BT_HAL_BLUEZ_NAME,
2828 device_path, BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
2830 g_free(device_path);
2831 if (NULL == device_proxy) {
2832 ERR("device_proxy returned NULL");
2833 return BT_STATUS_FAIL;
2836 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
2837 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
2838 G_DBUS_CALL_FLAGS_NONE,
2842 if (result == NULL) {
2843 if (error != NULL) {
2844 ERR("Error occured in Proxy call [%s]\n", error->message);
2845 g_error_free(error);
2847 g_object_unref(device_proxy);
2848 return BT_STATUS_FAIL;
2851 g_variant_get(result , "(@a{sv})", &value);
2852 g_variant_unref(result);
2854 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
2855 if (tmp_value == NULL) {
2856 g_object_unref(device_proxy);
2857 g_variant_unref(value);
2858 return BT_STATUS_FAIL;
2861 mtu = g_variant_get_uint16(tmp_value);
2863 DBG("ATT MTU : [%d]", mtu);
2865 g_variant_unref(tmp_value);
2866 g_variant_unref(value);
2867 g_object_unref(device_proxy);
2869 *mtu_size = (int) mtu;
2874 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2876 gchar *device_path = NULL;
2877 GDBusProxy *device_proxy = NULL;
2878 GDBusConnection *conn;
2879 hal_gattc_client_info_t *gattc_client = NULL;
2880 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2881 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2883 conn = _bt_hal_get_system_gconn();
2887 return BT_STATUS_FAIL;
2890 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2891 if (gattc_client == NULL) {
2892 INFO("GATT client conn info not found");
2894 return BT_STATUS_FAIL;
2897 _bt_hal_convert_addr_type_to_string(device_address,
2898 (unsigned char *)gattc_client->bd_addr.address);
2900 device_path = _bt_hal_get_device_object_path(device_address);
2901 if (device_path == NULL) {
2902 ERR("device_path NULL : [%s]", device_address);
2904 return BT_STATUS_FAIL;
2907 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2908 NULL, BT_HAL_BLUEZ_NAME,
2909 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2911 g_free(device_path);
2912 if (NULL == device_proxy) {
2913 ERR("device_proxy returned NULL");
2915 return BT_STATUS_FAIL;
2918 conn_mtu->conn_id = conn_id;
2919 conn_mtu->mtu = mtu;
2921 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2922 g_variant_new("(q)", mtu),
2923 G_DBUS_CALL_FLAGS_NONE,
2924 BT_HAL_MAX_DBUS_TIMEOUT,
2926 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2929 return BT_STATUS_SUCCESS;
2932 /** MTU Exchange request from client */
2933 static bt_status_t configure_mtu(int conn_id, int mtu)
2935 CHECK_BTGATT_INIT();
2937 return __hal_configure_mtu(conn_id, mtu);
2940 /** Setup scan filter params */
2941 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2942 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2943 int rssi_low_thres, int dely_mode, int found_timeout,
2944 int lost_timeout, int found_timeout_cnt)
2947 GError *error = NULL;
2948 GVariant *ret, *param;
2949 CHECK_BTGATT_INIT();
2951 proxy = _bt_hal_get_adapter_proxy();
2954 return BT_STATUS_FAIL;
2956 param = g_variant_new("(iiiiiiiiiiii)",
2969 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2970 param, G_DBUS_CALL_FLAGS_NONE,
2974 ERR("scan_filter_param_setup Fail: %s", error->message);
2975 g_clear_error(&error);
2976 return BT_STATUS_FAIL;
2980 g_variant_unref(ret);
2982 return BT_STATUS_SUCCESS;
2985 /** Configure a scan filter condition */
2986 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2987 int filt_index, int company_id,
2988 int company_id_mask, const bt_uuid_t *p_uuid,
2989 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2990 char addr_type, int data_len, char* p_data, int mask_len,
2994 GError *error = NULL;
2995 GVariant *ret, *param;
2996 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2997 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2998 GArray *arr_uuid = NULL;
2999 GArray *arr_uuid_mask = NULL;
3000 GArray *arr_data = NULL;
3001 GArray *arr_data_mask = NULL;
3002 CHECK_BTGATT_INIT();
3004 proxy = _bt_hal_get_adapter_proxy();
3007 return BT_STATUS_FAIL;
3009 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
3011 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3013 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
3015 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
3017 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3018 NULL, 0, TRUE, NULL, NULL);
3019 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3020 NULL, 0, TRUE, NULL, NULL);
3021 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3022 NULL, 0, TRUE, NULL, NULL);
3023 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3024 NULL, 0, TRUE, NULL, NULL);
3026 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3027 client_if, // client_if
3028 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3029 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
3030 filt_index, // filter_index
3031 company_id, // company_id
3032 company_id_mask, // company_id_mask
3033 arr_uuid_param, // p_uuid
3034 arr_uuid_mask_param, // p_uuid_mask
3036 addr_type, // address_type
3037 arr_data_param, // p_data
3038 arr_data_mask_param); // p_mask
3040 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3041 param, G_DBUS_CALL_FLAGS_NONE,
3045 ERR("scan_filter_add_remove Fail: %s", error->message);
3046 g_clear_error(&error);
3047 return BT_STATUS_FAIL;
3051 g_variant_unref(ret);
3053 return BT_STATUS_SUCCESS;
3056 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
3058 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
3059 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3060 NULL, 0, TRUE, NULL, NULL);
3061 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3062 NULL, 0, TRUE, NULL, NULL);
3063 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3064 NULL, 0, TRUE, NULL, NULL);
3065 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3066 NULL, 0, TRUE, NULL, NULL);
3068 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3069 client_if, // client_if
3070 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3071 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
3072 filt_index, // filter_index
3073 company_id, // company_id
3074 company_id_mask, // company_id_mask
3075 arr_uuid_param, // p_uuid
3076 arr_uuid_mask_param, // p_uuid_mask
3078 addr_type, // address_type
3079 arr_data_param, // p_data
3080 arr_data_mask_param);
3082 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3083 param, G_DBUS_CALL_FLAGS_NONE,
3087 ERR("scan_filter_add_remove Fail: %s", error->message);
3088 g_clear_error(&error);
3089 return BT_STATUS_FAIL;
3093 g_variant_unref(ret);
3095 return BT_STATUS_SUCCESS;
3098 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
3100 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3101 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3103 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3104 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3106 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3107 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3108 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3109 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3110 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3111 NULL, 0, TRUE, NULL, NULL);
3112 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3113 NULL, 0, TRUE, NULL, NULL);
3115 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3116 client_if, // client_if
3117 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3118 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
3119 filt_index, // filter_index
3120 company_id, // company_id
3121 company_id_mask, // company_id_mask
3122 arr_uuid_param, // p_uuid
3123 arr_uuid_mask_param, // p_uuid_mask
3125 addr_type, // address_type
3126 arr_data_param, // p_data
3127 arr_data_mask_param);
3129 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3130 param, G_DBUS_CALL_FLAGS_NONE,
3134 ERR("scan_filter_add_remove Fail: %s", error->message);
3135 g_clear_error(&error);
3136 return BT_STATUS_FAIL;
3140 g_variant_unref(ret);
3142 g_array_free(arr_uuid, TRUE);
3143 g_array_free(arr_uuid_mask, TRUE);
3145 return BT_STATUS_SUCCESS;
3148 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3150 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3151 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3153 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3154 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3156 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3157 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3158 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3159 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3160 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3161 NULL, 0, TRUE, NULL, NULL);
3162 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3163 NULL, 0, TRUE, NULL, NULL);
3165 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3166 client_if, // client_if
3167 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3168 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3169 filt_index, // filter_index
3170 company_id, // company_id
3171 company_id_mask, // company_id_mask
3172 arr_uuid_param, // p_uuid
3173 arr_uuid_mask_param, // p_uuid_mask
3175 addr_type, // address_type
3176 arr_data_param, // p_data
3177 arr_data_mask_param);
3179 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3180 G_DBUS_CALL_FLAGS_NONE,
3184 ERR("scan_filter_add_remove Fail: %s", error->message);
3185 g_clear_error(&error);
3186 return BT_STATUS_FAIL;
3190 g_variant_unref(ret);
3192 g_array_free(arr_uuid, TRUE);
3193 g_array_free(arr_uuid_mask, TRUE);
3195 return BT_STATUS_SUCCESS;
3198 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3200 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3201 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3203 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3204 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3206 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3207 NULL, 0, TRUE, NULL, NULL);
3208 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3209 NULL, 0, TRUE, NULL, NULL);
3210 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3211 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3212 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3213 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3215 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3216 client_if, // client_if
3217 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3218 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3219 filt_index, // filter_index
3220 company_id, // company_id
3221 company_id_mask, // company_id_mask
3222 arr_uuid_param, // p_uuid
3223 arr_uuid_mask_param, // p_uuid_mask
3225 addr_type, // address_type
3226 arr_data_param, // p_data
3227 arr_data_mask_param);
3229 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3230 G_DBUS_CALL_FLAGS_NONE,
3234 ERR("scan_filter_add_remove Fail: %s", error->message);
3235 g_clear_error(&error);
3236 return BT_STATUS_FAIL;
3240 g_variant_unref(ret);
3242 g_array_free(arr_data, TRUE);
3243 g_array_free(arr_data_mask, TRUE);
3245 return BT_STATUS_SUCCESS;
3248 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3250 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3251 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3253 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3254 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3256 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3257 NULL, 0, TRUE, NULL, NULL);
3258 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3259 NULL, 0, TRUE, NULL, NULL);
3260 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3261 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3262 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3263 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3265 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3266 client_if, // client_if
3267 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3268 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3269 filt_index, // filter_index
3270 company_id, // company_id
3271 company_id_mask, // company_id_mask
3272 arr_uuid_param, // p_uuid
3273 arr_uuid_mask_param, // p_uuid_mask
3275 addr_type, // address_type
3276 arr_data_param, // p_data
3277 arr_data_mask_param);
3279 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3280 G_DBUS_CALL_FLAGS_NONE,
3284 ERR("scan_filter_add_remove Fail: %s", error->message);
3285 g_clear_error(&error);
3286 return BT_STATUS_FAIL;
3290 g_variant_unref(ret);
3292 g_array_free(arr_data, TRUE);
3293 g_array_free(arr_data_mask, TRUE);
3295 return BT_STATUS_SUCCESS;
3298 return BT_STATUS_UNSUPPORTED;
3301 /** Clear all scan filter conditions for specific filter index*/
3302 bt_status_t scan_filter_clear(int client_if, int filt_index)
3305 GError *error = NULL;
3307 CHECK_BTGATT_INIT();
3309 proxy = _bt_hal_get_adapter_proxy();
3311 return BT_STATUS_FAIL;
3313 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3314 g_variant_new("(ii)", client_if, filt_index),
3315 G_DBUS_CALL_FLAGS_NONE,
3319 ERR("scan_filter_clear Fail: %s", error->message);
3320 g_clear_error(&error);
3321 return BT_STATUS_FAIL;
3324 g_variant_unref(ret);
3325 return BT_STATUS_SUCCESS;
3328 /** Enable / disable scan filter feature*/
3329 bt_status_t scan_filter_enable(int client_if, bool enable)
3332 GError *error = NULL;
3334 CHECK_BTGATT_INIT();
3336 proxy = _bt_hal_get_adapter_proxy();
3338 return BT_STATUS_FAIL;
3340 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3341 g_variant_new("(ib)", client_if, enable),
3342 G_DBUS_CALL_FLAGS_NONE,
3346 ERR("scan_filter_enable Fail: %s", error->message);
3347 g_clear_error(&error);
3348 return BT_STATUS_FAIL;
3350 g_variant_unref(ret);
3352 return BT_STATUS_SUCCESS;
3355 /** Sets the LE scan interval and window in units of N*0.625 msec */
3357 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3361 CHECK_BTGATT_INIT();
3363 le_scan_type = scan_type;
3364 ret = _bt_hal_adapter_le_set_scan_parameters(
3365 scan_type, scan_interval, scan_window);
3369 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3371 CHECK_BTGATT_INIT();
3372 return BT_STATUS_UNSUPPORTED;
3376 /* Configure the batchscan storage */
3377 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3378 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3380 CHECK_BTGATT_INIT();
3381 return BT_STATUS_UNSUPPORTED;
3384 /* Enable batchscan */
3385 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3386 int scan_interval, int scan_window, int addr_type, int discard_rule)
3388 CHECK_BTGATT_INIT();
3389 return BT_STATUS_UNSUPPORTED;
3392 /* Disable batchscan */
3393 bt_status_t batchscan_dis_batch_scan(int client_if)
3395 CHECK_BTGATT_INIT();
3396 return BT_STATUS_UNSUPPORTED;
3399 /* Read out batchscan reports */
3400 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3402 CHECK_BTGATT_INIT();
3403 return BT_STATUS_UNSUPPORTED;
3406 bt_status_t btif_gatt_get_data_batching_available_packets(unsigned int *available_packets)
3409 GError *error = NULL;
3411 guint32 available_pkts;
3413 CHECK_BTGATT_INIT();
3415 if (available_packets == NULL) {
3416 ERR("available_packets is NULL");
3417 return BT_STATUS_PARM_INVALID;
3420 proxy = _bt_hal_get_adapter_proxy();
3421 if (proxy == NULL) {
3422 ERR("proxy is NULL");
3423 return BT_STATUS_FAIL;
3426 ret = g_dbus_proxy_call_sync(proxy, "GetLeBatchingAvailablePkts",
3428 G_DBUS_CALL_FLAGS_NONE,
3431 int result = BT_STATUS_FAIL;
3433 ERR("SetLeBatchingParam Fail: %s", error->message);
3434 if (g_strrstr(error->message, "Operation is not supported"))
3435 result = BT_STATUS_UNSUPPORTED;
3437 g_clear_error(&error);
3440 g_variant_get(ret, "(u)", &available_pkts);
3441 g_variant_unref(ret);
3443 INFO("GATT Batching available packets: %u", available_pkts);
3444 *available_packets = available_pkts;
3445 return BT_STATUS_SUCCESS;
3448 bt_status_t btif_gatt_enable_data_batching(const bt_bdaddr_t *bd_addr, int packet_threshold, int timeout)
3450 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3452 GError *error = NULL;
3454 CHECK_BTGATT_INIT();
3456 if (bd_addr == NULL) {
3457 ERR("bd_addr is NULL");
3458 return BT_STATUS_PARM_INVALID;
3461 proxy = _bt_hal_get_adapter_proxy();
3462 if (proxy == NULL) {
3463 ERR("proxy is NULL");
3464 return BT_STATUS_FAIL;
3467 _bt_hal_convert_addr_type_to_string(device_address,
3468 (unsigned char *)bd_addr->address);
3469 ret = g_dbus_proxy_call_sync(proxy, "EnableLeBatching",
3470 g_variant_new("(sii)", device_address, packet_threshold, timeout),
3471 G_DBUS_CALL_FLAGS_NONE,
3474 int result = BT_STATUS_FAIL;
3476 ERR("SetLeBatchingParam Fail: %s", error->message);
3477 if (g_strrstr(error->message, "Operation is not supported"))
3478 result = BT_STATUS_UNSUPPORTED;
3479 else if (g_strrstr(error->message, "Invalid arguments"))
3480 result = BT_STATUS_PARM_INVALID;
3482 g_clear_error(&error);
3485 g_variant_unref(ret);
3487 INFO("GATT Batching is enabled");
3488 return BT_STATUS_SUCCESS;
3491 bt_status_t btif_gatt_disable_data_batching(const bt_bdaddr_t *bd_addr)
3493 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3495 GError *error = NULL;
3497 CHECK_BTGATT_INIT();
3499 if (bd_addr == NULL) {
3500 ERR("bd_addr is NULL");
3501 return BT_STATUS_PARM_INVALID;
3504 proxy = _bt_hal_get_adapter_proxy();
3505 if (proxy == NULL) {
3506 ERR("proxy is NULL");
3507 return BT_STATUS_FAIL;
3510 _bt_hal_convert_addr_type_to_string(device_address,
3511 (unsigned char *)bd_addr->address);
3512 ret = g_dbus_proxy_call_sync(proxy, "DisableLeBatching",
3513 g_variant_new("(s)", device_address),
3514 G_DBUS_CALL_FLAGS_NONE,
3517 int result = BT_STATUS_FAIL;
3519 ERR("SetLeBatching Fail: %s", error->message);
3520 if (g_strrstr(error->message, "Operation is not supported"))
3521 result = BT_STATUS_UNSUPPORTED;
3523 g_clear_error(&error);
3526 g_variant_unref(ret);
3528 INFO("GATT Batching is disabled");
3529 return BT_STATUS_SUCCESS;
3532 const btgatt_client_interface_t btgatt_client_interface = {
3533 .register_client = btif_gattc_register_client,
3534 .unregister_client = btif_gattc_unregister_client,
3536 .connect = btif_gattc_client_connect,
3537 .disconnect = btif_gattc_client_disconnect,
3539 .search_service = btif_gattc_client_search_service,
3540 .get_included_service = get_included_service,
3541 .get_characteristic = btif_gattc_get_characteristic,
3542 .get_descriptor = btif_gattc_get_descriptor,
3543 .read_characteristic = btif_read_characteristic,
3544 .write_characteristic = btif_write_characteristic,
3545 .acquire_write = btif_get_acquire_write_fd,
3546 .acquire_notify = btif_get_acquire_notify_fd,
3547 .read_descriptor = btif_read_descriptor,
3548 .write_descriptor = btif_write_descriptor,
3549 .execute_write = execute_write,
3550 .register_for_notification = btif_register_for_notification,
3551 .deregister_for_notification = btif_deregister_for_notification,
3552 .read_remote_rssi = read_remote_rssi,
3553 .ota_fw_update = ota_fw_update,
3554 .get_device_type = get_device_type,
3555 .conn_parameter_update = btif_gattc_conn_parameter_update,
3556 .test_command = test_command,
3557 .get_att_mtu = get_att_mtu,
3558 .configure_mtu = configure_mtu,
3559 .scan_filter_param_setup = scan_filter_param_setup,
3560 .scan_filter_add_remove = scan_filter_add_remove,
3561 .scan_filter_clear = scan_filter_clear,
3562 .scan_filter_enable = scan_filter_enable,
3563 .set_scan_parameters = set_scan_parameters,
3564 .batchscan_cfg_storage = batchscan_cfg_storage,
3565 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3566 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3567 .batchscan_read_reports = batchscan_read_reports,
3568 .add_connection_info = btif_gattc_add_connection_info,
3569 .get_data_batching_available_packets = btif_gatt_get_data_batching_available_packets,
3570 .enable_data_batching = btif_gatt_enable_data_batching,
3571 .disable_data_batching = btif_gatt_disable_data_batching,
3574 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3577 hal_gattc_server_info_t *info = NULL;
3579 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3580 info = (hal_gattc_server_info_t*)l->data;
3584 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3591 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3594 hal_gattc_client_info_t *info = NULL;
3596 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3597 info = (hal_gattc_client_info_t*)l->data;
3601 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3608 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3611 hal_gattc_client_info_t *info = NULL;
3613 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3614 info = (hal_gattc_client_info_t*)l->data;
3618 if (info->conn_id == conn_id)
3625 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3628 hal_gattc_server_info_t *info = NULL;
3629 hal_gattc_client_info_t *gattc_client = NULL;
3631 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3632 if (gattc_client == NULL) {
3633 ERR("GATT client conn info not found");
3637 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3638 info = (hal_gattc_server_info_t*)l->data;
3642 if ((info->inst_id == gattc_client->inst_id) &&
3643 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3650 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3651 gboolean auto_connect)
3653 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3654 gchar *device_path = NULL;
3655 GDBusProxy *device_proxy = NULL;
3656 GDBusConnection *conn;
3657 int ret = BT_STATUS_SUCCESS;
3658 hal_gattc_client_info_t *gattc_data;
3660 if (NULL == bd_addr) {
3661 ERR("bd_addr is NULL");
3662 return BT_STATUS_PARM_INVALID;
3665 conn = _bt_hal_get_system_gconn();
3667 ERR("_bt_gdbus_get_system_gconn returned NULL");
3668 return BT_STATUS_FAIL;
3671 _bt_hal_convert_addr_type_to_string(device_address,
3672 (unsigned char *)bd_addr->address);
3673 device_path = _bt_hal_get_device_object_path(device_address);
3674 if (device_path == NULL) {
3675 ERR("device_path NULL : [%s]", device_address);
3676 ret = BT_STATUS_FAIL;
3680 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3681 NULL, BT_HAL_BLUEZ_NAME,
3682 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3683 g_free(device_path);
3684 if (NULL == device_proxy) {
3685 ERR("device_proxy returned NULL");
3686 return BT_STATUS_FAIL;
3689 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3690 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3691 BT_HAL_ADDRESS_LENGTH_MAX);
3693 DBG("ConnectLE [%s]", device_address);
3695 gattc_data->client_if = client_if;
3697 g_dbus_proxy_call(device_proxy, "ConnectLE",
3698 g_variant_new("(b)", auto_connect),
3699 G_DBUS_CALL_FLAGS_NONE,
3700 BT_HAL_MAX_DBUS_TIMEOUT,
3702 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3707 static bt_status_t _bt_hold_current_advertising()
3709 int ret = BT_STATUS_FAIL;
3710 gboolean is_advertising = FALSE;
3713 if (_bt_hal_is_support_multi_adv() == TRUE) {
3714 DBG("VSC adv used");
3715 return BT_STATUS_SUCCESS;
3718 /* Dependent on Kernel operation. Hold adv to prevent stopping adv on kernel */
3719 is_advertising = _bt_hal_is_advertising_in_slot(0);
3720 if (is_advertising) {
3721 DBG("+ Stop current advertising");
3723 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3724 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3730 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3732 DBG("+ start current advertising");
3734 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3739 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3741 DBG("Try to initiate pending LE connection");
3743 pending_le_conn_timer_id = 0;
3745 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3746 &pending_le_conn_info->bd_addr,
3747 pending_le_conn_info->auto_connect);
3749 g_free(pending_le_conn_info);
3750 pending_le_conn_info = NULL;
3755 static int __hal_generate_conn_id()
3757 return ++hal_gatt_conn_id;
3760 static int __hal_generate_server_instance_id()
3762 return ++bt_inst_id;
3765 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3768 GError *g_error = NULL;
3769 GVariant *reply = NULL;
3770 hal_gattc_client_info_t *gattc_data = user_data;
3771 int result = BT_STATUS_SUCCESS;
3772 struct hal_ev_gatt_client_connected ev;
3773 hal_gattc_server_info_t *gatt_conn_info = NULL;
3775 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3776 g_object_unref(proxy);
3777 if (reply == NULL) {
3778 ERR("Connect LE Dbus Call Error");
3780 ERR("Error: %s\n", g_error->message);
3781 g_clear_error(&g_error);
3783 result = BT_STATUS_FAIL;
3785 g_variant_unref(reply);
3787 if (NULL == gattc_data) {
3788 ERR("gattc_data is NULL");
3793 if (result == BT_STATUS_FAIL) {
3794 memset(&ev, 0, sizeof(ev));
3797 ev.client_if = gattc_data->client_if;
3798 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3799 BT_HAL_ADDRESS_LENGTH_MAX);
3802 ERR("gatt client callback not registered");
3804 DBG("sending gatt client connected event");
3805 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3811 DBG("LE connected. Adding the gattc server/client conn info in list");
3812 gattc_data->conn_id = __hal_generate_conn_id() ;
3813 gattc_data->inst_id = __hal_generate_server_instance_id();
3815 #ifndef __INTEGRATE_HAL_GATT_INFO__
3816 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3819 /*add gatt server connection info*/
3820 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3821 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3822 gatt_conn_info->conn_id = gattc_data->conn_id;
3823 gatt_conn_info->inst_id = gattc_data->inst_id;
3824 #ifdef __INTEGRATE_HAL_GATT_INFO__
3825 gatt_conn_info->client_if = gattc_data->client_if;
3827 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3832 /*remove conn_info*/
3837 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3839 g_free(desc_info->desc_path);
3843 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3846 hal_gattc_desc_t *desc_info = NULL;
3847 for (l = char_info->gatt_list_descs; l != NULL; ) {
3848 desc_info = l->data;
3849 l = g_slist_next(l);
3850 if (desc_info == NULL)
3852 /* Remove descriptor element */
3853 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3854 __hal_gattc_free_desc_info(desc_info);
3856 g_slist_free(char_info->gatt_list_descs);
3857 g_free(char_info->chr_path);
3861 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3864 hal_gattc_char_t *char_info = NULL;
3865 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3866 char_info = l->data;
3867 l = g_slist_next(l);
3868 if (char_info == NULL)
3870 /* Remove characteristic element */
3871 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3872 __hal_gattc_free_char_info(char_info);
3874 g_slist_free(svc_info->gatt_list_chars);
3875 g_free(svc_info->svc_path);
3879 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3882 hal_gattc_service_t *svc_info = NULL;
3886 for (l = conn_info->gatt_list_services; l != NULL; ) {
3887 svc_info = (hal_gattc_service_t *)l->data;
3888 l = g_slist_next(l);
3889 if (svc_info == NULL)
3891 /* Remove service element */
3892 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3893 __hal_gattc_free_svc_info(svc_info);
3895 g_slist_free(conn_info->gatt_list_services);
3899 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3901 bt_bdaddr_t bd_addr;
3902 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3903 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3909 int _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3911 int result = BT_STATUS_SUCCESS;
3912 struct hal_ev_gatt_client_connected ev;
3913 hal_gattc_server_info_t *conn_info = NULL;
3914 bt_bdaddr_t bd_addr;
3916 hal_gattc_client_info_t *gattc_client = NULL;
3917 #ifndef __INTEGRATE_HAL_GATT_INFO__
3921 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3922 HAL_EV_GATT_CLIENT_DISCONNECTED;
3924 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3925 /* find the gatt client info */
3926 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3927 if (NULL == gattc_client) {
3928 ERR("Fail to get gatt client info");
3932 gattc_client->is_gatt_connected = gatt_connected;
3935 memset(&ev, 0, sizeof(ev));
3936 ev.conn_id = gattc_client->conn_id;
3938 ev.client_if = gattc_client->client_if;
3939 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3940 BT_HAL_ADDRESS_LENGTH_MAX);
3943 ERR("gatt client callback not registered");
3945 event_cb(event, (void *)&ev, sizeof(ev));
3948 if (!gatt_connected) {
3949 #ifndef __INTEGRATE_HAL_GATT_INFO__
3950 inst_id = gattc_client->inst_id;
3952 /* remove the gatt client info from the client list also*/
3953 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3954 g_free(gattc_client);
3957 //find the connected server info
3958 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3959 if (NULL == conn_info) {
3960 ERR("Fail to get gatt server info");
3964 #ifndef __INTEGRATE_HAL_GATT_INFO__
3965 if (inst_id != conn_info->inst_id) {
3966 ERR("server instance is different");
3971 //remove gatt conn info from the server list
3972 DBG("remove the server conn_info from list after gatt disconnection");
3973 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3974 __hal_clean_gattc_server_info(conn_info);
3980 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3981 const char* uuid_str, int inst_id)
3983 struct hal_ev_gatt_client_search_result ev;
3986 ERR("gatt client callback not registered");
3990 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3992 memset(&ev, 0, sizeof(ev));
3993 ev.conn_id = conn_id;
3994 ev.inst_id = inst_id;
3995 ev.is_primary = is_primary;
3996 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3998 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
4001 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
4003 struct hal_ev_gatt_client_search_complete ev;
4006 ERR("gatt client callback not registered");
4010 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
4013 memset(&ev, 0, sizeof(ev));
4014 ev.conn_id = conn_id;
4017 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
4020 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
4021 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
4022 char *char_value, int len)
4024 struct hal_ev_gatt_client_notify_changed_value ev;
4025 hal_gattc_client_info_t *gattc_client = NULL;
4028 ERR("gatt client callback not registered");
4032 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
4033 if (NULL == gattc_client) {
4034 ERR("failed to get the gatt client info");
4039 DBG("sending gatt client connected status event");
4040 memset(&ev, 0, sizeof(ev));
4042 ev.conn_id = gattc_client->conn_id;
4043 ev.inst_id = conn_info->inst_id;
4044 ev.is_primary = svc_info->is_primary;
4045 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
4046 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
4048 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
4050 if (len > 0 && (char_value != NULL)) {
4051 memcpy(ev.value, char_value, len);
4055 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
4058 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
4059 char *char_value, int len)
4061 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
4062 hal_gattc_server_info_t *conn_info = NULL;
4063 bt_bdaddr_t bd_addr;
4066 hal_gattc_service_t *svc_info = NULL;
4067 hal_gattc_char_t *char_info = NULL;
4071 _bt_hal_convert_device_path_to_address(char_handle, device_address);
4072 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
4073 DBG("device address:[%s]", device_address);
4074 DBG("char handle:[%s]", char_handle);
4076 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
4077 conn_info = __bt_find_gatt_conn_info(&bd_addr);
4079 if (conn_info != NULL) {
4080 //find service for notified char path
4081 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
4082 svc_info = (hal_gattc_service_t*)l->data;
4083 if (svc_info == NULL)
4086 /* find characteristic object path */
4087 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
4088 char_info = (hal_gattc_char_t *)k->data;
4089 if (char_info == NULL)
4092 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
4093 DBG("Found char handle[%s]", char_info->chr_path);
4096 _bt_hal_send_value_changed_event(conn_info, svc_info,
4097 char_info, char_value, len);
4105 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
4107 GDBusConnection *g_conn = NULL;
4108 GDBusProxy *properties_proxy = NULL;
4109 GVariant *result = NULL;
4110 GError *error = NULL;
4111 GVariantIter *property_iter = NULL;
4112 const gchar *key = NULL;
4113 GVariant *value = NULL;
4114 const char *uuid_str = NULL;
4116 gboolean is_primary = FALSE;
4117 GVariantIter *char_iter = NULL;
4118 const char *char_handle = NULL;
4119 GPtrArray *gp_char_array = NULL;
4121 if (service_path == NULL) {
4122 ERR("service_path is NULL");
4123 return BT_STATUS_FAIL;
4126 DBG("service_path: %s", service_path);
4128 g_conn = _bt_hal_get_system_gconn();
4129 if (g_conn == NULL) {
4130 ERR("g_conn is NULL");
4131 return BT_STATUS_FAIL;
4134 properties_proxy = g_dbus_proxy_new_sync(g_conn,
4135 G_DBUS_PROXY_FLAGS_NONE, NULL,
4138 BT_HAL_PROPERTIES_INTERFACE,
4140 if (properties_proxy == NULL) {
4141 ERR("properties_proxy is NULL");
4142 return BT_STATUS_FAIL;
4145 result = g_dbus_proxy_call_sync(properties_proxy,
4147 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
4148 G_DBUS_CALL_FLAGS_NONE,
4150 if (result == NULL) {
4151 if (error != NULL) {
4152 ERR("Fail to get properties (Error: %s)", error->message);
4153 g_clear_error(&error);
4155 ERR("Fail to get properties");
4157 g_object_unref(properties_proxy);
4158 return BT_STATUS_FAIL;
4161 g_variant_get(result, "(a{sv})", &property_iter);
4163 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
4164 if (g_strcmp0(key, "UUID") == 0) {
4165 uuid_str = g_variant_get_string(value, &len);
4166 } else if (g_strcmp0(key, "Primary") == 0) {
4167 is_primary = g_variant_get_boolean(value);
4168 } else if (g_strcmp0(key, "Characteristics") == 0) {
4169 g_variant_get(value, "ao", &char_iter);
4170 if (char_iter != NULL) {
4171 if (gp_char_array == NULL)
4172 gp_char_array = g_ptr_array_new();
4174 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
4175 DBG("char_handle: %s", char_handle);
4176 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
4178 g_variant_iter_free(char_iter);
4183 if (uuid_str == NULL || gp_char_array == NULL) {
4184 ERR("uuid_str and gp_char_array should be set");
4188 /* Create new service */
4189 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
4192 g_variant_iter_free(property_iter);
4193 g_variant_unref(result);
4194 g_object_unref(properties_proxy);
4196 return BT_STATUS_SUCCESS;
4199 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
4201 GDBusConnection *conn = NULL;
4202 GDBusProxy *proxy = NULL;
4204 GVariant *ret = NULL;
4205 GVariant *value = NULL;
4207 conn = _bt_hal_get_system_gconn();
4209 ERR("_bt_gdbus_get_system_gconn returned NULL");
4213 proxy = g_dbus_proxy_new_sync(conn,
4214 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
4215 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
4216 if (proxy == NULL) {
4217 ERR("device_proxy returned NULL");
4221 ret = g_dbus_proxy_call_sync(proxy, "Get",
4222 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
4223 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
4225 ERR("DBus Error : %s", err->message);
4226 g_clear_error(&err);
4228 g_variant_get(ret, "(v)", &value);
4229 *service_uuid = g_variant_dup_string(value, NULL);
4230 g_variant_unref(value);
4231 g_variant_unref(ret);
4235 g_object_unref(proxy);
4240 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
4242 struct hal_ev_gatt_client_service_changed ev = {0, };
4243 char address[BT_HAL_ADDRESS_STRING_SIZE];
4244 hal_gattc_server_info_t *server_info = NULL;
4245 hal_gattc_client_info_t *gattc_client = NULL;
4246 hal_gattc_service_t *service = NULL;
4247 GSList *list = NULL;
4248 char *uuid_str = NULL;
4250 _bt_hal_convert_device_path_to_address(path, address);
4251 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
4252 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
4253 if (server_info == NULL) {
4254 ERR("server_info is NULL");
4258 gattc_client = __bt_find_gatt_client_info((bt_bdaddr_t *)ev.bdaddr);
4259 if (gattc_client == NULL) {
4260 ERR("gattc_client is NULL");
4264 if (server_info->is_gatt_connected == FALSE && gattc_client->is_gatt_connected == FALSE) {
4265 DBG("GattConnected signal is not received yet. Just skip [%d %d]",
4266 server_info->is_gatt_connected, gattc_client->is_gatt_connected);
4271 /* Get service UUID from path */
4272 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
4274 INFO("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
4275 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
4278 ERR("uuid_str is NULL");
4282 /* Create new service and append into the list */
4283 __hal_gattc_get_service_info(server_info, path);
4285 /* Find service UUID from path */
4286 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4287 service = (hal_gattc_service_t *)list->data;
4288 if (service == NULL)
4291 if (g_strcmp0(service->svc_path, path) == 0) {
4292 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4293 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4294 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4295 INFO("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
4297 /* Remove service info in list */
4298 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4299 __hal_gattc_free_svc_info(service);
4307 ERR("uuid_str is NULL");
4312 /* Send GATT Client service changed event */
4313 ev.change_type = is_added;
4314 ev.conn_id = server_info->conn_id;
4315 ev.inst_id = server_info->inst_id;
4316 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));