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;
172 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
173 gboolean auto_connect);
174 static bt_status_t _bt_hold_current_advertising();
175 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
176 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
177 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
179 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
180 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
181 const char* uuid_str, int inst_id);
182 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
183 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr);
184 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
185 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
188 /* To send stack event to hal-av handler */
189 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
194 void _bt_hal_unregister_gatt_client_handler_cb(void)
200 int _bt_hal_gatt_client_get_le_scan_type(void)
206 static gboolean __bt_hal_register_client_cb(gpointer user_data)
208 struct hal_ev_gatt_client_registered ev;
209 hal_gatt_client_app *client_info = user_data;
212 /* Prepare to send AV connecting event */
213 memset(&ev, 0, sizeof(ev));
214 ev.status = BT_STATUS_SUCCESS;
215 ev.client_if = client_info->client_if;
216 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
219 ERR("GATT Callback not registered");
221 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
222 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
229 static int __hal_generate_client_id()
231 return ++bt_client_if;
234 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
237 hal_gatt_client_app *info = NULL;
238 hal_gatt_client_app *gattc_app = NULL;
240 //check if client app is already registered
241 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
242 info = (hal_gatt_client_app*)l->data;
246 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
247 DBG("gatt client app already registered");
252 DBG("adding the gatt client app");
255 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
256 gattc_app->client_if = __hal_generate_client_id();
257 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
259 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
264 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
266 hal_gatt_client_app *gattc_app = NULL;
267 hal_gatt_client_app *client_app_info = NULL;
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 client_app_info->client_if = gattc_app->client_if;
280 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
281 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
283 DBG("registered client client_if [%d]", client_app_info->client_if);
285 return BT_STATUS_SUCCESS;
288 /** Registers a GATT client application with the stack */
289 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
294 return __hal_gattc_register_client_app(uuid);
297 bt_status_t __hal_gattc_unregister_client(int client_if)
300 hal_gatt_client_app *info = NULL;
302 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
304 /* remove the gatt client app */
305 for (l = hal_gattc_client_app_list; l != NULL; ) {
306 info = (hal_gatt_client_app*)l->data;
312 if (info->client_if == client_if) {
313 DBG("gatt client app found");
314 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
319 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
320 return BT_STATUS_SUCCESS;
323 /** Unregister a client application from the stack */
324 bt_status_t btif_gattc_unregister_client(int client_if)
329 return __hal_gattc_unregister_client(client_if);
332 /** Start or stop LE device scanning */
333 bt_status_t scan(int client_if, bool start)
340 ret = _bt_hal_adapter_le_start_scan();
342 ret = _bt_hal_adapter_le_stop_scan();
347 /** Create a connection to a remote LE or dual-mode device */
348 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
351 int ret = BT_STATUS_SUCCESS;
357 return BT_STATUS_PARM_INVALID;
359 ret = _bt_hold_current_advertising();
360 if (ret == BT_STATUS_SUCCESS) {
361 DBG("Current advertising is held");
362 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
363 pending_le_conn_info->client_if = client_if;
364 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
365 BT_HAL_ADDRESS_LENGTH_MAX);
366 pending_le_conn_info->auto_connect = is_direct;
368 pending_le_conn_timer_id =
369 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
371 return BT_STATUS_SUCCESS;
373 ERR("advertising is not stopped");
376 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
380 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
383 GError *g_error = NULL;
384 GVariant *reply = NULL;
385 hal_gattc_client_info_t *gatt_conn_info = user_data;
386 int result = BT_STATUS_SUCCESS;
387 struct hal_ev_gatt_client_connected ev;
391 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
392 g_object_unref(proxy);
394 ERR("Connect LE Dbus Call Error");
396 ERR("Error: %s\n", g_error->message);
397 g_clear_error(&g_error);
399 result = BT_STATUS_FAIL;
401 g_variant_unref(reply);
403 if (NULL == gatt_conn_info) {
404 ERR("server_data is NULL");
409 if (result == BT_STATUS_FAIL) {
410 memset(&ev, 0, sizeof(ev));
411 ev.conn_id = gatt_conn_info->conn_id;
413 ev.client_if = gatt_conn_info->client_if;
414 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
415 BT_HAL_ADDRESS_LENGTH_MAX);
418 ERR("gatt client callback not registered");
420 DBG("sending gatt client disconnected event");
421 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
427 g_free(gatt_conn_info);
432 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
435 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
437 GDBusProxy *device_proxy;
438 GDBusConnection *conn;
439 int ret = BT_STATUS_SUCCESS;
440 hal_gattc_client_info_t *gattc_data;
442 if (NULL == bd_addr) {
443 ERR("bd_addr is NULL");
444 return BT_STATUS_PARM_INVALID;
447 conn = _bt_hal_get_system_gconn();
449 ERR("_bt_gdbus_get_system_gconn returned NULL");
450 return BT_STATUS_FAIL;
453 _bt_hal_convert_addr_type_to_string(device_address,
454 (unsigned char *)bd_addr->address);
455 device_path = _bt_hal_get_device_object_path(device_address);
456 if (device_path == NULL) {
457 DBG("device_path NULL");
458 ret = BT_STATUS_FAIL;
462 ERR("device_path:%s", device_path);
464 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
465 NULL, BT_HAL_BLUEZ_NAME,
466 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
468 if (NULL == device_proxy) {
469 ERR("device_proxy returned NULL");
470 return BT_STATUS_FAIL;
473 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
474 memcpy(gattc_data->bd_addr.address, bd_addr->address,
475 BT_HAL_ADDRESS_LENGTH_MAX);
476 gattc_data->client_if = client_if;
477 gattc_data->conn_id = conn_id;
479 DBG("DisconnectLE [%s]", device_address);
481 g_dbus_proxy_call(device_proxy, "DisconnectLE",
483 G_DBUS_CALL_FLAGS_NONE,
484 BT_HAL_MAX_DBUS_TIMEOUT,
486 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
490 /** Disconnect a remote device or cancel a pending connection */
491 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
498 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
501 /** Clear the attribute cache for a given device */
502 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
505 return BT_STATUS_UNSUPPORTED;
508 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
513 hal_gattc_service_t *info = NULL;
515 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
516 info = (hal_gattc_service_t*)l->data;
520 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t))) {
521 INFO("Found GATT service uuid");
529 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
530 bt_gatt_characteristic_property_t prop)
535 hal_gattc_char_t *info = NULL;
537 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
538 info = (hal_gattc_char_t*)l->data;
542 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
543 (info->permission & prop)) {
544 INFO("Found GATT char uuid");
551 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
556 hal_gattc_char_t *info = NULL;
558 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
559 info = (hal_gattc_char_t*)l->data;
563 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
564 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
565 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
566 INFO("Found GATT char uuid");
573 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
578 hal_gattc_desc_t *info = NULL;
580 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
581 info = (hal_gattc_desc_t*)l->data;
585 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t))) {
586 INFO("Found GATT descriptor uuid");
594 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
595 const char *uuid_str, char *object_path, int is_primary)
598 hal_gattc_service_t *gattc_service = NULL;
600 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
601 gattc_service->svc_path = g_strdup(object_path);
602 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
603 gattc_service->is_primary = is_primary;
605 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
607 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
609 DBG("svc path {%s] svc uuid [%s]", object_path, uuid_str);
611 return gattc_service;
614 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
617 hal_gattc_char_t *gattc_char = NULL;
619 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
620 gattc_char->chr_path = g_strdup(char_handle);
622 DBG("svc path: [%s]", gatt_svc->svc_path);
623 DBG("char path: [%s]", gattc_char->chr_path);
625 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
628 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
629 const char* uuid_str, char *object_path, GPtrArray *gp_char_array)
631 hal_gattc_service_t* gatt_svc = NULL;
633 gchar *gp_char_path = NULL;
637 /* add the service */
638 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
639 if (gatt_svc == NULL) {
640 ERR("Failed to add service");
644 /* add the characteristic */
645 for (i = 0; i < gp_char_array->len; i++) {
646 gp_char_path = g_ptr_array_index(gp_char_array, i);
647 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
650 g_ptr_array_free(gp_char_array, TRUE);
653 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
655 hal_gattc_desc_t *gattc_desc = NULL;
657 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
658 gattc_desc->desc_path = g_strdup(desc_path);
660 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
662 DBG("char path: [%s]", gattc_char->chr_path);
663 DBG("desc path: [%s]", gattc_desc->desc_path);
666 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
667 GPtrArray *gp_desc_array, unsigned int char_permission)
669 gchar *gp_desc_path = NULL;
674 if (char_uuid_str == NULL) {
675 DBG("char_uuid_str is NULL");
679 //update the char uuid
680 DBG("char UUID: [%s] ", char_uuid_str);
681 DBG("char path: [%s]", gattc_char->chr_path);
683 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
685 //update char permission
686 gattc_char->permission = char_permission;
689 for (i = 0; i < gp_desc_array->len; i++) {
690 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
691 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
695 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
699 if (desc_uuid_str == NULL) {
700 DBG("char_uuid_str is NULL");
704 //update the descriptor uuid
705 DBG("desc UUID: [%s] ", desc_uuid_str);
706 DBG("desc path: [%s]", gattc_desc->desc_path);
708 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
711 static void browse_service_char(int conn_id)
713 hal_gattc_server_info_t *conn_info = NULL;
717 hal_gattc_service_t *svc_info = NULL;
718 hal_gattc_char_t *char_info = NULL;
719 hal_gattc_desc_t *desc_info = NULL;
723 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
724 if (conn_info == NULL) {
725 DBG("conn_info is NULL");
729 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
731 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
732 svc_info = (hal_gattc_service_t*)l->data;
733 if (svc_info == NULL)
736 DBG("svc path [%s]", svc_info->svc_path);
738 /* find characteristic object path */
739 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
740 char_info = (hal_gattc_char_t *)k->data;
741 if (char_info == NULL)
744 DBG("char path[%s]", char_info->chr_path);
747 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
748 desc_info = (hal_gattc_desc_t *)m->data;
749 if (desc_info == NULL)
752 DBG("desc path[%s]", desc_info->desc_path);
761 * Enumerate all GATT services on a connected device.
762 * Optionally, the results can be filtered for a given UUID.
764 static bt_status_t _gattc_client_search_service(int conn_id)
768 GVariant *result = NULL;
770 GVariantIter *svc_iter;
771 GVariantIter *interface_iter;
772 char *object_path = NULL;
773 char *interface_str = NULL;
774 const gchar *key = NULL;
775 GVariant *value = NULL;
776 GPtrArray *gp_array = NULL;
777 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
778 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
779 int ret = BT_STATUS_FAIL;
781 const gchar *uuid_str = NULL;
783 hal_gattc_server_info_t *conn_info = NULL;
784 gboolean is_primary = FALSE;
787 char *char_handle = NULL;
788 GVariantIter *char_iter = NULL;
789 GPtrArray *gp_char_array = NULL;
793 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
794 if (NULL == conn_info) {
795 DBG("Failed to get the conn_info");
796 return BT_STATUS_FAIL;
799 _bt_hal_convert_addr_type_to_string(device_address,
800 (unsigned char *)conn_info->bd_addr.address);
802 result = _bt_hal_get_managed_objects();
806 gp_array = g_ptr_array_new();
807 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
809 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
811 if (object_path == NULL)
814 _bt_hal_convert_device_path_to_address(object_path, temp_address);
816 if (g_strcmp0(temp_address, device_address) != 0)
819 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
820 &interface_str, &svc_iter)) {
821 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
824 DBG("[%d] Object Path : %s", idx++, object_path);
825 /* for characteristic */
826 gp_char_array = g_ptr_array_new();
827 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
828 if (g_strcmp0(key, "Primary") == 0) {
829 is_primary = g_variant_get_boolean(value);
832 g_ptr_array_add(gp_array, (gpointer)object_path);
835 } else if (g_strcmp0(key, "UUID") == 0) {
836 uuid_str = g_variant_get_string(value, &len);
837 DBG(" UUID: [%s]", uuid_str);
838 } else if (g_strcmp0(key, "Characteristics") == 0) {
839 g_variant_get(value, "ao", &char_iter);
840 if (char_iter != NULL) {
841 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
842 DBG("char handle : %s", char_handle);
843 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
850 DBG("send search service result event");
851 _bt_hal_send_search_service_result_event(conn_id, is_primary,
852 uuid_str, conn_info->inst_id);
854 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
859 if (gp_array->len == 0 || svc_count == 0) {
860 ERR("gp_array is NULL");
861 ret = BT_STATUS_FAIL;
863 ret = BT_STATUS_SUCCESS;
866 browse_service_char(conn_id);
867 /* send search service complete event */
868 _bt_hal_send_search_service_complete_event(conn_id, ret);
870 g_ptr_array_free(gp_array, TRUE);
871 g_variant_iter_free(iter);
872 g_variant_unref(result);
877 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
879 if (NULL == filter_uuid) {
880 DBG("Browse all the services");
881 return _gattc_client_search_service(conn_id);
883 DBG("TODO implement it");
884 return BT_STATUS_UNSUPPORTED;
888 * Enumerate included services for a given service.
889 * Set start_incl_srvc_id to NULL to get the first included service.
891 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
892 btgatt_srvc_id_t *start_incl_srvc_id)
895 return BT_STATUS_UNSUPPORTED;
898 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
899 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
901 struct hal_ev_gatt_client_char_search_result ev;
904 ERR("gatt client callback not registered");
908 DBG("sending gatt client search char result event conn_id[%d] status[%d]", conn_id, status);
910 memset(&ev, 0, sizeof(ev));
911 ev.conn_id = conn_id;
912 ev.inst_id = svc_id->id.inst_id;
913 ev.is_primary = svc_id->is_primary;
915 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
917 if (status == BT_STATUS_SUCCESS) {
918 DBG("building char uuid");
919 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
920 ev.char_prop = char_prop;
923 DBG("sending the char search event");
925 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
928 static int _hal_get_permission_flag(char *permission)
932 if (NULL == permission) {
933 ERR("gatt permission is NULL");
937 if (!g_strcmp0(permission, "broadcast"))
938 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
939 else if (!g_strcmp0(permission, "read"))
940 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
941 else if (!g_strcmp0(permission, "write-without-response"))
942 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
943 else if (!g_strcmp0(permission, "write"))
944 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
945 else if (!g_strcmp0(permission, "notify"))
946 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
947 else if (!g_strcmp0(permission, "indicate"))
948 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
949 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
950 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
951 else if (!g_strcmp0(permission, "reliable-write"))
952 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
953 else if (!g_strcmp0(permission, "writable-auxiliaries"))
954 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
955 else if (!g_strcmp0(permission, "encrypt-read"))
956 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
957 else if (!g_strcmp0(permission, "encrypt-write"))
958 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
959 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
960 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
961 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
962 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
968 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
970 GDBusProxy *properties_proxy = NULL;
971 GError *error = NULL;
972 GVariant *value = NULL;
973 GVariant *result = NULL;
974 GDBusConnection *g_conn;
976 char *char_desc_handle = NULL;
978 GVariantIter *property_iter;
979 GVariantIter *char_desc_iter;
980 char* char_handle = NULL;
981 gchar *char_uuid_str = NULL;
982 GPtrArray *gp_desc_array = NULL;
983 GVariantIter *char_perm_iter;
985 unsigned int char_permission = 0 ;
989 if (gattc_char->chr_path == NULL) {
990 DBG("char path is NULL");
991 return BT_STATUS_FAIL;
993 char_handle = gattc_char->chr_path;
995 DBG("char path:[%s]", gattc_char->chr_path);
997 g_conn = _bt_hal_get_system_gconn();
998 if (NULL == g_conn) {
999 ERR("_bt_gdbus_get_system_gconn returned NULL");
1000 return BT_STATUS_FAIL;
1003 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1004 G_DBUS_PROXY_FLAGS_NONE, NULL,
1007 BT_HAL_PROPERTIES_INTERFACE,
1010 if (properties_proxy == NULL) {
1011 ERR("properties_proxy returned NULL");
1012 return BT_STATUS_FAIL;
1015 result = g_dbus_proxy_call_sync(properties_proxy,
1017 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1018 G_DBUS_CALL_FLAGS_NONE,
1023 if (error != NULL) {
1024 ERR("Fail to get properties (Error: %s)", error->message);
1025 g_clear_error(&error);
1027 ERR("Fail to get properties");
1028 g_object_unref(properties_proxy);
1029 return BT_STATUS_FAIL;
1032 gp_desc_array = g_ptr_array_new();
1034 g_variant_get(result, "(a{sv})", &property_iter);
1036 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1037 if (!g_strcmp0(key, "UUID")) {
1038 char_uuid_str = g_variant_dup_string(value, &len);
1039 DBG("char UUID [%s]", char_uuid_str);
1040 } else if (!g_strcmp0(key, "Flags")) {
1041 g_variant_get(value, "as", &char_perm_iter);
1042 char_permission = 0x00;
1044 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1045 DBG("char permission: [%s]", permission);
1046 char_permission |= _hal_get_permission_flag(permission);
1048 } else if (!g_strcmp0(key, "Descriptors")) {
1049 g_variant_get(value, "ao", &char_desc_iter);
1050 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1051 DBG("char descriptor handle : %s", char_desc_handle);
1053 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1058 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1060 g_free(char_uuid_str);
1061 g_variant_iter_free(property_iter);
1062 g_variant_unref(result);
1063 g_object_unref(properties_proxy);
1064 g_ptr_array_free(gp_desc_array, TRUE);
1066 return BT_STATUS_SUCCESS;
1069 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1070 btgatt_srvc_id_t *srvc_id)
1072 hal_gattc_server_info_t * conn_info = NULL;
1073 hal_gattc_service_t *gattc_service = NULL;
1075 hal_gattc_char_t *gattc_char = NULL;
1076 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1077 int status = BT_STATUS_FAIL;
1080 DBG("conn_id[%d]", conn_id);
1082 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1083 if (NULL == conn_info) {
1084 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1085 return BT_STATUS_FAIL;
1089 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1090 if (NULL == gattc_service) {
1091 DBG("Failed to get the gatt service");
1092 return BT_STATUS_FAIL;
1095 DBG("service path [%s]", gattc_service->svc_path);
1097 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1098 DBG("service uuid [%s]", svc_uuid_str);
1100 /* find characteristic object path */
1101 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1102 gattc_char = (hal_gattc_char_t *)l->data;
1103 status = _hal_gattc_get_characteristic_info(gattc_char);
1106 if (BT_STATUS_SUCCESS == status) {
1107 DBG("Sending the success charateristics event");
1108 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1109 &gattc_char->chr_uuid, gattc_char->permission);
1113 DBG("sending final event");
1115 status = BT_STATUS_FAIL;
1116 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1118 browse_service_char(conn_id);
1119 /* retrive uuid for characteristic and object path for descriptor */
1121 return BT_STATUS_SUCCESS;
1125 * Enumerate characteristics for a given service.
1126 * Set start_char_id to NULL to get the first characteristic.
1128 bt_status_t btif_gattc_get_characteristic(int conn_id,
1129 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1132 CHECK_BTGATT_INIT();
1134 if (start_char_id == NULL) {
1135 DBG("Get all the characteristics");
1136 return _gattc_get_all_characteristic(conn_id, srvc_id);
1139 DBG("TBD Get specific characteristics");
1140 return BT_STATUS_UNSUPPORTED;
1144 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1146 GDBusProxy *properties_proxy = NULL;
1147 GError *error = NULL;
1148 GVariant *value = NULL;
1149 GVariant *result = NULL;
1150 GDBusConnection *g_conn;
1153 GVariantIter *property_iter;
1154 char* desc_handle = NULL;
1155 const gchar *desc_uuid_str = NULL;
1159 if (gattc_desc->desc_path == NULL) {
1160 DBG("desc path is NULL");
1161 return BT_STATUS_FAIL;
1163 desc_handle = gattc_desc->desc_path;
1165 DBG("desc path:[%s]", gattc_desc->desc_path);
1167 g_conn = _bt_hal_get_system_gconn();
1168 if (NULL == g_conn) {
1169 ERR("_bt_gdbus_get_system_gconn returned NULL");
1170 return BT_STATUS_FAIL;
1173 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1174 G_DBUS_PROXY_FLAGS_NONE, NULL,
1177 BT_HAL_PROPERTIES_INTERFACE,
1180 if (properties_proxy == NULL) {
1181 ERR("properties_proxy returned NULL");
1182 return BT_STATUS_FAIL;
1185 result = g_dbus_proxy_call_sync(properties_proxy,
1187 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1188 G_DBUS_CALL_FLAGS_NONE,
1193 if (error != NULL) {
1194 ERR("Fail to get properties (Error: %s)", error->message);
1195 g_clear_error(&error);
1197 ERR("Fail to get properties");
1198 g_object_unref(properties_proxy);
1199 return BT_STATUS_FAIL;
1202 g_variant_get(result, "(a{sv})", &property_iter);
1204 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1205 if (!g_strcmp0(key, "UUID")) {
1206 desc_uuid_str = g_variant_get_string(value, &len);
1207 DBG("desc UUID [%s]", desc_uuid_str);
1208 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1213 g_variant_iter_free(property_iter);
1214 g_variant_unref(result);
1215 g_object_unref(properties_proxy);
1217 return BT_STATUS_SUCCESS;
1220 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1221 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1223 struct hal_ev_gatt_client_desc_search_result ev;
1226 ERR("gatt client callback not registered");
1230 DBG("sending gatt client search desc result event conn_id[%d] status[%d]", conn_id, status);
1232 memset(&ev, 0, sizeof(ev));
1233 ev.conn_id = conn_id;
1234 ev.inst_id = svc_id->id.inst_id;
1235 ev.is_primary = svc_id->is_primary;
1238 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1239 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1241 if (status == BT_STATUS_SUCCESS) {
1242 DBG("building desc uuid");
1243 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1246 DBG("sending the desc search event");
1248 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1251 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1252 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1254 hal_gattc_server_info_t * conn_info = NULL;
1255 hal_gattc_service_t *gattc_service = NULL;
1258 hal_gattc_char_t *gattc_char = NULL;
1259 hal_gattc_desc_t *gattc_desc = NULL;
1260 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1261 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1262 int status = BT_STATUS_FAIL;
1266 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1267 if (NULL == conn_info) {
1268 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1269 return BT_STATUS_FAIL;
1273 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1274 if (NULL == gattc_service) {
1275 DBG("Failed to get the gatt service");
1276 return BT_STATUS_FAIL;
1279 DBG("service path [%s]", gattc_service->svc_path);
1280 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1281 DBG("service uuid [%s]", svc_uuid_str);
1283 /* find characteristics */
1284 /* a service can have two char with same uuid */
1285 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1286 gattc_char = (hal_gattc_char_t*)l->data;
1287 if (gattc_char == NULL)
1290 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1291 INFO("Found GATT char uuid");
1292 DBG("char path [%s]", gattc_char->chr_path);
1293 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1294 DBG("char uuid [%s]", char_uuid_str);
1296 /* get descriptor uuid */
1297 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1298 gattc_desc = (hal_gattc_desc_t *)m->data;
1299 if (gattc_desc == NULL)
1302 status = _hal_gattc_get_descriptor_info(gattc_desc);
1305 if (BT_STATUS_SUCCESS == status) {
1306 DBG("Sending the success descriptor event");
1307 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1308 char_id, &gattc_desc->desc_uuid);
1314 DBG("sending final event");
1316 status = BT_STATUS_FAIL;
1317 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1319 browse_service_char(conn_id);
1320 /* retrive uuid for characteristic and object path for descriptor */
1322 return BT_STATUS_SUCCESS;
1326 * Enumerate descriptors for a given characteristic.
1327 * Set start_descr_id to NULL to get the first descriptor.
1329 bt_status_t btif_gattc_get_descriptor(int conn_id,
1330 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1331 btgatt_gatt_id_t *start_descr_id)
1334 CHECK_BTGATT_INIT();
1336 if (start_descr_id == NULL) {
1337 DBG("Get all the descriptors");
1338 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1340 DBG("TBD Get specific descriptor");
1341 return BT_STATUS_UNSUPPORTED;
1345 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1347 struct hal_ev_gatt_client_read_data ev;
1350 ERR("gatt client callback not registered");
1354 DBG("sending gatt client charac read conn_id[%d] status[%d]", resp_data->conn_id, result);
1356 memset(&ev, 0, sizeof(ev));
1357 ev.conn_id = resp_data->conn_id;
1358 ev.inst_id = resp_data->srvc_id.id.inst_id;
1359 ev.is_primary = resp_data->srvc_id.is_primary;
1362 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1363 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1367 DBG("building the char read value [%d]", len);
1368 memcpy(ev.value, value, len);
1371 DBG("sending the gatt client read charac event");
1373 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1376 static void __hal_internal_read_char_cb(GObject *source_object,
1377 GAsyncResult *res, gpointer user_data)
1379 GError *error = NULL;
1380 GDBusConnection *system_gconn = NULL;
1383 GByteArray *gp_byte_array = NULL;
1385 hal_gatt_resp_data_t *resp_data = user_data;
1386 int result = BT_STATUS_SUCCESS;
1391 system_gconn = _bt_hal_get_system_gconn();
1392 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1395 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1398 result = BT_STATUS_FAIL;
1399 __hal_send_char_read_event(resp_data, result, NULL, 0);
1400 g_clear_error(&error);
1405 gp_byte_array = g_byte_array_new();
1406 g_variant_get(value, "(ay)", &iter);
1408 while (g_variant_iter_loop(iter, "y", &g_byte))
1409 g_byte_array_append(gp_byte_array, &g_byte, 1);
1413 for (i = 0; i < gp_byte_array->len; i++)
1414 DBG("%02x", gp_byte_array->data[i]);
1417 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1421 g_byte_array_free(gp_byte_array, TRUE);
1422 g_variant_iter_free(iter);
1423 g_variant_unref(value);
1429 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1430 btgatt_gatt_id_t *char_id, int auth_req)
1432 GDBusConnection *g_conn;
1433 hal_gatt_resp_data_t *resp_data;
1434 hal_gattc_service_t *gattc_service = NULL;
1435 GVariantBuilder *builder = NULL;
1437 hal_gattc_server_info_t * conn_info = NULL;
1438 hal_gattc_char_t *gattc_char = NULL;
1439 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1440 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1441 char* char_handle = NULL;
1445 /* get the connection info */
1446 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1447 if (NULL == conn_info) {
1448 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1449 return BT_STATUS_FAIL;
1453 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1454 if (NULL == gattc_service) {
1455 DBG("Failed to get the gatt service");
1456 return BT_STATUS_FAIL;
1459 DBG("service path [%s]", gattc_service->svc_path);
1460 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1461 DBG("service uuid [%s]", svc_uuid_str);
1464 /* find characteristic */
1465 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1466 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1467 if (NULL == gattc_char) {
1468 DBG("Failed to get the gatt char");
1469 return BT_STATUS_FAIL;
1472 DBG("char path [%s]", gattc_char->chr_path);
1473 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1474 DBG("char uuid [%s]", char_uuid_str);
1476 g_conn = _bt_hal_get_system_gconn();
1477 if (NULL == g_conn) {
1478 ERR("_bt_gdbus_get_system_gconn returned NULL");
1479 return BT_STATUS_FAIL;
1482 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1483 resp_data->conn_id = conn_id;
1484 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1485 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1487 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1490 g_variant_builder_add(builder, "{sv}", "offset",
1491 g_variant_new("q", offset));
1493 char_handle = gattc_char->chr_path;
1495 DBG("calling char read value");
1497 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1498 "ReadValue", g_variant_new("(a{sv})", builder),
1499 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1500 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1501 (gpointer)resp_data);
1502 g_variant_builder_unref(builder);
1504 return BT_STATUS_SUCCESS;
1507 /** Read a characteristic on a remote device */
1508 bt_status_t btif_read_characteristic(int conn_id,
1509 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1512 CHECK_BTGATT_INIT();
1515 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1518 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1520 struct hal_ev_gatt_client_write_result ev;
1523 ERR("gatt client callback not registered");
1527 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
1529 memset(&ev, 0, sizeof(ev));
1530 ev.conn_id = resp_data->conn_id;
1531 ev.inst_id = resp_data->srvc_id.id.inst_id;
1532 ev.is_primary = resp_data->srvc_id.is_primary;
1535 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1536 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1538 DBG("sending the gatt client write charac event");
1540 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1543 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1544 GAsyncResult *res, gpointer user_data)
1546 GError *error = NULL;
1547 GDBusConnection *system_gconn = NULL;
1549 hal_gatt_resp_data_t *resp_data = user_data;
1550 int result = BT_STATUS_SUCCESS;
1554 system_gconn = _bt_hal_get_system_gconn();
1555 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1558 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1560 result = BT_STATUS_FAIL;
1562 __hal_send_char_write_event(resp_data, result);
1563 g_clear_error(&error);
1568 //send write value event
1569 __hal_send_char_write_event(resp_data, result);
1572 g_variant_unref(value);
1577 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1580 case HAL_GATT_WRITE_TYPE_WRITE:
1581 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1583 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1584 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1587 ERR("Unknow write type : %d", type);
1588 return BT_STATUS_FAIL;
1591 return BT_STATUS_SUCCESS;
1595 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1597 GDBusConnection *conn;
1598 GVariantBuilder *builder = NULL;
1604 GUnixFDList *fd_list = NULL;
1606 conn = _bt_hal_get_system_gconn();
1608 ERR("_bt_gdbus_get_system_gconn returned NULL");
1609 return BT_STATUS_FAIL;
1612 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1613 //val = g_variant_new("ay", builder1);
1615 g_variant_builder_add(builder, "{sv}", "offset",
1616 g_variant_new("q", offset));
1618 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1619 "AcquireWrite", g_variant_new("(a{sv})", builder),
1620 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1621 NULL, &fd_list, NULL, &err);
1623 g_dbus_error_strip_remote_error(err);
1624 ERR("Error: %s", err->message);
1626 g_variant_builder_unref(builder);
1627 return BT_STATUS_FAIL;
1630 g_variant_get(value, "(hq)", &idx, &att_mtu);
1631 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1633 INFO("FD is %d index is %d mtu is %d", *fd, idx, att_mtu);
1636 g_object_unref(fd_list);
1637 g_variant_unref(value);
1638 g_variant_builder_unref(builder);
1640 return BT_STATUS_SUCCESS;
1643 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1645 GDBusConnection *conn;
1646 GVariantBuilder *builder = NULL;
1650 gint32 idx, notify_fd;
1652 GUnixFDList *fd_list = NULL;
1654 conn = _bt_hal_get_system_gconn();
1657 ERR("_bt_gdbus_get_system_gconn returned NULL");
1658 return BT_STATUS_FAIL;
1662 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1665 g_variant_builder_add(builder, "{sv}", "offset",
1666 g_variant_new("q", offset));
1668 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1669 "AcquireNotify", g_variant_new("(a{sv})", builder),
1670 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1671 NULL, &fd_list, NULL, &err);
1673 g_dbus_error_strip_remote_error(err);
1674 ERR("Error: %s", err->message);
1676 g_variant_builder_unref(builder);
1677 return BT_STATUS_FAIL;
1680 g_variant_get(value, "(hq)", &idx, &att_mtu);
1681 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1684 INFO("Acquired characteristic Notify fd %d, mtu %d", notify_fd, *mtu);
1688 g_object_unref(fd_list);
1689 g_variant_unref(value);
1690 g_variant_builder_unref(builder);
1692 return BT_STATUS_SUCCESS;
1696 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1697 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1699 GVariant *val, *options;
1700 GVariantBuilder *builder1;
1701 GVariantBuilder *builder2;
1702 GDBusConnection *g_conn;
1705 hal_gatt_resp_data_t *resp_data;
1706 hal_gattc_service_t *gattc_service = NULL;
1707 hal_gattc_server_info_t * conn_info = NULL;
1708 hal_gattc_char_t *gattc_char = NULL;
1709 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1710 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1711 char* char_handle = NULL;
1712 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1713 int ret = BT_STATUS_SUCCESS;
1717 ret = __hal_get_write_prop(write_type, &write_prop);
1718 if (BT_STATUS_FAIL == ret) {
1719 DBG("received invalid write type:[%d] ", write_type);
1720 return BT_STATUS_FAIL;
1723 /* get the connection info */
1724 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1725 if (NULL == conn_info) {
1726 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1727 return BT_STATUS_FAIL;
1731 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1732 if (NULL == gattc_service) {
1733 DBG("Failed to get the gatt service");
1734 return BT_STATUS_FAIL;
1737 DBG("service path [%s]", gattc_service->svc_path);
1738 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1739 DBG("service uuid [%s]", svc_uuid_str);
1741 /* find characteristic */
1742 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1743 if (NULL == gattc_char) {
1744 DBG("Failed to get the gatt char");
1745 return BT_STATUS_FAIL;
1748 DBG("char path [%s]", gattc_char->chr_path);
1749 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1750 DBG("char uuid [%s]", char_uuid_str);
1752 g_conn = _bt_hal_get_system_gconn();
1753 if (NULL == g_conn) {
1754 ERR("_bt_gdbus_get_system_gconn returned NULL");
1755 return BT_STATUS_FAIL;
1758 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1759 resp_data->conn_id = conn_id;
1760 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1761 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1763 char_handle = gattc_char->chr_path;
1765 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1767 for (i = 0; i < length; i++)
1768 g_variant_builder_add(builder1, "y", value[i]);
1770 val = g_variant_new("ay", builder1);
1772 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1774 g_variant_builder_add(builder2, "{sv}", "offset",
1775 g_variant_new_uint16(offset));
1777 options = g_variant_new("a{sv}", builder2);
1779 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1781 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1783 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1784 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1785 (gpointer)resp_data);
1787 g_variant_builder_unref(builder1);
1788 g_variant_builder_unref(builder2);
1790 return BT_STATUS_SUCCESS;
1793 bt_status_t btif_get_acquire_write_fd(int conn_id,
1794 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1795 int auth_req, int *fd, int*mtu)
1797 CHECK_BTGATT_INIT();
1801 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1804 hal_gattc_service_t *gattc_service = NULL;
1805 hal_gattc_server_info_t * conn_info = NULL;
1806 hal_gattc_char_t *gattc_char = NULL;
1807 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1809 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1810 int ret = BT_STATUS_SUCCESS;
1814 /* get the connection info */
1815 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1816 if (NULL == conn_info) {
1817 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1818 return BT_STATUS_FAIL;
1822 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1823 if (NULL == gattc_service) {
1824 DBG("Failed to get the gatt service");
1825 return BT_STATUS_FAIL;
1828 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1829 if (NULL == gattc_char) {
1830 DBG("Failed to get the gatt char");
1831 return BT_STATUS_FAIL;
1834 DBG("char path [%s]", gattc_char->chr_path);
1835 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1836 DBG("char uuid [%s]", char_uuid_str);
1839 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1840 if (ret != BT_STATUS_SUCCESS)
1844 ERR("Characterstics FD erite characterstics fd is %d", *fd);
1849 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1850 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1852 CHECK_BTGATT_INIT();
1856 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1859 hal_gattc_service_t *gattc_service = NULL;
1860 hal_gattc_server_info_t * conn_info = NULL;
1861 hal_gattc_char_t *gattc_char = NULL;
1862 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1864 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1865 int ret = BT_STATUS_SUCCESS;
1869 /* get the connection info */
1870 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1871 if (NULL == conn_info) {
1872 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1873 return BT_STATUS_FAIL;
1877 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1878 if (NULL == gattc_service) {
1879 DBG("Failed to get the gatt service");
1880 return BT_STATUS_FAIL;
1883 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1884 if (NULL == gattc_char) {
1885 DBG("Failed to get the gatt char");
1886 return BT_STATUS_FAIL;
1889 DBG("char path [%s]", gattc_char->chr_path);
1890 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1891 DBG("char uuid [%s]", char_uuid_str);
1894 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1895 if (ret != BT_STATUS_SUCCESS)
1899 ERR("Characterstics FD write characterstics fd is %d", *fd);
1906 /** Write a remote characteristic */
1907 bt_status_t btif_write_characteristic(int conn_id,
1908 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1909 int write_type, int len, int auth_req,
1912 CHECK_BTGATT_INIT();
1916 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1917 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1918 len, auth_req, p_value);
1921 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1923 struct hal_ev_gatt_client_read_data ev;
1926 ERR("gatt client callback not registered");
1930 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1932 memset(&ev, 0, sizeof(ev));
1933 ev.conn_id = resp_data->conn_id;
1934 ev.inst_id = resp_data->srvc_id.id.inst_id;
1935 ev.is_primary = resp_data->srvc_id.is_primary;
1938 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1939 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1940 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1944 DBG("building the desc read value [%d]", len);
1945 memcpy(ev.value, value, len);
1948 DBG("sending the gatt client read descriptor event");
1950 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1953 static void __hal_internal_read_desc_cb(GObject *source_object,
1954 GAsyncResult *res, gpointer user_data)
1956 GError *error = NULL;
1957 GDBusConnection *system_gconn = NULL;
1960 GByteArray *gp_byte_array = NULL;
1962 hal_gatt_resp_data_t *resp_data = user_data;
1963 int result = BT_STATUS_SUCCESS;
1968 system_gconn = _bt_hal_get_system_gconn();
1969 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1972 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1975 result = BT_STATUS_FAIL;
1976 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1977 g_clear_error(&error);
1982 gp_byte_array = g_byte_array_new();
1983 g_variant_get(value, "(ay)", &iter);
1985 while (g_variant_iter_loop(iter, "y", &g_byte))
1986 g_byte_array_append(gp_byte_array, &g_byte, 1);
1990 for (i = 0; i < gp_byte_array->len; i++)
1991 DBG("%02x", gp_byte_array->data[i]);
1994 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1998 g_byte_array_free(gp_byte_array, TRUE);
1999 g_variant_iter_free(iter);
2000 g_variant_unref(value);
2005 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2006 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2008 GDBusConnection *g_conn;
2009 hal_gatt_resp_data_t *resp_data;
2010 hal_gattc_service_t *gattc_service = NULL;
2011 GVariantBuilder *builder = NULL;
2013 hal_gattc_server_info_t * conn_info = NULL;
2014 hal_gattc_char_t *gattc_char = NULL;
2015 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2016 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2017 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2018 char* desc_handle = NULL;
2021 hal_gattc_desc_t *gattc_desc = NULL;
2025 /* get the connection info */
2026 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2027 if (NULL == conn_info) {
2028 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
2029 return BT_STATUS_FAIL;
2033 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2034 if (NULL == gattc_service) {
2035 DBG("Failed to get the gatt service");
2036 return BT_STATUS_FAIL;
2039 DBG("service path [%s]", gattc_service->svc_path);
2040 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2041 DBG("service uuid [%s]", svc_uuid_str);
2043 /* find characteristic */
2044 /* service can have two char with same uuid */
2045 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2046 gattc_char = (hal_gattc_char_t*)l->data;
2047 if (gattc_char == NULL)
2050 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2051 INFO("Found GATT char uuid");
2052 DBG("char path [%s]", gattc_char->chr_path);
2053 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2054 DBG("char uuid [%s]", char_uuid_str);
2056 /* find descriptor */
2057 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2059 DBG("desc path [%s]", gattc_desc->desc_path);
2060 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2061 DBG("desc uuid [%s]", desc_uuid_str);
2067 if (NULL == gattc_desc) {
2068 DBG("Failed to get the gatt desc");
2069 return BT_STATUS_FAIL;
2072 g_conn = _bt_hal_get_system_gconn();
2073 if (NULL == g_conn) {
2074 ERR("_bt_gdbus_get_system_gconn returned NULL");
2075 return BT_STATUS_FAIL;
2078 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2079 resp_data->conn_id = conn_id;
2080 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2081 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2082 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2084 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2087 g_variant_builder_add(builder, "{sv}", "offset",
2088 g_variant_new("q", offset));
2090 desc_handle = gattc_desc->desc_path;
2092 DBG("calling desc read value");
2094 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2095 "ReadValue", g_variant_new("(a{sv})", builder),
2096 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2097 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2098 (gpointer)resp_data);
2099 g_variant_builder_unref(builder);
2101 return BT_STATUS_SUCCESS;
2104 /** Read the descriptor for a given characteristic */
2105 bt_status_t btif_read_descriptor(int conn_id,
2106 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2107 btgatt_gatt_id_t *descr_id, int auth_req)
2109 CHECK_BTGATT_INIT();
2111 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2114 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2116 struct hal_ev_gatt_client_write_result ev;
2119 ERR("gatt client callback not registered");
2123 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
2125 memset(&ev, 0, sizeof(ev));
2126 ev.conn_id = resp_data->conn_id;
2127 ev.inst_id = resp_data->srvc_id.id.inst_id;
2128 ev.is_primary = resp_data->srvc_id.is_primary;
2131 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2132 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2133 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2135 DBG("sending the gatt client write charac event");
2137 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2140 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2141 GAsyncResult *res, gpointer user_data)
2143 GError *error = NULL;
2144 GDBusConnection *system_gconn = NULL;
2146 hal_gatt_resp_data_t *resp_data = user_data;
2147 int result = BT_STATUS_SUCCESS;
2151 system_gconn = _bt_hal_get_system_gconn();
2152 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2155 ERR("write descriptor dbus failed Error: [%s]", error->message);
2158 result = BT_STATUS_FAIL;
2159 __hal_send_desc_write_event(resp_data, result);
2160 g_clear_error(&error);
2165 //send write value event
2166 __hal_send_desc_write_event(resp_data, result);
2169 g_variant_unref(value);
2174 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2175 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2176 int write_type, int length, int auth_req, char* value)
2178 GVariant *val, *options;
2179 GVariantBuilder *builder1;
2180 GVariantBuilder *builder2;
2181 GDBusConnection *g_conn;
2184 hal_gatt_resp_data_t *resp_data;
2185 hal_gattc_service_t *gattc_service = NULL;
2186 hal_gattc_server_info_t * conn_info = NULL;
2187 hal_gattc_char_t *gattc_char = NULL;
2188 hal_gattc_desc_t *gattc_desc = NULL;
2189 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2190 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2191 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2192 char* desc_handle = NULL;
2193 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2194 int ret = BT_STATUS_SUCCESS;
2199 ret = __hal_get_write_prop(write_type, &write_prop);
2200 if (BT_STATUS_FAIL == ret) {
2201 DBG("received invalid write type:[%d] ", write_type);
2202 return BT_STATUS_FAIL;
2205 /* get the connection info */
2206 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2207 if (NULL == conn_info) {
2208 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
2209 return BT_STATUS_FAIL;
2213 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2214 if (NULL == gattc_service) {
2215 DBG("Failed to get the gatt service");
2216 return BT_STATUS_FAIL;
2219 DBG("service path [%s]", gattc_service->svc_path);
2220 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2221 DBG("service uuid [%s]", svc_uuid_str);
2223 /* find characteristic */
2224 /* service can have two char with same uuid */
2225 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2226 gattc_char = (hal_gattc_char_t*)l->data;
2227 if (gattc_char == NULL)
2230 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2231 INFO("Found GATT char uuid");
2232 DBG("char path [%s]", gattc_char->chr_path);
2233 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2234 DBG("char uuid [%s]", char_uuid_str);
2236 /* find descriptor */
2237 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2239 DBG("desc path [%s]", gattc_desc->desc_path);
2240 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2241 DBG("desc uuid [%s]", desc_uuid_str);
2247 if (NULL == gattc_desc) {
2248 DBG("Failed to get the gatt desc");
2249 return BT_STATUS_FAIL;
2252 g_conn = _bt_hal_get_system_gconn();
2253 if (NULL == g_conn) {
2254 ERR("_bt_gdbus_get_system_gconn returned NULL");
2255 return BT_STATUS_FAIL;
2258 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2259 resp_data->conn_id = conn_id;
2260 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2261 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2262 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2264 desc_handle = gattc_desc->desc_path;
2266 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2268 for (i = 0; i < length; i++)
2269 g_variant_builder_add(builder1, "y", value[i]);
2271 val = g_variant_new("ay", builder1);
2273 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2275 g_variant_builder_add(builder2, "{sv}", "offset",
2276 g_variant_new_uint16(offset));
2278 options = g_variant_new("a{sv}", builder2);
2280 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2282 g_variant_new("(@ay@a{sv})", val, options),
2284 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2285 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2286 (gpointer)resp_data);
2288 g_variant_builder_unref(builder1);
2289 g_variant_builder_unref(builder2);
2291 return BT_STATUS_SUCCESS;
2294 /** Write a remote descriptor for a given characteristic */
2295 bt_status_t btif_write_descriptor(int conn_id,
2296 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2297 btgatt_gatt_id_t *descr_id, int write_type, int len,
2298 int auth_req, char* p_value)
2300 CHECK_BTGATT_INIT();
2302 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2303 len, auth_req, p_value);
2306 /** Execute a prepared write operation */
2307 bt_status_t execute_write(int conn_id, int execute)
2309 CHECK_BTGATT_INIT();
2310 return BT_STATUS_UNSUPPORTED;
2313 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2315 struct hal_ev_gatt_client_watch_notification ev;
2316 hal_gatt_resp_data_t *resp_data = user_data;
2318 DBG("sending the watch register notification event");
2319 /* send the event */
2320 memset(&ev, 0, sizeof(ev));
2321 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2323 ev.status = resp_data->result;
2325 ev.is_primary = resp_data->srvc_id.is_primary;
2326 ev.inst_id = resp_data->srvc_id.id.inst_id;
2328 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2329 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2332 ERR("GATT Callback not registered");
2334 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2341 static bt_status_t _hal_register_for_notification(int client_if,
2342 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2343 btgatt_gatt_id_t *char_id)
2345 int result = BT_STATUS_SUCCESS;
2346 GError *error = NULL;
2347 GDBusConnection *g_conn;
2348 hal_gattc_client_info_t *gattc_client = NULL;
2349 hal_gattc_server_info_t * conn_info = NULL;
2350 hal_gattc_service_t *gattc_service = NULL;
2351 hal_gattc_char_t *gattc_char = NULL;
2352 char* char_handle = NULL;
2353 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2354 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2355 hal_gatt_resp_data_t *resp_data;
2359 gattc_client = __bt_find_gatt_client_info(bd_addr);
2360 if (gattc_client == NULL) {
2361 ERR("failed to get the gatt client info");
2362 return BT_STATUS_FAIL;
2365 if (gattc_client->client_if != client_if) {
2366 ERR("could not find the gatt client for client id[%d]", client_if);
2367 return BT_STATUS_FAIL;
2370 /* get the connection info */
2371 conn_info = __bt_find_gatt_conn_info(bd_addr);
2372 if (NULL == conn_info) {
2373 ERR("Failed to get the conn_info");
2374 return BT_STATUS_FAIL;
2377 if (conn_info->inst_id != gattc_client->inst_id) {
2378 ERR("could not fild the conn_info");
2379 return BT_STATUS_FAIL;
2383 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2384 if (NULL == gattc_service) {
2385 DBG("Failed to get the gatt service");
2386 return BT_STATUS_FAIL;
2389 DBG("service path [%s]", gattc_service->svc_path);
2390 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2391 DBG("service uuid [%s]", svc_uuid_str);
2394 /* find characteristic */
2395 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2396 if (NULL == gattc_char) {
2397 DBG("Failed to get the gatt char");
2398 return BT_STATUS_FAIL;
2401 DBG("char path [%s]", gattc_char->chr_path);
2402 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2403 DBG("char uuid [%s]", char_uuid_str);
2405 char_handle = gattc_char->chr_path;
2407 g_conn = _bt_hal_get_system_gconn();
2408 if (g_conn == NULL) {
2410 return BT_STATUS_FAIL;
2413 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2415 DBG("#StartNotify");
2416 g_dbus_connection_call_sync(g_conn,
2419 BT_HAL_GATT_CHAR_INTERFACE,
2423 G_DBUS_CALL_FLAGS_NONE,
2424 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2427 g_dbus_error_strip_remote_error(error);
2428 ERR("### Watch Failed: %s", error->message);
2429 if (g_strrstr(error->message, "Already notifying"))
2430 result = BT_STATUS_SUCCESS;
2431 else if (g_strrstr(error->message, "In Progress"))
2432 result = BT_STATUS_BUSY;
2433 else if (g_strrstr(error->message, "Operation is not supported"))
2434 result = BT_STATUS_UNSUPPORTED;
2435 /*failed because of either Insufficient Authorization or Write Not Permitted */
2436 else if (g_strrstr(error->message, "Write not permitted") ||
2437 g_strrstr(error->message, "Operation Not Authorized"))
2438 result = BT_STATUS_AUTH_FAILURE;
2439 /* failed because of either Insufficient Authentication,
2440 Insufficient Encryption Key Size, or Insufficient Encryption. */
2441 else if (g_strrstr(error->message, "Not paired"))
2442 result = BT_STATUS_NOT_READY;
2444 result = BT_STATUS_FAIL;
2446 g_clear_error(&error);
2449 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2450 resp_data->result = result;
2451 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2452 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2454 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2458 return BT_STATUS_SUCCESS;
2462 * Register to receive notifications or indications for a given
2465 bt_status_t btif_register_for_notification(int client_if,
2466 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2467 btgatt_gatt_id_t *char_id)
2469 CHECK_BTGATT_INIT();
2471 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2474 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2476 struct hal_ev_gatt_client_watch_notification ev;
2477 hal_gatt_resp_data_t *resp_data = user_data;
2479 DBG("sending the watch deregister notification event");
2480 /* send the event */
2481 memset(&ev, 0, sizeof(ev));
2482 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2484 ev.status = resp_data->result;
2486 ev.is_primary = resp_data->srvc_id.is_primary;
2487 ev.inst_id = resp_data->srvc_id.id.inst_id;
2489 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2490 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2493 ERR("GATT Callback not registered");
2495 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2502 static bt_status_t _hal_deregister_for_notification(int client_if,
2503 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2504 btgatt_gatt_id_t *char_id)
2506 int result = BT_STATUS_SUCCESS;
2507 GError *error = NULL;
2508 GDBusConnection *g_conn;
2509 hal_gattc_client_info_t *gattc_client = NULL;
2510 hal_gattc_server_info_t * conn_info = NULL;
2511 hal_gattc_service_t *gattc_service = NULL;
2512 hal_gattc_char_t *gattc_char = NULL;
2513 char* char_handle = NULL;
2514 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2515 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2516 hal_gatt_resp_data_t *resp_data;
2520 gattc_client = __bt_find_gatt_client_info(bd_addr);
2521 if (gattc_client == NULL) {
2522 ERR("failed to get the gatt client info");
2523 return BT_STATUS_FAIL;
2526 if (gattc_client->client_if != client_if) {
2527 ERR("could not find the gatt client for client id[%d]", client_if);
2528 return BT_STATUS_FAIL;
2531 /* get the connection info */
2532 conn_info = __bt_find_gatt_conn_info(bd_addr);
2533 if (NULL == conn_info) {
2534 ERR("Failed to get the conn_info");
2535 return BT_STATUS_FAIL;
2538 if (conn_info->inst_id != gattc_client->inst_id) {
2539 ERR("could not fild the conn_info");
2540 return BT_STATUS_FAIL;
2544 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2545 if (NULL == gattc_service) {
2546 DBG("Failed to get the gatt service");
2547 return BT_STATUS_FAIL;
2550 DBG("service path [%s]", gattc_service->svc_path);
2551 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2552 DBG("service uuid [%s]", svc_uuid_str);
2555 /* find characteristic */
2556 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2557 if (NULL == gattc_char) {
2558 DBG("Failed to get the gatt char");
2559 return BT_STATUS_FAIL;
2562 DBG("char path [%s]", gattc_char->chr_path);
2563 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2564 DBG("char uuid [%s]", char_uuid_str);
2566 char_handle = gattc_char->chr_path;
2568 g_conn = _bt_hal_get_system_gconn();
2569 if (g_conn == NULL) {
2571 return BT_STATUS_FAIL;
2574 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2576 DBG("#StartNotify");
2577 g_dbus_connection_call_sync(g_conn,
2580 BT_HAL_GATT_CHAR_INTERFACE,
2584 G_DBUS_CALL_FLAGS_NONE,
2585 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2588 ERR("### Watch Failed: %s", error->message);
2589 g_clear_error(&error);
2590 result = BT_STATUS_FAIL;
2593 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2594 resp_data->result = result;
2595 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2596 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2598 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2602 return BT_STATUS_SUCCESS;
2604 /** Deregister a previous request for notifications/indications */
2605 bt_status_t btif_deregister_for_notification(int client_if,
2606 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2607 btgatt_gatt_id_t *char_id)
2609 CHECK_BTGATT_INIT();
2610 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2613 /** Request RSSI for a given remote device */
2614 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2616 CHECK_BTGATT_INIT();
2617 return BT_STATUS_UNSUPPORTED;
2620 /** OTA firmware download */
2621 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2623 CHECK_BTGATT_INIT();
2624 return BT_STATUS_UNSUPPORTED;
2627 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2628 int get_device_type(const bt_bdaddr_t *bd_addr)
2630 CHECK_BTGATT_INIT();
2631 return BT_STATUS_UNSUPPORTED;
2634 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2635 int min_int, int max_int, int latency, int timeout)
2637 gchar *device_path = NULL;
2638 GError *error = NULL;
2639 GDBusProxy *device_proxy = NULL;
2640 GDBusConnection *conn;
2642 int ret = BT_STATUS_SUCCESS;
2643 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2645 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2646 min_int, max_int, latency, timeout);
2648 conn = _bt_hal_get_system_gconn();
2651 return BT_STATUS_FAIL;
2654 _bt_hal_convert_addr_type_to_string(device_address,
2655 (unsigned char *)bd_addr->address);
2656 device_path = _bt_hal_get_device_object_path(device_address);
2658 if (device_path == NULL) {
2659 ERR("device_path NULL : [%s]", device_address);
2660 return BT_STATUS_FAIL;
2663 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2664 NULL, BT_HAL_BLUEZ_NAME,
2665 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2667 g_free(device_path);
2668 if (NULL == device_proxy) {
2669 ERR("device_proxy returned NULL");
2670 return BT_STATUS_FAIL;
2673 INFO("### LeConnUpdate");
2674 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2675 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2676 G_DBUS_CALL_FLAGS_NONE,
2681 g_object_unref(device_proxy);
2682 if (reply == NULL) {
2684 ERR("Error %s[%s]", error->message, device_address);
2685 if (g_strrstr(error->message, "In Progress"))
2686 ret = BT_STATUS_SUCCESS;
2688 ret = BT_STATUS_FAIL;
2689 g_error_free(error);
2693 g_variant_unref(reply);
2695 INFO("LE Connection parameter Updated");
2699 /** Request a connection parameter update */
2700 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2702 CHECK_BTGATT_INIT();
2706 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2709 /** Test mode interface */
2710 bt_status_t test_command(int command, btgatt_test_params_t* params)
2712 CHECK_BTGATT_INIT();
2713 return BT_STATUS_UNSUPPORTED;
2716 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2719 GError *g_error = NULL;
2720 GVariant *reply = NULL;
2721 int result = BT_STATUS_SUCCESS;
2722 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2723 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2727 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2728 g_object_unref(proxy);
2729 if (reply == NULL) {
2730 ERR("Connect LE Dbus Call Error");
2732 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2733 g_clear_error(&g_error);
2735 result = BT_STATUS_FAIL;
2737 g_variant_unref(reply);
2739 memset(&ev, 0, sizeof(ev));
2741 ev.mtu = conn_mtu->mtu;
2742 ev.conn_id = conn_mtu->conn_id;
2745 ERR("gatt client callback not registered");
2747 DBG("sending gatt client MTU exchange completed event");
2748 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2755 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2757 gchar *device_path = NULL;
2758 GDBusProxy *device_proxy = NULL;
2759 GDBusConnection *conn;
2760 hal_gattc_client_info_t *gattc_client = NULL;
2761 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2762 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2764 conn = _bt_hal_get_system_gconn();
2767 return BT_STATUS_FAIL;
2770 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2771 if (gattc_client == NULL) {
2772 INFO("GATT client conn info not found");
2773 return BT_STATUS_FAIL;
2776 _bt_hal_convert_addr_type_to_string(device_address,
2777 (unsigned char *)gattc_client->bd_addr.address);
2779 device_path = _bt_hal_get_device_object_path(device_address);
2780 if (device_path == NULL) {
2781 ERR("device_path NULL : [%s]", device_address);
2782 return BT_STATUS_FAIL;
2785 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2786 NULL, BT_HAL_BLUEZ_NAME,
2787 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2789 g_free(device_path);
2790 if (NULL == device_proxy) {
2791 ERR("device_proxy returned NULL");
2792 return BT_STATUS_FAIL;
2795 conn_mtu->conn_id = conn_id;
2796 conn_mtu->mtu = mtu;
2798 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2799 g_variant_new("(q)", mtu),
2800 G_DBUS_CALL_FLAGS_NONE,
2801 BT_HAL_MAX_DBUS_TIMEOUT,
2803 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2806 return BT_STATUS_SUCCESS;
2809 /** MTU Exchange request from client */
2810 static bt_status_t configure_mtu(int conn_id, int mtu)
2812 CHECK_BTGATT_INIT();
2814 return __hal_configure_mtu(conn_id, mtu);
2817 /** Setup scan filter params */
2818 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2819 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2820 int rssi_low_thres, int dely_mode, int found_timeout,
2821 int lost_timeout, int found_timeout_cnt)
2824 GError *error = NULL;
2825 GVariant *ret, *param;
2826 CHECK_BTGATT_INIT();
2828 proxy = _bt_hal_get_adapter_proxy();
2831 return BT_STATUS_FAIL;
2833 param = g_variant_new("(iiiiiiiiiiii)",
2846 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2847 param, G_DBUS_CALL_FLAGS_NONE,
2851 ERR("scan_filter_param_setup Fail: %s", error->message);
2852 g_clear_error(&error);
2853 return BT_STATUS_FAIL;
2857 g_variant_unref(ret);
2859 return BT_STATUS_SUCCESS;
2862 /** Configure a scan filter condition */
2863 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2864 int filt_index, int company_id,
2865 int company_id_mask, const bt_uuid_t *p_uuid,
2866 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2867 char addr_type, int data_len, char* p_data, int mask_len,
2871 GError *error = NULL;
2872 GVariant *ret, *param;
2873 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2874 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2875 GArray *arr_uuid = NULL;
2876 GArray *arr_uuid_mask = NULL;
2877 GArray *arr_data = NULL;
2878 GArray *arr_data_mask = NULL;
2879 CHECK_BTGATT_INIT();
2881 proxy = _bt_hal_get_adapter_proxy();
2884 return BT_STATUS_FAIL;
2886 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2888 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2890 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2892 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2894 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2895 NULL, 0, TRUE, NULL, NULL);
2896 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2897 NULL, 0, TRUE, NULL, NULL);
2898 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2899 NULL, 0, TRUE, NULL, NULL);
2900 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2901 NULL, 0, TRUE, NULL, NULL);
2903 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2904 client_if, // client_if
2905 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2906 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2907 filt_index, // filter_index
2908 company_id, // company_id
2909 company_id_mask, // company_id_mask
2910 arr_uuid_param, // p_uuid
2911 arr_uuid_mask_param, // p_uuid_mask
2913 addr_type, // address_type
2914 arr_data_param, // p_data
2915 arr_data_mask_param); // p_mask
2917 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2918 param, G_DBUS_CALL_FLAGS_NONE,
2922 ERR("scan_filter_add_remove Fail: %s", error->message);
2923 g_clear_error(&error);
2924 return BT_STATUS_FAIL;
2928 g_variant_unref(ret);
2930 return BT_STATUS_SUCCESS;
2933 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2935 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2936 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2937 NULL, 0, TRUE, NULL, NULL);
2938 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2939 NULL, 0, TRUE, NULL, NULL);
2940 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2941 NULL, 0, TRUE, NULL, NULL);
2942 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2943 NULL, 0, TRUE, NULL, NULL);
2945 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2946 client_if, // client_if
2947 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2948 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2949 filt_index, // filter_index
2950 company_id, // company_id
2951 company_id_mask, // company_id_mask
2952 arr_uuid_param, // p_uuid
2953 arr_uuid_mask_param, // p_uuid_mask
2955 addr_type, // address_type
2956 arr_data_param, // p_data
2957 arr_data_mask_param);
2959 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2960 param, G_DBUS_CALL_FLAGS_NONE,
2964 ERR("scan_filter_add_remove Fail: %s", error->message);
2965 g_clear_error(&error);
2966 return BT_STATUS_FAIL;
2970 g_variant_unref(ret);
2972 return BT_STATUS_SUCCESS;
2975 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2977 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2978 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2980 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2981 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2983 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2984 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2985 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2986 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2987 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2988 NULL, 0, TRUE, NULL, NULL);
2989 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2990 NULL, 0, TRUE, NULL, NULL);
2992 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2993 client_if, // client_if
2994 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2995 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
2996 filt_index, // filter_index
2997 company_id, // company_id
2998 company_id_mask, // company_id_mask
2999 arr_uuid_param, // p_uuid
3000 arr_uuid_mask_param, // p_uuid_mask
3002 addr_type, // address_type
3003 arr_data_param, // p_data
3004 arr_data_mask_param);
3006 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3007 param, G_DBUS_CALL_FLAGS_NONE,
3011 ERR("scan_filter_add_remove Fail: %s", error->message);
3012 g_clear_error(&error);
3013 return BT_STATUS_FAIL;
3017 g_variant_unref(ret);
3019 g_array_free(arr_uuid, TRUE);
3020 g_array_free(arr_uuid_mask, TRUE);
3022 return BT_STATUS_SUCCESS;
3025 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3027 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3028 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3030 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3031 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3033 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3034 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3035 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3036 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3037 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3038 NULL, 0, TRUE, NULL, NULL);
3039 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3040 NULL, 0, TRUE, NULL, NULL);
3042 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3043 client_if, // client_if
3044 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3045 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3046 filt_index, // filter_index
3047 company_id, // company_id
3048 company_id_mask, // company_id_mask
3049 arr_uuid_param, // p_uuid
3050 arr_uuid_mask_param, // p_uuid_mask
3052 addr_type, // address_type
3053 arr_data_param, // p_data
3054 arr_data_mask_param);
3056 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3057 G_DBUS_CALL_FLAGS_NONE,
3061 ERR("scan_filter_add_remove Fail: %s", error->message);
3062 g_clear_error(&error);
3063 return BT_STATUS_FAIL;
3067 g_variant_unref(ret);
3069 g_array_free(arr_uuid, TRUE);
3070 g_array_free(arr_uuid_mask, TRUE);
3072 return BT_STATUS_SUCCESS;
3075 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3077 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3078 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3080 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3081 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3083 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3084 NULL, 0, TRUE, NULL, NULL);
3085 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3086 NULL, 0, TRUE, NULL, NULL);
3087 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3088 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3089 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3090 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3092 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3093 client_if, // client_if
3094 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3095 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3096 filt_index, // filter_index
3097 company_id, // company_id
3098 company_id_mask, // company_id_mask
3099 arr_uuid_param, // p_uuid
3100 arr_uuid_mask_param, // p_uuid_mask
3102 addr_type, // address_type
3103 arr_data_param, // p_data
3104 arr_data_mask_param);
3106 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3107 G_DBUS_CALL_FLAGS_NONE,
3111 ERR("scan_filter_add_remove Fail: %s", error->message);
3112 g_clear_error(&error);
3113 return BT_STATUS_FAIL;
3117 g_variant_unref(ret);
3119 g_array_free(arr_data, TRUE);
3120 g_array_free(arr_data_mask, TRUE);
3122 return BT_STATUS_SUCCESS;
3125 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3127 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3128 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3130 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3131 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3133 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3134 NULL, 0, TRUE, NULL, NULL);
3135 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3136 NULL, 0, TRUE, NULL, NULL);
3137 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3138 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3139 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3140 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3142 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3143 client_if, // client_if
3144 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3145 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3146 filt_index, // filter_index
3147 company_id, // company_id
3148 company_id_mask, // company_id_mask
3149 arr_uuid_param, // p_uuid
3150 arr_uuid_mask_param, // p_uuid_mask
3152 addr_type, // address_type
3153 arr_data_param, // p_data
3154 arr_data_mask_param);
3156 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3157 G_DBUS_CALL_FLAGS_NONE,
3161 ERR("scan_filter_add_remove Fail: %s", error->message);
3162 g_clear_error(&error);
3163 return BT_STATUS_FAIL;
3167 g_variant_unref(ret);
3169 g_array_free(arr_data, TRUE);
3170 g_array_free(arr_data_mask, TRUE);
3172 return BT_STATUS_SUCCESS;
3175 return BT_STATUS_UNSUPPORTED;
3178 /** Clear all scan filter conditions for specific filter index*/
3179 bt_status_t scan_filter_clear(int client_if, int filt_index)
3182 GError *error = NULL;
3184 CHECK_BTGATT_INIT();
3186 proxy = _bt_hal_get_adapter_proxy();
3188 return BT_STATUS_FAIL;
3190 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3191 g_variant_new("(ii)", client_if, filt_index),
3192 G_DBUS_CALL_FLAGS_NONE,
3196 ERR("scan_filter_clear Fail: %s", error->message);
3197 g_clear_error(&error);
3198 return BT_STATUS_FAIL;
3201 g_variant_unref(ret);
3202 return BT_STATUS_SUCCESS;
3205 /** Enable / disable scan filter feature*/
3206 bt_status_t scan_filter_enable(int client_if, bool enable)
3209 GError *error = NULL;
3211 CHECK_BTGATT_INIT();
3213 proxy = _bt_hal_get_adapter_proxy();
3215 return BT_STATUS_FAIL;
3217 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3218 g_variant_new("(ib)", client_if, enable),
3219 G_DBUS_CALL_FLAGS_NONE,
3223 ERR("scan_filter_enable Fail: %s", error->message);
3224 g_clear_error(&error);
3225 return BT_STATUS_FAIL;
3227 g_variant_unref(ret);
3229 return BT_STATUS_SUCCESS;
3232 /** Sets the LE scan interval and window in units of N*0.625 msec */
3234 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3238 CHECK_BTGATT_INIT();
3240 le_scan_type = scan_type;
3241 ret = _bt_hal_adapter_le_set_scan_parameters(
3242 scan_type, scan_interval, scan_window);
3246 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3248 CHECK_BTGATT_INIT();
3249 return BT_STATUS_UNSUPPORTED;
3253 /* Configure the batchscan storage */
3254 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3255 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3257 CHECK_BTGATT_INIT();
3258 return BT_STATUS_UNSUPPORTED;
3261 /* Enable batchscan */
3262 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3263 int scan_interval, int scan_window, int addr_type, int discard_rule)
3265 CHECK_BTGATT_INIT();
3266 return BT_STATUS_UNSUPPORTED;
3269 /* Disable batchscan */
3270 bt_status_t batchscan_dis_batch_scan(int client_if)
3272 CHECK_BTGATT_INIT();
3273 return BT_STATUS_UNSUPPORTED;
3276 /* Read out batchscan reports */
3277 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3279 CHECK_BTGATT_INIT();
3280 return BT_STATUS_UNSUPPORTED;
3283 const btgatt_client_interface_t btgatt_client_interface = {
3284 .register_client = btif_gattc_register_client,
3285 .unregister_client = btif_gattc_unregister_client,
3287 .connect = btif_gattc_client_connect,
3288 .disconnect = btif_gattc_client_disconnect,
3290 .search_service = btif_gattc_client_search_service,
3291 .get_included_service = get_included_service,
3292 .get_characteristic = btif_gattc_get_characteristic,
3293 .get_descriptor = btif_gattc_get_descriptor,
3294 .read_characteristic = btif_read_characteristic,
3295 .write_characteristic = btif_write_characteristic,
3296 .acquire_write = btif_get_acquire_write_fd,
3297 .acquire_notify = btif_get_acquire_notify_fd,
3298 .read_descriptor = btif_read_descriptor,
3299 .write_descriptor = btif_write_descriptor,
3300 .execute_write = execute_write,
3301 .register_for_notification = btif_register_for_notification,
3302 .deregister_for_notification = btif_deregister_for_notification,
3303 .read_remote_rssi = read_remote_rssi,
3304 .ota_fw_update = ota_fw_update,
3305 .get_device_type = get_device_type,
3306 .conn_parameter_update = btif_gattc_conn_parameter_update,
3307 .test_command = test_command,
3308 .configure_mtu = configure_mtu,
3309 .scan_filter_param_setup = scan_filter_param_setup,
3310 .scan_filter_add_remove = scan_filter_add_remove,
3311 .scan_filter_clear = scan_filter_clear,
3312 .scan_filter_enable = scan_filter_enable,
3313 .set_scan_parameters = set_scan_parameters,
3314 .batchscan_cfg_storage = batchscan_cfg_storage,
3315 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3316 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3317 .batchscan_read_reports = batchscan_read_reports
3320 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr)
3325 hal_gattc_server_info_t *info = NULL;
3327 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3328 info = (hal_gattc_server_info_t*)l->data;
3332 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
3333 INFO("GATT connection found addr");
3340 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3345 hal_gattc_client_info_t *info = NULL;
3347 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3348 info = (hal_gattc_client_info_t*)l->data;
3352 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
3353 INFO("GATT client info found addr");
3360 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3365 hal_gattc_client_info_t *info = NULL;
3367 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3368 info = (hal_gattc_client_info_t*)l->data;
3372 if (info->conn_id == conn_id) {
3373 INFO("GATT client info found for conn_id [%d]", conn_id);
3380 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3385 hal_gattc_server_info_t *info = NULL;
3386 hal_gattc_client_info_t *gattc_client = NULL;
3388 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3389 if (gattc_client == NULL) {
3390 INFO("GATT client conn info not found");
3394 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3395 info = (hal_gattc_server_info_t*)l->data;
3399 if ((info->inst_id == gattc_client->inst_id) &&
3400 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3401 INFO("GATT connection found for conn_id [%d]", conn_id);
3408 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3409 gboolean auto_connect)
3411 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3412 gchar *device_path = NULL;
3413 GDBusProxy *device_proxy = NULL;
3414 GDBusConnection *conn;
3415 int ret = BT_STATUS_SUCCESS;
3416 hal_gattc_client_info_t *gattc_data;
3420 if (NULL == bd_addr) {
3421 ERR("bd_addr is NULL");
3422 return BT_STATUS_PARM_INVALID;
3425 conn = _bt_hal_get_system_gconn();
3427 ERR("_bt_gdbus_get_system_gconn returned NULL");
3428 return BT_STATUS_FAIL;
3431 _bt_hal_convert_addr_type_to_string(device_address,
3432 (unsigned char *)bd_addr->address);
3433 device_path = _bt_hal_get_device_object_path(device_address);
3434 if (device_path == NULL) {
3435 ERR("device_path NULL : [%s]", device_address);
3436 ret = BT_STATUS_FAIL;
3439 ERR("device_path:%s", device_path);
3441 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3442 NULL, BT_HAL_BLUEZ_NAME,
3443 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3444 g_free(device_path);
3445 if (NULL == device_proxy) {
3446 ERR("device_proxy returned NULL");
3447 return BT_STATUS_FAIL;
3450 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3451 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3452 BT_HAL_ADDRESS_LENGTH_MAX);
3454 DBG("Connect LE [%s]", device_address);
3456 gattc_data->client_if = client_if;
3458 g_dbus_proxy_call(device_proxy, "ConnectLE",
3459 g_variant_new("(b)", auto_connect),
3460 G_DBUS_CALL_FLAGS_NONE,
3461 BT_HAL_MAX_DBUS_TIMEOUT,
3463 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3468 static bt_status_t _bt_hold_current_advertising()
3470 int ret = BT_STATUS_FAIL;
3471 gboolean is_advertising = FALSE;
3474 is_advertising = _bt_hal_is_advertising_in_slot(0);
3475 if (is_advertising) {
3476 DBG("+ Stop current advertising");
3478 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3479 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3485 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3487 DBG("+ start current advertising");
3489 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3494 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3496 DBG("Try to initiate pending LE connection");
3498 pending_le_conn_timer_id = 0;
3500 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3501 &pending_le_conn_info->bd_addr,
3502 pending_le_conn_info->auto_connect);
3504 g_free(pending_le_conn_info);
3505 pending_le_conn_info = NULL;
3510 static int __hal_generate_conn_id()
3512 return ++bt_conn_id;
3515 static int __hal_generate_server_instance_id()
3517 return ++bt_inst_id;
3520 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3523 GError *g_error = NULL;
3524 GVariant *reply = NULL;
3525 hal_gattc_client_info_t *gattc_data = user_data;
3526 int result = BT_STATUS_SUCCESS;
3527 struct hal_ev_gatt_client_connected ev;
3528 hal_gattc_server_info_t *gatt_conn_info = NULL;
3532 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3533 g_object_unref(proxy);
3534 if (reply == NULL) {
3535 ERR("Connect LE Dbus Call Error");
3537 ERR("Error: %s\n", g_error->message);
3538 g_clear_error(&g_error);
3540 result = BT_STATUS_FAIL;
3542 g_variant_unref(reply);
3544 if (NULL == gattc_data) {
3545 ERR("server_data is NULL");
3550 if (result == BT_STATUS_FAIL) {
3551 memset(&ev, 0, sizeof(ev));
3554 ev.client_if = gattc_data->client_if;
3555 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3556 BT_HAL_ADDRESS_LENGTH_MAX);
3559 ERR("gatt client callback not registered");
3561 DBG("sending gatt client connected event");
3562 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3568 DBG("adding the server conn info in list");
3569 gattc_data->conn_id = __hal_generate_conn_id() ;
3570 gattc_data->inst_id = __hal_generate_server_instance_id();
3572 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3574 /*add gatt server connection info*/
3575 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3576 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3577 gatt_conn_info->inst_id = gattc_data->inst_id;
3578 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3584 /*remove conn_info*/
3589 void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3591 g_free(svc_info->svc_path);
3595 void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3597 g_free(char_info->chr_path);
3601 void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3603 g_free(desc_info->desc_path);
3607 void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3612 hal_gattc_service_t *svc_info = NULL;
3613 hal_gattc_char_t *char_info = NULL;
3614 hal_gattc_desc_t *desc_info = NULL;
3618 for (l = conn_info->gatt_list_services; l != NULL;) {
3619 svc_info = (hal_gattc_service_t*)l->data;
3620 if (svc_info == NULL)
3622 l = g_slist_next(l);
3624 for (m = svc_info->gatt_list_chars; m != NULL; ) {
3625 char_info = (hal_gattc_char_t*)m->data;
3626 if (char_info == NULL)
3628 m = g_slist_next(m);
3630 for (k = char_info->gatt_list_descs; k != NULL; ) {
3631 desc_info = (hal_gattc_desc_t*)k->data;
3632 if (desc_info == NULL)
3634 k = g_slist_next(k);
3636 /*remove desc element*/
3637 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3638 __hal_gattc_free_desc_info(desc_info);
3641 /*remove desc list*/
3642 g_slist_free(char_info->gatt_list_descs);
3643 char_info->gatt_list_descs = NULL;
3645 /*remove char element*/
3646 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3647 __hal_gattc_free_char_info(char_info);
3650 /*remove char list*/
3651 g_slist_free(svc_info->gatt_list_chars);
3652 svc_info->gatt_list_chars = NULL;
3654 /*remove svc element*/
3655 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3656 __hal_gattc_free_svc_info(svc_info);
3659 /*remove svc list */
3660 g_slist_free(conn_info->gatt_list_services);
3661 conn_info->gatt_list_services = NULL;
3663 /*remove conn info*/
3667 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3669 bt_bdaddr_t bd_addr;
3670 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3671 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3677 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3679 int result = BT_STATUS_SUCCESS;
3680 struct hal_ev_gatt_client_connected ev;
3681 hal_gattc_server_info_t *conn_info = NULL;
3682 bt_bdaddr_t bd_addr;
3684 hal_gattc_client_info_t *gattc_client = NULL;
3688 DBG("+ connected device address [%s]", address);
3690 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3691 HAL_EV_GATT_CLIENT_DISCONNECTED;
3693 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3694 /* find the gatt client info */
3695 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3696 if (NULL == gattc_client) {
3697 ERR("Fail to get gatt client info");
3702 memset(&ev, 0, sizeof(ev));
3703 ev.conn_id = gattc_client->conn_id;
3705 ev.client_if = gattc_client->client_if;
3706 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3707 BT_HAL_ADDRESS_LENGTH_MAX);
3710 ERR("gatt client callback not registered");
3712 DBG("sending gatt client connected status event");
3713 event_cb(event, (void *)&ev, sizeof(ev));
3716 if (!gatt_connected) {
3717 inst_id = gattc_client->inst_id;
3719 /* remove the gatt client info from the client list also*/
3720 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3721 g_free(gattc_client);
3723 //find the connected server info
3724 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3725 if (NULL == conn_info) {
3726 ERR("Fail to get gatt server info");
3730 if (inst_id != conn_info->inst_id) {
3731 ERR("server instance is different");
3735 //remove gatt conn info from the server list
3736 DBG("remove the server conn_info from list after gatt disconnection");
3737 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3738 __hal_clean_gattc_server_info(conn_info);
3744 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3745 const char* uuid_str, int inst_id)
3747 struct hal_ev_gatt_client_search_result ev;
3750 ERR("gatt client callback not registered");
3754 DBG("sending gatt client search service result event conn_id[%d]", conn_id);
3756 memset(&ev, 0, sizeof(ev));
3757 ev.conn_id = conn_id;
3758 ev.inst_id = inst_id;
3759 ev.is_primary = is_primary;
3760 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3762 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3765 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3767 struct hal_ev_gatt_client_search_complete ev;
3770 ERR("gatt client callback not registered");
3774 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3777 memset(&ev, 0, sizeof(ev));
3778 ev.conn_id = conn_id;
3781 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3784 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3785 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3786 char *char_value, int len)
3788 struct hal_ev_gatt_client_notify_changed_value ev;
3789 hal_gattc_client_info_t *gattc_client = NULL;
3792 ERR("gatt client callback not registered");
3796 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3797 if (NULL == gattc_client) {
3798 ERR("failed to get the gatt client info");
3803 DBG("sending gatt client connected status event");
3804 memset(&ev, 0, sizeof(ev));
3806 ev.conn_id = gattc_client->conn_id;
3807 ev.inst_id = conn_info->inst_id;
3808 ev.is_primary = svc_info->is_primary;
3809 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3810 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3812 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3814 if (len > 0 && (char_value != NULL)) {
3815 memcpy(ev.value, char_value, len);
3819 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3822 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3823 char *char_value, int len)
3825 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3826 hal_gattc_server_info_t *conn_info = NULL;
3827 bt_bdaddr_t bd_addr;
3830 hal_gattc_service_t *svc_info = NULL;
3831 hal_gattc_char_t *char_info = NULL;
3835 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3836 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3837 DBG("device address:[%s]", device_address);
3838 DBG("char handle:[%s]", char_handle);
3840 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3841 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3843 if (conn_info != NULL) {
3844 //find service for notified char path
3845 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3846 svc_info = (hal_gattc_service_t*)l->data;
3847 if (svc_info == NULL)
3850 /* find characteristic object path */
3851 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3852 char_info = (hal_gattc_char_t *)k->data;
3853 if (char_info == NULL)
3856 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3857 DBG("Found char handle[%s]", char_info->chr_path);
3860 _bt_hal_send_value_changed_event(conn_info, svc_info,
3861 char_info, char_value, len);