summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammed Sadiq <sadiq@sadiqpk.org>2019-06-11 18:16:01 +0530
committerBenjamin Berg <benjamin@sipsolutions.net>2019-07-05 13:22:58 +0000
commit45cc86c410dac7c051c123934dfc2a6a49414e0b (patch)
tree5b832a0ce4deb0091e963030f0417928a53ab6e9
parenta0776377c7f3dd16a7ed76781cf9e12265d000e2 (diff)
downloadgnome-settings-daemon-45cc86c410dac7c051c123934dfc2a6a49414e0b.tar.gz
rfkill: Handle Airplane mode for Wireless WAN
This commit allows handling airplane mode for WWAN interfaces which will be handled via rfkill and Modem Manager. The following boolean DBUS properties are added: * WwanAirplaneMode: read/write * WwanHardwareAirplaneMode: read * WwanHasAirplaneMode: read https://gitlab.gnome.org/GNOME/gnome-settings-daemon/issues/414
-rw-r--r--plugins/rfkill/gsd-rfkill-manager.c144
1 files changed, 138 insertions, 6 deletions
diff --git a/plugins/rfkill/gsd-rfkill-manager.c b/plugins/rfkill/gsd-rfkill-manager.c
index 5ad560eb..4c24c733 100644
--- a/plugins/rfkill/gsd-rfkill-manager.c
+++ b/plugins/rfkill/gsd-rfkill-manager.c
@@ -38,6 +38,16 @@
* "org.gnome.SettingsDaemon.Rfkill" \
* "BluetoothAirplaneMode" \
* "<true|false>"
+ *
+ * and
+ * gdbus call \
+ * --session \
+ * --dest org.gnome.SettingsDaemon.Rfkill \
+ * --object-path /org/gnome/SettingsDaemon/Rfkill \
+ * --method org.freedesktop.DBus.Properties.Set \
+ * "org.gnome.SettingsDaemon.Rfkill" \
+ * "WwanAirplaneMode" \
+ * "<true|false>"
*/
#include "config.h"
@@ -62,6 +72,7 @@ struct _GsdRfkillManager
CcRfkillGlib *rfkill;
GHashTable *killswitches;
GHashTable *bt_killswitches;
+ GHashTable *wwan_killswitches;
/* In addition to using the rfkill kernel subsystem
(which is exposed by wlan, wimax, bluetooth, nfc,
@@ -100,6 +111,9 @@ static const gchar introspection_xml[] =
" <property name='BluetoothAirplaneMode' type='b' access='readwrite'/>"
" <property name='BluetoothHardwareAirplaneMode' type='b' access='read'/>"
" <property name='BluetoothHasAirplaneMode' type='b' access='read'/>"
+" <property name='WwanAirplaneMode' type='b' access='readwrite'/>"
+" <property name='WwanHardwareAirplaneMode' type='b' access='read'/>"
+" <property name='WwanHasAirplaneMode' type='b' access='read'/>"
" </interface>"
"</node>";
@@ -185,6 +199,58 @@ engine_get_has_bluetooth_airplane_mode (GsdRfkillManager *manager)
}
static gboolean
+engine_get_wwan_airplane_mode (GsdRfkillManager *manager)
+{
+ gboolean is_airplane;
+
+ is_airplane = engine_get_airplane_mode_helper (manager->wwan_killswitches);
+
+ /* Try our luck with Modem Manager too. Check only if no rfkill
+ * devices found, or if rfkill reports all devices to be down.
+ * (Airplane mode will be disabled if at least one device is up,
+ * so if rfkill says no device is up, check any device is up via
+ * Network Manager (which in turn, is handled via Modem Manager))
+ */
+ if (g_hash_table_size (manager->wwan_killswitches) == 0 || is_airplane)
+ if (manager->wwan_interesting)
+ is_airplane = !manager->wwan_enabled;
+
+ return is_airplane;
+}
+
+static gboolean
+engine_get_wwan_hardware_airplane_mode (GsdRfkillManager *manager)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ /* If we have no killswitches, hw airplane mode is off. */
+ if (g_hash_table_size (manager->wwan_killswitches) == 0)
+ return FALSE;
+
+ g_hash_table_iter_init (&iter, manager->wwan_killswitches);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ int state;
+
+ state = GPOINTER_TO_INT (value);
+
+ /* A single rfkill switch that's not hw blocked? Hw airplane mode is off */
+ if (state != RFKILL_STATE_HARD_BLOCKED) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+engine_get_has_wwan_airplane_mode (GsdRfkillManager *manager)
+{
+ return (g_hash_table_size (manager->wwan_killswitches) > 0 ||
+ manager->wwan_interesting);
+}
+
+static gboolean
engine_get_airplane_mode (GsdRfkillManager *manager)
{
if (!manager->wwan_interesting)
@@ -261,6 +327,12 @@ engine_properties_changed (GsdRfkillManager *manager)
g_variant_new_boolean (engine_get_bluetooth_hardware_airplane_mode (manager)));
g_variant_builder_add (&props_builder, "{sv}", "BluetoothHasAirplaneMode",
g_variant_new_boolean (engine_get_has_bluetooth_airplane_mode (manager)));
+ g_variant_builder_add (&props_builder, "{sv}", "WwanAirplaneMode",
+ g_variant_new_boolean (engine_get_wwan_airplane_mode (manager)));
+ g_variant_builder_add (&props_builder, "{sv}", "WwanHardwareAirplaneMode",
+ g_variant_new_boolean (engine_get_wwan_hardware_airplane_mode (manager)));
+ g_variant_builder_add (&props_builder, "{sv}", "WwanHasAirplaneMode",
+ g_variant_new_boolean (engine_get_has_wwan_airplane_mode (manager)));
props_changed = g_variant_new ("(s@a{sv}@as)", GSD_RFKILL_DBUS_NAME,
g_variant_builder_end (&props_builder),
@@ -284,6 +356,12 @@ rfkill_changed (CcRfkillGlib *rfkill,
for (l = events; l != NULL; l = l->next) {
struct rfkill_event *event = l->data;
+ const gchar *type = "";
+
+ if (event->type == RFKILL_TYPE_BLUETOOTH)
+ type = "Bluetooth";
+ else if (event->type == RFKILL_TYPE_WWAN)
+ type = "WWAN";
switch (event->op) {
case RFKILL_OP_ADD:
@@ -302,10 +380,13 @@ rfkill_changed (CcRfkillGlib *rfkill,
g_hash_table_insert (manager->bt_killswitches,
GINT_TO_POINTER (event->idx),
GINT_TO_POINTER (value));
- g_debug ("%s %srfkill with ID %d",
- event->op == RFKILL_OP_ADD ? "Added" : "Changed",
- event->type == RFKILL_TYPE_BLUETOOTH ? "Bluetooth " : "",
- event->idx);
+ else if (event->type == RFKILL_TYPE_WWAN)
+ g_hash_table_insert (manager->wwan_killswitches,
+ GINT_TO_POINTER (event->idx),
+ GINT_TO_POINTER (value));
+ g_debug ("%s %srfkill with ID %d",
+ event->op == RFKILL_OP_ADD ? "Added" : "Changed",
+ type, event->idx);
break;
case RFKILL_OP_DEL:
g_hash_table_remove (manager->killswitches,
@@ -313,8 +394,10 @@ rfkill_changed (CcRfkillGlib *rfkill,
if (event->type == RFKILL_TYPE_BLUETOOTH)
g_hash_table_remove (manager->bt_killswitches,
GINT_TO_POINTER (event->idx));
- g_debug ("Removed %srfkill with ID %d", event->type == RFKILL_TYPE_BLUETOOTH ? "Bluetooth " : "",
- event->idx);
+ else if (event->type == RFKILL_TYPE_WWAN)
+ g_hash_table_remove (manager->wwan_killswitches,
+ GINT_TO_POINTER (event->idx));
+ g_debug ("Removed %srfkill with ID %d", type, event->idx);
break;
}
}
@@ -372,6 +455,29 @@ engine_set_bluetooth_airplane_mode (GsdRfkillManager *manager,
}
static gboolean
+engine_set_wwan_airplane_mode (GsdRfkillManager *manager,
+ gboolean enable)
+{
+ cc_rfkill_glib_send_change_all_event (manager->rfkill, RFKILL_TYPE_WWAN,
+ enable, manager->cancellable, rfkill_set_cb, manager);
+
+ if (manager->nm_client) {
+ g_dbus_proxy_call (manager->nm_client,
+ "org.freedesktop.DBus.Properties.Set",
+ g_variant_new ("(ssv)",
+ "org.freedesktop.NetworkManager",
+ "WwanEnabled",
+ g_variant_new_boolean (!enable)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, /* timeout */
+ manager->cancellable,
+ set_wwan_complete, NULL);
+ }
+
+ return TRUE;
+}
+
+static gboolean
engine_set_airplane_mode (GsdRfkillManager *manager,
gboolean enable)
{
@@ -418,6 +524,12 @@ handle_set_property (GDBusConnection *connection,
return engine_set_bluetooth_airplane_mode (manager, airplane_mode);
}
+ if (g_strcmp0 (property_name, "WwanAirplaneMode") == 0) {
+ gboolean airplane_mode;
+ g_variant_get (value, "b", &airplane_mode);
+ return engine_set_wwan_airplane_mode (manager, airplane_mode);
+ }
+
return FALSE;
}
@@ -480,6 +592,24 @@ handle_get_property (GDBusConnection *connection,
return g_variant_new_boolean (has_airplane_mode);
}
+ if (g_strcmp0 (property_name, "WwanAirplaneMode") == 0) {
+ gboolean airplane_mode;
+ airplane_mode = engine_get_wwan_airplane_mode (manager);
+ return g_variant_new_boolean (airplane_mode);
+ }
+
+ if (g_strcmp0 (property_name, "WwanHardwareAirplaneMode") == 0) {
+ gboolean hw_airplane_mode;
+ hw_airplane_mode = engine_get_wwan_hardware_airplane_mode (manager);
+ return g_variant_new_boolean (hw_airplane_mode);
+ }
+
+ if (g_strcmp0 (property_name, "WwanHasAirplaneMode") == 0) {
+ gboolean has_airplane_mode;
+ has_airplane_mode = engine_get_has_wwan_airplane_mode (manager);
+ return g_variant_new_boolean (has_airplane_mode);
+ }
+
return NULL;
}
@@ -666,6 +796,7 @@ gsd_rfkill_manager_start (GsdRfkillManager *manager,
manager->killswitches = g_hash_table_new (g_direct_hash, g_direct_equal);
manager->bt_killswitches = g_hash_table_new (g_direct_hash, g_direct_equal);
+ manager->wwan_killswitches = g_hash_table_new (g_direct_hash, g_direct_equal);
manager->rfkill = cc_rfkill_glib_new ();
g_signal_connect (G_OBJECT (manager->rfkill), "changed",
G_CALLBACK (rfkill_changed), manager);
@@ -724,6 +855,7 @@ gsd_rfkill_manager_stop (GsdRfkillManager *manager)
g_clear_object (&manager->rfkill);
g_clear_pointer (&manager->killswitches, g_hash_table_destroy);
g_clear_pointer (&manager->bt_killswitches, g_hash_table_destroy);
+ g_clear_pointer (&manager->wwan_killswitches, g_hash_table_destroy);
if (manager->cancellable) {
g_cancellable_cancel (manager->cancellable);