Category Archives: Electronics

[MSF] FightStick (TeensyLC XINPUT Controller) – 4


Wiring up the TeensyLC

teensylc - my pinout

Above is a crude drawing of the pin-out used for this fight stick. The board is based on active low inputs, so we switch them to ground. I used all three grounds available as thru-hole. I had to create a splice for ground on start and select. Using the three grounds allowed me to separate the wires into neat sleeves that ran to each row of buttons and the joystick. Next I will show you the layout of the buttons on the stick:

Button Layout

Finally I will go ahead and finish this up with various shots of the stick and how it was wired up. We decided that creating the harnesses individually first would be easiest. So a harness was created for both rows, start select, and the joystick. Then they were cut at the correct length and soldered to the teensy board. The wires were kept clean by sleeving each harness with 1/4” PET Sleeving and using 3/8” Heat Shrink on the ends. For the wire we just used 22AWG stranded with 0.110”x0.020” Female Disconnects. Also remember to test the joystick with a voltmeter. The switches can be misleading and you need to remember that because of the pivot point a direction actually activates the micro switch on the opposite side.


Table of Contents

[MSF] FightStick (TeensyLC XINPUT Controller) – 3

Message Analyzer

The XBOX 360 Controller

With the need for drivers, there was no way to roll my own solution. Asking everyone to put their 64-bit version of windows into test mode just to use this controller seemed a little insane. My only real option at this point was to imitate something that existed. It most likely would have been easier to reproduce a more simple PC only controller (ie the F310). The PC only controllers have a lot less interfaces and endpoints, but I already had 360 controllers and did not feel like buying anything new.

My favorite resource for how the controller operates is the Free60 gamepad wiki page. The 360 controller is a HID controller with the HID report descriptor removed and the device class, subclass, and protocol set to 0xFF (255). This ensures that the HID driver does not attach to the device so the Microsoft driver can pick it up. The vendor ID is 0x45e (Microsoft) and the product ID is 0x028e. Once you set the device to the same VID and PID the driver will attach to the driver and attempt to enumerate it.

There are only two descriptors you need to worry about for the controller. This is because there is no HID report descriptor. There is the device descriptor, which tells the host things such as USB version, device class, device subclass, device protocol, max packet size for endpoint 0, VID, PID, etc. The other descriptor is the configuration descriptor, which tells the host about the device configuration, each interface, and their endpoints. The configuration descriptor listed on Free60 is not the entire descriptor. I had to pull one from the controller using Microsoft Message Analyzer. There is some padding included in the controller’s actual configuration and that padding needs to be there for the device to correctly enumerate. I will try to do my best at explaining the configuration descriptor. This will not be an in depth explanation of the entire descriptor. You should read the comments included in my code, USB in a Nutshell, and consider picking up a copy of USB Complete. A fair warning though, USB complete focuses mainly on the PC side of coding for USB devices. When I first studied USB for embedded devices I needed to create PC side software to configure the device over generic HID. Jan Axelson’s book was a tremendous resource in developing my PC USB library and understanding the underlying elements of USB.

// USB Configuration Descriptor.  This huge descriptor tells all
// of the devices capbilities.
static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
        // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
        9,                                      // bLength;
        2,                                      // bDescriptorType;
        LSB(CONFIG_DESC_SIZE),                 // wTotalLength
        NUM_INTERFACE,                          // bNumInterfaces
        1,                                      // bConfigurationValue
        0,                                      // iConfiguration
    DEVICE_ATTRIBUTES,						// bmAttributes
    DEVICE_POWER,							// bMaxPower

The configuration descriptor first tells the PC it is a configuration type descriptor (0x02) with a length of 9. It then tells us that this is describing configuration 1 and that there are 4 interfaces in this configuration. The device is bus powered and has a max power draw of 500mA. It describes the total length of the configuration descriptor as 153 which we can get from the original controller descriptor or by counting bytes. However, as I discussed earlier, you will notice that the descriptor listed at Free60 comes out to 93 or 94 bytes. This is because the padding is missing and trust me you need the padding. Interface 0 has an interface class of 0xFF, subclass 0x5D, and a protocol of 0x01. This interface is actually the only one that concerns us on the PC. It contains two endpoints, 0x81 (Endpoint 1 in) and 0x02 (Endpoint 2 out). The directions are based from the host’s point of view and are described in the MSB of the endpoint address. With setting the most significant bit to a 1 making the endpoint an IN. This means that all button reports going TO the PC with be sent on endpoint 0x81, while any LED patterns the PC sends the controller are being RECEIVED by the device on endpoint 0x02. The other endpoints are used for other peripheral such as headsets, chatpads, etc. The only other interface that might be of use to you is the last one, interface 4. It claims it has 0 endpoints, but this is the interface that handles the security handshake with the Infineon security chip. It is the only interface with a string descriptor. I have included this string descriptor just in case someone decides they want to attempt to replicate a man in the middle device similar to what BrandonW created. In emails between myself and Brandon, he indicated that the 360 will just stop communicating with the controller if this string descriptor for interface 4 doesn’t exist.

The next thing that we need to look at, is the way the controller sends button reports to the host. Once again, Free60 is on top of things with this. However, pay close attention to the indexes provided. The standard bit format of a byte goes: bit 7, bit 6, bit 5, bit 4, bit 3, bit 2, bit 1, and bit 0. Remember this is sent from the device to the host on endpoint 1 in a 20 byte packet. Below is the button report broken down:

