swbt-python 0.5.2__tar.gz → 0.5.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {swbt_python-0.5.2 → swbt_python-0.5.4}/PKG-INFO +2 -2
- {swbt_python-0.5.2 → swbt_python-0.5.4}/pyproject.toml +2 -2
- swbt_python-0.5.4/spec/complete/unit_083/PROFILE_SCHEMA_V2_CURRENT_KEY_ONLY.md +133 -0
- swbt_python-0.5.4/spec/complete/unit_086/NORMAL_INPUT_READINESS.md +297 -0
- swbt_python-0.5.4/spec/dev-journal.md +17 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/hardware-test-log.md +140 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/initial/api.md +12 -3
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/initial/architecture.md +4 -4
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/initial/lifecycle.md +16 -12
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/initial/protocol.md +1 -1
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/initial/testing.md +8 -4
- swbt_python-0.5.4/spec/wip/unit_084/BUMBLE_0_0_233.md +142 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/gamepad/interface.py +18 -14
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/gamepad/runtime.py +93 -23
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/report_loop.py +11 -0
- swbt_python-0.5.4/src/swbt/transport/_bumble_acl.py +17 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/_bumble_key_store.py +2 -28
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/_bumble_lifecycle.py +28 -54
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/_pairing_profile.py +7 -11
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/bumble.py +8 -7
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/gamepad_factory.py +21 -1
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/hardware/test_pairing_profile.py +4 -4
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/hardware/test_reply_holdoff.py +74 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/integration/test_examples.py +3 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/integration/test_pairing_profile.py +3 -4
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/integration/test_switch_gamepad_fake_transport.py +374 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/fixtures/source_audit/switch_protocol_values.toml +9 -11
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_bumble_acl.py +2 -3
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_bumble_lifecycle.py +7 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_bumble_transport.py +75 -21
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_pairing_profile.py +34 -14
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_pairing_profile_runtime.py +15 -4
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_report_loop.py +78 -0
- swbt_python-0.5.2/spec/dev-journal.md +0 -3
- swbt_python-0.5.2/src/swbt/transport/_bumble_acl.py +0 -33
- {swbt_python-0.5.2 → swbt_python-0.5.4}/AGENTS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/LICENSE +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/README.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/examples/hardware_bringup.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/examples/pairing_probe.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/examples/tap_a.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_001/M0_PROTOCOL_CORE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_002/M1_SWITCH_GAMEPAD_FAKE_TRANSPORT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_003/M2_BUMBLE_HID_TRANSPORT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_004/M3_PAIRING_L2CAP.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_005/M4_SUBCOMMAND_RESPONDER_HARDWARE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_006/M5_INPUT_OPERATION_API.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_007/M6_RECONNECT_KEYSTORE_DIAGNOSTICS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_008/M7_PACKAGING_EXAMPLES_CLI.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_009/PORTING_SOURCE_AUDIT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_010/DIAGNOSTICS_TRACE_SCHEMA.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_011/HARDWARE_TEST_LOG_MATRIX.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_012/INITIAL_RELEASE_GATE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_013/POST_M5_INPUT_SEMANTIC_CHARACTERIZATION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_014/DEVICE_CLOSE_GRACEFUL_DISCONNECT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_015/CONTEXT_MANAGER_RESOURCE_SCOPE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_016/JSON_KEY_STORE_CURRENT_PREVIOUS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_017/SWITCH_GAMEPAD_API_HARDENING.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_018/KEY_STORE_TRANSPORT_BOUNDARY.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_019/TRANSPORT_RECONNECT_CONTRACT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_020/STRUCTURAL_REFACTOR_BOUNDARIES.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_021/SWITCH_GAMEPAD_INPUT_API_CONTRACT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_022/PUBLIC_API_USAGE_HARDWARE_DOCS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_023/MKDOCS_DOCUMENTATION_SITE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_024/STICK_INPUT_SHORTHAND_API.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_025/IMU_INPUT_SHORTHAND_API.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_026/LINUX_MACOS_ADAPTER_EXPERIMENTAL.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_027/ADAPTER_DISCOVERY_API.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_028/CONTROLLER_PROFILE_CUSTOMIZATION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_029/CONTROLLER_PROFILE_INJECTION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_030/JOYCON_PROFILE_IDENTITY_SPI.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_031/JOYCON_INPUT_REPORT_MAPPING.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_032/PROFILE_AWARE_SUBCOMMAND_STATE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_033/PROFILE_AWARE_BUMBLE_SDP.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_034/JOYCON_CONVENIENCE_API_DOCS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_035/JOYCON_DEVICE_INFO_ADDRESS_WIRING.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_036/JOYCON_SDP_IDENTITY_POLICY.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_037/JOYCON_DEFAULT_CONTROLLER_COLORS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_038/REARCHITECTURE_DECISION_BOUNDARY_TESTS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_039/CONTROLLER_RUNTIME_EXTRACTION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_040/PUBLIC_CONTROLLER_API_MODEL.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_041/CONTROLLER_CONFIG_PROFILE_OWNERSHIP.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_042/INTERNAL_TRANSPORT_FACTORY.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_043/PROTOCOL_PROFILE_MODULE_SPLIT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_044/REARCHITECTURE_DOCS_RELEASE_MATRIX.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_045/INTERNAL_API_BOUNDARY_CLEANUP.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_046/HARDWARE_PROFILE_TEST_SCENARIOS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_047/VIRTUAL_GYRO_CALIBRATION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_048/VIRTUAL_ACCELEROMETER_CALIBRATION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_049/IMU_SESSION_AND_ENCODING_REDESIGN.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_050/DIRECT_REPORTING_TYPES.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_051/CSR_BD_ADDR_REWRITE_EXPERIMENT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_052/EXP_LOCAL_ADDRESS_PROFILE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_053/EXP_LOCAL_ADDRESS_PROFILE_JOYCON.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_054/EXP_LOCAL_ADDRESS_PROFILE_DIRECT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_055/REMOVE_NATIVE_KEY_STORE_API.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_056/PAIRING_PROFILE_NAMING.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_057/PAIRING_PROFILE_CONTROLLER_KIND.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_058/MULTI_ADDRESS_RECONNECT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_059/EXPERIMENTAL_DIRECT_SEND_TIMING_PROBE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_060/HCI_ACL_COMPLETION_CORRELATION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_061/EXPERIMENTAL_CLASSIC_LINK_POLICY_AB.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_062/PERIODIC_ACL_DRAIN_CHARACTERIZATION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_063/PERIODIC_NO_DRAIN_CHARACTERIZATION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_064/BUMBLE_ENQUEUE_COMPLETION_CONTRACT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_065/PERIODIC_DEADLINE_SCHEDULER.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_066/PAIRING_PROFILE_DEFAULT_ADDRESS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_067/DEFAULT_BATTERY_STATUS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_068/DIRECT_PRE_CLOSE_INPUT_REFLECTION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_069/CONTROLLER_HANDSHAKE_READINESS.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_070/DIAGNOSTICS_AND_UNUSED_PATHS_CLEANUP.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_071/CONTROLLER_CONSTRUCTION_PATH.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_072/CONNECTION_RUNTIME_INTEGRATION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_073/TEST_CONTRACT_BOUNDARY_CLEANUP.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_074/PUBLIC_GAMEPAD_IMPLEMENTATION_OWNERSHIP.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_075/CONCRETE_CONTROLLER_MODULE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_076/HARDWARE_HAPPY_CASE_VALIDATION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_077/RUNTIME_INPUT_UPDATE_DISPATCH.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_078/TEST_RUNTIME_FIXTURES.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_079/PAIRING_PROFILE_KEY_STORE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_080/TRANSPORT_PROTOCOL_CONTRACT.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_081/PROTOCOL_HANDSHAKE.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/complete/unit_082/REPLY_HOLDOFF_VALIDATION.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/initial/README.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/initial/naming.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/initial/risks.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/initial/roadmap.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/initial/transport-bumble.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/rearchitecture/01-design-change-overview.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/rearchitecture/02-as-is-to-be.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/rearchitecture/03-public-api-config-profile.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/rearchitecture/04-runtime-profile-transport-details.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/rearchitecture/05-milestones-implementation.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/rearchitecture/README.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/spec/rearchitecture/mkdocs-nav-snippet.yml +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/__init__.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/adapter_discovery.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/diagnostics.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/errors.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/gamepad/__init__.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/gamepad/_config.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/gamepad/connection.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/gamepad/constants.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/gamepad/controllers.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/gamepad/output.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/gamepad/protocol_handshake.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/gamepad/transport_factory.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/imu.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/input.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/probe.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/__init__.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/buttons.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/descriptors.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/imu_report.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/input_report.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/output_report.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/profiles/__init__.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/profiles/base.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/profiles/joycon.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/profiles/pro_controller.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/rumble.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/session.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/spi.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/protocol/subcommand.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/py.typed +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/state_store.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/__init__.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/_adapter_identity.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/_bumble_hidp.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/_bumble_sdp.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/_bumble_usb_devices.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/_csr_bd_addr.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/_csr_bd_addr_harness.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/base.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/src/swbt/transport/fake.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/__init__.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/conftest.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/hardware/README.md +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/hardware/test_battery_status.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/hardware/test_bumble_transport.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/hardware/test_close_disconnect.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/hardware/test_context_manager_resource_scope.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/hardware/test_controller_colors.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/hardware/test_multi_address_reconnect.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/hardware/test_pairing_l2cap.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/integration/__init__.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/__init__.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_adapter_discovery.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_adapter_identity.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_bumble_hidp.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_bumble_sdp.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_ci_workflow.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_csr_bd_addr_experiment.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_csr_bd_addr_harness.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_diagnostics.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_gamepad_config.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_gamepad_connection_workflow.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_gamepad_output_dispatcher.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_gamepad_transport_factory.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_imu_report.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_input_report.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_input_state.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_output_report.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_package_import.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_package_metadata.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_probe_cli.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_protocol_boundary.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_protocol_handshake.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_protocol_profile.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_protocol_session.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_public_api_boundary.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_publish_workflow.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_rumble_state.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_source_audit_fixtures.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_subcommand_responder.py +0 -0
- {swbt_python-0.5.2 → swbt_python-0.5.4}/tests/unit/test_virtual_spi_flash.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: swbt-python
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.4
|
|
4
4
|
Summary: Python library for presenting an NX-compatible virtual Bluetooth HID input device.
|
|
5
5
|
Keywords: bluetooth,bluetooth-hid,controller,gamepad,hid,nx
|
|
6
6
|
Author: niart120
|
|
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries
|
|
20
20
|
Classifier: Typing :: Typed
|
|
21
|
-
Requires-Dist: bumble
|
|
21
|
+
Requires-Dist: bumble==0.0.233
|
|
22
22
|
Maintainer: niart120
|
|
23
23
|
Maintainer-email: niart120 <38847256+niart120@users.noreply.github.com>
|
|
24
24
|
Requires-Python: >=3.12
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "swbt-python"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.4"
|
|
4
4
|
description = "Python library for presenting an NX-compatible virtual Bluetooth HID input device."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -34,7 +34,7 @@ classifiers = [
|
|
|
34
34
|
"Typing :: Typed",
|
|
35
35
|
]
|
|
36
36
|
dependencies = [
|
|
37
|
-
"bumble
|
|
37
|
+
"bumble==0.0.233",
|
|
38
38
|
]
|
|
39
39
|
|
|
40
40
|
[project.scripts]
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Pairing profile schema v2: current key only
|
|
2
|
+
|
|
3
|
+
## 1. 概要
|
|
4
|
+
|
|
5
|
+
### 1.1 目的
|
|
6
|
+
|
|
7
|
+
pairing profile schema を v2 に上げ、現在選択中の Bluetooth address namespace だけへ pairing key を保存する。v1 profile は runtime で読み替えず、adapter を開く前に再ペアリングを案内する `InvalidProfileError` で拒否する。
|
|
8
|
+
|
|
9
|
+
### 1.2 起点 / source
|
|
10
|
+
|
|
11
|
+
| source | 内容 | path |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| GitHub Issue #143 | previous pairing key 世代の廃止、schema v2、破壊的変更の利用者案内 | `https://github.com/niart120/swbt-python/issues/143` |
|
|
14
|
+
| 実装事実 | v1 は current key 更新時に `swbt.previous::` namespace を書き込む | `src/swbt/transport/_pairing_profile.py`, `src/swbt/transport/_bumble_key_store.py` |
|
|
15
|
+
|
|
16
|
+
### 1.3 use case
|
|
17
|
+
|
|
18
|
+
| actor / boundary | 入力または状態 | 期待する観測結果 | 制約 |
|
|
19
|
+
|---|---|---|---|
|
|
20
|
+
| 新規 explicit profile 利用者 | locally administered address を指定して profile を作成 | schema v2 と当該 address の空 namespace だけを保存する | previous namespace を作らない |
|
|
21
|
+
| adapter-default profile 利用者 | profile 作成後、power-on で current address が解決する | 解決済み address の current namespace だけを key 更新する | profile 作成時は空 map |
|
|
22
|
+
| v1 profile 利用者 | `profile_path` を runtime へ渡す | adapter open 前に v2 profile の作成と再ペアリングを示す `InvalidProfileError` | compatibility load / migration を提供しない |
|
|
23
|
+
|
|
24
|
+
## 2. 対象範囲
|
|
25
|
+
|
|
26
|
+
- schema version を 2 にする。
|
|
27
|
+
- new profile、key update、diagnostics から previous 世代を除く。
|
|
28
|
+
- current namespace の key lookup、複数 peer 拒否、atomic save、identity guard を維持する。
|
|
29
|
+
- fake transport の pairing / reconnect と explicit / adapter-default variant を確認する。
|
|
30
|
+
- 公開 docs と release notes に破壊的変更と再ペアリング手順を記載する。
|
|
31
|
+
|
|
32
|
+
## 3. 対象外
|
|
33
|
+
|
|
34
|
+
- BD_ADDR 切替、identity kind、CSR identity preparation の変更。
|
|
35
|
+
- previous key fallback、復元 API / CLI、v1 互換読込、自動または in-place migration。
|
|
36
|
+
- 実機 pairing / reconnect の実行。
|
|
37
|
+
|
|
38
|
+
## 4. 関連 docs
|
|
39
|
+
|
|
40
|
+
- `spec/initial/architecture.md`
|
|
41
|
+
- `spec/initial/api.md`
|
|
42
|
+
- `spec/initial/lifecycle.md`
|
|
43
|
+
- `spec/initial/testing.md`
|
|
44
|
+
- `docs/usage.md`
|
|
45
|
+
- `docs/release-notes.md`
|
|
46
|
+
|
|
47
|
+
## 5. 根拠監査
|
|
48
|
+
|
|
49
|
+
| 項目 | 要否 | 状態 | 根拠 / 理由 |
|
|
50
|
+
|---|---|---|---|
|
|
51
|
+
| Switch HID / report bytes | not applicable | not applicable | report format、subcommand、input timing を変更しない。 |
|
|
52
|
+
| Bumble / transport | not applicable | not applicable | Bumble API / SDP / L2CAP の仮定を追加せず、既存 key-store adapter の保存世代だけを変更する。 |
|
|
53
|
+
| OS / driver / adapter | not applicable | not applicable | adapter open や driver 操作を変更しない。 |
|
|
54
|
+
|
|
55
|
+
## 6. 振る舞い仕様
|
|
56
|
+
|
|
57
|
+
| 振る舞い | 入力・状態 | 期待結果 | 備考 |
|
|
58
|
+
|---|---|---|---|
|
|
59
|
+
| v2 profile creation | explicit address | current address namespace だけを持つ schema v2 JSON | atomic create を維持 |
|
|
60
|
+
| v1 early rejection | schema v1 JSON | adapter open 前に v2 と再ペアリングを案内する `InvalidProfileError` | migration しない |
|
|
61
|
+
| current-only update | current key を新しい peer key で更新 | current namespace は新しい 1 peer だけ、previous namespace は作成しない | active lookup は current のみ |
|
|
62
|
+
| diagnostics | key update 成功 / 失敗 | status、peer_address、失敗時 error_type/message だけを記録 | key material、generation、previous_saved は出さない |
|
|
63
|
+
|
|
64
|
+
## 7. TDD Test List
|
|
65
|
+
|
|
66
|
+
| status | item | type | layer | hardware | notes |
|
|
67
|
+
|---|---|---|---|---|---|
|
|
68
|
+
| refactor-skipped | explicit address の新規 profile は schema v2 と current namespace だけを保存する | regression | unit | no | `test_pairing_profile_create_new_atomically_saves_schema_v2_current_only_pro_envelope` が red から green。構造整理なし。 |
|
|
69
|
+
| refactor-skipped | schema v1 profile は adapter open 前に再作成・再ペアリングを案内して拒否する | regression | unit | no | loader と runtime の両方で v1 を拒否し、transport creation 前の停止を確認。構造整理なし。 |
|
|
70
|
+
| refactor-skipped | current key 更新は previous namespace を作らず、current key だけを置換する | regression | integration | no | `_PairingProfileKeyStore.update()` の 2 回更新を確認。構造整理なし。 |
|
|
71
|
+
| refactor-skipped | adapter-default profile は power-on 後に解決した current namespace だけを更新する | regression | unit / integration | no | existing Bumble fake device test で遅延 namespace 選択を確認。構造整理なし。 |
|
|
72
|
+
| refactor-skipped | key_store_update diagnostics は generation / previous_saved を記録しない | regression | unit | no | 成功・失敗 event の両方を確認。構造整理なし。 |
|
|
73
|
+
| refactor-skipped | v2 profile は fake transport pairing と active reconnect で current key を利用する | regression | integration | no | integration suite の fake transport pairing / reconnect と profile key-store update を通過。構造整理なし。 |
|
|
74
|
+
|
|
75
|
+
## 8. 文書検証計画
|
|
76
|
+
|
|
77
|
+
| document | audience / task | source of truth | mechanical check | review result | unresolved |
|
|
78
|
+
|---|---|---|---|---|---|
|
|
79
|
+
| `docs/usage.md` | v1 profile の利用者が v2 profile を作り直して再ペアリングする | Issue #143 と profile loader | `uv run --group docs mkdocs build --strict` | done | none |
|
|
80
|
+
| `docs/release-notes.md` | 破壊的変更と compatibility / migration 非提供を把握する | Issue #143 | `uv run --group docs mkdocs build --strict` | done | none |
|
|
81
|
+
|
|
82
|
+
## 9. 設計メモ
|
|
83
|
+
|
|
84
|
+
これは behavior change である。green 後の構造整理は、current-only 保存を変えない範囲に分離する。v1 error は loader に置き、adapter の生成・open より前に失敗させる。
|
|
85
|
+
|
|
86
|
+
## 10. 対象ファイル
|
|
87
|
+
|
|
88
|
+
| path | change | 内容 |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `src/swbt/transport/_pairing_profile.py` | modify | v2 envelope creation と v1 rejection message |
|
|
91
|
+
| `src/swbt/transport/_bumble_key_store.py` | modify | previous generation を除く current-only update と diagnostics |
|
|
92
|
+
| `tests/unit/test_pairing_profile.py` | modify | v2 / v1 early rejection |
|
|
93
|
+
| `tests/unit/test_bumble_transport.py` | modify | diagnostics と adapter-default current namespace |
|
|
94
|
+
| `tests/integration/test_pairing_profile.py` | modify | fake transport pairing / reconnect の保存契約 |
|
|
95
|
+
| `docs/usage.md` | modify | v1 profile の再作成・再ペアリング |
|
|
96
|
+
| `docs/release-notes.md` | modify | breaking change |
|
|
97
|
+
| `spec/initial/lifecycle.md` | modify | current-only key store と v1 非互換の設計判断 |
|
|
98
|
+
|
|
99
|
+
## 11. 検証
|
|
100
|
+
|
|
101
|
+
| command | result | notes |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `uv run pytest tests/unit -q --basetemp tmp/issue143-unit` | passed, 448 passed | profile loader、runtime、Bumble fake device、diagnostics を含む |
|
|
104
|
+
| `uv run pytest tests/integration -q --basetemp tmp/issue143-integration-all` | passed, 154 passed | fake transport pairing / reconnect と profile key-store update を含む |
|
|
105
|
+
| `uv run ruff format --check .` | passed | 106 files formatted |
|
|
106
|
+
| `uv run ruff check .` | passed | lint passed |
|
|
107
|
+
| `uv run ty check --no-progress` | passed | type check passed |
|
|
108
|
+
| `uv run --group docs mkdocs build --strict` | passed | public docs build passed |
|
|
109
|
+
| `uv build` | passed | `swbt_python-0.5.2.tar.gz` と `swbt_python-0.5.2-py3-none-any.whl` を作成 |
|
|
110
|
+
| `pytest -m bumble` / `pytest -m hardware` | not run | adapter / Switch 操作の明示承認がない。Issue の必須条件ではない。 |
|
|
111
|
+
|
|
112
|
+
## 12. 実機実行条件
|
|
113
|
+
|
|
114
|
+
| 項目 | 内容 |
|
|
115
|
+
|---|---|
|
|
116
|
+
| 実機要否 | not required |
|
|
117
|
+
| 承認範囲 | 実機確認は Issue 完了条件に含めない。実行する場合は別途明示承認を得る。 |
|
|
118
|
+
| adapter | not applicable |
|
|
119
|
+
| 実行遮断 | 環境変数による遮断は採用しない。明示承認、対象 adapter、command、cleanup plan で管理する |
|
|
120
|
+
| log / artifact | 実行時のみ `spec/hardware-test-log.md` に記録する |
|
|
121
|
+
| cleanup | 実機未実行 |
|
|
122
|
+
|
|
123
|
+
## 13. 先送り事項
|
|
124
|
+
|
|
125
|
+
- none
|
|
126
|
+
|
|
127
|
+
## 14. チェックリスト
|
|
128
|
+
|
|
129
|
+
- [x] 対象範囲と対象外を確認した
|
|
130
|
+
- [x] TDD Test List または文書検証計画を更新した
|
|
131
|
+
- [x] 必要な根拠監査を記録した
|
|
132
|
+
- [x] 実機実行条件を記録した
|
|
133
|
+
- [x] 検証結果または未実行理由を記録した
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# 通常入力 readiness 仕様書
|
|
2
|
+
|
|
3
|
+
## 1. 概要
|
|
4
|
+
|
|
5
|
+
### 1.1 目的
|
|
6
|
+
|
|
7
|
+
GitHub Issue #149 に従い、`pair()` / `reconnect()` などの接続 API が正常終了した時点で、
|
|
8
|
+
controller の通常入力経路が接続初期化中の automatic input holdoff によって抑止されない
|
|
9
|
+
契約を定義する。
|
|
10
|
+
|
|
11
|
+
Periodic / Direct は同じ公開契約を共有する。ただし、通常入力の送信主体は異なる。
|
|
12
|
+
Periodic は library の `ReportLoop`、Direct は呼び出し側の明示 input operation が送信を
|
|
13
|
+
所有する。このため、共通の完了条件を特定の periodic report の送信有無では定義しない。
|
|
14
|
+
|
|
15
|
+
### 1.2 起点 / source
|
|
16
|
+
|
|
17
|
+
| source | 内容 | path |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| GitHub Issue | Pair / active reconnect 完了直後の 50 ms press / release が、300 ms holdoff 中に local state 上で上書きされ、wire へ出ない | https://github.com/niart120/swbt-python/issues/149 |
|
|
20
|
+
| user decision | 「短時間入力を一度も欠落させない」キュー型契約には強めず、接続初期化由来の抑止だけを除く | conversation |
|
|
21
|
+
| current implementation | `ReportSender` は全 `0x21` reply 受理後に automatic input を 300 ms 抑止し、明示 input は抑止しない | `src/swbt/report_loop.py` |
|
|
22
|
+
| pre-change lifecycle | protocol ready で接続 waiter を起こした後、Periodic の `ReportLoop` を開始していた | 変更前の `src/swbt/gamepad/runtime.py` |
|
|
23
|
+
| prior validation | 300 ms は fake / hardware 比較後に維持され、ready 後の新規 subcommand は未観測 | `spec/complete/unit_082/REPLY_HOLDOFF_VALIDATION.md` |
|
|
24
|
+
| prior readiness contract | Periodic / Direct は supported report mode と nonzero player lights による protocol ready を共有する | `spec/complete/unit_069/CONTROLLER_HANDSHAKE_READINESS.md` |
|
|
25
|
+
|
|
26
|
+
### 1.3 use case
|
|
27
|
+
|
|
28
|
+
| actor / boundary | 入力または状態 | 期待する観測結果 | 制約 |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| Periodic controller 利用者 | `await pair()` / `await reconnect()` の直後に `apply()` し、既定 8 ms 周期より長い 50 ms 後に neutral へ戻す | 接続初期化で設定された holdoff に全送信機会を奪われず、通常 cadence の `0x30` に入力が現れる | 1周期未満の全 state 遷移配送は保証しない |
|
|
31
|
+
| Direct controller 利用者 | 接続 API 完了直後に `send()` または意味的入力操作を呼ぶ | protocol ready 後の明示 input が従来どおり transport へ送られる | Direct に automatic report や待機用 neutral probe を追加しない |
|
|
32
|
+
| diagnostics 利用者 | protocol ready から通常入力 readiness までを trace する | protocol handshake 完了と public 接続 API の完了境界を区別できる | report counter のポーリングを利用者へ要求しない |
|
|
33
|
+
| timeout / cancellation 利用者 | Periodic が protocol ready 後の holdoff 終了を待っている間に timeout、cancel、disconnect が起きる | 接続成功を返さず、既存の cleanup と失敗 semantics を維持する | 接続 timeout budget を新たに加算しない |
|
|
34
|
+
|
|
35
|
+
## 2. 対象範囲
|
|
36
|
+
|
|
37
|
+
- `pair()`、`reconnect()`、`connect()` と対応する `try_*` API の正常終了条件。
|
|
38
|
+
- これらへ委譲する `create_profile()` の object return 条件。
|
|
39
|
+
- protocol ready と通常入力 readiness の内部境界。
|
|
40
|
+
- Periodic の automatic input holdoff と接続完了の同期。
|
|
41
|
+
- Direct の明示 input 経路が同じ公開契約を満たすことの回帰確認。
|
|
42
|
+
- timeout、cancellation、disconnect、close、session reset。
|
|
43
|
+
- diagnostics、公開 API docstring、利用者向け docs、初期設計文書の整合。
|
|
44
|
+
- fake transport による Pair / active reconnect と全 controller profile の検証。
|
|
45
|
+
- Pro Controller の代表的な実機確認。
|
|
46
|
+
|
|
47
|
+
## 3. 対象外
|
|
48
|
+
|
|
49
|
+
- `apply()` の各 state 遷移をキューに保存し、必ず1回以上配送する機能。
|
|
50
|
+
- report period より短い press / release を含む全 transient input の配送保証。
|
|
51
|
+
- Periodic の latest-state coalescing semantics の変更。
|
|
52
|
+
- Direct に automatic `0x30`、待機用 neutral probe、`ReportLoop` を追加すること。
|
|
53
|
+
- 300 ms holdoff の値、開始条件、ready 後 subcommand への適用範囲の変更。
|
|
54
|
+
- steady-state report cadence、deadline scheduler、Bluetooth transport の変更。
|
|
55
|
+
- HID report ID、byte layout、timer、IMU encoding の変更。
|
|
56
|
+
- Joy-Con 実機確認。共通 runtime / sender 以外へ変更が及ぶ場合は実機要否を再評価する。
|
|
57
|
+
|
|
58
|
+
## 4. 関連 docs
|
|
59
|
+
|
|
60
|
+
- `spec/initial/api.md`
|
|
61
|
+
- `spec/initial/architecture.md`
|
|
62
|
+
- `spec/initial/lifecycle.md`
|
|
63
|
+
- `spec/initial/protocol.md`
|
|
64
|
+
- `spec/initial/testing.md`
|
|
65
|
+
- `spec/initial/risks.md`
|
|
66
|
+
- `spec/complete/unit_069/CONTROLLER_HANDSHAKE_READINESS.md`
|
|
67
|
+
- `spec/complete/unit_081/PROTOCOL_HANDSHAKE.md`
|
|
68
|
+
- `spec/complete/unit_082/REPLY_HOLDOFF_VALIDATION.md`
|
|
69
|
+
- `spec/hardware-test-log.md`
|
|
70
|
+
|
|
71
|
+
## 5. 根拠監査
|
|
72
|
+
|
|
73
|
+
| 項目 | 要否 | 状態 | 根拠 / 理由 |
|
|
74
|
+
|---|---|---|---|
|
|
75
|
+
| 300 ms automatic input holdoff | required | done | unit_082 で implementation fact と実機比較を記録済み。値と適用範囲は変更しない |
|
|
76
|
+
| Switch HID / report bytes | not applicable | not applicable | `0x21` / `0x30` の ID、layout、payload を変更しない |
|
|
77
|
+
| Bumble / transport | not applicable | not applicable | transport の受理契約と実装を変更しない |
|
|
78
|
+
| OS / driver / adapter | required | done | no-open列挙とPnP driver情報で、Windows 11、`usb:0`、CSR8510 A10 `0A12:0001`、WinUSB / libwdiを実行直前に確認 |
|
|
79
|
+
|
|
80
|
+
### 5.1 事実
|
|
81
|
+
|
|
82
|
+
- `send_subcommand_reply()` は transport の受理後に holdoff deadline を更新する。
|
|
83
|
+
- `send_automatic_input()` は同じ sender lock 内で deadline を検査し、期限前は送信しない。
|
|
84
|
+
- Direct の `send_input()` は automatic input ではなく、holdoff を検査しない。
|
|
85
|
+
- protocol ready を成立させる最後の reply 自身が holdoff deadline を更新する。
|
|
86
|
+
- 変更前の runtime は接続 waiter を起こしてから Periodic の `ReportLoop` を開始していた。
|
|
87
|
+
|
|
88
|
+
### 5.2 推論
|
|
89
|
+
|
|
90
|
+
- public 接続 API の完了条件を「最初の periodic `0x30` 送信」にすると、automatic report を
|
|
91
|
+
持たない Direct では成立しない。
|
|
92
|
+
- 共通契約は report の有無ではなく、「その reporting mode の通常入力経路が接続初期化由来の
|
|
93
|
+
抑止を受けない状態」として定義できる。
|
|
94
|
+
- Periodic では protocol ready 時点の holdoff deadline だけを snapshot して待つと、待機中に
|
|
95
|
+
受理した追加 reply が deadline を延長する競合を見落とす。readiness 公開前に受理された
|
|
96
|
+
最新 reply の deadline を反映する必要がある。
|
|
97
|
+
|
|
98
|
+
### 5.3 未検証
|
|
99
|
+
|
|
100
|
+
- protocol ready 後に Switch が新しい subcommand を送る条件と頻度は未確認である。
|
|
101
|
+
- 接続完了後に届いた新しい reply が automatic input を再び一時抑止する挙動は、本仕様で変更しない。
|
|
102
|
+
- active reconnect、Joy-Con、別adapter、別OS、別firmwareでの修正後50 ms inputは未検証である。
|
|
103
|
+
|
|
104
|
+
## 6. 振る舞い仕様
|
|
105
|
+
|
|
106
|
+
| 振る舞い | 入力・状態 | 期待結果 | 備考 |
|
|
107
|
+
|---|---|---|---|
|
|
108
|
+
| protocol ready | supported report mode と nonzero player lights が揃い、成立させた reply が transport に受理される | protocol handshake を停止・回収し、通常入力 readiness の評価へ進む | protocol ready 自体の predicate は変更しない |
|
|
109
|
+
| Periodic readiness 待機 | protocol ready だが最新 reply の automatic input holdoff 中 | public 接続成功を返さず、connection state は接続処理中のままとする | 外部の固定 sleep や report counter polling は不要 |
|
|
110
|
+
| Periodic readiness 成立 | readiness 公開前に受理された最新 reply の holdoff deadline に到達する | `ReportLoop` を開始してから接続成功を公開する | probe report の成功を条件にしない |
|
|
111
|
+
| Periodic 最初の通常 cadence | 接続 API 完了後に local state が更新される | 次の通常 cadence から latest state を送信対象にできる | 各 state の配送保証ではない |
|
|
112
|
+
| Direct readiness 成立 | protocol ready に到達する | 明示 input 経路が holdoff 対象外であるため、同じ接続成功契約を直ちに満たす | automatic deadline の経過を待たない |
|
|
113
|
+
| Direct 無送信 | Direct の接続 API が完了する | 待機確認のための `0x30` を自動送信しない | lifecycle 全体で ReportLoop を持たない |
|
|
114
|
+
| 追加 reply | Periodic が readiness 待機中に新しい reply を transport が受理する | 待機 deadline を最新値へ延長し、古い deadline では成功を公開しない | holdoff 更新と readiness 公開を競合させない |
|
|
115
|
+
| readiness 公開後の reply | 接続 API 完了後に新しい reply を受理する | 既存方針どおり automatic input holdoff を適用できる | 永続的な「無抑止」は保証しない |
|
|
116
|
+
| timeout | Periodic が readiness 待機中に接続操作の既存 deadline を超える | timeout として失敗し、cleanup する | 300 msを別 budget として加算しない |
|
|
117
|
+
| cancellation | readiness 待機中の接続 task を cancel する | readiness waiter と接続処理を停止し、既存 cancellation / cleanup semantics を維持する | background waiter を残さない |
|
|
118
|
+
| disconnect | readiness 公開前に link が切れる | 接続成功を返さず、失敗として待機 API を起こす | stale deadline を次 session へ持ち越さない |
|
|
119
|
+
| session reset | close 後に再度 open / pair / reconnect する | 前 session の holdoff deadline と readiness を再利用しない | sender は session 単位 |
|
|
120
|
+
| 50 ms入力 | 既定 8 ms Periodic の接続 API 完了直後に press、50 ms後に release | 初期化 holdoff に全 cadence を抑止されず、press state の periodic `0x30` が1件以上観測できる | 50 msという検証条件であり、任意の短時間入力保証ではない |
|
|
121
|
+
|
|
122
|
+
## 7. TDD Test List
|
|
123
|
+
|
|
124
|
+
| status | item | type | layer | hardware | notes |
|
|
125
|
+
|---|---|---|---|---|---|
|
|
126
|
+
| green | reply 受理直後の Periodic 通常入力 readiness は holdoff 期限前に成立せず、境界時刻で成立する | new | unit | no | 注入時計で wall clock 非依存に確認 |
|
|
127
|
+
| green | readiness 待機中に追加 reply を受理すると、古い期限では成立せず最新期限まで待つ | edge | unit | no | deadline snapshot ではなく最新値を再評価 |
|
|
128
|
+
| green | protocol ready 後も holdoff 中の Periodic `pair()` は完了せず、期限到達後に完了する | regression | integration | no | controlled readiness gate で Pair 経路を確認 |
|
|
129
|
+
| green | Periodic active reconnect は protocol ready 後の holdoff 終了まで `status="connected"` を返さない | regression | integration | no | controlled readiness gate で `try_reconnect()` を確認 |
|
|
130
|
+
| green | Direct の Pair / active reconnect は protocol ready で完了し、holdoff 経過や automatic `0x30` を要求しない | regression | integration | no | Pro / Joy-Con L/R を parameterize |
|
|
131
|
+
| green | `connect()`、`try_connect()`、`create_profile()` は選択した Pair / reconnect と同じ通常入力 readiness を使う | regression | integration | no | connect 2入口と6具象create_profileのpair委譲を確認 |
|
|
132
|
+
| green | Periodic の接続完了直後に50 ms保持した stateが通常 cadence の `0x30` に現れる | regression | integration | no | 既定8 msのButton Aとneutralを確認。全transient配送へ一般化しない |
|
|
133
|
+
| green | readiness 待機中の timeout は成功を返さず既存 cleanup を完了する | edge | integration | no | timeout 後close、`stage=input_readiness`、次回Pairのfresh readinessを確認 |
|
|
134
|
+
| green | readiness 待機中の cancellation / disconnect は waiter を残さず、次 session が stale readiness を再利用しない | edge | integration | no | cancellation red後にwaiter回収を追加。disconnect失敗の`stage=input_readiness`も確認 |
|
|
135
|
+
| green | Pro Controller の Pair または active reconnect 完了直後の50 ms Button Aがperiodic `0x30`とSwitch UIに反映される | characterization | hardware | yes | fresh PairでA付き周期`0x30`を7件記録し、利用者が対象機器側の反映を確認 |
|
|
136
|
+
|
|
137
|
+
## 8. 文書検証計画
|
|
138
|
+
|
|
139
|
+
| document | audience / task | source of truth | mechanical check | review result | unresolved |
|
|
140
|
+
|---|---|---|---|---|---|
|
|
141
|
+
| `spec/initial/api.md` | 接続 API 完了後に入力を開始する利用者 | 本仕様 §6 | `uv run --group docs mkdocs build --strict` | pass | Periodic / Direct 共通契約と方式差を反映。未解決なし |
|
|
142
|
+
| `spec/initial/architecture.md` | runtime と report loop の所有境界を確認する maintainer | 本仕様 §6 / §9 | `uv run --group docs mkdocs build --strict` | pass | report loop の開始時点を通常入力 readiness と一致。未解決なし |
|
|
143
|
+
| `spec/initial/lifecycle.md` | maintainer が protocol ready と通常入力 readiness の順序を追う | 本仕様 §6 / §9 | `uv run --group docs mkdocs build --strict` | pass | timeout / disconnect を含む状態遷移を反映。未解決なし |
|
|
144
|
+
| `spec/initial/testing.md` | fake / hardware test の分担を確認する maintainer | 本仕様 §7 | `uv run --group docs mkdocs build --strict` | pass | 50 ms は代表条件であり全 transient 保証ではないと明記。未解決なし |
|
|
145
|
+
| public API docstring / `docs/api.md` / `docs/usage.md` / `docs/release-notes.md` / `docs/hardware.md` | 接続後に入力する利用者と実機確認担当者 | 本仕様 §6 / §7、`spec/hardware-test-log.md` | docs build + `docs-quality-review` | pass | 契約、非保証、50 ms実機観測、未確認範囲を照合。must-fix なし |
|
|
146
|
+
|
|
147
|
+
自然言語の意味要件を固定語句の存在・不在 assertion に置き換えない。公開文書の事実性、
|
|
148
|
+
操作順、未保証範囲は正本との照合と `docs-quality-review` で確認する。
|
|
149
|
+
|
|
150
|
+
## 9. 設計メモ
|
|
151
|
+
|
|
152
|
+
### 9.1 共通契約
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
connection API success
|
|
156
|
+
implies
|
|
157
|
+
the reporting mode's normal input path is not blocked
|
|
158
|
+
by a holdoff already created during connection initialization
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
「通常入力経路」は reporting mode ごとに次を指す。
|
|
162
|
+
|
|
163
|
+
| reporting mode | 通常入力経路 | readiness の具体条件 |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| Periodic | local latest stateを通常 cadence で送る `ReportLoop` | readiness 公開前に受理された最新 reply の automatic input holdoff が終了済み |
|
|
166
|
+
| Direct | `send()` と意味的 input operation による明示送信 | protocol ready で明示 input sender が利用可能 |
|
|
167
|
+
|
|
168
|
+
この違いは公開契約の差ではなく、送信所有者の違いである。
|
|
169
|
+
|
|
170
|
+
### 9.2 `connected` の意味
|
|
171
|
+
|
|
172
|
+
`connected` と接続 API の正常終了は、protocol ready だけでなく通常入力 readiness も満たす。
|
|
173
|
+
diagnostics では次を分ける。
|
|
174
|
+
|
|
175
|
+
- `protocol_ready`: handshake predicate を成立させた reply が受理され、handshake task を
|
|
176
|
+
停止・回収した時点。
|
|
177
|
+
- `input_ready`: reporting mode ごとの通常入力 readiness が成立した時点。
|
|
178
|
+
- `active_reconnect_result(status="connected")`: `input_ready` 後。
|
|
179
|
+
|
|
180
|
+
Direct では `protocol_ready` と `input_ready` が連続して記録される。Periodic では通常、
|
|
181
|
+
最後の初期化 reply が設定した holdoff の残り時間だけ間隔が空く。
|
|
182
|
+
|
|
183
|
+
`input_ready` を接続成功の linearization point とする。sender の同期境界でこれより前に
|
|
184
|
+
受理された reply は readiness 待機へ反映し、これより後に受理された reply は接続後の
|
|
185
|
+
通常処理として扱う。coroutine を再開する wall-clock 上の瞬間と Bluetooth event の到着を
|
|
186
|
+
完全に排他する保証は置かない。
|
|
187
|
+
|
|
188
|
+
### 9.3 holdoff と readiness の同期
|
|
189
|
+
|
|
190
|
+
readiness 判定は、holdoff deadline の単発 snapshot や `sleep(0.3)` で実装しない。
|
|
191
|
+
subcommand reply の transport 受理、deadline 更新、readiness の再評価を同じ sender の
|
|
192
|
+
同期境界で順序付ける。
|
|
193
|
+
|
|
194
|
+
readiness 公開前に追加 reply が受理された場合、その reply が更新した deadline を待つ。
|
|
195
|
+
readiness 公開後に受理された reply は既存の automatic input holdoff として扱う。本仕様は
|
|
196
|
+
ready 後 holdoff の廃止や initializing 限定化を行わない。
|
|
197
|
+
|
|
198
|
+
### 9.4 ReportLoop の開始
|
|
199
|
+
|
|
200
|
+
Periodic の `ReportLoop` は通常入力 readiness 成立後に開始する。接続完了確認のための
|
|
201
|
+
neutral probe は送らない。loop の最初の deadline は開始時刻から `report_period_us` 後とし、
|
|
202
|
+
接続完了直後の `apply()` はその時点の latest state を次回 cadence の候補にする。
|
|
203
|
+
|
|
204
|
+
Direct は lifecycle 全体で通常 `ReportLoop` を持たない。handshake 中の
|
|
205
|
+
`handshake_bootstrap` / `handshake_report_mode` は `ProtocolHandshake` が所有する内部
|
|
206
|
+
automatic neutral であり、Direct の通常入力には数えない。
|
|
207
|
+
|
|
208
|
+
### 9.5 transient input の境界
|
|
209
|
+
|
|
210
|
+
Periodic は latest-state model を維持する。複数の `apply()` が同じ通常 cadence より前に
|
|
211
|
+
完了した場合、中間 state は後続 state に統合され得る。これを欠落防止 queue へ変更しない。
|
|
212
|
+
|
|
213
|
+
Issue #149 の 50 ms / 8 ms は通常なら複数 cadence を含むため、接続初期化 holdoff による
|
|
214
|
+
全機会の抑止を検出する代表条件として使う。50 msを任意の環境、任意の period に対する
|
|
215
|
+
最小配送時間として公開しない。
|
|
216
|
+
|
|
217
|
+
## 10. 対象ファイル
|
|
218
|
+
|
|
219
|
+
| path | change | 内容 |
|
|
220
|
+
|---|---|---|
|
|
221
|
+
| `src/swbt/report_loop.py` | modify | automatic input readiness の待機と reply deadline 更新の同期 |
|
|
222
|
+
| `src/swbt/gamepad/runtime.py` | modify | protocol ready 後の mode 別 readiness、event、timeout、cleanup、diagnostics |
|
|
223
|
+
| `src/swbt/gamepad/interface.py` | modify | 公開接続 API docstring の readiness 契約 |
|
|
224
|
+
| `tests/unit/test_report_loop.py` | modify | deadline 境界と追加 reply の決定的 unit test |
|
|
225
|
+
| `tests/integration/test_switch_gamepad_fake_transport.py` | modify | Pair / reconnect / Direct / Periodic / failure lifecycle |
|
|
226
|
+
| `tests/hardware/test_reply_holdoff.py` | modify | fresh Pair 完了直後50 ms入力の実機 gate |
|
|
227
|
+
| `spec/initial/api.md` | modify | 接続成功後の通常入力契約 |
|
|
228
|
+
| `spec/initial/architecture.md` | modify | ReportLoop の生成時点と runtime の wait 所有 |
|
|
229
|
+
| `spec/initial/lifecycle.md` | modify | protocol ready と input ready の状態遷移 |
|
|
230
|
+
| `spec/initial/protocol.md` | modify | holdoff 対象となる ReportLoop の開始境界を明確化 |
|
|
231
|
+
| `spec/initial/testing.md` | modify | fake / hardware completion gate |
|
|
232
|
+
| `docs/api.md` | modify | 利用者向け接続 API 説明 |
|
|
233
|
+
| `docs/usage.md` | modify | 接続後の入力開始手順と latest-state の非保証 |
|
|
234
|
+
| `docs/release-notes.md` | modify | 修正内容、互換境界、実機未確認範囲 |
|
|
235
|
+
| `docs/hardware.md` | modify | `protocol_ready` と `input_ready` の診断手順 |
|
|
236
|
+
| `spec/hardware-test-log.md` | modify | 承認後の実機条件と結果 |
|
|
237
|
+
|
|
238
|
+
実装時に実ファイル構成を再確認し、内部 helper 名をこの表へ合わせるためだけの変更は行わない。
|
|
239
|
+
|
|
240
|
+
## 11. 検証
|
|
241
|
+
|
|
242
|
+
| command | result | notes |
|
|
243
|
+
|---|---|---|
|
|
244
|
+
| `git diff --no-index --check -- NUL spec/complete/unit_086/NORMAL_INPUT_READINESS.md` | pass | 新規 untracked spec に whitespace error なし。差分ありを表す exit 1、error output なし |
|
|
245
|
+
| `uv run pytest tests/unit/test_report_loop.py::test_automatic_input_readiness_waits_until_reply_holdoff_boundary -q` | pass | red は `_sleep` 未対応の `TypeError`、green は `1 passed` |
|
|
246
|
+
| `uv run pytest tests/unit/test_report_loop.py -q` | pass | first cycle 後 `11 passed` |
|
|
247
|
+
| `uv run pytest tests/unit/test_report_loop.py::test_additional_reply_extends_automatic_input_readiness_wait -q` | pass | first cycle の再評価 loop で green、`1 passed` |
|
|
248
|
+
| targeted Pair / Direct readiness integration | pass | Periodic red は waiter 未呼び出しで timeout。runtime 分離後、既存境界を含め `9 passed` |
|
|
249
|
+
| targeted active reconnect readiness integration | pass | Periodic `1 passed`、Direct Pro / Joy-Con L/R `3 passed` |
|
|
250
|
+
| `uv run pytest tests/integration/test_switch_gamepad_fake_transport.py::test_periodic_input_after_pair_is_not_blocked_by_initialization_holdoff -q` | pass | 接続完了後50 msのButton Aと後続neutralをperiodic `0x30`で確認 |
|
|
251
|
+
| targeted timeout / cancellation / disconnect readiness integration | pass | timeout後の再Pair、task cancellation、disconnect、既存reconnect cancellationを含む `4 passed` |
|
|
252
|
+
| targeted connect / create_profile delegation integration | pass | connect 2入口と6具象create_profileのpair委譲、計 `8 passed` |
|
|
253
|
+
| `uv run ruff format --check .` | pass | `106 files already formatted` |
|
|
254
|
+
| `uv run ruff check .` | pass | `All checks passed!` |
|
|
255
|
+
| `uv run ty check --no-progress` | pass | `All checks passed!` |
|
|
256
|
+
| `uv run pytest tests/unit` | pass | final gateは`450 passed in 2.09s` |
|
|
257
|
+
| `uv run pytest tests/integration` | pass | final gateは`165 passed in 3.05s` |
|
|
258
|
+
| `uv run --group docs mkdocs build --strict` | pass | strict build 成功 |
|
|
259
|
+
| `uv run pytest --collect-only tests/hardware/test_reply_holdoff.py -q` | pass | 修正後harnessを含む10件を収集。adapter / Switch は開いていない |
|
|
260
|
+
| approved Pro Controller fresh Pair hardware gate | observed-pass | commandはdiagnostics reasonのtest bugで`1 failed in 5.58s`。artifactはA付き周期`0x30`を7件、neutral、cleanupを記録し、利用者がUI反映を確認。test bugは`reason=periodic`へ修正 |
|
|
261
|
+
| hardware artifact review | pass | debug PDUのtimer `0x15`–`0x1B`でButton A bitを7件、次のtimer `0x1C`でneutralを確認 |
|
|
262
|
+
|
|
263
|
+
## 12. 実機実行条件
|
|
264
|
+
|
|
265
|
+
| 項目 | 内容 |
|
|
266
|
+
|---|---|
|
|
267
|
+
| 実機要否 | required for completion |
|
|
268
|
+
| 承認範囲 | Pro Controller の Pair または active reconnect、HID advertising、subcommand handling、通常 periodic report、50 ms Button A press / release、neutral close、adapter release |
|
|
269
|
+
| adapter | 実行直前に対象 adapter、identity、driver を確認する。過去の `usb:0` / CSR8510 A10 / WinUSB を現在値として仮定しない |
|
|
270
|
+
| 実行遮断 | 環境変数による遮断は採用しない。明示承認、対象 adapter、command、Switch-facing 動作、cleanup plan で管理する |
|
|
271
|
+
| log / artifact | OS、Python / Bumble / swbt-python version、Switch model / firmware、profile / route、`protocol_ready`、`input_ready`、reply、periodic `0x30`、UI 観測を保存する |
|
|
272
|
+
| cleanup | neutral、ReportLoop停止、disconnect、transport close、adapter release。失敗時も同じ項目を確認する |
|
|
273
|
+
| 実行結果 | fresh Pairでobserved-pass。詳細は`spec/hardware-test-log.md`の2026-07-26 unit_086記録 |
|
|
274
|
+
|
|
275
|
+
実機 test は自動 trace の periodic `0x30` と利用者による Switch UI 観測を分けて記録する。
|
|
276
|
+
明示承認なしに `bumble` / `hardware` marker を実行しない。
|
|
277
|
+
|
|
278
|
+
## 13. 先送り事項
|
|
279
|
+
|
|
280
|
+
- ready 後 subcommand の発生条件と、steady-state holdoff の必要性。観測できた場合は unit_082
|
|
281
|
+
の後続として別 work unit / Issue に分ける。
|
|
282
|
+
- 各 Periodic state 遷移を配送する queue。latest-state API の別契約になるため本仕様には含めない。
|
|
283
|
+
- report period に対する最小 transient input duration の公開保証。OS / scheduler / transport を
|
|
284
|
+
含む保証設計が必要なため本仕様には含めない。
|
|
285
|
+
|
|
286
|
+
## 14. チェックリスト
|
|
287
|
+
|
|
288
|
+
- [x] 対象範囲と対象外を確認した
|
|
289
|
+
- [x] Periodic / Direct に等価な公開契約を定義した
|
|
290
|
+
- [x] 「最初の periodic `0x30`」を共通 completion gate から除外した
|
|
291
|
+
- [x] transient input の全配送を対象外として明記した
|
|
292
|
+
- [x] TDD Test List を作成した
|
|
293
|
+
- [x] 必要な根拠監査を記録した
|
|
294
|
+
- [x] 実機実行条件を記録した
|
|
295
|
+
- [x] 実装と local gate を完了した
|
|
296
|
+
- [x] 公開文書を更新し `docs-quality-review` を完了した
|
|
297
|
+
- [x] 明示承認付き実機 gate を完了した
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Dev Journal
|
|
2
|
+
|
|
3
|
+
swbt-python の設計観測、未解決事項、先送り判断の記録。
|
|
4
|
+
|
|
5
|
+
## 2026-07-26: VID:PID 33FA:0010 の HCI extended-features 応答
|
|
6
|
+
|
|
7
|
+
### 現状
|
|
8
|
+
|
|
9
|
+
Windows 11 / WinUSB / libwdi / Bumble 0.0.233 で検出した `33FA:0010` は、Bumble の `Read Local Extended Features` (`0x1004`) に対する応答を event length `0x01` として返し、通常の `power_on()` を停止させた。
|
|
10
|
+
|
|
11
|
+
### 観察
|
|
12
|
+
|
|
13
|
+
実験用に `0x1004` の対応判定を抑止すると、Bumble は既存の `0x1003` 代替経路を使い、HID advertising、fresh pairing、protocol ready、Button A の Switch UI 反映、neutral close まで成功した。active reconnect は同条件で2回、`host_connection` 後かつ L2CAP 前に Switch reason `19` で切断された。実験用コードは main に取り込まない。
|
|
14
|
+
|
|
15
|
+
### 方針
|
|
16
|
+
|
|
17
|
+
この adapter を正式対応にしない。再検討する場合は、Bumble の upstream driver / quirk として扱える根拠、または複数個体・別 OS/driver での再現を先に集める。観測 artifact と実行条件は `spec/hardware-test-log.md` を正本とする。
|