2020-12-23 22:21:36 +01:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
2019-09-25 13:13:40 +02:00
|
|
|
/*
|
2013-05-09 10:24:08 -04:00
|
|
|
* Copyright (C) 2009 - 2013 Red Hat, Inc.
|
|
|
|
|
*/
|
|
|
|
|
|
2021-02-04 18:04:13 +01:00
|
|
|
#include "src/core/nm-default-daemon.h"
|
2013-05-09 10:24:08 -04:00
|
|
|
|
2016-09-29 13:49:01 +02:00
|
|
|
#include "nm-rfkill-manager.h"
|
|
|
|
|
|
2017-03-12 15:54:02 +01:00
|
|
|
#include <libudev.h>
|
|
|
|
|
|
2022-02-01 22:55:15 +01:00
|
|
|
#include "c-list/src/c-list.h"
|
2021-02-18 08:13:35 +01:00
|
|
|
#include "libnm-udev-aux/nm-udev-utils.h"
|
2013-05-09 10:24:08 -04:00
|
|
|
|
2016-09-29 13:49:01 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
RFKILL_CHANGED,
|
|
|
|
|
LAST_SIGNAL,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static guint signals[LAST_SIGNAL] = {0};
|
2013-05-09 10:24:08 -04:00
|
|
|
|
|
|
|
|
typedef struct {
|
2017-03-12 15:54:02 +01:00
|
|
|
NMUdevClient *udev_client;
|
2013-05-09 10:24:08 -04:00
|
|
|
|
|
|
|
|
/* Authoritative rfkill state (RFKILL_* enum) */
|
2022-02-01 20:21:34 +01:00
|
|
|
NMRfkillState rfkill_states[NM_RFKILL_TYPE_MAX];
|
2022-02-01 22:55:15 +01:00
|
|
|
|
|
|
|
|
CList killswitch_lst_head;
|
2013-05-09 10:24:08 -04:00
|
|
|
} NMRfkillManagerPrivate;
|
|
|
|
|
|
2016-09-29 13:49:01 +02:00
|
|
|
struct _NMRfkillManager {
|
|
|
|
|
GObject parent;
|
|
|
|
|
NMRfkillManagerPrivate _priv;
|
|
|
|
|
};
|
2013-05-09 10:24:08 -04:00
|
|
|
|
2016-09-29 13:49:01 +02:00
|
|
|
struct _NMRfkillManagerClass {
|
|
|
|
|
GObjectClass parent;
|
2013-05-09 10:24:08 -04:00
|
|
|
};
|
|
|
|
|
|
2016-09-29 13:49:01 +02:00
|
|
|
G_DEFINE_TYPE(NMRfkillManager, nm_rfkill_manager, G_TYPE_OBJECT)
|
|
|
|
|
|
|
|
|
|
#define NM_RFKILL_MANAGER_GET_PRIVATE(self) \
|
|
|
|
|
_NM_GET_PRIVATE(self, NMRfkillManager, NM_IS_RFKILL_MANAGER)
|
2013-05-09 10:24:08 -04:00
|
|
|
|
2016-09-29 13:49:01 +02:00
|
|
|
/*****************************************************************************/
|
2013-05-09 10:24:08 -04:00
|
|
|
|
|
|
|
|
typedef struct {
|
2022-02-01 22:55:15 +01:00
|
|
|
CList killswitch_lst;
|
2022-02-01 20:21:34 +01:00
|
|
|
char *name;
|
|
|
|
|
char *path;
|
|
|
|
|
char *driver;
|
2022-02-01 22:46:27 +01:00
|
|
|
guint64 seqnum;
|
2022-02-01 20:21:34 +01:00
|
|
|
NMRfkillType rtype;
|
|
|
|
|
int state;
|
2022-02-01 22:46:27 +01:00
|
|
|
bool platform : 1;
|
2013-05-09 10:24:08 -04:00
|
|
|
} Killswitch;
|
|
|
|
|
|
2022-02-01 20:21:34 +01:00
|
|
|
NMRfkillState
|
|
|
|
|
nm_rfkill_manager_get_rfkill_state(NMRfkillManager *self, NMRfkillType rtype)
|
2013-05-09 10:24:08 -04:00
|
|
|
{
|
2022-02-01 20:21:34 +01:00
|
|
|
g_return_val_if_fail(self != NULL, NM_RFKILL_STATE_UNBLOCKED);
|
|
|
|
|
g_return_val_if_fail(rtype < NM_RFKILL_TYPE_MAX, NM_RFKILL_STATE_UNBLOCKED);
|
2013-05-09 10:24:08 -04:00
|
|
|
|
|
|
|
|
return NM_RFKILL_MANAGER_GET_PRIVATE(self)->rfkill_states[rtype];
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-01 22:32:46 +01:00
|
|
|
const char *
|
|
|
|
|
nm_rfkill_type_to_string(NMRfkillType type)
|
2013-05-09 10:24:08 -04:00
|
|
|
{
|
2022-02-01 22:32:46 +01:00
|
|
|
switch (type) {
|
|
|
|
|
case NM_RFKILL_TYPE_WLAN:
|
2018-11-21 11:32:38 +01:00
|
|
|
return "Wi-Fi";
|
2022-02-01 22:32:46 +01:00
|
|
|
case NM_RFKILL_TYPE_WWAN:
|
2013-05-09 10:24:08 -04:00
|
|
|
return "WWAN";
|
2022-02-01 22:32:46 +01:00
|
|
|
case NM_RFKILL_TYPE_UNKNOWN:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return nm_assert_unreachable_val("unknown");
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
2022-02-01 22:38:26 +01:00
|
|
|
nm_rfkill_state_to_string(NMRfkillState state)
|
2013-05-09 10:24:08 -04:00
|
|
|
{
|
2022-02-01 22:38:26 +01:00
|
|
|
switch (state) {
|
|
|
|
|
case NM_RFKILL_STATE_UNBLOCKED:
|
2013-05-09 10:24:08 -04:00
|
|
|
return "unblocked";
|
2022-02-01 22:38:26 +01:00
|
|
|
case NM_RFKILL_STATE_SOFT_BLOCKED:
|
2013-05-09 10:24:08 -04:00
|
|
|
return "soft-blocked";
|
2022-02-01 22:38:26 +01:00
|
|
|
case NM_RFKILL_STATE_HARD_BLOCKED:
|
2013-05-09 10:24:08 -04:00
|
|
|
return "hard-blocked";
|
2022-02-01 22:38:26 +01:00
|
|
|
}
|
|
|
|
|
return nm_assert_unreachable_val("unknown");
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Killswitch *
|
2022-02-01 20:21:34 +01:00
|
|
|
killswitch_new(struct udev_device *device, NMRfkillType rtype)
|
2013-05-09 10:24:08 -04:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
Killswitch *ks;
|
2022-02-01 22:46:27 +01:00
|
|
|
struct udev_device *parent = NULL;
|
|
|
|
|
struct udev_device *grandparent = NULL;
|
|
|
|
|
const char *driver;
|
|
|
|
|
const char *subsys;
|
|
|
|
|
const char *parent_subsys = NULL;
|
|
|
|
|
gboolean platform;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-12 15:54:02 +01:00
|
|
|
driver = udev_device_get_property_value(device, "DRIVER");
|
|
|
|
|
subsys = udev_device_get_subsystem(device);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
/* Check parent for various attributes */
|
2017-03-12 15:54:02 +01:00
|
|
|
parent = udev_device_get_parent(device);
|
2013-05-09 10:24:08 -04:00
|
|
|
if (parent) {
|
2017-03-12 15:54:02 +01:00
|
|
|
parent_subsys = udev_device_get_subsystem(parent);
|
2013-05-09 10:24:08 -04:00
|
|
|
if (!driver)
|
2017-03-12 15:54:02 +01:00
|
|
|
driver = udev_device_get_property_value(parent, "DRIVER");
|
2013-05-09 10:24:08 -04:00
|
|
|
if (!driver) {
|
|
|
|
|
/* Sigh; try the grandparent */
|
2017-03-12 15:54:02 +01:00
|
|
|
grandparent = udev_device_get_parent(parent);
|
2013-05-09 10:24:08 -04:00
|
|
|
if (grandparent)
|
2017-03-12 15:54:02 +01:00
|
|
|
driver = udev_device_get_property_value(grandparent, "DRIVER");
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
2013-05-09 10:24:08 -04:00
|
|
|
if (!driver)
|
|
|
|
|
driver = "(unknown)";
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-01 22:46:27 +01:00
|
|
|
platform = FALSE;
|
|
|
|
|
if (nm_streq0(subsys, "platform") || nm_streq0(parent_subsys, "platform")
|
|
|
|
|
|| nm_streq0(subsys, "acpi") || nm_streq0(parent_subsys, "acpi"))
|
|
|
|
|
platform = TRUE;
|
|
|
|
|
|
|
|
|
|
ks = g_slice_new(Killswitch);
|
|
|
|
|
*ks = (Killswitch){
|
|
|
|
|
.name = g_strdup(udev_device_get_sysname(device)),
|
|
|
|
|
.seqnum = udev_device_get_seqnum(device),
|
|
|
|
|
.path = g_strdup(udev_device_get_syspath(device)),
|
|
|
|
|
.rtype = rtype,
|
|
|
|
|
.driver = g_strdup(driver),
|
|
|
|
|
.platform = platform,
|
|
|
|
|
};
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
return ks;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
killswitch_destroy(Killswitch *ks)
|
|
|
|
|
{
|
2022-02-01 22:55:15 +01:00
|
|
|
c_list_unlink_stale(&ks->killswitch_lst);
|
2013-05-09 10:24:08 -04:00
|
|
|
g_free(ks->name);
|
|
|
|
|
g_free(ks->path);
|
|
|
|
|
g_free(ks->driver);
|
2022-02-01 22:46:27 +01:00
|
|
|
nm_g_slice_free(ks);
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
|
|
|
|
|
2022-02-01 20:21:34 +01:00
|
|
|
static NMRfkillState
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
sysfs_state_to_nm_state(int sysfs_state)
|
2013-05-09 10:24:08 -04:00
|
|
|
{
|
|
|
|
|
switch (sysfs_state) {
|
|
|
|
|
case 0:
|
2022-02-01 20:21:34 +01:00
|
|
|
return NM_RFKILL_STATE_SOFT_BLOCKED;
|
2013-05-09 10:24:08 -04:00
|
|
|
case 1:
|
2022-02-01 20:21:34 +01:00
|
|
|
return NM_RFKILL_STATE_UNBLOCKED;
|
2013-05-09 10:24:08 -04:00
|
|
|
case 2:
|
2022-02-01 20:21:34 +01:00
|
|
|
return NM_RFKILL_STATE_HARD_BLOCKED;
|
2013-05-09 10:24:08 -04:00
|
|
|
default:
|
|
|
|
|
nm_log_warn(LOGD_RFKILL, "unhandled rfkill state %d", sysfs_state);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-02-01 20:21:34 +01:00
|
|
|
return NM_RFKILL_STATE_UNBLOCKED;
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
recheck_killswitches(NMRfkillManager *self)
|
|
|
|
|
{
|
|
|
|
|
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
2022-02-01 22:55:15 +01:00
|
|
|
Killswitch *ks;
|
2022-02-01 20:21:34 +01:00
|
|
|
NMRfkillState poll_states[NM_RFKILL_TYPE_MAX];
|
|
|
|
|
NMRfkillState platform_states[NM_RFKILL_TYPE_MAX];
|
|
|
|
|
gboolean platform_checked[NM_RFKILL_TYPE_MAX];
|
2013-05-09 10:24:08 -04:00
|
|
|
int i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
/* Default state is unblocked */
|
2022-02-01 20:21:34 +01:00
|
|
|
for (i = 0; i < NM_RFKILL_TYPE_MAX; i++) {
|
|
|
|
|
poll_states[i] = NM_RFKILL_STATE_UNBLOCKED;
|
|
|
|
|
platform_states[i] = NM_RFKILL_STATE_UNBLOCKED;
|
2013-05-09 10:24:08 -04:00
|
|
|
platform_checked[i] = FALSE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
/* Poll the states of all killswitches */
|
2022-02-01 22:55:15 +01:00
|
|
|
c_list_for_each_entry (ks, &priv->killswitch_lst_head, killswitch_lst) {
|
2017-03-12 15:54:02 +01:00
|
|
|
struct udev_device *device;
|
2022-02-01 20:21:34 +01:00
|
|
|
NMRfkillState dev_state;
|
2013-05-09 10:24:08 -04:00
|
|
|
int sysfs_state;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-12 15:54:02 +01:00
|
|
|
device = udev_device_new_from_subsystem_sysname(nm_udev_client_get_udev(priv->udev_client),
|
|
|
|
|
"rfkill",
|
|
|
|
|
ks->name);
|
|
|
|
|
if (!device)
|
|
|
|
|
continue;
|
|
|
|
|
sysfs_state =
|
|
|
|
|
_nm_utils_ascii_str_to_int64(udev_device_get_property_value(device, "RFKILL_STATE"),
|
|
|
|
|
10,
|
|
|
|
|
G_MININT,
|
|
|
|
|
G_MAXINT,
|
|
|
|
|
-1);
|
|
|
|
|
dev_state = sysfs_state_to_nm_state(sysfs_state);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-12 15:54:02 +01:00
|
|
|
nm_log_dbg(LOGD_RFKILL,
|
|
|
|
|
"%s rfkill%s switch %s state now %d/%u",
|
2022-02-01 22:32:46 +01:00
|
|
|
nm_rfkill_type_to_string(ks->rtype),
|
2017-03-12 15:54:02 +01:00
|
|
|
ks->platform ? " platform" : "",
|
|
|
|
|
ks->name,
|
|
|
|
|
sysfs_state,
|
|
|
|
|
dev_state);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-12 15:54:02 +01:00
|
|
|
if (ks->platform == FALSE) {
|
|
|
|
|
if (dev_state > poll_states[ks->rtype])
|
|
|
|
|
poll_states[ks->rtype] = dev_state;
|
|
|
|
|
} else {
|
|
|
|
|
platform_checked[ks->rtype] = TRUE;
|
|
|
|
|
if (dev_state > platform_states[ks->rtype])
|
|
|
|
|
platform_states[ks->rtype] = dev_state;
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
2022-02-01 22:55:15 +01:00
|
|
|
|
2017-03-12 15:54:02 +01:00
|
|
|
udev_device_unref(device);
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
/* Log and emit change signal for final rfkill states */
|
2022-02-01 20:21:34 +01:00
|
|
|
for (i = 0; i < NM_RFKILL_TYPE_MAX; i++) {
|
2013-05-09 10:24:08 -04:00
|
|
|
if (platform_checked[i] == TRUE) {
|
|
|
|
|
/* blocked platform switch state overrides device state, otherwise
|
|
|
|
|
* let the device state stand. (bgo #655773)
|
|
|
|
|
*/
|
2022-02-01 20:21:34 +01:00
|
|
|
if (platform_states[i] != NM_RFKILL_STATE_UNBLOCKED)
|
2013-05-09 10:24:08 -04:00
|
|
|
poll_states[i] = platform_states[i];
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
if (poll_states[i] != priv->rfkill_states[i]) {
|
|
|
|
|
nm_log_dbg(LOGD_RFKILL,
|
|
|
|
|
"%s rfkill state now '%s'",
|
2022-02-01 22:32:46 +01:00
|
|
|
nm_rfkill_type_to_string(i),
|
2022-02-01 22:38:26 +01:00
|
|
|
nm_rfkill_state_to_string(poll_states[i]));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
priv->rfkill_states[i] = poll_states[i];
|
2022-02-02 12:04:27 +01:00
|
|
|
g_signal_emit(self,
|
|
|
|
|
signals[RFKILL_CHANGED],
|
|
|
|
|
0,
|
|
|
|
|
(guint) i,
|
|
|
|
|
(guint) priv->rfkill_states[i]);
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Killswitch *
|
|
|
|
|
killswitch_find_by_name(NMRfkillManager *self, const char *name)
|
|
|
|
|
{
|
|
|
|
|
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
2022-02-01 22:55:15 +01:00
|
|
|
Killswitch *ks;
|
2013-05-09 10:24:08 -04:00
|
|
|
|
2022-02-01 22:55:15 +01:00
|
|
|
nm_assert(name);
|
2013-05-09 10:24:08 -04:00
|
|
|
|
2022-02-01 22:55:15 +01:00
|
|
|
c_list_for_each_entry (ks, &priv->killswitch_lst_head, killswitch_lst) {
|
|
|
|
|
if (nm_streq(name, ks->name))
|
|
|
|
|
return ks;
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-01 20:21:34 +01:00
|
|
|
static NMRfkillType
|
2013-05-09 10:24:08 -04:00
|
|
|
rfkill_type_to_enum(const char *str)
|
|
|
|
|
{
|
2022-02-01 22:41:27 +01:00
|
|
|
if (str) {
|
|
|
|
|
if (nm_streq(str, "wlan"))
|
|
|
|
|
return NM_RFKILL_TYPE_WLAN;
|
|
|
|
|
if (nm_streq(str, "wwan"))
|
|
|
|
|
return NM_RFKILL_TYPE_WWAN;
|
|
|
|
|
}
|
2013-05-09 10:24:08 -04:00
|
|
|
|
2022-02-01 20:21:34 +01:00
|
|
|
return NM_RFKILL_TYPE_UNKNOWN;
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-03-12 15:54:02 +01:00
|
|
|
add_one_killswitch(NMRfkillManager *self, struct udev_device *device)
|
2013-05-09 10:24:08 -04:00
|
|
|
{
|
|
|
|
|
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
2022-02-01 20:21:34 +01:00
|
|
|
NMRfkillType rtype;
|
2021-11-09 13:28:54 +01:00
|
|
|
Killswitch *ks;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-01 22:41:27 +01:00
|
|
|
rtype = rfkill_type_to_enum(udev_device_get_property_value(device, "RFKILL_TYPE"));
|
2022-02-01 20:21:34 +01:00
|
|
|
if (rtype == NM_RFKILL_TYPE_UNKNOWN)
|
2013-05-09 10:24:08 -04:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-01 22:55:15 +01:00
|
|
|
ks = killswitch_new(device, rtype);
|
|
|
|
|
c_list_link_front(&priv->killswitch_lst_head, &ks->killswitch_lst);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
nm_log_info(LOGD_RFKILL,
|
|
|
|
|
"%s: found %s radio killswitch (at %s) (%sdriver %s)",
|
|
|
|
|
ks->name,
|
2022-02-01 22:32:46 +01:00
|
|
|
nm_rfkill_type_to_string(rtype),
|
2013-05-09 10:24:08 -04:00
|
|
|
ks->path,
|
|
|
|
|
ks->platform ? "platform " : "",
|
2018-04-24 11:20:03 +02:00
|
|
|
ks->driver ?: "<unknown>");
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-03-12 15:54:02 +01:00
|
|
|
rfkill_add(NMRfkillManager *self, struct udev_device *device)
|
2013-05-09 10:24:08 -04:00
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail(device != NULL);
|
2017-03-12 15:54:02 +01:00
|
|
|
name = udev_device_get_sysname(device);
|
2022-02-01 23:00:58 +01:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
g_return_if_fail(name != NULL);
|
|
|
|
|
|
|
|
|
|
if (!killswitch_find_by_name(self, name))
|
|
|
|
|
add_one_killswitch(self, device);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rfkill_remove(NMRfkillManager *self, struct udev_device *device)
|
|
|
|
|
{
|
|
|
|
|
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
2022-02-01 22:55:15 +01:00
|
|
|
Killswitch *ks;
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *name;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
g_return_if_fail(device != NULL);
|
2022-02-01 22:55:15 +01:00
|
|
|
|
2017-03-12 15:54:02 +01:00
|
|
|
name = udev_device_get_sysname(device);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-01 22:55:15 +01:00
|
|
|
g_return_if_fail(name != NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-01 22:55:15 +01:00
|
|
|
c_list_for_each_entry (ks, &priv->killswitch_lst_head, killswitch_lst) {
|
|
|
|
|
if (nm_streq(ks->name, name)) {
|
2013-05-09 10:24:08 -04:00
|
|
|
nm_log_info(LOGD_RFKILL, "radio killswitch %s disappeared", ks->path);
|
|
|
|
|
killswitch_destroy(ks);
|
2022-02-01 22:55:15 +01:00
|
|
|
return;
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-03-12 15:54:02 +01:00
|
|
|
handle_uevent(NMUdevClient *client, struct udev_device *device, gpointer user_data)
|
2013-05-09 10:24:08 -04:00
|
|
|
{
|
|
|
|
|
NMRfkillManager *self = NM_RFKILL_MANAGER(user_data);
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *subsys;
|
|
|
|
|
const char *action;
|
2017-03-12 15:54:02 +01:00
|
|
|
|
|
|
|
|
action = udev_device_get_action(device);
|
2013-05-09 10:24:08 -04:00
|
|
|
|
|
|
|
|
g_return_if_fail(action != NULL);
|
|
|
|
|
|
|
|
|
|
/* A bit paranoid */
|
2017-03-12 15:54:02 +01:00
|
|
|
subsys = udev_device_get_subsystem(device);
|
2022-02-01 23:00:58 +01:00
|
|
|
g_return_if_fail(nm_streq0(subsys, "rfkill"));
|
2013-05-09 10:24:08 -04:00
|
|
|
|
2016-10-06 21:28:40 +02:00
|
|
|
nm_log_dbg(LOGD_PLATFORM,
|
|
|
|
|
"udev rfkill event: action '%s' device '%s'",
|
2017-03-12 15:54:02 +01:00
|
|
|
action,
|
|
|
|
|
udev_device_get_sysname(device));
|
2013-05-09 10:24:08 -04:00
|
|
|
|
2022-02-01 23:00:58 +01:00
|
|
|
if (nm_streq(action, "add"))
|
2013-05-09 10:24:08 -04:00
|
|
|
rfkill_add(self, device);
|
2022-02-01 23:00:58 +01:00
|
|
|
else if (nm_streq(action, "remove"))
|
2013-05-09 10:24:08 -04:00
|
|
|
rfkill_remove(self, device);
|
|
|
|
|
|
|
|
|
|
recheck_killswitches(self);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-29 13:49:01 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
static void
|
|
|
|
|
nm_rfkill_manager_init(NMRfkillManager *self)
|
|
|
|
|
{
|
|
|
|
|
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
2021-11-09 13:28:54 +01:00
|
|
|
struct udev_enumerate *enumerate;
|
2017-03-12 15:54:02 +01:00
|
|
|
struct udev_list_entry *iter;
|
|
|
|
|
guint i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-01 22:55:15 +01:00
|
|
|
c_list_init(&priv->killswitch_lst_head);
|
|
|
|
|
|
2022-02-01 20:21:34 +01:00
|
|
|
for (i = 0; i < NM_RFKILL_TYPE_MAX; i++)
|
|
|
|
|
priv->rfkill_states[i] = NM_RFKILL_STATE_UNBLOCKED;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2021-02-03 14:43:48 +01:00
|
|
|
priv->udev_client = nm_udev_client_new(NM_MAKE_STRV("rfkill"), handle_uevent, self);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-12 15:54:02 +01:00
|
|
|
enumerate = nm_udev_client_enumerate_new(priv->udev_client);
|
|
|
|
|
udev_enumerate_scan_devices(enumerate);
|
|
|
|
|
iter = udev_enumerate_get_list_entry(enumerate);
|
|
|
|
|
for (; iter; iter = udev_list_entry_get_next(iter)) {
|
|
|
|
|
struct udev_device *udevice;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-12 15:54:02 +01:00
|
|
|
udevice = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
|
|
|
|
|
udev_list_entry_get_name(iter));
|
|
|
|
|
if (!udevice)
|
|
|
|
|
continue;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-12 15:54:02 +01:00
|
|
|
add_one_killswitch(self, udevice);
|
|
|
|
|
udev_device_unref(udevice);
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
2017-03-12 15:54:02 +01:00
|
|
|
udev_enumerate_unref(enumerate);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
recheck_killswitches(self);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-29 13:49:01 +02:00
|
|
|
NMRfkillManager *
|
|
|
|
|
nm_rfkill_manager_new(void)
|
|
|
|
|
{
|
2021-02-08 16:55:35 +01:00
|
|
|
return g_object_new(NM_TYPE_RFKILL_MANAGER, NULL);
|
2016-09-29 13:49:01 +02:00
|
|
|
}
|
|
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
static void
|
|
|
|
|
dispose(GObject *object)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMRfkillManager *self = NM_RFKILL_MANAGER(object);
|
2013-05-09 10:24:08 -04:00
|
|
|
NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self);
|
2022-02-01 22:55:15 +01:00
|
|
|
Killswitch *ks;
|
2013-05-09 10:24:08 -04:00
|
|
|
|
2022-02-01 22:55:15 +01:00
|
|
|
while ((ks = c_list_first_entry(&priv->killswitch_lst_head, Killswitch, killswitch_lst)))
|
|
|
|
|
killswitch_destroy(ks);
|
2013-05-09 10:24:08 -04:00
|
|
|
|
udev/trivial: rename nm_udev_client_unref() to nm_udev_client_destory()
NMUdevClient does not actually implement ref-counting, because it's not
used. Still, the destroy function was named nm_udev_client_unref(),
because theoretically then we could later, as the need arises, make
the type ref-counted. Then unref function already had the right name.
However, NMUdevClient also has a callback function that emits monitor
events. Again for simplicity, this callback function cannot be reset, it
can only be set once (in the constructor) and can also not be unset nor
disabled.
When the user of NMUdevClient is done with the instance and calls
"unref", then it must be sure that the callback is no longer invoked
afterwards. In practice that is already the case, but "unref" makes it
sound as if somebody else could also still hold a reference -- in which
case the user would have to first unset/disable the callback.
Rename the function to "destroy()", so that it's clear that the instance
is gone afterwards and that the callback will not be invoked anymore.
2021-02-03 14:48:01 +01:00
|
|
|
priv->udev_client = nm_udev_client_destroy(priv->udev_client);
|
2017-03-12 15:54:02 +01:00
|
|
|
|
2016-08-23 11:45:51 +02:00
|
|
|
G_OBJECT_CLASS(nm_rfkill_manager_parent_class)->dispose(object);
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_rfkill_manager_class_init(NMRfkillManagerClass *klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-09 10:24:08 -04:00
|
|
|
object_class->dispose = dispose;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-09-29 13:49:01 +02:00
|
|
|
signals[RFKILL_CHANGED] = g_signal_new(NM_RFKILL_MANAGER_SIGNAL_RFKILL_CHANGED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
0,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
G_TYPE_NONE,
|
|
|
|
|
2,
|
2022-02-02 12:04:27 +01:00
|
|
|
G_TYPE_UINT /* NMRfkillType */,
|
|
|
|
|
G_TYPE_UINT /* NMRfkillState */);
|
2013-05-09 10:24:08 -04:00
|
|
|
}
|