Skip to content

Latest commit

 

History

History
60 lines (35 loc) · 8.8 KB

File metadata and controls

60 lines (35 loc) · 8.8 KB

Linux / BlueZ

The experimental Linux backend runs the existing Switch2Kit controller engine against BlueZ's system D-Bus GATT API. Swift hosts use Switch2ControllerManager; native hosts use the same Switch2KitC ABI and in-process SDL3 adapter as on macOS. It is a real radio implementation, not a fixture-only factory or a network bridge. Windows has a separate WinRT backend; Android has no backend.

Requirements and connection

Build with Swift 6.2 or later on a supported glibc Linux distribution. Native hosts also need CMake 3.24+, a C/C++ compiler, and their normal dependencies. Runtime requires compatible Swift libraries, libsystemd.so.0 (the sd-bus client library), a running BlueZ service, and a powered LE-capable adapter. The system itself need not use systemd as PID 1. The GATT characteristic MTU property must report a sufficient negotiated ATT MTU for complete controller commands; missing MTU uses the conservative 20-byte write limit rather than guessing or splitting protocol frames.

swift build --product Switch2KitC
swift test -Xswiftc -warnings-as-errors

Create the manager on the main actor, or call s2k_create on the main thread. Creation does not open the radio. Start support, request discovery, then hold Sync on the controller. The C polling API does not need a Linux GUI event loop; Swift hosts using main-actor presentation snapshots must keep their executor running. Combine/SwiftUI and the dashboard remain macOS features; use observation or currentSnapshot on Linux.

The process uses the normal system-bus address and BlueZ permissions. It does not change adapter power, install permissive D-Bus rules, invoke sudo, call BlueZ Pair/RemoveDevice, or erase stored device bonds. A denied bus or GATT operation is reported rather than bypassed. Nintendo's existing controller-protocol bond handshake is separate from operating-system pairing; on Sync discovery it uses the selected adapter's address. Stop another application's connection before claiming the same controller.

The first powered adapter is selected deterministically; an already-selected powered adapter is retained. Selection is automatic in this initial backend, not a public adapter-selection API. An adapter reset closes the current manual discovery window; request discovery again on the replacement adapter. A Bluetooth daemon restart invalidates connections and refreshes the object model. After a system-bus failure, resolve the underlying service/access problem and stop/start the manager.

Ownership, identity and bounds

Native asynchronous D-Bus calls and notifications run on the existing serial Bluetooth queue. The existing handshake, input parser, motion profiles, rumble expiry, event hub and connection-generation checks are reused. No controller protocol is reimplemented in the BlueZ binding. Notification delivery is event-driven, not a subprocess or a fixed-rate polling loop.

Only fresh, recognized Nintendo manufacturer data observed during discovery admits a controller. Cached startup objects and already-connected devices are not silently claimed. Discovery sessions and connections are released explicitly. Cancellation fences delayed replies; teardown clears published input before releasing the radio. Disconnect completion can follow the API's logical stop boundary.

Physical IDs are name-based UUIDs of the adapter address, remote address type and remote address. They are stable across reconnects with that tuple, without a new settings file. They are not a cryptographic anonymization guarantee. A different adapter or rotating device address changes identity; migration from macOS CoreBluetooth IDs is not automatic. Connection IDs still change on every reconnect.

Writes are bounded to one outstanding D-Bus write per physical device and the characteristic's negotiated write limit. Existing motor coalescing and expiry remain authoritative; the adapter never accumulates a separate queue of old motor packets. D-Bus parsing, object storage, pending requests and service enumeration are bounded. Services, notification loss and radio changes retire the affected connection rather than retaining held input.

Native emulators and installation

For playing games, start with the maintained Dolphin fork or Cemu fork. Their build helpers enable Switch2Kit and install its native library; no source patches or separate dashboard are needed. Downloads are development builds for the distribution identified by the workflow, not universal Linux binaries.

For the SDK's separate pinned source-patch examples, follow the Dolphin/Cemu source integration guide, using Linux dependencies instead of Xcode, Homebrew or MoltenVK. Both optional patches accept Linux with SDL enabled; Dolphin also requires Qt. The build helper selects Linux arguments, builds all enabled upstream installation targets, and retains the targeted macOS bundle build on Apple hosts. The emulator owns the same discovery UI and controller lifecycle; no dashboard is required.

bash scripts/build-switch2kit-emulator.sh dolphin /path/to/patched/dolphin /path/to/build
cmake --install /path/to/build --prefix /path/to/install

switch2kit_install_linux(target) installs the C library, its compiler-selected Swift runtime dependency closure, and complete license/attribution notices. It adds the relative library directory to the host's install RPATH and removes compiler-specific search paths from the packaged ELF copies, not from the original toolchain files. Host executables must be installed into CMAKE_INSTALL_BINDIR; the supplied integrations do so. Build-tree executables use CMake's normal build RPATH. switch2kit_embed remains the macOS bundle helper.

Keep the entire installed directory layout when extracting or relocating a package. A successfully staged application does not require a Swift compiler installation or LD_LIBRARY_PATH override at launch:

/path/to/install/bin/dolphin-emu
# Or: /path/to/install/bin/Cemu_release

This is not a universal self-contained Linux app bundle. Compatible glibc, C++ and desktop libraries, graphics drivers, libsystemd.so.0, and the BlueZ service remain system prerequisites. Use the distribution/architecture identified by the application workflow and require successful native build and extracted-package checks for that revision. A source archive is not an application, and copying only the emulator executable is insufficient.

swift build alone builds the SDK rather than staging a host application. Runtime-license selection is provided for Swift 6.2.1 and 6.3.3; other distributions need their complete Swift license and ICU third-party notices supplied through SWITCH2KIT_SWIFT_LICENSE and SWITCH2KIT_RUNTIME_ICU_LICENSE. Missing libraries or notices are packaging errors to resolve, not a reason to bypass the loader or omit license texts.

Verification and hardware boundary

bash tests/linux-bluez/run.sh starts a private D-Bus daemon and synthetic BlueZ service, then exercises the actual Linux library through an independent C++ consumer. It covers all four controller models, full session handshakes and adapter-address bonding, button edges, raw motion, analog trigger data, motor writes, stable identity/reconnect, stale handles, ownership, permission failures, missing services, write limits, cancellation, invalidation and malformed input. It does not touch the system Bluetooth service or a physical controller. Python is only a test dependency.

The Linux workflow runs package, radio, retained portable and real-SDL tests, builds both pinned Dolphin and Cemu applications, and checks their installed native-library dependencies after relocation with the original build paths unavailable. python3 tests/linux-runtime/verify.py separately executes real C++ consumers against the relocated facade and checks that removing it fails at the loader. A configured CI job is not a successful run until its results are checked. Full Linux Cemu execution, controller firmware/radio compatibility, measured motion, physical rumble and gameplay still require hardware qualification. Record Linux distribution/kernel, BlueZ version, adapter, controller model/firmware, source revision, input, reconnect and motor start/stop observations; do not relabel an existing macOS acceptance record as Linux evidence. Linux source/fixture success is not proof of those outcomes; retain the existing hardware acceptance procedure.

The existing motion calibration tool can discover and capture through this backend. The Linux path uses the same C reader, freshness checks and operator-supplied measurements; it does not supply premeasured profiles.