From ec74519d4526462b3b7bd2a941a2575899850098 Mon Sep 17 00:00:00 2001
From: ayozetr <53948812+ayozetr@users.noreply.github.com>
Date: Sat, 13 Jun 2026 23:33:21 +0100
Subject: [PATCH] Add power switch to enable/disable the selected wheel
Add a per-device power switch that authorizes/deauthorizes the selected
wheel at the USB level (sysfs 'authorized'), hiding it from every game and
application without unplugging it.
A deauthorized wheel leaves the input subsystem and disappears from the
device list, so the switch keeps representing it (off, with a status label
showing how to re-enable it) until the user flips the switch back on. The
disabled wheel is remembered (persisted in config) and re-enabled by writing
to its stored USB path.
- device: track usb_path and add is_authorized/can_set_authorized/set_authorized
- device_manager: resolve usb_path via find_parent and add authorize_path to
re-enable a wheel that already left the input subsystem
- gui: power switch wired to the selected device, with a status label and
remembered disabled wheel; update_power_controls keeps the switch coherent
on every device-list refresh
- udev: new 99-oversteer-wheel-power.rules granting write access to the
'authorized' attribute for supported wheels only
- po: translate the new strings (Power, Re-enable, tooltip, permission
message) into all 9 languages
---
.gitignore | 2 +
data/udev/99-oversteer-wheel-power.rules | 71 ++++++++++++++++++++++++
oversteer/device.py | 30 ++++++++++
oversteer/device_manager.py | 18 ++++++
oversteer/gtk_handlers.py | 6 ++
oversteer/gtk_ui.py | 17 ++++++
oversteer/gui.py | 57 +++++++++++++++++++
oversteer/main.ui | 54 ++++++++++++++++++
po/ca.po | 19 +++++++
po/de.po | 19 +++++++
po/es.po | 22 ++++++++
po/fi.po | 19 +++++++
po/gl.po | 19 +++++++
po/hu.po | 19 +++++++
po/pl.po | 19 +++++++
po/ru.po | 19 +++++++
po/tr.po | 19 +++++++
17 files changed, 429 insertions(+)
create mode 100644 data/udev/99-oversteer-wheel-power.rules
diff --git a/.gitignore b/.gitignore
index 9cd9129..0f4c7ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@
__pycache__
/extra
*~
+/.dev-locale
+/run.py
diff --git a/data/udev/99-oversteer-wheel-power.rules b/data/udev/99-oversteer-wheel-power.rules
new file mode 100644
index 0000000..a2ebf15
--- /dev/null
+++ b/data/udev/99-oversteer-wheel-power.rules
@@ -0,0 +1,71 @@
+# Allow regular users to enable/disable supported wheels from Oversteer.
+#
+# Oversteer's power switch writes to the USB device's "authorized" attribute
+# (1 = visible to the system, 0 = hidden from every game/application). That
+# attribute lives at the usb_device node and is owned by root, so this rule
+# grants write access to it for the supported wheels only, avoiding any other
+# USB device (mice, keyboards, etc.).
+#
+# The usb_device node and its "authorized" attribute exist as long as the wheel
+# is plugged in, even while deauthorized, so this single rule covers both
+# disabling and re-enabling.
+
+ACTION=="remove", GOTO="oversteer_power_end"
+SUBSYSTEM!="usb", GOTO="oversteer_power_end"
+ENV{DEVTYPE}!="usb_device", GOTO="oversteer_power_end"
+
+# Logitech wheels
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c294", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c29a", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c298", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c299", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c29b", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c24f", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c262", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c266", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c26e", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c268", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c272", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c295", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="ca03", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c29c", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c291", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c293", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="046d", ATTR{idProduct}=="c20e", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+
+# Thrustmaster wheels
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b677", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b696", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b66e", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b66f", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b66d", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b65e", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b668", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b66a", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b67f", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b664", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b692", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b669", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="044f", ATTR{idProduct}=="b689", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+
+# Other Thrustmaster (different vendor IDs)
+ATTR{idVendor}=="24c6", ATTR{idProduct}=="5b00", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="06f8", ATTR{idProduct}=="0004", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+
+# Fanatec wheels
+ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0020", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0e03", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0005", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0001", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0004", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0006", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0007", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+
+# Cammus
+ATTR{idVendor}=="3416", ATTR{idProduct}=="0301", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+
+# Generic FFBoard / Flashfire
+ATTR{idVendor}=="1209", ATTR{idProduct}=="ffb0", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+ATTR{idVendor}=="2f24", ATTR{idProduct}=="010d", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'"
+
+LABEL="oversteer_power_end"
diff --git a/oversteer/device.py b/oversteer/device.py
index 039990f..ae17b6b 100644
--- a/oversteer/device.py
+++ b/oversteer/device.py
@@ -27,6 +27,7 @@ def __init__(self, device_manager, data):
self.product_id = None
self.usb_id = None
self.dev_path = None
+ self.usb_path = None
self.dev_name = None
self.name = None
self.ready = True
@@ -82,6 +83,35 @@ def check_file_permissions(self, filename):
def get_max_range(self):
return self.max_range
+ def authorized_file(self):
+ if self.usb_path is None:
+ return None
+ return os.path.join(self.usb_path, 'authorized')
+
+ def is_authorized(self):
+ path = self.authorized_file()
+ if path is None or not os.access(path, os.F_OK | os.R_OK):
+ return None
+ with open(path, "r") as file:
+ data = file.read()
+ return int(data.strip()) == 1
+
+ def can_set_authorized(self):
+ path = self.authorized_file()
+ if path is None:
+ return False
+ return os.access(path, os.W_OK)
+
+ def set_authorized(self, authorized):
+ path = self.authorized_file()
+ if path is None:
+ return False
+ value = "1" if authorized else "0"
+ logging.debug("Setting authorized: %s (%s)", value, path)
+ with open(path, "w") as file:
+ file.write(value)
+ return True
+
def list_modes(self):
path = self.checked_device_file("alternate_modes")
if not path:
diff --git a/oversteer/device_manager.py b/oversteer/device_manager.py
index f30a4f8..cd16b93 100644
--- a/oversteer/device_manager.py
+++ b/oversteer/device_manager.py
@@ -117,6 +117,9 @@ def update_device_list(self, udevice):
logging.debug("%s: ID_VENDOR_ID: %s ID_MODEL_ID: %s", device_node,
udevice.get('ID_VENDOR_ID'), udevice.get('ID_MODEL_ID'))
+ usb_device = udevice.find_parent('usb', 'usb_device')
+ usb_path = usb_device.sys_path if usb_device is not None else None
+
device.set({
'id': id,
'vendor_id': udevice.get('ID_VENDOR_ID'),
@@ -124,6 +127,7 @@ def update_device_list(self, udevice):
'usb_id': usb_id,
'dev_name': device_node,
'dev_path': os.path.realpath(os.path.join(udevice.sys_path, 'device', 'device')),
+ 'usb_path': usb_path,
'name': bytes(udevice.get('ID_VENDOR_ENC') + ' ' + udevice.get('ID_MODEL_ENC'),
'utf-8').decode('unicode_escape'),
'max_range': self.supported_wheels[usb_id],
@@ -144,6 +148,20 @@ def get_device(self, did):
return self.devices[did]
return next((item for item in self.devices.values() if item.dev_name == did), None)
+ def authorize_path(self, usb_path, authorized):
+ # Re-enable a wheel that is no longer in the device list (it left the
+ # input subsystem when it was deauthorized). The usb_device node and its
+ # 'authorized' attribute still exist while the wheel stays plugged in.
+ if usb_path is None:
+ return False
+ path = os.path.join(usb_path, 'authorized')
+ if not os.access(path, os.F_OK | os.W_OK):
+ return False
+ with open(path, "w") as file:
+ file.write("1" if authorized else "0")
+ self.changed = True
+ return True
+
def is_changed(self):
changed = self.changed
self.changed = False
diff --git a/oversteer/gtk_handlers.py b/oversteer/gtk_handlers.py
index e7bb146..954a49c 100644
--- a/oversteer/gtk_handlers.py
+++ b/oversteer/gtk_handlers.py
@@ -52,6 +52,12 @@ def on_update_clicked(self, button):
self.controller.populate_window()
self.ui.update()
+ def on_wheel_power_state_set(self, widget, state):
+ if self.ui._suppress_power_signal:
+ return False
+ self.controller.set_wheel_power(state)
+ return False
+
def on_change_emulation_mode_clicked(self, widget):
mode = self.ui.emulation_mode_combobox.get_active_id()
self.model.set_mode(mode)
diff --git a/oversteer/gtk_ui.py b/oversteer/gtk_ui.py
index 8cd63b5..adc75c8 100644
--- a/oversteer/gtk_ui.py
+++ b/oversteer/gtk_ui.py
@@ -16,6 +16,7 @@ def __init__(self, controller, argv):
self.ffbmeter_timer = False
self.current_test_canvas = None
self.current_test_toolbar = None
+ self._suppress_power_signal = False
Gdk.init(argv)
style_provider = Gtk.CssProvider()
@@ -168,6 +169,20 @@ def set_check_permissions(self, state):
def set_device_id(self, device_id):
self.device_combobox.set_active_id(device_id)
+ def set_wheel_power(self, state, sensitive = True):
+ # Update the switch without triggering a write back to the device.
+ self._suppress_power_signal = True
+ self.wheel_power.set_sensitive(sensitive and state is not None)
+ self.wheel_power.set_active(bool(state))
+ self._suppress_power_signal = False
+
+ def set_wheel_power_status(self, text):
+ if text:
+ self.wheel_power_status.set_label(text)
+ self.wheel_power_status.show()
+ else:
+ self.wheel_power_status.hide()
+
def set_devices(self, devices):
model = self.device_combobox.get_model()
if model is None:
@@ -578,6 +593,8 @@ def _set_builder_objects(self):
self.check_permissions = self.builder.get_object('check_permissions')
self.device_combobox = self.builder.get_object('device')
+ self.wheel_power = self.builder.get_object('wheel_power')
+ self.wheel_power_status = self.builder.get_object('wheel_power_status')
self.profile_combobox = self.builder.get_object('profile')
self.new_profile_name_entry = self.builder.get_object('new_profile_name')
self.save_profile_button = self.builder.get_object('save_profile')
diff --git a/oversteer/gui.py b/oversteer/gui.py
index 77e604a..2a75f42 100644
--- a/oversteer/gui.py
+++ b/oversteer/gui.py
@@ -56,6 +56,7 @@ def __init__(self, application, model, argv):
self.model = model
self.device_manager = self.app.device_manager
self.device = None
+ self.disabled_wheel = None
self.grab_input = False
self.test = None
self.linear_chart = None
@@ -155,6 +156,7 @@ def populate_devices(self):
if device.is_ready():
device_list.append((device.get_id(), device.name))
self.ui.set_devices(device_list)
+ self.update_power_controls()
def populate_profiles(self):
profiles = []
@@ -166,6 +168,52 @@ def populate_profiles(self):
def populate_window(self):
self.populate_devices()
self.populate_profiles()
+ self.update_power_controls()
+
+ def update_power_controls(self):
+ # A disabled wheel leaves the device list, so the switch keeps
+ # representing it (off, with a status message) until it's re-enabled.
+ if self.disabled_wheel is not None:
+ self.ui.set_wheel_power(False, True)
+ self.ui.set_wheel_power_status(_("Re-enable {}").format(self.disabled_wheel['name']))
+ elif self.device is not None and self.device.is_authorized() is not None:
+ self.ui.set_wheel_power(self.device.is_authorized(), self.device.can_set_authorized())
+ self.ui.set_wheel_power_status(None)
+ else:
+ self.ui.set_wheel_power(False, False)
+ self.ui.set_wheel_power_status(None)
+
+ def set_wheel_power(self, state):
+ try:
+ if state:
+ if self.disabled_wheel is not None:
+ # Re-enable the remembered wheel; it's no longer in the list.
+ if not self.device_manager.authorize_path(self.disabled_wheel['usb_path'], True):
+ raise PermissionError
+ self.disabled_wheel = None
+ self.save_preferences()
+ elif self.device is not None:
+ self.device.set_authorized(True)
+ else:
+ if self.device is None:
+ return
+ self.device.set_authorized(False)
+ # Remember the wheel so it can be re-enabled with the switch
+ # after it disappears from the device list.
+ self.disabled_wheel = {
+ 'usb_path': self.device.usb_path,
+ 'name': self.device.name,
+ }
+ self.save_preferences()
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except OSError:
+ if self.app.udev_path:
+ self.install_udev_files()
+ else:
+ self.ui.info_dialog(_("You don't have the required permissions to " +
+ "enable or disable the wheel."))
+ self.update_power_controls()
def change_device(self, device_id):
self.device = self.device_manager.get_device(device_id)
@@ -188,6 +236,8 @@ def change_device(self, device_id):
self.model = Model(self.device, self.ui)
self.models[self.device.get_id()] = self.model
+ self.update_power_controls()
+
self.ui.set_max_range(self.device.get_max_range())
self.ui.set_modes(self.model.get_mode_list())
@@ -265,6 +315,11 @@ def load_preferences(self):
Locale.setlocale(Locale.LC_ALL, (self.locale, 'UTF-8'))
if 'check_permissions' in config['DEFAULT']:
self.check_permissions = config['DEFAULT']['check_permissions'] == '1'
+ if config['DEFAULT'].get('disabled_wheel_path', '') != '':
+ self.disabled_wheel = {
+ 'usb_path': config['DEFAULT']['disabled_wheel_path'],
+ 'name': config['DEFAULT'].get('disabled_wheel_name', _('wheel')),
+ }
if 'button_config' in config['DEFAULT'] and config['DEFAULT']['button_config'] != '':
if 'button_toggle' not in config['DEFAULT']:
self.button_config = list(map(int, config['DEFAULT']['button_config'].split(',')))
@@ -298,6 +353,8 @@ def save_preferences(self):
'check_permissions': '1' if self.check_permissions else '0',
'button_toggle': ','.join(map(str, self.button_config[0])),
'button_config': ','.join(map(str, self.button_config[1:])),
+ 'disabled_wheel_path': self.disabled_wheel['usb_path'] if self.disabled_wheel else '',
+ 'disabled_wheel_name': self.disabled_wheel['name'] if self.disabled_wheel else '',
}
config_file = os.path.join(self.config_path, 'config.ini')
with open(config_file, 'w') as file:
diff --git a/oversteer/main.ui b/oversteer/main.ui
index b5ad218..d59b1a3 100644
--- a/oversteer/main.ui
+++ b/oversteer/main.ui
@@ -356,6 +356,60 @@
1
+
+
+
+ False
+ True
+ 2
+
+
False
diff --git a/po/ca.po b/po/ca.po
index cb1e70a..372188b 100644
--- a/po/ca.po
+++ b/po/ca.po
@@ -912,6 +912,25 @@ msgstr "Configurador de volants"
msgid "game;racing;cars;wheels"
msgstr "jocs;carreres;coches;volants"
+#: oversteer/main.ui:369
+msgid "Power"
+msgstr "Encesa"
+
+#: oversteer/main.ui:364
+msgid ""
+"Enable or disable the wheel for the whole system. When disabled, no game or "
+"application can see it."
+msgstr "Activa o desactiva el volant per a tot el sistema. Quan està desactivat, cap joc o aplicació no el pot veure."
+
+#: oversteer/gui.py:178
+#, python-brace-format
+msgid "Re-enable {}"
+msgstr "Reactiva {}"
+
+#: oversteer/gui.py:214
+msgid "You don't have the required permissions to enable or disable the wheel."
+msgstr "No tens els permissos requerits per a activar o desactivar el volant."
+
#~ msgid "io.github.berarma.Oversteer"
#~ msgstr "io.github.berarma.Oversteer"
diff --git a/po/de.po b/po/de.po
index 4e91f7a..15e2973 100644
--- a/po/de.po
+++ b/po/de.po
@@ -908,5 +908,24 @@ msgstr "Lenkradmanager"
msgid "game;racing;cars;wheels"
msgstr "Spiele;Rennen;Autos;Lenkrad"
+#: oversteer/main.ui:369
+msgid "Power"
+msgstr "Ein/Aus"
+
+#: oversteer/main.ui:364
+msgid ""
+"Enable or disable the wheel for the whole system. When disabled, no game or "
+"application can see it."
+msgstr "Aktiviert oder deaktiviert das Lenkrad systemweit. Wenn deaktiviert, kann es kein Spiel und keine Anwendung sehen."
+
+#: oversteer/gui.py:178
+#, python-brace-format
+msgid "Re-enable {}"
+msgstr "{} wieder aktivieren"
+
+#: oversteer/gui.py:214
+msgid "You don't have the required permissions to enable or disable the wheel."
+msgstr "Keine Berechtigung, das Lenkrad zu aktivieren oder zu deaktivieren."
+
#~ msgid "io.github.berarma.Oversteer"
#~ msgstr "io.github.berarma.Oversteer"
diff --git a/po/es.po b/po/es.po
index be2fac5..0044955 100644
--- a/po/es.po
+++ b/po/es.po
@@ -918,6 +918,28 @@ msgstr "Configurador de volantes"
msgid "game;racing;cars;wheels"
msgstr "juego;carreras;coches;volantes"
+#: oversteer/main.ui:369
+msgid "Power"
+msgstr "Encendido"
+
+#: oversteer/main.ui:364
+msgid ""
+"Enable or disable the wheel for the whole system. When disabled, no game or "
+"application can see it."
+msgstr ""
+"Activa o desactiva el volante para todo el sistema. Cuando está desactivado, "
+"ningún juego o aplicación puede verlo."
+
+#: oversteer/gui.py:178
+#, python-brace-format
+msgid "Re-enable {}"
+msgstr "Reactivar {}"
+
+#: oversteer/gui.py:214
+msgid "You don't have the required permissions to enable or disable the wheel."
+msgstr ""
+"No tienes los permisos necesarios para activar o desactivar el volante."
+
#~ msgid "io.github.berarma.Oversteer"
#~ msgstr "io.github.berarma.Oversteer"
diff --git a/po/fi.po b/po/fi.po
index 79c34b6..f87aca8 100644
--- a/po/fi.po
+++ b/po/fi.po
@@ -909,3 +909,22 @@ msgstr "Rattimanageri"
#: data/io.github.berarma.Oversteer.desktop.in:12
msgid "game;racing;cars;wheels"
msgstr "peli;ajo;autot;ratit"
+
+#: oversteer/main.ui:369
+msgid "Power"
+msgstr "Virta"
+
+#: oversteer/main.ui:364
+msgid ""
+"Enable or disable the wheel for the whole system. When disabled, no game or "
+"application can see it."
+msgstr "Ota ratti käyttöön tai poista se käytöstä koko järjestelmässä. Kun se on poistettu käytöstä, mikään peli tai sovellus ei näe sitä."
+
+#: oversteer/gui.py:178
+#, python-brace-format
+msgid "Re-enable {}"
+msgstr "Ota {} uudelleen käyttöön"
+
+#: oversteer/gui.py:214
+msgid "You don't have the required permissions to enable or disable the wheel."
+msgstr "Sinulla ei ole tarvittavia oikeuksia ottaa rattia käyttöön tai poistaa sitä käytöstä."
diff --git a/po/gl.po b/po/gl.po
index c905505..209f19d 100644
--- a/po/gl.po
+++ b/po/gl.po
@@ -913,6 +913,25 @@ msgstr "Configurador de Volantes"
msgid "game;racing;cars;wheels"
msgstr "xogo;carreiras;coches;volantes"
+#: oversteer/main.ui:369
+msgid "Power"
+msgstr "Acendido"
+
+#: oversteer/main.ui:364
+msgid ""
+"Enable or disable the wheel for the whole system. When disabled, no game or "
+"application can see it."
+msgstr "Activa ou desactiva o volante para todo o sistema. Cando está desactivado, ningún xogo ou aplicación pode velo."
+
+#: oversteer/gui.py:178
+#, python-brace-format
+msgid "Re-enable {}"
+msgstr "Reactivar {}"
+
+#: oversteer/gui.py:214
+msgid "You don't have the required permissions to enable or disable the wheel."
+msgstr "Non tes os permisos necesarios para activar ou desactivar o volante."
+
#~ msgid "io.github.berarma.Oversteer"
#~ msgstr "io.github.berarma.Oversteer"
diff --git a/po/hu.po b/po/hu.po
index 38f9235..930e53b 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -926,5 +926,24 @@ msgstr "Kormánykerék-kezelő"
msgid "game;racing;cars;wheels"
msgstr "game;racing;cars;wheels;játék;verseny;autók;kormánykerék"
+#: oversteer/main.ui:369
+msgid "Power"
+msgstr "Be/Ki"
+
+#: oversteer/main.ui:364
+msgid ""
+"Enable or disable the wheel for the whole system. When disabled, no game or "
+"application can see it."
+msgstr "Engedélyezi vagy letiltja a kormánykereket az egész rendszer számára. Letiltva egyetlen játék vagy alkalmazás sem látja."
+
+#: oversteer/gui.py:178
+#, python-brace-format
+msgid "Re-enable {}"
+msgstr "{} újraengedélyezése"
+
+#: oversteer/gui.py:214
+msgid "You don't have the required permissions to enable or disable the wheel."
+msgstr "Nincs jogosultsága a kormánykerék engedélyezéséhez vagy letiltásához."
+
#~ msgid "io.github.berarma.Oversteer"
#~ msgstr "io.github.berarma.Oversteer"
diff --git a/po/pl.po b/po/pl.po
index 1f1240d..0288657 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -918,3 +918,22 @@ msgstr "Oversteer"
#: data/io.github.berarma.Oversteer.desktop.in:12
msgid "game;racing;cars;wheels"
msgstr "gra;wyścigi;auta;kierownice;"
+
+#: oversteer/main.ui:369
+msgid "Power"
+msgstr "Zasilanie"
+
+#: oversteer/main.ui:364
+msgid ""
+"Enable or disable the wheel for the whole system. When disabled, no game or "
+"application can see it."
+msgstr "Włącza lub wyłącza kierownicę dla całego systemu. Po wyłączeniu żadna gra ani aplikacja jej nie widzi."
+
+#: oversteer/gui.py:178
+#, python-brace-format
+msgid "Re-enable {}"
+msgstr "Włącz ponownie {}"
+
+#: oversteer/gui.py:214
+msgid "You don't have the required permissions to enable or disable the wheel."
+msgstr "Nie masz uprawnień by włączyć lub wyłączyć kierownicę."
diff --git a/po/ru.po b/po/ru.po
index 6e705a3..e950156 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -913,5 +913,24 @@ msgstr "Мастер настройки руля"
msgid "game;racing;cars;wheels"
msgstr "игра;гонки;автомобили;рули"
+#: oversteer/main.ui:369
+msgid "Power"
+msgstr "Питание"
+
+#: oversteer/main.ui:364
+msgid ""
+"Enable or disable the wheel for the whole system. When disabled, no game or "
+"application can see it."
+msgstr "Включает или отключает руль для всей системы. В отключённом состоянии его не видит ни одна игра или приложение."
+
+#: oversteer/gui.py:178
+#, python-brace-format
+msgid "Re-enable {}"
+msgstr "Снова включить {}"
+
+#: oversteer/gui.py:214
+msgid "You don't have the required permissions to enable or disable the wheel."
+msgstr "У вас нет необходимых разрешений для включения или отключения руля."
+
#~ msgid "io.github.berarma.Oversteer"
#~ msgstr "io.github.berarma.Oversteer"
diff --git a/po/tr.po b/po/tr.po
index ff7c561..1fd0854 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -912,6 +912,25 @@ msgstr "Direksiyon Yöneticisi"
msgid "game;racing;cars;wheels"
msgstr "oyun;yarış;arabalar;direksiyonlar"
+#: oversteer/main.ui:369
+msgid "Power"
+msgstr "Güç"
+
+#: oversteer/main.ui:364
+msgid ""
+"Enable or disable the wheel for the whole system. When disabled, no game or "
+"application can see it."
+msgstr "Direksiyonu tüm sistem için etkinleştirir veya devre dışı bırakır. Devre dışı bırakıldığında hiçbir oyun veya uygulama onu göremez."
+
+#: oversteer/gui.py:178
+#, python-brace-format
+msgid "Re-enable {}"
+msgstr "{} cihazını yeniden etkinleştir"
+
+#: oversteer/gui.py:214
+msgid "You don't have the required permissions to enable or disable the wheel."
+msgstr "Direksiyonu etkinleştirmek veya devre dışı bırakmak için gerekli izinlere sahip değilsiniz."
+
#~ msgid "io.github.berarma.Oversteer"
#~ msgstr "io.github.berarma.Oversteer"