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;
120 GSList *gatt_list_chars;
121 } hal_gattc_service_t;
124 bt_bdaddr_t bd_addr; /*remote server address*/
125 int inst_id; /*server instance id*/
126 GSList *gatt_list_services;
127 } hal_gattc_server_info_t;
129 /* Linked List of connected GATT server */
130 static GSList *hal_gattc_server_info_list = NULL;
134 bt_bdaddr_t bd_addr; /*remote server address*/
137 } hal_gattc_client_info_t;
139 /* Linked list of connected GATT client connection */
140 static GSList * hal_gattc_client_info_list = NULL;
142 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
143 static guint pending_le_conn_timer_id = 0;
144 static int bt_conn_id = 0;
145 static int bt_inst_id = 0;
147 #define BT_GATTC_CL_MAX 32
152 btgatt_srvc_id_t srvc_id;
153 btgatt_gatt_id_t char_id;
154 btgatt_gatt_id_t desc_id;
155 } hal_gatt_resp_data_t;
160 } hal_gatt_client_app;
162 static GSList * hal_gattc_client_app_list = NULL;
164 static int bt_client_if = 0;
167 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
168 gboolean auto_connect);
169 static bt_status_t _bt_hold_current_advertising();
170 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
171 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
172 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
174 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
175 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
176 const char* uuid_str, int inst_id);
177 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
178 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr);
179 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
182 /* To send stack event to hal-av handler */
183 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
188 void _bt_hal_unregister_gatt_client_handler_cb(void)
194 int _bt_hal_gatt_client_get_le_scan_type(void)
200 static gboolean __bt_hal_register_client_cb(gpointer user_data)
202 struct hal_ev_gatt_client_registered ev;
203 hal_gatt_client_app *client_info = user_data;
206 /* Prepare to send AV connecting event */
207 memset(&ev, 0, sizeof(ev));
208 ev.status = BT_STATUS_SUCCESS;
209 ev.client_if = client_info->client_if;
210 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
213 ERR("GATT Callback not registered");
215 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
216 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
223 static int __hal_generate_client_id()
225 return ++bt_client_if;
228 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
231 hal_gatt_client_app *info = NULL;
232 hal_gatt_client_app *gattc_app = NULL;
234 //check if client app is already registered
235 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
236 info = (hal_gatt_client_app*)l->data;
240 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
241 DBG("gatt client app already registered");
246 DBG("adding the gatt client app");
249 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
250 if (gattc_app == NULL) {
251 DBG("Failed to allocate memory");
255 gattc_app->client_if = __hal_generate_client_id();
256 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
258 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
263 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
265 hal_gatt_client_app *gattc_app = NULL;
266 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 if (NULL == client_app_info) {
279 ERR("Failed to allocate memory");
280 return BT_STATUS_FAIL;
283 client_app_info->client_if = gattc_app->client_if;
284 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
285 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
287 DBG("registered client client_if [%d]", client_app_info->client_if);
289 return BT_STATUS_SUCCESS;
292 /** Registers a GATT client application with the stack */
293 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
298 return __hal_gattc_register_client_app(uuid);
301 bt_status_t __hal_gattc_unregister_client(int client_if)
304 hal_gatt_client_app *info = NULL;
306 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
308 /* remove the gatt client app */
309 for (l = hal_gattc_client_app_list; l != NULL; ) {
310 info = (hal_gatt_client_app*)l->data;
316 if (info->client_if == client_if) {
317 DBG("gatt client app found");
318 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
323 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
324 return BT_STATUS_SUCCESS;
327 /** Unregister a client application from the stack */
328 bt_status_t btif_gattc_unregister_client(int client_if)
333 return __hal_gattc_unregister_client(client_if);
336 /** Start or stop LE device scanning */
337 bt_status_t scan(int client_if, bool start)
344 ret = _bt_hal_adapter_le_start_scan();
346 ret = _bt_hal_adapter_le_stop_scan();
351 /** Create a connection to a remote LE or dual-mode device */
352 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
355 int ret = BT_STATUS_SUCCESS;
361 return BT_STATUS_PARM_INVALID;
363 ret = _bt_hold_current_advertising();
364 if (ret == BT_STATUS_SUCCESS) {
365 DBG("Current advertising is held");
366 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
367 pending_le_conn_info->client_if = client_if;
368 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
369 BT_HAL_ADDRESS_LENGTH_MAX);
370 pending_le_conn_info->auto_connect = is_direct;
372 pending_le_conn_timer_id =
373 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
375 return BT_STATUS_SUCCESS;
377 ERR("advertising is not stopped");
380 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
384 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
387 GError *g_error = NULL;
388 GVariant *reply = NULL;
389 hal_gattc_client_info_t *gatt_conn_info = user_data;
390 int result = BT_STATUS_SUCCESS;
391 struct hal_ev_gatt_client_connected ev;
395 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
396 g_object_unref(proxy);
398 ERR("Connect LE Dbus Call Error");
400 ERR("Error: %s\n", g_error->message);
401 g_clear_error(&g_error);
403 result = BT_STATUS_FAIL;
405 g_variant_unref(reply);
407 if (NULL == gatt_conn_info) {
408 ERR("server_data is NULL");
413 if (result == BT_STATUS_FAIL) {
414 memset(&ev, 0, sizeof(ev));
415 ev.conn_id = gatt_conn_info->conn_id;
417 ev.client_if = gatt_conn_info->client_if;
418 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
419 BT_HAL_ADDRESS_LENGTH_MAX);
422 ERR("gatt client callback not registered");
424 DBG("sending gatt client disconnected event");
425 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
431 g_free(gatt_conn_info);
436 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
439 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
441 GDBusProxy *device_proxy;
442 GDBusConnection *conn;
443 int ret = BT_STATUS_SUCCESS;
444 hal_gattc_client_info_t *gattc_data;
446 if (NULL == bd_addr) {
447 ERR("bd_addr is NULL");
448 return BT_STATUS_PARM_INVALID;
451 conn = _bt_hal_get_system_gconn();
453 ERR("_bt_gdbus_get_system_gconn returned NULL");
454 return BT_STATUS_FAIL;
457 _bt_hal_convert_addr_type_to_string(device_address,
458 (unsigned char *)bd_addr->address);
459 device_path = _bt_hal_get_device_object_path(device_address);
460 if (device_path == NULL) {
461 DBG("device_path NULL");
462 ret = BT_STATUS_FAIL;
466 ERR("device_path:%s", device_path);
468 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
469 NULL, BT_HAL_BLUEZ_NAME,
470 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
472 if (NULL == device_proxy) {
473 ERR("device_proxy returned NULL");
474 return BT_STATUS_FAIL;
477 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
478 if (NULL == gattc_data) {
479 ERR("Unable to allocate memory");
480 ret = BT_STATUS_FAIL;
484 memcpy(gattc_data->bd_addr.address, bd_addr->address,
485 BT_HAL_ADDRESS_LENGTH_MAX);
486 gattc_data->client_if = client_if;
487 gattc_data->conn_id = conn_id;
489 DBG("DisconnectLE [%s]", device_address);
491 g_dbus_proxy_call(device_proxy, "DisconnectLE",
493 G_DBUS_CALL_FLAGS_NONE,
494 BT_HAL_MAX_DBUS_TIMEOUT,
496 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
500 g_object_unref(device_proxy);
507 /** Disconnect a remote device or cancel a pending connection */
508 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
515 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
518 /** Clear the attribute cache for a given device */
519 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
522 return BT_STATUS_UNSUPPORTED;
525 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
530 hal_gattc_service_t *info = NULL;
532 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
533 info = (hal_gattc_service_t*)l->data;
537 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t))) {
538 INFO("Found GATT service uuid");
546 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
547 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)) {
561 INFO("Found GATT char uuid");
568 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
573 hal_gattc_desc_t *info = NULL;
575 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
576 info = (hal_gattc_desc_t*)l->data;
580 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t))) {
581 INFO("Found GATT descriptor uuid");
589 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
590 const char *uuid_str, char *object_path)
593 hal_gattc_service_t *gattc_service = NULL;
595 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
596 gattc_service->svc_path = g_strdup(object_path);
597 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
599 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
601 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
603 DBG("svc path {%s] svc uuid [%s]", object_path, uuid_str);
605 return gattc_service;
608 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
611 hal_gattc_char_t *gattc_char = NULL;
613 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
614 gattc_char->chr_path = g_strdup(char_handle);
616 DBG("svc path: [%s]", gatt_svc->svc_path);
617 DBG("char path: [%s]", gattc_char->chr_path);
619 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
622 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
623 const char* uuid_str, char *object_path, GPtrArray *gp_char_array)
625 hal_gattc_service_t* gatt_svc = NULL;
627 gchar *gp_char_path = NULL;
631 /* add the service */
632 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path);
633 if (gatt_svc == NULL) {
634 ERR("Failed to add service");
638 /* add the characteristic */
639 for (i = 0; i < gp_char_array->len; i++) {
640 gp_char_path = g_ptr_array_index(gp_char_array, i);
641 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
644 g_ptr_array_free(gp_char_array, TRUE);
647 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
649 hal_gattc_desc_t *gattc_desc = NULL;
651 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
652 gattc_desc->desc_path = g_strdup(desc_path);
654 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
656 DBG("char path: [%s]", gattc_char->chr_path);
657 DBG("desc path: [%s]", gattc_desc->desc_path);
660 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
661 GPtrArray *gp_desc_array, unsigned int char_permission)
663 gchar *gp_desc_path = NULL;
668 if (char_uuid_str == NULL) {
669 DBG("char_uuid_str is NULL");
673 //update the char uuid
674 DBG("char UUID: [%s] ", char_uuid_str);
675 DBG("char path: [%s]", gattc_char->chr_path);
677 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
679 //update char permission
680 gattc_char->permission = char_permission;
683 for (i = 0; i < gp_desc_array->len; i++) {
684 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
685 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
689 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
693 if (desc_uuid_str == NULL) {
694 DBG("char_uuid_str is NULL");
698 //update the descriptor uuid
699 DBG("desc UUID: [%s] ", desc_uuid_str);
700 DBG("desc path: [%s]", gattc_desc->desc_path);
702 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
705 static void browse_service_char(int conn_id)
707 hal_gattc_server_info_t *conn_info = NULL;
711 hal_gattc_service_t *svc_info = NULL;
712 hal_gattc_char_t *char_info = NULL;
713 hal_gattc_desc_t *desc_info = NULL;
717 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
718 if (conn_info == NULL) {
719 DBG("conn_info is NULL");
723 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
725 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
726 svc_info = (hal_gattc_service_t*)l->data;
727 if (svc_info == NULL)
730 DBG("svc path [%s]", svc_info->svc_path);
732 /* find characteristic object path */
733 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
734 char_info = (hal_gattc_char_t *)k->data;
735 if (char_info == NULL)
738 DBG("char path[%s]", char_info->chr_path);
741 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
742 desc_info = (hal_gattc_desc_t *)m->data;
743 if (desc_info == NULL)
746 DBG("desc path[%s]", desc_info->desc_path);
755 * Enumerate all GATT services on a connected device.
756 * Optionally, the results can be filtered for a given UUID.
758 static bt_status_t _gattc_client_search_service(int conn_id)
762 GVariant *result = NULL;
764 GVariantIter *svc_iter;
765 GVariantIter *interface_iter;
766 char *object_path = NULL;
767 char *interface_str = NULL;
768 const gchar *key = NULL;
769 GVariant *value = NULL;
770 GPtrArray *gp_array = NULL;
771 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
772 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
773 int ret = BT_STATUS_FAIL;
775 const gchar *uuid_str = NULL;
777 hal_gattc_server_info_t *conn_info = NULL;
778 gboolean is_primary = FALSE;
781 char *char_handle = NULL;
782 GVariantIter *char_iter = NULL;
783 GPtrArray *gp_char_array = NULL;
787 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
788 if (NULL == conn_info) {
789 DBG("Failed to get the conn_info");
790 return BT_STATUS_FAIL;
793 _bt_hal_convert_addr_type_to_string(device_address,
794 (unsigned char *)conn_info->bd_addr.address);
796 result = _bt_hal_get_managed_objects();
800 gp_array = g_ptr_array_new();
801 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
803 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
805 if (object_path == NULL)
808 _bt_hal_convert_device_path_to_address(object_path, temp_address);
810 if (g_strcmp0(temp_address, device_address) != 0)
813 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
814 &interface_str, &svc_iter)) {
815 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
818 DBG("[%d] Object Path : %s", idx++, object_path);
819 /* for characteristic */
820 gp_char_array = g_ptr_array_new();
821 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
822 if (g_strcmp0(key, "Primary") == 0) {
823 is_primary = g_variant_get_boolean(value);
826 g_ptr_array_add(gp_array, (gpointer)object_path);
829 } else if (g_strcmp0(key, "UUID") == 0) {
830 uuid_str = g_variant_get_string(value, &len);
831 DBG(" UUID: [%s]", uuid_str);
832 } else if (g_strcmp0(key, "Characteristics") == 0) {
833 g_variant_get(value, "ao", &char_iter);
834 if (char_iter != NULL) {
835 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
836 DBG("char handle : %s", char_handle);
837 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
844 DBG("send search service result event");
845 _bt_hal_send_search_service_result_event(conn_id, is_primary,
846 uuid_str, conn_info->inst_id);
848 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
853 if (gp_array->len == 0 || svc_count == 0) {
854 ERR("gp_array is NULL");
855 ret = BT_STATUS_FAIL;
857 ret = BT_STATUS_SUCCESS;
860 browse_service_char(conn_id);
861 /* send search service complete event */
862 _bt_hal_send_search_service_complete_event(conn_id, ret);
864 g_ptr_array_free(gp_array, TRUE);
865 g_variant_iter_free(iter);
866 g_variant_unref(result);
871 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
873 if (NULL == filter_uuid) {
874 DBG("Browse all the services");
875 return _gattc_client_search_service(conn_id);
877 DBG("TODO implement it");
878 return BT_STATUS_UNSUPPORTED;
882 * Enumerate included services for a given service.
883 * Set start_incl_srvc_id to NULL to get the first included service.
885 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
886 btgatt_srvc_id_t *start_incl_srvc_id)
889 return BT_STATUS_UNSUPPORTED;
892 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
893 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
895 struct hal_ev_gatt_client_char_search_result ev;
898 ERR("gatt client callback not registered");
902 DBG("sending gatt client search char result event conn_id[%d] status[%d]", conn_id, status);
904 memset(&ev, 0, sizeof(ev));
905 ev.conn_id = conn_id;
906 ev.inst_id = svc_id->id.inst_id;
907 ev.is_primary = svc_id->is_primary;
909 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
911 if (status == BT_STATUS_SUCCESS) {
912 DBG("building char uuid");
913 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
914 ev.char_prop = char_prop;
917 DBG("sending the char search event");
919 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
922 static int _hal_get_permission_flag(char *permission)
926 if (NULL == permission) {
927 ERR("gatt permission is NULL");
931 if (!g_strcmp0(permission, "broadcast"))
932 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
933 else if (!g_strcmp0(permission, "read"))
934 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
935 else if (!g_strcmp0(permission, "write-without-response"))
936 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
937 else if (!g_strcmp0(permission, "write"))
938 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
939 else if (!g_strcmp0(permission, "notify"))
940 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
941 else if (!g_strcmp0(permission, "indicate"))
942 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
943 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
944 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
945 else if (!g_strcmp0(permission, "reliable-write"))
946 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
947 else if (!g_strcmp0(permission, "writable-auxiliaries"))
948 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
949 else if (!g_strcmp0(permission, "encrypt-read"))
950 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
951 else if (!g_strcmp0(permission, "encrypt-write"))
952 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
953 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
954 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
955 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
956 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
962 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
964 GDBusProxy *properties_proxy = NULL;
965 GError *error = NULL;
966 GVariant *value = NULL;
967 GVariant *result = NULL;
968 GDBusConnection *g_conn;
970 char *char_desc_handle = NULL;
972 GVariantIter *property_iter;
973 GVariantIter *char_desc_iter;
974 char* char_handle = NULL;
975 gchar *char_uuid_str = NULL;
976 GPtrArray *gp_desc_array = NULL;
977 GVariantIter *char_perm_iter;
979 unsigned int char_permission = 0 ;
983 if (gattc_char->chr_path == NULL) {
984 DBG("char path is NULL");
985 return BT_STATUS_FAIL;
987 char_handle = gattc_char->chr_path;
989 DBG("char path:[%s]", gattc_char->chr_path);
991 g_conn = _bt_hal_get_system_gconn();
992 if (NULL == g_conn) {
993 ERR("_bt_gdbus_get_system_gconn returned NULL");
994 return BT_STATUS_FAIL;
997 properties_proxy = g_dbus_proxy_new_sync(g_conn,
998 G_DBUS_PROXY_FLAGS_NONE, NULL,
1001 BT_HAL_PROPERTIES_INTERFACE,
1004 if (properties_proxy == NULL) {
1005 ERR("properties_proxy returned NULL");
1006 return BT_STATUS_FAIL;
1009 result = g_dbus_proxy_call_sync(properties_proxy,
1011 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1012 G_DBUS_CALL_FLAGS_NONE,
1017 if (error != NULL) {
1018 ERR("Fail to get properties (Error: %s)", error->message);
1019 g_clear_error(&error);
1021 ERR("Fail to get properties");
1022 g_object_unref(properties_proxy);
1023 return BT_STATUS_FAIL;
1026 gp_desc_array = g_ptr_array_new();
1028 g_variant_get(result, "(a{sv})", &property_iter);
1030 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1031 if (!g_strcmp0(key, "UUID")) {
1032 char_uuid_str = g_variant_dup_string(value, &len);
1033 DBG("char UUID [%s]", char_uuid_str);
1034 } else if (!g_strcmp0(key, "Flags")) {
1035 g_variant_get(value, "as", &char_perm_iter);
1036 char_permission = 0x00;
1038 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1039 DBG("char permission: [%s]", permission);
1040 char_permission |= _hal_get_permission_flag(permission);
1042 } else if (!g_strcmp0(key, "Descriptors")) {
1043 g_variant_get(value, "ao", &char_desc_iter);
1044 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1045 DBG("char descriptor handle : %s", char_desc_handle);
1047 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1052 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1054 g_free(char_uuid_str);
1055 g_variant_iter_free(property_iter);
1056 g_variant_unref(result);
1057 g_object_unref(properties_proxy);
1058 g_ptr_array_free(gp_desc_array, TRUE);
1060 return BT_STATUS_SUCCESS;
1063 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1064 btgatt_srvc_id_t *srvc_id)
1066 hal_gattc_server_info_t * conn_info = NULL;
1067 hal_gattc_service_t *gattc_service = NULL;
1069 hal_gattc_char_t *gattc_char = NULL;
1070 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1071 int status = BT_STATUS_FAIL;
1074 DBG("conn_id[%d]", conn_id);
1076 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1077 if (NULL == conn_info) {
1078 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1079 return BT_STATUS_FAIL;
1083 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1084 if (NULL == gattc_service) {
1085 DBG("Failed to get the gatt service");
1086 return BT_STATUS_FAIL;
1089 DBG("service path [%s]", gattc_service->svc_path);
1091 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1092 DBG("service uuid [%s]", svc_uuid_str);
1094 /* find characteristic object path */
1095 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1096 gattc_char = (hal_gattc_char_t *)l->data;
1097 status = _hal_gattc_get_characteristic_info(gattc_char);
1100 if (BT_STATUS_SUCCESS == status) {
1101 DBG("Sending the success charateristics event");
1102 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1103 &gattc_char->chr_uuid, gattc_char->permission);
1107 DBG("sending final event");
1109 status = BT_STATUS_FAIL;
1110 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1112 browse_service_char(conn_id);
1113 /* retrive uuid for characteristic and object path for descriptor */
1115 return BT_STATUS_SUCCESS;
1119 * Enumerate characteristics for a given service.
1120 * Set start_char_id to NULL to get the first characteristic.
1122 bt_status_t btif_gattc_get_characteristic(int conn_id,
1123 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1126 CHECK_BTGATT_INIT();
1128 if (start_char_id == NULL) {
1129 DBG("Get all the characteristics");
1130 return _gattc_get_all_characteristic(conn_id, srvc_id);
1133 DBG("TBD Get specific characteristics");
1134 return BT_STATUS_UNSUPPORTED;
1138 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1140 GDBusProxy *properties_proxy = NULL;
1141 GError *error = NULL;
1142 GVariant *value = NULL;
1143 GVariant *result = NULL;
1144 GDBusConnection *g_conn;
1147 GVariantIter *property_iter;
1148 char* desc_handle = NULL;
1149 const gchar *desc_uuid_str = NULL;
1153 if (gattc_desc->desc_path == NULL) {
1154 DBG("desc path is NULL");
1155 return BT_STATUS_FAIL;
1157 desc_handle = gattc_desc->desc_path;
1159 DBG("desc path:[%s]", gattc_desc->desc_path);
1161 g_conn = _bt_hal_get_system_gconn();
1162 if (NULL == g_conn) {
1163 ERR("_bt_gdbus_get_system_gconn returned NULL");
1164 return BT_STATUS_FAIL;
1167 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1168 G_DBUS_PROXY_FLAGS_NONE, NULL,
1171 BT_HAL_PROPERTIES_INTERFACE,
1174 if (properties_proxy == NULL) {
1175 ERR("properties_proxy returned NULL");
1176 return BT_STATUS_FAIL;
1179 result = g_dbus_proxy_call_sync(properties_proxy,
1181 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1182 G_DBUS_CALL_FLAGS_NONE,
1187 if (error != NULL) {
1188 ERR("Fail to get properties (Error: %s)", error->message);
1189 g_clear_error(&error);
1191 ERR("Fail to get properties");
1192 g_object_unref(properties_proxy);
1193 return BT_STATUS_FAIL;
1196 g_variant_get(result, "(a{sv})", &property_iter);
1198 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1199 if (!g_strcmp0(key, "UUID")) {
1200 desc_uuid_str = g_variant_get_string(value, &len);
1201 DBG("desc UUID [%s]", desc_uuid_str);
1202 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1207 g_variant_iter_free(property_iter);
1208 g_variant_unref(result);
1209 g_object_unref(properties_proxy);
1211 return BT_STATUS_SUCCESS;
1214 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1215 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1217 struct hal_ev_gatt_client_desc_search_result ev;
1220 ERR("gatt client callback not registered");
1224 DBG("sending gatt client search desc result event conn_id[%d] status[%d]", conn_id, status);
1226 memset(&ev, 0, sizeof(ev));
1227 ev.conn_id = conn_id;
1228 ev.inst_id = svc_id->id.inst_id;
1229 ev.is_primary = svc_id->is_primary;
1232 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1233 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1235 if (status == BT_STATUS_SUCCESS) {
1236 DBG("building desc uuid");
1237 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1240 DBG("sending the desc search event");
1242 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1245 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1246 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1248 hal_gattc_server_info_t * conn_info = NULL;
1249 hal_gattc_service_t *gattc_service = NULL;
1252 hal_gattc_char_t *gattc_char = NULL;
1253 hal_gattc_desc_t *gattc_desc = NULL;
1254 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1255 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1256 int status = BT_STATUS_FAIL;
1260 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1261 if (NULL == conn_info) {
1262 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1263 return BT_STATUS_FAIL;
1267 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1268 if (NULL == gattc_service) {
1269 DBG("Failed to get the gatt service");
1270 return BT_STATUS_FAIL;
1273 DBG("service path [%s]", gattc_service->svc_path);
1274 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1275 DBG("service uuid [%s]", svc_uuid_str);
1277 /* find characteristics */
1278 /* a service can have two char with same uuid */
1279 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1280 gattc_char = (hal_gattc_char_t*)l->data;
1281 if (gattc_char == NULL)
1284 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1285 INFO("Found GATT char uuid");
1286 DBG("char path [%s]", gattc_char->chr_path);
1287 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1288 DBG("char uuid [%s]", char_uuid_str);
1290 /* get descriptor uuid */
1291 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1292 gattc_desc = (hal_gattc_desc_t *)m->data;
1293 if (gattc_desc == NULL)
1296 status = _hal_gattc_get_descriptor_info(gattc_desc);
1299 if (BT_STATUS_SUCCESS == status) {
1300 DBG("Sending the success descriptor event");
1301 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1302 char_id, &gattc_desc->desc_uuid);
1308 DBG("sending final event");
1310 status = BT_STATUS_FAIL;
1311 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1313 browse_service_char(conn_id);
1314 /* retrive uuid for characteristic and object path for descriptor */
1316 return BT_STATUS_SUCCESS;
1320 * Enumerate descriptors for a given characteristic.
1321 * Set start_descr_id to NULL to get the first descriptor.
1323 bt_status_t btif_gattc_get_descriptor(int conn_id,
1324 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1325 btgatt_gatt_id_t *start_descr_id)
1328 CHECK_BTGATT_INIT();
1330 if (start_descr_id == NULL) {
1331 DBG("Get all the descriptors");
1332 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1334 DBG("TBD Get specific descriptor");
1335 return BT_STATUS_UNSUPPORTED;
1339 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1341 struct hal_ev_gatt_client_read_data ev;
1344 ERR("gatt client callback not registered");
1348 DBG("sending gatt client charac read conn_id[%d] status[%d]", resp_data->conn_id, result);
1350 memset(&ev, 0, sizeof(ev));
1351 ev.conn_id = resp_data->conn_id;
1352 ev.inst_id = resp_data->srvc_id.id.inst_id;
1353 ev.is_primary = resp_data->srvc_id.is_primary;
1356 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1357 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1361 DBG("building the char read value [%d]", len);
1362 memcpy(ev.value, value, len);
1365 DBG("sending the gatt client read charac event");
1367 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1370 static void __hal_internal_read_char_cb(GObject *source_object,
1371 GAsyncResult *res, gpointer user_data)
1373 GError *error = NULL;
1374 GDBusConnection *system_gconn = NULL;
1377 GByteArray *gp_byte_array = NULL;
1379 hal_gatt_resp_data_t *resp_data = user_data;
1380 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 for (i = 0; i < gp_byte_array->len; i++)
1408 DBG("%02x", gp_byte_array->data[i]);
1411 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1415 g_byte_array_free(gp_byte_array, TRUE);
1416 g_variant_iter_free(iter);
1417 g_variant_unref(value);
1423 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1424 btgatt_gatt_id_t *char_id, int auth_req)
1426 GDBusConnection *g_conn;
1427 hal_gatt_resp_data_t *resp_data;
1428 hal_gattc_service_t *gattc_service = NULL;
1429 GVariantBuilder *builder = NULL;
1431 hal_gattc_server_info_t * conn_info = NULL;
1432 hal_gattc_char_t *gattc_char = NULL;
1433 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1434 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1435 char* char_handle = NULL;
1439 /* get the connection info */
1440 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1441 if (NULL == conn_info) {
1442 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1443 return BT_STATUS_FAIL;
1447 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1448 if (NULL == gattc_service) {
1449 DBG("Failed to get the gatt service");
1450 return BT_STATUS_FAIL;
1453 DBG("service path [%s]", gattc_service->svc_path);
1454 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1455 DBG("service uuid [%s]", svc_uuid_str);
1458 /* find characteristic */
1459 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1460 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1461 if (NULL == gattc_char) {
1462 DBG("Failed to get the gatt char");
1463 return BT_STATUS_FAIL;
1466 DBG("char path [%s]", gattc_char->chr_path);
1467 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1468 DBG("char uuid [%s]", char_uuid_str);
1470 g_conn = _bt_hal_get_system_gconn();
1471 if (NULL == g_conn) {
1472 ERR("_bt_gdbus_get_system_gconn returned NULL");
1473 return BT_STATUS_FAIL;
1476 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1477 if (NULL == resp_data) {
1478 ERR("failed to get the memory");
1479 return BT_STATUS_FAIL;
1482 resp_data->conn_id = conn_id;
1483 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1484 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1486 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1489 g_variant_builder_add(builder, "{sv}", "offset",
1490 g_variant_new("q", offset));
1492 char_handle = gattc_char->chr_path;
1494 DBG("calling char read value");
1496 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1497 "ReadValue", g_variant_new("(a{sv})", builder),
1498 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1499 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1500 (gpointer)resp_data);
1501 g_variant_builder_unref(builder);
1503 return BT_STATUS_SUCCESS;
1506 /** Read a characteristic on a remote device */
1507 bt_status_t btif_read_characteristic(int conn_id,
1508 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1511 CHECK_BTGATT_INIT();
1514 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1517 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1519 struct hal_ev_gatt_client_write_result ev;
1522 ERR("gatt client callback not registered");
1526 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
1528 memset(&ev, 0, sizeof(ev));
1529 ev.conn_id = resp_data->conn_id;
1530 ev.inst_id = resp_data->srvc_id.id.inst_id;
1531 ev.is_primary = resp_data->srvc_id.is_primary;
1534 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1535 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1537 DBG("sending the gatt client write charac event");
1539 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1542 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1543 GAsyncResult *res, gpointer user_data)
1545 GError *error = NULL;
1546 GDBusConnection *system_gconn = NULL;
1548 hal_gatt_resp_data_t *resp_data = user_data;
1549 int result = BT_STATUS_SUCCESS;
1553 system_gconn = _bt_hal_get_system_gconn();
1554 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1557 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1559 result = BT_STATUS_FAIL;
1561 __hal_send_char_write_event(resp_data, result);
1562 g_clear_error(&error);
1567 //send write value event
1568 __hal_send_char_write_event(resp_data, result);
1571 g_variant_unref(value);
1576 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1579 case HAL_GATT_WRITE_TYPE_WRITE:
1580 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1582 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1583 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1586 ERR("Unknow write type : %d", type);
1587 return BT_STATUS_FAIL;
1590 return BT_STATUS_SUCCESS;
1594 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1596 GDBusConnection *conn;
1597 GVariantBuilder *builder = NULL;
1603 GUnixFDList *fd_list = NULL;
1605 conn = _bt_hal_get_system_gconn();
1607 ERR("_bt_gdbus_get_system_gconn returned NULL");
1608 return BT_STATUS_FAIL;
1611 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1612 //val = g_variant_new("ay", builder1);
1614 g_variant_builder_add(builder, "{sv}", "offset",
1615 g_variant_new("q", offset));
1617 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1618 "AcquireWrite", g_variant_new("(a{sv})", builder),
1619 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1620 NULL, &fd_list, NULL, &err);
1622 g_dbus_error_strip_remote_error(err);
1623 ERR("Error: %s", err->message);
1625 g_variant_builder_unref(builder);
1626 return BT_STATUS_FAIL;
1629 g_variant_get(value, "(hq)", &idx, &att_mtu);
1630 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1632 INFO("FD is %d index is %d mtu is %d", *fd, idx, att_mtu);
1635 g_object_unref(fd_list);
1636 g_variant_unref(value);
1637 g_variant_builder_unref(builder);
1639 return BT_STATUS_SUCCESS;
1642 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1644 GDBusConnection *conn;
1645 GVariantBuilder *builder = NULL;
1649 gint32 idx, notify_fd;
1651 GUnixFDList *fd_list = NULL;
1653 conn = _bt_hal_get_system_gconn();
1656 ERR("_bt_gdbus_get_system_gconn returned NULL");
1657 return BT_STATUS_FAIL;
1661 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1664 g_variant_builder_add(builder, "{sv}", "offset",
1665 g_variant_new("q", offset));
1667 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1668 "AcquireNotify", g_variant_new("(a{sv})", builder),
1669 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1670 NULL, &fd_list, NULL, &err);
1672 g_dbus_error_strip_remote_error(err);
1673 ERR("Error: %s", err->message);
1675 g_variant_builder_unref(builder);
1676 return BT_STATUS_FAIL;
1679 g_variant_get(value, "(hq)", &idx, &att_mtu);
1680 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1683 INFO("Acquired characteristic Notify fd %d, mtu %d", notify_fd, *mtu);
1687 g_object_unref(fd_list);
1688 g_variant_unref(value);
1689 g_variant_builder_unref(builder);
1691 return BT_STATUS_SUCCESS;
1695 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1696 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1698 GVariant *val, *options;
1699 GVariantBuilder *builder1;
1700 GVariantBuilder *builder2;
1701 GDBusConnection *g_conn;
1704 hal_gatt_resp_data_t *resp_data;
1705 hal_gattc_service_t *gattc_service = NULL;
1706 hal_gattc_server_info_t * conn_info = NULL;
1707 hal_gattc_char_t *gattc_char = NULL;
1708 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1709 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1710 char* char_handle = NULL;
1711 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1712 int ret = BT_STATUS_SUCCESS;
1716 ret = __hal_get_write_prop(write_type, &write_prop);
1717 if (BT_STATUS_FAIL == ret) {
1718 DBG("received invalid write type:[%d] ", write_type);
1719 return BT_STATUS_FAIL;
1722 /* get the connection info */
1723 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1724 if (NULL == conn_info) {
1725 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1726 return BT_STATUS_FAIL;
1730 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1731 if (NULL == gattc_service) {
1732 DBG("Failed to get the gatt service");
1733 return BT_STATUS_FAIL;
1736 DBG("service path [%s]", gattc_service->svc_path);
1737 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1738 DBG("service uuid [%s]", svc_uuid_str);
1740 /* find characteristic */
1741 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1742 if (NULL == gattc_char) {
1743 DBG("Failed to get the gatt char");
1744 return BT_STATUS_FAIL;
1747 DBG("char path [%s]", gattc_char->chr_path);
1748 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1749 DBG("char uuid [%s]", char_uuid_str);
1751 g_conn = _bt_hal_get_system_gconn();
1752 if (NULL == g_conn) {
1753 ERR("_bt_gdbus_get_system_gconn returned NULL");
1754 return BT_STATUS_FAIL;
1757 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1758 if (NULL == resp_data) {
1759 ERR("failed to get the memory");
1760 return BT_STATUS_FAIL;
1763 resp_data->conn_id = conn_id;
1764 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1765 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1767 char_handle = gattc_char->chr_path;
1769 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1771 for (i = 0; i < length; i++)
1772 g_variant_builder_add(builder1, "y", value[i]);
1774 val = g_variant_new("ay", builder1);
1776 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1778 g_variant_builder_add(builder2, "{sv}", "offset",
1779 g_variant_new_uint16(offset));
1781 options = g_variant_new("a{sv}", builder2);
1783 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1785 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1787 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1788 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1789 (gpointer)resp_data);
1791 g_variant_builder_unref(builder1);
1792 g_variant_builder_unref(builder2);
1794 return BT_STATUS_SUCCESS;
1797 bt_status_t btif_get_acquire_write_fd(int conn_id,
1798 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1799 int auth_req, int *fd, int*mtu)
1801 CHECK_BTGATT_INIT();
1805 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1808 hal_gattc_service_t *gattc_service = NULL;
1809 hal_gattc_server_info_t * conn_info = NULL;
1810 hal_gattc_char_t *gattc_char = NULL;
1811 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1813 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1814 int ret = BT_STATUS_SUCCESS;
1818 /* get the connection info */
1819 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1820 if (NULL == conn_info) {
1821 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1822 return BT_STATUS_FAIL;
1826 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1827 if (NULL == gattc_service) {
1828 DBG("Failed to get the gatt service");
1829 return BT_STATUS_FAIL;
1832 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1833 if (NULL == gattc_char) {
1834 DBG("Failed to get the gatt char");
1835 return BT_STATUS_FAIL;
1838 DBG("char path [%s]", gattc_char->chr_path);
1839 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1840 DBG("char uuid [%s]", char_uuid_str);
1843 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1844 if (ret != BT_STATUS_SUCCESS)
1848 ERR("Characterstics FD erite characterstics fd is %d", *fd);
1853 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1854 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1856 CHECK_BTGATT_INIT();
1860 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1863 hal_gattc_service_t *gattc_service = NULL;
1864 hal_gattc_server_info_t * conn_info = NULL;
1865 hal_gattc_char_t *gattc_char = NULL;
1866 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1868 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1869 int ret = BT_STATUS_SUCCESS;
1873 /* get the connection info */
1874 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1875 if (NULL == conn_info) {
1876 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1877 return BT_STATUS_FAIL;
1881 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1882 if (NULL == gattc_service) {
1883 DBG("Failed to get the gatt service");
1884 return BT_STATUS_FAIL;
1887 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1888 if (NULL == gattc_char) {
1889 DBG("Failed to get the gatt char");
1890 return BT_STATUS_FAIL;
1893 DBG("char path [%s]", gattc_char->chr_path);
1894 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1895 DBG("char uuid [%s]", char_uuid_str);
1898 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1899 if (ret != BT_STATUS_SUCCESS)
1903 ERR("Characterstics FD write characterstics fd is %d", *fd);
1910 /** Write a remote characteristic */
1911 bt_status_t btif_write_characteristic(int conn_id,
1912 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1913 int write_type, int len, int auth_req,
1916 CHECK_BTGATT_INIT();
1920 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1921 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1922 len, auth_req, p_value);
1925 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1927 struct hal_ev_gatt_client_read_data ev;
1930 ERR("gatt client callback not registered");
1934 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1936 memset(&ev, 0, sizeof(ev));
1937 ev.conn_id = resp_data->conn_id;
1938 ev.inst_id = resp_data->srvc_id.id.inst_id;
1939 ev.is_primary = resp_data->srvc_id.is_primary;
1942 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1943 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1944 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1948 DBG("building the desc read value [%d]", len);
1949 memcpy(ev.value, value, len);
1952 DBG("sending the gatt client read descriptor event");
1954 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1957 static void __hal_internal_read_desc_cb(GObject *source_object,
1958 GAsyncResult *res, gpointer user_data)
1960 GError *error = NULL;
1961 GDBusConnection *system_gconn = NULL;
1964 GByteArray *gp_byte_array = NULL;
1966 hal_gatt_resp_data_t *resp_data = user_data;
1967 int result = BT_STATUS_SUCCESS;
1972 system_gconn = _bt_hal_get_system_gconn();
1973 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1976 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1979 result = BT_STATUS_FAIL;
1980 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1981 g_clear_error(&error);
1986 gp_byte_array = g_byte_array_new();
1987 g_variant_get(value, "(ay)", &iter);
1989 while (g_variant_iter_loop(iter, "y", &g_byte))
1990 g_byte_array_append(gp_byte_array, &g_byte, 1);
1994 for (i = 0; i < gp_byte_array->len; i++)
1995 DBG("%02x", gp_byte_array->data[i]);
1998 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2002 g_byte_array_free(gp_byte_array, TRUE);
2003 g_variant_iter_free(iter);
2004 g_variant_unref(value);
2009 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2010 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2012 GDBusConnection *g_conn;
2013 hal_gatt_resp_data_t *resp_data;
2014 hal_gattc_service_t *gattc_service = NULL;
2015 GVariantBuilder *builder = NULL;
2017 hal_gattc_server_info_t * conn_info = NULL;
2018 hal_gattc_char_t *gattc_char = NULL;
2019 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2020 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2021 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2022 char* desc_handle = NULL;
2025 hal_gattc_desc_t *gattc_desc = NULL;
2029 /* get the connection info */
2030 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2031 if (NULL == conn_info) {
2032 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
2033 return BT_STATUS_FAIL;
2037 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2038 if (NULL == gattc_service) {
2039 DBG("Failed to get the gatt service");
2040 return BT_STATUS_FAIL;
2043 DBG("service path [%s]", gattc_service->svc_path);
2044 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2045 DBG("service uuid [%s]", svc_uuid_str);
2047 /* find characteristic */
2048 /* service can have two char with same uuid */
2049 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2050 gattc_char = (hal_gattc_char_t*)l->data;
2051 if (gattc_char == NULL)
2054 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2055 INFO("Found GATT char uuid");
2056 DBG("char path [%s]", gattc_char->chr_path);
2057 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2058 DBG("char uuid [%s]", char_uuid_str);
2060 /* find descriptor */
2061 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2063 DBG("desc path [%s]", gattc_desc->desc_path);
2064 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2065 DBG("desc uuid [%s]", desc_uuid_str);
2071 if (NULL == gattc_desc) {
2072 DBG("Failed to get the gatt desc");
2073 return BT_STATUS_FAIL;
2076 g_conn = _bt_hal_get_system_gconn();
2077 if (NULL == g_conn) {
2078 ERR("_bt_gdbus_get_system_gconn returned NULL");
2079 return BT_STATUS_FAIL;
2082 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2083 if (NULL == resp_data) {
2084 ERR("failed to get the memory");
2085 return BT_STATUS_FAIL;
2088 resp_data->conn_id = conn_id;
2089 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2090 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2091 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2093 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2096 g_variant_builder_add(builder, "{sv}", "offset",
2097 g_variant_new("q", offset));
2099 desc_handle = gattc_desc->desc_path;
2101 DBG("calling desc read value");
2103 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2104 "ReadValue", g_variant_new("(a{sv})", builder),
2105 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2106 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2107 (gpointer)resp_data);
2108 g_variant_builder_unref(builder);
2110 return BT_STATUS_SUCCESS;
2113 /** Read the descriptor for a given characteristic */
2114 bt_status_t btif_read_descriptor(int conn_id,
2115 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2116 btgatt_gatt_id_t *descr_id, int auth_req)
2118 CHECK_BTGATT_INIT();
2120 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2123 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2125 struct hal_ev_gatt_client_write_result ev;
2128 ERR("gatt client callback not registered");
2132 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
2134 memset(&ev, 0, sizeof(ev));
2135 ev.conn_id = resp_data->conn_id;
2136 ev.inst_id = resp_data->srvc_id.id.inst_id;
2137 ev.is_primary = resp_data->srvc_id.is_primary;
2140 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2141 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2142 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2144 DBG("sending the gatt client write charac event");
2146 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2149 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2150 GAsyncResult *res, gpointer user_data)
2152 GError *error = NULL;
2153 GDBusConnection *system_gconn = NULL;
2155 hal_gatt_resp_data_t *resp_data = user_data;
2156 int result = BT_STATUS_SUCCESS;
2160 system_gconn = _bt_hal_get_system_gconn();
2161 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2164 ERR("write descriptor dbus failed Error: [%s]", error->message);
2167 result = BT_STATUS_FAIL;
2168 __hal_send_desc_write_event(resp_data, result);
2169 g_clear_error(&error);
2174 //send write value event
2175 __hal_send_desc_write_event(resp_data, result);
2178 g_variant_unref(value);
2183 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2184 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2185 int write_type, int length, int auth_req, char* value)
2187 GVariant *val, *options;
2188 GVariantBuilder *builder1;
2189 GVariantBuilder *builder2;
2190 GDBusConnection *g_conn;
2193 hal_gatt_resp_data_t *resp_data;
2194 hal_gattc_service_t *gattc_service = NULL;
2195 hal_gattc_server_info_t * conn_info = NULL;
2196 hal_gattc_char_t *gattc_char = NULL;
2197 hal_gattc_desc_t *gattc_desc = NULL;
2198 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2199 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2200 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2201 char* desc_handle = NULL;
2202 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2203 int ret = BT_STATUS_SUCCESS;
2208 ret = __hal_get_write_prop(write_type, &write_prop);
2209 if (BT_STATUS_FAIL == ret) {
2210 DBG("received invalid write type:[%d] ", write_type);
2211 return BT_STATUS_FAIL;
2214 /* get the connection info */
2215 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2216 if (NULL == conn_info) {
2217 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
2218 return BT_STATUS_FAIL;
2222 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2223 if (NULL == gattc_service) {
2224 DBG("Failed to get the gatt service");
2225 return BT_STATUS_FAIL;
2228 DBG("service path [%s]", gattc_service->svc_path);
2229 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2230 DBG("service uuid [%s]", svc_uuid_str);
2232 /* find characteristic */
2233 /* service can have two char with same uuid */
2234 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2235 gattc_char = (hal_gattc_char_t*)l->data;
2236 if (gattc_char == NULL)
2239 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2240 INFO("Found GATT char uuid");
2241 DBG("char path [%s]", gattc_char->chr_path);
2242 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2243 DBG("char uuid [%s]", char_uuid_str);
2245 /* find descriptor */
2246 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2248 DBG("desc path [%s]", gattc_desc->desc_path);
2249 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2250 DBG("desc uuid [%s]", desc_uuid_str);
2256 if (NULL == gattc_desc) {
2257 DBG("Failed to get the gatt desc");
2258 return BT_STATUS_FAIL;
2261 g_conn = _bt_hal_get_system_gconn();
2262 if (NULL == g_conn) {
2263 ERR("_bt_gdbus_get_system_gconn returned NULL");
2264 return BT_STATUS_FAIL;
2267 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2268 if (NULL == resp_data) {
2269 ERR("failed to get the memory");
2270 return BT_STATUS_FAIL;
2273 resp_data->conn_id = conn_id;
2274 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2275 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2276 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2278 desc_handle = gattc_desc->desc_path;
2280 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2282 for (i = 0; i < length; i++)
2283 g_variant_builder_add(builder1, "y", value[i]);
2285 val = g_variant_new("ay", builder1);
2287 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2289 g_variant_builder_add(builder2, "{sv}", "offset",
2290 g_variant_new_uint16(offset));
2292 options = g_variant_new("a{sv}", builder2);
2294 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2296 g_variant_new("(@ay@a{sv})", val, options),
2298 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2299 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2300 (gpointer)resp_data);
2302 g_variant_builder_unref(builder1);
2303 g_variant_builder_unref(builder2);
2305 return BT_STATUS_SUCCESS;
2308 /** Write a remote descriptor for a given characteristic */
2309 bt_status_t btif_write_descriptor(int conn_id,
2310 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2311 btgatt_gatt_id_t *descr_id, int write_type, int len,
2312 int auth_req, char* p_value)
2314 CHECK_BTGATT_INIT();
2316 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2317 len, auth_req, p_value);
2320 /** Execute a prepared write operation */
2321 bt_status_t execute_write(int conn_id, int execute)
2323 CHECK_BTGATT_INIT();
2324 return BT_STATUS_UNSUPPORTED;
2327 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2329 struct hal_ev_gatt_client_watch_notification ev;
2330 hal_gatt_resp_data_t *resp_data = user_data;
2332 DBG("sending the watch register notification event");
2333 /* send the event */
2334 memset(&ev, 0, sizeof(ev));
2335 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2337 ev.status = resp_data->result;
2339 ev.is_primary = resp_data->srvc_id.is_primary;
2340 ev.inst_id = resp_data->srvc_id.id.inst_id;
2342 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2343 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2346 ERR("GATT Callback not registered");
2348 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2355 static bt_status_t _hal_register_for_notification(int client_if,
2356 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2357 btgatt_gatt_id_t *char_id)
2359 int result = BT_STATUS_SUCCESS;
2360 GError *error = NULL;
2361 GDBusConnection *g_conn;
2362 hal_gattc_client_info_t *gattc_client = NULL;
2363 hal_gattc_server_info_t * conn_info = NULL;
2364 hal_gattc_service_t *gattc_service = NULL;
2365 hal_gattc_char_t *gattc_char = NULL;
2366 char* char_handle = NULL;
2367 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2368 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2369 hal_gatt_resp_data_t *resp_data;
2373 gattc_client = __bt_find_gatt_client_info(bd_addr);
2374 if (gattc_client == NULL) {
2375 ERR("failed to get the gatt client info");
2376 return BT_STATUS_FAIL;
2379 if (gattc_client->client_if != client_if) {
2380 ERR("could not find the gatt client for client id[%d]", client_if);
2381 return BT_STATUS_FAIL;
2384 /* get the connection info */
2385 conn_info = __bt_find_gatt_conn_info(bd_addr);
2386 if (NULL == conn_info) {
2387 ERR("Failed to get the conn_info");
2388 return BT_STATUS_FAIL;
2391 if (conn_info->inst_id != gattc_client->inst_id) {
2392 ERR("could not fild the conn_info");
2393 return BT_STATUS_FAIL;
2397 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2398 if (NULL == gattc_service) {
2399 DBG("Failed to get the gatt service");
2400 return BT_STATUS_FAIL;
2403 DBG("service path [%s]", gattc_service->svc_path);
2404 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2405 DBG("service uuid [%s]", svc_uuid_str);
2408 /* find characteristic */
2409 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
2410 HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY);
2411 if (NULL == gattc_char) {
2412 DBG("Failed to get the gatt char");
2413 return BT_STATUS_FAIL;
2416 DBG("char path [%s]", gattc_char->chr_path);
2417 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2418 DBG("char uuid [%s]", char_uuid_str);
2420 char_handle = gattc_char->chr_path;
2422 g_conn = _bt_hal_get_system_gconn();
2423 if (g_conn == NULL) {
2425 return BT_STATUS_FAIL;
2428 resp_data = malloc(sizeof(hal_gatt_resp_data_t));
2429 if (NULL == resp_data) {
2430 ERR("failed to get the memory");
2431 return BT_STATUS_FAIL;
2434 DBG("#StartNotify");
2435 g_dbus_connection_call_sync(g_conn,
2438 BT_HAL_GATT_CHAR_INTERFACE,
2442 G_DBUS_CALL_FLAGS_NONE,
2443 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2446 g_dbus_error_strip_remote_error(error);
2447 ERR("### Watch Failed: %s", error->message);
2448 if (g_strrstr(error->message, "Already notifying"))
2449 result = BT_STATUS_SUCCESS;
2450 else if (g_strrstr(error->message, "In Progress"))
2451 result = BT_STATUS_BUSY;
2452 else if (g_strrstr(error->message, "Operation is not supported"))
2453 result = BT_STATUS_UNSUPPORTED;
2454 /*failed because of either Insufficient Authorization or Write Not Permitted */
2455 else if (g_strrstr(error->message, "Write not permitted") ||
2456 g_strrstr(error->message, "Operation Not Authorized"))
2457 result = BT_STATUS_AUTH_FAILURE;
2458 /* failed because of either Insufficient Authentication,
2459 Insufficient Encryption Key Size, or Insufficient Encryption. */
2460 else if (g_strrstr(error->message, "Not paired"))
2461 result = BT_STATUS_NOT_READY;
2463 result = BT_STATUS_FAIL;
2465 g_clear_error(&error);
2468 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2469 resp_data->result = result;
2470 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2471 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2473 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2477 return BT_STATUS_SUCCESS;
2481 * Register to receive notifications or indications for a given
2484 bt_status_t btif_register_for_notification(int client_if,
2485 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2486 btgatt_gatt_id_t *char_id)
2488 CHECK_BTGATT_INIT();
2490 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2493 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2495 struct hal_ev_gatt_client_watch_notification ev;
2496 hal_gatt_resp_data_t *resp_data = user_data;
2498 DBG("sending the watch deregister notification event");
2499 /* send the event */
2500 memset(&ev, 0, sizeof(ev));
2501 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2503 ev.status = resp_data->result;
2505 ev.is_primary = resp_data->srvc_id.is_primary;
2506 ev.inst_id = resp_data->srvc_id.id.inst_id;
2508 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2509 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2512 ERR("GATT Callback not registered");
2514 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2521 static bt_status_t _hal_deregister_for_notification(int client_if,
2522 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2523 btgatt_gatt_id_t *char_id)
2525 int result = BT_STATUS_SUCCESS;
2526 GError *error = NULL;
2527 GDBusConnection *g_conn;
2528 hal_gattc_client_info_t *gattc_client = NULL;
2529 hal_gattc_server_info_t * conn_info = NULL;
2530 hal_gattc_service_t *gattc_service = NULL;
2531 hal_gattc_char_t *gattc_char = NULL;
2532 char* char_handle = NULL;
2533 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2534 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2535 hal_gatt_resp_data_t *resp_data;
2539 gattc_client = __bt_find_gatt_client_info(bd_addr);
2540 if (gattc_client == NULL) {
2541 ERR("failed to get the gatt client info");
2542 return BT_STATUS_FAIL;
2545 if (gattc_client->client_if != client_if) {
2546 ERR("could not find the gatt client for client id[%d]", client_if);
2547 return BT_STATUS_FAIL;
2550 /* get the connection info */
2551 conn_info = __bt_find_gatt_conn_info(bd_addr);
2552 if (NULL == conn_info) {
2553 ERR("Failed to get the conn_info");
2554 return BT_STATUS_FAIL;
2557 if (conn_info->inst_id != gattc_client->inst_id) {
2558 ERR("could not fild the conn_info");
2559 return BT_STATUS_FAIL;
2563 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2564 if (NULL == gattc_service) {
2565 DBG("Failed to get the gatt service");
2566 return BT_STATUS_FAIL;
2569 DBG("service path [%s]", gattc_service->svc_path);
2570 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2571 DBG("service uuid [%s]", svc_uuid_str);
2574 /* find characteristic */
2575 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
2576 HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY);
2577 if (NULL == gattc_char) {
2578 DBG("Failed to get the gatt char");
2579 return BT_STATUS_FAIL;
2582 DBG("char path [%s]", gattc_char->chr_path);
2583 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2584 DBG("char uuid [%s]", char_uuid_str);
2586 char_handle = gattc_char->chr_path;
2588 g_conn = _bt_hal_get_system_gconn();
2589 if (g_conn == NULL) {
2591 return BT_STATUS_FAIL;
2594 resp_data = malloc(sizeof(hal_gatt_resp_data_t));
2595 if (NULL == resp_data) {
2596 ERR("failed to get the memory");
2597 return BT_STATUS_FAIL;
2600 DBG("#StartNotify");
2601 g_dbus_connection_call_sync(g_conn,
2604 BT_HAL_GATT_CHAR_INTERFACE,
2608 G_DBUS_CALL_FLAGS_NONE,
2609 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2612 ERR("### Watch Failed: %s", error->message);
2613 g_clear_error(&error);
2614 result = BT_STATUS_FAIL;
2617 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2618 resp_data->result = result;
2619 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2620 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2622 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2626 return BT_STATUS_SUCCESS;
2628 /** Deregister a previous request for notifications/indications */
2629 bt_status_t btif_deregister_for_notification(int client_if,
2630 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2631 btgatt_gatt_id_t *char_id)
2633 CHECK_BTGATT_INIT();
2634 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2637 /** Request RSSI for a given remote device */
2638 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2640 CHECK_BTGATT_INIT();
2641 return BT_STATUS_UNSUPPORTED;
2644 /** OTA firmware download */
2645 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2647 CHECK_BTGATT_INIT();
2648 return BT_STATUS_UNSUPPORTED;
2651 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2652 int get_device_type(const bt_bdaddr_t *bd_addr)
2654 CHECK_BTGATT_INIT();
2655 return BT_STATUS_UNSUPPORTED;
2658 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2659 int min_int, int max_int, int latency, int timeout)
2661 gchar *device_path = NULL;
2662 GError *error = NULL;
2663 GDBusProxy *device_proxy = NULL;
2664 GDBusConnection *conn;
2666 int ret = BT_STATUS_SUCCESS;
2667 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2669 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2670 min_int, max_int, latency, timeout);
2672 conn = _bt_hal_get_system_gconn();
2675 return BT_STATUS_FAIL;
2678 _bt_hal_convert_addr_type_to_string(device_address,
2679 (unsigned char *)bd_addr->address);
2680 device_path = _bt_hal_get_device_object_path(device_address);
2682 if (device_path == NULL) {
2683 ERR("device_path NULL : [%s]", device_address);
2684 return BT_STATUS_FAIL;
2687 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2688 NULL, BT_HAL_BLUEZ_NAME,
2689 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2691 g_free(device_path);
2692 if (NULL == device_proxy) {
2693 ERR("device_proxy returned NULL");
2694 return BT_STATUS_FAIL;
2697 INFO("### LeConnUpdate");
2698 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2699 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2700 G_DBUS_CALL_FLAGS_NONE,
2705 g_object_unref(device_proxy);
2706 if (reply == NULL) {
2708 ERR("Error %s[%s]", error->message, device_address);
2709 if (g_strrstr(error->message, "In Progress"))
2710 ret = BT_STATUS_SUCCESS;
2712 ret = BT_STATUS_FAIL;
2713 g_error_free(error);
2717 g_variant_unref(reply);
2719 INFO("LE Connection parameter Updated");
2723 /** Request a connection parameter update */
2724 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2726 CHECK_BTGATT_INIT();
2730 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2733 /** Test mode interface */
2734 bt_status_t test_command(int command, btgatt_test_params_t* params)
2736 CHECK_BTGATT_INIT();
2737 return BT_STATUS_UNSUPPORTED;
2740 /** MTU Exchange request from client */
2741 bt_status_t configure_mtu(int conn_id, int mtu)
2743 CHECK_BTGATT_INIT();
2744 return BT_STATUS_UNSUPPORTED;
2747 /** Setup scan filter params */
2748 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2749 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2750 int rssi_low_thres, int dely_mode, int found_timeout,
2751 int lost_timeout, int found_timeout_cnt)
2753 CHECK_BTGATT_INIT();
2754 return BT_STATUS_UNSUPPORTED;
2757 /** Configure a scan filter condition */
2758 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2759 int filt_index, int company_id,
2760 int company_id_mask, const bt_uuid_t *p_uuid,
2761 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2762 char addr_type, int data_len, char* p_data, int mask_len,
2765 CHECK_BTGATT_INIT();
2766 return BT_STATUS_UNSUPPORTED;
2769 /** Clear all scan filter conditions for specific filter index*/
2770 bt_status_t scan_filter_clear(int client_if, int filt_index)
2772 CHECK_BTGATT_INIT();
2773 return BT_STATUS_UNSUPPORTED;
2776 /** Enable / disable scan filter feature*/
2777 bt_status_t scan_filter_enable(int client_if, bool enable)
2779 CHECK_BTGATT_INIT();
2780 return BT_STATUS_UNSUPPORTED;
2783 /** Sets the LE scan interval and window in units of N*0.625 msec */
2785 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
2789 CHECK_BTGATT_INIT();
2791 le_scan_type = scan_type;
2792 ret = _bt_hal_adapter_le_set_scan_parameters(
2793 scan_type, scan_interval, scan_window);
2797 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
2799 CHECK_BTGATT_INIT();
2800 return BT_STATUS_UNSUPPORTED;
2804 /* Configure the batchscan storage */
2805 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
2806 int batch_scan_trunc_max, int batch_scan_notify_threshold)
2808 CHECK_BTGATT_INIT();
2809 return BT_STATUS_UNSUPPORTED;
2812 /* Enable batchscan */
2813 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
2814 int scan_interval, int scan_window, int addr_type, int discard_rule)
2816 CHECK_BTGATT_INIT();
2817 return BT_STATUS_UNSUPPORTED;
2820 /* Disable batchscan */
2821 bt_status_t batchscan_dis_batch_scan(int client_if)
2823 CHECK_BTGATT_INIT();
2824 return BT_STATUS_UNSUPPORTED;
2827 /* Read out batchscan reports */
2828 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
2830 CHECK_BTGATT_INIT();
2831 return BT_STATUS_UNSUPPORTED;
2834 const btgatt_client_interface_t btgatt_client_interface = {
2835 btif_gattc_register_client,
2836 btif_gattc_unregister_client,
2838 btif_gattc_client_connect,
2839 btif_gattc_client_disconnect,
2841 btif_gattc_client_search_service,
2842 get_included_service,
2843 btif_gattc_get_characteristic,
2844 btif_gattc_get_descriptor,
2845 btif_read_characteristic,
2846 btif_write_characteristic,
2847 btif_get_acquire_write_fd,
2848 btif_get_acquire_notify_fd,
2849 btif_read_descriptor,
2850 btif_write_descriptor,
2852 btif_register_for_notification,
2853 btif_deregister_for_notification,
2857 btif_gattc_conn_parameter_update,
2860 scan_filter_param_setup,
2861 scan_filter_add_remove,
2864 set_scan_parameters,
2865 batchscan_cfg_storage,
2866 batchscan_enb_batch_scan,
2867 batchscan_dis_batch_scan,
2868 batchscan_read_reports
2871 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr)
2876 hal_gattc_server_info_t *info = NULL;
2878 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
2879 info = (hal_gattc_server_info_t*)l->data;
2883 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
2884 INFO("GATT connection found addr");
2891 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
2896 hal_gattc_client_info_t *info = NULL;
2898 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
2899 info = (hal_gattc_client_info_t*)l->data;
2903 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
2904 INFO("GATT client info found addr");
2911 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
2916 hal_gattc_client_info_t *info = NULL;
2918 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
2919 info = (hal_gattc_client_info_t*)l->data;
2923 if (info->conn_id == conn_id) {
2924 INFO("GATT client info found for conn_id [%d]", conn_id);
2931 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
2936 hal_gattc_server_info_t *info = NULL;
2937 hal_gattc_client_info_t *gattc_client = NULL;
2939 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2940 if (gattc_client == NULL) {
2941 INFO("GATT client conn info not found");
2945 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
2946 info = (hal_gattc_server_info_t*)l->data;
2950 if ((info->inst_id == gattc_client->inst_id) &&
2951 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
2952 INFO("GATT connection found for conn_id [%d]", conn_id);
2959 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
2960 gboolean auto_connect)
2962 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2963 gchar *device_path = NULL;
2964 GDBusProxy *device_proxy = NULL;
2965 GDBusConnection *conn;
2966 int ret = BT_STATUS_SUCCESS;
2967 hal_gattc_client_info_t *gattc_data;
2971 if (NULL == bd_addr) {
2972 ERR("bd_addr is NULL");
2973 return BT_STATUS_PARM_INVALID;
2976 conn = _bt_hal_get_system_gconn();
2978 ERR("_bt_gdbus_get_system_gconn returned NULL");
2979 return BT_STATUS_FAIL;
2982 _bt_hal_convert_addr_type_to_string(device_address,
2983 (unsigned char *)bd_addr->address);
2984 device_path = _bt_hal_get_device_object_path(device_address);
2985 if (device_path == NULL) {
2986 ERR("device_path NULL : [%s]", device_address);
2987 ret = BT_STATUS_FAIL;
2990 ERR("device_path:%s", device_path);
2992 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2993 NULL, BT_HAL_BLUEZ_NAME,
2994 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2995 g_free(device_path);
2996 if (NULL == device_proxy) {
2997 ERR("device_proxy returned NULL");
2998 return BT_STATUS_FAIL;
3001 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3002 if (gattc_data == NULL) {
3003 ERR("Unable to allocate memory");
3004 ret = BT_STATUS_NOMEM;
3007 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3008 BT_HAL_ADDRESS_LENGTH_MAX);
3010 DBG("Connect LE [%s]", device_address);
3012 gattc_data->client_if = client_if;
3014 g_dbus_proxy_call(device_proxy, "ConnectLE",
3015 g_variant_new("(b)", auto_connect),
3016 G_DBUS_CALL_FLAGS_NONE,
3017 BT_HAL_MAX_DBUS_TIMEOUT,
3019 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3025 g_object_unref(device_proxy);
3032 static bt_status_t _bt_hold_current_advertising()
3034 int ret = BT_STATUS_FAIL;
3035 gboolean is_advertising = FALSE;
3038 is_advertising = _bt_hal_is_advertising_in_slot(0);
3039 if (is_advertising) {
3040 DBG("+ Stop current advertising");
3042 ret = _bt_hal_enable_advertising(0, FALSE, FALSE);
3043 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3049 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3051 DBG("+ start current advertising");
3053 _bt_hal_enable_advertising(0, TRUE, FALSE);
3058 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3060 DBG("Try to initiate pending LE connection");
3062 pending_le_conn_timer_id = 0;
3064 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3065 &pending_le_conn_info->bd_addr,
3066 pending_le_conn_info->auto_connect);
3068 g_free(pending_le_conn_info);
3069 pending_le_conn_info = NULL;
3074 static int __hal_generate_conn_id()
3076 return ++bt_conn_id;
3079 static int __hal_generate_server_instance_id()
3081 return ++bt_inst_id;
3084 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3087 GError *g_error = NULL;
3088 GVariant *reply = NULL;
3089 hal_gattc_client_info_t *gattc_data = user_data;
3090 int result = BT_STATUS_SUCCESS;
3091 struct hal_ev_gatt_client_connected ev;
3092 hal_gattc_server_info_t *gatt_conn_info = NULL;
3096 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3097 g_object_unref(proxy);
3098 if (reply == NULL) {
3099 ERR("Connect LE Dbus Call Error");
3101 ERR("Error: %s\n", g_error->message);
3102 g_clear_error(&g_error);
3104 result = BT_STATUS_FAIL;
3106 g_variant_unref(reply);
3108 if (NULL == gattc_data) {
3109 ERR("server_data is NULL");
3114 if (result == BT_STATUS_FAIL) {
3115 memset(&ev, 0, sizeof(ev));
3118 ev.client_if = gattc_data->client_if;
3119 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3120 BT_HAL_ADDRESS_LENGTH_MAX);
3123 ERR("gatt client callback not registered");
3125 DBG("sending gatt client connected event");
3126 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3132 DBG("adding the server conn info in list");
3133 gattc_data->conn_id = __hal_generate_conn_id() ;
3134 gattc_data->inst_id = __hal_generate_server_instance_id();
3136 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3138 /*add gatt server connection info*/
3139 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3140 if (gatt_conn_info == NULL) {
3141 ERR("Failed to allocate memory");
3145 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3146 gatt_conn_info->inst_id = gattc_data->inst_id;
3147 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3153 /*remove conn_info*/
3158 void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3160 g_free(svc_info->svc_path);
3164 void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3166 g_free(char_info->chr_path);
3170 void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3172 g_free(desc_info->desc_path);
3176 void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3181 hal_gattc_service_t *svc_info = NULL;
3182 hal_gattc_char_t *char_info = NULL;
3183 hal_gattc_desc_t *desc_info = NULL;
3187 for (l = conn_info->gatt_list_services; l != NULL;) {
3188 svc_info = (hal_gattc_service_t*)l->data;
3189 if (svc_info == NULL)
3191 l = g_slist_next(l);
3193 for (m = svc_info->gatt_list_chars; m != NULL; ) {
3194 char_info = (hal_gattc_char_t*)m->data;
3195 if (char_info == NULL)
3197 m = g_slist_next(m);
3199 for (k = char_info->gatt_list_descs; k != NULL; ) {
3200 desc_info = (hal_gattc_desc_t*)k->data;
3201 if (desc_info == NULL)
3203 k = g_slist_next(k);
3205 /*remove desc element*/
3206 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3207 __hal_gattc_free_desc_info(desc_info);
3210 /*remove desc list*/
3211 g_slist_free(char_info->gatt_list_descs);
3212 char_info->gatt_list_descs = NULL;
3214 /*remove char element*/
3215 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3216 __hal_gattc_free_char_info(char_info);
3219 /*remove char list*/
3220 g_slist_free(svc_info->gatt_list_chars);
3221 svc_info->gatt_list_chars = NULL;
3223 /*remove svc element*/
3224 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3225 __hal_gattc_free_svc_info(svc_info);
3228 /*remove svc list */
3229 g_slist_free(conn_info->gatt_list_services);
3230 conn_info->gatt_list_services = NULL;
3232 /*remove conn info*/
3236 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3238 int result = BT_STATUS_SUCCESS;
3239 struct hal_ev_gatt_client_connected ev;
3240 hal_gattc_server_info_t *conn_info = NULL;
3241 bt_bdaddr_t bd_addr;
3243 hal_gattc_client_info_t *gattc_client = NULL;
3247 DBG("+ connected device address [%s]", address);
3249 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3250 HAL_EV_GATT_CLIENT_DISCONNECTED;
3252 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3253 /* find the gatt client info */
3254 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3255 if (NULL == gattc_client) {
3256 ERR("Fail to get gatt client info");
3261 memset(&ev, 0, sizeof(ev));
3262 ev.conn_id = gattc_client->conn_id;
3264 ev.client_if = gattc_client->client_if;
3265 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3266 BT_HAL_ADDRESS_LENGTH_MAX);
3269 ERR("gatt client callback not registered");
3271 DBG("sending gatt client connected status event");
3272 event_cb(event, (void *)&ev, sizeof(ev));
3275 if (!gatt_connected) {
3276 inst_id = gattc_client->inst_id;
3278 /* remove the gatt client info from the client list also*/
3279 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3280 g_free(gattc_client);
3282 //find the connected server info
3283 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3284 if (NULL == conn_info) {
3285 ERR("Fail to get gatt server info");
3289 if (inst_id != conn_info->inst_id) {
3290 ERR("server instance is different");
3294 //remove gatt conn info from the server list
3295 DBG("remove the server conn_info from list after gatt disconnection");
3296 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3297 __hal_clean_gattc_server_info(conn_info);
3303 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3304 const char* uuid_str, int inst_id)
3306 struct hal_ev_gatt_client_search_result ev;
3309 ERR("gatt client callback not registered");
3313 DBG("sending gatt client search service result event conn_id[%d]", conn_id);
3315 memset(&ev, 0, sizeof(ev));
3316 ev.conn_id = conn_id;
3317 ev.inst_id = inst_id;
3318 ev.is_primary = is_primary;
3319 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3321 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3324 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3326 struct hal_ev_gatt_client_search_complete ev;
3329 ERR("gatt client callback not registered");
3333 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3336 memset(&ev, 0, sizeof(ev));
3337 ev.conn_id = conn_id;
3340 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));