_bt_gatt_client_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC,
result, &desc_prop,
event_info->cb, event_info->user_data);
- }
+ } else if (strcasecmp(signal_name, BT_GATT_CLIENT_SERVICE_CHANGED) == 0) {
+ BT_DBG("GATT Client event[BT_GATT_CLIENT_SERVICE_CHANGED]");
+ bt_gatt_service_change_t change = {0, };
+ char *address_str = NULL;
+ char *name = NULL;
+
+ g_variant_get(parameters, "(i&s&s)", &change.change_type, &address_str, &change.uuid);
+ _bt_convert_addr_string_to_type(change.device_addr.addr, address_str);
+ bluetooth_get_uuid_name(change.uuid, &name);
+ BT_INFO(" ### GATT Service %s [%s]", change.change_type ? "Added" : "Removed", name);
+ g_free(name);
+
+ if (_bluetooth_gatt_check_service_change_watcher_address(&change.device_addr) == FALSE) {
+ BT_INFO("No watcher for %s", address_str);
+ return;
+ }
+
+ _bt_gatt_client_event_cb(BLUETOOTH_EVENT_GATT_CLIENT_SERVICE_CHANGED,
+ BLUETOOTH_ERROR_NONE, &change,
+ event_info->cb, event_info->user_data);
+ }
}
#endif
uint32_t data_len;
} __attribute__((packed));
-#define HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED 0xCF
+#define HAL_EV_GATT_CLIENT_SERVICE_CHANGED 0xCF
+struct hal_ev_gatt_client_service_changed {
+ uint8_t bdaddr[6];
+ uint8_t change_type;
+ uint8_t uuid[16];
+} __attribute__((packed));
+
+#define HAL_EV_GATT_CLIENT_MTU_EXCHANGE_COMPLETED 0xD0
struct hal_ev_gatt_client_mtu_exchange_completed {
int32_t conn_id;
int32_t mtu;
}
}
+static void __bt_hal_handle_gatt_service_event(GVariant *parameters, const char *signal_name)
+{
+ if (signal_name == NULL)
+ return;
+
+ if (strcasecmp(signal_name, "GattServiceAdded") == 0) {
+ char *path = NULL;
+ g_variant_get(parameters, "(&s)", &path);
+ _bt_hal_handle_gattc_service_changed_event(TRUE, path);
+ }
+}
static gboolean __bt_hal_event_manager(gpointer data)
{
while (g_variant_iter_loop(iter, "s", &str)) {
if (g_strcmp0(str, BT_HAL_PLAYER_CONTROL_INTERFACE) == 0)
_bt_hal_remove_control_device_path(obj_path);
+ else if (g_strcmp0(str, BT_HAL_GATT_SERVICE_INTERFACE) == 0)
+ _bt_hal_handle_gattc_service_changed_event(FALSE, obj_path);
}
g_variant_iter_free(iter);
} else if (strcasecmp(param->signal_name, "NameOwnerChanged") == 0) {
__bt_hal_handle_avrcp_transport_events(param->parameters, param->signal_name, param->object_path);
} else if (g_strcmp0(param->interface_name, BT_HAL_GATT_CHAR_INTERFACE) == 0) {
__bt_hal_handle_gatt_char_event(param->parameters, param->signal_name);
+ } else if (g_strcmp0(param->interface_name, BT_HAL_GATT_SERVICE_INTERFACE) == 0) {
+ DBG("Manager Event: Interface Name: BT_HAL_GATT_SERVICE_INTERFACE");
+ __bt_hal_handle_gatt_service_event(param->parameters, param->signal_name);
}
/* Free data */
static int __bt_hal_register_gatt_subscribe_signal(GDBusConnection *conn,
int subscribe)
{
- static int subs_gatt_id = -1;
-
- DBG("+");
+ static int subs_gatt_char_id = -1;
+ static int subs_gatt_service_id = -1;
if (subscribe) {
- if (subs_gatt_id == -1) {
- subs_gatt_id = g_dbus_connection_signal_subscribe(conn,
+ if (subs_gatt_char_id == -1) {
+ subs_gatt_char_id = g_dbus_connection_signal_subscribe(conn,
NULL, BT_HAL_GATT_CHAR_INTERFACE,
NULL, NULL, NULL, 0,
__bt_hal_manager_event_filter,
NULL, NULL);
}
+ if (subs_gatt_service_id == -1) {
+ subs_gatt_service_id = g_dbus_connection_signal_subscribe(conn,
+ NULL, BT_HAL_GATT_SERVICE_INTERFACE,
+ NULL, NULL, NULL, 0,
+ __bt_hal_manager_event_filter,
+ NULL, NULL);
+ }
} else {
- if (subs_gatt_id == -1) {
+ if (subs_gatt_char_id == -1) {
+ g_dbus_connection_signal_unsubscribe(conn,
+ subs_gatt_char_id);
+ subs_gatt_char_id = -1;
+ }
+ if (subs_gatt_service_id == -1) {
g_dbus_connection_signal_unsubscribe(conn,
- subs_gatt_id);
- subs_gatt_id = -1;
+ subs_gatt_service_id);
+ subs_gatt_service_id = -1;
}
}
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_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr);
static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
static hal_gattc_client_info_t *__bt_find_gatt_client_info_from_conn_id(int conn_id);
static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info,
- const char *uuid_str, char *object_path, int is_primary)
+ const char *uuid_str, const char *object_path, int is_primary)
{
DBG("+");
hal_gattc_service_t *gattc_service = NULL;
}
static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboolean is_primary,
- const char* uuid_str, char *object_path, GPtrArray *gp_char_array)
+ const char* uuid_str, const char *object_path, GPtrArray *gp_char_array)
{
hal_gattc_service_t* gatt_svc = NULL;
int i;
.add_connection_info = btif_gattc_add_connection_info
};
-static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr)
+static hal_gattc_server_info_t *__bt_find_gatt_conn_info(const bt_bdaddr_t *serv_addr)
{
DBG("+");
}
}
}
+
+static bt_status_t __hal_gattc_get_service_info(hal_gattc_server_info_t *server_info, const char *service_path)
+{
+ GDBusConnection *g_conn = NULL;
+ GDBusProxy *properties_proxy = NULL;
+ GVariant *result = NULL;
+ GError *error = NULL;
+ GVariantIter *property_iter = NULL;
+ const gchar *key = NULL;
+ GVariant *value = NULL;
+ const char *uuid_str = NULL;
+ gsize len = 0;
+ gboolean is_primary = FALSE;
+ GVariantIter *char_iter = NULL;
+ const char *char_handle = NULL;
+ GPtrArray *gp_char_array = NULL;
+
+ if (service_path == NULL) {
+ ERR("service_path is NULL");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("service_path: %s", service_path);
+
+ g_conn = _bt_hal_get_system_gconn();
+ if (g_conn == NULL) {
+ ERR("g_conn is NULL");
+ return BT_STATUS_FAIL;
+ }
+
+ properties_proxy = g_dbus_proxy_new_sync(g_conn,
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ BT_HAL_BLUEZ_NAME,
+ service_path,
+ BT_HAL_PROPERTIES_INTERFACE,
+ NULL, &error);
+ if (properties_proxy == NULL) {
+ ERR("properties_proxy is NULL");
+ return BT_STATUS_FAIL;
+ }
+
+ result = g_dbus_proxy_call_sync(properties_proxy,
+ "GetAll",
+ g_variant_new("(s)", BT_HAL_GATT_SERVICE_INTERFACE),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (result == NULL) {
+ if (error != NULL) {
+ ERR("Fail to get properties (Error: %s)", error->message);
+ g_clear_error(&error);
+ } else {
+ ERR("Fail to get properties");
+ }
+ g_object_unref(properties_proxy);
+ return BT_STATUS_FAIL;
+ }
+
+ g_variant_get(result, "(a{sv})", &property_iter);
+
+ while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) {
+ if (g_strcmp0(key, "UUID") == 0) {
+ uuid_str = g_variant_get_string(value, &len);
+ DBG("UUID: %s", uuid_str);
+ } else if (g_strcmp0(key, "Primary") == 0) {
+ is_primary = g_variant_get_boolean(value);
+ DBG("is_primary: %s", is_primary ? "TRUE" : "FALSE");
+ } else if (g_strcmp0(key, "Characteristics") == 0) {
+ g_variant_get(value, "ao", &char_iter);
+ if (char_iter != NULL) {
+ gp_char_array = g_ptr_array_new();
+ while (g_variant_iter_loop(char_iter, "&o", &char_handle)) {
+ DBG("char_handle: %s", char_handle);
+ g_ptr_array_add(gp_char_array, (gpointer)char_handle);
+ }
+ }
+ }
+ }
+
+ /* Create new service */
+ _gattc_create_new_service(server_info, is_primary, uuid_str, service_path, gp_char_array);
+
+ g_variant_iter_free(property_iter);
+ g_variant_unref(result);
+ g_object_unref(properties_proxy);
+ DBG("-");
+ return BT_STATUS_SUCCESS;
+}
+
+static void __bt_hal_gattc_get_uuid_from_path(const char *path, char **service_uuid)
+{
+ GDBusConnection *conn = NULL;
+ GDBusProxy *proxy = NULL;
+ GError *err = NULL;
+ GVariant *ret = NULL;
+ GVariant *value = NULL;
+
+ conn = _bt_hal_get_system_gconn();
+ if (conn == NULL) {
+ ERR("_bt_gdbus_get_system_gconn returned NULL");
+ return;
+ }
+
+ proxy = g_dbus_proxy_new_sync(conn,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
+ BT_HAL_BLUEZ_NAME, path, BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
+ if (proxy == NULL) {
+ ERR("device_proxy returned NULL");
+ return;
+ }
+
+ ret = g_dbus_proxy_call_sync(proxy, "Get",
+ g_variant_new("(ss)", BT_HAL_GATT_SERVICE_INTERFACE, "UUID"),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+ if (err) {
+ ERR("DBus Error : %s", err->message);
+ g_clear_error(&err);
+ } else {
+ g_variant_get(ret, "(v)", &value);
+ *service_uuid = g_variant_dup_string(value, NULL);
+ g_variant_unref(value);
+ g_variant_unref(ret);
+ }
+
+ if (proxy)
+ g_object_unref(proxy);
+
+ return;
+}
+
+void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path)
+{
+ struct hal_ev_gatt_client_service_changed ev = {0, };
+ char address[BT_HAL_ADDRESS_STRING_SIZE];
+ hal_gattc_server_info_t *server_info = NULL;
+ hal_gattc_service_t *service = NULL;
+ GSList *list = NULL;
+ char *uuid_str = NULL;
+
+ _bt_hal_convert_device_path_to_address(path, address);
+ _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
+ ev.change_type = is_added;
+ server_info = __bt_find_gatt_conn_info((bt_bdaddr_t *)ev.bdaddr);
+ if (server_info == NULL) {
+ ERR("service_info is NULL");
+ return;
+ }
+
+ if (is_added) {
+ __bt_hal_gattc_get_uuid_from_path(path, &uuid_str);
+ DBG("GATT Service(%s) Added", uuid_str);
+ /* Set UUID by using path */
+ _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid_str);
+ g_free(uuid_str);
+
+ /* Create new service and append into the list */
+ __hal_gattc_get_service_info(server_info, path);
+ } else {
+ /* Find service UUID from path */
+ for (list = server_info->gatt_list_services; list; list = g_slist_next(list)) {
+ service = (hal_gattc_service_t *)list->data;
+ if (service == NULL)
+ continue;
+
+ if (g_strcmp0(service->svc_path, path) == 0) {
+ memcpy(ev.uuid, service->svc_uuid.uu, sizeof(bt_uuid_t));
+ uuid_str = g_malloc0(BT_HAL_UUID_STRING_LEN);
+ /* Set UUID from stored service info */
+ _bt_hal_convert_uuid_type_to_string(uuid_str, ev.uuid);
+ DBG("GATT Service(%s) Removed", uuid_str);
+ g_free(uuid_str);
+
+ /* Remove service info in list */
+ server_info->gatt_list_services = g_slist_remove(server_info->gatt_list_services, service);
+ __hal_gattc_free_svc_info(service);
+ break;
+ }
+ }
+ }
+
+ /* Send GATT Client service changed event */
+ event_cb(HAL_EV_GATT_CLIENT_SERVICE_CHANGED, (void *)&ev, sizeof(ev));
+}
+
void _bt_hal_handle_gattc_connected_event(char* address, gboolean connected);
void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle,
char *char_value, int len);
+void _bt_hal_handle_gattc_service_changed_event(gboolean is_added, const char *path);
#ifdef TIZEN_BT_HAL
int _bt_hal_gatt_client_get_le_scan_type(void);
static void __bt_handle_gatt_client_write_desc(void *buf, uint16_t len);
static void __bt_handle_gatt_client_watch_notification(void *buf, uint16_t len);
static void __bt_handle_gatt_client_changed_value(void *buf, uint16_t len);
+static void __bt_hal_handle_gatt_client_service_changed(void *buf, uint16_t len);
static void __bt_hal_handle_gatt_client_mtu_exchange_completed(void *buf, uint16_t len);
/*****************************************************************************************************/
__bt_handle_gatt_client_changed_value(buf, len);
break;
}
+ case HAL_EV_GATT_CLIENT_SERVICE_CHANGED: {
+ __bt_hal_handle_gatt_client_service_changed(buf, len);
+ break;
+ }
case HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES:{
__bt_hal_handle_gatt_server_acquire_write_requested(buf, len);
break;
bt_gatt_callbacks->client->notify_cb(ev->conn_id, &changd_value_parm);
}
+static void __bt_hal_handle_gatt_client_service_changed(void *buf, uint16_t len)
+{
+ struct hal_ev_gatt_client_service_changed *ev = buf;
+
+ DBG("GATT Client service changed event received");
+
+ if (bt_gatt_callbacks->client->service_changed_cb)
+ bt_gatt_callbacks->client->service_changed_cb((bt_bdaddr_t *)ev->bdaddr, ev->change_type, ev->uuid);
+}
+
static bt_hal_le_adv_info_t *__bt_hal_get_adv_ind_info(char *addr)
{
GSList *l;
*/
typedef void (*notify_callback)(int conn_id, btgatt_notify_params_t *p_data);
+/** Registers service changed callback operation */
+typedef void (*service_changed_callback)(bt_bdaddr_t *bd_addr, int change_type, uint8_t *path);
+
/** Reports result of a GATT read operation */
typedef void (*read_characteristic_callback)(int conn_id, int status,
btgatt_read_params_t *p_data);
get_included_service_callback get_included_service_cb;
register_for_notification_callback register_for_notification_cb;
notify_callback notify_cb;
+ service_changed_callback service_changed_cb;
read_characteristic_callback read_characteristic_cb;
write_characteristic_callback write_characteristic_cb;
read_descriptor_callback read_descriptor_cb;
oal_gatt_srvc_id_t srvc_id;
} event_gattc_notify_data;
+typedef struct {
+ bt_address_t address;
+ uint8_t change_type;
+ oal_uuid_t uuid;
+} event_gattc_service_changed_data;
+
typedef struct {
uint16_t value_type;
uint16_t data_len;
oal_status_t gattc_add_connection_info(bt_address_t *device_address, int conn_id, int server_inst_id);
+oal_status_t gattc_register_service_changed_cb(bt_address_t *device_address);
+
+oal_status_t gattc_unregister_service_changed_cb(bt_address_t *device_address);
+
oal_status_t gattc_register_for_notification(int client_id, bt_address_t * address,
oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id);
static void cb_gattc_register_for_notification(int conn_id, int registered, int status,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id);
static void cb_gattc_notify(int conn_id, btgatt_notify_params_t *p_data);
+static void cb_gattc_service_changed(bt_bdaddr_t *bd_addr, int change_type, uint8_t *uuid);
static void cb_gattc_configure_mtu_cmpl(int conn_id, int status, int mtu);
/*TODO GATT CLient callbacks will be implemented in subsequent patches */
.get_included_service_cb = NULL,
.register_for_notification_cb = cb_gattc_register_for_notification,
.notify_cb = cb_gattc_notify,
+ .service_changed_cb = cb_gattc_service_changed,
.read_characteristic_cb = cb_gattc_read_characteristic,
.write_characteristic_cb = cb_gattc_write_characteristic,
.read_descriptor_cb = cb_gattc_read_descriptor,
}
}
+static void cb_gattc_service_changed(bt_bdaddr_t *bd_addr, int change_type, uint8_t *uuid)
+{
+ event_gattc_service_changed_data *event = g_new0(event_gattc_service_changed_data, 1);
+
+ memcpy(event->address.addr, bd_addr->address, 6);
+ event->change_type = change_type;
+ memcpy(event->uuid.uuid, uuid, sizeof(event->uuid.uuid));
+
+ send_event_bda_trace(OAL_EVENT_GATTC_SERVICE_CHANGED_IND, event, sizeof(*event), (bt_address_t *)bd_addr);
+}
static void cb_gattc_read_characteristic(int conn_id, int status, btgatt_read_params_t *p_data)
{
static void __bt_handle_client_notification_registered(event_gattc_regdereg_notify_t *event_data,
gboolean is_registered);
static void __bt_handle_client_notification_data(event_gattc_notify_data *event_data);
+static void __bt_handle_client_service_changed_ind(event_gattc_service_changed_data *event_data);
static void __bt_handle_client_mtu_exchange_completed(event_gattc_mtu_configured_t *event_data);
#endif
__bt_handle_client_notification_data((event_gattc_notify_data *) event_data);
break;
}
+ case OAL_EVENT_GATTC_SERVICE_CHANGED_IND: {
+ BT_INFO("OAL Event: GATT Client service changed indication");
+ __bt_handle_client_service_changed_ind((event_gattc_service_changed_data *)event_data);
+ break;
+ }
case OAL_EVENT_GATTC_MTU_EXCHANGE_COMPLETED: {
BT_INFO("OAL Event: GATT Client MTU Exchange Complete");
__bt_handle_client_mtu_exchange_completed((event_gattc_mtu_configured_t *) event_data);
g_free(addr);
}
+static void __bt_handle_client_service_changed_ind(event_gattc_service_changed_data *event_data)
+{
+ GVariant *param = NULL;
+ char *address_str = NULL;
+ char *uuid_str = NULL;
+
+ address_str = g_malloc0(BT_ADDRESS_STRING_SIZE);
+ uuid_str = g_malloc0(BT_UUID_STRING_MAX);
+ _bt_convert_addr_type_to_string(address_str, event_data->address.addr);
+ _bt_uuid_to_string(&event_data->uuid, uuid_str);
+
+ param = g_variant_new("(iss)", event_data->change_type, address_str, uuid_str);
+
+ _bt_send_event(BT_GATT_CLIENT_EVENT,
+ BLUETOOTH_EVENT_GATT_CLIENT_SERVICE_CHANGED,
+ param);
+}
+
gboolean _bt_is_remote_gatt_device_connected(bluetooth_device_address_t *address)
{
char *addr;
bluetooth_device_address_t device_addr;
char *svc_path;
bluetooth_gatt_service_change_type_t change_type;
+#ifdef TIZEN_GATT_CLIENT
+ char *uuid;
+#endif
} bt_gatt_service_change_t;
/**
#define BT_GATT_CLIENT_WRITE_CHAR "GattWriteCharValue"
#define BT_GATT_CLIENT_READ_DESC "GattReadDescriptor"
#define BT_GATT_CLIENT_WRITE_DESC "GattWriteDescriptor"
+#define BT_GATT_CLIENT_SERVICE_CHANGED "GattServiceChanged"
#endif
#define BT_GATT_REQ_ATT_MTU_CHANGED "GattReqAttMtuChanged"