4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include <hardware/bluetooth.h>
23 #include <hardware/bt_gatt.h>
31 #include <gio/gunixfdlist.h>
34 #include "bt-hal-log.h"
35 #include "bt-hal-msg.h"
36 #include "bt-hal-event-receiver.h"
37 #include "bt-hal-adapter-le.h"
39 #include "bt-hal-gatt-client.h"
40 #include "bt-hal-dbus-common-utils.h"
41 #include "bt-hal-utils.h"
43 /************************************************************************************
45 ************************************************************************************/
46 extern const btgatt_callbacks_t *bt_gatt_callbacks;
47 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
49 ERR("%s: BTGATT not initialized", __FUNCTION__);\
50 return BT_STATUS_NOT_READY;\
52 DBG("%s", __FUNCTION__);\
56 int le_scan_type = BT_GATTC_LE_SCAN_TYPE_PASSIVE;
59 static handle_stack_msg event_cb = NULL;
61 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
62 #define MAX_HAL_OBJECT_PATH_LEN 100
65 HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST = 0x01,
66 HAL_GATT_CHARACTERISTIC_PROPERTY_READ = 0x02,
67 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE = 0x04,
68 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE = 0x08,
69 HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY = 0x10,
70 HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE = 0x20,
71 HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE = 0x40,
72 HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE = 0x80,
73 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES = 0x100,
74 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ = 0x200,
75 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE = 0x400,
76 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ = 0x800,
77 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE = 0x1000,
78 HAL_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS = 0xffff,
79 } bt_gatt_characteristic_property_t;
83 HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE = 1,
84 HAL_GATT_WRITE_TYPE_WRITE ,
85 } hal_gatt_write_type_t;
89 HAL_GATT_PROPERTY_BROADCAST = 0x01, /**< Broadcast property */
90 HAL_GATT_PROPERTY_READ = 0x02, /**< Read property */
91 HAL_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE = 0x04, /**< Write without response property */
92 HAL_GATT_PROPERTY_WRITE = 0x08, /**< Write property */
93 HAL_GATT_PROPERTY_NOTIFY = 0x10, /**< Notify property */
94 HAL_GATT_PROPERTY_INDICATE = 0x20, /**< Indicate property */
95 HAL_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES = 0x40, /**< Authenticated signed writes property */
96 HAL_GATT_PROPERTY_EXTENDED_PROPERTIES = 0x80, /**< Extended properties */
97 } hal_gatt_property_e;
102 gboolean auto_connect;
103 } bt_pending_le_conn_info_s;
113 unsigned int permission;
114 GSList *gatt_list_descs;
121 GSList *gatt_list_chars;
122 } hal_gattc_service_t;
125 bt_bdaddr_t bd_addr; /*remote server address*/
127 int inst_id; /*server instance id*/
128 gboolean is_gatt_connected; /*status for GattConnected signal*/
129 GSList *gatt_list_services;
130 } hal_gattc_server_info_t;
134 bt_bdaddr_t bd_addr; /*remote server address*/
137 gboolean is_gatt_connected; /*status for GattConnected signal*/
138 } hal_gattc_client_info_t;
141 bt_bdaddr_t bd_addr; /* remote server address */
142 int conn_id; /* connection id */
143 int inst_id; /* server instance id */
144 gboolean is_gatt_connected; /* status for GattConnected signal */
145 int client_if; /* client id */
146 GSList *gatt_list_services;
147 } hal_gattc_conn_info_t;
150 * Remove this feature after verified.
151 * Remove hal_gattc_client/server_info_t and use hal_gattc_conn_info_t
152 * Remove hal_gattc_client/server_info_list and use hal_gattc_conn_info_list
154 #define __INTEGRATE_HAL_GATT_INFO__
155 #ifndef __INTEGRATE_HAL_GATT_INFO__
156 /* Linked List of connected GATT server */
157 static GSList *hal_gattc_server_info_list = NULL;
158 /* Linked list of connected GATT client connection */
159 static GSList *hal_gattc_client_info_list = NULL;
161 static GSList *hal_gattc_conn_info_list = NULL;
162 #define hal_gattc_server_info_t hal_gattc_conn_info_t
163 #define hal_gattc_client_info_t hal_gattc_conn_info_t
164 #define hal_gattc_server_info_list hal_gattc_conn_info_list
165 #define hal_gattc_client_info_list hal_gattc_conn_info_list
168 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
169 static guint pending_le_conn_timer_id = 0;
170 int hal_gatt_conn_id = 0;
171 static int bt_inst_id = 0;
173 /* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
174 /* TODO: Adjust MAX Client after modifying MAX app handle logic */
175 #define BT_GATTC_CL_MAX 11
177 static int assigned_if = 0;
178 static gboolean client_if_used[BT_GATTC_CL_MAX];
183 btgatt_srvc_id_t srvc_id;
184 btgatt_gatt_id_t char_id;
185 btgatt_gatt_id_t desc_id;
186 } hal_gatt_resp_data_t;
191 } hal_gatt_client_app;
193 static GSList * hal_gattc_client_app_list = NULL;
200 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
201 gboolean auto_connect);
202 static bt_status_t _bt_hold_current_advertising();
203 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
204 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
205 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
207 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
208 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
209 const char* uuid_str, int inst_id);
210 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
211 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr);
212 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
213 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
215 void _bt_hal_gatt_client_init(void)
218 memset(client_if_used, 0x00, sizeof(client_if_used));
221 static int __bt_hal_gatt_assign_if(void)
225 index = assigned_if + 1;
227 if (index >= BT_GATTC_CL_MAX)
230 while (client_if_used[index] == TRUE) {
231 if (index == assigned_if) {
232 /* No available ID */
233 ERR("All interface ID is used");
239 if (index >= BT_GATTC_CL_MAX)
244 client_if_used[index] = TRUE;
249 static void __bt_hal_gatt_delete_if(int client_if)
251 if (client_if >= BT_GATTC_CL_MAX || client_if < 0)
254 client_if_used[client_if] = FALSE;
258 /* To send stack event to hal-av handler */
259 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
264 void _bt_hal_unregister_gatt_client_handler_cb(void)
270 int _bt_hal_gatt_client_get_le_scan_type(void)
276 static gboolean __bt_hal_register_client_cb(gpointer user_data)
278 struct hal_ev_gatt_client_registered ev;
279 hal_gatt_client_app *client_info = user_data;
281 /* Prepare to send AV connecting event */
282 memset(&ev, 0, sizeof(ev));
283 ev.status = BT_STATUS_SUCCESS;
284 ev.client_if = client_info->client_if;
285 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
288 ERR("GATT Callback not registered");
290 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
291 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
298 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
302 hal_gatt_client_app *info = NULL;
303 hal_gatt_client_app *gattc_app = NULL;
305 //check if client app is already registered
306 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
307 info = (hal_gatt_client_app*)l->data;
311 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
312 DBG("gatt client app already registered");
317 client_if = __bt_hal_gatt_assign_if();
318 if (client_if == -1) {
319 ERR("Fail to allocate the client if");
323 DBG("adding the gatt client app");
326 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
327 gattc_app->client_if = client_if;
328 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
330 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
335 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
337 hal_gatt_client_app *gattc_app = NULL;
338 hal_gatt_client_app *client_app_info = NULL;
340 /* add gatt client in list */
341 gattc_app = __hal_gattc_add_client_app(app_uuid);
342 if (gattc_app == NULL) {
343 ERR("Failed to register gatt client app");
344 return BT_STATUS_FAIL;
348 client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
349 client_app_info->client_if = gattc_app->client_if;
350 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
351 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
353 DBG("registered client client_if [%d]", client_app_info->client_if);
355 return BT_STATUS_SUCCESS;
358 /** Registers a GATT client application with the stack */
359 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
363 return __hal_gattc_register_client_app(uuid);
366 bt_status_t btif_gattc_add_connection_info(const bt_bdaddr_t *bd_addr, int conn_id, int server_inst_id)
368 #ifndef __INTEGRATE_HAL_GATT_INFO__
369 hal_gattc_client_info_t *client_info = NULL;
371 hal_gattc_server_info_t *server_info = NULL;
373 #ifndef __INTEGRATE_HAL_GATT_INFO__
374 /* Add client connection info in list */
375 client_info = g_malloc0(sizeof(hal_gattc_client_info_t));
376 client_info->client_if = -1;
377 memcpy(client_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
378 client_info->conn_id = conn_id;
379 client_info->inst_id = server_inst_id;
380 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, client_info);
381 DBG("Added client connection info in list");
384 /* Add server connection info in list */
385 server_info = __bt_find_gatt_conn_info(bd_addr);
386 if (server_info == NULL) {
387 server_info = g_malloc0(sizeof(hal_gattc_server_info_t));
388 memcpy(server_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
389 server_info->conn_id = conn_id;
390 server_info->inst_id = server_inst_id;
391 server_info->is_gatt_connected = TRUE;
392 #ifdef __INTEGRATE_HAL_GATT_INFO__
393 server_info->client_if = -1;
395 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, server_info);
396 DBG("Added server connection info in list");
399 return BT_STATUS_SUCCESS;
402 bt_status_t __hal_gattc_unregister_client(int client_if)
405 hal_gatt_client_app *info = NULL;
406 gboolean is_deleted = FALSE;
409 client_count = g_slist_length(hal_gattc_client_app_list);
411 /* remove the gatt client app */
412 for (l = hal_gattc_client_app_list; l != NULL; ) {
413 info = (hal_gatt_client_app*)l->data;
419 if (info->client_if == client_if) {
420 __bt_hal_gatt_delete_if(client_if);
422 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
428 DBG("Deleted. registered client count: [%d -> %d]", client_count, g_slist_length(hal_gattc_client_app_list));
430 ERR("Not deleted. registered client count: [%d]", client_count);
432 return BT_STATUS_SUCCESS;
435 /** Unregister a client application from the stack */
436 bt_status_t btif_gattc_unregister_client(int client_if)
440 return __hal_gattc_unregister_client(client_if);
443 /** Start or stop LE device scanning */
444 bt_status_t scan(int client_if, bool start)
451 ret = _bt_hal_adapter_le_start_scan();
453 ret = _bt_hal_adapter_le_stop_scan();
458 /** Create a connection to a remote LE or dual-mode device */
459 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
462 int ret = BT_STATUS_SUCCESS;
467 return BT_STATUS_PARM_INVALID;
469 ret = _bt_hold_current_advertising();
470 if (ret == BT_STATUS_SUCCESS) {
471 DBG("Current advertising is held");
472 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
473 pending_le_conn_info->client_if = client_if;
474 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
475 BT_HAL_ADDRESS_LENGTH_MAX);
476 pending_le_conn_info->auto_connect = is_direct;
478 pending_le_conn_timer_id =
479 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
481 return BT_STATUS_SUCCESS;
483 ERR("advertising is not stopped");
486 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
490 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
493 GError *g_error = NULL;
494 GVariant *reply = NULL;
495 hal_gattc_client_info_t *gatt_conn_info = user_data;
496 int result = BT_STATUS_SUCCESS;
497 struct hal_ev_gatt_client_connected ev;
501 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
502 g_object_unref(proxy);
504 ERR("Connect LE Dbus Call Error");
506 ERR("Error: %s\n", g_error->message);
507 g_clear_error(&g_error);
509 result = BT_STATUS_FAIL;
511 g_variant_unref(reply);
513 if (NULL == gatt_conn_info) {
514 ERR("server_data is NULL");
519 if (result == BT_STATUS_FAIL) {
520 memset(&ev, 0, sizeof(ev));
521 ev.conn_id = gatt_conn_info->conn_id;
523 ev.client_if = gatt_conn_info->client_if;
524 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
525 BT_HAL_ADDRESS_LENGTH_MAX);
528 ERR("gatt client callback not registered");
530 DBG("sending gatt client disconnected event");
531 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
537 g_free(gatt_conn_info);
542 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
545 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
547 GDBusProxy *device_proxy;
548 GDBusConnection *conn;
549 int ret = BT_STATUS_SUCCESS;
550 hal_gattc_client_info_t *gattc_data;
552 if (NULL == bd_addr) {
553 ERR("bd_addr is NULL");
554 return BT_STATUS_PARM_INVALID;
557 conn = _bt_hal_get_system_gconn();
559 ERR("_bt_gdbus_get_system_gconn returned NULL");
560 return BT_STATUS_FAIL;
563 _bt_hal_convert_addr_type_to_string(device_address,
564 (unsigned char *)bd_addr->address);
565 device_path = _bt_hal_get_device_object_path(device_address);
566 if (device_path == NULL) {
567 DBG("device_path NULL");
568 ret = BT_STATUS_FAIL;
572 ERR("device_path:%s", device_path);
574 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
575 NULL, BT_HAL_BLUEZ_NAME,
576 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
578 if (NULL == device_proxy) {
579 ERR("device_proxy returned NULL");
580 return BT_STATUS_FAIL;
583 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
584 memcpy(gattc_data->bd_addr.address, bd_addr->address,
585 BT_HAL_ADDRESS_LENGTH_MAX);
586 gattc_data->client_if = client_if;
587 gattc_data->conn_id = conn_id;
589 DBG("DisconnectLE [%s]", device_address);
591 g_dbus_proxy_call(device_proxy, "DisconnectLE",
593 G_DBUS_CALL_FLAGS_NONE,
594 BT_HAL_MAX_DBUS_TIMEOUT,
596 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
600 /** Disconnect a remote device or cancel a pending connection */
601 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
606 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
609 /** Clear the attribute cache for a given device */
610 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
613 return BT_STATUS_UNSUPPORTED;
616 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
619 hal_gattc_service_t *info = NULL;
621 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
622 info = (hal_gattc_service_t*)l->data;
626 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t)))
634 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
635 bt_gatt_characteristic_property_t prop)
638 hal_gattc_char_t *info = NULL;
640 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
641 info = (hal_gattc_char_t*)l->data;
645 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
646 (info->permission & prop)) {
653 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
656 hal_gattc_char_t *info = NULL;
658 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
659 info = (hal_gattc_char_t*)l->data;
663 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
664 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
665 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
672 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
675 hal_gattc_desc_t *info = NULL;
677 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
678 info = (hal_gattc_desc_t*)l->data;
682 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t)))
689 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
690 const char *uuid_str, const char *object_path, int is_primary)
692 hal_gattc_service_t *gattc_service = NULL;
694 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
695 gattc_service->svc_path = g_strdup(object_path);
696 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
697 gattc_service->is_primary = is_primary;
699 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
700 INFO("Total svc [%d] Added [%s] [%s]", g_slist_length(conn_info->gatt_list_services), object_path + 15, uuid_str);
702 return gattc_service;
705 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
707 hal_gattc_char_t *gattc_char = NULL;
709 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
710 gattc_char->chr_path = g_strdup(char_handle);
712 DBG("[%s]", gattc_char->chr_path + 15);
714 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
717 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
718 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
720 hal_gattc_service_t* gatt_svc = NULL;
722 gchar *gp_char_path = NULL;
723 uint8_t uuid[BT_HAL_STACK_UUID_SIZE];
725 _bt_hal_convert_uuid_string_to_type(uuid, uuid_str);
726 gatt_svc = _gattc_find_service_from_uuid(conn_info, (bt_uuid_t *)uuid);
728 DBG("Aleady added to gatt_list_services");
732 /* add the service */
733 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
734 if (gatt_svc == NULL) {
735 ERR("Failed to add service");
739 /* add the characteristic */
740 for (i = 0; i < gp_char_array->len; i++) {
741 gp_char_path = g_ptr_array_index(gp_char_array, i);
742 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
745 g_ptr_array_free(gp_char_array, TRUE);
748 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
750 hal_gattc_desc_t *gattc_desc = NULL;
752 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
753 gattc_desc->desc_path = g_strdup(desc_path);
755 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
758 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
759 GPtrArray *gp_desc_array, unsigned int char_permission)
761 gchar *gp_desc_path = NULL;
764 if (char_uuid_str == NULL) {
765 DBG("char_uuid_str is NULL");
769 //update the char uuid
770 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
772 //update char permission
773 gattc_char->permission = char_permission;
776 for (i = 0; i < gp_desc_array->len; i++) {
777 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
778 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
782 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
784 if (desc_uuid_str == NULL) {
785 DBG("char_uuid_str is NULL");
789 //update the descriptor uuid
790 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
792 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
795 static void browse_service_char(int conn_id)
797 hal_gattc_server_info_t *conn_info = NULL;
801 hal_gattc_service_t *svc_info = NULL;
802 hal_gattc_char_t *char_info = NULL;
803 hal_gattc_desc_t *desc_info = NULL;
805 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
806 if (conn_info == NULL) {
807 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
811 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
812 svc_info = (hal_gattc_service_t*)l->data;
813 if (svc_info == NULL)
816 /* find characteristic object path */
817 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
818 char_info = (hal_gattc_char_t *)k->data;
819 if (char_info == NULL)
823 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
824 desc_info = (hal_gattc_desc_t *)m->data;
825 if (desc_info == NULL)
835 * Enumerate all GATT services on a connected device.
836 * Optionally, the results can be filtered for a given UUID.
838 static bt_status_t _gattc_client_search_service(int conn_id)
842 GVariant *result = NULL;
844 GVariantIter *svc_iter;
845 GVariantIter *interface_iter;
846 char *object_path = NULL;
847 char *interface_str = NULL;
848 const gchar *key = NULL;
849 GVariant *value = NULL;
850 GPtrArray *gp_array = NULL;
851 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
852 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
853 int ret = BT_STATUS_FAIL;
855 const gchar *uuid_str = NULL;
857 hal_gattc_server_info_t *conn_info = NULL;
858 gboolean is_primary = FALSE;
861 char *char_handle = NULL;
862 GVariantIter *char_iter = NULL;
863 GPtrArray *gp_char_array = NULL;
865 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
866 if (NULL == conn_info) {
867 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
868 return BT_STATUS_FAIL;
872 // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
873 /* Check the service info is stored */
874 if (g_slist_length(conn_info->gatt_list_services) > 0) {
876 hal_gattc_service_t *svc_info = NULL;
877 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
878 DBG("Send event from service info list");
879 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
881 if (svc_info == NULL)
883 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
884 _bt_hal_send_search_service_result_event(conn_id,
885 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
887 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
888 return BT_STATUS_SUCCESS;
890 DBG("No stored service, request to bluez");
894 _bt_hal_convert_addr_type_to_string(device_address,
895 (unsigned char *)conn_info->bd_addr.address);
897 result = _bt_hal_get_managed_objects();
901 gp_array = g_ptr_array_new();
902 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
904 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
906 if (object_path == NULL)
909 _bt_hal_convert_device_path_to_address(object_path, temp_address);
911 if (g_strcmp0(temp_address, device_address) != 0)
914 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
915 &interface_str, &svc_iter)) {
916 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
919 DBG("[%d] %s", idx++, object_path + 15);
920 /* for characteristic */
921 gp_char_array = g_ptr_array_new();
922 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
923 if (g_strcmp0(key, "Primary") == 0) {
924 is_primary = g_variant_get_boolean(value);
926 g_ptr_array_add(gp_array, (gpointer)object_path);
929 } else if (g_strcmp0(key, "UUID") == 0) {
930 uuid_str = g_variant_get_string(value, &len);
931 } else if (g_strcmp0(key, "Characteristics") == 0) {
932 g_variant_get(value, "ao", &char_iter);
933 if (char_iter != NULL) {
934 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
935 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
937 g_variant_iter_free(char_iter);
943 _bt_hal_send_search_service_result_event(conn_id, is_primary,
944 uuid_str, conn_info->inst_id);
946 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
951 if (gp_array->len == 0 || svc_count == 0) {
952 ERR("gp_array is NULL");
953 ret = BT_STATUS_FAIL;
955 ret = BT_STATUS_SUCCESS;
958 browse_service_char(conn_id);
959 /* send search service complete event */
960 _bt_hal_send_search_service_complete_event(conn_id, ret);
962 g_ptr_array_free(gp_array, TRUE);
963 g_variant_iter_free(iter);
964 g_variant_unref(result);
969 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
971 if (NULL == filter_uuid) {
972 DBG("Browse all the services");
973 return _gattc_client_search_service(conn_id);
975 DBG("TODO implement it");
976 return BT_STATUS_UNSUPPORTED;
980 * Enumerate included services for a given service.
981 * Set start_incl_srvc_id to NULL to get the first included service.
983 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
984 btgatt_srvc_id_t *start_incl_srvc_id)
987 return BT_STATUS_UNSUPPORTED;
990 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
991 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
993 struct hal_ev_gatt_client_char_search_result ev;
996 ERR("gatt client callback not registered");
1000 memset(&ev, 0, sizeof(ev));
1001 ev.conn_id = conn_id;
1002 ev.inst_id = svc_id->id.inst_id;
1003 ev.is_primary = svc_id->is_primary;
1005 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1007 if (status == BT_STATUS_SUCCESS) {
1008 /* building char uuid */
1009 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
1010 ev.char_prop = char_prop;
1013 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
1014 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1017 static int _hal_get_permission_flag(char *permission)
1021 if (NULL == permission) {
1022 ERR("gatt permission is NULL");
1026 if (!g_strcmp0(permission, "broadcast"))
1027 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
1028 else if (!g_strcmp0(permission, "read"))
1029 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
1030 else if (!g_strcmp0(permission, "write-without-response"))
1031 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1032 else if (!g_strcmp0(permission, "write"))
1033 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1034 else if (!g_strcmp0(permission, "notify"))
1035 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1036 else if (!g_strcmp0(permission, "indicate"))
1037 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
1038 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
1039 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
1040 else if (!g_strcmp0(permission, "reliable-write"))
1041 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
1042 else if (!g_strcmp0(permission, "writable-auxiliaries"))
1043 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1044 else if (!g_strcmp0(permission, "encrypt-read"))
1045 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1046 else if (!g_strcmp0(permission, "encrypt-write"))
1047 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1048 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1049 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1050 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1051 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1056 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1058 char perm[200] = { 0, };
1060 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1061 g_strlcat(perm, "broadcast ", sizeof(perm));
1062 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1063 g_strlcat(perm, "read ", sizeof(perm));
1064 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1065 g_strlcat(perm, "write-without-response ", sizeof(perm));
1066 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1067 g_strlcat(perm, "write ", sizeof(perm));
1068 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1069 g_strlcat(perm, "notify ", sizeof(perm));
1070 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1071 g_strlcat(perm, "indicate ", sizeof(perm));
1072 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1073 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1074 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1075 g_strlcat(perm, "reliable-write ", sizeof(perm));
1076 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1077 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1078 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1079 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1080 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1081 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1082 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1083 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1084 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1085 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1087 DBG("permission [0x%04x] : %s\n", permission, perm);
1091 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1093 GDBusProxy *properties_proxy = NULL;
1094 GError *error = NULL;
1095 GVariant *value = NULL;
1096 GVariant *result = NULL;
1097 GDBusConnection *g_conn;
1099 char *char_desc_handle = NULL;
1101 GVariantIter *property_iter;
1102 GVariantIter *char_desc_iter;
1103 char* char_handle = NULL;
1104 gchar *char_uuid_str = NULL;
1105 GPtrArray *gp_desc_array = NULL;
1106 GVariantIter *char_perm_iter;
1108 unsigned int char_permission = 0 ;
1110 if (gattc_char->chr_path == NULL) {
1111 DBG("char path is NULL");
1112 return BT_STATUS_FAIL;
1114 char_handle = gattc_char->chr_path;
1116 g_conn = _bt_hal_get_system_gconn();
1117 if (NULL == g_conn) {
1118 ERR("_bt_gdbus_get_system_gconn returned NULL");
1119 return BT_STATUS_FAIL;
1122 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1123 G_DBUS_PROXY_FLAGS_NONE, NULL,
1126 BT_HAL_PROPERTIES_INTERFACE,
1129 if (properties_proxy == NULL) {
1130 ERR("properties_proxy returned NULL");
1131 return BT_STATUS_FAIL;
1134 result = g_dbus_proxy_call_sync(properties_proxy,
1136 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1137 G_DBUS_CALL_FLAGS_NONE,
1142 if (error != NULL) {
1143 ERR("Fail to get properties (Error: %s)", error->message);
1144 g_clear_error(&error);
1146 ERR("Fail to get properties");
1147 g_object_unref(properties_proxy);
1148 return BT_STATUS_FAIL;
1151 gp_desc_array = g_ptr_array_new();
1153 g_variant_get(result, "(a{sv})", &property_iter);
1155 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1156 if (!g_strcmp0(key, "UUID")) {
1157 char_uuid_str = g_variant_dup_string(value, &len);
1158 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1159 } else if (!g_strcmp0(key, "Flags")) {
1160 g_variant_get(value, "as", &char_perm_iter);
1161 char_permission = 0x00;
1163 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1164 char_permission |= _hal_get_permission_flag(permission);
1166 __hal_convert_permission_flag_to_str(char_permission);
1167 g_variant_iter_free(char_perm_iter);
1168 } else if (!g_strcmp0(key, "Descriptors")) {
1169 g_variant_get(value, "ao", &char_desc_iter);
1170 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1171 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1173 g_variant_iter_free(char_desc_iter);
1177 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1179 g_free(char_uuid_str);
1180 g_variant_iter_free(property_iter);
1181 g_variant_unref(result);
1182 g_object_unref(properties_proxy);
1183 g_ptr_array_free(gp_desc_array, TRUE);
1185 return BT_STATUS_SUCCESS;
1188 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1189 btgatt_srvc_id_t *srvc_id)
1191 hal_gattc_server_info_t * conn_info = NULL;
1192 hal_gattc_service_t *gattc_service = NULL;
1194 hal_gattc_char_t *gattc_char = NULL;
1195 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1196 int status = BT_STATUS_FAIL;
1198 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1199 if (NULL == conn_info) {
1200 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1201 return BT_STATUS_FAIL;
1205 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1206 if (NULL == gattc_service) {
1207 ERR("Failed to get the gatt service");
1208 return BT_STATUS_FAIL;
1211 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1212 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1214 /* find characteristic object path */
1215 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1216 gattc_char = (hal_gattc_char_t *)l->data;
1217 status = _hal_gattc_get_characteristic_info(gattc_char);
1220 if (BT_STATUS_SUCCESS == status) {
1221 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1222 &gattc_char->chr_uuid, gattc_char->permission);
1226 status = BT_STATUS_FAIL;
1227 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1229 browse_service_char(conn_id);
1230 /* retrive uuid for characteristic and object path for descriptor */
1232 return BT_STATUS_SUCCESS;
1236 * Enumerate characteristics for a given service.
1237 * Set start_char_id to NULL to get the first characteristic.
1239 bt_status_t btif_gattc_get_characteristic(int conn_id,
1240 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1242 CHECK_BTGATT_INIT();
1244 if (start_char_id == NULL) {
1245 return _gattc_get_all_characteristic(conn_id, srvc_id);
1248 DBG("TBD Get specific characteristics");
1249 return BT_STATUS_UNSUPPORTED;
1253 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1255 GDBusProxy *properties_proxy = NULL;
1256 GError *error = NULL;
1257 GVariant *value = NULL;
1258 GVariant *result = NULL;
1259 GDBusConnection *g_conn;
1262 GVariantIter *property_iter;
1263 char* desc_handle = NULL;
1264 const gchar *desc_uuid_str = NULL;
1266 if (gattc_desc->desc_path == NULL) {
1267 DBG("desc path is NULL");
1268 return BT_STATUS_FAIL;
1270 desc_handle = gattc_desc->desc_path;
1272 g_conn = _bt_hal_get_system_gconn();
1273 if (NULL == g_conn) {
1274 ERR("_bt_gdbus_get_system_gconn returned NULL");
1275 return BT_STATUS_FAIL;
1278 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1279 G_DBUS_PROXY_FLAGS_NONE, NULL,
1282 BT_HAL_PROPERTIES_INTERFACE,
1285 if (properties_proxy == NULL) {
1286 ERR("properties_proxy returned NULL");
1287 return BT_STATUS_FAIL;
1290 result = g_dbus_proxy_call_sync(properties_proxy,
1292 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1293 G_DBUS_CALL_FLAGS_NONE,
1298 if (error != NULL) {
1299 ERR("Fail to get properties (Error: %s)", error->message);
1300 g_clear_error(&error);
1302 ERR("Fail to get properties");
1303 g_object_unref(properties_proxy);
1304 return BT_STATUS_FAIL;
1307 g_variant_get(result, "(a{sv})", &property_iter);
1309 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1310 if (!g_strcmp0(key, "UUID")) {
1311 desc_uuid_str = g_variant_get_string(value, &len);
1312 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1314 g_free((gchar *)key);
1315 g_variant_unref(value);
1320 g_variant_iter_free(property_iter);
1321 g_variant_unref(result);
1322 g_object_unref(properties_proxy);
1324 return BT_STATUS_SUCCESS;
1327 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1328 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1330 struct hal_ev_gatt_client_desc_search_result ev;
1333 ERR("gatt client callback not registered");
1337 memset(&ev, 0, sizeof(ev));
1338 ev.conn_id = conn_id;
1339 ev.inst_id = svc_id->id.inst_id;
1340 ev.is_primary = svc_id->is_primary;
1343 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1344 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1346 if (status == BT_STATUS_SUCCESS) {
1347 /* building desc uuid */
1348 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1351 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1353 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1356 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1357 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1359 hal_gattc_server_info_t * conn_info = NULL;
1360 hal_gattc_service_t *gattc_service = NULL;
1363 hal_gattc_char_t *gattc_char = NULL;
1364 hal_gattc_desc_t *gattc_desc = NULL;
1365 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1366 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1367 int status = BT_STATUS_FAIL;
1369 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1370 if (NULL == conn_info) {
1371 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1372 return BT_STATUS_FAIL;
1376 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1377 if (NULL == gattc_service) {
1378 ERR("Failed to get the gatt service");
1379 return BT_STATUS_FAIL;
1382 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1383 // DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1385 /* find characteristics */
1386 /* a service can have two char with same uuid */
1387 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1388 gattc_char = (hal_gattc_char_t*)l->data;
1389 if (gattc_char == NULL)
1392 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1393 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1394 // DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1396 /* get descriptor uuid */
1397 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1398 gattc_desc = (hal_gattc_desc_t *)m->data;
1399 if (gattc_desc == NULL)
1402 status = _hal_gattc_get_descriptor_info(gattc_desc);
1405 if (BT_STATUS_SUCCESS == status) {
1406 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1407 char_id, &gattc_desc->desc_uuid);
1413 status = BT_STATUS_FAIL;
1414 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1416 browse_service_char(conn_id);
1417 /* retrive uuid for characteristic and object path for descriptor */
1419 return BT_STATUS_SUCCESS;
1423 * Enumerate descriptors for a given characteristic.
1424 * Set start_descr_id to NULL to get the first descriptor.
1426 bt_status_t btif_gattc_get_descriptor(int conn_id,
1427 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1428 btgatt_gatt_id_t *start_descr_id)
1430 CHECK_BTGATT_INIT();
1432 if (start_descr_id == NULL) {
1433 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1435 DBG("TBD Get specific descriptor");
1436 return BT_STATUS_UNSUPPORTED;
1440 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1442 struct hal_ev_gatt_client_read_data ev;
1445 ERR("gatt client callback not registered");
1449 memset(&ev, 0, sizeof(ev));
1450 ev.conn_id = resp_data->conn_id;
1451 ev.inst_id = resp_data->srvc_id.id.inst_id;
1452 ev.is_primary = resp_data->srvc_id.is_primary;
1455 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1456 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1460 /* building the char read value */
1461 memcpy(ev.value, value, len);
1464 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1466 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1469 static void __hal_internal_read_char_cb(GObject *source_object,
1470 GAsyncResult *res, gpointer user_data)
1472 GError *error = NULL;
1473 GDBusConnection *system_gconn = NULL;
1476 GByteArray *gp_byte_array = NULL;
1478 hal_gatt_resp_data_t *resp_data = user_data;
1479 int result = BT_STATUS_SUCCESS;
1481 system_gconn = _bt_hal_get_system_gconn();
1482 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1485 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1488 result = BT_STATUS_FAIL;
1489 __hal_send_char_read_event(resp_data, result, NULL, 0);
1490 g_clear_error(&error);
1495 gp_byte_array = g_byte_array_new();
1496 g_variant_get(value, "(ay)", &iter);
1498 while (g_variant_iter_loop(iter, "y", &g_byte))
1499 g_byte_array_append(gp_byte_array, &g_byte, 1);
1503 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1507 g_byte_array_free(gp_byte_array, TRUE);
1508 g_variant_iter_free(iter);
1509 g_variant_unref(value);
1513 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1514 btgatt_gatt_id_t *char_id, int auth_req)
1516 GDBusConnection *g_conn;
1517 hal_gatt_resp_data_t *resp_data;
1518 hal_gattc_service_t *gattc_service = NULL;
1519 GVariantBuilder *builder = NULL;
1521 hal_gattc_server_info_t * conn_info = NULL;
1522 hal_gattc_char_t *gattc_char = NULL;
1523 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1524 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1525 char* char_handle = NULL;
1527 /* get the connection info */
1528 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1529 if (NULL == conn_info) {
1530 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1531 return BT_STATUS_FAIL;
1535 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1536 if (NULL == gattc_service) {
1537 ERR("Failed to get the gatt service");
1538 return BT_STATUS_FAIL;
1541 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1543 /* find characteristic */
1544 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1545 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1546 if (NULL == gattc_char) {
1547 ERR("Failed to get the gatt char");
1548 return BT_STATUS_FAIL;
1551 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1552 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1554 g_conn = _bt_hal_get_system_gconn();
1555 if (NULL == g_conn) {
1556 ERR("_bt_gdbus_get_system_gconn returned NULL");
1557 return BT_STATUS_FAIL;
1560 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1561 resp_data->conn_id = conn_id;
1562 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1563 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1565 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1568 g_variant_builder_add(builder, "{sv}", "offset",
1569 g_variant_new("q", offset));
1571 char_handle = gattc_char->chr_path;
1573 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1574 "ReadValue", g_variant_new("(a{sv})", builder),
1575 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1576 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1577 (gpointer)resp_data);
1578 g_variant_builder_unref(builder);
1580 return BT_STATUS_SUCCESS;
1583 /** Read a characteristic on a remote device */
1584 bt_status_t btif_read_characteristic(int conn_id,
1585 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1588 CHECK_BTGATT_INIT();
1590 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1593 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1595 struct hal_ev_gatt_client_write_result ev;
1598 ERR("gatt client callback not registered");
1602 memset(&ev, 0, sizeof(ev));
1603 ev.conn_id = resp_data->conn_id;
1604 ev.inst_id = resp_data->srvc_id.id.inst_id;
1605 ev.is_primary = resp_data->srvc_id.is_primary;
1608 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1609 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1611 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1614 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1615 GAsyncResult *res, gpointer user_data)
1617 GError *error = NULL;
1618 GDBusConnection *system_gconn = NULL;
1620 hal_gatt_resp_data_t *resp_data = user_data;
1621 int result = BT_STATUS_SUCCESS;
1623 system_gconn = _bt_hal_get_system_gconn();
1624 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1627 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1629 result = BT_STATUS_FAIL;
1631 __hal_send_char_write_event(resp_data, result);
1632 g_clear_error(&error);
1637 //send write value event
1638 __hal_send_char_write_event(resp_data, result);
1641 g_variant_unref(value);
1645 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1648 case HAL_GATT_WRITE_TYPE_WRITE:
1649 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1651 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1652 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1655 ERR("Unknow write type : %d", type);
1656 return BT_STATUS_FAIL;
1659 return BT_STATUS_SUCCESS;
1663 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1665 GDBusConnection *conn;
1666 GVariantBuilder *builder = NULL;
1672 GUnixFDList *fd_list = NULL;
1674 conn = _bt_hal_get_system_gconn();
1676 ERR("_bt_gdbus_get_system_gconn returned NULL");
1677 return BT_STATUS_FAIL;
1680 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1681 //val = g_variant_new("ay", builder1);
1683 g_variant_builder_add(builder, "{sv}", "offset",
1684 g_variant_new("q", offset));
1686 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1687 "AcquireWrite", g_variant_new("(a{sv})", builder),
1688 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1689 NULL, &fd_list, NULL, &err);
1691 g_dbus_error_strip_remote_error(err);
1692 ERR("Error: %s", err->message);
1694 g_variant_builder_unref(builder);
1695 return BT_STATUS_FAIL;
1698 g_variant_get(value, "(hq)", &idx, &att_mtu);
1699 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1701 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1704 g_object_unref(fd_list);
1705 g_variant_unref(value);
1706 g_variant_builder_unref(builder);
1708 return BT_STATUS_SUCCESS;
1711 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1713 GDBusConnection *conn;
1714 GVariantBuilder *builder = NULL;
1718 gint32 idx, notify_fd;
1720 GUnixFDList *fd_list = NULL;
1722 conn = _bt_hal_get_system_gconn();
1725 ERR("_bt_gdbus_get_system_gconn returned NULL");
1726 return BT_STATUS_FAIL;
1730 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1733 g_variant_builder_add(builder, "{sv}", "offset",
1734 g_variant_new("q", offset));
1736 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1737 "AcquireNotify", g_variant_new("(a{sv})", builder),
1738 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1739 NULL, &fd_list, NULL, &err);
1741 g_dbus_error_strip_remote_error(err);
1742 ERR("Error: %s", err->message);
1744 g_variant_builder_unref(builder);
1745 return BT_STATUS_FAIL;
1748 g_variant_get(value, "(hq)", &idx, &att_mtu);
1749 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1752 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1756 g_object_unref(fd_list);
1757 g_variant_unref(value);
1758 g_variant_builder_unref(builder);
1760 return BT_STATUS_SUCCESS;
1764 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1765 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1767 GVariant *val, *options;
1768 GVariantBuilder *builder1;
1769 GVariantBuilder *builder2;
1770 GDBusConnection *g_conn;
1773 hal_gatt_resp_data_t *resp_data;
1774 hal_gattc_service_t *gattc_service = NULL;
1775 hal_gattc_server_info_t * conn_info = NULL;
1776 hal_gattc_char_t *gattc_char = NULL;
1777 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1778 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1779 char* char_handle = NULL;
1780 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1781 int ret = BT_STATUS_SUCCESS;
1783 ret = __hal_get_write_prop(write_type, &write_prop);
1784 if (BT_STATUS_FAIL == ret) {
1785 DBG("received invalid write type:[%d] ", write_type);
1786 return BT_STATUS_FAIL;
1789 /* get the connection info */
1790 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1791 if (NULL == conn_info) {
1792 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1793 return BT_STATUS_FAIL;
1797 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1798 if (NULL == gattc_service) {
1799 ERR("Failed to get the gatt service");
1800 return BT_STATUS_FAIL;
1803 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1804 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1806 /* find characteristic */
1807 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1808 if (NULL == gattc_char) {
1809 ERR("Failed to get the gatt char");
1810 return BT_STATUS_FAIL;
1813 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1814 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1816 g_conn = _bt_hal_get_system_gconn();
1817 if (NULL == g_conn) {
1818 ERR("_bt_gdbus_get_system_gconn returned NULL");
1819 return BT_STATUS_FAIL;
1822 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1823 resp_data->conn_id = conn_id;
1824 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1825 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1827 char_handle = gattc_char->chr_path;
1829 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1831 for (i = 0; i < length; i++)
1832 g_variant_builder_add(builder1, "y", value[i]);
1834 val = g_variant_new("ay", builder1);
1836 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1838 g_variant_builder_add(builder2, "{sv}", "offset",
1839 g_variant_new_uint16(offset));
1841 options = g_variant_new("a{sv}", builder2);
1843 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1845 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1847 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1848 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1849 (gpointer)resp_data);
1851 g_variant_builder_unref(builder1);
1852 g_variant_builder_unref(builder2);
1854 return BT_STATUS_SUCCESS;
1857 bt_status_t btif_get_acquire_write_fd(int conn_id,
1858 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1859 int auth_req, int *fd, int*mtu)
1861 CHECK_BTGATT_INIT();
1863 hal_gattc_service_t *gattc_service = NULL;
1864 hal_gattc_server_info_t * conn_info = NULL;
1865 hal_gattc_char_t *gattc_char = NULL;
1866 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1868 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1869 int ret = BT_STATUS_SUCCESS;
1871 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1873 /* get the connection info */
1874 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1875 if (NULL == conn_info) {
1876 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1877 return BT_STATUS_FAIL;
1881 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1882 if (NULL == gattc_service) {
1883 ERR("Failed to get the gatt service");
1884 return BT_STATUS_FAIL;
1887 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1888 if (NULL == gattc_char) {
1889 ERR("Failed to get the gatt char");
1890 return BT_STATUS_FAIL;
1893 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1894 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1896 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1897 if (ret != BT_STATUS_SUCCESS)
1903 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1904 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1906 CHECK_BTGATT_INIT();
1908 hal_gattc_service_t *gattc_service = NULL;
1909 hal_gattc_server_info_t * conn_info = NULL;
1910 hal_gattc_char_t *gattc_char = NULL;
1911 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1913 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1914 int ret = BT_STATUS_SUCCESS;
1916 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1918 /* get the connection info */
1919 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1920 if (NULL == conn_info) {
1921 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1922 return BT_STATUS_FAIL;
1926 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1927 if (NULL == gattc_service) {
1928 ERR("Failed to get the gatt service");
1929 return BT_STATUS_FAIL;
1932 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1933 if (NULL == gattc_char) {
1934 ERR("Failed to get the gatt char");
1935 return BT_STATUS_FAIL;
1938 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1939 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1941 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1942 if (ret != BT_STATUS_SUCCESS)
1949 /** Write a remote characteristic */
1950 bt_status_t btif_write_characteristic(int conn_id,
1951 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1952 int write_type, int len, int auth_req,
1955 CHECK_BTGATT_INIT();
1957 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1958 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1959 len, auth_req, p_value);
1962 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1964 struct hal_ev_gatt_client_read_data ev;
1967 ERR("gatt client callback not registered");
1971 memset(&ev, 0, sizeof(ev));
1972 ev.conn_id = resp_data->conn_id;
1973 ev.inst_id = resp_data->srvc_id.id.inst_id;
1974 ev.is_primary = resp_data->srvc_id.is_primary;
1977 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1978 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1979 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1983 /* building the desc read value */
1984 memcpy(ev.value, value, len);
1987 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1989 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1992 static void __hal_internal_read_desc_cb(GObject *source_object,
1993 GAsyncResult *res, gpointer user_data)
1995 GError *error = NULL;
1996 GDBusConnection *system_gconn = NULL;
1999 GByteArray *gp_byte_array = NULL;
2001 hal_gatt_resp_data_t *resp_data = user_data;
2002 int result = BT_STATUS_SUCCESS;
2007 system_gconn = _bt_hal_get_system_gconn();
2008 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2011 ERR("Read descriptor dbus failed Error:[%s]", error->message);
2014 result = BT_STATUS_FAIL;
2015 __hal_send_desc_read_event(resp_data, result, NULL, 0);
2016 g_clear_error(&error);
2021 gp_byte_array = g_byte_array_new();
2022 g_variant_get(value, "(ay)", &iter);
2024 while (g_variant_iter_loop(iter, "y", &g_byte))
2025 g_byte_array_append(gp_byte_array, &g_byte, 1);
2029 for (i = 0; i < gp_byte_array->len; i++)
2030 DBG("%02x", gp_byte_array->data[i]);
2033 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2037 g_byte_array_free(gp_byte_array, TRUE);
2038 g_variant_iter_free(iter);
2039 g_variant_unref(value);
2044 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2045 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2047 GDBusConnection *g_conn;
2048 hal_gatt_resp_data_t *resp_data;
2049 hal_gattc_service_t *gattc_service = NULL;
2050 GVariantBuilder *builder = NULL;
2052 hal_gattc_server_info_t * conn_info = NULL;
2053 hal_gattc_char_t *gattc_char = NULL;
2054 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2055 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2056 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2057 char* desc_handle = NULL;
2060 hal_gattc_desc_t *gattc_desc = NULL;
2062 /* get the connection info */
2063 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2064 if (NULL == conn_info) {
2065 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2066 return BT_STATUS_FAIL;
2070 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2071 if (NULL == gattc_service) {
2072 ERR("Failed to get the gatt service");
2073 return BT_STATUS_FAIL;
2076 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2077 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2079 /* find characteristic */
2080 /* service can have two char with same uuid */
2081 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2082 gattc_char = (hal_gattc_char_t*)l->data;
2083 if (gattc_char == NULL)
2086 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2087 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2088 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2090 /* find descriptor */
2091 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2093 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2094 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2100 if (NULL == gattc_desc) {
2101 ERR("Failed to get the gatt desc");
2102 return BT_STATUS_FAIL;
2105 g_conn = _bt_hal_get_system_gconn();
2106 if (NULL == g_conn) {
2107 ERR("_bt_gdbus_get_system_gconn returned NULL");
2108 return BT_STATUS_FAIL;
2111 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2112 resp_data->conn_id = conn_id;
2113 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2114 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2115 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2117 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2120 g_variant_builder_add(builder, "{sv}", "offset",
2121 g_variant_new("q", offset));
2123 desc_handle = gattc_desc->desc_path;
2125 DBG("calling desc read value");
2127 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2128 "ReadValue", g_variant_new("(a{sv})", builder),
2129 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2130 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2131 (gpointer)resp_data);
2132 g_variant_builder_unref(builder);
2134 return BT_STATUS_SUCCESS;
2137 /** Read the descriptor for a given characteristic */
2138 bt_status_t btif_read_descriptor(int conn_id,
2139 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2140 btgatt_gatt_id_t *descr_id, int auth_req)
2142 CHECK_BTGATT_INIT();
2144 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2147 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2149 struct hal_ev_gatt_client_write_result ev;
2152 ERR("gatt client callback not registered");
2156 memset(&ev, 0, sizeof(ev));
2157 ev.conn_id = resp_data->conn_id;
2158 ev.inst_id = resp_data->srvc_id.id.inst_id;
2159 ev.is_primary = resp_data->srvc_id.is_primary;
2162 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2163 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2164 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2166 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2168 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2171 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2172 GAsyncResult *res, gpointer user_data)
2174 GError *error = NULL;
2175 GDBusConnection *system_gconn = NULL;
2177 hal_gatt_resp_data_t *resp_data = user_data;
2178 int result = BT_STATUS_SUCCESS;
2182 system_gconn = _bt_hal_get_system_gconn();
2183 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2186 ERR("write descriptor dbus failed Error: [%s]", error->message);
2189 result = BT_STATUS_FAIL;
2190 __hal_send_desc_write_event(resp_data, result);
2191 g_clear_error(&error);
2196 //send write value event
2197 __hal_send_desc_write_event(resp_data, result);
2200 g_variant_unref(value);
2205 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2206 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2207 int write_type, int length, int auth_req, char* value)
2209 GVariant *val, *options;
2210 GVariantBuilder *builder1;
2211 GVariantBuilder *builder2;
2212 GDBusConnection *g_conn;
2215 hal_gatt_resp_data_t *resp_data;
2216 hal_gattc_service_t *gattc_service = NULL;
2217 hal_gattc_server_info_t * conn_info = NULL;
2218 hal_gattc_char_t *gattc_char = NULL;
2219 hal_gattc_desc_t *gattc_desc = NULL;
2220 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2221 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2222 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2223 char* desc_handle = NULL;
2224 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2225 int ret = BT_STATUS_SUCCESS;
2230 ret = __hal_get_write_prop(write_type, &write_prop);
2231 if (BT_STATUS_FAIL == ret) {
2232 ERR("received invalid write type:[%d] ", write_type);
2233 return BT_STATUS_FAIL;
2236 /* get the connection info */
2237 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2238 if (NULL == conn_info) {
2239 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2240 return BT_STATUS_FAIL;
2244 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2245 if (NULL == gattc_service) {
2246 ERR("Failed to get the gatt service");
2247 return BT_STATUS_FAIL;
2250 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2251 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2253 /* find characteristic */
2254 /* service can have two char with same uuid */
2255 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2256 gattc_char = (hal_gattc_char_t*)l->data;
2257 if (gattc_char == NULL)
2260 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2261 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2262 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2264 /* find descriptor */
2265 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2267 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2268 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2274 if (NULL == gattc_desc) {
2275 ERR("Failed to get the gatt desc");
2276 return BT_STATUS_FAIL;
2279 g_conn = _bt_hal_get_system_gconn();
2280 if (NULL == g_conn) {
2281 ERR("_bt_gdbus_get_system_gconn returned NULL");
2282 return BT_STATUS_FAIL;
2285 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2286 resp_data->conn_id = conn_id;
2287 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2288 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2289 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2291 desc_handle = gattc_desc->desc_path;
2293 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2295 for (i = 0; i < length; i++)
2296 g_variant_builder_add(builder1, "y", value[i]);
2298 val = g_variant_new("ay", builder1);
2300 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2302 g_variant_builder_add(builder2, "{sv}", "offset",
2303 g_variant_new_uint16(offset));
2305 options = g_variant_new("a{sv}", builder2);
2307 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2309 g_variant_new("(@ay@a{sv})", val, options),
2311 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2312 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2313 (gpointer)resp_data);
2315 g_variant_builder_unref(builder1);
2316 g_variant_builder_unref(builder2);
2318 return BT_STATUS_SUCCESS;
2321 /** Write a remote descriptor for a given characteristic */
2322 bt_status_t btif_write_descriptor(int conn_id,
2323 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2324 btgatt_gatt_id_t *descr_id, int write_type, int len,
2325 int auth_req, char* p_value)
2327 CHECK_BTGATT_INIT();
2329 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2330 len, auth_req, p_value);
2333 /** Execute a prepared write operation */
2334 bt_status_t execute_write(int conn_id, int execute)
2336 CHECK_BTGATT_INIT();
2337 return BT_STATUS_UNSUPPORTED;
2340 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2342 struct hal_ev_gatt_client_watch_notification ev;
2343 hal_gatt_resp_data_t *resp_data = user_data;
2345 DBG("sending the watch register notification event");
2346 /* send the event */
2347 memset(&ev, 0, sizeof(ev));
2348 ev.conn_id = resp_data->conn_id;
2350 ev.status = resp_data->result;
2352 ev.is_primary = resp_data->srvc_id.is_primary;
2353 ev.inst_id = resp_data->srvc_id.id.inst_id;
2355 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2356 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2359 ERR("GATT Callback not registered");
2361 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2368 static bt_status_t _hal_register_for_notification(int conn_id,
2369 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2370 btgatt_gatt_id_t *char_id)
2372 int result = BT_STATUS_SUCCESS;
2373 GError *error = NULL;
2374 GDBusConnection *g_conn;
2375 hal_gattc_client_info_t *gattc_client = NULL;
2376 hal_gattc_server_info_t * conn_info = NULL;
2377 hal_gattc_service_t *gattc_service = NULL;
2378 hal_gattc_char_t *gattc_char = NULL;
2379 char* char_handle = NULL;
2380 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2381 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2382 hal_gatt_resp_data_t *resp_data;
2386 gattc_client = __bt_find_gatt_client_info(bd_addr);
2387 if (gattc_client == NULL) {
2388 ERR("failed to get the gatt client info");
2389 return BT_STATUS_FAIL;
2392 if (gattc_client->conn_id != conn_id) {
2393 ERR("could not find the gatt client for client id[%d]", conn_id);
2394 return BT_STATUS_FAIL;
2397 /* get the connection info */
2398 conn_info = __bt_find_gatt_conn_info(bd_addr);
2399 if (NULL == conn_info) {
2400 ERR("Failed to get the conn_info");
2401 return BT_STATUS_FAIL;
2404 if (conn_info->inst_id != gattc_client->inst_id) {
2405 ERR("could not fild the conn_info");
2406 return BT_STATUS_FAIL;
2410 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2411 if (NULL == gattc_service) {
2412 ERR("Failed to get the gatt service");
2413 return BT_STATUS_FAIL;
2416 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2417 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2420 /* find characteristic */
2421 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2422 if (NULL == gattc_char) {
2423 ERR("Failed to get the gatt char");
2424 return BT_STATUS_FAIL;
2427 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2428 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2430 char_handle = gattc_char->chr_path;
2432 g_conn = _bt_hal_get_system_gconn();
2433 if (g_conn == NULL) {
2435 return BT_STATUS_FAIL;
2438 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2440 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2442 g_dbus_connection_call_sync(g_conn,
2445 BT_HAL_GATT_CHAR_INTERFACE,
2449 G_DBUS_CALL_FLAGS_NONE,
2450 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2453 g_dbus_error_strip_remote_error(error);
2454 ERR("### StartNotify Failed: %s", error->message);
2455 if (g_strrstr(error->message, "Already notifying"))
2456 result = BT_STATUS_SUCCESS;
2457 else if (g_strrstr(error->message, "In Progress"))
2458 result = BT_STATUS_BUSY;
2459 else if (g_strrstr(error->message, "Operation is not supported"))
2460 result = BT_STATUS_UNSUPPORTED;
2461 /*failed because of either Insufficient Authorization or Write Not Permitted */
2462 else if (g_strrstr(error->message, "Write not permitted") ||
2463 g_strrstr(error->message, "Operation Not Authorized"))
2464 result = BT_STATUS_AUTH_FAILURE;
2465 /* failed because of either Insufficient Authentication,
2466 Insufficient Encryption Key Size, or Insufficient Encryption. */
2467 else if (g_strrstr(error->message, "Not paired"))
2468 result = BT_STATUS_NOT_READY;
2470 result = BT_STATUS_FAIL;
2472 g_clear_error(&error);
2475 resp_data->conn_id = gattc_client->conn_id;
2476 resp_data->result = result;
2477 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2478 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2480 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2484 return BT_STATUS_SUCCESS;
2488 * Register to receive notifications or indications for a given
2491 bt_status_t btif_register_for_notification(int conn_id,
2492 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2493 btgatt_gatt_id_t *char_id)
2495 CHECK_BTGATT_INIT();
2497 return _hal_register_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2500 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2502 struct hal_ev_gatt_client_watch_notification ev;
2503 hal_gatt_resp_data_t *resp_data = user_data;
2505 DBG("sending the watch deregister notification event");
2506 /* send the event */
2507 memset(&ev, 0, sizeof(ev));
2508 ev.conn_id = resp_data->conn_id;
2510 ev.status = resp_data->result;
2512 ev.is_primary = resp_data->srvc_id.is_primary;
2513 ev.inst_id = resp_data->srvc_id.id.inst_id;
2515 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2516 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2519 ERR("GATT Callback not registered");
2521 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2528 static bt_status_t _hal_deregister_for_notification(int conn_id,
2529 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2530 btgatt_gatt_id_t *char_id)
2532 int result = BT_STATUS_SUCCESS;
2533 GError *error = NULL;
2534 GDBusConnection *g_conn;
2535 hal_gattc_client_info_t *gattc_client = NULL;
2536 hal_gattc_server_info_t * conn_info = NULL;
2537 hal_gattc_service_t *gattc_service = NULL;
2538 hal_gattc_char_t *gattc_char = NULL;
2539 char* char_handle = NULL;
2540 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2541 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2542 hal_gatt_resp_data_t *resp_data;
2546 gattc_client = __bt_find_gatt_client_info(bd_addr);
2547 if (gattc_client == NULL) {
2548 ERR("failed to get the gatt client info");
2549 return BT_STATUS_FAIL;
2552 if (gattc_client->conn_id != conn_id) {
2553 ERR("could not find the gatt client for client id[%d]", conn_id);
2554 return BT_STATUS_FAIL;
2557 /* get the connection info */
2558 conn_info = __bt_find_gatt_conn_info(bd_addr);
2559 if (NULL == conn_info) {
2560 ERR("Failed to get the conn_info");
2561 return BT_STATUS_FAIL;
2564 if (conn_info->inst_id != gattc_client->inst_id) {
2565 ERR("could not fild the conn_info");
2566 return BT_STATUS_FAIL;
2570 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2571 if (NULL == gattc_service) {
2572 ERR("Failed to get the gatt service");
2573 return BT_STATUS_FAIL;
2576 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2577 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2580 /* find characteristic */
2581 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2582 if (NULL == gattc_char) {
2583 ERR("Failed to get the gatt char");
2584 return BT_STATUS_FAIL;
2587 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2588 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2590 char_handle = gattc_char->chr_path;
2592 g_conn = _bt_hal_get_system_gconn();
2593 if (g_conn == NULL) {
2595 return BT_STATUS_FAIL;
2598 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2600 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2601 g_dbus_connection_call_sync(g_conn,
2604 BT_HAL_GATT_CHAR_INTERFACE,
2608 G_DBUS_CALL_FLAGS_NONE,
2609 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2612 ERR("### StopNotify Failed: %s", error->message);
2613 g_clear_error(&error);
2614 result = BT_STATUS_FAIL;
2617 resp_data->conn_id = gattc_client->conn_id;
2618 resp_data->result = result;
2619 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2620 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2622 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2626 return BT_STATUS_SUCCESS;
2628 /** Deregister a previous request for notifications/indications */
2629 bt_status_t btif_deregister_for_notification(int conn_id,
2630 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2631 btgatt_gatt_id_t *char_id)
2633 CHECK_BTGATT_INIT();
2634 return _hal_deregister_for_notification(conn_id, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2637 /** Request RSSI for a given remote device */
2638 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2640 CHECK_BTGATT_INIT();
2641 return BT_STATUS_UNSUPPORTED;
2644 /** OTA firmware download */
2645 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2647 CHECK_BTGATT_INIT();
2648 return BT_STATUS_UNSUPPORTED;
2651 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2652 int get_device_type(const bt_bdaddr_t *bd_addr)
2654 CHECK_BTGATT_INIT();
2655 return BT_STATUS_UNSUPPORTED;
2658 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2659 int min_int, int max_int, int latency, int timeout)
2661 gchar *device_path = NULL;
2662 GError *error = NULL;
2663 GDBusProxy *device_proxy = NULL;
2664 GDBusConnection *conn;
2666 int ret = BT_STATUS_SUCCESS;
2667 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2669 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2670 min_int, max_int, latency, timeout);
2672 conn = _bt_hal_get_system_gconn();
2675 return BT_STATUS_FAIL;
2678 _bt_hal_convert_addr_type_to_string(device_address,
2679 (unsigned char *)bd_addr->address);
2680 device_path = _bt_hal_get_device_object_path(device_address);
2682 if (device_path == NULL) {
2683 ERR("device_path NULL : [%s]", device_address);
2684 return BT_STATUS_FAIL;
2687 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2688 NULL, BT_HAL_BLUEZ_NAME,
2689 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2691 g_free(device_path);
2692 if (NULL == device_proxy) {
2693 ERR("device_proxy returned NULL");
2694 return BT_STATUS_FAIL;
2697 DBG("Request LeConnUpdate");
2698 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2699 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2700 G_DBUS_CALL_FLAGS_NONE,
2705 g_object_unref(device_proxy);
2706 if (reply == NULL) {
2708 ERR("Error %s[%s]", error->message, device_address);
2709 if (g_strrstr(error->message, "In Progress"))
2710 ret = BT_STATUS_SUCCESS;
2712 ret = BT_STATUS_FAIL;
2713 g_error_free(error);
2717 g_variant_unref(reply);
2719 DBG("LE Connection parameter Updated");
2723 /** Request a connection parameter update */
2724 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2726 CHECK_BTGATT_INIT();
2728 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2731 /** Test mode interface */
2732 bt_status_t test_command(int command, btgatt_test_params_t* params)
2734 CHECK_BTGATT_INIT();
2735 return BT_STATUS_UNSUPPORTED;
2738 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2741 GError *g_error = NULL;
2742 GVariant *reply = NULL;
2743 int result = BT_STATUS_SUCCESS;
2744 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2745 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2747 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2748 g_object_unref(proxy);
2749 if (reply == NULL) {
2750 ERR("Connect LE Dbus Call Error");
2752 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2753 g_clear_error(&g_error);
2755 result = BT_STATUS_FAIL;
2757 g_variant_unref(reply);
2759 memset(&ev, 0, sizeof(ev));
2761 ev.mtu = conn_mtu->mtu;
2762 ev.conn_id = conn_mtu->conn_id;
2765 ERR("gatt client callback not registered");
2767 DBG("sending gatt client MTU exchange completed event");
2768 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2774 static bt_status_t get_att_mtu(int conn_id, int *mtu_size)
2776 CHECK_BTGATT_INIT();
2777 GDBusProxy *device_proxy;
2778 gchar *device_path = NULL;
2779 GError *error = NULL;
2781 GVariant *tmp_value;
2782 GDBusConnection *conn;
2783 GVariant *result = NULL;
2784 int ret = BT_STATUS_SUCCESS;
2785 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2786 hal_gattc_client_info_t *gattc_client = NULL;
2789 if (mtu_size == NULL)
2790 return BT_STATUS_PARM_INVALID;
2792 conn = _bt_hal_get_system_gconn();
2795 return BT_STATUS_FAIL;
2798 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2799 if (gattc_client == NULL) {
2800 INFO("GATT client conn info not found");
2801 return BT_STATUS_FAIL;
2804 _bt_hal_convert_addr_type_to_string(device_address,
2805 (unsigned char *)gattc_client->bd_addr.address);
2807 device_path = _bt_hal_get_device_object_path(device_address);
2808 if (device_path == NULL) {
2809 ERR("device_path NULL : [%s]", device_address);
2810 return BT_STATUS_FAIL;
2813 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2814 NULL, BT_HAL_BLUEZ_NAME,
2815 device_path, BT_HAL_PROPERTIES_INTERFACE, NULL, NULL);
2817 g_free(device_path);
2818 if (NULL == device_proxy) {
2819 ERR("device_proxy returned NULL");
2820 return BT_STATUS_FAIL;
2823 result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
2824 g_variant_new("(s)", BT_HAL_DEVICE_INTERFACE),
2825 G_DBUS_CALL_FLAGS_NONE,
2829 if (result == NULL) {
2830 if (error != NULL) {
2831 ERR("Error occured in Proxy call [%s]\n", error->message);
2832 g_error_free(error);
2834 g_object_unref(device_proxy);
2835 return BT_STATUS_FAIL;
2838 g_variant_get(result , "(@a{sv})", &value);
2839 g_variant_unref(result);
2841 tmp_value = g_variant_lookup_value(value, "AttMtu", G_VARIANT_TYPE_UINT16);
2842 if (tmp_value == NULL) {
2843 g_object_unref(device_proxy);
2844 g_variant_unref(value);
2845 return BT_STATUS_FAIL;
2848 mtu = g_variant_get_uint16(tmp_value);
2850 DBG("ATT MTU : [%d]", mtu);
2852 g_variant_unref(tmp_value);
2853 g_variant_unref(value);
2854 g_object_unref(device_proxy);
2856 *mtu_size = (int) mtu;
2861 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2863 gchar *device_path = NULL;
2864 GDBusProxy *device_proxy = NULL;
2865 GDBusConnection *conn;
2866 hal_gattc_client_info_t *gattc_client = NULL;
2867 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2868 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2870 conn = _bt_hal_get_system_gconn();
2874 return BT_STATUS_FAIL;
2877 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2878 if (gattc_client == NULL) {
2879 INFO("GATT client conn info not found");
2881 return BT_STATUS_FAIL;
2884 _bt_hal_convert_addr_type_to_string(device_address,
2885 (unsigned char *)gattc_client->bd_addr.address);
2887 device_path = _bt_hal_get_device_object_path(device_address);
2888 if (device_path == NULL) {
2889 ERR("device_path NULL : [%s]", device_address);
2891 return BT_STATUS_FAIL;
2894 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2895 NULL, BT_HAL_BLUEZ_NAME,
2896 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2898 g_free(device_path);
2899 if (NULL == device_proxy) {
2900 ERR("device_proxy returned NULL");
2902 return BT_STATUS_FAIL;
2905 conn_mtu->conn_id = conn_id;
2906 conn_mtu->mtu = mtu;
2908 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2909 g_variant_new("(q)", mtu),
2910 G_DBUS_CALL_FLAGS_NONE,
2911 BT_HAL_MAX_DBUS_TIMEOUT,
2913 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2916 return BT_STATUS_SUCCESS;
2919 /** MTU Exchange request from client */
2920 static bt_status_t configure_mtu(int conn_id, int mtu)
2922 CHECK_BTGATT_INIT();
2924 return __hal_configure_mtu(conn_id, mtu);
2927 /** Setup scan filter params */
2928 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2929 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2930 int rssi_low_thres, int dely_mode, int found_timeout,
2931 int lost_timeout, int found_timeout_cnt)
2934 GError *error = NULL;
2935 GVariant *ret, *param;
2936 CHECK_BTGATT_INIT();
2938 proxy = _bt_hal_get_adapter_proxy();
2941 return BT_STATUS_FAIL;
2943 param = g_variant_new("(iiiiiiiiiiii)",
2956 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2957 param, G_DBUS_CALL_FLAGS_NONE,
2961 ERR("scan_filter_param_setup Fail: %s", error->message);
2962 g_clear_error(&error);
2963 return BT_STATUS_FAIL;
2967 g_variant_unref(ret);
2969 return BT_STATUS_SUCCESS;
2972 /** Configure a scan filter condition */
2973 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2974 int filt_index, int company_id,
2975 int company_id_mask, const bt_uuid_t *p_uuid,
2976 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2977 char addr_type, int data_len, char* p_data, int mask_len,
2981 GError *error = NULL;
2982 GVariant *ret, *param;
2983 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2984 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2985 GArray *arr_uuid = NULL;
2986 GArray *arr_uuid_mask = NULL;
2987 GArray *arr_data = NULL;
2988 GArray *arr_data_mask = NULL;
2989 CHECK_BTGATT_INIT();
2991 proxy = _bt_hal_get_adapter_proxy();
2994 return BT_STATUS_FAIL;
2996 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2998 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3000 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
3002 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
3004 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3005 NULL, 0, TRUE, NULL, NULL);
3006 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3007 NULL, 0, TRUE, NULL, NULL);
3008 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3009 NULL, 0, TRUE, NULL, NULL);
3010 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3011 NULL, 0, TRUE, NULL, NULL);
3013 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3014 client_if, // client_if
3015 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3016 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
3017 filt_index, // filter_index
3018 company_id, // company_id
3019 company_id_mask, // company_id_mask
3020 arr_uuid_param, // p_uuid
3021 arr_uuid_mask_param, // p_uuid_mask
3023 addr_type, // address_type
3024 arr_data_param, // p_data
3025 arr_data_mask_param); // p_mask
3027 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3028 param, G_DBUS_CALL_FLAGS_NONE,
3032 ERR("scan_filter_add_remove Fail: %s", error->message);
3033 g_clear_error(&error);
3034 return BT_STATUS_FAIL;
3038 g_variant_unref(ret);
3040 return BT_STATUS_SUCCESS;
3043 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
3045 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
3046 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3047 NULL, 0, TRUE, NULL, NULL);
3048 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3049 NULL, 0, TRUE, NULL, NULL);
3050 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3051 NULL, 0, TRUE, NULL, NULL);
3052 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3053 NULL, 0, TRUE, NULL, NULL);
3055 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3056 client_if, // client_if
3057 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3058 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
3059 filt_index, // filter_index
3060 company_id, // company_id
3061 company_id_mask, // company_id_mask
3062 arr_uuid_param, // p_uuid
3063 arr_uuid_mask_param, // p_uuid_mask
3065 addr_type, // address_type
3066 arr_data_param, // p_data
3067 arr_data_mask_param);
3069 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3070 param, G_DBUS_CALL_FLAGS_NONE,
3074 ERR("scan_filter_add_remove Fail: %s", error->message);
3075 g_clear_error(&error);
3076 return BT_STATUS_FAIL;
3080 g_variant_unref(ret);
3082 return BT_STATUS_SUCCESS;
3085 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
3087 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3088 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3090 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3091 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3093 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3094 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3095 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3096 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3097 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3098 NULL, 0, TRUE, NULL, NULL);
3099 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3100 NULL, 0, TRUE, NULL, NULL);
3102 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3103 client_if, // client_if
3104 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3105 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
3106 filt_index, // filter_index
3107 company_id, // company_id
3108 company_id_mask, // company_id_mask
3109 arr_uuid_param, // p_uuid
3110 arr_uuid_mask_param, // p_uuid_mask
3112 addr_type, // address_type
3113 arr_data_param, // p_data
3114 arr_data_mask_param);
3116 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3117 param, G_DBUS_CALL_FLAGS_NONE,
3121 ERR("scan_filter_add_remove Fail: %s", error->message);
3122 g_clear_error(&error);
3123 return BT_STATUS_FAIL;
3127 g_variant_unref(ret);
3129 g_array_free(arr_uuid, TRUE);
3130 g_array_free(arr_uuid_mask, TRUE);
3132 return BT_STATUS_SUCCESS;
3135 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3137 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3138 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3140 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3141 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3143 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3144 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3145 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3146 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3147 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3148 NULL, 0, TRUE, NULL, NULL);
3149 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3150 NULL, 0, TRUE, NULL, NULL);
3152 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3153 client_if, // client_if
3154 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3155 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3156 filt_index, // filter_index
3157 company_id, // company_id
3158 company_id_mask, // company_id_mask
3159 arr_uuid_param, // p_uuid
3160 arr_uuid_mask_param, // p_uuid_mask
3162 addr_type, // address_type
3163 arr_data_param, // p_data
3164 arr_data_mask_param);
3166 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3167 G_DBUS_CALL_FLAGS_NONE,
3171 ERR("scan_filter_add_remove Fail: %s", error->message);
3172 g_clear_error(&error);
3173 return BT_STATUS_FAIL;
3177 g_variant_unref(ret);
3179 g_array_free(arr_uuid, TRUE);
3180 g_array_free(arr_uuid_mask, TRUE);
3182 return BT_STATUS_SUCCESS;
3185 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3187 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3188 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3190 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3191 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3193 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3194 NULL, 0, TRUE, NULL, NULL);
3195 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3196 NULL, 0, TRUE, NULL, NULL);
3197 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3198 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3199 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3200 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3202 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3203 client_if, // client_if
3204 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3205 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3206 filt_index, // filter_index
3207 company_id, // company_id
3208 company_id_mask, // company_id_mask
3209 arr_uuid_param, // p_uuid
3210 arr_uuid_mask_param, // p_uuid_mask
3212 addr_type, // address_type
3213 arr_data_param, // p_data
3214 arr_data_mask_param);
3216 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3217 G_DBUS_CALL_FLAGS_NONE,
3221 ERR("scan_filter_add_remove Fail: %s", error->message);
3222 g_clear_error(&error);
3223 return BT_STATUS_FAIL;
3227 g_variant_unref(ret);
3229 g_array_free(arr_data, TRUE);
3230 g_array_free(arr_data_mask, TRUE);
3232 return BT_STATUS_SUCCESS;
3235 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3237 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3238 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3240 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3241 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3243 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3244 NULL, 0, TRUE, NULL, NULL);
3245 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3246 NULL, 0, TRUE, NULL, NULL);
3247 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3248 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3249 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3250 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3252 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3253 client_if, // client_if
3254 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3255 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3256 filt_index, // filter_index
3257 company_id, // company_id
3258 company_id_mask, // company_id_mask
3259 arr_uuid_param, // p_uuid
3260 arr_uuid_mask_param, // p_uuid_mask
3262 addr_type, // address_type
3263 arr_data_param, // p_data
3264 arr_data_mask_param);
3266 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3267 G_DBUS_CALL_FLAGS_NONE,
3271 ERR("scan_filter_add_remove Fail: %s", error->message);
3272 g_clear_error(&error);
3273 return BT_STATUS_FAIL;
3277 g_variant_unref(ret);
3279 g_array_free(arr_data, TRUE);
3280 g_array_free(arr_data_mask, TRUE);
3282 return BT_STATUS_SUCCESS;
3285 return BT_STATUS_UNSUPPORTED;
3288 /** Clear all scan filter conditions for specific filter index*/
3289 bt_status_t scan_filter_clear(int client_if, int filt_index)
3292 GError *error = NULL;
3294 CHECK_BTGATT_INIT();
3296 proxy = _bt_hal_get_adapter_proxy();
3298 return BT_STATUS_FAIL;
3300 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3301 g_variant_new("(ii)", client_if, filt_index),
3302 G_DBUS_CALL_FLAGS_NONE,
3306 ERR("scan_filter_clear Fail: %s", error->message);
3307 g_clear_error(&error);
3308 return BT_STATUS_FAIL;
3311 g_variant_unref(ret);
3312 return BT_STATUS_SUCCESS;
3315 /** Enable / disable scan filter feature*/
3316 bt_status_t scan_filter_enable(int client_if, bool enable)
3319 GError *error = NULL;
3321 CHECK_BTGATT_INIT();
3323 proxy = _bt_hal_get_adapter_proxy();
3325 return BT_STATUS_FAIL;
3327 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3328 g_variant_new("(ib)", client_if, enable),
3329 G_DBUS_CALL_FLAGS_NONE,
3333 ERR("scan_filter_enable Fail: %s", error->message);
3334 g_clear_error(&error);
3335 return BT_STATUS_FAIL;
3337 g_variant_unref(ret);
3339 return BT_STATUS_SUCCESS;
3342 /** Sets the LE scan interval and window in units of N*0.625 msec */
3344 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3348 CHECK_BTGATT_INIT();
3350 le_scan_type = scan_type;
3351 ret = _bt_hal_adapter_le_set_scan_parameters(
3352 scan_type, scan_interval, scan_window);
3356 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3358 CHECK_BTGATT_INIT();
3359 return BT_STATUS_UNSUPPORTED;
3363 /* Configure the batchscan storage */
3364 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3365 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3367 CHECK_BTGATT_INIT();
3368 return BT_STATUS_UNSUPPORTED;
3371 /* Enable batchscan */
3372 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3373 int scan_interval, int scan_window, int addr_type, int discard_rule)
3375 CHECK_BTGATT_INIT();
3376 return BT_STATUS_UNSUPPORTED;
3379 /* Disable batchscan */
3380 bt_status_t batchscan_dis_batch_scan(int client_if)
3382 CHECK_BTGATT_INIT();
3383 return BT_STATUS_UNSUPPORTED;
3386 /* Read out batchscan reports */
3387 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3389 CHECK_BTGATT_INIT();
3390 return BT_STATUS_UNSUPPORTED;
3393 bt_status_t btif_gatt_get_data_batching_available_packets(unsigned int *available_packets)
3396 GError *error = NULL;
3398 guint32 available_pkts;
3400 CHECK_BTGATT_INIT();
3402 if (available_packets == NULL) {
3403 ERR("available_packets is NULL");
3404 return BT_STATUS_PARM_INVALID;
3407 proxy = _bt_hal_get_adapter_proxy();
3408 if (proxy == NULL) {
3409 ERR("proxy is NULL");
3410 return BT_STATUS_FAIL;
3413 ret = g_dbus_proxy_call_sync(proxy, "GetLeBatchingAvailablePkts",
3415 G_DBUS_CALL_FLAGS_NONE,
3418 int result = BT_STATUS_FAIL;
3420 ERR("SetLeBatchingParam Fail: %s", error->message);
3421 if (g_strrstr(error->message, "Operation is not supported"))
3422 result = BT_STATUS_UNSUPPORTED;
3424 g_clear_error(&error);
3427 g_variant_get(ret, "(u)", &available_pkts);
3428 g_variant_unref(ret);
3430 INFO("GATT Batching available packets: %u", available_pkts);
3431 *available_packets = available_pkts;
3432 return BT_STATUS_SUCCESS;
3435 bt_status_t btif_gatt_enable_data_batching(const bt_bdaddr_t *bd_addr, int packet_threshold, int timeout)
3437 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3439 GError *error = NULL;
3441 CHECK_BTGATT_INIT();
3443 if (bd_addr == NULL) {
3444 ERR("bd_addr is NULL");
3445 return BT_STATUS_PARM_INVALID;
3448 proxy = _bt_hal_get_adapter_proxy();
3449 if (proxy == NULL) {
3450 ERR("proxy is NULL");
3451 return BT_STATUS_FAIL;
3454 _bt_hal_convert_addr_type_to_string(device_address,
3455 (unsigned char *)bd_addr->address);
3456 ret = g_dbus_proxy_call_sync(proxy, "EnableLeBatching",
3457 g_variant_new("(sii)", device_address, packet_threshold, timeout),
3458 G_DBUS_CALL_FLAGS_NONE,
3461 int result = BT_STATUS_FAIL;
3463 ERR("SetLeBatchingParam Fail: %s", error->message);
3464 if (g_strrstr(error->message, "Operation is not supported"))
3465 result = BT_STATUS_UNSUPPORTED;
3466 else if (g_strrstr(error->message, "Invalid arguments"))
3467 result = BT_STATUS_PARM_INVALID;
3469 g_clear_error(&error);
3472 g_variant_unref(ret);
3474 INFO("GATT Batching is enabled");
3475 return BT_STATUS_SUCCESS;
3478 bt_status_t btif_gatt_disable_data_batching(const bt_bdaddr_t *bd_addr)
3480 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3482 GError *error = NULL;
3484 CHECK_BTGATT_INIT();
3486 if (bd_addr == NULL) {
3487 ERR("bd_addr is NULL");
3488 return BT_STATUS_PARM_INVALID;
3491 proxy = _bt_hal_get_adapter_proxy();
3492 if (proxy == NULL) {
3493 ERR("proxy is NULL");
3494 return BT_STATUS_FAIL;
3497 _bt_hal_convert_addr_type_to_string(device_address,
3498 (unsigned char *)bd_addr->address);
3499 ret = g_dbus_proxy_call_sync(proxy, "DisableLeBatching",
3500 g_variant_new("(s)", device_address),
3501 G_DBUS_CALL_FLAGS_NONE,
3504 int result = BT_STATUS_FAIL;
3506 ERR("SetLeBatching Fail: %s", error->message);
3507 if (g_strrstr(error->message, "Operation is not supported"))
3508 result = BT_STATUS_UNSUPPORTED;
3510 g_clear_error(&error);
3513 g_variant_unref(ret);
3515 INFO("GATT Batching is disabled");
3516 return BT_STATUS_SUCCESS;
3519 const btgatt_client_interface_t btgatt_client_interface = {
3520 .register_client = btif_gattc_register_client,
3521 .unregister_client = btif_gattc_unregister_client,
3523 .connect = btif_gattc_client_connect,
3524 .disconnect = btif_gattc_client_disconnect,
3526 .search_service = btif_gattc_client_search_service,
3527 .get_included_service = get_included_service,
3528 .get_characteristic = btif_gattc_get_characteristic,
3529 .get_descriptor = btif_gattc_get_descriptor,
3530 .read_characteristic = btif_read_characteristic,
3531 .write_characteristic = btif_write_characteristic,
3532 .acquire_write = btif_get_acquire_write_fd,
3533 .acquire_notify = btif_get_acquire_notify_fd,
3534 .read_descriptor = btif_read_descriptor,
3535 .write_descriptor = btif_write_descriptor,
3536 .execute_write = execute_write,
3537 .register_for_notification = btif_register_for_notification,
3538 .deregister_for_notification = btif_deregister_for_notification,
3539 .read_remote_rssi = read_remote_rssi,
3540 .ota_fw_update = ota_fw_update,
3541 .get_device_type = get_device_type,
3542 .conn_parameter_update = btif_gattc_conn_parameter_update,
3543 .test_command = test_command,
3544 .get_att_mtu = get_att_mtu,
3545 .configure_mtu = configure_mtu,
3546 .scan_filter_param_setup = scan_filter_param_setup,
3547 .scan_filter_add_remove = scan_filter_add_remove,
3548 .scan_filter_clear = scan_filter_clear,
3549 .scan_filter_enable = scan_filter_enable,
3550 .set_scan_parameters = set_scan_parameters,
3551 .batchscan_cfg_storage = batchscan_cfg_storage,
3552 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3553 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3554 .batchscan_read_reports = batchscan_read_reports,
3555 .add_connection_info = btif_gattc_add_connection_info,
3556 .get_data_batching_available_packets = btif_gatt_get_data_batching_available_packets,
3557 .enable_data_batching = btif_gatt_enable_data_batching,
3558 .disable_data_batching = btif_gatt_disable_data_batching,
3561 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3564 hal_gattc_server_info_t *info = NULL;
3566 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3567 info = (hal_gattc_server_info_t*)l->data;
3571 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3578 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3581 hal_gattc_client_info_t *info = NULL;
3583 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3584 info = (hal_gattc_client_info_t*)l->data;
3588 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3595 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3598 hal_gattc_client_info_t *info = NULL;
3600 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3601 info = (hal_gattc_client_info_t*)l->data;
3605 if (info->conn_id == conn_id)
3612 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3615 hal_gattc_server_info_t *info = NULL;
3616 hal_gattc_client_info_t *gattc_client = NULL;
3618 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3619 if (gattc_client == NULL) {
3620 ERR("GATT client conn info not found");
3624 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3625 info = (hal_gattc_server_info_t*)l->data;
3629 if ((info->inst_id == gattc_client->inst_id) &&
3630 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3637 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3638 gboolean auto_connect)
3640 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3641 gchar *device_path = NULL;
3642 GDBusProxy *device_proxy = NULL;
3643 GDBusConnection *conn;
3644 int ret = BT_STATUS_SUCCESS;
3645 hal_gattc_client_info_t *gattc_data;
3647 if (NULL == bd_addr) {
3648 ERR("bd_addr is NULL");
3649 return BT_STATUS_PARM_INVALID;
3652 conn = _bt_hal_get_system_gconn();
3654 ERR("_bt_gdbus_get_system_gconn returned NULL");
3655 return BT_STATUS_FAIL;
3658 _bt_hal_convert_addr_type_to_string(device_address,
3659 (unsigned char *)bd_addr->address);
3660 device_path = _bt_hal_get_device_object_path(device_address);
3661 if (device_path == NULL) {
3662 ERR("device_path NULL : [%s]", device_address);
3663 ret = BT_STATUS_FAIL;
3667 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3668 NULL, BT_HAL_BLUEZ_NAME,
3669 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3670 g_free(device_path);
3671 if (NULL == device_proxy) {
3672 ERR("device_proxy returned NULL");
3673 return BT_STATUS_FAIL;
3676 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3677 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3678 BT_HAL_ADDRESS_LENGTH_MAX);
3680 DBG("ConnectLE [%s]", device_address);
3682 gattc_data->client_if = client_if;
3684 g_dbus_proxy_call(device_proxy, "ConnectLE",
3685 g_variant_new("(b)", auto_connect),
3686 G_DBUS_CALL_FLAGS_NONE,
3687 BT_HAL_MAX_DBUS_TIMEOUT,
3689 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3694 static bt_status_t _bt_hold_current_advertising()
3696 int ret = BT_STATUS_FAIL;
3697 gboolean is_advertising = FALSE;
3700 if (_bt_hal_is_support_multi_adv() == TRUE) {
3701 DBG("VSC adv used");
3702 return BT_STATUS_SUCCESS;
3705 /* Dependent on Kernel operation. Hold adv to prevent stopping adv on kernel */
3706 is_advertising = _bt_hal_is_advertising_in_slot(0);
3707 if (is_advertising) {
3708 DBG("+ Stop current advertising");
3710 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3711 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3717 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3719 DBG("+ start current advertising");
3721 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3726 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3728 DBG("Try to initiate pending LE connection");
3730 pending_le_conn_timer_id = 0;
3732 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3733 &pending_le_conn_info->bd_addr,
3734 pending_le_conn_info->auto_connect);
3736 g_free(pending_le_conn_info);
3737 pending_le_conn_info = NULL;
3742 static int __hal_generate_conn_id()
3744 return ++hal_gatt_conn_id;
3747 static int __hal_generate_server_instance_id()
3749 return ++bt_inst_id;
3752 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3755 GError *g_error = NULL;
3756 GVariant *reply = NULL;
3757 hal_gattc_client_info_t *gattc_data = user_data;
3758 int result = BT_STATUS_SUCCESS;
3759 struct hal_ev_gatt_client_connected ev;
3760 hal_gattc_server_info_t *gatt_conn_info = NULL;
3762 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3763 g_object_unref(proxy);
3764 if (reply == NULL) {
3765 ERR("Connect LE Dbus Call Error");
3767 ERR("Error: %s\n", g_error->message);
3768 g_clear_error(&g_error);
3770 result = BT_STATUS_FAIL;
3772 g_variant_unref(reply);
3774 if (NULL == gattc_data) {
3775 ERR("gattc_data is NULL");
3780 if (result == BT_STATUS_FAIL) {
3781 memset(&ev, 0, sizeof(ev));
3784 ev.client_if = gattc_data->client_if;
3785 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3786 BT_HAL_ADDRESS_LENGTH_MAX);
3789 ERR("gatt client callback not registered");
3791 DBG("sending gatt client connected event");
3792 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3798 DBG("LE connected. Adding the gattc server/client conn info in list");
3799 gattc_data->conn_id = __hal_generate_conn_id() ;
3800 gattc_data->inst_id = __hal_generate_server_instance_id();
3802 #ifndef __INTEGRATE_HAL_GATT_INFO__
3803 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3806 /*add gatt server connection info*/
3807 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3808 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3809 gatt_conn_info->conn_id = gattc_data->conn_id;
3810 gatt_conn_info->inst_id = gattc_data->inst_id;
3811 #ifdef __INTEGRATE_HAL_GATT_INFO__
3812 gatt_conn_info->client_if = gattc_data->client_if;
3814 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3819 /*remove conn_info*/
3824 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3826 g_free(desc_info->desc_path);
3830 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3833 hal_gattc_desc_t *desc_info = NULL;
3834 for (l = char_info->gatt_list_descs; l != NULL; ) {
3835 desc_info = l->data;
3836 l = g_slist_next(l);
3837 if (desc_info == NULL)
3839 /* Remove descriptor element */
3840 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3841 __hal_gattc_free_desc_info(desc_info);
3843 g_slist_free(char_info->gatt_list_descs);
3844 g_free(char_info->chr_path);
3848 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3851 hal_gattc_char_t *char_info = NULL;
3852 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3853 char_info = l->data;
3854 l = g_slist_next(l);
3855 if (char_info == NULL)
3857 /* Remove characteristic element */
3858 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3859 __hal_gattc_free_char_info(char_info);
3861 g_slist_free(svc_info->gatt_list_chars);
3862 g_free(svc_info->svc_path);
3866 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3869 hal_gattc_service_t *svc_info = NULL;
3873 for (l = conn_info->gatt_list_services; l != NULL; ) {
3874 svc_info = (hal_gattc_service_t *)l->data;
3875 l = g_slist_next(l);
3876 if (svc_info == NULL)
3878 /* Remove service element */
3879 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3880 __hal_gattc_free_svc_info(svc_info);
3882 g_slist_free(conn_info->gatt_list_services);
3886 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3888 bt_bdaddr_t bd_addr;
3889 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3890 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3896 int _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3898 int result = BT_STATUS_SUCCESS;
3899 struct hal_ev_gatt_client_connected ev;
3900 hal_gattc_server_info_t *conn_info = NULL;
3901 bt_bdaddr_t bd_addr;
3903 hal_gattc_client_info_t *gattc_client = NULL;
3904 #ifndef __INTEGRATE_HAL_GATT_INFO__
3908 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3909 HAL_EV_GATT_CLIENT_DISCONNECTED;
3911 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3912 /* find the gatt client info */
3913 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3914 if (NULL == gattc_client) {
3915 ERR("Fail to get gatt client info");
3919 gattc_client->is_gatt_connected = gatt_connected;
3922 memset(&ev, 0, sizeof(ev));
3923 ev.conn_id = gattc_client->conn_id;
3925 ev.client_if = gattc_client->client_if;
3926 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3927 BT_HAL_ADDRESS_LENGTH_MAX);
3930 ERR("gatt client callback not registered");
3932 event_cb(event, (void *)&ev, sizeof(ev));
3935 if (!gatt_connected) {
3936 #ifndef __INTEGRATE_HAL_GATT_INFO__
3937 inst_id = gattc_client->inst_id;
3939 /* remove the gatt client info from the client list also*/
3940 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3941 g_free(gattc_client);
3944 //find the connected server info
3945 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3946 if (NULL == conn_info) {
3947 ERR("Fail to get gatt server info");
3951 #ifndef __INTEGRATE_HAL_GATT_INFO__
3952 if (inst_id != conn_info->inst_id) {
3953 ERR("server instance is different");
3958 //remove gatt conn info from the server list
3959 DBG("remove the server conn_info from list after gatt disconnection");
3960 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3961 __hal_clean_gattc_server_info(conn_info);
3967 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3968 const char* uuid_str, int inst_id)
3970 struct hal_ev_gatt_client_search_result ev;
3973 ERR("gatt client callback not registered");
3977 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3979 memset(&ev, 0, sizeof(ev));
3980 ev.conn_id = conn_id;
3981 ev.inst_id = inst_id;
3982 ev.is_primary = is_primary;
3983 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3985 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3988 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3990 struct hal_ev_gatt_client_search_complete ev;
3993 ERR("gatt client callback not registered");
3997 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
4000 memset(&ev, 0, sizeof(ev));
4001 ev.conn_id = conn_id;
4004 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
4007 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
4008 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
4009 char *char_value, int len)
4011 struct hal_ev_gatt_client_notify_changed_value ev;
4012 hal_gattc_client_info_t *gattc_client = NULL;
4015 ERR("gatt client callback not registered");
4019 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
4020 if (NULL == gattc_client) {
4021 ERR("failed to get the gatt client info");
4026 DBG("sending gatt client connected status event");
4027 memset(&ev, 0, sizeof(ev));
4029 ev.conn_id = gattc_client->conn_id;
4030 ev.inst_id = conn_info->inst_id;
4031 ev.is_primary = svc_info->is_primary;
4032 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
4033 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
4035 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
4037 if (len > 0 && (char_value != NULL)) {
4038 memcpy(ev.value, char_value, len);
4042 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
4045 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
4046 char *char_value, int len)
4048 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
4049 hal_gattc_server_info_t *conn_info = NULL;
4050 bt_bdaddr_t bd_addr;
4053 hal_gattc_service_t *svc_info = NULL;
4054 hal_gattc_char_t *char_info = NULL;
4058 _bt_hal_convert_device_path_to_address(char_handle, device_address);
4059 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
4060 DBG("device address:[%s]", device_address);
4061 DBG("char handle:[%s]", char_handle);
4063 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
4064 conn_info = __bt_find_gatt_conn_info(&bd_addr);
4066 if (conn_info != NULL) {
4067 //find service for notified char path
4068 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
4069 svc_info = (hal_gattc_service_t*)l->data;
4070 if (svc_info == NULL)
4073 /* find characteristic object path */
4074 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
4075 char_info = (hal_gattc_char_t *)k->data;
4076 if (char_info == NULL)
4079 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
4080 DBG("Found char handle[%s]", char_info->chr_path);
4083 _bt_hal_send_value_changed_event(conn_info, svc_info,
4084 char_info, char_value, len);
4092 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
4094 GDBusConnection *g_conn = NULL;
4095 GDBusProxy *properties_proxy = NULL;
4096 GVariant *result = NULL;
4097 GError *error = NULL;
4098 GVariantIter *property_iter = NULL;
4099 const gchar *key = NULL;
4100 GVariant *value = NULL;
4101 const char *uuid_str = NULL;
4103 gboolean is_primary = FALSE;
4104 GVariantIter *char_iter = NULL;
4105 const char *char_handle = NULL;
4106 GPtrArray *gp_char_array = NULL;
4108 if (service_path == NULL) {
4109 ERR("service_path is NULL");
4110 return BT_STATUS_FAIL;
4113 DBG("service_path: %s", service_path);
4115 g_conn = _bt_hal_get_system_gconn();
4116 if (g_conn == NULL) {
4117 ERR("g_conn is NULL");
4118 return BT_STATUS_FAIL;
4121 properties_proxy = g_dbus_proxy_new_sync(g_conn,
4122 G_DBUS_PROXY_FLAGS_NONE, NULL,
4125 BT_HAL_PROPERTIES_INTERFACE,
4127 if (properties_proxy == NULL) {
4128 ERR("properties_proxy is NULL");
4129 return BT_STATUS_FAIL;
4132 result = g_dbus_proxy_call_sync(properties_proxy,
4134 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
4135 G_DBUS_CALL_FLAGS_NONE,
4137 if (result == NULL) {
4138 if (error != NULL) {
4139 ERR("Fail to get properties (Error: %s)", error->message);
4140 g_clear_error(&error);
4142 ERR("Fail to get properties");
4144 g_object_unref(properties_proxy);
4145 return BT_STATUS_FAIL;
4148 g_variant_get(result, "(a{sv})", &property_iter);
4150 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
4151 if (g_strcmp0(key, "UUID") == 0) {
4152 uuid_str = g_variant_get_string(value, &len);
4153 } else if (g_strcmp0(key, "Primary") == 0) {
4154 is_primary = g_variant_get_boolean(value);
4155 } else if (g_strcmp0(key, "Characteristics") == 0) {
4156 g_variant_get(value, "ao", &char_iter);
4157 if (char_iter != NULL) {
4158 if (gp_char_array == NULL)
4159 gp_char_array = g_ptr_array_new();
4161 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
4162 DBG("char_handle: %s", char_handle);
4163 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
4165 g_variant_iter_free(char_iter);
4170 if (uuid_str == NULL || gp_char_array == NULL) {
4171 ERR("uuid_str and gp_char_array should be set");
4175 /* Create new service */
4176 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
4179 g_variant_iter_free(property_iter);
4180 g_variant_unref(result);
4181 g_object_unref(properties_proxy);
4183 return BT_STATUS_SUCCESS;
4186 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
4188 GDBusConnection *conn = NULL;
4189 GDBusProxy *proxy = NULL;
4191 GVariant *ret = NULL;
4192 GVariant *value = NULL;
4194 conn = _bt_hal_get_system_gconn();
4196 ERR("_bt_gdbus_get_system_gconn returned NULL");
4200 proxy = g_dbus_proxy_new_sync(conn,
4201 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
4202 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
4203 if (proxy == NULL) {
4204 ERR("device_proxy returned NULL");
4208 ret = g_dbus_proxy_call_sync(proxy, "Get",
4209 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
4210 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
4212 ERR("DBus Error : %s", err->message);
4213 g_clear_error(&err);
4215 g_variant_get(ret, "(v)", &value);
4216 *service_uuid = g_variant_dup_string(value, NULL);
4217 g_variant_unref(value);
4218 g_variant_unref(ret);
4222 g_object_unref(proxy);
4227 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
4229 struct hal_ev_gatt_client_service_changed ev = {0, };
4230 char address[BT_HAL_ADDRESS_STRING_SIZE];
4231 hal_gattc_server_info_t *server_info = NULL;
4232 hal_gattc_client_info_t *gattc_client = NULL;
4233 hal_gattc_service_t *service = NULL;
4234 GSList *list = NULL;
4235 char *uuid_str = NULL;
4237 _bt_hal_convert_device_path_to_address(path, address);
4238 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
4239 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
4240 if (server_info == NULL) {
4241 ERR("server_info is NULL");
4245 gattc_client = __bt_find_gatt_client_info((bt_bdaddr_t *)ev.bdaddr);
4246 if (gattc_client == NULL) {
4247 ERR("gattc_client is NULL");
4251 if (server_info->is_gatt_connected == FALSE && gattc_client->is_gatt_connected == FALSE) {
4252 DBG("GattConnected signal is not received yet. Just skip [%d %d]",
4253 server_info->is_gatt_connected, gattc_client->is_gatt_connected);
4258 /* Get service UUID from path */
4259 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
4261 INFO("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
4262 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
4265 ERR("uuid_str is NULL");
4269 /* Create new service and append into the list */
4270 __hal_gattc_get_service_info(server_info, path);
4272 /* Find service UUID from path */
4273 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4274 service = (hal_gattc_service_t *)list->data;
4275 if (service == NULL)
4278 if (g_strcmp0(service->svc_path, path) == 0) {
4279 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4280 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4281 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4282 INFO("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
4284 /* Remove service info in list */
4285 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4286 __hal_gattc_free_svc_info(service);
4294 ERR("uuid_str is NULL");
4299 /* Send GATT Client service changed event */
4300 ev.change_type = is_added;
4301 ev.conn_id = server_info->conn_id;
4302 ev.inst_id = server_info->inst_id;
4303 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));