swbt-python 0.3.0__tar.gz → 0.5.0__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.3.0 → swbt_python-0.5.0}/AGENTS.md +10 -1
- {swbt_python-0.3.0 → swbt_python-0.5.0}/PKG-INFO +16 -19
- swbt_python-0.5.0/README.md +121 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/examples/hardware_bringup.py +9 -7
- swbt_python-0.5.0/examples/pairing_probe.py +73 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/examples/tap_a.py +7 -5
- {swbt_python-0.3.0 → swbt_python-0.5.0}/pyproject.toml +2 -2
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_005/M4_SUBCOMMAND_RESPONDER_HARDWARE.md +1 -1
- swbt_python-0.5.0/spec/complete/unit_050/DIRECT_REPORTING_TYPES.md +260 -0
- swbt_python-0.5.0/spec/complete/unit_051/CSR_BD_ADDR_REWRITE_EXPERIMENT.md +258 -0
- swbt_python-0.5.0/spec/complete/unit_052/EXP_LOCAL_ADDRESS_PROFILE.md +265 -0
- swbt_python-0.5.0/spec/complete/unit_053/EXP_LOCAL_ADDRESS_PROFILE_JOYCON.md +153 -0
- swbt_python-0.5.0/spec/complete/unit_054/EXP_LOCAL_ADDRESS_PROFILE_DIRECT.md +139 -0
- swbt_python-0.5.0/spec/complete/unit_055/REMOVE_NATIVE_KEY_STORE_API.md +60 -0
- swbt_python-0.5.0/spec/complete/unit_058/MULTI_ADDRESS_RECONNECT.md +105 -0
- swbt_python-0.5.0/spec/complete/unit_059/EXPERIMENTAL_DIRECT_SEND_TIMING_PROBE.md +143 -0
- swbt_python-0.5.0/spec/complete/unit_060/HCI_ACL_COMPLETION_CORRELATION.md +141 -0
- swbt_python-0.5.0/spec/complete/unit_061/EXPERIMENTAL_CLASSIC_LINK_POLICY_AB.md +136 -0
- swbt_python-0.5.0/spec/complete/unit_062/PERIODIC_ACL_DRAIN_CHARACTERIZATION.md +137 -0
- swbt_python-0.5.0/spec/complete/unit_063/PERIODIC_NO_DRAIN_CHARACTERIZATION.md +128 -0
- swbt_python-0.5.0/spec/complete/unit_064/BUMBLE_ENQUEUE_COMPLETION_CONTRACT.md +165 -0
- swbt_python-0.5.0/spec/complete/unit_065/PERIODIC_DEADLINE_SCHEDULER.md +150 -0
- swbt_python-0.5.0/spec/complete/unit_066/PAIRING_PROFILE_DEFAULT_ADDRESS.md +217 -0
- swbt_python-0.5.0/spec/complete/unit_067/DEFAULT_BATTERY_STATUS.md +148 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/hardware-test-log.md +566 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/initial/api.md +119 -69
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/initial/architecture.md +22 -15
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/initial/lifecycle.md +37 -24
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/initial/protocol.md +4 -1
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/initial/risks.md +22 -10
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/initial/roadmap.md +3 -3
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/initial/testing.md +38 -10
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/initial/transport-bumble.md +36 -7
- swbt_python-0.5.0/spec/wip/unit_056/PAIRING_PROFILE_NAMING.md +126 -0
- swbt_python-0.5.0/spec/wip/unit_057/PAIRING_PROFILE_CONTROLLER_KIND.md +133 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/__init__.py +16 -0
- swbt_python-0.5.0/src/swbt/_testing/gamepad.py +145 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/diagnostics.py +4 -10
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/errors.py +37 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/gamepad/__init__.py +12 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/gamepad/_config.py +6 -6
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/gamepad/connection.py +4 -4
- swbt_python-0.5.0/src/swbt/gamepad/core.py +732 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/gamepad/interface.py +55 -26
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/gamepad/output.py +7 -5
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/gamepad/runtime.py +182 -37
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/gamepad/transport_factory.py +34 -7
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/probe.py +7 -6
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/profiles/base.py +1 -1
- swbt_python-0.5.0/src/swbt/report_loop.py +212 -0
- swbt_python-0.5.0/src/swbt/transport/_adapter_identity.py +220 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/transport/_bumble_key_store.py +108 -57
- swbt_python-0.5.0/src/swbt/transport/_csr_bd_addr.py +249 -0
- swbt_python-0.5.0/src/swbt/transport/_csr_bd_addr_harness.py +279 -0
- swbt_python-0.5.0/src/swbt/transport/_pairing_profile.py +243 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/transport/base.py +5 -2
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/transport/bumble.py +110 -15
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/conftest.py +31 -0
- swbt_python-0.5.0/tests/hardware/test_battery_status.py +77 -0
- swbt_python-0.5.0/tests/hardware/test_multi_address_reconnect.py +148 -0
- swbt_python-0.5.0/tests/hardware/test_pairing_profile.py +564 -0
- swbt_python-0.5.0/tests/integration/test_pairing_profile.py +300 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/integration/test_switch_gamepad_fake_transport.py +475 -50
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/fixtures/source_audit/switch_protocol_values.toml +2 -2
- swbt_python-0.5.0/tests/unit/test_adapter_identity.py +250 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_bumble_transport.py +317 -400
- swbt_python-0.5.0/tests/unit/test_csr_bd_addr_experiment.py +188 -0
- swbt_python-0.5.0/tests/unit/test_csr_bd_addr_harness.py +130 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_diagnostics.py +3 -7
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_gamepad_connection_workflow.py +3 -3
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_gamepad_output_dispatcher.py +6 -3
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_gamepad_transport_factory.py +15 -11
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_package_import.py +13 -0
- swbt_python-0.5.0/tests/unit/test_pairing_profile.py +286 -0
- swbt_python-0.5.0/tests/unit/test_pairing_profile_runtime.py +336 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_probe_cli.py +5 -5
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_protocol_profile.py +2 -1
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_public_api_boundary.py +146 -115
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_publish_workflow.py +0 -27
- swbt_python-0.5.0/tests/unit/test_report_loop.py +322 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_source_audit_fixtures.py +3 -1
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_subcommand_responder.py +9 -0
- swbt_python-0.3.0/README.md +0 -124
- swbt_python-0.3.0/examples/pairing_probe.py +0 -98
- swbt_python-0.3.0/src/swbt/_testing/gamepad.py +0 -74
- swbt_python-0.3.0/src/swbt/gamepad/core.py +0 -409
- swbt_python-0.3.0/src/swbt/report_loop.py +0 -129
- swbt_python-0.3.0/tests/hardware/test_input_operations.py +0 -1139
- swbt_python-0.3.0/tests/hardware/test_joycon_profile.py +0 -1648
- swbt_python-0.3.0/tests/hardware/test_reconnect_keystore.py +0 -313
- swbt_python-0.3.0/tests/unit/test_bumble_key_store_metadata.py +0 -51
- swbt_python-0.3.0/tests/unit/test_docs_workflow.py +0 -68
- swbt_python-0.3.0/tests/unit/test_hardware_test_log_docs.py +0 -73
- swbt_python-0.3.0/tests/unit/test_mkdocs_site.py +0 -46
- swbt_python-0.3.0/tests/unit/test_public_api_docstrings.py +0 -287
- swbt_python-0.3.0/tests/unit/test_public_docs.py +0 -376
- swbt_python-0.3.0/tests/unit/test_readme_docs.py +0 -133
- swbt_python-0.3.0/tests/unit/test_release_gate_docs.py +0 -82
- swbt_python-0.3.0/tests/unit/test_report_loop.py +0 -127
- {swbt_python-0.3.0 → swbt_python-0.5.0}/LICENSE +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_001/M0_PROTOCOL_CORE.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_002/M1_SWITCH_GAMEPAD_FAKE_TRANSPORT.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_003/M2_BUMBLE_HID_TRANSPORT.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_004/M3_PAIRING_L2CAP.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_006/M5_INPUT_OPERATION_API.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_007/M6_RECONNECT_KEYSTORE_DIAGNOSTICS.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_008/M7_PACKAGING_EXAMPLES_CLI.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_009/PORTING_SOURCE_AUDIT.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_010/DIAGNOSTICS_TRACE_SCHEMA.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_011/HARDWARE_TEST_LOG_MATRIX.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_012/INITIAL_RELEASE_GATE.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_013/POST_M5_INPUT_SEMANTIC_CHARACTERIZATION.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_014/DEVICE_CLOSE_GRACEFUL_DISCONNECT.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_015/CONTEXT_MANAGER_RESOURCE_SCOPE.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_016/JSON_KEY_STORE_CURRENT_PREVIOUS.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_017/SWITCH_GAMEPAD_API_HARDENING.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_018/KEY_STORE_TRANSPORT_BOUNDARY.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_019/TRANSPORT_RECONNECT_CONTRACT.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_020/STRUCTURAL_REFACTOR_BOUNDARIES.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_021/SWITCH_GAMEPAD_INPUT_API_CONTRACT.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_022/PUBLIC_API_USAGE_HARDWARE_DOCS.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_023/MKDOCS_DOCUMENTATION_SITE.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_024/STICK_INPUT_SHORTHAND_API.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_025/IMU_INPUT_SHORTHAND_API.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_026/LINUX_MACOS_ADAPTER_EXPERIMENTAL.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_027/ADAPTER_DISCOVERY_API.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_028/CONTROLLER_PROFILE_CUSTOMIZATION.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_029/CONTROLLER_PROFILE_INJECTION.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_030/JOYCON_PROFILE_IDENTITY_SPI.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_031/JOYCON_INPUT_REPORT_MAPPING.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_032/PROFILE_AWARE_SUBCOMMAND_STATE.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_033/PROFILE_AWARE_BUMBLE_SDP.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_034/JOYCON_CONVENIENCE_API_DOCS.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_035/JOYCON_DEVICE_INFO_ADDRESS_WIRING.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_036/JOYCON_SDP_IDENTITY_POLICY.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_037/JOYCON_DEFAULT_CONTROLLER_COLORS.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_038/REARCHITECTURE_DECISION_BOUNDARY_TESTS.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_039/CONTROLLER_RUNTIME_EXTRACTION.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_040/PUBLIC_CONTROLLER_API_MODEL.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_041/CONTROLLER_CONFIG_PROFILE_OWNERSHIP.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_042/INTERNAL_TRANSPORT_FACTORY.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_043/PROTOCOL_PROFILE_MODULE_SPLIT.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_044/REARCHITECTURE_DOCS_RELEASE_MATRIX.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_045/INTERNAL_API_BOUNDARY_CLEANUP.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_046/HARDWARE_PROFILE_TEST_SCENARIOS.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_047/VIRTUAL_GYRO_CALIBRATION.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_048/VIRTUAL_ACCELEROMETER_CALIBRATION.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_049/IMU_SESSION_AND_ENCODING_REDESIGN.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/dev-journal.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/initial/README.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/initial/naming.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/rearchitecture/01-design-change-overview.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/rearchitecture/02-as-is-to-be.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/rearchitecture/03-public-api-config-profile.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/rearchitecture/04-runtime-profile-transport-details.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/rearchitecture/05-milestones-implementation.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/rearchitecture/README.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/spec/rearchitecture/mkdocs-nav-snippet.yml +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/_testing/__init__.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/adapter_discovery.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/gamepad/constants.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/imu.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/input.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/__init__.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/buttons.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/descriptors.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/imu_report.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/input_report.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/output_report.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/profiles/__init__.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/profiles/joycon.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/profiles/pro_controller.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/rumble.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/session.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/spi.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/protocol/subcommand.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/py.typed +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/state_store.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/transport/__init__.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/transport/_bumble_acl.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/transport/_bumble_hidp.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/transport/_bumble_lifecycle.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/transport/_bumble_sdp.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/transport/_bumble_usb_devices.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/src/swbt/transport/fake.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/hardware/README.md +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/hardware/test_bumble_transport.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/hardware/test_close_disconnect.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/hardware/test_context_manager_resource_scope.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/hardware/test_controller_colors.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/hardware/test_pairing_l2cap.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/integration/test_examples.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_adapter_discovery.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_bumble_acl.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_bumble_hidp.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_bumble_lifecycle.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_bumble_sdp.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_ci_workflow.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_imu_report.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_input_report.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_input_state.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_output_report.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_package_metadata.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_protocol_boundary.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_protocol_session.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_rumble_state.py +0 -0
- {swbt_python-0.3.0 → swbt_python-0.5.0}/tests/unit/test_virtual_spi_flash.py +0 -0
|
@@ -77,10 +77,18 @@
|
|
|
77
77
|
| 実機観測 | `spec/hardware-test-log.md` |
|
|
78
78
|
| 初期設計 | `spec/initial/` |
|
|
79
79
|
|
|
80
|
-
作業仕様には、対象範囲、対象外、関連 docs、根拠監査、TDD Test List
|
|
80
|
+
作業仕様には、対象範囲、対象外、関連 docs、根拠監査、TDD Test List または文書検証計画、検証、実機実行条件、先送り事項、チェックリストを含める。
|
|
81
81
|
|
|
82
82
|
複数の作業仕様から参照する安定した判断は、既存の `spec/initial/` を更新するか、必要に応じて `spec/` 配下へ分ける。未確定の観測は `spec/dev-journal.md` に置く。
|
|
83
83
|
|
|
84
|
+
## 文書の検証
|
|
85
|
+
|
|
86
|
+
- 自然言語の意味要件を、固定語句の存在・不在 assertion に置き換えない。正しい言い換えを落とす検査、または誤った説明を通す検査は追加しない。
|
|
87
|
+
- 自動検査の対象は、生成、構造、リンク、参照先、front matter、構造化データ、生成元との対応など、機械的に観測でき、失敗原因を切り分けられる契約に限る。
|
|
88
|
+
- 説明の事実性、読者が手順を完了するための前提・操作・終了後の復帰手順、未検証範囲の伝達は、正本との照合を伴うレビューで検証する。pytest の成功をその根拠にしない。
|
|
89
|
+
- docs / spec / skill だけの作業では、TDD Test List と pytest を必須にしない。選んだ自動検査、レビュー、未実行の検証を理由付きで記録する。
|
|
90
|
+
- README、利用者向け docs、公開 API docstring、release notes を変更した場合は `docs-quality-review` を使い、未解決の修正必須事項を handoff または PR 本文に残す。
|
|
91
|
+
|
|
84
92
|
## Agent Skills
|
|
85
93
|
|
|
86
94
|
repo-local skill は `.agents/skills` を正本として管理する。`.github/skills` には重複配置しない。
|
|
@@ -92,6 +100,7 @@ repo-local skill は `.agents/skills` を正本として管理する。`.github/
|
|
|
92
100
|
- `spec-format`: `spec/wip` / `spec/complete` の作業仕様を作成、更新、完了移動する。
|
|
93
101
|
- `dev-journal`: 小さい設計観測や先送り事項を `spec/dev-journal.md` に記録する。
|
|
94
102
|
- `docs-wording`: README、docs、release notes の文言整理で、swbt-python 固有の訳語と残す英語表記をそろえる。
|
|
103
|
+
- `docs-quality-review`: README、利用者向け docs、公開 API docstring、release notes を、対象読者の利用手順、根拠、未検証範囲、読みやすさの観点で確認する。
|
|
95
104
|
- `source-audit`: Switch HID、Bumble、既存実装、実機ログ由来の値を根拠分類して記録する。
|
|
96
105
|
- `hardware-harness`: Bumble adapter、Bluetooth dongle、Switch 実機を使う検証の承認境界と記録項目を確認する。
|
|
97
106
|
- `tdd-workflow`: TDD Test List から red / green / refactor を進める。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: swbt-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
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
|
|
@@ -52,10 +52,10 @@ uv sync --dev
|
|
|
52
52
|
|
|
53
53
|
[公開ドキュメント](https://niart120.github.io/swbt-python/) には API、利用例、実機準備手順、AI エージェント向け要約があります。
|
|
54
54
|
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
55
|
+
- [API リファレンス](https://niart120.github.io/swbt-python/api/)
|
|
56
|
+
- [利用例](https://niart120.github.io/swbt-python/usage/)
|
|
57
|
+
- [実機準備手順](https://niart120.github.io/swbt-python/hardware/)
|
|
58
|
+
- [Agent Brief](https://niart120.github.io/swbt-python/agent-brief/)
|
|
59
59
|
|
|
60
60
|
同じ内容は `docs/` 配下でも確認できます。
|
|
61
61
|
|
|
@@ -67,10 +67,7 @@ from swbt import Button, ProController
|
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
async def main() -> None:
|
|
70
|
-
async with ProController(
|
|
71
|
-
adapter="usb:0",
|
|
72
|
-
key_store_path="switch-bond.json",
|
|
73
|
-
) as pad:
|
|
70
|
+
async with ProController(adapter="usb:0") as pad:
|
|
74
71
|
await pad.connect(
|
|
75
72
|
timeout=30.0,
|
|
76
73
|
allow_pairing=True,
|
|
@@ -82,11 +79,11 @@ async def main() -> None:
|
|
|
82
79
|
asyncio.run(main())
|
|
83
80
|
```
|
|
84
81
|
|
|
85
|
-
Pro Controller
|
|
82
|
+
Pro Controller 相当の一時的な仮想デバイスを作成し、ペアリング後に A ボタン入力を送信するコードの例です。接続情報を永続化する場合は `ProController.create_profile()` を使います。`local_address` を省略するとアダプタが現在報告する Bluetooth アドレスを維持し、揮発領域へ書き込みません。利用者管理のローカルアドレスへ切り替える手順は[利用例](docs/usage.md)、対応する専用 USB Bluetooth ドングルと復旧手順は[実機準備手順](docs/hardware.md)を参照してください。
|
|
86
83
|
|
|
87
84
|
### Joy-Con L/R
|
|
88
85
|
|
|
89
|
-
Joy-Con 相当の仮想デバイスは `JoyConL(...)` または `JoyConR(...)`
|
|
86
|
+
Joy-Con 相当の仮想デバイスは `JoyConL(...)` または `JoyConR(...)` で作成します。以下の例は `JoyConL.create_profile()` で作成済みのプロファイルを再利用します。接続と入力の扱い方は `ProController` と同じです。
|
|
90
87
|
|
|
91
88
|
```python
|
|
92
89
|
import asyncio
|
|
@@ -96,7 +93,7 @@ from swbt import Button, JoyConL, Stick
|
|
|
96
93
|
async def main() -> None:
|
|
97
94
|
async with JoyConL(
|
|
98
95
|
adapter="usb:0",
|
|
99
|
-
|
|
96
|
+
profile_path="switch-left-joycon-profile.json",
|
|
100
97
|
) as left:
|
|
101
98
|
await left.connect(timeout=30.0, allow_pairing=True)
|
|
102
99
|
await left.tap(Button.SR, Button.SL)
|
|
@@ -108,27 +105,27 @@ async def main() -> None:
|
|
|
108
105
|
asyncio.run(main())
|
|
109
106
|
```
|
|
110
107
|
|
|
111
|
-
|
|
108
|
+
「持ちかた/順番を変える」画面で Joy-Con としてペアリングする場合は、接続後に `await left.tap(Button.SR, Button.SL)` のように SR+SL を送信する必要があります。
|
|
112
109
|
|
|
113
|
-
Pro Controller
|
|
110
|
+
Pro Controller、周期送信型 Joy-Con、直接送信型はすべて、Bluetooth アドレスの選択方法とペアリングキーをまとめる `profile_path` を使います。新規プロファイルは各具象クラスの `create_profile()` で作成し、コントローラー形状と対象機器ごとに保存先を分けてください。v0.4.0 の `key_store_path` で使用していた JSON 形式のペアリング情報との互換経路はありません。Joy-Con L で右スティックや A/B/X/Y、Joy-Con R で左スティックや十字キーを入力すると `UnsupportedInputError` が送出されます。`JoyConPair` は未実装です。
|
|
114
111
|
|
|
115
112
|
## 接続方法
|
|
116
113
|
|
|
117
|
-
実機接続には、PC の通常 Bluetooth 機能と共有しない専用 USB Bluetooth ドングルと、OS ごとのドライバー準備が必要です。Windows では、[Zadig](https://zadig.akeo.ie/) などで専用ドングルに WinUSB / libwdi
|
|
114
|
+
実機接続には、PC の通常 Bluetooth 機能と共有しない専用 USB Bluetooth ドングルと、OS ごとのドライバー準備が必要です。Windows では、[Zadig](https://zadig.akeo.ie/) などで専用ドングルに WinUSB / libwdi ドライバーを入れてからアダプタ名を確認します。
|
|
118
115
|
|
|
119
|
-
ドライバー準備、アダプタ名の確認、トラブルシューティングの詳細は
|
|
116
|
+
ドライバー準備、アダプタ名の確認、トラブルシューティングの詳細は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)にあります。
|
|
120
117
|
|
|
121
118
|
### 確認済み構成
|
|
122
119
|
|
|
123
|
-
2026-07-07 時点では、Windows 11 / CSR8510 A10 / WinUSB / `usb:0` / Switch 2
|
|
120
|
+
2026-07-07 時点では、Windows 11 / CSR8510 A10 / WinUSB / `usb:0` / Switch 2 ファームウェア 22.1.0 で、Pro Controller のペアリング、保存済みペアリング情報を使う再接続、主要なボタン / スティック入力、ニュートラル復帰を確認済みです。
|
|
124
121
|
|
|
125
|
-
同じ Windows 構成で、Joy-Con L/R も部分的に動作確認済みです。確認済み範囲と未確認範囲の詳細は
|
|
122
|
+
同じ Windows 構成で、Joy-Con L/R も部分的に動作確認済みです。確認済み範囲と未確認範囲の詳細は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)にあります。
|
|
126
123
|
|
|
127
124
|
macOS 15.7.7 / CSR8510 A10 では、Pro Controller のペアリング、保存済みペアリング情報を使う再接続、ボタン入力、ニュートラル復帰を記録しています。
|
|
128
125
|
|
|
129
126
|
### 実験的構成
|
|
130
127
|
|
|
131
|
-
Linux は experimental です。手順は
|
|
128
|
+
Linux は experimental です。手順は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)に整備されていますが、専用 USB Bluetooth ドングルにアクセスできるか、ペアリングできるか、入力が反映されるかは未確認です。macOS は Pro Controller の一部挙動のみ検証済みです。Joy-Con、別ドングル、別ファームウェアでの互換性は未確認です。
|
|
132
129
|
|
|
133
130
|
## 開発
|
|
134
131
|
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# swbt-python
|
|
2
|
+
|
|
3
|
+
NX 向けの仮想 Bluetooth HID 入力デバイスを Python から扱うためのライブラリです。
|
|
4
|
+
|
|
5
|
+
本ライブラリは pre-alpha 版です。実機での動作は Bluetooth ドングル、ドライバー、対象機器の FW バージョンに依存します。
|
|
6
|
+
|
|
7
|
+
## 必要なもの
|
|
8
|
+
|
|
9
|
+
- Python 3.12 以降
|
|
10
|
+
- uv
|
|
11
|
+
- Bumble が利用可能な専用 USB Bluetooth ドングル
|
|
12
|
+
|
|
13
|
+
## インストール
|
|
14
|
+
|
|
15
|
+
```powershell
|
|
16
|
+
pip install swbt-python
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
ソースから動かす場合は次を使います。
|
|
20
|
+
|
|
21
|
+
```powershell
|
|
22
|
+
uv sync --dev
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## ドキュメント
|
|
26
|
+
|
|
27
|
+
[公開ドキュメント](https://niart120.github.io/swbt-python/) には API、利用例、実機準備手順、AI エージェント向け要約があります。
|
|
28
|
+
|
|
29
|
+
- [API リファレンス](https://niart120.github.io/swbt-python/api/)
|
|
30
|
+
- [利用例](https://niart120.github.io/swbt-python/usage/)
|
|
31
|
+
- [実機準備手順](https://niart120.github.io/swbt-python/hardware/)
|
|
32
|
+
- [Agent Brief](https://niart120.github.io/swbt-python/agent-brief/)
|
|
33
|
+
|
|
34
|
+
同じ内容は `docs/` 配下でも確認できます。
|
|
35
|
+
|
|
36
|
+
## 利用例
|
|
37
|
+
### Pro Controller
|
|
38
|
+
```python
|
|
39
|
+
import asyncio
|
|
40
|
+
from swbt import Button, ProController
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
async def main() -> None:
|
|
44
|
+
async with ProController(adapter="usb:0") as pad:
|
|
45
|
+
await pad.connect(
|
|
46
|
+
timeout=30.0,
|
|
47
|
+
allow_pairing=True,
|
|
48
|
+
)
|
|
49
|
+
await pad.tap(Button.A)
|
|
50
|
+
await pad.neutral()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
asyncio.run(main())
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Pro Controller 相当の一時的な仮想デバイスを作成し、ペアリング後に A ボタン入力を送信するコードの例です。接続情報を永続化する場合は `ProController.create_profile()` を使います。`local_address` を省略するとアダプタが現在報告する Bluetooth アドレスを維持し、揮発領域へ書き込みません。利用者管理のローカルアドレスへ切り替える手順は[利用例](docs/usage.md)、対応する専用 USB Bluetooth ドングルと復旧手順は[実機準備手順](docs/hardware.md)を参照してください。
|
|
57
|
+
|
|
58
|
+
### Joy-Con L/R
|
|
59
|
+
|
|
60
|
+
Joy-Con 相当の仮想デバイスは `JoyConL(...)` または `JoyConR(...)` で作成します。以下の例は `JoyConL.create_profile()` で作成済みのプロファイルを再利用します。接続と入力の扱い方は `ProController` と同じです。
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
import asyncio
|
|
64
|
+
from swbt import Button, JoyConL, Stick
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
async def main() -> None:
|
|
68
|
+
async with JoyConL(
|
|
69
|
+
adapter="usb:0",
|
|
70
|
+
profile_path="switch-left-joycon-profile.json",
|
|
71
|
+
) as left:
|
|
72
|
+
await left.connect(timeout=30.0, allow_pairing=True)
|
|
73
|
+
await left.tap(Button.SR, Button.SL)
|
|
74
|
+
await left.tap(Button.L)
|
|
75
|
+
await left.lstick(Stick.left())
|
|
76
|
+
await left.neutral()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
asyncio.run(main())
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
「持ちかた/順番を変える」画面で Joy-Con としてペアリングする場合は、接続後に `await left.tap(Button.SR, Button.SL)` のように SR+SL を送信する必要があります。
|
|
83
|
+
|
|
84
|
+
Pro Controller、周期送信型 Joy-Con、直接送信型はすべて、Bluetooth アドレスの選択方法とペアリングキーをまとめる `profile_path` を使います。新規プロファイルは各具象クラスの `create_profile()` で作成し、コントローラー形状と対象機器ごとに保存先を分けてください。v0.4.0 の `key_store_path` で使用していた JSON 形式のペアリング情報との互換経路はありません。Joy-Con L で右スティックや A/B/X/Y、Joy-Con R で左スティックや十字キーを入力すると `UnsupportedInputError` が送出されます。`JoyConPair` は未実装です。
|
|
85
|
+
|
|
86
|
+
## 接続方法
|
|
87
|
+
|
|
88
|
+
実機接続には、PC の通常 Bluetooth 機能と共有しない専用 USB Bluetooth ドングルと、OS ごとのドライバー準備が必要です。Windows では、[Zadig](https://zadig.akeo.ie/) などで専用ドングルに WinUSB / libwdi ドライバーを入れてからアダプタ名を確認します。
|
|
89
|
+
|
|
90
|
+
ドライバー準備、アダプタ名の確認、トラブルシューティングの詳細は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)にあります。
|
|
91
|
+
|
|
92
|
+
### 確認済み構成
|
|
93
|
+
|
|
94
|
+
2026-07-07 時点では、Windows 11 / CSR8510 A10 / WinUSB / `usb:0` / Switch 2 ファームウェア 22.1.0 で、Pro Controller のペアリング、保存済みペアリング情報を使う再接続、主要なボタン / スティック入力、ニュートラル復帰を確認済みです。
|
|
95
|
+
|
|
96
|
+
同じ Windows 構成で、Joy-Con L/R も部分的に動作確認済みです。確認済み範囲と未確認範囲の詳細は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)にあります。
|
|
97
|
+
|
|
98
|
+
macOS 15.7.7 / CSR8510 A10 では、Pro Controller のペアリング、保存済みペアリング情報を使う再接続、ボタン入力、ニュートラル復帰を記録しています。
|
|
99
|
+
|
|
100
|
+
### 実験的構成
|
|
101
|
+
|
|
102
|
+
Linux は experimental です。手順は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)に整備されていますが、専用 USB Bluetooth ドングルにアクセスできるか、ペアリングできるか、入力が反映されるかは未確認です。macOS は Pro Controller の一部挙動のみ検証済みです。Joy-Con、別ドングル、別ファームウェアでの互換性は未確認です。
|
|
103
|
+
|
|
104
|
+
## 開発
|
|
105
|
+
|
|
106
|
+
```powershell
|
|
107
|
+
uv sync --dev
|
|
108
|
+
uv run ruff format --check .
|
|
109
|
+
uv run ruff check .
|
|
110
|
+
uv run ty check --no-progress
|
|
111
|
+
uv run pytest tests/unit
|
|
112
|
+
uv run pytest tests/integration
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## ライセンス
|
|
116
|
+
|
|
117
|
+
MIT ライセンスです。全文は [LICENSE](https://github.com/niart120/swbt-python/blob/main/LICENSE) にあります。
|
|
118
|
+
|
|
119
|
+
## 注記
|
|
120
|
+
|
|
121
|
+
このプロジェクトは、対象機器や関連商標の権利者から承認、後援、提携を受けたものではありません。
|
|
@@ -17,7 +17,7 @@ from swbt import Button, DiagnosticsConfig, ProController
|
|
|
17
17
|
async def run(
|
|
18
18
|
*,
|
|
19
19
|
adapter: str,
|
|
20
|
-
|
|
20
|
+
profile_path: str,
|
|
21
21
|
trace_path: Path,
|
|
22
22
|
connect_timeout: float,
|
|
23
23
|
tap_duration: float,
|
|
@@ -26,7 +26,7 @@ async def run(
|
|
|
26
26
|
|
|
27
27
|
Args:
|
|
28
28
|
adapter: Bumble adapter moniker, such as ``"usb:0"``.
|
|
29
|
-
|
|
29
|
+
profile_path: Existing swbt profile path.
|
|
30
30
|
trace_path: JSON Lines diagnostics trace output path.
|
|
31
31
|
connect_timeout: Seconds to wait for reconnect or pairing.
|
|
32
32
|
tap_duration: Seconds to keep Button A pressed.
|
|
@@ -35,7 +35,7 @@ async def run(
|
|
|
35
35
|
with trace_path.open("w", encoding="utf-8") as trace_writer:
|
|
36
36
|
await _bring_up_with_trace(
|
|
37
37
|
adapter=adapter,
|
|
38
|
-
|
|
38
|
+
profile_path=profile_path,
|
|
39
39
|
connect_timeout=connect_timeout,
|
|
40
40
|
tap_duration=tap_duration,
|
|
41
41
|
trace_writer=trace_writer,
|
|
@@ -45,7 +45,7 @@ async def run(
|
|
|
45
45
|
async def _bring_up_with_trace(
|
|
46
46
|
*,
|
|
47
47
|
adapter: str,
|
|
48
|
-
|
|
48
|
+
profile_path: str,
|
|
49
49
|
connect_timeout: float,
|
|
50
50
|
tap_duration: float,
|
|
51
51
|
trace_writer: TextIO,
|
|
@@ -53,7 +53,7 @@ async def _bring_up_with_trace(
|
|
|
53
53
|
diagnostics = DiagnosticsConfig(trace_writer=trace_writer)
|
|
54
54
|
async with ProController(
|
|
55
55
|
adapter=adapter,
|
|
56
|
-
|
|
56
|
+
profile_path=profile_path,
|
|
57
57
|
diagnostics=diagnostics,
|
|
58
58
|
) as pad:
|
|
59
59
|
await pad.connect(
|
|
@@ -77,7 +77,9 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
77
77
|
),
|
|
78
78
|
)
|
|
79
79
|
parser.add_argument("--adapter", default="usb:0", help="Bumble adapter moniker")
|
|
80
|
-
parser.add_argument(
|
|
80
|
+
parser.add_argument(
|
|
81
|
+
"--profile", dest="profile_path", required=True, help="existing swbt profile path"
|
|
82
|
+
)
|
|
81
83
|
parser.add_argument("--trace", required=True, type=Path, help="JSON Lines trace output path")
|
|
82
84
|
parser.add_argument("--timeout", default=30.0, type=float, help="connection timeout seconds")
|
|
83
85
|
parser.add_argument(
|
|
@@ -102,7 +104,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
102
104
|
asyncio.run(
|
|
103
105
|
run(
|
|
104
106
|
adapter=args.adapter,
|
|
105
|
-
|
|
107
|
+
profile_path=args.profile_path,
|
|
106
108
|
trace_path=args.trace,
|
|
107
109
|
connect_timeout=args.timeout,
|
|
108
110
|
tap_duration=args.tap_duration,
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Create one Pro Controller profile after explicit hardware approval."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import asyncio
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from swbt import DiagnosticsConfig, ProController
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
async def run(
|
|
12
|
+
*,
|
|
13
|
+
adapter: str,
|
|
14
|
+
profile_path: str,
|
|
15
|
+
local_address: str,
|
|
16
|
+
trace_path: Path,
|
|
17
|
+
pair_timeout: float,
|
|
18
|
+
) -> None:
|
|
19
|
+
"""Create a profile and run its first approved pairing.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
adapter: Bumble adapter moniker, such as ``"usb:0"``.
|
|
23
|
+
profile_path: New swbt profile path. It must not already exist.
|
|
24
|
+
local_address: Individual locally administered Bluetooth address.
|
|
25
|
+
trace_path: JSON Lines diagnostics trace output path.
|
|
26
|
+
pair_timeout: Seconds to wait for a host connection.
|
|
27
|
+
"""
|
|
28
|
+
trace_path.parent.mkdir(parents=True, exist_ok=True)
|
|
29
|
+
with trace_path.open("w", encoding="utf-8") as trace_writer:
|
|
30
|
+
pad = await ProController.create_profile(
|
|
31
|
+
adapter=adapter,
|
|
32
|
+
profile_path=profile_path,
|
|
33
|
+
local_address=local_address,
|
|
34
|
+
pair_timeout=pair_timeout,
|
|
35
|
+
diagnostics=DiagnosticsConfig(trace_writer=trace_writer),
|
|
36
|
+
)
|
|
37
|
+
await pad.close()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
41
|
+
"""Build the example argument parser."""
|
|
42
|
+
parser = argparse.ArgumentParser(
|
|
43
|
+
description="Create a profile and pair after explicit approval with cleanup.",
|
|
44
|
+
)
|
|
45
|
+
parser.add_argument("--adapter", default="usb:0", help="Bumble adapter moniker")
|
|
46
|
+
parser.add_argument("--profile", required=True, help="new swbt profile path")
|
|
47
|
+
parser.add_argument(
|
|
48
|
+
"--local-address",
|
|
49
|
+
required=True,
|
|
50
|
+
help="individual locally administered Bluetooth address",
|
|
51
|
+
)
|
|
52
|
+
parser.add_argument("--trace", required=True, type=Path, help="JSON Lines trace output path")
|
|
53
|
+
parser.add_argument("--timeout", default=30.0, type=float, help="pairing timeout seconds")
|
|
54
|
+
return parser
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def main(argv: Sequence[str] | None = None) -> int:
|
|
58
|
+
"""Run the example."""
|
|
59
|
+
args = build_parser().parse_args(argv)
|
|
60
|
+
asyncio.run(
|
|
61
|
+
run(
|
|
62
|
+
adapter=args.adapter,
|
|
63
|
+
profile_path=args.profile,
|
|
64
|
+
local_address=args.local_address,
|
|
65
|
+
trace_path=args.trace,
|
|
66
|
+
pair_timeout=args.timeout,
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
return 0
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
raise SystemExit(main())
|
|
@@ -29,7 +29,7 @@ async def tap_a_once(pad: SwitchGamepad, *, duration: float = 0.08) -> None:
|
|
|
29
29
|
async def run(
|
|
30
30
|
*,
|
|
31
31
|
adapter: str,
|
|
32
|
-
|
|
32
|
+
profile_path: str,
|
|
33
33
|
connect_timeout: float,
|
|
34
34
|
duration: float,
|
|
35
35
|
allow_pairing: bool,
|
|
@@ -38,12 +38,12 @@ async def run(
|
|
|
38
38
|
|
|
39
39
|
Args:
|
|
40
40
|
adapter: Bumble adapter moniker, such as ``"usb:0"``.
|
|
41
|
-
|
|
41
|
+
profile_path: Existing swbt profile path.
|
|
42
42
|
connect_timeout: Seconds to wait for each connection attempt.
|
|
43
43
|
duration: Seconds to keep Button A pressed.
|
|
44
44
|
allow_pairing: If ``True``, allow first-time pairing when no bond exists.
|
|
45
45
|
"""
|
|
46
|
-
async with ProController(adapter=adapter,
|
|
46
|
+
async with ProController(adapter=adapter, profile_path=profile_path) as pad:
|
|
47
47
|
await pad.connect(
|
|
48
48
|
timeout=connect_timeout,
|
|
49
49
|
allow_pairing=allow_pairing,
|
|
@@ -61,7 +61,9 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
61
61
|
description="Tap Button A once through swbt-python.",
|
|
62
62
|
)
|
|
63
63
|
parser.add_argument("--adapter", default="usb:0", help="Bumble adapter moniker")
|
|
64
|
-
parser.add_argument(
|
|
64
|
+
parser.add_argument(
|
|
65
|
+
"--profile", dest="profile_path", required=True, help="existing swbt profile path"
|
|
66
|
+
)
|
|
65
67
|
parser.add_argument("--timeout", default=30.0, type=float, help="connection timeout seconds")
|
|
66
68
|
parser.add_argument(
|
|
67
69
|
"--duration",
|
|
@@ -90,7 +92,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
90
92
|
asyncio.run(
|
|
91
93
|
run(
|
|
92
94
|
adapter=args.adapter,
|
|
93
|
-
|
|
95
|
+
profile_path=args.profile_path,
|
|
94
96
|
connect_timeout=args.timeout,
|
|
95
97
|
duration=args.duration,
|
|
96
98
|
allow_pairing=args.allow_pairing,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "swbt-python"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.5.0"
|
|
4
4
|
description = "Python library for presenting an NX-compatible virtual Bluetooth HID input device."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -141,7 +141,7 @@ error-on-warning = true
|
|
|
141
141
|
output-format = "concise"
|
|
142
142
|
|
|
143
143
|
[tool.pytest.ini_options]
|
|
144
|
-
addopts = "-ra --strict-config --strict-markers"
|
|
144
|
+
addopts = "-ra --strict-config --strict-markers --basetemp=tmp/pytest"
|
|
145
145
|
testpaths = ["tests"]
|
|
146
146
|
markers = [
|
|
147
147
|
"bumble: requires a dedicated USB Bluetooth dongle opened through Bumble",
|
{swbt_python-0.3.0 → swbt_python-0.5.0}/spec/complete/unit_005/M4_SUBCOMMAND_RESPONDER_HARDWARE.md
RENAMED
|
@@ -60,7 +60,7 @@ Switch から受け取る output report と subcommand sequence を実機 trace
|
|
|
60
60
|
| 項目 | 要否 | 状態 | 根拠 / 理由 |
|
|
61
61
|
|---|---|---|---|
|
|
62
62
|
| Switch HID / report bytes | required | done | `tests/unit/fixtures/source_audit/switch_protocol_values.toml` の `output_report_parser_layout`、`subcommand_reply_0x21_layout`、`subcommand_reply_payloads`、`spi_flash_boundary_and_seed_map`、`raw_rumble_payload` を source fact / implementation fact として使う |
|
|
63
|
-
| Bumble / transport | required | done | `bumble_hid_device_api`、`bumble_hidp_output_report_boundary`、`btstack_reference_hid_sdp_policy`、`bumble_reference_classic_link_policy`、`bumble_acl_packet_queue_drain_boundary` を使う。Bumble `0.0.230` の DATA / SET_REPORT callback 境界、参照実装の HID SDP policy、service name / language base 属性、daemon production の default link policy `ROLE_SWITCH|SNIFF_MODE` = `0x0005`、
|
|
63
|
+
| Bumble / transport | required | done | `bumble_hid_device_api`、`bumble_hidp_output_report_boundary`、`btstack_reference_hid_sdp_policy`、`bumble_reference_classic_link_policy`、`bumble_acl_packet_queue_drain_boundary` を使う。Bumble `0.0.230` の DATA / SET_REPORT callback 境界、参照実装の HID SDP policy、service name / language base 属性、daemon production の default link policy `ROLE_SWITCH|SNIFF_MODE` = `0x0005`、ACL queue の投入・drain 境界は根拠化済み。通常送信をenqueue受理、明示切断をdrain境界とする現行方針は unit_064 で更新した。実機 sequence の callback timing は M4 実行時の hardware observation として別記録にする |
|
|
64
64
|
| OS / driver / adapter | required | done | `swbt_daemon_csr8510_winusb_observation` は既存 daemon の条件付き観測であり、Bumble / 別 firmware へ一般化しない。M4 実機 trace は adapter、driver、Bumble version、Switch firmware 付きで `docs/hardware-test-log.md` に記録する |
|
|
65
65
|
|
|
66
66
|
## 6. 振る舞い仕様
|