diff --git a/src/revpi_middleware/dbus_middleware1/system_config/interface_config.py b/src/revpi_middleware/dbus_middleware1/system_config/interface_config.py index 0e96390..0356ba8 100644 --- a/src/revpi_middleware/dbus_middleware1/system_config/interface_config.py +++ b/src/revpi_middleware/dbus_middleware1/system_config/interface_config.py @@ -8,6 +8,7 @@ from logging import getLogger from .revpi_config import ( ConfigActions, configure_avahi_daemon, + configure_bluetooth, configure_con_can, configure_dphys_swapfile, configure_external_antenna, @@ -92,7 +93,7 @@ AVAILABLE_FEATURES = { simple_systemd, ["noderedrevpinodes-server.service"] ), "revpipyload": FeatureFunction(simple_systemd, ["revpipyload.service"]), - "bluetooth": False, + "bluetooth": FeatureFunction(configure_bluetooth, []), "ieee80211": FeatureFunction(configure_wifi, []), "avahi": FeatureFunction(configure_avahi_daemon, []), "external-antenna": FeatureFunction(configure_external_antenna, []), diff --git a/src/revpi_middleware/dbus_middleware1/system_config/revpi_config.py b/src/revpi_middleware/dbus_middleware1/system_config/revpi_config.py index da1832c..5b99432 100644 --- a/src/revpi_middleware/dbus_middleware1/system_config/revpi_config.py +++ b/src/revpi_middleware/dbus_middleware1/system_config/revpi_config.py @@ -20,6 +20,7 @@ log = getLogger(__name__) ConfigVariable = namedtuple("ConfigVariable", ["name", "value", "line_index"]) +LINUX_BT_CLASS_PATH = "/sys/class/bluetooth" LINUX_WIFI_CLASS_PATH = "/sys/class/ieee80211" CONFIG_TXT_LOCATIONS = ("/boot/firmware/config.txt", "/boot/config.txt") @@ -212,6 +213,40 @@ def configure_avahi_daemon(action: ConfigActions): return return_value +def configure_bluetooth(action: ConfigActions): + hci_device = join(LINUX_BT_CLASS_PATH, "hci0") + bt_rfkill_index = get_rfkill_index(hci_device) + + # If the bluetooth device is not present, the device should have been + # brought up by revpi-bluetooth's udev rules or vendor magic (devices + # based on CM4 and newer). Nothing we can do here, so treat the interface + # as disabled. + + if action is ConfigActions.ENABLE: + if bt_rfkill_index is not None: + subprocess.call(["rfkill", "unblock", str(bt_rfkill_index)]) + + elif action is ConfigActions.DISABLE: + if bt_rfkill_index is not None: + subprocess.call(["rfkill", "block", str(bt_rfkill_index)]) + + elif action is ConfigActions.STATUS: + if bt_rfkill_index is None: + return False + + with open(f"/sys/class/rfkill/rfkill{bt_rfkill_index}/soft", "r") as f: + buffer = f.read().strip() + return buffer == "0" + + elif action is ConfigActions.AVAILABLE: + return bt_rfkill_index is not None + + else: + raise ValueError(f"action {action} not supported") + + return None + + def configure_con_can(action: ConfigActions): revpi = RevPiConfig() if action is ConfigActions.AVAILABLE: