Branch: master->amiibo_edits
Emulate Nintendo Switch Controllers over Bluetooth.
Tested on Raspberry 4B Raspbian, should work on 3B+ too and anything that can do the setup.
Emulation of JOYCON_R, JOYCON_L and PRO_CONTROLLER. Able to send:
- button commands
- stick state
- nfc for amiibo read & owner registration
- Install dependencies
Raspbian:
sudo apt install python3-dbus libhidapi-hidraw0 libbluetooth-dev bluez
Python: (a setup.py is present but not yet up to date)
Note that pip here has to be run as root, as otherwise the packages are not available to the root user.
sudo pip3 install aioconsole hid crc8
If you are unsure if the packages are properly installed, try running sudo python3
and import each using import package_name
.
- setup bluetooth
- [I shouldn't have to say this, but] make sure you have a working Bluetooth adapter
If you are running inside a VM, the PC might but not the VM. Check for a controller usingbluetoothctl show
orbluetoothctl list
. Also a good indicator it the actual os reporting to not have bluetooth anymore. - disable SDP [only necessary when pairing]
change theExecStart
parameter in/lib/systemd/system/bluetooth.service
toExecStart=/usr/lib/bluetooth/bluetoothd -C -P sap,input,avrcp
.
This is to remove the additional reported features as the switch only looks for a controller.
This also breaks all other Bluetooth gadgets, as this also disabled the needed drivers. - disable input plugin [experimental alternative to above when not pairing]
When not pairing, you can get away with only disabling theinput
plugin, only breaking bluetooth-input devices on your PC. Do so by changingExecStart
toExecStart=/usr/lib/bluetooth/bluetoothd -C -P input
instead. - Restart bluetooth-deamon to apply the changes:
sudo systemctl daemon-reload sudo systemctl restart bluetooth.service
- see Issue #4 if despite that the switch doesn't connect or disconnects randomly.
- [I shouldn't have to say this, but] make sure you have a working Bluetooth adapter
There is a simple CLI (sudo python3 run_controller_cli.py
) provided with this app. Startup-options are:
usage: run_controller_cli.py [-h] [-l LOG] [-d DEVICE_ID]
[--spi_flash SPI_FLASH] [-r RECONNECT_BT_ADDR]
[--nfc NFC]
controller
positional arguments:
controller JOYCON_R, JOYCON_L or PRO_CONTROLLER
optional arguments:
-h, --help show this help message and exit
-l LOG, --log LOG BT-communication logfile output
-d DEVICE_ID, --device_id DEVICE_ID
not fully working yet, the BT-adapter to use
--spi_flash SPI_FLASH
controller SPI-memory dump to use
-r RECONNECT_BT_ADDR, --reconnect_bt_addr RECONNECT_BT_ADDR
The Switch console Bluetooth address (or "auto" for
automatic detection), for reconnecting as an already
paired controller.
--nfc NFC amiibo dump placed on the controller. Equivalent to
the nfc command.
To use the script:
- start it (this is a minimal example)
sudo python3 run_controller_cli.py PRO_CONTROLLER
-
The cli does sanity checks on startup, you might get promps telling you they failed. Check the command-line options and your setup in this case. (Note: not the logging messages). You can however still try to proceed, sometimes it works despite the warnings.
-
Afterwards a PRO_CONTROLLER instance waiting for the Switch to connect is created.
-
If you didn't pass the
-r
option, Open the "Change Grip/Order" menu of the Switch and wait for it to pair. -
If you already connected the emulated controller once, you can use the reconnect option of the script (
-r <Switch Bluetooth Mac address>
). Don't open the "Change Grip/Order" menu in this case, just make sure the switch is turned on. You can find out a paired mac address using thebluetoothctl paired-devices
system command or pass-r auto
as address for automatic detection. -
After connecting, a command line interface is opened.
Note: Press <enter> if you don't see a prompt.Call "help" to see a list of available commands.
See the run_controller_cli.py
for an example how to use the API. A minimal example:
from joycontrol.protocol import controller_protocol_factory
from joycontrol.server import create_hid_server
from joycontrol.controller import Controller
# the type of controller to create
controller = Controller.PRO_CONTROLLER # or JOYCON_L or JOYCON_R
# a callback to create the corresponding protocol once a connection is established
factory = controller_protocol_factory(controller)
# start the emulated controller
transport, protocol = await create_hid_server(factory)
# get a reference to the state beeing emulated.
controller_state = protocol.get_controller_state()
# wait for input to be accepted
await controller_state.connect()
# some sample input
controller_state.button_state.set_button('a', True)
# wait for it to be sent at least once
await controller_state.send()
- Some bluetooth adapters seem to cause disconnects for reasons unknown, try to use an usb adapter or a raspi instead.
- Incompatibility with Bluetooth "input" plugin requires it to be disabled (along with the others), see Issue #8
- The reconnect doesn't ever connect,
bluetoothctl
shows the connection constantly turning on and off. This means the switch tries initial pairing, you have to unpair the switch and try without the-r
option again. - ...
- Special thanks to https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering for reverse engineering of the joycon protocol
- Thanks to the growing number of contributers and users