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 INFO("[%d] [%s] [%s]", g_slist_length(conn_info->gatt_list_services), object_path + 15, uuid_str);
665 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
667 return gattc_service;
670 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
672 hal_gattc_char_t *gattc_char = NULL;
674 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
675 gattc_char->chr_path = g_strdup(char_handle);
677 DBG("svc path: [%s]", gatt_svc->svc_path);
678 DBG("char path: [%s]", gattc_char->chr_path);
680 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
683 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
684 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
686 hal_gattc_service_t* gatt_svc = NULL;
688 gchar *gp_char_path = NULL;
690 /* add the service */
691 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
692 if (gatt_svc == NULL) {
693 ERR("Failed to add service");
697 /* add the characteristic */
698 for (i = 0; i < gp_char_array->len; i++) {
699 gp_char_path = g_ptr_array_index(gp_char_array, i);
700 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
703 g_ptr_array_free(gp_char_array, TRUE);
706 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
708 hal_gattc_desc_t *gattc_desc = NULL;
710 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
711 gattc_desc->desc_path = g_strdup(desc_path);
713 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
716 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
717 GPtrArray *gp_desc_array, unsigned int char_permission)
719 gchar *gp_desc_path = NULL;
722 if (char_uuid_str == NULL) {
723 DBG("char_uuid_str is NULL");
727 //update the char uuid
728 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
730 //update char permission
731 gattc_char->permission = char_permission;
734 for (i = 0; i < gp_desc_array->len; i++) {
735 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
736 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
740 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
742 if (desc_uuid_str == NULL) {
743 DBG("char_uuid_str is NULL");
747 //update the descriptor uuid
748 DBG("desc UUID: [%s] ", desc_uuid_str);
749 DBG("desc path: [%s]", gattc_desc->desc_path);
751 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
754 static void browse_service_char(int conn_id)
756 hal_gattc_server_info_t *conn_info = NULL;
760 hal_gattc_service_t *svc_info = NULL;
761 hal_gattc_char_t *char_info = NULL;
762 hal_gattc_desc_t *desc_info = NULL;
764 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
765 if (conn_info == NULL) {
766 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
770 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
771 svc_info = (hal_gattc_service_t*)l->data;
772 if (svc_info == NULL)
775 /* find characteristic object path */
776 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
777 char_info = (hal_gattc_char_t *)k->data;
778 if (char_info == NULL)
782 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
783 desc_info = (hal_gattc_desc_t *)m->data;
784 if (desc_info == NULL)
794 * Enumerate all GATT services on a connected device.
795 * Optionally, the results can be filtered for a given UUID.
797 static bt_status_t _gattc_client_search_service(int conn_id)
801 GVariant *result = NULL;
803 GVariantIter *svc_iter;
804 GVariantIter *interface_iter;
805 char *object_path = NULL;
806 char *interface_str = NULL;
807 const gchar *key = NULL;
808 GVariant *value = NULL;
809 GPtrArray *gp_array = NULL;
810 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
811 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
812 int ret = BT_STATUS_FAIL;
814 const gchar *uuid_str = NULL;
816 hal_gattc_server_info_t *conn_info = NULL;
817 gboolean is_primary = FALSE;
820 char *char_handle = NULL;
821 GVariantIter *char_iter = NULL;
822 GPtrArray *gp_char_array = NULL;
824 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
825 if (NULL == conn_info) {
826 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
827 return BT_STATUS_FAIL;
831 // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
832 /* Check the service info is stored */
833 if (g_slist_length(conn_info->gatt_list_services) > 0) {
835 hal_gattc_service_t *svc_info = NULL;
836 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
837 DBG("Send event from service info list");
838 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
840 if (svc_info == NULL)
842 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
843 _bt_hal_send_search_service_result_event(conn_id,
844 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
846 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
847 return BT_STATUS_SUCCESS;
849 DBG("No stored service, request to bluez");
853 _bt_hal_convert_addr_type_to_string(device_address,
854 (unsigned char *)conn_info->bd_addr.address);
856 result = _bt_hal_get_managed_objects();
860 gp_array = g_ptr_array_new();
861 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
863 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
865 if (object_path == NULL)
868 _bt_hal_convert_device_path_to_address(object_path, temp_address);
870 if (g_strcmp0(temp_address, device_address) != 0)
873 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
874 &interface_str, &svc_iter)) {
875 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
878 DBG("[%d] Object Path : %s", idx++, object_path);
879 /* for characteristic */
880 gp_char_array = g_ptr_array_new();
881 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
882 if (g_strcmp0(key, "Primary") == 0) {
883 is_primary = g_variant_get_boolean(value);
885 g_ptr_array_add(gp_array, (gpointer)object_path);
888 } else if (g_strcmp0(key, "UUID") == 0) {
889 uuid_str = g_variant_get_string(value, &len);
890 } else if (g_strcmp0(key, "Characteristics") == 0) {
891 g_variant_get(value, "ao", &char_iter);
892 if (char_iter != NULL) {
893 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
894 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
901 _bt_hal_send_search_service_result_event(conn_id, is_primary,
902 uuid_str, conn_info->inst_id);
904 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
909 if (gp_array->len == 0 || svc_count == 0) {
910 ERR("gp_array is NULL");
911 ret = BT_STATUS_FAIL;
913 ret = BT_STATUS_SUCCESS;
916 browse_service_char(conn_id);
917 /* send search service complete event */
918 _bt_hal_send_search_service_complete_event(conn_id, ret);
920 g_ptr_array_free(gp_array, TRUE);
921 g_variant_iter_free(iter);
922 g_variant_unref(result);
927 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
929 if (NULL == filter_uuid) {
930 DBG("Browse all the services");
931 return _gattc_client_search_service(conn_id);
933 DBG("TODO implement it");
934 return BT_STATUS_UNSUPPORTED;
938 * Enumerate included services for a given service.
939 * Set start_incl_srvc_id to NULL to get the first included service.
941 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
942 btgatt_srvc_id_t *start_incl_srvc_id)
945 return BT_STATUS_UNSUPPORTED;
948 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
949 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
951 struct hal_ev_gatt_client_char_search_result ev;
954 ERR("gatt client callback not registered");
958 memset(&ev, 0, sizeof(ev));
959 ev.conn_id = conn_id;
960 ev.inst_id = svc_id->id.inst_id;
961 ev.is_primary = svc_id->is_primary;
963 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
965 if (status == BT_STATUS_SUCCESS) {
966 /* building char uuid */
967 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
968 ev.char_prop = char_prop;
971 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
972 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
975 static int _hal_get_permission_flag(char *permission)
979 if (NULL == permission) {
980 ERR("gatt permission is NULL");
984 if (!g_strcmp0(permission, "broadcast"))
985 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
986 else if (!g_strcmp0(permission, "read"))
987 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
988 else if (!g_strcmp0(permission, "write-without-response"))
989 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
990 else if (!g_strcmp0(permission, "write"))
991 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
992 else if (!g_strcmp0(permission, "notify"))
993 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
994 else if (!g_strcmp0(permission, "indicate"))
995 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
996 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
997 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
998 else if (!g_strcmp0(permission, "reliable-write"))
999 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
1000 else if (!g_strcmp0(permission, "writable-auxiliaries"))
1001 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1002 else if (!g_strcmp0(permission, "encrypt-read"))
1003 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1004 else if (!g_strcmp0(permission, "encrypt-write"))
1005 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1006 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1007 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1008 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1009 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1014 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1016 char perm[200] = { 0, };
1018 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1019 g_strlcat(perm, "broadcast ", sizeof(perm));
1020 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1021 g_strlcat(perm, "read ", sizeof(perm));
1022 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1023 g_strlcat(perm, "write-without-response ", sizeof(perm));
1024 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1025 g_strlcat(perm, "write ", sizeof(perm));
1026 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1027 g_strlcat(perm, "notify ", sizeof(perm));
1028 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1029 g_strlcat(perm, "indicate ", sizeof(perm));
1030 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1031 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1032 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1033 g_strlcat(perm, "reliable-write ", sizeof(perm));
1034 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1035 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1036 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1037 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1038 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1039 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1040 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1041 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1042 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1043 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1045 DBG("permission [0x%04x] : %s\n", permission, perm);
1049 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1051 GDBusProxy *properties_proxy = NULL;
1052 GError *error = NULL;
1053 GVariant *value = NULL;
1054 GVariant *result = NULL;
1055 GDBusConnection *g_conn;
1057 char *char_desc_handle = NULL;
1059 GVariantIter *property_iter;
1060 GVariantIter *char_desc_iter;
1061 char* char_handle = NULL;
1062 gchar *char_uuid_str = NULL;
1063 GPtrArray *gp_desc_array = NULL;
1064 GVariantIter *char_perm_iter;
1066 unsigned int char_permission = 0 ;
1068 if (gattc_char->chr_path == NULL) {
1069 DBG("char path is NULL");
1070 return BT_STATUS_FAIL;
1072 char_handle = gattc_char->chr_path;
1074 g_conn = _bt_hal_get_system_gconn();
1075 if (NULL == g_conn) {
1076 ERR("_bt_gdbus_get_system_gconn returned NULL");
1077 return BT_STATUS_FAIL;
1080 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1081 G_DBUS_PROXY_FLAGS_NONE, NULL,
1084 BT_HAL_PROPERTIES_INTERFACE,
1087 if (properties_proxy == NULL) {
1088 ERR("properties_proxy returned NULL");
1089 return BT_STATUS_FAIL;
1092 result = g_dbus_proxy_call_sync(properties_proxy,
1094 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1095 G_DBUS_CALL_FLAGS_NONE,
1100 if (error != NULL) {
1101 ERR("Fail to get properties (Error: %s)", error->message);
1102 g_clear_error(&error);
1104 ERR("Fail to get properties");
1105 g_object_unref(properties_proxy);
1106 return BT_STATUS_FAIL;
1109 gp_desc_array = g_ptr_array_new();
1111 g_variant_get(result, "(a{sv})", &property_iter);
1113 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1114 if (!g_strcmp0(key, "UUID")) {
1115 char_uuid_str = g_variant_dup_string(value, &len);
1116 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1117 } else if (!g_strcmp0(key, "Flags")) {
1118 g_variant_get(value, "as", &char_perm_iter);
1119 char_permission = 0x00;
1121 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1122 char_permission |= _hal_get_permission_flag(permission);
1124 __hal_convert_permission_flag_to_str(char_permission);
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);
1133 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1135 g_free(char_uuid_str);
1136 g_variant_iter_free(property_iter);
1137 g_variant_unref(result);
1138 g_object_unref(properties_proxy);
1139 g_ptr_array_free(gp_desc_array, TRUE);
1141 return BT_STATUS_SUCCESS;
1144 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1145 btgatt_srvc_id_t *srvc_id)
1147 hal_gattc_server_info_t * conn_info = NULL;
1148 hal_gattc_service_t *gattc_service = NULL;
1150 hal_gattc_char_t *gattc_char = NULL;
1151 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1152 int status = BT_STATUS_FAIL;
1154 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1155 if (NULL == conn_info) {
1156 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1157 return BT_STATUS_FAIL;
1161 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1162 if (NULL == gattc_service) {
1163 ERR("Failed to get the gatt service");
1164 return BT_STATUS_FAIL;
1167 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1168 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1170 /* find characteristic object path */
1171 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1172 gattc_char = (hal_gattc_char_t *)l->data;
1173 status = _hal_gattc_get_characteristic_info(gattc_char);
1176 if (BT_STATUS_SUCCESS == status) {
1177 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1178 &gattc_char->chr_uuid, gattc_char->permission);
1182 status = BT_STATUS_FAIL;
1183 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1185 browse_service_char(conn_id);
1186 /* retrive uuid for characteristic and object path for descriptor */
1188 return BT_STATUS_SUCCESS;
1192 * Enumerate characteristics for a given service.
1193 * Set start_char_id to NULL to get the first characteristic.
1195 bt_status_t btif_gattc_get_characteristic(int conn_id,
1196 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1198 CHECK_BTGATT_INIT();
1200 if (start_char_id == NULL) {
1201 DBG("Get all the characteristics");
1202 return _gattc_get_all_characteristic(conn_id, srvc_id);
1205 DBG("TBD Get specific characteristics");
1206 return BT_STATUS_UNSUPPORTED;
1210 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1212 GDBusProxy *properties_proxy = NULL;
1213 GError *error = NULL;
1214 GVariant *value = NULL;
1215 GVariant *result = NULL;
1216 GDBusConnection *g_conn;
1219 GVariantIter *property_iter;
1220 char* desc_handle = NULL;
1221 const gchar *desc_uuid_str = NULL;
1223 if (gattc_desc->desc_path == NULL) {
1224 DBG("desc path is NULL");
1225 return BT_STATUS_FAIL;
1227 desc_handle = gattc_desc->desc_path;
1229 g_conn = _bt_hal_get_system_gconn();
1230 if (NULL == g_conn) {
1231 ERR("_bt_gdbus_get_system_gconn returned NULL");
1232 return BT_STATUS_FAIL;
1235 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1236 G_DBUS_PROXY_FLAGS_NONE, NULL,
1239 BT_HAL_PROPERTIES_INTERFACE,
1242 if (properties_proxy == NULL) {
1243 ERR("properties_proxy returned NULL");
1244 return BT_STATUS_FAIL;
1247 result = g_dbus_proxy_call_sync(properties_proxy,
1249 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1250 G_DBUS_CALL_FLAGS_NONE,
1255 if (error != NULL) {
1256 ERR("Fail to get properties (Error: %s)", error->message);
1257 g_clear_error(&error);
1259 ERR("Fail to get properties");
1260 g_object_unref(properties_proxy);
1261 return BT_STATUS_FAIL;
1264 g_variant_get(result, "(a{sv})", &property_iter);
1266 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1267 if (!g_strcmp0(key, "UUID")) {
1268 desc_uuid_str = g_variant_get_string(value, &len);
1269 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1274 g_variant_iter_free(property_iter);
1275 g_variant_unref(result);
1276 g_object_unref(properties_proxy);
1278 return BT_STATUS_SUCCESS;
1281 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1282 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1284 struct hal_ev_gatt_client_desc_search_result ev;
1287 ERR("gatt client callback not registered");
1291 memset(&ev, 0, sizeof(ev));
1292 ev.conn_id = conn_id;
1293 ev.inst_id = svc_id->id.inst_id;
1294 ev.is_primary = svc_id->is_primary;
1297 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1298 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1300 if (status == BT_STATUS_SUCCESS) {
1301 /* building desc uuid */
1302 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1305 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1307 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1310 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1311 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1313 hal_gattc_server_info_t * conn_info = NULL;
1314 hal_gattc_service_t *gattc_service = NULL;
1317 hal_gattc_char_t *gattc_char = NULL;
1318 hal_gattc_desc_t *gattc_desc = NULL;
1319 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1320 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1321 int status = BT_STATUS_FAIL;
1323 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1324 if (NULL == conn_info) {
1325 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1326 return BT_STATUS_FAIL;
1330 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1331 if (NULL == gattc_service) {
1332 ERR("Failed to get the gatt service");
1333 return BT_STATUS_FAIL;
1336 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1337 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1339 /* find characteristics */
1340 /* a service can have two char with same uuid */
1341 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1342 gattc_char = (hal_gattc_char_t*)l->data;
1343 if (gattc_char == NULL)
1346 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1347 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1348 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1350 /* get descriptor uuid */
1351 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1352 gattc_desc = (hal_gattc_desc_t *)m->data;
1353 if (gattc_desc == NULL)
1356 status = _hal_gattc_get_descriptor_info(gattc_desc);
1359 if (BT_STATUS_SUCCESS == status) {
1360 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1361 char_id, &gattc_desc->desc_uuid);
1367 status = BT_STATUS_FAIL;
1368 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1370 browse_service_char(conn_id);
1371 /* retrive uuid for characteristic and object path for descriptor */
1373 return BT_STATUS_SUCCESS;
1377 * Enumerate descriptors for a given characteristic.
1378 * Set start_descr_id to NULL to get the first descriptor.
1380 bt_status_t btif_gattc_get_descriptor(int conn_id,
1381 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1382 btgatt_gatt_id_t *start_descr_id)
1384 CHECK_BTGATT_INIT();
1386 if (start_descr_id == NULL) {
1387 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1389 DBG("TBD Get specific descriptor");
1390 return BT_STATUS_UNSUPPORTED;
1394 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1396 struct hal_ev_gatt_client_read_data ev;
1399 ERR("gatt client callback not registered");
1403 memset(&ev, 0, sizeof(ev));
1404 ev.conn_id = resp_data->conn_id;
1405 ev.inst_id = resp_data->srvc_id.id.inst_id;
1406 ev.is_primary = resp_data->srvc_id.is_primary;
1409 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1410 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1414 /* building the char read value */
1415 memcpy(ev.value, value, len);
1418 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1420 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1423 static void __hal_internal_read_char_cb(GObject *source_object,
1424 GAsyncResult *res, gpointer user_data)
1426 GError *error = NULL;
1427 GDBusConnection *system_gconn = NULL;
1430 GByteArray *gp_byte_array = NULL;
1432 hal_gatt_resp_data_t *resp_data = user_data;
1433 int result = BT_STATUS_SUCCESS;
1435 system_gconn = _bt_hal_get_system_gconn();
1436 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1439 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1442 result = BT_STATUS_FAIL;
1443 __hal_send_char_read_event(resp_data, result, NULL, 0);
1444 g_clear_error(&error);
1449 gp_byte_array = g_byte_array_new();
1450 g_variant_get(value, "(ay)", &iter);
1452 while (g_variant_iter_loop(iter, "y", &g_byte))
1453 g_byte_array_append(gp_byte_array, &g_byte, 1);
1457 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1461 g_byte_array_free(gp_byte_array, TRUE);
1462 g_variant_iter_free(iter);
1463 g_variant_unref(value);
1467 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1468 btgatt_gatt_id_t *char_id, int auth_req)
1470 GDBusConnection *g_conn;
1471 hal_gatt_resp_data_t *resp_data;
1472 hal_gattc_service_t *gattc_service = NULL;
1473 GVariantBuilder *builder = NULL;
1475 hal_gattc_server_info_t * conn_info = NULL;
1476 hal_gattc_char_t *gattc_char = NULL;
1477 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1478 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1479 char* char_handle = NULL;
1481 /* get the connection info */
1482 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1483 if (NULL == conn_info) {
1484 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1485 return BT_STATUS_FAIL;
1489 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1490 if (NULL == gattc_service) {
1491 ERR("Failed to get the gatt service");
1492 return BT_STATUS_FAIL;
1495 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1497 /* find characteristic */
1498 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1499 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1500 if (NULL == gattc_char) {
1501 ERR("Failed to get the gatt char");
1502 return BT_STATUS_FAIL;
1505 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1506 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1508 g_conn = _bt_hal_get_system_gconn();
1509 if (NULL == g_conn) {
1510 ERR("_bt_gdbus_get_system_gconn returned NULL");
1511 return BT_STATUS_FAIL;
1514 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1515 resp_data->conn_id = conn_id;
1516 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1517 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1519 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1522 g_variant_builder_add(builder, "{sv}", "offset",
1523 g_variant_new("q", offset));
1525 char_handle = gattc_char->chr_path;
1527 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1528 "ReadValue", g_variant_new("(a{sv})", builder),
1529 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1530 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1531 (gpointer)resp_data);
1532 g_variant_builder_unref(builder);
1534 return BT_STATUS_SUCCESS;
1537 /** Read a characteristic on a remote device */
1538 bt_status_t btif_read_characteristic(int conn_id,
1539 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1542 CHECK_BTGATT_INIT();
1544 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1547 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1549 struct hal_ev_gatt_client_write_result ev;
1552 ERR("gatt client callback not registered");
1556 memset(&ev, 0, sizeof(ev));
1557 ev.conn_id = resp_data->conn_id;
1558 ev.inst_id = resp_data->srvc_id.id.inst_id;
1559 ev.is_primary = resp_data->srvc_id.is_primary;
1562 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1563 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1565 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1567 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1570 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1571 GAsyncResult *res, gpointer user_data)
1573 GError *error = NULL;
1574 GDBusConnection *system_gconn = NULL;
1576 hal_gatt_resp_data_t *resp_data = user_data;
1577 int result = BT_STATUS_SUCCESS;
1581 system_gconn = _bt_hal_get_system_gconn();
1582 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1585 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1587 result = BT_STATUS_FAIL;
1589 __hal_send_char_write_event(resp_data, result);
1590 g_clear_error(&error);
1595 //send write value event
1596 __hal_send_char_write_event(resp_data, result);
1599 g_variant_unref(value);
1604 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1607 case HAL_GATT_WRITE_TYPE_WRITE:
1608 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1610 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1611 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1614 ERR("Unknow write type : %d", type);
1615 return BT_STATUS_FAIL;
1618 return BT_STATUS_SUCCESS;
1622 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1624 GDBusConnection *conn;
1625 GVariantBuilder *builder = NULL;
1631 GUnixFDList *fd_list = NULL;
1633 conn = _bt_hal_get_system_gconn();
1635 ERR("_bt_gdbus_get_system_gconn returned NULL");
1636 return BT_STATUS_FAIL;
1639 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1640 //val = g_variant_new("ay", builder1);
1642 g_variant_builder_add(builder, "{sv}", "offset",
1643 g_variant_new("q", offset));
1645 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1646 "AcquireWrite", g_variant_new("(a{sv})", builder),
1647 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1648 NULL, &fd_list, NULL, &err);
1650 g_dbus_error_strip_remote_error(err);
1651 ERR("Error: %s", err->message);
1653 g_variant_builder_unref(builder);
1654 return BT_STATUS_FAIL;
1657 g_variant_get(value, "(hq)", &idx, &att_mtu);
1658 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1660 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1663 g_object_unref(fd_list);
1664 g_variant_unref(value);
1665 g_variant_builder_unref(builder);
1667 return BT_STATUS_SUCCESS;
1670 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1672 GDBusConnection *conn;
1673 GVariantBuilder *builder = NULL;
1677 gint32 idx, notify_fd;
1679 GUnixFDList *fd_list = NULL;
1681 conn = _bt_hal_get_system_gconn();
1684 ERR("_bt_gdbus_get_system_gconn returned NULL");
1685 return BT_STATUS_FAIL;
1689 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1692 g_variant_builder_add(builder, "{sv}", "offset",
1693 g_variant_new("q", offset));
1695 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1696 "AcquireNotify", g_variant_new("(a{sv})", builder),
1697 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1698 NULL, &fd_list, NULL, &err);
1700 g_dbus_error_strip_remote_error(err);
1701 ERR("Error: %s", err->message);
1703 g_variant_builder_unref(builder);
1704 return BT_STATUS_FAIL;
1707 g_variant_get(value, "(hq)", &idx, &att_mtu);
1708 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1711 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1715 g_object_unref(fd_list);
1716 g_variant_unref(value);
1717 g_variant_builder_unref(builder);
1719 return BT_STATUS_SUCCESS;
1723 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1724 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1726 GVariant *val, *options;
1727 GVariantBuilder *builder1;
1728 GVariantBuilder *builder2;
1729 GDBusConnection *g_conn;
1732 hal_gatt_resp_data_t *resp_data;
1733 hal_gattc_service_t *gattc_service = NULL;
1734 hal_gattc_server_info_t * conn_info = NULL;
1735 hal_gattc_char_t *gattc_char = NULL;
1736 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1737 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1738 char* char_handle = NULL;
1739 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1740 int ret = BT_STATUS_SUCCESS;
1742 ret = __hal_get_write_prop(write_type, &write_prop);
1743 if (BT_STATUS_FAIL == ret) {
1744 DBG("received invalid write type:[%d] ", write_type);
1745 return BT_STATUS_FAIL;
1748 /* get the connection info */
1749 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1750 if (NULL == conn_info) {
1751 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1752 return BT_STATUS_FAIL;
1756 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1757 if (NULL == gattc_service) {
1758 ERR("Failed to get the gatt service");
1759 return BT_STATUS_FAIL;
1762 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1763 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1765 /* find characteristic */
1766 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1767 if (NULL == gattc_char) {
1768 ERR("Failed to get the gatt char");
1769 return BT_STATUS_FAIL;
1772 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1773 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1775 g_conn = _bt_hal_get_system_gconn();
1776 if (NULL == g_conn) {
1777 ERR("_bt_gdbus_get_system_gconn returned NULL");
1778 return BT_STATUS_FAIL;
1781 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1782 resp_data->conn_id = conn_id;
1783 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1784 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1786 char_handle = gattc_char->chr_path;
1788 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1790 for (i = 0; i < length; i++)
1791 g_variant_builder_add(builder1, "y", value[i]);
1793 val = g_variant_new("ay", builder1);
1795 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1797 g_variant_builder_add(builder2, "{sv}", "offset",
1798 g_variant_new_uint16(offset));
1800 options = g_variant_new("a{sv}", builder2);
1802 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1804 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1806 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1807 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1808 (gpointer)resp_data);
1810 g_variant_builder_unref(builder1);
1811 g_variant_builder_unref(builder2);
1813 return BT_STATUS_SUCCESS;
1816 bt_status_t btif_get_acquire_write_fd(int conn_id,
1817 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1818 int auth_req, int *fd, int*mtu)
1820 CHECK_BTGATT_INIT();
1822 hal_gattc_service_t *gattc_service = NULL;
1823 hal_gattc_server_info_t * conn_info = NULL;
1824 hal_gattc_char_t *gattc_char = NULL;
1825 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1827 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1828 int ret = BT_STATUS_SUCCESS;
1830 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1832 /* get the connection info */
1833 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1834 if (NULL == conn_info) {
1835 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1836 return BT_STATUS_FAIL;
1840 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1841 if (NULL == gattc_service) {
1842 ERR("Failed to get the gatt service");
1843 return BT_STATUS_FAIL;
1846 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1847 if (NULL == gattc_char) {
1848 ERR("Failed to get the gatt char");
1849 return BT_STATUS_FAIL;
1852 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1853 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1855 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1856 if (ret != BT_STATUS_SUCCESS)
1862 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1863 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1865 CHECK_BTGATT_INIT();
1867 hal_gattc_service_t *gattc_service = NULL;
1868 hal_gattc_server_info_t * conn_info = NULL;
1869 hal_gattc_char_t *gattc_char = NULL;
1870 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1872 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1873 int ret = BT_STATUS_SUCCESS;
1875 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1877 /* get the connection info */
1878 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1879 if (NULL == conn_info) {
1880 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1881 return BT_STATUS_FAIL;
1885 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1886 if (NULL == gattc_service) {
1887 ERR("Failed to get the gatt service");
1888 return BT_STATUS_FAIL;
1891 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1892 if (NULL == gattc_char) {
1893 ERR("Failed to get the gatt char");
1894 return BT_STATUS_FAIL;
1897 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1898 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1900 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1901 if (ret != BT_STATUS_SUCCESS)
1908 /** Write a remote characteristic */
1909 bt_status_t btif_write_characteristic(int conn_id,
1910 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1911 int write_type, int len, int auth_req,
1914 CHECK_BTGATT_INIT();
1916 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1917 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1918 len, auth_req, p_value);
1921 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1923 struct hal_ev_gatt_client_read_data ev;
1926 ERR("gatt client callback not registered");
1930 memset(&ev, 0, sizeof(ev));
1931 ev.conn_id = resp_data->conn_id;
1932 ev.inst_id = resp_data->srvc_id.id.inst_id;
1933 ev.is_primary = resp_data->srvc_id.is_primary;
1936 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1937 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1938 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1942 /* building the desc read value */
1943 memcpy(ev.value, value, len);
1946 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1948 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1951 static void __hal_internal_read_desc_cb(GObject *source_object,
1952 GAsyncResult *res, gpointer user_data)
1954 GError *error = NULL;
1955 GDBusConnection *system_gconn = NULL;
1958 GByteArray *gp_byte_array = NULL;
1960 hal_gatt_resp_data_t *resp_data = user_data;
1961 int result = BT_STATUS_SUCCESS;
1966 system_gconn = _bt_hal_get_system_gconn();
1967 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1970 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1973 result = BT_STATUS_FAIL;
1974 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1975 g_clear_error(&error);
1980 gp_byte_array = g_byte_array_new();
1981 g_variant_get(value, "(ay)", &iter);
1983 while (g_variant_iter_loop(iter, "y", &g_byte))
1984 g_byte_array_append(gp_byte_array, &g_byte, 1);
1988 for (i = 0; i < gp_byte_array->len; i++)
1989 DBG("%02x", gp_byte_array->data[i]);
1992 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1996 g_byte_array_free(gp_byte_array, TRUE);
1997 g_variant_iter_free(iter);
1998 g_variant_unref(value);
2003 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2004 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2006 GDBusConnection *g_conn;
2007 hal_gatt_resp_data_t *resp_data;
2008 hal_gattc_service_t *gattc_service = NULL;
2009 GVariantBuilder *builder = NULL;
2011 hal_gattc_server_info_t * conn_info = NULL;
2012 hal_gattc_char_t *gattc_char = NULL;
2013 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2014 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2015 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2016 char* desc_handle = NULL;
2019 hal_gattc_desc_t *gattc_desc = NULL;
2021 /* get the connection info */
2022 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2023 if (NULL == conn_info) {
2024 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2025 return BT_STATUS_FAIL;
2029 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2030 if (NULL == gattc_service) {
2031 ERR("Failed to get the gatt service");
2032 return BT_STATUS_FAIL;
2035 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2036 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2038 /* find characteristic */
2039 /* service can have two char with same uuid */
2040 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2041 gattc_char = (hal_gattc_char_t*)l->data;
2042 if (gattc_char == NULL)
2045 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2046 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2047 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2049 /* find descriptor */
2050 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2052 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2053 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2059 if (NULL == gattc_desc) {
2060 ERR("Failed to get the gatt desc");
2061 return BT_STATUS_FAIL;
2064 g_conn = _bt_hal_get_system_gconn();
2065 if (NULL == g_conn) {
2066 ERR("_bt_gdbus_get_system_gconn returned NULL");
2067 return BT_STATUS_FAIL;
2070 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2071 resp_data->conn_id = conn_id;
2072 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2073 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2074 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2076 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2079 g_variant_builder_add(builder, "{sv}", "offset",
2080 g_variant_new("q", offset));
2082 desc_handle = gattc_desc->desc_path;
2084 DBG("calling desc read value");
2086 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2087 "ReadValue", g_variant_new("(a{sv})", builder),
2088 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2089 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2090 (gpointer)resp_data);
2091 g_variant_builder_unref(builder);
2093 return BT_STATUS_SUCCESS;
2096 /** Read the descriptor for a given characteristic */
2097 bt_status_t btif_read_descriptor(int conn_id,
2098 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2099 btgatt_gatt_id_t *descr_id, int auth_req)
2101 CHECK_BTGATT_INIT();
2103 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2106 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2108 struct hal_ev_gatt_client_write_result ev;
2111 ERR("gatt client callback not registered");
2115 memset(&ev, 0, sizeof(ev));
2116 ev.conn_id = resp_data->conn_id;
2117 ev.inst_id = resp_data->srvc_id.id.inst_id;
2118 ev.is_primary = resp_data->srvc_id.is_primary;
2121 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2122 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2123 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2125 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2127 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2130 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2131 GAsyncResult *res, gpointer user_data)
2133 GError *error = NULL;
2134 GDBusConnection *system_gconn = NULL;
2136 hal_gatt_resp_data_t *resp_data = user_data;
2137 int result = BT_STATUS_SUCCESS;
2141 system_gconn = _bt_hal_get_system_gconn();
2142 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2145 ERR("write descriptor dbus failed Error: [%s]", error->message);
2148 result = BT_STATUS_FAIL;
2149 __hal_send_desc_write_event(resp_data, result);
2150 g_clear_error(&error);
2155 //send write value event
2156 __hal_send_desc_write_event(resp_data, result);
2159 g_variant_unref(value);
2164 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2165 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2166 int write_type, int length, int auth_req, char* value)
2168 GVariant *val, *options;
2169 GVariantBuilder *builder1;
2170 GVariantBuilder *builder2;
2171 GDBusConnection *g_conn;
2174 hal_gatt_resp_data_t *resp_data;
2175 hal_gattc_service_t *gattc_service = NULL;
2176 hal_gattc_server_info_t * conn_info = NULL;
2177 hal_gattc_char_t *gattc_char = NULL;
2178 hal_gattc_desc_t *gattc_desc = NULL;
2179 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2180 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2181 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2182 char* desc_handle = NULL;
2183 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2184 int ret = BT_STATUS_SUCCESS;
2189 ret = __hal_get_write_prop(write_type, &write_prop);
2190 if (BT_STATUS_FAIL == ret) {
2191 ERR("received invalid write type:[%d] ", write_type);
2192 return BT_STATUS_FAIL;
2195 /* get the connection info */
2196 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2197 if (NULL == conn_info) {
2198 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2199 return BT_STATUS_FAIL;
2203 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2204 if (NULL == gattc_service) {
2205 ERR("Failed to get the gatt service");
2206 return BT_STATUS_FAIL;
2209 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2210 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2212 /* find characteristic */
2213 /* service can have two char with same uuid */
2214 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2215 gattc_char = (hal_gattc_char_t*)l->data;
2216 if (gattc_char == NULL)
2219 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2220 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2221 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2223 /* find descriptor */
2224 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2226 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2227 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2233 if (NULL == gattc_desc) {
2234 ERR("Failed to get the gatt desc");
2235 return BT_STATUS_FAIL;
2238 g_conn = _bt_hal_get_system_gconn();
2239 if (NULL == g_conn) {
2240 ERR("_bt_gdbus_get_system_gconn returned NULL");
2241 return BT_STATUS_FAIL;
2244 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2245 resp_data->conn_id = conn_id;
2246 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2247 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2248 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2250 desc_handle = gattc_desc->desc_path;
2252 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2254 for (i = 0; i < length; i++)
2255 g_variant_builder_add(builder1, "y", value[i]);
2257 val = g_variant_new("ay", builder1);
2259 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2261 g_variant_builder_add(builder2, "{sv}", "offset",
2262 g_variant_new_uint16(offset));
2264 options = g_variant_new("a{sv}", builder2);
2266 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2268 g_variant_new("(@ay@a{sv})", val, options),
2270 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2271 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2272 (gpointer)resp_data);
2274 g_variant_builder_unref(builder1);
2275 g_variant_builder_unref(builder2);
2277 return BT_STATUS_SUCCESS;
2280 /** Write a remote descriptor for a given characteristic */
2281 bt_status_t btif_write_descriptor(int conn_id,
2282 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2283 btgatt_gatt_id_t *descr_id, int write_type, int len,
2284 int auth_req, char* p_value)
2286 CHECK_BTGATT_INIT();
2288 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2289 len, auth_req, p_value);
2292 /** Execute a prepared write operation */
2293 bt_status_t execute_write(int conn_id, int execute)
2295 CHECK_BTGATT_INIT();
2296 return BT_STATUS_UNSUPPORTED;
2299 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2301 struct hal_ev_gatt_client_watch_notification ev;
2302 hal_gatt_resp_data_t *resp_data = user_data;
2304 DBG("sending the watch register notification event");
2305 /* send the event */
2306 memset(&ev, 0, sizeof(ev));
2307 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2309 ev.status = resp_data->result;
2311 ev.is_primary = resp_data->srvc_id.is_primary;
2312 ev.inst_id = resp_data->srvc_id.id.inst_id;
2314 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2315 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2318 ERR("GATT Callback not registered");
2320 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2327 static bt_status_t _hal_register_for_notification(int client_if,
2328 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2329 btgatt_gatt_id_t *char_id)
2331 int result = BT_STATUS_SUCCESS;
2332 GError *error = NULL;
2333 GDBusConnection *g_conn;
2334 hal_gattc_client_info_t *gattc_client = NULL;
2335 hal_gattc_server_info_t * conn_info = NULL;
2336 hal_gattc_service_t *gattc_service = NULL;
2337 hal_gattc_char_t *gattc_char = NULL;
2338 char* char_handle = NULL;
2339 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2340 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2341 hal_gatt_resp_data_t *resp_data;
2345 gattc_client = __bt_find_gatt_client_info(bd_addr);
2346 if (gattc_client == NULL) {
2347 ERR("failed to get the gatt client info");
2348 return BT_STATUS_FAIL;
2351 if (gattc_client->client_if != client_if) {
2352 ERR("could not find the gatt client for client id[%d]", client_if);
2353 return BT_STATUS_FAIL;
2356 /* get the connection info */
2357 conn_info = __bt_find_gatt_conn_info(bd_addr);
2358 if (NULL == conn_info) {
2359 ERR("Failed to get the conn_info");
2360 return BT_STATUS_FAIL;
2363 if (conn_info->inst_id != gattc_client->inst_id) {
2364 ERR("could not fild the conn_info");
2365 return BT_STATUS_FAIL;
2369 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2370 if (NULL == gattc_service) {
2371 ERR("Failed to get the gatt service");
2372 return BT_STATUS_FAIL;
2375 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2376 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2379 /* find characteristic */
2380 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2381 if (NULL == gattc_char) {
2382 ERR("Failed to get the gatt char");
2383 return BT_STATUS_FAIL;
2386 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2387 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2389 char_handle = gattc_char->chr_path;
2391 g_conn = _bt_hal_get_system_gconn();
2392 if (g_conn == NULL) {
2394 return BT_STATUS_FAIL;
2397 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2399 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2401 g_dbus_connection_call_sync(g_conn,
2404 BT_HAL_GATT_CHAR_INTERFACE,
2408 G_DBUS_CALL_FLAGS_NONE,
2409 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2412 g_dbus_error_strip_remote_error(error);
2413 ERR("### StartNotify Failed: %s", error->message);
2414 if (g_strrstr(error->message, "Already notifying"))
2415 result = BT_STATUS_SUCCESS;
2416 else if (g_strrstr(error->message, "In Progress"))
2417 result = BT_STATUS_BUSY;
2418 else if (g_strrstr(error->message, "Operation is not supported"))
2419 result = BT_STATUS_UNSUPPORTED;
2420 /*failed because of either Insufficient Authorization or Write Not Permitted */
2421 else if (g_strrstr(error->message, "Write not permitted") ||
2422 g_strrstr(error->message, "Operation Not Authorized"))
2423 result = BT_STATUS_AUTH_FAILURE;
2424 /* failed because of either Insufficient Authentication,
2425 Insufficient Encryption Key Size, or Insufficient Encryption. */
2426 else if (g_strrstr(error->message, "Not paired"))
2427 result = BT_STATUS_NOT_READY;
2429 result = BT_STATUS_FAIL;
2431 g_clear_error(&error);
2434 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2435 resp_data->result = result;
2436 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2437 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2439 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2443 return BT_STATUS_SUCCESS;
2447 * Register to receive notifications or indications for a given
2450 bt_status_t btif_register_for_notification(int client_if,
2451 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2452 btgatt_gatt_id_t *char_id)
2454 CHECK_BTGATT_INIT();
2456 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2459 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2461 struct hal_ev_gatt_client_watch_notification ev;
2462 hal_gatt_resp_data_t *resp_data = user_data;
2464 DBG("sending the watch deregister notification event");
2465 /* send the event */
2466 memset(&ev, 0, sizeof(ev));
2467 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2469 ev.status = resp_data->result;
2471 ev.is_primary = resp_data->srvc_id.is_primary;
2472 ev.inst_id = resp_data->srvc_id.id.inst_id;
2474 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2475 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2478 ERR("GATT Callback not registered");
2480 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2487 static bt_status_t _hal_deregister_for_notification(int client_if,
2488 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2489 btgatt_gatt_id_t *char_id)
2491 int result = BT_STATUS_SUCCESS;
2492 GError *error = NULL;
2493 GDBusConnection *g_conn;
2494 hal_gattc_client_info_t *gattc_client = NULL;
2495 hal_gattc_server_info_t * conn_info = NULL;
2496 hal_gattc_service_t *gattc_service = NULL;
2497 hal_gattc_char_t *gattc_char = NULL;
2498 char* char_handle = NULL;
2499 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2500 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2501 hal_gatt_resp_data_t *resp_data;
2505 gattc_client = __bt_find_gatt_client_info(bd_addr);
2506 if (gattc_client == NULL) {
2507 ERR("failed to get the gatt client info");
2508 return BT_STATUS_FAIL;
2511 if (gattc_client->client_if != client_if) {
2512 ERR("could not find the gatt client for client id[%d]", client_if);
2513 return BT_STATUS_FAIL;
2516 /* get the connection info */
2517 conn_info = __bt_find_gatt_conn_info(bd_addr);
2518 if (NULL == conn_info) {
2519 ERR("Failed to get the conn_info");
2520 return BT_STATUS_FAIL;
2523 if (conn_info->inst_id != gattc_client->inst_id) {
2524 ERR("could not fild the conn_info");
2525 return BT_STATUS_FAIL;
2529 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2530 if (NULL == gattc_service) {
2531 ERR("Failed to get the gatt service");
2532 return BT_STATUS_FAIL;
2535 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2536 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2539 /* find characteristic */
2540 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2541 if (NULL == gattc_char) {
2542 ERR("Failed to get the gatt char");
2543 return BT_STATUS_FAIL;
2546 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2547 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2549 char_handle = gattc_char->chr_path;
2551 g_conn = _bt_hal_get_system_gconn();
2552 if (g_conn == NULL) {
2554 return BT_STATUS_FAIL;
2557 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2559 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2560 g_dbus_connection_call_sync(g_conn,
2563 BT_HAL_GATT_CHAR_INTERFACE,
2567 G_DBUS_CALL_FLAGS_NONE,
2568 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2571 ERR("### StopNotify Failed: %s", error->message);
2572 g_clear_error(&error);
2573 result = BT_STATUS_FAIL;
2576 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2577 resp_data->result = result;
2578 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2579 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2581 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2585 return BT_STATUS_SUCCESS;
2587 /** Deregister a previous request for notifications/indications */
2588 bt_status_t btif_deregister_for_notification(int client_if,
2589 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2590 btgatt_gatt_id_t *char_id)
2592 CHECK_BTGATT_INIT();
2593 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2596 /** Request RSSI for a given remote device */
2597 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2599 CHECK_BTGATT_INIT();
2600 return BT_STATUS_UNSUPPORTED;
2603 /** OTA firmware download */
2604 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2606 CHECK_BTGATT_INIT();
2607 return BT_STATUS_UNSUPPORTED;
2610 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2611 int get_device_type(const bt_bdaddr_t *bd_addr)
2613 CHECK_BTGATT_INIT();
2614 return BT_STATUS_UNSUPPORTED;
2617 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2618 int min_int, int max_int, int latency, int timeout)
2620 gchar *device_path = NULL;
2621 GError *error = NULL;
2622 GDBusProxy *device_proxy = NULL;
2623 GDBusConnection *conn;
2625 int ret = BT_STATUS_SUCCESS;
2626 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2628 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2629 min_int, max_int, latency, timeout);
2631 conn = _bt_hal_get_system_gconn();
2634 return BT_STATUS_FAIL;
2637 _bt_hal_convert_addr_type_to_string(device_address,
2638 (unsigned char *)bd_addr->address);
2639 device_path = _bt_hal_get_device_object_path(device_address);
2641 if (device_path == NULL) {
2642 ERR("device_path NULL : [%s]", device_address);
2643 return BT_STATUS_FAIL;
2646 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2647 NULL, BT_HAL_BLUEZ_NAME,
2648 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2650 g_free(device_path);
2651 if (NULL == device_proxy) {
2652 ERR("device_proxy returned NULL");
2653 return BT_STATUS_FAIL;
2656 INFO("Request LeConnUpdate");
2657 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2658 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2659 G_DBUS_CALL_FLAGS_NONE,
2664 g_object_unref(device_proxy);
2665 if (reply == NULL) {
2667 ERR("Error %s[%s]", error->message, device_address);
2668 if (g_strrstr(error->message, "In Progress"))
2669 ret = BT_STATUS_SUCCESS;
2671 ret = BT_STATUS_FAIL;
2672 g_error_free(error);
2676 g_variant_unref(reply);
2678 DBG("LE Connection parameter Updated");
2682 /** Request a connection parameter update */
2683 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2685 CHECK_BTGATT_INIT();
2687 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2690 /** Test mode interface */
2691 bt_status_t test_command(int command, btgatt_test_params_t* params)
2693 CHECK_BTGATT_INIT();
2694 return BT_STATUS_UNSUPPORTED;
2697 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2700 GError *g_error = NULL;
2701 GVariant *reply = NULL;
2702 int result = BT_STATUS_SUCCESS;
2703 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2704 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2706 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2707 g_object_unref(proxy);
2708 if (reply == NULL) {
2709 ERR("Connect LE Dbus Call Error");
2711 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2712 g_clear_error(&g_error);
2714 result = BT_STATUS_FAIL;
2716 g_variant_unref(reply);
2718 memset(&ev, 0, sizeof(ev));
2720 ev.mtu = conn_mtu->mtu;
2721 ev.conn_id = conn_mtu->conn_id;
2724 ERR("gatt client callback not registered");
2726 DBG("sending gatt client MTU exchange completed event");
2727 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2734 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2736 gchar *device_path = NULL;
2737 GDBusProxy *device_proxy = NULL;
2738 GDBusConnection *conn;
2739 hal_gattc_client_info_t *gattc_client = NULL;
2740 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2741 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2743 conn = _bt_hal_get_system_gconn();
2746 return BT_STATUS_FAIL;
2749 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2750 if (gattc_client == NULL) {
2751 INFO("GATT client conn info not found");
2752 return BT_STATUS_FAIL;
2755 _bt_hal_convert_addr_type_to_string(device_address,
2756 (unsigned char *)gattc_client->bd_addr.address);
2758 device_path = _bt_hal_get_device_object_path(device_address);
2759 if (device_path == NULL) {
2760 ERR("device_path NULL : [%s]", device_address);
2761 return BT_STATUS_FAIL;
2764 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2765 NULL, BT_HAL_BLUEZ_NAME,
2766 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2768 g_free(device_path);
2769 if (NULL == device_proxy) {
2770 ERR("device_proxy returned NULL");
2771 return BT_STATUS_FAIL;
2774 conn_mtu->conn_id = conn_id;
2775 conn_mtu->mtu = mtu;
2777 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2778 g_variant_new("(q)", mtu),
2779 G_DBUS_CALL_FLAGS_NONE,
2780 BT_HAL_MAX_DBUS_TIMEOUT,
2782 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2785 return BT_STATUS_SUCCESS;
2788 /** MTU Exchange request from client */
2789 static bt_status_t configure_mtu(int conn_id, int mtu)
2791 CHECK_BTGATT_INIT();
2793 return __hal_configure_mtu(conn_id, mtu);
2796 /** Setup scan filter params */
2797 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2798 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2799 int rssi_low_thres, int dely_mode, int found_timeout,
2800 int lost_timeout, int found_timeout_cnt)
2803 GError *error = NULL;
2804 GVariant *ret, *param;
2805 CHECK_BTGATT_INIT();
2807 proxy = _bt_hal_get_adapter_proxy();
2810 return BT_STATUS_FAIL;
2812 param = g_variant_new("(iiiiiiiiiiii)",
2825 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2826 param, G_DBUS_CALL_FLAGS_NONE,
2830 ERR("scan_filter_param_setup Fail: %s", error->message);
2831 g_clear_error(&error);
2832 return BT_STATUS_FAIL;
2836 g_variant_unref(ret);
2838 return BT_STATUS_SUCCESS;
2841 /** Configure a scan filter condition */
2842 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2843 int filt_index, int company_id,
2844 int company_id_mask, const bt_uuid_t *p_uuid,
2845 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2846 char addr_type, int data_len, char* p_data, int mask_len,
2850 GError *error = NULL;
2851 GVariant *ret, *param;
2852 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2853 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2854 GArray *arr_uuid = NULL;
2855 GArray *arr_uuid_mask = NULL;
2856 GArray *arr_data = NULL;
2857 GArray *arr_data_mask = NULL;
2858 CHECK_BTGATT_INIT();
2860 proxy = _bt_hal_get_adapter_proxy();
2863 return BT_STATUS_FAIL;
2865 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2867 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2869 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2871 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2873 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2874 NULL, 0, TRUE, NULL, NULL);
2875 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2876 NULL, 0, TRUE, NULL, NULL);
2877 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2878 NULL, 0, TRUE, NULL, NULL);
2879 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2880 NULL, 0, TRUE, NULL, NULL);
2882 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2883 client_if, // client_if
2884 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2885 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2886 filt_index, // filter_index
2887 company_id, // company_id
2888 company_id_mask, // company_id_mask
2889 arr_uuid_param, // p_uuid
2890 arr_uuid_mask_param, // p_uuid_mask
2892 addr_type, // address_type
2893 arr_data_param, // p_data
2894 arr_data_mask_param); // p_mask
2896 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2897 param, G_DBUS_CALL_FLAGS_NONE,
2901 ERR("scan_filter_add_remove Fail: %s", error->message);
2902 g_clear_error(&error);
2903 return BT_STATUS_FAIL;
2907 g_variant_unref(ret);
2909 return BT_STATUS_SUCCESS;
2912 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2914 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2915 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2916 NULL, 0, TRUE, NULL, NULL);
2917 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2918 NULL, 0, TRUE, NULL, NULL);
2919 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2920 NULL, 0, TRUE, NULL, NULL);
2921 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2922 NULL, 0, TRUE, NULL, NULL);
2924 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2925 client_if, // client_if
2926 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2927 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2928 filt_index, // filter_index
2929 company_id, // company_id
2930 company_id_mask, // company_id_mask
2931 arr_uuid_param, // p_uuid
2932 arr_uuid_mask_param, // p_uuid_mask
2934 addr_type, // address_type
2935 arr_data_param, // p_data
2936 arr_data_mask_param);
2938 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2939 param, G_DBUS_CALL_FLAGS_NONE,
2943 ERR("scan_filter_add_remove Fail: %s", error->message);
2944 g_clear_error(&error);
2945 return BT_STATUS_FAIL;
2949 g_variant_unref(ret);
2951 return BT_STATUS_SUCCESS;
2954 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2956 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2957 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2959 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2960 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2962 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2963 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2964 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2965 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2966 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2967 NULL, 0, TRUE, NULL, NULL);
2968 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2969 NULL, 0, TRUE, NULL, NULL);
2971 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2972 client_if, // client_if
2973 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2974 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
2975 filt_index, // filter_index
2976 company_id, // company_id
2977 company_id_mask, // company_id_mask
2978 arr_uuid_param, // p_uuid
2979 arr_uuid_mask_param, // p_uuid_mask
2981 addr_type, // address_type
2982 arr_data_param, // p_data
2983 arr_data_mask_param);
2985 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2986 param, G_DBUS_CALL_FLAGS_NONE,
2990 ERR("scan_filter_add_remove Fail: %s", error->message);
2991 g_clear_error(&error);
2992 return BT_STATUS_FAIL;
2996 g_variant_unref(ret);
2998 g_array_free(arr_uuid, TRUE);
2999 g_array_free(arr_uuid_mask, TRUE);
3001 return BT_STATUS_SUCCESS;
3004 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3006 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3007 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3009 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3010 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3012 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3013 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3014 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3015 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3016 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3017 NULL, 0, TRUE, NULL, NULL);
3018 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3019 NULL, 0, TRUE, NULL, NULL);
3021 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3022 client_if, // client_if
3023 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3024 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3025 filt_index, // filter_index
3026 company_id, // company_id
3027 company_id_mask, // company_id_mask
3028 arr_uuid_param, // p_uuid
3029 arr_uuid_mask_param, // p_uuid_mask
3031 addr_type, // address_type
3032 arr_data_param, // p_data
3033 arr_data_mask_param);
3035 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3036 G_DBUS_CALL_FLAGS_NONE,
3040 ERR("scan_filter_add_remove Fail: %s", error->message);
3041 g_clear_error(&error);
3042 return BT_STATUS_FAIL;
3046 g_variant_unref(ret);
3048 g_array_free(arr_uuid, TRUE);
3049 g_array_free(arr_uuid_mask, TRUE);
3051 return BT_STATUS_SUCCESS;
3054 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3056 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3057 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3059 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3060 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3062 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3063 NULL, 0, TRUE, NULL, NULL);
3064 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3065 NULL, 0, TRUE, NULL, NULL);
3066 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3067 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3068 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3069 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3071 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3072 client_if, // client_if
3073 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3074 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3075 filt_index, // filter_index
3076 company_id, // company_id
3077 company_id_mask, // company_id_mask
3078 arr_uuid_param, // p_uuid
3079 arr_uuid_mask_param, // p_uuid_mask
3081 addr_type, // address_type
3082 arr_data_param, // p_data
3083 arr_data_mask_param);
3085 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3086 G_DBUS_CALL_FLAGS_NONE,
3090 ERR("scan_filter_add_remove Fail: %s", error->message);
3091 g_clear_error(&error);
3092 return BT_STATUS_FAIL;
3096 g_variant_unref(ret);
3098 g_array_free(arr_data, TRUE);
3099 g_array_free(arr_data_mask, TRUE);
3101 return BT_STATUS_SUCCESS;
3104 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3106 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3107 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3109 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3110 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3112 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3113 NULL, 0, TRUE, NULL, NULL);
3114 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3115 NULL, 0, TRUE, NULL, NULL);
3116 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3117 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3118 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3119 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3121 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3122 client_if, // client_if
3123 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3124 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3125 filt_index, // filter_index
3126 company_id, // company_id
3127 company_id_mask, // company_id_mask
3128 arr_uuid_param, // p_uuid
3129 arr_uuid_mask_param, // p_uuid_mask
3131 addr_type, // address_type
3132 arr_data_param, // p_data
3133 arr_data_mask_param);
3135 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3136 G_DBUS_CALL_FLAGS_NONE,
3140 ERR("scan_filter_add_remove Fail: %s", error->message);
3141 g_clear_error(&error);
3142 return BT_STATUS_FAIL;
3146 g_variant_unref(ret);
3148 g_array_free(arr_data, TRUE);
3149 g_array_free(arr_data_mask, TRUE);
3151 return BT_STATUS_SUCCESS;
3154 return BT_STATUS_UNSUPPORTED;
3157 /** Clear all scan filter conditions for specific filter index*/
3158 bt_status_t scan_filter_clear(int client_if, int filt_index)
3161 GError *error = NULL;
3163 CHECK_BTGATT_INIT();
3165 proxy = _bt_hal_get_adapter_proxy();
3167 return BT_STATUS_FAIL;
3169 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3170 g_variant_new("(ii)", client_if, filt_index),
3171 G_DBUS_CALL_FLAGS_NONE,
3175 ERR("scan_filter_clear Fail: %s", error->message);
3176 g_clear_error(&error);
3177 return BT_STATUS_FAIL;
3180 g_variant_unref(ret);
3181 return BT_STATUS_SUCCESS;
3184 /** Enable / disable scan filter feature*/
3185 bt_status_t scan_filter_enable(int client_if, bool enable)
3188 GError *error = NULL;
3190 CHECK_BTGATT_INIT();
3192 proxy = _bt_hal_get_adapter_proxy();
3194 return BT_STATUS_FAIL;
3196 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3197 g_variant_new("(ib)", client_if, enable),
3198 G_DBUS_CALL_FLAGS_NONE,
3202 ERR("scan_filter_enable Fail: %s", error->message);
3203 g_clear_error(&error);
3204 return BT_STATUS_FAIL;
3206 g_variant_unref(ret);
3208 return BT_STATUS_SUCCESS;
3211 /** Sets the LE scan interval and window in units of N*0.625 msec */
3213 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3217 CHECK_BTGATT_INIT();
3219 le_scan_type = scan_type;
3220 ret = _bt_hal_adapter_le_set_scan_parameters(
3221 scan_type, scan_interval, scan_window);
3225 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3227 CHECK_BTGATT_INIT();
3228 return BT_STATUS_UNSUPPORTED;
3232 /* Configure the batchscan storage */
3233 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3234 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3236 CHECK_BTGATT_INIT();
3237 return BT_STATUS_UNSUPPORTED;
3240 /* Enable batchscan */
3241 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3242 int scan_interval, int scan_window, int addr_type, int discard_rule)
3244 CHECK_BTGATT_INIT();
3245 return BT_STATUS_UNSUPPORTED;
3248 /* Disable batchscan */
3249 bt_status_t batchscan_dis_batch_scan(int client_if)
3251 CHECK_BTGATT_INIT();
3252 return BT_STATUS_UNSUPPORTED;
3255 /* Read out batchscan reports */
3256 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3258 CHECK_BTGATT_INIT();
3259 return BT_STATUS_UNSUPPORTED;
3262 const btgatt_client_interface_t btgatt_client_interface = {
3263 .register_client = btif_gattc_register_client,
3264 .unregister_client = btif_gattc_unregister_client,
3266 .connect = btif_gattc_client_connect,
3267 .disconnect = btif_gattc_client_disconnect,
3269 .search_service = btif_gattc_client_search_service,
3270 .get_included_service = get_included_service,
3271 .get_characteristic = btif_gattc_get_characteristic,
3272 .get_descriptor = btif_gattc_get_descriptor,
3273 .read_characteristic = btif_read_characteristic,
3274 .write_characteristic = btif_write_characteristic,
3275 .acquire_write = btif_get_acquire_write_fd,
3276 .acquire_notify = btif_get_acquire_notify_fd,
3277 .read_descriptor = btif_read_descriptor,
3278 .write_descriptor = btif_write_descriptor,
3279 .execute_write = execute_write,
3280 .register_for_notification = btif_register_for_notification,
3281 .deregister_for_notification = btif_deregister_for_notification,
3282 .read_remote_rssi = read_remote_rssi,
3283 .ota_fw_update = ota_fw_update,
3284 .get_device_type = get_device_type,
3285 .conn_parameter_update = btif_gattc_conn_parameter_update,
3286 .test_command = test_command,
3287 .configure_mtu = configure_mtu,
3288 .scan_filter_param_setup = scan_filter_param_setup,
3289 .scan_filter_add_remove = scan_filter_add_remove,
3290 .scan_filter_clear = scan_filter_clear,
3291 .scan_filter_enable = scan_filter_enable,
3292 .set_scan_parameters = set_scan_parameters,
3293 .batchscan_cfg_storage = batchscan_cfg_storage,
3294 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3295 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3296 .batchscan_read_reports = batchscan_read_reports,
3297 .add_connection_info = btif_gattc_add_connection_info,
3300 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3303 hal_gattc_server_info_t *info = NULL;
3305 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3306 info = (hal_gattc_server_info_t*)l->data;
3310 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3317 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3320 hal_gattc_client_info_t *info = NULL;
3322 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3323 info = (hal_gattc_client_info_t*)l->data;
3327 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3334 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3337 hal_gattc_client_info_t *info = NULL;
3339 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3340 info = (hal_gattc_client_info_t*)l->data;
3344 if (info->conn_id == conn_id)
3351 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3354 hal_gattc_server_info_t *info = NULL;
3355 hal_gattc_client_info_t *gattc_client = NULL;
3357 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3358 if (gattc_client == NULL) {
3359 ERR("GATT client conn info not found");
3363 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3364 info = (hal_gattc_server_info_t*)l->data;
3368 if ((info->inst_id == gattc_client->inst_id) &&
3369 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3376 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3377 gboolean auto_connect)
3379 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3380 gchar *device_path = NULL;
3381 GDBusProxy *device_proxy = NULL;
3382 GDBusConnection *conn;
3383 int ret = BT_STATUS_SUCCESS;
3384 hal_gattc_client_info_t *gattc_data;
3388 if (NULL == bd_addr) {
3389 ERR("bd_addr is NULL");
3390 return BT_STATUS_PARM_INVALID;
3393 conn = _bt_hal_get_system_gconn();
3395 ERR("_bt_gdbus_get_system_gconn returned NULL");
3396 return BT_STATUS_FAIL;
3399 _bt_hal_convert_addr_type_to_string(device_address,
3400 (unsigned char *)bd_addr->address);
3401 device_path = _bt_hal_get_device_object_path(device_address);
3402 if (device_path == NULL) {
3403 ERR("device_path NULL : [%s]", device_address);
3404 ret = BT_STATUS_FAIL;
3407 ERR("device_path:%s", device_path);
3409 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3410 NULL, BT_HAL_BLUEZ_NAME,
3411 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3412 g_free(device_path);
3413 if (NULL == device_proxy) {
3414 ERR("device_proxy returned NULL");
3415 return BT_STATUS_FAIL;
3418 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3419 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3420 BT_HAL_ADDRESS_LENGTH_MAX);
3422 DBG("Connect LE [%s]", device_address);
3424 gattc_data->client_if = client_if;
3426 g_dbus_proxy_call(device_proxy, "ConnectLE",
3427 g_variant_new("(b)", auto_connect),
3428 G_DBUS_CALL_FLAGS_NONE,
3429 BT_HAL_MAX_DBUS_TIMEOUT,
3431 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3436 static bt_status_t _bt_hold_current_advertising()
3438 int ret = BT_STATUS_FAIL;
3439 gboolean is_advertising = FALSE;
3442 is_advertising = _bt_hal_is_advertising_in_slot(0);
3443 if (is_advertising) {
3444 DBG("+ Stop current advertising");
3446 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3447 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3453 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3455 DBG("+ start current advertising");
3457 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3462 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3464 DBG("Try to initiate pending LE connection");
3466 pending_le_conn_timer_id = 0;
3468 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3469 &pending_le_conn_info->bd_addr,
3470 pending_le_conn_info->auto_connect);
3472 g_free(pending_le_conn_info);
3473 pending_le_conn_info = NULL;
3478 static int __hal_generate_conn_id()
3480 return ++bt_conn_id;
3483 static int __hal_generate_server_instance_id()
3485 return ++bt_inst_id;
3488 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3491 GError *g_error = NULL;
3492 GVariant *reply = NULL;
3493 hal_gattc_client_info_t *gattc_data = user_data;
3494 int result = BT_STATUS_SUCCESS;
3495 struct hal_ev_gatt_client_connected ev;
3496 hal_gattc_server_info_t *gatt_conn_info = NULL;
3500 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3501 g_object_unref(proxy);
3502 if (reply == NULL) {
3503 ERR("Connect LE Dbus Call Error");
3505 ERR("Error: %s\n", g_error->message);
3506 g_clear_error(&g_error);
3508 result = BT_STATUS_FAIL;
3510 g_variant_unref(reply);
3512 if (NULL == gattc_data) {
3513 ERR("server_data is NULL");
3518 if (result == BT_STATUS_FAIL) {
3519 memset(&ev, 0, sizeof(ev));
3522 ev.client_if = gattc_data->client_if;
3523 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3524 BT_HAL_ADDRESS_LENGTH_MAX);
3527 ERR("gatt client callback not registered");
3529 DBG("sending gatt client connected event");
3530 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3536 DBG("adding the server conn info in list");
3537 gattc_data->conn_id = __hal_generate_conn_id() ;
3538 gattc_data->inst_id = __hal_generate_server_instance_id();
3540 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3542 /*add gatt server connection info*/
3543 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3544 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3545 gatt_conn_info->conn_id = gattc_data->conn_id;
3546 gatt_conn_info->inst_id = gattc_data->inst_id;
3547 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3553 /*remove conn_info*/
3558 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3560 g_free(desc_info->desc_path);
3564 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3567 hal_gattc_desc_t *desc_info = NULL;
3568 for (l = char_info->gatt_list_descs; l != NULL; ) {
3569 desc_info = l->data;
3570 l = g_slist_next(l);
3571 if (desc_info == NULL)
3573 /* Remove descriptor element */
3574 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3575 __hal_gattc_free_desc_info(desc_info);
3577 g_slist_free(char_info->gatt_list_descs);
3578 g_free(char_info->chr_path);
3582 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3585 hal_gattc_char_t *char_info = NULL;
3586 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3587 char_info = l->data;
3588 l = g_slist_next(l);
3589 if (char_info == NULL)
3591 /* Remove characteristic element */
3592 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3593 __hal_gattc_free_char_info(char_info);
3595 g_slist_free(svc_info->gatt_list_chars);
3596 g_free(svc_info->svc_path);
3600 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3603 hal_gattc_service_t *svc_info = NULL;
3607 for (l = conn_info->gatt_list_services; l != NULL; ) {
3608 svc_info = (hal_gattc_service_t *)l->data;
3609 l = g_slist_next(l);
3610 if (svc_info == NULL)
3612 /* Remove service element */
3613 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3614 __hal_gattc_free_svc_info(svc_info);
3616 g_slist_free(conn_info->gatt_list_services);
3620 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3622 bt_bdaddr_t bd_addr;
3623 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3624 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3630 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3632 int result = BT_STATUS_SUCCESS;
3633 struct hal_ev_gatt_client_connected ev;
3634 hal_gattc_server_info_t *conn_info = NULL;
3635 bt_bdaddr_t bd_addr;
3637 hal_gattc_client_info_t *gattc_client = NULL;
3641 DBG("+ connected device address [%s]", address);
3643 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3644 HAL_EV_GATT_CLIENT_DISCONNECTED;
3646 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3647 /* find the gatt client info */
3648 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3649 if (NULL == gattc_client) {
3650 ERR("Fail to get gatt client info");
3655 memset(&ev, 0, sizeof(ev));
3656 ev.conn_id = gattc_client->conn_id;
3658 ev.client_if = gattc_client->client_if;
3659 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3660 BT_HAL_ADDRESS_LENGTH_MAX);
3663 ERR("gatt client callback not registered");
3665 DBG("sending gatt client connected status event");
3666 event_cb(event, (void *)&ev, sizeof(ev));
3669 if (!gatt_connected) {
3670 inst_id = gattc_client->inst_id;
3672 /* remove the gatt client info from the client list also*/
3673 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3674 g_free(gattc_client);
3676 //find the connected server info
3677 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3678 if (NULL == conn_info) {
3679 ERR("Fail to get gatt server info");
3683 if (inst_id != conn_info->inst_id) {
3684 ERR("server instance is different");
3688 //remove gatt conn info from the server list
3689 DBG("remove the server conn_info from list after gatt disconnection");
3690 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3691 __hal_clean_gattc_server_info(conn_info);
3697 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3698 const char* uuid_str, int inst_id)
3700 struct hal_ev_gatt_client_search_result ev;
3703 ERR("gatt client callback not registered");
3707 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3709 memset(&ev, 0, sizeof(ev));
3710 ev.conn_id = conn_id;
3711 ev.inst_id = inst_id;
3712 ev.is_primary = is_primary;
3713 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3715 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3718 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3720 struct hal_ev_gatt_client_search_complete ev;
3723 ERR("gatt client callback not registered");
3727 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3730 memset(&ev, 0, sizeof(ev));
3731 ev.conn_id = conn_id;
3734 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3737 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3738 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3739 char *char_value, int len)
3741 struct hal_ev_gatt_client_notify_changed_value ev;
3742 hal_gattc_client_info_t *gattc_client = NULL;
3745 ERR("gatt client callback not registered");
3749 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3750 if (NULL == gattc_client) {
3751 ERR("failed to get the gatt client info");
3756 DBG("sending gatt client connected status event");
3757 memset(&ev, 0, sizeof(ev));
3759 ev.conn_id = gattc_client->conn_id;
3760 ev.inst_id = conn_info->inst_id;
3761 ev.is_primary = svc_info->is_primary;
3762 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3763 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3765 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3767 if (len > 0 && (char_value != NULL)) {
3768 memcpy(ev.value, char_value, len);
3772 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3775 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3776 char *char_value, int len)
3778 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3779 hal_gattc_server_info_t *conn_info = NULL;
3780 bt_bdaddr_t bd_addr;
3783 hal_gattc_service_t *svc_info = NULL;
3784 hal_gattc_char_t *char_info = NULL;
3788 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3789 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3790 DBG("device address:[%s]", device_address);
3791 DBG("char handle:[%s]", char_handle);
3793 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3794 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3796 if (conn_info != NULL) {
3797 //find service for notified char path
3798 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3799 svc_info = (hal_gattc_service_t*)l->data;
3800 if (svc_info == NULL)
3803 /* find characteristic object path */
3804 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3805 char_info = (hal_gattc_char_t *)k->data;
3806 if (char_info == NULL)
3809 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3810 DBG("Found char handle[%s]", char_info->chr_path);
3813 _bt_hal_send_value_changed_event(conn_info, svc_info,
3814 char_info, char_value, len);
3822 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3824 GDBusConnection *g_conn = NULL;
3825 GDBusProxy *properties_proxy = NULL;
3826 GVariant *result = NULL;
3827 GError *error = NULL;
3828 GVariantIter *property_iter = NULL;
3829 const gchar *key = NULL;
3830 GVariant *value = NULL;
3831 const char *uuid_str = NULL;
3833 gboolean is_primary = FALSE;
3834 GVariantIter *char_iter = NULL;
3835 const char *char_handle = NULL;
3836 GPtrArray *gp_char_array = NULL;
3838 if (service_path == NULL) {
3839 ERR("service_path is NULL");
3840 return BT_STATUS_FAIL;
3843 DBG("service_path: %s", service_path);
3845 g_conn = _bt_hal_get_system_gconn();
3846 if (g_conn == NULL) {
3847 ERR("g_conn is NULL");
3848 return BT_STATUS_FAIL;
3851 properties_proxy = g_dbus_proxy_new_sync(g_conn,
3852 G_DBUS_PROXY_FLAGS_NONE, NULL,
3855 BT_HAL_PROPERTIES_INTERFACE,
3857 if (properties_proxy == NULL) {
3858 ERR("properties_proxy is NULL");
3859 return BT_STATUS_FAIL;
3862 result = g_dbus_proxy_call_sync(properties_proxy,
3864 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
3865 G_DBUS_CALL_FLAGS_NONE,
3867 if (result == NULL) {
3868 if (error != NULL) {
3869 ERR("Fail to get properties (Error: %s)", error->message);
3870 g_clear_error(&error);
3872 ERR("Fail to get properties");
3874 g_object_unref(properties_proxy);
3875 return BT_STATUS_FAIL;
3878 g_variant_get(result, "(a{sv})", &property_iter);
3880 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
3881 if (g_strcmp0(key, "UUID") == 0) {
3882 uuid_str = g_variant_get_string(value, &len);
3883 DBG("UUID: %s", uuid_str);
3884 } else if (g_strcmp0(key, "Primary") == 0) {
3885 is_primary = g_variant_get_boolean(value);
3886 DBG("is_primary: %s", is_primary ? "TRUE" : "FALSE");
3887 } else if (g_strcmp0(key, "Characteristics") == 0) {
3888 g_variant_get(value, "ao", &char_iter);
3889 if (char_iter != NULL) {
3890 gp_char_array = g_ptr_array_new();
3891 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
3892 DBG("char_handle: %s", char_handle);
3893 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
3899 if (uuid_str == NULL || gp_char_array == NULL) {
3900 ERR("uuid_str and gp_char_array should be set");
3904 /* Create new service */
3905 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
3908 g_variant_iter_free(property_iter);
3909 g_variant_unref(result);
3910 g_object_unref(properties_proxy);
3912 return BT_STATUS_SUCCESS;
3915 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
3917 GDBusConnection *conn = NULL;
3918 GDBusProxy *proxy = NULL;
3920 GVariant *ret = NULL;
3921 GVariant *value = NULL;
3923 conn = _bt_hal_get_system_gconn();
3925 ERR("_bt_gdbus_get_system_gconn returned NULL");
3929 proxy = g_dbus_proxy_new_sync(conn,
3930 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
3931 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
3932 if (proxy == NULL) {
3933 ERR("device_proxy returned NULL");
3937 ret = g_dbus_proxy_call_sync(proxy, "Get",
3938 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
3939 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3941 ERR("DBus Error : %s", err->message);
3942 g_clear_error(&err);
3944 g_variant_get(ret, "(v)", &value);
3945 *service_uuid = g_variant_dup_string(value, NULL);
3946 g_variant_unref(value);
3947 g_variant_unref(ret);
3951 g_object_unref(proxy);
3956 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
3958 struct hal_ev_gatt_client_service_changed ev = {0, };
3959 char address[BT_HAL_ADDRESS_STRING_SIZE];
3960 hal_gattc_server_info_t *server_info = NULL;
3961 hal_gattc_service_t *service = NULL;
3962 GSList *list = NULL;
3963 char *uuid_str = NULL;
3965 _bt_hal_convert_device_path_to_address(path, address);
3966 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
3967 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
3968 if (server_info == NULL) {
3969 ERR("service_info is NULL");
3974 /* Get service UUID from path */
3975 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
3977 DBG("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
3978 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3981 ERR("uuid_str is NULL");
3985 /* Create new service and append into the list */
3986 __hal_gattc_get_service_info(server_info, path);
3988 /* Find service UUID from path */
3989 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
3990 service = (hal_gattc_service_t *)list->data;
3991 if (service == NULL)
3994 if (g_strcmp0(service->svc_path, path) == 0) {
3995 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
3996 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
3997 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
3998 DBG("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
4000 /* Remove service info in list */
4001 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4002 __hal_gattc_free_svc_info(service);
4010 ERR("uuid_str is NULL");
4015 /* Send GATT Client service changed event */
4016 ev.change_type = is_added;
4017 ev.conn_id = server_info->conn_id;
4018 ev.inst_id = server_info->inst_id;
4019 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));