summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2013-11-26 10:40:57 +0100
committerBastien Nocera <hadess@hadess.net>2013-11-26 17:40:34 +0100
commit562dcef4b4245311519d0fadc66f42bf660a5acb (patch)
tree07e863b04fc9bec2b041ff7ca8c7b861a775af47
parent1d53a9c7d9468b7c375be04edfb20ff318a76096 (diff)
downloadgnome-settings-daemon-562dcef4b4245311519d0fadc66f42bf660a5acb.tar.gz
rfkill: Add Bluetooth killswitch support
https://bugzilla.gnome.org/show_bug.cgi?id=719339
-rw-r--r--plugins/rfkill/gsd-rfkill-manager.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/plugins/rfkill/gsd-rfkill-manager.c b/plugins/rfkill/gsd-rfkill-manager.c
index 3813f08e..26ade21f 100644
--- a/plugins/rfkill/gsd-rfkill-manager.c
+++ b/plugins/rfkill/gsd-rfkill-manager.c
@@ -41,6 +41,7 @@ struct GsdRfkillManagerPrivate
CcRfkillGlib *rfkill;
GHashTable *killswitches;
+ GHashTable *bt_killswitches;
/* In addition to using the rfkill kernel subsystem
(which is exposed by wlan, wimax, bluetooth, nfc,
@@ -67,6 +68,9 @@ static const gchar introspection_xml[] =
" <property name='AirplaneMode' type='b' access='readwrite'/>"
" <property name='HardwareAirplaneMode' type='b' access='read'/>"
" <property name='HasAirplaneMode' type='b' access='read'/>"
+" <property name='BluetoothAirplaneMode' type='b' access='readwrite'/>"
+" <property name='BluetoothHardwareAirplaneMode' type='b' access='read'/>"
+" <property name='BluetoothHasAirplaneMode' type='b' access='read'/>"
" </interface>"
"</node>";
@@ -95,6 +99,60 @@ gsd_rfkill_manager_init (GsdRfkillManager *manager)
}
static gboolean
+engine_get_bluetooth_airplane_mode (GsdRfkillManager *manager)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ if (g_hash_table_size (manager->priv->bt_killswitches) == 0)
+ return FALSE;
+
+ g_hash_table_iter_init (&iter, manager->priv->bt_killswitches);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ int state;
+
+ state = GPOINTER_TO_INT (value);
+
+ /* A single rfkill switch that's unblocked? Airplane mode is off */
+ if (state == RFKILL_STATE_UNBLOCKED)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+engine_get_bluetooth_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->priv->bt_killswitches) == 0)
+ return FALSE;
+
+ g_hash_table_iter_init (&iter, manager->priv->bt_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_bluetooth_airplane_mode (GsdRfkillManager *manager)
+{
+ return (g_hash_table_size (manager->priv->bt_killswitches) > 0);
+}
+
+static gboolean
engine_get_airplane_mode (GsdRfkillManager *manager)
{
GHashTableIter iter;
@@ -171,6 +229,12 @@ engine_properties_changed (GsdRfkillManager *manager)
g_variant_new_boolean (engine_get_hardware_airplane_mode (manager)));
g_variant_builder_add (&props_builder, "{sv}", "HasAirplaneMode",
g_variant_new_boolean (engine_get_has_airplane_mode (manager)));
+ g_variant_builder_add (&props_builder, "{sv}", "BluetoothAirplaneMode",
+ g_variant_new_boolean (engine_get_bluetooth_airplane_mode (manager)));
+ g_variant_builder_add (&props_builder, "{sv}", "BluetoothHardwareAirplaneMode",
+ 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)));
props_changed = g_variant_new ("(s@a{sv}@as)", GSD_RFKILL_DBUS_NAME,
g_variant_builder_end (&props_builder),
@@ -208,10 +272,17 @@ rfkill_changed (CcRfkillGlib *rfkill,
g_hash_table_insert (manager->priv->killswitches,
GINT_TO_POINTER (event->idx),
GINT_TO_POINTER (value));
+ if (event->type == RFKILL_TYPE_BLUETOOTH)
+ g_hash_table_insert (manager->priv->bt_killswitches,
+ GINT_TO_POINTER (event->idx),
+ GINT_TO_POINTER (value));
break;
case RFKILL_OP_DEL:
g_hash_table_remove (manager->priv->killswitches,
GINT_TO_POINTER (event->idx));
+ if (event->type == RFKILL_TYPE_BLUETOOTH)
+ g_hash_table_remove (manager->priv->bt_killswitches,
+ GINT_TO_POINTER (event->idx));
break;
}
}
@@ -260,6 +331,21 @@ set_wwan_complete (GObject *object,
}
static gboolean
+engine_set_bluetooth_airplane_mode (GsdRfkillManager *manager,
+ gboolean enable)
+{
+ struct rfkill_event event;
+
+ memset (&event, 0, sizeof(event));
+ event.op = RFKILL_OP_CHANGE_ALL;
+ event.type = RFKILL_TYPE_BLUETOOTH;
+ event.soft = enable ? 1 : 0;
+ cc_rfkill_glib_send_event (manager->priv->rfkill, &event, NULL, rfkill_set_cb, manager);
+
+ return TRUE;
+}
+
+static gboolean
engine_set_airplane_mode (GsdRfkillManager *manager,
gboolean enable)
{
@@ -305,6 +391,10 @@ handle_set_property (GDBusConnection *connection,
gboolean airplane_mode;
g_variant_get (value, "b", &airplane_mode);
return engine_set_airplane_mode (manager, airplane_mode);
+ } else if (g_strcmp0 (property_name, "BluetoothAirplaneMode") == 0) {
+ gboolean airplane_mode;
+ g_variant_get (value, "b", &airplane_mode);
+ return engine_set_bluetooth_airplane_mode (manager, airplane_mode);
}
return FALSE;
@@ -345,6 +435,24 @@ handle_get_property (GDBusConnection *connection,
return g_variant_new_boolean (has_airplane_mode);
}
+ if (g_strcmp0 (property_name, "BluetoothAirplaneMode") == 0) {
+ gboolean airplane_mode;
+ airplane_mode = engine_get_bluetooth_airplane_mode (manager);
+ return g_variant_new_boolean (airplane_mode);
+ }
+
+ if (g_strcmp0 (property_name, "BluetoothHardwareAirplaneMode") == 0) {
+ gboolean hw_airplane_mode;
+ hw_airplane_mode = engine_get_bluetooth_hardware_airplane_mode (manager);
+ return g_variant_new_boolean (hw_airplane_mode);
+ }
+
+ if (g_strcmp0 (property_name, "BluetoothHasAirplaneMode") == 0) {
+ gboolean has_airplane_mode;
+ has_airplane_mode = engine_get_has_bluetooth_airplane_mode (manager);
+ return g_variant_new_boolean (has_airplane_mode);
+ }
+
return NULL;
}
@@ -522,6 +630,7 @@ gsd_rfkill_manager_start (GsdRfkillManager *manager,
g_assert (manager->priv->introspection_data != NULL);
manager->priv->killswitches = g_hash_table_new (g_direct_hash, g_direct_equal);
+ manager->priv->bt_killswitches = g_hash_table_new (g_direct_hash, g_direct_equal);
manager->priv->rfkill = cc_rfkill_glib_new ();
g_signal_connect (G_OBJECT (manager->priv->rfkill), "changed",
G_CALLBACK (rfkill_changed), manager);
@@ -571,6 +680,7 @@ gsd_rfkill_manager_stop (GsdRfkillManager *manager)
g_clear_object (&p->connection);
g_clear_object (&p->rfkill);
g_clear_pointer (&p->killswitches, g_hash_table_destroy);
+ g_clear_pointer (&p->bt_killswitches, g_hash_table_destroy);
if (p->nm_cancellable) {
g_cancellable_cancel (p->nm_cancellable);