April 8, 2014 // 7:21 pm
- Below is a demonstration video of unofficial PS4 Keyboard and Mouse support for PlayStation 4 games courtesy of electrical engineer and DIY hobbyist Frank Zhao
) via Eleccelerator (linked above).
To quote: Keyboard and Mouse for PlayStation 4 Games (second prototype)
Why did you do this?
I like playing shooter games on PC but my laptop is too weak to play them. Game consoles do not support USB keyboards and USB mouse, they only support gamepads. Gamepad controls are not suitable for shooter games, using a keyboard and mouse is much more comfortable for gameplay.
How does it work?
I designed a circuit that features a microcontroller and USB hub. The keyboard and mouse plugs into the USB hub, and then the microcontroller takes the data from the keyboard and mouse, translates them to the data format used by the PlayStation 4. It does the translation in a way as though the mouse was the right thumbstick, and the keys are mapped to buttons (the WASD keys are mapped to the left thumbstick).
I wanted to share this story because I am very happy that I finally managed to get this far! Anybody who is attempting this and thought it was impossible to do can now breath a sigh of relief because it definitely can be done.
I have already accomplished a similar project that worked with a PS3 (UsbXlater), something that connected to the PS3 via USB that translated keyboard and mouse data format to gamepad data format.
Once the PS4 launched, I reversed engineered the USB protocol used by the DualShock, and then attempted the same technique. But... it didn’t work, after trying a few tricks, it still didn’t work.
I started talking with people who are working on similar projects, such as Matlo from GIMX.fr and the creators of XIM. None of us could get PS4 to respond to data coming from USB. What we did was use my circuit as a “proxy”, transparently passing the USB data such that the USB traffic replicated traffic between the PlayStation and DualShock exactly, except with only minor modifications to the bytes that represent the button presses. It did not work, it seemed like only wireless traffic was used by the PlayStation, not USB traffic.
In my reverse engineering, I discovered (by poking around the circuit using an oscilloscope) that the DualShock’s circuit exposes two signals that are actually the UART signals between a Bluetooth module and the DualShock’s microcontroller. I soldered some wires to these signal and determined that it is using H4 HCI over UART at 3 Mbit/s. I connected these signals to my logic analyzer to capture the UART traffic, logged it, and wrote a script to reformat the log into pcap format (wiki.wireshark.org/Development/LibpcapFileFormat) so the traffic can be analyzed using WireShark (which actually have specific analysis for H4 HCI).
Through this, I learned about how the Bluetooth pairing procedure works. The Bluetooth link key (pretend it’s a 16 byte long pairing code) is the next challenge. But it turns out, the link key is actually exchanged during USB enumeration. I noticed this because I noticed a chunk of bytes that looked random in the USB enumeration traffic, which gave me a hunch to check if it was the same bytes as the link key. So to obtain a link key, my circuit is connected to the PS4 via USB first. That’s how the Bluetooth pairing security problem was solved.
At this point, I wrote a bit of firmware code that allowed me to store things in flash memory. I also implemented wear leveling. The Bluetooth link keys and addresses can now be stored in flash memory, so the user only needs to obtain them once, not every time.
I also noticed 4 bytes of random-looking data appended to every packet, after a few checks, it turns out that these are just a 32 bit CRC that is not a part of official Bluetooth specifications, so Sony must have added them just to be safe. If this was a cryptographic hash or if the CRC used a different seed or used a different polynomial, then spoofing the packets would be much more difficult (impossible to somebody without cryptography skills).
At this point, I had to make a modification to my own circuit so that it included a Bluetooth module. I had several choices but eventually settled on using a common USB Bluetooth dongle (Advantages: fast, certified, cheap. Disadvantage: occupies a USB port).
Then I tried to program my own Bluetooth stack firmware (I had to literally learn the entire Bluetooth spec). I almost finished writing one but I was not happy with how complicated it needed to become in order to handle all possible situations. I decided to utilize an open source Bluetooth stack instead, named BTstack (code.google.com/p/btstack/). I had to reimplement my USB transport layer for it and make some tweaks to it, but it does the job well enough right now.
While I was doing this, Matlo is way ahead of me and he already tried to send data to the PS4 via Bluetooth. However the PS4 is ignoring his data and we are both wondering why. Matlo noticed that some very infrequent traffic that we did not understand. This turns out to be the challenges and responses of the authentication procedure.
We did not know how to generate the responses (the challenges are 256 bytes of random data, we did not have the cryptography expertise to even start attempting to defeat it). Matlo created a tool called l2cap_proxy (github.com/matlo/l2cap_proxy) that replayed all traffic between two devices exactly. It worked, which is how we discovered the vulnerability that my circuit exploits. (Sony engineers forgot to include a digital signature, if the encryption depended on the Bluetooth address in some way, then the proxy attack would not have worked.)
This means that a real DualShock is required to be connected over Bluetooth at all times, because the PlayStation never actually stops requesting authentication. This is a bit inconvenient. The traffic over Bluetooth is so high that Matlo noticed that his computer will sometimes miss packets. This is a problem if Matlo wants his code working on a small platform such as the Raspberry Pi.
The Bluetooth L2CAP traffic still uses the HID PSM so all of the traffic look similar to USB traffic, and the report IDs being used are the same. So I conducted an experiment (using PyUSB - sourceforge.net/projects/pyusb/) to feed the challenges to the DualShock by USB instead of Bluetooth, then attempt to read the response by USB. It didn’t work, the responses came back all zeros, so that didn’t work, which was disappointing.
The traffic is so high that my own circuit can’t keep up either, I had to prioritize my FIFOs so the important authentication packets are guaranteed to be delivered, the other stuff have 80% chance of being re-routed correctly. When the low priority FIFO gets filled to capacity, packets are lost.
So The final stretch was to code my firmware to work like Matlo’s proxy, except the packets that needed to be modified with new button bytes thumbstick bytes. Since some packets are modified, the CRC need to be recalculated, which is done easily because the STM32 microcontroller I am using has a CRC engine already (which is faster than software implemented CRC).
At one point in this story, the UsbXlater circuit had to be redesigned to include the USB hub. The original USB stack (provided by ST) had to be re-written to provide support for hubs. This took a huge chunk of time as well.
The project is open source, see the UsbXlater github repo (github.com/frank26080115/UsbXlater) for now, it’s not perfect though, there’s still a lot to be done.
I need to redesign the circuit, it needs a 4 port hub instead of 3, and I need to swap the two USB interfaces (the HS interface has 12 host channels and the FS interface has only 8, I need to use the HS interface for the hub). I also need to make a keybinding configuration utility so the control mapping can be adapted to other games.
FAQ for the non-technical people:
This doesn’t sound impressive at all, there are a lot of products out there already that does this for the Xbox 360, Xbox One, and PlayStation 3. What makes this project so special?
The first thing I did was make it work with the PlayStation 3 by spoofing a DualShock 3 connected using the USB connection. This was easy. But the same technique could not be used for the PlayStation 4. The PlayStation 4 seems to ignore data through the USB channel. To overcome this, a USB Bluetooth dongle is connected to my circuit’s USB hub. My firmware spoofs a DualShock 4 over Bluetooth instead of USB.
It sounds too easy still, doesn’t it? Sony implemented a challenge-response authentication procedure. The PlayStation will send an encrypted question to a DualShock, and only a real DualShock will be able to generate the correct answer to the question. If another device attempts to provide a wrong answer, the PlayStation will ignore that device.
To overcome this, a DualShock is connected to my circuit, and the questions from the PlayStation are re-routed to the DualShock so that the DualShock tells my circuit the “answer”, and my circuit then re-routes the answer to the PlayStation, thus defeating the authentication.
This is actually an vulnerability, a mistake made by Sony. They forgot to include a digital signature, if the encryption depended on the Bluetooth address in some way, then the proxy attack would not have worked.
I’ve seen some guy solder a DAC/digital-potentiometer inside a DualShock to accomplish this, it sounds much simpler than your method, how is your circuit different?
My circuit is all digital, no analog noise, no input latency from analog-digital conversion, no need to disassemble the DualShock.
How did you trick the DualShock and PlayStation to connect to your circuit instead of each other?
The Bluetooth device address (basically the MAC address) is given to the DualShock first via USB. You connect the DualShock to my circuit to do this step. The link key is also given to the DualShock this way (a link key is similar to a pairing code, but not exactly).
The Bluetooth device address and link key of the PlayStation is also obtained by connecting my circuit to the PlayStation by a USB cable. My circuit goes into USB device mode that pretends to be a DualShock to accomplish this.
All of this information is stored in flash memory so it only needs to be done once.
What about the touch pad and motion sensors?
Since the traffic is being “proxied”, the DualShock still works as the input device, the keyboard and mouse input is mixed in. This means the touch pad data and motion data are not modified, so the DualShock still works. Because of my proxy technique, the LED colours and vibration data are not modified so they still work in games.
But nothing is stopping me from modifying the touch pad and motion data. I just didn’t have time.
What about audio?
The DualShock uses HID for audio, which is weird. I expected A2DP to be used for audio but apparently the audio data is mixed in with the HID data. I don’t know why. As I have mentioned before, there are packets being lost, which means audio data will be lost. Hence, audio does not work with my circuit, sorry. It’s simply too much data to process on a microcontroller (and Matlo had trouble with the data rate even on a full PC).
How did I remove acceleration from the thumbstick controls?
I took a video of BF4′s minimap spinning at different speeds, plot that speed vs stick curve, flip the curve to generate a look-up-table.
How about the Hori Pad? It works over USB, how come your circuit can’t?
I have no idea how they do it, but since the Hori Pad is an official Sony licensed product, Sony can make some sort of exception for it in the PS4′s operating system. I purchased a Hori Pad and I will reverse engineer it once I get it.
Have you attempted to look inside the DualShock’s firmware?
No, I have not. I did see two test points on the DualShock’s PCB that may have been the SWDIO and SWCLK pins for a SWD interface, but if Sony locked the firmware and I attempted to read it, it would cause the microcontroller to wipe itself (self destruct the firmware). It would brick the DualShock and make me waste $60.
What tools did you use to analyze the USB traffic and Bluetooth traffic?
For the USB traffic, I used a Total Phase Beagle USB 12 (eleccelerator.com/review-total-phase-beagle-usb-12-analyzer/). For Bluetooth, I tried to use an Ubertooth One (ubertooth.sourceforge.net/), but was unsuccessful because it could not perform the neccessary frequency hopping correctly for some reason. However, after the discovery of the H4 HCI UART signals, I didn’t need the Ubertooth because HCI traffic contains all the information I needed (in an unencrypted form too, which is a bonus).
Why does the circuit board look so weird?
It was designed to go into a specific project box (one that is off the shelf).
Where’s the love for Xbox?
I don’t have one... It can totally be done, but Xbox uses WiFi Direct, not Bluetooth.
Finally, below are some related PlayStation 4 Keyboard and Mouse support videos as well:
To quote (via softfactory.com.br/index.php/blog/entry/carbon-project-hardware-stuff):
Unlike PS3, the PS4 doesn't support controller connection through USB interface, this interface is used only for controller pairing. So, for while the only solution is using the DualShock 4.
This kind of solution is quick and dirty because we are simulating the pressure of buttons and sticks movements. As I said in YouTube, this is a DIY project so here you will have all informations needed to built your 'carbon' device. So be patient because there's a lot of informations to be organized, built and etc.