mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-22 14:49:24 +01:00
station: Move state tracking from device
This commit is contained in:
parent
69f1c3321a
commit
e028b7019c
221
src/device.c
221
src/device.c
@ -50,13 +50,11 @@
|
||||
|
||||
struct device {
|
||||
uint32_t index;
|
||||
enum device_state state;
|
||||
struct l_dbus_message *scan_pending;
|
||||
struct scan_bss *connected_bss;
|
||||
struct network *connected_network;
|
||||
struct l_dbus_message *connect_pending;
|
||||
struct l_dbus_message *disconnect_pending;
|
||||
struct watchlist state_watches;
|
||||
struct timespec roam_min_time;
|
||||
struct l_timeout *roam_trigger_timeout;
|
||||
uint32_t roam_scan_id;
|
||||
@ -67,6 +65,7 @@ struct device {
|
||||
struct netdev *netdev;
|
||||
struct station *station;
|
||||
|
||||
bool powered : 1;
|
||||
bool scanning : 1;
|
||||
bool autoconnect : 1;
|
||||
bool preparing_roam : 1;
|
||||
@ -103,28 +102,6 @@ void __iwd_device_foreach(iwd_device_foreach_func func, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *device_state_to_string(enum device_state state)
|
||||
{
|
||||
switch (state) {
|
||||
case DEVICE_STATE_OFF:
|
||||
return "off";
|
||||
case DEVICE_STATE_DISCONNECTED:
|
||||
return "disconnected";
|
||||
case DEVICE_STATE_AUTOCONNECT:
|
||||
return "autoconnect";
|
||||
case DEVICE_STATE_CONNECTING:
|
||||
return "connecting";
|
||||
case DEVICE_STATE_CONNECTED:
|
||||
return "connected";
|
||||
case DEVICE_STATE_DISCONNECTING:
|
||||
return "disconnecting";
|
||||
case DEVICE_STATE_ROAMING:
|
||||
return "roaming";
|
||||
}
|
||||
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
void device_set_scan_results(struct device *device, struct l_queue *bss_list,
|
||||
bool add_to_autoconnect)
|
||||
{
|
||||
@ -136,7 +113,7 @@ static bool new_scan_results(uint32_t wiphy_id, uint32_t ifindex, int err,
|
||||
{
|
||||
struct device *device = userdata;
|
||||
struct l_dbus *dbus = dbus_get_bus();
|
||||
bool autoconnect = device->state == DEVICE_STATE_AUTOCONNECT;
|
||||
bool autoconnect;
|
||||
|
||||
if (device->scanning) {
|
||||
device->scanning = false;
|
||||
@ -151,6 +128,8 @@ static bool new_scan_results(uint32_t wiphy_id, uint32_t ifindex, int err,
|
||||
if (netdev_get_iftype(device->netdev) != NETDEV_IFTYPE_STATION)
|
||||
return false;
|
||||
|
||||
autoconnect = station_get_state(device->station) ==
|
||||
STATION_STATE_AUTOCONNECT;
|
||||
device_set_scan_results(device, bss_list, autoconnect);
|
||||
|
||||
if (autoconnect)
|
||||
@ -173,11 +152,17 @@ const char *device_get_path(struct device *device)
|
||||
return path;
|
||||
}
|
||||
|
||||
/* TODO: Remove when Station/Device is split */
|
||||
bool device_is_busy(struct device *device)
|
||||
{
|
||||
if (device->state != DEVICE_STATE_DISCONNECTED &&
|
||||
device->state != DEVICE_STATE_AUTOCONNECT &&
|
||||
device->state != DEVICE_STATE_OFF)
|
||||
enum station_state state;
|
||||
|
||||
if (!device->powered || !device->station)
|
||||
return false;
|
||||
|
||||
state = station_get_state(device->station);
|
||||
if (state != STATION_STATE_DISCONNECTED &&
|
||||
state != STATION_STATE_AUTOCONNECT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -188,11 +173,6 @@ struct wiphy *device_get_wiphy(struct device *device)
|
||||
return device->wiphy;
|
||||
}
|
||||
|
||||
enum device_state device_get_state(struct device *device)
|
||||
{
|
||||
return device->state;
|
||||
}
|
||||
|
||||
static void periodic_scan_trigger(int err, void *user_data)
|
||||
{
|
||||
struct device *device = user_data;
|
||||
@ -216,67 +196,49 @@ static void periodic_scan_stop(struct device *device)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t device_add_state_watch(struct device *device,
|
||||
device_state_watch_func_t func,
|
||||
void *user_data,
|
||||
device_destroy_func_t destroy)
|
||||
{
|
||||
return watchlist_add(&device->state_watches, func, user_data, destroy);
|
||||
}
|
||||
|
||||
bool device_remove_state_watch(struct device *device, uint32_t id)
|
||||
{
|
||||
return watchlist_remove(&device->state_watches, id);
|
||||
}
|
||||
|
||||
struct network *device_network_find(struct device *device, const char *ssid,
|
||||
enum security security)
|
||||
{
|
||||
return station_network_find(device->station, ssid, security);
|
||||
}
|
||||
|
||||
static void device_enter_state(struct device *device, enum device_state state)
|
||||
static void device_enter_state(struct device *device, enum station_state state)
|
||||
{
|
||||
struct station *station = device->station;
|
||||
struct l_dbus *dbus = dbus_get_bus();
|
||||
bool disconnected;
|
||||
|
||||
l_debug("Old State: %s, new state: %s",
|
||||
device_state_to_string(device->state),
|
||||
device_state_to_string(state));
|
||||
station_state_to_string(station->state),
|
||||
station_state_to_string(state));
|
||||
|
||||
switch (state) {
|
||||
case DEVICE_STATE_OFF:
|
||||
periodic_scan_stop(device);
|
||||
break;
|
||||
case DEVICE_STATE_AUTOCONNECT:
|
||||
case STATION_STATE_AUTOCONNECT:
|
||||
scan_periodic_start(device->index, periodic_scan_trigger,
|
||||
new_scan_results, device);
|
||||
break;
|
||||
case DEVICE_STATE_DISCONNECTED:
|
||||
case STATION_STATE_DISCONNECTED:
|
||||
periodic_scan_stop(device);
|
||||
break;
|
||||
case DEVICE_STATE_CONNECTED:
|
||||
case STATION_STATE_CONNECTED:
|
||||
periodic_scan_stop(device);
|
||||
break;
|
||||
case DEVICE_STATE_CONNECTING:
|
||||
case STATION_STATE_CONNECTING:
|
||||
break;
|
||||
case DEVICE_STATE_DISCONNECTING:
|
||||
case STATION_STATE_DISCONNECTING:
|
||||
break;
|
||||
case DEVICE_STATE_ROAMING:
|
||||
case STATION_STATE_ROAMING:
|
||||
break;
|
||||
}
|
||||
|
||||
disconnected = device->state <= DEVICE_STATE_AUTOCONNECT;
|
||||
disconnected = station->state <= STATION_STATE_AUTOCONNECT;
|
||||
|
||||
if ((disconnected && state > DEVICE_STATE_AUTOCONNECT) ||
|
||||
(!disconnected && state != device->state))
|
||||
if ((disconnected && state > STATION_STATE_AUTOCONNECT) ||
|
||||
(!disconnected && state != station->state))
|
||||
l_dbus_property_changed(dbus, device_get_path(device),
|
||||
IWD_DEVICE_INTERFACE, "State");
|
||||
|
||||
device->state = state;
|
||||
|
||||
WATCHLIST_NOTIFY(&device->state_watches,
|
||||
device_state_watch_func_t, state);
|
||||
station_enter_state(station, state);
|
||||
}
|
||||
|
||||
static void device_reset_connection_state(struct device *device)
|
||||
@ -288,9 +250,9 @@ static void device_reset_connection_state(struct device *device)
|
||||
if (!network)
|
||||
return;
|
||||
|
||||
if (device->state == DEVICE_STATE_CONNECTED ||
|
||||
device->state == DEVICE_STATE_CONNECTING ||
|
||||
device->state == DEVICE_STATE_ROAMING)
|
||||
if (station->state == STATION_STATE_CONNECTED ||
|
||||
station->state == STATION_STATE_CONNECTING ||
|
||||
station->state == STATION_STATE_ROAMING)
|
||||
network_disconnected(network);
|
||||
|
||||
l_timeout_remove(device->roam_trigger_timeout);
|
||||
@ -319,10 +281,10 @@ static void device_disassociated(struct device *device)
|
||||
|
||||
device_reset_connection_state(device);
|
||||
|
||||
device_enter_state(device, DEVICE_STATE_DISCONNECTED);
|
||||
device_enter_state(device, STATION_STATE_DISCONNECTED);
|
||||
|
||||
if (device->autoconnect)
|
||||
device_enter_state(device, DEVICE_STATE_AUTOCONNECT);
|
||||
device_enter_state(device, STATION_STATE_AUTOCONNECT);
|
||||
}
|
||||
|
||||
static void device_disconnect_event(struct device *device)
|
||||
@ -343,6 +305,8 @@ static void device_disconnect_event(struct device *device)
|
||||
|
||||
static void device_roam_failed(struct device *device)
|
||||
{
|
||||
struct station *station = device->station;
|
||||
|
||||
/*
|
||||
* If we're still connected to the old BSS, only clear preparing_roam
|
||||
* and reattempt in 60 seconds if signal level is still low at that
|
||||
@ -357,7 +321,7 @@ static void device_roam_failed(struct device *device)
|
||||
device->roam_no_orig_ap = false;
|
||||
device->ap_directed_roaming = false;
|
||||
|
||||
if (device->state == DEVICE_STATE_ROAMING)
|
||||
if (station->state == STATION_STATE_ROAMING)
|
||||
device_disassociated(device);
|
||||
else if (device->signal_low)
|
||||
device_roam_timeout_rearm(device, 60);
|
||||
@ -368,10 +332,11 @@ static void device_reassociate_cb(struct netdev *netdev,
|
||||
void *user_data)
|
||||
{
|
||||
struct device *device = user_data;
|
||||
struct station *station = device->station;
|
||||
|
||||
l_debug("%d, result: %d", device->index, result);
|
||||
|
||||
if (device->state != DEVICE_STATE_ROAMING)
|
||||
if (station->state != STATION_STATE_ROAMING)
|
||||
return;
|
||||
|
||||
if (result == NETDEV_RESULT_OK) {
|
||||
@ -383,7 +348,7 @@ static void device_reassociate_cb(struct netdev *netdev,
|
||||
device->roam_min_time.tv_sec = 0;
|
||||
device->roam_no_orig_ap = false;
|
||||
|
||||
device_enter_state(device, DEVICE_STATE_CONNECTED);
|
||||
device_enter_state(device, STATION_STATE_CONNECTED);
|
||||
} else
|
||||
device_roam_failed(device);
|
||||
}
|
||||
@ -393,10 +358,11 @@ static void device_fast_transition_cb(struct netdev *netdev,
|
||||
void *user_data)
|
||||
{
|
||||
struct device *device = user_data;
|
||||
struct station *station = device->station;
|
||||
|
||||
l_debug("%d, result: %d", device->index, result);
|
||||
|
||||
if (device->state != DEVICE_STATE_ROAMING)
|
||||
if (station->state != STATION_STATE_ROAMING)
|
||||
return;
|
||||
|
||||
if (result == NETDEV_RESULT_OK) {
|
||||
@ -408,7 +374,7 @@ static void device_fast_transition_cb(struct netdev *netdev,
|
||||
device->roam_min_time.tv_sec = 0;
|
||||
device->roam_no_orig_ap = false;
|
||||
|
||||
device_enter_state(device, DEVICE_STATE_CONNECTED);
|
||||
device_enter_state(device, STATION_STATE_CONNECTED);
|
||||
} else
|
||||
device_roam_failed(device);
|
||||
}
|
||||
@ -431,7 +397,7 @@ static void device_transition_reassociate(struct device *device,
|
||||
device->connected_bss = bss;
|
||||
station->connected_bss = bss;
|
||||
device->preparing_roam = false;
|
||||
device_enter_state(device, DEVICE_STATE_ROAMING);
|
||||
device_enter_state(device, STATION_STATE_ROAMING);
|
||||
}
|
||||
|
||||
static bool bss_match_bssid(const void *a, const void *b)
|
||||
@ -549,7 +515,7 @@ static void device_transition_start(struct device *device, struct scan_bss *bss)
|
||||
device->connected_bss = bss;
|
||||
station->connected_bss = bss;
|
||||
device->preparing_roam = false;
|
||||
device_enter_state(device, DEVICE_STATE_ROAMING);
|
||||
device_enter_state(device, STATION_STATE_ROAMING);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -991,12 +957,13 @@ static void device_ap_roam_frame_event(struct netdev *netdev,
|
||||
void *user_data)
|
||||
{
|
||||
struct device *device = user_data;
|
||||
struct station *station = device->station;
|
||||
uint32_t pos = 0;
|
||||
uint8_t req_mode;
|
||||
uint16_t dtimer;
|
||||
uint8_t valid_interval;
|
||||
|
||||
if (device->preparing_roam || device->state == DEVICE_STATE_ROAMING)
|
||||
if (device->preparing_roam || station->state == STATION_STATE_ROAMING)
|
||||
return;
|
||||
|
||||
if (body_len < 7)
|
||||
@ -1068,10 +1035,12 @@ format_error:
|
||||
|
||||
static void device_lost_beacon(struct device *device)
|
||||
{
|
||||
struct station *station = device->station;
|
||||
|
||||
l_debug("%d", device->index);
|
||||
|
||||
if (device->state != DEVICE_STATE_ROAMING &&
|
||||
device->state != DEVICE_STATE_CONNECTED)
|
||||
if (station->state != STATION_STATE_ROAMING &&
|
||||
station->state != STATION_STATE_CONNECTED)
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -1083,7 +1052,7 @@ static void device_lost_beacon(struct device *device)
|
||||
*/
|
||||
device->roam_no_orig_ap = true;
|
||||
|
||||
if (device->preparing_roam || device->state == DEVICE_STATE_ROAMING)
|
||||
if (device->preparing_roam || station->state == STATION_STATE_ROAMING)
|
||||
return;
|
||||
|
||||
device_roam_trigger_cb(NULL, device);
|
||||
@ -1126,7 +1095,7 @@ static void device_connect_cb(struct netdev *netdev, enum netdev_result result,
|
||||
}
|
||||
|
||||
network_connected(device->connected_network);
|
||||
device_enter_state(device, DEVICE_STATE_CONNECTED);
|
||||
device_enter_state(device, STATION_STATE_CONNECTED);
|
||||
}
|
||||
|
||||
static void device_signal_agent_notify(struct signal_agent *agent,
|
||||
@ -1164,6 +1133,7 @@ static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
||||
void *user_data)
|
||||
{
|
||||
struct device *device = user_data;
|
||||
struct station *station = device->station;
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_EVENT_AUTHENTICATING:
|
||||
@ -1186,7 +1156,7 @@ static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
||||
device->signal_low = true;
|
||||
|
||||
if (device->preparing_roam ||
|
||||
device->state == DEVICE_STATE_ROAMING)
|
||||
station->state == STATION_STATE_ROAMING)
|
||||
break;
|
||||
|
||||
/* Set a 5-second initial timeout */
|
||||
@ -1212,16 +1182,18 @@ static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
||||
|
||||
bool device_set_autoconnect(struct device *device, bool autoconnect)
|
||||
{
|
||||
struct station *station = device->station;
|
||||
|
||||
if (device->autoconnect == autoconnect)
|
||||
return true;
|
||||
|
||||
device->autoconnect = autoconnect;
|
||||
|
||||
if (device->state == DEVICE_STATE_DISCONNECTED && autoconnect)
|
||||
device_enter_state(device, DEVICE_STATE_AUTOCONNECT);
|
||||
if (station->state == STATION_STATE_DISCONNECTED && autoconnect)
|
||||
device_enter_state(device, STATION_STATE_AUTOCONNECT);
|
||||
|
||||
if (device->state == DEVICE_STATE_AUTOCONNECT && !autoconnect)
|
||||
device_enter_state(device, DEVICE_STATE_DISCONNECTED);
|
||||
if (station->state == STATION_STATE_AUTOCONNECT && !autoconnect)
|
||||
device_enter_state(device, STATION_STATE_DISCONNECTED);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1253,7 +1225,7 @@ int __device_connect_network(struct device *device, struct network *network,
|
||||
device->connected_network = network;
|
||||
station->connected_network = network;
|
||||
|
||||
device_enter_state(device, DEVICE_STATE_CONNECTING);
|
||||
device_enter_state(device, STATION_STATE_CONNECTING);
|
||||
|
||||
l_dbus_property_changed(dbus, device_get_path(device),
|
||||
IWD_DEVICE_INTERFACE, "ConnectedNetwork");
|
||||
@ -1323,7 +1295,7 @@ static struct l_dbus_message *device_scan(struct l_dbus *dbus,
|
||||
if (netdev_get_iftype(device->netdev) != NETDEV_IFTYPE_STATION)
|
||||
return dbus_error_not_available(message);
|
||||
|
||||
if (device->state == DEVICE_STATE_OFF)
|
||||
if (!device->powered)
|
||||
return dbus_error_failed(message);
|
||||
|
||||
device->scan_pending = l_dbus_message_ref(message);
|
||||
@ -1378,18 +1350,20 @@ static void device_disconnect_cb(struct netdev *netdev, bool success,
|
||||
|
||||
}
|
||||
|
||||
device_enter_state(device, DEVICE_STATE_DISCONNECTED);
|
||||
device_enter_state(device, STATION_STATE_DISCONNECTED);
|
||||
|
||||
if (device->autoconnect)
|
||||
device_enter_state(device, DEVICE_STATE_AUTOCONNECT);
|
||||
device_enter_state(device, STATION_STATE_AUTOCONNECT);
|
||||
}
|
||||
|
||||
int device_disconnect(struct device *device)
|
||||
{
|
||||
if (device->state == DEVICE_STATE_DISCONNECTING)
|
||||
struct station *station = device->station;
|
||||
|
||||
if (station->state == STATION_STATE_DISCONNECTING)
|
||||
return -EBUSY;
|
||||
|
||||
if (!device->connected_bss)
|
||||
if (!station->connected_bss)
|
||||
return -ENOTCONN;
|
||||
|
||||
if (netdev_disconnect(device->netdev, device_disconnect_cb, device) < 0)
|
||||
@ -1402,7 +1376,7 @@ int device_disconnect(struct device *device)
|
||||
*/
|
||||
device_reset_connection_state(device);
|
||||
|
||||
device_enter_state(device, DEVICE_STATE_DISCONNECTING);
|
||||
device_enter_state(device, STATION_STATE_DISCONNECTING);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1412,6 +1386,7 @@ static struct l_dbus_message *device_dbus_disconnect(struct l_dbus *dbus,
|
||||
void *user_data)
|
||||
{
|
||||
struct device *device = user_data;
|
||||
struct station *station = device->station;
|
||||
int result;
|
||||
|
||||
l_debug("");
|
||||
@ -1422,8 +1397,8 @@ static struct l_dbus_message *device_dbus_disconnect(struct l_dbus *dbus,
|
||||
*/
|
||||
device_set_autoconnect(device, false);
|
||||
|
||||
if (device->state == DEVICE_STATE_AUTOCONNECT ||
|
||||
device->state == DEVICE_STATE_DISCONNECTED)
|
||||
if (station->state == STATION_STATE_AUTOCONNECT ||
|
||||
station->state == STATION_STATE_DISCONNECTED)
|
||||
return l_dbus_message_new_method_return(message);
|
||||
|
||||
result = device_disconnect(device);
|
||||
@ -1680,7 +1655,7 @@ static struct l_dbus_message *device_connect_hidden_network(struct l_dbus *dbus,
|
||||
|
||||
l_debug("");
|
||||
|
||||
if (device->state == DEVICE_STATE_OFF)
|
||||
if (!device->powered)
|
||||
return dbus_error_failed(message);
|
||||
|
||||
if (device->connect_pending || device_is_busy(device))
|
||||
@ -1760,7 +1735,7 @@ static bool device_property_get_powered(struct l_dbus *dbus,
|
||||
void *user_data)
|
||||
{
|
||||
struct device *device = user_data;
|
||||
bool powered = device->state != DEVICE_STATE_OFF;
|
||||
bool powered = device->powered;
|
||||
|
||||
l_dbus_message_builder_append_basic(builder, 'b', &powered);
|
||||
|
||||
@ -1812,7 +1787,7 @@ static struct l_dbus_message *device_property_set_powered(struct l_dbus *dbus,
|
||||
if (!l_dbus_message_iter_get_variant(new_value, "b", &powered))
|
||||
return dbus_error_invalid_args(message);
|
||||
|
||||
if (powered == (device->state != DEVICE_STATE_OFF)) {
|
||||
if (powered == device->powered) {
|
||||
complete(dbus, message, NULL);
|
||||
|
||||
return NULL;
|
||||
@ -1913,7 +1888,7 @@ static bool device_property_get_state(struct l_dbus *dbus,
|
||||
void *user_data)
|
||||
{
|
||||
struct device *device = user_data;
|
||||
const char *statestr = "unknown";
|
||||
const char *statestr;
|
||||
|
||||
/* TODO: Remove when Device/Station split is done */
|
||||
if (netdev_get_iftype(device->netdev) != NETDEV_IFTYPE_STATION) {
|
||||
@ -1923,28 +1898,19 @@ static bool device_property_get_state(struct l_dbus *dbus,
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (device->state) {
|
||||
case DEVICE_STATE_CONNECTED:
|
||||
statestr = "connected";
|
||||
break;
|
||||
case DEVICE_STATE_CONNECTING:
|
||||
statestr = "connecting";
|
||||
break;
|
||||
case DEVICE_STATE_DISCONNECTING:
|
||||
statestr = "disconnecting";
|
||||
break;
|
||||
case DEVICE_STATE_OFF:
|
||||
case DEVICE_STATE_DISCONNECTED:
|
||||
case DEVICE_STATE_AUTOCONNECT:
|
||||
statestr = "disconnected";
|
||||
break;
|
||||
case DEVICE_STATE_ROAMING:
|
||||
statestr = "roaming";
|
||||
break;
|
||||
if (device->powered == false) {
|
||||
l_dbus_message_builder_append_basic(builder,
|
||||
's', "disconnected");
|
||||
return true;
|
||||
}
|
||||
|
||||
l_dbus_message_builder_append_basic(builder, 's', statestr);
|
||||
statestr = station_state_to_string(device->station->state);
|
||||
|
||||
/* Special case. For now we treat AUTOCONNECT as disconnected */
|
||||
if (device->station->state == STATION_STATE_AUTOCONNECT)
|
||||
statestr = "disconnected";
|
||||
|
||||
l_dbus_message_builder_append_basic(builder, 's', statestr);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2100,6 +2066,7 @@ static void device_netdev_notify(struct netdev *netdev,
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_WATCH_EVENT_UP:
|
||||
device->powered = true;
|
||||
l_dbus_property_changed(dbus, device_get_path(device),
|
||||
IWD_DEVICE_INTERFACE, "Powered");
|
||||
|
||||
@ -2110,9 +2077,9 @@ static void device_netdev_notify(struct netdev *netdev,
|
||||
device->station = station_create(device->wiphy, device->netdev);
|
||||
|
||||
if (device->autoconnect)
|
||||
device_enter_state(device, DEVICE_STATE_AUTOCONNECT);
|
||||
device_enter_state(device, STATION_STATE_AUTOCONNECT);
|
||||
else
|
||||
device_enter_state(device, DEVICE_STATE_DISCONNECTED);
|
||||
device_enter_state(device, STATION_STATE_DISCONNECTED);
|
||||
break;
|
||||
case NETDEV_WATCH_EVENT_DOWN:
|
||||
if (device->station) {
|
||||
@ -2120,7 +2087,8 @@ static void device_netdev_notify(struct netdev *netdev,
|
||||
device->station = NULL;
|
||||
}
|
||||
|
||||
device_enter_state(device, DEVICE_STATE_OFF);
|
||||
device->powered = false;
|
||||
periodic_scan_stop(device);
|
||||
|
||||
if (device->scan_pending)
|
||||
dbus_pending_reply(&device->scan_pending,
|
||||
@ -2156,7 +2124,6 @@ struct device *device_create(struct wiphy *wiphy, struct netdev *netdev)
|
||||
const uint8_t action_ap_roam_prefix[2] = { 0x0a, 0x07 };
|
||||
|
||||
device = l_new(struct device, 1);
|
||||
watchlist_init(&device->state_watches, NULL);
|
||||
device->index = ifindex;
|
||||
device->wiphy = wiphy;
|
||||
device->netdev = netdev;
|
||||
@ -2182,10 +2149,12 @@ struct device *device_create(struct wiphy *wiphy, struct netdev *netdev)
|
||||
action_ap_roam_prefix, sizeof(action_ap_roam_prefix),
|
||||
device_ap_roam_frame_event, device);
|
||||
|
||||
if (netdev_get_is_up(netdev) &&
|
||||
device->powered = netdev_get_is_up(netdev);
|
||||
|
||||
if (device->powered &&
|
||||
netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION) {
|
||||
device->station = station_create(device->wiphy, device->netdev);
|
||||
device_enter_state(device, DEVICE_STATE_AUTOCONNECT);
|
||||
device_enter_state(device, STATION_STATE_AUTOCONNECT);
|
||||
}
|
||||
|
||||
return device;
|
||||
@ -2213,8 +2182,6 @@ static void device_free(void *user)
|
||||
}
|
||||
|
||||
|
||||
watchlist_destroy(&device->state_watches);
|
||||
|
||||
dbus = dbus_get_bus();
|
||||
l_dbus_unregister_object(dbus, device_get_path(device));
|
||||
|
||||
|
20
src/device.h
20
src/device.h
@ -28,30 +28,10 @@ struct wiphy;
|
||||
struct netdev;
|
||||
struct device;
|
||||
|
||||
enum device_state {
|
||||
DEVICE_STATE_OFF = 0, /* Interface down */
|
||||
DEVICE_STATE_DISCONNECTED, /* Disconnected, no auto-connect */
|
||||
DEVICE_STATE_AUTOCONNECT, /* Disconnected, try auto-connect */
|
||||
DEVICE_STATE_CONNECTING, /* Connecting */
|
||||
DEVICE_STATE_CONNECTED,
|
||||
DEVICE_STATE_DISCONNECTING,
|
||||
DEVICE_STATE_ROAMING
|
||||
};
|
||||
|
||||
typedef void (*device_state_watch_func_t)(enum device_state, void *userdata);
|
||||
typedef void (*device_destroy_func_t)(void *userdata);
|
||||
|
||||
struct network *device_get_connected_network(struct device *device);
|
||||
const char *device_get_path(struct device *device);
|
||||
bool device_is_busy(struct device *device);
|
||||
struct wiphy *device_get_wiphy(struct device *device);
|
||||
enum device_state device_get_state(struct device *device);
|
||||
|
||||
uint32_t device_add_state_watch(struct device *device,
|
||||
device_state_watch_func_t func,
|
||||
void *user_data,
|
||||
device_destroy_func_t destroy);
|
||||
bool device_remove_state_watch(struct device *device, uint32_t id);
|
||||
|
||||
void device_set_scan_results(struct device *device, struct l_queue *bss_list,
|
||||
bool add_to_autoconnect);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "src/util.h"
|
||||
#include "src/iwd.h"
|
||||
#include "src/common.h"
|
||||
#include "src/watchlist.h"
|
||||
#include "src/scan.h"
|
||||
#include "src/netdev.h"
|
||||
#include "src/wiphy.h"
|
||||
@ -496,6 +497,52 @@ not_supported:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *station_state_to_string(enum station_state state)
|
||||
{
|
||||
switch (state) {
|
||||
case STATION_STATE_DISCONNECTED:
|
||||
return "disconnected";
|
||||
case STATION_STATE_AUTOCONNECT:
|
||||
return "autoconnect";
|
||||
case STATION_STATE_CONNECTING:
|
||||
return "connecting";
|
||||
case STATION_STATE_CONNECTED:
|
||||
return "connected";
|
||||
case STATION_STATE_DISCONNECTING:
|
||||
return "disconnecting";
|
||||
case STATION_STATE_ROAMING:
|
||||
return "roaming";
|
||||
}
|
||||
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
void station_enter_state(struct station *station, enum station_state state)
|
||||
{
|
||||
station->state = state;
|
||||
|
||||
WATCHLIST_NOTIFY(&station->state_watches,
|
||||
station_state_watch_func_t, state);
|
||||
}
|
||||
|
||||
enum station_state station_get_state(struct station *station)
|
||||
{
|
||||
return station->state;
|
||||
}
|
||||
|
||||
uint32_t station_add_state_watch(struct station *station,
|
||||
station_state_watch_func_t func,
|
||||
void *user_data,
|
||||
station_destroy_func_t destroy)
|
||||
{
|
||||
return watchlist_add(&station->state_watches, func, user_data, destroy);
|
||||
}
|
||||
|
||||
bool station_remove_state_watch(struct station *station, uint32_t id)
|
||||
{
|
||||
return watchlist_remove(&station->state_watches, id);
|
||||
}
|
||||
|
||||
struct station *station_find(uint32_t ifindex)
|
||||
{
|
||||
const struct l_queue_entry *entry;
|
||||
@ -516,6 +563,7 @@ struct station *station_create(struct wiphy *wiphy, struct netdev *netdev)
|
||||
struct station *station;
|
||||
|
||||
station = l_new(struct station, 1);
|
||||
watchlist_init(&station->state_watches, NULL);
|
||||
|
||||
station->bss_list = l_queue_new();
|
||||
station->networks = l_hashmap_new();
|
||||
@ -544,6 +592,8 @@ void station_free(struct station *station)
|
||||
l_queue_destroy(station->bss_list, bss_free);
|
||||
l_queue_destroy(station->autoconnect_list, l_free);
|
||||
|
||||
watchlist_destroy(&station->state_watches);
|
||||
|
||||
l_free(station);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,21 @@ enum security;
|
||||
struct scan_bss;
|
||||
struct network;
|
||||
|
||||
enum station_state {
|
||||
STATION_STATE_DISCONNECTED, /* Disconnected, no auto-connect */
|
||||
STATION_STATE_AUTOCONNECT, /* Disconnected, try auto-connect */
|
||||
STATION_STATE_CONNECTING, /* Connecting */
|
||||
STATION_STATE_CONNECTED,
|
||||
STATION_STATE_DISCONNECTING,
|
||||
STATION_STATE_ROAMING
|
||||
};
|
||||
|
||||
typedef void (*station_state_watch_func_t)(enum station_state, void *userdata);
|
||||
typedef void (*station_destroy_func_t)(void *userdata);
|
||||
|
||||
struct station {
|
||||
enum station_state state;
|
||||
struct watchlist state_watches;
|
||||
struct scan_bss *connected_bss;
|
||||
struct network *connected_network;
|
||||
struct l_queue *autoconnect_list;
|
||||
@ -60,6 +74,15 @@ struct handshake_state *station_handshake_setup(struct station *station,
|
||||
struct network *network,
|
||||
struct scan_bss *bss);
|
||||
|
||||
const char *station_state_to_string(enum station_state state);
|
||||
void station_enter_state(struct station *station, enum station_state state);
|
||||
enum station_state station_get_state(struct station *station);
|
||||
uint32_t station_add_state_watch(struct station *station,
|
||||
station_state_watch_func_t func,
|
||||
void *user_data,
|
||||
station_destroy_func_t destroy);
|
||||
bool station_remove_state_watch(struct station *station, uint32_t id);
|
||||
|
||||
struct station *station_find(uint32_t ifindex);
|
||||
struct station *station_create(struct wiphy *wiphy, struct netdev *netdev);
|
||||
void station_free(struct station *station);
|
||||
|
85
src/wsc.c
85
src/wsc.c
@ -30,8 +30,10 @@
|
||||
|
||||
#include "src/dbus.h"
|
||||
#include "src/netdev.h"
|
||||
#include "src/watchlist.h"
|
||||
#include "src/device.h"
|
||||
#include "src/wiphy.h"
|
||||
#include "src/station.h"
|
||||
#include "src/scan.h"
|
||||
#include "src/ie.h"
|
||||
#include "src/wscutil.h"
|
||||
@ -50,7 +52,7 @@ static uint32_t netdev_watch = 0;
|
||||
|
||||
struct wsc {
|
||||
struct netdev *netdev;
|
||||
struct device *device; /* TODO: Should be Station */
|
||||
struct station *station;
|
||||
struct l_dbus_message *pending;
|
||||
struct l_dbus_message *pending_cancel;
|
||||
uint8_t *wsc_ies;
|
||||
@ -58,7 +60,7 @@ struct wsc {
|
||||
struct l_timeout *walk_timer;
|
||||
uint32_t scan_id;
|
||||
struct scan_bss *target;
|
||||
uint32_t device_state_watch;
|
||||
uint32_t station_state_watch;
|
||||
struct {
|
||||
char ssid[33];
|
||||
enum security security;
|
||||
@ -112,12 +114,13 @@ static struct l_dbus_message *wsc_error_time_expired(struct l_dbus_message *msg)
|
||||
}
|
||||
static void wsc_try_credentials(struct wsc *wsc)
|
||||
{
|
||||
struct device *device = netdev_get_device(wsc->netdev);
|
||||
unsigned int i;
|
||||
struct network *network;
|
||||
struct scan_bss *bss;
|
||||
|
||||
for (i = 0; i < wsc->n_creds; i++) {
|
||||
network = device_network_find(wsc->device,
|
||||
network = device_network_find(device,
|
||||
wsc->creds[i].ssid,
|
||||
wsc->creds[i].security);
|
||||
if (!network)
|
||||
@ -135,7 +138,7 @@ static void wsc_try_credentials(struct wsc *wsc)
|
||||
!network_set_psk(network, wsc->creds[i].psk))
|
||||
continue;
|
||||
|
||||
device_connect_network(wsc->device, network, bss, wsc->pending);
|
||||
device_connect_network(device, network, bss, wsc->pending);
|
||||
l_dbus_message_unref(wsc->pending);
|
||||
wsc->pending = NULL;
|
||||
|
||||
@ -144,7 +147,7 @@ static void wsc_try_credentials(struct wsc *wsc)
|
||||
|
||||
dbus_pending_reply(&wsc->pending,
|
||||
wsc_error_not_reachable(wsc->pending));
|
||||
device_set_autoconnect(wsc->device, true);
|
||||
device_set_autoconnect(device, true);
|
||||
done:
|
||||
memset(wsc->creds, 0, sizeof(wsc->creds));
|
||||
wsc->n_creds = 0;
|
||||
@ -189,6 +192,7 @@ static void wsc_disconnect_cb(struct netdev *netdev, bool success,
|
||||
void *user_data)
|
||||
{
|
||||
struct wsc *wsc = user_data;
|
||||
struct device *device = netdev_get_device(wsc->netdev);
|
||||
struct l_dbus_message *reply;
|
||||
|
||||
l_debug("%p, success: %d", wsc, success);
|
||||
@ -199,13 +203,14 @@ static void wsc_disconnect_cb(struct netdev *netdev, bool success,
|
||||
l_dbus_message_set_arguments(reply, "");
|
||||
dbus_pending_reply(&wsc->pending_cancel, reply);
|
||||
|
||||
device_set_autoconnect(wsc->device, true);
|
||||
device_set_autoconnect(device, true);
|
||||
}
|
||||
|
||||
static void wsc_connect_cb(struct netdev *netdev, enum netdev_result result,
|
||||
void *user_data)
|
||||
{
|
||||
struct wsc *wsc = user_data;
|
||||
struct device *device = netdev_get_device(wsc->netdev);
|
||||
|
||||
l_debug("%d, result: %d", netdev_get_ifindex(wsc->netdev), result);
|
||||
|
||||
@ -235,7 +240,7 @@ static void wsc_connect_cb(struct netdev *netdev, enum netdev_result result,
|
||||
break;
|
||||
}
|
||||
|
||||
device_set_autoconnect(wsc->device, true);
|
||||
device_set_autoconnect(device, true);
|
||||
}
|
||||
|
||||
static void wsc_credential_obtained(struct wsc *wsc,
|
||||
@ -469,23 +474,24 @@ static void wsc_connect(struct wsc *wsc)
|
||||
wsc->wsc_association = true;
|
||||
}
|
||||
|
||||
static void device_state_watch(enum device_state state, void *userdata)
|
||||
static void station_state_watch(enum station_state state, void *userdata)
|
||||
{
|
||||
struct wsc *wsc = userdata;
|
||||
|
||||
if (state != DEVICE_STATE_DISCONNECTED)
|
||||
if (state != STATION_STATE_DISCONNECTED)
|
||||
return;
|
||||
|
||||
l_debug("%p", wsc);
|
||||
|
||||
device_remove_state_watch(wsc->device, wsc->device_state_watch);
|
||||
wsc->device_state_watch = 0;
|
||||
station_remove_state_watch(wsc->station, wsc->station_state_watch);
|
||||
wsc->station_state_watch = 0;
|
||||
|
||||
wsc_connect(wsc);
|
||||
}
|
||||
|
||||
static void wsc_check_can_connect(struct wsc *wsc, struct scan_bss *target)
|
||||
{
|
||||
struct device *device = netdev_get_device(wsc->netdev);
|
||||
l_debug("%p", wsc);
|
||||
|
||||
/*
|
||||
@ -493,27 +499,27 @@ static void wsc_check_can_connect(struct wsc *wsc, struct scan_bss *target)
|
||||
* be triggering any more scans while disconnecting / connecting
|
||||
*/
|
||||
wsc->target = target;
|
||||
device_set_autoconnect(wsc->device, false);
|
||||
device_set_autoconnect(device, false);
|
||||
|
||||
switch (device_get_state(wsc->device)) {
|
||||
case DEVICE_STATE_DISCONNECTED:
|
||||
switch (station_get_state(wsc->station)) {
|
||||
case STATION_STATE_DISCONNECTED:
|
||||
wsc_connect(wsc);
|
||||
return;
|
||||
case DEVICE_STATE_CONNECTING:
|
||||
case DEVICE_STATE_CONNECTED:
|
||||
if (device_disconnect(wsc->device) < 0)
|
||||
case STATION_STATE_CONNECTING:
|
||||
case STATION_STATE_CONNECTED:
|
||||
if (device_disconnect(device) < 0)
|
||||
goto error;
|
||||
|
||||
/* fall through */
|
||||
case DEVICE_STATE_DISCONNECTING:
|
||||
wsc->device_state_watch =
|
||||
device_add_state_watch(wsc->device, device_state_watch,
|
||||
wsc, NULL);
|
||||
case STATION_STATE_DISCONNECTING:
|
||||
wsc->station_state_watch =
|
||||
station_add_state_watch(wsc->station,
|
||||
station_state_watch,
|
||||
wsc, NULL);
|
||||
return;
|
||||
case DEVICE_STATE_AUTOCONNECT:
|
||||
case DEVICE_STATE_OFF:
|
||||
case DEVICE_STATE_ROAMING:
|
||||
l_warn("wsc_check_can_connect: invalid device state");
|
||||
case STATION_STATE_AUTOCONNECT:
|
||||
case STATION_STATE_ROAMING:
|
||||
l_warn("wsc_check_can_connect: invalid station state");
|
||||
break;
|
||||
}
|
||||
error:
|
||||
@ -564,6 +570,7 @@ static bool push_button_scan_results(uint32_t wiphy_id, uint32_t ifindex,
|
||||
void *userdata)
|
||||
{
|
||||
struct wsc *wsc = userdata;
|
||||
struct device *device = netdev_get_device(wsc->netdev);
|
||||
struct scan_bss *bss_2g;
|
||||
struct scan_bss *bss_5g;
|
||||
struct scan_bss *target;
|
||||
@ -666,7 +673,7 @@ static bool push_button_scan_results(uint32_t wiphy_id, uint32_t ifindex,
|
||||
}
|
||||
|
||||
wsc_cancel_scan(wsc);
|
||||
device_set_scan_results(wsc->device, bss_list, false);
|
||||
device_set_scan_results(device, bss_list, false);
|
||||
|
||||
l_debug("Found AP to connect to: %s",
|
||||
util_address_to_string(target->addr));
|
||||
@ -723,6 +730,7 @@ static bool pin_scan_results(uint32_t wiphy_id, uint32_t ifindex, int err,
|
||||
static const uint8_t wildcard_address[] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
struct wsc *wsc = userdata;
|
||||
struct device *device = netdev_get_device(wsc->netdev);
|
||||
struct scan_bss *target = NULL;
|
||||
const struct l_queue_entry *bss_entry;
|
||||
struct wsc_probe_response probe_response;
|
||||
@ -813,7 +821,7 @@ static bool pin_scan_results(uint32_t wiphy_id, uint32_t ifindex, int err,
|
||||
}
|
||||
|
||||
wsc_cancel_scan(wsc);
|
||||
device_set_scan_results(wsc->device, bss_list, false);
|
||||
device_set_scan_results(device, bss_list, false);
|
||||
|
||||
l_debug("Found AP to connect to: %s",
|
||||
util_address_to_string(target->addr));
|
||||
@ -897,6 +905,10 @@ static struct l_dbus_message *wsc_push_button(struct l_dbus *dbus,
|
||||
if (wsc->pending)
|
||||
return dbus_error_busy(message);
|
||||
|
||||
wsc->station = station_find(netdev_get_ifindex(wsc->netdev));
|
||||
if (!wsc->station)
|
||||
return dbus_error_not_available(message);
|
||||
|
||||
if (!wsc_initiate_scan(wsc, WSC_DEVICE_PASSWORD_ID_PUSH_BUTTON,
|
||||
push_button_scan_results))
|
||||
return dbus_error_failed(message);
|
||||
@ -942,6 +954,10 @@ static struct l_dbus_message *wsc_start_pin(struct l_dbus *dbus,
|
||||
if (wsc->pending)
|
||||
return dbus_error_busy(message);
|
||||
|
||||
wsc->station = station_find(netdev_get_ifindex(wsc->netdev));
|
||||
if (!wsc->station)
|
||||
return dbus_error_not_available(message);
|
||||
|
||||
if (!l_dbus_message_get_arguments(message, "s", &pin))
|
||||
return dbus_error_invalid_args(message);
|
||||
|
||||
@ -976,9 +992,10 @@ static struct l_dbus_message *wsc_cancel(struct l_dbus *dbus,
|
||||
|
||||
wsc_cancel_scan(wsc);
|
||||
|
||||
if (wsc->device_state_watch) {
|
||||
device_remove_state_watch(wsc->device, wsc->device_state_watch);
|
||||
wsc->device_state_watch = 0;
|
||||
if (wsc->station_state_watch) {
|
||||
station_remove_state_watch(wsc->station,
|
||||
wsc->station_state_watch);
|
||||
wsc->station_state_watch = 0;
|
||||
wsc->target = NULL;
|
||||
}
|
||||
|
||||
@ -1021,9 +1038,10 @@ static void wsc_free(void *userdata)
|
||||
|
||||
wsc_cancel_scan(wsc);
|
||||
|
||||
if (wsc->device_state_watch) {
|
||||
device_remove_state_watch(wsc->device, wsc->device_state_watch);
|
||||
wsc->device_state_watch = 0;
|
||||
if (wsc->station_state_watch) {
|
||||
station_remove_state_watch(wsc->station,
|
||||
wsc->station_state_watch);
|
||||
wsc->station_state_watch = 0;
|
||||
wsc->target = NULL;
|
||||
}
|
||||
|
||||
@ -1048,7 +1066,6 @@ static void wsc_add_interface(struct netdev *netdev)
|
||||
|
||||
wsc = l_new(struct wsc, 1);
|
||||
wsc->netdev = netdev;
|
||||
wsc->device = netdev_get_device(netdev);
|
||||
|
||||
if (!l_dbus_object_add_interface(dbus, netdev_get_path(netdev),
|
||||
IWD_WSC_INTERFACE,
|
||||
|
Loading…
Reference in New Issue
Block a user