Branch: master->amiibo_edits->web
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 bluezPython: (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 -H pip3 install aioconsole hid crc8 aiohttpIf 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 showorbluetoothctl list. Also a good indicator it the actual os reporting to not have bluetooth anymore. - disable SDP [only necessary when pairing]
change theExecStartparameter in/lib/systemd/system/bluetooth.servicetoExecStart=/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 theinputplugin, only breaking bluetooth-input devices on your PC. Do so by changingExecStarttoExecStart=/usr/lib/bluetooth/bluetoothd -C -P inputinstead. - Restart bluetooth-deamon to apply the changes:
sudo systemctl daemon-reload sudo systemctl restart bluetooth.service
- see Issue #4 if despite that the switch disconnects randomly.
- [I shouldn't have to say this, but] make sure you have a working Bluetooth adapter
There is a simple CLI (suco 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
-roption, 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-devicessystem command or pass-r autoas 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,
bluetoothctlshows the connection constantly turning on and off. This means the switch tries initial pairing, you have to unpair the switch and try without the-roption 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