diff options
| author | Michael Biebl <biebl@debian.org> | 2021-02-11 18:11:46 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-02-11 18:11:46 +0100 |
| commit | 80ec1decc49c72efec2a8b87c06245c92c0ab807 (patch) | |
| tree | e3b229aa94e8dcf0590f2317664176e7b8f7607b /src/nm-rfkill-manager.c | |
| parent | 65f86e8f56267192d42f2b629fc6b0c99fb9cd0c (diff) | |
New upstream version 1.29.90 upstream/1.29.90
Diffstat (limited to 'src/nm-rfkill-manager.c')
| -rw-r--r-- | src/nm-rfkill-manager.c | 431 |
1 files changed, 0 insertions, 431 deletions
diff --git a/src/nm-rfkill-manager.c b/src/nm-rfkill-manager.c deleted file mode 100644 index 4b3e18d7..00000000 --- a/src/nm-rfkill-manager.c +++ /dev/null @@ -1,431 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2009 - 2013 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-rfkill-manager.h" - -#include <libudev.h> - -#include "nm-udev-aux/nm-udev-utils.h" - -/*****************************************************************************/ - -enum { - RFKILL_CHANGED, - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL] = {0}; - -typedef struct { - NMUdevClient *udev_client; - - /* Authoritative rfkill state (RFKILL_* enum) */ - RfKillState rfkill_states[RFKILL_TYPE_MAX]; - GSList * killswitches; -} NMRfkillManagerPrivate; - -struct _NMRfkillManager { - GObject parent; - NMRfkillManagerPrivate _priv; -}; - -struct _NMRfkillManagerClass { - GObjectClass parent; -}; - -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) - -/*****************************************************************************/ - -typedef struct { - char * name; - guint64 seqnum; - char * path; - char * driver; - RfKillType rtype; - int state; - gboolean platform; -} Killswitch; - -RfKillState -nm_rfkill_manager_get_rfkill_state(NMRfkillManager *self, RfKillType rtype) -{ - g_return_val_if_fail(self != NULL, RFKILL_UNBLOCKED); - g_return_val_if_fail(rtype < RFKILL_TYPE_MAX, RFKILL_UNBLOCKED); - - return NM_RFKILL_MANAGER_GET_PRIVATE(self)->rfkill_states[rtype]; -} - -static const char * -rfkill_type_to_desc(RfKillType rtype) -{ - if (rtype == 0) - return "Wi-Fi"; - else if (rtype == 1) - return "WWAN"; - else if (rtype == 2) - return "WiMAX"; - return "unknown"; -} - -static const char * -rfkill_state_to_desc(RfKillState rstate) -{ - if (rstate == 0) - return "unblocked"; - else if (rstate == 1) - return "soft-blocked"; - else if (rstate == 2) - return "hard-blocked"; - return "unknown"; -} - -static Killswitch * -killswitch_new(struct udev_device *device, RfKillType rtype) -{ - Killswitch * ks; - struct udev_device *parent = NULL, *grandparent = NULL; - const char * driver, *subsys, *parent_subsys = NULL; - - ks = g_malloc0(sizeof(Killswitch)); - ks->name = g_strdup(udev_device_get_sysname(device)); - ks->seqnum = udev_device_get_seqnum(device); - ks->path = g_strdup(udev_device_get_syspath(device)); - ks->rtype = rtype; - - driver = udev_device_get_property_value(device, "DRIVER"); - subsys = udev_device_get_subsystem(device); - - /* Check parent for various attributes */ - parent = udev_device_get_parent(device); - if (parent) { - parent_subsys = udev_device_get_subsystem(parent); - if (!driver) - driver = udev_device_get_property_value(parent, "DRIVER"); - if (!driver) { - /* Sigh; try the grandparent */ - grandparent = udev_device_get_parent(parent); - if (grandparent) - driver = udev_device_get_property_value(grandparent, "DRIVER"); - } - } - - if (!driver) - driver = "(unknown)"; - ks->driver = g_strdup(driver); - - if (g_strcmp0(subsys, "platform") == 0 || g_strcmp0(parent_subsys, "platform") == 0 - || g_strcmp0(subsys, "acpi") == 0 || g_strcmp0(parent_subsys, "acpi") == 0) - ks->platform = TRUE; - - return ks; -} - -static void -killswitch_destroy(Killswitch *ks) -{ - g_return_if_fail(ks != NULL); - - g_free(ks->name); - g_free(ks->path); - g_free(ks->driver); - memset(ks, 0, sizeof(Killswitch)); - g_free(ks); -} - -static RfKillState -sysfs_state_to_nm_state(int sysfs_state) -{ - switch (sysfs_state) { - case 0: - return RFKILL_SOFT_BLOCKED; - case 1: - return RFKILL_UNBLOCKED; - case 2: - return RFKILL_HARD_BLOCKED; - default: - nm_log_warn(LOGD_RFKILL, "unhandled rfkill state %d", sysfs_state); - break; - } - return RFKILL_UNBLOCKED; -} - -static void -recheck_killswitches(NMRfkillManager *self) -{ - NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self); - GSList * iter; - RfKillState poll_states[RFKILL_TYPE_MAX]; - RfKillState platform_states[RFKILL_TYPE_MAX]; - gboolean platform_checked[RFKILL_TYPE_MAX]; - int i; - - /* Default state is unblocked */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) { - poll_states[i] = RFKILL_UNBLOCKED; - platform_states[i] = RFKILL_UNBLOCKED; - platform_checked[i] = FALSE; - } - - /* Poll the states of all killswitches */ - for (iter = priv->killswitches; iter; iter = g_slist_next(iter)) { - Killswitch * ks = iter->data; - struct udev_device *device; - RfKillState dev_state; - int sysfs_state; - - 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); - - nm_log_dbg(LOGD_RFKILL, - "%s rfkill%s switch %s state now %d/%u", - rfkill_type_to_desc(ks->rtype), - ks->platform ? " platform" : "", - ks->name, - sysfs_state, - dev_state); - - 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; - } - udev_device_unref(device); - } - - /* Log and emit change signal for final rfkill states */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) { - if (platform_checked[i] == TRUE) { - /* blocked platform switch state overrides device state, otherwise - * let the device state stand. (bgo #655773) - */ - if (platform_states[i] != RFKILL_UNBLOCKED) - poll_states[i] = platform_states[i]; - } - - if (poll_states[i] != priv->rfkill_states[i]) { - nm_log_dbg(LOGD_RFKILL, - "%s rfkill state now '%s'", - rfkill_type_to_desc(i), - rfkill_state_to_desc(poll_states[i])); - - priv->rfkill_states[i] = poll_states[i]; - g_signal_emit(self, signals[RFKILL_CHANGED], 0, i, priv->rfkill_states[i]); - } - } -} - -static Killswitch * -killswitch_find_by_name(NMRfkillManager *self, const char *name) -{ - NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self); - GSList * iter; - - g_return_val_if_fail(name != NULL, NULL); - - for (iter = priv->killswitches; iter; iter = g_slist_next(iter)) { - Killswitch *candidate = iter->data; - - if (!strcmp(name, candidate->name)) - return candidate; - } - return NULL; -} - -static RfKillType -rfkill_type_to_enum(const char *str) -{ - g_return_val_if_fail(str != NULL, RFKILL_TYPE_UNKNOWN); - - if (!strcmp(str, "wlan")) - return RFKILL_TYPE_WLAN; - else if (!strcmp(str, "wwan")) - return RFKILL_TYPE_WWAN; - - return RFKILL_TYPE_UNKNOWN; -} - -static void -add_one_killswitch(NMRfkillManager *self, struct udev_device *device) -{ - NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self); - const char * str_type; - RfKillType rtype; - Killswitch * ks; - - str_type = udev_device_get_property_value(device, "RFKILL_TYPE"); - rtype = rfkill_type_to_enum(str_type); - if (rtype == RFKILL_TYPE_UNKNOWN) - return; - - ks = killswitch_new(device, rtype); - priv->killswitches = g_slist_prepend(priv->killswitches, ks); - - nm_log_info(LOGD_RFKILL, - "%s: found %s radio killswitch (at %s) (%sdriver %s)", - ks->name, - rfkill_type_to_desc(rtype), - ks->path, - ks->platform ? "platform " : "", - ks->driver ?: "<unknown>"); -} - -static void -rfkill_add(NMRfkillManager *self, struct udev_device *device) -{ - const char *name; - - g_return_if_fail(device != NULL); - name = udev_device_get_sysname(device); - 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); - GSList * iter; - const char * name; - - g_return_if_fail(device != NULL); - name = udev_device_get_sysname(device); - g_return_if_fail(name != NULL); - - for (iter = priv->killswitches; iter; iter = g_slist_next(iter)) { - Killswitch *ks = iter->data; - - if (!strcmp(ks->name, name)) { - nm_log_info(LOGD_RFKILL, "radio killswitch %s disappeared", ks->path); - priv->killswitches = g_slist_remove(priv->killswitches, ks); - killswitch_destroy(ks); - break; - } - } -} - -static void -handle_uevent(NMUdevClient *client, struct udev_device *device, gpointer user_data) -{ - NMRfkillManager *self = NM_RFKILL_MANAGER(user_data); - const char * subsys; - const char * action; - - action = udev_device_get_action(device); - - g_return_if_fail(action != NULL); - - /* A bit paranoid */ - subsys = udev_device_get_subsystem(device); - g_return_if_fail(!g_strcmp0(subsys, "rfkill")); - - nm_log_dbg(LOGD_PLATFORM, - "udev rfkill event: action '%s' device '%s'", - action, - udev_device_get_sysname(device)); - - if (!strcmp(action, "add")) - rfkill_add(self, device); - else if (!strcmp(action, "remove")) - rfkill_remove(self, device); - - recheck_killswitches(self); -} - -/*****************************************************************************/ - -static void -nm_rfkill_manager_init(NMRfkillManager *self) -{ - NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self); - struct udev_enumerate * enumerate; - struct udev_list_entry *iter; - guint i; - - for (i = 0; i < RFKILL_TYPE_MAX; i++) - priv->rfkill_states[i] = RFKILL_UNBLOCKED; - - priv->udev_client = nm_udev_client_new((const char *[]){"rfkill", NULL}, handle_uevent, self); - - 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; - - udevice = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate), - udev_list_entry_get_name(iter)); - if (!udevice) - continue; - - add_one_killswitch(self, udevice); - udev_device_unref(udevice); - } - udev_enumerate_unref(enumerate); - - recheck_killswitches(self); -} - -NMRfkillManager * -nm_rfkill_manager_new(void) -{ - return NM_RFKILL_MANAGER(g_object_new(NM_TYPE_RFKILL_MANAGER, NULL)); -} - -static void -dispose(GObject *object) -{ - NMRfkillManager * self = NM_RFKILL_MANAGER(object); - NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE(self); - - if (priv->killswitches) { - g_slist_free_full(priv->killswitches, (GDestroyNotify) killswitch_destroy); - priv->killswitches = NULL; - } - - priv->udev_client = nm_udev_client_unref(priv->udev_client); - - G_OBJECT_CLASS(nm_rfkill_manager_parent_class)->dispose(object); -} - -static void -nm_rfkill_manager_class_init(NMRfkillManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - - object_class->dispose = dispose; - - 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, - G_TYPE_UINT, - G_TYPE_UINT); -} |