Switch 2 controllers support
Answers checklist.
- [x] I have read and will follow the terms above.
- [x] I have read the documentation BlueRetro wiki and the issue is not addressed there.
- [x] I have updated my BlueRetro to latest version available.
- [x] I have searched the issue tracker for a similar issue and not found a similar issue.
BlueRetro firmware version
ALL
BlueRetro firmware specification
HW1
BlueRetro firmware variant
Universal
BlueRetro hardware type
External adapter dongle (1 port only)
Manufacturer
ALL
System used
Nintendo GameCube
Bluetooth controller brand & name
No response
What is the problem? (only list ONE problem per report)
This issue will track progress adding support for Switch 2 controllers including:
- SW2 Pro
- SW2 Joycon
- SW2 GameCube
What did you expect to happen?
_
Attach BlueRetro debug trace here
No response
@shiftybee I see no controller in the trace, was it set in pairing mode while you took it? I'm actualy waiting for mine right now, it out for delivery!
just got mine, can't seem to pair with switch 1 neither over bluetooth or cable. doesn't appear on bluetooth on PC and over usb seen as If_HID but no button inputs....
Have they gone away from "standards" for this controller and made it more proprietery? that would suck... I'm sure you will figure out how to get it working on blueretro but it would be be unusable on PC which would be my main use outside of with my actual Gamecube... ! I have laserbears v1 internal mod.
@shiftybee I see no controller in the trace, was it set in pairing mode while you took it? I'm actualy waiting for mine right now, it out for delivery!
I tried to, but I guess if you didn't see anything useful I guess not. Hopefully the other trace is helpful, or you're able to get yours working, I was just trying to give you a head start.
No luck pairing my SW2 GameCube Controller on HW2 so far :( Did you got it to pair @shiftybee ?
Quick update, I got my Switch 2 & GC controller.
So from the get go this doesn't look like it's using BT standard for pairing. I'm not even sure if it BT at all.
Regular SW1 Pro controller connect to it, so at least the console itself support BT. I did connect a fake SW Pro BT controller base on BR for debugging a bit. Connection process look like a regular SW with a SW1 device. The device name for SW2 over bluetooth appear to be same as SW1 = "Nintendo Switch"
I did name a BlueRetro to "Nintendo Switch" and also spooffed the SW2 BDADDR. Using my SW2 GC controller that was paired to that BDADDR didn't yield any connection to BlueRetro.
I think that's a good hint it's not standard in some way.
FCC data suggest it's using a BR/EDR/LE IC: https://apps.fcc.gov/oetcf/eas/reports/ViewExhibitReport.cfm?mode=Exhibits&RequestTimeout=500&calledFromFrame=N&application_id=mR8hRP0ewN278qkCQN4EYA%3D%3D&fcc_id=BKEBEE021
Damn you Nintendo. Is there still a chance of getting it to work? Otherwise I have two weeks to send it back ;)
No luck pairing my SW2 GameCube Controller on HW2 so far :( Did you got it to pair @shiftybee ?
No, I haven't been home since my first comment. Sounds like it's going to be a bit of a rocky road getting this thing to connect to anything other than the SW2 :(
OK took a better look at it.
Look like it's a BLE device
Here a trace of my laptop trying connecting to it (bonding fail):
Filter for beacon: bthci_evt.bd_addr == 3c:a9:ab:5f:cd:9e
Another trace this stime trying to scan service through chrome://bluetooth-internals
Another trace made with android while using LightBlue app
android_sw2_gc_lightblue_btsnoop_hci.log
There are a couple ways to proceed
- Easiest would be to sniff HCI packets off the SW2 console Mediatek radio PCIe bus, unfortunately PCIe sniffers are expensive. Controller is a single chip design, so HCI is not exposed.
- Create a mock BLE device based on GC controller exposed bits and trace on that side what a SW2 console accessing it does.
- Poke GC controller randomly to figure how it work
My plan is to do approach #2 this weekend, it's going to take some time.
Thank you for getting to this with such urgency! 🔥
really sucks that nintendo has goen about it this way. your hard work is much appreciated 🫡
Someone took a capture with wireshark of the USB pairing process with a Switch 2 and then some button inputs, if this is helpful https://docs.handheldlegend.com/s/link-zone
It looks like the USB device is missing firmware on an "out of the box" Switch 2 NSO GameCube Controller. When you compare my stock capture to the one linked above you see that it only enumerates the Vendor device and is missing the HID and UAC endpoints
So it likely needs to be plugged into a Switch 2 before it becomes usable
Can someone take a USB Full-Speed capture of plugging an NSO controller in for the first time so we can get see bitstream upload process?
It looks like the USB device is missing firmware on an "out of the box" Switch 2 NSO GameCube Controller. When you compare my stock capture to the one linked above you see that it only enumerates the Vendor device and is missing the HID and UAC endpoints
So it likely needs to be plugged into a Switch 2 before it becomes usable
https://trevor.jp/fresh-nso-controller.pcapng
aw MAN, i was hoping that wouldn't be the case... i guess i'll have to find someone nearby that has one
Once I'm done with the BT stuff I can try upgrade my openvizsla to cynthion FW and dump it.
I haven't plug any of the controllers to the SW2 via usb yet.
whatever can get this thing to work. i'm also keeping an eye on SDL's development so that it can get to working on steam and dolphin. hopefully this can aid in getting it to work there too
It looks like the USB device is missing firmware on an "out of the box" Switch 2 NSO GameCube Controller. When you compare my stock capture to the one linked above you see that it only enumerates the Vendor device and is missing the HID and UAC endpoints
So it likely needs to be plugged into a Switch 2 before it becomes usable
Ugh, that's really unfortunate. Does it look like it behaves like a standard controller after that point (i.e. like one that could be used with a PC or other device)?
~I don't have a Switch 2 on hand but from the capture @jakelandau linked, it looks like the answer is yes~
EDIT: I was wrong, @djedditt has informed me that it is just an init sequence that needs to be sent to the config endpoint https://handheldlegend.github.io/procon2tool/
Quick update
Here a branch with alpha level of support for anyone curious: https://github.com/darthcloud/BlueRetro/commit/718543470e394f42b22714bfba8b7ba973551e10
Here the buttons bitfield definition (uint32_t little_endian) https://github.com/darthcloud/BlueRetro/blob/718543470e394f42b22714bfba8b7ba973551e10/main/adapter/wireless/sw2.c#L20-L46
The report is 63 bytes https://github.com/darthcloud/BlueRetro/blob/718543470e394f42b22714bfba8b7ba973551e10/main/adapter/wireless/sw2.c#L79-L87
To get the reports you need to enable the notification for the report at handle 0x000A
uint16_t data = BT_GATT_CCC_NOTIFY;
bt_att_cmd_write_req(device->acl_handle, 0x000b, (uint8_t *)&data, sizeof(data));
Here some btsnoop trace:
blueretro_sw2_pro2.log blueretro_sw2_gamecube.log
TODO:
- Fix reconnection
- Figure how to tell between the 4 controllers type
- Figure how rumble work
- Figure how LEDs works
- Figure how to get axis calibration data
This is the button bitfield for Switch Pro Controller 2 and NSO GC controller, I think the data from the Switch 1 no longer applies, different orders it seems? This is over USB, might be different compared to Bluetooth.
| Byte | Bitmask | Button |
|---|---|---|
| 3 | 0x01 | B |
| 3 | 0x02 | A |
| 3 | 0x04 | Y |
| 3 | 0x08 | X |
| 3 | 0x10 | R |
| 3 | 0x20 | ZR |
| 3 | 0x40 | Plus |
| 3 | 0x80 | Stick R Button |
| 4 | 0x01 | Dpad Down |
| 4 | 0x02 | Dpad Right |
| 4 | 0x04 | Dpad Left |
| 4 | 0x08 | Dpad Up |
| 4 | 0x10 | L |
| 4 | 0x20 | ZL |
| 4 | 0x40 | Minus |
| 4 | 0x80 | Stick L Button |
| 5 | 0x01 | Home |
| 5 | 0x02 | Capture |
| 5 | 0x04 | GR |
| 5 | 0x08 | GL |
| 5 | 0x10 | Chat |
Another update
Identifying controller type
Figured how to tell the controllers type apart, the BLE beacon include the VIP & PID in the manufacturer specific data at offset 6 & 8 https://github.com/darthcloud/BlueRetro/blob/600159aebe55befbf6f03d712d9d29f34675c08d/main/bluetooth/hci.c#L1143-L1151
057e:2073 GameCube
057e:2069 Pro 2
057e:2067 Right Joycon 2
057e:2066 Left Joycon 2
Input reports
Also found another report format on handle 0x000E still 63 bytes VS the one i'm using at 0x000A the buttons bitfield is 3 bytes rather than 4 The GC triggers are located right after the joysticks data rather than completely at the end.
Finding CMD interface
Here my result at poking the BLE ATT server The cmd interface is probably on one of the write without responce handle.
| Handle | UUID | UUID Name | Characteristic Properties | Notes |
|---|---|---|---|---|
| 0x0001 | 00c5af5d-1964-4e30-8f51-1956f96bd280 | Unknown | ||
| 0x0002 | 2803 | Characteristic | Read | |
| 0x0003 | 00c5af5d-1964-4e30-8f51-1956f96bd281 | Unknown | ||
| 0x0004 | 2803 | Characteristic | Write | size: 2 |
| 0x0005 | 00c5af5d-1964-4e30-8f51-1956f96bd282 | Unknown | ||
| 0x0006 | 2803 | Characteristic | Read | |
| 0x0007 | 00c5af5d-1964-4e30-8f51-1956f96bd283 | Unknown | ||
| 0x0008 | ab7de9be-89fe-49ad-828f-118f09df7fd0 | Unknown | ||
| 0x0009 | 2803 | Characteristic | Notify, Read | |
| 0x000a | ab7de9be-89fe-49ad-828f-118f09df7fd2 | Unknown | HID input report (64 bytes) Format 1 | |
| 0x000b | 2902 | Client Characteristic Configuration | ||
| 0x000c | 679d5510-5a24-4dee-9557-95df80486ecb | Unknown | Read: 00 00 | |
| 0x000d | 2803 | Characteristic | Notify, Read | |
| 0x000e | 8261cba1-9435-420c-84d6-f0c75a2c8e4d | Unknown | HID input report (64 bytes) Format 2 (inputs more compact) | |
| 0x000f | 2902 | Client Characteristic Configuration | ||
| 0x0010 | 679d5510-5a24-4dee-9557-95df80486ecb | Unknown | Read: 00 00 | |
| 0x0011 | 2803 | Characteristic | Write w/o Rsp | |
| 0x0012 | 3f8fb670-ab25-45bf-b540-38c72834d064 | Unknown | ||
| 0x0013 | 2803 | Characteristic | Write w/o Rsp | |
| 0x0014 | 649d4ac9-8eb7-4e6c-af44-1ea54fe5f005 | Unknown | ||
| 0x0015 | 2803 | Characteristic | Write w/o Rsp | |
| 0x0016 | af95885e-44b3-4a24-9cf0-483cc129469a | Unknown | ||
| 0x0017 | 2803 | Characteristic | Write w/o Rsp | |
| 0x0018 | 4147423d-fdae-4df7-a4f7-d23e5df59f8d | Unknown | ||
| 0x0019 | 2803 | Characteristic | Notify | |
| 0x001a | c765a961-d9d8-4d36-a20a-5315b111836a | Unknown | ||
| 0x001b | 2902 | Client Characteristic Configuration | ||
| 0x001c | b746df8c-f358-495b-9cd2-e3bbeda4f979 | Unknown | Read: 00 00 | |
| 0x001d | 2803 | Characteristic | Notify | |
| 0x001e | 46f6ad29-cdaf-4569-a2fe-339020b94604 | Unknown | ||
| 0x001f | 2902 | Client Characteristic Configuration | ||
| 0x0020 | b746df8c-f358-495b-9cd2-e3bbeda4f979 | Unknown | Read: 00 00 | |
| 0x0021 | 2803 | Characteristic | Notify | |
| 0x0022 | d3bd69d2-841c-4241-ab15-f86f406d2a80 | Unknown | ||
| 0x0023 | 2902 | Client Characteristic Configuration | ||
| 0x0024 | b746df8c-f358-495b-9cd2-e3bbeda4f979 | Unknown | Read: 00 00 | |
| 0x0025 | 2803 | Characteristic | Notify, Read | |
| 0x0026 | ab7de9be-89fe-49ad-828f-118f09df7fde | Unknown | ||
| 0x0028 | 679d5510-5a24-4dee-9557-95df80486ecb | Unknown | Read: 00 00 | |
| 0x0029 | 2803 | Characteristic | Write w/o Rsp | |
| 0x002a | ab7de9be-89fe-49ad-828f-118f09df7fdf | Unknown | ||
| 0x002b | 1800 | Generic Access | ||
| 0x002c | 2803 | Characteristic | Read | |
| 0x002d | 2a00 | Device Name | Read: 44 65 76 69 63 65 4E 61 6D 65 | |
| 0x002e | 2803 | Characteristic | Read | Read: 44 65 76 69 63 65 4E 61 6D 65 |
| 0x002f | 2a01 | Appearance | Read: 82 0A | |
| 0x0030 | 1801 | Generic Attribute | Read: 82 0A |
Reconnection
Could not figure how to reconnect the controller yet.
The controller look to only want to pair and not bond, which is fine and work in pairing mode. but when they reconnect they will disconnect after trying to pair again.
Also if never connected to a SW2 the controller are in shipping mode, so they wont reconnect at all. Connecting them once to SW2 clear that flag like on SW1.
Mock controller FW
I didn't have much sucess trying to make a BLE FW that broadcast the same beacon as a SW2 controller.
The SW2 console does connect to it, but it sit there in silence and send no cmd packet whatsoever.
Base on on what I see when using the SW2 controller on BlueRetro they do not initial any cmd on their own.
So not sure why console remain silent with my mock controller.
Here some proper build
Only pairing work, reconnect dont work. LED will stay in moving pattern on controller No rumble
TODO
- Fix reconnection
- Figure how rumble work
- Figure how LEDs works
- Figure how to get axis calibration data
- Figure how to clear shipping mode
To set the player leds you need to send the following payload -> 09 91 00 07 00 08 00 00 [01] 00 00 00 00 00 00 00 LedPattern: 0x01 Command: 0x07 (Player lights set pattern) ReportType: 0x09 (Player lights) ReportMode: 0x91 (Request)
Changing the 0x01 to something like 0x03 will turn first and second led on the controller.
Yes thats the payload on USB but that doesn't say which BLE attribute it's at nor the extra framing around it.
if never connected to a SW2 the controller are in shipping mode, so they wont reconnect at all. Connecting them once to SW2 clear that flag like on SW1.
Can you elaborate on this? The controller doesn't work at all until connected to a Switch 2? Can this be replicated in some way with a PC utility?
No its only the part, when pressing any buttons trigger a reconnection. Using the sync button to pair work fine. Most SW1 implementation do send the cmd to disable shipping mode. Its a BT specific feature.