Button Report PDF

As you write your code, you may wonder what the button names correlate to on an XBOX 360 controller. Here is a table to help you with that:

Button to XBOX Conversion PDF

The last endpoint we really care about is endpoint 2 out. This comes into the device from the PC and contains messages. The only message we care about is message type 0x01, which is LED control. The packet will come in 3 bytes with byte 1 being message type and byte 2 as the length. The 3rd byte contains the pattern to be performed. Below are the different patterns that the controller can produce:

LED Report PDF

Table of Contents


[MSF] FightStick (TeensyLC XINPUT Controller) – 2


Dinput VS Xinput

There is likely to be quite a few misconceptions and errors in this area of my understanding. I am not a game developer and actually do very minimal PC application development. Originally games used a DLL named Dinput to communicate with controllers in their software. You could use Dinput.dll to probe a controller, learn its ins and outs, and then utilize it in your game. Microsoft deemed this too difficult a task for PC game developers. Since they were releasing a new controller, they really wanted to make it accessible to developers to work with. They decided to reinvent how developers access their controllers. The big issue that affects the hobbyist community is that it is no longer a HID device. Look at any game you play, it supports the XBOX 360 controller. Not being HID is the biggest downfall to Xinput devices (sometimes referred to as XUSB devices in Microsoft documentation). This creates a huge problem for us because without being HID you will need drivers for your device. Getting drivers signed is an expensive expenditure and not something most are willing to do for non-commercial projects.

So naturally the next thought is “Who cares? We will just stick to Dinput HID controllers!” That would work, if the whole gaming world didn’t adopt Xinput. For a long time, people supported both Xinput and Dinput in their games. Sadly, it is no longer that way. Actually many games incorrectly manage Dinput devices and cause errors to occur that make games unplayable. This is where the constant looking up or the constantly spinning left comes in. The Dinput device is actually assigned an extra axis on accident and that causes you to look whichever way it is assigned, indefinitely. Many examples of this are found on games that do not need a controller but behave incorrectly when you have one plugged in, Tribes: Ascend being a good example. So now you need to make your Dinput device look like an Xinput one. Up until this point you had one option, you would put software called X360CE (or other similar software) into your game directory, you would assign your controller’s inputs to similar ones on a 360 controller, and it would create a custom xinput.dll in the game folder that correctly mapped your controller for use.

Using X360CE was an easy option for us, but I just couldn’t do it. We worked hard on making sure these fightsticks turned out nice and I wasn’t about to settle for putting some software in all my game directories. That was when the idea was born. There has to be a way to imitate the XBOX 360 controller. I mean it’s just a USB device afterall, right? It was time to investigate!

Table of Contents

[MSF] FightStick (TeensyLC XINPUT Controller)

Collage 2015-05-01 20_00_26
Introduction to the Project

The idea for this project came up when discussing the release of Mortal Kombat X. The guys at Mechanical Squid Factory (our gaming group) decided they wanted to branch out into the competitive fighting game scene. We started doing research into fighting games and that brought us to a forum called Shoryuken. The realization that a regular gamepad might not provide the best experience quickly set in. We decided that a fight stick would be just too expensive and thought keyboard would work out. The entire team played through the story of MKX and thought our fingers would never function again after contorting them to the keyboard. Soon enough we couldn’t take it anymore and pieced together fight sticks. Most of our parts were ordered from FocusAttack and the cases from Art at Tek-Innovations. As you can tell, the cases are laser cut by Art and they do have a 2 week turn around time. However, they really are beautiful when assembled. We then opted for a DIY solution to a controller board. This could save us $40-$50 since we only planned on using these on the PC anyways.

I began scouring through development boards. I had to meet just a few criteria but they were strict. I needed it to be small, support USB, and most of all, be CHEAP. Many of the boards just didn’t provide enough cost benefit over an existing solution. Finally I found an awesome little ARM cortex development board called the TeensyLC. It met all the criteria with flying colors and it had an ARM on it, which was an awesome bonus. What I did not know is the frustration that would follow after receiving these boards. There was nothing wrong with the TeensyLC, it was the bundling with arduino that caused most of the headaches. I am strong in my hate against arduino. I feel that it definitely has a place, but it has recently crept into places it does not belong. In the beginning, however, the arduino integration was actually a plus. I needed a joystick that plugged into a PC. It is pretty common for a device to have a HID joystick example if it supports HID USB. I went ahead and ordered 3 of them for the group.

What happened next is what I guess you could call scope creep. The project was finished and it was working great. Standard HID USB Joystick and it showed up with our name on it. Then someone uses it in a portion of the game that doesn’t just use the DPAD. Shouldn’t be an issue right? Wrong! The character continued to just look up constantly. I tried adding extra axes and setting them to center to fix it. I even tried changing all the bit lengths for the axes to the same that the XBOX uses, but nothing would work. We then started loading up other joystick games and realizing that most of them just didn’t work or if they did, you just constantly looked up or spun in a specific direction. With a little bit of google-fu I quickly learned that I had created a joystick compatible with Dinput and that was no longer a thing unfortunately. The industry was all about Xinput, which is a real bummer for hobbyist. That’s when the scope expanded and my struggles with adjusting my work flow to the Arduino IDE began.

You can find my code in my GIT repository!

Table of Contents