Xbox 360 Big Button Controllers on a PC using WinUSB and C#

Like so many others I have had these rather excellent controllers lying around since I bought the game a few years ago.

They can be bought for cheap these days, the whole set usually goes for less than £10 on Amazon.

I've wanted to use them for a project for a while but never got around to it. I naively assumed that getting them to work would be easy, boy was I wrong.

What is even worse is that I found very little existing work on the internet related to these controllers. Darn!

What happens when you plug the IR controller into a PC is that you simply get an "Unknown device" listed in the Device Manager as no PC drivers are available for this system.

Update

I've updated the library and code discussed in this article significantly and the whole project can now be found on GitHub at http://sverrirs.github.io/XboxBigButton/. This includes the driver, installers, C# library code and example projects. If you're interested in the blog entries discussing these updates they can be found here: entry #1 (C#), entry #2 (Unity3d), entry #3 (remote control), entry #4 (installer), entry #5 (Chrome App).

Existing work

There is a Linux driver project (xbox360bb) that was made for the control structure which provided some help as to the protocol and the necessary USB setup. Unfortunately almost none of the code is applicable to Windows and very little could be reused.

The Sony PS2/PS3 buzz controllers have a really nice library implemented in C# by Brent Beardsley, called BuzzIO.

Other than this not much else could be found.

The Big Button Infra Red receiver that handles all the communication with the controllers

The Big Button Infra Red receiver that handles all the communication with the controllers

What didn't work

I started off trying to leverage and adapt the BuzzIO code (which is really nicely done) to the Big Button controllers. Unfortunately after unsuccessfully trying for a few days. Messing around with the SetupDi_* and HidD_* and CreateFile(...) kernel functions just didn't want to work with the device.

It took me a while until I realised that these USB functions really don't work unless the device gets an DeviceInterfaceGuid listed, and this Guid doesn't get assigned unless there is a driver.

Then I attempted to use the LibUsbDotNet USB library. It was supposed to be able to handle communications with driver-less devices. Unfortunately this library cannot be used with a x64 bit Windows operating system due to a "safe mode" that was designed for peripheral drivers. I suspect this issue is also present in Win8 and Win10+.

However the libusbdotnet library got me on the right track as it mentiones the WinUSB system. This system is based around a generic USB driver that is provided by Microsoft and shipped with all Windows XP SP3 and newer. It takes a while to read up on this and the USB system but it is well worth it!

After that I found the excellent WinUSB.NET project written by the Mad Wizard Thomas :)

What worked

The solution that finally worked was two-fold

  1. Use WinUSB to create a driver for the IR controller
  2. Connect to the driver using the WinUSB.NET library

Step 1: Creating the WinUSB driver

The way to leverage the WinUSB sytem is to provide and write your own .INF file that describes the basics of the device you intend to connect to and the DeviceInterfaceGuid you want to give it.

I found two great sources to get me started on the file, INF template on the winusbnet wiki and an answer on stackoverflow.

Hint: To debug the loading of device drivers in Windows you can use the SetupAPI. The logs can be found under C:\Windows\Inf\setupapi.dev.log

Here is my final INF configuration that successfully loads up the driver on my system. You need a few extra dlls that handle the registration, the entire install can be downloaded in this zip file.

The custom WinUSB driver loaded successfully. Done by right clicking the

The custom WinUSB driver loaded successfully. Done by right clicking the "unknown device" and selecting the option to update the driver

Step 2: Using C# to talk to the custom driver

Using both the information from the Linux Driver project and this excellent blog I managed to establish connection and read successfully from the device.

Here is my test code (it is very primitive but shows all the necessary steps):

Interpreting the results

When running this example and pressing random buttons on the controllers the following output can be seen

Input examples from the controllers. The input buffers should be only 5 bytes

Input examples from the controllers. The input buffers should be only 5 bytes

Taking the first input line (after the "Waiting on main thread") as an example, the format is as follows:

Byte Data Description
0 00 Header, ignore
1 05 Length of the input data in bytes
2 01 Controller index number
  x00 = green
  x01 = red
  x02 = blue
  x03 = yellow
3 00 Big button directions and the small white buttons
  x01 = UP
  x02 = DOWN
  x04 = LEFT
  x08 = RIGHT
  x20 = BACK
  x10 = START
4 40 Action buttons
  x04 = Xbox button
  x08 = Big button push
  x10 = A
  x20 = B
  x40 = X
  x80 = Y
5 00 rubbish, ignore

This post can also be found on LinkedIn: https://www.linkedin.com/pulse/xbox-360-big-button-controllers-pc-using-winusb-c-sigmundarson

All images in this post are shamelessly "borrowed" from blogeek.ch



Software Developer
For hire


Developer & Programmer with +15 years professional experience building software.


Seeking WFH, remoting or freelance opportunities.