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*/
126 int inst_id; /*server instance id*/
127 GSList *gatt_list_services;
128 } hal_gattc_server_info_t;
130 /* Linked List of connected GATT server */
131 static GSList *hal_gattc_server_info_list = NULL;
135 bt_bdaddr_t bd_addr; /*remote server address*/
138 } hal_gattc_client_info_t;
140 /* Linked list of connected GATT client connection */
141 static GSList * hal_gattc_client_info_list = NULL;
143 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
144 static guint pending_le_conn_timer_id = 0;
145 static int bt_conn_id = 0;
146 static int bt_inst_id = 0;
148 #define BT_GATTC_CL_MAX 32
153 btgatt_srvc_id_t srvc_id;
154 btgatt_gatt_id_t char_id;
155 btgatt_gatt_id_t desc_id;
156 } hal_gatt_resp_data_t;
161 } hal_gatt_client_app;
163 static GSList * hal_gattc_client_app_list = NULL;
165 static int bt_client_if = 0;
172 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
173 gboolean auto_connect);
174 static bt_status_t _bt_hold_current_advertising();
175 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
176 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
177 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
179 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
180 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
181 const char* uuid_str, int inst_id);
182 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
183 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr);
184 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
185 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
188 /* To send stack event to hal-av handler */
189 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
194 void _bt_hal_unregister_gatt_client_handler_cb(void)
200 int _bt_hal_gatt_client_get_le_scan_type(void)
206 static gboolean __bt_hal_register_client_cb(gpointer user_data)
208 struct hal_ev_gatt_client_registered ev;
209 hal_gatt_client_app *client_info = user_data;
212 /* Prepare to send AV connecting event */
213 memset(&ev, 0, sizeof(ev));
214 ev.status = BT_STATUS_SUCCESS;
215 ev.client_if = client_info->client_if;
216 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
219 ERR("GATT Callback not registered");
221 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
222 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
229 static int __hal_generate_client_id()
231 return ++bt_client_if;
234 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
237 hal_gatt_client_app *info = NULL;
238 hal_gatt_client_app *gattc_app = NULL;
240 //check if client app is already registered
241 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
242 info = (hal_gatt_client_app*)l->data;
246 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
247 DBG("gatt client app already registered");
252 DBG("adding the gatt client app");
255 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
256 gattc_app->client_if = __hal_generate_client_id();
257 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
259 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
264 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
266 hal_gatt_client_app *gattc_app = NULL;
267 hal_gatt_client_app *client_app_info = NULL;
270 /* add gatt client in list */
271 gattc_app = __hal_gattc_add_client_app(app_uuid);
272 if (gattc_app == NULL) {
273 ERR("Failed to register gatt client app");
274 return BT_STATUS_FAIL;
278 client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
279 client_app_info->client_if = gattc_app->client_if;
280 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
281 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
283 DBG("registered client client_if [%d]", client_app_info->client_if);
285 return BT_STATUS_SUCCESS;
288 /** Registers a GATT client application with the stack */
289 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
294 return __hal_gattc_register_client_app(uuid);
297 bt_status_t btif_gattc_add_connection_info(const bt_bdaddr_t *bd_addr, int conn_id, int server_inst_id)
299 hal_gattc_client_info_t *client_info = NULL;
300 hal_gattc_server_info_t *server_info = NULL;
302 /* Add client connection info in list */
303 client_info = g_malloc0(sizeof(hal_gattc_client_info_t));
304 client_info->client_if = -1;
305 memcpy(client_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
306 client_info->conn_id = conn_id;
307 client_info->inst_id = server_inst_id;
308 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, client_info);
309 DBG("Added client connection info in list");
311 /* Add server connection info in list */
312 server_info = __bt_find_gatt_conn_info(bd_addr);
313 if (server_info == NULL) {
314 server_info = g_malloc0(sizeof(hal_gattc_server_info_t));
315 memcpy(server_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
316 server_info->inst_id = server_inst_id;
317 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, server_info);
318 DBG("Added server connection info in list");
321 return BT_STATUS_SUCCESS;
324 bt_status_t __hal_gattc_unregister_client(int client_if)
327 hal_gatt_client_app *info = NULL;
329 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
331 /* remove the gatt client app */
332 for (l = hal_gattc_client_app_list; l != NULL; ) {
333 info = (hal_gatt_client_app*)l->data;
339 if (info->client_if == client_if) {
340 DBG("gatt client app found");
341 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
346 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
347 return BT_STATUS_SUCCESS;
350 /** Unregister a client application from the stack */
351 bt_status_t btif_gattc_unregister_client(int client_if)
356 return __hal_gattc_unregister_client(client_if);
359 /** Start or stop LE device scanning */
360 bt_status_t scan(int client_if, bool start)
367 ret = _bt_hal_adapter_le_start_scan();
369 ret = _bt_hal_adapter_le_stop_scan();
374 /** Create a connection to a remote LE or dual-mode device */
375 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
378 int ret = BT_STATUS_SUCCESS;
384 return BT_STATUS_PARM_INVALID;
386 ret = _bt_hold_current_advertising();
387 if (ret == BT_STATUS_SUCCESS) {
388 DBG("Current advertising is held");
389 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
390 pending_le_conn_info->client_if = client_if;
391 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
392 BT_HAL_ADDRESS_LENGTH_MAX);
393 pending_le_conn_info->auto_connect = is_direct;
395 pending_le_conn_timer_id =
396 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
398 return BT_STATUS_SUCCESS;
400 ERR("advertising is not stopped");
403 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
407 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
410 GError *g_error = NULL;
411 GVariant *reply = NULL;
412 hal_gattc_client_info_t *gatt_conn_info = user_data;
413 int result = BT_STATUS_SUCCESS;
414 struct hal_ev_gatt_client_connected ev;
418 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
419 g_object_unref(proxy);
421 ERR("Connect LE Dbus Call Error");
423 ERR("Error: %s\n", g_error->message);
424 g_clear_error(&g_error);
426 result = BT_STATUS_FAIL;
428 g_variant_unref(reply);
430 if (NULL == gatt_conn_info) {
431 ERR("server_data is NULL");
436 if (result == BT_STATUS_FAIL) {
437 memset(&ev, 0, sizeof(ev));
438 ev.conn_id = gatt_conn_info->conn_id;
440 ev.client_if = gatt_conn_info->client_if;
441 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
442 BT_HAL_ADDRESS_LENGTH_MAX);
445 ERR("gatt client callback not registered");
447 DBG("sending gatt client disconnected event");
448 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
454 g_free(gatt_conn_info);
459 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
462 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
464 GDBusProxy *device_proxy;
465 GDBusConnection *conn;
466 int ret = BT_STATUS_SUCCESS;
467 hal_gattc_client_info_t *gattc_data;
469 if (NULL == bd_addr) {
470 ERR("bd_addr is NULL");
471 return BT_STATUS_PARM_INVALID;
474 conn = _bt_hal_get_system_gconn();
476 ERR("_bt_gdbus_get_system_gconn returned NULL");
477 return BT_STATUS_FAIL;
480 _bt_hal_convert_addr_type_to_string(device_address,
481 (unsigned char *)bd_addr->address);
482 device_path = _bt_hal_get_device_object_path(device_address);
483 if (device_path == NULL) {
484 DBG("device_path NULL");
485 ret = BT_STATUS_FAIL;
489 ERR("device_path:%s", device_path);
491 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
492 NULL, BT_HAL_BLUEZ_NAME,
493 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
495 if (NULL == device_proxy) {
496 ERR("device_proxy returned NULL");
497 return BT_STATUS_FAIL;
500 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
501 memcpy(gattc_data->bd_addr.address, bd_addr->address,
502 BT_HAL_ADDRESS_LENGTH_MAX);
503 gattc_data->client_if = client_if;
504 gattc_data->conn_id = conn_id;
506 DBG("DisconnectLE [%s]", device_address);
508 g_dbus_proxy_call(device_proxy, "DisconnectLE",
510 G_DBUS_CALL_FLAGS_NONE,
511 BT_HAL_MAX_DBUS_TIMEOUT,
513 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
517 /** Disconnect a remote device or cancel a pending connection */
518 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
525 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
528 /** Clear the attribute cache for a given device */
529 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
532 return BT_STATUS_UNSUPPORTED;
535 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
540 hal_gattc_service_t *info = NULL;
542 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
543 info = (hal_gattc_service_t*)l->data;
547 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t))) {
548 INFO("Found GATT service uuid");
556 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
557 bt_gatt_characteristic_property_t prop)
562 hal_gattc_char_t *info = NULL;
564 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
565 info = (hal_gattc_char_t*)l->data;
569 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
570 (info->permission & prop)) {
571 INFO("Found GATT char uuid");
578 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
583 hal_gattc_char_t *info = NULL;
585 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
586 info = (hal_gattc_char_t*)l->data;
590 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
591 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
592 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
593 INFO("Found GATT char uuid");
600 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
605 hal_gattc_desc_t *info = NULL;
607 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
608 info = (hal_gattc_desc_t*)l->data;
612 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t))) {
613 INFO("Found GATT descriptor uuid");
621 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
622 const char *uuid_str, const char *object_path, int is_primary)
625 hal_gattc_service_t *gattc_service = NULL;
627 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
628 gattc_service->svc_path = g_strdup(object_path);
629 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
630 gattc_service->is_primary = is_primary;
632 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
634 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
636 DBG("svc path [%s] svc uuid [%s]", object_path, uuid_str);
638 return gattc_service;
641 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
644 hal_gattc_char_t *gattc_char = NULL;
646 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
647 gattc_char->chr_path = g_strdup(char_handle);
649 DBG("svc path: [%s]", gatt_svc->svc_path);
650 DBG("char path: [%s]", gattc_char->chr_path);
652 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
655 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
656 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
658 hal_gattc_service_t* gatt_svc = NULL;
660 gchar *gp_char_path = NULL;
664 /* add the service */
665 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
666 if (gatt_svc == NULL) {
667 ERR("Failed to add service");
671 /* add the characteristic */
672 for (i = 0; i < gp_char_array->len; i++) {
673 gp_char_path = g_ptr_array_index(gp_char_array, i);
674 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
677 g_ptr_array_free(gp_char_array, TRUE);
680 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
682 hal_gattc_desc_t *gattc_desc = NULL;
684 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
685 gattc_desc->desc_path = g_strdup(desc_path);
687 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
689 DBG("char path: [%s]", gattc_char->chr_path);
690 DBG("desc path: [%s]", gattc_desc->desc_path);
693 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
694 GPtrArray *gp_desc_array, unsigned int char_permission)
696 gchar *gp_desc_path = NULL;
701 if (char_uuid_str == NULL) {
702 DBG("char_uuid_str is NULL");
706 //update the char uuid
707 DBG("char UUID: [%s] ", char_uuid_str);
708 DBG("char path: [%s]", gattc_char->chr_path);
710 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
712 //update char permission
713 gattc_char->permission = char_permission;
716 for (i = 0; i < gp_desc_array->len; i++) {
717 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
718 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
722 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
726 if (desc_uuid_str == NULL) {
727 DBG("char_uuid_str is NULL");
731 //update the descriptor uuid
732 DBG("desc UUID: [%s] ", desc_uuid_str);
733 DBG("desc path: [%s]", gattc_desc->desc_path);
735 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
738 static void browse_service_char(int conn_id)
740 hal_gattc_server_info_t *conn_info = NULL;
744 hal_gattc_service_t *svc_info = NULL;
745 hal_gattc_char_t *char_info = NULL;
746 hal_gattc_desc_t *desc_info = NULL;
748 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
749 if (conn_info == NULL) {
750 ERR("conn_info is NULL");
754 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
756 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
757 svc_info = (hal_gattc_service_t*)l->data;
758 if (svc_info == NULL)
761 DBG("[%s]", svc_info->svc_path);
763 /* find characteristic object path */
764 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
765 char_info = (hal_gattc_char_t *)k->data;
766 if (char_info == NULL)
769 DBG("[%s]", char_info->chr_path);
772 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
773 desc_info = (hal_gattc_desc_t *)m->data;
774 if (desc_info == NULL)
777 DBG("[%s]", desc_info->desc_path);
786 * Enumerate all GATT services on a connected device.
787 * Optionally, the results can be filtered for a given UUID.
789 static bt_status_t _gattc_client_search_service(int conn_id)
793 GVariant *result = NULL;
795 GVariantIter *svc_iter;
796 GVariantIter *interface_iter;
797 char *object_path = NULL;
798 char *interface_str = NULL;
799 const gchar *key = NULL;
800 GVariant *value = NULL;
801 GPtrArray *gp_array = NULL;
802 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
803 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
804 int ret = BT_STATUS_FAIL;
806 const gchar *uuid_str = NULL;
808 hal_gattc_server_info_t *conn_info = NULL;
809 gboolean is_primary = FALSE;
812 char *char_handle = NULL;
813 GVariantIter *char_iter = NULL;
814 GPtrArray *gp_char_array = NULL;
818 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
819 if (NULL == conn_info) {
820 ERR("Failed to get the conn_info");
821 return BT_STATUS_FAIL;
824 /* Check the service info is stored */
825 if (g_slist_length(conn_info->gatt_list_services) > 0) {
827 hal_gattc_service_t *svc_info = NULL;
828 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
829 DBG("Send event from service info list");
830 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
832 if (svc_info == NULL)
834 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
835 _bt_hal_send_search_service_result_event(conn_id,
836 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
838 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
839 return BT_STATUS_SUCCESS;
841 DBG("No stored service, request to bluez");
844 _bt_hal_convert_addr_type_to_string(device_address,
845 (unsigned char *)conn_info->bd_addr.address);
847 result = _bt_hal_get_managed_objects();
851 gp_array = g_ptr_array_new();
852 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
854 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
856 if (object_path == NULL)
859 _bt_hal_convert_device_path_to_address(object_path, temp_address);
861 if (g_strcmp0(temp_address, device_address) != 0)
864 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
865 &interface_str, &svc_iter)) {
866 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
869 DBG("[%d] Object Path : %s", idx++, object_path);
870 /* for characteristic */
871 gp_char_array = g_ptr_array_new();
872 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
873 if (g_strcmp0(key, "Primary") == 0) {
874 is_primary = g_variant_get_boolean(value);
877 g_ptr_array_add(gp_array, (gpointer)object_path);
880 } else if (g_strcmp0(key, "UUID") == 0) {
881 uuid_str = g_variant_get_string(value, &len);
882 DBG(" UUID: [%s]", uuid_str);
883 } else if (g_strcmp0(key, "Characteristics") == 0) {
884 g_variant_get(value, "ao", &char_iter);
885 if (char_iter != NULL) {
886 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
887 DBG("char handle : %s", char_handle);
888 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
895 DBG("send search service result event");
896 _bt_hal_send_search_service_result_event(conn_id, is_primary,
897 uuid_str, conn_info->inst_id);
899 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
904 if (gp_array->len == 0 || svc_count == 0) {
905 ERR("gp_array is NULL");
906 ret = BT_STATUS_FAIL;
908 ret = BT_STATUS_SUCCESS;
911 browse_service_char(conn_id);
912 /* send search service complete event */
913 _bt_hal_send_search_service_complete_event(conn_id, ret);
915 g_ptr_array_free(gp_array, TRUE);
916 g_variant_iter_free(iter);
917 g_variant_unref(result);
922 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
924 if (NULL == filter_uuid) {
925 DBG("Browse all the services");
926 return _gattc_client_search_service(conn_id);
928 DBG("TODO implement it");
929 return BT_STATUS_UNSUPPORTED;
933 * Enumerate included services for a given service.
934 * Set start_incl_srvc_id to NULL to get the first included service.
936 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
937 btgatt_srvc_id_t *start_incl_srvc_id)
940 return BT_STATUS_UNSUPPORTED;
943 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
944 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
946 struct hal_ev_gatt_client_char_search_result ev;
949 ERR("gatt client callback not registered");
953 DBG("sending gatt client search char result event conn_id[%d] status[%d]", conn_id, status);
955 memset(&ev, 0, sizeof(ev));
956 ev.conn_id = conn_id;
957 ev.inst_id = svc_id->id.inst_id;
958 ev.is_primary = svc_id->is_primary;
960 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
962 if (status == BT_STATUS_SUCCESS) {
963 DBG("building char uuid");
964 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
965 ev.char_prop = char_prop;
968 DBG("sending the char search event");
970 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
973 static int _hal_get_permission_flag(char *permission)
977 if (NULL == permission) {
978 ERR("gatt permission is NULL");
982 if (!g_strcmp0(permission, "broadcast"))
983 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
984 else if (!g_strcmp0(permission, "read"))
985 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
986 else if (!g_strcmp0(permission, "write-without-response"))
987 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
988 else if (!g_strcmp0(permission, "write"))
989 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
990 else if (!g_strcmp0(permission, "notify"))
991 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
992 else if (!g_strcmp0(permission, "indicate"))
993 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
994 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
995 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
996 else if (!g_strcmp0(permission, "reliable-write"))
997 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
998 else if (!g_strcmp0(permission, "writable-auxiliaries"))
999 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1000 else if (!g_strcmp0(permission, "encrypt-read"))
1001 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1002 else if (!g_strcmp0(permission, "encrypt-write"))
1003 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1004 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1005 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1006 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1007 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1013 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1015 GDBusProxy *properties_proxy = NULL;
1016 GError *error = NULL;
1017 GVariant *value = NULL;
1018 GVariant *result = NULL;
1019 GDBusConnection *g_conn;
1021 char *char_desc_handle = NULL;
1023 GVariantIter *property_iter;
1024 GVariantIter *char_desc_iter;
1025 char* char_handle = NULL;
1026 gchar *char_uuid_str = NULL;
1027 GPtrArray *gp_desc_array = NULL;
1028 GVariantIter *char_perm_iter;
1030 unsigned int char_permission = 0 ;
1032 if (gattc_char->chr_path == NULL) {
1033 DBG("char path is NULL");
1034 return BT_STATUS_FAIL;
1036 char_handle = gattc_char->chr_path;
1038 DBG("char path:[%s]", gattc_char->chr_path);
1040 g_conn = _bt_hal_get_system_gconn();
1041 if (NULL == g_conn) {
1042 ERR("_bt_gdbus_get_system_gconn returned NULL");
1043 return BT_STATUS_FAIL;
1046 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1047 G_DBUS_PROXY_FLAGS_NONE, NULL,
1050 BT_HAL_PROPERTIES_INTERFACE,
1053 if (properties_proxy == NULL) {
1054 ERR("properties_proxy returned NULL");
1055 return BT_STATUS_FAIL;
1058 result = g_dbus_proxy_call_sync(properties_proxy,
1060 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1061 G_DBUS_CALL_FLAGS_NONE,
1066 if (error != NULL) {
1067 ERR("Fail to get properties (Error: %s)", error->message);
1068 g_clear_error(&error);
1070 ERR("Fail to get properties");
1071 g_object_unref(properties_proxy);
1072 return BT_STATUS_FAIL;
1075 gp_desc_array = g_ptr_array_new();
1077 g_variant_get(result, "(a{sv})", &property_iter);
1079 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1080 if (!g_strcmp0(key, "UUID")) {
1081 char_uuid_str = g_variant_dup_string(value, &len);
1082 DBG("char UUID [%s]", char_uuid_str);
1083 } else if (!g_strcmp0(key, "Flags")) {
1084 g_variant_get(value, "as", &char_perm_iter);
1085 char_permission = 0x00;
1087 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1088 DBG("char permission: [%s]", permission);
1089 char_permission |= _hal_get_permission_flag(permission);
1091 } else if (!g_strcmp0(key, "Descriptors")) {
1092 g_variant_get(value, "ao", &char_desc_iter);
1093 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1094 DBG("char descriptor : %s", char_desc_handle);
1096 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1101 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1103 g_free(char_uuid_str);
1104 g_variant_iter_free(property_iter);
1105 g_variant_unref(result);
1106 g_object_unref(properties_proxy);
1107 g_ptr_array_free(gp_desc_array, TRUE);
1109 return BT_STATUS_SUCCESS;
1112 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1113 btgatt_srvc_id_t *srvc_id)
1115 hal_gattc_server_info_t * conn_info = NULL;
1116 hal_gattc_service_t *gattc_service = NULL;
1118 hal_gattc_char_t *gattc_char = NULL;
1119 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1120 int status = BT_STATUS_FAIL;
1122 DBG("conn_id[%d]", conn_id);
1124 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1125 if (NULL == conn_info) {
1126 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1127 return BT_STATUS_FAIL;
1131 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1132 if (NULL == gattc_service) {
1133 ERR("Failed to get the gatt service");
1134 return BT_STATUS_FAIL;
1137 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1138 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1140 /* find characteristic object path */
1141 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1142 gattc_char = (hal_gattc_char_t *)l->data;
1143 status = _hal_gattc_get_characteristic_info(gattc_char);
1146 if (BT_STATUS_SUCCESS == status) {
1147 DBG("Sending the success charateristics event");
1148 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1149 &gattc_char->chr_uuid, gattc_char->permission);
1153 DBG("sending final event");
1155 status = BT_STATUS_FAIL;
1156 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1158 browse_service_char(conn_id);
1159 /* retrive uuid for characteristic and object path for descriptor */
1161 return BT_STATUS_SUCCESS;
1165 * Enumerate characteristics for a given service.
1166 * Set start_char_id to NULL to get the first characteristic.
1168 bt_status_t btif_gattc_get_characteristic(int conn_id,
1169 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1172 CHECK_BTGATT_INIT();
1174 if (start_char_id == NULL) {
1175 DBG("Get all the characteristics");
1176 return _gattc_get_all_characteristic(conn_id, srvc_id);
1179 DBG("TBD Get specific characteristics");
1180 return BT_STATUS_UNSUPPORTED;
1184 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1186 GDBusProxy *properties_proxy = NULL;
1187 GError *error = NULL;
1188 GVariant *value = NULL;
1189 GVariant *result = NULL;
1190 GDBusConnection *g_conn;
1193 GVariantIter *property_iter;
1194 char* desc_handle = NULL;
1195 const gchar *desc_uuid_str = NULL;
1199 if (gattc_desc->desc_path == NULL) {
1200 DBG("desc path is NULL");
1201 return BT_STATUS_FAIL;
1203 desc_handle = gattc_desc->desc_path;
1205 DBG("desc path:[%s]", gattc_desc->desc_path);
1207 g_conn = _bt_hal_get_system_gconn();
1208 if (NULL == g_conn) {
1209 ERR("_bt_gdbus_get_system_gconn returned NULL");
1210 return BT_STATUS_FAIL;
1213 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1214 G_DBUS_PROXY_FLAGS_NONE, NULL,
1217 BT_HAL_PROPERTIES_INTERFACE,
1220 if (properties_proxy == NULL) {
1221 ERR("properties_proxy returned NULL");
1222 return BT_STATUS_FAIL;
1225 result = g_dbus_proxy_call_sync(properties_proxy,
1227 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1228 G_DBUS_CALL_FLAGS_NONE,
1233 if (error != NULL) {
1234 ERR("Fail to get properties (Error: %s)", error->message);
1235 g_clear_error(&error);
1237 ERR("Fail to get properties");
1238 g_object_unref(properties_proxy);
1239 return BT_STATUS_FAIL;
1242 g_variant_get(result, "(a{sv})", &property_iter);
1244 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1245 if (!g_strcmp0(key, "UUID")) {
1246 desc_uuid_str = g_variant_get_string(value, &len);
1247 DBG("desc UUID [%s]", desc_uuid_str);
1248 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1253 g_variant_iter_free(property_iter);
1254 g_variant_unref(result);
1255 g_object_unref(properties_proxy);
1257 return BT_STATUS_SUCCESS;
1260 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1261 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1263 struct hal_ev_gatt_client_desc_search_result ev;
1266 ERR("gatt client callback not registered");
1270 DBG("sending gatt client search desc result event conn_id[%d] status[%d]", conn_id, status);
1272 memset(&ev, 0, sizeof(ev));
1273 ev.conn_id = conn_id;
1274 ev.inst_id = svc_id->id.inst_id;
1275 ev.is_primary = svc_id->is_primary;
1278 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1279 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1281 if (status == BT_STATUS_SUCCESS) {
1282 DBG("building desc uuid");
1283 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1286 DBG("sending the desc search event");
1288 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1291 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1292 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1294 hal_gattc_server_info_t * conn_info = NULL;
1295 hal_gattc_service_t *gattc_service = NULL;
1298 hal_gattc_char_t *gattc_char = NULL;
1299 hal_gattc_desc_t *gattc_desc = NULL;
1300 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1301 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1302 int status = BT_STATUS_FAIL;
1304 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1305 if (NULL == conn_info) {
1306 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1307 return BT_STATUS_FAIL;
1311 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1312 if (NULL == gattc_service) {
1313 ERR("Failed to get the gatt service");
1314 return BT_STATUS_FAIL;
1317 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1318 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1320 /* find characteristics */
1321 /* a service can have two char with same uuid */
1322 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1323 gattc_char = (hal_gattc_char_t*)l->data;
1324 if (gattc_char == NULL)
1327 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1328 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1329 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1331 /* get descriptor uuid */
1332 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1333 gattc_desc = (hal_gattc_desc_t *)m->data;
1334 if (gattc_desc == NULL)
1337 status = _hal_gattc_get_descriptor_info(gattc_desc);
1340 if (BT_STATUS_SUCCESS == status) {
1341 DBG("Sending the success descriptor event");
1342 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1343 char_id, &gattc_desc->desc_uuid);
1349 DBG("sending final event");
1351 status = BT_STATUS_FAIL;
1352 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1354 browse_service_char(conn_id);
1355 /* retrive uuid for characteristic and object path for descriptor */
1357 return BT_STATUS_SUCCESS;
1361 * Enumerate descriptors for a given characteristic.
1362 * Set start_descr_id to NULL to get the first descriptor.
1364 bt_status_t btif_gattc_get_descriptor(int conn_id,
1365 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1366 btgatt_gatt_id_t *start_descr_id)
1369 CHECK_BTGATT_INIT();
1371 if (start_descr_id == NULL) {
1372 DBG("Get all the descriptors");
1373 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1375 DBG("TBD Get specific descriptor");
1376 return BT_STATUS_UNSUPPORTED;
1380 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1382 struct hal_ev_gatt_client_read_data ev;
1385 ERR("gatt client callback not registered");
1389 DBG("sending gatt client charac read conn_id[%d] status[%d]", resp_data->conn_id, result);
1391 memset(&ev, 0, sizeof(ev));
1392 ev.conn_id = resp_data->conn_id;
1393 ev.inst_id = resp_data->srvc_id.id.inst_id;
1394 ev.is_primary = resp_data->srvc_id.is_primary;
1397 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1398 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1402 DBG("building the char read value [%d]", len);
1403 memcpy(ev.value, value, len);
1406 DBG("sending the gatt client read charac event");
1408 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1411 static void __hal_internal_read_char_cb(GObject *source_object,
1412 GAsyncResult *res, gpointer user_data)
1414 GError *error = NULL;
1415 GDBusConnection *system_gconn = NULL;
1418 GByteArray *gp_byte_array = NULL;
1420 hal_gatt_resp_data_t *resp_data = user_data;
1421 int result = BT_STATUS_SUCCESS;
1425 system_gconn = _bt_hal_get_system_gconn();
1426 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1429 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1432 result = BT_STATUS_FAIL;
1433 __hal_send_char_read_event(resp_data, result, NULL, 0);
1434 g_clear_error(&error);
1439 gp_byte_array = g_byte_array_new();
1440 g_variant_get(value, "(ay)", &iter);
1442 while (g_variant_iter_loop(iter, "y", &g_byte))
1443 g_byte_array_append(gp_byte_array, &g_byte, 1);
1447 for (i = 0; i < gp_byte_array->len; i++)
1448 DBG("%02x", gp_byte_array->data[i]);
1452 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1456 g_byte_array_free(gp_byte_array, TRUE);
1457 g_variant_iter_free(iter);
1458 g_variant_unref(value);
1464 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1465 btgatt_gatt_id_t *char_id, int auth_req)
1467 GDBusConnection *g_conn;
1468 hal_gatt_resp_data_t *resp_data;
1469 hal_gattc_service_t *gattc_service = NULL;
1470 GVariantBuilder *builder = NULL;
1472 hal_gattc_server_info_t * conn_info = NULL;
1473 hal_gattc_char_t *gattc_char = NULL;
1474 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1475 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1476 char* char_handle = NULL;
1478 /* get the connection info */
1479 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1480 if (NULL == conn_info) {
1481 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1482 return BT_STATUS_FAIL;
1486 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1487 if (NULL == gattc_service) {
1488 ERR("Failed to get the gatt service");
1489 return BT_STATUS_FAIL;
1492 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1493 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1495 /* find characteristic */
1496 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1497 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1498 if (NULL == gattc_char) {
1499 ERR("Failed to get the gatt char");
1500 return BT_STATUS_FAIL;
1503 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1504 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1506 g_conn = _bt_hal_get_system_gconn();
1507 if (NULL == g_conn) {
1508 ERR("_bt_gdbus_get_system_gconn returned NULL");
1509 return BT_STATUS_FAIL;
1512 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1513 resp_data->conn_id = conn_id;
1514 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1515 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1517 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1520 g_variant_builder_add(builder, "{sv}", "offset",
1521 g_variant_new("q", offset));
1523 char_handle = gattc_char->chr_path;
1525 DBG("calling char read value");
1527 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1528 "ReadValue", g_variant_new("(a{sv})", builder),
1529 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1530 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1531 (gpointer)resp_data);
1532 g_variant_builder_unref(builder);
1534 return BT_STATUS_SUCCESS;
1537 /** Read a characteristic on a remote device */
1538 bt_status_t btif_read_characteristic(int conn_id,
1539 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1542 CHECK_BTGATT_INIT();
1545 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1548 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1550 struct hal_ev_gatt_client_write_result ev;
1553 ERR("gatt client callback not registered");
1557 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
1559 memset(&ev, 0, sizeof(ev));
1560 ev.conn_id = resp_data->conn_id;
1561 ev.inst_id = resp_data->srvc_id.id.inst_id;
1562 ev.is_primary = resp_data->srvc_id.is_primary;
1565 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1566 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1568 DBG("sending the gatt client write charac event");
1570 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1573 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1574 GAsyncResult *res, gpointer user_data)
1576 GError *error = NULL;
1577 GDBusConnection *system_gconn = NULL;
1579 hal_gatt_resp_data_t *resp_data = user_data;
1580 int result = BT_STATUS_SUCCESS;
1584 system_gconn = _bt_hal_get_system_gconn();
1585 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1588 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1590 result = BT_STATUS_FAIL;
1592 __hal_send_char_write_event(resp_data, result);
1593 g_clear_error(&error);
1598 //send write value event
1599 __hal_send_char_write_event(resp_data, result);
1602 g_variant_unref(value);
1607 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1610 case HAL_GATT_WRITE_TYPE_WRITE:
1611 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1613 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1614 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1617 ERR("Unknow write type : %d", type);
1618 return BT_STATUS_FAIL;
1621 return BT_STATUS_SUCCESS;
1625 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1627 GDBusConnection *conn;
1628 GVariantBuilder *builder = NULL;
1634 GUnixFDList *fd_list = NULL;
1636 conn = _bt_hal_get_system_gconn();
1638 ERR("_bt_gdbus_get_system_gconn returned NULL");
1639 return BT_STATUS_FAIL;
1642 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1643 //val = g_variant_new("ay", builder1);
1645 g_variant_builder_add(builder, "{sv}", "offset",
1646 g_variant_new("q", offset));
1648 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1649 "AcquireWrite", g_variant_new("(a{sv})", builder),
1650 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1651 NULL, &fd_list, NULL, &err);
1653 g_dbus_error_strip_remote_error(err);
1654 ERR("Error: %s", err->message);
1656 g_variant_builder_unref(builder);
1657 return BT_STATUS_FAIL;
1660 g_variant_get(value, "(hq)", &idx, &att_mtu);
1661 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1663 INFO("FD is %d index is %d mtu is %d", *fd, idx, att_mtu);
1666 g_object_unref(fd_list);
1667 g_variant_unref(value);
1668 g_variant_builder_unref(builder);
1670 return BT_STATUS_SUCCESS;
1673 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1675 GDBusConnection *conn;
1676 GVariantBuilder *builder = NULL;
1680 gint32 idx, notify_fd;
1682 GUnixFDList *fd_list = NULL;
1684 conn = _bt_hal_get_system_gconn();
1687 ERR("_bt_gdbus_get_system_gconn returned NULL");
1688 return BT_STATUS_FAIL;
1692 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1695 g_variant_builder_add(builder, "{sv}", "offset",
1696 g_variant_new("q", offset));
1698 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1699 "AcquireNotify", g_variant_new("(a{sv})", builder),
1700 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1701 NULL, &fd_list, NULL, &err);
1703 g_dbus_error_strip_remote_error(err);
1704 ERR("Error: %s", err->message);
1706 g_variant_builder_unref(builder);
1707 return BT_STATUS_FAIL;
1710 g_variant_get(value, "(hq)", &idx, &att_mtu);
1711 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1714 INFO("Acquired characteristic Notify fd %d, mtu %d", notify_fd, *mtu);
1718 g_object_unref(fd_list);
1719 g_variant_unref(value);
1720 g_variant_builder_unref(builder);
1722 return BT_STATUS_SUCCESS;
1726 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1727 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1729 GVariant *val, *options;
1730 GVariantBuilder *builder1;
1731 GVariantBuilder *builder2;
1732 GDBusConnection *g_conn;
1735 hal_gatt_resp_data_t *resp_data;
1736 hal_gattc_service_t *gattc_service = NULL;
1737 hal_gattc_server_info_t * conn_info = NULL;
1738 hal_gattc_char_t *gattc_char = NULL;
1739 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1740 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1741 char* char_handle = NULL;
1742 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1743 int ret = BT_STATUS_SUCCESS;
1747 ret = __hal_get_write_prop(write_type, &write_prop);
1748 if (BT_STATUS_FAIL == ret) {
1749 DBG("received invalid write type:[%d] ", write_type);
1750 return BT_STATUS_FAIL;
1753 /* get the connection info */
1754 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1755 if (NULL == conn_info) {
1756 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1757 return BT_STATUS_FAIL;
1761 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1762 if (NULL == gattc_service) {
1763 ERR("Failed to get the gatt service");
1764 return BT_STATUS_FAIL;
1767 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1768 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1770 /* find characteristic */
1771 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1772 if (NULL == gattc_char) {
1773 ERR("Failed to get the gatt char");
1774 return BT_STATUS_FAIL;
1777 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1778 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1780 g_conn = _bt_hal_get_system_gconn();
1781 if (NULL == g_conn) {
1782 ERR("_bt_gdbus_get_system_gconn returned NULL");
1783 return BT_STATUS_FAIL;
1786 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1787 resp_data->conn_id = conn_id;
1788 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1789 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1791 char_handle = gattc_char->chr_path;
1793 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1795 for (i = 0; i < length; i++)
1796 g_variant_builder_add(builder1, "y", value[i]);
1798 val = g_variant_new("ay", builder1);
1800 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1802 g_variant_builder_add(builder2, "{sv}", "offset",
1803 g_variant_new_uint16(offset));
1805 options = g_variant_new("a{sv}", builder2);
1807 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1809 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1811 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1812 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1813 (gpointer)resp_data);
1815 g_variant_builder_unref(builder1);
1816 g_variant_builder_unref(builder2);
1818 return BT_STATUS_SUCCESS;
1821 bt_status_t btif_get_acquire_write_fd(int conn_id,
1822 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1823 int auth_req, int *fd, int*mtu)
1825 CHECK_BTGATT_INIT();
1827 hal_gattc_service_t *gattc_service = NULL;
1828 hal_gattc_server_info_t * conn_info = NULL;
1829 hal_gattc_char_t *gattc_char = NULL;
1830 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1832 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1833 int ret = BT_STATUS_SUCCESS;
1836 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1838 /* get the connection info */
1839 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1840 if (NULL == conn_info) {
1841 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1842 return BT_STATUS_FAIL;
1846 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1847 if (NULL == gattc_service) {
1848 ERR("Failed to get the gatt service");
1849 return BT_STATUS_FAIL;
1852 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1853 if (NULL == gattc_char) {
1854 ERR("Failed to get the gatt char");
1855 return BT_STATUS_FAIL;
1858 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1859 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1861 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1862 if (ret != BT_STATUS_SUCCESS)
1865 INFO("Characterstics FD erite characterstics fd is %d", *fd);
1869 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1870 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1872 CHECK_BTGATT_INIT();
1874 hal_gattc_service_t *gattc_service = NULL;
1875 hal_gattc_server_info_t * conn_info = NULL;
1876 hal_gattc_char_t *gattc_char = NULL;
1877 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1879 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1880 int ret = BT_STATUS_SUCCESS;
1883 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1885 /* get the connection info */
1886 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1887 if (NULL == conn_info) {
1888 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1889 return BT_STATUS_FAIL;
1893 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1894 if (NULL == gattc_service) {
1895 ERR("Failed to get the gatt service");
1896 return BT_STATUS_FAIL;
1899 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1900 if (NULL == gattc_char) {
1901 ERR("Failed to get the gatt char");
1902 return BT_STATUS_FAIL;
1905 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1906 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1908 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1909 if (ret != BT_STATUS_SUCCESS)
1912 INFO("Characterstics FD write characterstics fd is %d", *fd);
1918 /** Write a remote characteristic */
1919 bt_status_t btif_write_characteristic(int conn_id,
1920 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1921 int write_type, int len, int auth_req,
1924 CHECK_BTGATT_INIT();
1928 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1929 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1930 len, auth_req, p_value);
1933 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1935 struct hal_ev_gatt_client_read_data ev;
1938 ERR("gatt client callback not registered");
1942 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1944 memset(&ev, 0, sizeof(ev));
1945 ev.conn_id = resp_data->conn_id;
1946 ev.inst_id = resp_data->srvc_id.id.inst_id;
1947 ev.is_primary = resp_data->srvc_id.is_primary;
1950 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1951 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1952 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1956 DBG("building the desc read value [%d]", len);
1957 memcpy(ev.value, value, len);
1960 DBG("sending the gatt client read descriptor event");
1962 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1965 static void __hal_internal_read_desc_cb(GObject *source_object,
1966 GAsyncResult *res, gpointer user_data)
1968 GError *error = NULL;
1969 GDBusConnection *system_gconn = NULL;
1972 GByteArray *gp_byte_array = NULL;
1974 hal_gatt_resp_data_t *resp_data = user_data;
1975 int result = BT_STATUS_SUCCESS;
1980 system_gconn = _bt_hal_get_system_gconn();
1981 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1984 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1987 result = BT_STATUS_FAIL;
1988 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1989 g_clear_error(&error);
1994 gp_byte_array = g_byte_array_new();
1995 g_variant_get(value, "(ay)", &iter);
1997 while (g_variant_iter_loop(iter, "y", &g_byte))
1998 g_byte_array_append(gp_byte_array, &g_byte, 1);
2002 for (i = 0; i < gp_byte_array->len; i++)
2003 DBG("%02x", gp_byte_array->data[i]);
2006 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2010 g_byte_array_free(gp_byte_array, TRUE);
2011 g_variant_iter_free(iter);
2012 g_variant_unref(value);
2017 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2018 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2020 GDBusConnection *g_conn;
2021 hal_gatt_resp_data_t *resp_data;
2022 hal_gattc_service_t *gattc_service = NULL;
2023 GVariantBuilder *builder = NULL;
2025 hal_gattc_server_info_t * conn_info = NULL;
2026 hal_gattc_char_t *gattc_char = NULL;
2027 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2028 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2029 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2030 char* desc_handle = NULL;
2033 hal_gattc_desc_t *gattc_desc = NULL;
2037 /* get the connection info */
2038 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2039 if (NULL == conn_info) {
2040 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
2041 return BT_STATUS_FAIL;
2045 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2046 if (NULL == gattc_service) {
2047 ERR("Failed to get the gatt service");
2048 return BT_STATUS_FAIL;
2051 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2052 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2054 /* find characteristic */
2055 /* service can have two char with same uuid */
2056 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2057 gattc_char = (hal_gattc_char_t*)l->data;
2058 if (gattc_char == NULL)
2061 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2062 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2063 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2065 /* find descriptor */
2066 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2068 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2069 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2075 if (NULL == gattc_desc) {
2076 ERR("Failed to get the gatt desc");
2077 return BT_STATUS_FAIL;
2080 g_conn = _bt_hal_get_system_gconn();
2081 if (NULL == g_conn) {
2082 ERR("_bt_gdbus_get_system_gconn returned NULL");
2083 return BT_STATUS_FAIL;
2086 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2087 resp_data->conn_id = conn_id;
2088 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2089 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2090 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2092 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2095 g_variant_builder_add(builder, "{sv}", "offset",
2096 g_variant_new("q", offset));
2098 desc_handle = gattc_desc->desc_path;
2100 DBG("calling desc read value");
2102 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2103 "ReadValue", g_variant_new("(a{sv})", builder),
2104 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2105 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2106 (gpointer)resp_data);
2107 g_variant_builder_unref(builder);
2109 return BT_STATUS_SUCCESS;
2112 /** Read the descriptor for a given characteristic */
2113 bt_status_t btif_read_descriptor(int conn_id,
2114 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2115 btgatt_gatt_id_t *descr_id, int auth_req)
2117 CHECK_BTGATT_INIT();
2119 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2122 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2124 struct hal_ev_gatt_client_write_result ev;
2127 ERR("gatt client callback not registered");
2131 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
2133 memset(&ev, 0, sizeof(ev));
2134 ev.conn_id = resp_data->conn_id;
2135 ev.inst_id = resp_data->srvc_id.id.inst_id;
2136 ev.is_primary = resp_data->srvc_id.is_primary;
2139 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2140 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2141 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2143 DBG("sending the gatt client write charac event");
2145 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2148 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2149 GAsyncResult *res, gpointer user_data)
2151 GError *error = NULL;
2152 GDBusConnection *system_gconn = NULL;
2154 hal_gatt_resp_data_t *resp_data = user_data;
2155 int result = BT_STATUS_SUCCESS;
2159 system_gconn = _bt_hal_get_system_gconn();
2160 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2163 ERR("write descriptor dbus failed Error: [%s]", error->message);
2166 result = BT_STATUS_FAIL;
2167 __hal_send_desc_write_event(resp_data, result);
2168 g_clear_error(&error);
2173 //send write value event
2174 __hal_send_desc_write_event(resp_data, result);
2177 g_variant_unref(value);
2182 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2183 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2184 int write_type, int length, int auth_req, char* value)
2186 GVariant *val, *options;
2187 GVariantBuilder *builder1;
2188 GVariantBuilder *builder2;
2189 GDBusConnection *g_conn;
2192 hal_gatt_resp_data_t *resp_data;
2193 hal_gattc_service_t *gattc_service = NULL;
2194 hal_gattc_server_info_t * conn_info = NULL;
2195 hal_gattc_char_t *gattc_char = NULL;
2196 hal_gattc_desc_t *gattc_desc = NULL;
2197 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2198 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2199 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2200 char* desc_handle = NULL;
2201 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2202 int ret = BT_STATUS_SUCCESS;
2207 ret = __hal_get_write_prop(write_type, &write_prop);
2208 if (BT_STATUS_FAIL == ret) {
2209 ERR("received invalid write type:[%d] ", write_type);
2210 return BT_STATUS_FAIL;
2213 /* get the connection info */
2214 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2215 if (NULL == conn_info) {
2216 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
2217 return BT_STATUS_FAIL;
2221 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2222 if (NULL == gattc_service) {
2223 ERR("Failed to get the gatt service");
2224 return BT_STATUS_FAIL;
2227 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2228 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2230 /* find characteristic */
2231 /* service can have two char with same uuid */
2232 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2233 gattc_char = (hal_gattc_char_t*)l->data;
2234 if (gattc_char == NULL)
2237 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2238 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2239 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2241 /* find descriptor */
2242 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2244 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2245 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2251 if (NULL == gattc_desc) {
2252 ERR("Failed to get the gatt desc");
2253 return BT_STATUS_FAIL;
2256 g_conn = _bt_hal_get_system_gconn();
2257 if (NULL == g_conn) {
2258 ERR("_bt_gdbus_get_system_gconn returned NULL");
2259 return BT_STATUS_FAIL;
2262 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2263 resp_data->conn_id = conn_id;
2264 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2265 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2266 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2268 desc_handle = gattc_desc->desc_path;
2270 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2272 for (i = 0; i < length; i++)
2273 g_variant_builder_add(builder1, "y", value[i]);
2275 val = g_variant_new("ay", builder1);
2277 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2279 g_variant_builder_add(builder2, "{sv}", "offset",
2280 g_variant_new_uint16(offset));
2282 options = g_variant_new("a{sv}", builder2);
2284 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2286 g_variant_new("(@ay@a{sv})", val, options),
2288 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2289 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2290 (gpointer)resp_data);
2292 g_variant_builder_unref(builder1);
2293 g_variant_builder_unref(builder2);
2295 return BT_STATUS_SUCCESS;
2298 /** Write a remote descriptor for a given characteristic */
2299 bt_status_t btif_write_descriptor(int conn_id,
2300 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2301 btgatt_gatt_id_t *descr_id, int write_type, int len,
2302 int auth_req, char* p_value)
2304 CHECK_BTGATT_INIT();
2306 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2307 len, auth_req, p_value);
2310 /** Execute a prepared write operation */
2311 bt_status_t execute_write(int conn_id, int execute)
2313 CHECK_BTGATT_INIT();
2314 return BT_STATUS_UNSUPPORTED;
2317 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2319 struct hal_ev_gatt_client_watch_notification ev;
2320 hal_gatt_resp_data_t *resp_data = user_data;
2322 DBG("sending the watch register notification event");
2323 /* send the event */
2324 memset(&ev, 0, sizeof(ev));
2325 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2327 ev.status = resp_data->result;
2329 ev.is_primary = resp_data->srvc_id.is_primary;
2330 ev.inst_id = resp_data->srvc_id.id.inst_id;
2332 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2333 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2336 ERR("GATT Callback not registered");
2338 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2345 static bt_status_t _hal_register_for_notification(int client_if,
2346 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2347 btgatt_gatt_id_t *char_id)
2349 int result = BT_STATUS_SUCCESS;
2350 GError *error = NULL;
2351 GDBusConnection *g_conn;
2352 hal_gattc_client_info_t *gattc_client = NULL;
2353 hal_gattc_server_info_t * conn_info = NULL;
2354 hal_gattc_service_t *gattc_service = NULL;
2355 hal_gattc_char_t *gattc_char = NULL;
2356 char* char_handle = NULL;
2357 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2358 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2359 hal_gatt_resp_data_t *resp_data;
2363 gattc_client = __bt_find_gatt_client_info(bd_addr);
2364 if (gattc_client == NULL) {
2365 ERR("failed to get the gatt client info");
2366 return BT_STATUS_FAIL;
2369 if (gattc_client->client_if != client_if) {
2370 ERR("could not find the gatt client for client id[%d]", client_if);
2371 return BT_STATUS_FAIL;
2374 /* get the connection info */
2375 conn_info = __bt_find_gatt_conn_info(bd_addr);
2376 if (NULL == conn_info) {
2377 ERR("Failed to get the conn_info");
2378 return BT_STATUS_FAIL;
2381 if (conn_info->inst_id != gattc_client->inst_id) {
2382 ERR("could not fild the conn_info");
2383 return BT_STATUS_FAIL;
2387 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2388 if (NULL == gattc_service) {
2389 ERR("Failed to get the gatt service");
2390 return BT_STATUS_FAIL;
2393 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2394 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2397 /* find characteristic */
2398 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2399 if (NULL == gattc_char) {
2400 ERR("Failed to get the gatt char");
2401 return BT_STATUS_FAIL;
2404 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2405 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2407 char_handle = gattc_char->chr_path;
2409 g_conn = _bt_hal_get_system_gconn();
2410 if (g_conn == NULL) {
2412 return BT_STATUS_FAIL;
2415 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2417 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2419 g_dbus_connection_call_sync(g_conn,
2422 BT_HAL_GATT_CHAR_INTERFACE,
2426 G_DBUS_CALL_FLAGS_NONE,
2427 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2430 g_dbus_error_strip_remote_error(error);
2431 ERR("### StartNotify Failed: %s", error->message);
2432 if (g_strrstr(error->message, "Already notifying"))
2433 result = BT_STATUS_SUCCESS;
2434 else if (g_strrstr(error->message, "In Progress"))
2435 result = BT_STATUS_BUSY;
2436 else if (g_strrstr(error->message, "Operation is not supported"))
2437 result = BT_STATUS_UNSUPPORTED;
2438 /*failed because of either Insufficient Authorization or Write Not Permitted */
2439 else if (g_strrstr(error->message, "Write not permitted") ||
2440 g_strrstr(error->message, "Operation Not Authorized"))
2441 result = BT_STATUS_AUTH_FAILURE;
2442 /* failed because of either Insufficient Authentication,
2443 Insufficient Encryption Key Size, or Insufficient Encryption. */
2444 else if (g_strrstr(error->message, "Not paired"))
2445 result = BT_STATUS_NOT_READY;
2447 result = BT_STATUS_FAIL;
2449 g_clear_error(&error);
2452 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2453 resp_data->result = result;
2454 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2455 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2457 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2461 return BT_STATUS_SUCCESS;
2465 * Register to receive notifications or indications for a given
2468 bt_status_t btif_register_for_notification(int client_if,
2469 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2470 btgatt_gatt_id_t *char_id)
2472 CHECK_BTGATT_INIT();
2474 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2477 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2479 struct hal_ev_gatt_client_watch_notification ev;
2480 hal_gatt_resp_data_t *resp_data = user_data;
2482 DBG("sending the watch deregister notification event");
2483 /* send the event */
2484 memset(&ev, 0, sizeof(ev));
2485 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2487 ev.status = resp_data->result;
2489 ev.is_primary = resp_data->srvc_id.is_primary;
2490 ev.inst_id = resp_data->srvc_id.id.inst_id;
2492 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2493 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2496 ERR("GATT Callback not registered");
2498 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2505 static bt_status_t _hal_deregister_for_notification(int client_if,
2506 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2507 btgatt_gatt_id_t *char_id)
2509 int result = BT_STATUS_SUCCESS;
2510 GError *error = NULL;
2511 GDBusConnection *g_conn;
2512 hal_gattc_client_info_t *gattc_client = NULL;
2513 hal_gattc_server_info_t * conn_info = NULL;
2514 hal_gattc_service_t *gattc_service = NULL;
2515 hal_gattc_char_t *gattc_char = NULL;
2516 char* char_handle = NULL;
2517 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2518 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2519 hal_gatt_resp_data_t *resp_data;
2523 gattc_client = __bt_find_gatt_client_info(bd_addr);
2524 if (gattc_client == NULL) {
2525 ERR("failed to get the gatt client info");
2526 return BT_STATUS_FAIL;
2529 if (gattc_client->client_if != client_if) {
2530 ERR("could not find the gatt client for client id[%d]", client_if);
2531 return BT_STATUS_FAIL;
2534 /* get the connection info */
2535 conn_info = __bt_find_gatt_conn_info(bd_addr);
2536 if (NULL == conn_info) {
2537 ERR("Failed to get the conn_info");
2538 return BT_STATUS_FAIL;
2541 if (conn_info->inst_id != gattc_client->inst_id) {
2542 ERR("could not fild the conn_info");
2543 return BT_STATUS_FAIL;
2547 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2548 if (NULL == gattc_service) {
2549 ERR("Failed to get the gatt service");
2550 return BT_STATUS_FAIL;
2553 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2554 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2557 /* find characteristic */
2558 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2559 if (NULL == gattc_char) {
2560 ERR("Failed to get the gatt char");
2561 return BT_STATUS_FAIL;
2564 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2565 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2567 char_handle = gattc_char->chr_path;
2569 g_conn = _bt_hal_get_system_gconn();
2570 if (g_conn == NULL) {
2572 return BT_STATUS_FAIL;
2575 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2577 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2578 g_dbus_connection_call_sync(g_conn,
2581 BT_HAL_GATT_CHAR_INTERFACE,
2585 G_DBUS_CALL_FLAGS_NONE,
2586 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2589 ERR("### StopNotify Failed: %s", error->message);
2590 g_clear_error(&error);
2591 result = BT_STATUS_FAIL;
2594 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2595 resp_data->result = result;
2596 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2597 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2599 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2603 return BT_STATUS_SUCCESS;
2605 /** Deregister a previous request for notifications/indications */
2606 bt_status_t btif_deregister_for_notification(int client_if,
2607 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2608 btgatt_gatt_id_t *char_id)
2610 CHECK_BTGATT_INIT();
2611 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2614 /** Request RSSI for a given remote device */
2615 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2617 CHECK_BTGATT_INIT();
2618 return BT_STATUS_UNSUPPORTED;
2621 /** OTA firmware download */
2622 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2624 CHECK_BTGATT_INIT();
2625 return BT_STATUS_UNSUPPORTED;
2628 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2629 int get_device_type(const bt_bdaddr_t *bd_addr)
2631 CHECK_BTGATT_INIT();
2632 return BT_STATUS_UNSUPPORTED;
2635 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2636 int min_int, int max_int, int latency, int timeout)
2638 gchar *device_path = NULL;
2639 GError *error = NULL;
2640 GDBusProxy *device_proxy = NULL;
2641 GDBusConnection *conn;
2643 int ret = BT_STATUS_SUCCESS;
2644 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2646 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2647 min_int, max_int, latency, timeout);
2649 conn = _bt_hal_get_system_gconn();
2652 return BT_STATUS_FAIL;
2655 _bt_hal_convert_addr_type_to_string(device_address,
2656 (unsigned char *)bd_addr->address);
2657 device_path = _bt_hal_get_device_object_path(device_address);
2659 if (device_path == NULL) {
2660 ERR("device_path NULL : [%s]", device_address);
2661 return BT_STATUS_FAIL;
2664 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2665 NULL, BT_HAL_BLUEZ_NAME,
2666 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2668 g_free(device_path);
2669 if (NULL == device_proxy) {
2670 ERR("device_proxy returned NULL");
2671 return BT_STATUS_FAIL;
2674 INFO("Request LeConnUpdate");
2675 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2676 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2677 G_DBUS_CALL_FLAGS_NONE,
2682 g_object_unref(device_proxy);
2683 if (reply == NULL) {
2685 ERR("Error %s[%s]", error->message, device_address);
2686 if (g_strrstr(error->message, "In Progress"))
2687 ret = BT_STATUS_SUCCESS;
2689 ret = BT_STATUS_FAIL;
2690 g_error_free(error);
2694 g_variant_unref(reply);
2696 DBG("LE Connection parameter Updated");
2700 /** Request a connection parameter update */
2701 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2703 CHECK_BTGATT_INIT();
2707 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2710 /** Test mode interface */
2711 bt_status_t test_command(int command, btgatt_test_params_t* params)
2713 CHECK_BTGATT_INIT();
2714 return BT_STATUS_UNSUPPORTED;
2717 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2720 GError *g_error = NULL;
2721 GVariant *reply = NULL;
2722 int result = BT_STATUS_SUCCESS;
2723 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2724 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2728 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2729 g_object_unref(proxy);
2730 if (reply == NULL) {
2731 ERR("Connect LE Dbus Call Error");
2733 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2734 g_clear_error(&g_error);
2736 result = BT_STATUS_FAIL;
2738 g_variant_unref(reply);
2740 memset(&ev, 0, sizeof(ev));
2742 ev.mtu = conn_mtu->mtu;
2743 ev.conn_id = conn_mtu->conn_id;
2746 ERR("gatt client callback not registered");
2748 DBG("sending gatt client MTU exchange completed event");
2749 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2756 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2758 gchar *device_path = NULL;
2759 GDBusProxy *device_proxy = NULL;
2760 GDBusConnection *conn;
2761 hal_gattc_client_info_t *gattc_client = NULL;
2762 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2763 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2765 conn = _bt_hal_get_system_gconn();
2768 return BT_STATUS_FAIL;
2771 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2772 if (gattc_client == NULL) {
2773 INFO("GATT client conn info not found");
2774 return BT_STATUS_FAIL;
2777 _bt_hal_convert_addr_type_to_string(device_address,
2778 (unsigned char *)gattc_client->bd_addr.address);
2780 device_path = _bt_hal_get_device_object_path(device_address);
2781 if (device_path == NULL) {
2782 ERR("device_path NULL : [%s]", device_address);
2783 return BT_STATUS_FAIL;
2786 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2787 NULL, BT_HAL_BLUEZ_NAME,
2788 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2790 g_free(device_path);
2791 if (NULL == device_proxy) {
2792 ERR("device_proxy returned NULL");
2793 return BT_STATUS_FAIL;
2796 conn_mtu->conn_id = conn_id;
2797 conn_mtu->mtu = mtu;
2799 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2800 g_variant_new("(q)", mtu),
2801 G_DBUS_CALL_FLAGS_NONE,
2802 BT_HAL_MAX_DBUS_TIMEOUT,
2804 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2807 return BT_STATUS_SUCCESS;
2810 /** MTU Exchange request from client */
2811 static bt_status_t configure_mtu(int conn_id, int mtu)
2813 CHECK_BTGATT_INIT();
2815 return __hal_configure_mtu(conn_id, mtu);
2818 /** Setup scan filter params */
2819 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2820 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2821 int rssi_low_thres, int dely_mode, int found_timeout,
2822 int lost_timeout, int found_timeout_cnt)
2825 GError *error = NULL;
2826 GVariant *ret, *param;
2827 CHECK_BTGATT_INIT();
2829 proxy = _bt_hal_get_adapter_proxy();
2832 return BT_STATUS_FAIL;
2834 param = g_variant_new("(iiiiiiiiiiii)",
2847 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2848 param, G_DBUS_CALL_FLAGS_NONE,
2852 ERR("scan_filter_param_setup Fail: %s", error->message);
2853 g_clear_error(&error);
2854 return BT_STATUS_FAIL;
2858 g_variant_unref(ret);
2860 return BT_STATUS_SUCCESS;
2863 /** Configure a scan filter condition */
2864 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2865 int filt_index, int company_id,
2866 int company_id_mask, const bt_uuid_t *p_uuid,
2867 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2868 char addr_type, int data_len, char* p_data, int mask_len,
2872 GError *error = NULL;
2873 GVariant *ret, *param;
2874 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2875 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2876 GArray *arr_uuid = NULL;
2877 GArray *arr_uuid_mask = NULL;
2878 GArray *arr_data = NULL;
2879 GArray *arr_data_mask = NULL;
2880 CHECK_BTGATT_INIT();
2882 proxy = _bt_hal_get_adapter_proxy();
2885 return BT_STATUS_FAIL;
2887 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2889 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2891 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2893 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2895 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2896 NULL, 0, TRUE, NULL, NULL);
2897 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2898 NULL, 0, TRUE, NULL, NULL);
2899 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2900 NULL, 0, TRUE, NULL, NULL);
2901 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2902 NULL, 0, TRUE, NULL, NULL);
2904 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2905 client_if, // client_if
2906 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2907 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2908 filt_index, // filter_index
2909 company_id, // company_id
2910 company_id_mask, // company_id_mask
2911 arr_uuid_param, // p_uuid
2912 arr_uuid_mask_param, // p_uuid_mask
2914 addr_type, // address_type
2915 arr_data_param, // p_data
2916 arr_data_mask_param); // p_mask
2918 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2919 param, G_DBUS_CALL_FLAGS_NONE,
2923 ERR("scan_filter_add_remove Fail: %s", error->message);
2924 g_clear_error(&error);
2925 return BT_STATUS_FAIL;
2929 g_variant_unref(ret);
2931 return BT_STATUS_SUCCESS;
2934 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2936 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2937 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2938 NULL, 0, TRUE, NULL, NULL);
2939 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2940 NULL, 0, TRUE, NULL, NULL);
2941 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2942 NULL, 0, TRUE, NULL, NULL);
2943 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2944 NULL, 0, TRUE, NULL, NULL);
2946 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2947 client_if, // client_if
2948 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2949 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2950 filt_index, // filter_index
2951 company_id, // company_id
2952 company_id_mask, // company_id_mask
2953 arr_uuid_param, // p_uuid
2954 arr_uuid_mask_param, // p_uuid_mask
2956 addr_type, // address_type
2957 arr_data_param, // p_data
2958 arr_data_mask_param);
2960 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2961 param, G_DBUS_CALL_FLAGS_NONE,
2965 ERR("scan_filter_add_remove Fail: %s", error->message);
2966 g_clear_error(&error);
2967 return BT_STATUS_FAIL;
2971 g_variant_unref(ret);
2973 return BT_STATUS_SUCCESS;
2976 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2978 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2979 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2981 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2982 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2984 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2985 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2986 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2987 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2988 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2989 NULL, 0, TRUE, NULL, NULL);
2990 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2991 NULL, 0, TRUE, NULL, NULL);
2993 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2994 client_if, // client_if
2995 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2996 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
2997 filt_index, // filter_index
2998 company_id, // company_id
2999 company_id_mask, // company_id_mask
3000 arr_uuid_param, // p_uuid
3001 arr_uuid_mask_param, // p_uuid_mask
3003 addr_type, // address_type
3004 arr_data_param, // p_data
3005 arr_data_mask_param);
3007 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3008 param, G_DBUS_CALL_FLAGS_NONE,
3012 ERR("scan_filter_add_remove Fail: %s", error->message);
3013 g_clear_error(&error);
3014 return BT_STATUS_FAIL;
3018 g_variant_unref(ret);
3020 g_array_free(arr_uuid, TRUE);
3021 g_array_free(arr_uuid_mask, TRUE);
3023 return BT_STATUS_SUCCESS;
3026 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3028 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3029 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3031 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3032 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3034 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3035 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3036 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3037 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3038 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3039 NULL, 0, TRUE, NULL, NULL);
3040 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3041 NULL, 0, TRUE, NULL, NULL);
3043 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3044 client_if, // client_if
3045 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3046 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3047 filt_index, // filter_index
3048 company_id, // company_id
3049 company_id_mask, // company_id_mask
3050 arr_uuid_param, // p_uuid
3051 arr_uuid_mask_param, // p_uuid_mask
3053 addr_type, // address_type
3054 arr_data_param, // p_data
3055 arr_data_mask_param);
3057 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3058 G_DBUS_CALL_FLAGS_NONE,
3062 ERR("scan_filter_add_remove Fail: %s", error->message);
3063 g_clear_error(&error);
3064 return BT_STATUS_FAIL;
3068 g_variant_unref(ret);
3070 g_array_free(arr_uuid, TRUE);
3071 g_array_free(arr_uuid_mask, TRUE);
3073 return BT_STATUS_SUCCESS;
3076 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3078 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3079 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3081 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3082 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3084 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3085 NULL, 0, TRUE, NULL, NULL);
3086 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3087 NULL, 0, TRUE, NULL, NULL);
3088 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3089 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3090 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3091 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3093 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3094 client_if, // client_if
3095 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3096 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3097 filt_index, // filter_index
3098 company_id, // company_id
3099 company_id_mask, // company_id_mask
3100 arr_uuid_param, // p_uuid
3101 arr_uuid_mask_param, // p_uuid_mask
3103 addr_type, // address_type
3104 arr_data_param, // p_data
3105 arr_data_mask_param);
3107 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3108 G_DBUS_CALL_FLAGS_NONE,
3112 ERR("scan_filter_add_remove Fail: %s", error->message);
3113 g_clear_error(&error);
3114 return BT_STATUS_FAIL;
3118 g_variant_unref(ret);
3120 g_array_free(arr_data, TRUE);
3121 g_array_free(arr_data_mask, TRUE);
3123 return BT_STATUS_SUCCESS;
3126 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3128 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3129 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3131 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3132 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3134 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3135 NULL, 0, TRUE, NULL, NULL);
3136 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3137 NULL, 0, TRUE, NULL, NULL);
3138 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3139 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3140 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3141 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3143 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3144 client_if, // client_if
3145 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3146 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3147 filt_index, // filter_index
3148 company_id, // company_id
3149 company_id_mask, // company_id_mask
3150 arr_uuid_param, // p_uuid
3151 arr_uuid_mask_param, // p_uuid_mask
3153 addr_type, // address_type
3154 arr_data_param, // p_data
3155 arr_data_mask_param);
3157 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3158 G_DBUS_CALL_FLAGS_NONE,
3162 ERR("scan_filter_add_remove Fail: %s", error->message);
3163 g_clear_error(&error);
3164 return BT_STATUS_FAIL;
3168 g_variant_unref(ret);
3170 g_array_free(arr_data, TRUE);
3171 g_array_free(arr_data_mask, TRUE);
3173 return BT_STATUS_SUCCESS;
3176 return BT_STATUS_UNSUPPORTED;
3179 /** Clear all scan filter conditions for specific filter index*/
3180 bt_status_t scan_filter_clear(int client_if, int filt_index)
3183 GError *error = NULL;
3185 CHECK_BTGATT_INIT();
3187 proxy = _bt_hal_get_adapter_proxy();
3189 return BT_STATUS_FAIL;
3191 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3192 g_variant_new("(ii)", client_if, filt_index),
3193 G_DBUS_CALL_FLAGS_NONE,
3197 ERR("scan_filter_clear Fail: %s", error->message);
3198 g_clear_error(&error);
3199 return BT_STATUS_FAIL;
3202 g_variant_unref(ret);
3203 return BT_STATUS_SUCCESS;
3206 /** Enable / disable scan filter feature*/
3207 bt_status_t scan_filter_enable(int client_if, bool enable)
3210 GError *error = NULL;
3212 CHECK_BTGATT_INIT();
3214 proxy = _bt_hal_get_adapter_proxy();
3216 return BT_STATUS_FAIL;
3218 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3219 g_variant_new("(ib)", client_if, enable),
3220 G_DBUS_CALL_FLAGS_NONE,
3224 ERR("scan_filter_enable Fail: %s", error->message);
3225 g_clear_error(&error);
3226 return BT_STATUS_FAIL;
3228 g_variant_unref(ret);
3230 return BT_STATUS_SUCCESS;
3233 /** Sets the LE scan interval and window in units of N*0.625 msec */
3235 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3239 CHECK_BTGATT_INIT();
3241 le_scan_type = scan_type;
3242 ret = _bt_hal_adapter_le_set_scan_parameters(
3243 scan_type, scan_interval, scan_window);
3247 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3249 CHECK_BTGATT_INIT();
3250 return BT_STATUS_UNSUPPORTED;
3254 /* Configure the batchscan storage */
3255 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3256 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3258 CHECK_BTGATT_INIT();
3259 return BT_STATUS_UNSUPPORTED;
3262 /* Enable batchscan */
3263 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3264 int scan_interval, int scan_window, int addr_type, int discard_rule)
3266 CHECK_BTGATT_INIT();
3267 return BT_STATUS_UNSUPPORTED;
3270 /* Disable batchscan */
3271 bt_status_t batchscan_dis_batch_scan(int client_if)
3273 CHECK_BTGATT_INIT();
3274 return BT_STATUS_UNSUPPORTED;
3277 /* Read out batchscan reports */
3278 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3280 CHECK_BTGATT_INIT();
3281 return BT_STATUS_UNSUPPORTED;
3284 const btgatt_client_interface_t btgatt_client_interface = {
3285 .register_client = btif_gattc_register_client,
3286 .unregister_client = btif_gattc_unregister_client,
3288 .connect = btif_gattc_client_connect,
3289 .disconnect = btif_gattc_client_disconnect,
3291 .search_service = btif_gattc_client_search_service,
3292 .get_included_service = get_included_service,
3293 .get_characteristic = btif_gattc_get_characteristic,
3294 .get_descriptor = btif_gattc_get_descriptor,
3295 .read_characteristic = btif_read_characteristic,
3296 .write_characteristic = btif_write_characteristic,
3297 .acquire_write = btif_get_acquire_write_fd,
3298 .acquire_notify = btif_get_acquire_notify_fd,
3299 .read_descriptor = btif_read_descriptor,
3300 .write_descriptor = btif_write_descriptor,
3301 .execute_write = execute_write,
3302 .register_for_notification = btif_register_for_notification,
3303 .deregister_for_notification = btif_deregister_for_notification,
3304 .read_remote_rssi = read_remote_rssi,
3305 .ota_fw_update = ota_fw_update,
3306 .get_device_type = get_device_type,
3307 .conn_parameter_update = btif_gattc_conn_parameter_update,
3308 .test_command = test_command,
3309 .configure_mtu = configure_mtu,
3310 .scan_filter_param_setup = scan_filter_param_setup,
3311 .scan_filter_add_remove = scan_filter_add_remove,
3312 .scan_filter_clear = scan_filter_clear,
3313 .scan_filter_enable = scan_filter_enable,
3314 .set_scan_parameters = set_scan_parameters,
3315 .batchscan_cfg_storage = batchscan_cfg_storage,
3316 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3317 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3318 .batchscan_read_reports = batchscan_read_reports,
3319 .add_connection_info = btif_gattc_add_connection_info
3322 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3327 hal_gattc_server_info_t *info = NULL;
3329 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3330 info = (hal_gattc_server_info_t*)l->data;
3334 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
3335 INFO("GATT connection found addr");
3342 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3347 hal_gattc_client_info_t *info = NULL;
3349 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3350 info = (hal_gattc_client_info_t*)l->data;
3354 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
3355 INFO("GATT client info found addr");
3362 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3365 hal_gattc_client_info_t *info = NULL;
3367 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3368 info = (hal_gattc_client_info_t*)l->data;
3372 if (info->conn_id == conn_id) {
3373 INFO("GATT client info found for conn_id [%d]", conn_id);
3380 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3383 hal_gattc_server_info_t *info = NULL;
3384 hal_gattc_client_info_t *gattc_client = NULL;
3386 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3387 if (gattc_client == NULL) {
3388 ERR("GATT client conn info not found");
3392 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3393 info = (hal_gattc_server_info_t*)l->data;
3397 if ((info->inst_id == gattc_client->inst_id) &&
3398 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3399 INFO("GATT connection found for conn_id [%d]", conn_id);
3406 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3407 gboolean auto_connect)
3409 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3410 gchar *device_path = NULL;
3411 GDBusProxy *device_proxy = NULL;
3412 GDBusConnection *conn;
3413 int ret = BT_STATUS_SUCCESS;
3414 hal_gattc_client_info_t *gattc_data;
3418 if (NULL == bd_addr) {
3419 ERR("bd_addr is NULL");
3420 return BT_STATUS_PARM_INVALID;
3423 conn = _bt_hal_get_system_gconn();
3425 ERR("_bt_gdbus_get_system_gconn returned NULL");
3426 return BT_STATUS_FAIL;
3429 _bt_hal_convert_addr_type_to_string(device_address,
3430 (unsigned char *)bd_addr->address);
3431 device_path = _bt_hal_get_device_object_path(device_address);
3432 if (device_path == NULL) {
3433 ERR("device_path NULL : [%s]", device_address);
3434 ret = BT_STATUS_FAIL;
3437 ERR("device_path:%s", device_path);
3439 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3440 NULL, BT_HAL_BLUEZ_NAME,
3441 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3442 g_free(device_path);
3443 if (NULL == device_proxy) {
3444 ERR("device_proxy returned NULL");
3445 return BT_STATUS_FAIL;
3448 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3449 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3450 BT_HAL_ADDRESS_LENGTH_MAX);
3452 DBG("Connect LE [%s]", device_address);
3454 gattc_data->client_if = client_if;
3456 g_dbus_proxy_call(device_proxy, "ConnectLE",
3457 g_variant_new("(b)", auto_connect),
3458 G_DBUS_CALL_FLAGS_NONE,
3459 BT_HAL_MAX_DBUS_TIMEOUT,
3461 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3466 static bt_status_t _bt_hold_current_advertising()
3468 int ret = BT_STATUS_FAIL;
3469 gboolean is_advertising = FALSE;
3472 is_advertising = _bt_hal_is_advertising_in_slot(0);
3473 if (is_advertising) {
3474 DBG("+ Stop current advertising");
3476 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3477 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3483 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3485 DBG("+ start current advertising");
3487 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3492 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3494 DBG("Try to initiate pending LE connection");
3496 pending_le_conn_timer_id = 0;
3498 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3499 &pending_le_conn_info->bd_addr,
3500 pending_le_conn_info->auto_connect);
3502 g_free(pending_le_conn_info);
3503 pending_le_conn_info = NULL;
3508 static int __hal_generate_conn_id()
3510 return ++bt_conn_id;
3513 static int __hal_generate_server_instance_id()
3515 return ++bt_inst_id;
3518 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3521 GError *g_error = NULL;
3522 GVariant *reply = NULL;
3523 hal_gattc_client_info_t *gattc_data = user_data;
3524 int result = BT_STATUS_SUCCESS;
3525 struct hal_ev_gatt_client_connected ev;
3526 hal_gattc_server_info_t *gatt_conn_info = NULL;
3530 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3531 g_object_unref(proxy);
3532 if (reply == NULL) {
3533 ERR("Connect LE Dbus Call Error");
3535 ERR("Error: %s\n", g_error->message);
3536 g_clear_error(&g_error);
3538 result = BT_STATUS_FAIL;
3540 g_variant_unref(reply);
3542 if (NULL == gattc_data) {
3543 ERR("server_data is NULL");
3548 if (result == BT_STATUS_FAIL) {
3549 memset(&ev, 0, sizeof(ev));
3552 ev.client_if = gattc_data->client_if;
3553 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3554 BT_HAL_ADDRESS_LENGTH_MAX);
3557 ERR("gatt client callback not registered");
3559 DBG("sending gatt client connected event");
3560 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3566 DBG("adding the server conn info in list");
3567 gattc_data->conn_id = __hal_generate_conn_id() ;
3568 gattc_data->inst_id = __hal_generate_server_instance_id();
3570 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3572 /*add gatt server connection info*/
3573 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3574 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3575 gatt_conn_info->inst_id = gattc_data->inst_id;
3576 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3582 /*remove conn_info*/
3587 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3589 g_free(desc_info->desc_path);
3593 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3596 hal_gattc_desc_t *desc_info = NULL;
3597 for (l = char_info->gatt_list_descs; l != NULL; ) {
3598 desc_info = l->data;
3599 l = g_slist_next(l);
3600 if (desc_info == NULL)
3602 /* Remove descriptor element */
3603 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3604 __hal_gattc_free_desc_info(desc_info);
3606 g_slist_free(char_info->gatt_list_descs);
3607 g_free(char_info->chr_path);
3611 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3614 hal_gattc_char_t *char_info = NULL;
3615 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3616 char_info = l->data;
3617 l = g_slist_next(l);
3618 if (char_info == NULL)
3620 /* Remove characteristic element */
3621 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3622 __hal_gattc_free_char_info(char_info);
3624 g_slist_free(svc_info->gatt_list_chars);
3625 g_free(svc_info->svc_path);
3629 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3632 hal_gattc_service_t *svc_info = NULL;
3636 for (l = conn_info->gatt_list_services; l != NULL; ) {
3637 svc_info = (hal_gattc_service_t *)l->data;
3638 l = g_slist_next(l);
3639 if (svc_info == NULL)
3641 /* Remove service element */
3642 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3643 __hal_gattc_free_svc_info(svc_info);
3645 g_slist_free(conn_info->gatt_list_services);
3649 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3651 bt_bdaddr_t bd_addr;
3652 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3653 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3659 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3661 int result = BT_STATUS_SUCCESS;
3662 struct hal_ev_gatt_client_connected ev;
3663 hal_gattc_server_info_t *conn_info = NULL;
3664 bt_bdaddr_t bd_addr;
3666 hal_gattc_client_info_t *gattc_client = NULL;
3670 DBG("+ connected device address [%s]", address);
3672 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3673 HAL_EV_GATT_CLIENT_DISCONNECTED;
3675 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3676 /* find the gatt client info */
3677 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3678 if (NULL == gattc_client) {
3679 ERR("Fail to get gatt client info");
3684 memset(&ev, 0, sizeof(ev));
3685 ev.conn_id = gattc_client->conn_id;
3687 ev.client_if = gattc_client->client_if;
3688 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3689 BT_HAL_ADDRESS_LENGTH_MAX);
3692 ERR("gatt client callback not registered");
3694 DBG("sending gatt client connected status event");
3695 event_cb(event, (void *)&ev, sizeof(ev));
3698 if (!gatt_connected) {
3699 inst_id = gattc_client->inst_id;
3701 /* remove the gatt client info from the client list also*/
3702 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3703 g_free(gattc_client);
3705 //find the connected server info
3706 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3707 if (NULL == conn_info) {
3708 ERR("Fail to get gatt server info");
3712 if (inst_id != conn_info->inst_id) {
3713 ERR("server instance is different");
3717 //remove gatt conn info from the server list
3718 DBG("remove the server conn_info from list after gatt disconnection");
3719 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3720 __hal_clean_gattc_server_info(conn_info);
3726 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3727 const char* uuid_str, int inst_id)
3729 struct hal_ev_gatt_client_search_result ev;
3732 ERR("gatt client callback not registered");
3736 DBG("sending gatt client search service result event conn_id[%d]", conn_id);
3738 memset(&ev, 0, sizeof(ev));
3739 ev.conn_id = conn_id;
3740 ev.inst_id = inst_id;
3741 ev.is_primary = is_primary;
3742 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3744 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3747 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3749 struct hal_ev_gatt_client_search_complete ev;
3752 ERR("gatt client callback not registered");
3756 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3759 memset(&ev, 0, sizeof(ev));
3760 ev.conn_id = conn_id;
3763 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3766 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3767 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3768 char *char_value, int len)
3770 struct hal_ev_gatt_client_notify_changed_value ev;
3771 hal_gattc_client_info_t *gattc_client = NULL;
3774 ERR("gatt client callback not registered");
3778 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3779 if (NULL == gattc_client) {
3780 ERR("failed to get the gatt client info");
3785 DBG("sending gatt client connected status event");
3786 memset(&ev, 0, sizeof(ev));
3788 ev.conn_id = gattc_client->conn_id;
3789 ev.inst_id = conn_info->inst_id;
3790 ev.is_primary = svc_info->is_primary;
3791 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3792 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3794 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3796 if (len > 0 && (char_value != NULL)) {
3797 memcpy(ev.value, char_value, len);
3801 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3804 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3805 char *char_value, int len)
3807 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3808 hal_gattc_server_info_t *conn_info = NULL;
3809 bt_bdaddr_t bd_addr;
3812 hal_gattc_service_t *svc_info = NULL;
3813 hal_gattc_char_t *char_info = NULL;
3817 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3818 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3819 DBG("device address:[%s]", device_address);
3820 DBG("char handle:[%s]", char_handle);
3822 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3823 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3825 if (conn_info != NULL) {
3826 //find service for notified char path
3827 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3828 svc_info = (hal_gattc_service_t*)l->data;
3829 if (svc_info == NULL)
3832 /* find characteristic object path */
3833 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3834 char_info = (hal_gattc_char_t *)k->data;
3835 if (char_info == NULL)
3838 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3839 DBG("Found char handle[%s]", char_info->chr_path);
3842 _bt_hal_send_value_changed_event(conn_info, svc_info,
3843 char_info, char_value, len);
3851 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3853 GDBusConnection *g_conn = NULL;
3854 GDBusProxy *properties_proxy = NULL;
3855 GVariant *result = NULL;
3856 GError *error = NULL;
3857 GVariantIter *property_iter = NULL;
3858 const gchar *key = NULL;
3859 GVariant *value = NULL;
3860 const char *uuid_str = NULL;
3862 gboolean is_primary = FALSE;
3863 GVariantIter *char_iter = NULL;
3864 const char *char_handle = NULL;
3865 GPtrArray *gp_char_array = NULL;
3867 if (service_path == NULL) {
3868 ERR("service_path is NULL");
3869 return BT_STATUS_FAIL;
3872 DBG("service_path: %s", service_path);
3874 g_conn = _bt_hal_get_system_gconn();
3875 if (g_conn == NULL) {
3876 ERR("g_conn is NULL");
3877 return BT_STATUS_FAIL;
3880 properties_proxy = g_dbus_proxy_new_sync(g_conn,
3881 G_DBUS_PROXY_FLAGS_NONE, NULL,
3884 BT_HAL_PROPERTIES_INTERFACE,
3886 if (properties_proxy == NULL) {
3887 ERR("properties_proxy is NULL");
3888 return BT_STATUS_FAIL;
3891 result = g_dbus_proxy_call_sync(properties_proxy,
3893 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
3894 G_DBUS_CALL_FLAGS_NONE,
3896 if (result == NULL) {
3897 if (error != NULL) {
3898 ERR("Fail to get properties (Error: %s)", error->message);
3899 g_clear_error(&error);
3901 ERR("Fail to get properties");
3903 g_object_unref(properties_proxy);
3904 return BT_STATUS_FAIL;
3907 g_variant_get(result, "(a{sv})", &property_iter);
3909 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
3910 if (g_strcmp0(key, "UUID") == 0) {
3911 uuid_str = g_variant_get_string(value, &len);
3912 DBG("UUID: %s", uuid_str);
3913 } else if (g_strcmp0(key, "Primary") == 0) {
3914 is_primary = g_variant_get_boolean(value);
3915 DBG("is_primary: %s", is_primary ? "TRUE" : "FALSE");
3916 } else if (g_strcmp0(key, "Characteristics") == 0) {
3917 g_variant_get(value, "ao", &char_iter);
3918 if (char_iter != NULL) {
3919 gp_char_array = g_ptr_array_new();
3920 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
3921 DBG("char_handle: %s", char_handle);
3922 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
3928 if (uuid_str == NULL || gp_char_array == NULL) {
3929 ERR("uuid_str and gp_char_array should be set");
3933 /* Create new service */
3934 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
3937 g_variant_iter_free(property_iter);
3938 g_variant_unref(result);
3939 g_object_unref(properties_proxy);
3941 return BT_STATUS_SUCCESS;
3944 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
3946 GDBusConnection *conn = NULL;
3947 GDBusProxy *proxy = NULL;
3949 GVariant *ret = NULL;
3950 GVariant *value = NULL;
3952 conn = _bt_hal_get_system_gconn();
3954 ERR("_bt_gdbus_get_system_gconn returned NULL");
3958 proxy = g_dbus_proxy_new_sync(conn,
3959 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
3960 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
3961 if (proxy == NULL) {
3962 ERR("device_proxy returned NULL");
3966 ret = g_dbus_proxy_call_sync(proxy, "Get",
3967 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
3968 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3970 ERR("DBus Error : %s", err->message);
3971 g_clear_error(&err);
3973 g_variant_get(ret, "(v)", &value);
3974 *service_uuid = g_variant_dup_string(value, NULL);
3975 g_variant_unref(value);
3976 g_variant_unref(ret);
3980 g_object_unref(proxy);
3985 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
3987 struct hal_ev_gatt_client_service_changed ev = {0, };
3988 char address[BT_HAL_ADDRESS_STRING_SIZE];
3989 hal_gattc_server_info_t *server_info = NULL;
3990 hal_gattc_service_t *service = NULL;
3991 GSList *list = NULL;
3992 char *uuid_str = NULL;
3994 _bt_hal_convert_device_path_to_address(path, address);
3995 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
3996 ev.change_type = is_added;
3997 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
3998 if (server_info == NULL) {
3999 ERR("service_info is NULL");
4004 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
4005 DBG("GATT Service(%s) Added", uuid_str);
4006 /* Set UUID by using path */
4007 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
4010 /* Create new service and append into the list */
4011 __hal_gattc_get_service_info(server_info, path);
4013 /* Find service UUID from path */
4014 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4015 service = (hal_gattc_service_t *)list->data;
4016 if (service == NULL)
4019 if (g_strcmp0(service->svc_path, path) == 0) {
4020 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4021 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4022 /* Set UUID from stored service info */
4023 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4024 DBG("GATT Service(%s) Removed", uuid_str);
4027 /* Remove service info in list */
4028 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4029 __hal_gattc_free_svc_info(service);
4035 /* Send GATT Client service changed event */
4036 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));