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>
33 #include "bt-hal-log.h"
34 #include "bt-hal-msg.h"
35 #include "bt-hal-event-receiver.h"
36 #include "bt-hal-adapter-le.h"
38 #include "bt-hal-gatt-client.h"
39 #include "bt-hal-dbus-common-utils.h"
40 #include "bt-hal-utils.h"
42 /************************************************************************************
44 ************************************************************************************/
45 extern const btgatt_callbacks_t *bt_gatt_callbacks;
46 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
48 ERR("%s: BTGATT not initialized", __FUNCTION__);\
49 return BT_STATUS_NOT_READY;\
51 DBG("%s", __FUNCTION__);\
55 int le_scan_type = BT_GATTC_LE_SCAN_TYPE_PASSIVE;
58 static handle_stack_msg event_cb = NULL;
60 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
61 #define MAX_HAL_OBJECT_PATH_LEN 100
64 HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST = 0x01,
65 HAL_GATT_CHARACTERISTIC_PROPERTY_READ = 0x02,
66 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE = 0x04,
67 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE = 0x08,
68 HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY = 0x10,
69 HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE = 0x20,
70 HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE = 0x40,
71 HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE = 0x80,
72 HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES = 0x100,
73 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ = 0x200,
74 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE = 0x400,
75 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ = 0x800,
76 HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE = 0x1000,
77 HAL_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS = 0xffff,
78 } bt_gatt_characteristic_property_t;
82 HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE = 1,
83 HAL_GATT_WRITE_TYPE_WRITE ,
84 } hal_gatt_write_type_t;
88 HAL_GATT_PROPERTY_BROADCAST = 0x01, /**< Broadcast property */
89 HAL_GATT_PROPERTY_READ = 0x02, /**< Read property */
90 HAL_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE = 0x04, /**< Write without response property */
91 HAL_GATT_PROPERTY_WRITE = 0x08, /**< Write property */
92 HAL_GATT_PROPERTY_NOTIFY = 0x10, /**< Notify property */
93 HAL_GATT_PROPERTY_INDICATE = 0x20, /**< Indicate property */
94 HAL_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES = 0x40, /**< Authenticated signed writes property */
95 HAL_GATT_PROPERTY_EXTENDED_PROPERTIES = 0x80, /**< Extended properties */
96 } hal_gatt_property_e;
101 gboolean auto_connect;
102 } bt_pending_le_conn_info_s;
112 unsigned int permission;
113 GSList *gatt_list_descs;
119 GSList *gatt_list_chars;
120 } hal_gattc_service_t;
123 bt_bdaddr_t bd_addr; /*remote server address*/
124 int inst_id; /*server instance id*/
125 GSList *gatt_list_services;
126 } hal_gattc_server_info_t;
128 /* Linked List of connected GATT server */
129 static GSList *hal_gattc_server_info_list = NULL;
133 bt_bdaddr_t bd_addr; /*remote server address*/
136 } hal_gattc_client_info_t;
138 /* Linked list of connected GATT client connection */
139 static GSList * hal_gattc_client_info_list = NULL;
141 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
142 static guint pending_le_conn_timer_id = 0;
143 static int bt_conn_id = 0;
144 static int bt_inst_id = 0;
146 #define BT_GATTC_CL_MAX 32
151 btgatt_srvc_id_t srvc_id;
152 btgatt_gatt_id_t char_id;
153 btgatt_gatt_id_t desc_id;
154 } hal_gatt_resp_data_t;
159 } hal_gatt_client_app;
161 static GSList * hal_gattc_client_app_list = NULL;
163 static int bt_client_if = 0;
166 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
167 gboolean auto_connect);
168 static bt_status_t _bt_hold_current_advertising();
169 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
170 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
171 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
173 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
174 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
175 const char* uuid_str, int inst_id);
176 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
177 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr);
178 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
181 /* To send stack event to hal-av handler */
182 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
187 void _bt_hal_unregister_gatt_client_handler_cb(void)
193 int _bt_hal_gatt_client_get_le_scan_type(void)
199 static gboolean __bt_hal_register_client_cb(gpointer user_data)
201 struct hal_ev_gatt_client_registered ev;
202 hal_gatt_client_app *client_info = user_data;
205 /* Prepare to send AV connecting event */
206 memset(&ev, 0, sizeof(ev));
207 ev.status = BT_STATUS_SUCCESS;
208 ev.client_if = client_info->client_if;
209 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
212 ERR("GATT Callback not registered");
214 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
215 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
222 static int __hal_generate_client_id()
224 return ++bt_client_if;
227 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
230 hal_gatt_client_app *info = NULL;
231 hal_gatt_client_app *gattc_app = NULL;
233 //check if client app is already registered
234 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
235 info = (hal_gatt_client_app*)l->data;
239 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
240 DBG("gatt client app already registered");
245 DBG("adding the gatt client app");
248 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
249 if (gattc_app == NULL) {
250 DBG("Failed to allocate memory");
254 gattc_app->client_if = __hal_generate_client_id();
255 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
257 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
262 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
264 hal_gatt_client_app *gattc_app = NULL;
265 hal_gatt_client_app *client_app_info = NULL;
268 /* add gatt client in list */
269 gattc_app = __hal_gattc_add_client_app(app_uuid);
270 if (gattc_app == NULL) {
271 ERR("Failed to register gatt client app");
272 return BT_STATUS_FAIL;
276 client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
277 if (NULL == client_app_info) {
278 ERR("Failed to allocate memory");
279 return BT_STATUS_FAIL;
282 client_app_info->client_if = gattc_app->client_if;
283 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
284 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
286 DBG("registered client client_if [%d]", client_app_info->client_if);
288 return BT_STATUS_SUCCESS;
291 /** Registers a GATT client application with the stack */
292 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
297 return __hal_gattc_register_client_app(uuid);
300 bt_status_t __hal_gattc_unregister_client(int client_if)
303 hal_gatt_client_app *info = NULL;
305 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
307 /* remove the gatt client app */
308 for (l = hal_gattc_client_app_list; l != NULL; ) {
309 info = (hal_gatt_client_app*)l->data;
315 if (info->client_if == client_if) {
316 DBG("gatt client app found");
317 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
322 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
323 return BT_STATUS_SUCCESS;
326 /** Unregister a client application from the stack */
327 bt_status_t btif_gattc_unregister_client(int client_if)
332 return __hal_gattc_unregister_client(client_if);
335 /** Start or stop LE device scanning */
336 bt_status_t scan(int client_if, bool start)
343 ret = _bt_hal_adapter_le_start_scan();
345 ret = _bt_hal_adapter_le_stop_scan();
350 /** Create a connection to a remote LE or dual-mode device */
351 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
354 int ret = BT_STATUS_SUCCESS;
360 return BT_STATUS_PARM_INVALID;
362 ret = _bt_hold_current_advertising();
363 if (ret == BT_STATUS_SUCCESS) {
364 DBG("Current advertising is held");
365 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
366 pending_le_conn_info->client_if = client_if;
367 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
368 BT_HAL_ADDRESS_LENGTH_MAX);
369 pending_le_conn_info->auto_connect = is_direct;
371 pending_le_conn_timer_id =
372 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
374 return BT_STATUS_SUCCESS;
376 ERR("advertising is not stopped");
379 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
383 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
386 GError *g_error = NULL;
387 GVariant *reply = NULL;
388 hal_gattc_client_info_t *gatt_conn_info = user_data;
389 int result = BT_STATUS_SUCCESS;
390 struct hal_ev_gatt_client_connected ev;
394 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
395 g_object_unref(proxy);
397 ERR("Connect LE Dbus Call Error");
399 ERR("Error: %s\n", g_error->message);
400 g_clear_error(&g_error);
402 result = BT_STATUS_FAIL;
404 g_variant_unref(reply);
406 if (NULL == gatt_conn_info) {
407 ERR("server_data is NULL");
412 if (result == BT_STATUS_FAIL) {
413 memset(&ev, 0, sizeof(ev));
414 ev.conn_id = gatt_conn_info->conn_id;
416 ev.client_if = gatt_conn_info->client_if;
417 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
418 BT_HAL_ADDRESS_LENGTH_MAX);
421 ERR("gatt client callback not registered");
423 DBG("sending gatt client disconnected event");
424 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
430 g_free(gatt_conn_info);
435 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
438 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
440 GDBusProxy *device_proxy;
441 GDBusConnection *conn;
442 int ret = BT_STATUS_SUCCESS;
443 hal_gattc_client_info_t *gattc_data;
445 if (NULL == bd_addr) {
446 ERR("bd_addr is NULL");
447 return BT_STATUS_PARM_INVALID;
450 conn = _bt_hal_get_system_gconn();
452 ERR("_bt_gdbus_get_system_gconn returned NULL");
453 return BT_STATUS_FAIL;
456 _bt_hal_convert_addr_type_to_string(device_address,
457 (unsigned char *)bd_addr->address);
458 device_path = _bt_hal_get_device_object_path(device_address);
459 if (device_path == NULL) {
460 DBG("device_path NULL");
461 ret = BT_STATUS_FAIL;
465 ERR("device_path:%s", device_path);
467 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
468 NULL, BT_HAL_BLUEZ_NAME,
469 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
471 if (NULL == device_proxy) {
472 ERR("device_proxy returned NULL");
473 return BT_STATUS_FAIL;
476 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
477 if (NULL == gattc_data) {
478 ERR("Unable to allocate memory");
479 ret = BT_STATUS_FAIL;
483 memcpy(gattc_data->bd_addr.address, bd_addr->address,
484 BT_HAL_ADDRESS_LENGTH_MAX);
485 gattc_data->client_if = client_if;
486 gattc_data->conn_id = conn_id;
488 DBG("DisconnectLE [%s]", device_address);
490 g_dbus_proxy_call(device_proxy, "DisconnectLE",
492 G_DBUS_CALL_FLAGS_NONE,
493 BT_HAL_MAX_DBUS_TIMEOUT,
495 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
499 g_object_unref(device_proxy);
506 /** Disconnect a remote device or cancel a pending connection */
507 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
514 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
517 /** Clear the attribute cache for a given device */
518 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
521 return BT_STATUS_UNSUPPORTED;
524 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
529 hal_gattc_service_t *info = NULL;
531 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
532 info = (hal_gattc_service_t*)l->data;
536 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t))) {
537 INFO("Found GATT service uuid");
545 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
546 bt_gatt_characteristic_property_t prop)
551 hal_gattc_char_t *info = NULL;
553 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
554 info = (hal_gattc_char_t*)l->data;
558 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
559 (info->permission & prop)) {
560 INFO("Found GATT char uuid");
567 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
572 hal_gattc_desc_t *info = NULL;
574 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
575 info = (hal_gattc_desc_t*)l->data;
579 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t))) {
580 INFO("Found GATT descriptor uuid");
588 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
589 const char *uuid_str, char *object_path)
592 hal_gattc_service_t *gattc_service = NULL;
594 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
595 gattc_service->svc_path = g_strdup(object_path);
596 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
598 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
600 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
602 DBG("svc path {%s] svc uuid [%s]", object_path, uuid_str);
604 return gattc_service;
607 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
610 hal_gattc_char_t *gattc_char = NULL;
612 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
613 gattc_char->chr_path = g_strdup(char_handle);
615 DBG("svc path: [%s]", gatt_svc->svc_path);
616 DBG("char path: [%s]", gattc_char->chr_path);
618 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
621 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
622 const char* uuid_str, char *object_path, GPtrArray *gp_char_array)
624 hal_gattc_service_t* gatt_svc = NULL;
626 gchar *gp_char_path = NULL;
630 /* add the service */
631 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path);
632 if (gatt_svc == NULL) {
633 ERR("Failed to add service");
637 /* add the characteristic */
638 for (i = 0; i < gp_char_array->len; i++) {
639 gp_char_path = g_ptr_array_index(gp_char_array, i);
640 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
643 g_ptr_array_free(gp_char_array, TRUE);
646 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
648 hal_gattc_desc_t *gattc_desc = NULL;
650 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
651 gattc_desc->desc_path = g_strdup(desc_path);
653 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
655 DBG("char path: [%s]", gattc_char->chr_path);
656 DBG("desc path: [%s]", gattc_desc->desc_path);
659 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
660 GPtrArray *gp_desc_array, unsigned int char_permission)
662 gchar *gp_desc_path = NULL;
667 if (char_uuid_str == NULL) {
668 DBG("char_uuid_str is NULL");
672 //update the char uuid
673 DBG("char UUID: [%s] ", char_uuid_str);
674 DBG("char path: [%s]", gattc_char->chr_path);
676 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
678 //update char permission
679 gattc_char->permission = char_permission;
682 for (i = 0; i < gp_desc_array->len; i++) {
683 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
684 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
688 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
692 if (desc_uuid_str == NULL) {
693 DBG("char_uuid_str is NULL");
697 //update the descriptor uuid
698 DBG("desc UUID: [%s] ", desc_uuid_str);
699 DBG("desc path: [%s]", gattc_desc->desc_path);
701 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
704 static void browse_service_char(int conn_id)
706 hal_gattc_server_info_t *conn_info = NULL;
710 hal_gattc_service_t *svc_info = NULL;
711 hal_gattc_char_t *char_info = NULL;
712 hal_gattc_desc_t *desc_info = NULL;
716 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
717 if (conn_info == NULL) {
718 DBG("conn_info is NULL");
722 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
724 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
725 svc_info = (hal_gattc_service_t*)l->data;
726 if (svc_info == NULL)
729 DBG("svc path [%s]", svc_info->svc_path);
731 /* find characteristic object path */
732 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
733 char_info = (hal_gattc_char_t *)k->data;
734 if (char_info == NULL)
737 DBG("char path[%s]", char_info->chr_path);
740 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
741 desc_info = (hal_gattc_desc_t *)m->data;
742 if (desc_info == NULL)
745 DBG("desc path[%s]", desc_info->desc_path);
754 * Enumerate all GATT services on a connected device.
755 * Optionally, the results can be filtered for a given UUID.
757 static bt_status_t _gattc_client_search_service(int conn_id)
761 GVariant *result = NULL;
763 GVariantIter *svc_iter;
764 GVariantIter *interface_iter;
765 char *object_path = NULL;
766 char *interface_str = NULL;
767 const gchar *key = NULL;
768 GVariant *value = NULL;
769 GPtrArray *gp_array = NULL;
770 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
771 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
772 int ret = BT_STATUS_FAIL;
774 const gchar *uuid_str = NULL;
776 hal_gattc_server_info_t *conn_info = NULL;
777 gboolean is_primary = FALSE;
780 char *char_handle = NULL;
781 GVariantIter *char_iter = NULL;
782 GPtrArray *gp_char_array = NULL;
786 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
787 if (NULL == conn_info) {
788 DBG("Failed to get the conn_info");
789 return BT_STATUS_FAIL;
792 _bt_hal_convert_addr_type_to_string(device_address,
793 (unsigned char *)conn_info->bd_addr.address);
795 result = _bt_hal_get_managed_objects();
799 gp_array = g_ptr_array_new();
800 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
802 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
804 if (object_path == NULL)
807 _bt_hal_convert_device_path_to_address(object_path, temp_address);
809 if (g_strcmp0(temp_address, device_address) != 0)
812 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
813 &interface_str, &svc_iter)) {
814 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
817 DBG("[%d] Object Path : %s", idx++, object_path);
818 /* for characteristic */
819 gp_char_array = g_ptr_array_new();
820 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
821 if (g_strcmp0(key, "Primary") == 0) {
822 is_primary = g_variant_get_boolean(value);
825 g_ptr_array_add(gp_array, (gpointer)object_path);
828 } else if (g_strcmp0(key, "UUID") == 0) {
829 uuid_str = g_variant_get_string(value, &len);
830 DBG(" UUID: [%s]", uuid_str);
831 } else if (g_strcmp0(key, "Characteristics") == 0) {
832 g_variant_get(value, "ao", &char_iter);
833 if (char_iter != NULL) {
834 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
835 DBG("char handle : %s", char_handle);
836 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
843 DBG("send search service result event");
844 _bt_hal_send_search_service_result_event(conn_id, is_primary,
845 uuid_str, conn_info->inst_id);
847 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
852 if (gp_array->len == 0 || svc_count == 0) {
853 ERR("gp_array is NULL");
854 ret = BT_STATUS_FAIL;
856 ret = BT_STATUS_SUCCESS;
859 browse_service_char(conn_id);
860 /* send search service complete event */
861 _bt_hal_send_search_service_complete_event(conn_id, ret);
863 g_ptr_array_free(gp_array, TRUE);
864 g_variant_iter_free(iter);
865 g_variant_unref(result);
870 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
872 if (NULL == filter_uuid) {
873 DBG("Browse all the services");
874 return _gattc_client_search_service(conn_id);
876 DBG("TODO implement it");
877 return BT_STATUS_UNSUPPORTED;
881 * Enumerate included services for a given service.
882 * Set start_incl_srvc_id to NULL to get the first included service.
884 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
885 btgatt_srvc_id_t *start_incl_srvc_id)
888 return BT_STATUS_UNSUPPORTED;
891 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
892 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
894 struct hal_ev_gatt_client_char_search_result ev;
897 ERR("gatt client callback not registered");
901 DBG("sending gatt client search char result event conn_id[%d] status[%d]", conn_id, status);
903 memset(&ev, 0, sizeof(ev));
904 ev.conn_id = conn_id;
905 ev.inst_id = svc_id->id.inst_id;
906 ev.is_primary = svc_id->is_primary;
908 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
910 if (status == BT_STATUS_SUCCESS) {
911 DBG("building char uuid");
912 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
913 ev.char_prop = char_prop;
916 DBG("sending the char search event");
918 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
921 static int _hal_get_permission_flag(char *permission)
925 if (NULL == permission) {
926 ERR("gatt permission is NULL");
930 if (!g_strcmp0(permission, "broadcast"))
931 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
932 else if (!g_strcmp0(permission, "read"))
933 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
934 else if (!g_strcmp0(permission, "write-without-response"))
935 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
936 else if (!g_strcmp0(permission, "write"))
937 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
938 else if (!g_strcmp0(permission, "notify"))
939 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
940 else if (!g_strcmp0(permission, "indicate"))
941 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
942 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
943 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
944 else if (!g_strcmp0(permission, "reliable-write"))
945 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
946 else if (!g_strcmp0(permission, "writable-auxiliaries"))
947 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
948 else if (!g_strcmp0(permission, "encrypt-read"))
949 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
950 else if (!g_strcmp0(permission, "encrypt-write"))
951 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
952 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
953 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
954 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
955 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
961 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
963 GDBusProxy *properties_proxy = NULL;
964 GError *error = NULL;
965 GVariant *value = NULL;
966 GVariant *result = NULL;
967 GDBusConnection *g_conn;
969 char *char_desc_handle = NULL;
971 GVariantIter *property_iter;
972 GVariantIter *char_desc_iter;
973 char* char_handle = NULL;
974 gchar *char_uuid_str = NULL;
975 GPtrArray *gp_desc_array = NULL;
976 GVariantIter *char_perm_iter;
978 unsigned int char_permission = 0 ;
982 if (gattc_char->chr_path == NULL) {
983 DBG("char path is NULL");
984 return BT_STATUS_FAIL;
986 char_handle = gattc_char->chr_path;
988 DBG("char path:[%s]", gattc_char->chr_path);
990 g_conn = _bt_hal_get_system_gconn();
991 if (NULL == g_conn) {
992 ERR("_bt_gdbus_get_system_gconn returned NULL");
993 return BT_STATUS_FAIL;
996 properties_proxy = g_dbus_proxy_new_sync(g_conn,
997 G_DBUS_PROXY_FLAGS_NONE, NULL,
1000 BT_HAL_PROPERTIES_INTERFACE,
1003 if (properties_proxy == NULL) {
1004 ERR("properties_proxy returned NULL");
1005 return BT_STATUS_FAIL;
1008 result = g_dbus_proxy_call_sync(properties_proxy,
1010 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1011 G_DBUS_CALL_FLAGS_NONE,
1016 if (error != NULL) {
1017 ERR("Fail to get properties (Error: %s)", error->message);
1018 g_clear_error(&error);
1020 ERR("Fail to get properties");
1021 g_object_unref(properties_proxy);
1022 return BT_STATUS_FAIL;
1025 gp_desc_array = g_ptr_array_new();
1027 g_variant_get(result, "(a{sv})", &property_iter);
1029 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1030 if (!g_strcmp0(key, "UUID")) {
1031 char_uuid_str = g_variant_dup_string(value, &len);
1032 DBG("char UUID [%s]", char_uuid_str);
1033 } else if (!g_strcmp0(key, "Flags")) {
1034 g_variant_get(value, "as", &char_perm_iter);
1035 char_permission = 0x00;
1037 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1038 DBG("char permission: [%s]", permission);
1039 char_permission |= _hal_get_permission_flag(permission);
1041 } else if (!g_strcmp0(key, "Descriptors")) {
1042 g_variant_get(value, "ao", &char_desc_iter);
1043 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1044 DBG("char descriptor handle : %s", char_desc_handle);
1046 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1051 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1053 g_free(char_uuid_str);
1054 g_variant_iter_free(property_iter);
1055 g_variant_unref(result);
1056 g_object_unref(properties_proxy);
1057 g_ptr_array_free(gp_desc_array, TRUE);
1059 return BT_STATUS_SUCCESS;
1062 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1063 btgatt_srvc_id_t *srvc_id)
1065 hal_gattc_server_info_t * conn_info = NULL;
1066 hal_gattc_service_t *gattc_service = NULL;
1068 hal_gattc_char_t *gattc_char = NULL;
1069 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1070 int status = BT_STATUS_FAIL;
1073 DBG("conn_id[%d]", conn_id);
1075 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1076 if (NULL == conn_info) {
1077 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1078 return BT_STATUS_FAIL;
1082 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1083 if (NULL == gattc_service) {
1084 DBG("Failed to get the gatt service");
1085 return BT_STATUS_FAIL;
1088 DBG("service path [%s]", gattc_service->svc_path);
1090 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1091 DBG("service uuid [%s]", svc_uuid_str);
1093 /* find characteristic object path */
1094 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1095 gattc_char = (hal_gattc_char_t *)l->data;
1096 status = _hal_gattc_get_characteristic_info(gattc_char);
1099 if (BT_STATUS_SUCCESS == status) {
1100 DBG("Sending the success charateristics event");
1101 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1102 &gattc_char->chr_uuid, gattc_char->permission);
1106 DBG("sending final event");
1108 status = BT_STATUS_FAIL;
1109 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1111 browse_service_char(conn_id);
1112 /* retrive uuid for characteristic and object path for descriptor */
1114 return BT_STATUS_SUCCESS;
1118 * Enumerate characteristics for a given service.
1119 * Set start_char_id to NULL to get the first characteristic.
1121 bt_status_t btif_gattc_get_characteristic(int conn_id,
1122 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1125 CHECK_BTGATT_INIT();
1127 if (start_char_id == NULL) {
1128 DBG("Get all the characteristics");
1129 return _gattc_get_all_characteristic(conn_id, srvc_id);
1132 DBG("TBD Get specific characteristics");
1133 return BT_STATUS_UNSUPPORTED;
1137 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1139 GDBusProxy *properties_proxy = NULL;
1140 GError *error = NULL;
1141 GVariant *value = NULL;
1142 GVariant *result = NULL;
1143 GDBusConnection *g_conn;
1146 GVariantIter *property_iter;
1147 char* desc_handle = NULL;
1148 const gchar *desc_uuid_str = NULL;
1152 if (gattc_desc->desc_path == NULL) {
1153 DBG("desc path is NULL");
1154 return BT_STATUS_FAIL;
1156 desc_handle = gattc_desc->desc_path;
1158 DBG("desc path:[%s]", gattc_desc->desc_path);
1160 g_conn = _bt_hal_get_system_gconn();
1161 if (NULL == g_conn) {
1162 ERR("_bt_gdbus_get_system_gconn returned NULL");
1163 return BT_STATUS_FAIL;
1166 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1167 G_DBUS_PROXY_FLAGS_NONE, NULL,
1170 BT_HAL_PROPERTIES_INTERFACE,
1173 if (properties_proxy == NULL) {
1174 ERR("properties_proxy returned NULL");
1175 return BT_STATUS_FAIL;
1178 result = g_dbus_proxy_call_sync(properties_proxy,
1180 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1181 G_DBUS_CALL_FLAGS_NONE,
1186 if (error != NULL) {
1187 ERR("Fail to get properties (Error: %s)", error->message);
1188 g_clear_error(&error);
1190 ERR("Fail to get properties");
1191 g_object_unref(properties_proxy);
1192 return BT_STATUS_FAIL;
1195 g_variant_get(result, "(a{sv})", &property_iter);
1197 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1198 if (!g_strcmp0(key, "UUID")) {
1199 desc_uuid_str = g_variant_get_string(value, &len);
1200 DBG("desc UUID [%s]", desc_uuid_str);
1201 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1206 g_variant_iter_free(property_iter);
1207 g_variant_unref(result);
1208 g_object_unref(properties_proxy);
1210 return BT_STATUS_SUCCESS;
1213 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1214 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1216 struct hal_ev_gatt_client_desc_search_result ev;
1219 ERR("gatt client callback not registered");
1223 DBG("sending gatt client search desc result event conn_id[%d] status[%d]", conn_id, status);
1225 memset(&ev, 0, sizeof(ev));
1226 ev.conn_id = conn_id;
1227 ev.inst_id = svc_id->id.inst_id;
1228 ev.is_primary = svc_id->is_primary;
1231 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1232 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1234 if (status == BT_STATUS_SUCCESS) {
1235 DBG("building desc uuid");
1236 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1239 DBG("sending the desc search event");
1241 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1244 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1245 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1247 hal_gattc_server_info_t * conn_info = NULL;
1248 hal_gattc_service_t *gattc_service = NULL;
1251 hal_gattc_char_t *gattc_char = NULL;
1252 hal_gattc_desc_t *gattc_desc = NULL;
1253 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1254 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1255 int status = BT_STATUS_FAIL;
1259 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1260 if (NULL == conn_info) {
1261 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1262 return BT_STATUS_FAIL;
1266 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1267 if (NULL == gattc_service) {
1268 DBG("Failed to get the gatt service");
1269 return BT_STATUS_FAIL;
1272 DBG("service path [%s]", gattc_service->svc_path);
1273 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1274 DBG("service uuid [%s]", svc_uuid_str);
1276 /* find characteristics */
1277 /* a service can have two char with same uuid */
1278 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1279 gattc_char = (hal_gattc_char_t*)l->data;
1280 if (gattc_char == NULL)
1283 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1284 INFO("Found GATT char uuid");
1285 DBG("char path [%s]", gattc_char->chr_path);
1286 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1287 DBG("char uuid [%s]", char_uuid_str);
1289 /* get descriptor uuid */
1290 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1291 gattc_desc = (hal_gattc_desc_t *)m->data;
1292 if (gattc_desc == NULL)
1295 status = _hal_gattc_get_descriptor_info(gattc_desc);
1298 if (BT_STATUS_SUCCESS == status) {
1299 DBG("Sending the success descriptor event");
1300 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1301 char_id, &gattc_desc->desc_uuid);
1307 DBG("sending final event");
1309 status = BT_STATUS_FAIL;
1310 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1312 browse_service_char(conn_id);
1313 /* retrive uuid for characteristic and object path for descriptor */
1315 return BT_STATUS_SUCCESS;
1319 * Enumerate descriptors for a given characteristic.
1320 * Set start_descr_id to NULL to get the first descriptor.
1322 bt_status_t btif_gattc_get_descriptor(int conn_id,
1323 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1324 btgatt_gatt_id_t *start_descr_id)
1327 CHECK_BTGATT_INIT();
1329 if (start_descr_id == NULL) {
1330 DBG("Get all the descriptors");
1331 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1333 DBG("TBD Get specific descriptor");
1334 return BT_STATUS_UNSUPPORTED;
1338 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1340 struct hal_ev_gatt_client_read_data ev;
1343 ERR("gatt client callback not registered");
1347 DBG("sending gatt client charac read conn_id[%d] status[%d]", resp_data->conn_id, result);
1349 memset(&ev, 0, sizeof(ev));
1350 ev.conn_id = resp_data->conn_id;
1351 ev.inst_id = resp_data->srvc_id.id.inst_id;
1352 ev.is_primary = resp_data->srvc_id.is_primary;
1355 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1356 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1360 DBG("building the char read value [%d]", len);
1361 memcpy(ev.value, value, len);
1364 DBG("sending the gatt client read charac event");
1366 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1369 static void __hal_internal_read_char_cb(GObject *source_object,
1370 GAsyncResult *res, gpointer user_data)
1372 GError *error = NULL;
1373 GDBusConnection *system_gconn = NULL;
1376 GByteArray *gp_byte_array = NULL;
1378 hal_gatt_resp_data_t *resp_data = user_data;
1379 int result = BT_STATUS_SUCCESS;
1384 system_gconn = _bt_hal_get_system_gconn();
1385 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1388 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1391 result = BT_STATUS_FAIL;
1392 __hal_send_char_read_event(resp_data, result, NULL, 0);
1393 g_clear_error(&error);
1398 gp_byte_array = g_byte_array_new();
1399 g_variant_get(value, "(ay)", &iter);
1401 while (g_variant_iter_loop(iter, "y", &g_byte))
1402 g_byte_array_append(gp_byte_array, &g_byte, 1);
1406 for (i = 0; i < gp_byte_array->len; i++)
1407 DBG("%02x", gp_byte_array->data[i]);
1410 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1414 g_byte_array_free(gp_byte_array, TRUE);
1415 g_variant_iter_free(iter);
1416 g_variant_unref(value);
1422 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1423 btgatt_gatt_id_t *char_id, int auth_req)
1425 GDBusConnection *g_conn;
1426 hal_gatt_resp_data_t *resp_data;
1427 hal_gattc_service_t *gattc_service = NULL;
1428 GVariantBuilder *builder = NULL;
1430 hal_gattc_server_info_t * conn_info = NULL;
1431 hal_gattc_char_t *gattc_char = NULL;
1432 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1433 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1434 char* char_handle = NULL;
1438 /* get the connection info */
1439 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1440 if (NULL == conn_info) {
1441 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1442 return BT_STATUS_FAIL;
1446 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1447 if (NULL == gattc_service) {
1448 DBG("Failed to get the gatt service");
1449 return BT_STATUS_FAIL;
1452 DBG("service path [%s]", gattc_service->svc_path);
1453 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1454 DBG("service uuid [%s]", svc_uuid_str);
1457 /* find characteristic */
1458 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1459 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1460 if (NULL == gattc_char) {
1461 DBG("Failed to get the gatt char");
1462 return BT_STATUS_FAIL;
1465 DBG("char path [%s]", gattc_char->chr_path);
1466 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1467 DBG("char uuid [%s]", char_uuid_str);
1469 g_conn = _bt_hal_get_system_gconn();
1470 if (NULL == g_conn) {
1471 ERR("_bt_gdbus_get_system_gconn returned NULL");
1472 return BT_STATUS_FAIL;
1475 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1476 if (NULL == resp_data) {
1477 ERR("failed to get the memory");
1478 return BT_STATUS_FAIL;
1481 resp_data->conn_id = conn_id;
1482 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1483 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1485 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1488 g_variant_builder_add(builder, "{sv}", "offset",
1489 g_variant_new("q", offset));
1491 char_handle = gattc_char->chr_path;
1493 DBG("calling char read value");
1495 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1496 "ReadValue", g_variant_new("(a{sv})", builder),
1497 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1498 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1499 (gpointer)resp_data);
1500 g_variant_builder_unref(builder);
1502 return BT_STATUS_SUCCESS;
1505 /** Read a characteristic on a remote device */
1506 bt_status_t btif_read_characteristic(int conn_id,
1507 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1510 CHECK_BTGATT_INIT();
1513 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1516 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1518 struct hal_ev_gatt_client_write_result ev;
1521 ERR("gatt client callback not registered");
1525 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
1527 memset(&ev, 0, sizeof(ev));
1528 ev.conn_id = resp_data->conn_id;
1529 ev.inst_id = resp_data->srvc_id.id.inst_id;
1530 ev.is_primary = resp_data->srvc_id.is_primary;
1533 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1534 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1536 DBG("sending the gatt client write charac event");
1538 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1541 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1542 GAsyncResult *res, gpointer user_data)
1544 GError *error = NULL;
1545 GDBusConnection *system_gconn = NULL;
1547 hal_gatt_resp_data_t *resp_data = user_data;
1548 int result = BT_STATUS_SUCCESS;
1552 system_gconn = _bt_hal_get_system_gconn();
1553 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1556 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1558 result = BT_STATUS_FAIL;
1560 __hal_send_char_write_event(resp_data, result);
1561 g_clear_error(&error);
1566 //send write value event
1567 __hal_send_char_write_event(resp_data, result);
1570 g_variant_unref(value);
1575 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1578 case HAL_GATT_WRITE_TYPE_WRITE:
1579 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1581 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1582 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1585 ERR("Unknow write type : %d", type);
1586 return BT_STATUS_FAIL;
1589 return BT_STATUS_SUCCESS;
1592 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1593 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1595 GVariant *val, *options;
1596 GVariantBuilder *builder1;
1597 GVariantBuilder *builder2;
1598 GDBusConnection *g_conn;
1601 hal_gatt_resp_data_t *resp_data;
1602 hal_gattc_service_t *gattc_service = NULL;
1603 hal_gattc_server_info_t * conn_info = NULL;
1604 hal_gattc_char_t *gattc_char = NULL;
1605 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1606 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1607 char* char_handle = NULL;
1608 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1609 int ret = BT_STATUS_SUCCESS;
1613 ret = __hal_get_write_prop(write_type, &write_prop);
1614 if (BT_STATUS_FAIL == ret) {
1615 DBG("received invalid write type:[%d] ", write_type);
1616 return BT_STATUS_FAIL;
1619 /* get the connection info */
1620 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1621 if (NULL == conn_info) {
1622 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1623 return BT_STATUS_FAIL;
1627 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1628 if (NULL == gattc_service) {
1629 DBG("Failed to get the gatt service");
1630 return BT_STATUS_FAIL;
1633 DBG("service path [%s]", gattc_service->svc_path);
1634 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1635 DBG("service uuid [%s]", svc_uuid_str);
1637 /* find characteristic */
1638 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1639 if (NULL == gattc_char) {
1640 DBG("Failed to get the gatt char");
1641 return BT_STATUS_FAIL;
1644 DBG("char path [%s]", gattc_char->chr_path);
1645 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1646 DBG("char uuid [%s]", char_uuid_str);
1648 g_conn = _bt_hal_get_system_gconn();
1649 if (NULL == g_conn) {
1650 ERR("_bt_gdbus_get_system_gconn returned NULL");
1651 return BT_STATUS_FAIL;
1654 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1655 if (NULL == resp_data) {
1656 ERR("failed to get the memory");
1657 return BT_STATUS_FAIL;
1660 resp_data->conn_id = conn_id;
1661 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1662 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1664 char_handle = gattc_char->chr_path;
1666 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1668 for (i = 0; i < length; i++)
1669 g_variant_builder_add(builder1, "y", value[i]);
1671 val = g_variant_new("ay", builder1);
1673 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1675 g_variant_builder_add(builder2, "{sv}", "offset",
1676 g_variant_new_uint16(offset));
1678 options = g_variant_new("a{sv}", builder2);
1680 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1682 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1684 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1685 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1686 (gpointer)resp_data);
1688 g_variant_builder_unref(builder1);
1689 g_variant_builder_unref(builder2);
1691 return BT_STATUS_SUCCESS;
1694 /** Write a remote characteristic */
1695 bt_status_t btif_write_characteristic(int conn_id,
1696 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1697 int write_type, int len, int auth_req,
1700 CHECK_BTGATT_INIT();
1704 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1705 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1706 len, auth_req, p_value);
1709 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1711 struct hal_ev_gatt_client_read_data ev;
1714 ERR("gatt client callback not registered");
1718 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1720 memset(&ev, 0, sizeof(ev));
1721 ev.conn_id = resp_data->conn_id;
1722 ev.inst_id = resp_data->srvc_id.id.inst_id;
1723 ev.is_primary = resp_data->srvc_id.is_primary;
1726 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1727 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1728 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1732 DBG("building the desc read value [%d]", len);
1733 memcpy(ev.value, value, len);
1736 DBG("sending the gatt client read descriptor event");
1738 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1741 static void __hal_internal_read_desc_cb(GObject *source_object,
1742 GAsyncResult *res, gpointer user_data)
1744 GError *error = NULL;
1745 GDBusConnection *system_gconn = NULL;
1748 GByteArray *gp_byte_array = NULL;
1750 hal_gatt_resp_data_t *resp_data = user_data;
1751 int result = BT_STATUS_SUCCESS;
1756 system_gconn = _bt_hal_get_system_gconn();
1757 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1760 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1763 result = BT_STATUS_FAIL;
1764 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1765 g_clear_error(&error);
1770 gp_byte_array = g_byte_array_new();
1771 g_variant_get(value, "(ay)", &iter);
1773 while (g_variant_iter_loop(iter, "y", &g_byte))
1774 g_byte_array_append(gp_byte_array, &g_byte, 1);
1778 for (i = 0; i < gp_byte_array->len; i++)
1779 DBG("%02x", gp_byte_array->data[i]);
1782 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1786 g_byte_array_free(gp_byte_array, TRUE);
1787 g_variant_iter_free(iter);
1788 g_variant_unref(value);
1793 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1794 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
1796 GDBusConnection *g_conn;
1797 hal_gatt_resp_data_t *resp_data;
1798 hal_gattc_service_t *gattc_service = NULL;
1799 GVariantBuilder *builder = NULL;
1801 hal_gattc_server_info_t * conn_info = NULL;
1802 hal_gattc_char_t *gattc_char = NULL;
1803 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1804 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1805 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
1806 char* desc_handle = NULL;
1809 hal_gattc_desc_t *gattc_desc = NULL;
1813 /* get the connection info */
1814 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1815 if (NULL == conn_info) {
1816 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
1817 return BT_STATUS_FAIL;
1821 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1822 if (NULL == gattc_service) {
1823 DBG("Failed to get the gatt service");
1824 return BT_STATUS_FAIL;
1827 DBG("service path [%s]", gattc_service->svc_path);
1828 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1829 DBG("service uuid [%s]", svc_uuid_str);
1831 /* find characteristic */
1832 /* service can have two char with same uuid */
1833 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1834 gattc_char = (hal_gattc_char_t*)l->data;
1835 if (gattc_char == NULL)
1838 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1839 INFO("Found GATT char uuid");
1840 DBG("char path [%s]", gattc_char->chr_path);
1841 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1842 DBG("char uuid [%s]", char_uuid_str);
1844 /* find descriptor */
1845 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
1847 DBG("desc path [%s]", gattc_desc->desc_path);
1848 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
1849 DBG("desc uuid [%s]", desc_uuid_str);
1855 if (NULL == gattc_desc) {
1856 DBG("Failed to get the gatt desc");
1857 return BT_STATUS_FAIL;
1860 g_conn = _bt_hal_get_system_gconn();
1861 if (NULL == g_conn) {
1862 ERR("_bt_gdbus_get_system_gconn returned NULL");
1863 return BT_STATUS_FAIL;
1866 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1867 if (NULL == resp_data) {
1868 ERR("failed to get the memory");
1869 return BT_STATUS_FAIL;
1872 resp_data->conn_id = conn_id;
1873 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1874 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1875 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
1877 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1880 g_variant_builder_add(builder, "{sv}", "offset",
1881 g_variant_new("q", offset));
1883 desc_handle = gattc_desc->desc_path;
1885 DBG("calling desc read value");
1887 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
1888 "ReadValue", g_variant_new("(a{sv})", builder),
1889 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1890 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
1891 (gpointer)resp_data);
1892 g_variant_builder_unref(builder);
1894 return BT_STATUS_SUCCESS;
1897 /** Read the descriptor for a given characteristic */
1898 bt_status_t btif_read_descriptor(int conn_id,
1899 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1900 btgatt_gatt_id_t *descr_id, int auth_req)
1902 CHECK_BTGATT_INIT();
1904 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
1907 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
1909 struct hal_ev_gatt_client_write_result ev;
1912 ERR("gatt client callback not registered");
1916 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
1918 memset(&ev, 0, sizeof(ev));
1919 ev.conn_id = resp_data->conn_id;
1920 ev.inst_id = resp_data->srvc_id.id.inst_id;
1921 ev.is_primary = resp_data->srvc_id.is_primary;
1924 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1925 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1926 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
1928 DBG("sending the gatt client write charac event");
1930 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
1933 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
1934 GAsyncResult *res, gpointer user_data)
1936 GError *error = NULL;
1937 GDBusConnection *system_gconn = NULL;
1939 hal_gatt_resp_data_t *resp_data = user_data;
1940 int result = BT_STATUS_SUCCESS;
1944 system_gconn = _bt_hal_get_system_gconn();
1945 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1948 ERR("write descriptor dbus failed Error: [%s]", error->message);
1951 result = BT_STATUS_FAIL;
1952 __hal_send_desc_write_event(resp_data, result);
1953 g_clear_error(&error);
1958 //send write value event
1959 __hal_send_desc_write_event(resp_data, result);
1962 g_variant_unref(value);
1967 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1968 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
1969 int write_type, int length, int auth_req, char* value)
1971 GVariant *val, *options;
1972 GVariantBuilder *builder1;
1973 GVariantBuilder *builder2;
1974 GDBusConnection *g_conn;
1977 hal_gatt_resp_data_t *resp_data;
1978 hal_gattc_service_t *gattc_service = NULL;
1979 hal_gattc_server_info_t * conn_info = NULL;
1980 hal_gattc_char_t *gattc_char = NULL;
1981 hal_gattc_desc_t *gattc_desc = NULL;
1982 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1983 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1984 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
1985 char* desc_handle = NULL;
1986 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1987 int ret = BT_STATUS_SUCCESS;
1992 ret = __hal_get_write_prop(write_type, &write_prop);
1993 if (BT_STATUS_FAIL == ret) {
1994 DBG("received invalid write type:[%d] ", write_type);
1995 return BT_STATUS_FAIL;
1998 /* get the connection info */
1999 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2000 if (NULL == conn_info) {
2001 DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
2002 return BT_STATUS_FAIL;
2006 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2007 if (NULL == gattc_service) {
2008 DBG("Failed to get the gatt service");
2009 return BT_STATUS_FAIL;
2012 DBG("service path [%s]", gattc_service->svc_path);
2013 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2014 DBG("service uuid [%s]", svc_uuid_str);
2016 /* find characteristic */
2017 /* service can have two char with same uuid */
2018 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2019 gattc_char = (hal_gattc_char_t*)l->data;
2020 if (gattc_char == NULL)
2023 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2024 INFO("Found GATT char uuid");
2025 DBG("char path [%s]", gattc_char->chr_path);
2026 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2027 DBG("char uuid [%s]", char_uuid_str);
2029 /* find descriptor */
2030 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2032 DBG("desc path [%s]", gattc_desc->desc_path);
2033 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2034 DBG("desc uuid [%s]", desc_uuid_str);
2040 if (NULL == gattc_desc) {
2041 DBG("Failed to get the gatt desc");
2042 return BT_STATUS_FAIL;
2045 g_conn = _bt_hal_get_system_gconn();
2046 if (NULL == g_conn) {
2047 ERR("_bt_gdbus_get_system_gconn returned NULL");
2048 return BT_STATUS_FAIL;
2051 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2052 if (NULL == resp_data) {
2053 ERR("failed to get the memory");
2054 return BT_STATUS_FAIL;
2057 resp_data->conn_id = conn_id;
2058 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2059 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2060 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2062 desc_handle = gattc_desc->desc_path;
2064 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2066 for (i = 0; i < length; i++)
2067 g_variant_builder_add(builder1, "y", value[i]);
2069 val = g_variant_new("ay", builder1);
2071 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2073 g_variant_builder_add(builder2, "{sv}", "offset",
2074 g_variant_new_uint16(offset));
2076 options = g_variant_new("a{sv}", builder2);
2078 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2080 g_variant_new("(@ay@a{sv})", val, options),
2082 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2083 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2084 (gpointer)resp_data);
2086 g_variant_builder_unref(builder1);
2087 g_variant_builder_unref(builder2);
2089 return BT_STATUS_SUCCESS;
2092 /** Write a remote descriptor for a given characteristic */
2093 bt_status_t btif_write_descriptor(int conn_id,
2094 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2095 btgatt_gatt_id_t *descr_id, int write_type, int len,
2096 int auth_req, char* p_value)
2098 CHECK_BTGATT_INIT();
2100 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2101 len, auth_req, p_value);
2104 /** Execute a prepared write operation */
2105 bt_status_t execute_write(int conn_id, int execute)
2107 CHECK_BTGATT_INIT();
2108 return BT_STATUS_UNSUPPORTED;
2111 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2113 struct hal_ev_gatt_client_watch_notification ev;
2114 hal_gatt_resp_data_t *resp_data = user_data;
2116 DBG("sending the watch register notification event");
2117 /* send the event */
2118 memset(&ev, 0, sizeof(ev));
2119 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2121 ev.status = resp_data->result;
2123 ev.is_primary = resp_data->srvc_id.is_primary;
2124 ev.inst_id = resp_data->srvc_id.id.inst_id;
2126 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2127 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2130 ERR("GATT Callback not registered");
2132 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2139 static bt_status_t _hal_register_for_notification(int client_if,
2140 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2141 btgatt_gatt_id_t *char_id)
2143 int result = BT_STATUS_SUCCESS;
2144 GError *error = NULL;
2145 GDBusConnection *g_conn;
2146 hal_gattc_client_info_t *gattc_client = NULL;
2147 hal_gattc_server_info_t * conn_info = NULL;
2148 hal_gattc_service_t *gattc_service = NULL;
2149 hal_gattc_char_t *gattc_char = NULL;
2150 char* char_handle = NULL;
2151 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2152 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2153 hal_gatt_resp_data_t *resp_data;
2157 gattc_client = __bt_find_gatt_client_info(bd_addr);
2158 if (gattc_client == NULL) {
2159 ERR("failed to get the gatt client info");
2160 return BT_STATUS_FAIL;
2163 if (gattc_client->client_if != client_if) {
2164 ERR("could not find the gatt client for client id[%d]", client_if);
2165 return BT_STATUS_FAIL;
2168 /* get the connection info */
2169 conn_info = __bt_find_gatt_conn_info(bd_addr);
2170 if (NULL == conn_info) {
2171 ERR("Failed to get the conn_info");
2172 return BT_STATUS_FAIL;
2175 if (conn_info->inst_id != gattc_client->inst_id) {
2176 ERR("could not fild the conn_info");
2177 return BT_STATUS_FAIL;
2181 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2182 if (NULL == gattc_service) {
2183 DBG("Failed to get the gatt service");
2184 return BT_STATUS_FAIL;
2187 DBG("service path [%s]", gattc_service->svc_path);
2188 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2189 DBG("service uuid [%s]", svc_uuid_str);
2192 /* find characteristic */
2193 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
2194 HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY);
2195 if (NULL == gattc_char) {
2196 DBG("Failed to get the gatt char");
2197 return BT_STATUS_FAIL;
2200 DBG("char path [%s]", gattc_char->chr_path);
2201 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2202 DBG("char uuid [%s]", char_uuid_str);
2204 char_handle = gattc_char->chr_path;
2206 g_conn = _bt_hal_get_system_gconn();
2207 if (g_conn == NULL) {
2209 return BT_STATUS_FAIL;
2212 resp_data = malloc(sizeof(hal_gatt_resp_data_t));
2213 if (NULL == resp_data) {
2214 ERR("failed to get the memory");
2215 return BT_STATUS_FAIL;
2218 DBG("#StartNotify");
2219 g_dbus_connection_call_sync(g_conn,
2222 BT_HAL_GATT_CHAR_INTERFACE,
2226 G_DBUS_CALL_FLAGS_NONE,
2227 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2230 g_dbus_error_strip_remote_error(error);
2231 ERR("### Watch Failed: %s", error->message);
2232 if (g_strrstr(error->message, "Already notifying"))
2233 result = BT_STATUS_SUCCESS;
2234 else if (g_strrstr(error->message, "In Progress"))
2235 result = BT_STATUS_BUSY;
2236 else if (g_strrstr(error->message, "Operation is not supported"))
2237 result = BT_STATUS_UNSUPPORTED;
2238 /*failed because of either Insufficient Authorization or Write Not Permitted */
2239 else if (g_strrstr(error->message, "Write not permitted") ||
2240 g_strrstr(error->message, "Operation Not Authorized"))
2241 result = BT_STATUS_AUTH_FAILURE;
2242 /* failed because of either Insufficient Authentication,
2243 Insufficient Encryption Key Size, or Insufficient Encryption. */
2244 else if (g_strrstr(error->message, "Not paired"))
2245 result = BT_STATUS_NOT_READY;
2247 result = BT_STATUS_FAIL;
2249 g_clear_error(&error);
2252 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2253 resp_data->result = result;
2254 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2255 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2257 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2261 return BT_STATUS_SUCCESS;
2265 * Register to receive notifications or indications for a given
2268 bt_status_t btif_register_for_notification(int client_if,
2269 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2270 btgatt_gatt_id_t *char_id)
2272 CHECK_BTGATT_INIT();
2274 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2277 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2279 struct hal_ev_gatt_client_watch_notification ev;
2280 hal_gatt_resp_data_t *resp_data = user_data;
2282 DBG("sending the watch deregister notification event");
2283 /* send the event */
2284 memset(&ev, 0, sizeof(ev));
2285 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2287 ev.status = resp_data->result;
2289 ev.is_primary = resp_data->srvc_id.is_primary;
2290 ev.inst_id = resp_data->srvc_id.id.inst_id;
2292 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2293 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2296 ERR("GATT Callback not registered");
2298 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2305 static bt_status_t _hal_deregister_for_notification(int client_if,
2306 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2307 btgatt_gatt_id_t *char_id)
2309 int result = BT_STATUS_SUCCESS;
2310 GError *error = NULL;
2311 GDBusConnection *g_conn;
2312 hal_gattc_client_info_t *gattc_client = NULL;
2313 hal_gattc_server_info_t * conn_info = NULL;
2314 hal_gattc_service_t *gattc_service = NULL;
2315 hal_gattc_char_t *gattc_char = NULL;
2316 char* char_handle = NULL;
2317 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2318 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2319 hal_gatt_resp_data_t *resp_data;
2323 gattc_client = __bt_find_gatt_client_info(bd_addr);
2324 if (gattc_client == NULL) {
2325 ERR("failed to get the gatt client info");
2326 return BT_STATUS_FAIL;
2329 if (gattc_client->client_if != client_if) {
2330 ERR("could not find the gatt client for client id[%d]", client_if);
2331 return BT_STATUS_FAIL;
2334 /* get the connection info */
2335 conn_info = __bt_find_gatt_conn_info(bd_addr);
2336 if (NULL == conn_info) {
2337 ERR("Failed to get the conn_info");
2338 return BT_STATUS_FAIL;
2341 if (conn_info->inst_id != gattc_client->inst_id) {
2342 ERR("could not fild the conn_info");
2343 return BT_STATUS_FAIL;
2347 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2348 if (NULL == gattc_service) {
2349 DBG("Failed to get the gatt service");
2350 return BT_STATUS_FAIL;
2353 DBG("service path [%s]", gattc_service->svc_path);
2354 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2355 DBG("service uuid [%s]", svc_uuid_str);
2358 /* find characteristic */
2359 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
2360 HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY);
2361 if (NULL == gattc_char) {
2362 DBG("Failed to get the gatt char");
2363 return BT_STATUS_FAIL;
2366 DBG("char path [%s]", gattc_char->chr_path);
2367 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2368 DBG("char uuid [%s]", char_uuid_str);
2370 char_handle = gattc_char->chr_path;
2372 g_conn = _bt_hal_get_system_gconn();
2373 if (g_conn == NULL) {
2375 return BT_STATUS_FAIL;
2378 resp_data = malloc(sizeof(hal_gatt_resp_data_t));
2379 if (NULL == resp_data) {
2380 ERR("failed to get the memory");
2381 return BT_STATUS_FAIL;
2384 DBG("#StartNotify");
2385 g_dbus_connection_call_sync(g_conn,
2388 BT_HAL_GATT_CHAR_INTERFACE,
2392 G_DBUS_CALL_FLAGS_NONE,
2393 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2396 ERR("### Watch Failed: %s", error->message);
2397 g_clear_error(&error);
2398 result = BT_STATUS_FAIL;
2401 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2402 resp_data->result = result;
2403 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2404 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2406 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2410 return BT_STATUS_SUCCESS;
2412 /** Deregister a previous request for notifications/indications */
2413 bt_status_t btif_deregister_for_notification(int client_if,
2414 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2415 btgatt_gatt_id_t *char_id)
2417 CHECK_BTGATT_INIT();
2418 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2421 /** Request RSSI for a given remote device */
2422 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2424 CHECK_BTGATT_INIT();
2425 return BT_STATUS_UNSUPPORTED;
2428 /** OTA firmware download */
2429 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2431 CHECK_BTGATT_INIT();
2432 return BT_STATUS_UNSUPPORTED;
2435 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2436 int get_device_type(const bt_bdaddr_t *bd_addr)
2438 CHECK_BTGATT_INIT();
2439 return BT_STATUS_UNSUPPORTED;
2442 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2443 int min_int, int max_int, int latency, int timeout)
2445 gchar *device_path = NULL;
2446 GError *error = NULL;
2447 GDBusProxy *device_proxy = NULL;
2448 GDBusConnection *conn;
2450 int ret = BT_STATUS_SUCCESS;
2451 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2453 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2454 min_int, max_int, latency, timeout);
2456 conn = _bt_hal_get_system_gconn();
2459 return BT_STATUS_FAIL;
2462 _bt_hal_convert_addr_type_to_string(device_address,
2463 (unsigned char *)bd_addr->address);
2464 device_path = _bt_hal_get_device_object_path(device_address);
2466 if (device_path == NULL) {
2467 ERR("device_path NULL : [%s]", device_address);
2468 return BT_STATUS_FAIL;
2471 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2472 NULL, BT_HAL_BLUEZ_NAME,
2473 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2475 g_free(device_path);
2476 if (NULL == device_proxy) {
2477 ERR("device_proxy returned NULL");
2478 return BT_STATUS_FAIL;
2481 INFO("### LeConnUpdate");
2482 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2483 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2484 G_DBUS_CALL_FLAGS_NONE,
2489 g_object_unref(device_proxy);
2490 if (reply == NULL) {
2492 ERR("Error %s[%s]", error->message, device_address);
2493 if (g_strrstr(error->message, "In Progress"))
2494 ret = BT_STATUS_SUCCESS;
2496 ret = BT_STATUS_FAIL;
2497 g_error_free(error);
2501 g_variant_unref(reply);
2503 INFO("LE Connection parameter Updated");
2507 /** Request a connection parameter update */
2508 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2510 CHECK_BTGATT_INIT();
2514 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2517 /** Test mode interface */
2518 bt_status_t test_command(int command, btgatt_test_params_t* params)
2520 CHECK_BTGATT_INIT();
2521 return BT_STATUS_UNSUPPORTED;
2524 /** MTU Exchange request from client */
2525 bt_status_t configure_mtu(int conn_id, int mtu)
2527 CHECK_BTGATT_INIT();
2528 return BT_STATUS_UNSUPPORTED;
2531 /** Setup scan filter params */
2532 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2533 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2534 int rssi_low_thres, int dely_mode, int found_timeout,
2535 int lost_timeout, int found_timeout_cnt)
2537 CHECK_BTGATT_INIT();
2538 return BT_STATUS_UNSUPPORTED;
2541 /** Configure a scan filter condition */
2542 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2543 int filt_index, int company_id,
2544 int company_id_mask, const bt_uuid_t *p_uuid,
2545 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2546 char addr_type, int data_len, char* p_data, int mask_len,
2549 CHECK_BTGATT_INIT();
2550 return BT_STATUS_UNSUPPORTED;
2553 /** Clear all scan filter conditions for specific filter index*/
2554 bt_status_t scan_filter_clear(int client_if, int filt_index)
2556 CHECK_BTGATT_INIT();
2557 return BT_STATUS_UNSUPPORTED;
2560 /** Enable / disable scan filter feature*/
2561 bt_status_t scan_filter_enable(int client_if, bool enable)
2563 CHECK_BTGATT_INIT();
2564 return BT_STATUS_UNSUPPORTED;
2567 /** Sets the LE scan interval and window in units of N*0.625 msec */
2569 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
2573 CHECK_BTGATT_INIT();
2575 le_scan_type = scan_type;
2576 ret = _bt_hal_adapter_le_set_scan_parameters(
2577 scan_type, scan_interval, scan_window);
2581 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
2583 CHECK_BTGATT_INIT();
2584 return BT_STATUS_UNSUPPORTED;
2588 /* Configure the batchscan storage */
2589 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
2590 int batch_scan_trunc_max, int batch_scan_notify_threshold)
2592 CHECK_BTGATT_INIT();
2593 return BT_STATUS_UNSUPPORTED;
2596 /* Enable batchscan */
2597 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
2598 int scan_interval, int scan_window, int addr_type, int discard_rule)
2600 CHECK_BTGATT_INIT();
2601 return BT_STATUS_UNSUPPORTED;
2604 /* Disable batchscan */
2605 bt_status_t batchscan_dis_batch_scan(int client_if)
2607 CHECK_BTGATT_INIT();
2608 return BT_STATUS_UNSUPPORTED;
2611 /* Read out batchscan reports */
2612 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
2614 CHECK_BTGATT_INIT();
2615 return BT_STATUS_UNSUPPORTED;
2618 const btgatt_client_interface_t btgatt_client_interface = {
2619 btif_gattc_register_client,
2620 btif_gattc_unregister_client,
2622 btif_gattc_client_connect,
2623 btif_gattc_client_disconnect,
2625 btif_gattc_client_search_service,
2626 get_included_service,
2627 btif_gattc_get_characteristic,
2628 btif_gattc_get_descriptor,
2629 btif_read_characteristic,
2630 btif_write_characteristic,
2631 btif_read_descriptor,
2632 btif_write_descriptor,
2634 btif_register_for_notification,
2635 btif_deregister_for_notification,
2639 btif_gattc_conn_parameter_update,
2642 scan_filter_param_setup,
2643 scan_filter_add_remove,
2646 set_scan_parameters,
2647 batchscan_cfg_storage,
2648 batchscan_enb_batch_scan,
2649 batchscan_dis_batch_scan,
2650 batchscan_read_reports
2653 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr)
2658 hal_gattc_server_info_t *info = NULL;
2660 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
2661 info = (hal_gattc_server_info_t*)l->data;
2665 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
2666 INFO("GATT connection found addr");
2673 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
2678 hal_gattc_client_info_t *info = NULL;
2680 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
2681 info = (hal_gattc_client_info_t*)l->data;
2685 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
2686 INFO("GATT client info found addr");
2693 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
2698 hal_gattc_client_info_t *info = NULL;
2700 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
2701 info = (hal_gattc_client_info_t*)l->data;
2705 if (info->conn_id == conn_id) {
2706 INFO("GATT client info found for conn_id [%d]", conn_id);
2713 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
2718 hal_gattc_server_info_t *info = NULL;
2719 hal_gattc_client_info_t *gattc_client = NULL;
2721 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2722 if (gattc_client == NULL) {
2723 INFO("GATT client conn info not found");
2727 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
2728 info = (hal_gattc_server_info_t*)l->data;
2732 if ((info->inst_id == gattc_client->inst_id) &&
2733 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
2734 INFO("GATT connection found for conn_id [%d]", conn_id);
2741 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
2742 gboolean auto_connect)
2744 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2745 gchar *device_path = NULL;
2746 GDBusProxy *device_proxy = NULL;
2747 GDBusConnection *conn;
2748 int ret = BT_STATUS_SUCCESS;
2749 hal_gattc_client_info_t *gattc_data;
2753 if (NULL == bd_addr) {
2754 ERR("bd_addr is NULL");
2755 return BT_STATUS_PARM_INVALID;
2758 conn = _bt_hal_get_system_gconn();
2760 ERR("_bt_gdbus_get_system_gconn returned NULL");
2761 return BT_STATUS_FAIL;
2764 _bt_hal_convert_addr_type_to_string(device_address,
2765 (unsigned char *)bd_addr->address);
2766 device_path = _bt_hal_get_device_object_path(device_address);
2767 if (device_path == NULL) {
2768 ERR("device_path NULL : [%s]", device_address);
2769 ret = BT_STATUS_FAIL;
2772 ERR("device_path:%s", device_path);
2774 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2775 NULL, BT_HAL_BLUEZ_NAME,
2776 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2777 g_free(device_path);
2778 if (NULL == device_proxy) {
2779 ERR("device_proxy returned NULL");
2780 return BT_STATUS_FAIL;
2783 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
2784 if (gattc_data == NULL) {
2785 ERR("Unable to allocate memory");
2786 ret = BT_STATUS_NOMEM;
2789 memcpy(gattc_data->bd_addr.address, bd_addr->address,
2790 BT_HAL_ADDRESS_LENGTH_MAX);
2792 DBG("Connect LE [%s]", device_address);
2794 gattc_data->client_if = client_if;
2796 g_dbus_proxy_call(device_proxy, "ConnectLE",
2797 g_variant_new("(b)", auto_connect),
2798 G_DBUS_CALL_FLAGS_NONE,
2799 BT_HAL_MAX_DBUS_TIMEOUT,
2801 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
2807 g_object_unref(device_proxy);
2814 static bt_status_t _bt_hold_current_advertising()
2816 int ret = BT_STATUS_FAIL;
2817 gboolean is_advertising = FALSE;
2820 is_advertising = _bt_hal_is_advertising_in_slot(0);
2821 if (is_advertising) {
2822 DBG("+ Stop current advertising");
2824 ret = _bt_hal_enable_advertising(0, FALSE, FALSE);
2825 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
2831 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
2833 DBG("+ start current advertising");
2835 _bt_hal_enable_advertising(0, TRUE, FALSE);
2840 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
2842 DBG("Try to initiate pending LE connection");
2844 pending_le_conn_timer_id = 0;
2846 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
2847 &pending_le_conn_info->bd_addr,
2848 pending_le_conn_info->auto_connect);
2850 g_free(pending_le_conn_info);
2851 pending_le_conn_info = NULL;
2856 static int __hal_generate_conn_id()
2858 return ++bt_conn_id;
2861 static int __hal_generate_server_instance_id()
2863 return ++bt_inst_id;
2866 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
2869 GError *g_error = NULL;
2870 GVariant *reply = NULL;
2871 hal_gattc_client_info_t *gattc_data = user_data;
2872 int result = BT_STATUS_SUCCESS;
2873 struct hal_ev_gatt_client_connected ev;
2874 hal_gattc_server_info_t *gatt_conn_info = NULL;
2878 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2879 g_object_unref(proxy);
2880 if (reply == NULL) {
2881 ERR("Connect LE Dbus Call Error");
2883 ERR("Error: %s\n", g_error->message);
2884 g_clear_error(&g_error);
2886 result = BT_STATUS_FAIL;
2888 g_variant_unref(reply);
2890 if (NULL == gattc_data) {
2891 ERR("server_data is NULL");
2896 if (result == BT_STATUS_FAIL) {
2897 memset(&ev, 0, sizeof(ev));
2900 ev.client_if = gattc_data->client_if;
2901 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
2902 BT_HAL_ADDRESS_LENGTH_MAX);
2905 ERR("gatt client callback not registered");
2907 DBG("sending gatt client connected event");
2908 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
2914 DBG("adding the server conn info in list");
2915 gattc_data->conn_id = __hal_generate_conn_id() ;
2916 gattc_data->inst_id = __hal_generate_server_instance_id();
2918 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
2920 /*add gatt server connection info*/
2921 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
2922 if (gatt_conn_info == NULL) {
2923 ERR("Failed to allocate memory");
2927 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
2928 gatt_conn_info->inst_id = gattc_data->inst_id;
2929 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
2935 /*remove conn_info*/
2940 void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
2942 g_free(svc_info->svc_path);
2946 void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
2948 g_free(char_info->chr_path);
2952 void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
2954 g_free(desc_info->desc_path);
2958 void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
2963 hal_gattc_service_t *svc_info = NULL;
2964 hal_gattc_char_t *char_info = NULL;
2965 hal_gattc_desc_t *desc_info = NULL;
2969 for (l = conn_info->gatt_list_services; l != NULL;) {
2970 svc_info = (hal_gattc_service_t*)l->data;
2971 if (svc_info == NULL)
2973 l = g_slist_next(l);
2975 for (m = svc_info->gatt_list_chars; m != NULL; ) {
2976 char_info = (hal_gattc_char_t*)m->data;
2977 if (char_info == NULL)
2979 m = g_slist_next(m);
2981 for (k = char_info->gatt_list_descs; k != NULL; ) {
2982 desc_info = (hal_gattc_desc_t*)k->data;
2983 if (desc_info == NULL)
2985 k = g_slist_next(k);
2987 /*remove desc element*/
2988 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
2989 __hal_gattc_free_desc_info(desc_info);
2992 /*remove desc list*/
2993 g_slist_free(char_info->gatt_list_descs);
2994 char_info->gatt_list_descs = NULL;
2996 /*remove char element*/
2997 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
2998 __hal_gattc_free_char_info(char_info);
3001 /*remove char list*/
3002 g_slist_free(svc_info->gatt_list_chars);
3003 svc_info->gatt_list_chars = NULL;
3005 /*remove svc element*/
3006 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3007 __hal_gattc_free_svc_info(svc_info);
3010 /*remove svc list */
3011 g_slist_free(conn_info->gatt_list_services);
3012 conn_info->gatt_list_services = NULL;
3014 /*remove conn info*/
3018 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3020 int result = BT_STATUS_SUCCESS;
3021 struct hal_ev_gatt_client_connected ev;
3022 hal_gattc_server_info_t *conn_info = NULL;
3023 bt_bdaddr_t bd_addr;
3025 hal_gattc_client_info_t *gattc_client = NULL;
3029 DBG("+ connected device address [%s]", address);
3031 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3032 HAL_EV_GATT_CLIENT_DISCONNECTED;
3034 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3035 /* find the gatt client info */
3036 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3037 if (NULL == gattc_client) {
3038 ERR("Fail to get gatt client info");
3043 memset(&ev, 0, sizeof(ev));
3044 ev.conn_id = gattc_client->conn_id;
3046 ev.client_if = gattc_client->client_if;
3047 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3048 BT_HAL_ADDRESS_LENGTH_MAX);
3051 ERR("gatt client callback not registered");
3053 DBG("sending gatt client connected status event");
3054 event_cb(event, (void *)&ev, sizeof(ev));
3057 if (!gatt_connected) {
3058 inst_id = gattc_client->inst_id;
3060 /* remove the gatt client info from the client list also*/
3061 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3062 g_free(gattc_client);
3064 //find the connected server info
3065 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3066 if (NULL == conn_info) {
3067 ERR("Fail to get gatt server info");
3071 if (inst_id != conn_info->inst_id) {
3072 ERR("server instance is different");
3076 //remove gatt conn info from the server list
3077 DBG("remove the server conn_info from list after gatt disconnection");
3078 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3079 __hal_clean_gattc_server_info(conn_info);
3085 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3086 const char* uuid_str, int inst_id)
3088 struct hal_ev_gatt_client_search_result ev;
3091 ERR("gatt client callback not registered");
3095 DBG("sending gatt client search service result event conn_id[%d]", conn_id);
3097 memset(&ev, 0, sizeof(ev));
3098 ev.conn_id = conn_id;
3099 ev.inst_id = inst_id;
3100 ev.is_primary = is_primary;
3101 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3103 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3106 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3108 struct hal_ev_gatt_client_search_complete ev;
3111 ERR("gatt client callback not registered");
3115 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3118 memset(&ev, 0, sizeof(ev));
3119 ev.conn_id = conn_id;
3122 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));