diff --git a/ADAPTER_PARITY_PLAN.md b/ADAPTER_PARITY_PLAN.md index 8644fe2..b3e67d5 100644 --- a/ADAPTER_PARITY_PLAN.md +++ b/ADAPTER_PARITY_PLAN.md @@ -119,7 +119,8 @@ The final Windows fix uses a distinct probe device revision because Windows cach Current test artifact: -- `firmware/switch-pico-adapter-feasibility.uf2` +- `firmware/switch-pico-aio.uf2` (includes the automatic Switch/XInput behavior; + the separate feasibility build has been retired). Windows test command: diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dfbb34..b1f21bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,8 +24,6 @@ if (EXISTS ${picoVscode}) endif() # ==================================================================================== option(SWITCH_PICO_LOG "Enable UART debug logging" OFF) -option(SWITCH_PICO_ADAPTER_FEASIBILITY - "Build the automatic Switch/XInput feasibility prototype" OFF) if(SWITCH_PICO_INPUT_BACKEND STREQUAL "BLUEPAD32") set(SWITCH_PICO_NATIVE_DEFAULT ON) set(SWITCH_PICO_CLOCK_DEFAULT 300) @@ -119,11 +117,6 @@ if(SWITCH_PICO_INPUT_BACKEND STREQUAL "BLUEPAD32" message(FATAL_ERROR "SWITCH_PICO_INPUT_BACKEND=BLUEPAD32 requires PICO_BOARD=pico2_w") endif() -if(SWITCH_PICO_ADAPTER_FEASIBILITY - AND NOT SWITCH_PICO_INPUT_BACKEND STREQUAL "BLUEPAD32") - message(FATAL_ERROR - "SWITCH_PICO_ADAPTER_FEASIBILITY requires the BLUEPAD32 backend") -endif() if(SWITCH_PICO_HAPTICS_EXPERIMENT AND NOT SWITCH_PICO_INPUT_BACKEND STREQUAL "BLUEPAD32") message(FATAL_ERROR diff --git a/README.md b/README.md index 5a0eb98..f88c9a3 100644 --- a/README.md +++ b/README.md @@ -57,10 +57,18 @@ Build and flash a Pico 2 W in BOOTSEL mode: python3 build.py --aio ``` -This uses an isolated `build-aio/` CMake cache and publishes: +This uses an isolated `build-aio/` CMake cache. The main firmware variants are: -- `firmware/switch-pico-aio.elf` -- `firmware/switch-pico-aio.uf2` +| Variant | UF2 image | +| --- | --- | +| Regular Pico, UART input | [switch-pico.uf2](firmware/switch-pico.uf2) | +| Pico 2 W AIO, mixed Bluetooth | [switch-pico-aio.uf2](firmware/switch-pico-aio.uf2) | +| Pico 2 W AIO, BLE only | [switch-pico-aio-ble.uf2](firmware/switch-pico-aio-ble.uf2) | +| Pico 2 W AIO, Classic only | [switch-pico-aio-classic.uf2](firmware/switch-pico-aio-classic.uf2) | + +Each image has a matching `.elf` in `firmware/`. All AIO variants include the same +automatic Switch/XInput and manual USB output modes; no separate feasibility +firmware is needed. The wake-capture image remains a separate setup utility. The default `python3 build.py` command and `firmware/switch-pico.*` artifacts remain the UART/Pico build. The AIO build requires `PICO_BOARD=pico2_w`; it is not interchangeable with the original non-wireless Pico firmware. @@ -87,7 +95,7 @@ cmake --build build-aio-ble ``` Use `CLASSIC` or `MIXED` and a matching build directory for the other modes. -Add `-DSWITCH_PICO_ADAPTER_FEASIBILITY=ON` for automatic Switch/XInput output. +Every AIO build includes automatic Switch/XInput and manual USB output modes. Invalid modes and single-transport selections with the UART backend are rejected. The build helper also supports the selector; these commands **build and flash**: @@ -95,7 +103,7 @@ The build helper also supports the selector; these commands **build and flash**: ```sh python3 build.py --aio --bluetooth-mode ble python3 build.py --aio --bluetooth-mode classic -python3 build.py --adapter-feasibility --bluetooth-mode ble +python3 build.py --aio --bluetooth-mode mixed ``` The helper defaults explicitly to `mixed`. Single-transport build directories and @@ -812,7 +820,7 @@ were created, copies the release artifacts into `firmware/`, and flashes the ELF with `picotool`. `build.py` automatically locates the Pico SDK and Arm GNU toolchain from valid -existing `build/`, `build-aio/`, or `build-feasibility/` CMake caches, then from +existing regular, AIO (including BLE/Classic), and wake-capture CMake caches, then from project-local `build/_deps/pico_sdk-src` and `build/toolchain` installs, and finally from conventional user and system locations. A compiler already on `PATH` is used without setting a toolchain override. Explicit `PICO_SDK_PATH` diff --git a/build.py b/build.py index bfdee1e..13cb11f 100755 --- a/build.py +++ b/build.py @@ -15,7 +15,6 @@ FIRMWARE_SOURCE_DIR = SCRIPT_DIR / "src" / "firmware" CONFIG_FILE = FIRMWARE_SOURCE_DIR / "platform" / "pico" / "controller_color_config.h" BUILD_DIR = SCRIPT_DIR / "build" AIO_BUILD_DIR = SCRIPT_DIR / "build-aio" -FEASIBILITY_BUILD_DIR = SCRIPT_DIR / "build-feasibility" WAKE_CAPTURE_SOURCE_DIR = SCRIPT_DIR / "tools" / "switch2_wake_capture" WAKE_CAPTURE_BUILD_DIR = SCRIPT_DIR / "build-wake-capture" FIRMWARE_DIR = SCRIPT_DIR / "firmware" @@ -23,8 +22,6 @@ FIRMWARE_ELF_PATH = FIRMWARE_DIR / "switch-pico.elf" FIRMWARE_UF2_PATH = FIRMWARE_DIR / "switch-pico.uf2" AIO_FIRMWARE_ELF_PATH = FIRMWARE_DIR / "switch-pico-aio.elf" AIO_FIRMWARE_UF2_PATH = FIRMWARE_DIR / "switch-pico-aio.uf2" -FEASIBILITY_FIRMWARE_ELF_PATH = FIRMWARE_DIR / "switch-pico-adapter-feasibility.elf" -FEASIBILITY_FIRMWARE_UF2_PATH = FIRMWARE_DIR / "switch-pico-adapter-feasibility.uf2" WAKE_CAPTURE_FIRMWARE_ELF_PATH = FIRMWARE_DIR / "switch-pico-wake-capture.elf" WAKE_CAPTURE_FIRMWARE_UF2_PATH = FIRMWARE_DIR / "switch-pico-wake-capture.uf2" @@ -42,11 +39,9 @@ CMAKE_CACHE_PATHS = tuple( for build_dir in ( BUILD_DIR, AIO_BUILD_DIR, - FEASIBILITY_BUILD_DIR, WAKE_CAPTURE_BUILD_DIR, *( - base.with_name(f"{base.name}-{mode}") - for base in (AIO_BUILD_DIR, FEASIBILITY_BUILD_DIR) + AIO_BUILD_DIR.with_name(f"{AIO_BUILD_DIR.name}-{mode}") for mode in ("ble", "classic") ), ) @@ -282,11 +277,6 @@ def parse_args(): action="store_true", help="Build and flash the Pico 2 W Bluepad32 all-in-one firmware.", ) - mode_group.add_argument( - "--adapter-feasibility", - action="store_true", - help="Build and flash the Pico 2 W automatic Switch/XInput prototype.", - ) mode_group.add_argument( "--wake-capture", action="store_true", @@ -296,7 +286,7 @@ def parse_args(): "--bluetooth-mode", choices=("mixed", "ble", "classic"), default="mixed", - help="Select active Bluetooth transports for --aio or --adapter-feasibility.", + help="Select active Bluetooth transports for --aio.", ) group = parser.add_mutually_exclusive_group() group.add_argument( @@ -312,8 +302,8 @@ def parse_args(): args = parser.parse_args() if args.wake_capture and (args.random_grip_color or args.grip_color): parser.error("wake capture firmware does not use grip-color options") - if args.bluetooth_mode != "mixed" and not (args.aio or args.adapter_feasibility): - parser.error("--bluetooth-mode requires --aio or --adapter-feasibility") + if args.bluetooth_mode != "mixed" and not args.aio: + parser.error("--bluetooth-mode requires --aio") return args @@ -392,7 +382,6 @@ def resolve_picotool(): def build( aio, - adapter_feasibility, build_dir, elf_path, uf2_path, @@ -401,23 +390,21 @@ def build( *, bluetooth_mode="mixed", ): - if aio or adapter_feasibility: + if aio: definitions = [ "-DSWITCH_PICO_LOG=OFF", "-DPICO_BOARD=pico2_w", "-DSWITCH_PICO_INPUT_BACKEND=BLUEPAD32", ] - if adapter_feasibility: - definitions.append("-DSWITCH_PICO_ADAPTER_FEASIBILITY=ON") else: definitions = [ "-DSWITCH_PICO_LOG=OFF", "-DPICO_BOARD=pico", "-DSWITCH_PICO_INPUT_BACKEND=UART", ] - # AIO and XInput images use the qualified native transport by default. + # AIO includes all USB output modes and uses the native transport by default. # UART remains unchanged; explicit flags also prevent stale cache choices. - native = "ON" if aio or adapter_feasibility else "OFF" + native = "ON" if aio else "OFF" definitions.extend( [ f"-DSWITCH_PICO_BLUETOOTH_MODE={bluetooth_mode.upper()}", @@ -529,13 +516,7 @@ def main(): update_grip_colors(color) print(f"Grip color set to #{color} in {CONFIG_FILE.name}") - if args.adapter_feasibility: - build_dir = FEASIBILITY_BUILD_DIR - elf_path = FEASIBILITY_BUILD_DIR / "switch-pico.elf" - uf2_path = FEASIBILITY_BUILD_DIR / "switch-pico.uf2" - firmware_elf_path = FEASIBILITY_FIRMWARE_ELF_PATH - firmware_uf2_path = FEASIBILITY_FIRMWARE_UF2_PATH - elif args.aio: + if args.aio: build_dir = AIO_BUILD_DIR elf_path = AIO_BUILD_DIR / "switch-pico.elf" uf2_path = AIO_BUILD_DIR / "switch-pico.uf2" @@ -558,7 +539,6 @@ def main(): build( args.aio, - args.adapter_feasibility, build_dir, elf_path, uf2_path, @@ -568,7 +548,7 @@ def main(): ) flash( elf_path, - allow_elf_override=not args.aio and not args.adapter_feasibility, + allow_elf_override=not args.aio, ) diff --git a/firmware/switch-pico-adapter-feasibility.elf b/firmware/switch-pico-aio-ble.elf similarity index 57% rename from firmware/switch-pico-adapter-feasibility.elf rename to firmware/switch-pico-aio-ble.elf index 031d9ff..aba7d86 100755 Binary files a/firmware/switch-pico-adapter-feasibility.elf and b/firmware/switch-pico-aio-ble.elf differ diff --git a/firmware/switch-pico-adapter-feasibility.uf2 b/firmware/switch-pico-aio-ble.uf2 similarity index 55% rename from firmware/switch-pico-adapter-feasibility.uf2 rename to firmware/switch-pico-aio-ble.uf2 index e3b2671..ab20a62 100644 Binary files a/firmware/switch-pico-adapter-feasibility.uf2 and b/firmware/switch-pico-aio-ble.uf2 differ diff --git a/firmware/switch-pico-aio-classic.elf b/firmware/switch-pico-aio-classic.elf new file mode 100755 index 0000000..68105a0 Binary files /dev/null and b/firmware/switch-pico-aio-classic.elf differ diff --git a/firmware/switch-pico-aio-classic.uf2 b/firmware/switch-pico-aio-classic.uf2 new file mode 100644 index 0000000..f3d06ed Binary files /dev/null and b/firmware/switch-pico-aio-classic.uf2 differ diff --git a/firmware/switch-pico-aio.elf b/firmware/switch-pico-aio.elf index 214746b..21eea6a 100755 Binary files a/firmware/switch-pico-aio.elf and b/firmware/switch-pico-aio.elf differ diff --git a/firmware/switch-pico-aio.uf2 b/firmware/switch-pico-aio.uf2 index e3b2671..34e8dd6 100644 Binary files a/firmware/switch-pico-aio.uf2 and b/firmware/switch-pico-aio.uf2 differ diff --git a/tests/test_bluepad32_backend_lifecycle_native.py b/tests/test_bluepad32_backend_lifecycle_native.py index 1b6cb41..f773b92 100644 --- a/tests/test_bluepad32_backend_lifecycle_native.py +++ b/tests/test_bluepad32_backend_lifecycle_native.py @@ -10,23 +10,14 @@ def test_bluepad32_backend_lifecycle_native(tmp_path: Path) -> None: compiler = shutil.which("c++") or shutil.which("g++") assert compiler is not None, "a host C++ compiler is required" - for bluetooth_mode, adapter_feasibility, native, short_packets in ( - ("mixed", False, False, False), - ("mixed", True, False, False), - ("mixed", True, True, False), - ("mixed", True, True, True), - ("ble", False, False, False), - ("classic", False, False, False), + for bluetooth_mode, native, short_packets in ( + ("mixed", False, False), + ("mixed", True, False), + ("mixed", True, True), + ("ble", False, False), + ("classic", False, False), ): - suffix = ( - "_native32" - if short_packets - else "_native64" - if native - else "_adapter" - if adapter_feasibility - else "" - ) + suffix = "_native32" if short_packets else "_native64" if native else "" executable = ( tmp_path / f"bluepad32_backend_lifecycle_test_{bluetooth_mode}{suffix}" ) @@ -38,11 +29,10 @@ def test_bluepad32_backend_lifecycle_native(tmp_path: Path) -> None: "-Werror", "-pedantic", "-DSWITCH_PICO_HID_INSTANCE_COUNT=4", + "-DSWITCH_PICO_USB_OUTPUT_MODES=1", f"-DSWITCH_PICO_ENABLE_BLE={int(bluetooth_mode != 'classic')}", f"-DSWITCH_PICO_ENABLE_CLASSIC={int(bluetooth_mode != 'ble')}", ] - if adapter_feasibility: - command.append("-DSWITCH_PICO_USB_OUTPUT_MODES=1") if native: command.extend( [ diff --git a/tests/test_build.py b/tests/test_build.py index 4595d69..785d355 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -209,14 +209,11 @@ def build_cli(tmp_path, monkeypatch): "CONFIG_FILE", "BUILD_DIR", "AIO_BUILD_DIR", - "FEASIBILITY_BUILD_DIR", "FIRMWARE_DIR", "FIRMWARE_ELF_PATH", "FIRMWARE_UF2_PATH", "AIO_FIRMWARE_ELF_PATH", "AIO_FIRMWARE_UF2_PATH", - "FEASIBILITY_FIRMWARE_ELF_PATH", - "FEASIBILITY_FIRMWARE_UF2_PATH", ): original = getattr(build_script, name) monkeypatch.setattr(build_script, name, tmp_path / original.relative_to(ROOT)) @@ -247,24 +244,13 @@ def build_cli(tmp_path, monkeypatch): return commands -@pytest.mark.parametrize( - ("variant", "directory", "artifact"), - [ - ("--aio", "build-aio", "switch-pico-aio"), - ( - "--adapter-feasibility", - "build-feasibility", - "switch-pico-adapter-feasibility", - ), - ], -) def test_bluetooth_modes_configure_and_publish_isolated_artifacts( - tmp_path, monkeypatch, build_cli, variant, directory, artifact + tmp_path, monkeypatch, build_cli ): # Switch away from mixed and back, leaving every other image untouched. published = {} for mode in (None, "ble", "classic", "mixed"): - arguments = ["build.py", variant] + arguments = ["build.py", "--aio"] if mode is not None: arguments.extend(["--bluetooth-mode", mode]) monkeypatch.setattr(build_script.sys, "argv", arguments) @@ -272,14 +258,11 @@ def test_bluetooth_modes_configure_and_publish_isolated_artifacts( selected = mode or "mixed" suffix = "" if selected == "mixed" else f"-{selected}" - build_dir = tmp_path / f"{directory}{suffix}" + build_dir = tmp_path / f"build-aio{suffix}" configure, compile_command, flash_command = build_cli[-3:] assert configure[:5] == ["cmake", "-S", str(tmp_path), "-B", str(build_dir)] assert f"-DSWITCH_PICO_BLUETOOTH_MODE={selected.upper()}" in configure assert "-DSWITCH_PICO_INPUT_BACKEND=BLUEPAD32" in configure - assert ("-DSWITCH_PICO_ADAPTER_FEASIBILITY=ON" in configure) == ( - variant == "--adapter-feasibility" - ) assert compile_command == ["cmake", "--build", str(build_dir)] assert flash_command == [ "picotool", @@ -288,8 +271,8 @@ def test_bluetooth_modes_configure_and_publish_isolated_artifacts( "-fx", ] for extension in ("elf", "uf2"): - destination = tmp_path / "firmware" / f"{artifact}{suffix}.{extension}" - published[destination] = f"{directory}{suffix}:{extension}".encode() + destination = tmp_path / "firmware" / f"switch-pico-aio{suffix}.{extension}" + published[destination] = f"build-aio{suffix}:{extension}".encode() for destination, expected in published.items(): assert destination.read_bytes() == expected