4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include <hardware/bluetooth.h>
23 #include <hardware/bt_gatt.h>
31 #include <gio/gunixfdlist.h>
34 #include "bt-hal-log.h"
35 #include "bt-hal-msg.h"
36 #include "bt-hal-event-receiver.h"
37 #include "bt-hal-adapter-le.h"
39 #include "bt-hal-gatt-client.h"
40 #include "bt-hal-dbus-common-utils.h"
41 #include "bt-hal-utils.h"
43 /************************************************************************************
45 ************************************************************************************/
46 extern const btgatt_callbacks_t *bt_gatt_callbacks;
47 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
49 ERR("%s: BTGATT not initialized", __FUNCTION__);\
50 return BT_STATUS_NOT_READY;\
52 DBG("%s", __FUNCTION__);\
56 int le_scan_type = BT_GATTC_LE_SCAN_TYPE_PASSIVE;
59 static handle_stack_msg event_cb = NULL;
61 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
62 #define MAX_HAL_OBJECT_PATH_LEN 100
65 HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST = 0x01,
66 HAL_GATT_CHARACTERISTIC_PROPERTY_READ = 0x02,
67 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE = 0x04,
68 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE = 0x08,
69 HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY = 0x10,
70 HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE = 0x20,
71 HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE = 0x40,
72 HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE = 0x80,
73 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES = 0x100,
74 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ = 0x200,
75 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE = 0x400,
76 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ = 0x800,
77 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE = 0x1000,
78 HAL_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS = 0xffff,
79 } bt_gatt_characteristic_property_t;
83 HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE = 1,
84 HAL_GATT_WRITE_TYPE_WRITE ,
85 } hal_gatt_write_type_t;
89 HAL_GATT_PROPERTY_BROADCAST = 0x01, /**< Broadcast property */
90 HAL_GATT_PROPERTY_READ = 0x02, /**< Read property */
91 HAL_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE = 0x04, /**< Write without response property */
92 HAL_GATT_PROPERTY_WRITE = 0x08, /**< Write property */
93 HAL_GATT_PROPERTY_NOTIFY = 0x10, /**< Notify property */
94 HAL_GATT_PROPERTY_INDICATE = 0x20, /**< Indicate property */
95 HAL_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES = 0x40, /**< Authenticated signed writes property */
96 HAL_GATT_PROPERTY_EXTENDED_PROPERTIES = 0x80, /**< Extended properties */
97 } hal_gatt_property_e;
102 gboolean auto_connect;
103 } bt_pending_le_conn_info_s;
113 unsigned int permission;
114 GSList *gatt_list_descs;
121 GSList *gatt_list_chars;
122 } hal_gattc_service_t;
125 bt_bdaddr_t bd_addr; /*remote server address*/
127 int inst_id; /*server instance id*/
128 GSList *gatt_list_services;
129 } hal_gattc_server_info_t;
131 /* Linked List of connected GATT server */
132 static GSList *hal_gattc_server_info_list = NULL;
136 bt_bdaddr_t bd_addr; /*remote server address*/
139 } hal_gattc_client_info_t;
141 /* Linked list of connected GATT client connection */
142 static GSList * hal_gattc_client_info_list = NULL;
144 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
145 static guint pending_le_conn_timer_id = 0;
146 static int bt_conn_id = 0;
147 static int bt_inst_id = 0;
149 /* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
150 /* TODO: Adjust MAX Client after modifying MAX app handle logic */
151 #define BT_GATTC_CL_MAX 11
153 static int assigned_if = 0;
154 static gboolean client_if_used[BT_GATTC_CL_MAX];
159 btgatt_srvc_id_t srvc_id;
160 btgatt_gatt_id_t char_id;
161 btgatt_gatt_id_t desc_id;
162 } hal_gatt_resp_data_t;
167 } hal_gatt_client_app;
169 static GSList * hal_gattc_client_app_list = NULL;
176 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
177 gboolean auto_connect);
178 static bt_status_t _bt_hold_current_advertising();
179 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
180 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
181 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
183 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
184 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
185 const char* uuid_str, int inst_id);
186 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
187 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr);
188 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
189 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
191 void _bt_hal_gatt_client_init(void)
194 memset(client_if_used, 0x00, sizeof(client_if_used));
197 static int __bt_hal_gatt_assign_if(void)
201 index = assigned_if + 1;
203 if (index >= BT_GATTC_CL_MAX)
206 while (client_if_used[index] == TRUE) {
207 if (index == assigned_if) {
208 /* No available ID */
209 ERR("All interface ID is used");
215 if (index >= BT_GATTC_CL_MAX)
220 client_if_used[index] = TRUE;
225 static void __bt_hal_gatt_delete_if(int client_if)
227 if (client_if >= BT_GATTC_CL_MAX || client_if < 0)
230 client_if_used[client_if] = FALSE;
234 /* To send stack event to hal-av handler */
235 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
240 void _bt_hal_unregister_gatt_client_handler_cb(void)
246 int _bt_hal_gatt_client_get_le_scan_type(void)
252 static gboolean __bt_hal_register_client_cb(gpointer user_data)
254 struct hal_ev_gatt_client_registered ev;
255 hal_gatt_client_app *client_info = user_data;
257 /* Prepare to send AV connecting event */
258 memset(&ev, 0, sizeof(ev));
259 ev.status = BT_STATUS_SUCCESS;
260 ev.client_if = client_info->client_if;
261 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
264 ERR("GATT Callback not registered");
266 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
267 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
274 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
278 hal_gatt_client_app *info = NULL;
279 hal_gatt_client_app *gattc_app = NULL;
281 //check if client app is already registered
282 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
283 info = (hal_gatt_client_app*)l->data;
287 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
288 DBG("gatt client app already registered");
293 client_if = __bt_hal_gatt_assign_if();
294 if (client_if == -1) {
295 ERR("Fail to allocate the client if");
299 DBG("adding the gatt client app");
302 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
303 gattc_app->client_if = client_if;
304 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
306 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
311 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
313 hal_gatt_client_app *gattc_app = NULL;
314 hal_gatt_client_app *client_app_info = NULL;
316 /* add gatt client in list */
317 gattc_app = __hal_gattc_add_client_app(app_uuid);
318 if (gattc_app == NULL) {
319 ERR("Failed to register gatt client app");
320 return BT_STATUS_FAIL;
324 client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
325 client_app_info->client_if = gattc_app->client_if;
326 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
327 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
329 DBG("registered client client_if [%d]", client_app_info->client_if);
331 return BT_STATUS_SUCCESS;
334 /** Registers a GATT client application with the stack */
335 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
339 return __hal_gattc_register_client_app(uuid);
342 bt_status_t btif_gattc_add_connection_info(const bt_bdaddr_t *bd_addr, int conn_id, int server_inst_id)
344 hal_gattc_client_info_t *client_info = NULL;
345 hal_gattc_server_info_t *server_info = NULL;
347 /* Add client connection info in list */
348 client_info = g_malloc0(sizeof(hal_gattc_client_info_t));
349 client_info->client_if = -1;
350 memcpy(client_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
351 client_info->conn_id = conn_id;
352 client_info->inst_id = server_inst_id;
353 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, client_info);
354 DBG("Added client connection info in list");
356 /* Add server connection info in list */
357 server_info = __bt_find_gatt_conn_info(bd_addr);
358 if (server_info == NULL) {
359 server_info = g_malloc0(sizeof(hal_gattc_server_info_t));
360 memcpy(server_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
361 server_info->conn_id = conn_id;
362 server_info->inst_id = server_inst_id;
363 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, server_info);
364 DBG("Added server connection info in list");
367 return BT_STATUS_SUCCESS;
370 bt_status_t __hal_gattc_unregister_client(int client_if)
373 hal_gatt_client_app *info = NULL;
375 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
377 /* remove the gatt client app */
378 for (l = hal_gattc_client_app_list; l != NULL; ) {
379 info = (hal_gatt_client_app*)l->data;
385 if (info->client_if == client_if) {
386 DBG("gatt client app found");
388 __bt_hal_gatt_delete_if(client_if);
390 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
395 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
396 return BT_STATUS_SUCCESS;
399 /** Unregister a client application from the stack */
400 bt_status_t btif_gattc_unregister_client(int client_if)
404 return __hal_gattc_unregister_client(client_if);
407 /** Start or stop LE device scanning */
408 bt_status_t scan(int client_if, bool start)
415 ret = _bt_hal_adapter_le_start_scan();
417 ret = _bt_hal_adapter_le_stop_scan();
422 /** Create a connection to a remote LE or dual-mode device */
423 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
426 int ret = BT_STATUS_SUCCESS;
431 return BT_STATUS_PARM_INVALID;
433 ret = _bt_hold_current_advertising();
434 if (ret == BT_STATUS_SUCCESS) {
435 DBG("Current advertising is held");
436 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
437 pending_le_conn_info->client_if = client_if;
438 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
439 BT_HAL_ADDRESS_LENGTH_MAX);
440 pending_le_conn_info->auto_connect = is_direct;
442 pending_le_conn_timer_id =
443 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
445 return BT_STATUS_SUCCESS;
447 ERR("advertising is not stopped");
450 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
454 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
457 GError *g_error = NULL;
458 GVariant *reply = NULL;
459 hal_gattc_client_info_t *gatt_conn_info = user_data;
460 int result = BT_STATUS_SUCCESS;
461 struct hal_ev_gatt_client_connected ev;
465 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
466 g_object_unref(proxy);
468 ERR("Connect LE Dbus Call Error");
470 ERR("Error: %s\n", g_error->message);
471 g_clear_error(&g_error);
473 result = BT_STATUS_FAIL;
475 g_variant_unref(reply);
477 if (NULL == gatt_conn_info) {
478 ERR("server_data is NULL");
483 if (result == BT_STATUS_FAIL) {
484 memset(&ev, 0, sizeof(ev));
485 ev.conn_id = gatt_conn_info->conn_id;
487 ev.client_if = gatt_conn_info->client_if;
488 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
489 BT_HAL_ADDRESS_LENGTH_MAX);
492 ERR("gatt client callback not registered");
494 DBG("sending gatt client disconnected event");
495 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
501 g_free(gatt_conn_info);
506 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
509 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
511 GDBusProxy *device_proxy;
512 GDBusConnection *conn;
513 int ret = BT_STATUS_SUCCESS;
514 hal_gattc_client_info_t *gattc_data;
516 if (NULL == bd_addr) {
517 ERR("bd_addr is NULL");
518 return BT_STATUS_PARM_INVALID;
521 conn = _bt_hal_get_system_gconn();
523 ERR("_bt_gdbus_get_system_gconn returned NULL");
524 return BT_STATUS_FAIL;
527 _bt_hal_convert_addr_type_to_string(device_address,
528 (unsigned char *)bd_addr->address);
529 device_path = _bt_hal_get_device_object_path(device_address);
530 if (device_path == NULL) {
531 DBG("device_path NULL");
532 ret = BT_STATUS_FAIL;
536 ERR("device_path:%s", device_path);
538 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
539 NULL, BT_HAL_BLUEZ_NAME,
540 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
542 if (NULL == device_proxy) {
543 ERR("device_proxy returned NULL");
544 return BT_STATUS_FAIL;
547 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
548 memcpy(gattc_data->bd_addr.address, bd_addr->address,
549 BT_HAL_ADDRESS_LENGTH_MAX);
550 gattc_data->client_if = client_if;
551 gattc_data->conn_id = conn_id;
553 DBG("DisconnectLE [%s]", device_address);
555 g_dbus_proxy_call(device_proxy, "DisconnectLE",
557 G_DBUS_CALL_FLAGS_NONE,
558 BT_HAL_MAX_DBUS_TIMEOUT,
560 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
564 /** Disconnect a remote device or cancel a pending connection */
565 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
570 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
573 /** Clear the attribute cache for a given device */
574 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
577 return BT_STATUS_UNSUPPORTED;
580 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
583 hal_gattc_service_t *info = NULL;
585 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
586 info = (hal_gattc_service_t*)l->data;
590 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t)))
598 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
599 bt_gatt_characteristic_property_t prop)
602 hal_gattc_char_t *info = NULL;
604 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
605 info = (hal_gattc_char_t*)l->data;
609 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
610 (info->permission & prop)) {
617 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
620 hal_gattc_char_t *info = NULL;
622 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
623 info = (hal_gattc_char_t*)l->data;
627 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
628 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
629 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
636 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
639 hal_gattc_desc_t *info = NULL;
641 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
642 info = (hal_gattc_desc_t*)l->data;
646 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t)))
653 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
654 const char *uuid_str, const char *object_path, int is_primary)
656 hal_gattc_service_t *gattc_service = NULL;
658 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
659 gattc_service->svc_path = g_strdup(object_path);
660 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
661 gattc_service->is_primary = is_primary;
663 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
664 INFO("Toatal svc [%d] Added [%s] [%s]", g_slist_length(conn_info->gatt_list_services), object_path + 15, uuid_str);
666 return gattc_service;
669 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
671 hal_gattc_char_t *gattc_char = NULL;
673 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
674 gattc_char->chr_path = g_strdup(char_handle);
676 DBG("svc path: [%s]", gatt_svc->svc_path);
677 DBG("char path: [%s]", gattc_char->chr_path);
679 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
682 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
683 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
685 hal_gattc_service_t* gatt_svc = NULL;
687 gchar *gp_char_path = NULL;
689 /* add the service */
690 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
691 if (gatt_svc == NULL) {
692 ERR("Failed to add service");
696 /* add the characteristic */
697 for (i = 0; i < gp_char_array->len; i++) {
698 gp_char_path = g_ptr_array_index(gp_char_array, i);
699 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
702 g_ptr_array_free(gp_char_array, TRUE);
705 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
707 hal_gattc_desc_t *gattc_desc = NULL;
709 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
710 gattc_desc->desc_path = g_strdup(desc_path);
712 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
715 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
716 GPtrArray *gp_desc_array, unsigned int char_permission)
718 gchar *gp_desc_path = NULL;
721 if (char_uuid_str == NULL) {
722 DBG("char_uuid_str is NULL");
726 //update the char uuid
727 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
729 //update char permission
730 gattc_char->permission = char_permission;
733 for (i = 0; i < gp_desc_array->len; i++) {
734 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
735 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
739 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
741 if (desc_uuid_str == NULL) {
742 DBG("char_uuid_str is NULL");
746 //update the descriptor uuid
747 DBG("desc UUID: [%s] ", desc_uuid_str);
748 DBG("desc path: [%s]", gattc_desc->desc_path);
750 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
753 static void browse_service_char(int conn_id)
755 hal_gattc_server_info_t *conn_info = NULL;
759 hal_gattc_service_t *svc_info = NULL;
760 hal_gattc_char_t *char_info = NULL;
761 hal_gattc_desc_t *desc_info = NULL;
763 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
764 if (conn_info == NULL) {
765 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
769 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
770 svc_info = (hal_gattc_service_t*)l->data;
771 if (svc_info == NULL)
774 /* find characteristic object path */
775 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
776 char_info = (hal_gattc_char_t *)k->data;
777 if (char_info == NULL)
781 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
782 desc_info = (hal_gattc_desc_t *)m->data;
783 if (desc_info == NULL)
793 * Enumerate all GATT services on a connected device.
794 * Optionally, the results can be filtered for a given UUID.
796 static bt_status_t _gattc_client_search_service(int conn_id)
800 GVariant *result = NULL;
802 GVariantIter *svc_iter;
803 GVariantIter *interface_iter;
804 char *object_path = NULL;
805 char *interface_str = NULL;
806 const gchar *key = NULL;
807 GVariant *value = NULL;
808 GPtrArray *gp_array = NULL;
809 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
810 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
811 int ret = BT_STATUS_FAIL;
813 const gchar *uuid_str = NULL;
815 hal_gattc_server_info_t *conn_info = NULL;
816 gboolean is_primary = FALSE;
819 char *char_handle = NULL;
820 GVariantIter *char_iter = NULL;
821 GPtrArray *gp_char_array = NULL;
823 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
824 if (NULL == conn_info) {
825 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
826 return BT_STATUS_FAIL;
830 // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
831 /* Check the service info is stored */
832 if (g_slist_length(conn_info->gatt_list_services) > 0) {
834 hal_gattc_service_t *svc_info = NULL;
835 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
836 DBG("Send event from service info list");
837 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
839 if (svc_info == NULL)
841 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
842 _bt_hal_send_search_service_result_event(conn_id,
843 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
845 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
846 return BT_STATUS_SUCCESS;
848 DBG("No stored service, request to bluez");
852 _bt_hal_convert_addr_type_to_string(device_address,
853 (unsigned char *)conn_info->bd_addr.address);
855 result = _bt_hal_get_managed_objects();
859 gp_array = g_ptr_array_new();
860 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
862 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
864 if (object_path == NULL)
867 _bt_hal_convert_device_path_to_address(object_path, temp_address);
869 if (g_strcmp0(temp_address, device_address) != 0)
872 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
873 &interface_str, &svc_iter)) {
874 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
877 DBG("[%d] Object Path : %s", idx++, object_path);
878 /* for characteristic */
879 gp_char_array = g_ptr_array_new();
880 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
881 if (g_strcmp0(key, "Primary") == 0) {
882 is_primary = g_variant_get_boolean(value);
884 g_ptr_array_add(gp_array, (gpointer)object_path);
887 } else if (g_strcmp0(key, "UUID") == 0) {
888 uuid_str = g_variant_get_string(value, &len);
889 } else if (g_strcmp0(key, "Characteristics") == 0) {
890 g_variant_get(value, "ao", &char_iter);
891 if (char_iter != NULL) {
892 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
893 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
900 _bt_hal_send_search_service_result_event(conn_id, is_primary,
901 uuid_str, conn_info->inst_id);
903 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
908 if (gp_array->len == 0 || svc_count == 0) {
909 ERR("gp_array is NULL");
910 ret = BT_STATUS_FAIL;
912 ret = BT_STATUS_SUCCESS;
915 browse_service_char(conn_id);
916 /* send search service complete event */
917 _bt_hal_send_search_service_complete_event(conn_id, ret);
919 g_ptr_array_free(gp_array, TRUE);
920 g_variant_iter_free(iter);
921 g_variant_unref(result);
926 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
928 if (NULL == filter_uuid) {
929 DBG("Browse all the services");
930 return _gattc_client_search_service(conn_id);
932 DBG("TODO implement it");
933 return BT_STATUS_UNSUPPORTED;
937 * Enumerate included services for a given service.
938 * Set start_incl_srvc_id to NULL to get the first included service.
940 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
941 btgatt_srvc_id_t *start_incl_srvc_id)
944 return BT_STATUS_UNSUPPORTED;
947 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
948 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
950 struct hal_ev_gatt_client_char_search_result ev;
953 ERR("gatt client callback not registered");
957 memset(&ev, 0, sizeof(ev));
958 ev.conn_id = conn_id;
959 ev.inst_id = svc_id->id.inst_id;
960 ev.is_primary = svc_id->is_primary;
962 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
964 if (status == BT_STATUS_SUCCESS) {
965 /* building char uuid */
966 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
967 ev.char_prop = char_prop;
970 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
971 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
974 static int _hal_get_permission_flag(char *permission)
978 if (NULL == permission) {
979 ERR("gatt permission is NULL");
983 if (!g_strcmp0(permission, "broadcast"))
984 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
985 else if (!g_strcmp0(permission, "read"))
986 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
987 else if (!g_strcmp0(permission, "write-without-response"))
988 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
989 else if (!g_strcmp0(permission, "write"))
990 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
991 else if (!g_strcmp0(permission, "notify"))
992 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
993 else if (!g_strcmp0(permission, "indicate"))
994 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
995 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
996 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
997 else if (!g_strcmp0(permission, "reliable-write"))
998 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
999 else if (!g_strcmp0(permission, "writable-auxiliaries"))
1000 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1001 else if (!g_strcmp0(permission, "encrypt-read"))
1002 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1003 else if (!g_strcmp0(permission, "encrypt-write"))
1004 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1005 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1006 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1007 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1008 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1013 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1015 char perm[200] = { 0, };
1017 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1018 g_strlcat(perm, "broadcast ", sizeof(perm));
1019 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1020 g_strlcat(perm, "read ", sizeof(perm));
1021 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1022 g_strlcat(perm, "write-without-response ", sizeof(perm));
1023 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1024 g_strlcat(perm, "write ", sizeof(perm));
1025 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1026 g_strlcat(perm, "notify ", sizeof(perm));
1027 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1028 g_strlcat(perm, "indicate ", sizeof(perm));
1029 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1030 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1031 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1032 g_strlcat(perm, "reliable-write ", sizeof(perm));
1033 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1034 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1035 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1036 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1037 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1038 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1039 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1040 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1041 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1042 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1044 DBG("permission [0x%04x] : %s\n", permission, perm);
1048 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1050 GDBusProxy *properties_proxy = NULL;
1051 GError *error = NULL;
1052 GVariant *value = NULL;
1053 GVariant *result = NULL;
1054 GDBusConnection *g_conn;
1056 char *char_desc_handle = NULL;
1058 GVariantIter *property_iter;
1059 GVariantIter *char_desc_iter;
1060 char* char_handle = NULL;
1061 gchar *char_uuid_str = NULL;
1062 GPtrArray *gp_desc_array = NULL;
1063 GVariantIter *char_perm_iter;
1065 unsigned int char_permission = 0 ;
1067 if (gattc_char->chr_path == NULL) {
1068 DBG("char path is NULL");
1069 return BT_STATUS_FAIL;
1071 char_handle = gattc_char->chr_path;
1073 g_conn = _bt_hal_get_system_gconn();
1074 if (NULL == g_conn) {
1075 ERR("_bt_gdbus_get_system_gconn returned NULL");
1076 return BT_STATUS_FAIL;
1079 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1080 G_DBUS_PROXY_FLAGS_NONE, NULL,
1083 BT_HAL_PROPERTIES_INTERFACE,
1086 if (properties_proxy == NULL) {
1087 ERR("properties_proxy returned NULL");
1088 return BT_STATUS_FAIL;
1091 result = g_dbus_proxy_call_sync(properties_proxy,
1093 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1094 G_DBUS_CALL_FLAGS_NONE,
1099 if (error != NULL) {
1100 ERR("Fail to get properties (Error: %s)", error->message);
1101 g_clear_error(&error);
1103 ERR("Fail to get properties");
1104 g_object_unref(properties_proxy);
1105 return BT_STATUS_FAIL;
1108 gp_desc_array = g_ptr_array_new();
1110 g_variant_get(result, "(a{sv})", &property_iter);
1112 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1113 if (!g_strcmp0(key, "UUID")) {
1114 char_uuid_str = g_variant_dup_string(value, &len);
1115 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1116 } else if (!g_strcmp0(key, "Flags")) {
1117 g_variant_get(value, "as", &char_perm_iter);
1118 char_permission = 0x00;
1120 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1121 char_permission |= _hal_get_permission_flag(permission);
1123 __hal_convert_permission_flag_to_str(char_permission);
1124 g_variant_iter_free(char_perm_iter);
1125 } else if (!g_strcmp0(key, "Descriptors")) {
1126 g_variant_get(value, "ao", &char_desc_iter);
1127 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1128 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1130 g_variant_iter_free(char_desc_iter);
1134 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1136 g_free(char_uuid_str);
1137 g_variant_iter_free(property_iter);
1138 g_variant_unref(result);
1139 g_object_unref(properties_proxy);
1140 g_ptr_array_free(gp_desc_array, TRUE);
1142 return BT_STATUS_SUCCESS;
1145 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1146 btgatt_srvc_id_t *srvc_id)
1148 hal_gattc_server_info_t * conn_info = NULL;
1149 hal_gattc_service_t *gattc_service = NULL;
1151 hal_gattc_char_t *gattc_char = NULL;
1152 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1153 int status = BT_STATUS_FAIL;
1155 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1156 if (NULL == conn_info) {
1157 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1158 return BT_STATUS_FAIL;
1162 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1163 if (NULL == gattc_service) {
1164 ERR("Failed to get the gatt service");
1165 return BT_STATUS_FAIL;
1168 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1169 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1171 /* find characteristic object path */
1172 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1173 gattc_char = (hal_gattc_char_t *)l->data;
1174 status = _hal_gattc_get_characteristic_info(gattc_char);
1177 if (BT_STATUS_SUCCESS == status) {
1178 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1179 &gattc_char->chr_uuid, gattc_char->permission);
1183 status = BT_STATUS_FAIL;
1184 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1186 browse_service_char(conn_id);
1187 /* retrive uuid for characteristic and object path for descriptor */
1189 return BT_STATUS_SUCCESS;
1193 * Enumerate characteristics for a given service.
1194 * Set start_char_id to NULL to get the first characteristic.
1196 bt_status_t btif_gattc_get_characteristic(int conn_id,
1197 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1199 CHECK_BTGATT_INIT();
1201 if (start_char_id == NULL) {
1202 DBG("Get all the characteristics");
1203 return _gattc_get_all_characteristic(conn_id, srvc_id);
1206 DBG("TBD Get specific characteristics");
1207 return BT_STATUS_UNSUPPORTED;
1211 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1213 GDBusProxy *properties_proxy = NULL;
1214 GError *error = NULL;
1215 GVariant *value = NULL;
1216 GVariant *result = NULL;
1217 GDBusConnection *g_conn;
1220 GVariantIter *property_iter;
1221 char* desc_handle = NULL;
1222 const gchar *desc_uuid_str = NULL;
1224 if (gattc_desc->desc_path == NULL) {
1225 DBG("desc path is NULL");
1226 return BT_STATUS_FAIL;
1228 desc_handle = gattc_desc->desc_path;
1230 g_conn = _bt_hal_get_system_gconn();
1231 if (NULL == g_conn) {
1232 ERR("_bt_gdbus_get_system_gconn returned NULL");
1233 return BT_STATUS_FAIL;
1236 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1237 G_DBUS_PROXY_FLAGS_NONE, NULL,
1240 BT_HAL_PROPERTIES_INTERFACE,
1243 if (properties_proxy == NULL) {
1244 ERR("properties_proxy returned NULL");
1245 return BT_STATUS_FAIL;
1248 result = g_dbus_proxy_call_sync(properties_proxy,
1250 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1251 G_DBUS_CALL_FLAGS_NONE,
1256 if (error != NULL) {
1257 ERR("Fail to get properties (Error: %s)", error->message);
1258 g_clear_error(&error);
1260 ERR("Fail to get properties");
1261 g_object_unref(properties_proxy);
1262 return BT_STATUS_FAIL;
1265 g_variant_get(result, "(a{sv})", &property_iter);
1267 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1268 if (!g_strcmp0(key, "UUID")) {
1269 desc_uuid_str = g_variant_get_string(value, &len);
1270 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1272 g_free((gchar *)key);
1273 g_variant_unref(value);
1278 g_variant_iter_free(property_iter);
1279 g_variant_unref(result);
1280 g_object_unref(properties_proxy);
1282 return BT_STATUS_SUCCESS;
1285 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1286 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1288 struct hal_ev_gatt_client_desc_search_result ev;
1291 ERR("gatt client callback not registered");
1295 memset(&ev, 0, sizeof(ev));
1296 ev.conn_id = conn_id;
1297 ev.inst_id = svc_id->id.inst_id;
1298 ev.is_primary = svc_id->is_primary;
1301 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1302 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1304 if (status == BT_STATUS_SUCCESS) {
1305 /* building desc uuid */
1306 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1309 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1311 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1314 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1315 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1317 hal_gattc_server_info_t * conn_info = NULL;
1318 hal_gattc_service_t *gattc_service = NULL;
1321 hal_gattc_char_t *gattc_char = NULL;
1322 hal_gattc_desc_t *gattc_desc = NULL;
1323 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1324 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1325 int status = BT_STATUS_FAIL;
1327 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1328 if (NULL == conn_info) {
1329 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1330 return BT_STATUS_FAIL;
1334 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1335 if (NULL == gattc_service) {
1336 ERR("Failed to get the gatt service");
1337 return BT_STATUS_FAIL;
1340 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1341 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1343 /* find characteristics */
1344 /* a service can have two char with same uuid */
1345 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1346 gattc_char = (hal_gattc_char_t*)l->data;
1347 if (gattc_char == NULL)
1350 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1351 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1352 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1354 /* get descriptor uuid */
1355 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1356 gattc_desc = (hal_gattc_desc_t *)m->data;
1357 if (gattc_desc == NULL)
1360 status = _hal_gattc_get_descriptor_info(gattc_desc);
1363 if (BT_STATUS_SUCCESS == status) {
1364 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1365 char_id, &gattc_desc->desc_uuid);
1371 status = BT_STATUS_FAIL;
1372 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1374 browse_service_char(conn_id);
1375 /* retrive uuid for characteristic and object path for descriptor */
1377 return BT_STATUS_SUCCESS;
1381 * Enumerate descriptors for a given characteristic.
1382 * Set start_descr_id to NULL to get the first descriptor.
1384 bt_status_t btif_gattc_get_descriptor(int conn_id,
1385 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1386 btgatt_gatt_id_t *start_descr_id)
1388 CHECK_BTGATT_INIT();
1390 if (start_descr_id == NULL) {
1391 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1393 DBG("TBD Get specific descriptor");
1394 return BT_STATUS_UNSUPPORTED;
1398 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1400 struct hal_ev_gatt_client_read_data ev;
1403 ERR("gatt client callback not registered");
1407 memset(&ev, 0, sizeof(ev));
1408 ev.conn_id = resp_data->conn_id;
1409 ev.inst_id = resp_data->srvc_id.id.inst_id;
1410 ev.is_primary = resp_data->srvc_id.is_primary;
1413 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1414 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1418 /* building the char read value */
1419 memcpy(ev.value, value, len);
1422 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1424 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1427 static void __hal_internal_read_char_cb(GObject *source_object,
1428 GAsyncResult *res, gpointer user_data)
1430 GError *error = NULL;
1431 GDBusConnection *system_gconn = NULL;
1434 GByteArray *gp_byte_array = NULL;
1436 hal_gatt_resp_data_t *resp_data = user_data;
1437 int result = BT_STATUS_SUCCESS;
1439 system_gconn = _bt_hal_get_system_gconn();
1440 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1443 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1446 result = BT_STATUS_FAIL;
1447 __hal_send_char_read_event(resp_data, result, NULL, 0);
1448 g_clear_error(&error);
1453 gp_byte_array = g_byte_array_new();
1454 g_variant_get(value, "(ay)", &iter);
1456 while (g_variant_iter_loop(iter, "y", &g_byte))
1457 g_byte_array_append(gp_byte_array, &g_byte, 1);
1461 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1465 g_byte_array_free(gp_byte_array, TRUE);
1466 g_variant_iter_free(iter);
1467 g_variant_unref(value);
1471 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1472 btgatt_gatt_id_t *char_id, int auth_req)
1474 GDBusConnection *g_conn;
1475 hal_gatt_resp_data_t *resp_data;
1476 hal_gattc_service_t *gattc_service = NULL;
1477 GVariantBuilder *builder = NULL;
1479 hal_gattc_server_info_t * conn_info = NULL;
1480 hal_gattc_char_t *gattc_char = NULL;
1481 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1482 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1483 char* char_handle = NULL;
1485 /* get the connection info */
1486 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1487 if (NULL == conn_info) {
1488 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1489 return BT_STATUS_FAIL;
1493 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1494 if (NULL == gattc_service) {
1495 ERR("Failed to get the gatt service");
1496 return BT_STATUS_FAIL;
1499 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1501 /* find characteristic */
1502 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1503 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1504 if (NULL == gattc_char) {
1505 ERR("Failed to get the gatt char");
1506 return BT_STATUS_FAIL;
1509 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1510 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1512 g_conn = _bt_hal_get_system_gconn();
1513 if (NULL == g_conn) {
1514 ERR("_bt_gdbus_get_system_gconn returned NULL");
1515 return BT_STATUS_FAIL;
1518 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1519 resp_data->conn_id = conn_id;
1520 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1521 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1523 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1526 g_variant_builder_add(builder, "{sv}", "offset",
1527 g_variant_new("q", offset));
1529 char_handle = gattc_char->chr_path;
1531 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1532 "ReadValue", g_variant_new("(a{sv})", builder),
1533 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1534 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1535 (gpointer)resp_data);
1536 g_variant_builder_unref(builder);
1538 return BT_STATUS_SUCCESS;
1541 /** Read a characteristic on a remote device */
1542 bt_status_t btif_read_characteristic(int conn_id,
1543 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1546 CHECK_BTGATT_INIT();
1548 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1551 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1553 struct hal_ev_gatt_client_write_result ev;
1556 ERR("gatt client callback not registered");
1560 memset(&ev, 0, sizeof(ev));
1561 ev.conn_id = resp_data->conn_id;
1562 ev.inst_id = resp_data->srvc_id.id.inst_id;
1563 ev.is_primary = resp_data->srvc_id.is_primary;
1566 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1567 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1569 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1571 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1574 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1575 GAsyncResult *res, gpointer user_data)
1577 GError *error = NULL;
1578 GDBusConnection *system_gconn = NULL;
1580 hal_gatt_resp_data_t *resp_data = user_data;
1581 int result = BT_STATUS_SUCCESS;
1585 system_gconn = _bt_hal_get_system_gconn();
1586 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1589 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1591 result = BT_STATUS_FAIL;
1593 __hal_send_char_write_event(resp_data, result);
1594 g_clear_error(&error);
1599 //send write value event
1600 __hal_send_char_write_event(resp_data, result);
1603 g_variant_unref(value);
1608 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1611 case HAL_GATT_WRITE_TYPE_WRITE:
1612 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1614 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1615 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1618 ERR("Unknow write type : %d", type);
1619 return BT_STATUS_FAIL;
1622 return BT_STATUS_SUCCESS;
1626 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1628 GDBusConnection *conn;
1629 GVariantBuilder *builder = NULL;
1635 GUnixFDList *fd_list = NULL;
1637 conn = _bt_hal_get_system_gconn();
1639 ERR("_bt_gdbus_get_system_gconn returned NULL");
1640 return BT_STATUS_FAIL;
1643 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1644 //val = g_variant_new("ay", builder1);
1646 g_variant_builder_add(builder, "{sv}", "offset",
1647 g_variant_new("q", offset));
1649 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1650 "AcquireWrite", g_variant_new("(a{sv})", builder),
1651 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1652 NULL, &fd_list, NULL, &err);
1654 g_dbus_error_strip_remote_error(err);
1655 ERR("Error: %s", err->message);
1657 g_variant_builder_unref(builder);
1658 return BT_STATUS_FAIL;
1661 g_variant_get(value, "(hq)", &idx, &att_mtu);
1662 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1664 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1667 g_object_unref(fd_list);
1668 g_variant_unref(value);
1669 g_variant_builder_unref(builder);
1671 return BT_STATUS_SUCCESS;
1674 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1676 GDBusConnection *conn;
1677 GVariantBuilder *builder = NULL;
1681 gint32 idx, notify_fd;
1683 GUnixFDList *fd_list = NULL;
1685 conn = _bt_hal_get_system_gconn();
1688 ERR("_bt_gdbus_get_system_gconn returned NULL");
1689 return BT_STATUS_FAIL;
1693 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1696 g_variant_builder_add(builder, "{sv}", "offset",
1697 g_variant_new("q", offset));
1699 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1700 "AcquireNotify", g_variant_new("(a{sv})", builder),
1701 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1702 NULL, &fd_list, NULL, &err);
1704 g_dbus_error_strip_remote_error(err);
1705 ERR("Error: %s", err->message);
1707 g_variant_builder_unref(builder);
1708 return BT_STATUS_FAIL;
1711 g_variant_get(value, "(hq)", &idx, &att_mtu);
1712 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1715 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1719 g_object_unref(fd_list);
1720 g_variant_unref(value);
1721 g_variant_builder_unref(builder);
1723 return BT_STATUS_SUCCESS;
1727 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1728 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1730 GVariant *val, *options;
1731 GVariantBuilder *builder1;
1732 GVariantBuilder *builder2;
1733 GDBusConnection *g_conn;
1736 hal_gatt_resp_data_t *resp_data;
1737 hal_gattc_service_t *gattc_service = NULL;
1738 hal_gattc_server_info_t * conn_info = NULL;
1739 hal_gattc_char_t *gattc_char = NULL;
1740 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1741 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1742 char* char_handle = NULL;
1743 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1744 int ret = BT_STATUS_SUCCESS;
1746 ret = __hal_get_write_prop(write_type, &write_prop);
1747 if (BT_STATUS_FAIL == ret) {
1748 DBG("received invalid write type:[%d] ", write_type);
1749 return BT_STATUS_FAIL;
1752 /* get the connection info */
1753 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1754 if (NULL == conn_info) {
1755 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1756 return BT_STATUS_FAIL;
1760 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1761 if (NULL == gattc_service) {
1762 ERR("Failed to get the gatt service");
1763 return BT_STATUS_FAIL;
1766 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1767 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1769 /* find characteristic */
1770 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1771 if (NULL == gattc_char) {
1772 ERR("Failed to get the gatt char");
1773 return BT_STATUS_FAIL;
1776 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1777 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1779 g_conn = _bt_hal_get_system_gconn();
1780 if (NULL == g_conn) {
1781 ERR("_bt_gdbus_get_system_gconn returned NULL");
1782 return BT_STATUS_FAIL;
1785 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1786 resp_data->conn_id = conn_id;
1787 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1788 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1790 char_handle = gattc_char->chr_path;
1792 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1794 for (i = 0; i < length; i++)
1795 g_variant_builder_add(builder1, "y", value[i]);
1797 val = g_variant_new("ay", builder1);
1799 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1801 g_variant_builder_add(builder2, "{sv}", "offset",
1802 g_variant_new_uint16(offset));
1804 options = g_variant_new("a{sv}", builder2);
1806 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1808 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1810 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1811 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1812 (gpointer)resp_data);
1814 g_variant_builder_unref(builder1);
1815 g_variant_builder_unref(builder2);
1817 return BT_STATUS_SUCCESS;
1820 bt_status_t btif_get_acquire_write_fd(int conn_id,
1821 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1822 int auth_req, int *fd, int*mtu)
1824 CHECK_BTGATT_INIT();
1826 hal_gattc_service_t *gattc_service = NULL;
1827 hal_gattc_server_info_t * conn_info = NULL;
1828 hal_gattc_char_t *gattc_char = NULL;
1829 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1831 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1832 int ret = BT_STATUS_SUCCESS;
1834 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1836 /* get the connection info */
1837 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1838 if (NULL == conn_info) {
1839 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1840 return BT_STATUS_FAIL;
1844 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1845 if (NULL == gattc_service) {
1846 ERR("Failed to get the gatt service");
1847 return BT_STATUS_FAIL;
1850 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1851 if (NULL == gattc_char) {
1852 ERR("Failed to get the gatt char");
1853 return BT_STATUS_FAIL;
1856 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1857 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1859 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1860 if (ret != BT_STATUS_SUCCESS)
1866 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1867 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1869 CHECK_BTGATT_INIT();
1871 hal_gattc_service_t *gattc_service = NULL;
1872 hal_gattc_server_info_t * conn_info = NULL;
1873 hal_gattc_char_t *gattc_char = NULL;
1874 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1876 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1877 int ret = BT_STATUS_SUCCESS;
1879 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1881 /* get the connection info */
1882 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1883 if (NULL == conn_info) {
1884 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1885 return BT_STATUS_FAIL;
1889 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1890 if (NULL == gattc_service) {
1891 ERR("Failed to get the gatt service");
1892 return BT_STATUS_FAIL;
1895 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1896 if (NULL == gattc_char) {
1897 ERR("Failed to get the gatt char");
1898 return BT_STATUS_FAIL;
1901 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1902 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1904 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1905 if (ret != BT_STATUS_SUCCESS)
1912 /** Write a remote characteristic */
1913 bt_status_t btif_write_characteristic(int conn_id,
1914 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1915 int write_type, int len, int auth_req,
1918 CHECK_BTGATT_INIT();
1920 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1921 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1922 len, auth_req, p_value);
1925 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1927 struct hal_ev_gatt_client_read_data ev;
1930 ERR("gatt client callback not registered");
1934 memset(&ev, 0, sizeof(ev));
1935 ev.conn_id = resp_data->conn_id;
1936 ev.inst_id = resp_data->srvc_id.id.inst_id;
1937 ev.is_primary = resp_data->srvc_id.is_primary;
1940 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1941 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1942 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1946 /* building the desc read value */
1947 memcpy(ev.value, value, len);
1950 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1952 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1955 static void __hal_internal_read_desc_cb(GObject *source_object,
1956 GAsyncResult *res, gpointer user_data)
1958 GError *error = NULL;
1959 GDBusConnection *system_gconn = NULL;
1962 GByteArray *gp_byte_array = NULL;
1964 hal_gatt_resp_data_t *resp_data = user_data;
1965 int result = BT_STATUS_SUCCESS;
1970 system_gconn = _bt_hal_get_system_gconn();
1971 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1974 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1977 result = BT_STATUS_FAIL;
1978 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1979 g_clear_error(&error);
1984 gp_byte_array = g_byte_array_new();
1985 g_variant_get(value, "(ay)", &iter);
1987 while (g_variant_iter_loop(iter, "y", &g_byte))
1988 g_byte_array_append(gp_byte_array, &g_byte, 1);
1992 for (i = 0; i < gp_byte_array->len; i++)
1993 DBG("%02x", gp_byte_array->data[i]);
1996 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2000 g_byte_array_free(gp_byte_array, TRUE);
2001 g_variant_iter_free(iter);
2002 g_variant_unref(value);
2007 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2008 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2010 GDBusConnection *g_conn;
2011 hal_gatt_resp_data_t *resp_data;
2012 hal_gattc_service_t *gattc_service = NULL;
2013 GVariantBuilder *builder = NULL;
2015 hal_gattc_server_info_t * conn_info = NULL;
2016 hal_gattc_char_t *gattc_char = NULL;
2017 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2018 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2019 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2020 char* desc_handle = NULL;
2023 hal_gattc_desc_t *gattc_desc = NULL;
2025 /* get the connection info */
2026 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2027 if (NULL == conn_info) {
2028 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2029 return BT_STATUS_FAIL;
2033 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2034 if (NULL == gattc_service) {
2035 ERR("Failed to get the gatt service");
2036 return BT_STATUS_FAIL;
2039 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2040 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2042 /* find characteristic */
2043 /* service can have two char with same uuid */
2044 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2045 gattc_char = (hal_gattc_char_t*)l->data;
2046 if (gattc_char == NULL)
2049 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2050 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2051 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2053 /* find descriptor */
2054 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2056 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2057 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2063 if (NULL == gattc_desc) {
2064 ERR("Failed to get the gatt desc");
2065 return BT_STATUS_FAIL;
2068 g_conn = _bt_hal_get_system_gconn();
2069 if (NULL == g_conn) {
2070 ERR("_bt_gdbus_get_system_gconn returned NULL");
2071 return BT_STATUS_FAIL;
2074 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2075 resp_data->conn_id = conn_id;
2076 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2077 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2078 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2080 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2083 g_variant_builder_add(builder, "{sv}", "offset",
2084 g_variant_new("q", offset));
2086 desc_handle = gattc_desc->desc_path;
2088 DBG("calling desc read value");
2090 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2091 "ReadValue", g_variant_new("(a{sv})", builder),
2092 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2093 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2094 (gpointer)resp_data);
2095 g_variant_builder_unref(builder);
2097 return BT_STATUS_SUCCESS;
2100 /** Read the descriptor for a given characteristic */
2101 bt_status_t btif_read_descriptor(int conn_id,
2102 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2103 btgatt_gatt_id_t *descr_id, int auth_req)
2105 CHECK_BTGATT_INIT();
2107 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2110 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2112 struct hal_ev_gatt_client_write_result ev;
2115 ERR("gatt client callback not registered");
2119 memset(&ev, 0, sizeof(ev));
2120 ev.conn_id = resp_data->conn_id;
2121 ev.inst_id = resp_data->srvc_id.id.inst_id;
2122 ev.is_primary = resp_data->srvc_id.is_primary;
2125 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2126 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2127 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2129 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2131 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2134 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2135 GAsyncResult *res, gpointer user_data)
2137 GError *error = NULL;
2138 GDBusConnection *system_gconn = NULL;
2140 hal_gatt_resp_data_t *resp_data = user_data;
2141 int result = BT_STATUS_SUCCESS;
2145 system_gconn = _bt_hal_get_system_gconn();
2146 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2149 ERR("write descriptor dbus failed Error: [%s]", error->message);
2152 result = BT_STATUS_FAIL;
2153 __hal_send_desc_write_event(resp_data, result);
2154 g_clear_error(&error);
2159 //send write value event
2160 __hal_send_desc_write_event(resp_data, result);
2163 g_variant_unref(value);
2168 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2169 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2170 int write_type, int length, int auth_req, char* value)
2172 GVariant *val, *options;
2173 GVariantBuilder *builder1;
2174 GVariantBuilder *builder2;
2175 GDBusConnection *g_conn;
2178 hal_gatt_resp_data_t *resp_data;
2179 hal_gattc_service_t *gattc_service = NULL;
2180 hal_gattc_server_info_t * conn_info = NULL;
2181 hal_gattc_char_t *gattc_char = NULL;
2182 hal_gattc_desc_t *gattc_desc = NULL;
2183 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2184 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2185 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2186 char* desc_handle = NULL;
2187 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2188 int ret = BT_STATUS_SUCCESS;
2193 ret = __hal_get_write_prop(write_type, &write_prop);
2194 if (BT_STATUS_FAIL == ret) {
2195 ERR("received invalid write type:[%d] ", write_type);
2196 return BT_STATUS_FAIL;
2199 /* get the connection info */
2200 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2201 if (NULL == conn_info) {
2202 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2203 return BT_STATUS_FAIL;
2207 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2208 if (NULL == gattc_service) {
2209 ERR("Failed to get the gatt service");
2210 return BT_STATUS_FAIL;
2213 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2214 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2216 /* find characteristic */
2217 /* service can have two char with same uuid */
2218 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2219 gattc_char = (hal_gattc_char_t*)l->data;
2220 if (gattc_char == NULL)
2223 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2224 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2225 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2227 /* find descriptor */
2228 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2230 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2231 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2237 if (NULL == gattc_desc) {
2238 ERR("Failed to get the gatt desc");
2239 return BT_STATUS_FAIL;
2242 g_conn = _bt_hal_get_system_gconn();
2243 if (NULL == g_conn) {
2244 ERR("_bt_gdbus_get_system_gconn returned NULL");
2245 return BT_STATUS_FAIL;
2248 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2249 resp_data->conn_id = conn_id;
2250 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2251 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2252 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2254 desc_handle = gattc_desc->desc_path;
2256 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2258 for (i = 0; i < length; i++)
2259 g_variant_builder_add(builder1, "y", value[i]);
2261 val = g_variant_new("ay", builder1);
2263 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2265 g_variant_builder_add(builder2, "{sv}", "offset",
2266 g_variant_new_uint16(offset));
2268 options = g_variant_new("a{sv}", builder2);
2270 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2272 g_variant_new("(@ay@a{sv})", val, options),
2274 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2275 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2276 (gpointer)resp_data);
2278 g_variant_builder_unref(builder1);
2279 g_variant_builder_unref(builder2);
2281 return BT_STATUS_SUCCESS;
2284 /** Write a remote descriptor for a given characteristic */
2285 bt_status_t btif_write_descriptor(int conn_id,
2286 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2287 btgatt_gatt_id_t *descr_id, int write_type, int len,
2288 int auth_req, char* p_value)
2290 CHECK_BTGATT_INIT();
2292 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2293 len, auth_req, p_value);
2296 /** Execute a prepared write operation */
2297 bt_status_t execute_write(int conn_id, int execute)
2299 CHECK_BTGATT_INIT();
2300 return BT_STATUS_UNSUPPORTED;
2303 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2305 struct hal_ev_gatt_client_watch_notification ev;
2306 hal_gatt_resp_data_t *resp_data = user_data;
2308 DBG("sending the watch register notification event");
2309 /* send the event */
2310 memset(&ev, 0, sizeof(ev));
2311 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2313 ev.status = resp_data->result;
2315 ev.is_primary = resp_data->srvc_id.is_primary;
2316 ev.inst_id = resp_data->srvc_id.id.inst_id;
2318 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2319 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2322 ERR("GATT Callback not registered");
2324 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2331 static bt_status_t _hal_register_for_notification(int client_if,
2332 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2333 btgatt_gatt_id_t *char_id)
2335 int result = BT_STATUS_SUCCESS;
2336 GError *error = NULL;
2337 GDBusConnection *g_conn;
2338 hal_gattc_client_info_t *gattc_client = NULL;
2339 hal_gattc_server_info_t * conn_info = NULL;
2340 hal_gattc_service_t *gattc_service = NULL;
2341 hal_gattc_char_t *gattc_char = NULL;
2342 char* char_handle = NULL;
2343 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2344 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2345 hal_gatt_resp_data_t *resp_data;
2349 gattc_client = __bt_find_gatt_client_info(bd_addr);
2350 if (gattc_client == NULL) {
2351 ERR("failed to get the gatt client info");
2352 return BT_STATUS_FAIL;
2355 if (gattc_client->client_if != client_if) {
2356 ERR("could not find the gatt client for client id[%d]", client_if);
2357 return BT_STATUS_FAIL;
2360 /* get the connection info */
2361 conn_info = __bt_find_gatt_conn_info(bd_addr);
2362 if (NULL == conn_info) {
2363 ERR("Failed to get the conn_info");
2364 return BT_STATUS_FAIL;
2367 if (conn_info->inst_id != gattc_client->inst_id) {
2368 ERR("could not fild the conn_info");
2369 return BT_STATUS_FAIL;
2373 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2374 if (NULL == gattc_service) {
2375 ERR("Failed to get the gatt service");
2376 return BT_STATUS_FAIL;
2379 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2380 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2383 /* find characteristic */
2384 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2385 if (NULL == gattc_char) {
2386 ERR("Failed to get the gatt char");
2387 return BT_STATUS_FAIL;
2390 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2391 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2393 char_handle = gattc_char->chr_path;
2395 g_conn = _bt_hal_get_system_gconn();
2396 if (g_conn == NULL) {
2398 return BT_STATUS_FAIL;
2401 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2403 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2405 g_dbus_connection_call_sync(g_conn,
2408 BT_HAL_GATT_CHAR_INTERFACE,
2412 G_DBUS_CALL_FLAGS_NONE,
2413 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2416 g_dbus_error_strip_remote_error(error);
2417 ERR("### StartNotify Failed: %s", error->message);
2418 if (g_strrstr(error->message, "Already notifying"))
2419 result = BT_STATUS_SUCCESS;
2420 else if (g_strrstr(error->message, "In Progress"))
2421 result = BT_STATUS_BUSY;
2422 else if (g_strrstr(error->message, "Operation is not supported"))
2423 result = BT_STATUS_UNSUPPORTED;
2424 /*failed because of either Insufficient Authorization or Write Not Permitted */
2425 else if (g_strrstr(error->message, "Write not permitted") ||
2426 g_strrstr(error->message, "Operation Not Authorized"))
2427 result = BT_STATUS_AUTH_FAILURE;
2428 /* failed because of either Insufficient Authentication,
2429 Insufficient Encryption Key Size, or Insufficient Encryption. */
2430 else if (g_strrstr(error->message, "Not paired"))
2431 result = BT_STATUS_NOT_READY;
2433 result = BT_STATUS_FAIL;
2435 g_clear_error(&error);
2438 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2439 resp_data->result = result;
2440 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2441 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2443 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2447 return BT_STATUS_SUCCESS;
2451 * Register to receive notifications or indications for a given
2454 bt_status_t btif_register_for_notification(int client_if,
2455 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2456 btgatt_gatt_id_t *char_id)
2458 CHECK_BTGATT_INIT();
2460 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2463 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2465 struct hal_ev_gatt_client_watch_notification ev;
2466 hal_gatt_resp_data_t *resp_data = user_data;
2468 DBG("sending the watch deregister notification event");
2469 /* send the event */
2470 memset(&ev, 0, sizeof(ev));
2471 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2473 ev.status = resp_data->result;
2475 ev.is_primary = resp_data->srvc_id.is_primary;
2476 ev.inst_id = resp_data->srvc_id.id.inst_id;
2478 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2479 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2482 ERR("GATT Callback not registered");
2484 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2491 static bt_status_t _hal_deregister_for_notification(int client_if,
2492 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2493 btgatt_gatt_id_t *char_id)
2495 int result = BT_STATUS_SUCCESS;
2496 GError *error = NULL;
2497 GDBusConnection *g_conn;
2498 hal_gattc_client_info_t *gattc_client = NULL;
2499 hal_gattc_server_info_t * conn_info = NULL;
2500 hal_gattc_service_t *gattc_service = NULL;
2501 hal_gattc_char_t *gattc_char = NULL;
2502 char* char_handle = NULL;
2503 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2504 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2505 hal_gatt_resp_data_t *resp_data;
2509 gattc_client = __bt_find_gatt_client_info(bd_addr);
2510 if (gattc_client == NULL) {
2511 ERR("failed to get the gatt client info");
2512 return BT_STATUS_FAIL;
2515 if (gattc_client->client_if != client_if) {
2516 ERR("could not find the gatt client for client id[%d]", client_if);
2517 return BT_STATUS_FAIL;
2520 /* get the connection info */
2521 conn_info = __bt_find_gatt_conn_info(bd_addr);
2522 if (NULL == conn_info) {
2523 ERR("Failed to get the conn_info");
2524 return BT_STATUS_FAIL;
2527 if (conn_info->inst_id != gattc_client->inst_id) {
2528 ERR("could not fild the conn_info");
2529 return BT_STATUS_FAIL;
2533 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2534 if (NULL == gattc_service) {
2535 ERR("Failed to get the gatt service");
2536 return BT_STATUS_FAIL;
2539 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2540 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2543 /* find characteristic */
2544 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2545 if (NULL == gattc_char) {
2546 ERR("Failed to get the gatt char");
2547 return BT_STATUS_FAIL;
2550 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2551 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2553 char_handle = gattc_char->chr_path;
2555 g_conn = _bt_hal_get_system_gconn();
2556 if (g_conn == NULL) {
2558 return BT_STATUS_FAIL;
2561 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2563 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2564 g_dbus_connection_call_sync(g_conn,
2567 BT_HAL_GATT_CHAR_INTERFACE,
2571 G_DBUS_CALL_FLAGS_NONE,
2572 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2575 ERR("### StopNotify Failed: %s", error->message);
2576 g_clear_error(&error);
2577 result = BT_STATUS_FAIL;
2580 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2581 resp_data->result = result;
2582 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2583 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2585 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2589 return BT_STATUS_SUCCESS;
2591 /** Deregister a previous request for notifications/indications */
2592 bt_status_t btif_deregister_for_notification(int client_if,
2593 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2594 btgatt_gatt_id_t *char_id)
2596 CHECK_BTGATT_INIT();
2597 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2600 /** Request RSSI for a given remote device */
2601 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2603 CHECK_BTGATT_INIT();
2604 return BT_STATUS_UNSUPPORTED;
2607 /** OTA firmware download */
2608 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2610 CHECK_BTGATT_INIT();
2611 return BT_STATUS_UNSUPPORTED;
2614 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2615 int get_device_type(const bt_bdaddr_t *bd_addr)
2617 CHECK_BTGATT_INIT();
2618 return BT_STATUS_UNSUPPORTED;
2621 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2622 int min_int, int max_int, int latency, int timeout)
2624 gchar *device_path = NULL;
2625 GError *error = NULL;
2626 GDBusProxy *device_proxy = NULL;
2627 GDBusConnection *conn;
2629 int ret = BT_STATUS_SUCCESS;
2630 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2632 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2633 min_int, max_int, latency, timeout);
2635 conn = _bt_hal_get_system_gconn();
2638 return BT_STATUS_FAIL;
2641 _bt_hal_convert_addr_type_to_string(device_address,
2642 (unsigned char *)bd_addr->address);
2643 device_path = _bt_hal_get_device_object_path(device_address);
2645 if (device_path == NULL) {
2646 ERR("device_path NULL : [%s]", device_address);
2647 return BT_STATUS_FAIL;
2650 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2651 NULL, BT_HAL_BLUEZ_NAME,
2652 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2654 g_free(device_path);
2655 if (NULL == device_proxy) {
2656 ERR("device_proxy returned NULL");
2657 return BT_STATUS_FAIL;
2660 INFO("Request LeConnUpdate");
2661 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2662 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2663 G_DBUS_CALL_FLAGS_NONE,
2668 g_object_unref(device_proxy);
2669 if (reply == NULL) {
2671 ERR("Error %s[%s]", error->message, device_address);
2672 if (g_strrstr(error->message, "In Progress"))
2673 ret = BT_STATUS_SUCCESS;
2675 ret = BT_STATUS_FAIL;
2676 g_error_free(error);
2680 g_variant_unref(reply);
2682 DBG("LE Connection parameter Updated");
2686 /** Request a connection parameter update */
2687 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2689 CHECK_BTGATT_INIT();
2691 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2694 /** Test mode interface */
2695 bt_status_t test_command(int command, btgatt_test_params_t* params)
2697 CHECK_BTGATT_INIT();
2698 return BT_STATUS_UNSUPPORTED;
2701 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2704 GError *g_error = NULL;
2705 GVariant *reply = NULL;
2706 int result = BT_STATUS_SUCCESS;
2707 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2708 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2710 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2711 g_object_unref(proxy);
2712 if (reply == NULL) {
2713 ERR("Connect LE Dbus Call Error");
2715 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2716 g_clear_error(&g_error);
2718 result = BT_STATUS_FAIL;
2720 g_variant_unref(reply);
2722 memset(&ev, 0, sizeof(ev));
2724 ev.mtu = conn_mtu->mtu;
2725 ev.conn_id = conn_mtu->conn_id;
2728 ERR("gatt client callback not registered");
2730 DBG("sending gatt client MTU exchange completed event");
2731 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2738 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2740 gchar *device_path = NULL;
2741 GDBusProxy *device_proxy = NULL;
2742 GDBusConnection *conn;
2743 hal_gattc_client_info_t *gattc_client = NULL;
2744 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2745 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2747 conn = _bt_hal_get_system_gconn();
2750 return BT_STATUS_FAIL;
2753 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2754 if (gattc_client == NULL) {
2755 INFO("GATT client conn info not found");
2756 return BT_STATUS_FAIL;
2759 _bt_hal_convert_addr_type_to_string(device_address,
2760 (unsigned char *)gattc_client->bd_addr.address);
2762 device_path = _bt_hal_get_device_object_path(device_address);
2763 if (device_path == NULL) {
2764 ERR("device_path NULL : [%s]", device_address);
2765 return BT_STATUS_FAIL;
2768 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2769 NULL, BT_HAL_BLUEZ_NAME,
2770 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2772 g_free(device_path);
2773 if (NULL == device_proxy) {
2774 ERR("device_proxy returned NULL");
2775 return BT_STATUS_FAIL;
2778 conn_mtu->conn_id = conn_id;
2779 conn_mtu->mtu = mtu;
2781 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2782 g_variant_new("(q)", mtu),
2783 G_DBUS_CALL_FLAGS_NONE,
2784 BT_HAL_MAX_DBUS_TIMEOUT,
2786 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2789 return BT_STATUS_SUCCESS;
2792 /** MTU Exchange request from client */
2793 static bt_status_t configure_mtu(int conn_id, int mtu)
2795 CHECK_BTGATT_INIT();
2797 return __hal_configure_mtu(conn_id, mtu);
2800 /** Setup scan filter params */
2801 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2802 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2803 int rssi_low_thres, int dely_mode, int found_timeout,
2804 int lost_timeout, int found_timeout_cnt)
2807 GError *error = NULL;
2808 GVariant *ret, *param;
2809 CHECK_BTGATT_INIT();
2811 proxy = _bt_hal_get_adapter_proxy();
2814 return BT_STATUS_FAIL;
2816 param = g_variant_new("(iiiiiiiiiiii)",
2829 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2830 param, G_DBUS_CALL_FLAGS_NONE,
2834 ERR("scan_filter_param_setup Fail: %s", error->message);
2835 g_clear_error(&error);
2836 return BT_STATUS_FAIL;
2840 g_variant_unref(ret);
2842 return BT_STATUS_SUCCESS;
2845 /** Configure a scan filter condition */
2846 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2847 int filt_index, int company_id,
2848 int company_id_mask, const bt_uuid_t *p_uuid,
2849 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2850 char addr_type, int data_len, char* p_data, int mask_len,
2854 GError *error = NULL;
2855 GVariant *ret, *param;
2856 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2857 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2858 GArray *arr_uuid = NULL;
2859 GArray *arr_uuid_mask = NULL;
2860 GArray *arr_data = NULL;
2861 GArray *arr_data_mask = NULL;
2862 CHECK_BTGATT_INIT();
2864 proxy = _bt_hal_get_adapter_proxy();
2867 return BT_STATUS_FAIL;
2869 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2871 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2873 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2875 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2877 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2878 NULL, 0, TRUE, NULL, NULL);
2879 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2880 NULL, 0, TRUE, NULL, NULL);
2881 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2882 NULL, 0, TRUE, NULL, NULL);
2883 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2884 NULL, 0, TRUE, NULL, NULL);
2886 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2887 client_if, // client_if
2888 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2889 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2890 filt_index, // filter_index
2891 company_id, // company_id
2892 company_id_mask, // company_id_mask
2893 arr_uuid_param, // p_uuid
2894 arr_uuid_mask_param, // p_uuid_mask
2896 addr_type, // address_type
2897 arr_data_param, // p_data
2898 arr_data_mask_param); // p_mask
2900 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2901 param, G_DBUS_CALL_FLAGS_NONE,
2905 ERR("scan_filter_add_remove Fail: %s", error->message);
2906 g_clear_error(&error);
2907 return BT_STATUS_FAIL;
2911 g_variant_unref(ret);
2913 return BT_STATUS_SUCCESS;
2916 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2918 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2919 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2920 NULL, 0, TRUE, NULL, NULL);
2921 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2922 NULL, 0, TRUE, NULL, NULL);
2923 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2924 NULL, 0, TRUE, NULL, NULL);
2925 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2926 NULL, 0, TRUE, NULL, NULL);
2928 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2929 client_if, // client_if
2930 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2931 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2932 filt_index, // filter_index
2933 company_id, // company_id
2934 company_id_mask, // company_id_mask
2935 arr_uuid_param, // p_uuid
2936 arr_uuid_mask_param, // p_uuid_mask
2938 addr_type, // address_type
2939 arr_data_param, // p_data
2940 arr_data_mask_param);
2942 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2943 param, G_DBUS_CALL_FLAGS_NONE,
2947 ERR("scan_filter_add_remove Fail: %s", error->message);
2948 g_clear_error(&error);
2949 return BT_STATUS_FAIL;
2953 g_variant_unref(ret);
2955 return BT_STATUS_SUCCESS;
2958 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2960 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2961 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2963 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2964 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2966 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2967 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2968 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2969 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2970 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2971 NULL, 0, TRUE, NULL, NULL);
2972 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2973 NULL, 0, TRUE, NULL, NULL);
2975 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2976 client_if, // client_if
2977 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2978 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
2979 filt_index, // filter_index
2980 company_id, // company_id
2981 company_id_mask, // company_id_mask
2982 arr_uuid_param, // p_uuid
2983 arr_uuid_mask_param, // p_uuid_mask
2985 addr_type, // address_type
2986 arr_data_param, // p_data
2987 arr_data_mask_param);
2989 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2990 param, G_DBUS_CALL_FLAGS_NONE,
2994 ERR("scan_filter_add_remove Fail: %s", error->message);
2995 g_clear_error(&error);
2996 return BT_STATUS_FAIL;
3000 g_variant_unref(ret);
3002 g_array_free(arr_uuid, TRUE);
3003 g_array_free(arr_uuid_mask, TRUE);
3005 return BT_STATUS_SUCCESS;
3008 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3010 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3011 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3013 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3014 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3016 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3017 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3018 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3019 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3020 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3021 NULL, 0, TRUE, NULL, NULL);
3022 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3023 NULL, 0, TRUE, NULL, NULL);
3025 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3026 client_if, // client_if
3027 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3028 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3029 filt_index, // filter_index
3030 company_id, // company_id
3031 company_id_mask, // company_id_mask
3032 arr_uuid_param, // p_uuid
3033 arr_uuid_mask_param, // p_uuid_mask
3035 addr_type, // address_type
3036 arr_data_param, // p_data
3037 arr_data_mask_param);
3039 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3040 G_DBUS_CALL_FLAGS_NONE,
3044 ERR("scan_filter_add_remove Fail: %s", error->message);
3045 g_clear_error(&error);
3046 return BT_STATUS_FAIL;
3050 g_variant_unref(ret);
3052 g_array_free(arr_uuid, TRUE);
3053 g_array_free(arr_uuid_mask, TRUE);
3055 return BT_STATUS_SUCCESS;
3058 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3060 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3061 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3063 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3064 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3066 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3067 NULL, 0, TRUE, NULL, NULL);
3068 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3069 NULL, 0, TRUE, NULL, NULL);
3070 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3071 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3072 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3073 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3075 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3076 client_if, // client_if
3077 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3078 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3079 filt_index, // filter_index
3080 company_id, // company_id
3081 company_id_mask, // company_id_mask
3082 arr_uuid_param, // p_uuid
3083 arr_uuid_mask_param, // p_uuid_mask
3085 addr_type, // address_type
3086 arr_data_param, // p_data
3087 arr_data_mask_param);
3089 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3090 G_DBUS_CALL_FLAGS_NONE,
3094 ERR("scan_filter_add_remove Fail: %s", error->message);
3095 g_clear_error(&error);
3096 return BT_STATUS_FAIL;
3100 g_variant_unref(ret);
3102 g_array_free(arr_data, TRUE);
3103 g_array_free(arr_data_mask, TRUE);
3105 return BT_STATUS_SUCCESS;
3108 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3110 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3111 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3113 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3114 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3116 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3117 NULL, 0, TRUE, NULL, NULL);
3118 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3119 NULL, 0, TRUE, NULL, NULL);
3120 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3121 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3122 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3123 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3125 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3126 client_if, // client_if
3127 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3128 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3129 filt_index, // filter_index
3130 company_id, // company_id
3131 company_id_mask, // company_id_mask
3132 arr_uuid_param, // p_uuid
3133 arr_uuid_mask_param, // p_uuid_mask
3135 addr_type, // address_type
3136 arr_data_param, // p_data
3137 arr_data_mask_param);
3139 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3140 G_DBUS_CALL_FLAGS_NONE,
3144 ERR("scan_filter_add_remove Fail: %s", error->message);
3145 g_clear_error(&error);
3146 return BT_STATUS_FAIL;
3150 g_variant_unref(ret);
3152 g_array_free(arr_data, TRUE);
3153 g_array_free(arr_data_mask, TRUE);
3155 return BT_STATUS_SUCCESS;
3158 return BT_STATUS_UNSUPPORTED;
3161 /** Clear all scan filter conditions for specific filter index*/
3162 bt_status_t scan_filter_clear(int client_if, int filt_index)
3165 GError *error = NULL;
3167 CHECK_BTGATT_INIT();
3169 proxy = _bt_hal_get_adapter_proxy();
3171 return BT_STATUS_FAIL;
3173 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3174 g_variant_new("(ii)", client_if, filt_index),
3175 G_DBUS_CALL_FLAGS_NONE,
3179 ERR("scan_filter_clear Fail: %s", error->message);
3180 g_clear_error(&error);
3181 return BT_STATUS_FAIL;
3184 g_variant_unref(ret);
3185 return BT_STATUS_SUCCESS;
3188 /** Enable / disable scan filter feature*/
3189 bt_status_t scan_filter_enable(int client_if, bool enable)
3192 GError *error = NULL;
3194 CHECK_BTGATT_INIT();
3196 proxy = _bt_hal_get_adapter_proxy();
3198 return BT_STATUS_FAIL;
3200 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3201 g_variant_new("(ib)", client_if, enable),
3202 G_DBUS_CALL_FLAGS_NONE,
3206 ERR("scan_filter_enable Fail: %s", error->message);
3207 g_clear_error(&error);
3208 return BT_STATUS_FAIL;
3210 g_variant_unref(ret);
3212 return BT_STATUS_SUCCESS;
3215 /** Sets the LE scan interval and window in units of N*0.625 msec */
3217 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3221 CHECK_BTGATT_INIT();
3223 le_scan_type = scan_type;
3224 ret = _bt_hal_adapter_le_set_scan_parameters(
3225 scan_type, scan_interval, scan_window);
3229 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3231 CHECK_BTGATT_INIT();
3232 return BT_STATUS_UNSUPPORTED;
3236 /* Configure the batchscan storage */
3237 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3238 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3240 CHECK_BTGATT_INIT();
3241 return BT_STATUS_UNSUPPORTED;
3244 /* Enable batchscan */
3245 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3246 int scan_interval, int scan_window, int addr_type, int discard_rule)
3248 CHECK_BTGATT_INIT();
3249 return BT_STATUS_UNSUPPORTED;
3252 /* Disable batchscan */
3253 bt_status_t batchscan_dis_batch_scan(int client_if)
3255 CHECK_BTGATT_INIT();
3256 return BT_STATUS_UNSUPPORTED;
3259 /* Read out batchscan reports */
3260 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3262 CHECK_BTGATT_INIT();
3263 return BT_STATUS_UNSUPPORTED;
3266 const btgatt_client_interface_t btgatt_client_interface = {
3267 .register_client = btif_gattc_register_client,
3268 .unregister_client = btif_gattc_unregister_client,
3270 .connect = btif_gattc_client_connect,
3271 .disconnect = btif_gattc_client_disconnect,
3273 .search_service = btif_gattc_client_search_service,
3274 .get_included_service = get_included_service,
3275 .get_characteristic = btif_gattc_get_characteristic,
3276 .get_descriptor = btif_gattc_get_descriptor,
3277 .read_characteristic = btif_read_characteristic,
3278 .write_characteristic = btif_write_characteristic,
3279 .acquire_write = btif_get_acquire_write_fd,
3280 .acquire_notify = btif_get_acquire_notify_fd,
3281 .read_descriptor = btif_read_descriptor,
3282 .write_descriptor = btif_write_descriptor,
3283 .execute_write = execute_write,
3284 .register_for_notification = btif_register_for_notification,
3285 .deregister_for_notification = btif_deregister_for_notification,
3286 .read_remote_rssi = read_remote_rssi,
3287 .ota_fw_update = ota_fw_update,
3288 .get_device_type = get_device_type,
3289 .conn_parameter_update = btif_gattc_conn_parameter_update,
3290 .test_command = test_command,
3291 .configure_mtu = configure_mtu,
3292 .scan_filter_param_setup = scan_filter_param_setup,
3293 .scan_filter_add_remove = scan_filter_add_remove,
3294 .scan_filter_clear = scan_filter_clear,
3295 .scan_filter_enable = scan_filter_enable,
3296 .set_scan_parameters = set_scan_parameters,
3297 .batchscan_cfg_storage = batchscan_cfg_storage,
3298 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3299 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3300 .batchscan_read_reports = batchscan_read_reports,
3301 .add_connection_info = btif_gattc_add_connection_info,
3304 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3307 hal_gattc_server_info_t *info = NULL;
3309 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3310 info = (hal_gattc_server_info_t*)l->data;
3314 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3321 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3324 hal_gattc_client_info_t *info = NULL;
3326 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3327 info = (hal_gattc_client_info_t*)l->data;
3331 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3338 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3341 hal_gattc_client_info_t *info = NULL;
3343 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3344 info = (hal_gattc_client_info_t*)l->data;
3348 if (info->conn_id == conn_id)
3355 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3358 hal_gattc_server_info_t *info = NULL;
3359 hal_gattc_client_info_t *gattc_client = NULL;
3361 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3362 if (gattc_client == NULL) {
3363 ERR("GATT client conn info not found");
3367 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3368 info = (hal_gattc_server_info_t*)l->data;
3372 if ((info->inst_id == gattc_client->inst_id) &&
3373 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3380 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3381 gboolean auto_connect)
3383 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3384 gchar *device_path = NULL;
3385 GDBusProxy *device_proxy = NULL;
3386 GDBusConnection *conn;
3387 int ret = BT_STATUS_SUCCESS;
3388 hal_gattc_client_info_t *gattc_data;
3390 if (NULL == bd_addr) {
3391 ERR("bd_addr is NULL");
3392 return BT_STATUS_PARM_INVALID;
3395 conn = _bt_hal_get_system_gconn();
3397 ERR("_bt_gdbus_get_system_gconn returned NULL");
3398 return BT_STATUS_FAIL;
3401 _bt_hal_convert_addr_type_to_string(device_address,
3402 (unsigned char *)bd_addr->address);
3403 device_path = _bt_hal_get_device_object_path(device_address);
3404 if (device_path == NULL) {
3405 ERR("device_path NULL : [%s]", device_address);
3406 ret = BT_STATUS_FAIL;
3410 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3411 NULL, BT_HAL_BLUEZ_NAME,
3412 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3413 g_free(device_path);
3414 if (NULL == device_proxy) {
3415 ERR("device_proxy returned NULL");
3416 return BT_STATUS_FAIL;
3419 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3420 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3421 BT_HAL_ADDRESS_LENGTH_MAX);
3423 DBG("ConnectLE [%s]", device_address);
3425 gattc_data->client_if = client_if;
3427 g_dbus_proxy_call(device_proxy, "ConnectLE",
3428 g_variant_new("(b)", auto_connect),
3429 G_DBUS_CALL_FLAGS_NONE,
3430 BT_HAL_MAX_DBUS_TIMEOUT,
3432 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3437 static bt_status_t _bt_hold_current_advertising()
3439 int ret = BT_STATUS_FAIL;
3440 gboolean is_advertising = FALSE;
3443 is_advertising = _bt_hal_is_advertising_in_slot(0);
3444 if (is_advertising) {
3445 DBG("+ Stop current advertising");
3447 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3448 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3454 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3456 DBG("+ start current advertising");
3458 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3463 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3465 DBG("Try to initiate pending LE connection");
3467 pending_le_conn_timer_id = 0;
3469 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3470 &pending_le_conn_info->bd_addr,
3471 pending_le_conn_info->auto_connect);
3473 g_free(pending_le_conn_info);
3474 pending_le_conn_info = NULL;
3479 static int __hal_generate_conn_id()
3481 return ++bt_conn_id;
3484 static int __hal_generate_server_instance_id()
3486 return ++bt_inst_id;
3489 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3492 GError *g_error = NULL;
3493 GVariant *reply = NULL;
3494 hal_gattc_client_info_t *gattc_data = user_data;
3495 int result = BT_STATUS_SUCCESS;
3496 struct hal_ev_gatt_client_connected ev;
3497 hal_gattc_server_info_t *gatt_conn_info = NULL;
3499 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3500 g_object_unref(proxy);
3501 if (reply == NULL) {
3502 ERR("Connect LE Dbus Call Error");
3504 ERR("Error: %s\n", g_error->message);
3505 g_clear_error(&g_error);
3507 result = BT_STATUS_FAIL;
3509 g_variant_unref(reply);
3511 if (NULL == gattc_data) {
3512 ERR("gattc_data is NULL");
3517 if (result == BT_STATUS_FAIL) {
3518 memset(&ev, 0, sizeof(ev));
3521 ev.client_if = gattc_data->client_if;
3522 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3523 BT_HAL_ADDRESS_LENGTH_MAX);
3526 ERR("gatt client callback not registered");
3528 DBG("sending gatt client connected event");
3529 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3535 DBG("LE connected. Adding the gattc server/client conn info in list");
3536 gattc_data->conn_id = __hal_generate_conn_id() ;
3537 gattc_data->inst_id = __hal_generate_server_instance_id();
3539 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3541 /*add gatt server connection info*/
3542 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3543 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3544 gatt_conn_info->conn_id = gattc_data->conn_id;
3545 gatt_conn_info->inst_id = gattc_data->inst_id;
3546 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3551 /*remove conn_info*/
3556 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3558 g_free(desc_info->desc_path);
3562 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3565 hal_gattc_desc_t *desc_info = NULL;
3566 for (l = char_info->gatt_list_descs; l != NULL; ) {
3567 desc_info = l->data;
3568 l = g_slist_next(l);
3569 if (desc_info == NULL)
3571 /* Remove descriptor element */
3572 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3573 __hal_gattc_free_desc_info(desc_info);
3575 g_slist_free(char_info->gatt_list_descs);
3576 g_free(char_info->chr_path);
3580 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3583 hal_gattc_char_t *char_info = NULL;
3584 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3585 char_info = l->data;
3586 l = g_slist_next(l);
3587 if (char_info == NULL)
3589 /* Remove characteristic element */
3590 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3591 __hal_gattc_free_char_info(char_info);
3593 g_slist_free(svc_info->gatt_list_chars);
3594 g_free(svc_info->svc_path);
3598 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3601 hal_gattc_service_t *svc_info = NULL;
3605 for (l = conn_info->gatt_list_services; l != NULL; ) {
3606 svc_info = (hal_gattc_service_t *)l->data;
3607 l = g_slist_next(l);
3608 if (svc_info == NULL)
3610 /* Remove service element */
3611 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3612 __hal_gattc_free_svc_info(svc_info);
3614 g_slist_free(conn_info->gatt_list_services);
3618 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3620 bt_bdaddr_t bd_addr;
3621 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3622 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3628 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3630 int result = BT_STATUS_SUCCESS;
3631 struct hal_ev_gatt_client_connected ev;
3632 hal_gattc_server_info_t *conn_info = NULL;
3633 bt_bdaddr_t bd_addr;
3635 hal_gattc_client_info_t *gattc_client = NULL;
3639 DBG("+ connected device address [%s]", address);
3641 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3642 HAL_EV_GATT_CLIENT_DISCONNECTED;
3644 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3645 /* find the gatt client info */
3646 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3647 if (NULL == gattc_client) {
3648 ERR("Fail to get gatt client info");
3653 memset(&ev, 0, sizeof(ev));
3654 ev.conn_id = gattc_client->conn_id;
3656 ev.client_if = gattc_client->client_if;
3657 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3658 BT_HAL_ADDRESS_LENGTH_MAX);
3661 ERR("gatt client callback not registered");
3663 event_cb(event, (void *)&ev, sizeof(ev));
3666 if (!gatt_connected) {
3667 inst_id = gattc_client->inst_id;
3669 /* remove the gatt client info from the client list also*/
3670 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3671 g_free(gattc_client);
3673 //find the connected server info
3674 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3675 if (NULL == conn_info) {
3676 ERR("Fail to get gatt server info");
3680 if (inst_id != conn_info->inst_id) {
3681 ERR("server instance is different");
3685 //remove gatt conn info from the server list
3686 DBG("remove the server conn_info from list after gatt disconnection");
3687 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3688 __hal_clean_gattc_server_info(conn_info);
3694 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3695 const char* uuid_str, int inst_id)
3697 struct hal_ev_gatt_client_search_result ev;
3700 ERR("gatt client callback not registered");
3704 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3706 memset(&ev, 0, sizeof(ev));
3707 ev.conn_id = conn_id;
3708 ev.inst_id = inst_id;
3709 ev.is_primary = is_primary;
3710 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3712 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3715 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3717 struct hal_ev_gatt_client_search_complete ev;
3720 ERR("gatt client callback not registered");
3724 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3727 memset(&ev, 0, sizeof(ev));
3728 ev.conn_id = conn_id;
3731 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3734 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3735 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3736 char *char_value, int len)
3738 struct hal_ev_gatt_client_notify_changed_value ev;
3739 hal_gattc_client_info_t *gattc_client = NULL;
3742 ERR("gatt client callback not registered");
3746 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3747 if (NULL == gattc_client) {
3748 ERR("failed to get the gatt client info");
3753 DBG("sending gatt client connected status event");
3754 memset(&ev, 0, sizeof(ev));
3756 ev.conn_id = gattc_client->conn_id;
3757 ev.inst_id = conn_info->inst_id;
3758 ev.is_primary = svc_info->is_primary;
3759 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3760 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3762 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3764 if (len > 0 && (char_value != NULL)) {
3765 memcpy(ev.value, char_value, len);
3769 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3772 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3773 char *char_value, int len)
3775 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3776 hal_gattc_server_info_t *conn_info = NULL;
3777 bt_bdaddr_t bd_addr;
3780 hal_gattc_service_t *svc_info = NULL;
3781 hal_gattc_char_t *char_info = NULL;
3785 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3786 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3787 DBG("device address:[%s]", device_address);
3788 DBG("char handle:[%s]", char_handle);
3790 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3791 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3793 if (conn_info != NULL) {
3794 //find service for notified char path
3795 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3796 svc_info = (hal_gattc_service_t*)l->data;
3797 if (svc_info == NULL)
3800 /* find characteristic object path */
3801 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3802 char_info = (hal_gattc_char_t *)k->data;
3803 if (char_info == NULL)
3806 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3807 DBG("Found char handle[%s]", char_info->chr_path);
3810 _bt_hal_send_value_changed_event(conn_info, svc_info,
3811 char_info, char_value, len);
3819 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3821 GDBusConnection *g_conn = NULL;
3822 GDBusProxy *properties_proxy = NULL;
3823 GVariant *result = NULL;
3824 GError *error = NULL;
3825 GVariantIter *property_iter = NULL;
3826 const gchar *key = NULL;
3827 GVariant *value = NULL;
3828 const char *uuid_str = NULL;
3830 gboolean is_primary = FALSE;
3831 GVariantIter *char_iter = NULL;
3832 const char *char_handle = NULL;
3833 GPtrArray *gp_char_array = NULL;
3835 if (service_path == NULL) {
3836 ERR("service_path is NULL");
3837 return BT_STATUS_FAIL;
3840 DBG("service_path: %s", service_path);
3842 g_conn = _bt_hal_get_system_gconn();
3843 if (g_conn == NULL) {
3844 ERR("g_conn is NULL");
3845 return BT_STATUS_FAIL;
3848 properties_proxy = g_dbus_proxy_new_sync(g_conn,
3849 G_DBUS_PROXY_FLAGS_NONE, NULL,
3852 BT_HAL_PROPERTIES_INTERFACE,
3854 if (properties_proxy == NULL) {
3855 ERR("properties_proxy is NULL");
3856 return BT_STATUS_FAIL;
3859 result = g_dbus_proxy_call_sync(properties_proxy,
3861 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
3862 G_DBUS_CALL_FLAGS_NONE,
3864 if (result == NULL) {
3865 if (error != NULL) {
3866 ERR("Fail to get properties (Error: %s)", error->message);
3867 g_clear_error(&error);
3869 ERR("Fail to get properties");
3871 g_object_unref(properties_proxy);
3872 return BT_STATUS_FAIL;
3875 g_variant_get(result, "(a{sv})", &property_iter);
3877 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
3878 if (g_strcmp0(key, "UUID") == 0) {
3879 uuid_str = g_variant_get_string(value, &len);
3880 } else if (g_strcmp0(key, "Primary") == 0) {
3881 is_primary = g_variant_get_boolean(value);
3882 } else if (g_strcmp0(key, "Characteristics") == 0) {
3883 g_variant_get(value, "ao", &char_iter);
3884 if (char_iter != NULL) {
3885 gp_char_array = g_ptr_array_new();
3886 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
3887 DBG("char_handle: %s", char_handle);
3888 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
3890 g_variant_iter_free(char_iter);
3895 if (uuid_str == NULL || gp_char_array == NULL) {
3896 ERR("uuid_str and gp_char_array should be set");
3900 /* Create new service */
3901 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
3904 g_variant_iter_free(property_iter);
3905 g_variant_unref(result);
3906 g_object_unref(properties_proxy);
3908 return BT_STATUS_SUCCESS;
3911 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
3913 GDBusConnection *conn = NULL;
3914 GDBusProxy *proxy = NULL;
3916 GVariant *ret = NULL;
3917 GVariant *value = NULL;
3919 conn = _bt_hal_get_system_gconn();
3921 ERR("_bt_gdbus_get_system_gconn returned NULL");
3925 proxy = g_dbus_proxy_new_sync(conn,
3926 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
3927 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
3928 if (proxy == NULL) {
3929 ERR("device_proxy returned NULL");
3933 ret = g_dbus_proxy_call_sync(proxy, "Get",
3934 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
3935 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3937 ERR("DBus Error : %s", err->message);
3938 g_clear_error(&err);
3940 g_variant_get(ret, "(v)", &value);
3941 *service_uuid = g_variant_dup_string(value, NULL);
3942 g_variant_unref(value);
3943 g_variant_unref(ret);
3947 g_object_unref(proxy);
3952 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
3954 struct hal_ev_gatt_client_service_changed ev = {0, };
3955 char address[BT_HAL_ADDRESS_STRING_SIZE];
3956 hal_gattc_server_info_t *server_info = NULL;
3957 hal_gattc_service_t *service = NULL;
3958 GSList *list = NULL;
3959 char *uuid_str = NULL;
3961 _bt_hal_convert_device_path_to_address(path, address);
3962 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
3963 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
3964 if (server_info == NULL) {
3965 ERR("service_info is NULL");
3970 /* Get service UUID from path */
3971 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
3973 DBG("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
3974 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3977 ERR("uuid_str is NULL");
3981 /* Create new service and append into the list */
3982 __hal_gattc_get_service_info(server_info, path);
3984 /* Find service UUID from path */
3985 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
3986 service = (hal_gattc_service_t *)list->data;
3987 if (service == NULL)
3990 if (g_strcmp0(service->svc_path, path) == 0) {
3991 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
3992 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
3993 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
3994 DBG("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
3996 /* Remove service info in list */
3997 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
3998 __hal_gattc_free_svc_info(service);
4006 ERR("uuid_str is NULL");
4011 /* Send GATT Client service changed event */
4012 ev.change_type = is_added;
4013 ev.conn_id = server_info->conn_id;
4014 ev.inst_id = server_info->inst_id;
4015 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));