Hardware
swbt-python の実機接続では、PC の標準 Bluetooth 機能ではなく、Bumble から直接開く専用 USB Bluetooth dongle を使います。
最初に driver と adapter 名を確認し、その後に対象機器側で controller pairing / search 画面を開いて接続します。
Setup
General Requirements
| 項目 | 内容 |
|---|---|
| Python | Python 3.12 以降 |
| USB Bluetooth dongle | PC の通常 Bluetooth 機能と共有しない専用 dongle |
| 対象機器 | controller pairing / search 画面へ手動で移動できること |
Driver / USB Access
Bumble の usb: adapter は USB HCI transport を libusb 経由で使用します。
ここでの driver 準備は、OS の Bluetooth 機能で使う driver ではなく、専用 dongle を Bumble から直接開くための OS 側設定を指します。
| OS | status | 準備 |
|---|---|---|
| Windows | supported | Zadig などで専用 dongle に WinUSB / libwdi driver を導入する |
| Linux | experimental | libusb-1.0 が使えること、USB デバイスにアクセスできること、kernel / BlueZ が対象 dongle を使用中でないことを確認する |
| macOS | experimental | libusb-1.0 が使えること、macOS Bluetooth stack が外付け HCI を使用しない設定になっていること、必要に応じて libusb の library path を指定する |
Bumble USB Transport Requirements
Bumble の usb: adapter は USB HCI transport を libusb 経由で扱います。Bumble の USB transport documentation では、usb: moniker、libusb-1.0、usb_probe / lsusb による列挙確認が示されています。
swbt-python の lock file では Bumble 0.0.230 と libusb1 / libusb-package dependency を固定しています。
Windows USB & Driver Setup
Windows では、Zadig などで専用 USB Bluetooth dongle に WinUSB / libwdi driver を導入する必要があります。
Zadig は、Windows 上で WinUSB などの汎用 USB driver を対象デバイスへ入れるためのツールです。
Zadig では次の順に進めます。
- 専用 USB Bluetooth dongle を接続し、Zadig を管理者権限で起動する。
- 対象の dongle を選択する。
- 一覧に出ない場合は
Options > List All Devicesを使う。 - 選択した USB デバイスの VID / PID が対象 dongle と一致することを確認する。
- driver は
WinUSBを選ぶ。 Install Driverを実行する。
Zadig の操作画面と詳細: Zadig 2.x User Guide。
Linux USB & Driver Setup
Linux の手順はこの Hardware Guide に整備されていますが、動作検証されていないことに留意してください。
Linux では、Bumble 同梱の libusb_package で libusb-1.0 が見つからない場合、OS 側で apt install libusb-1.0-0 が必要になることがあります。USB デバイスへのアクセス権を付け、kernel / BlueZ が dongle を使用中の場合は hciconfig hciX down などで解放する必要があります。
macOS USB & Driver Setup
macOS では、macOS Bluetooth stack が外付け HCI を使用しないように sudo nvram bluetoothHostControllerSwitchBehavior="never" の設定が必要になる場合があります。実行前に現在の値を確認します。
nvram bluetoothHostControllerSwitchBehavior
libusb-1.0.dylib が見つからない場合は、Homebrew で libusb を入れます。
brew install libusb
Intel Mac の Homebrew 環境では、libusb1 が /usr/local/opt/libusb/lib を自動探索しない場合があります。その場合は、実行時に DYLD_LIBRARY_PATH を指定します。
export DYLD_LIBRARY_PATH=/usr/local/opt/libusb/lib
uv run swbt-probe adapters --json
swbt-python を source checkout から動かす場合、依存 package の build で pkgconf と openssl@3 が必要になることがあります。
brew install pkgconf openssl@3
2026-07-05 の実機観測では、macOS 15.7.7、CSR8510 A10、Homebrew libusb 1.0.30、Bumble 0.0.230、Python 3.12.13、adapter usb:0 で、pairing、HID control / interrupt L2CAP、保存済み bond を使う active reconnect、button 入力、neutral cleanup を確認しています。
Linux / macOS Verification Scope
Linux / macOS は experimental です。ここに書いた内容は、Bumble から専用 adapter を使う前に確認する項目です。接続成功を保証するものではありません。
Linux 上の adapter listing、adapter open、HID advertising、pairing、reconnect、input reflection はまだ確認していません。macOS CI で確認するのは、依存関係のインストール、単体テスト、fake transport を使った結合テスト、パッケージ作成までです。USB Bluetooth dongle は使いません。
Adapter Name
driver 準備後、Bumble から見える adapter 名を確認します。
Python から確認する場合は list_adapters() を使います。
from swbt import list_adapters
for info in list_adapters():
print(info.name, info.aliases)
info.name は ProController(adapter=info.name) など concrete controller の adapter に渡す値です。list_adapters() は専用 USB Bluetooth dongle 候補を列挙します。対象機器本体や周辺 Bluetooth host は列挙しません。
CLI から確認する場合は swbt-probe adapters --json を使います。
swbt-probe adapters --json
list_adapters() と swbt-probe adapters --json は adapter 一覧確認用です。USB descriptor の読み取りは行いますが、Switch に向けた pairing、HID advertising、report loop は開始しません。Bumble transport として device handle を開きません。
adapter には usb:0 のような Bumble adapter 名を指定します。adapter 名は PC の接続状態で変わるため、コード例の usb:0 を固定値として扱わないでください。
Pairing And Reconnect
key_store_path は pairing 情報を保存する JSON key store path です。保存済み bond を使う場合は ProController(adapter="usb:0", key_store_path="switch-bond.json") のように指定します。
Profile-specific Key Stores
key store は controller profile ごとに分けてください。Pro Controller 相当、Joy-Con L 相当、Joy-Con R 相当のように HID identity や SDP record が異なる profile を同じ key store に混ぜると、保存済み bond と実際に advertising する identity の対応が崩れます。
運用例:
- Pro Controller 相当:
keys/pro-controller.json - Joy-Con L 相当:
keys/joy-con-left.json - Joy-Con R 相当:
keys/joy-con-right.json
同じ profile でも、接続先の対象機器を分ける場合は key store も分けます。1 つの key store は「1 つの対象機器」と「1 つの controller profile」の組み合わせに固定してください。
Controller Profile Verification Matrix
| Controller profile | Status | Verified scope | Not verified | Key store |
|---|---|---|---|---|
| Pro Controller | verified | Windows 11 / CSR8510 A10 / WinUSB / Switch 2 firmware 22.1.0 で pairing、reconnect、Button A / D-pad / left stick / right stick、neutral cleanup を確認。macOS 15.7.7 / CSR8510 A10 でも pairing、active reconnect、Button 入力、neutral cleanup を確認 | Linux、CSR8510 A10 以外の dongle、別 firmware、pairing-free incoming bond reuse | Use a separate key_store_path for each target device and controller profile |
| Joy-Con L | limited observation | Windows 11 / CSR8510 A10 / WinUSB / Switch 2 firmware 22.1.0 で Joy-Con L device name、device-info reply、subcommand 応答、SR+SL registration のユーザ目視を記録 | reconnect / normal input reflection、SDP の細部一致、OS / dongle / firmware をまたぐ互換性 | Use a separate key_store_path from Pro Controller and Joy-Con R |
| Joy-Con R | not verified | unit tests と fake transport integration で profile selection と unsupported input を確認 | pairing、reconnect / normal input reflection、Switch UI 登録、OS / dongle / firmware をまたぐ互換性 | Use a separate key_store_path from Pro Controller and Joy-Con L |
Joy-Con profile の実機互換は限定的な観測です。2026-07-06 の Joy-Con L run では、Joy-Con (L) の device name、Joy-Con L device-info reply、Switch からの subcommand 応答、neutral report loop、clean close を trace で確認しました。SDP policy 反映後の retest では、Joy-Con L の観測済み初期 sequence 0x02 / 0x08 / 0x10 / 0x03 / 0x04 / 0x40 / 0x30 / 0x48 に返信した後、Button.SR + Button.SL を約 5 秒間押下状態で periodic report に乗せ、ユーザ目視では Switch UI で Joy-Con として登録されました。Joy-Con 固有の reconnect、通常入力反映、Joy-Con R、SDP の細部一致、OS / dongle / firmware をまたぐ互換性は確認済みとして扱わないでください。
Bumble adapter open、HID advertising、Switch pairing、Switch-facing output report / subcommand handling、periodic input report loop は実機または USB Bluetooth dongle に触れる操作です。Joy-Con profile でこれらを試す場合も、対象 adapter、実行 command、Switch-facing 動作範囲、cleanup plan を明示したうえで、人間の承認を得てから実行してください。
connect(timeout=..., allow_pairing=True) は保存済み bond があれば reconnect を優先し、bond がない場合だけ pairing fallback へ進みます。初回 pairing では対象機器を controller pairing / search 画面に置いてください。
reconnect(timeout=...) は key store に current bonded peer が 1 件ある場合だけ active reconnect を試します。pairing fallback はしません。
1 つの key store に複数の current peers を混ぜないでください。複数 current peers は multiple current peers の不正状態として扱い、どの peer を使うかを推測しません。別対象機器には別の key_store_path を使ってください。
Confirmed Behavior
2026-07-04 時点では、Windows 11、CSR8510 A10、WinUSB / libwdi、Switch 2 firmware 22.1.0 の組み合わせで次を確認済みです。
- 初回 pairing。
- 保存済み pairing 情報を使う reconnect。
- Button A、D-pad、left / right stick の入力反映。
- neutral 後に入力が残らないこと。
2026-07-05 時点では、macOS 15.7.7、CSR8510 A10、Homebrew libusb、Switch 2、adapter usb:0 の組み合わせで次を確認済みです。
- 初回 pairing。
- 保存済み pairing 情報を使う active reconnect。
- 主要 subcommand への応答を含む初期化 sequence。
- Button 入力の反映。
- neutral 後に入力が残らないこと。
確認済み条件の trace、Bumble version、Python version、driver version は repository 内の spec/hardware-test-log.md にあります。
Notes
Linux / macOS で必要になる OS 側設定は、Bumble から専用 adapter を使うためのものです。PC の通常 Bluetooth 機能と同じ adapter は使わないでください。
Troubleshooting
Adapter Does Not Open
- 専用 USB Bluetooth dongle を使っているか確認します。
- Windows では WinUSB / libwdi に切り替わっているか確認します。
- 専用 dongle の adapter 名を指定しているか確認します。
list_adapters()またはswbt-probe adapters --jsonで adapter 名を確認します。adapters=[]は HCI 候補 0 件です。driver、USB 接続、OS 側の占有状態を確認します。AdapterDiscoveryErrorは libusb の読み込みや USB 列挙開始の失敗です。adapter open 失敗とは別に扱います。
Pairing Timeout
- 対象機器が controller pairing / search 画面にいるか確認します。
pair()またはconnect(..., allow_pairing=True)を使っているか確認します。- trace に
advertising_start、connection_request、host_connectionがあるか確認します。
No Bond
reconnect()/try_reconnect()は保存済み bond がない場合、no bondとして失敗します。- 初回接続では
connect(..., allow_pairing=True)かpair()を使います。 key_store_pathが別ファイルを指していないか確認します。
Multiple Current Peers
- 1 つの key store に複数の current peers がある状態です。
- 対象機器ごとに key store を分けます。
- 復旧する場合は該当 key store を削除し、pairing をやり直します。
Input Is Not Reflected In The UI
- pairing / reconnect 直後の初期通信が終わってから入力を送っているか確認します。
tap()は即時 report を送ります。press()/release()/sticks()/neutral()は state update API であり、即時送信を保証しません。- trace の
report_tx、subcommand_rx、subcommand_reply_tx、connected、disconnectedを確認します。