#include <dlog.h>
#include <gio/gio.h>
#include <glib.h>
+#include <gio/gunixfdlist.h>
#include "bt-hal-log.h"
typedef struct {
gchar *svc_path;
bt_uuid_t svc_uuid;
+ int is_primary;
GSList *gatt_list_chars;
} hal_gattc_service_t;
/* Linked list of connected GATT client connection */
static GSList * hal_gattc_client_info_list = NULL;
-
static bt_pending_le_conn_info_s *pending_le_conn_info = NULL;
static guint pending_le_conn_timer_id = 0;
static int bt_conn_id = 0;
typedef struct {
int conn_id;
+ int result;
btgatt_srvc_id_t srvc_id;
btgatt_gatt_id_t char_id;
btgatt_gatt_id_t desc_id;
} hal_gatt_resp_data_t;
-
typedef struct {
int client_if;
bt_uuid_t app_uuid;
static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
const char* uuid_str, int inst_id);
static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
+static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr);
+static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
/* To send stack event to hal-av handler */
}
-static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
+static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid,
+ bt_gatt_characteristic_property_t prop)
+{
+ DBG("+");
+
+ GSList *l;
+ hal_gattc_char_t *info = NULL;
+
+ for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
+ info = (hal_gattc_char_t*)l->data;
+ if (info == NULL)
+ continue;
+
+ if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
+ (info->permission & prop)) {
+ INFO("Found GATT char uuid");
+ return info;
+ }
+ }
+ return NULL;
+}
+
+static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid)
{
DBG("+");
if (info == NULL)
continue;
- if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t))) {
+ if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) &&
+ ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) ||
+ (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) {
INFO("Found GATT char uuid");
return info;
}
static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
- const char *uuid_str, char *object_path)
+ const char *uuid_str, char *object_path, int is_primary)
{
DBG("+");
hal_gattc_service_t *gattc_service = NULL;
gattc_service = g_malloc0(sizeof(hal_gattc_service_t));
gattc_service->svc_path = g_strdup(object_path);
_bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str);
+ gattc_service->is_primary = is_primary;
DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services));
DBG("+");
/* add the service */
- gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path);
+ gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary);
if (gatt_svc == NULL) {
ERR("Failed to add service");
return;
GVariantIter *property_iter;
GVariantIter *char_desc_iter;
char* char_handle = NULL;
- const gchar *char_uuid_str = NULL;
+ gchar *char_uuid_str = NULL;
GPtrArray *gp_desc_array = NULL;
GVariantIter *char_perm_iter;
gchar* permission;
_hal_gattc_update_char_property(gattc_char, char_uuid_str, gp_desc_array, char_permission);
+ g_free(char_uuid_str);
g_variant_iter_free(property_iter);
g_variant_unref(result);
g_object_unref(properties_proxy);
while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
if (!g_strcmp0(key, "UUID")) {
- desc_uuid_str = g_variant_dup_string(value, &len);
+ desc_uuid_str = g_variant_get_string(value, &len);
DBG("desc UUID [%s]", desc_uuid_str);
+ _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
+ break;
}
}
- _hal_gattc_update_desc_property(gattc_desc, desc_uuid_str);
-
g_variant_iter_free(property_iter);
g_variant_unref(result);
g_object_unref(properties_proxy);
hal_gattc_server_info_t * conn_info = NULL;
hal_gattc_service_t *gattc_service = NULL;
GSList *l;
+ GSList *m;
hal_gattc_char_t *gattc_char = NULL;
hal_gattc_desc_t *gattc_desc = NULL;
char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
DBG("service uuid [%s]", svc_uuid_str);
/* find characteristics */
- gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
- if (NULL == gattc_char) {
- DBG("Failed to get the gatt char");
- return BT_STATUS_FAIL;
- }
+ /* a service can have two char with same uuid */
+ for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
+ gattc_char = (hal_gattc_char_t*)l->data;
+ if (gattc_char == NULL)
+ continue;
- DBG("char path [%s]", gattc_char->chr_path);
- _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
- DBG("char uuid [%s]", char_uuid_str);
+ if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
+ INFO("Found GATT char uuid");
+ DBG("char path [%s]", gattc_char->chr_path);
+ _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+ DBG("char uuid [%s]", char_uuid_str);
+
+ /* get descriptor uuid */
+ for (m = gattc_char->gatt_list_descs; m != NULL; m = g_slist_next(m)) {
+ gattc_desc = (hal_gattc_desc_t *)m->data;
+ if (gattc_desc == NULL)
+ continue;
- /* get descriptor uuid */
- for (l = gattc_char->gatt_list_descs; l != NULL; l = g_slist_next(l)) {
- gattc_desc = (hal_gattc_desc_t *)l->data;
- status = _hal_gattc_get_descriptor_info(gattc_desc);
+ status = _hal_gattc_get_descriptor_info(gattc_desc);
- /* send event */
- if (BT_STATUS_SUCCESS == status) {
- DBG("Sending the success descriptor event");
- _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
- char_id, &gattc_desc->desc_uuid);
+ /* send event */
+ if (BT_STATUS_SUCCESS == status) {
+ DBG("Sending the success descriptor event");
+ _bt_hal_send_client_desc_search_result_event(conn_id, status, srvc_id,
+ char_id, &gattc_desc->desc_uuid);
+ }
+ }
}
}
value = g_dbus_connection_call_finish(system_gconn, res, &error);
if (error) {
- ERR("Read Characteristic dbus failed Error:", error->message);
+ ERR("Read Characteristic dbus failed Error:[%s]", error->message);
//send failed event
result = BT_STATUS_FAIL;
/* find characteristic */
- gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
+ gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid,
+ HAL_GATT_CHARACTERISTIC_PROPERTY_READ);
if (NULL == gattc_char) {
DBG("Failed to get the gatt char");
return BT_STATUS_FAIL;
value = g_dbus_connection_call_finish(system_gconn, res, &error);
if (error) {
- ERR("write Characteristic dbus failed Error:", error->message);
+ ERR("write Characteristic dbus failed Error:[%s]", error->message);
result = BT_STATUS_FAIL;
//send failed event
DBG("-");
}
-static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, hal_gatt_property_e *prop)
+static bt_status_t __hal_get_write_prop(hal_gatt_write_type_t type, bt_gatt_characteristic_property_t *prop)
{
switch (type) {
case HAL_GATT_WRITE_TYPE_WRITE:
- *prop = HAL_GATT_PROPERTY_WRITE;
+ *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
break;
case HAL_GATT_WRITE_TYPE_WRITE_NO_RESPONSE:
- *prop = HAL_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE;
+ *prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
break;
default:
ERR("Unknow write type : %d", type);
return BT_STATUS_SUCCESS;
}
+
+static int __bluetooth_gatt_acquire_write_fd(const char *chr, int *fd, int *mtu)
+{
+ GDBusConnection *conn;
+ GVariantBuilder *builder = NULL;
+ guint16 offset = 0;
+ GError *err = NULL;
+ GVariant *value;
+ gint32 idx;
+ guint16 att_mtu;
+ GUnixFDList *fd_list = NULL;
+
+ conn = _bt_hal_get_system_gconn();
+ if (NULL == conn) {
+ ERR("_bt_gdbus_get_system_gconn returned NULL");
+ return BT_STATUS_FAIL;
+ }
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+ //val = g_variant_new("ay", builder1);
+
+ g_variant_builder_add(builder, "{sv}", "offset",
+ g_variant_new("q", offset));
+
+ value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
+ "AcquireWrite", g_variant_new("(a{sv})", builder),
+ G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
+ NULL, &fd_list, NULL, &err);
+ if (err != NULL) {
+ g_dbus_error_strip_remote_error(err);
+ ERR("Error: %s", err->message);
+ g_error_free(err);
+ g_variant_builder_unref(builder);
+ return BT_STATUS_FAIL;
+ }
+
+ g_variant_get(value, "(hq)", &idx, &att_mtu);
+ *fd = g_unix_fd_list_get(fd_list, idx, NULL);
+
+ INFO("FD is %d index is %d mtu is %d", *fd, idx, att_mtu);
+ *mtu = att_mtu;
+
+ g_object_unref(fd_list);
+ g_variant_unref(value);
+ g_variant_builder_unref(builder);
+
+ return BT_STATUS_SUCCESS;
+}
+
+static int __bluetooth_gatt_acquire_notify_fd(const char *chr, int *fd, int *mtu)
+{
+ GDBusConnection *conn;
+ GVariantBuilder *builder = NULL;
+ guint16 offset = 0;
+ GError *err = NULL;
+ GVariant *value;
+ gint32 idx, notify_fd;
+ guint16 att_mtu;
+ GUnixFDList *fd_list = NULL;
+
+ conn = _bt_hal_get_system_gconn();
+
+ if (NULL == conn) {
+ ERR("_bt_gdbus_get_system_gconn returned NULL");
+ return BT_STATUS_FAIL;
+ }
+
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+
+ g_variant_builder_add(builder, "{sv}", "offset",
+ g_variant_new("q", offset));
+
+ value = g_dbus_connection_call_with_unix_fd_list_sync(conn, BT_HAL_BLUEZ_NAME, chr, BT_HAL_GATT_CHAR_INTERFACE,
+ "AcquireNotify", g_variant_new("(a{sv})", builder),
+ G_VARIANT_TYPE("(hq)"), G_DBUS_CALL_FLAGS_NONE, -1,
+ NULL, &fd_list, NULL, &err);
+ if (err != NULL) {
+ g_dbus_error_strip_remote_error(err);
+ ERR("Error: %s", err->message);
+ g_error_free(err);
+ g_variant_builder_unref(builder);
+ return BT_STATUS_FAIL;
+ }
+
+ g_variant_get(value, "(hq)", &idx, &att_mtu);
+ notify_fd = g_unix_fd_list_get(fd_list, idx, NULL);
+ *mtu = att_mtu;
+
+ INFO("Acquired characteristic Notify fd %d, mtu %d", notify_fd, *mtu);
+
+ *fd = notify_fd;
+
+ g_object_unref(fd_list);
+ g_variant_unref(value);
+ g_variant_builder_unref(builder);
+
+ return BT_STATUS_SUCCESS;
+}
+
+
static bt_status_t _hal_write_characteristic_value(int conn_id, btgatt_srvc_id_t *srvc_id,
btgatt_gatt_id_t *char_id, int write_type, int length, int auth_req, char* value)
{
char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
char char_uuid_str[BT_HAL_UUID_STRING_LEN];
char* char_handle = NULL;
- hal_gatt_property_e write_prop = HAL_GATT_PROPERTY_WRITE;
+ bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
int ret = BT_STATUS_SUCCESS;
DBG("+");
DBG("service uuid [%s]", svc_uuid_str);
/* find characteristic */
- gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
+ gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
if (NULL == gattc_char) {
DBG("Failed to get the gatt char");
return BT_STATUS_FAIL;
return BT_STATUS_SUCCESS;
}
+bt_status_t btif_get_acquire_write_fd(int conn_id,
+ btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
+ int auth_req, int *fd, int*mtu)
+{
+ CHECK_BTGATT_INIT();
+
+ DBG("+");
+
+ DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
+
+
+ hal_gattc_service_t *gattc_service = NULL;
+ hal_gattc_server_info_t * conn_info = NULL;
+ hal_gattc_char_t *gattc_char = NULL;
+ char char_uuid_str[BT_HAL_UUID_STRING_LEN];
+
+ bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE;
+ int ret = BT_STATUS_SUCCESS;
+
+ DBG("+");
+
+ /* get the connection info */
+ conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
+ if (NULL == conn_info) {
+ DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
+ return BT_STATUS_FAIL;
+ }
+
+ /* find service */
+ gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
+ if (NULL == gattc_service) {
+ DBG("Failed to get the gatt service");
+ return BT_STATUS_FAIL;
+ }
+
+ gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
+ if (NULL == gattc_char) {
+ DBG("Failed to get the gatt char");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("char path [%s]", gattc_char->chr_path);
+ _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+ DBG("char uuid [%s]", char_uuid_str);
+
+
+ ret = __bluetooth_gatt_acquire_write_fd(gattc_char->chr_path, fd, mtu);
+ if (ret != BT_STATUS_SUCCESS)
+ return ret;
+
+
+ ERR("Characterstics FD erite characterstics fd is %d", *fd);
+
+ return ret;
+}
+
+bt_status_t btif_get_acquire_notify_fd(int conn_id,
+ btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, int *fd, int *mtu)
+{
+ CHECK_BTGATT_INIT();
+
+ DBG("+");
+
+ DBG("svc isntance id:[%d]", srvc_id->id.inst_id);
+
+
+ hal_gattc_service_t *gattc_service = NULL;
+ hal_gattc_server_info_t * conn_info = NULL;
+ hal_gattc_char_t *gattc_char = NULL;
+ char char_uuid_str[BT_HAL_UUID_STRING_LEN];
+
+ bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY;
+ int ret = BT_STATUS_SUCCESS;
+
+ DBG("+");
+
+ /* get the connection info */
+ conn_info = __bt_find_gatt_conn_info_from_conn_id(conn_id);
+ if (NULL == conn_info) {
+ DBG("Failed to get the conn_info for conn_id[%d]", conn_id);
+ return BT_STATUS_FAIL;
+ }
+
+ /* find service */
+ gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
+ if (NULL == gattc_service) {
+ DBG("Failed to get the gatt service");
+ return BT_STATUS_FAIL;
+ }
+
+ gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, write_prop);
+ if (NULL == gattc_char) {
+ DBG("Failed to get the gatt char");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("char path [%s]", gattc_char->chr_path);
+ _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+ DBG("char uuid [%s]", char_uuid_str);
+
+
+ ret = __bluetooth_gatt_acquire_notify_fd(gattc_char->chr_path, fd, mtu);
+ if (ret != BT_STATUS_SUCCESS)
+ return ret;
+
+
+ ERR("Characterstics FD write characterstics fd is %d", *fd);
+
+ return ret;
+
+}
+
+
/** Write a remote characteristic */
bt_status_t btif_write_characteristic(int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
value = g_dbus_connection_call_finish(system_gconn, res, &error);
if (error) {
- ERR("Read descriptor dbus failed Error:", error->message);
+ ERR("Read descriptor dbus failed Error:[%s]", error->message);
//send failed event
result = BT_STATUS_FAIL;
char char_uuid_str[BT_HAL_UUID_STRING_LEN];
char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
char* desc_handle = NULL;
+ GSList *l;
hal_gattc_desc_t *gattc_desc = NULL;
DBG("service uuid [%s]", svc_uuid_str);
/* find characteristic */
- gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
- if (NULL == gattc_char) {
- DBG("Failed to get the gatt char");
- return BT_STATUS_FAIL;
- }
+ /* service can have two char with same uuid */
+ for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
+ gattc_char = (hal_gattc_char_t*)l->data;
+ if (gattc_char == NULL)
+ continue;
- DBG("char path [%s]", gattc_char->chr_path);
- _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
- DBG("char uuid [%s]", char_uuid_str);
+ if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
+ INFO("Found GATT char uuid");
+ DBG("char path [%s]", gattc_char->chr_path);
+ _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+ DBG("char uuid [%s]", char_uuid_str);
+
+ /* find descriptor */
+ gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
+ if (gattc_desc) {
+ DBG("desc path [%s]", gattc_desc->desc_path);
+ _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
+ DBG("desc uuid [%s]", desc_uuid_str);
+ break;
+ }
+ }
+ }
- /* find descriptor */
- gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &desc_id->uuid);
if (NULL == gattc_desc) {
DBG("Failed to get the gatt desc");
return BT_STATUS_FAIL;
}
- DBG("desc path [%s]", gattc_desc->desc_path);
- _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
- DBG("desc uuid [%s]", desc_uuid_str);
-
g_conn = _bt_hal_get_system_gconn();
if (NULL == g_conn) {
ERR("_bt_gdbus_get_system_gconn returned NULL");
value = g_dbus_connection_call_finish(system_gconn, res, &error);
if (error) {
- ERR("write descriptor dbus failed Error:", error->message);
+ ERR("write descriptor dbus failed Error: [%s]", error->message);
//send failed event
result = BT_STATUS_FAIL;
char char_uuid_str[BT_HAL_UUID_STRING_LEN];
char desc_uuid_str[BT_HAL_UUID_STRING_LEN];
char* desc_handle = NULL;
- hal_gatt_property_e write_prop = HAL_GATT_PROPERTY_WRITE;
+ bt_gatt_characteristic_property_t write_prop = HAL_GATT_CHARACTERISTIC_PROPERTY_WRITE;
int ret = BT_STATUS_SUCCESS;
+ GSList *l;
DBG("+");
DBG("service uuid [%s]", svc_uuid_str);
/* find characteristic */
- gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
- if (NULL == gattc_char) {
- DBG("Failed to get the gatt char");
- return BT_STATUS_FAIL;
- }
+ /* service can have two char with same uuid */
+ for (l = gattc_service->gatt_list_chars; l != NULL; l = g_slist_next(l)) {
+ gattc_char = (hal_gattc_char_t*)l->data;
+ if (gattc_char == NULL)
+ continue;
- DBG("char path [%s]", gattc_char->chr_path);
- _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
- DBG("char uuid [%s]", char_uuid_str);
+ if (!memcmp(&gattc_char->chr_uuid, &char_id->uuid, sizeof(bt_uuid_t))) {
+ INFO("Found GATT char uuid");
+ DBG("char path [%s]", gattc_char->chr_path);
+ _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+ DBG("char uuid [%s]", char_uuid_str);
+
+ /* find descriptor */
+ gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
+ if (gattc_desc) {
+ DBG("desc path [%s]", gattc_desc->desc_path);
+ _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
+ DBG("desc uuid [%s]", desc_uuid_str);
+ break;
+ }
+ }
+ }
- /* find descriptor */
- gattc_desc = _gattc_find_desc_from_uuid(gattc_char, &descr_id->uuid);
if (NULL == gattc_desc) {
- DBG("Failed to get the gatt char");
+ DBG("Failed to get the gatt desc");
return BT_STATUS_FAIL;
}
- DBG("desc path [%s]", gattc_desc->desc_path);
- _bt_hal_convert_uuid_type_to_string(desc_uuid_str, gattc_desc->desc_uuid.uu);
- DBG("char uuid [%s]", desc_uuid_str);
-
g_conn = _bt_hal_get_system_gconn();
if (NULL == g_conn) {
ERR("_bt_gdbus_get_system_gconn returned NULL");
return BT_STATUS_UNSUPPORTED;
}
+static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
+{
+ struct hal_ev_gatt_client_watch_notification ev;
+ hal_gatt_resp_data_t *resp_data = user_data;
+
+ DBG("sending the watch register notification event");
+ /* send the event */
+ memset(&ev, 0, sizeof(ev));
+ ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
+ ev.registered = 1;
+ ev.status = resp_data->result;
+
+ ev.is_primary = resp_data->srvc_id.is_primary;
+ ev.inst_id = resp_data->srvc_id.id.inst_id;
+
+ memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
+ memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
+
+ if (!event_cb)
+ ERR("GATT Callback not registered");
+ else
+ event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
+
+ g_free(user_data);
+
+ return FALSE;
+}
+
+static bt_status_t _hal_register_for_notification(int client_if,
+ bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
+ btgatt_gatt_id_t *char_id)
+{
+ int result = BT_STATUS_SUCCESS;
+ GError *error = NULL;
+ GDBusConnection *g_conn;
+ hal_gattc_client_info_t *gattc_client = NULL;
+ hal_gattc_server_info_t * conn_info = NULL;
+ hal_gattc_service_t *gattc_service = NULL;
+ hal_gattc_char_t *gattc_char = NULL;
+ char* char_handle = NULL;
+ char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
+ char char_uuid_str[BT_HAL_UUID_STRING_LEN];
+ hal_gatt_resp_data_t *resp_data;
+
+ DBG("+");
+
+ gattc_client = __bt_find_gatt_client_info(bd_addr);
+ if (gattc_client == NULL) {
+ ERR("failed to get the gatt client info");
+ return BT_STATUS_FAIL;
+ }
+
+ if (gattc_client->client_if != client_if) {
+ ERR("could not find the gatt client for client id[%d]", client_if);
+ return BT_STATUS_FAIL;
+ }
+
+ /* get the connection info */
+ conn_info = __bt_find_gatt_conn_info(bd_addr);
+ if (NULL == conn_info) {
+ ERR("Failed to get the conn_info");
+ return BT_STATUS_FAIL;
+ }
+
+ if (conn_info->inst_id != gattc_client->inst_id) {
+ ERR("could not fild the conn_info");
+ return BT_STATUS_FAIL;
+ }
+
+ /* find service */
+ gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
+ if (NULL == gattc_service) {
+ DBG("Failed to get the gatt service");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("service path [%s]", gattc_service->svc_path);
+ _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
+ DBG("service uuid [%s]", svc_uuid_str);
+
+
+ /* find characteristic */
+ gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
+ if (NULL == gattc_char) {
+ DBG("Failed to get the gatt char");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("char path [%s]", gattc_char->chr_path);
+ _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+ DBG("char uuid [%s]", char_uuid_str);
+
+ char_handle = gattc_char->chr_path;
+
+ g_conn = _bt_hal_get_system_gconn();
+ if (g_conn == NULL) {
+ ERR("conn NULL");
+ return BT_STATUS_FAIL;
+ }
+
+ resp_data = malloc(sizeof(hal_gatt_resp_data_t));
+ if (NULL == resp_data) {
+ ERR("failed to get the memory");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("#StartNotify");
+ g_dbus_connection_call_sync(g_conn,
+ BT_HAL_BLUEZ_NAME,
+ char_handle,
+ BT_HAL_GATT_CHAR_INTERFACE,
+ "StartNotify",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
+
+ if (error) {
+ g_dbus_error_strip_remote_error(error);
+ ERR("### Watch Failed: %s", error->message);
+ if (g_strrstr(error->message, "Already notifying"))
+ result = BT_STATUS_SUCCESS;
+ else if (g_strrstr(error->message, "In Progress"))
+ result = BT_STATUS_BUSY;
+ else if (g_strrstr(error->message, "Operation is not supported"))
+ result = BT_STATUS_UNSUPPORTED;
+ /*failed because of either Insufficient Authorization or Write Not Permitted */
+ else if (g_strrstr(error->message, "Write not permitted") ||
+ g_strrstr(error->message, "Operation Not Authorized"))
+ result = BT_STATUS_AUTH_FAILURE;
+ /* failed because of either Insufficient Authentication,
+ Insufficient Encryption Key Size, or Insufficient Encryption. */
+ else if (g_strrstr(error->message, "Not paired"))
+ result = BT_STATUS_NOT_READY;
+ else
+ result = BT_STATUS_FAIL;
+
+ g_clear_error(&error);
+ }
+
+ resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
+ resp_data->result = result;
+ memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
+
+ g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
+
+ DBG("-");
+
+ return BT_STATUS_SUCCESS;
+}
+
/**
* Register to receive notifications or indications for a given
* characteristic
*/
-bt_status_t register_for_notification(int client_if,
+bt_status_t btif_register_for_notification(int client_if,
const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
btgatt_gatt_id_t *char_id)
{
CHECK_BTGATT_INIT();
- return BT_STATUS_UNSUPPORTED;
+
+ return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
}
+static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
+{
+ struct hal_ev_gatt_client_watch_notification ev;
+ hal_gatt_resp_data_t *resp_data = user_data;
+
+ DBG("sending the watch deregister notification event");
+ /* send the event */
+ memset(&ev, 0, sizeof(ev));
+ ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
+ ev.registered = 0;
+ ev.status = resp_data->result;
+
+ ev.is_primary = resp_data->srvc_id.is_primary;
+ ev.inst_id = resp_data->srvc_id.id.inst_id;
+
+ memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
+ memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
+
+ if (!event_cb)
+ ERR("GATT Callback not registered");
+ else
+ event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
+
+ g_free(user_data);
+
+ return FALSE;
+}
+
+static bt_status_t _hal_deregister_for_notification(int client_if,
+ bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
+ btgatt_gatt_id_t *char_id)
+{
+ int result = BT_STATUS_SUCCESS;
+ GError *error = NULL;
+ GDBusConnection *g_conn;
+ hal_gattc_client_info_t *gattc_client = NULL;
+ hal_gattc_server_info_t * conn_info = NULL;
+ hal_gattc_service_t *gattc_service = NULL;
+ hal_gattc_char_t *gattc_char = NULL;
+ char* char_handle = NULL;
+ char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
+ char char_uuid_str[BT_HAL_UUID_STRING_LEN];
+ hal_gatt_resp_data_t *resp_data;
+
+ DBG("+");
+
+ gattc_client = __bt_find_gatt_client_info(bd_addr);
+ if (gattc_client == NULL) {
+ ERR("failed to get the gatt client info");
+ return BT_STATUS_FAIL;
+ }
+
+ if (gattc_client->client_if != client_if) {
+ ERR("could not find the gatt client for client id[%d]", client_if);
+ return BT_STATUS_FAIL;
+ }
+
+ /* get the connection info */
+ conn_info = __bt_find_gatt_conn_info(bd_addr);
+ if (NULL == conn_info) {
+ ERR("Failed to get the conn_info");
+ return BT_STATUS_FAIL;
+ }
+
+ if (conn_info->inst_id != gattc_client->inst_id) {
+ ERR("could not fild the conn_info");
+ return BT_STATUS_FAIL;
+ }
+
+ /* find service */
+ gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
+ if (NULL == gattc_service) {
+ DBG("Failed to get the gatt service");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("service path [%s]", gattc_service->svc_path);
+ _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
+ DBG("service uuid [%s]", svc_uuid_str);
+
+
+ /* find characteristic */
+ gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid);
+ if (NULL == gattc_char) {
+ DBG("Failed to get the gatt char");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("char path [%s]", gattc_char->chr_path);
+ _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+ DBG("char uuid [%s]", char_uuid_str);
+
+ char_handle = gattc_char->chr_path;
+
+ g_conn = _bt_hal_get_system_gconn();
+ if (g_conn == NULL) {
+ ERR("conn NULL");
+ return BT_STATUS_FAIL;
+ }
+
+ resp_data = malloc(sizeof(hal_gatt_resp_data_t));
+ if (NULL == resp_data) {
+ ERR("failed to get the memory");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("#StartNotify");
+ g_dbus_connection_call_sync(g_conn,
+ BT_HAL_BLUEZ_NAME,
+ char_handle,
+ BT_HAL_GATT_CHAR_INTERFACE,
+ "StopNotify",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
+
+ if (error) {
+ ERR("### Watch Failed: %s", error->message);
+ g_clear_error(&error);
+ result = BT_STATUS_FAIL;
+ }
+
+ resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
+ resp_data->result = result;
+ memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
+
+ g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
+
+ DBG("-");
+
+ return BT_STATUS_SUCCESS;
+}
/** Deregister a previous request for notifications/indications */
-bt_status_t deregister_for_notification(int client_if,
+bt_status_t btif_deregister_for_notification(int client_if,
const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
btgatt_gatt_id_t *char_id)
{
CHECK_BTGATT_INIT();
- return BT_STATUS_UNSUPPORTED;
+ return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
}
/** Request RSSI for a given remote device */
}
const btgatt_client_interface_t btgatt_client_interface = {
- btif_gattc_register_client,
- btif_gattc_unregister_client,
- scan,
- btif_gattc_client_connect,
- btif_gattc_client_disconnect,
- refresh,
- btif_gattc_client_search_service,
- get_included_service,
- btif_gattc_get_characteristic,
- btif_gattc_get_descriptor,
- btif_read_characteristic,
- btif_write_characteristic,
- btif_read_descriptor,
- btif_write_descriptor,
- execute_write,
- register_for_notification,
- deregister_for_notification,
- read_remote_rssi,
- ota_fw_update,
- get_device_type,
- btif_gattc_conn_parameter_update,
- test_command,
- configure_mtu,
- scan_filter_param_setup,
- scan_filter_add_remove,
- scan_filter_clear,
- scan_filter_enable,
- set_scan_parameters,
- batchscan_cfg_storage,
- batchscan_enb_batch_scan,
- batchscan_dis_batch_scan,
- batchscan_read_reports
+ .register_client = btif_gattc_register_client,
+ .unregister_client = btif_gattc_unregister_client,
+ .scan = scan,
+ .connect = btif_gattc_client_connect,
+ .disconnect = btif_gattc_client_disconnect,
+ .refresh = refresh,
+ .search_service = btif_gattc_client_search_service,
+ .get_included_service = get_included_service,
+ .get_characteristic = btif_gattc_get_characteristic,
+ .get_descriptor = btif_gattc_get_descriptor,
+ .read_characteristic = btif_read_characteristic,
+ .write_characteristic = btif_write_characteristic,
+ .acquire_write = btif_get_acquire_write_fd,
+ .acquire_notify = btif_get_acquire_notify_fd,
+ .read_descriptor = btif_read_descriptor,
+ .write_descriptor = btif_write_descriptor,
+ .execute_write = execute_write,
+ .register_for_notification = btif_register_for_notification,
+ .deregister_for_notification = btif_deregister_for_notification,
+ .read_remote_rssi = read_remote_rssi,
+ .ota_fw_update = ota_fw_update,
+ .get_device_type = get_device_type,
+ .conn_parameter_update = btif_gattc_conn_parameter_update,
+ .test_command = test_command,
+ .configure_mtu = configure_mtu,
+ .scan_filter_param_setup = scan_filter_param_setup,
+ .scan_filter_add_remove = scan_filter_add_remove,
+ .scan_filter_clear = scan_filter_clear,
+ .scan_filter_enable = scan_filter_enable,
+ .set_scan_parameters = set_scan_parameters,
+ .batchscan_cfg_storage = batchscan_cfg_storage,
+ .batchscan_enb_batch_scan = batchscan_enb_batch_scan,
+ .batchscan_dis_batch_scan = batchscan_dis_batch_scan,
+ .batchscan_read_reports = batchscan_read_reports
};
static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr)
event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev));
}
+
+static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info,
+ hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info,
+ char *char_value, int len)
+{
+ struct hal_ev_gatt_client_notify_changed_value ev;
+ hal_gattc_client_info_t *gattc_client = NULL;
+
+ if (!event_cb) {
+ ERR("gatt client callback not registered");
+ return;
+ }
+
+ gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr);
+ if (NULL == gattc_client) {
+ ERR("failed to get the gatt client info");
+ return ;
+ }
+
+ //send event
+ DBG("sending gatt client connected status event");
+ memset(&ev, 0, sizeof(ev));
+
+ ev.conn_id = gattc_client->conn_id;
+ ev.inst_id = conn_info->inst_id;
+ ev.is_primary = svc_info->is_primary;
+ memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid));
+ memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid));
+
+ memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX);
+
+ if (len > 0 && (char_value != NULL)) {
+ memcpy(ev.value, char_value, len);
+ ev.len = len;
+ }
+
+ event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev));
+}
+
+void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
+ char *char_value, int len)
+{
+ char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 };
+ hal_gattc_server_info_t *conn_info = NULL;
+ bt_bdaddr_t bd_addr;
+ GSList *l;
+ GSList *k;
+ hal_gattc_service_t *svc_info = NULL;
+ hal_gattc_char_t *char_info = NULL;
+
+ DBG("+");
+
+ _bt_hal_convert_device_path_to_address(char_handle, device_address);
+ device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0';
+ DBG("device address:[%s]", device_address);
+ DBG("char handle:[%s]", char_handle);
+
+ _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address);
+ conn_info = __bt_find_gatt_conn_info(&bd_addr);
+
+ if (conn_info != NULL) {
+ //find service for notified char path
+ for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) {
+ svc_info = (hal_gattc_service_t*)l->data;
+ if (svc_info == NULL)
+ continue;
+
+ /* find characteristic object path */
+ for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) {
+ char_info = (hal_gattc_char_t *)k->data;
+ if (char_info == NULL)
+ continue;
+
+ if (g_strcmp0(char_info->chr_path, char_handle) == 0) {
+ DBG("Found char handle[%s]", char_info->chr_path);
+
+ //send event
+ _bt_hal_send_value_changed_event(conn_info, svc_info,
+ char_info, char_value, len);
+ return;
+ }
+ }
+ }
+ }
+}