diff --git a/src/network.c b/src/network.c index 1e4a997c..c3da4115 100644 --- a/src/network.c +++ b/src/network.c @@ -1176,9 +1176,6 @@ static struct l_dbus_message *network_connect(struct l_dbus *dbus, l_debug(""); - if (station_is_busy(station)) - return dbus_error_busy(message); - /* * Select the best BSS to use at this time. If we have to query the * agent this may not be the final choice because BSS visibility can diff --git a/src/station.c b/src/station.c index 593b05b0..9f881cfd 100644 --- a/src/station.c +++ b/src/station.c @@ -63,6 +63,8 @@ struct station { struct watchlist state_watches; struct scan_bss *connected_bss; struct network *connected_network; + struct scan_bss *connect_pending_bss; + struct network *connect_pending_network; struct l_queue *autoconnect_list; struct l_queue *bss_list; struct l_queue *hidden_bss_list_sorted; @@ -2225,6 +2227,53 @@ int __station_connect_network(struct station *station, struct network *network, return 0; } +static void station_disconnect_onconnect_cb(struct netdev *netdev, bool success, + void *user_data) +{ + struct station *station = user_data; + int err; + + station_enter_state(station, STATION_STATE_DISCONNECTED); + + err = __station_connect_network(station, + station->connect_pending_network, + station->connect_pending_bss); + + station->connect_pending_network = NULL; + station->connect_pending_bss = NULL; + + if (err < 0) { + l_dbus_send(dbus_get_bus(), + dbus_error_from_errno(err, + station->connect_pending)); + return; + } + + station_enter_state(station, STATION_STATE_CONNECTING); +} + +static void station_disconnect_onconnect(struct station *station, + struct network *network, + struct scan_bss *bss, + struct l_dbus_message *message) +{ + if (netdev_disconnect(station->netdev, station_disconnect_onconnect_cb, + station) < 0) { + l_dbus_send(dbus_get_bus(), + dbus_error_from_errno(-EIO, message)); + return; + } + + station_reset_connection_state(station); + + station_enter_state(station, STATION_STATE_DISCONNECTING); + + station->connect_pending_network = network; + station->connect_pending_bss = bss; + + station->connect_pending = l_dbus_message_ref(message); +} + void station_connect_network(struct station *station, struct network *network, struct scan_bss *bss, struct l_dbus_message *message) @@ -2233,8 +2282,9 @@ void station_connect_network(struct station *station, struct network *network, int err; if (station_is_busy(station)) { - err = -EBUSY; - goto error; + station_disconnect_onconnect(station, network, bss, message); + + return; } err = __station_connect_network(station, network, bss);