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(const 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 btif_gattc_add_connection_info(const bt_bdaddr_t *bd_addr, int conn_id, int server_inst_id)
299 hal_gattc_client_info_t *client_info = NULL;
300 hal_gattc_server_info_t *server_info = NULL;
302 /* Add client connection info in list */
303 client_info = g_malloc0(sizeof(hal_gattc_client_info_t));
304 client_info->client_if = -1;
305 memcpy(client_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
306 client_info->conn_id = conn_id;
307 client_info->inst_id = server_inst_id;
308 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, client_info);
310 /* Add server connection info in list */
311 server_info = g_malloc0(sizeof(hal_gattc_server_info_t));
312 memcpy(server_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
313 server_info->inst_id = server_inst_id;
314 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, server_info);
316 DBG("Added client/server connection info in list");
317 return BT_STATUS_SUCCESS;
320 bt_status_t __hal_gattc_unregister_client(int client_if)
323 hal_gatt_client_app *info = NULL;
325 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
327 /* remove the gatt client app */
328 for (l = hal_gattc_client_app_list; l != NULL; ) {
329 info = (hal_gatt_client_app*)l->data;
335 if (info->client_if == client_if) {
336 DBG("gatt client app found");
337 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
342 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
343 return BT_STATUS_SUCCESS;
346 /** Unregister a client application from the stack */
347 bt_status_t btif_gattc_unregister_client(int client_if)
352 return __hal_gattc_unregister_client(client_if);
355 /** Start or stop LE device scanning */
356 bt_status_t scan(int client_if, bool start)
363 ret = _bt_hal_adapter_le_start_scan();
365 ret = _bt_hal_adapter_le_stop_scan();
370 /** Create a connection to a remote LE or dual-mode device */
371 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
374 int ret = BT_STATUS_SUCCESS;
380 return BT_STATUS_PARM_INVALID;
382 ret = _bt_hold_current_advertising();
383 if (ret == BT_STATUS_SUCCESS) {
384 DBG("Current advertising is held");
385 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
386 pending_le_conn_info->client_if = client_if;
387 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
388 BT_HAL_ADDRESS_LENGTH_MAX);
389 pending_le_conn_info->auto_connect = is_direct;
391 pending_le_conn_timer_id =
392 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
394 return BT_STATUS_SUCCESS;
396 ERR("advertising is not stopped");
399 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
403 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
406 GError *g_error = NULL;
407 GVariant *reply = NULL;
408 hal_gattc_client_info_t *gatt_conn_info = user_data;
409 int result = BT_STATUS_SUCCESS;
410 struct hal_ev_gatt_client_connected ev;
414 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
415 g_object_unref(proxy);
417 ERR("Connect LE Dbus Call Error");
419 ERR("Error: %s\n", g_error->message);
420 g_clear_error(&g_error);
422 result = BT_STATUS_FAIL;
424 g_variant_unref(reply);
426 if (NULL == gatt_conn_info) {
427 ERR("server_data is NULL");
432 if (result == BT_STATUS_FAIL) {
433 memset(&ev, 0, sizeof(ev));
434 ev.conn_id = gatt_conn_info->conn_id;
436 ev.client_if = gatt_conn_info->client_if;
437 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
438 BT_HAL_ADDRESS_LENGTH_MAX);
441 ERR("gatt client callback not registered");
443 DBG("sending gatt client disconnected event");
444 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
450 g_free(gatt_conn_info);
455 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
458 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
460 GDBusProxy *device_proxy;
461 GDBusConnection *conn;
462 int ret = BT_STATUS_SUCCESS;
463 hal_gattc_client_info_t *gattc_data;
465 if (NULL == bd_addr) {
466 ERR("bd_addr is NULL");
467 return BT_STATUS_PARM_INVALID;
470 conn = _bt_hal_get_system_gconn();
472 ERR("_bt_gdbus_get_system_gconn returned NULL");
473 return BT_STATUS_FAIL;
476 _bt_hal_convert_addr_type_to_string(device_address,
477 (unsigned char *)bd_addr->address);
478 device_path = _bt_hal_get_device_object_path(device_address);
479 if (device_path == NULL) {
480 DBG("device_path NULL");
481 ret = BT_STATUS_FAIL;
485 ERR("device_path:%s", device_path);
487 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
488 NULL, BT_HAL_BLUEZ_NAME,
489 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
491 if (NULL == device_proxy) {
492 ERR("device_proxy returned NULL");
493 return BT_STATUS_FAIL;
496 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
497 memcpy(gattc_data->bd_addr.address, bd_addr->address,
498 BT_HAL_ADDRESS_LENGTH_MAX);
499 gattc_data->client_if = client_if;
500 gattc_data->conn_id = conn_id;
502 DBG("DisconnectLE [%s]", device_address);
504 g_dbus_proxy_call(device_proxy, "DisconnectLE",
506 G_DBUS_CALL_FLAGS_NONE,
507 BT_HAL_MAX_DBUS_TIMEOUT,
509 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
513 /** Disconnect a remote device or cancel a pending connection */
514 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
521 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
524 /** Clear the attribute cache for a given device */
525 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
528 return BT_STATUS_UNSUPPORTED;
531 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
536 hal_gattc_service_t *info = NULL;
538 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
539 info = (hal_gattc_service_t*)l->data;
543 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t))) {
544 INFO("Found GATT service uuid");
552 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
553 bt_gatt_characteristic_property_t prop)
558 hal_gattc_char_t *info = NULL;
560 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
561 info = (hal_gattc_char_t*)l->data;
565 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
566 (info->permission & prop)) {
567 INFO("Found GATT char uuid");
574 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
579 hal_gattc_char_t *info = NULL;
581 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
582 info = (hal_gattc_char_t*)l->data;
586 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
587 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
588 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
589 INFO("Found GATT char uuid");
596 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
601 hal_gattc_desc_t *info = NULL;
603 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
604 info = (hal_gattc_desc_t*)l->data;
608 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t))) {
609 INFO("Found GATT descriptor uuid");
617 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
618 const char *uuid_str, const char *object_path, int is_primary)
621 hal_gattc_service_t *gattc_service = NULL;
623 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
624 gattc_service->svc_path = g_strdup(object_path);
625 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
626 gattc_service->is_primary = is_primary;
628 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
630 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
632 DBG("svc path [%s] svc uuid [%s]", object_path, uuid_str);
634 return gattc_service;
637 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
640 hal_gattc_char_t *gattc_char = NULL;
642 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
643 gattc_char->chr_path = g_strdup(char_handle);
645 DBG("svc path: [%s]", gatt_svc->svc_path);
646 DBG("char path: [%s]", gattc_char->chr_path);
648 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
651 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
652 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
654 hal_gattc_service_t* gatt_svc = NULL;
656 gchar *gp_char_path = NULL;
660 /* add the service */
661 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
662 if (gatt_svc == NULL) {
663 ERR("Failed to add service");
667 /* add the characteristic */
668 for (i = 0; i < gp_char_array->len; i++) {
669 gp_char_path = g_ptr_array_index(gp_char_array, i);
670 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
673 g_ptr_array_free(gp_char_array, TRUE);
676 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
678 hal_gattc_desc_t *gattc_desc = NULL;
680 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
681 gattc_desc->desc_path = g_strdup(desc_path);
683 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
685 DBG("char path: [%s]", gattc_char->chr_path);
686 DBG("desc path: [%s]", gattc_desc->desc_path);
689 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
690 GPtrArray *gp_desc_array, unsigned int char_permission)
692 gchar *gp_desc_path = NULL;
697 if (char_uuid_str == NULL) {
698 DBG("char_uuid_str is NULL");
702 //update the char uuid
703 DBG("char UUID: [%s] ", char_uuid_str);
704 DBG("char path: [%s]", gattc_char->chr_path);
706 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
708 //update char permission
709 gattc_char->permission = char_permission;
712 for (i = 0; i < gp_desc_array->len; i++) {
713 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
714 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
718 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
722 if (desc_uuid_str == NULL) {
723 DBG("char_uuid_str is NULL");
727 //update the descriptor uuid
728 DBG("desc UUID: [%s] ", desc_uuid_str);
729 DBG("desc path: [%s]", gattc_desc->desc_path);
731 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
734 static void browse_service_char(int conn_id)
736 hal_gattc_server_info_t *conn_info = NULL;
740 hal_gattc_service_t *svc_info = NULL;
741 hal_gattc_char_t *char_info = NULL;
742 hal_gattc_desc_t *desc_info = NULL;
744 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
745 if (conn_info == NULL) {
746 ERR("conn_info is NULL");
750 DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
752 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
753 svc_info = (hal_gattc_service_t*)l->data;
754 if (svc_info == NULL)
757 DBG("[%s]", svc_info->svc_path);
759 /* find characteristic object path */
760 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
761 char_info = (hal_gattc_char_t *)k->data;
762 if (char_info == NULL)
765 DBG("[%s]", char_info->chr_path);
768 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
769 desc_info = (hal_gattc_desc_t *)m->data;
770 if (desc_info == NULL)
773 DBG("[%s]", desc_info->desc_path);
782 * Enumerate all GATT services on a connected device.
783 * Optionally, the results can be filtered for a given UUID.
785 static bt_status_t _gattc_client_search_service(int conn_id)
789 GVariant *result = NULL;
791 GVariantIter *svc_iter;
792 GVariantIter *interface_iter;
793 char *object_path = NULL;
794 char *interface_str = NULL;
795 const gchar *key = NULL;
796 GVariant *value = NULL;
797 GPtrArray *gp_array = NULL;
798 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
799 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
800 int ret = BT_STATUS_FAIL;
802 const gchar *uuid_str = NULL;
804 hal_gattc_server_info_t *conn_info = NULL;
805 gboolean is_primary = FALSE;
808 char *char_handle = NULL;
809 GVariantIter *char_iter = NULL;
810 GPtrArray *gp_char_array = NULL;
814 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
815 if (NULL == conn_info) {
816 ERR("Failed to get the conn_info");
817 return BT_STATUS_FAIL;
820 /* Check the service info is stored */
821 if (g_slist_length(conn_info->gatt_list_services) > 0) {
823 hal_gattc_service_t *svc_info = NULL;
824 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
825 DBG("Send event from service info list");
826 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
828 if (svc_info == NULL)
830 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
831 _bt_hal_send_search_service_result_event(conn_id,
832 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
834 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
835 return BT_STATUS_SUCCESS;
837 DBG("No stored service, request to bluez");
840 _bt_hal_convert_addr_type_to_string(device_address,
841 (unsigned char *)conn_info->bd_addr.address);
843 result = _bt_hal_get_managed_objects();
847 gp_array = g_ptr_array_new();
848 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
850 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
852 if (object_path == NULL)
855 _bt_hal_convert_device_path_to_address(object_path, temp_address);
857 if (g_strcmp0(temp_address, device_address) != 0)
860 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
861 &interface_str, &svc_iter)) {
862 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
865 DBG("[%d] Object Path : %s", idx++, object_path);
866 /* for characteristic */
867 gp_char_array = g_ptr_array_new();
868 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
869 if (g_strcmp0(key, "Primary") == 0) {
870 is_primary = g_variant_get_boolean(value);
873 g_ptr_array_add(gp_array, (gpointer)object_path);
876 } else if (g_strcmp0(key, "UUID") == 0) {
877 uuid_str = g_variant_get_string(value, &len);
878 DBG(" UUID: [%s]", uuid_str);
879 } else if (g_strcmp0(key, "Characteristics") == 0) {
880 g_variant_get(value, "ao", &char_iter);
881 if (char_iter != NULL) {
882 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
883 DBG("char handle : %s", char_handle);
884 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
891 DBG("send search service result event");
892 _bt_hal_send_search_service_result_event(conn_id, is_primary,
893 uuid_str, conn_info->inst_id);
895 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
900 if (gp_array->len == 0 || svc_count == 0) {
901 ERR("gp_array is NULL");
902 ret = BT_STATUS_FAIL;
904 ret = BT_STATUS_SUCCESS;
907 browse_service_char(conn_id);
908 /* send search service complete event */
909 _bt_hal_send_search_service_complete_event(conn_id, ret);
911 g_ptr_array_free(gp_array, TRUE);
912 g_variant_iter_free(iter);
913 g_variant_unref(result);
918 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
920 if (NULL == filter_uuid) {
921 DBG("Browse all the services");
922 return _gattc_client_search_service(conn_id);
924 DBG("TODO implement it");
925 return BT_STATUS_UNSUPPORTED;
929 * Enumerate included services for a given service.
930 * Set start_incl_srvc_id to NULL to get the first included service.
932 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
933 btgatt_srvc_id_t *start_incl_srvc_id)
936 return BT_STATUS_UNSUPPORTED;
939 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
940 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
942 struct hal_ev_gatt_client_char_search_result ev;
945 ERR("gatt client callback not registered");
949 DBG("sending gatt client search char result event conn_id[%d] status[%d]", conn_id, status);
951 memset(&ev, 0, sizeof(ev));
952 ev.conn_id = conn_id;
953 ev.inst_id = svc_id->id.inst_id;
954 ev.is_primary = svc_id->is_primary;
956 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
958 if (status == BT_STATUS_SUCCESS) {
959 DBG("building char uuid");
960 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
961 ev.char_prop = char_prop;
964 DBG("sending the char search event");
966 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
969 static int _hal_get_permission_flag(char *permission)
973 if (NULL == permission) {
974 ERR("gatt permission is NULL");
978 if (!g_strcmp0(permission, "broadcast"))
979 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
980 else if (!g_strcmp0(permission, "read"))
981 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
982 else if (!g_strcmp0(permission, "write-without-response"))
983 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
984 else if (!g_strcmp0(permission, "write"))
985 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
986 else if (!g_strcmp0(permission, "notify"))
987 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
988 else if (!g_strcmp0(permission, "indicate"))
989 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
990 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
991 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
992 else if (!g_strcmp0(permission, "reliable-write"))
993 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
994 else if (!g_strcmp0(permission, "writable-auxiliaries"))
995 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
996 else if (!g_strcmp0(permission, "encrypt-read"))
997 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
998 else if (!g_strcmp0(permission, "encrypt-write"))
999 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1000 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1001 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1002 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1003 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1009 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1011 GDBusProxy *properties_proxy = NULL;
1012 GError *error = NULL;
1013 GVariant *value = NULL;
1014 GVariant *result = NULL;
1015 GDBusConnection *g_conn;
1017 char *char_desc_handle = NULL;
1019 GVariantIter *property_iter;
1020 GVariantIter *char_desc_iter;
1021 char* char_handle = NULL;
1022 gchar *char_uuid_str = NULL;
1023 GPtrArray *gp_desc_array = NULL;
1024 GVariantIter *char_perm_iter;
1026 unsigned int char_permission = 0 ;
1028 if (gattc_char->chr_path == NULL) {
1029 DBG("char path is NULL");
1030 return BT_STATUS_FAIL;
1032 char_handle = gattc_char->chr_path;
1034 DBG("char path:[%s]", gattc_char->chr_path);
1036 g_conn = _bt_hal_get_system_gconn();
1037 if (NULL == g_conn) {
1038 ERR("_bt_gdbus_get_system_gconn returned NULL");
1039 return BT_STATUS_FAIL;
1042 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1043 G_DBUS_PROXY_FLAGS_NONE, NULL,
1046 BT_HAL_PROPERTIES_INTERFACE,
1049 if (properties_proxy == NULL) {
1050 ERR("properties_proxy returned NULL");
1051 return BT_STATUS_FAIL;
1054 result = g_dbus_proxy_call_sync(properties_proxy,
1056 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1057 G_DBUS_CALL_FLAGS_NONE,
1062 if (error != NULL) {
1063 ERR("Fail to get properties (Error: %s)", error->message);
1064 g_clear_error(&error);
1066 ERR("Fail to get properties");
1067 g_object_unref(properties_proxy);
1068 return BT_STATUS_FAIL;
1071 gp_desc_array = g_ptr_array_new();
1073 g_variant_get(result, "(a{sv})", &property_iter);
1075 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1076 if (!g_strcmp0(key, "UUID")) {
1077 char_uuid_str = g_variant_dup_string(value, &len);
1078 DBG("char UUID [%s]", char_uuid_str);
1079 } else if (!g_strcmp0(key, "Flags")) {
1080 g_variant_get(value, "as", &char_perm_iter);
1081 char_permission = 0x00;
1083 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1084 DBG("char permission: [%s]", permission);
1085 char_permission |= _hal_get_permission_flag(permission);
1087 } else if (!g_strcmp0(key, "Descriptors")) {
1088 g_variant_get(value, "ao", &char_desc_iter);
1089 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1090 DBG("char descriptor : %s", char_desc_handle);
1092 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1097 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1099 g_free(char_uuid_str);
1100 g_variant_iter_free(property_iter);
1101 g_variant_unref(result);
1102 g_object_unref(properties_proxy);
1103 g_ptr_array_free(gp_desc_array, TRUE);
1105 return BT_STATUS_SUCCESS;
1108 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1109 btgatt_srvc_id_t *srvc_id)
1111 hal_gattc_server_info_t * conn_info = NULL;
1112 hal_gattc_service_t *gattc_service = NULL;
1114 hal_gattc_char_t *gattc_char = NULL;
1115 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1116 int status = BT_STATUS_FAIL;
1118 DBG("conn_id[%d]", conn_id);
1120 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1121 if (NULL == conn_info) {
1122 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1123 return BT_STATUS_FAIL;
1127 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1128 if (NULL == gattc_service) {
1129 ERR("Failed to get the gatt service");
1130 return BT_STATUS_FAIL;
1133 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1134 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1136 /* find characteristic object path */
1137 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1138 gattc_char = (hal_gattc_char_t *)l->data;
1139 status = _hal_gattc_get_characteristic_info(gattc_char);
1142 if (BT_STATUS_SUCCESS == status) {
1143 DBG("Sending the success charateristics event");
1144 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1145 &gattc_char->chr_uuid, gattc_char->permission);
1149 DBG("sending final event");
1151 status = BT_STATUS_FAIL;
1152 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1154 browse_service_char(conn_id);
1155 /* retrive uuid for characteristic and object path for descriptor */
1157 return BT_STATUS_SUCCESS;
1161 * Enumerate characteristics for a given service.
1162 * Set start_char_id to NULL to get the first characteristic.
1164 bt_status_t btif_gattc_get_characteristic(int conn_id,
1165 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1168 CHECK_BTGATT_INIT();
1170 if (start_char_id == NULL) {
1171 DBG("Get all the characteristics");
1172 return _gattc_get_all_characteristic(conn_id, srvc_id);
1175 DBG("TBD Get specific characteristics");
1176 return BT_STATUS_UNSUPPORTED;
1180 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1182 GDBusProxy *properties_proxy = NULL;
1183 GError *error = NULL;
1184 GVariant *value = NULL;
1185 GVariant *result = NULL;
1186 GDBusConnection *g_conn;
1189 GVariantIter *property_iter;
1190 char* desc_handle = NULL;
1191 const gchar *desc_uuid_str = NULL;
1195 if (gattc_desc->desc_path == NULL) {
1196 DBG("desc path is NULL");
1197 return BT_STATUS_FAIL;
1199 desc_handle = gattc_desc->desc_path;
1201 DBG("desc path:[%s]", gattc_desc->desc_path);
1203 g_conn = _bt_hal_get_system_gconn();
1204 if (NULL == g_conn) {
1205 ERR("_bt_gdbus_get_system_gconn returned NULL");
1206 return BT_STATUS_FAIL;
1209 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1210 G_DBUS_PROXY_FLAGS_NONE, NULL,
1213 BT_HAL_PROPERTIES_INTERFACE,
1216 if (properties_proxy == NULL) {
1217 ERR("properties_proxy returned NULL");
1218 return BT_STATUS_FAIL;
1221 result = g_dbus_proxy_call_sync(properties_proxy,
1223 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1224 G_DBUS_CALL_FLAGS_NONE,
1229 if (error != NULL) {
1230 ERR("Fail to get properties (Error: %s)", error->message);
1231 g_clear_error(&error);
1233 ERR("Fail to get properties");
1234 g_object_unref(properties_proxy);
1235 return BT_STATUS_FAIL;
1238 g_variant_get(result, "(a{sv})", &property_iter);
1240 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1241 if (!g_strcmp0(key, "UUID")) {
1242 desc_uuid_str = g_variant_get_string(value, &len);
1243 DBG("desc UUID [%s]", desc_uuid_str);
1244 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1249 g_variant_iter_free(property_iter);
1250 g_variant_unref(result);
1251 g_object_unref(properties_proxy);
1253 return BT_STATUS_SUCCESS;
1256 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1257 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1259 struct hal_ev_gatt_client_desc_search_result ev;
1262 ERR("gatt client callback not registered");
1266 DBG("sending gatt client search desc result event conn_id[%d] status[%d]", conn_id, status);
1268 memset(&ev, 0, sizeof(ev));
1269 ev.conn_id = conn_id;
1270 ev.inst_id = svc_id->id.inst_id;
1271 ev.is_primary = svc_id->is_primary;
1274 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1275 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1277 if (status == BT_STATUS_SUCCESS) {
1278 DBG("building desc uuid");
1279 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1282 DBG("sending the desc search event");
1284 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1287 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1288 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1290 hal_gattc_server_info_t * conn_info = NULL;
1291 hal_gattc_service_t *gattc_service = NULL;
1294 hal_gattc_char_t *gattc_char = NULL;
1295 hal_gattc_desc_t *gattc_desc = NULL;
1296 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1297 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1298 int status = BT_STATUS_FAIL;
1300 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1301 if (NULL == conn_info) {
1302 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1303 return BT_STATUS_FAIL;
1307 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1308 if (NULL == gattc_service) {
1309 ERR("Failed to get the gatt service");
1310 return BT_STATUS_FAIL;
1313 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1314 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1316 /* find characteristics */
1317 /* a service can have two char with same uuid */
1318 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1319 gattc_char = (hal_gattc_char_t*)l->data;
1320 if (gattc_char == NULL)
1323 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1324 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1325 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1327 /* get descriptor uuid */
1328 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1329 gattc_desc = (hal_gattc_desc_t *)m->data;
1330 if (gattc_desc == NULL)
1333 status = _hal_gattc_get_descriptor_info(gattc_desc);
1336 if (BT_STATUS_SUCCESS == status) {
1337 DBG("Sending the success descriptor event");
1338 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1339 char_id, &gattc_desc->desc_uuid);
1345 DBG("sending final event");
1347 status = BT_STATUS_FAIL;
1348 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1350 browse_service_char(conn_id);
1351 /* retrive uuid for characteristic and object path for descriptor */
1353 return BT_STATUS_SUCCESS;
1357 * Enumerate descriptors for a given characteristic.
1358 * Set start_descr_id to NULL to get the first descriptor.
1360 bt_status_t btif_gattc_get_descriptor(int conn_id,
1361 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1362 btgatt_gatt_id_t *start_descr_id)
1365 CHECK_BTGATT_INIT();
1367 if (start_descr_id == NULL) {
1368 DBG("Get all the descriptors");
1369 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1371 DBG("TBD Get specific descriptor");
1372 return BT_STATUS_UNSUPPORTED;
1376 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1378 struct hal_ev_gatt_client_read_data ev;
1381 ERR("gatt client callback not registered");
1385 DBG("sending gatt client charac read conn_id[%d] status[%d]", resp_data->conn_id, result);
1387 memset(&ev, 0, sizeof(ev));
1388 ev.conn_id = resp_data->conn_id;
1389 ev.inst_id = resp_data->srvc_id.id.inst_id;
1390 ev.is_primary = resp_data->srvc_id.is_primary;
1393 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1394 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1398 DBG("building the char read value [%d]", len);
1399 memcpy(ev.value, value, len);
1402 DBG("sending the gatt client read charac event");
1404 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1407 static void __hal_internal_read_char_cb(GObject *source_object,
1408 GAsyncResult *res, gpointer user_data)
1410 GError *error = NULL;
1411 GDBusConnection *system_gconn = NULL;
1414 GByteArray *gp_byte_array = NULL;
1416 hal_gatt_resp_data_t *resp_data = user_data;
1417 int result = BT_STATUS_SUCCESS;
1421 system_gconn = _bt_hal_get_system_gconn();
1422 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1425 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1428 result = BT_STATUS_FAIL;
1429 __hal_send_char_read_event(resp_data, result, NULL, 0);
1430 g_clear_error(&error);
1435 gp_byte_array = g_byte_array_new();
1436 g_variant_get(value, "(ay)", &iter);
1438 while (g_variant_iter_loop(iter, "y", &g_byte))
1439 g_byte_array_append(gp_byte_array, &g_byte, 1);
1443 for (i = 0; i < gp_byte_array->len; i++)
1444 DBG("%02x", gp_byte_array->data[i]);
1448 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1452 g_byte_array_free(gp_byte_array, TRUE);
1453 g_variant_iter_free(iter);
1454 g_variant_unref(value);
1460 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1461 btgatt_gatt_id_t *char_id, int auth_req)
1463 GDBusConnection *g_conn;
1464 hal_gatt_resp_data_t *resp_data;
1465 hal_gattc_service_t *gattc_service = NULL;
1466 GVariantBuilder *builder = NULL;
1468 hal_gattc_server_info_t * conn_info = NULL;
1469 hal_gattc_char_t *gattc_char = NULL;
1470 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1471 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1472 char* char_handle = NULL;
1474 /* get the connection info */
1475 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1476 if (NULL == conn_info) {
1477 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1478 return BT_STATUS_FAIL;
1482 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1483 if (NULL == gattc_service) {
1484 ERR("Failed to get the gatt service");
1485 return BT_STATUS_FAIL;
1488 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1489 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1491 /* find characteristic */
1492 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1493 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1494 if (NULL == gattc_char) {
1495 ERR("Failed to get the gatt char");
1496 return BT_STATUS_FAIL;
1499 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1500 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1502 g_conn = _bt_hal_get_system_gconn();
1503 if (NULL == g_conn) {
1504 ERR("_bt_gdbus_get_system_gconn returned NULL");
1505 return BT_STATUS_FAIL;
1508 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1509 resp_data->conn_id = conn_id;
1510 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1511 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1513 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1516 g_variant_builder_add(builder, "{sv}", "offset",
1517 g_variant_new("q", offset));
1519 char_handle = gattc_char->chr_path;
1521 DBG("calling char read value");
1523 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1524 "ReadValue", g_variant_new("(a{sv})", builder),
1525 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1526 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1527 (gpointer)resp_data);
1528 g_variant_builder_unref(builder);
1530 return BT_STATUS_SUCCESS;
1533 /** Read a characteristic on a remote device */
1534 bt_status_t btif_read_characteristic(int conn_id,
1535 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1538 CHECK_BTGATT_INIT();
1541 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1544 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1546 struct hal_ev_gatt_client_write_result ev;
1549 ERR("gatt client callback not registered");
1553 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
1555 memset(&ev, 0, sizeof(ev));
1556 ev.conn_id = resp_data->conn_id;
1557 ev.inst_id = resp_data->srvc_id.id.inst_id;
1558 ev.is_primary = resp_data->srvc_id.is_primary;
1561 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1562 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1564 DBG("sending the gatt client write charac event");
1566 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1569 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1570 GAsyncResult *res, gpointer user_data)
1572 GError *error = NULL;
1573 GDBusConnection *system_gconn = NULL;
1575 hal_gatt_resp_data_t *resp_data = user_data;
1576 int result = BT_STATUS_SUCCESS;
1580 system_gconn = _bt_hal_get_system_gconn();
1581 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1584 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1586 result = BT_STATUS_FAIL;
1588 __hal_send_char_write_event(resp_data, result);
1589 g_clear_error(&error);
1594 //send write value event
1595 __hal_send_char_write_event(resp_data, result);
1598 g_variant_unref(value);
1603 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1606 case HAL_GATT_WRITE_TYPE_WRITE:
1607 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1609 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1610 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1613 ERR("Unknow write type : %d", type);
1614 return BT_STATUS_FAIL;
1617 return BT_STATUS_SUCCESS;
1621 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1623 GDBusConnection *conn;
1624 GVariantBuilder *builder = NULL;
1630 GUnixFDList *fd_list = NULL;
1632 conn = _bt_hal_get_system_gconn();
1634 ERR("_bt_gdbus_get_system_gconn returned NULL");
1635 return BT_STATUS_FAIL;
1638 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1639 //val = g_variant_new("ay", builder1);
1641 g_variant_builder_add(builder, "{sv}", "offset",
1642 g_variant_new("q", offset));
1644 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1645 "AcquireWrite", g_variant_new("(a{sv})", builder),
1646 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1647 NULL, &fd_list, NULL, &err);
1649 g_dbus_error_strip_remote_error(err);
1650 ERR("Error: %s", err->message);
1652 g_variant_builder_unref(builder);
1653 return BT_STATUS_FAIL;
1656 g_variant_get(value, "(hq)", &idx, &att_mtu);
1657 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1659 INFO("FD is %d index is %d mtu is %d", *fd, idx, att_mtu);
1662 g_object_unref(fd_list);
1663 g_variant_unref(value);
1664 g_variant_builder_unref(builder);
1666 return BT_STATUS_SUCCESS;
1669 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1671 GDBusConnection *conn;
1672 GVariantBuilder *builder = NULL;
1676 gint32 idx, notify_fd;
1678 GUnixFDList *fd_list = NULL;
1680 conn = _bt_hal_get_system_gconn();
1683 ERR("_bt_gdbus_get_system_gconn returned NULL");
1684 return BT_STATUS_FAIL;
1688 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1691 g_variant_builder_add(builder, "{sv}", "offset",
1692 g_variant_new("q", offset));
1694 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1695 "AcquireNotify", g_variant_new("(a{sv})", builder),
1696 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1697 NULL, &fd_list, NULL, &err);
1699 g_dbus_error_strip_remote_error(err);
1700 ERR("Error: %s", err->message);
1702 g_variant_builder_unref(builder);
1703 return BT_STATUS_FAIL;
1706 g_variant_get(value, "(hq)", &idx, &att_mtu);
1707 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1710 INFO("Acquired characteristic Notify fd %d, mtu %d", notify_fd, *mtu);
1714 g_object_unref(fd_list);
1715 g_variant_unref(value);
1716 g_variant_builder_unref(builder);
1718 return BT_STATUS_SUCCESS;
1722 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1723 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1725 GVariant *val, *options;
1726 GVariantBuilder *builder1;
1727 GVariantBuilder *builder2;
1728 GDBusConnection *g_conn;
1731 hal_gatt_resp_data_t *resp_data;
1732 hal_gattc_service_t *gattc_service = NULL;
1733 hal_gattc_server_info_t * conn_info = NULL;
1734 hal_gattc_char_t *gattc_char = NULL;
1735 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1736 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1737 char* char_handle = NULL;
1738 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1739 int ret = BT_STATUS_SUCCESS;
1743 ret = __hal_get_write_prop(write_type, &write_prop);
1744 if (BT_STATUS_FAIL == ret) {
1745 DBG("received invalid write type:[%d] ", write_type);
1746 return BT_STATUS_FAIL;
1749 /* get the connection info */
1750 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1751 if (NULL == conn_info) {
1752 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1753 return BT_STATUS_FAIL;
1757 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1758 if (NULL == gattc_service) {
1759 ERR("Failed to get the gatt service");
1760 return BT_STATUS_FAIL;
1763 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1764 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1766 /* find characteristic */
1767 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1768 if (NULL == gattc_char) {
1769 ERR("Failed to get the gatt char");
1770 return BT_STATUS_FAIL;
1773 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1774 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1776 g_conn = _bt_hal_get_system_gconn();
1777 if (NULL == g_conn) {
1778 ERR("_bt_gdbus_get_system_gconn returned NULL");
1779 return BT_STATUS_FAIL;
1782 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1783 resp_data->conn_id = conn_id;
1784 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1785 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1787 char_handle = gattc_char->chr_path;
1789 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1791 for (i = 0; i < length; i++)
1792 g_variant_builder_add(builder1, "y", value[i]);
1794 val = g_variant_new("ay", builder1);
1796 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1798 g_variant_builder_add(builder2, "{sv}", "offset",
1799 g_variant_new_uint16(offset));
1801 options = g_variant_new("a{sv}", builder2);
1803 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1805 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1807 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1808 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1809 (gpointer)resp_data);
1811 g_variant_builder_unref(builder1);
1812 g_variant_builder_unref(builder2);
1814 return BT_STATUS_SUCCESS;
1817 bt_status_t btif_get_acquire_write_fd(int conn_id,
1818 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1819 int auth_req, int *fd, int*mtu)
1821 CHECK_BTGATT_INIT();
1823 hal_gattc_service_t *gattc_service = NULL;
1824 hal_gattc_server_info_t * conn_info = NULL;
1825 hal_gattc_char_t *gattc_char = NULL;
1826 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1828 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1829 int ret = BT_STATUS_SUCCESS;
1832 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1834 /* get the connection info */
1835 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1836 if (NULL == conn_info) {
1837 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1838 return BT_STATUS_FAIL;
1842 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1843 if (NULL == gattc_service) {
1844 ERR("Failed to get the gatt service");
1845 return BT_STATUS_FAIL;
1848 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1849 if (NULL == gattc_char) {
1850 ERR("Failed to get the gatt char");
1851 return BT_STATUS_FAIL;
1854 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1855 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1857 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1858 if (ret != BT_STATUS_SUCCESS)
1861 INFO("Characterstics FD erite characterstics fd is %d", *fd);
1865 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1866 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1868 CHECK_BTGATT_INIT();
1870 hal_gattc_service_t *gattc_service = NULL;
1871 hal_gattc_server_info_t * conn_info = NULL;
1872 hal_gattc_char_t *gattc_char = NULL;
1873 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1875 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1876 int ret = BT_STATUS_SUCCESS;
1879 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1881 /* get the connection info */
1882 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1883 if (NULL == conn_info) {
1884 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
1885 return BT_STATUS_FAIL;
1889 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1890 if (NULL == gattc_service) {
1891 ERR("Failed to get the gatt service");
1892 return BT_STATUS_FAIL;
1895 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1896 if (NULL == gattc_char) {
1897 ERR("Failed to get the gatt char");
1898 return BT_STATUS_FAIL;
1901 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1902 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1904 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1905 if (ret != BT_STATUS_SUCCESS)
1908 INFO("Characterstics FD write characterstics fd is %d", *fd);
1914 /** Write a remote characteristic */
1915 bt_status_t btif_write_characteristic(int conn_id,
1916 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1917 int write_type, int len, int auth_req,
1920 CHECK_BTGATT_INIT();
1924 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1925 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1926 len, auth_req, p_value);
1929 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1931 struct hal_ev_gatt_client_read_data ev;
1934 ERR("gatt client callback not registered");
1938 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1940 memset(&ev, 0, sizeof(ev));
1941 ev.conn_id = resp_data->conn_id;
1942 ev.inst_id = resp_data->srvc_id.id.inst_id;
1943 ev.is_primary = resp_data->srvc_id.is_primary;
1946 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1947 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1948 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1952 DBG("building the desc read value [%d]", len);
1953 memcpy(ev.value, value, len);
1956 DBG("sending the gatt client read descriptor event");
1958 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1961 static void __hal_internal_read_desc_cb(GObject *source_object,
1962 GAsyncResult *res, gpointer user_data)
1964 GError *error = NULL;
1965 GDBusConnection *system_gconn = NULL;
1968 GByteArray *gp_byte_array = NULL;
1970 hal_gatt_resp_data_t *resp_data = user_data;
1971 int result = BT_STATUS_SUCCESS;
1976 system_gconn = _bt_hal_get_system_gconn();
1977 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1980 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1983 result = BT_STATUS_FAIL;
1984 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1985 g_clear_error(&error);
1990 gp_byte_array = g_byte_array_new();
1991 g_variant_get(value, "(ay)", &iter);
1993 while (g_variant_iter_loop(iter, "y", &g_byte))
1994 g_byte_array_append(gp_byte_array, &g_byte, 1);
1998 for (i = 0; i < gp_byte_array->len; i++)
1999 DBG("%02x", gp_byte_array->data[i]);
2002 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2006 g_byte_array_free(gp_byte_array, TRUE);
2007 g_variant_iter_free(iter);
2008 g_variant_unref(value);
2013 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2014 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2016 GDBusConnection *g_conn;
2017 hal_gatt_resp_data_t *resp_data;
2018 hal_gattc_service_t *gattc_service = NULL;
2019 GVariantBuilder *builder = NULL;
2021 hal_gattc_server_info_t * conn_info = NULL;
2022 hal_gattc_char_t *gattc_char = NULL;
2023 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2024 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2025 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2026 char* desc_handle = NULL;
2029 hal_gattc_desc_t *gattc_desc = NULL;
2033 /* get the connection info */
2034 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2035 if (NULL == conn_info) {
2036 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
2037 return BT_STATUS_FAIL;
2041 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2042 if (NULL == gattc_service) {
2043 ERR("Failed to get the gatt service");
2044 return BT_STATUS_FAIL;
2047 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2048 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2050 /* find characteristic */
2051 /* service can have two char with same uuid */
2052 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2053 gattc_char = (hal_gattc_char_t*)l->data;
2054 if (gattc_char == NULL)
2057 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2058 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2059 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2061 /* find descriptor */
2062 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2064 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2065 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2071 if (NULL == gattc_desc) {
2072 ERR("Failed to get the gatt desc");
2073 return BT_STATUS_FAIL;
2076 g_conn = _bt_hal_get_system_gconn();
2077 if (NULL == g_conn) {
2078 ERR("_bt_gdbus_get_system_gconn returned NULL");
2079 return BT_STATUS_FAIL;
2082 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2083 resp_data->conn_id = conn_id;
2084 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2085 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2086 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2088 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2091 g_variant_builder_add(builder, "{sv}", "offset",
2092 g_variant_new("q", offset));
2094 desc_handle = gattc_desc->desc_path;
2096 DBG("calling desc read value");
2098 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2099 "ReadValue", g_variant_new("(a{sv})", builder),
2100 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2101 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2102 (gpointer)resp_data);
2103 g_variant_builder_unref(builder);
2105 return BT_STATUS_SUCCESS;
2108 /** Read the descriptor for a given characteristic */
2109 bt_status_t btif_read_descriptor(int conn_id,
2110 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2111 btgatt_gatt_id_t *descr_id, int auth_req)
2113 CHECK_BTGATT_INIT();
2115 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2118 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2120 struct hal_ev_gatt_client_write_result ev;
2123 ERR("gatt client callback not registered");
2127 DBG("sending gatt client charac write conn_id[%d] status[%d]", resp_data->conn_id, result);
2129 memset(&ev, 0, sizeof(ev));
2130 ev.conn_id = resp_data->conn_id;
2131 ev.inst_id = resp_data->srvc_id.id.inst_id;
2132 ev.is_primary = resp_data->srvc_id.is_primary;
2135 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2136 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2137 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2139 DBG("sending the gatt client write charac event");
2141 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2144 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2145 GAsyncResult *res, gpointer user_data)
2147 GError *error = NULL;
2148 GDBusConnection *system_gconn = NULL;
2150 hal_gatt_resp_data_t *resp_data = user_data;
2151 int result = BT_STATUS_SUCCESS;
2155 system_gconn = _bt_hal_get_system_gconn();
2156 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2159 ERR("write descriptor dbus failed Error: [%s]", error->message);
2162 result = BT_STATUS_FAIL;
2163 __hal_send_desc_write_event(resp_data, result);
2164 g_clear_error(&error);
2169 //send write value event
2170 __hal_send_desc_write_event(resp_data, result);
2173 g_variant_unref(value);
2178 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2179 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2180 int write_type, int length, int auth_req, char* value)
2182 GVariant *val, *options;
2183 GVariantBuilder *builder1;
2184 GVariantBuilder *builder2;
2185 GDBusConnection *g_conn;
2188 hal_gatt_resp_data_t *resp_data;
2189 hal_gattc_service_t *gattc_service = NULL;
2190 hal_gattc_server_info_t * conn_info = NULL;
2191 hal_gattc_char_t *gattc_char = NULL;
2192 hal_gattc_desc_t *gattc_desc = NULL;
2193 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2194 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2195 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2196 char* desc_handle = NULL;
2197 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2198 int ret = BT_STATUS_SUCCESS;
2203 ret = __hal_get_write_prop(write_type, &write_prop);
2204 if (BT_STATUS_FAIL == ret) {
2205 ERR("received invalid write type:[%d] ", write_type);
2206 return BT_STATUS_FAIL;
2209 /* get the connection info */
2210 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2211 if (NULL == conn_info) {
2212 ERR("Failed to get the conn_info for conn_id[%d]", conn_id);
2213 return BT_STATUS_FAIL;
2217 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2218 if (NULL == gattc_service) {
2219 ERR("Failed to get the gatt service");
2220 return BT_STATUS_FAIL;
2223 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2224 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2226 /* find characteristic */
2227 /* service can have two char with same uuid */
2228 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2229 gattc_char = (hal_gattc_char_t*)l->data;
2230 if (gattc_char == NULL)
2233 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2234 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2235 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2237 /* find descriptor */
2238 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2240 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2241 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2247 if (NULL == gattc_desc) {
2248 ERR("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 ERR("Failed to get the gatt service");
2386 return BT_STATUS_FAIL;
2389 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2390 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2393 /* find characteristic */
2394 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2395 if (NULL == gattc_char) {
2396 ERR("Failed to get the gatt char");
2397 return BT_STATUS_FAIL;
2400 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2401 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2403 char_handle = gattc_char->chr_path;
2405 g_conn = _bt_hal_get_system_gconn();
2406 if (g_conn == NULL) {
2408 return BT_STATUS_FAIL;
2411 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2413 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2415 g_dbus_connection_call_sync(g_conn,
2418 BT_HAL_GATT_CHAR_INTERFACE,
2422 G_DBUS_CALL_FLAGS_NONE,
2423 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2426 g_dbus_error_strip_remote_error(error);
2427 ERR("### StartNotify Failed: %s", error->message);
2428 if (g_strrstr(error->message, "Already notifying"))
2429 result = BT_STATUS_SUCCESS;
2430 else if (g_strrstr(error->message, "In Progress"))
2431 result = BT_STATUS_BUSY;
2432 else if (g_strrstr(error->message, "Operation is not supported"))
2433 result = BT_STATUS_UNSUPPORTED;
2434 /*failed because of either Insufficient Authorization or Write Not Permitted */
2435 else if (g_strrstr(error->message, "Write not permitted") ||
2436 g_strrstr(error->message, "Operation Not Authorized"))
2437 result = BT_STATUS_AUTH_FAILURE;
2438 /* failed because of either Insufficient Authentication,
2439 Insufficient Encryption Key Size, or Insufficient Encryption. */
2440 else if (g_strrstr(error->message, "Not paired"))
2441 result = BT_STATUS_NOT_READY;
2443 result = BT_STATUS_FAIL;
2445 g_clear_error(&error);
2448 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2449 resp_data->result = result;
2450 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2451 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2453 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2457 return BT_STATUS_SUCCESS;
2461 * Register to receive notifications or indications for a given
2464 bt_status_t btif_register_for_notification(int client_if,
2465 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2466 btgatt_gatt_id_t *char_id)
2468 CHECK_BTGATT_INIT();
2470 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2473 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2475 struct hal_ev_gatt_client_watch_notification ev;
2476 hal_gatt_resp_data_t *resp_data = user_data;
2478 DBG("sending the watch deregister notification event");
2479 /* send the event */
2480 memset(&ev, 0, sizeof(ev));
2481 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2483 ev.status = resp_data->result;
2485 ev.is_primary = resp_data->srvc_id.is_primary;
2486 ev.inst_id = resp_data->srvc_id.id.inst_id;
2488 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2489 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2492 ERR("GATT Callback not registered");
2494 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2501 static bt_status_t _hal_deregister_for_notification(int client_if,
2502 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2503 btgatt_gatt_id_t *char_id)
2505 int result = BT_STATUS_SUCCESS;
2506 GError *error = NULL;
2507 GDBusConnection *g_conn;
2508 hal_gattc_client_info_t *gattc_client = NULL;
2509 hal_gattc_server_info_t * conn_info = NULL;
2510 hal_gattc_service_t *gattc_service = NULL;
2511 hal_gattc_char_t *gattc_char = NULL;
2512 char* char_handle = NULL;
2513 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2514 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2515 hal_gatt_resp_data_t *resp_data;
2519 gattc_client = __bt_find_gatt_client_info(bd_addr);
2520 if (gattc_client == NULL) {
2521 ERR("failed to get the gatt client info");
2522 return BT_STATUS_FAIL;
2525 if (gattc_client->client_if != client_if) {
2526 ERR("could not find the gatt client for client id[%d]", client_if);
2527 return BT_STATUS_FAIL;
2530 /* get the connection info */
2531 conn_info = __bt_find_gatt_conn_info(bd_addr);
2532 if (NULL == conn_info) {
2533 ERR("Failed to get the conn_info");
2534 return BT_STATUS_FAIL;
2537 if (conn_info->inst_id != gattc_client->inst_id) {
2538 ERR("could not fild the conn_info");
2539 return BT_STATUS_FAIL;
2543 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2544 if (NULL == gattc_service) {
2545 ERR("Failed to get the gatt service");
2546 return BT_STATUS_FAIL;
2549 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2550 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2553 /* find characteristic */
2554 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2555 if (NULL == gattc_char) {
2556 ERR("Failed to get the gatt char");
2557 return BT_STATUS_FAIL;
2560 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2561 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2563 char_handle = gattc_char->chr_path;
2565 g_conn = _bt_hal_get_system_gconn();
2566 if (g_conn == NULL) {
2568 return BT_STATUS_FAIL;
2571 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2573 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2574 g_dbus_connection_call_sync(g_conn,
2577 BT_HAL_GATT_CHAR_INTERFACE,
2581 G_DBUS_CALL_FLAGS_NONE,
2582 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2585 ERR("### StopNotify Failed: %s", error->message);
2586 g_clear_error(&error);
2587 result = BT_STATUS_FAIL;
2590 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2591 resp_data->result = result;
2592 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2593 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2595 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2599 return BT_STATUS_SUCCESS;
2601 /** Deregister a previous request for notifications/indications */
2602 bt_status_t btif_deregister_for_notification(int client_if,
2603 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2604 btgatt_gatt_id_t *char_id)
2606 CHECK_BTGATT_INIT();
2607 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2610 /** Request RSSI for a given remote device */
2611 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2613 CHECK_BTGATT_INIT();
2614 return BT_STATUS_UNSUPPORTED;
2617 /** OTA firmware download */
2618 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2620 CHECK_BTGATT_INIT();
2621 return BT_STATUS_UNSUPPORTED;
2624 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2625 int get_device_type(const bt_bdaddr_t *bd_addr)
2627 CHECK_BTGATT_INIT();
2628 return BT_STATUS_UNSUPPORTED;
2631 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2632 int min_int, int max_int, int latency, int timeout)
2634 gchar *device_path = NULL;
2635 GError *error = NULL;
2636 GDBusProxy *device_proxy = NULL;
2637 GDBusConnection *conn;
2639 int ret = BT_STATUS_SUCCESS;
2640 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2642 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2643 min_int, max_int, latency, timeout);
2645 conn = _bt_hal_get_system_gconn();
2648 return BT_STATUS_FAIL;
2651 _bt_hal_convert_addr_type_to_string(device_address,
2652 (unsigned char *)bd_addr->address);
2653 device_path = _bt_hal_get_device_object_path(device_address);
2655 if (device_path == NULL) {
2656 ERR("device_path NULL : [%s]", device_address);
2657 return BT_STATUS_FAIL;
2660 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2661 NULL, BT_HAL_BLUEZ_NAME,
2662 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2664 g_free(device_path);
2665 if (NULL == device_proxy) {
2666 ERR("device_proxy returned NULL");
2667 return BT_STATUS_FAIL;
2670 INFO("Request LeConnUpdate");
2671 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2672 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2673 G_DBUS_CALL_FLAGS_NONE,
2678 g_object_unref(device_proxy);
2679 if (reply == NULL) {
2681 ERR("Error %s[%s]", error->message, device_address);
2682 if (g_strrstr(error->message, "In Progress"))
2683 ret = BT_STATUS_SUCCESS;
2685 ret = BT_STATUS_FAIL;
2686 g_error_free(error);
2690 g_variant_unref(reply);
2692 DBG("LE Connection parameter Updated");
2696 /** Request a connection parameter update */
2697 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2699 CHECK_BTGATT_INIT();
2703 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2706 /** Test mode interface */
2707 bt_status_t test_command(int command, btgatt_test_params_t* params)
2709 CHECK_BTGATT_INIT();
2710 return BT_STATUS_UNSUPPORTED;
2713 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2716 GError *g_error = NULL;
2717 GVariant *reply = NULL;
2718 int result = BT_STATUS_SUCCESS;
2719 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2720 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2724 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2725 g_object_unref(proxy);
2726 if (reply == NULL) {
2727 ERR("Connect LE Dbus Call Error");
2729 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2730 g_clear_error(&g_error);
2732 result = BT_STATUS_FAIL;
2734 g_variant_unref(reply);
2736 memset(&ev, 0, sizeof(ev));
2738 ev.mtu = conn_mtu->mtu;
2739 ev.conn_id = conn_mtu->conn_id;
2742 ERR("gatt client callback not registered");
2744 DBG("sending gatt client MTU exchange completed event");
2745 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2752 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2754 gchar *device_path = NULL;
2755 GDBusProxy *device_proxy = NULL;
2756 GDBusConnection *conn;
2757 hal_gattc_client_info_t *gattc_client = NULL;
2758 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2759 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2761 conn = _bt_hal_get_system_gconn();
2764 return BT_STATUS_FAIL;
2767 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2768 if (gattc_client == NULL) {
2769 INFO("GATT client conn info not found");
2770 return BT_STATUS_FAIL;
2773 _bt_hal_convert_addr_type_to_string(device_address,
2774 (unsigned char *)gattc_client->bd_addr.address);
2776 device_path = _bt_hal_get_device_object_path(device_address);
2777 if (device_path == NULL) {
2778 ERR("device_path NULL : [%s]", device_address);
2779 return BT_STATUS_FAIL;
2782 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2783 NULL, BT_HAL_BLUEZ_NAME,
2784 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2786 g_free(device_path);
2787 if (NULL == device_proxy) {
2788 ERR("device_proxy returned NULL");
2789 return BT_STATUS_FAIL;
2792 conn_mtu->conn_id = conn_id;
2793 conn_mtu->mtu = mtu;
2795 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2796 g_variant_new("(q)", mtu),
2797 G_DBUS_CALL_FLAGS_NONE,
2798 BT_HAL_MAX_DBUS_TIMEOUT,
2800 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2803 return BT_STATUS_SUCCESS;
2806 /** MTU Exchange request from client */
2807 static bt_status_t configure_mtu(int conn_id, int mtu)
2809 CHECK_BTGATT_INIT();
2811 return __hal_configure_mtu(conn_id, mtu);
2814 /** Setup scan filter params */
2815 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2816 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2817 int rssi_low_thres, int dely_mode, int found_timeout,
2818 int lost_timeout, int found_timeout_cnt)
2821 GError *error = NULL;
2822 GVariant *ret, *param;
2823 CHECK_BTGATT_INIT();
2825 proxy = _bt_hal_get_adapter_proxy();
2828 return BT_STATUS_FAIL;
2830 param = g_variant_new("(iiiiiiiiiiii)",
2843 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2844 param, G_DBUS_CALL_FLAGS_NONE,
2848 ERR("scan_filter_param_setup Fail: %s", error->message);
2849 g_clear_error(&error);
2850 return BT_STATUS_FAIL;
2854 g_variant_unref(ret);
2856 return BT_STATUS_SUCCESS;
2859 /** Configure a scan filter condition */
2860 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2861 int filt_index, int company_id,
2862 int company_id_mask, const bt_uuid_t *p_uuid,
2863 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2864 char addr_type, int data_len, char* p_data, int mask_len,
2868 GError *error = NULL;
2869 GVariant *ret, *param;
2870 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2871 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2872 GArray *arr_uuid = NULL;
2873 GArray *arr_uuid_mask = NULL;
2874 GArray *arr_data = NULL;
2875 GArray *arr_data_mask = NULL;
2876 CHECK_BTGATT_INIT();
2878 proxy = _bt_hal_get_adapter_proxy();
2881 return BT_STATUS_FAIL;
2883 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2885 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2887 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2889 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2891 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2892 NULL, 0, TRUE, NULL, NULL);
2893 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2894 NULL, 0, TRUE, NULL, NULL);
2895 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2896 NULL, 0, TRUE, NULL, NULL);
2897 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2898 NULL, 0, TRUE, NULL, NULL);
2900 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2901 client_if, // client_if
2902 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2903 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2904 filt_index, // filter_index
2905 company_id, // company_id
2906 company_id_mask, // company_id_mask
2907 arr_uuid_param, // p_uuid
2908 arr_uuid_mask_param, // p_uuid_mask
2910 addr_type, // address_type
2911 arr_data_param, // p_data
2912 arr_data_mask_param); // p_mask
2914 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2915 param, G_DBUS_CALL_FLAGS_NONE,
2919 ERR("scan_filter_add_remove Fail: %s", error->message);
2920 g_clear_error(&error);
2921 return BT_STATUS_FAIL;
2925 g_variant_unref(ret);
2927 return BT_STATUS_SUCCESS;
2930 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2932 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2933 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2934 NULL, 0, TRUE, NULL, NULL);
2935 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2936 NULL, 0, TRUE, NULL, NULL);
2937 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2938 NULL, 0, TRUE, NULL, NULL);
2939 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2940 NULL, 0, TRUE, NULL, NULL);
2942 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2943 client_if, // client_if
2944 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2945 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2946 filt_index, // filter_index
2947 company_id, // company_id
2948 company_id_mask, // company_id_mask
2949 arr_uuid_param, // p_uuid
2950 arr_uuid_mask_param, // p_uuid_mask
2952 addr_type, // address_type
2953 arr_data_param, // p_data
2954 arr_data_mask_param);
2956 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2957 param, G_DBUS_CALL_FLAGS_NONE,
2961 ERR("scan_filter_add_remove Fail: %s", error->message);
2962 g_clear_error(&error);
2963 return BT_STATUS_FAIL;
2967 g_variant_unref(ret);
2969 return BT_STATUS_SUCCESS;
2972 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2974 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2975 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2977 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2978 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2980 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2981 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2982 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2983 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2984 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2985 NULL, 0, TRUE, NULL, NULL);
2986 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2987 NULL, 0, TRUE, NULL, NULL);
2989 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2990 client_if, // client_if
2991 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2992 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
2993 filt_index, // filter_index
2994 company_id, // company_id
2995 company_id_mask, // company_id_mask
2996 arr_uuid_param, // p_uuid
2997 arr_uuid_mask_param, // p_uuid_mask
2999 addr_type, // address_type
3000 arr_data_param, // p_data
3001 arr_data_mask_param);
3003 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
3004 param, G_DBUS_CALL_FLAGS_NONE,
3008 ERR("scan_filter_add_remove Fail: %s", error->message);
3009 g_clear_error(&error);
3010 return BT_STATUS_FAIL;
3014 g_variant_unref(ret);
3016 g_array_free(arr_uuid, TRUE);
3017 g_array_free(arr_uuid_mask, TRUE);
3019 return BT_STATUS_SUCCESS;
3022 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3024 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3025 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3027 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3028 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3030 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3031 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3032 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3033 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3034 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3035 NULL, 0, TRUE, NULL, NULL);
3036 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3037 NULL, 0, TRUE, NULL, NULL);
3039 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3040 client_if, // client_if
3041 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3042 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3043 filt_index, // filter_index
3044 company_id, // company_id
3045 company_id_mask, // company_id_mask
3046 arr_uuid_param, // p_uuid
3047 arr_uuid_mask_param, // p_uuid_mask
3049 addr_type, // address_type
3050 arr_data_param, // p_data
3051 arr_data_mask_param);
3053 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3054 G_DBUS_CALL_FLAGS_NONE,
3058 ERR("scan_filter_add_remove Fail: %s", error->message);
3059 g_clear_error(&error);
3060 return BT_STATUS_FAIL;
3064 g_variant_unref(ret);
3066 g_array_free(arr_uuid, TRUE);
3067 g_array_free(arr_uuid_mask, TRUE);
3069 return BT_STATUS_SUCCESS;
3072 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3074 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3075 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3077 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3078 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3080 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3081 NULL, 0, TRUE, NULL, NULL);
3082 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3083 NULL, 0, TRUE, NULL, NULL);
3084 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3085 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3086 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3087 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3089 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3090 client_if, // client_if
3091 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3092 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3093 filt_index, // filter_index
3094 company_id, // company_id
3095 company_id_mask, // company_id_mask
3096 arr_uuid_param, // p_uuid
3097 arr_uuid_mask_param, // p_uuid_mask
3099 addr_type, // address_type
3100 arr_data_param, // p_data
3101 arr_data_mask_param);
3103 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3104 G_DBUS_CALL_FLAGS_NONE,
3108 ERR("scan_filter_add_remove Fail: %s", error->message);
3109 g_clear_error(&error);
3110 return BT_STATUS_FAIL;
3114 g_variant_unref(ret);
3116 g_array_free(arr_data, TRUE);
3117 g_array_free(arr_data_mask, TRUE);
3119 return BT_STATUS_SUCCESS;
3122 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3124 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3125 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3127 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3128 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3130 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3131 NULL, 0, TRUE, NULL, NULL);
3132 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3133 NULL, 0, TRUE, NULL, NULL);
3134 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3135 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3136 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3137 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3139 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3140 client_if, // client_if
3141 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3142 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3143 filt_index, // filter_index
3144 company_id, // company_id
3145 company_id_mask, // company_id_mask
3146 arr_uuid_param, // p_uuid
3147 arr_uuid_mask_param, // p_uuid_mask
3149 addr_type, // address_type
3150 arr_data_param, // p_data
3151 arr_data_mask_param);
3153 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3154 G_DBUS_CALL_FLAGS_NONE,
3158 ERR("scan_filter_add_remove Fail: %s", error->message);
3159 g_clear_error(&error);
3160 return BT_STATUS_FAIL;
3164 g_variant_unref(ret);
3166 g_array_free(arr_data, TRUE);
3167 g_array_free(arr_data_mask, TRUE);
3169 return BT_STATUS_SUCCESS;
3172 return BT_STATUS_UNSUPPORTED;
3175 /** Clear all scan filter conditions for specific filter index*/
3176 bt_status_t scan_filter_clear(int client_if, int filt_index)
3179 GError *error = NULL;
3181 CHECK_BTGATT_INIT();
3183 proxy = _bt_hal_get_adapter_proxy();
3185 return BT_STATUS_FAIL;
3187 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3188 g_variant_new("(ii)", client_if, filt_index),
3189 G_DBUS_CALL_FLAGS_NONE,
3193 ERR("scan_filter_clear Fail: %s", error->message);
3194 g_clear_error(&error);
3195 return BT_STATUS_FAIL;
3198 g_variant_unref(ret);
3199 return BT_STATUS_SUCCESS;
3202 /** Enable / disable scan filter feature*/
3203 bt_status_t scan_filter_enable(int client_if, bool enable)
3206 GError *error = NULL;
3208 CHECK_BTGATT_INIT();
3210 proxy = _bt_hal_get_adapter_proxy();
3212 return BT_STATUS_FAIL;
3214 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3215 g_variant_new("(ib)", client_if, enable),
3216 G_DBUS_CALL_FLAGS_NONE,
3220 ERR("scan_filter_enable Fail: %s", error->message);
3221 g_clear_error(&error);
3222 return BT_STATUS_FAIL;
3224 g_variant_unref(ret);
3226 return BT_STATUS_SUCCESS;
3229 /** Sets the LE scan interval and window in units of N*0.625 msec */
3231 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3235 CHECK_BTGATT_INIT();
3237 le_scan_type = scan_type;
3238 ret = _bt_hal_adapter_le_set_scan_parameters(
3239 scan_type, scan_interval, scan_window);
3243 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3245 CHECK_BTGATT_INIT();
3246 return BT_STATUS_UNSUPPORTED;
3250 /* Configure the batchscan storage */
3251 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3252 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3254 CHECK_BTGATT_INIT();
3255 return BT_STATUS_UNSUPPORTED;
3258 /* Enable batchscan */
3259 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3260 int scan_interval, int scan_window, int addr_type, int discard_rule)
3262 CHECK_BTGATT_INIT();
3263 return BT_STATUS_UNSUPPORTED;
3266 /* Disable batchscan */
3267 bt_status_t batchscan_dis_batch_scan(int client_if)
3269 CHECK_BTGATT_INIT();
3270 return BT_STATUS_UNSUPPORTED;
3273 /* Read out batchscan reports */
3274 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3276 CHECK_BTGATT_INIT();
3277 return BT_STATUS_UNSUPPORTED;
3280 const btgatt_client_interface_t btgatt_client_interface = {
3281 .register_client = btif_gattc_register_client,
3282 .unregister_client = btif_gattc_unregister_client,
3284 .connect = btif_gattc_client_connect,
3285 .disconnect = btif_gattc_client_disconnect,
3287 .search_service = btif_gattc_client_search_service,
3288 .get_included_service = get_included_service,
3289 .get_characteristic = btif_gattc_get_characteristic,
3290 .get_descriptor = btif_gattc_get_descriptor,
3291 .read_characteristic = btif_read_characteristic,
3292 .write_characteristic = btif_write_characteristic,
3293 .acquire_write = btif_get_acquire_write_fd,
3294 .acquire_notify = btif_get_acquire_notify_fd,
3295 .read_descriptor = btif_read_descriptor,
3296 .write_descriptor = btif_write_descriptor,
3297 .execute_write = execute_write,
3298 .register_for_notification = btif_register_for_notification,
3299 .deregister_for_notification = btif_deregister_for_notification,
3300 .read_remote_rssi = read_remote_rssi,
3301 .ota_fw_update = ota_fw_update,
3302 .get_device_type = get_device_type,
3303 .conn_parameter_update = btif_gattc_conn_parameter_update,
3304 .test_command = test_command,
3305 .configure_mtu = configure_mtu,
3306 .scan_filter_param_setup = scan_filter_param_setup,
3307 .scan_filter_add_remove = scan_filter_add_remove,
3308 .scan_filter_clear = scan_filter_clear,
3309 .scan_filter_enable = scan_filter_enable,
3310 .set_scan_parameters = set_scan_parameters,
3311 .batchscan_cfg_storage = batchscan_cfg_storage,
3312 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3313 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3314 .batchscan_read_reports = batchscan_read_reports,
3315 .add_connection_info = btif_gattc_add_connection_info
3318 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3323 hal_gattc_server_info_t *info = NULL;
3325 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3326 info = (hal_gattc_server_info_t*)l->data;
3330 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
3331 INFO("GATT connection found addr");
3338 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3343 hal_gattc_client_info_t *info = NULL;
3345 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3346 info = (hal_gattc_client_info_t*)l->data;
3350 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t))) {
3351 INFO("GATT client info found addr");
3358 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3361 hal_gattc_client_info_t *info = NULL;
3363 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3364 info = (hal_gattc_client_info_t*)l->data;
3368 if (info->conn_id == conn_id) {
3369 INFO("GATT client info found for conn_id [%d]", conn_id);
3376 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3379 hal_gattc_server_info_t *info = NULL;
3380 hal_gattc_client_info_t *gattc_client = NULL;
3382 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3383 if (gattc_client == NULL) {
3384 ERR("GATT client conn info not found");
3388 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3389 info = (hal_gattc_server_info_t*)l->data;
3393 if ((info->inst_id == gattc_client->inst_id) &&
3394 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3395 INFO("GATT connection found for conn_id [%d]", conn_id);
3402 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3403 gboolean auto_connect)
3405 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3406 gchar *device_path = NULL;
3407 GDBusProxy *device_proxy = NULL;
3408 GDBusConnection *conn;
3409 int ret = BT_STATUS_SUCCESS;
3410 hal_gattc_client_info_t *gattc_data;
3414 if (NULL == bd_addr) {
3415 ERR("bd_addr is NULL");
3416 return BT_STATUS_PARM_INVALID;
3419 conn = _bt_hal_get_system_gconn();
3421 ERR("_bt_gdbus_get_system_gconn returned NULL");
3422 return BT_STATUS_FAIL;
3425 _bt_hal_convert_addr_type_to_string(device_address,
3426 (unsigned char *)bd_addr->address);
3427 device_path = _bt_hal_get_device_object_path(device_address);
3428 if (device_path == NULL) {
3429 ERR("device_path NULL : [%s]", device_address);
3430 ret = BT_STATUS_FAIL;
3433 ERR("device_path:%s", device_path);
3435 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3436 NULL, BT_HAL_BLUEZ_NAME,
3437 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3438 g_free(device_path);
3439 if (NULL == device_proxy) {
3440 ERR("device_proxy returned NULL");
3441 return BT_STATUS_FAIL;
3444 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3445 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3446 BT_HAL_ADDRESS_LENGTH_MAX);
3448 DBG("Connect LE [%s]", device_address);
3450 gattc_data->client_if = client_if;
3452 g_dbus_proxy_call(device_proxy, "ConnectLE",
3453 g_variant_new("(b)", auto_connect),
3454 G_DBUS_CALL_FLAGS_NONE,
3455 BT_HAL_MAX_DBUS_TIMEOUT,
3457 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3462 static bt_status_t _bt_hold_current_advertising()
3464 int ret = BT_STATUS_FAIL;
3465 gboolean is_advertising = FALSE;
3468 is_advertising = _bt_hal_is_advertising_in_slot(0);
3469 if (is_advertising) {
3470 DBG("+ Stop current advertising");
3472 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3473 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3479 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3481 DBG("+ start current advertising");
3483 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3488 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3490 DBG("Try to initiate pending LE connection");
3492 pending_le_conn_timer_id = 0;
3494 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3495 &pending_le_conn_info->bd_addr,
3496 pending_le_conn_info->auto_connect);
3498 g_free(pending_le_conn_info);
3499 pending_le_conn_info = NULL;
3504 static int __hal_generate_conn_id()
3506 return ++bt_conn_id;
3509 static int __hal_generate_server_instance_id()
3511 return ++bt_inst_id;
3514 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3517 GError *g_error = NULL;
3518 GVariant *reply = NULL;
3519 hal_gattc_client_info_t *gattc_data = user_data;
3520 int result = BT_STATUS_SUCCESS;
3521 struct hal_ev_gatt_client_connected ev;
3522 hal_gattc_server_info_t *gatt_conn_info = NULL;
3526 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3527 g_object_unref(proxy);
3528 if (reply == NULL) {
3529 ERR("Connect LE Dbus Call Error");
3531 ERR("Error: %s\n", g_error->message);
3532 g_clear_error(&g_error);
3534 result = BT_STATUS_FAIL;
3536 g_variant_unref(reply);
3538 if (NULL == gattc_data) {
3539 ERR("server_data is NULL");
3544 if (result == BT_STATUS_FAIL) {
3545 memset(&ev, 0, sizeof(ev));
3548 ev.client_if = gattc_data->client_if;
3549 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3550 BT_HAL_ADDRESS_LENGTH_MAX);
3553 ERR("gatt client callback not registered");
3555 DBG("sending gatt client connected event");
3556 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3562 DBG("adding the server conn info in list");
3563 gattc_data->conn_id = __hal_generate_conn_id() ;
3564 gattc_data->inst_id = __hal_generate_server_instance_id();
3566 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3568 /*add gatt server connection info*/
3569 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3570 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3571 gatt_conn_info->inst_id = gattc_data->inst_id;
3572 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3578 /*remove conn_info*/
3583 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3585 g_free(desc_info->desc_path);
3589 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3592 hal_gattc_desc_t *desc_info = NULL;
3593 for (l = char_info->gatt_list_descs; l != NULL; ) {
3594 desc_info = l->data;
3595 l = g_slist_next(l);
3596 if (desc_info == NULL)
3598 /* Remove descriptor element */
3599 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3600 __hal_gattc_free_desc_info(desc_info);
3602 g_slist_free(char_info->gatt_list_descs);
3603 g_free(char_info->chr_path);
3607 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3610 hal_gattc_char_t *char_info = NULL;
3611 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3612 char_info = l->data;
3613 l = g_slist_next(l);
3614 if (char_info == NULL)
3616 /* Remove characteristic element */
3617 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3618 __hal_gattc_free_char_info(char_info);
3620 g_slist_free(svc_info->gatt_list_chars);
3621 g_free(svc_info->svc_path);
3625 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3628 hal_gattc_service_t *svc_info = NULL;
3632 for (l = conn_info->gatt_list_services; l != NULL; ) {
3633 svc_info = (hal_gattc_service_t *)l->data;
3634 l = g_slist_next(l);
3635 if (svc_info == NULL)
3637 /* Remove service element */
3638 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3639 __hal_gattc_free_svc_info(svc_info);
3641 g_slist_free(conn_info->gatt_list_services);
3645 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3647 bt_bdaddr_t bd_addr;
3648 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3649 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3655 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3657 int result = BT_STATUS_SUCCESS;
3658 struct hal_ev_gatt_client_connected ev;
3659 hal_gattc_server_info_t *conn_info = NULL;
3660 bt_bdaddr_t bd_addr;
3662 hal_gattc_client_info_t *gattc_client = NULL;
3666 DBG("+ connected device address [%s]", address);
3668 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3669 HAL_EV_GATT_CLIENT_DISCONNECTED;
3671 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3672 /* find the gatt client info */
3673 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3674 if (NULL == gattc_client) {
3675 ERR("Fail to get gatt client info");
3680 memset(&ev, 0, sizeof(ev));
3681 ev.conn_id = gattc_client->conn_id;
3683 ev.client_if = gattc_client->client_if;
3684 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3685 BT_HAL_ADDRESS_LENGTH_MAX);
3688 ERR("gatt client callback not registered");
3690 DBG("sending gatt client connected status event");
3691 event_cb(event, (void *)&ev, sizeof(ev));
3694 if (!gatt_connected) {
3695 inst_id = gattc_client->inst_id;
3697 /* remove the gatt client info from the client list also*/
3698 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3699 g_free(gattc_client);
3701 //find the connected server info
3702 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3703 if (NULL == conn_info) {
3704 ERR("Fail to get gatt server info");
3708 if (inst_id != conn_info->inst_id) {
3709 ERR("server instance is different");
3713 //remove gatt conn info from the server list
3714 DBG("remove the server conn_info from list after gatt disconnection");
3715 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3716 __hal_clean_gattc_server_info(conn_info);
3722 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3723 const char* uuid_str, int inst_id)
3725 struct hal_ev_gatt_client_search_result ev;
3728 ERR("gatt client callback not registered");
3732 DBG("sending gatt client search service result event conn_id[%d]", conn_id);
3734 memset(&ev, 0, sizeof(ev));
3735 ev.conn_id = conn_id;
3736 ev.inst_id = inst_id;
3737 ev.is_primary = is_primary;
3738 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3740 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3743 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3745 struct hal_ev_gatt_client_search_complete ev;
3748 ERR("gatt client callback not registered");
3752 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3755 memset(&ev, 0, sizeof(ev));
3756 ev.conn_id = conn_id;
3759 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3762 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3763 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3764 char *char_value, int len)
3766 struct hal_ev_gatt_client_notify_changed_value ev;
3767 hal_gattc_client_info_t *gattc_client = NULL;
3770 ERR("gatt client callback not registered");
3774 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3775 if (NULL == gattc_client) {
3776 ERR("failed to get the gatt client info");
3781 DBG("sending gatt client connected status event");
3782 memset(&ev, 0, sizeof(ev));
3784 ev.conn_id = gattc_client->conn_id;
3785 ev.inst_id = conn_info->inst_id;
3786 ev.is_primary = svc_info->is_primary;
3787 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3788 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3790 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3792 if (len > 0 && (char_value != NULL)) {
3793 memcpy(ev.value, char_value, len);
3797 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3800 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3801 char *char_value, int len)
3803 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3804 hal_gattc_server_info_t *conn_info = NULL;
3805 bt_bdaddr_t bd_addr;
3808 hal_gattc_service_t *svc_info = NULL;
3809 hal_gattc_char_t *char_info = NULL;
3813 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3814 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3815 DBG("device address:[%s]", device_address);
3816 DBG("char handle:[%s]", char_handle);
3818 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3819 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3821 if (conn_info != NULL) {
3822 //find service for notified char path
3823 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3824 svc_info = (hal_gattc_service_t*)l->data;
3825 if (svc_info == NULL)
3828 /* find characteristic object path */
3829 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3830 char_info = (hal_gattc_char_t *)k->data;
3831 if (char_info == NULL)
3834 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3835 DBG("Found char handle[%s]", char_info->chr_path);
3838 _bt_hal_send_value_changed_event(conn_info, svc_info,
3839 char_info, char_value, len);
3847 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3849 GDBusConnection *g_conn = NULL;
3850 GDBusProxy *properties_proxy = NULL;
3851 GVariant *result = NULL;
3852 GError *error = NULL;
3853 GVariantIter *property_iter = NULL;
3854 const gchar *key = NULL;
3855 GVariant *value = NULL;
3856 const char *uuid_str = NULL;
3858 gboolean is_primary = FALSE;
3859 GVariantIter *char_iter = NULL;
3860 const char *char_handle = NULL;
3861 GPtrArray *gp_char_array = NULL;
3863 if (service_path == NULL) {
3864 ERR("service_path is NULL");
3865 return BT_STATUS_FAIL;
3868 DBG("service_path: %s", service_path);
3870 g_conn = _bt_hal_get_system_gconn();
3871 if (g_conn == NULL) {
3872 ERR("g_conn is NULL");
3873 return BT_STATUS_FAIL;
3876 properties_proxy = g_dbus_proxy_new_sync(g_conn,
3877 G_DBUS_PROXY_FLAGS_NONE, NULL,
3880 BT_HAL_PROPERTIES_INTERFACE,
3882 if (properties_proxy == NULL) {
3883 ERR("properties_proxy is NULL");
3884 return BT_STATUS_FAIL;
3887 result = g_dbus_proxy_call_sync(properties_proxy,
3889 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
3890 G_DBUS_CALL_FLAGS_NONE,
3892 if (result == NULL) {
3893 if (error != NULL) {
3894 ERR("Fail to get properties (Error: %s)", error->message);
3895 g_clear_error(&error);
3897 ERR("Fail to get properties");
3899 g_object_unref(properties_proxy);
3900 return BT_STATUS_FAIL;
3903 g_variant_get(result, "(a{sv})", &property_iter);
3905 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
3906 if (g_strcmp0(key, "UUID") == 0) {
3907 uuid_str = g_variant_get_string(value, &len);
3908 DBG("UUID: %s", uuid_str);
3909 } else if (g_strcmp0(key, "Primary") == 0) {
3910 is_primary = g_variant_get_boolean(value);
3911 DBG("is_primary: %s", is_primary ? "TRUE" : "FALSE");
3912 } else if (g_strcmp0(key, "Characteristics") == 0) {
3913 g_variant_get(value, "ao", &char_iter);
3914 if (char_iter != NULL) {
3915 gp_char_array = g_ptr_array_new();
3916 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
3917 DBG("char_handle: %s", char_handle);
3918 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
3924 /* Create new service */
3925 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
3927 g_variant_iter_free(property_iter);
3928 g_variant_unref(result);
3929 g_object_unref(properties_proxy);
3931 return BT_STATUS_SUCCESS;
3934 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
3936 GDBusConnection *conn = NULL;
3937 GDBusProxy *proxy = NULL;
3939 GVariant *ret = NULL;
3940 GVariant *value = NULL;
3942 conn = _bt_hal_get_system_gconn();
3944 ERR("_bt_gdbus_get_system_gconn returned NULL");
3948 proxy = g_dbus_proxy_new_sync(conn,
3949 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
3950 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
3951 if (proxy == NULL) {
3952 ERR("device_proxy returned NULL");
3956 ret = g_dbus_proxy_call_sync(proxy, "Get",
3957 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
3958 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3960 ERR("DBus Error : %s", err->message);
3961 g_clear_error(&err);
3963 g_variant_get(ret, "(v)", &value);
3964 *service_uuid = g_variant_dup_string(value, NULL);
3965 g_variant_unref(value);
3966 g_variant_unref(ret);
3970 g_object_unref(proxy);
3975 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
3977 struct hal_ev_gatt_client_service_changed ev = {0, };
3978 char address[BT_HAL_ADDRESS_STRING_SIZE];
3979 hal_gattc_server_info_t *server_info = NULL;
3980 hal_gattc_service_t *service = NULL;
3981 GSList *list = NULL;
3982 char *uuid_str = NULL;
3984 _bt_hal_convert_device_path_to_address(path, address);
3985 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
3986 ev.change_type = is_added;
3987 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
3988 if (server_info == NULL) {
3989 ERR("service_info is NULL");
3994 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
3995 DBG("GATT Service(%s) Added", uuid_str);
3996 /* Set UUID by using path */
3997 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
4000 /* Create new service and append into the list */
4001 __hal_gattc_get_service_info(server_info, path);
4003 /* Find service UUID from path */
4004 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4005 service = (hal_gattc_service_t *)list->data;
4006 if (service == NULL)
4009 if (g_strcmp0(service->svc_path, path) == 0) {
4010 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4011 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4012 /* Set UUID from stored service info */
4013 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4014 DBG("GATT Service(%s) Removed", uuid_str);
4017 /* Remove service info in list */
4018 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4019 __hal_gattc_free_svc_info(service);
4025 /* Send GATT Client service changed event */
4026 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));