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*/
127 int inst_id; /*server instance id*/
128 GSList *gatt_list_services;
129 } hal_gattc_server_info_t;
131 /* Linked List of connected GATT server */
132 static GSList *hal_gattc_server_info_list = NULL;
136 bt_bdaddr_t bd_addr; /*remote server address*/
139 gboolean is_gatt_connected;
140 } hal_gattc_client_info_t;
142 /* Linked list of connected GATT client connection */
143 static GSList * hal_gattc_client_info_list = NULL;
145 static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
146 static guint pending_le_conn_timer_id = 0;
147 static int bt_conn_id = 0;
148 static int bt_inst_id = 0;
150 /* Should match the range with bt-service-gatt.c's MAX_APPS_SUPPORTED */
151 /* TODO: Adjust MAX Client after modifying MAX app handle logic */
152 #define BT_GATTC_CL_MAX 11
154 static int assigned_if = 0;
155 static gboolean client_if_used[BT_GATTC_CL_MAX];
160 btgatt_srvc_id_t srvc_id;
161 btgatt_gatt_id_t char_id;
162 btgatt_gatt_id_t desc_id;
163 } hal_gatt_resp_data_t;
168 } hal_gatt_client_app;
170 static GSList * hal_gattc_client_app_list = NULL;
177 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
178 gboolean auto_connect);
179 static bt_status_t _bt_hold_current_advertising();
180 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data);
181 static gboolean __bt_connect_le_timer_cb(gpointer user_data);
182 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
184 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id);
185 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
186 const char* uuid_str, int inst_id);
187 static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
188 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr);
189 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
190 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
192 void _bt_hal_gatt_client_init(void)
195 memset(client_if_used, 0x00, sizeof(client_if_used));
198 static int __bt_hal_gatt_assign_if(void)
202 index = assigned_if + 1;
204 if (index >= BT_GATTC_CL_MAX)
207 while (client_if_used[index] == TRUE) {
208 if (index == assigned_if) {
209 /* No available ID */
210 ERR("All interface ID is used");
216 if (index >= BT_GATTC_CL_MAX)
221 client_if_used[index] = TRUE;
226 static void __bt_hal_gatt_delete_if(int client_if)
228 if (client_if >= BT_GATTC_CL_MAX || client_if < 0)
231 client_if_used[client_if] = FALSE;
235 /* To send stack event to hal-av handler */
236 void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb)
241 void _bt_hal_unregister_gatt_client_handler_cb(void)
247 int _bt_hal_gatt_client_get_le_scan_type(void)
253 static gboolean __bt_hal_register_client_cb(gpointer user_data)
255 struct hal_ev_gatt_client_registered ev;
256 hal_gatt_client_app *client_info = user_data;
258 /* Prepare to send AV connecting event */
259 memset(&ev, 0, sizeof(ev));
260 ev.status = BT_STATUS_SUCCESS;
261 ev.client_if = client_info->client_if;
262 memcpy(ev.app_uuid, client_info->app_uuid.uu, sizeof(ev.app_uuid));
265 ERR("GATT Callback not registered");
267 DBG("GATT client registered, client_if: [%d]", client_info->client_if);
268 event_cb(HAL_EV_GATT_CLIENT_REGISTERED, (void *)&ev, sizeof(ev));
275 static hal_gatt_client_app *__hal_gattc_add_client_app(bt_uuid_t *app_uuid)
279 hal_gatt_client_app *info = NULL;
280 hal_gatt_client_app *gattc_app = NULL;
282 //check if client app is already registered
283 for (l = hal_gattc_client_app_list; l != NULL; l = g_slist_next(l)) {
284 info = (hal_gatt_client_app*)l->data;
288 if (memcmp(&info->app_uuid, app_uuid, sizeof(bt_uuid_t)) == 0) {
289 DBG("gatt client app already registered");
294 client_if = __bt_hal_gatt_assign_if();
295 if (client_if == -1) {
296 ERR("Fail to allocate the client if");
300 DBG("adding the gatt client app");
303 gattc_app = g_malloc0(sizeof(hal_gatt_client_app));
304 gattc_app->client_if = client_if;
305 memcpy(&gattc_app->app_uuid, app_uuid, sizeof(bt_uuid_t));
307 hal_gattc_client_app_list = g_slist_append(hal_gattc_client_app_list, gattc_app);
312 static bt_status_t __hal_gattc_register_client_app(bt_uuid_t *app_uuid)
314 hal_gatt_client_app *gattc_app = NULL;
315 hal_gatt_client_app *client_app_info = NULL;
317 /* add gatt client in list */
318 gattc_app = __hal_gattc_add_client_app(app_uuid);
319 if (gattc_app == NULL) {
320 ERR("Failed to register gatt client app");
321 return BT_STATUS_FAIL;
325 client_app_info = g_malloc0(sizeof(hal_gatt_client_app));
326 client_app_info->client_if = gattc_app->client_if;
327 memcpy(&client_app_info->app_uuid, app_uuid, sizeof(bt_uuid_t));
328 g_idle_add(__bt_hal_register_client_cb, (gpointer)client_app_info);
330 DBG("registered client client_if [%d]", client_app_info->client_if);
332 return BT_STATUS_SUCCESS;
335 /** Registers a GATT client application with the stack */
336 bt_status_t btif_gattc_register_client(bt_uuid_t *uuid)
340 return __hal_gattc_register_client_app(uuid);
343 bt_status_t btif_gattc_add_connection_info(const bt_bdaddr_t *bd_addr, int conn_id, int server_inst_id)
345 hal_gattc_client_info_t *client_info = NULL;
346 hal_gattc_server_info_t *server_info = NULL;
348 /* Add client connection info in list */
349 client_info = g_malloc0(sizeof(hal_gattc_client_info_t));
350 client_info->client_if = -1;
351 memcpy(client_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
352 client_info->conn_id = conn_id;
353 client_info->inst_id = server_inst_id;
354 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, client_info);
355 DBG("Added client connection info in list");
357 /* Add server connection info in list */
358 server_info = __bt_find_gatt_conn_info(bd_addr);
359 if (server_info == NULL) {
360 server_info = g_malloc0(sizeof(hal_gattc_server_info_t));
361 memcpy(server_info->bd_addr.address, bd_addr->address, BT_HAL_ADDRESS_LENGTH_MAX);
362 server_info->conn_id = conn_id;
363 server_info->inst_id = server_inst_id;
364 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, server_info);
365 DBG("Added server connection info in list");
368 return BT_STATUS_SUCCESS;
371 bt_status_t __hal_gattc_unregister_client(int client_if)
374 hal_gatt_client_app *info = NULL;
376 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
378 /* remove the gatt client app */
379 for (l = hal_gattc_client_app_list; l != NULL; ) {
380 info = (hal_gatt_client_app*)l->data;
386 if (info->client_if == client_if) {
387 DBG("gatt client app found");
389 __bt_hal_gatt_delete_if(client_if);
391 hal_gattc_client_app_list = g_slist_remove(hal_gattc_client_app_list, info);
396 DBG("registered client count: [%d]", g_slist_length(hal_gattc_client_app_list));
397 return BT_STATUS_SUCCESS;
400 /** Unregister a client application from the stack */
401 bt_status_t btif_gattc_unregister_client(int client_if)
405 return __hal_gattc_unregister_client(client_if);
408 /** Start or stop LE device scanning */
409 bt_status_t scan(int client_if, bool start)
416 ret = _bt_hal_adapter_le_start_scan();
418 ret = _bt_hal_adapter_le_stop_scan();
423 /** Create a connection to a remote LE or dual-mode device */
424 bt_status_t btif_gattc_client_connect(int client_if, const bt_bdaddr_t *bd_addr,
427 int ret = BT_STATUS_SUCCESS;
432 return BT_STATUS_PARM_INVALID;
434 ret = _bt_hold_current_advertising();
435 if (ret == BT_STATUS_SUCCESS) {
436 DBG("Current advertising is held");
437 pending_le_conn_info = g_malloc0(sizeof(bt_pending_le_conn_info_s));
438 pending_le_conn_info->client_if = client_if;
439 memcpy(pending_le_conn_info->bd_addr.address, bd_addr->address,
440 BT_HAL_ADDRESS_LENGTH_MAX);
441 pending_le_conn_info->auto_connect = is_direct;
443 pending_le_conn_timer_id =
444 g_timeout_add(1000, __bt_connect_le_timer_cb, NULL);
446 return BT_STATUS_SUCCESS;
448 ERR("advertising is not stopped");
451 return __bt_connect_le_device_internal(client_if, bd_addr, is_direct);
455 static void __le_disconnection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
458 GError *g_error = NULL;
459 GVariant *reply = NULL;
460 hal_gattc_client_info_t *gatt_conn_info = user_data;
461 int result = BT_STATUS_SUCCESS;
462 struct hal_ev_gatt_client_connected ev;
466 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
467 g_object_unref(proxy);
469 ERR("Connect LE Dbus Call Error");
471 ERR("Error: %s\n", g_error->message);
472 g_clear_error(&g_error);
474 result = BT_STATUS_FAIL;
476 g_variant_unref(reply);
478 if (NULL == gatt_conn_info) {
479 ERR("server_data is NULL");
484 if (result == BT_STATUS_FAIL) {
485 memset(&ev, 0, sizeof(ev));
486 ev.conn_id = gatt_conn_info->conn_id;
488 ev.client_if = gatt_conn_info->client_if;
489 memcpy(ev.bdaddr, gatt_conn_info->bd_addr.address,
490 BT_HAL_ADDRESS_LENGTH_MAX);
493 ERR("gatt client callback not registered");
495 DBG("sending gatt client disconnected event");
496 event_cb(HAL_EV_GATT_CLIENT_DISCONNECTED, (void *)&ev, sizeof(ev));
502 g_free(gatt_conn_info);
507 bt_status_t _hal_gattc_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
510 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
512 GDBusProxy *device_proxy;
513 GDBusConnection *conn;
514 int ret = BT_STATUS_SUCCESS;
515 hal_gattc_client_info_t *gattc_data;
517 if (NULL == bd_addr) {
518 ERR("bd_addr is NULL");
519 return BT_STATUS_PARM_INVALID;
522 conn = _bt_hal_get_system_gconn();
524 ERR("_bt_gdbus_get_system_gconn returned NULL");
525 return BT_STATUS_FAIL;
528 _bt_hal_convert_addr_type_to_string(device_address,
529 (unsigned char *)bd_addr->address);
530 device_path = _bt_hal_get_device_object_path(device_address);
531 if (device_path == NULL) {
532 DBG("device_path NULL");
533 ret = BT_STATUS_FAIL;
537 ERR("device_path:%s", device_path);
539 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
540 NULL, BT_HAL_BLUEZ_NAME,
541 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
543 if (NULL == device_proxy) {
544 ERR("device_proxy returned NULL");
545 return BT_STATUS_FAIL;
548 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
549 memcpy(gattc_data->bd_addr.address, bd_addr->address,
550 BT_HAL_ADDRESS_LENGTH_MAX);
551 gattc_data->client_if = client_if;
552 gattc_data->conn_id = conn_id;
554 DBG("DisconnectLE [%s]", device_address);
556 g_dbus_proxy_call(device_proxy, "DisconnectLE",
558 G_DBUS_CALL_FLAGS_NONE,
559 BT_HAL_MAX_DBUS_TIMEOUT,
561 (GAsyncReadyCallback)__le_disconnection_req_cb, gattc_data);
565 /** Disconnect a remote device or cancel a pending connection */
566 bt_status_t btif_gattc_client_disconnect(int client_if, const bt_bdaddr_t *bd_addr,
571 return _hal_gattc_disconnect(client_if, bd_addr, conn_id);
574 /** Clear the attribute cache for a given device */
575 bt_status_t refresh(int client_if, const bt_bdaddr_t *bd_addr)
578 return BT_STATUS_UNSUPPORTED;
581 static hal_gattc_service_t* _gattc_find_service_from_uuid(hal_gattc_server_info_t *conn_info, bt_uuid_t *svc_uuid)
584 hal_gattc_service_t *info = NULL;
586 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
587 info = (hal_gattc_service_t*)l->data;
591 if (!memcmp(&info->svc_uuid, svc_uuid, sizeof(bt_uuid_t)))
599 static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
600 bt_gatt_characteristic_property_t prop)
603 hal_gattc_char_t *info = NULL;
605 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
606 info = (hal_gattc_char_t*)l->data;
610 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
611 (info->permission & prop)) {
618 static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
621 hal_gattc_char_t *info = NULL;
623 for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
624 info = (hal_gattc_char_t*)l->data;
628 if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
629 ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
630 (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
637 static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid)
640 hal_gattc_desc_t *info = NULL;
642 for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
643 info = (hal_gattc_desc_t*)l->data;
647 if (!memcmp(&info->desc_uuid, desc_uuid, sizeof(bt_uuid_t)))
654 static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
655 const char *uuid_str, const char *object_path, int is_primary)
657 hal_gattc_service_t *gattc_service = NULL;
659 gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
660 gattc_service->svc_path = g_strdup(object_path);
661 _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
662 gattc_service->is_primary = is_primary;
664 conn_info->gatt_list_services = g_slist_append(conn_info->gatt_list_services, gattc_service);
665 INFO("Toatal svc [%d] Added [%s] [%s]", g_slist_length(conn_info->gatt_list_services), object_path + 15, uuid_str);
667 return gattc_service;
670 static void _hal_gattc_add_characteristic(hal_gattc_service_t *gatt_svc, char *char_handle)
672 hal_gattc_char_t *gattc_char = NULL;
674 gattc_char = g_malloc0(sizeof(hal_gattc_char_t));
675 gattc_char->chr_path = g_strdup(char_handle);
677 DBG("svc path: [%s]", gatt_svc->svc_path);
678 DBG("char path: [%s]", gattc_char->chr_path);
680 gatt_svc->gatt_list_chars = g_slist_append(gatt_svc->gatt_list_chars, gattc_char);
683 static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
684 const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
686 hal_gattc_service_t* gatt_svc = NULL;
688 gchar *gp_char_path = NULL;
690 /* add the service */
691 gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
692 if (gatt_svc == NULL) {
693 ERR("Failed to add service");
697 /* add the characteristic */
698 for (i = 0; i < gp_char_array->len; i++) {
699 gp_char_path = g_ptr_array_index(gp_char_array, i);
700 _hal_gattc_add_characteristic(gatt_svc, gp_char_path);
703 g_ptr_array_free(gp_char_array, TRUE);
706 static void _hal_gattc_add_descriptor(hal_gattc_char_t *gattc_char, char *desc_path)
708 hal_gattc_desc_t *gattc_desc = NULL;
710 gattc_desc = g_malloc0(sizeof(hal_gattc_desc_t));
711 gattc_desc->desc_path = g_strdup(desc_path);
713 gattc_char->gatt_list_descs = g_slist_append(gattc_char->gatt_list_descs, gattc_desc);
716 static void _hal_gattc_update_char_property(hal_gattc_char_t *gattc_char, const char* char_uuid_str,
717 GPtrArray *gp_desc_array, unsigned int char_permission)
719 gchar *gp_desc_path = NULL;
722 if (char_uuid_str == NULL) {
723 DBG("char_uuid_str is NULL");
727 //update the char uuid
728 _bt_hal_convert_uuid_string_to_type(gattc_char->chr_uuid.uu, char_uuid_str);
730 //update char permission
731 gattc_char->permission = char_permission;
734 for (i = 0; i < gp_desc_array->len; i++) {
735 gp_desc_path = g_ptr_array_index(gp_desc_array, i);
736 _hal_gattc_add_descriptor(gattc_char, gp_desc_path);
740 static void _hal_gattc_update_desc_property(hal_gattc_desc_t *gattc_desc, const char* desc_uuid_str)
742 if (desc_uuid_str == NULL) {
743 DBG("char_uuid_str is NULL");
747 //update the descriptor uuid
748 DBG("desc UUID: [%s] ", desc_uuid_str);
749 DBG("desc path: [%s]", gattc_desc->desc_path);
751 _bt_hal_convert_uuid_string_to_type(gattc_desc->desc_uuid.uu, desc_uuid_str);
754 static void browse_service_char(int conn_id)
756 hal_gattc_server_info_t *conn_info = NULL;
760 hal_gattc_service_t *svc_info = NULL;
761 hal_gattc_char_t *char_info = NULL;
762 hal_gattc_desc_t *desc_info = NULL;
764 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
765 if (conn_info == NULL) {
766 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
770 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
771 svc_info = (hal_gattc_service_t*)l->data;
772 if (svc_info == NULL)
775 /* find characteristic object path */
776 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
777 char_info = (hal_gattc_char_t *)k->data;
778 if (char_info == NULL)
782 for (m = char_info->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
783 desc_info = (hal_gattc_desc_t *)m->data;
784 if (desc_info == NULL)
794 * Enumerate all GATT services on a connected device.
795 * Optionally, the results can be filtered for a given UUID.
797 static bt_status_t _gattc_client_search_service(int conn_id)
801 GVariant *result = NULL;
803 GVariantIter *svc_iter;
804 GVariantIter *interface_iter;
805 char *object_path = NULL;
806 char *interface_str = NULL;
807 const gchar *key = NULL;
808 GVariant *value = NULL;
809 GPtrArray *gp_array = NULL;
810 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
811 char temp_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
812 int ret = BT_STATUS_FAIL;
814 const gchar *uuid_str = NULL;
816 hal_gattc_server_info_t *conn_info = NULL;
817 gboolean is_primary = FALSE;
820 char *char_handle = NULL;
821 GVariantIter *char_iter = NULL;
822 GPtrArray *gp_char_array = NULL;
824 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
825 if (NULL == conn_info) {
826 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
827 return BT_STATUS_FAIL;
831 // TODO: This logic is not able to handle in case service-added event is coming unexpectedly.
832 /* Check the service info is stored */
833 if (g_slist_length(conn_info->gatt_list_services) > 0) {
835 hal_gattc_service_t *svc_info = NULL;
836 char svc_uuid_str[BT_HAL_UUID_STRING_LEN] = {0, };
837 DBG("Send event from service info list");
838 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
840 if (svc_info == NULL)
842 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, svc_info->svc_uuid.uu);
843 _bt_hal_send_search_service_result_event(conn_id,
844 svc_info->is_primary, svc_uuid_str, conn_info->inst_id);
846 _bt_hal_send_search_service_complete_event(conn_id, BT_STATUS_SUCCESS);
847 return BT_STATUS_SUCCESS;
849 DBG("No stored service, request to bluez");
853 _bt_hal_convert_addr_type_to_string(device_address,
854 (unsigned char *)conn_info->bd_addr.address);
856 result = _bt_hal_get_managed_objects();
860 gp_array = g_ptr_array_new();
861 g_variant_get(result, "(a{oa{sa{sv}}})", &iter);
863 while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path,
865 if (object_path == NULL)
868 _bt_hal_convert_device_path_to_address(object_path, temp_address);
870 if (g_strcmp0(temp_address, device_address) != 0)
873 while (g_variant_iter_loop(interface_iter, "{sa{sv}}",
874 &interface_str, &svc_iter)) {
875 if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0)
878 DBG("[%d] Object Path : %s", idx++, object_path);
879 /* for characteristic */
880 gp_char_array = g_ptr_array_new();
881 while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) {
882 if (g_strcmp0(key, "Primary") == 0) {
883 is_primary = g_variant_get_boolean(value);
885 g_ptr_array_add(gp_array, (gpointer)object_path);
888 } else if (g_strcmp0(key, "UUID") == 0) {
889 uuid_str = g_variant_get_string(value, &len);
890 } else if (g_strcmp0(key, "Characteristics") == 0) {
891 g_variant_get(value, "ao", &char_iter);
892 if (char_iter != NULL) {
893 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
894 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
901 _bt_hal_send_search_service_result_event(conn_id, is_primary,
902 uuid_str, conn_info->inst_id);
904 _gattc_create_new_service(conn_info, is_primary, uuid_str, object_path, gp_char_array);
909 if (gp_array->len == 0 || svc_count == 0) {
910 ERR("gp_array is NULL");
911 ret = BT_STATUS_FAIL;
913 ret = BT_STATUS_SUCCESS;
916 browse_service_char(conn_id);
917 /* send search service complete event */
918 _bt_hal_send_search_service_complete_event(conn_id, ret);
920 g_ptr_array_free(gp_array, TRUE);
921 g_variant_iter_free(iter);
922 g_variant_unref(result);
927 bt_status_t btif_gattc_client_search_service(int conn_id, bt_uuid_t *filter_uuid)
929 if (NULL == filter_uuid) {
930 DBG("Browse all the services");
931 return _gattc_client_search_service(conn_id);
933 DBG("TODO implement it");
934 return BT_STATUS_UNSUPPORTED;
938 * Enumerate included services for a given service.
939 * Set start_incl_srvc_id to NULL to get the first included service.
941 bt_status_t get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
942 btgatt_srvc_id_t *start_incl_srvc_id)
945 return BT_STATUS_UNSUPPORTED;
948 static void _bt_hal_send_client_char_search_result_event(int conn_id, int status,
949 btgatt_srvc_id_t *svc_id, bt_uuid_t *char_uuid, int char_prop)
951 struct hal_ev_gatt_client_char_search_result ev;
954 ERR("gatt client callback not registered");
958 memset(&ev, 0, sizeof(ev));
959 ev.conn_id = conn_id;
960 ev.inst_id = svc_id->id.inst_id;
961 ev.is_primary = svc_id->is_primary;
963 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
965 if (status == BT_STATUS_SUCCESS) {
966 /* building char uuid */
967 memcpy(ev.char_uuid, char_uuid->uu, sizeof(ev.char_uuid));
968 ev.char_prop = char_prop;
971 DBG("sending the char search event. conn_id[%d] status[%d]", conn_id, status);
972 event_cb(HAL_EV_GATT_CLIENT_CHARAC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
975 static int _hal_get_permission_flag(char *permission)
979 if (NULL == permission) {
980 ERR("gatt permission is NULL");
984 if (!g_strcmp0(permission, "broadcast"))
985 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST;
986 else if (!g_strcmp0(permission, "read"))
987 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_READ;
988 else if (!g_strcmp0(permission, "write-without-response"))
989 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
990 else if (!g_strcmp0(permission, "write"))
991 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
992 else if (!g_strcmp0(permission, "notify"))
993 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
994 else if (!g_strcmp0(permission, "indicate"))
995 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
996 else if (!g_strcmp0(permission, "authenticated-signed-writes"))
997 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE;
998 else if (!g_strcmp0(permission, "reliable-write"))
999 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE;
1000 else if (!g_strcmp0(permission, "writable-auxiliaries"))
1001 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES;
1002 else if (!g_strcmp0(permission, "encrypt-read"))
1003 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ;
1004 else if (!g_strcmp0(permission, "encrypt-write"))
1005 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE;
1006 else if (!g_strcmp0(permission, "encrypt-authenticated-read"))
1007 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ;
1008 else if (!g_strcmp0(permission, "encrypt-authenticated-write"))
1009 ret = HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE;
1014 static void __hal_convert_permission_flag_to_str(unsigned int permission)
1016 char perm[200] = { 0, };
1018 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_BROADCAST)
1019 g_strlcat(perm, "broadcast ", sizeof(perm));
1020 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_READ)
1021 g_strlcat(perm, "read ", sizeof(perm));
1022 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE)
1023 g_strlcat(perm, "write-without-response ", sizeof(perm));
1024 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE)
1025 g_strlcat(perm, "write ", sizeof(perm));
1026 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY)
1027 g_strlcat(perm, "notify ", sizeof(perm));
1028 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE)
1029 g_strlcat(perm, "indicate ", sizeof(perm));
1030 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE)
1031 g_strlcat(perm, "authenticated-signed-writes ", sizeof(perm));
1032 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_RELIABLE_WRITE)
1033 g_strlcat(perm, "reliable-write ", sizeof(perm));
1034 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_WRITABLE_AUXILIARIES)
1035 g_strlcat(perm, "writable-auxiliaries ", sizeof(perm));
1036 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_READ)
1037 g_strlcat(perm, "encrypt-read ", sizeof(perm));
1038 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_WRITE)
1039 g_strlcat(perm, "encrypt-write ", sizeof(perm));
1040 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_READ)
1041 g_strlcat(perm, "encrypt-authenticated-read ", sizeof(perm));
1042 if (permission & HAL_GATT_CHARACTERISTIC_PROPERTY_ENCRYPT_AUTHENTICATED_WRITE)
1043 g_strlcat(perm, "encrypt-authenticated-write ", sizeof(perm));
1045 DBG("permission [0x%04x] : %s\n", permission, perm);
1049 static bt_status_t _hal_gattc_get_characteristic_info(hal_gattc_char_t *gattc_char)
1051 GDBusProxy *properties_proxy = NULL;
1052 GError *error = NULL;
1053 GVariant *value = NULL;
1054 GVariant *result = NULL;
1055 GDBusConnection *g_conn;
1057 char *char_desc_handle = NULL;
1059 GVariantIter *property_iter;
1060 GVariantIter *char_desc_iter;
1061 char* char_handle = NULL;
1062 gchar *char_uuid_str = NULL;
1063 GPtrArray *gp_desc_array = NULL;
1064 GVariantIter *char_perm_iter;
1066 unsigned int char_permission = 0 ;
1068 if (gattc_char->chr_path == NULL) {
1069 DBG("char path is NULL");
1070 return BT_STATUS_FAIL;
1072 char_handle = gattc_char->chr_path;
1074 g_conn = _bt_hal_get_system_gconn();
1075 if (NULL == g_conn) {
1076 ERR("_bt_gdbus_get_system_gconn returned NULL");
1077 return BT_STATUS_FAIL;
1080 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1081 G_DBUS_PROXY_FLAGS_NONE, NULL,
1084 BT_HAL_PROPERTIES_INTERFACE,
1087 if (properties_proxy == NULL) {
1088 ERR("properties_proxy returned NULL");
1089 return BT_STATUS_FAIL;
1092 result = g_dbus_proxy_call_sync(properties_proxy,
1094 g_variant_new("(s)", BT_HAL_GATT_CHAR_INTERFACE),
1095 G_DBUS_CALL_FLAGS_NONE,
1100 if (error != NULL) {
1101 ERR("Fail to get properties (Error: %s)", error->message);
1102 g_clear_error(&error);
1104 ERR("Fail to get properties");
1105 g_object_unref(properties_proxy);
1106 return BT_STATUS_FAIL;
1109 gp_desc_array = g_ptr_array_new();
1111 g_variant_get(result, "(a{sv})", &property_iter);
1113 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1114 if (!g_strcmp0(key, "UUID")) {
1115 char_uuid_str = g_variant_dup_string(value, &len);
1116 INFO("%s [%s]", char_handle + 37, char_uuid_str);
1117 } else if (!g_strcmp0(key, "Flags")) {
1118 g_variant_get(value, "as", &char_perm_iter);
1119 char_permission = 0x00;
1121 while (g_variant_iter_loop(char_perm_iter, "s", &permission)) {
1122 char_permission |= _hal_get_permission_flag(permission);
1124 __hal_convert_permission_flag_to_str(char_permission);
1125 g_variant_iter_free(char_perm_iter);
1126 } else if (!g_strcmp0(key, "Descriptors")) {
1127 g_variant_get(value, "ao", &char_desc_iter);
1128 while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) {
1129 g_ptr_array_add(gp_desc_array, (gpointer)char_desc_handle);
1131 g_variant_iter_free(char_desc_iter);
1135 _hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
1137 g_free(char_uuid_str);
1138 g_variant_iter_free(property_iter);
1139 g_variant_unref(result);
1140 g_object_unref(properties_proxy);
1141 g_ptr_array_free(gp_desc_array, TRUE);
1143 return BT_STATUS_SUCCESS;
1146 static bt_status_t _gattc_get_all_characteristic(int conn_id,
1147 btgatt_srvc_id_t *srvc_id)
1149 hal_gattc_server_info_t * conn_info = NULL;
1150 hal_gattc_service_t *gattc_service = NULL;
1152 hal_gattc_char_t *gattc_char = NULL;
1153 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1154 int status = BT_STATUS_FAIL;
1156 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1157 if (NULL == conn_info) {
1158 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1159 return BT_STATUS_FAIL;
1163 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1164 if (NULL == gattc_service) {
1165 ERR("Failed to get the gatt service");
1166 return BT_STATUS_FAIL;
1169 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1170 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1172 /* find characteristic object path */
1173 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1174 gattc_char = (hal_gattc_char_t *)l->data;
1175 status = _hal_gattc_get_characteristic_info(gattc_char);
1178 if (BT_STATUS_SUCCESS == status) {
1179 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id,
1180 &gattc_char->chr_uuid, gattc_char->permission);
1184 status = BT_STATUS_FAIL;
1185 _bt_hal_send_client_char_search_result_event(conn_id, status, srvc_id, NULL, 0);
1187 browse_service_char(conn_id);
1188 /* retrive uuid for characteristic and object path for descriptor */
1190 return BT_STATUS_SUCCESS;
1194 * Enumerate characteristics for a given service.
1195 * Set start_char_id to NULL to get the first characteristic.
1197 bt_status_t btif_gattc_get_characteristic(int conn_id,
1198 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id)
1200 CHECK_BTGATT_INIT();
1202 if (start_char_id == NULL) {
1203 DBG("Get all the characteristics");
1204 return _gattc_get_all_characteristic(conn_id, srvc_id);
1207 DBG("TBD Get specific characteristics");
1208 return BT_STATUS_UNSUPPORTED;
1212 static bt_status_t _hal_gattc_get_descriptor_info(hal_gattc_desc_t *gattc_desc)
1214 GDBusProxy *properties_proxy = NULL;
1215 GError *error = NULL;
1216 GVariant *value = NULL;
1217 GVariant *result = NULL;
1218 GDBusConnection *g_conn;
1221 GVariantIter *property_iter;
1222 char* desc_handle = NULL;
1223 const gchar *desc_uuid_str = NULL;
1225 if (gattc_desc->desc_path == NULL) {
1226 DBG("desc path is NULL");
1227 return BT_STATUS_FAIL;
1229 desc_handle = gattc_desc->desc_path;
1231 g_conn = _bt_hal_get_system_gconn();
1232 if (NULL == g_conn) {
1233 ERR("_bt_gdbus_get_system_gconn returned NULL");
1234 return BT_STATUS_FAIL;
1237 properties_proxy = g_dbus_proxy_new_sync(g_conn,
1238 G_DBUS_PROXY_FLAGS_NONE, NULL,
1241 BT_HAL_PROPERTIES_INTERFACE,
1244 if (properties_proxy == NULL) {
1245 ERR("properties_proxy returned NULL");
1246 return BT_STATUS_FAIL;
1249 result = g_dbus_proxy_call_sync(properties_proxy,
1251 g_variant_new("(s)", BT_HAL_GATT_DESC_INTERFACE),
1252 G_DBUS_CALL_FLAGS_NONE,
1257 if (error != NULL) {
1258 ERR("Fail to get properties (Error: %s)", error->message);
1259 g_clear_error(&error);
1261 ERR("Fail to get properties");
1262 g_object_unref(properties_proxy);
1263 return BT_STATUS_FAIL;
1266 g_variant_get(result, "(a{sv})", &property_iter);
1268 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
1269 if (!g_strcmp0(key, "UUID")) {
1270 desc_uuid_str = g_variant_get_string(value, &len);
1271 _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
1273 g_free((gchar *)key);
1274 g_variant_unref(value);
1279 g_variant_iter_free(property_iter);
1280 g_variant_unref(result);
1281 g_object_unref(properties_proxy);
1283 return BT_STATUS_SUCCESS;
1286 static void _bt_hal_send_client_desc_search_result_event(int conn_id, int status,
1287 btgatt_srvc_id_t *svc_id, btgatt_gatt_id_t *char_id, bt_uuid_t *desc_uuid)
1289 struct hal_ev_gatt_client_desc_search_result ev;
1292 ERR("gatt client callback not registered");
1296 memset(&ev, 0, sizeof(ev));
1297 ev.conn_id = conn_id;
1298 ev.inst_id = svc_id->id.inst_id;
1299 ev.is_primary = svc_id->is_primary;
1302 memcpy(ev.svc_uuid, svc_id->id.uuid.uu, sizeof(ev.svc_uuid));
1303 memcpy(ev.char_uuid, char_id->uuid.uu, sizeof(ev.char_uuid));
1305 if (status == BT_STATUS_SUCCESS) {
1306 /* building desc uuid */
1307 memcpy(ev.desc_uuid, desc_uuid->uu, sizeof(ev.desc_uuid));
1310 DBG("sending the desc search event. conn_id[%d] status[%d]", conn_id, status);
1312 event_cb(HAL_EV_GATT_CLIENT_DESC_SEARCH_RESULT, (void *)&ev, sizeof(ev));
1315 static bt_status_t _hal_gattc_get_all_descriptor(int conn_id,
1316 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
1318 hal_gattc_server_info_t * conn_info = NULL;
1319 hal_gattc_service_t *gattc_service = NULL;
1322 hal_gattc_char_t *gattc_char = NULL;
1323 hal_gattc_desc_t *gattc_desc = NULL;
1324 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1325 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1326 int status = BT_STATUS_FAIL;
1328 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1329 if (NULL == conn_info) {
1330 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1331 return BT_STATUS_FAIL;
1335 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1336 if (NULL == gattc_service) {
1337 ERR("Failed to get the gatt service");
1338 return BT_STATUS_FAIL;
1341 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1342 INFO("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1344 /* find characteristics */
1345 /* a service can have two char with same uuid */
1346 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
1347 gattc_char = (hal_gattc_char_t*)l->data;
1348 if (gattc_char == NULL)
1351 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
1352 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1353 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1355 /* get descriptor uuid */
1356 for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
1357 gattc_desc = (hal_gattc_desc_t *)m->data;
1358 if (gattc_desc == NULL)
1361 status = _hal_gattc_get_descriptor_info(gattc_desc);
1364 if (BT_STATUS_SUCCESS == status) {
1365 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
1366 char_id, &gattc_desc->desc_uuid);
1372 status = BT_STATUS_FAIL;
1373 _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id, char_id, NULL);
1375 browse_service_char(conn_id);
1376 /* retrive uuid for characteristic and object path for descriptor */
1378 return BT_STATUS_SUCCESS;
1382 * Enumerate descriptors for a given characteristic.
1383 * Set start_descr_id to NULL to get the first descriptor.
1385 bt_status_t btif_gattc_get_descriptor(int conn_id,
1386 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1387 btgatt_gatt_id_t *start_descr_id)
1389 CHECK_BTGATT_INIT();
1391 if (start_descr_id == NULL) {
1392 return _hal_gattc_get_all_descriptor(conn_id, srvc_id, char_id);
1394 DBG("TBD Get specific descriptor");
1395 return BT_STATUS_UNSUPPORTED;
1399 static void __hal_send_char_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1401 struct hal_ev_gatt_client_read_data ev;
1404 ERR("gatt client callback not registered");
1408 memset(&ev, 0, sizeof(ev));
1409 ev.conn_id = resp_data->conn_id;
1410 ev.inst_id = resp_data->srvc_id.id.inst_id;
1411 ev.is_primary = resp_data->srvc_id.is_primary;
1414 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1415 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1419 /* building the char read value */
1420 memcpy(ev.value, value, len);
1423 DBG("sending gatt client charac read event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1425 event_cb(HAL_EV_GATT_CLIENT_READ_CHARAC, (void *)&ev, sizeof(ev));
1428 static void __hal_internal_read_char_cb(GObject *source_object,
1429 GAsyncResult *res, gpointer user_data)
1431 GError *error = NULL;
1432 GDBusConnection *system_gconn = NULL;
1435 GByteArray *gp_byte_array = NULL;
1437 hal_gatt_resp_data_t *resp_data = user_data;
1438 int result = BT_STATUS_SUCCESS;
1440 system_gconn = _bt_hal_get_system_gconn();
1441 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1444 ERR("Read Characteristic dbus failed Error:[%s]", error->message);
1447 result = BT_STATUS_FAIL;
1448 __hal_send_char_read_event(resp_data, result, NULL, 0);
1449 g_clear_error(&error);
1454 gp_byte_array = g_byte_array_new();
1455 g_variant_get(value, "(ay)", &iter);
1457 while (g_variant_iter_loop(iter, "y", &g_byte))
1458 g_byte_array_append(gp_byte_array, &g_byte, 1);
1462 __hal_send_char_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
1466 g_byte_array_free(gp_byte_array, TRUE);
1467 g_variant_iter_free(iter);
1468 g_variant_unref(value);
1472 static bt_status_t _hal_read_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1473 btgatt_gatt_id_t *char_id, int auth_req)
1475 GDBusConnection *g_conn;
1476 hal_gatt_resp_data_t *resp_data;
1477 hal_gattc_service_t *gattc_service = NULL;
1478 GVariantBuilder *builder = NULL;
1480 hal_gattc_server_info_t * conn_info = NULL;
1481 hal_gattc_char_t *gattc_char = NULL;
1482 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1483 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1484 char* char_handle = NULL;
1486 /* get the connection info */
1487 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1488 if (NULL == conn_info) {
1489 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1490 return BT_STATUS_FAIL;
1494 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1495 if (NULL == gattc_service) {
1496 ERR("Failed to get the gatt service");
1497 return BT_STATUS_FAIL;
1500 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1502 /* find characteristic */
1503 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
1504 HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
1505 if (NULL == gattc_char) {
1506 ERR("Failed to get the gatt char");
1507 return BT_STATUS_FAIL;
1510 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1511 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1513 g_conn = _bt_hal_get_system_gconn();
1514 if (NULL == g_conn) {
1515 ERR("_bt_gdbus_get_system_gconn returned NULL");
1516 return BT_STATUS_FAIL;
1519 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1520 resp_data->conn_id = conn_id;
1521 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1522 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1524 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1527 g_variant_builder_add(builder, "{sv}", "offset",
1528 g_variant_new("q", offset));
1530 char_handle = gattc_char->chr_path;
1532 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1533 "ReadValue", g_variant_new("(a{sv})", builder),
1534 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1535 (GAsyncReadyCallback)__hal_internal_read_char_cb,
1536 (gpointer)resp_data);
1537 g_variant_builder_unref(builder);
1539 return BT_STATUS_SUCCESS;
1542 /** Read a characteristic on a remote device */
1543 bt_status_t btif_read_characteristic(int conn_id,
1544 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1547 CHECK_BTGATT_INIT();
1549 return _hal_read_characteristic_value(conn_id, srvc_id, char_id, auth_req);
1552 static void __hal_send_char_write_event(hal_gatt_resp_data_t *resp_data, int result)
1554 struct hal_ev_gatt_client_write_result ev;
1557 ERR("gatt client callback not registered");
1561 memset(&ev, 0, sizeof(ev));
1562 ev.conn_id = resp_data->conn_id;
1563 ev.inst_id = resp_data->srvc_id.id.inst_id;
1564 ev.is_primary = resp_data->srvc_id.is_primary;
1567 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1568 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1570 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
1572 event_cb(HAL_EV_GATT_CLIENT_WRITE_CHARAC, (void *)&ev, sizeof(ev));
1575 static void __hal_bluetooth_internal_write_cb(GObject *source_object,
1576 GAsyncResult *res, gpointer user_data)
1578 GError *error = NULL;
1579 GDBusConnection *system_gconn = NULL;
1581 hal_gatt_resp_data_t *resp_data = user_data;
1582 int result = BT_STATUS_SUCCESS;
1586 system_gconn = _bt_hal_get_system_gconn();
1587 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1590 ERR("write Characteristic dbus failed Error:[%s]", error->message);
1592 result = BT_STATUS_FAIL;
1594 __hal_send_char_write_event(resp_data, result);
1595 g_clear_error(&error);
1600 //send write value event
1601 __hal_send_char_write_event(resp_data, result);
1604 g_variant_unref(value);
1609 static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
1612 case HAL_GATT_WRITE_TYPE_WRITE:
1613 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1615 case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
1616 *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1619 ERR("Unknow write type : %d", type);
1620 return BT_STATUS_FAIL;
1623 return BT_STATUS_SUCCESS;
1627 static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
1629 GDBusConnection *conn;
1630 GVariantBuilder *builder = NULL;
1636 GUnixFDList *fd_list = NULL;
1638 conn = _bt_hal_get_system_gconn();
1640 ERR("_bt_gdbus_get_system_gconn returned NULL");
1641 return BT_STATUS_FAIL;
1644 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1645 //val = g_variant_new("ay", builder1);
1647 g_variant_builder_add(builder, "{sv}", "offset",
1648 g_variant_new("q", offset));
1650 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1651 "AcquireWrite", g_variant_new("(a{sv})", builder),
1652 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1653 NULL, &fd_list, NULL, &err);
1655 g_dbus_error_strip_remote_error(err);
1656 ERR("Error: %s", err->message);
1658 g_variant_builder_unref(builder);
1659 return BT_STATUS_FAIL;
1662 g_variant_get(value, "(hq)", &idx, &att_mtu);
1663 *fd = g_unix_fd_list_get(fd_list, idx, NULL);
1665 INFO("Acquired Write fd %d, index %d, mtu %d", *fd, idx, att_mtu);
1668 g_object_unref(fd_list);
1669 g_variant_unref(value);
1670 g_variant_builder_unref(builder);
1672 return BT_STATUS_SUCCESS;
1675 static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
1677 GDBusConnection *conn;
1678 GVariantBuilder *builder = NULL;
1682 gint32 idx, notify_fd;
1684 GUnixFDList *fd_list = NULL;
1686 conn = _bt_hal_get_system_gconn();
1689 ERR("_bt_gdbus_get_system_gconn returned NULL");
1690 return BT_STATUS_FAIL;
1694 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1697 g_variant_builder_add(builder, "{sv}", "offset",
1698 g_variant_new("q", offset));
1700 value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
1701 "AcquireNotify", g_variant_new("(a{sv})", builder),
1702 G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
1703 NULL, &fd_list, NULL, &err);
1705 g_dbus_error_strip_remote_error(err);
1706 ERR("Error: %s", err->message);
1708 g_variant_builder_unref(builder);
1709 return BT_STATUS_FAIL;
1712 g_variant_get(value, "(hq)", &idx, &att_mtu);
1713 notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
1716 INFO("Acquired Notify fd %d, mtu %d", notify_fd, *mtu);
1720 g_object_unref(fd_list);
1721 g_variant_unref(value);
1722 g_variant_builder_unref(builder);
1724 return BT_STATUS_SUCCESS;
1728 static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
1729 btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
1731 GVariant *val, *options;
1732 GVariantBuilder *builder1;
1733 GVariantBuilder *builder2;
1734 GDBusConnection *g_conn;
1737 hal_gatt_resp_data_t *resp_data;
1738 hal_gattc_service_t *gattc_service = NULL;
1739 hal_gattc_server_info_t * conn_info = NULL;
1740 hal_gattc_char_t *gattc_char = NULL;
1741 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
1742 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1743 char* char_handle = NULL;
1744 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
1745 int ret = BT_STATUS_SUCCESS;
1747 ret = __hal_get_write_prop(write_type, &write_prop);
1748 if (BT_STATUS_FAIL == ret) {
1749 DBG("received invalid write type:[%d] ", write_type);
1750 return BT_STATUS_FAIL;
1753 /* get the connection info */
1754 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1755 if (NULL == conn_info) {
1756 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1757 return BT_STATUS_FAIL;
1761 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1762 if (NULL == gattc_service) {
1763 ERR("Failed to get the gatt service");
1764 return BT_STATUS_FAIL;
1767 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
1768 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
1770 /* find characteristic */
1771 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1772 if (NULL == gattc_char) {
1773 ERR("Failed to get the gatt char");
1774 return BT_STATUS_FAIL;
1777 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1778 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1780 g_conn = _bt_hal_get_system_gconn();
1781 if (NULL == g_conn) {
1782 ERR("_bt_gdbus_get_system_gconn returned NULL");
1783 return BT_STATUS_FAIL;
1786 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
1787 resp_data->conn_id = conn_id;
1788 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
1789 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
1791 char_handle = gattc_char->chr_path;
1793 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1795 for (i = 0; i < length; i++)
1796 g_variant_builder_add(builder1, "y", value[i]);
1798 val = g_variant_new("ay", builder1);
1800 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1802 g_variant_builder_add(builder2, "{sv}", "offset",
1803 g_variant_new_uint16(offset));
1805 options = g_variant_new("a{sv}", builder2);
1807 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, char_handle, BT_HAL_GATT_CHAR_INTERFACE,
1809 g_variant_new("(y@ay@a{sv})", write_prop, val, options),
1811 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1812 (GAsyncReadyCallback)__hal_bluetooth_internal_write_cb,
1813 (gpointer)resp_data);
1815 g_variant_builder_unref(builder1);
1816 g_variant_builder_unref(builder2);
1818 return BT_STATUS_SUCCESS;
1821 bt_status_t btif_get_acquire_write_fd(int conn_id,
1822 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1823 int auth_req, int *fd, int*mtu)
1825 CHECK_BTGATT_INIT();
1827 hal_gattc_service_t *gattc_service = NULL;
1828 hal_gattc_server_info_t * conn_info = NULL;
1829 hal_gattc_char_t *gattc_char = NULL;
1830 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1832 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
1833 int ret = BT_STATUS_SUCCESS;
1835 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1837 /* get the connection info */
1838 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1839 if (NULL == conn_info) {
1840 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1841 return BT_STATUS_FAIL;
1845 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1846 if (NULL == gattc_service) {
1847 ERR("Failed to get the gatt service");
1848 return BT_STATUS_FAIL;
1851 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1852 if (NULL == gattc_char) {
1853 ERR("Failed to get the gatt char");
1854 return BT_STATUS_FAIL;
1857 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1858 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1860 ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
1861 if (ret != BT_STATUS_SUCCESS)
1867 bt_status_t btif_get_acquire_notify_fd(int conn_id,
1868 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
1870 CHECK_BTGATT_INIT();
1872 hal_gattc_service_t *gattc_service = NULL;
1873 hal_gattc_server_info_t * conn_info = NULL;
1874 hal_gattc_char_t *gattc_char = NULL;
1875 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
1877 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
1878 int ret = BT_STATUS_SUCCESS;
1880 DBG("svc isntance id [%d]", srvc_id->id.inst_id);
1882 /* get the connection info */
1883 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
1884 if (NULL == conn_info) {
1885 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
1886 return BT_STATUS_FAIL;
1890 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
1891 if (NULL == gattc_service) {
1892 ERR("Failed to get the gatt service");
1893 return BT_STATUS_FAIL;
1896 gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
1897 if (NULL == gattc_char) {
1898 ERR("Failed to get the gatt char");
1899 return BT_STATUS_FAIL;
1902 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
1903 INFO("%s %s", gattc_char->chr_path + 37, char_uuid_str);
1905 ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
1906 if (ret != BT_STATUS_SUCCESS)
1913 /** Write a remote characteristic */
1914 bt_status_t btif_write_characteristic(int conn_id,
1915 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
1916 int write_type, int len, int auth_req,
1919 CHECK_BTGATT_INIT();
1921 DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
1922 return _hal_write_characteristic_value(conn_id, srvc_id, char_id, write_type,
1923 len, auth_req, p_value);
1926 static void __hal_send_desc_read_event(hal_gatt_resp_data_t *resp_data, int result, uint8_t *value, int len)
1928 struct hal_ev_gatt_client_read_data ev;
1931 ERR("gatt client callback not registered");
1935 memset(&ev, 0, sizeof(ev));
1936 ev.conn_id = resp_data->conn_id;
1937 ev.inst_id = resp_data->srvc_id.id.inst_id;
1938 ev.is_primary = resp_data->srvc_id.is_primary;
1941 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
1942 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
1943 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.char_uuid));
1947 /* building the desc read value */
1948 memcpy(ev.value, value, len);
1951 DBG("sending gatt client desc read conn_id[%d] status[%d]", resp_data->conn_id, result);
1953 event_cb(HAL_EV_GATT_CLIENT_READ_DESC, (void *)&ev, sizeof(ev));
1956 static void __hal_internal_read_desc_cb(GObject *source_object,
1957 GAsyncResult *res, gpointer user_data)
1959 GError *error = NULL;
1960 GDBusConnection *system_gconn = NULL;
1963 GByteArray *gp_byte_array = NULL;
1965 hal_gatt_resp_data_t *resp_data = user_data;
1966 int result = BT_STATUS_SUCCESS;
1971 system_gconn = _bt_hal_get_system_gconn();
1972 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1975 ERR("Read descriptor dbus failed Error:[%s]", error->message);
1978 result = BT_STATUS_FAIL;
1979 __hal_send_desc_read_event(resp_data, result, NULL, 0);
1980 g_clear_error(&error);
1985 gp_byte_array = g_byte_array_new();
1986 g_variant_get(value, "(ay)", &iter);
1988 while (g_variant_iter_loop(iter, "y", &g_byte))
1989 g_byte_array_append(gp_byte_array, &g_byte, 1);
1993 for (i = 0; i < gp_byte_array->len; i++)
1994 DBG("%02x", gp_byte_array->data[i]);
1997 __hal_send_desc_read_event(resp_data, result, gp_byte_array->data, gp_byte_array->len);
2001 g_byte_array_free(gp_byte_array, TRUE);
2002 g_variant_iter_free(iter);
2003 g_variant_unref(value);
2008 static bt_status_t _hal_read_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2009 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *desc_id, int auth_req)
2011 GDBusConnection *g_conn;
2012 hal_gatt_resp_data_t *resp_data;
2013 hal_gattc_service_t *gattc_service = NULL;
2014 GVariantBuilder *builder = NULL;
2016 hal_gattc_server_info_t * conn_info = NULL;
2017 hal_gattc_char_t *gattc_char = NULL;
2018 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2019 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2020 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2021 char* desc_handle = NULL;
2024 hal_gattc_desc_t *gattc_desc = NULL;
2026 /* get the connection info */
2027 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2028 if (NULL == conn_info) {
2029 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2030 return BT_STATUS_FAIL;
2034 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2035 if (NULL == gattc_service) {
2036 ERR("Failed to get the gatt service");
2037 return BT_STATUS_FAIL;
2040 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2041 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2043 /* find characteristic */
2044 /* service can have two char with same uuid */
2045 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2046 gattc_char = (hal_gattc_char_t*)l->data;
2047 if (gattc_char == NULL)
2050 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2051 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2052 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2054 /* find descriptor */
2055 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
2057 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2058 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2064 if (NULL == gattc_desc) {
2065 ERR("Failed to get the gatt desc");
2066 return BT_STATUS_FAIL;
2069 g_conn = _bt_hal_get_system_gconn();
2070 if (NULL == g_conn) {
2071 ERR("_bt_gdbus_get_system_gconn returned NULL");
2072 return BT_STATUS_FAIL;
2075 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2076 resp_data->conn_id = conn_id;
2077 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2078 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2079 memcpy(&resp_data->desc_id, desc_id, sizeof(btgatt_gatt_id_t));
2081 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2084 g_variant_builder_add(builder, "{sv}", "offset",
2085 g_variant_new("q", offset));
2087 desc_handle = gattc_desc->desc_path;
2089 DBG("calling desc read value");
2091 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2092 "ReadValue", g_variant_new("(a{sv})", builder),
2093 G_VARIANT_TYPE("(ay)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2094 (GAsyncReadyCallback)__hal_internal_read_desc_cb,
2095 (gpointer)resp_data);
2096 g_variant_builder_unref(builder);
2098 return BT_STATUS_SUCCESS;
2101 /** Read the descriptor for a given characteristic */
2102 bt_status_t btif_read_descriptor(int conn_id,
2103 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2104 btgatt_gatt_id_t *descr_id, int auth_req)
2106 CHECK_BTGATT_INIT();
2108 return _hal_read_descriptor_value(conn_id, srvc_id, char_id, descr_id, auth_req);
2111 static void __hal_send_desc_write_event(hal_gatt_resp_data_t *resp_data, int result)
2113 struct hal_ev_gatt_client_write_result ev;
2116 ERR("gatt client callback not registered");
2120 memset(&ev, 0, sizeof(ev));
2121 ev.conn_id = resp_data->conn_id;
2122 ev.inst_id = resp_data->srvc_id.id.inst_id;
2123 ev.is_primary = resp_data->srvc_id.is_primary;
2126 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2127 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2128 memcpy(ev.desc_uuid, resp_data->desc_id.uuid.uu, sizeof(ev.desc_uuid));
2130 DBG("sending gatt client charac write event. conn_id[%d] status[%d]", resp_data->conn_id, result);
2132 event_cb(HAL_EV_GATT_CLIENT_WRITE_DESC, (void *)&ev, sizeof(ev));
2135 static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
2136 GAsyncResult *res, gpointer user_data)
2138 GError *error = NULL;
2139 GDBusConnection *system_gconn = NULL;
2141 hal_gatt_resp_data_t *resp_data = user_data;
2142 int result = BT_STATUS_SUCCESS;
2146 system_gconn = _bt_hal_get_system_gconn();
2147 value = g_dbus_connection_call_finish(system_gconn, res, &error);
2150 ERR("write descriptor dbus failed Error: [%s]", error->message);
2153 result = BT_STATUS_FAIL;
2154 __hal_send_desc_write_event(resp_data, result);
2155 g_clear_error(&error);
2160 //send write value event
2161 __hal_send_desc_write_event(resp_data, result);
2164 g_variant_unref(value);
2169 static bt_status_t _hal_write_descriptor_value(int conn_id, btgatt_srvc_id_t *srvc_id,
2170 btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id,
2171 int write_type, int length, int auth_req, char* value)
2173 GVariant *val, *options;
2174 GVariantBuilder *builder1;
2175 GVariantBuilder *builder2;
2176 GDBusConnection *g_conn;
2179 hal_gatt_resp_data_t *resp_data;
2180 hal_gattc_service_t *gattc_service = NULL;
2181 hal_gattc_server_info_t * conn_info = NULL;
2182 hal_gattc_char_t *gattc_char = NULL;
2183 hal_gattc_desc_t *gattc_desc = NULL;
2184 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2185 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2186 char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
2187 char* desc_handle = NULL;
2188 bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
2189 int ret = BT_STATUS_SUCCESS;
2194 ret = __hal_get_write_prop(write_type, &write_prop);
2195 if (BT_STATUS_FAIL == ret) {
2196 ERR("received invalid write type:[%d] ", write_type);
2197 return BT_STATUS_FAIL;
2200 /* get the connection info */
2201 conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
2202 if (NULL == conn_info) {
2203 ERR("Failed to get the conn_info for conn_id [%d]", conn_id);
2204 return BT_STATUS_FAIL;
2208 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2209 if (NULL == gattc_service) {
2210 ERR("Failed to get the gatt service");
2211 return BT_STATUS_FAIL;
2214 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2215 DBG("%s %s", gattc_service->svc_path + 37, svc_uuid_str);
2217 /* find characteristic */
2218 /* service can have two char with same uuid */
2219 for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
2220 gattc_char = (hal_gattc_char_t*)l->data;
2221 if (gattc_char == NULL)
2224 if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
2225 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2226 DBG("%s %s", gattc_char->chr_path + 37, char_uuid_str);
2228 /* find descriptor */
2229 gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
2231 _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
2232 DBG("%s %s", gattc_desc->desc_path + 37, desc_uuid_str);
2238 if (NULL == gattc_desc) {
2239 ERR("Failed to get the gatt desc");
2240 return BT_STATUS_FAIL;
2243 g_conn = _bt_hal_get_system_gconn();
2244 if (NULL == g_conn) {
2245 ERR("_bt_gdbus_get_system_gconn returned NULL");
2246 return BT_STATUS_FAIL;
2249 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2250 resp_data->conn_id = conn_id;
2251 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2252 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2253 memcpy(&resp_data->desc_id, descr_id, sizeof(btgatt_gatt_id_t));
2255 desc_handle = gattc_desc->desc_path;
2257 builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
2259 for (i = 0; i < length; i++)
2260 g_variant_builder_add(builder1, "y", value[i]);
2262 val = g_variant_new("ay", builder1);
2264 builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
2266 g_variant_builder_add(builder2, "{sv}", "offset",
2267 g_variant_new_uint16(offset));
2269 options = g_variant_new("a{sv}", builder2);
2271 g_dbus_connection_call(g_conn, BT_HAL_BLUEZ_NAME, desc_handle, BT_HAL_GATT_DESC_INTERFACE,
2273 g_variant_new("(@ay@a{sv})", val, options),
2275 G_DBUS_CALL_FLAGS_NONE, -1, NULL,
2276 (GAsyncReadyCallback)__hal_bluetooth_internal_desc_write_cb,
2277 (gpointer)resp_data);
2279 g_variant_builder_unref(builder1);
2280 g_variant_builder_unref(builder2);
2282 return BT_STATUS_SUCCESS;
2285 /** Write a remote descriptor for a given characteristic */
2286 bt_status_t btif_write_descriptor(int conn_id,
2287 btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
2288 btgatt_gatt_id_t *descr_id, int write_type, int len,
2289 int auth_req, char* p_value)
2291 CHECK_BTGATT_INIT();
2293 return _hal_write_descriptor_value(conn_id, srvc_id, char_id, descr_id, write_type,
2294 len, auth_req, p_value);
2297 /** Execute a prepared write operation */
2298 bt_status_t execute_write(int conn_id, int execute)
2300 CHECK_BTGATT_INIT();
2301 return BT_STATUS_UNSUPPORTED;
2304 static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
2306 struct hal_ev_gatt_client_watch_notification ev;
2307 hal_gatt_resp_data_t *resp_data = user_data;
2309 DBG("sending the watch register notification event");
2310 /* send the event */
2311 memset(&ev, 0, sizeof(ev));
2312 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2314 ev.status = resp_data->result;
2316 ev.is_primary = resp_data->srvc_id.is_primary;
2317 ev.inst_id = resp_data->srvc_id.id.inst_id;
2319 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2320 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2323 ERR("GATT Callback not registered");
2325 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2332 static bt_status_t _hal_register_for_notification(int client_if,
2333 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2334 btgatt_gatt_id_t *char_id)
2336 int result = BT_STATUS_SUCCESS;
2337 GError *error = NULL;
2338 GDBusConnection *g_conn;
2339 hal_gattc_client_info_t *gattc_client = NULL;
2340 hal_gattc_server_info_t * conn_info = NULL;
2341 hal_gattc_service_t *gattc_service = NULL;
2342 hal_gattc_char_t *gattc_char = NULL;
2343 char* char_handle = NULL;
2344 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2345 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2346 hal_gatt_resp_data_t *resp_data;
2350 gattc_client = __bt_find_gatt_client_info(bd_addr);
2351 if (gattc_client == NULL) {
2352 ERR("failed to get the gatt client info");
2353 return BT_STATUS_FAIL;
2356 if (gattc_client->client_if != client_if) {
2357 ERR("could not find the gatt client for client id[%d]", client_if);
2358 return BT_STATUS_FAIL;
2361 /* get the connection info */
2362 conn_info = __bt_find_gatt_conn_info(bd_addr);
2363 if (NULL == conn_info) {
2364 ERR("Failed to get the conn_info");
2365 return BT_STATUS_FAIL;
2368 if (conn_info->inst_id != gattc_client->inst_id) {
2369 ERR("could not fild the conn_info");
2370 return BT_STATUS_FAIL;
2374 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2375 if (NULL == gattc_service) {
2376 ERR("Failed to get the gatt service");
2377 return BT_STATUS_FAIL;
2380 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2381 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2384 /* find characteristic */
2385 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2386 if (NULL == gattc_char) {
2387 ERR("Failed to get the gatt char");
2388 return BT_STATUS_FAIL;
2391 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2392 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2394 char_handle = gattc_char->chr_path;
2396 g_conn = _bt_hal_get_system_gconn();
2397 if (g_conn == NULL) {
2399 return BT_STATUS_FAIL;
2402 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2404 INFO_C("### Request StartNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2406 g_dbus_connection_call_sync(g_conn,
2409 BT_HAL_GATT_CHAR_INTERFACE,
2413 G_DBUS_CALL_FLAGS_NONE,
2414 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2417 g_dbus_error_strip_remote_error(error);
2418 ERR("### StartNotify Failed: %s", error->message);
2419 if (g_strrstr(error->message, "Already notifying"))
2420 result = BT_STATUS_SUCCESS;
2421 else if (g_strrstr(error->message, "In Progress"))
2422 result = BT_STATUS_BUSY;
2423 else if (g_strrstr(error->message, "Operation is not supported"))
2424 result = BT_STATUS_UNSUPPORTED;
2425 /*failed because of either Insufficient Authorization or Write Not Permitted */
2426 else if (g_strrstr(error->message, "Write not permitted") ||
2427 g_strrstr(error->message, "Operation Not Authorized"))
2428 result = BT_STATUS_AUTH_FAILURE;
2429 /* failed because of either Insufficient Authentication,
2430 Insufficient Encryption Key Size, or Insufficient Encryption. */
2431 else if (g_strrstr(error->message, "Not paired"))
2432 result = BT_STATUS_NOT_READY;
2434 result = BT_STATUS_FAIL;
2436 g_clear_error(&error);
2439 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2440 resp_data->result = result;
2441 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2442 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2444 g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
2448 return BT_STATUS_SUCCESS;
2452 * Register to receive notifications or indications for a given
2455 bt_status_t btif_register_for_notification(int client_if,
2456 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2457 btgatt_gatt_id_t *char_id)
2459 CHECK_BTGATT_INIT();
2461 return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2464 static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
2466 struct hal_ev_gatt_client_watch_notification ev;
2467 hal_gatt_resp_data_t *resp_data = user_data;
2469 DBG("sending the watch deregister notification event");
2470 /* send the event */
2471 memset(&ev, 0, sizeof(ev));
2472 ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
2474 ev.status = resp_data->result;
2476 ev.is_primary = resp_data->srvc_id.is_primary;
2477 ev.inst_id = resp_data->srvc_id.id.inst_id;
2479 memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
2480 memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
2483 ERR("GATT Callback not registered");
2485 event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
2492 static bt_status_t _hal_deregister_for_notification(int client_if,
2493 bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2494 btgatt_gatt_id_t *char_id)
2496 int result = BT_STATUS_SUCCESS;
2497 GError *error = NULL;
2498 GDBusConnection *g_conn;
2499 hal_gattc_client_info_t *gattc_client = NULL;
2500 hal_gattc_server_info_t * conn_info = NULL;
2501 hal_gattc_service_t *gattc_service = NULL;
2502 hal_gattc_char_t *gattc_char = NULL;
2503 char* char_handle = NULL;
2504 char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
2505 char char_uuid_str[BT_HAL_UUID_STRING_LEN];
2506 hal_gatt_resp_data_t *resp_data;
2510 gattc_client = __bt_find_gatt_client_info(bd_addr);
2511 if (gattc_client == NULL) {
2512 ERR("failed to get the gatt client info");
2513 return BT_STATUS_FAIL;
2516 if (gattc_client->client_if != client_if) {
2517 ERR("could not find the gatt client for client id[%d]", client_if);
2518 return BT_STATUS_FAIL;
2521 /* get the connection info */
2522 conn_info = __bt_find_gatt_conn_info(bd_addr);
2523 if (NULL == conn_info) {
2524 ERR("Failed to get the conn_info");
2525 return BT_STATUS_FAIL;
2528 if (conn_info->inst_id != gattc_client->inst_id) {
2529 ERR("could not fild the conn_info");
2530 return BT_STATUS_FAIL;
2534 gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
2535 if (NULL == gattc_service) {
2536 ERR("Failed to get the gatt service");
2537 return BT_STATUS_FAIL;
2540 _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
2541 DBG("%s %s", gattc_service->svc_path + 15, svc_uuid_str);
2544 /* find characteristic */
2545 gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
2546 if (NULL == gattc_char) {
2547 ERR("Failed to get the gatt char");
2548 return BT_STATUS_FAIL;
2551 _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
2552 DBG("%s %s", gattc_char->chr_path + 15, char_uuid_str);
2554 char_handle = gattc_char->chr_path;
2556 g_conn = _bt_hal_get_system_gconn();
2557 if (g_conn == NULL) {
2559 return BT_STATUS_FAIL;
2562 resp_data = g_malloc0(sizeof(hal_gatt_resp_data_t));
2564 INFO("### Request StopNotify : %s [%s]", gattc_char->chr_path + 15, char_uuid_str);
2565 g_dbus_connection_call_sync(g_conn,
2568 BT_HAL_GATT_CHAR_INTERFACE,
2572 G_DBUS_CALL_FLAGS_NONE,
2573 BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
2576 ERR("### StopNotify Failed: %s", error->message);
2577 g_clear_error(&error);
2578 result = BT_STATUS_FAIL;
2581 resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
2582 resp_data->result = result;
2583 memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
2584 memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
2586 g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
2590 return BT_STATUS_SUCCESS;
2592 /** Deregister a previous request for notifications/indications */
2593 bt_status_t btif_deregister_for_notification(int client_if,
2594 const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
2595 btgatt_gatt_id_t *char_id)
2597 CHECK_BTGATT_INIT();
2598 return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
2601 /** Request RSSI for a given remote device */
2602 bt_status_t read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
2604 CHECK_BTGATT_INIT();
2605 return BT_STATUS_UNSUPPORTED;
2608 /** OTA firmware download */
2609 bt_status_t ota_fw_update(int client_if, int conn_id, const bt_bdaddr_t *bd_addr, char* path)
2611 CHECK_BTGATT_INIT();
2612 return BT_STATUS_UNSUPPORTED;
2615 /** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
2616 int get_device_type(const bt_bdaddr_t *bd_addr)
2618 CHECK_BTGATT_INIT();
2619 return BT_STATUS_UNSUPPORTED;
2622 static bt_status_t __hal_update_conn_parameter(bt_bdaddr_t *bd_addr,
2623 int min_int, int max_int, int latency, int timeout)
2625 gchar *device_path = NULL;
2626 GError *error = NULL;
2627 GDBusProxy *device_proxy = NULL;
2628 GDBusConnection *conn;
2630 int ret = BT_STATUS_SUCCESS;
2631 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2633 INFO("Min interval: %d, Max interval: %d, Latency: %d, Supervision timeout: %d",
2634 min_int, max_int, latency, timeout);
2636 conn = _bt_hal_get_system_gconn();
2639 return BT_STATUS_FAIL;
2642 _bt_hal_convert_addr_type_to_string(device_address,
2643 (unsigned char *)bd_addr->address);
2644 device_path = _bt_hal_get_device_object_path(device_address);
2646 if (device_path == NULL) {
2647 ERR("device_path NULL : [%s]", device_address);
2648 return BT_STATUS_FAIL;
2651 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2652 NULL, BT_HAL_BLUEZ_NAME,
2653 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2655 g_free(device_path);
2656 if (NULL == device_proxy) {
2657 ERR("device_proxy returned NULL");
2658 return BT_STATUS_FAIL;
2661 INFO("Request LeConnUpdate");
2662 reply = g_dbus_proxy_call_sync(device_proxy, "LeConnUpdate",
2663 g_variant_new("(uuuu)", min_int, max_int, latency, timeout),
2664 G_DBUS_CALL_FLAGS_NONE,
2669 g_object_unref(device_proxy);
2670 if (reply == NULL) {
2672 ERR("Error %s[%s]", error->message, device_address);
2673 if (g_strrstr(error->message, "In Progress"))
2674 ret = BT_STATUS_SUCCESS;
2676 ret = BT_STATUS_FAIL;
2677 g_error_free(error);
2681 g_variant_unref(reply);
2683 DBG("LE Connection parameter Updated");
2687 /** Request a connection parameter update */
2688 bt_status_t btif_gattc_conn_parameter_update(bt_bdaddr_t *bd, int min_int, int max_int, int latency, int timeout)
2690 CHECK_BTGATT_INIT();
2692 return __hal_update_conn_parameter(bd, min_int, max_int, latency, timeout);
2695 /** Test mode interface */
2696 bt_status_t test_command(int command, btgatt_test_params_t* params)
2698 CHECK_BTGATT_INIT();
2699 return BT_STATUS_UNSUPPORTED;
2702 static void __bt_request_att_mtu_device_cb(GDBusProxy *proxy, GAsyncResult *res,
2705 GError *g_error = NULL;
2706 GVariant *reply = NULL;
2707 int result = BT_STATUS_SUCCESS;
2708 struct hal_ev_gatt_client_mtu_exchange_completed ev;
2709 struct conn_mtu_s *conn_mtu = (struct conn_mtu_s *)user_data;
2711 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
2712 g_object_unref(proxy);
2713 if (reply == NULL) {
2714 ERR("Connect LE Dbus Call Error");
2716 ERR("Error occured in RequestAttMtu [%s]", g_error->message);
2717 g_clear_error(&g_error);
2719 result = BT_STATUS_FAIL;
2721 g_variant_unref(reply);
2723 memset(&ev, 0, sizeof(ev));
2725 ev.mtu = conn_mtu->mtu;
2726 ev.conn_id = conn_mtu->conn_id;
2729 ERR("gatt client callback not registered");
2731 DBG("sending gatt client MTU exchange completed event");
2732 event_cb(HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED , (void *)&ev, sizeof(ev));
2739 static bt_status_t __hal_configure_mtu(int conn_id, int mtu)
2741 gchar *device_path = NULL;
2742 GDBusProxy *device_proxy = NULL;
2743 GDBusConnection *conn;
2744 hal_gattc_client_info_t *gattc_client = NULL;
2745 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2746 struct conn_mtu_s *conn_mtu = g_malloc0(sizeof(struct conn_mtu_s));
2748 conn = _bt_hal_get_system_gconn();
2752 return BT_STATUS_FAIL;
2755 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
2756 if (gattc_client == NULL) {
2757 INFO("GATT client conn info not found");
2759 return BT_STATUS_FAIL;
2762 _bt_hal_convert_addr_type_to_string(device_address,
2763 (unsigned char *)gattc_client->bd_addr.address);
2765 device_path = _bt_hal_get_device_object_path(device_address);
2766 if (device_path == NULL) {
2767 ERR("device_path NULL : [%s]", device_address);
2769 return BT_STATUS_FAIL;
2772 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
2773 NULL, BT_HAL_BLUEZ_NAME,
2774 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
2776 g_free(device_path);
2777 if (NULL == device_proxy) {
2778 ERR("device_proxy returned NULL");
2780 return BT_STATUS_FAIL;
2783 conn_mtu->conn_id = conn_id;
2784 conn_mtu->mtu = mtu;
2786 g_dbus_proxy_call(device_proxy, "RequestAttMtu",
2787 g_variant_new("(q)", mtu),
2788 G_DBUS_CALL_FLAGS_NONE,
2789 BT_HAL_MAX_DBUS_TIMEOUT,
2791 (GAsyncReadyCallback)__bt_request_att_mtu_device_cb,
2794 return BT_STATUS_SUCCESS;
2797 /** MTU Exchange request from client */
2798 static bt_status_t configure_mtu(int conn_id, int mtu)
2800 CHECK_BTGATT_INIT();
2802 return __hal_configure_mtu(conn_id, mtu);
2805 /** Setup scan filter params */
2806 bt_status_t scan_filter_param_setup(int client_if, int action, int filt_index, int feat_seln,
2807 int list_logic_type, int filt_logic_type, int rssi_high_thres,
2808 int rssi_low_thres, int dely_mode, int found_timeout,
2809 int lost_timeout, int found_timeout_cnt)
2812 GError *error = NULL;
2813 GVariant *ret, *param;
2814 CHECK_BTGATT_INIT();
2816 proxy = _bt_hal_get_adapter_proxy();
2819 return BT_STATUS_FAIL;
2821 param = g_variant_new("(iiiiiiiiiiii)",
2834 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_param_setup",
2835 param, G_DBUS_CALL_FLAGS_NONE,
2839 ERR("scan_filter_param_setup Fail: %s", error->message);
2840 g_clear_error(&error);
2841 return BT_STATUS_FAIL;
2845 g_variant_unref(ret);
2847 return BT_STATUS_SUCCESS;
2850 /** Configure a scan filter condition */
2851 bt_status_t scan_filter_add_remove(int client_if, int action, int filt_type,
2852 int filt_index, int company_id,
2853 int company_id_mask, const bt_uuid_t *p_uuid,
2854 const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
2855 char addr_type, int data_len, char* p_data, int mask_len,
2859 GError *error = NULL;
2860 GVariant *ret, *param;
2861 GVariant *arr_uuid_param = NULL, *arr_uuid_mask_param = NULL;
2862 GVariant *arr_data_param = NULL, *arr_data_mask_param = NULL;
2863 GArray *arr_uuid = NULL;
2864 GArray *arr_uuid_mask = NULL;
2865 GArray *arr_data = NULL;
2866 GArray *arr_data_mask = NULL;
2867 CHECK_BTGATT_INIT();
2869 proxy = _bt_hal_get_adapter_proxy();
2872 return BT_STATUS_FAIL;
2874 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS) {
2876 char address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
2878 _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
2880 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS being added\nRemote Device Address is [%s]", address);
2882 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2883 NULL, 0, TRUE, NULL, NULL);
2884 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2885 NULL, 0, TRUE, NULL, NULL);
2886 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2887 NULL, 0, TRUE, NULL, NULL);
2888 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2889 NULL, 0, TRUE, NULL, NULL);
2891 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2892 client_if, // client_if
2893 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2894 BT_SCAN_FILTER_FEATURE_DEVICE_ADDRESS, // filter_type
2895 filt_index, // filter_index
2896 company_id, // company_id
2897 company_id_mask, // company_id_mask
2898 arr_uuid_param, // p_uuid
2899 arr_uuid_mask_param, // p_uuid_mask
2901 addr_type, // address_type
2902 arr_data_param, // p_data
2903 arr_data_mask_param); // p_mask
2905 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2906 param, G_DBUS_CALL_FLAGS_NONE,
2910 ERR("scan_filter_add_remove Fail: %s", error->message);
2911 g_clear_error(&error);
2912 return BT_STATUS_FAIL;
2916 g_variant_unref(ret);
2918 return BT_STATUS_SUCCESS;
2921 if (filt_type == BT_SCAN_FILTER_FEATURE_DEVICE_NAME) {
2923 INFO("BT_SCAN_FILTER_FEATURE_DEVICE_NAME being added\nRemote Device Name is %s", p_data);
2924 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2925 NULL, 0, TRUE, NULL, NULL);
2926 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2927 NULL, 0, TRUE, NULL, NULL);
2928 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2929 NULL, 0, TRUE, NULL, NULL);
2930 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2931 NULL, 0, TRUE, NULL, NULL);
2933 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2934 client_if, // client_if
2935 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2936 BT_SCAN_FILTER_FEATURE_DEVICE_NAME, // filter_type
2937 filt_index, // filter_index
2938 company_id, // company_id
2939 company_id_mask, // company_id_mask
2940 arr_uuid_param, // p_uuid
2941 arr_uuid_mask_param, // p_uuid_mask
2943 addr_type, // address_type
2944 arr_data_param, // p_data
2945 arr_data_mask_param);
2947 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2948 param, G_DBUS_CALL_FLAGS_NONE,
2952 ERR("scan_filter_add_remove Fail: %s", error->message);
2953 g_clear_error(&error);
2954 return BT_STATUS_FAIL;
2958 g_variant_unref(ret);
2960 return BT_STATUS_SUCCESS;
2963 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_UUID) {
2965 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
2966 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
2968 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
2969 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
2971 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
2972 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
2973 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2974 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
2975 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
2976 NULL, 0, TRUE, NULL, NULL);
2977 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
2978 NULL, 0, TRUE, NULL, NULL);
2980 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
2981 client_if, // client_if
2982 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
2983 BT_SCAN_FILTER_FEATURE_SERVICE_UUID, // filter_type
2984 filt_index, // filter_index
2985 company_id, // company_id
2986 company_id_mask, // company_id_mask
2987 arr_uuid_param, // p_uuid
2988 arr_uuid_mask_param, // p_uuid_mask
2990 addr_type, // address_type
2991 arr_data_param, // p_data
2992 arr_data_mask_param);
2994 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove",
2995 param, G_DBUS_CALL_FLAGS_NONE,
2999 ERR("scan_filter_add_remove Fail: %s", error->message);
3000 g_clear_error(&error);
3001 return BT_STATUS_FAIL;
3005 g_variant_unref(ret);
3007 g_array_free(arr_uuid, TRUE);
3008 g_array_free(arr_uuid_mask, TRUE);
3010 return BT_STATUS_SUCCESS;
3013 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID) {
3015 arr_uuid = g_array_new(TRUE, TRUE, sizeof(guint8));
3016 arr_uuid_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3018 g_array_append_vals(arr_uuid, p_uuid->uu, data_len * sizeof(guint8));
3019 g_array_append_vals(arr_uuid_mask, p_uuid_mask->uu, mask_len * sizeof(guint8));
3021 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3022 arr_uuid->data, arr_uuid->len, TRUE, NULL, NULL);
3023 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3024 arr_uuid_mask->data, arr_uuid_mask->len, TRUE, NULL, NULL);
3025 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3026 NULL, 0, TRUE, NULL, NULL);
3027 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3028 NULL, 0, TRUE, NULL, NULL);
3030 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3031 client_if, // client_if
3032 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3033 BT_SCAN_FILTER_FEATURE_SERVICE_SOLICITATION_UUID, // filter_type
3034 filt_index, // filter_index
3035 company_id, // company_id
3036 company_id_mask, // company_id_mask
3037 arr_uuid_param, // p_uuid
3038 arr_uuid_mask_param, // p_uuid_mask
3040 addr_type, // address_type
3041 arr_data_param, // p_data
3042 arr_data_mask_param);
3044 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3045 G_DBUS_CALL_FLAGS_NONE,
3049 ERR("scan_filter_add_remove Fail: %s", error->message);
3050 g_clear_error(&error);
3051 return BT_STATUS_FAIL;
3055 g_variant_unref(ret);
3057 g_array_free(arr_uuid, TRUE);
3058 g_array_free(arr_uuid_mask, TRUE);
3060 return BT_STATUS_SUCCESS;
3063 if (filt_type == BT_SCAN_FILTER_FEATURE_SERVICE_DATA) {
3065 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3066 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3068 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3069 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3071 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3072 NULL, 0, TRUE, NULL, NULL);
3073 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3074 NULL, 0, TRUE, NULL, NULL);
3075 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3076 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3077 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3078 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3080 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3081 client_if, // client_if
3082 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3083 BT_SCAN_FILTER_FEATURE_SERVICE_DATA, // filter_type
3084 filt_index, // filter_index
3085 company_id, // company_id
3086 company_id_mask, // company_id_mask
3087 arr_uuid_param, // p_uuid
3088 arr_uuid_mask_param, // p_uuid_mask
3090 addr_type, // address_type
3091 arr_data_param, // p_data
3092 arr_data_mask_param);
3094 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3095 G_DBUS_CALL_FLAGS_NONE,
3099 ERR("scan_filter_add_remove Fail: %s", error->message);
3100 g_clear_error(&error);
3101 return BT_STATUS_FAIL;
3105 g_variant_unref(ret);
3107 g_array_free(arr_data, TRUE);
3108 g_array_free(arr_data_mask, TRUE);
3110 return BT_STATUS_SUCCESS;
3113 if (filt_type == BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA) {
3115 arr_data = g_array_new(TRUE, TRUE, sizeof(guint8));
3116 arr_data_mask = g_array_new(TRUE, TRUE, sizeof(guint8));
3118 g_array_append_vals(arr_data, p_data, data_len * sizeof(guint8));
3119 g_array_append_vals(arr_data_mask, p_mask, mask_len * sizeof(guint8));
3121 arr_uuid_param = g_variant_new_from_data((const GVariantType *)"ay",
3122 NULL, 0, TRUE, NULL, NULL);
3123 arr_uuid_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3124 NULL, 0, TRUE, NULL, NULL);
3125 arr_data_param = g_variant_new_from_data((const GVariantType *)"ay",
3126 arr_data->data, arr_data->len, TRUE, NULL, NULL);
3127 arr_data_mask_param = g_variant_new_from_data((const GVariantType *)"ay",
3128 arr_data_mask->data, arr_data_mask->len, TRUE, NULL, NULL);
3130 param = g_variant_new("(iiiiii@ay@aysu@ay@ay)",
3131 client_if, // client_if
3132 action, // action (Add - 0x00, Delete - 0x01, Clear - 0x02)
3133 BT_SCAN_FILTER_FEATURE_MANUFACTURER_DATA, // filter_type
3134 filt_index, // filter_index
3135 company_id, // company_id
3136 company_id_mask, // company_id_mask
3137 arr_uuid_param, // p_uuid
3138 arr_uuid_mask_param, // p_uuid_mask
3140 addr_type, // address_type
3141 arr_data_param, // p_data
3142 arr_data_mask_param);
3144 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_add_remove", param,
3145 G_DBUS_CALL_FLAGS_NONE,
3149 ERR("scan_filter_add_remove Fail: %s", error->message);
3150 g_clear_error(&error);
3151 return BT_STATUS_FAIL;
3155 g_variant_unref(ret);
3157 g_array_free(arr_data, TRUE);
3158 g_array_free(arr_data_mask, TRUE);
3160 return BT_STATUS_SUCCESS;
3163 return BT_STATUS_UNSUPPORTED;
3166 /** Clear all scan filter conditions for specific filter index*/
3167 bt_status_t scan_filter_clear(int client_if, int filt_index)
3170 GError *error = NULL;
3172 CHECK_BTGATT_INIT();
3174 proxy = _bt_hal_get_adapter_proxy();
3176 return BT_STATUS_FAIL;
3178 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_clear",
3179 g_variant_new("(ii)", client_if, filt_index),
3180 G_DBUS_CALL_FLAGS_NONE,
3184 ERR("scan_filter_clear Fail: %s", error->message);
3185 g_clear_error(&error);
3186 return BT_STATUS_FAIL;
3189 g_variant_unref(ret);
3190 return BT_STATUS_SUCCESS;
3193 /** Enable / disable scan filter feature*/
3194 bt_status_t scan_filter_enable(int client_if, bool enable)
3197 GError *error = NULL;
3199 CHECK_BTGATT_INIT();
3201 proxy = _bt_hal_get_adapter_proxy();
3203 return BT_STATUS_FAIL;
3205 ret = g_dbus_proxy_call_sync(proxy, "scan_filter_enable",
3206 g_variant_new("(ib)", client_if, enable),
3207 G_DBUS_CALL_FLAGS_NONE,
3211 ERR("scan_filter_enable Fail: %s", error->message);
3212 g_clear_error(&error);
3213 return BT_STATUS_FAIL;
3215 g_variant_unref(ret);
3217 return BT_STATUS_SUCCESS;
3220 /** Sets the LE scan interval and window in units of N*0.625 msec */
3222 bt_status_t set_scan_parameters(int scan_type, int scan_interval, int scan_window)
3226 CHECK_BTGATT_INIT();
3228 le_scan_type = scan_type;
3229 ret = _bt_hal_adapter_le_set_scan_parameters(
3230 scan_type, scan_interval, scan_window);
3234 bt_status_t set_scan_parameters(int scan_interval, int scan_window)
3236 CHECK_BTGATT_INIT();
3237 return BT_STATUS_UNSUPPORTED;
3241 /* Configure the batchscan storage */
3242 bt_status_t batchscan_cfg_storage(int client_if, int batch_scan_full_max,
3243 int batch_scan_trunc_max, int batch_scan_notify_threshold)
3245 CHECK_BTGATT_INIT();
3246 return BT_STATUS_UNSUPPORTED;
3249 /* Enable batchscan */
3250 bt_status_t batchscan_enb_batch_scan(int client_if, int scan_mode,
3251 int scan_interval, int scan_window, int addr_type, int discard_rule)
3253 CHECK_BTGATT_INIT();
3254 return BT_STATUS_UNSUPPORTED;
3257 /* Disable batchscan */
3258 bt_status_t batchscan_dis_batch_scan(int client_if)
3260 CHECK_BTGATT_INIT();
3261 return BT_STATUS_UNSUPPORTED;
3264 /* Read out batchscan reports */
3265 bt_status_t batchscan_read_reports(int client_if, int scan_mode)
3267 CHECK_BTGATT_INIT();
3268 return BT_STATUS_UNSUPPORTED;
3271 const btgatt_client_interface_t btgatt_client_interface = {
3272 .register_client = btif_gattc_register_client,
3273 .unregister_client = btif_gattc_unregister_client,
3275 .connect = btif_gattc_client_connect,
3276 .disconnect = btif_gattc_client_disconnect,
3278 .search_service = btif_gattc_client_search_service,
3279 .get_included_service = get_included_service,
3280 .get_characteristic = btif_gattc_get_characteristic,
3281 .get_descriptor = btif_gattc_get_descriptor,
3282 .read_characteristic = btif_read_characteristic,
3283 .write_characteristic = btif_write_characteristic,
3284 .acquire_write = btif_get_acquire_write_fd,
3285 .acquire_notify = btif_get_acquire_notify_fd,
3286 .read_descriptor = btif_read_descriptor,
3287 .write_descriptor = btif_write_descriptor,
3288 .execute_write = execute_write,
3289 .register_for_notification = btif_register_for_notification,
3290 .deregister_for_notification = btif_deregister_for_notification,
3291 .read_remote_rssi = read_remote_rssi,
3292 .ota_fw_update = ota_fw_update,
3293 .get_device_type = get_device_type,
3294 .conn_parameter_update = btif_gattc_conn_parameter_update,
3295 .test_command = test_command,
3296 .configure_mtu = configure_mtu,
3297 .scan_filter_param_setup = scan_filter_param_setup,
3298 .scan_filter_add_remove = scan_filter_add_remove,
3299 .scan_filter_clear = scan_filter_clear,
3300 .scan_filter_enable = scan_filter_enable,
3301 .set_scan_parameters = set_scan_parameters,
3302 .batchscan_cfg_storage = batchscan_cfg_storage,
3303 .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
3304 .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
3305 .batchscan_read_reports = batchscan_read_reports,
3306 .add_connection_info = btif_gattc_add_connection_info,
3309 static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
3312 hal_gattc_server_info_t *info = NULL;
3314 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3315 info = (hal_gattc_server_info_t*)l->data;
3319 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3326 static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr)
3329 hal_gattc_client_info_t *info = NULL;
3331 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3332 info = (hal_gattc_client_info_t*)l->data;
3336 if (!memcmp(&info->bd_addr, serv_addr, sizeof(bt_bdaddr_t)))
3343 static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id)
3346 hal_gattc_client_info_t *info = NULL;
3348 for (l = hal_gattc_client_info_list; l != NULL; l = g_slist_next(l)) {
3349 info = (hal_gattc_client_info_t*)l->data;
3353 if (info->conn_id == conn_id)
3360 static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int conn_id)
3363 hal_gattc_server_info_t *info = NULL;
3364 hal_gattc_client_info_t *gattc_client = NULL;
3366 gattc_client = __bt_find_gatt_client_info_from_conn_id(conn_id);
3367 if (gattc_client == NULL) {
3368 ERR("GATT client conn info not found");
3372 for (l = hal_gattc_server_info_list; l != NULL; l = g_slist_next(l)) {
3373 info = (hal_gattc_server_info_t*)l->data;
3377 if ((info->inst_id == gattc_client->inst_id) &&
3378 !memcmp(&info->bd_addr, &gattc_client->bd_addr, sizeof(bt_bdaddr_t))) {
3385 static bt_status_t __bt_connect_le_device_internal(int client_if, const bt_bdaddr_t *bd_addr,
3386 gboolean auto_connect)
3388 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3389 gchar *device_path = NULL;
3390 GDBusProxy *device_proxy = NULL;
3391 GDBusConnection *conn;
3392 int ret = BT_STATUS_SUCCESS;
3393 hal_gattc_client_info_t *gattc_data;
3395 if (NULL == bd_addr) {
3396 ERR("bd_addr is NULL");
3397 return BT_STATUS_PARM_INVALID;
3400 conn = _bt_hal_get_system_gconn();
3402 ERR("_bt_gdbus_get_system_gconn returned NULL");
3403 return BT_STATUS_FAIL;
3406 _bt_hal_convert_addr_type_to_string(device_address,
3407 (unsigned char *)bd_addr->address);
3408 device_path = _bt_hal_get_device_object_path(device_address);
3409 if (device_path == NULL) {
3410 ERR("device_path NULL : [%s]", device_address);
3411 ret = BT_STATUS_FAIL;
3415 device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
3416 NULL, BT_HAL_BLUEZ_NAME,
3417 device_path, BT_HAL_DEVICE_INTERFACE, NULL, NULL);
3418 g_free(device_path);
3419 if (NULL == device_proxy) {
3420 ERR("device_proxy returned NULL");
3421 return BT_STATUS_FAIL;
3424 gattc_data = g_malloc0(sizeof(hal_gattc_client_info_t));
3425 memcpy(gattc_data->bd_addr.address, bd_addr->address,
3426 BT_HAL_ADDRESS_LENGTH_MAX);
3428 DBG("ConnectLE [%s]", device_address);
3430 gattc_data->client_if = client_if;
3432 g_dbus_proxy_call(device_proxy, "ConnectLE",
3433 g_variant_new("(b)", auto_connect),
3434 G_DBUS_CALL_FLAGS_NONE,
3435 BT_HAL_MAX_DBUS_TIMEOUT,
3437 (GAsyncReadyCallback)__le_connection_req_cb, gattc_data);
3442 static bt_status_t _bt_hold_current_advertising()
3444 int ret = BT_STATUS_FAIL;
3445 gboolean is_advertising = FALSE;
3448 is_advertising = _bt_hal_is_advertising_in_slot(0);
3449 if (is_advertising) {
3450 DBG("+ Stop current advertising");
3452 ret = _bt_hal_enable_advertising(0, 0, FALSE, FALSE);
3453 g_timeout_add(2000, __bt_hold_current_advertising_timeout_cb, NULL);
3459 static gboolean __bt_hold_current_advertising_timeout_cb(gpointer user_data)
3461 DBG("+ start current advertising");
3463 _bt_hal_enable_advertising(0, 0, TRUE, FALSE);
3468 static gboolean __bt_connect_le_timer_cb(gpointer user_data)
3470 DBG("Try to initiate pending LE connection");
3472 pending_le_conn_timer_id = 0;
3474 __bt_connect_le_device_internal(pending_le_conn_info->client_if,
3475 &pending_le_conn_info->bd_addr,
3476 pending_le_conn_info->auto_connect);
3478 g_free(pending_le_conn_info);
3479 pending_le_conn_info = NULL;
3484 static int __hal_generate_conn_id()
3486 return ++bt_conn_id;
3489 static int __hal_generate_server_instance_id()
3491 return ++bt_inst_id;
3494 static void __le_connection_req_cb(GDBusProxy *proxy, GAsyncResult *res,
3497 GError *g_error = NULL;
3498 GVariant *reply = NULL;
3499 hal_gattc_client_info_t *gattc_data = user_data;
3500 int result = BT_STATUS_SUCCESS;
3501 struct hal_ev_gatt_client_connected ev;
3502 hal_gattc_server_info_t *gatt_conn_info = NULL;
3504 reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
3505 g_object_unref(proxy);
3506 if (reply == NULL) {
3507 ERR("Connect LE Dbus Call Error");
3509 ERR("Error: %s\n", g_error->message);
3510 g_clear_error(&g_error);
3512 result = BT_STATUS_FAIL;
3514 g_variant_unref(reply);
3516 if (NULL == gattc_data) {
3517 ERR("gattc_data is NULL");
3522 if (result == BT_STATUS_FAIL) {
3523 memset(&ev, 0, sizeof(ev));
3526 ev.client_if = gattc_data->client_if;
3527 memcpy(ev.bdaddr, gattc_data->bd_addr.address,
3528 BT_HAL_ADDRESS_LENGTH_MAX);
3531 ERR("gatt client callback not registered");
3533 DBG("sending gatt client connected event");
3534 event_cb(HAL_EV_GATT_CLIENT_CONNECTED, (void *)&ev, sizeof(ev));
3540 DBG("LE connected. Adding the gattc server/client conn info in list");
3541 gattc_data->conn_id = __hal_generate_conn_id() ;
3542 gattc_data->inst_id = __hal_generate_server_instance_id();
3544 hal_gattc_client_info_list = g_slist_append(hal_gattc_client_info_list, gattc_data);
3546 /*add gatt server connection info*/
3547 gatt_conn_info = g_malloc0(sizeof(hal_gattc_server_info_t));
3548 memcpy(gatt_conn_info->bd_addr.address, gattc_data->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3549 gatt_conn_info->conn_id = gattc_data->conn_id;
3550 gatt_conn_info->inst_id = gattc_data->inst_id;
3551 hal_gattc_server_info_list = g_slist_append(hal_gattc_server_info_list, gatt_conn_info);
3556 /*remove conn_info*/
3561 static void __hal_gattc_free_desc_info(hal_gattc_desc_t *desc_info)
3563 g_free(desc_info->desc_path);
3567 static void __hal_gattc_free_char_info(hal_gattc_char_t *char_info)
3570 hal_gattc_desc_t *desc_info = NULL;
3571 for (l = char_info->gatt_list_descs; l != NULL; ) {
3572 desc_info = l->data;
3573 l = g_slist_next(l);
3574 if (desc_info == NULL)
3576 /* Remove descriptor element */
3577 char_info->gatt_list_descs = g_slist_remove(char_info->gatt_list_descs, desc_info);
3578 __hal_gattc_free_desc_info(desc_info);
3580 g_slist_free(char_info->gatt_list_descs);
3581 g_free(char_info->chr_path);
3585 static void __hal_gattc_free_svc_info(hal_gattc_service_t *svc_info)
3588 hal_gattc_char_t *char_info = NULL;
3589 for (l = svc_info->gatt_list_chars; l != NULL; ) {
3590 char_info = l->data;
3591 l = g_slist_next(l);
3592 if (char_info == NULL)
3594 /* Remove characteristic element */
3595 svc_info->gatt_list_chars = g_slist_remove(svc_info->gatt_list_chars, char_info);
3596 __hal_gattc_free_char_info(char_info);
3598 g_slist_free(svc_info->gatt_list_chars);
3599 g_free(svc_info->svc_path);
3603 static void __hal_clean_gattc_server_info(hal_gattc_server_info_t *conn_info)
3606 hal_gattc_service_t *svc_info = NULL;
3610 for (l = conn_info->gatt_list_services; l != NULL; ) {
3611 svc_info = (hal_gattc_service_t *)l->data;
3612 l = g_slist_next(l);
3613 if (svc_info == NULL)
3615 /* Remove service element */
3616 conn_info->gatt_list_services = g_slist_remove(conn_info->gatt_list_services, svc_info);
3617 __hal_gattc_free_svc_info(svc_info);
3619 g_slist_free(conn_info->gatt_list_services);
3623 gboolean _bt_hal_check_gattc_is_existing(const char *address)
3625 bt_bdaddr_t bd_addr;
3626 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3627 if (__bt_find_gatt_client_info(&bd_addr) != NULL)
3633 void _bt_hal_handle_gattc_connected_event(char* address, gboolean gatt_connected)
3635 int result = BT_STATUS_SUCCESS;
3636 struct hal_ev_gatt_client_connected ev;
3637 hal_gattc_server_info_t *conn_info = NULL;
3638 bt_bdaddr_t bd_addr;
3640 hal_gattc_client_info_t *gattc_client = NULL;
3643 event = gatt_connected ? HAL_EV_GATT_CLIENT_CONNECTED :
3644 HAL_EV_GATT_CLIENT_DISCONNECTED;
3646 _bt_hal_convert_addr_string_to_type(bd_addr.address, address);
3647 /* find the gatt client info */
3648 gattc_client = __bt_find_gatt_client_info(&bd_addr);
3649 if (NULL == gattc_client) {
3650 ERR("Fail to get gatt client info");
3654 gattc_client->is_gatt_connected = gatt_connected;
3657 memset(&ev, 0, sizeof(ev));
3658 ev.conn_id = gattc_client->conn_id;
3660 ev.client_if = gattc_client->client_if;
3661 memcpy(ev.bdaddr, gattc_client->bd_addr.address,
3662 BT_HAL_ADDRESS_LENGTH_MAX);
3665 ERR("gatt client callback not registered");
3667 event_cb(event, (void *)&ev, sizeof(ev));
3670 if (!gatt_connected) {
3671 inst_id = gattc_client->inst_id;
3673 /* remove the gatt client info from the client list also*/
3674 hal_gattc_client_info_list = g_slist_remove(hal_gattc_client_info_list, gattc_client);
3675 g_free(gattc_client);
3677 //find the connected server info
3678 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3679 if (NULL == conn_info) {
3680 ERR("Fail to get gatt server info");
3684 if (inst_id != conn_info->inst_id) {
3685 ERR("server instance is different");
3689 //remove gatt conn info from the server list
3690 DBG("remove the server conn_info from list after gatt disconnection");
3691 hal_gattc_server_info_list = g_slist_remove(hal_gattc_server_info_list, conn_info);
3692 __hal_clean_gattc_server_info(conn_info);
3696 static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
3697 const char* uuid_str, int inst_id)
3699 struct hal_ev_gatt_client_search_result ev;
3702 ERR("gatt client callback not registered");
3706 DBG("Send service searching result. [%s] conn_id[%d]", uuid_str, conn_id);
3708 memset(&ev, 0, sizeof(ev));
3709 ev.conn_id = conn_id;
3710 ev.inst_id = inst_id;
3711 ev.is_primary = is_primary;
3712 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3714 event_cb(HAL_EV_GATT_CLIENT_SEARCH_RESULT, (void *)&ev, sizeof(ev));
3717 static void _bt_hal_send_search_service_complete_event(int conn_id, int status)
3719 struct hal_ev_gatt_client_search_complete ev;
3722 ERR("gatt client callback not registered");
3726 DBG("sending gatt client search service complete event conn_id[%d]", conn_id);
3729 memset(&ev, 0, sizeof(ev));
3730 ev.conn_id = conn_id;
3733 event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
3736 static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
3737 hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
3738 char *char_value, int len)
3740 struct hal_ev_gatt_client_notify_changed_value ev;
3741 hal_gattc_client_info_t *gattc_client = NULL;
3744 ERR("gatt client callback not registered");
3748 gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
3749 if (NULL == gattc_client) {
3750 ERR("failed to get the gatt client info");
3755 DBG("sending gatt client connected status event");
3756 memset(&ev, 0, sizeof(ev));
3758 ev.conn_id = gattc_client->conn_id;
3759 ev.inst_id = conn_info->inst_id;
3760 ev.is_primary = svc_info->is_primary;
3761 memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
3762 memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
3764 memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
3766 if (len > 0 && (char_value != NULL)) {
3767 memcpy(ev.value, char_value, len);
3771 event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
3774 void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
3775 char *char_value, int len)
3777 char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
3778 hal_gattc_server_info_t *conn_info = NULL;
3779 bt_bdaddr_t bd_addr;
3782 hal_gattc_service_t *svc_info = NULL;
3783 hal_gattc_char_t *char_info = NULL;
3787 _bt_hal_convert_device_path_to_address(char_handle, device_address);
3788 device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
3789 DBG("device address:[%s]", device_address);
3790 DBG("char handle:[%s]", char_handle);
3792 _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
3793 conn_info = __bt_find_gatt_conn_info(&bd_addr);
3795 if (conn_info != NULL) {
3796 //find service for notified char path
3797 for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
3798 svc_info = (hal_gattc_service_t*)l->data;
3799 if (svc_info == NULL)
3802 /* find characteristic object path */
3803 for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
3804 char_info = (hal_gattc_char_t *)k->data;
3805 if (char_info == NULL)
3808 if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
3809 DBG("Found char handle[%s]", char_info->chr_path);
3812 _bt_hal_send_value_changed_event(conn_info, svc_info,
3813 char_info, char_value, len);
3821 static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
3823 GDBusConnection *g_conn = NULL;
3824 GDBusProxy *properties_proxy = NULL;
3825 GVariant *result = NULL;
3826 GError *error = NULL;
3827 GVariantIter *property_iter = NULL;
3828 const gchar *key = NULL;
3829 GVariant *value = NULL;
3830 const char *uuid_str = NULL;
3832 gboolean is_primary = FALSE;
3833 GVariantIter *char_iter = NULL;
3834 const char *char_handle = NULL;
3835 GPtrArray *gp_char_array = NULL;
3837 if (service_path == NULL) {
3838 ERR("service_path is NULL");
3839 return BT_STATUS_FAIL;
3842 DBG("service_path: %s", service_path);
3844 g_conn = _bt_hal_get_system_gconn();
3845 if (g_conn == NULL) {
3846 ERR("g_conn is NULL");
3847 return BT_STATUS_FAIL;
3850 properties_proxy = g_dbus_proxy_new_sync(g_conn,
3851 G_DBUS_PROXY_FLAGS_NONE, NULL,
3854 BT_HAL_PROPERTIES_INTERFACE,
3856 if (properties_proxy == NULL) {
3857 ERR("properties_proxy is NULL");
3858 return BT_STATUS_FAIL;
3861 result = g_dbus_proxy_call_sync(properties_proxy,
3863 g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
3864 G_DBUS_CALL_FLAGS_NONE,
3866 if (result == NULL) {
3867 if (error != NULL) {
3868 ERR("Fail to get properties (Error: %s)", error->message);
3869 g_clear_error(&error);
3871 ERR("Fail to get properties");
3873 g_object_unref(properties_proxy);
3874 return BT_STATUS_FAIL;
3877 g_variant_get(result, "(a{sv})", &property_iter);
3879 while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
3880 if (g_strcmp0(key, "UUID") == 0) {
3881 uuid_str = g_variant_get_string(value, &len);
3882 } else if (g_strcmp0(key, "Primary") == 0) {
3883 is_primary = g_variant_get_boolean(value);
3884 } else if (g_strcmp0(key, "Characteristics") == 0) {
3885 g_variant_get(value, "ao", &char_iter);
3886 if (char_iter != NULL) {
3887 gp_char_array = g_ptr_array_new();
3888 while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
3889 DBG("char_handle: %s", char_handle);
3890 g_ptr_array_add(gp_char_array, (gpointer)char_handle);
3892 g_variant_iter_free(char_iter);
3897 if (uuid_str == NULL || gp_char_array == NULL) {
3898 ERR("uuid_str and gp_char_array should be set");
3902 /* Create new service */
3903 _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
3906 g_variant_iter_free(property_iter);
3907 g_variant_unref(result);
3908 g_object_unref(properties_proxy);
3910 return BT_STATUS_SUCCESS;
3913 static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
3915 GDBusConnection *conn = NULL;
3916 GDBusProxy *proxy = NULL;
3918 GVariant *ret = NULL;
3919 GVariant *value = NULL;
3921 conn = _bt_hal_get_system_gconn();
3923 ERR("_bt_gdbus_get_system_gconn returned NULL");
3927 proxy = g_dbus_proxy_new_sync(conn,
3928 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
3929 BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
3930 if (proxy == NULL) {
3931 ERR("device_proxy returned NULL");
3935 ret = g_dbus_proxy_call_sync(proxy, "Get",
3936 g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
3937 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3939 ERR("DBus Error : %s", err->message);
3940 g_clear_error(&err);
3942 g_variant_get(ret, "(v)", &value);
3943 *service_uuid = g_variant_dup_string(value, NULL);
3944 g_variant_unref(value);
3945 g_variant_unref(ret);
3949 g_object_unref(proxy);
3954 void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
3956 struct hal_ev_gatt_client_service_changed ev = {0, };
3957 char address[BT_HAL_ADDRESS_STRING_SIZE];
3958 hal_gattc_server_info_t *server_info = NULL;
3959 hal_gattc_client_info_t *gattc_client = NULL;
3960 hal_gattc_service_t *service = NULL;
3961 GSList *list = NULL;
3962 char *uuid_str = NULL;
3964 _bt_hal_convert_device_path_to_address(path, address);
3965 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
3966 server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
3967 if (server_info == NULL) {
3968 ERR("service_info is NULL");
3972 gattc_client = __bt_find_gatt_client_info((bt_bdaddr_t *)ev.bdaddr);
3973 if (gattc_client == NULL) {
3974 ERR("gattc_client is NULL");
3978 if (gattc_client->is_gatt_connected == FALSE) {
3979 DBG("GattConnected signal is not received yet. Just skip");
3984 /* Get service UUID from path */
3985 __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
3987 DBG("conn_id(%d) GATT Service(%s) Added", server_info->conn_id, uuid_str);
3988 _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
3991 ERR("uuid_str is NULL");
3995 /* Create new service and append into the list */
3996 __hal_gattc_get_service_info(server_info, path);
3998 /* Find service UUID from path */
3999 for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
4000 service = (hal_gattc_service_t *)list->data;
4001 if (service == NULL)
4004 if (g_strcmp0(service->svc_path, path) == 0) {
4005 memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
4006 uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
4007 _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
4008 DBG("conn_id(%d) GATT Service(%s) Removed", server_info->conn_id, uuid_str);
4010 /* Remove service info in list */
4011 server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
4012 __hal_gattc_free_svc_info(service);
4020 ERR("uuid_str is NULL");
4025 /* Send GATT Client service changed event */
4026 ev.change_type = is_added;
4027 ev.conn_id = server_info->conn_id;
4028 ev.inst_id = server_info->inst_id;
4029 event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));