mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-15 12:34:55 +00:00
2008-06-30 Dan Williams <dcbw@redhat.com>
Attempt to fix various issues causing rh #448889. Mainly, to qualify for the DISCONNECTED state, the device must not be rfkilled _and_ have a valid priv->supplicant.iface. When either condition is false, the device should transition back to UNAVAILABLE because it cannot be used. * src/nm-device-wifi.c - (constructor): cleanup; connect to supplicant manager here since the supplicant manager is always around - (supplicant_interface_acquire): rename from init_supplicant_interface, ensure the supplicant manager is in the IDLE state - (supplicant_interface_release): rename from cleanup_supplicant_interface, cancel any pending scans too - (real_bring_up): don't set up the supplicnat interface here, because we need the supplicant interface at times when the device may not be "up" - (real_take_down): just remove the periodic source - (schedule_scan): ensure a state that would peg the CPU doesn't happen - (remove_supplicant_interface_connection_error_handler): cleanup; don't do anything if there's no supplicant interface - (cleanup_association_attempt): cleanup - (supplicant_iface_state_cb_handler): request an immediate scan when the interface enters the READY state; transition to UNAVAILABLE state when the interface goes down because the device can't be used without a supplicant interface - (supplicant_mgr_state_cb_handler): if the supplicant goes away, clean up and transition to UNAVAILABLE; if the supplicant becomes ready, acquire the supplicant interface and transition to DISCONNECTED if the radio isn't killed - (nm_device_wifi_dispose): move most of device_cleanup() here - (state_changed_cb): release any existing supplicant interface; if the radio is enabled then try to acquire a new supplicant interface; if the radio is enabled and a supplicant interface has been acquired, we can transition to DISCONNECTED - (nm_device_wifi_set_enabled): if bringing the hardware up failed, don't enable the radio, because HAL probably lied to us about the killswitch being off. If bringing the hardware up worked, then try to grab a supplicant interface, and if that was successful, transition to DISCONNECTED git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3785 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
parent
46e854c006
commit
5c7c7da098
41
ChangeLog
41
ChangeLog
|
@ -1,3 +1,44 @@
|
|||
2008-06-30 Dan Williams <dcbw@redhat.com>
|
||||
|
||||
Attempt to fix various issues causing rh #448889. Mainly, to qualify for
|
||||
the DISCONNECTED state, the device must not be rfkilled _and_ have a valid
|
||||
priv->supplicant.iface. When either condition is false, the device should
|
||||
transition back to UNAVAILABLE because it cannot be used.
|
||||
|
||||
* src/nm-device-wifi.c
|
||||
- (constructor): cleanup; connect to supplicant manager here since the
|
||||
supplicant manager is always around
|
||||
- (supplicant_interface_acquire): rename from init_supplicant_interface,
|
||||
ensure the supplicant manager is in the IDLE state
|
||||
- (supplicant_interface_release): rename from cleanup_supplicant_interface,
|
||||
cancel any pending scans too
|
||||
- (real_bring_up): don't set up the supplicnat interface here, because
|
||||
we need the supplicant interface at times when the device may not
|
||||
be "up"
|
||||
- (real_take_down): just remove the periodic source
|
||||
- (schedule_scan): ensure a state that would peg the CPU doesn't happen
|
||||
- (remove_supplicant_interface_connection_error_handler): cleanup; don't
|
||||
do anything if there's no supplicant interface
|
||||
- (cleanup_association_attempt): cleanup
|
||||
- (supplicant_iface_state_cb_handler): request an immediate scan when
|
||||
the interface enters the READY state; transition to UNAVAILABLE
|
||||
state when the interface goes down because the device can't be used
|
||||
without a supplicant interface
|
||||
- (supplicant_mgr_state_cb_handler): if the supplicant goes away, clean
|
||||
up and transition to UNAVAILABLE; if the supplicant becomes ready,
|
||||
acquire the supplicant interface and transition to DISCONNECTED
|
||||
if the radio isn't killed
|
||||
- (nm_device_wifi_dispose): move most of device_cleanup() here
|
||||
- (state_changed_cb): release any existing supplicant interface; if the
|
||||
radio is enabled then try to acquire a new supplicant interface;
|
||||
if the radio is enabled and a supplicant interface has been acquired,
|
||||
we can transition to DISCONNECTED
|
||||
- (nm_device_wifi_set_enabled): if bringing the hardware up failed,
|
||||
don't enable the radio, because HAL probably lied to us about the
|
||||
killswitch being off. If bringing the hardware up worked, then
|
||||
try to grab a supplicant interface, and if that was successful,
|
||||
transition to DISCONNECTED
|
||||
|
||||
2008-06-30 Dan Williams <dcbw@redhat.com>
|
||||
|
||||
* src/supplicant-manager/nm-supplicant-interface.c
|
||||
|
|
|
@ -54,15 +54,6 @@ static gboolean impl_device_get_access_points (NMDeviceWifi *device,
|
|||
GPtrArray **aps,
|
||||
GError **err);
|
||||
|
||||
static guint32 nm_device_wifi_get_frequency (NMDeviceWifi *self);
|
||||
|
||||
static void nm_device_wifi_set_ssid (NMDeviceWifi *self,
|
||||
const GByteArray * ssid);
|
||||
|
||||
#if DEBUG
|
||||
static void nm_device_wifi_ap_list_print (NMDeviceWifi *self);
|
||||
#endif
|
||||
|
||||
#include "nm-device-wifi-glue.h"
|
||||
|
||||
|
||||
|
@ -166,6 +157,15 @@ struct _NMDeviceWifiPrivate
|
|||
gboolean has_scan_capa_ssid;
|
||||
};
|
||||
|
||||
static guint32 nm_device_wifi_get_frequency (NMDeviceWifi *self);
|
||||
|
||||
static void nm_device_wifi_set_ssid (NMDeviceWifi *self, const GByteArray * ssid);
|
||||
|
||||
#if DEBUG
|
||||
static void nm_device_wifi_ap_list_print (NMDeviceWifi *self);
|
||||
#endif
|
||||
|
||||
static gboolean request_wireless_scan (gpointer user_data);
|
||||
|
||||
static void schedule_scan (NMDeviceWifi *self, gboolean backoff);
|
||||
|
||||
|
@ -205,10 +205,6 @@ static void supplicant_mgr_state_cb (NMSupplicantInterface * iface,
|
|||
guint32 old_state,
|
||||
NMDeviceWifi *self);
|
||||
|
||||
static void cleanup_supplicant_interface (NMDeviceWifi * self);
|
||||
|
||||
static void device_cleanup (NMDeviceWifi *self);
|
||||
|
||||
static guint32 nm_device_wifi_get_bitrate (NMDeviceWifi *self);
|
||||
|
||||
|
||||
|
@ -463,11 +459,10 @@ constructor (GType type,
|
|||
NMDeviceWifi *self;
|
||||
NMDeviceWifiPrivate *priv;
|
||||
const char *iface;
|
||||
int fd;
|
||||
int fd, i, err;
|
||||
struct iw_range range;
|
||||
struct iw_range_with_scan_capa *scan_capa_range;
|
||||
struct iwreq wrq;
|
||||
int i;
|
||||
|
||||
klass = G_OBJECT_CLASS (nm_device_wifi_parent_class);
|
||||
object = klass->constructor (type, n_construct_params, construct_params);
|
||||
|
@ -488,7 +483,9 @@ constructor (GType type,
|
|||
wrq.u.data.pointer = (caddr_t) ⦥
|
||||
wrq.u.data.length = sizeof (struct iw_range);
|
||||
|
||||
if (ioctl (fd, SIOCGIWRANGE, &wrq) < 0)
|
||||
err = ioctl (fd, SIOCGIWRANGE, &wrq);
|
||||
close (fd);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
priv->max_qual.qual = range.max_qual.qual;
|
||||
|
@ -526,55 +523,115 @@ constructor (GType type,
|
|||
/* 802.11 wireless-specific capabilities */
|
||||
priv->capabilities = get_wireless_capabilities (self, &range, wrq.u.data.length);
|
||||
|
||||
close (fd);
|
||||
/* Connect to the supplicant manager */
|
||||
priv->supplicant.mgr = nm_supplicant_manager_get ();
|
||||
priv->supplicant.mgr_state_id = g_signal_connect (priv->supplicant.mgr,
|
||||
"state",
|
||||
G_CALLBACK (supplicant_mgr_state_cb),
|
||||
self);
|
||||
|
||||
return object;
|
||||
|
||||
error:
|
||||
if (fd >= 0)
|
||||
close (fd);
|
||||
g_object_unref (object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
init_supplicant_interface (NMDeviceWifi * self)
|
||||
static gboolean
|
||||
supplicant_interface_acquire (NMDeviceWifi *self)
|
||||
{
|
||||
Supplicant * sup;
|
||||
guint id;
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
guint id, mgr_state;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
sup = (Supplicant *) &self->priv->supplicant;
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (priv->supplicant.mgr != NULL, FALSE);
|
||||
/* interface already acquired? */
|
||||
g_return_val_if_fail (priv->supplicant.iface == NULL, TRUE);
|
||||
|
||||
sup->iface = nm_supplicant_manager_get_iface (sup->mgr,
|
||||
mgr_state = nm_supplicant_manager_get_state (priv->supplicant.mgr);
|
||||
g_return_val_if_fail (mgr_state == NM_SUPPLICANT_MANAGER_STATE_IDLE, FALSE);
|
||||
|
||||
priv->supplicant.iface = nm_supplicant_manager_get_iface (priv->supplicant.mgr,
|
||||
nm_device_get_iface (NM_DEVICE (self)),
|
||||
TRUE);
|
||||
if (sup->iface == NULL) {
|
||||
if (priv->supplicant.iface == NULL) {
|
||||
nm_warning ("Couldn't initialize supplicant interface for %s.",
|
||||
nm_device_get_iface (NM_DEVICE (self)));
|
||||
} else {
|
||||
id = g_signal_connect (sup->iface,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
id = g_signal_connect (priv->supplicant.iface,
|
||||
"state",
|
||||
G_CALLBACK (supplicant_iface_state_cb),
|
||||
self);
|
||||
sup->iface_state_id = id;
|
||||
priv->supplicant.iface_state_id = id;
|
||||
|
||||
id = g_signal_connect (sup->iface,
|
||||
id = g_signal_connect (priv->supplicant.iface,
|
||||
"scanned-ap",
|
||||
G_CALLBACK (supplicant_iface_scanned_ap_cb),
|
||||
self);
|
||||
sup->iface_scanned_ap_id = id;
|
||||
priv->supplicant.iface_scanned_ap_id = id;
|
||||
|
||||
id = g_signal_connect (sup->iface,
|
||||
id = g_signal_connect (priv->supplicant.iface,
|
||||
"scan-result",
|
||||
G_CALLBACK (supplicant_iface_scan_result_cb),
|
||||
self);
|
||||
sup->iface_scan_result_id = id;
|
||||
priv->supplicant.iface_scan_result_id = id;
|
||||
|
||||
id = g_signal_connect (sup->iface,
|
||||
id = g_signal_connect (priv->supplicant.iface,
|
||||
"connection-state",
|
||||
G_CALLBACK (supplicant_iface_connection_state_cb),
|
||||
self);
|
||||
sup->iface_con_state_id = id;
|
||||
priv->supplicant.iface_con_state_id = id;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
supplicant_interface_release (NMDeviceWifi *self)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
cancel_pending_scan (self);
|
||||
|
||||
/* Reset the scan interval to be pretty frequent when disconnected */
|
||||
priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP;
|
||||
|
||||
if (priv->supplicant.iface_error_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id);
|
||||
priv->supplicant.iface_error_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_state_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id);
|
||||
priv->supplicant.iface_state_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_scanned_ap_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scanned_ap_id);
|
||||
priv->supplicant.iface_scanned_ap_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_scan_result_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scan_result_id);
|
||||
priv->supplicant.iface_scan_result_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_con_state_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_con_state_id);
|
||||
priv->supplicant.iface_con_state_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface) {
|
||||
/* Tell the supplicant to disconnect from the current AP */
|
||||
nm_supplicant_interface_disconnect (priv->supplicant.iface);
|
||||
|
||||
nm_supplicant_manager_release_iface (priv->supplicant.mgr, priv->supplicant.iface);
|
||||
priv->supplicant.iface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -763,19 +820,7 @@ real_bring_up (NMDevice *dev)
|
|||
NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
nm_device_wifi_set_mode (self, NM_802_11_MODE_INFRA);
|
||||
|
||||
priv->supplicant.mgr = nm_supplicant_manager_get ();
|
||||
priv->supplicant.mgr_state_id = g_signal_connect (priv->supplicant.mgr,
|
||||
"state",
|
||||
G_CALLBACK (supplicant_mgr_state_cb),
|
||||
self);
|
||||
if (nm_supplicant_manager_get_state (priv->supplicant.mgr) == NM_SUPPLICANT_MANAGER_STATE_IDLE)
|
||||
init_supplicant_interface (self);
|
||||
|
||||
/* Peridoically update signal strength */
|
||||
priv->periodic_source_id = g_timeout_add (6000, nm_device_wifi_periodic_update, self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -797,8 +842,9 @@ remove_all_aps (NMDeviceWifi *self)
|
|||
}
|
||||
|
||||
static void
|
||||
device_cleanup (NMDeviceWifi *self)
|
||||
real_take_down (NMDevice *dev)
|
||||
{
|
||||
NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
if (priv->periodic_source_id) {
|
||||
|
@ -806,46 +852,11 @@ device_cleanup (NMDeviceWifi *self)
|
|||
priv->periodic_source_id = 0;
|
||||
}
|
||||
|
||||
cancel_pending_scan (self);
|
||||
/* Reset the scan interval to be pretty frequent when disconnected */
|
||||
priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP;
|
||||
|
||||
cleanup_association_attempt (self, TRUE);
|
||||
|
||||
/* Tell the supplicant to disconnect from the current AP */
|
||||
if (priv->supplicant.iface)
|
||||
nm_supplicant_interface_disconnect (priv->supplicant.iface);
|
||||
|
||||
cleanup_supplicant_interface (self);
|
||||
|
||||
if (priv->supplicant.mgr_state_id) {
|
||||
g_signal_handler_disconnect (priv->supplicant.mgr, priv->supplicant.mgr_state_id);
|
||||
priv->supplicant.mgr_state_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.mgr) {
|
||||
g_object_unref (priv->supplicant.mgr);
|
||||
priv->supplicant.mgr = NULL;
|
||||
}
|
||||
|
||||
if (priv->ssid) {
|
||||
g_byte_array_free (priv->ssid, TRUE);
|
||||
priv->ssid = NULL;
|
||||
}
|
||||
|
||||
|
||||
set_current_ap (self, NULL);
|
||||
remove_all_aps (self);
|
||||
}
|
||||
|
||||
static void
|
||||
real_take_down (NMDevice *dev)
|
||||
{
|
||||
NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
|
||||
|
||||
device_cleanup (self);
|
||||
}
|
||||
|
||||
static void
|
||||
real_deactivate_quickly (NMDevice *dev)
|
||||
{
|
||||
|
@ -1521,6 +1532,8 @@ can_scan (NMDeviceWifi *self)
|
|||
NMDeviceState dev_state;
|
||||
gboolean is_disconnected = FALSE;
|
||||
|
||||
g_return_val_if_fail (priv->supplicant.iface != NULL, FALSE);
|
||||
|
||||
sup_state = nm_supplicant_interface_get_connection_state (priv->supplicant.iface);
|
||||
dev_state = nm_device_get_state (NM_DEVICE (self));
|
||||
|
||||
|
@ -1608,6 +1621,11 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff)
|
|||
priv->scan_interval = MAX(priv->scan_interval, SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP);
|
||||
/* ... or more than 120s */
|
||||
priv->scan_interval = MIN(priv->scan_interval, SCAN_INTERVAL_MAX);
|
||||
} else if (!backoff && (priv->scan_interval == 0)) {
|
||||
/* Invalid combination; would cause continual rescheduling of
|
||||
* the scan and hog CPU. Reset to something minimally sane.
|
||||
*/
|
||||
priv->scan_interval = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1898,24 +1916,27 @@ supplicant_iface_scanned_ap_cb (NMSupplicantInterface *iface,
|
|||
static void
|
||||
remove_supplicant_interface_connection_error_handler (NMDeviceWifi *self)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
if (self->priv->supplicant.iface_error_id != 0) {
|
||||
g_signal_handler_disconnect (self->priv->supplicant.iface,
|
||||
self->priv->supplicant.iface_error_id);
|
||||
self->priv->supplicant.iface_error_id = 0;
|
||||
if (!priv->supplicant.iface)
|
||||
return;
|
||||
|
||||
if (priv->supplicant.iface_error_id != 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface,
|
||||
priv->supplicant.iface_error_id);
|
||||
priv->supplicant.iface_error_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
remove_supplicant_interface_connection_error_handler (self);
|
||||
remove_supplicant_timeouts (self);
|
||||
if (disconnect && self->priv->supplicant.iface)
|
||||
nm_supplicant_interface_disconnect (self->priv->supplicant.iface);
|
||||
if (disconnect && priv->supplicant.iface)
|
||||
nm_supplicant_interface_disconnect (priv->supplicant.iface);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2076,11 +2097,14 @@ supplicant_iface_state_cb_handler (gpointer user_data)
|
|||
|
||||
if (new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
|
||||
priv->scan_interval = SCAN_INTERVAL_MIN;
|
||||
schedule_scan (self, TRUE);
|
||||
} else if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
|
||||
|
||||
/* Request a scan to get latest results */
|
||||
cancel_pending_scan (self);
|
||||
request_wireless_scan (self);
|
||||
} else if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
|
||||
cleanup_association_attempt (self, FALSE);
|
||||
cleanup_supplicant_interface (self);
|
||||
supplicant_interface_release (self);
|
||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
g_slice_free (struct state_cb_data, cb_data);
|
||||
|
@ -2174,57 +2198,21 @@ supplicant_iface_connection_state_cb (NMSupplicantInterface * iface,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
cleanup_supplicant_interface (NMDeviceWifi * self)
|
||||
{
|
||||
Supplicant * sup;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
sup = &self->priv->supplicant;
|
||||
|
||||
if (sup->iface_error_id > 0) {
|
||||
g_signal_handler_disconnect (sup->iface, sup->iface_error_id);
|
||||
sup->iface_error_id = 0;
|
||||
}
|
||||
|
||||
if (sup->iface_state_id > 0) {
|
||||
g_signal_handler_disconnect (sup->iface, sup->iface_state_id);
|
||||
sup->iface_state_id = 0;
|
||||
}
|
||||
|
||||
if (sup->iface_scanned_ap_id > 0) {
|
||||
g_signal_handler_disconnect (sup->iface, sup->iface_scanned_ap_id);
|
||||
sup->iface_scanned_ap_id = 0;
|
||||
}
|
||||
|
||||
if (sup->iface_scan_result_id > 0) {
|
||||
g_signal_handler_disconnect (sup->iface, sup->iface_scan_result_id);
|
||||
sup->iface_scan_result_id = 0;
|
||||
}
|
||||
|
||||
if (sup->iface_con_state_id > 0) {
|
||||
g_signal_handler_disconnect (sup->iface, sup->iface_con_state_id);
|
||||
sup->iface_con_state_id = 0;
|
||||
}
|
||||
|
||||
if (sup->iface) {
|
||||
nm_supplicant_manager_release_iface (sup->mgr, sup->iface);
|
||||
sup->iface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
supplicant_mgr_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
struct state_cb_data * cb_data = (struct state_cb_data *) user_data;
|
||||
NMDeviceWifi *self;
|
||||
NMDeviceWifiPrivate *priv;
|
||||
NMDevice *dev;
|
||||
guint32 new_state, old_state;
|
||||
NMDeviceState dev_state;
|
||||
|
||||
g_return_val_if_fail (cb_data != NULL, FALSE);
|
||||
|
||||
self = cb_data->self;
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
dev = NM_DEVICE (self);
|
||||
new_state = cb_data->new_state;
|
||||
old_state = cb_data->old_state;
|
||||
|
||||
|
@ -2235,20 +2223,26 @@ supplicant_mgr_state_cb_handler (gpointer user_data)
|
|||
|
||||
/* If the supplicant went away, release the supplicant interface */
|
||||
if (new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
|
||||
if (self->priv->supplicant.iface) {
|
||||
NMDevice * dev = NM_DEVICE (self);
|
||||
|
||||
if (priv->supplicant.iface) {
|
||||
cleanup_association_attempt (self, FALSE);
|
||||
cleanup_supplicant_interface (self);
|
||||
supplicant_interface_release (self);
|
||||
|
||||
if (nm_device_is_activating (dev)) {
|
||||
nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED);
|
||||
}
|
||||
if (nm_device_is_activating (dev))
|
||||
nm_device_state_changed (dev, NM_DEVICE_STATE_UNAVAILABLE);
|
||||
}
|
||||
} else if (new_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) {
|
||||
if (!self->priv->supplicant.iface) {
|
||||
dev_state = nm_device_get_state (dev);
|
||||
if ( priv->enabled
|
||||
&& !priv->supplicant.iface
|
||||
&& (dev_state >= NM_DEVICE_STATE_UNAVAILABLE)) {
|
||||
/* request a supplicant interface from the supplicant manager */
|
||||
init_supplicant_interface (self);
|
||||
supplicant_interface_acquire (self);
|
||||
|
||||
/* if wireless is enabled and we have a supplicant interface,
|
||||
* we can transition to the DISCONNECTED state.
|
||||
*/
|
||||
if (priv->supplicant.iface)
|
||||
nm_device_state_changed (dev, NM_DEVICE_STATE_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3030,7 +3024,31 @@ nm_device_wifi_dispose (GObject *object)
|
|||
|
||||
priv->dispose_has_run = TRUE;
|
||||
|
||||
device_cleanup (self);
|
||||
if (priv->periodic_source_id) {
|
||||
g_source_remove (priv->periodic_source_id);
|
||||
priv->periodic_source_id = 0;
|
||||
}
|
||||
|
||||
cleanup_association_attempt (self, TRUE);
|
||||
supplicant_interface_release (self);
|
||||
|
||||
if (priv->supplicant.mgr_state_id) {
|
||||
g_signal_handler_disconnect (priv->supplicant.mgr, priv->supplicant.mgr_state_id);
|
||||
priv->supplicant.mgr_state_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.mgr) {
|
||||
g_object_unref (priv->supplicant.mgr);
|
||||
priv->supplicant.mgr = NULL;
|
||||
}
|
||||
|
||||
if (priv->ssid) {
|
||||
g_byte_array_free (priv->ssid, TRUE);
|
||||
priv->ssid = NULL;
|
||||
}
|
||||
|
||||
set_current_ap (self, NULL);
|
||||
remove_all_aps (self);
|
||||
|
||||
if (priv->state_to_disconnected_id) {
|
||||
g_source_remove (priv->state_to_disconnected_id);
|
||||
|
@ -3206,18 +3224,30 @@ state_changed_cb (NMDevice *device, NMDeviceState state, gpointer user_data)
|
|||
priv->state_to_disconnected_id = 0;
|
||||
}
|
||||
|
||||
if (state <= NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
/* Clean up the supplicant interface because in these states the
|
||||
* device cannot be used.
|
||||
*/
|
||||
if (priv->supplicant.iface)
|
||||
supplicant_interface_release (self);
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case NM_DEVICE_STATE_UNMANAGED:
|
||||
clear_aps = TRUE;
|
||||
break;
|
||||
case NM_DEVICE_STATE_UNAVAILABLE:
|
||||
/* If transitioning to UNAVAILBLE and the device is not rfkilled,
|
||||
* transition to DISCONNECTED because the device is ready to use.
|
||||
* Otherwise the rfkill/enabled handler handle the transition to
|
||||
* DISCONNECTED when the device is no longer rfkilled.
|
||||
/* If the device is enabled and the supplicant manager is ready,
|
||||
* acquire a supplicant interface and transition to DISCONNECTED because
|
||||
* the device is now ready to use.
|
||||
*/
|
||||
if (priv->enabled)
|
||||
if (priv->enabled) {
|
||||
if (!priv->supplicant.iface)
|
||||
supplicant_interface_acquire (self);
|
||||
|
||||
if (priv->supplicant.iface)
|
||||
priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, self);
|
||||
}
|
||||
clear_aps = TRUE;
|
||||
break;
|
||||
case NM_DEVICE_STATE_ACTIVATED:
|
||||
|
@ -3308,18 +3338,26 @@ nm_device_wifi_set_enabled (NMDeviceWifi *self, gboolean enabled)
|
|||
priv->enabled = enabled;
|
||||
|
||||
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
|
||||
if (state >= NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
if (enabled) {
|
||||
nm_device_hw_bring_up (NM_DEVICE (self), TRUE);
|
||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED);
|
||||
if (state < NM_DEVICE_STATE_UNAVAILABLE)
|
||||
return;
|
||||
|
||||
/* Request a scan to get results immediately */
|
||||
cancel_pending_scan (self);
|
||||
request_wireless_scan (self);
|
||||
if (enabled) {
|
||||
g_warn_if_fail (state == NM_DEVICE_STATE_UNAVAILABLE);
|
||||
|
||||
if (!nm_device_hw_bring_up (NM_DEVICE (self), TRUE)) {
|
||||
/* The device sucks, or HAL was lying to us about the killswitch state */
|
||||
priv->enabled = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!priv->supplicant.iface)
|
||||
supplicant_interface_acquire (self);
|
||||
|
||||
if (priv->supplicant.iface)
|
||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED);
|
||||
} else {
|
||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE);
|
||||
nm_device_hw_take_down (NM_DEVICE (self), TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue