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 #define BT_GATTC_CL_MAX 32
154 btgatt_srvc_id_t srvc_id;
155 btgatt_gatt_id_t char_id;
156 btgatt_gatt_id_t desc_id;
157 } hal_gatt_resp_data_t;
162 } hal_gatt_client_app;
164 static GSList * hal_gattc_client_app_list = NULL;
166 static int bt_client_if = 0;
173 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
174 gboolean auto_connect);
175 static bt_status_t _bt_hold_current_advertising();
176 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
177 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
178 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
180 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
181 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
182 const char* uuid_str, int inst_id);
183 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
184 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr);
185 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
186 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
189 /* To send stack event to hal-av handler */
190 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
195 void _bt_hal_unregister_gatt_client_handler_cb(void)
201 int _bt_hal_gatt_client_get_le_scan_type(void)
207 static gboolean __bt_hal_register_client_cb(gpointer user_data)
209 struct hal_ev_gatt_client_registered ev;
210 hal_gatt_client_app *client_info = user_data;
212 /* Prepare to send AV connecting event */
213 memset(&ev, 0, sizeof(ev));
214 ev.status = BT_STATUS_SUCCESS;
215 ev.client_if = client_info->client_if;
216 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
219 ERR("GATT Callback not registered");
221 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
222 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
229 static int __hal_generate_client_id()
231 return ++bt_client_if;
234 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
237 hal_gatt_client_app *info = NULL;
238 hal_gatt_client_app *gattc_app = NULL;
240 //check if client app is already registered
241 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
242 info = (hal_gatt_client_app*)l->data;
246 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
247 DBG("gatt client app already registered");
252 DBG("adding the gatt client app");
255 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
256 gattc_app->client_if = __hal_generate_client_id();
257 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
259 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
264 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
266 hal_gatt_client_app *gattc_app = NULL;
267 hal_gatt_client_app *client_app_info = NULL;
269 /* add gatt client in list */
270 gattc_app = __hal_gattc_add_client_app(app_uuid);
271 if (gattc_app == NULL) {
272 ERR("Failed to register gatt client app");
273 return BT_STATUS_FAIL;
277 client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
278 client_app_info->client_if = gattc_app->client_if;
279 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
280 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
282 DBG("registered client client_if [%d]", client_app_info->client_if);
284 return BT_STATUS_SUCCESS;
287 /** Registers a GATT client application with the stack */
288 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
292 return __hal_gattc_register_client_app(uuid);
295 bt_status_t btif_gattc_add_connection_info(const bt_bdaddr_t *bd_addr, int conn_id, int server_inst_id)
297 hal_gattc_client_info_t *client_info = NULL;
298 hal_gattc_server_info_t *server_info = NULL;
300 /* Add client connection info in list */
301 client_info = g_malloc0(sizeof(hal_gattc_client_info_t));
302 client_info->client_if = -1;
303 memcpy(client_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
304 client_info->conn_id = conn_id;
305 client_info->inst_id = server_inst_id;
306 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, client_info);
307 DBG("Added client connection info in list");
309 /* Add server connection info in list */
310 server_info = __bt_find_gatt_conn_info(bd_addr);
311 if (server_info == NULL) {
312 server_info = g_malloc0(sizeof(hal_gattc_server_info_t));
313 memcpy(server_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
314 server_info->conn_id = conn_id;
315 server_info->inst_id = server_inst_id;
316 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, server_info);
317 DBG("Added server connection info in list");
320 return BT_STATUS_SUCCESS;
323 bt_status_t __hal_gattc_unregister_client(int client_if)
326 hal_gatt_client_app *info = NULL;
328 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
330 /* remove the gatt client app */
331 for (l = hal_gattc_client_app_list; l != NULL; ) {
332 info = (hal_gatt_client_app*)l->data;
338 if (info->client_if == client_if) {
339 DBG("gatt client app found");
340 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
345 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
346 return BT_STATUS_SUCCESS;
349 /** Unregister a client application from the stack */
350 bt_status_t btif_gattc_unregister_client(int client_if)
354 return __hal_gattc_unregister_client(client_if);
357 /** Start or stop LE device scanning */
358 bt_status_t scan(int client_if, bool start)
365 ret = _bt_hal_adapter_le_start_scan();
367 ret = _bt_hal_adapter_le_stop_scan();
372 /** Create a connection to a remote LE or dual-mode device */
373 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
376 int ret = BT_STATUS_SUCCESS;
381 return BT_STATUS_PARM_INVALID;
383 ret = _bt_hold_current_advertising();
384 if (ret == BT_STATUS_SUCCESS) {
385 DBG("Current advertising is held");
386 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
387 pending_le_conn_info->client_if = client_if;
388 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
389 BT_HAL_ADDRESS_LENGTH_MAX);
390 pending_le_conn_info->auto_connect = is_direct;
392 pending_le_conn_timer_id =
393 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
395 return BT_STATUS_SUCCESS;
397 ERR("advertising is not stopped");
400 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
404 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
407 GError *g_error = NULL;
408 GVariant *reply = NULL;
409 hal_gattc_client_info_t *gatt_conn_info = user_data;
410 int result = BT_STATUS_SUCCESS;
411 struct hal_ev_gatt_client_connected ev;
415 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
416 g_object_unref(proxy);
418 ERR("Connect LE Dbus Call Error");
420 ERR("Error: %s\n", g_error->message);
421 g_clear_error(&g_error);
423 result = BT_STATUS_FAIL;
425 g_variant_unref(reply);
427 if (NULL == gatt_conn_info) {
428 ERR("server_data is NULL");
433 if (result == BT_STATUS_FAIL) {
434 memset(&ev, 0, sizeof(ev));
435 ev.conn_id = gatt_conn_info->conn_id;
437 ev.client_if = gatt_conn_info->client_if;
438 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
439 BT_HAL_ADDRESS_LENGTH_MAX);
442 ERR("gatt client callback not registered");
444 DBG("sending gatt client disconnected event");
445 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
451 g_free(gatt_conn_info);
456 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
459 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
461 GDBusProxy *device_proxy;
462 GDBusConnection *conn;
463 int ret = BT_STATUS_SUCCESS;
464 hal_gattc_client_info_t *gattc_data;
466 if (NULL == bd_addr) {
467 ERR("bd_addr is NULL");
468 return BT_STATUS_PARM_INVALID;
471 conn = _bt_hal_get_system_gconn();
473 ERR("_bt_gdbus_get_system_gconn returned NULL");
474 return BT_STATUS_FAIL;
477 _bt_hal_convert_addr_type_to_string(device_address,
478 (unsigned char *)bd_addr->address);
479 device_path = _bt_hal_get_device_object_path(device_address);
480 if (device_path == NULL) {
481 DBG("device_path NULL");
482 ret = BT_STATUS_FAIL;
486 ERR("device_path:%s", device_path);
488 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
489 NULL, BT_HAL_BLUEZ_NAME,
490 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
492 if (NULL == device_proxy) {
493 ERR("device_proxy returned NULL");
494 return BT_STATUS_FAIL;
497 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
498 memcpy(gattc_data->bd_addr.address, bd_addr->address,
499 BT_HAL_ADDRESS_LENGTH_MAX);
500 gattc_data->client_if = client_if;
501 gattc_data->conn_id = conn_id;
503 DBG("DisconnectLE [%s]", device_address);
505 g_dbus_proxy_call(device_proxy, "DisconnectLE",
507 G_DBUS_CALL_FLAGS_NONE,
508 BT_HAL_MAX_DBUS_TIMEOUT,
510 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
514 /** Disconnect a remote device or cancel a pending connection */
515 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
520 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
523 /** Clear the attribute cache for a given device */
524 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
527 return BT_STATUS_UNSUPPORTED;
530 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
533 hal_gattc_service_t *info = NULL;
535 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
536 info = (hal_gattc_service_t*)l->data;
540 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t)))
548 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
549 bt_gatt_characteristic_property_t prop)
552 hal_gattc_char_t *info = NULL;
554 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
555 info = (hal_gattc_char_t*)l->data;
559 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
560 (info->permission & prop)) {
567 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
570 hal_gattc_char_t *info = NULL;
572 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
573 info = (hal_gattc_char_t*)l->data;
577 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
578 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
579 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
586 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
589 hal_gattc_desc_t *info = NULL;
591 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
592 info = (hal_gattc_desc_t*)l->data;
596 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t)))
603 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
604 const char *uuid_str, const char *object_path, int is_primary)
606 hal_gattc_service_t *gattc_service = NULL;
608 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
609 gattc_service->svc_path = g_strdup(object_path);
610 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
611 gattc_service->is_primary = is_primary;
613 INFO("[%d] [%s] [%s]", g_slist_length(conn_info->gatt_list_services), object_path + 15, uuid_str);
615 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
617 return gattc_service;
620 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
622 hal_gattc_char_t *gattc_char = NULL;
624 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
625 gattc_char->chr_path = g_strdup(char_handle);
627 DBG("svc path: [%s]", gatt_svc->svc_path);
628 DBG("char path: [%s]", gattc_char->chr_path);
630 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
633 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
634 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
636 hal_gattc_service_t* gatt_svc = NULL;
638 gchar *gp_char_path = NULL;
640 /* add the service */
641 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
642 if (gatt_svc == NULL) {
643 ERR("Failed to add service");
647 /* add the characteristic */
648 for (i = 0; i < gp_char_array->len; i++) {
649 gp_char_path = g_ptr_array_index(gp_char_array, i);
650 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
653 g_ptr_array_free(gp_char_array, TRUE);
656 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
658 hal_gattc_desc_t *gattc_desc = NULL;
660 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
661 gattc_desc->desc_path = g_strdup(desc_path);
663 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
666 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
667 GPtrArray *gp_desc_array, unsigned int char_permission)
669 gchar *gp_desc_path = NULL;
672 if (char_uuid_str == NULL) {
673 DBG("char_uuid_str is NULL");
677 //update the char uuid
678 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
680 //update char permission
681 gattc_char->permission = char_permission;
684 for (i = 0; i < gp_desc_array->len; i++) {
685 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
686 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
690 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
692 if (desc_uuid_str == NULL) {
693 DBG("char_uuid_str is NULL");
697 //update the descriptor uuid
698 DBG("desc UUID: [%s] ", desc_uuid_str);
699 DBG("desc path: [%s]", gattc_desc->desc_path);
701 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
704 static void browse_service_char(int conn_id)
706 hal_gattc_server_info_t *conn_info = NULL;
710 hal_gattc_service_t *svc_info = NULL;
711 hal_gattc_char_t *char_info = NULL;
712 hal_gattc_desc_t *desc_info = NULL;
714 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
715 if (conn_info == NULL) {
716 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
720 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
721 svc_info = (hal_gattc_service_t*)l->data;
722 if (svc_info == NULL)
725 /* find characteristic object path */
726 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
727 char_info = (hal_gattc_char_t *)k->data;
728 if (char_info == NULL)
732 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
733 desc_info = (hal_gattc_desc_t *)m->data;
734 if (desc_info == NULL)
744 * Enumerate all GATT services on a connected device.
745 * Optionally, the results can be filtered for a given UUID.
747 static bt_status_t _gattc_client_search_service(int conn_id)
751 GVariant *result = NULL;
753 GVariantIter *svc_iter;
754 GVariantIter *interface_iter;
755 char *object_path = NULL;
756 char *interface_str = NULL;
757 const gchar *key = NULL;
758 GVariant *value = NULL;
759 GPtrArray *gp_array = NULL;
760 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
761 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
762 int ret = BT_STATUS_FAIL;
764 const gchar *uuid_str = NULL;
766 hal_gattc_server_info_t *conn_info = NULL;
767 gboolean is_primary = FALSE;
770 char *char_handle = NULL;
771 GVariantIter *char_iter = NULL;
772 GPtrArray *gp_char_array = NULL;
774 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
775 if (NULL == conn_info) {
776 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
777 return BT_STATUS_FAIL;
781 // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
782 /* Check the service info is stored */
783 if (g_slist_length(conn_info->gatt_list_services) > 0) {
785 hal_gattc_service_t *svc_info = NULL;
786 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
787 DBG("Send event from service info list");
788 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
790 if (svc_info == NULL)
792 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
793 _bt_hal_send_search_service_result_event(conn_id,
794 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
796 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
797 return BT_STATUS_SUCCESS;
799 DBG("No stored service, request to bluez");
803 _bt_hal_convert_addr_type_to_string(device_address,
804 (unsigned char *)conn_info->bd_addr.address);
806 result = _bt_hal_get_managed_objects();
810 gp_array = g_ptr_array_new();
811 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
813 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
815 if (object_path == NULL)
818 _bt_hal_convert_device_path_to_address(object_path, temp_address);
820 if (g_strcmp0(temp_address, device_address) != 0)
823 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
824 &interface_str, &svc_iter)) {
825 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
828 DBG("[%d] Object Path : %s", idx++, object_path);
829 /* for characteristic */
830 gp_char_array = g_ptr_array_new();
831 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
832 if (g_strcmp0(key, "Primary") == 0) {
833 is_primary = g_variant_get_boolean(value);
835 g_ptr_array_add(gp_array, (gpointer)object_path);
838 } else if (g_strcmp0(key, "UUID") == 0) {
839 uuid_str = g_variant_get_string(value, &len);
840 } else if (g_strcmp0(key, "Characteristics") == 0) {
841 g_variant_get(value, "ao", &char_iter);
842 if (char_iter != NULL) {
843 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
844 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
851 _bt_hal_send_search_service_result_event(conn_id, is_primary,
852 uuid_str, conn_info->inst_id);
854 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
859 if (gp_array->len == 0 || svc_count == 0) {
860 ERR("gp_array is NULL");
861 ret = BT_STATUS_FAIL;
863 ret = BT_STATUS_SUCCESS;
866 browse_service_char(conn_id);
867 /* send search service complete event */
868 _bt_hal_send_search_service_complete_event(conn_id, ret);
870 g_ptr_array_free(gp_array, TRUE);
871 g_variant_iter_free(iter);
872 g_variant_unref(result);
877 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
879 if (NULL == filter_uuid) {
880 DBG("Browse all the services");
881 return _gattc_client_search_service(conn_id);
883 DBG("TODO implement it");
884 return BT_STATUS_UNSUPPORTED;
888 * Enumerate included services for a given service.
889 * Set start_incl_srvc_id to NULL to get the first included service.
891 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
892 btgatt_srvc_id_t *start_incl_srvc_id)
895 return BT_STATUS_UNSUPPORTED;
898 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
899 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
901 struct hal_ev_gatt_client_char_search_result ev;
904 ERR("gatt client callback not registered");
908 memset(&ev, 0, sizeof(ev));
909 ev.conn_id = conn_id;
910 ev.inst_id = svc_id->id.inst_id;
911 ev.is_primary = svc_id->is_primary;
913 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
915 if (status == BT_STATUS_SUCCESS) {
916 /* building char uuid */
917 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
918 ev.char_prop = char_prop;
921 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
922 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
925 static int _hal_get_permission_flag(char *permission)
929 if (NULL == permission) {
930 ERR("gatt permission is NULL");
934 if (!g_strcmp0(permission, "broadcast"))
935 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
936 else if (!g_strcmp0(permission, "read"))
937 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
938 else if (!g_strcmp0(permission, "write-without-response"))
939 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
940 else if (!g_strcmp0(permission, "write"))
941 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
942 else if (!g_strcmp0(permission, "notify"))
943 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
944 else if (!g_strcmp0(permission, "indicate"))
945 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
946 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
947 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
948 else if (!g_strcmp0(permission, "reliable-write"))
949 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
950 else if (!g_strcmp0(permission, "writable-auxiliaries"))
951 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
952 else if (!g_strcmp0(permission, "encrypt-read"))
953 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
954 else if (!g_strcmp0(permission, "encrypt-write"))
955 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
956 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
957 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
958 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
959 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
964 static void __hal_convert_permission_flag_to_str(unsigned int permission)
966 char perm[200] = { 0, };
968 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
969 g_strlcat(perm, "broadcast ", sizeof(perm));
970 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
971 g_strlcat(perm, "read ", sizeof(perm));
972 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
973 g_strlcat(perm, "write-without-response ", sizeof(perm));
974 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
975 g_strlcat(perm, "write ", sizeof(perm));
976 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
977 g_strlcat(perm, "notify ", sizeof(perm));
978 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
979 g_strlcat(perm, "indicate ", sizeof(perm));
980 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
981 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
982 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
983 g_strlcat(perm, "reliable-write ", sizeof(perm));
984 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
985 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
986 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
987 g_strlcat(perm, "encrypt-read ", sizeof(perm));
988 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
989 g_strlcat(perm, "encrypt-write ", sizeof(perm));
990 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
991 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
992 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
993 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
995 DBG("permission [0x%04x] : %s\n", permission, perm);
999 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1001 GDBusProxy *properties_proxy = NULL;
1002 GError *error = NULL;
1003 GVariant *value = NULL;
1004 GVariant *result = NULL;
1005 GDBusConnection *g_conn;
1007 char *char_desc_handle = NULL;
1009 GVariantIter *property_iter;
1010 GVariantIter *char_desc_iter;
1011 char* char_handle = NULL;
1012 gchar *char_uuid_str = NULL;
1013 GPtrArray *gp_desc_array = NULL;
1014 GVariantIter *char_perm_iter;
1016 unsigned int char_permission = 0 ;
1018 if (gattc_char->chr_path == NULL) {
1019 DBG("char path is NULL");
1020 return BT_STATUS_FAIL;
1022 char_handle = gattc_char->chr_path;
1024 g_conn = _bt_hal_get_system_gconn();
1025 if (NULL == g_conn) {
1026 ERR("_bt_gdbus_get_system_gconn returned NULL");
1027 return BT_STATUS_FAIL;
1030 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1031 G_DBUS_PROXY_FLAGS_NONE, NULL,
1034 BT_HAL_PROPERTIES_INTERFACE,
1037 if (properties_proxy == NULL) {
1038 ERR("properties_proxy returned NULL");
1039 return BT_STATUS_FAIL;
1042 result = g_dbus_proxy_call_sync(properties_proxy,
1044 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1045 G_DBUS_CALL_FLAGS_NONE,
1050 if (error != NULL) {
1051 ERR("Fail to get properties (Error: %s)", error->message);
1052 g_clear_error(&error);
1054 ERR("Fail to get properties");
1055 g_object_unref(properties_proxy);
1056 return BT_STATUS_FAIL;
1059 gp_desc_array = g_ptr_array_new();
1061 g_variant_get(result, "(a{sv})", &property_iter);
1063 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1064 if (!g_strcmp0(key, "UUID")) {
1065 char_uuid_str = g_variant_dup_string(value, &len);
1066 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1067 } else if (!g_strcmp0(key, "Flags")) {
1068 g_variant_get(value, "as", &char_perm_iter);
1069 char_permission = 0x00;
1071 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1072 char_permission |= _hal_get_permission_flag(permission);
1074 __hal_convert_permission_flag_to_str(char_permission);
1075 } else if (!g_strcmp0(key, "Descriptors")) {
1076 g_variant_get(value, "ao", &char_desc_iter);
1077 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1078 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1083 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1085 g_free(char_uuid_str);
1086 g_variant_iter_free(property_iter);
1087 g_variant_unref(result);
1088 g_object_unref(properties_proxy);
1089 g_ptr_array_free(gp_desc_array, TRUE);
1091 return BT_STATUS_SUCCESS;
1094 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1095 btgatt_srvc_id_t *srvc_id)
1097 hal_gattc_server_info_t * conn_info = NULL;
1098 hal_gattc_service_t *gattc_service = NULL;
1100 hal_gattc_char_t *gattc_char = NULL;
1101 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1102 int status = BT_STATUS_FAIL;
1104 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1105 if (NULL == conn_info) {
1106 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1107 return BT_STATUS_FAIL;
1111 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1112 if (NULL == gattc_service) {
1113 ERR("Failed to get the gatt service");
1114 return BT_STATUS_FAIL;
1117 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1118 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1120 /* find characteristic object path */
1121 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1122 gattc_char = (hal_gattc_char_t *)l->data;
1123 status = _hal_gattc_get_characteristic_info(gattc_char);
1126 if (BT_STATUS_SUCCESS == status) {
1127 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1128 &gattc_char->chr_uuid, gattc_char->permission);
1132 status = BT_STATUS_FAIL;
1133 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1135 browse_service_char(conn_id);
1136 /* retrive uuid for characteristic and object path for descriptor */
1138 return BT_STATUS_SUCCESS;
1142 * Enumerate characteristics for a given service.
1143 * Set start_char_id to NULL to get the first characteristic.
1145 bt_status_t btif_gattc_get_characteristic(int conn_id,
1146 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1148 CHECK_BTGATT_INIT();
1150 if (start_char_id == NULL) {
1151 DBG("Get all the characteristics");
1152 return _gattc_get_all_characteristic(conn_id, srvc_id);
1155 DBG("TBD Get specific characteristics");
1156 return BT_STATUS_UNSUPPORTED;
1160 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1162 GDBusProxy *properties_proxy = NULL;
1163 GError *error = NULL;
1164 GVariant *value = NULL;
1165 GVariant *result = NULL;
1166 GDBusConnection *g_conn;
1169 GVariantIter *property_iter;
1170 char* desc_handle = NULL;
1171 const gchar *desc_uuid_str = NULL;
1173 if (gattc_desc->desc_path == NULL) {
1174 DBG("desc path is NULL");
1175 return BT_STATUS_FAIL;
1177 desc_handle = gattc_desc->desc_path;
1179 g_conn = _bt_hal_get_system_gconn();
1180 if (NULL == g_conn) {
1181 ERR("_bt_gdbus_get_system_gconn returned NULL");
1182 return BT_STATUS_FAIL;
1185 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1186 G_DBUS_PROXY_FLAGS_NONE, NULL,
1189 BT_HAL_PROPERTIES_INTERFACE,
1192 if (properties_proxy == NULL) {
1193 ERR("properties_proxy returned NULL");
1194 return BT_STATUS_FAIL;
1197 result = g_dbus_proxy_call_sync(properties_proxy,
1199 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1200 G_DBUS_CALL_FLAGS_NONE,
1205 if (error != NULL) {
1206 ERR("Fail to get properties (Error: %s)", error->message);
1207 g_clear_error(&error);
1209 ERR("Fail to get properties");
1210 g_object_unref(properties_proxy);
1211 return BT_STATUS_FAIL;
1214 g_variant_get(result, "(a{sv})", &property_iter);
1216 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1217 if (!g_strcmp0(key, "UUID")) {
1218 desc_uuid_str = g_variant_get_string(value, &len);
1219 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1224 g_variant_iter_free(property_iter);
1225 g_variant_unref(result);
1226 g_object_unref(properties_proxy);
1228 return BT_STATUS_SUCCESS;
1231 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1232 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1234 struct hal_ev_gatt_client_desc_search_result ev;
1237 ERR("gatt client callback not registered");
1241 memset(&ev, 0, sizeof(ev));
1242 ev.conn_id = conn_id;
1243 ev.inst_id = svc_id->id.inst_id;
1244 ev.is_primary = svc_id->is_primary;
1247 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1248 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1250 if (status == BT_STATUS_SUCCESS) {
1251 /* building desc uuid */
1252 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1255 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1257 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1260 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1261 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1263 hal_gattc_server_info_t * conn_info = NULL;
1264 hal_gattc_service_t *gattc_service = NULL;
1267 hal_gattc_char_t *gattc_char = NULL;
1268 hal_gattc_desc_t *gattc_desc = NULL;
1269 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1270 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1271 int status = BT_STATUS_FAIL;
1273 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1274 if (NULL == conn_info) {
1275 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1276 return BT_STATUS_FAIL;
1280 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1281 if (NULL == gattc_service) {
1282 ERR("Failed to get the gatt service");
1283 return BT_STATUS_FAIL;
1286 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1287 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1289 /* find characteristics */
1290 /* a service can have two char with same uuid */
1291 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1292 gattc_char = (hal_gattc_char_t*)l->data;
1293 if (gattc_char == NULL)
1296 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1297 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1298 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1300 /* get descriptor uuid */
1301 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1302 gattc_desc = (hal_gattc_desc_t *)m->data;
1303 if (gattc_desc == NULL)
1306 status = _hal_gattc_get_descriptor_info(gattc_desc);
1309 if (BT_STATUS_SUCCESS == status) {
1310 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1311 char_id, &gattc_desc->desc_uuid);
1317 status = BT_STATUS_FAIL;
1318 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1320 browse_service_char(conn_id);
1321 /* retrive uuid for characteristic and object path for descriptor */
1323 return BT_STATUS_SUCCESS;
1327 * Enumerate descriptors for a given characteristic.
1328 * Set start_descr_id to NULL to get the first descriptor.
1330 bt_status_t btif_gattc_get_descriptor(int conn_id,
1331 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1332 btgatt_gatt_id_t *start_descr_id)
1334 CHECK_BTGATT_INIT();
1336 if (start_descr_id == NULL) {
1337 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1339 DBG("TBD Get specific descriptor");
1340 return BT_STATUS_UNSUPPORTED;
1344 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1346 struct hal_ev_gatt_client_read_data ev;
1349 ERR("gatt client callback not registered");
1353 memset(&ev, 0, sizeof(ev));
1354 ev.conn_id = resp_data->conn_id;
1355 ev.inst_id = resp_data->srvc_id.id.inst_id;
1356 ev.is_primary = resp_data->srvc_id.is_primary;
1359 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1360 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1364 /* building the char read value */
1365 memcpy(ev.value, value, len);
1368 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1370 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1373 static void __hal_internal_read_char_cb(GObject *source_object,
1374 GAsyncResult *res, gpointer user_data)
1376 GError *error = NULL;
1377 GDBusConnection *system_gconn = NULL;
1380 GByteArray *gp_byte_array = NULL;
1382 hal_gatt_resp_data_t *resp_data = user_data;
1383 int result = BT_STATUS_SUCCESS;
1385 system_gconn = _bt_hal_get_system_gconn();
1386 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1389 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1392 result = BT_STATUS_FAIL;
1393 __hal_send_char_read_event(resp_data, result, NULL, 0);
1394 g_clear_error(&error);
1399 gp_byte_array = g_byte_array_new();
1400 g_variant_get(value, "(ay)", &iter);
1402 while (g_variant_iter_loop(iter, "y", &g_byte))
1403 g_byte_array_append(gp_byte_array, &g_byte, 1);
1407 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1411 g_byte_array_free(gp_byte_array, TRUE);
1412 g_variant_iter_free(iter);
1413 g_variant_unref(value);
1417 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1418 btgatt_gatt_id_t *char_id, int auth_req)
1420 GDBusConnection *g_conn;
1421 hal_gatt_resp_data_t *resp_data;
1422 hal_gattc_service_t *gattc_service = NULL;
1423 GVariantBuilder *builder = NULL;
1425 hal_gattc_server_info_t * conn_info = NULL;
1426 hal_gattc_char_t *gattc_char = NULL;
1427 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1428 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1429 char* char_handle = NULL;
1431 /* get the connection info */
1432 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1433 if (NULL == conn_info) {
1434 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1435 return BT_STATUS_FAIL;
1439 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1440 if (NULL == gattc_service) {
1441 ERR("Failed to get the gatt service");
1442 return BT_STATUS_FAIL;
1445 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1447 /* find characteristic */
1448 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1449 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1450 if (NULL == gattc_char) {
1451 ERR("Failed to get the gatt char");
1452 return BT_STATUS_FAIL;
1455 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1456 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1458 g_conn = _bt_hal_get_system_gconn();
1459 if (NULL == g_conn) {
1460 ERR("_bt_gdbus_get_system_gconn returned NULL");
1461 return BT_STATUS_FAIL;
1464 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1465 resp_data->conn_id = conn_id;
1466 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1467 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1469 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1472 g_variant_builder_add(builder, "{sv}", "offset",
1473 g_variant_new("q", offset));
1475 char_handle = gattc_char->chr_path;
1477 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1478 "ReadValue", g_variant_new("(a{sv})", builder),
1479 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1480 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1481 (gpointer)resp_data);
1482 g_variant_builder_unref(builder);
1484 return BT_STATUS_SUCCESS;
1487 /** Read a characteristic on a remote device */
1488 bt_status_t btif_read_characteristic(int conn_id,
1489 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1492 CHECK_BTGATT_INIT();
1494 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1497 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1499 struct hal_ev_gatt_client_write_result ev;
1502 ERR("gatt client callback not registered");
1506 memset(&ev, 0, sizeof(ev));
1507 ev.conn_id = resp_data->conn_id;
1508 ev.inst_id = resp_data->srvc_id.id.inst_id;
1509 ev.is_primary = resp_data->srvc_id.is_primary;
1512 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1513 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1515 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1517 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1520 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1521 GAsyncResult *res, gpointer user_data)
1523 GError *error = NULL;
1524 GDBusConnection *system_gconn = NULL;
1526 hal_gatt_resp_data_t *resp_data = user_data;
1527 int result = BT_STATUS_SUCCESS;
1531 system_gconn = _bt_hal_get_system_gconn();
1532 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1535 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1537 result = BT_STATUS_FAIL;
1539 __hal_send_char_write_event(resp_data, result);
1540 g_clear_error(&error);
1545 //send write value event
1546 __hal_send_char_write_event(resp_data, result);
1549 g_variant_unref(value);
1554 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1557 case HAL_GATT_WRITE_TYPE_WRITE:
1558 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1560 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1561 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1564 ERR("Unknow write type : %d", type);
1565 return BT_STATUS_FAIL;
1568 return BT_STATUS_SUCCESS;
1572 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1574 GDBusConnection *conn;
1575 GVariantBuilder *builder = NULL;
1581 GUnixFDList *fd_list = NULL;
1583 conn = _bt_hal_get_system_gconn();
1585 ERR("_bt_gdbus_get_system_gconn returned NULL");
1586 return BT_STATUS_FAIL;
1589 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1590 //val = g_variant_new("ay", builder1);
1592 g_variant_builder_add(builder, "{sv}", "offset",
1593 g_variant_new("q", offset));
1595 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1596 "AcquireWrite", g_variant_new("(a{sv})", builder),
1597 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1598 NULL, &fd_list, NULL, &err);
1600 g_dbus_error_strip_remote_error(err);
1601 ERR("Error: %s", err->message);
1603 g_variant_builder_unref(builder);
1604 return BT_STATUS_FAIL;
1607 g_variant_get(value, "(hq)", &idx, &att_mtu);
1608 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1610 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1613 g_object_unref(fd_list);
1614 g_variant_unref(value);
1615 g_variant_builder_unref(builder);
1617 return BT_STATUS_SUCCESS;
1620 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1622 GDBusConnection *conn;
1623 GVariantBuilder *builder = NULL;
1627 gint32 idx, notify_fd;
1629 GUnixFDList *fd_list = NULL;
1631 conn = _bt_hal_get_system_gconn();
1634 ERR("_bt_gdbus_get_system_gconn returned NULL");
1635 return BT_STATUS_FAIL;
1639 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
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 "AcquireNotify", 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 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1661 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1665 g_object_unref(fd_list);
1666 g_variant_unref(value);
1667 g_variant_builder_unref(builder);
1669 return BT_STATUS_SUCCESS;
1673 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1674 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1676 GVariant *val, *options;
1677 GVariantBuilder *builder1;
1678 GVariantBuilder *builder2;
1679 GDBusConnection *g_conn;
1682 hal_gatt_resp_data_t *resp_data;
1683 hal_gattc_service_t *gattc_service = NULL;
1684 hal_gattc_server_info_t * conn_info = NULL;
1685 hal_gattc_char_t *gattc_char = NULL;
1686 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1687 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1688 char* char_handle = NULL;
1689 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1690 int ret = BT_STATUS_SUCCESS;
1692 ret = __hal_get_write_prop(write_type, &write_prop);
1693 if (BT_STATUS_FAIL == ret) {
1694 DBG("received invalid write type:[%d] ", write_type);
1695 return BT_STATUS_FAIL;
1698 /* get the connection info */
1699 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1700 if (NULL == conn_info) {
1701 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1702 return BT_STATUS_FAIL;
1706 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1707 if (NULL == gattc_service) {
1708 ERR("Failed to get the gatt service");
1709 return BT_STATUS_FAIL;
1712 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1713 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1715 /* find characteristic */
1716 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1717 if (NULL == gattc_char) {
1718 ERR("Failed to get the gatt char");
1719 return BT_STATUS_FAIL;
1722 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1723 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1725 g_conn = _bt_hal_get_system_gconn();
1726 if (NULL == g_conn) {
1727 ERR("_bt_gdbus_get_system_gconn returned NULL");
1728 return BT_STATUS_FAIL;
1731 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1732 resp_data->conn_id = conn_id;
1733 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1734 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1736 char_handle = gattc_char->chr_path;
1738 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1740 for (i = 0; i < length; i++)
1741 g_variant_builder_add(builder1, "y", value[i]);
1743 val = g_variant_new("ay", builder1);
1745 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1747 g_variant_builder_add(builder2, "{sv}", "offset",
1748 g_variant_new_uint16(offset));
1750 options = g_variant_new("a{sv}", builder2);
1752 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1754 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1756 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1757 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1758 (gpointer)resp_data);
1760 g_variant_builder_unref(builder1);
1761 g_variant_builder_unref(builder2);
1763 return BT_STATUS_SUCCESS;
1766 bt_status_t btif_get_acquire_write_fd(int conn_id,
1767 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1768 int auth_req, int *fd, int*mtu)
1770 CHECK_BTGATT_INIT();
1772 hal_gattc_service_t *gattc_service = NULL;
1773 hal_gattc_server_info_t * conn_info = NULL;
1774 hal_gattc_char_t *gattc_char = NULL;
1775 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1777 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1778 int ret = BT_STATUS_SUCCESS;
1780 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1782 /* get the connection info */
1783 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1784 if (NULL == conn_info) {
1785 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1786 return BT_STATUS_FAIL;
1790 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1791 if (NULL == gattc_service) {
1792 ERR("Failed to get the gatt service");
1793 return BT_STATUS_FAIL;
1796 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1797 if (NULL == gattc_char) {
1798 ERR("Failed to get the gatt char");
1799 return BT_STATUS_FAIL;
1802 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1803 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1805 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1806 if (ret != BT_STATUS_SUCCESS)
1812 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1813 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1815 CHECK_BTGATT_INIT();
1817 hal_gattc_service_t *gattc_service = NULL;
1818 hal_gattc_server_info_t * conn_info = NULL;
1819 hal_gattc_char_t *gattc_char = NULL;
1820 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1822 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1823 int ret = BT_STATUS_SUCCESS;
1825 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1827 /* get the connection info */
1828 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1829 if (NULL == conn_info) {
1830 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1831 return BT_STATUS_FAIL;
1835 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1836 if (NULL == gattc_service) {
1837 ERR("Failed to get the gatt service");
1838 return BT_STATUS_FAIL;
1841 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1842 if (NULL == gattc_char) {
1843 ERR("Failed to get the gatt char");
1844 return BT_STATUS_FAIL;
1847 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1848 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1850 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1851 if (ret != BT_STATUS_SUCCESS)
1858 /** Write a remote characteristic */
1859 bt_status_t btif_write_characteristic(int conn_id,
1860 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1861 int write_type, int len, int auth_req,
1864 CHECK_BTGATT_INIT();
1866 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1867 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1868 len, auth_req, p_value);
1871 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1873 struct hal_ev_gatt_client_read_data ev;
1876 ERR("gatt client callback not registered");
1880 memset(&ev, 0, sizeof(ev));
1881 ev.conn_id = resp_data->conn_id;
1882 ev.inst_id = resp_data->srvc_id.id.inst_id;
1883 ev.is_primary = resp_data->srvc_id.is_primary;
1886 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1887 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1888 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1892 /* building the desc read value */
1893 memcpy(ev.value, value, len);
1896 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1898 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1901 static void __hal_internal_read_desc_cb(GObject *source_object,
1902 GAsyncResult *res, gpointer user_data)
1904 GError *error = NULL;
1905 GDBusConnection *system_gconn = NULL;
1908 GByteArray *gp_byte_array = NULL;
1910 hal_gatt_resp_data_t *resp_data = user_data;
1911 int result = BT_STATUS_SUCCESS;
1916 system_gconn = _bt_hal_get_system_gconn();
1917 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1920 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1923 result = BT_STATUS_FAIL;
1924 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1925 g_clear_error(&error);
1930 gp_byte_array = g_byte_array_new();
1931 g_variant_get(value, "(ay)", &iter);
1933 while (g_variant_iter_loop(iter, "y", &g_byte))
1934 g_byte_array_append(gp_byte_array, &g_byte, 1);
1938 for (i = 0; i < gp_byte_array->len; i++)
1939 DBG("%02x", gp_byte_array->data[i]);
1942 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1946 g_byte_array_free(gp_byte_array, TRUE);
1947 g_variant_iter_free(iter);
1948 g_variant_unref(value);
1953 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1954 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
1956 GDBusConnection *g_conn;
1957 hal_gatt_resp_data_t *resp_data;
1958 hal_gattc_service_t *gattc_service = NULL;
1959 GVariantBuilder *builder = NULL;
1961 hal_gattc_server_info_t * conn_info = NULL;
1962 hal_gattc_char_t *gattc_char = NULL;
1963 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1964 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1965 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
1966 char* desc_handle = NULL;
1969 hal_gattc_desc_t *gattc_desc = NULL;
1971 /* get the connection info */
1972 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1973 if (NULL == conn_info) {
1974 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1975 return BT_STATUS_FAIL;
1979 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1980 if (NULL == gattc_service) {
1981 ERR("Failed to get the gatt service");
1982 return BT_STATUS_FAIL;
1985 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1986 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1988 /* find characteristic */
1989 /* service can have two char with same uuid */
1990 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1991 gattc_char = (hal_gattc_char_t*)l->data;
1992 if (gattc_char == NULL)
1995 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1996 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1997 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1999 /* find descriptor */
2000 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2002 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2003 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2009 if (NULL == gattc_desc) {
2010 ERR("Failed to get the gatt desc");
2011 return BT_STATUS_FAIL;
2014 g_conn = _bt_hal_get_system_gconn();
2015 if (NULL == g_conn) {
2016 ERR("_bt_gdbus_get_system_gconn returned NULL");
2017 return BT_STATUS_FAIL;
2020 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2021 resp_data->conn_id = conn_id;
2022 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2023 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2024 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2026 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2029 g_variant_builder_add(builder, "{sv}", "offset",
2030 g_variant_new("q", offset));
2032 desc_handle = gattc_desc->desc_path;
2034 DBG("calling desc read value");
2036 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2037 "ReadValue", g_variant_new("(a{sv})", builder),
2038 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2039 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2040 (gpointer)resp_data);
2041 g_variant_builder_unref(builder);
2043 return BT_STATUS_SUCCESS;
2046 /** Read the descriptor for a given characteristic */
2047 bt_status_t btif_read_descriptor(int conn_id,
2048 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2049 btgatt_gatt_id_t *descr_id, int auth_req)
2051 CHECK_BTGATT_INIT();
2053 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2056 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2058 struct hal_ev_gatt_client_write_result ev;
2061 ERR("gatt client callback not registered");
2065 memset(&ev, 0, sizeof(ev));
2066 ev.conn_id = resp_data->conn_id;
2067 ev.inst_id = resp_data->srvc_id.id.inst_id;
2068 ev.is_primary = resp_data->srvc_id.is_primary;
2071 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2072 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2073 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2075 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2077 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2080 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2081 GAsyncResult *res, gpointer user_data)
2083 GError *error = NULL;
2084 GDBusConnection *system_gconn = NULL;
2086 hal_gatt_resp_data_t *resp_data = user_data;
2087 int result = BT_STATUS_SUCCESS;
2091 system_gconn = _bt_hal_get_system_gconn();
2092 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2095 ERR("write descriptor dbus failed Error: [%s]", error->message);
2098 result = BT_STATUS_FAIL;
2099 __hal_send_desc_write_event(resp_data, result);
2100 g_clear_error(&error);
2105 //send write value event
2106 __hal_send_desc_write_event(resp_data, result);
2109 g_variant_unref(value);
2114 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2115 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2116 int write_type, int length, int auth_req, char* value)
2118 GVariant *val, *options;
2119 GVariantBuilder *builder1;
2120 GVariantBuilder *builder2;
2121 GDBusConnection *g_conn;
2124 hal_gatt_resp_data_t *resp_data;
2125 hal_gattc_service_t *gattc_service = NULL;
2126 hal_gattc_server_info_t * conn_info = NULL;
2127 hal_gattc_char_t *gattc_char = NULL;
2128 hal_gattc_desc_t *gattc_desc = NULL;
2129 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2130 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2131 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2132 char* desc_handle = NULL;
2133 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2134 int ret = BT_STATUS_SUCCESS;
2139 ret = __hal_get_write_prop(write_type, &write_prop);
2140 if (BT_STATUS_FAIL == ret) {
2141 ERR("received invalid write type:[%d] ", write_type);
2142 return BT_STATUS_FAIL;
2145 /* get the connection info */
2146 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2147 if (NULL == conn_info) {
2148 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2149 return BT_STATUS_FAIL;
2153 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2154 if (NULL == gattc_service) {
2155 ERR("Failed to get the gatt service");
2156 return BT_STATUS_FAIL;
2159 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2160 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2162 /* find characteristic */
2163 /* service can have two char with same uuid */
2164 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2165 gattc_char = (hal_gattc_char_t*)l->data;
2166 if (gattc_char == NULL)
2169 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2170 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2171 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2173 /* find descriptor */
2174 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2176 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2177 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2183 if (NULL == gattc_desc) {
2184 ERR("Failed to get the gatt desc");
2185 return BT_STATUS_FAIL;
2188 g_conn = _bt_hal_get_system_gconn();
2189 if (NULL == g_conn) {
2190 ERR("_bt_gdbus_get_system_gconn returned NULL");
2191 return BT_STATUS_FAIL;
2194 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2195 resp_data->conn_id = conn_id;
2196 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2197 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2198 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2200 desc_handle = gattc_desc->desc_path;
2202 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2204 for (i = 0; i < length; i++)
2205 g_variant_builder_add(builder1, "y", value[i]);
2207 val = g_variant_new("ay", builder1);
2209 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2211 g_variant_builder_add(builder2, "{sv}", "offset",
2212 g_variant_new_uint16(offset));
2214 options = g_variant_new("a{sv}", builder2);
2216 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2218 g_variant_new("(@ay@a{sv})", val, options),
2220 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2221 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2222 (gpointer)resp_data);
2224 g_variant_builder_unref(builder1);
2225 g_variant_builder_unref(builder2);
2227 return BT_STATUS_SUCCESS;
2230 /** Write a remote descriptor for a given characteristic */
2231 bt_status_t btif_write_descriptor(int conn_id,
2232 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2233 btgatt_gatt_id_t *descr_id, int write_type, int len,
2234 int auth_req, char* p_value)
2236 CHECK_BTGATT_INIT();
2238 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2239 len, auth_req, p_value);
2242 /** Execute a prepared write operation */
2243 bt_status_t execute_write(int conn_id, int execute)
2245 CHECK_BTGATT_INIT();
2246 return BT_STATUS_UNSUPPORTED;
2249 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2251 struct hal_ev_gatt_client_watch_notification ev;
2252 hal_gatt_resp_data_t *resp_data = user_data;
2254 DBG("sending the watch register notification event");
2255 /* send the event */
2256 memset(&ev, 0, sizeof(ev));
2257 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2259 ev.status = resp_data->result;
2261 ev.is_primary = resp_data->srvc_id.is_primary;
2262 ev.inst_id = resp_data->srvc_id.id.inst_id;
2264 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2265 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2268 ERR("GATT Callback not registered");
2270 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2277 static bt_status_t _hal_register_for_notification(int client_if,
2278 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2279 btgatt_gatt_id_t *char_id)
2281 int result = BT_STATUS_SUCCESS;
2282 GError *error = NULL;
2283 GDBusConnection *g_conn;
2284 hal_gattc_client_info_t *gattc_client = NULL;
2285 hal_gattc_server_info_t * conn_info = NULL;
2286 hal_gattc_service_t *gattc_service = NULL;
2287 hal_gattc_char_t *gattc_char = NULL;
2288 char* char_handle = NULL;
2289 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2290 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2291 hal_gatt_resp_data_t *resp_data;
2295 gattc_client = __bt_find_gatt_client_info(bd_addr);
2296 if (gattc_client == NULL) {
2297 ERR("failed to get the gatt client info");
2298 return BT_STATUS_FAIL;
2301 if (gattc_client->client_if != client_if) {
2302 ERR("could not find the gatt client for client id[%d]", client_if);
2303 return BT_STATUS_FAIL;
2306 /* get the connection info */
2307 conn_info = __bt_find_gatt_conn_info(bd_addr);
2308 if (NULL == conn_info) {
2309 ERR("Failed to get the conn_info");
2310 return BT_STATUS_FAIL;
2313 if (conn_info->inst_id != gattc_client->inst_id) {
2314 ERR("could not fild the conn_info");
2315 return BT_STATUS_FAIL;
2319 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2320 if (NULL == gattc_service) {
2321 ERR("Failed to get the gatt service");
2322 return BT_STATUS_FAIL;
2325 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2326 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2329 /* find characteristic */
2330 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2331 if (NULL == gattc_char) {
2332 ERR("Failed to get the gatt char");
2333 return BT_STATUS_FAIL;
2336 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2337 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2339 char_handle = gattc_char->chr_path;
2341 g_conn = _bt_hal_get_system_gconn();
2342 if (g_conn == NULL) {
2344 return BT_STATUS_FAIL;
2347 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2349 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2351 g_dbus_connection_call_sync(g_conn,
2354 BT_HAL_GATT_CHAR_INTERFACE,
2358 G_DBUS_CALL_FLAGS_NONE,
2359 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2362 g_dbus_error_strip_remote_error(error);
2363 ERR("### StartNotify Failed: %s", error->message);
2364 if (g_strrstr(error->message, "Already notifying"))
2365 result = BT_STATUS_SUCCESS;
2366 else if (g_strrstr(error->message, "In Progress"))
2367 result = BT_STATUS_BUSY;
2368 else if (g_strrstr(error->message, "Operation is not supported"))
2369 result = BT_STATUS_UNSUPPORTED;
2370 /*failed because of either Insufficient Authorization or Write Not Permitted */
2371 else if (g_strrstr(error->message, "Write not permitted") ||
2372 g_strrstr(error->message, "Operation Not Authorized"))
2373 result = BT_STATUS_AUTH_FAILURE;
2374 /* failed because of either Insufficient Authentication,
2375 Insufficient Encryption Key Size, or Insufficient Encryption. */
2376 else if (g_strrstr(error->message, "Not paired"))
2377 result = BT_STATUS_NOT_READY;
2379 result = BT_STATUS_FAIL;
2381 g_clear_error(&error);
2384 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2385 resp_data->result = result;
2386 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2387 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2389 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2393 return BT_STATUS_SUCCESS;
2397 * Register to receive notifications or indications for a given
2400 bt_status_t btif_register_for_notification(int client_if,
2401 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2402 btgatt_gatt_id_t *char_id)
2404 CHECK_BTGATT_INIT();
2406 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2409 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2411 struct hal_ev_gatt_client_watch_notification ev;
2412 hal_gatt_resp_data_t *resp_data = user_data;
2414 DBG("sending the watch deregister notification event");
2415 /* send the event */
2416 memset(&ev, 0, sizeof(ev));
2417 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2419 ev.status = resp_data->result;
2421 ev.is_primary = resp_data->srvc_id.is_primary;
2422 ev.inst_id = resp_data->srvc_id.id.inst_id;
2424 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2425 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2428 ERR("GATT Callback not registered");
2430 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2437 static bt_status_t _hal_deregister_for_notification(int client_if,
2438 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2439 btgatt_gatt_id_t *char_id)
2441 int result = BT_STATUS_SUCCESS;
2442 GError *error = NULL;
2443 GDBusConnection *g_conn;
2444 hal_gattc_client_info_t *gattc_client = NULL;
2445 hal_gattc_server_info_t * conn_info = NULL;
2446 hal_gattc_service_t *gattc_service = NULL;
2447 hal_gattc_char_t *gattc_char = NULL;
2448 char* char_handle = NULL;
2449 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2450 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2451 hal_gatt_resp_data_t *resp_data;
2455 gattc_client = __bt_find_gatt_client_info(bd_addr);
2456 if (gattc_client == NULL) {
2457 ERR("failed to get the gatt client info");
2458 return BT_STATUS_FAIL;
2461 if (gattc_client->client_if != client_if) {
2462 ERR("could not find the gatt client for client id[%d]", client_if);
2463 return BT_STATUS_FAIL;
2466 /* get the connection info */
2467 conn_info = __bt_find_gatt_conn_info(bd_addr);
2468 if (NULL == conn_info) {
2469 ERR("Failed to get the conn_info");
2470 return BT_STATUS_FAIL;
2473 if (conn_info->inst_id != gattc_client->inst_id) {
2474 ERR("could not fild the conn_info");
2475 return BT_STATUS_FAIL;
2479 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2480 if (NULL == gattc_service) {
2481 ERR("Failed to get the gatt service");
2482 return BT_STATUS_FAIL;
2485 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2486 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2489 /* find characteristic */
2490 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2491 if (NULL == gattc_char) {
2492 ERR("Failed to get the gatt char");
2493 return BT_STATUS_FAIL;
2496 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2497 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2499 char_handle = gattc_char->chr_path;
2501 g_conn = _bt_hal_get_system_gconn();
2502 if (g_conn == NULL) {
2504 return BT_STATUS_FAIL;
2507 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2509 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2510 g_dbus_connection_call_sync(g_conn,
2513 BT_HAL_GATT_CHAR_INTERFACE,
2517 G_DBUS_CALL_FLAGS_NONE,
2518 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2521 ERR("### StopNotify Failed: %s", error->message);
2522 g_clear_error(&error);
2523 result = BT_STATUS_FAIL;
2526 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2527 resp_data->result = result;
2528 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2529 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2531 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2535 return BT_STATUS_SUCCESS;
2537 /** Deregister a previous request for notifications/indications */
2538 bt_status_t btif_deregister_for_notification(int client_if,
2539 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2540 btgatt_gatt_id_t *char_id)
2542 CHECK_BTGATT_INIT();
2543 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2546 /** Request RSSI for a given remote device */
2547 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2549 CHECK_BTGATT_INIT();
2550 return BT_STATUS_UNSUPPORTED;
2553 /** OTA firmware download */
2554 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2556 CHECK_BTGATT_INIT();
2557 return BT_STATUS_UNSUPPORTED;
2560 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2561 int get_device_type(const bt_bdaddr_t *bd_addr)
2563 CHECK_BTGATT_INIT();
2564 return BT_STATUS_UNSUPPORTED;
2567 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2568 int min_int, int max_int, int latency, int timeout)
2570 gchar *device_path = NULL;
2571 GError *error = NULL;
2572 GDBusProxy *device_proxy = NULL;
2573 GDBusConnection *conn;
2575 int ret = BT_STATUS_SUCCESS;
2576 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2578 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2579 min_int, max_int, latency, timeout);
2581 conn = _bt_hal_get_system_gconn();
2584 return BT_STATUS_FAIL;
2587 _bt_hal_convert_addr_type_to_string(device_address,
2588 (unsigned char *)bd_addr->address);
2589 device_path = _bt_hal_get_device_object_path(device_address);
2591 if (device_path == NULL) {
2592 ERR("device_path NULL : [%s]", device_address);
2593 return BT_STATUS_FAIL;
2596 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2597 NULL, BT_HAL_BLUEZ_NAME,
2598 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2600 g_free(device_path);
2601 if (NULL == device_proxy) {
2602 ERR("device_proxy returned NULL");
2603 return BT_STATUS_FAIL;
2606 INFO("Request LeConnUpdate");
2607 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2608 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2609 G_DBUS_CALL_FLAGS_NONE,
2614 g_object_unref(device_proxy);
2615 if (reply == NULL) {
2617 ERR("Error %s[%s]", error->message, device_address);
2618 if (g_strrstr(error->message, "In Progress"))
2619 ret = BT_STATUS_SUCCESS;
2621 ret = BT_STATUS_FAIL;
2622 g_error_free(error);
2626 g_variant_unref(reply);
2628 DBG("LE Connection parameter Updated");
2632 /** Request a connection parameter update */
2633 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2635 CHECK_BTGATT_INIT();
2637 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2640 /** Test mode interface */
2641 bt_status_t test_command(int command, btgatt_test_params_t* params)
2643 CHECK_BTGATT_INIT();
2644 return BT_STATUS_UNSUPPORTED;
2647 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2650 GError *g_error = NULL;
2651 GVariant *reply = NULL;
2652 int result = BT_STATUS_SUCCESS;
2653 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2654 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2656 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2657 g_object_unref(proxy);
2658 if (reply == NULL) {
2659 ERR("Connect LE Dbus Call Error");
2661 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2662 g_clear_error(&g_error);
2664 result = BT_STATUS_FAIL;
2666 g_variant_unref(reply);
2668 memset(&ev, 0, sizeof(ev));
2670 ev.mtu = conn_mtu->mtu;
2671 ev.conn_id = conn_mtu->conn_id;
2674 ERR("gatt client callback not registered");
2676 DBG("sending gatt client MTU exchange completed event");
2677 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2684 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2686 gchar *device_path = NULL;
2687 GDBusProxy *device_proxy = NULL;
2688 GDBusConnection *conn;
2689 hal_gattc_client_info_t *gattc_client = NULL;
2690 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2691 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2693 conn = _bt_hal_get_system_gconn();
2696 return BT_STATUS_FAIL;
2699 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2700 if (gattc_client == NULL) {
2701 INFO("GATT client conn info not found");
2702 return BT_STATUS_FAIL;
2705 _bt_hal_convert_addr_type_to_string(device_address,
2706 (unsigned char *)gattc_client->bd_addr.address);
2708 device_path = _bt_hal_get_device_object_path(device_address);
2709 if (device_path == NULL) {
2710 ERR("device_path NULL : [%s]", device_address);
2711 return BT_STATUS_FAIL;
2714 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2715 NULL, BT_HAL_BLUEZ_NAME,
2716 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2718 g_free(device_path);
2719 if (NULL == device_proxy) {
2720 ERR("device_proxy returned NULL");
2721 return BT_STATUS_FAIL;
2724 conn_mtu->conn_id = conn_id;
2725 conn_mtu->mtu = mtu;
2727 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2728 g_variant_new("(q)", mtu),
2729 G_DBUS_CALL_FLAGS_NONE,
2730 BT_HAL_MAX_DBUS_TIMEOUT,
2732 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2735 return BT_STATUS_SUCCESS;
2738 /** MTU Exchange request from client */
2739 static bt_status_t configure_mtu(int conn_id, int mtu)
2741 CHECK_BTGATT_INIT();
2743 return __hal_configure_mtu(conn_id, mtu);
2746 /** Setup scan filter params */
2747 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2748 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2749 int rssi_low_thres, int dely_mode, int found_timeout,
2750 int lost_timeout, int found_timeout_cnt)
2753 GError *error = NULL;
2754 GVariant *ret, *param;
2755 CHECK_BTGATT_INIT();
2757 proxy = _bt_hal_get_adapter_proxy();
2760 return BT_STATUS_FAIL;
2762 param = g_variant_new("(iiiiiiiiiiii)",
2775 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2776 param, G_DBUS_CALL_FLAGS_NONE,
2780 ERR("scan_filter_param_setup Fail: %s", error->message);
2781 g_clear_error(&error);
2782 return BT_STATUS_FAIL;
2786 g_variant_unref(ret);
2788 return BT_STATUS_SUCCESS;
2791 /** Configure a scan filter condition */
2792 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2793 int filt_index, int company_id,
2794 int company_id_mask, const bt_uuid_t *p_uuid,
2795 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2796 char addr_type, int data_len, char* p_data, int mask_len,
2800 GError *error = NULL;
2801 GVariant *ret, *param;
2802 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2803 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2804 GArray *arr_uuid = NULL;
2805 GArray *arr_uuid_mask = NULL;
2806 GArray *arr_data = NULL;
2807 GArray *arr_data_mask = NULL;
2808 CHECK_BTGATT_INIT();
2810 proxy = _bt_hal_get_adapter_proxy();
2813 return BT_STATUS_FAIL;
2815 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2817 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2819 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2821 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2823 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2824 NULL, 0, TRUE, NULL, NULL);
2825 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2826 NULL, 0, TRUE, NULL, NULL);
2827 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2828 NULL, 0, TRUE, NULL, NULL);
2829 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2830 NULL, 0, TRUE, NULL, NULL);
2832 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2833 client_if, // client_if
2834 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2835 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2836 filt_index, // filter_index
2837 company_id, // company_id
2838 company_id_mask, // company_id_mask
2839 arr_uuid_param, // p_uuid
2840 arr_uuid_mask_param, // p_uuid_mask
2842 addr_type, // address_type
2843 arr_data_param, // p_data
2844 arr_data_mask_param); // p_mask
2846 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2847 param, G_DBUS_CALL_FLAGS_NONE,
2851 ERR("scan_filter_add_remove Fail: %s", error->message);
2852 g_clear_error(&error);
2853 return BT_STATUS_FAIL;
2857 g_variant_unref(ret);
2859 return BT_STATUS_SUCCESS;
2862 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2864 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2865 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2866 NULL, 0, TRUE, NULL, NULL);
2867 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2868 NULL, 0, TRUE, NULL, NULL);
2869 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2870 NULL, 0, TRUE, NULL, NULL);
2871 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2872 NULL, 0, TRUE, NULL, NULL);
2874 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2875 client_if, // client_if
2876 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2877 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2878 filt_index, // filter_index
2879 company_id, // company_id
2880 company_id_mask, // company_id_mask
2881 arr_uuid_param, // p_uuid
2882 arr_uuid_mask_param, // p_uuid_mask
2884 addr_type, // address_type
2885 arr_data_param, // p_data
2886 arr_data_mask_param);
2888 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2889 param, G_DBUS_CALL_FLAGS_NONE,
2893 ERR("scan_filter_add_remove Fail: %s", error->message);
2894 g_clear_error(&error);
2895 return BT_STATUS_FAIL;
2899 g_variant_unref(ret);
2901 return BT_STATUS_SUCCESS;
2904 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2906 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2907 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2909 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2910 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2912 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2913 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2914 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2915 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2916 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2917 NULL, 0, TRUE, NULL, NULL);
2918 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2919 NULL, 0, TRUE, NULL, NULL);
2921 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2922 client_if, // client_if
2923 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2924 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
2925 filt_index, // filter_index
2926 company_id, // company_id
2927 company_id_mask, // company_id_mask
2928 arr_uuid_param, // p_uuid
2929 arr_uuid_mask_param, // p_uuid_mask
2931 addr_type, // address_type
2932 arr_data_param, // p_data
2933 arr_data_mask_param);
2935 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2936 param, G_DBUS_CALL_FLAGS_NONE,
2940 ERR("scan_filter_add_remove Fail: %s", error->message);
2941 g_clear_error(&error);
2942 return BT_STATUS_FAIL;
2946 g_variant_unref(ret);
2948 g_array_free(arr_uuid, TRUE);
2949 g_array_free(arr_uuid_mask, TRUE);
2951 return BT_STATUS_SUCCESS;
2954 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_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_SOLICITATION_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", param,
2986 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_DATA) {
3006 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3007 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3009 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3010 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3012 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3013 NULL, 0, TRUE, NULL, NULL);
3014 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3015 NULL, 0, TRUE, NULL, NULL);
3016 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3017 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3018 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3019 arr_data_mask->data, arr_data_mask->len, 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_DATA, // 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_data, TRUE);
3049 g_array_free(arr_data_mask, TRUE);
3051 return BT_STATUS_SUCCESS;
3054 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_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_MANUFACTURER_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 return BT_STATUS_UNSUPPORTED;
3107 /** Clear all scan filter conditions for specific filter index*/
3108 bt_status_t scan_filter_clear(int client_if, int filt_index)
3111 GError *error = NULL;
3113 CHECK_BTGATT_INIT();
3115 proxy = _bt_hal_get_adapter_proxy();
3117 return BT_STATUS_FAIL;
3119 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3120 g_variant_new("(ii)", client_if, filt_index),
3121 G_DBUS_CALL_FLAGS_NONE,
3125 ERR("scan_filter_clear Fail: %s", error->message);
3126 g_clear_error(&error);
3127 return BT_STATUS_FAIL;
3130 g_variant_unref(ret);
3131 return BT_STATUS_SUCCESS;
3134 /** Enable / disable scan filter feature*/
3135 bt_status_t scan_filter_enable(int client_if, bool enable)
3138 GError *error = NULL;
3140 CHECK_BTGATT_INIT();
3142 proxy = _bt_hal_get_adapter_proxy();
3144 return BT_STATUS_FAIL;
3146 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3147 g_variant_new("(ib)", client_if, enable),
3148 G_DBUS_CALL_FLAGS_NONE,
3152 ERR("scan_filter_enable Fail: %s", error->message);
3153 g_clear_error(&error);
3154 return BT_STATUS_FAIL;
3156 g_variant_unref(ret);
3158 return BT_STATUS_SUCCESS;
3161 /** Sets the LE scan interval and window in units of N*0.625 msec */
3163 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3167 CHECK_BTGATT_INIT();
3169 le_scan_type = scan_type;
3170 ret = _bt_hal_adapter_le_set_scan_parameters(
3171 scan_type, scan_interval, scan_window);
3175 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3177 CHECK_BTGATT_INIT();
3178 return BT_STATUS_UNSUPPORTED;
3182 /* Configure the batchscan storage */
3183 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3184 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3186 CHECK_BTGATT_INIT();
3187 return BT_STATUS_UNSUPPORTED;
3190 /* Enable batchscan */
3191 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3192 int scan_interval, int scan_window, int addr_type, int discard_rule)
3194 CHECK_BTGATT_INIT();
3195 return BT_STATUS_UNSUPPORTED;
3198 /* Disable batchscan */
3199 bt_status_t batchscan_dis_batch_scan(int client_if)
3201 CHECK_BTGATT_INIT();
3202 return BT_STATUS_UNSUPPORTED;
3205 /* Read out batchscan reports */
3206 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3208 CHECK_BTGATT_INIT();
3209 return BT_STATUS_UNSUPPORTED;
3212 const btgatt_client_interface_t btgatt_client_interface = {
3213 .register_client = btif_gattc_register_client,
3214 .unregister_client = btif_gattc_unregister_client,
3216 .connect = btif_gattc_client_connect,
3217 .disconnect = btif_gattc_client_disconnect,
3219 .search_service = btif_gattc_client_search_service,
3220 .get_included_service = get_included_service,
3221 .get_characteristic = btif_gattc_get_characteristic,
3222 .get_descriptor = btif_gattc_get_descriptor,
3223 .read_characteristic = btif_read_characteristic,
3224 .write_characteristic = btif_write_characteristic,
3225 .acquire_write = btif_get_acquire_write_fd,
3226 .acquire_notify = btif_get_acquire_notify_fd,
3227 .read_descriptor = btif_read_descriptor,
3228 .write_descriptor = btif_write_descriptor,
3229 .execute_write = execute_write,
3230 .register_for_notification = btif_register_for_notification,
3231 .deregister_for_notification = btif_deregister_for_notification,
3232 .read_remote_rssi = read_remote_rssi,
3233 .ota_fw_update = ota_fw_update,
3234 .get_device_type = get_device_type,
3235 .conn_parameter_update = btif_gattc_conn_parameter_update,
3236 .test_command = test_command,
3237 .configure_mtu = configure_mtu,
3238 .scan_filter_param_setup = scan_filter_param_setup,
3239 .scan_filter_add_remove = scan_filter_add_remove,
3240 .scan_filter_clear = scan_filter_clear,
3241 .scan_filter_enable = scan_filter_enable,
3242 .set_scan_parameters = set_scan_parameters,
3243 .batchscan_cfg_storage = batchscan_cfg_storage,
3244 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3245 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3246 .batchscan_read_reports = batchscan_read_reports,
3247 .add_connection_info = btif_gattc_add_connection_info,
3250 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3253 hal_gattc_server_info_t *info = NULL;
3255 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3256 info = (hal_gattc_server_info_t*)l->data;
3260 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3267 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3270 hal_gattc_client_info_t *info = NULL;
3272 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3273 info = (hal_gattc_client_info_t*)l->data;
3277 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3284 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3287 hal_gattc_client_info_t *info = NULL;
3289 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3290 info = (hal_gattc_client_info_t*)l->data;
3294 if (info->conn_id == conn_id)
3301 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3304 hal_gattc_server_info_t *info = NULL;
3305 hal_gattc_client_info_t *gattc_client = NULL;
3307 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3308 if (gattc_client == NULL) {
3309 ERR("GATT client conn info not found");
3313 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3314 info = (hal_gattc_server_info_t*)l->data;
3318 if ((info->inst_id == gattc_client->inst_id) &&
3319 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3326 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3327 gboolean auto_connect)
3329 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3330 gchar *device_path = NULL;
3331 GDBusProxy *device_proxy = NULL;
3332 GDBusConnection *conn;
3333 int ret = BT_STATUS_SUCCESS;
3334 hal_gattc_client_info_t *gattc_data;
3338 if (NULL == bd_addr) {
3339 ERR("bd_addr is NULL");
3340 return BT_STATUS_PARM_INVALID;
3343 conn = _bt_hal_get_system_gconn();
3345 ERR("_bt_gdbus_get_system_gconn returned NULL");
3346 return BT_STATUS_FAIL;
3349 _bt_hal_convert_addr_type_to_string(device_address,
3350 (unsigned char *)bd_addr->address);
3351 device_path = _bt_hal_get_device_object_path(device_address);
3352 if (device_path == NULL) {
3353 ERR("device_path NULL : [%s]", device_address);
3354 ret = BT_STATUS_FAIL;
3357 ERR("device_path:%s", device_path);
3359 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3360 NULL, BT_HAL_BLUEZ_NAME,
3361 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3362 g_free(device_path);
3363 if (NULL == device_proxy) {
3364 ERR("device_proxy returned NULL");
3365 return BT_STATUS_FAIL;
3368 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3369 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3370 BT_HAL_ADDRESS_LENGTH_MAX);
3372 DBG("Connect LE [%s]", device_address);
3374 gattc_data->client_if = client_if;
3376 g_dbus_proxy_call(device_proxy, "ConnectLE",
3377 g_variant_new("(b)", auto_connect),
3378 G_DBUS_CALL_FLAGS_NONE,
3379 BT_HAL_MAX_DBUS_TIMEOUT,
3381 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3386 static bt_status_t _bt_hold_current_advertising()
3388 int ret = BT_STATUS_FAIL;
3389 gboolean is_advertising = FALSE;
3392 is_advertising = _bt_hal_is_advertising_in_slot(0);
3393 if (is_advertising) {
3394 DBG("+ Stop current advertising");
3396 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3397 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3403 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3405 DBG("+ start current advertising");
3407 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3412 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3414 DBG("Try to initiate pending LE connection");
3416 pending_le_conn_timer_id = 0;
3418 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3419 &pending_le_conn_info->bd_addr,
3420 pending_le_conn_info->auto_connect);
3422 g_free(pending_le_conn_info);
3423 pending_le_conn_info = NULL;
3428 static int __hal_generate_conn_id()
3430 return ++bt_conn_id;
3433 static int __hal_generate_server_instance_id()
3435 return ++bt_inst_id;
3438 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3441 GError *g_error = NULL;
3442 GVariant *reply = NULL;
3443 hal_gattc_client_info_t *gattc_data = user_data;
3444 int result = BT_STATUS_SUCCESS;
3445 struct hal_ev_gatt_client_connected ev;
3446 hal_gattc_server_info_t *gatt_conn_info = NULL;
3450 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3451 g_object_unref(proxy);
3452 if (reply == NULL) {
3453 ERR("Connect LE Dbus Call Error");
3455 ERR("Error: %s\n", g_error->message);
3456 g_clear_error(&g_error);
3458 result = BT_STATUS_FAIL;
3460 g_variant_unref(reply);
3462 if (NULL == gattc_data) {
3463 ERR("server_data is NULL");
3468 if (result == BT_STATUS_FAIL) {
3469 memset(&ev, 0, sizeof(ev));
3472 ev.client_if = gattc_data->client_if;
3473 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3474 BT_HAL_ADDRESS_LENGTH_MAX);
3477 ERR("gatt client callback not registered");
3479 DBG("sending gatt client connected event");
3480 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3486 DBG("adding the server conn info in list");
3487 gattc_data->conn_id = __hal_generate_conn_id() ;
3488 gattc_data->inst_id = __hal_generate_server_instance_id();
3490 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3492 /*add gatt server connection info*/
3493 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3494 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3495 gatt_conn_info->conn_id = gattc_data->conn_id;
3496 gatt_conn_info->inst_id = gattc_data->inst_id;
3497 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3503 /*remove conn_info*/
3508 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3510 g_free(desc_info->desc_path);
3514 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3517 hal_gattc_desc_t *desc_info = NULL;
3518 for (l = char_info->gatt_list_descs; l != NULL; ) {
3519 desc_info = l->data;
3520 l = g_slist_next(l);
3521 if (desc_info == NULL)
3523 /* Remove descriptor element */
3524 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3525 __hal_gattc_free_desc_info(desc_info);
3527 g_slist_free(char_info->gatt_list_descs);
3528 g_free(char_info->chr_path);
3532 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3535 hal_gattc_char_t *char_info = NULL;
3536 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3537 char_info = l->data;
3538 l = g_slist_next(l);
3539 if (char_info == NULL)
3541 /* Remove characteristic element */
3542 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3543 __hal_gattc_free_char_info(char_info);
3545 g_slist_free(svc_info->gatt_list_chars);
3546 g_free(svc_info->svc_path);
3550 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3553 hal_gattc_service_t *svc_info = NULL;
3557 for (l = conn_info->gatt_list_services; l != NULL; ) {
3558 svc_info = (hal_gattc_service_t *)l->data;
3559 l = g_slist_next(l);
3560 if (svc_info == NULL)
3562 /* Remove service element */
3563 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3564 __hal_gattc_free_svc_info(svc_info);
3566 g_slist_free(conn_info->gatt_list_services);
3570 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3572 bt_bdaddr_t bd_addr;
3573 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3574 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3580 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3582 int result = BT_STATUS_SUCCESS;
3583 struct hal_ev_gatt_client_connected ev;
3584 hal_gattc_server_info_t *conn_info = NULL;
3585 bt_bdaddr_t bd_addr;
3587 hal_gattc_client_info_t *gattc_client = NULL;
3591 DBG("+ connected device address [%s]", address);
3593 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3594 HAL_EV_GATT_CLIENT_DISCONNECTED;
3596 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3597 /* find the gatt client info */
3598 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3599 if (NULL == gattc_client) {
3600 ERR("Fail to get gatt client info");
3605 memset(&ev, 0, sizeof(ev));
3606 ev.conn_id = gattc_client->conn_id;
3608 ev.client_if = gattc_client->client_if;
3609 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3610 BT_HAL_ADDRESS_LENGTH_MAX);
3613 ERR("gatt client callback not registered");
3615 DBG("sending gatt client connected status event");
3616 event_cb(event, (void *)&ev, sizeof(ev));
3619 if (!gatt_connected) {
3620 inst_id = gattc_client->inst_id;
3622 /* remove the gatt client info from the client list also*/
3623 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3624 g_free(gattc_client);
3626 //find the connected server info
3627 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3628 if (NULL == conn_info) {
3629 ERR("Fail to get gatt server info");
3633 if (inst_id != conn_info->inst_id) {
3634 ERR("server instance is different");
3638 //remove gatt conn info from the server list
3639 DBG("remove the server conn_info from list after gatt disconnection");
3640 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3641 __hal_clean_gattc_server_info(conn_info);
3647 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3648 const char* uuid_str, int inst_id)
3650 struct hal_ev_gatt_client_search_result ev;
3653 ERR("gatt client callback not registered");
3657 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3659 memset(&ev, 0, sizeof(ev));
3660 ev.conn_id = conn_id;
3661 ev.inst_id = inst_id;
3662 ev.is_primary = is_primary;
3663 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3665 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3668 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3670 struct hal_ev_gatt_client_search_complete ev;
3673 ERR("gatt client callback not registered");
3677 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3680 memset(&ev, 0, sizeof(ev));
3681 ev.conn_id = conn_id;
3684 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3687 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3688 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3689 char *char_value, int len)
3691 struct hal_ev_gatt_client_notify_changed_value ev;
3692 hal_gattc_client_info_t *gattc_client = NULL;
3695 ERR("gatt client callback not registered");
3699 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3700 if (NULL == gattc_client) {
3701 ERR("failed to get the gatt client info");
3706 DBG("sending gatt client connected status event");
3707 memset(&ev, 0, sizeof(ev));
3709 ev.conn_id = gattc_client->conn_id;
3710 ev.inst_id = conn_info->inst_id;
3711 ev.is_primary = svc_info->is_primary;
3712 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3713 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3715 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3717 if (len > 0 && (char_value != NULL)) {
3718 memcpy(ev.value, char_value, len);
3722 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3725 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3726 char *char_value, int len)
3728 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3729 hal_gattc_server_info_t *conn_info = NULL;
3730 bt_bdaddr_t bd_addr;
3733 hal_gattc_service_t *svc_info = NULL;
3734 hal_gattc_char_t *char_info = NULL;
3738 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3739 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3740 DBG("device address:[%s]", device_address);
3741 DBG("char handle:[%s]", char_handle);
3743 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3744 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3746 if (conn_info != NULL) {
3747 //find service for notified char path
3748 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3749 svc_info = (hal_gattc_service_t*)l->data;
3750 if (svc_info == NULL)
3753 /* find characteristic object path */
3754 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3755 char_info = (hal_gattc_char_t *)k->data;
3756 if (char_info == NULL)
3759 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3760 DBG("Found char handle[%s]", char_info->chr_path);
3763 _bt_hal_send_value_changed_event(conn_info, svc_info,
3764 char_info, char_value, len);
3772 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3774 GDBusConnection *g_conn = NULL;
3775 GDBusProxy *properties_proxy = NULL;
3776 GVariant *result = NULL;
3777 GError *error = NULL;
3778 GVariantIter *property_iter = NULL;
3779 const gchar *key = NULL;
3780 GVariant *value = NULL;
3781 const char *uuid_str = NULL;
3783 gboolean is_primary = FALSE;
3784 GVariantIter *char_iter = NULL;
3785 const char *char_handle = NULL;
3786 GPtrArray *gp_char_array = NULL;
3788 if (service_path == NULL) {
3789 ERR("service_path is NULL");
3790 return BT_STATUS_FAIL;
3793 DBG("service_path: %s", service_path);
3795 g_conn = _bt_hal_get_system_gconn();
3796 if (g_conn == NULL) {
3797 ERR("g_conn is NULL");
3798 return BT_STATUS_FAIL;
3801 properties_proxy = g_dbus_proxy_new_sync(g_conn,
3802 G_DBUS_PROXY_FLAGS_NONE, NULL,
3805 BT_HAL_PROPERTIES_INTERFACE,
3807 if (properties_proxy == NULL) {
3808 ERR("properties_proxy is NULL");
3809 return BT_STATUS_FAIL;
3812 result = g_dbus_proxy_call_sync(properties_proxy,
3814 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
3815 G_DBUS_CALL_FLAGS_NONE,
3817 if (result == NULL) {
3818 if (error != NULL) {
3819 ERR("Fail to get properties (Error: %s)", error->message);
3820 g_clear_error(&error);
3822 ERR("Fail to get properties");
3824 g_object_unref(properties_proxy);
3825 return BT_STATUS_FAIL;
3828 g_variant_get(result, "(a{sv})", &property_iter);
3830 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
3831 if (g_strcmp0(key, "UUID") == 0) {
3832 uuid_str = g_variant_get_string(value, &len);
3833 DBG("UUID: %s", uuid_str);
3834 } else if (g_strcmp0(key, "Primary") == 0) {
3835 is_primary = g_variant_get_boolean(value);
3836 DBG("is_primary: %s", is_primary ? "TRUE" : "FALSE");
3837 } else if (g_strcmp0(key, "Characteristics") == 0) {
3838 g_variant_get(value, "ao", &char_iter);
3839 if (char_iter != NULL) {
3840 gp_char_array = g_ptr_array_new();
3841 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
3842 DBG("char_handle: %s", char_handle);
3843 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
3849 if (uuid_str == NULL || gp_char_array == NULL) {
3850 ERR("uuid_str and gp_char_array should be set");
3854 /* Create new service */
3855 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
3858 g_variant_iter_free(property_iter);
3859 g_variant_unref(result);
3860 g_object_unref(properties_proxy);
3862 return BT_STATUS_SUCCESS;
3865 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
3867 GDBusConnection *conn = NULL;
3868 GDBusProxy *proxy = NULL;
3870 GVariant *ret = NULL;
3871 GVariant *value = NULL;
3873 conn = _bt_hal_get_system_gconn();
3875 ERR("_bt_gdbus_get_system_gconn returned NULL");
3879 proxy = g_dbus_proxy_new_sync(conn,
3880 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
3881 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
3882 if (proxy == NULL) {
3883 ERR("device_proxy returned NULL");
3887 ret = g_dbus_proxy_call_sync(proxy, "Get",
3888 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
3889 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3891 ERR("DBus Error : %s", err->message);
3892 g_clear_error(&err);
3894 g_variant_get(ret, "(v)", &value);
3895 *service_uuid = g_variant_dup_string(value, NULL);
3896 g_variant_unref(value);
3897 g_variant_unref(ret);
3901 g_object_unref(proxy);
3906 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
3908 struct hal_ev_gatt_client_service_changed ev = {0, };
3909 char address[BT_HAL_ADDRESS_STRING_SIZE];
3910 hal_gattc_server_info_t *server_info = NULL;
3911 hal_gattc_service_t *service = NULL;
3912 GSList *list = NULL;
3913 char *uuid_str = NULL;
3915 _bt_hal_convert_device_path_to_address(path, address);
3916 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
3917 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
3918 if (server_info == NULL) {
3919 ERR("service_info is NULL");
3924 /* Get service UUID from path */
3925 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
3927 DBG("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
3928 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3931 ERR("uuid_str is NULL");
3935 /* Create new service and append into the list */
3936 __hal_gattc_get_service_info(server_info, path);
3938 /* Find service UUID from path */
3939 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
3940 service = (hal_gattc_service_t *)list->data;
3941 if (service == NULL)
3944 if (g_strcmp0(service->svc_path, path) == 0) {
3945 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
3946 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
3947 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
3948 DBG("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
3950 /* Remove service info in list */
3951 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
3952 __hal_gattc_free_svc_info(service);
3960 ERR("uuid_str is NULL");
3965 /* Send GATT Client service changed event */
3966 ev.change_type = is_added;
3967 ev.conn_id = server_info->conn_id;
3968 ev.inst_id = server_info->inst_id;
3969 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));