4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include <hardware/bluetooth.h>
23 #include <hardware/bt_gatt.h>
31 #include <gio/gunixfdlist.h>
34 #include "bt-hal-log.h"
35 #include "bt-hal-msg.h"
36 #include "bt-hal-event-receiver.h"
37 #include "bt-hal-adapter-le.h"
39 #include "bt-hal-gatt-client.h"
40 #include "bt-hal-dbus-common-utils.h"
41 #include "bt-hal-utils.h"
43 /************************************************************************************
45 ************************************************************************************/
46 extern const btgatt_callbacks_t *bt_gatt_callbacks;
47 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
49 ERR("%s: BTGATT not initialized", __FUNCTION__);\
50 return BT_STATUS_NOT_READY;\
52 DBG("%s", __FUNCTION__);\
56 int le_scan_type = BT_GATTC_LE_SCAN_TYPE_PASSIVE;
59 static handle_stack_msg event_cb = NULL;
61 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
62 #define MAX_HAL_OBJECT_PATH_LEN 100
65 HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST = 0x01,
66 HAL_GATT_CHARACTERISTIC_PROPERTY_READ = 0x02,
67 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE = 0x04,
68 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE = 0x08,
69 HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY = 0x10,
70 HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE = 0x20,
71 HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE = 0x40,
72 HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE = 0x80,
73 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES = 0x100,
74 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ = 0x200,
75 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE = 0x400,
76 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ = 0x800,
77 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE = 0x1000,
78 HAL_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS = 0xffff,
79 } bt_gatt_characteristic_property_t;
83 HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE = 1,
84 HAL_GATT_WRITE_TYPE_WRITE ,
85 } hal_gatt_write_type_t;
89 HAL_GATT_PROPERTY_BROADCAST = 0x01, /**< Broadcast property */
90 HAL_GATT_PROPERTY_READ = 0x02, /**< Read property */
91 HAL_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE = 0x04, /**< Write without response property */
92 HAL_GATT_PROPERTY_WRITE = 0x08, /**< Write property */
93 HAL_GATT_PROPERTY_NOTIFY = 0x10, /**< Notify property */
94 HAL_GATT_PROPERTY_INDICATE = 0x20, /**< Indicate property */
95 HAL_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES = 0x40, /**< Authenticated signed writes property */
96 HAL_GATT_PROPERTY_EXTENDED_PROPERTIES = 0x80, /**< Extended properties */
97 } hal_gatt_property_e;
102 gboolean auto_connect;
103 } bt_pending_le_conn_info_s;
113 unsigned int permission;
114 GSList *gatt_list_descs;
121 GSList *gatt_list_chars;
122 } hal_gattc_service_t;
125 bt_bdaddr_t bd_addr; /*remote server address*/
126 int inst_id; /*server instance id*/
127 GSList *gatt_list_services;
128 } hal_gattc_server_info_t;
130 /* Linked List of connected GATT server */
131 static GSList *hal_gattc_server_info_list = NULL;
135 bt_bdaddr_t bd_addr; /*remote server address*/
138 } hal_gattc_client_info_t;
140 /* Linked list of connected GATT client connection */
141 static GSList * hal_gattc_client_info_list = NULL;
143 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
144 static guint pending_le_conn_timer_id = 0;
145 static int bt_conn_id = 0;
146 static int bt_inst_id = 0;
148 #define BT_GATTC_CL_MAX 32
153 btgatt_srvc_id_t srvc_id;
154 btgatt_gatt_id_t char_id;
155 btgatt_gatt_id_t desc_id;
156 } hal_gatt_resp_data_t;
161 } hal_gatt_client_app;
163 static GSList * hal_gattc_client_app_list = NULL;
165 static int bt_client_if = 0;
168 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
169 gboolean auto_connect);
170 static bt_status_t _bt_hold_current_advertising();
171 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
172 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
173 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
175 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
176 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
177 const char* uuid_str, int inst_id);
178 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
179 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr);
180 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
183 /* To send stack event to hal-av handler */
184 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
189 void _bt_hal_unregister_gatt_client_handler_cb(void)
195 int _bt_hal_gatt_client_get_le_scan_type(void)
201 static gboolean __bt_hal_register_client_cb(gpointer user_data)
203 struct hal_ev_gatt_client_registered ev;
204 hal_gatt_client_app *client_info = user_data;
207 /* Prepare to send AV connecting event */
208 memset(&ev, 0, sizeof(ev));
209 ev.status = BT_STATUS_SUCCESS;
210 ev.client_if = client_info->client_if;
211 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
214 ERR("GATT Callback not registered");
216 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
217 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
224 static int __hal_generate_client_id()
226 return ++bt_client_if;
229 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
232 hal_gatt_client_app *info = NULL;
233 hal_gatt_client_app *gattc_app = NULL;
235 //check if client app is already registered
236 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
237 info = (hal_gatt_client_app*)l->data;
241 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
242 DBG("gatt client app already registered");
247 DBG("adding the gatt client app");
250 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
251 if (gattc_app == NULL) {
252 DBG("Failed to allocate memory");
256 gattc_app->client_if = __hal_generate_client_id();
257 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
259 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
264 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
266 hal_gatt_client_app *gattc_app = NULL;
267 hal_gatt_client_app *client_app_info = NULL;
270 /* add gatt client in list */
271 gattc_app = __hal_gattc_add_client_app(app_uuid);
272 if (gattc_app == NULL) {
273 ERR("Failed to register gatt client app");
274 return BT_STATUS_FAIL;
278 client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
279 if (NULL == client_app_info) {
280 ERR("Failed to allocate memory");
281 return BT_STATUS_FAIL;
284 client_app_info->client_if = gattc_app->client_if;
285 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
286 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
288 DBG("registered client client_if [%d]", client_app_info->client_if);
290 return BT_STATUS_SUCCESS;
293 /** Registers a GATT client application with the stack */
294 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
299 return __hal_gattc_register_client_app(uuid);
302 bt_status_t __hal_gattc_unregister_client(int client_if)
305 hal_gatt_client_app *info = NULL;
307 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
309 /* remove the gatt client app */
310 for (l = hal_gattc_client_app_list; l != NULL; ) {
311 info = (hal_gatt_client_app*)l->data;
317 if (info->client_if == client_if) {
318 DBG("gatt client app found");
319 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
324 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
325 return BT_STATUS_SUCCESS;
328 /** Unregister a client application from the stack */
329 bt_status_t btif_gattc_unregister_client(int client_if)
334 return __hal_gattc_unregister_client(client_if);
337 /** Start or stop LE device scanning */
338 bt_status_t scan(int client_if, bool start)
345 ret = _bt_hal_adapter_le_start_scan();
347 ret = _bt_hal_adapter_le_stop_scan();
352 /** Create a connection to a remote LE or dual-mode device */
353 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
356 int ret = BT_STATUS_SUCCESS;
362 return BT_STATUS_PARM_INVALID;
364 ret = _bt_hold_current_advertising();
365 if (ret == BT_STATUS_SUCCESS) {
366 DBG("Current advertising is held");
367 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
368 pending_le_conn_info->client_if = client_if;
369 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
370 BT_HAL_ADDRESS_LENGTH_MAX);
371 pending_le_conn_info->auto_connect = is_direct;
373 pending_le_conn_timer_id =
374 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
376 return BT_STATUS_SUCCESS;
378 ERR("advertising is not stopped");
381 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
385 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
388 GError *g_error = NULL;
389 GVariant *reply = NULL;
390 hal_gattc_client_info_t *gatt_conn_info = user_data;
391 int result = BT_STATUS_SUCCESS;
392 struct hal_ev_gatt_client_connected ev;
396 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
397 g_object_unref(proxy);
399 ERR("Connect LE Dbus Call Error");
401 ERR("Error: %s\n", g_error->message);
402 g_clear_error(&g_error);
404 result = BT_STATUS_FAIL;
406 g_variant_unref(reply);
408 if (NULL == gatt_conn_info) {
409 ERR("server_data is NULL");
414 if (result == BT_STATUS_FAIL) {
415 memset(&ev, 0, sizeof(ev));
416 ev.conn_id = gatt_conn_info->conn_id;
418 ev.client_if = gatt_conn_info->client_if;
419 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
420 BT_HAL_ADDRESS_LENGTH_MAX);
423 ERR("gatt client callback not registered");
425 DBG("sending gatt client disconnected event");
426 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
432 g_free(gatt_conn_info);
437 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
440 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
442 GDBusProxy *device_proxy;
443 GDBusConnection *conn;
444 int ret = BT_STATUS_SUCCESS;
445 hal_gattc_client_info_t *gattc_data;
447 if (NULL == bd_addr) {
448 ERR("bd_addr is NULL");
449 return BT_STATUS_PARM_INVALID;
452 conn = _bt_hal_get_system_gconn();
454 ERR("_bt_gdbus_get_system_gconn returned NULL");
455 return BT_STATUS_FAIL;
458 _bt_hal_convert_addr_type_to_string(device_address,
459 (unsigned char *)bd_addr->address);
460 device_path = _bt_hal_get_device_object_path(device_address);
461 if (device_path == NULL) {
462 DBG("device_path NULL");
463 ret = BT_STATUS_FAIL;
467 ERR("device_path:%s", device_path);
469 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
470 NULL, BT_HAL_BLUEZ_NAME,
471 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
473 if (NULL == device_proxy) {
474 ERR("device_proxy returned NULL");
475 return BT_STATUS_FAIL;
478 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
479 if (NULL == gattc_data) {
480 ERR("Unable to allocate memory");
481 ret = BT_STATUS_FAIL;
485 memcpy(gattc_data->bd_addr.address, bd_addr->address,
486 BT_HAL_ADDRESS_LENGTH_MAX);
487 gattc_data->client_if = client_if;
488 gattc_data->conn_id = conn_id;
490 DBG("DisconnectLE [%s]", device_address);
492 g_dbus_proxy_call(device_proxy, "DisconnectLE",
494 G_DBUS_CALL_FLAGS_NONE,
495 BT_HAL_MAX_DBUS_TIMEOUT,
497 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
501 g_object_unref(device_proxy);
508 /** Disconnect a remote device or cancel a pending connection */
509 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
516 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
519 /** Clear the attribute cache for a given device */
520 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
523 return BT_STATUS_UNSUPPORTED;
526 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
531 hal_gattc_service_t *info = NULL;
533 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
534 info = (hal_gattc_service_t*)l->data;
538 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t))) {
539 INFO("Found GATT service uuid");
547 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
548 bt_gatt_characteristic_property_t prop)
553 hal_gattc_char_t *info = NULL;
555 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
556 info = (hal_gattc_char_t*)l->data;
560 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
561 (info->permission & prop)) {
562 INFO("Found GATT char uuid");
569 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
574 hal_gattc_char_t *info = NULL;
576 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
577 info = (hal_gattc_char_t*)l->data;
581 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
582 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
583 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
584 INFO("Found GATT char uuid");
591 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
596 hal_gattc_desc_t *info = NULL;
598 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
599 info = (hal_gattc_desc_t*)l->data;
603 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t))) {
604 INFO("Found GATT descriptor uuid");
612 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
613 const char *uuid_str, char *object_path, int is_primary)
616 hal_gattc_service_t *gattc_service = NULL;
618 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
619 gattc_service->svc_path = g_strdup(object_path);
620 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
621 gattc_service->is_primary = is_primary;
623 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
625 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
627 DBG("svc path {%s] svc uuid [%s]", object_path, uuid_str);
629 return gattc_service;
632 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
635 hal_gattc_char_t *gattc_char = NULL;
637 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
638 gattc_char->chr_path = g_strdup(char_handle);
640 DBG("svc path: [%s]", gatt_svc->svc_path);
641 DBG("char path: [%s]", gattc_char->chr_path);
643 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
646 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
647 const char* uuid_str, char *object_path, GPtrArray *gp_char_array)
649 hal_gattc_service_t* gatt_svc = NULL;
651 gchar *gp_char_path = NULL;
655 /* add the service */
656 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
657 if (gatt_svc == NULL) {
658 ERR("Failed to add service");
662 /* add the characteristic */
663 for (i = 0; i < gp_char_array->len; i++) {
664 gp_char_path = g_ptr_array_index(gp_char_array, i);
665 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
668 g_ptr_array_free(gp_char_array, TRUE);
671 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
673 hal_gattc_desc_t *gattc_desc = NULL;
675 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
676 gattc_desc->desc_path = g_strdup(desc_path);
678 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
680 DBG("char path: [%s]", gattc_char->chr_path);
681 DBG("desc path: [%s]", gattc_desc->desc_path);
684 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
685 GPtrArray *gp_desc_array, unsigned int char_permission)
687 gchar *gp_desc_path = NULL;
692 if (char_uuid_str == NULL) {
693 DBG("char_uuid_str is NULL");
697 //update the char uuid
698 DBG("char UUID: [%s] ", char_uuid_str);
699 DBG("char path: [%s]", gattc_char->chr_path);
701 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
703 //update char permission
704 gattc_char->permission = char_permission;
707 for (i = 0; i < gp_desc_array->len; i++) {
708 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
709 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
713 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
717 if (desc_uuid_str == NULL) {
718 DBG("char_uuid_str is NULL");
722 //update the descriptor uuid
723 DBG("desc UUID: [%s] ", desc_uuid_str);
724 DBG("desc path: [%s]", gattc_desc->desc_path);
726 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
729 static void browse_service_char(int conn_id)
731 hal_gattc_server_info_t *conn_info = NULL;
735 hal_gattc_service_t *svc_info = NULL;
736 hal_gattc_char_t *char_info = NULL;
737 hal_gattc_desc_t *desc_info = NULL;
741 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
742 if (conn_info == NULL) {
743 DBG("conn_info is NULL");
747 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
749 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
750 svc_info = (hal_gattc_service_t*)l->data;
751 if (svc_info == NULL)
754 DBG("svc path [%s]", svc_info->svc_path);
756 /* find characteristic object path */
757 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
758 char_info = (hal_gattc_char_t *)k->data;
759 if (char_info == NULL)
762 DBG("char path[%s]", char_info->chr_path);
765 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
766 desc_info = (hal_gattc_desc_t *)m->data;
767 if (desc_info == NULL)
770 DBG("desc path[%s]", desc_info->desc_path);
779 * Enumerate all GATT services on a connected device.
780 * Optionally, the results can be filtered for a given UUID.
782 static bt_status_t _gattc_client_search_service(int conn_id)
786 GVariant *result = NULL;
788 GVariantIter *svc_iter;
789 GVariantIter *interface_iter;
790 char *object_path = NULL;
791 char *interface_str = NULL;
792 const gchar *key = NULL;
793 GVariant *value = NULL;
794 GPtrArray *gp_array = NULL;
795 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
796 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
797 int ret = BT_STATUS_FAIL;
799 const gchar *uuid_str = NULL;
801 hal_gattc_server_info_t *conn_info = NULL;
802 gboolean is_primary = FALSE;
805 char *char_handle = NULL;
806 GVariantIter *char_iter = NULL;
807 GPtrArray *gp_char_array = NULL;
811 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
812 if (NULL == conn_info) {
813 DBG("Failed to get the conn_info");
814 return BT_STATUS_FAIL;
817 _bt_hal_convert_addr_type_to_string(device_address,
818 (unsigned char *)conn_info->bd_addr.address);
820 result = _bt_hal_get_managed_objects();
824 gp_array = g_ptr_array_new();
825 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
827 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
829 if (object_path == NULL)
832 _bt_hal_convert_device_path_to_address(object_path, temp_address);
834 if (g_strcmp0(temp_address, device_address) != 0)
837 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
838 &interface_str, &svc_iter)) {
839 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
842 DBG("[%d] Object Path : %s", idx++, object_path);
843 /* for characteristic */
844 gp_char_array = g_ptr_array_new();
845 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
846 if (g_strcmp0(key, "Primary") == 0) {
847 is_primary = g_variant_get_boolean(value);
850 g_ptr_array_add(gp_array, (gpointer)object_path);
853 } else if (g_strcmp0(key, "UUID") == 0) {
854 uuid_str = g_variant_get_string(value, &len);
855 DBG(" UUID: [%s]", uuid_str);
856 } else if (g_strcmp0(key, "Characteristics") == 0) {
857 g_variant_get(value, "ao", &char_iter);
858 if (char_iter != NULL) {
859 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
860 DBG("char handle : %s", char_handle);
861 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
868 DBG("send search service result event");
869 _bt_hal_send_search_service_result_event(conn_id, is_primary,
870 uuid_str, conn_info->inst_id);
872 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
877 if (gp_array->len == 0 || svc_count == 0) {
878 ERR("gp_array is NULL");
879 ret = BT_STATUS_FAIL;
881 ret = BT_STATUS_SUCCESS;
884 browse_service_char(conn_id);
885 /* send search service complete event */
886 _bt_hal_send_search_service_complete_event(conn_id, ret);
888 g_ptr_array_free(gp_array, TRUE);
889 g_variant_iter_free(iter);
890 g_variant_unref(result);
895 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
897 if (NULL == filter_uuid) {
898 DBG("Browse all the services");
899 return _gattc_client_search_service(conn_id);
901 DBG("TODO implement it");
902 return BT_STATUS_UNSUPPORTED;
906 * Enumerate included services for a given service.
907 * Set start_incl_srvc_id to NULL to get the first included service.
909 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
910 btgatt_srvc_id_t *start_incl_srvc_id)
913 return BT_STATUS_UNSUPPORTED;
916 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
917 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
919 struct hal_ev_gatt_client_char_search_result ev;
922 ERR("gatt client callback not registered");
926 DBG("sending gatt client search char result event conn_id[%d] status[%d]", conn_id, status);
928 memset(&ev, 0, sizeof(ev));
929 ev.conn_id = conn_id;
930 ev.inst_id = svc_id->id.inst_id;
931 ev.is_primary = svc_id->is_primary;
933 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
935 if (status == BT_STATUS_SUCCESS) {
936 DBG("building char uuid");
937 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
938 ev.char_prop = char_prop;
941 DBG("sending the char search event");
943 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
946 static int _hal_get_permission_flag(char *permission)
950 if (NULL == permission) {
951 ERR("gatt permission is NULL");
955 if (!g_strcmp0(permission, "broadcast"))
956 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
957 else if (!g_strcmp0(permission, "read"))
958 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
959 else if (!g_strcmp0(permission, "write-without-response"))
960 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
961 else if (!g_strcmp0(permission, "write"))
962 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
963 else if (!g_strcmp0(permission, "notify"))
964 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
965 else if (!g_strcmp0(permission, "indicate"))
966 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
967 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
968 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
969 else if (!g_strcmp0(permission, "reliable-write"))
970 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
971 else if (!g_strcmp0(permission, "writable-auxiliaries"))
972 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
973 else if (!g_strcmp0(permission, "encrypt-read"))
974 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
975 else if (!g_strcmp0(permission, "encrypt-write"))
976 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
977 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
978 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
979 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
980 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
986 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
988 GDBusProxy *properties_proxy = NULL;
989 GError *error = NULL;
990 GVariant *value = NULL;
991 GVariant *result = NULL;
992 GDBusConnection *g_conn;
994 char *char_desc_handle = NULL;
996 GVariantIter *property_iter;
997 GVariantIter *char_desc_iter;
998 char* char_handle = NULL;
999 gchar *char_uuid_str = NULL;
1000 GPtrArray *gp_desc_array = NULL;
1001 GVariantIter *char_perm_iter;
1003 unsigned int char_permission = 0 ;
1007 if (gattc_char->chr_path == NULL) {
1008 DBG("char path is NULL");
1009 return BT_STATUS_FAIL;
1011 char_handle = gattc_char->chr_path;
1013 DBG("char path:[%s]", gattc_char->chr_path);
1015 g_conn = _bt_hal_get_system_gconn();
1016 if (NULL == g_conn) {
1017 ERR("_bt_gdbus_get_system_gconn returned NULL");
1018 return BT_STATUS_FAIL;
1021 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1022 G_DBUS_PROXY_FLAGS_NONE, NULL,
1025 BT_HAL_PROPERTIES_INTERFACE,
1028 if (properties_proxy == NULL) {
1029 ERR("properties_proxy returned NULL");
1030 return BT_STATUS_FAIL;
1033 result = g_dbus_proxy_call_sync(properties_proxy,
1035 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1036 G_DBUS_CALL_FLAGS_NONE,
1041 if (error != NULL) {
1042 ERR("Fail to get properties (Error: %s)", error->message);
1043 g_clear_error(&error);
1045 ERR("Fail to get properties");
1046 g_object_unref(properties_proxy);
1047 return BT_STATUS_FAIL;
1050 gp_desc_array = g_ptr_array_new();
1052 g_variant_get(result, "(a{sv})", &property_iter);
1054 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1055 if (!g_strcmp0(key, "UUID")) {
1056 char_uuid_str = g_variant_dup_string(value, &len);
1057 DBG("char UUID [%s]", char_uuid_str);
1058 } else if (!g_strcmp0(key, "Flags")) {
1059 g_variant_get(value, "as", &char_perm_iter);
1060 char_permission = 0x00;
1062 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1063 DBG("char permission: [%s]", permission);
1064 char_permission |= _hal_get_permission_flag(permission);
1066 } else if (!g_strcmp0(key, "Descriptors")) {
1067 g_variant_get(value, "ao", &char_desc_iter);
1068 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1069 DBG("char descriptor handle : %s", char_desc_handle);
1071 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1076 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1078 g_free(char_uuid_str);
1079 g_variant_iter_free(property_iter);
1080 g_variant_unref(result);
1081 g_object_unref(properties_proxy);
1082 g_ptr_array_free(gp_desc_array, TRUE);
1084 return BT_STATUS_SUCCESS;
1087 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1088 btgatt_srvc_id_t *srvc_id)
1090 hal_gattc_server_info_t * conn_info = NULL;
1091 hal_gattc_service_t *gattc_service = NULL;
1093 hal_gattc_char_t *gattc_char = NULL;
1094 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1095 int status = BT_STATUS_FAIL;
1098 DBG("conn_id[%d]", conn_id);
1100 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1101 if (NULL == conn_info) {
1102 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1103 return BT_STATUS_FAIL;
1107 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1108 if (NULL == gattc_service) {
1109 DBG("Failed to get the gatt service");
1110 return BT_STATUS_FAIL;
1113 DBG("service path [%s]", gattc_service->svc_path);
1115 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1116 DBG("service uuid [%s]", svc_uuid_str);
1118 /* find characteristic object path */
1119 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1120 gattc_char = (hal_gattc_char_t *)l->data;
1121 status = _hal_gattc_get_characteristic_info(gattc_char);
1124 if (BT_STATUS_SUCCESS == status) {
1125 DBG("Sending the success charateristics event");
1126 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1127 &gattc_char->chr_uuid, gattc_char->permission);
1131 DBG("sending final event");
1133 status = BT_STATUS_FAIL;
1134 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1136 browse_service_char(conn_id);
1137 /* retrive uuid for characteristic and object path for descriptor */
1139 return BT_STATUS_SUCCESS;
1143 * Enumerate characteristics for a given service.
1144 * Set start_char_id to NULL to get the first characteristic.
1146 bt_status_t btif_gattc_get_characteristic(int conn_id,
1147 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1150 CHECK_BTGATT_INIT();
1152 if (start_char_id == NULL) {
1153 DBG("Get all the characteristics");
1154 return _gattc_get_all_characteristic(conn_id, srvc_id);
1157 DBG("TBD Get specific characteristics");
1158 return BT_STATUS_UNSUPPORTED;
1162 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1164 GDBusProxy *properties_proxy = NULL;
1165 GError *error = NULL;
1166 GVariant *value = NULL;
1167 GVariant *result = NULL;
1168 GDBusConnection *g_conn;
1171 GVariantIter *property_iter;
1172 char* desc_handle = NULL;
1173 const gchar *desc_uuid_str = NULL;
1177 if (gattc_desc->desc_path == NULL) {
1178 DBG("desc path is NULL");
1179 return BT_STATUS_FAIL;
1181 desc_handle = gattc_desc->desc_path;
1183 DBG("desc path:[%s]", gattc_desc->desc_path);
1185 g_conn = _bt_hal_get_system_gconn();
1186 if (NULL == g_conn) {
1187 ERR("_bt_gdbus_get_system_gconn returned NULL");
1188 return BT_STATUS_FAIL;
1191 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1192 G_DBUS_PROXY_FLAGS_NONE, NULL,
1195 BT_HAL_PROPERTIES_INTERFACE,
1198 if (properties_proxy == NULL) {
1199 ERR("properties_proxy returned NULL");
1200 return BT_STATUS_FAIL;
1203 result = g_dbus_proxy_call_sync(properties_proxy,
1205 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1206 G_DBUS_CALL_FLAGS_NONE,
1211 if (error != NULL) {
1212 ERR("Fail to get properties (Error: %s)", error->message);
1213 g_clear_error(&error);
1215 ERR("Fail to get properties");
1216 g_object_unref(properties_proxy);
1217 return BT_STATUS_FAIL;
1220 g_variant_get(result, "(a{sv})", &property_iter);
1222 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1223 if (!g_strcmp0(key, "UUID")) {
1224 desc_uuid_str = g_variant_get_string(value, &len);
1225 DBG("desc UUID [%s]", desc_uuid_str);
1226 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1231 g_variant_iter_free(property_iter);
1232 g_variant_unref(result);
1233 g_object_unref(properties_proxy);
1235 return BT_STATUS_SUCCESS;
1238 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1239 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1241 struct hal_ev_gatt_client_desc_search_result ev;
1244 ERR("gatt client callback not registered");
1248 DBG("sending gatt client search desc result event conn_id[%d] status[%d]", conn_id, status);
1250 memset(&ev, 0, sizeof(ev));
1251 ev.conn_id = conn_id;
1252 ev.inst_id = svc_id->id.inst_id;
1253 ev.is_primary = svc_id->is_primary;
1256 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1257 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1259 if (status == BT_STATUS_SUCCESS) {
1260 DBG("building desc uuid");
1261 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1264 DBG("sending the desc search event");
1266 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1269 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1270 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1272 hal_gattc_server_info_t * conn_info = NULL;
1273 hal_gattc_service_t *gattc_service = NULL;
1276 hal_gattc_char_t *gattc_char = NULL;
1277 hal_gattc_desc_t *gattc_desc = NULL;
1278 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1279 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1280 int status = BT_STATUS_FAIL;
1284 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1285 if (NULL == conn_info) {
1286 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1287 return BT_STATUS_FAIL;
1291 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1292 if (NULL == gattc_service) {
1293 DBG("Failed to get the gatt service");
1294 return BT_STATUS_FAIL;
1297 DBG("service path [%s]", gattc_service->svc_path);
1298 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1299 DBG("service uuid [%s]", svc_uuid_str);
1301 /* find characteristics */
1302 /* a service can have two char with same uuid */
1303 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1304 gattc_char = (hal_gattc_char_t*)l->data;
1305 if (gattc_char == NULL)
1308 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1309 INFO("Found GATT char uuid");
1310 DBG("char path [%s]", gattc_char->chr_path);
1311 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1312 DBG("char uuid [%s]", char_uuid_str);
1314 /* get descriptor uuid */
1315 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1316 gattc_desc = (hal_gattc_desc_t *)m->data;
1317 if (gattc_desc == NULL)
1320 status = _hal_gattc_get_descriptor_info(gattc_desc);
1323 if (BT_STATUS_SUCCESS == status) {
1324 DBG("Sending the success descriptor event");
1325 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1326 char_id, &gattc_desc->desc_uuid);
1332 DBG("sending final event");
1334 status = BT_STATUS_FAIL;
1335 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1337 browse_service_char(conn_id);
1338 /* retrive uuid for characteristic and object path for descriptor */
1340 return BT_STATUS_SUCCESS;
1344 * Enumerate descriptors for a given characteristic.
1345 * Set start_descr_id to NULL to get the first descriptor.
1347 bt_status_t btif_gattc_get_descriptor(int conn_id,
1348 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1349 btgatt_gatt_id_t *start_descr_id)
1352 CHECK_BTGATT_INIT();
1354 if (start_descr_id == NULL) {
1355 DBG("Get all the descriptors");
1356 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1358 DBG("TBD Get specific descriptor");
1359 return BT_STATUS_UNSUPPORTED;
1363 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1365 struct hal_ev_gatt_client_read_data ev;
1368 ERR("gatt client callback not registered");
1372 DBG("sending gatt client charac read conn_id[%d] status[%d]", resp_data->conn_id, result);
1374 memset(&ev, 0, sizeof(ev));
1375 ev.conn_id = resp_data->conn_id;
1376 ev.inst_id = resp_data->srvc_id.id.inst_id;
1377 ev.is_primary = resp_data->srvc_id.is_primary;
1380 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1381 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1385 DBG("building the char read value [%d]", len);
1386 memcpy(ev.value, value, len);
1389 DBG("sending the gatt client read charac event");
1391 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1394 static void __hal_internal_read_char_cb(GObject *source_object,
1395 GAsyncResult *res, gpointer user_data)
1397 GError *error = NULL;
1398 GDBusConnection *system_gconn = NULL;
1401 GByteArray *gp_byte_array = NULL;
1403 hal_gatt_resp_data_t *resp_data = user_data;
1404 int result = BT_STATUS_SUCCESS;
1409 system_gconn = _bt_hal_get_system_gconn();
1410 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1413 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1416 result = BT_STATUS_FAIL;
1417 __hal_send_char_read_event(resp_data, result, NULL, 0);
1418 g_clear_error(&error);
1423 gp_byte_array = g_byte_array_new();
1424 g_variant_get(value, "(ay)", &iter);
1426 while (g_variant_iter_loop(iter, "y", &g_byte))
1427 g_byte_array_append(gp_byte_array, &g_byte, 1);
1431 for (i = 0; i < gp_byte_array->len; i++)
1432 DBG("%02x", gp_byte_array->data[i]);
1435 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1439 g_byte_array_free(gp_byte_array, TRUE);
1440 g_variant_iter_free(iter);
1441 g_variant_unref(value);
1447 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1448 btgatt_gatt_id_t *char_id, int auth_req)
1450 GDBusConnection *g_conn;
1451 hal_gatt_resp_data_t *resp_data;
1452 hal_gattc_service_t *gattc_service = NULL;
1453 GVariantBuilder *builder = NULL;
1455 hal_gattc_server_info_t * conn_info = NULL;
1456 hal_gattc_char_t *gattc_char = NULL;
1457 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1458 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1459 char* char_handle = NULL;
1463 /* get the connection info */
1464 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1465 if (NULL == conn_info) {
1466 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1467 return BT_STATUS_FAIL;
1471 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1472 if (NULL == gattc_service) {
1473 DBG("Failed to get the gatt service");
1474 return BT_STATUS_FAIL;
1477 DBG("service path [%s]", gattc_service->svc_path);
1478 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1479 DBG("service uuid [%s]", svc_uuid_str);
1482 /* find characteristic */
1483 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1484 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1485 if (NULL == gattc_char) {
1486 DBG("Failed to get the gatt char");
1487 return BT_STATUS_FAIL;
1490 DBG("char path [%s]", gattc_char->chr_path);
1491 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1492 DBG("char uuid [%s]", char_uuid_str);
1494 g_conn = _bt_hal_get_system_gconn();
1495 if (NULL == g_conn) {
1496 ERR("_bt_gdbus_get_system_gconn returned NULL");
1497 return BT_STATUS_FAIL;
1500 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1501 if (NULL == resp_data) {
1502 ERR("failed to get the memory");
1503 return BT_STATUS_FAIL;
1506 resp_data->conn_id = conn_id;
1507 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1508 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1510 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1513 g_variant_builder_add(builder, "{sv}", "offset",
1514 g_variant_new("q", offset));
1516 char_handle = gattc_char->chr_path;
1518 DBG("calling char read value");
1520 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1521 "ReadValue", g_variant_new("(a{sv})", builder),
1522 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1523 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1524 (gpointer)resp_data);
1525 g_variant_builder_unref(builder);
1527 return BT_STATUS_SUCCESS;
1530 /** Read a characteristic on a remote device */
1531 bt_status_t btif_read_characteristic(int conn_id,
1532 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1535 CHECK_BTGATT_INIT();
1538 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1541 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1543 struct hal_ev_gatt_client_write_result ev;
1546 ERR("gatt client callback not registered");
1550 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
1552 memset(&ev, 0, sizeof(ev));
1553 ev.conn_id = resp_data->conn_id;
1554 ev.inst_id = resp_data->srvc_id.id.inst_id;
1555 ev.is_primary = resp_data->srvc_id.is_primary;
1558 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1559 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1561 DBG("sending the gatt client write charac event");
1563 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1566 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1567 GAsyncResult *res, gpointer user_data)
1569 GError *error = NULL;
1570 GDBusConnection *system_gconn = NULL;
1572 hal_gatt_resp_data_t *resp_data = user_data;
1573 int result = BT_STATUS_SUCCESS;
1577 system_gconn = _bt_hal_get_system_gconn();
1578 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1581 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1583 result = BT_STATUS_FAIL;
1585 __hal_send_char_write_event(resp_data, result);
1586 g_clear_error(&error);
1591 //send write value event
1592 __hal_send_char_write_event(resp_data, result);
1595 g_variant_unref(value);
1600 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1603 case HAL_GATT_WRITE_TYPE_WRITE:
1604 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1606 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1607 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1610 ERR("Unknow write type : %d", type);
1611 return BT_STATUS_FAIL;
1614 return BT_STATUS_SUCCESS;
1618 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1620 GDBusConnection *conn;
1621 GVariantBuilder *builder = NULL;
1627 GUnixFDList *fd_list = NULL;
1629 conn = _bt_hal_get_system_gconn();
1631 ERR("_bt_gdbus_get_system_gconn returned NULL");
1632 return BT_STATUS_FAIL;
1635 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1636 //val = g_variant_new("ay", builder1);
1638 g_variant_builder_add(builder, "{sv}", "offset",
1639 g_variant_new("q", offset));
1641 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1642 "AcquireWrite", g_variant_new("(a{sv})", builder),
1643 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1644 NULL, &fd_list, NULL, &err);
1646 g_dbus_error_strip_remote_error(err);
1647 ERR("Error: %s", err->message);
1649 g_variant_builder_unref(builder);
1650 return BT_STATUS_FAIL;
1653 g_variant_get(value, "(hq)", &idx, &att_mtu);
1654 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1656 INFO("FD is %d index is %d mtu is %d", *fd, idx, att_mtu);
1659 g_object_unref(fd_list);
1660 g_variant_unref(value);
1661 g_variant_builder_unref(builder);
1663 return BT_STATUS_SUCCESS;
1666 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1668 GDBusConnection *conn;
1669 GVariantBuilder *builder = NULL;
1673 gint32 idx, notify_fd;
1675 GUnixFDList *fd_list = NULL;
1677 conn = _bt_hal_get_system_gconn();
1680 ERR("_bt_gdbus_get_system_gconn returned NULL");
1681 return BT_STATUS_FAIL;
1685 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1688 g_variant_builder_add(builder, "{sv}", "offset",
1689 g_variant_new("q", offset));
1691 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1692 "AcquireNotify", g_variant_new("(a{sv})", builder),
1693 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1694 NULL, &fd_list, NULL, &err);
1696 g_dbus_error_strip_remote_error(err);
1697 ERR("Error: %s", err->message);
1699 g_variant_builder_unref(builder);
1700 return BT_STATUS_FAIL;
1703 g_variant_get(value, "(hq)", &idx, &att_mtu);
1704 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1707 INFO("Acquired characteristic Notify fd %d, mtu %d", notify_fd, *mtu);
1711 g_object_unref(fd_list);
1712 g_variant_unref(value);
1713 g_variant_builder_unref(builder);
1715 return BT_STATUS_SUCCESS;
1719 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1720 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1722 GVariant *val, *options;
1723 GVariantBuilder *builder1;
1724 GVariantBuilder *builder2;
1725 GDBusConnection *g_conn;
1728 hal_gatt_resp_data_t *resp_data;
1729 hal_gattc_service_t *gattc_service = NULL;
1730 hal_gattc_server_info_t * conn_info = NULL;
1731 hal_gattc_char_t *gattc_char = NULL;
1732 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1733 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1734 char* char_handle = NULL;
1735 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1736 int ret = BT_STATUS_SUCCESS;
1740 ret = __hal_get_write_prop(write_type, &write_prop);
1741 if (BT_STATUS_FAIL == ret) {
1742 DBG("received invalid write type:[%d] ", write_type);
1743 return BT_STATUS_FAIL;
1746 /* get the connection info */
1747 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1748 if (NULL == conn_info) {
1749 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1750 return BT_STATUS_FAIL;
1754 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1755 if (NULL == gattc_service) {
1756 DBG("Failed to get the gatt service");
1757 return BT_STATUS_FAIL;
1760 DBG("service path [%s]", gattc_service->svc_path);
1761 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1762 DBG("service uuid [%s]", svc_uuid_str);
1764 /* find characteristic */
1765 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1766 if (NULL == gattc_char) {
1767 DBG("Failed to get the gatt char");
1768 return BT_STATUS_FAIL;
1771 DBG("char path [%s]", gattc_char->chr_path);
1772 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1773 DBG("char uuid [%s]", char_uuid_str);
1775 g_conn = _bt_hal_get_system_gconn();
1776 if (NULL == g_conn) {
1777 ERR("_bt_gdbus_get_system_gconn returned NULL");
1778 return BT_STATUS_FAIL;
1781 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1782 if (NULL == resp_data) {
1783 ERR("failed to get the memory");
1784 return BT_STATUS_FAIL;
1787 resp_data->conn_id = conn_id;
1788 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1789 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1791 char_handle = gattc_char->chr_path;
1793 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1795 for (i = 0; i < length; i++)
1796 g_variant_builder_add(builder1, "y", value[i]);
1798 val = g_variant_new("ay", builder1);
1800 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1802 g_variant_builder_add(builder2, "{sv}", "offset",
1803 g_variant_new_uint16(offset));
1805 options = g_variant_new("a{sv}", builder2);
1807 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1809 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1811 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1812 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1813 (gpointer)resp_data);
1815 g_variant_builder_unref(builder1);
1816 g_variant_builder_unref(builder2);
1818 return BT_STATUS_SUCCESS;
1821 bt_status_t btif_get_acquire_write_fd(int conn_id,
1822 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1823 int auth_req, int *fd, int*mtu)
1825 CHECK_BTGATT_INIT();
1829 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1832 hal_gattc_service_t *gattc_service = NULL;
1833 hal_gattc_server_info_t * conn_info = NULL;
1834 hal_gattc_char_t *gattc_char = NULL;
1835 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1837 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1838 int ret = BT_STATUS_SUCCESS;
1842 /* get the connection info */
1843 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1844 if (NULL == conn_info) {
1845 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1846 return BT_STATUS_FAIL;
1850 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1851 if (NULL == gattc_service) {
1852 DBG("Failed to get the gatt service");
1853 return BT_STATUS_FAIL;
1856 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1857 if (NULL == gattc_char) {
1858 DBG("Failed to get the gatt char");
1859 return BT_STATUS_FAIL;
1862 DBG("char path [%s]", gattc_char->chr_path);
1863 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1864 DBG("char uuid [%s]", char_uuid_str);
1867 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1868 if (ret != BT_STATUS_SUCCESS)
1872 ERR("Characterstics FD erite characterstics fd is %d", *fd);
1877 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1878 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1880 CHECK_BTGATT_INIT();
1884 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1887 hal_gattc_service_t *gattc_service = NULL;
1888 hal_gattc_server_info_t * conn_info = NULL;
1889 hal_gattc_char_t *gattc_char = NULL;
1890 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1892 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1893 int ret = BT_STATUS_SUCCESS;
1897 /* get the connection info */
1898 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1899 if (NULL == conn_info) {
1900 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1901 return BT_STATUS_FAIL;
1905 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1906 if (NULL == gattc_service) {
1907 DBG("Failed to get the gatt service");
1908 return BT_STATUS_FAIL;
1911 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1912 if (NULL == gattc_char) {
1913 DBG("Failed to get the gatt char");
1914 return BT_STATUS_FAIL;
1917 DBG("char path [%s]", gattc_char->chr_path);
1918 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1919 DBG("char uuid [%s]", char_uuid_str);
1922 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1923 if (ret != BT_STATUS_SUCCESS)
1927 ERR("Characterstics FD write characterstics fd is %d", *fd);
1934 /** Write a remote characteristic */
1935 bt_status_t btif_write_characteristic(int conn_id,
1936 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1937 int write_type, int len, int auth_req,
1940 CHECK_BTGATT_INIT();
1944 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1945 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1946 len, auth_req, p_value);
1949 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1951 struct hal_ev_gatt_client_read_data ev;
1954 ERR("gatt client callback not registered");
1958 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1960 memset(&ev, 0, sizeof(ev));
1961 ev.conn_id = resp_data->conn_id;
1962 ev.inst_id = resp_data->srvc_id.id.inst_id;
1963 ev.is_primary = resp_data->srvc_id.is_primary;
1966 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1967 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1968 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1972 DBG("building the desc read value [%d]", len);
1973 memcpy(ev.value, value, len);
1976 DBG("sending the gatt client read descriptor event");
1978 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1981 static void __hal_internal_read_desc_cb(GObject *source_object,
1982 GAsyncResult *res, gpointer user_data)
1984 GError *error = NULL;
1985 GDBusConnection *system_gconn = NULL;
1988 GByteArray *gp_byte_array = NULL;
1990 hal_gatt_resp_data_t *resp_data = user_data;
1991 int result = BT_STATUS_SUCCESS;
1996 system_gconn = _bt_hal_get_system_gconn();
1997 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2000 ERR("Read descriptor dbus failed Error:[%s]", error->message);
2003 result = BT_STATUS_FAIL;
2004 __hal_send_desc_read_event(resp_data, result, NULL, 0);
2005 g_clear_error(&error);
2010 gp_byte_array = g_byte_array_new();
2011 g_variant_get(value, "(ay)", &iter);
2013 while (g_variant_iter_loop(iter, "y", &g_byte))
2014 g_byte_array_append(gp_byte_array, &g_byte, 1);
2018 for (i = 0; i < gp_byte_array->len; i++)
2019 DBG("%02x", gp_byte_array->data[i]);
2022 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2026 g_byte_array_free(gp_byte_array, TRUE);
2027 g_variant_iter_free(iter);
2028 g_variant_unref(value);
2033 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2034 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2036 GDBusConnection *g_conn;
2037 hal_gatt_resp_data_t *resp_data;
2038 hal_gattc_service_t *gattc_service = NULL;
2039 GVariantBuilder *builder = NULL;
2041 hal_gattc_server_info_t * conn_info = NULL;
2042 hal_gattc_char_t *gattc_char = NULL;
2043 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2044 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2045 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2046 char* desc_handle = NULL;
2049 hal_gattc_desc_t *gattc_desc = NULL;
2053 /* get the connection info */
2054 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2055 if (NULL == conn_info) {
2056 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
2057 return BT_STATUS_FAIL;
2061 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2062 if (NULL == gattc_service) {
2063 DBG("Failed to get the gatt service");
2064 return BT_STATUS_FAIL;
2067 DBG("service path [%s]", gattc_service->svc_path);
2068 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2069 DBG("service uuid [%s]", svc_uuid_str);
2071 /* find characteristic */
2072 /* service can have two char with same uuid */
2073 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2074 gattc_char = (hal_gattc_char_t*)l->data;
2075 if (gattc_char == NULL)
2078 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2079 INFO("Found GATT char uuid");
2080 DBG("char path [%s]", gattc_char->chr_path);
2081 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2082 DBG("char uuid [%s]", char_uuid_str);
2084 /* find descriptor */
2085 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2087 DBG("desc path [%s]", gattc_desc->desc_path);
2088 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2089 DBG("desc uuid [%s]", desc_uuid_str);
2095 if (NULL == gattc_desc) {
2096 DBG("Failed to get the gatt desc");
2097 return BT_STATUS_FAIL;
2100 g_conn = _bt_hal_get_system_gconn();
2101 if (NULL == g_conn) {
2102 ERR("_bt_gdbus_get_system_gconn returned NULL");
2103 return BT_STATUS_FAIL;
2106 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2107 if (NULL == resp_data) {
2108 ERR("failed to get the memory");
2109 return BT_STATUS_FAIL;
2112 resp_data->conn_id = conn_id;
2113 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2114 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2115 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2117 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2120 g_variant_builder_add(builder, "{sv}", "offset",
2121 g_variant_new("q", offset));
2123 desc_handle = gattc_desc->desc_path;
2125 DBG("calling desc read value");
2127 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2128 "ReadValue", g_variant_new("(a{sv})", builder),
2129 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2130 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2131 (gpointer)resp_data);
2132 g_variant_builder_unref(builder);
2134 return BT_STATUS_SUCCESS;
2137 /** Read the descriptor for a given characteristic */
2138 bt_status_t btif_read_descriptor(int conn_id,
2139 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2140 btgatt_gatt_id_t *descr_id, int auth_req)
2142 CHECK_BTGATT_INIT();
2144 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2147 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2149 struct hal_ev_gatt_client_write_result ev;
2152 ERR("gatt client callback not registered");
2156 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
2158 memset(&ev, 0, sizeof(ev));
2159 ev.conn_id = resp_data->conn_id;
2160 ev.inst_id = resp_data->srvc_id.id.inst_id;
2161 ev.is_primary = resp_data->srvc_id.is_primary;
2164 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2165 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2166 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2168 DBG("sending the gatt client write charac event");
2170 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2173 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2174 GAsyncResult *res, gpointer user_data)
2176 GError *error = NULL;
2177 GDBusConnection *system_gconn = NULL;
2179 hal_gatt_resp_data_t *resp_data = user_data;
2180 int result = BT_STATUS_SUCCESS;
2184 system_gconn = _bt_hal_get_system_gconn();
2185 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2188 ERR("write descriptor dbus failed Error: [%s]", error->message);
2191 result = BT_STATUS_FAIL;
2192 __hal_send_desc_write_event(resp_data, result);
2193 g_clear_error(&error);
2198 //send write value event
2199 __hal_send_desc_write_event(resp_data, result);
2202 g_variant_unref(value);
2207 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2208 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2209 int write_type, int length, int auth_req, char* value)
2211 GVariant *val, *options;
2212 GVariantBuilder *builder1;
2213 GVariantBuilder *builder2;
2214 GDBusConnection *g_conn;
2217 hal_gatt_resp_data_t *resp_data;
2218 hal_gattc_service_t *gattc_service = NULL;
2219 hal_gattc_server_info_t * conn_info = NULL;
2220 hal_gattc_char_t *gattc_char = NULL;
2221 hal_gattc_desc_t *gattc_desc = NULL;
2222 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2223 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2224 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2225 char* desc_handle = NULL;
2226 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2227 int ret = BT_STATUS_SUCCESS;
2232 ret = __hal_get_write_prop(write_type, &write_prop);
2233 if (BT_STATUS_FAIL == ret) {
2234 DBG("received invalid write type:[%d] ", write_type);
2235 return BT_STATUS_FAIL;
2238 /* get the connection info */
2239 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2240 if (NULL == conn_info) {
2241 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
2242 return BT_STATUS_FAIL;
2246 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2247 if (NULL == gattc_service) {
2248 DBG("Failed to get the gatt service");
2249 return BT_STATUS_FAIL;
2252 DBG("service path [%s]", gattc_service->svc_path);
2253 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2254 DBG("service uuid [%s]", svc_uuid_str);
2256 /* find characteristic */
2257 /* service can have two char with same uuid */
2258 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2259 gattc_char = (hal_gattc_char_t*)l->data;
2260 if (gattc_char == NULL)
2263 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2264 INFO("Found GATT char uuid");
2265 DBG("char path [%s]", gattc_char->chr_path);
2266 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2267 DBG("char uuid [%s]", char_uuid_str);
2269 /* find descriptor */
2270 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2272 DBG("desc path [%s]", gattc_desc->desc_path);
2273 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2274 DBG("desc uuid [%s]", desc_uuid_str);
2280 if (NULL == gattc_desc) {
2281 DBG("Failed to get the gatt desc");
2282 return BT_STATUS_FAIL;
2285 g_conn = _bt_hal_get_system_gconn();
2286 if (NULL == g_conn) {
2287 ERR("_bt_gdbus_get_system_gconn returned NULL");
2288 return BT_STATUS_FAIL;
2291 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2292 if (NULL == resp_data) {
2293 ERR("failed to get the memory");
2294 return BT_STATUS_FAIL;
2297 resp_data->conn_id = conn_id;
2298 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2299 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2300 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2302 desc_handle = gattc_desc->desc_path;
2304 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2306 for (i = 0; i < length; i++)
2307 g_variant_builder_add(builder1, "y", value[i]);
2309 val = g_variant_new("ay", builder1);
2311 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2313 g_variant_builder_add(builder2, "{sv}", "offset",
2314 g_variant_new_uint16(offset));
2316 options = g_variant_new("a{sv}", builder2);
2318 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2320 g_variant_new("(@ay@a{sv})", val, options),
2322 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2323 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2324 (gpointer)resp_data);
2326 g_variant_builder_unref(builder1);
2327 g_variant_builder_unref(builder2);
2329 return BT_STATUS_SUCCESS;
2332 /** Write a remote descriptor for a given characteristic */
2333 bt_status_t btif_write_descriptor(int conn_id,
2334 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2335 btgatt_gatt_id_t *descr_id, int write_type, int len,
2336 int auth_req, char* p_value)
2338 CHECK_BTGATT_INIT();
2340 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2341 len, auth_req, p_value);
2344 /** Execute a prepared write operation */
2345 bt_status_t execute_write(int conn_id, int execute)
2347 CHECK_BTGATT_INIT();
2348 return BT_STATUS_UNSUPPORTED;
2351 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2353 struct hal_ev_gatt_client_watch_notification ev;
2354 hal_gatt_resp_data_t *resp_data = user_data;
2356 DBG("sending the watch register notification event");
2357 /* send the event */
2358 memset(&ev, 0, sizeof(ev));
2359 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2361 ev.status = resp_data->result;
2363 ev.is_primary = resp_data->srvc_id.is_primary;
2364 ev.inst_id = resp_data->srvc_id.id.inst_id;
2366 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2367 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2370 ERR("GATT Callback not registered");
2372 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2379 static bt_status_t _hal_register_for_notification(int client_if,
2380 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2381 btgatt_gatt_id_t *char_id)
2383 int result = BT_STATUS_SUCCESS;
2384 GError *error = NULL;
2385 GDBusConnection *g_conn;
2386 hal_gattc_client_info_t *gattc_client = NULL;
2387 hal_gattc_server_info_t * conn_info = NULL;
2388 hal_gattc_service_t *gattc_service = NULL;
2389 hal_gattc_char_t *gattc_char = NULL;
2390 char* char_handle = NULL;
2391 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2392 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2393 hal_gatt_resp_data_t *resp_data;
2397 gattc_client = __bt_find_gatt_client_info(bd_addr);
2398 if (gattc_client == NULL) {
2399 ERR("failed to get the gatt client info");
2400 return BT_STATUS_FAIL;
2403 if (gattc_client->client_if != client_if) {
2404 ERR("could not find the gatt client for client id[%d]", client_if);
2405 return BT_STATUS_FAIL;
2408 /* get the connection info */
2409 conn_info = __bt_find_gatt_conn_info(bd_addr);
2410 if (NULL == conn_info) {
2411 ERR("Failed to get the conn_info");
2412 return BT_STATUS_FAIL;
2415 if (conn_info->inst_id != gattc_client->inst_id) {
2416 ERR("could not fild the conn_info");
2417 return BT_STATUS_FAIL;
2421 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2422 if (NULL == gattc_service) {
2423 DBG("Failed to get the gatt service");
2424 return BT_STATUS_FAIL;
2427 DBG("service path [%s]", gattc_service->svc_path);
2428 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2429 DBG("service uuid [%s]", svc_uuid_str);
2432 /* find characteristic */
2433 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2434 if (NULL == gattc_char) {
2435 DBG("Failed to get the gatt char");
2436 return BT_STATUS_FAIL;
2439 DBG("char path [%s]", gattc_char->chr_path);
2440 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2441 DBG("char uuid [%s]", char_uuid_str);
2443 char_handle = gattc_char->chr_path;
2445 g_conn = _bt_hal_get_system_gconn();
2446 if (g_conn == NULL) {
2448 return BT_STATUS_FAIL;
2451 resp_data = malloc(sizeof(hal_gatt_resp_data_t));
2452 if (NULL == resp_data) {
2453 ERR("failed to get the memory");
2454 return BT_STATUS_FAIL;
2457 DBG("#StartNotify");
2458 g_dbus_connection_call_sync(g_conn,
2461 BT_HAL_GATT_CHAR_INTERFACE,
2465 G_DBUS_CALL_FLAGS_NONE,
2466 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2469 g_dbus_error_strip_remote_error(error);
2470 ERR("### Watch Failed: %s", error->message);
2471 if (g_strrstr(error->message, "Already notifying"))
2472 result = BT_STATUS_SUCCESS;
2473 else if (g_strrstr(error->message, "In Progress"))
2474 result = BT_STATUS_BUSY;
2475 else if (g_strrstr(error->message, "Operation is not supported"))
2476 result = BT_STATUS_UNSUPPORTED;
2477 /*failed because of either Insufficient Authorization or Write Not Permitted */
2478 else if (g_strrstr(error->message, "Write not permitted") ||
2479 g_strrstr(error->message, "Operation Not Authorized"))
2480 result = BT_STATUS_AUTH_FAILURE;
2481 /* failed because of either Insufficient Authentication,
2482 Insufficient Encryption Key Size, or Insufficient Encryption. */
2483 else if (g_strrstr(error->message, "Not paired"))
2484 result = BT_STATUS_NOT_READY;
2486 result = BT_STATUS_FAIL;
2488 g_clear_error(&error);
2491 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2492 resp_data->result = result;
2493 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2494 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2496 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2500 return BT_STATUS_SUCCESS;
2504 * Register to receive notifications or indications for a given
2507 bt_status_t btif_register_for_notification(int client_if,
2508 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2509 btgatt_gatt_id_t *char_id)
2511 CHECK_BTGATT_INIT();
2513 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2516 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2518 struct hal_ev_gatt_client_watch_notification ev;
2519 hal_gatt_resp_data_t *resp_data = user_data;
2521 DBG("sending the watch deregister notification event");
2522 /* send the event */
2523 memset(&ev, 0, sizeof(ev));
2524 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2526 ev.status = resp_data->result;
2528 ev.is_primary = resp_data->srvc_id.is_primary;
2529 ev.inst_id = resp_data->srvc_id.id.inst_id;
2531 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2532 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2535 ERR("GATT Callback not registered");
2537 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2544 static bt_status_t _hal_deregister_for_notification(int client_if,
2545 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2546 btgatt_gatt_id_t *char_id)
2548 int result = BT_STATUS_SUCCESS;
2549 GError *error = NULL;
2550 GDBusConnection *g_conn;
2551 hal_gattc_client_info_t *gattc_client = NULL;
2552 hal_gattc_server_info_t * conn_info = NULL;
2553 hal_gattc_service_t *gattc_service = NULL;
2554 hal_gattc_char_t *gattc_char = NULL;
2555 char* char_handle = NULL;
2556 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2557 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2558 hal_gatt_resp_data_t *resp_data;
2562 gattc_client = __bt_find_gatt_client_info(bd_addr);
2563 if (gattc_client == NULL) {
2564 ERR("failed to get the gatt client info");
2565 return BT_STATUS_FAIL;
2568 if (gattc_client->client_if != client_if) {
2569 ERR("could not find the gatt client for client id[%d]", client_if);
2570 return BT_STATUS_FAIL;
2573 /* get the connection info */
2574 conn_info = __bt_find_gatt_conn_info(bd_addr);
2575 if (NULL == conn_info) {
2576 ERR("Failed to get the conn_info");
2577 return BT_STATUS_FAIL;
2580 if (conn_info->inst_id != gattc_client->inst_id) {
2581 ERR("could not fild the conn_info");
2582 return BT_STATUS_FAIL;
2586 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2587 if (NULL == gattc_service) {
2588 DBG("Failed to get the gatt service");
2589 return BT_STATUS_FAIL;
2592 DBG("service path [%s]", gattc_service->svc_path);
2593 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2594 DBG("service uuid [%s]", svc_uuid_str);
2597 /* find characteristic */
2598 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2599 if (NULL == gattc_char) {
2600 DBG("Failed to get the gatt char");
2601 return BT_STATUS_FAIL;
2604 DBG("char path [%s]", gattc_char->chr_path);
2605 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2606 DBG("char uuid [%s]", char_uuid_str);
2608 char_handle = gattc_char->chr_path;
2610 g_conn = _bt_hal_get_system_gconn();
2611 if (g_conn == NULL) {
2613 return BT_STATUS_FAIL;
2616 resp_data = malloc(sizeof(hal_gatt_resp_data_t));
2617 if (NULL == resp_data) {
2618 ERR("failed to get the memory");
2619 return BT_STATUS_FAIL;
2622 DBG("#StartNotify");
2623 g_dbus_connection_call_sync(g_conn,
2626 BT_HAL_GATT_CHAR_INTERFACE,
2630 G_DBUS_CALL_FLAGS_NONE,
2631 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2634 ERR("### Watch Failed: %s", error->message);
2635 g_clear_error(&error);
2636 result = BT_STATUS_FAIL;
2639 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2640 resp_data->result = result;
2641 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2642 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2644 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2648 return BT_STATUS_SUCCESS;
2650 /** Deregister a previous request for notifications/indications */
2651 bt_status_t btif_deregister_for_notification(int client_if,
2652 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2653 btgatt_gatt_id_t *char_id)
2655 CHECK_BTGATT_INIT();
2656 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2659 /** Request RSSI for a given remote device */
2660 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2662 CHECK_BTGATT_INIT();
2663 return BT_STATUS_UNSUPPORTED;
2666 /** OTA firmware download */
2667 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2669 CHECK_BTGATT_INIT();
2670 return BT_STATUS_UNSUPPORTED;
2673 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2674 int get_device_type(const bt_bdaddr_t *bd_addr)
2676 CHECK_BTGATT_INIT();
2677 return BT_STATUS_UNSUPPORTED;
2680 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2681 int min_int, int max_int, int latency, int timeout)
2683 gchar *device_path = NULL;
2684 GError *error = NULL;
2685 GDBusProxy *device_proxy = NULL;
2686 GDBusConnection *conn;
2688 int ret = BT_STATUS_SUCCESS;
2689 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2691 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2692 min_int, max_int, latency, timeout);
2694 conn = _bt_hal_get_system_gconn();
2697 return BT_STATUS_FAIL;
2700 _bt_hal_convert_addr_type_to_string(device_address,
2701 (unsigned char *)bd_addr->address);
2702 device_path = _bt_hal_get_device_object_path(device_address);
2704 if (device_path == NULL) {
2705 ERR("device_path NULL : [%s]", device_address);
2706 return BT_STATUS_FAIL;
2709 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2710 NULL, BT_HAL_BLUEZ_NAME,
2711 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2713 g_free(device_path);
2714 if (NULL == device_proxy) {
2715 ERR("device_proxy returned NULL");
2716 return BT_STATUS_FAIL;
2719 INFO("### LeConnUpdate");
2720 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2721 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2722 G_DBUS_CALL_FLAGS_NONE,
2727 g_object_unref(device_proxy);
2728 if (reply == NULL) {
2730 ERR("Error %s[%s]", error->message, device_address);
2731 if (g_strrstr(error->message, "In Progress"))
2732 ret = BT_STATUS_SUCCESS;
2734 ret = BT_STATUS_FAIL;
2735 g_error_free(error);
2739 g_variant_unref(reply);
2741 INFO("LE Connection parameter Updated");
2745 /** Request a connection parameter update */
2746 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2748 CHECK_BTGATT_INIT();
2752 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2755 /** Test mode interface */
2756 bt_status_t test_command(int command, btgatt_test_params_t* params)
2758 CHECK_BTGATT_INIT();
2759 return BT_STATUS_UNSUPPORTED;
2762 /** MTU Exchange request from client */
2763 bt_status_t configure_mtu(int conn_id, int mtu)
2765 CHECK_BTGATT_INIT();
2766 return BT_STATUS_UNSUPPORTED;
2769 /** Setup scan filter params */
2770 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2771 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2772 int rssi_low_thres, int dely_mode, int found_timeout,
2773 int lost_timeout, int found_timeout_cnt)
2775 CHECK_BTGATT_INIT();
2776 return BT_STATUS_UNSUPPORTED;
2779 /** Configure a scan filter condition */
2780 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2781 int filt_index, int company_id,
2782 int company_id_mask, const bt_uuid_t *p_uuid,
2783 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2784 char addr_type, int data_len, char* p_data, int mask_len,
2787 CHECK_BTGATT_INIT();
2788 return BT_STATUS_UNSUPPORTED;
2791 /** Clear all scan filter conditions for specific filter index*/
2792 bt_status_t scan_filter_clear(int client_if, int filt_index)
2794 CHECK_BTGATT_INIT();
2795 return BT_STATUS_UNSUPPORTED;
2798 /** Enable / disable scan filter feature*/
2799 bt_status_t scan_filter_enable(int client_if, bool enable)
2801 CHECK_BTGATT_INIT();
2802 return BT_STATUS_UNSUPPORTED;
2805 /** Sets the LE scan interval and window in units of N*0.625 msec */
2807 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
2811 CHECK_BTGATT_INIT();
2813 le_scan_type = scan_type;
2814 ret = _bt_hal_adapter_le_set_scan_parameters(
2815 scan_type, scan_interval, scan_window);
2819 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
2821 CHECK_BTGATT_INIT();
2822 return BT_STATUS_UNSUPPORTED;
2826 /* Configure the batchscan storage */
2827 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
2828 int batch_scan_trunc_max, int batch_scan_notify_threshold)
2830 CHECK_BTGATT_INIT();
2831 return BT_STATUS_UNSUPPORTED;
2834 /* Enable batchscan */
2835 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
2836 int scan_interval, int scan_window, int addr_type, int discard_rule)
2838 CHECK_BTGATT_INIT();
2839 return BT_STATUS_UNSUPPORTED;
2842 /* Disable batchscan */
2843 bt_status_t batchscan_dis_batch_scan(int client_if)
2845 CHECK_BTGATT_INIT();
2846 return BT_STATUS_UNSUPPORTED;
2849 /* Read out batchscan reports */
2850 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
2852 CHECK_BTGATT_INIT();
2853 return BT_STATUS_UNSUPPORTED;
2856 const btgatt_client_interface_t btgatt_client_interface = {
2857 .register_client = btif_gattc_register_client,
2858 .unregister_client = btif_gattc_unregister_client,
2860 .connect = btif_gattc_client_connect,
2861 .disconnect = btif_gattc_client_disconnect,
2863 .search_service = btif_gattc_client_search_service,
2864 .get_included_service = get_included_service,
2865 .get_characteristic = btif_gattc_get_characteristic,
2866 .get_descriptor = btif_gattc_get_descriptor,
2867 .read_characteristic = btif_read_characteristic,
2868 .write_characteristic = btif_write_characteristic,
2869 .acquire_write = btif_get_acquire_write_fd,
2870 .acquire_notify = btif_get_acquire_notify_fd,
2871 .read_descriptor = btif_read_descriptor,
2872 .write_descriptor = btif_write_descriptor,
2873 .execute_write = execute_write,
2874 .register_for_notification = btif_register_for_notification,
2875 .deregister_for_notification = btif_deregister_for_notification,
2876 .read_remote_rssi = read_remote_rssi,
2877 .ota_fw_update = ota_fw_update,
2878 .get_device_type = get_device_type,
2879 .conn_parameter_update = btif_gattc_conn_parameter_update,
2880 .test_command = test_command,
2881 .configure_mtu = configure_mtu,
2882 .scan_filter_param_setup = scan_filter_param_setup,
2883 .scan_filter_add_remove = scan_filter_add_remove,
2884 .scan_filter_clear = scan_filter_clear,
2885 .scan_filter_enable = scan_filter_enable,
2886 .set_scan_parameters = set_scan_parameters,
2887 .batchscan_cfg_storage = batchscan_cfg_storage,
2888 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
2889 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
2890 .batchscan_read_reports = batchscan_read_reports
2893 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr)
2898 hal_gattc_server_info_t *info = NULL;
2900 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
2901 info = (hal_gattc_server_info_t*)l->data;
2905 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
2906 INFO("GATT connection found addr");
2913 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
2918 hal_gattc_client_info_t *info = NULL;
2920 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
2921 info = (hal_gattc_client_info_t*)l->data;
2925 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
2926 INFO("GATT client info found addr");
2933 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
2938 hal_gattc_client_info_t *info = NULL;
2940 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
2941 info = (hal_gattc_client_info_t*)l->data;
2945 if (info->conn_id == conn_id) {
2946 INFO("GATT client info found for conn_id [%d]", conn_id);
2953 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
2958 hal_gattc_server_info_t *info = NULL;
2959 hal_gattc_client_info_t *gattc_client = NULL;
2961 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2962 if (gattc_client == NULL) {
2963 INFO("GATT client conn info not found");
2967 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
2968 info = (hal_gattc_server_info_t*)l->data;
2972 if ((info->inst_id == gattc_client->inst_id) &&
2973 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
2974 INFO("GATT connection found for conn_id [%d]", conn_id);
2981 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
2982 gboolean auto_connect)
2984 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2985 gchar *device_path = NULL;
2986 GDBusProxy *device_proxy = NULL;
2987 GDBusConnection *conn;
2988 int ret = BT_STATUS_SUCCESS;
2989 hal_gattc_client_info_t *gattc_data;
2993 if (NULL == bd_addr) {
2994 ERR("bd_addr is NULL");
2995 return BT_STATUS_PARM_INVALID;
2998 conn = _bt_hal_get_system_gconn();
3000 ERR("_bt_gdbus_get_system_gconn returned NULL");
3001 return BT_STATUS_FAIL;
3004 _bt_hal_convert_addr_type_to_string(device_address,
3005 (unsigned char *)bd_addr->address);
3006 device_path = _bt_hal_get_device_object_path(device_address);
3007 if (device_path == NULL) {
3008 ERR("device_path NULL : [%s]", device_address);
3009 ret = BT_STATUS_FAIL;
3012 ERR("device_path:%s", device_path);
3014 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3015 NULL, BT_HAL_BLUEZ_NAME,
3016 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3017 g_free(device_path);
3018 if (NULL == device_proxy) {
3019 ERR("device_proxy returned NULL");
3020 return BT_STATUS_FAIL;
3023 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3024 if (gattc_data == NULL) {
3025 ERR("Unable to allocate memory");
3026 ret = BT_STATUS_NOMEM;
3029 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3030 BT_HAL_ADDRESS_LENGTH_MAX);
3032 DBG("Connect LE [%s]", device_address);
3034 gattc_data->client_if = client_if;
3036 g_dbus_proxy_call(device_proxy, "ConnectLE",
3037 g_variant_new("(b)", auto_connect),
3038 G_DBUS_CALL_FLAGS_NONE,
3039 BT_HAL_MAX_DBUS_TIMEOUT,
3041 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3047 g_object_unref(device_proxy);
3054 static bt_status_t _bt_hold_current_advertising()
3056 int ret = BT_STATUS_FAIL;
3057 gboolean is_advertising = FALSE;
3060 is_advertising = _bt_hal_is_advertising_in_slot(0);
3061 if (is_advertising) {
3062 DBG("+ Stop current advertising");
3064 ret = _bt_hal_enable_advertising(0, FALSE, FALSE);
3065 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3071 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3073 DBG("+ start current advertising");
3075 _bt_hal_enable_advertising(0, TRUE, FALSE);
3080 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3082 DBG("Try to initiate pending LE connection");
3084 pending_le_conn_timer_id = 0;
3086 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3087 &pending_le_conn_info->bd_addr,
3088 pending_le_conn_info->auto_connect);
3090 g_free(pending_le_conn_info);
3091 pending_le_conn_info = NULL;
3096 static int __hal_generate_conn_id()
3098 return ++bt_conn_id;
3101 static int __hal_generate_server_instance_id()
3103 return ++bt_inst_id;
3106 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3109 GError *g_error = NULL;
3110 GVariant *reply = NULL;
3111 hal_gattc_client_info_t *gattc_data = user_data;
3112 int result = BT_STATUS_SUCCESS;
3113 struct hal_ev_gatt_client_connected ev;
3114 hal_gattc_server_info_t *gatt_conn_info = NULL;
3118 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3119 g_object_unref(proxy);
3120 if (reply == NULL) {
3121 ERR("Connect LE Dbus Call Error");
3123 ERR("Error: %s\n", g_error->message);
3124 g_clear_error(&g_error);
3126 result = BT_STATUS_FAIL;
3128 g_variant_unref(reply);
3130 if (NULL == gattc_data) {
3131 ERR("server_data is NULL");
3136 if (result == BT_STATUS_FAIL) {
3137 memset(&ev, 0, sizeof(ev));
3140 ev.client_if = gattc_data->client_if;
3141 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3142 BT_HAL_ADDRESS_LENGTH_MAX);
3145 ERR("gatt client callback not registered");
3147 DBG("sending gatt client connected event");
3148 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3154 DBG("adding the server conn info in list");
3155 gattc_data->conn_id = __hal_generate_conn_id() ;
3156 gattc_data->inst_id = __hal_generate_server_instance_id();
3158 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3160 /*add gatt server connection info*/
3161 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3162 if (gatt_conn_info == NULL) {
3163 ERR("Failed to allocate memory");
3167 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3168 gatt_conn_info->inst_id = gattc_data->inst_id;
3169 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3175 /*remove conn_info*/
3180 void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3182 g_free(svc_info->svc_path);
3186 void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3188 g_free(char_info->chr_path);
3192 void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3194 g_free(desc_info->desc_path);
3198 void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3203 hal_gattc_service_t *svc_info = NULL;
3204 hal_gattc_char_t *char_info = NULL;
3205 hal_gattc_desc_t *desc_info = NULL;
3209 for (l = conn_info->gatt_list_services; l != NULL;) {
3210 svc_info = (hal_gattc_service_t*)l->data;
3211 if (svc_info == NULL)
3213 l = g_slist_next(l);
3215 for (m = svc_info->gatt_list_chars; m != NULL; ) {
3216 char_info = (hal_gattc_char_t*)m->data;
3217 if (char_info == NULL)
3219 m = g_slist_next(m);
3221 for (k = char_info->gatt_list_descs; k != NULL; ) {
3222 desc_info = (hal_gattc_desc_t*)k->data;
3223 if (desc_info == NULL)
3225 k = g_slist_next(k);
3227 /*remove desc element*/
3228 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3229 __hal_gattc_free_desc_info(desc_info);
3232 /*remove desc list*/
3233 g_slist_free(char_info->gatt_list_descs);
3234 char_info->gatt_list_descs = NULL;
3236 /*remove char element*/
3237 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3238 __hal_gattc_free_char_info(char_info);
3241 /*remove char list*/
3242 g_slist_free(svc_info->gatt_list_chars);
3243 svc_info->gatt_list_chars = NULL;
3245 /*remove svc element*/
3246 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3247 __hal_gattc_free_svc_info(svc_info);
3250 /*remove svc list */
3251 g_slist_free(conn_info->gatt_list_services);
3252 conn_info->gatt_list_services = NULL;
3254 /*remove conn info*/
3258 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3260 int result = BT_STATUS_SUCCESS;
3261 struct hal_ev_gatt_client_connected ev;
3262 hal_gattc_server_info_t *conn_info = NULL;
3263 bt_bdaddr_t bd_addr;
3265 hal_gattc_client_info_t *gattc_client = NULL;
3269 DBG("+ connected device address [%s]", address);
3271 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3272 HAL_EV_GATT_CLIENT_DISCONNECTED;
3274 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3275 /* find the gatt client info */
3276 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3277 if (NULL == gattc_client) {
3278 ERR("Fail to get gatt client info");
3283 memset(&ev, 0, sizeof(ev));
3284 ev.conn_id = gattc_client->conn_id;
3286 ev.client_if = gattc_client->client_if;
3287 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3288 BT_HAL_ADDRESS_LENGTH_MAX);
3291 ERR("gatt client callback not registered");
3293 DBG("sending gatt client connected status event");
3294 event_cb(event, (void *)&ev, sizeof(ev));
3297 if (!gatt_connected) {
3298 inst_id = gattc_client->inst_id;
3300 /* remove the gatt client info from the client list also*/
3301 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3302 g_free(gattc_client);
3304 //find the connected server info
3305 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3306 if (NULL == conn_info) {
3307 ERR("Fail to get gatt server info");
3311 if (inst_id != conn_info->inst_id) {
3312 ERR("server instance is different");
3316 //remove gatt conn info from the server list
3317 DBG("remove the server conn_info from list after gatt disconnection");
3318 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3319 __hal_clean_gattc_server_info(conn_info);
3325 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3326 const char* uuid_str, int inst_id)
3328 struct hal_ev_gatt_client_search_result ev;
3331 ERR("gatt client callback not registered");
3335 DBG("sending gatt client search service result event conn_id[%d]", conn_id);
3337 memset(&ev, 0, sizeof(ev));
3338 ev.conn_id = conn_id;
3339 ev.inst_id = inst_id;
3340 ev.is_primary = is_primary;
3341 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3343 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3346 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3348 struct hal_ev_gatt_client_search_complete ev;
3351 ERR("gatt client callback not registered");
3355 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3358 memset(&ev, 0, sizeof(ev));
3359 ev.conn_id = conn_id;
3362 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3365 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3366 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3367 char *char_value, int len)
3369 struct hal_ev_gatt_client_notify_changed_value ev;
3370 hal_gattc_client_info_t *gattc_client = NULL;
3373 ERR("gatt client callback not registered");
3377 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3378 if (NULL == gattc_client) {
3379 ERR("failed to get the gatt client info");
3384 DBG("sending gatt client connected status event");
3385 memset(&ev, 0, sizeof(ev));
3387 ev.conn_id = gattc_client->conn_id;
3388 ev.inst_id = conn_info->inst_id;
3389 ev.is_primary = svc_info->is_primary;
3390 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3391 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3393 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3395 if (len > 0 && (char_value != NULL)) {
3396 memcpy(ev.value, char_value, len);
3400 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3403 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3404 char *char_value, int len)
3406 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3407 hal_gattc_server_info_t *conn_info = NULL;
3408 bt_bdaddr_t bd_addr;
3411 hal_gattc_service_t *svc_info = NULL;
3412 hal_gattc_char_t *char_info = NULL;
3416 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3417 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3418 DBG("device address:[%s]", device_address);
3419 DBG("char handle:[%s]", char_handle);
3421 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3422 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3424 if (conn_info != NULL) {
3425 //find service for notified char path
3426 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3427 svc_info = (hal_gattc_service_t*)l->data;
3428 if (svc_info == NULL)
3431 /* find characteristic object path */
3432 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3433 char_info = (hal_gattc_char_t *)k->data;
3434 if (char_info == NULL)
3437 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3438 DBG("Found char handle[%s]", char_info->chr_path);
3441 _bt_hal_send_value_changed_event(conn_info, svc_info,
3442 char_info, char_value, len);