-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HID Protocol for Bluetooth / USB #7
Comments
I'm also working to reverse engineer the joycons, I found this documentation. I think that Nintendo might use something similar to the joycons. [http://wiibrew.org/wiki/Wiimote](Wiimote HID) |
thanks, I did figure out the accelerometer and gyroscope data in the joycon status packet today, but only in the physical connection bewteen the joycon and console. I haven't began working on the bluetooth level yet, but I'll keep it in mind when I do. |
just to make you guys aware, there is a program similar to glovepie called freepie, the possibility of developing a module for the joycons may be faster/easier than an entire new driver. thanks and gj with all of this. heres the link btw |
@alejandrorangel Cool, thanks for that. I might try and throw some of the Wiimote packets at it this weekend and see if it reacts to any of them. |
Over USB the pro controller just does a handshake, then switches to bluetooth. |
@aspalmer That actually makes sense from the HID reports I was getting back, actually. Was able to get the HID info from the USB device, although no data was being sent. However when I paired the USB and Bluetooth together using some test code, I noticed one thing. Also, via USB the HID device is reported as a "stick" or "joystick", versus the Bluetooth HID which reports as "gamepad". Can actually see this from the descriptor you sent over actually. |
I'd love to see an iOS API for the JoyCon via Bluetooth. UPDATE: iOS uses its own Bluetooth controller specification which means it does not work natively with the Joy-Con or Switch Pro controllers. |
I have some notes on the Bluetooth hid buttons. The left stick & right stick buttons are adjacent button numbers. So are + - and home, capture. It sends the stick data as hat input, though. (0-8, 8 is neutral, 0 is up) Annoying. |
@riking What are you using to capture the Bluetooth traffic? |
@mfosse Oh, I just straight up connected the joycon to my Linux laptop and read the input data with Was about to try sending some of the 0x19 packets as OUPTUT or FEATURE reports and see what happens. So when I
Perhaps Byte 0 is the checksum? I should try calculating it. Byte 1 is always 0x8E. Byte 2, 3, 4 is the button status.
Next 3 bytes are only set by the left joycon. Next 3 bytes are only set by the right joycon. |
Yup, I found the stick data.
Haven't figured out the last bit of data. It only seems to send a couple of bit patterns: (L) (R) Definitely not the gyro data. |
Oooookay, looks like I'm going to need to pair the controllers before I move further - they started connecting to someone else's console, which is erroring out my Bluetooth stack. Here's what I have so far: |
Can confirm the joy-cons and pro controller do operate using the standard HID protocol, all except the gyro and accelerometer. |
I've got a working "combine both joycons into a single controller device" program here: https://github.com/riking/joycon |
I'm working on a vJoy feeder for the JoyCons here: https://github.com/mfosse/JoyCon-Driver |
The Charging Joy-Con grip seems to have two interfaces with an in/out endpoint per interface for each Joy-Con. I haven't managed to get any replies from input I've sent, however the Joy-Con grip, once an HID session is started, seems to send packets matching the first MAC address handshake command for UART every time the Joy-Con are inserted and ejected. The format seems to go as follows:
This can also be observed from Wireshark: The charging grip also has the same STM32 chip as the pro controller, and the same 5-pin layout found on the dock. Maybe the firmware can be dumped same as the dock to learn more about UART and Bluetooth commands @dekuNukem? |
Checked out the USB capture from @aspalmer and sending 0x80 0x01 gives me that MAC packet. It seems to respond to some of the other output reports in the capture similarly, so it seems that two Joy-Con in a charging grip effectively functions as a Pro Controller with two interfaces. |
Guys, please see #11; I don't think the HD rumble data is HID compliant. |
Has anyone managed to read any gyroscope or accelerometer data over bluetooth? I haven't had any luck so far. |
@riking I figured out what stick_unknown is
I don't have any idea what the other nibbles are, they seem random to me, but I haven't looked at them too closely. |
It seems there is indeed a set of HID commands which allow sending UART commands, Commands which seem to exist at 0x0800BB00 are:
EDIT: turns out the 'lookup table' stuff for 80 91 is actually for incoming UART data size, just managed to send a raw pre-handshake UART packet like such:
And the resulting data I got back was the MAC packet in a slightly different form:
EDIT 2: Seems 80 92 actually works to a degree to send post-handshake commands (with pre-handshake headers?), this works to get something resembling an input packet, but none of the actual input shows up.
EDIT 3: For the record... Since the firmware tells me this, these are the return sizes for any 19 01 03 07 00 91 XX ... UART command:
|
I left my controllers on the grip for a few days and now the status packet[1] is 0x6E on the R, but it's still 0x8E on the L. Battery level? EDIT: Docked the controller for a bit and it's back to 0x8E. Definitely a single nibble of battery Also, noticed something weird. The kernel is always returning 0 for the number of actual bytes written 🤔 This may be why I had no response to writes other than 0x1 🤔 |
Here's what the Linux Kernel gives for the report descriptor over bluetooth: https://www.irccloud.com/pastebin/P60ntzyH/ @shinyquagsire23 can you dump |
@riking That file doesn't seem to exist for me, but the charging grip also doesn't function as a controller by default. Also, I've managed to get a full initialization of the Joy-Con via the charging grip. The charging grip is able to send any UART command, so I am able to pull for full input at around 16ms per input, in addition to being able to dump my Joy-Con SPI firmware over HID. My HID program can be found at my repo, https://github.com/shinyquagsire23/HID-Joy-Con-Whispering Hopefully with that, it should be possible to test Joy-Con functionality more in-depth. I did try to have the same HID commands sent over Bluetooth but it seems it's not the same protocol, unfortunately... |
Sorry, the underscores weren't meant to be literal - replace them with the kernel-assigned device identifier.
Dang :( |
@riking Ah, I did replace the underscores but I guess I forgot to escape something and it failed, https://gist.github.com/shinyquagsire23/89ea38220e221950a233cd23f2fde28f |
Okay, wow. Much more straightforward than the Bluetooth dump. Looks like a charging grip is almost all you need to use the joycons as a controller, I'll have to get one and add button mapping support in to my program. Still doesn't help with the Bluetooth protocol except to reinforce that yes, 0x80 is definitely a bridge to the wires and it's definitely not available over Bluetooth. |
Bit of a long shot, but input 33 and 129 look like pitch/yaw inputs of a gyro |
33 is the status report (0x21) sent in reply to a 0x1 HID output report and parsed here https://github.com/riking/joycon/blob/master/src/joycon_input.c#L53 |
@Brikwerk I'm working on a similar project and just managed to emulate and pair a JoyCon with the Switch over Bluetooth using a Raspberry Pi 4B and the information provided here. The controller shows up in the "Change Grip/Order" menu. Code: https://github.com/mart1nro/joycontrol |
@mart1nro Wow, your project looks amazing. Thank you for posting! I'll definitely be taking a closer look and figuring out where I went wrong when I find some time here. I think I might need to strip out my usage of BlueZ's compatibility mode and PyBlueZ for things to start working. Your usage of the socket library is probably what I need to implement too. |
@mart1nro Very cool, may I ask what you use to reverse engineer bluetooth? Is all you need are the controller's descriptors, or is there more to it? I'd really appreciate any info you can give me, I need it for a current project. |
Hi guys If you have a GameCube controller you can mod it to control your switch A couple problems I have
Let me know if have any success with this. Hope it helps |
Hi, does anyone have some more information what exactly byte 12 (Vibrator input report) in the standard input report format does? |
|
@Ced2911 thank you for that ,i will try it on atmega32u4(teensy2.0) |
Hi all, Just wanted to update everyone on a project I've been developing that has finally hit a release milestone today: NXBT provides a Python package for controlling your Switch over a browser, through a terminal session, or with a macro. A couple things I'd like to note:
There are a couple of aspects I'm still trying to iron out with this utility, so feedback would be most appreciated! |
I'm trying to figure out how one might use a Raspberry Pi Pico with CircuitPython or MicroPython to spoof a Pro Controller via USB. I'm able to create a perfectly-good PC controller using CircuitPython, but when I plug it into the Switch, the Switch doesn't see it. Does anyone know a way in Python to tell it over USB that this is a Pro controller? |
@geekinchief you need to add a custom HID device to your CircuitPython build according to this discussion. It looks fairly non-trivial. |
Hey everyone, I wanted share some of my findings regarding Bluetooth communication with the Switch after the v12.0.0 update. Unfortunately, the new update has introduced changes to how controllers initially connect to the Switch and communicate. These changes are entirely from the Switch's side of things as there hasn't been a firmware update for controllers. To summarize:
I've written about the changes in more detail on this issue and proposed/implemented some fixes for controller emulation on Linux, if anyone's interested. |
I'm trying to start working based on @NathanReeves 's code. Are there any news regarding reconnecting a controller without using the "Change Grip/Order" menu? |
The first time you pair from the grip screen or via USB handover you have to store the link key and mac address of the console somehow. Then you may use that to connect later, whenever you want. IIRC the console has to be turned on already to use this method |
I'm just starting on this and I don't have much experience with boards (such as esp32) or bluetooth communication. Looking at joycontroller, I think there should be a way of starting a connection from the board but I'm digging through the libs and can't find a way of doing so. Edit: Should I try to do this one thing using current code with bluedroid implementation or should I attempt starting from scratch with NimBLE? |
One question, when a paired controller turns on and starts looking for the Switch, who iniciates the connection? The Switch or the controller? Is there documentation about this specific interaction somewhere? |
IIRC from years ago, when you do your initial pairing the console is scanning for joycons, by name, but then later a paired joycon can connect to the console, by address, such as when a paired joycon powers up the console. |
@mart1nro Have you ever found out what this value is for? I've been trying so fix this longstanding issue on the Linux kernel driver for the Pro Controller where it disconnects randomly when rumble is in use and that value might be the solution. |
I dont have any hardware to test anything right now. but I have used this git as a manual for a project before and my best guess from reading it now is that it might be a counter that reflects the current vibrator data that is "playing" on the controller. The vibrator data take a certain amount of time to "play" on the motors and the data does not need to be sent all the time... It is possible the in the absence of any other updates (no buttons being pressed) this vibration counter field keeps updating and therefore sending input reports as needed to inform the console of when a new vibrator report can be sent to keep the vibration reports flowing. But that's just totally a guess. IIRC the controller might disconnect/crash if you send any kind of bad packet to it on the control channel, I would check the contents of the last packet when this disconnect with linux happens, is it a valid packet? |
@timmeh87 I have been testing to see what values I get from that vibrator input report byte, but the values I get are different from the examples on that document. I get values between 0x08 and 0x0C, and I can't really find a pattern about what they mean. I was hopeful that these values tell us when we can send the next rumble command.
That's a good idea, even though @DanielOgorchock probably already gave that a check. |
Hello, I'm trying to work on a project that involves sniffing Bluetooth packets sent between the Joycon and the Switch Console using an FPGA. The Joycon contains a BCM20734 Bluetooth 4.1 transceiver, which supports Bluetooth Basic Rate (BR), Enhanced Data Rate (EDR), Low Energy (LE), but not High Speed (HS). However, the Joycon specifications listed on the Nintendo website state that the Joycon uses Bluetooth 3.0, and some users have commented that the Joycon uses Bluetooth 3.0 High Speed. I want to know which of the four Bluetooth versions that the Nintendo Joycon uses so that I can try to implement a Bluetooth sniffer on an FPGA. Does anybody have any idea on whether the Nintendo Joycon uses BR, EDR, HS, or LE? |
The way I "sniffed" the bluetooth was to just use a regular bluetooth chipset, the cc2564, with a man-in-the-middle attack. The chipset just figured out the correct bluetooth to use. 🤷. It was pretty simple. just cut and paste the descriptors into a new device on the 2564, connect to the joycon first and then use the console to connect to the "fake" joycon. pass though all reports and inspect them. Not sure what you were planning to do with a whole FPGA? |
Since you used the cc2564, I'm assuming the Nintendo Joycon uses Bluetooth 3.0 BR/EDR, not High Speed. I'm just using an FPGA for my project because I'm planning to make a project a thing that I can put on a resume, and I am an aspiring FPGA engineer. Do you think a passive sniffing of the Nintendo Switch console and Joycon would be possible? |
@jk2997 the Bluetooth pairing key is located in the SPI flash, so technically you could passively sniff it that way (and obtain the key via UART or USB and a Joy-Con grip) |
@shinyquagsire23 Would it be possible to passively sniff transmissions between the Nintendo Joycon and Switch console wirelessly (solely by monitoring Bluetooth traffic over-the-air)? |
So basically, figure out the Bluetooth address and clock of the console (which probably acts as the master of the piconet), adjust the receiving frequency of a transceiver like the nRF24L01, dewhiten the incoming signal, get the Long Term Key from the traffic intercepted between the console and the Joycon during the Bluetooth inquiry and paging process, and then use the transceiver and an AES-CCM decryptor to read the Bluetooth interactions? The address and clock of the master device could be used to deduce the frequency hopping scheme and Bluetooth whitening procedure. |
Hi,
Loving the work you've done - thanks ever so much. Couldn't find you on social media, so am just gonna drop a message here.
Have you been able to sniff the USB or Bluetooth HID protocol it's using? Been trying to bodge a driver together, and don't really have the tools to analyse the protocol. Whilst the buttons and joysticks work fine, I believe the console sends a feature report to the joy-cons to activate gyroscope input. So far I've not had much luck getting the gyroscope and accelerometers to send anything over the standard protocol.
Could be me, or it could be Nintendo's very kind way of introducing security through obscurity.
Some help on the matter would be great if you are free.
Thanks
The text was updated successfully, but these errors were encountered: