mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-29 10:20:11 +01:00
wifi: poll rfkill status for ipw2x00 devices
The ipw2x00 drivers won't be converted over to the kernel's rfkill subsystem until 2.6.33, and thus listening for udev rfkill change events on these devices doesn't work. So until then, poll rfkill state for ipw2x00 devices every few seconds in addition to listening to other rfkill sources.
This commit is contained in:
parent
66994a18a3
commit
e123fcb143
5 changed files with 240 additions and 47 deletions
|
|
@ -84,6 +84,7 @@ enum {
|
|||
PROP_CAPABILITIES,
|
||||
PROP_IFINDEX,
|
||||
PROP_SCANNING,
|
||||
PROP_IPW_RFKILL_STATE,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
|
@ -145,6 +146,11 @@ struct _NMDeviceWifiPrivate {
|
|||
struct ether_addr hw_addr;
|
||||
guint32 ifindex;
|
||||
|
||||
/* Legacy rfkill for ipw2x00; will be fixed with 2.6.33 kernel */
|
||||
char * ipw_rfkill_path;
|
||||
guint ipw_rfkill_id;
|
||||
RfKillState ipw_rfkill_state;
|
||||
|
||||
GByteArray * ssid;
|
||||
gint8 invalid_strength_counter;
|
||||
iwqual max_qual;
|
||||
|
|
@ -260,10 +266,54 @@ nm_wifi_error_get_type (void)
|
|||
return etype;
|
||||
}
|
||||
|
||||
static void
|
||||
access_point_removed (NMDeviceWifi *device, NMAccessPoint *ap)
|
||||
/* IPW rfkill handling (until 2.6.33) */
|
||||
RfKillState
|
||||
nm_device_wifi_get_ipw_rfkill_state (NMDeviceWifi *self)
|
||||
{
|
||||
g_signal_emit (device, signals[ACCESS_POINT_REMOVED], 0, ap);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
char *contents = NULL;
|
||||
RfKillState state = RFKILL_UNBLOCKED;
|
||||
|
||||
if ( priv->ipw_rfkill_path
|
||||
&& g_file_get_contents (priv->ipw_rfkill_path, &contents, NULL, NULL)) {
|
||||
contents = g_strstrip (contents);
|
||||
|
||||
/* 0 - RF kill not enabled
|
||||
* 1 - SW based RF kill active (sysfs)
|
||||
* 2 - HW based RF kill active
|
||||
* 3 - Both HW and SW baed RF kill active
|
||||
*/
|
||||
switch (contents[0]) {
|
||||
case '1':
|
||||
state = RFKILL_SOFT_BLOCKED;
|
||||
break;
|
||||
case '2':
|
||||
case '3':
|
||||
state = RFKILL_HARD_BLOCKED;
|
||||
break;
|
||||
case '0':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_free (contents);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ipw_rfkill_state_work (gpointer user_data)
|
||||
{
|
||||
NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
RfKillState old_state;
|
||||
|
||||
old_state = priv->ipw_rfkill_state;
|
||||
priv->ipw_rfkill_state = nm_device_wifi_get_ipw_rfkill_state (self);
|
||||
if (priv->ipw_rfkill_state != old_state)
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_IPW_RFKILL_STATE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -560,6 +610,22 @@ constructor (GType type,
|
|||
G_CALLBACK (supplicant_mgr_state_cb),
|
||||
self);
|
||||
|
||||
/* The ipw2x00 drivers don't integrate with the kernel rfkill subsystem until
|
||||
* 2.6.33. Thus all our nice libgudev magic is useless. So we get to poll.
|
||||
*
|
||||
* FIXME: when 2.6.33 comes lands, we can do some sysfs parkour to figure out
|
||||
* if we need to poll or not by matching /sys/class/net/ethX/device to one
|
||||
* of the /sys/class/rfkill/rfkillX/device links. If there's a match, we
|
||||
* don't have to poll.
|
||||
*/
|
||||
priv->ipw_rfkill_path = g_strdup_printf ("/sys/class/net/%s/device/rf_kill",
|
||||
nm_device_get_iface (NM_DEVICE (self)));
|
||||
if (!g_file_test (priv->ipw_rfkill_path, G_FILE_TEST_IS_REGULAR)) {
|
||||
g_free (priv->ipw_rfkill_path);
|
||||
priv->ipw_rfkill_path = NULL;
|
||||
}
|
||||
priv->ipw_rfkill_state = nm_device_wifi_get_ipw_rfkill_state (self);
|
||||
|
||||
return object;
|
||||
|
||||
error:
|
||||
|
|
@ -1015,6 +1081,12 @@ real_bring_up (NMDevice *dev)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
access_point_removed (NMDeviceWifi *device, NMAccessPoint *ap)
|
||||
{
|
||||
g_signal_emit (device, signals[ACCESS_POINT_REMOVED], 0, ap);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_all_aps (NMDeviceWifi *self)
|
||||
{
|
||||
|
|
@ -3260,6 +3332,19 @@ device_state_changed (NMDevice *device,
|
|||
supplicant_interface_release (self);
|
||||
}
|
||||
|
||||
/* Start or stop the rfkill poll worker for ipw cards */
|
||||
if (priv->ipw_rfkill_path) {
|
||||
if (new_state > NM_DEVICE_STATE_UNMANAGED) {
|
||||
if (!priv->ipw_rfkill_id)
|
||||
priv->ipw_rfkill_id = g_timeout_add_seconds (3, ipw_rfkill_state_work, self);
|
||||
} else if (new_state <= NM_DEVICE_STATE_UNMANAGED) {
|
||||
if (priv->ipw_rfkill_id) {
|
||||
g_source_remove (priv->ipw_rfkill_id);
|
||||
priv->ipw_rfkill_id = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (new_state) {
|
||||
case NM_DEVICE_STATE_UNMANAGED:
|
||||
clear_aps = TRUE;
|
||||
|
|
@ -3456,6 +3541,12 @@ dispose (GObject *object)
|
|||
set_current_ap (self, NULL);
|
||||
remove_all_aps (self);
|
||||
|
||||
g_free (priv->ipw_rfkill_path);
|
||||
if (priv->ipw_rfkill_id) {
|
||||
g_source_remove (priv->ipw_rfkill_id);
|
||||
priv->ipw_rfkill_id = 0;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
|
@ -3493,6 +3584,9 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_SCANNING:
|
||||
g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->supplicant.iface));
|
||||
break;
|
||||
case PROP_IPW_RFKILL_STATE:
|
||||
g_value_set_uint (value, nm_device_wifi_get_ipw_rfkill_state (device));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -3510,6 +3604,10 @@ set_property (GObject *object, guint prop_id,
|
|||
/* construct-only */
|
||||
priv->ifindex = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_IPW_RFKILL_STATE:
|
||||
/* construct only */
|
||||
priv->ipw_rfkill_state = g_value_get_uint (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -3607,6 +3705,13 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
|
|||
FALSE,
|
||||
G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_IPW_RFKILL_STATE,
|
||||
g_param_spec_uint (NM_DEVICE_WIFI_IPW_RFKILL_STATE,
|
||||
"IpwRfkillState",
|
||||
"ipw rf-kill state",
|
||||
RFKILL_UNBLOCKED, RFKILL_HARD_BLOCKED, RFKILL_UNBLOCKED,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
|
||||
|
||||
/* Signals */
|
||||
signals[ACCESS_POINT_ADDED] =
|
||||
g_signal_new ("access-point-added",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#include <dbus/dbus.h>
|
||||
#include <net/ethernet.h>
|
||||
|
||||
|
||||
#include "nm-rfkill.h"
|
||||
#include "nm-device.h"
|
||||
#include "NetworkManagerAP.h"
|
||||
|
||||
|
|
@ -49,6 +49,7 @@ G_BEGIN_DECLS
|
|||
#define NM_DEVICE_WIFI_CAPABILITIES "wireless-capabilities"
|
||||
#define NM_DEVICE_WIFI_IFINDEX "ifindex"
|
||||
#define NM_DEVICE_WIFI_SCANNING "scanning"
|
||||
#define NM_DEVICE_WIFI_IPW_RFKILL_STATE "ipw-rfkill-state"
|
||||
|
||||
#ifndef NM_DEVICE_WIFI_DEFINED
|
||||
#define NM_DEVICE_WIFI_DEFINED
|
||||
|
|
@ -105,6 +106,8 @@ void nm_device_wifi_set_enabled (NMDeviceWifi *self, gboolean enabled);
|
|||
|
||||
guint32 nm_device_wifi_get_ifindex (NMDeviceWifi *self);
|
||||
|
||||
RfKillState nm_device_wifi_get_ipw_rfkill_state (NMDeviceWifi *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* NM_DEVICE_WIFI_H */
|
||||
|
|
|
|||
133
src/nm-manager.c
133
src/nm-manager.c
|
|
@ -80,7 +80,6 @@ static gboolean impl_manager_legacy_state (NMManager *manager, guint32 *state, G
|
|||
#include "nm-manager-glue.h"
|
||||
|
||||
static void user_destroy_connections (NMManager *manager);
|
||||
static void manager_set_wireless_enabled (NMManager *manager, gboolean enabled);
|
||||
|
||||
static void connection_added_default_handler (NMManager *manager,
|
||||
NMConnection *connection,
|
||||
|
|
@ -95,10 +94,6 @@ static void udev_device_removed_cb (NMUdevManager *udev_mgr,
|
|||
GUdevDevice *device,
|
||||
gpointer user_data);
|
||||
|
||||
static void udev_manager_rfkill_changed_cb (NMUdevManager *udev_mgr,
|
||||
RfKillState state,
|
||||
gpointer user_data);
|
||||
|
||||
static void bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr,
|
||||
const char *bdaddr,
|
||||
const char *name,
|
||||
|
|
@ -1256,6 +1251,80 @@ next:
|
|||
g_slist_free (connections);
|
||||
}
|
||||
|
||||
static RfKillState
|
||||
nm_manager_get_ipw_rfkill_state (NMManager *self)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
GSList *iter;
|
||||
RfKillState ipw_state = RFKILL_UNBLOCKED;
|
||||
|
||||
for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
|
||||
NMDevice *candidate = NM_DEVICE (iter->data);
|
||||
RfKillState candidate_state;
|
||||
|
||||
if (NM_IS_DEVICE_WIFI (candidate)) {
|
||||
candidate_state = nm_device_wifi_get_ipw_rfkill_state (NM_DEVICE_WIFI (candidate));
|
||||
|
||||
if (candidate_state > ipw_state)
|
||||
ipw_state = candidate_state;
|
||||
}
|
||||
}
|
||||
|
||||
return ipw_state;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_manager_rfkill_update (NMManager *self)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
RfKillState udev_state, ipw_state, composite;
|
||||
gboolean new_we = TRUE, new_whe = TRUE;
|
||||
|
||||
udev_state = nm_udev_manager_get_rfkill_state (priv->udev_mgr);
|
||||
ipw_state = nm_manager_get_ipw_rfkill_state (self);
|
||||
|
||||
/* The composite state is the "worst" of either udev or ipw states */
|
||||
if (udev_state == RFKILL_HARD_BLOCKED || ipw_state == RFKILL_HARD_BLOCKED)
|
||||
composite = RFKILL_HARD_BLOCKED;
|
||||
else if (udev_state == RFKILL_SOFT_BLOCKED || ipw_state == RFKILL_SOFT_BLOCKED)
|
||||
composite = RFKILL_SOFT_BLOCKED;
|
||||
else
|
||||
composite = RFKILL_UNBLOCKED;
|
||||
|
||||
switch (composite) {
|
||||
case RFKILL_UNBLOCKED:
|
||||
new_we = TRUE;
|
||||
new_whe = TRUE;
|
||||
break;
|
||||
case RFKILL_SOFT_BLOCKED:
|
||||
new_we = FALSE;
|
||||
new_whe = TRUE;
|
||||
break;
|
||||
case RFKILL_HARD_BLOCKED:
|
||||
new_we = FALSE;
|
||||
new_whe = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
nm_info ("Wireless now %s by radio killswitch",
|
||||
(new_we && new_whe) ? "enabled" : "disabled");
|
||||
if (new_whe != priv->wireless_hw_enabled) {
|
||||
priv->wireless_hw_enabled = new_whe;
|
||||
g_object_notify (G_OBJECT (self), NM_MANAGER_WIRELESS_HARDWARE_ENABLED);
|
||||
}
|
||||
manager_set_wireless_enabled (self, new_we);
|
||||
}
|
||||
|
||||
static void
|
||||
manager_ipw_rfkill_state_changed (NMDeviceWifi *device,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
nm_manager_rfkill_update (NM_MANAGER (user_data));
|
||||
}
|
||||
|
||||
static void
|
||||
add_device (NMManager *self, NMDevice *device)
|
||||
{
|
||||
|
|
@ -1283,15 +1352,25 @@ add_device (NMManager *self, NMDevice *device)
|
|||
G_CALLBACK (manager_device_state_changed),
|
||||
self);
|
||||
|
||||
/* Attach to the access-point-added signal so that the manager can fill
|
||||
* non-SSID-broadcasting APs with an SSID.
|
||||
*/
|
||||
if (NM_IS_DEVICE_WIFI (device)) {
|
||||
/* Attach to the access-point-added signal so that the manager can fill
|
||||
* non-SSID-broadcasting APs with an SSID.
|
||||
*/
|
||||
g_signal_connect (device, "hidden-ap-found",
|
||||
G_CALLBACK (manager_hidden_ap_found),
|
||||
self);
|
||||
|
||||
/* Set initial rfkill state */
|
||||
/* Hook up rfkill handling for ipw-based cards until they get converted
|
||||
* to use the kernel's rfkill subsystem in 2.6.33.
|
||||
*/
|
||||
g_signal_connect (device, "notify::" NM_DEVICE_WIFI_IPW_RFKILL_STATE,
|
||||
G_CALLBACK (manager_ipw_rfkill_state_changed),
|
||||
self);
|
||||
|
||||
/* Update global rfkill state with this device's rfkill state, and
|
||||
* then set this device's rfkill state based on the global state.
|
||||
*/
|
||||
nm_manager_rfkill_update (self);
|
||||
nm_device_wifi_set_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled);
|
||||
}
|
||||
|
||||
|
|
@ -1613,37 +1692,10 @@ udev_device_removed_cb (NMUdevManager *manager,
|
|||
|
||||
static void
|
||||
udev_manager_rfkill_changed_cb (NMUdevManager *udev_mgr,
|
||||
RfKillState state,
|
||||
RfKillState udev_state,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMManager *self = NM_MANAGER (user_data);
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
gboolean new_we = TRUE, new_whe = TRUE;
|
||||
|
||||
switch (state) {
|
||||
case RFKILL_UNBLOCKED:
|
||||
new_we = TRUE;
|
||||
new_whe = TRUE;
|
||||
break;
|
||||
case RFKILL_SOFT_BLOCKED:
|
||||
new_we = FALSE;
|
||||
new_whe = TRUE;
|
||||
break;
|
||||
case RFKILL_HARD_BLOCKED:
|
||||
new_we = FALSE;
|
||||
new_whe = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
nm_info ("Wireless now %s by radio killswitch",
|
||||
(new_we && new_whe) ? "enabled" : "disabled");
|
||||
if (new_whe != priv->wireless_hw_enabled) {
|
||||
priv->wireless_hw_enabled = new_whe;
|
||||
g_object_notify (G_OBJECT (self), NM_MANAGER_WIRELESS_HARDWARE_ENABLED);
|
||||
}
|
||||
manager_set_wireless_enabled (self, new_we);
|
||||
nm_manager_rfkill_update (NM_MANAGER (user_data));
|
||||
}
|
||||
|
||||
GSList *
|
||||
|
|
@ -2496,6 +2548,11 @@ impl_manager_sleep (NMManager *self, gboolean sleep, GError **error)
|
|||
|
||||
unmanaged_specs = nm_sysconfig_settings_get_unmanaged_specs (priv->sys_settings);
|
||||
|
||||
/* Ensure rfkill state is up-to-date since we don't respond to state
|
||||
* changes during sleep.
|
||||
*/
|
||||
nm_manager_rfkill_update (self);
|
||||
|
||||
/* Re-manage managed devices */
|
||||
for (iter = priv->devices; iter; iter = iter->next) {
|
||||
NMDevice *device = NM_DEVICE (iter->data);
|
||||
|
|
|
|||
32
src/nm-rfkill.h
Normal file
32
src/nm-rfkill.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2007 - 2008 Novell, Inc.
|
||||
* Copyright (C) 2007 - 2008 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef NM_RFKILL_H
|
||||
#define NM_RFKILL_H
|
||||
|
||||
typedef enum {
|
||||
RFKILL_UNBLOCKED = 0,
|
||||
RFKILL_SOFT_BLOCKED = 1,
|
||||
RFKILL_HARD_BLOCKED = 2
|
||||
} RfKillState;
|
||||
|
||||
#endif /* NM_RFKILL_H */
|
||||
|
||||
|
|
@ -28,11 +28,7 @@
|
|||
#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
typedef enum {
|
||||
RFKILL_UNBLOCKED = 0,
|
||||
RFKILL_SOFT_BLOCKED = 1,
|
||||
RFKILL_HARD_BLOCKED = 2
|
||||
} RfKillState;
|
||||
#include "nm-rfkill.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue