There can be situation that after connection to LE bearer we will try
to start reverse discovery on BR/EDR bearer even when it is not connected.
This change separates SDP and GATT reverse services discoveries to their
respective bearers. SDP to BR/EDR and GATT to LE.
---
src/device.c | 129 +++++++++++++++++++++++++++++++++------------------
1 file changed, 83 insertions(+), 46 deletions(-)
diff --git a/src/device.c b/src/device.c
index 367e2f046..90d6a7615 100644
--- a/src/device.c
+++ b/src/device.c
@@ -158,6 +158,10 @@ struct bearer_state {
bool initiator;
bool connectable;
time_t last_seen;
+ /* reverse service discovery timer */
+ unsigned int discov_timer;
+ /* service discover request (SDP, GATT) */
+ struct browse_req *browse;
};
struct ltk_info {
@@ -236,9 +240,7 @@ struct btd_device {
bool temporary;
bool connectable;
unsigned int disconn_timer;
- unsigned int discov_timer;
unsigned int temporary_timer; /* Temporary/disappear timer */
- struct browse_req *browse; /* service discover request */
struct bonding_req *bonding;
struct authentication_req *authr; /* authentication request */
GSList *disconnects; /* disconnects message */
@@ -684,8 +686,10 @@ static void browse_request_free(struct browse_req *req)
{
struct btd_device *device = req->device;
- if (device->browse == req)
- device->browse = NULL;
+ if (device->bredr_state.browse == req)
+ device->bredr_state.browse = NULL;
+ if (device->le_state.browse == req)
+ device->le_state.browse = NULL;
if (req->listener_id)
g_dbus_remove_watch(dbus_conn, req->listener_id);
@@ -833,8 +837,10 @@ static void device_free(gpointer user_data)
if (device->disconn_timer)
timeout_remove(device->disconn_timer);
- if (device->discov_timer)
- timeout_remove(device->discov_timer);
+ if (device->bredr_state.discov_timer)
+ timeout_remove(device->bredr_state.discov_timer);
+ if (device->le_state.discov_timer)
+ timeout_remove(device->le_state.discov_timer);
if (device->temporary_timer)
timeout_remove(device->temporary_timer);
@@ -1848,8 +1854,10 @@ void device_request_disconnect(struct btd_device *device, DBusMessage *msg)
if (device->bonding)
bonding_request_cancel(device->bonding);
- if (device->browse)
- browse_request_cancel(device->browse);
+ if (device->bredr_state.browse)
+ browse_request_cancel(device->bredr_state.browse);
+ if (device->le_state.browse)
+ browse_request_cancel(device->le_state.browse);
if (device->att_io) {
g_io_channel_shutdown(device->att_io, FALSE, NULL);
@@ -2304,7 +2312,7 @@ void btd_device_update_allowed_services(struct btd_device *dev)
/* If service discovery is ongoing, let the service discovery complete
* callback call this function.
*/
- if (dev->browse) {
+ if (dev->bredr_state.browse) {
ba2str(&dev->bdaddr, addr);
DBG("service discovery of %s is ongoing. Skip updating allowed "
"services", addr);
@@ -2370,7 +2378,7 @@ int btd_device_connect_services(struct btd_device *dev, GSList *services)
{
GSList *l;
- if (dev->pending || dev->connect || dev->browse)
+ if (dev->pending || dev->connect || dev->bredr_state.browse)
return -EBUSY;
if (!btd_adapter_get_powered(dev->adapter))
@@ -2401,7 +2409,7 @@ static DBusMessage *connect_profiles(struct btd_device *dev, uint8_t bdaddr_type
DBG("%s %s, client %s", dev->path, uuid ? uuid : "(all)",
dbus_message_get_sender(msg));
- if (dev->pending || dev->connect || dev->browse)
+ if (dev->pending || dev->connect || dev->bredr_state.browse)
return btd_error_in_progress_str(msg, ERR_BREDR_CONN_BUSY);
if (!btd_adapter_get_powered(dev->adapter)) {
@@ -2784,7 +2792,7 @@ static void browse_request_complete(struct browse_req *req, uint8_t type,
/* if successfully resolved services we need to free browsing request
* before passing message back to connect functions, otherwise
- * device->browse is set and "InProgress" error is returned instead
+ * device->state.browse is set and "InProgress" error is returned instead
* of actually connecting services
*/
msg = dbus_message_ref(req->msg);
@@ -2829,7 +2837,7 @@ static void device_svc_resolved(struct btd_device *dev, uint8_t browse_type,
uint8_t bdaddr_type, int err)
{
struct bearer_state *state = get_state(dev, bdaddr_type);
- struct browse_req *req = dev->browse;
+ struct browse_req *req = state->browse;
DBG("%s err %d", dev->path, err);
@@ -3060,7 +3068,7 @@ static DBusMessage *pair_device(DBusConnection *conn, DBusMessage *msg,
err = device_connect_le(device);
else
err = adapter_create_bonding(adapter, &device->bdaddr,
- device->bdaddr_type,
+ bdaddr_type,
io_cap);
} else {
err = adapter_create_bonding(adapter, &device->bdaddr,
@@ -4657,8 +4665,10 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
device_cancel_bonding(device, status);
}
- if (device->browse)
- browse_request_cancel(device->browse);
+ if (device->bredr_state.browse)
+ browse_request_cancel(device->bredr_state.browse);
+ if (device->le_state.browse)
+ browse_request_cancel(device->le_state.browse);
while (device->services != NULL) {
struct btd_service *service = device->services->data;
@@ -5317,7 +5327,7 @@ static void att_disconnected_cb(int err, void *user_data)
DBG("");
- if (device->browse)
+ if (device->le_state.browse)
goto done;
DBG("%s (%d)", strerror(err), err);
@@ -5345,7 +5355,7 @@ done:
static void register_gatt_services(struct btd_device *device)
{
- struct browse_req *req = device->browse;
+ struct browse_req *req = device->le_state.browse;
GSList *services = NULL;
if (!bt_gatt_client_is_ready(device->client))
@@ -5636,8 +5646,8 @@ static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
adapter_connect_list_add(device->adapter, device);
}
- if (device->browse)
- browse_request_complete(device->browse,
+ if (device->le_state.browse)
+ browse_request_complete(device->le_state.browse,
BROWSE_GATT,
device->bdaddr_type,
-ECONNABORTED);
@@ -5751,15 +5761,24 @@ static struct browse_req *browse_request_new(struct btd_device *device,
DBusMessage *msg)
{
struct browse_req *req;
+ struct bearer_state *state;
- if (device->browse)
+ switch (type) {
+ case BROWSE_SDP:
+ state = get_state(device, BDADDR_BREDR);
+ break;
+ case BROWSE_GATT:
+ state = get_state(device, BDADDR_LE_PUBLIC);
+ break;
+ }
+ if (state->browse)
return NULL;
req = g_new0(struct browse_req, 1);
req->device = device;
req->type = type;
- device->browse = req;
+ state->browse = req;
if (!msg)
return req;
@@ -5879,15 +5898,17 @@ int device_discover_services(struct btd_device *device,
uint8_t bdaddr_type, DBusMessage *msg)
{
int err;
+ struct bearer_state *state;
if (bdaddr_type == BDADDR_BREDR)
err = device_browse_sdp(device, msg);
else
err = device_browse_gatt(device, msg);
- if (err == 0 && device->discov_timer) {
- timeout_remove(device->discov_timer);
- device->discov_timer = 0;
+ state = get_state(device, bdaddr_type);
+ if (err == 0 && state->discov_timer) {
+ timeout_remove(state->discov_timer);
+ state->discov_timer = 0;
}
return err;
@@ -6208,16 +6229,22 @@ bool device_is_connectable(struct btd_device *device)
return state->connectable;
}
-static bool start_discovery_cb(gpointer user_data)
+static bool start_sdp_discovery_cb(gpointer user_data)
{
struct btd_device *device = user_data;
- if (device->bredr)
- device_browse_sdp(device, NULL);
- else
- device_browse_gatt(device, NULL);
+ device->bredr_state.discov_timer = 0;
+ device_browse_sdp(device, NULL);
- device->discov_timer = 0;
+ return FALSE;
+}
+
+static bool start_gatt_discovery_cb(gpointer user_data)
+{
+ struct btd_device *device = user_data;
+
+ device->le_state.discov_timer = 0;
+ device_browse_gatt(device, NULL);
return FALSE;
}
@@ -6368,17 +6395,27 @@ void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,
g_dbus_send_reply(dbus_conn, bonding->msg, DBUS_TYPE_INVALID);
}
bonding_request_free(bonding);
- } else if (!state->svc_resolved) {
- if (!device->browse && !device->discov_timer &&
- btd_opts.reverse_discovery) {
- /* If we are not initiators and there is no currently
- * active discovery or discovery timer, set discovery
- * timer */
- DBG("setting timer for reverse service discovery");
- device->discov_timer = timeout_add_seconds(
- DISCOVERY_TIMER,
- start_discovery_cb,
- device, NULL);
+
+ } else if (!state->svc_resolved
+ && !state->browse
+ && !state->discov_timer
+ && btd_opts.reverse_discovery) {
+
+ /* If we are not initiators and there is no currently
+ * active discovery or discovery timer, set discovery
+ * timer */
+ if (bdaddr_type == BDADDR_BREDR) {
+ DBG("setting timer for reverse SDP service discovery");
+ state->discov_timer = timeout_add_seconds(
+ DISCOVERY_TIMER,
+ start_sdp_discovery_cb,
+ device, NULL);
+ } else {
+ DBG("setting timer for reverse GATT service discovery");
+ state->discov_timer = timeout_add_seconds(
+ DISCOVERY_TIMER,
+ start_gatt_discovery_cb,
+ device, NULL);
}
}
}
@@ -6416,11 +6453,11 @@ unsigned int device_wait_for_svc_complete(struct btd_device *dev,
if (state->svc_resolved || !btd_opts.reverse_discovery)
cb->idle_id = g_idle_add(svc_idle_cb, cb);
- else if (dev->discov_timer > 0) {
- timeout_remove(dev->discov_timer);
- dev->discov_timer = timeout_add_seconds(
+ else if (dev->bredr_state.discov_timer > 0) {
+ timeout_remove(dev->bredr_state.discov_timer);
+ dev->bredr_state.discov_timer = timeout_add_seconds(
0,
- start_discovery_cb,
+ start_sdp_discovery_cb,
dev, NULL);
}