Commit 45cc86c4 authored by Mohammed Sadiq's avatar Mohammed Sadiq Committed by Benjamin Berg

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

#414
parent a0776377
Pipeline #93064 passed with stages
in 4 minutes and 32 seconds
......@@ -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>";
......@@ -184,6 +198,58 @@ engine_get_has_bluetooth_airplane_mode (GsdRfkillManager *manager)
return (g_hash_table_size (manager->bt_killswitches) > 0);
}
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)
{
......@@ -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;
}
}
......@@ -371,6 +454,29 @@ engine_set_bluetooth_airplane_mode (GsdRfkillManager *manager,
return TRUE;
}
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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment