|
Packit Service |
87a54e |
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
Packit |
5756e2 |
/*
|
|
Packit |
5756e2 |
* Copyright (C) 2009 - 2013 Red Hat, Inc.
|
|
Packit |
5756e2 |
*/
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#include "nm-default.h"
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#include "nm-rfkill-manager.h"
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#include <libudev.h>
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
#include "nm-udev-aux/nm-udev-utils.h"
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
/*****************************************************************************/
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
enum {
|
|
Packit Service |
a1bd4f |
RFKILL_CHANGED,
|
|
Packit Service |
a1bd4f |
LAST_SIGNAL,
|
|
Packit |
5756e2 |
};
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
static guint signals[LAST_SIGNAL] = {0};
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
typedef struct {
|
|
Packit Service |
a1bd4f |
NMUdevClient *udev_client;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
/* Authoritative rfkill state (RFKILL_* enum) */
|
|
Packit Service |
a1bd4f |
RfKillState rfkill_states[RFKILL_TYPE_MAX];
|
|
Packit Service |
a1bd4f |
GSList * killswitches;
|
|
Packit |
5756e2 |
} NMRfkillManagerPrivate;
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
struct _NMRfkillManager {
|
|
Packit Service |
a1bd4f |
GObject parent;
|
|
Packit Service |
a1bd4f |
NMRfkillManagerPrivate _priv;
|
|
Packit |
5756e2 |
};
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
struct _NMRfkillManagerClass {
|
|
Packit Service |
a1bd4f |
GObjectClass parent;
|
|
Packit |
5756e2 |
};
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
G_DEFINE_TYPE(NMRfkillManager, nm_rfkill_manager, G_TYPE_OBJECT)
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
#define NM_RFKILL_MANAGER_GET_PRIVATE(self) \
|
|
Packit Service |
a1bd4f |
_NM_GET_PRIVATE(self, NMRfkillManager, NM_IS_RFKILL_MANAGER)
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
/*****************************************************************************/
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
typedef struct {
|
|
Packit Service |
a1bd4f |
char * name;
|
|
Packit Service |
a1bd4f |
guint64 seqnum;
|
|
Packit Service |
a1bd4f |
char * path;
|
|
Packit Service |
a1bd4f |
char * driver;
|
|
Packit Service |
a1bd4f |
RfKillType rtype;
|
|
Packit Service |
a1bd4f |
int state;
|
|
Packit Service |
a1bd4f |
gboolean platform;
|
|
Packit |
5756e2 |
} Killswitch;
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
RfKillState
|
|
Packit Service |
a1bd4f |
nm_rfkill_manager_get_rfkill_state(NMRfkillManager *self, RfKillType rtype)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
g_return_val_if_fail(self != NULL, RFKILL_UNBLOCKED);
|
|
Packit Service |
a1bd4f |
g_return_val_if_fail(rtype < RFKILL_TYPE_MAX, RFKILL_UNBLOCKED);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
return NM_RFKILL_MANAGER_GET_PRIVATE(self)->rfkill_states[rtype];
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static const char *
|
|
Packit Service |
a1bd4f |
rfkill_type_to_desc(RfKillType rtype)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
if (rtype == 0)
|
|
Packit Service |
a1bd4f |
return "Wi-Fi";
|
|
Packit Service |
a1bd4f |
else if (rtype == 1)
|
|
Packit Service |
a1bd4f |
return "WWAN";
|
|
Packit Service |
a1bd4f |
else if (rtype == 2)
|
|
Packit Service |
a1bd4f |
return "WiMAX";
|
|
Packit Service |
a1bd4f |
return "unknown";
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static const char *
|
|
Packit Service |
a1bd4f |
rfkill_state_to_desc(RfKillState rstate)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
if (rstate == 0)
|
|
Packit Service |
a1bd4f |
return "unblocked";
|
|
Packit Service |
a1bd4f |
else if (rstate == 1)
|
|
Packit Service |
a1bd4f |
return "soft-blocked";
|
|
Packit Service |
a1bd4f |
else if (rstate == 2)
|
|
Packit Service |
a1bd4f |
return "hard-blocked";
|
|
Packit Service |
a1bd4f |
return "unknown";
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static Killswitch *
|
|
Packit Service |
a1bd4f |
killswitch_new(struct udev_device *device, RfKillType rtype)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
Killswitch * ks;
|
|
Packit Service |
a1bd4f |
struct udev_device *parent = NULL, *grandparent = NULL;
|
|
Packit Service |
a1bd4f |
const char * driver, *subsys, *parent_subsys = NULL;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
ks = g_malloc0(sizeof(Killswitch));
|
|
Packit Service |
a1bd4f |
ks->name = g_strdup(udev_device_get_sysname(device));
|
|
Packit Service |
a1bd4f |
ks->seqnum = udev_device_get_seqnum(device);
|
|
Packit Service |
a1bd4f |
ks->path = g_strdup(udev_device_get_syspath(device));
|
|
Packit Service |
a1bd4f |
ks->rtype = rtype;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
driver = udev_device_get_property_value(device, "DRIVER");
|
|
Packit Service |
a1bd4f |
subsys = udev_device_get_subsystem(device);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* Check parent for various attributes */
|
|
Packit Service |
a1bd4f |
parent = udev_device_get_parent(device);
|
|
Packit Service |
a1bd4f |
if (parent) {
|
|
Packit Service |
a1bd4f |
parent_subsys = udev_device_get_subsystem(parent);
|
|
Packit Service |
a1bd4f |
if (!driver)
|
|
Packit Service |
a1bd4f |
driver = udev_device_get_property_value(parent, "DRIVER");
|
|
Packit Service |
a1bd4f |
if (!driver) {
|
|
Packit Service |
a1bd4f |
/* Sigh; try the grandparent */
|
|
Packit Service |
a1bd4f |
grandparent = udev_device_get_parent(parent);
|
|
Packit Service |
a1bd4f |
if (grandparent)
|
|
Packit Service |
a1bd4f |
driver = udev_device_get_property_value(grandparent, "DRIVER");
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!driver)
|
|
Packit Service |
a1bd4f |
driver = "(unknown)";
|
|
Packit Service |
a1bd4f |
ks->driver = g_strdup(driver);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (g_strcmp0(subsys, "platform") == 0 || g_strcmp0(parent_subsys, "platform") == 0
|
|
Packit Service |
a1bd4f |
|| g_strcmp0(subsys, "acpi") == 0 || g_strcmp0(parent_subsys, "acpi") == 0)
|
|
Packit Service |
a1bd4f |
ks->platform = TRUE;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
return ks;
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
killswitch_destroy(Killswitch *ks)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
g_return_if_fail(ks != NULL);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
g_free(ks->name);
|
|
Packit Service |
a1bd4f |
g_free(ks->path);
|
|
Packit Service |
a1bd4f |
g_free(ks->driver);
|
|
Packit Service |
a1bd4f |
memset(ks, 0, sizeof(Killswitch));
|
|
Packit Service |
a1bd4f |
g_free(ks);
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static RfKillState
|
|
Packit Service |
a1bd4f |
sysfs_state_to_nm_state(int sysfs_state)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
switch (sysfs_state) {
|
|
Packit Service |
a1bd4f |
case 0:
|
|
Packit Service |
a1bd4f |
return RFKILL_SOFT_BLOCKED;
|
|
Packit Service |
a1bd4f |
case 1:
|
|
Packit Service |
a1bd4f |
return RFKILL_UNBLOCKED;
|
|
Packit Service |
a1bd4f |
case 2:
|
|
Packit Service |
a1bd4f |
return RFKILL_HARD_BLOCKED;
|
|
Packit Service |
a1bd4f |
default:
|
|
Packit Service |
a1bd4f |
nm_log_warn(LOGD_RFKILL, "unhandled rfkill state %d", sysfs_state);
|
|
Packit Service |
a1bd4f |
break;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
return RFKILL_UNBLOCKED;
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
recheck_killswitches(NMRfkillManager *self)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
|
Packit Service |
a1bd4f |
GSList * iter;
|
|
Packit Service |
a1bd4f |
RfKillState poll_states[RFKILL_TYPE_MAX];
|
|
Packit Service |
a1bd4f |
RfKillState platform_states[RFKILL_TYPE_MAX];
|
|
Packit Service |
a1bd4f |
gboolean platform_checked[RFKILL_TYPE_MAX];
|
|
Packit Service |
a1bd4f |
int i;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* Default state is unblocked */
|
|
Packit Service |
a1bd4f |
for (i = 0; i < RFKILL_TYPE_MAX; i++) {
|
|
Packit Service |
a1bd4f |
poll_states[i] = RFKILL_UNBLOCKED;
|
|
Packit Service |
a1bd4f |
platform_states[i] = RFKILL_UNBLOCKED;
|
|
Packit Service |
a1bd4f |
platform_checked[i] = FALSE;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* Poll the states of all killswitches */
|
|
Packit Service |
a1bd4f |
for (iter = priv->killswitches; iter; iter = g_slist_next(iter)) {
|
|
Packit Service |
a1bd4f |
Killswitch * ks = iter->data;
|
|
Packit Service |
a1bd4f |
struct udev_device *device;
|
|
Packit Service |
a1bd4f |
RfKillState dev_state;
|
|
Packit Service |
a1bd4f |
int sysfs_state;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
device = udev_device_new_from_subsystem_sysname(nm_udev_client_get_udev(priv->udev_client),
|
|
Packit Service |
a1bd4f |
"rfkill",
|
|
Packit Service |
a1bd4f |
ks->name);
|
|
Packit Service |
a1bd4f |
if (!device)
|
|
Packit Service |
a1bd4f |
continue;
|
|
Packit Service |
a1bd4f |
sysfs_state =
|
|
Packit Service |
a1bd4f |
_nm_utils_ascii_str_to_int64(udev_device_get_property_value(device, "RFKILL_STATE"),
|
|
Packit Service |
a1bd4f |
10,
|
|
Packit Service |
a1bd4f |
G_MININT,
|
|
Packit Service |
a1bd4f |
G_MAXINT,
|
|
Packit Service |
a1bd4f |
-1);
|
|
Packit Service |
a1bd4f |
dev_state = sysfs_state_to_nm_state(sysfs_state);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
nm_log_dbg(LOGD_RFKILL,
|
|
Packit Service |
a1bd4f |
"%s rfkill%s switch %s state now %d/%u",
|
|
Packit Service |
a1bd4f |
rfkill_type_to_desc(ks->rtype),
|
|
Packit Service |
a1bd4f |
ks->platform ? " platform" : "",
|
|
Packit Service |
a1bd4f |
ks->name,
|
|
Packit Service |
a1bd4f |
sysfs_state,
|
|
Packit Service |
a1bd4f |
dev_state);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (ks->platform == FALSE) {
|
|
Packit Service |
a1bd4f |
if (dev_state > poll_states[ks->rtype])
|
|
Packit Service |
a1bd4f |
poll_states[ks->rtype] = dev_state;
|
|
Packit Service |
a1bd4f |
} else {
|
|
Packit Service |
a1bd4f |
platform_checked[ks->rtype] = TRUE;
|
|
Packit Service |
a1bd4f |
if (dev_state > platform_states[ks->rtype])
|
|
Packit Service |
a1bd4f |
platform_states[ks->rtype] = dev_state;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
udev_device_unref(device);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
/* Log and emit change signal for final rfkill states */
|
|
Packit Service |
a1bd4f |
for (i = 0; i < RFKILL_TYPE_MAX; i++) {
|
|
Packit Service |
a1bd4f |
if (platform_checked[i] == TRUE) {
|
|
Packit Service |
a1bd4f |
/* blocked platform switch state overrides device state, otherwise
|
|
Packit Service |
a1bd4f |
* let the device state stand. (bgo #655773)
|
|
Packit Service |
a1bd4f |
*/
|
|
Packit Service |
a1bd4f |
if (platform_states[i] != RFKILL_UNBLOCKED)
|
|
Packit Service |
a1bd4f |
poll_states[i] = platform_states[i];
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (poll_states[i] != priv->rfkill_states[i]) {
|
|
Packit Service |
a1bd4f |
nm_log_dbg(LOGD_RFKILL,
|
|
Packit Service |
a1bd4f |
"%s rfkill state now '%s'",
|
|
Packit Service |
a1bd4f |
rfkill_type_to_desc(i),
|
|
Packit Service |
a1bd4f |
rfkill_state_to_desc(poll_states[i]));
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
priv->rfkill_states[i] = poll_states[i];
|
|
Packit Service |
a1bd4f |
g_signal_emit(self, signals[RFKILL_CHANGED], 0, i, priv->rfkill_states[i]);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
}
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static Killswitch *
|
|
Packit Service |
a1bd4f |
killswitch_find_by_name(NMRfkillManager *self, const char *name)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
|
Packit Service |
a1bd4f |
GSList * iter;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
g_return_val_if_fail(name != NULL, NULL);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
for (iter = priv->killswitches; iter; iter = g_slist_next(iter)) {
|
|
Packit Service |
a1bd4f |
Killswitch *candidate = iter->data;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (!strcmp(name, candidate->name))
|
|
Packit Service |
a1bd4f |
return candidate;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
return NULL;
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static RfKillType
|
|
Packit Service |
a1bd4f |
rfkill_type_to_enum(const char *str)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
g_return_val_if_fail(str != NULL, RFKILL_TYPE_UNKNOWN);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (!strcmp(str, "wlan"))
|
|
Packit Service |
a1bd4f |
return RFKILL_TYPE_WLAN;
|
|
Packit Service |
a1bd4f |
else if (!strcmp(str, "wwan"))
|
|
Packit Service |
a1bd4f |
return RFKILL_TYPE_WWAN;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
return RFKILL_TYPE_UNKNOWN;
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
add_one_killswitch(NMRfkillManager *self, struct udev_device *device)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
|
Packit Service |
a1bd4f |
const char * str_type;
|
|
Packit Service |
a1bd4f |
RfKillType rtype;
|
|
Packit Service |
a1bd4f |
Killswitch * ks;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
str_type = udev_device_get_property_value(device, "RFKILL_TYPE");
|
|
Packit Service |
a1bd4f |
rtype = rfkill_type_to_enum(str_type);
|
|
Packit Service |
a1bd4f |
if (rtype == RFKILL_TYPE_UNKNOWN)
|
|
Packit Service |
a1bd4f |
return;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
ks = killswitch_new(device, rtype);
|
|
Packit Service |
a1bd4f |
priv->killswitches = g_slist_prepend(priv->killswitches, ks);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
nm_log_info(LOGD_RFKILL,
|
|
Packit Service |
a1bd4f |
"%s: found %s radio killswitch (at %s) (%sdriver %s)",
|
|
Packit Service |
a1bd4f |
ks->name,
|
|
Packit Service |
a1bd4f |
rfkill_type_to_desc(rtype),
|
|
Packit Service |
a1bd4f |
ks->path,
|
|
Packit Service |
a1bd4f |
ks->platform ? "platform " : "",
|
|
Packit Service |
a1bd4f |
ks->driver ?: "<unknown>");
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
rfkill_add(NMRfkillManager *self, struct udev_device *device)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
const char *name;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
g_return_if_fail(device != NULL);
|
|
Packit Service |
a1bd4f |
name = udev_device_get_sysname(device);
|
|
Packit Service |
a1bd4f |
g_return_if_fail(name != NULL);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (!killswitch_find_by_name(self, name))
|
|
Packit Service |
a1bd4f |
add_one_killswitch(self, device);
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
rfkill_remove(NMRfkillManager *self, struct udev_device *device)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
|
Packit Service |
a1bd4f |
GSList * iter;
|
|
Packit Service |
a1bd4f |
const char * name;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
g_return_if_fail(device != NULL);
|
|
Packit Service |
a1bd4f |
name = udev_device_get_sysname(device);
|
|
Packit Service |
a1bd4f |
g_return_if_fail(name != NULL);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
for (iter = priv->killswitches; iter; iter = g_slist_next(iter)) {
|
|
Packit Service |
a1bd4f |
Killswitch *ks = iter->data;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
if (!strcmp(ks->name, name)) {
|
|
Packit Service |
a1bd4f |
nm_log_info(LOGD_RFKILL, "radio killswitch %s disappeared", ks->path);
|
|
Packit Service |
a1bd4f |
priv->killswitches = g_slist_remove(priv->killswitches, ks);
|
|
Packit Service |
a1bd4f |
killswitch_destroy(ks);
|
|
Packit Service |
a1bd4f |
break;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
}
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
handle_uevent(NMUdevClient *client, struct udev_device *device, gpointer user_data)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
NMRfkillManager *self = NM_RFKILL_MANAGER(user_data);
|
|
Packit Service |
a1bd4f |
const char * subsys;
|
|
Packit Service |
a1bd4f |
const char * action;
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
action = udev_device_get_action(device);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
g_return_if_fail(action != NULL);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
/* A bit paranoid */
|
|
Packit Service |
a1bd4f |
subsys = udev_device_get_subsystem(device);
|
|
Packit Service |
a1bd4f |
g_return_if_fail(!g_strcmp0(subsys, "rfkill"));
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
nm_log_dbg(LOGD_PLATFORM,
|
|
Packit Service |
a1bd4f |
"udev rfkill event: action '%s' device '%s'",
|
|
Packit Service |
a1bd4f |
action,
|
|
Packit Service |
a1bd4f |
udev_device_get_sysname(device));
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (!strcmp(action, "add"))
|
|
Packit Service |
a1bd4f |
rfkill_add(self, device);
|
|
Packit Service |
a1bd4f |
else if (!strcmp(action, "remove"))
|
|
Packit Service |
a1bd4f |
rfkill_remove(self, device);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
recheck_killswitches(self);
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
/*****************************************************************************/
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
nm_rfkill_manager_init(NMRfkillManager *self)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
|
Packit Service |
a1bd4f |
struct udev_enumerate * enumerate;
|
|
Packit Service |
a1bd4f |
struct udev_list_entry *iter;
|
|
Packit Service |
a1bd4f |
guint i;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
for (i = 0; i < RFKILL_TYPE_MAX; i++)
|
|
Packit Service |
a1bd4f |
priv->rfkill_states[i] = RFKILL_UNBLOCKED;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
priv->udev_client = nm_udev_client_new((const char *[]){"rfkill", NULL}, handle_uevent, self);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
enumerate = nm_udev_client_enumerate_new(priv->udev_client);
|
|
Packit Service |
a1bd4f |
udev_enumerate_scan_devices(enumerate);
|
|
Packit Service |
a1bd4f |
iter = udev_enumerate_get_list_entry(enumerate);
|
|
Packit Service |
a1bd4f |
for (; iter; iter = udev_list_entry_get_next(iter)) {
|
|
Packit Service |
a1bd4f |
struct udev_device *udevice;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
udevice = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
|
|
Packit Service |
a1bd4f |
udev_list_entry_get_name(iter));
|
|
Packit Service |
a1bd4f |
if (!udevice)
|
|
Packit Service |
a1bd4f |
continue;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
add_one_killswitch(self, udevice);
|
|
Packit Service |
a1bd4f |
udev_device_unref(udevice);
|
|
Packit Service |
a1bd4f |
}
|
|
Packit Service |
a1bd4f |
udev_enumerate_unref(enumerate);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
recheck_killswitches(self);
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
NMRfkillManager *
|
|
Packit Service |
a1bd4f |
nm_rfkill_manager_new(void)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
return NM_RFKILL_MANAGER(g_object_new(NM_TYPE_RFKILL_MANAGER, NULL));
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
dispose(GObject *object)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
NMRfkillManager * self = NM_RFKILL_MANAGER(object);
|
|
Packit Service |
a1bd4f |
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
if (priv->killswitches) {
|
|
Packit Service |
a1bd4f |
g_slist_free_full(priv->killswitches, (GDestroyNotify) killswitch_destroy);
|
|
Packit Service |
a1bd4f |
priv->killswitches = NULL;
|
|
Packit Service |
a1bd4f |
}
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
priv->udev_client = nm_udev_client_unref(priv->udev_client);
|
|
Packit |
5756e2 |
|
|
Packit Service |
a1bd4f |
G_OBJECT_CLASS(nm_rfkill_manager_parent_class)->dispose(object);
|
|
Packit |
5756e2 |
}
|
|
Packit |
5756e2 |
|
|
Packit |
5756e2 |
static void
|
|
Packit Service |
a1bd4f |
nm_rfkill_manager_class_init(NMRfkillManagerClass *klass)
|
|
Packit |
5756e2 |
{
|
|
Packit Service |
a1bd4f |
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
object_class->dispose = dispose;
|
|
Packit Service |
a1bd4f |
|
|
Packit Service |
a1bd4f |
signals[RFKILL_CHANGED] = g_signal_new(NM_RFKILL_MANAGER_SIGNAL_RFKILL_CHANGED,
|
|
Packit Service |
a1bd4f |
G_OBJECT_CLASS_TYPE(object_class),
|
|
Packit Service |
a1bd4f |
G_SIGNAL_RUN_FIRST,
|
|
Packit Service |
a1bd4f |
0,
|
|
Packit Service |
a1bd4f |
NULL,
|
|
Packit Service |
a1bd4f |
NULL,
|
|
Packit Service |
a1bd4f |
NULL,
|
|
Packit Service |
a1bd4f |
G_TYPE_NONE,
|
|
Packit Service |
a1bd4f |
2,
|
|
Packit Service |
a1bd4f |
G_TYPE_UINT,
|
|
Packit Service |
a1bd4f |
G_TYPE_UINT);
|
|
Packit |
5756e2 |
}
|