Hacking a generic USB joystick using HIDAPI.

It has been a while since I posted something here. Lately I have been working on USB firmware and software applications. There are loads of things to post but have very less free time. I’ll post them when I got a free time.

What this article primarily talks about is on a method to communicate with the joystick using your own application. It may be to control a robot, who knows. I will be using a simple MFC application to communicate with the joystick.

In order to understand the article properly you should have at least a slight understanding about,

  1. MFC applications
  2. USB specifications
  3. HID class specifications
  4. C++

A helicopter view of how this communication works,

You have the device. A driver is needed to communicate with the device. The driver has something called IOCTLs which are used by the applications/libraries to communicate with the device. Ya, that’s enough.

HIDAPI is some sort of a library which is cross platform (i will be using it in windows though) and it will take care of all the IOCTL calls and provide us with an API to easily communicate with the device. In other words, we do not need to worry about specific IOCTL details, rather we just need to know how to use the API functions. HIDAPI uses the windows generic driver to communicate with the joystick or any other HID class USB devices. You can find HIDAPI home page here.

First thing I did was connecting the joystick to the pc and sniffing the USB packets using USBlyzer. After that I understood that there is an Interrupt Transfer which has 8 bytes of data. And it simply floods the USBlyzer window. I tried a bit to find the protocol but I haven’t had any luck. So I decided I will figure it out myself.

Using HIDAPI,

I cloned HIDAPI source through git and built it using MSVC2010. After I built the solution it creates a ‘dll’ file which has all the functions and a ‘lib’ file which has information about the dll file.

After that, I linked my MFC dialog application with the ‘dll’ file using MSVC2005. I statically linked the ‘dll’ to make it simpler. About ‘dll’s and linking to them will not be covered here as they are covered in detail in MSDN articles and it is pointless to duplicate them here. I will post a few as references at the end of this article. If you have any issue just drop a comment.

Following is the code I used to connect the joystick,

int m_iReturnCode;

m_iReturnCode = 0;

struct hid_device_ *m_pstrctDevice;

struct hid_device_info *strctDevInfo = NULL;

m_pstrctDevice = NULL;

m_iReturnCode = hid_init();

strctDevInfo = hid_enumerate(VID,PID);

m_pstrctDevice = hid_open(VID,PID,NULL);

Please note that this is just the code related to the HIDAPI. Here the ‘hid_init’ function will initialize the API. Then the ‘hid_enumerate’ function will find all the devices in the system which has the mentioned VID(Vendor ID) and PID(Peripheral ID) values. Then the ‘hid_open’ function will open the device and return a handle to use to control the device.

After this code I designed a simple UI to read the incoming data from the joystick. I used standard MFC dialog box.

The code related to the HIDAPI for the ‘Read’ button on clicked event is,

unsigned char* pucData = (unsigned char*) malloc(sizeof(char) * 64);

m_iReturnCode = hid_read(m_pstrctDevice,pucData,64);

Here the function will store any incoming data in the ‘pucData’ buffer. I will post the full code at the end of the article.

Decoded protocol,

After designing the UI I pressed keys in the joystick one by one and documented the changes of the data read through the application. Following are my findings,

original-sony-ps2-dual-shock-vibration-joystick-game-controller-bulk-chocobozz-1106-19-Chocobozz@122

Capture

Final test application,

After decoding the protocol I designed a simple test application to demonstrate the behavior. I called hid_read function within a while loop inside a separate thread and decoded the protocol using switch statements.

Capture

If you click on Start and then press joystick buttons, the pressed button will be displayed in the application. Click on stop in order to stop the button detection. If you want to read the status of the joystick only once, press the joystick button first and then click on Read to get the status to the Edit Box.

Github link,

https://github.com/pradeepa-s/joystick_hack_HIDAPI.git

You can clone the above repository and start adding cool stuff to it if you like.

References,

  1. USB 2.0 specifications
  2. USB in a nutshell
  3. USB made simple
  4. HIDAPI api
  5. MFC implicit dll linking
  6. DLLs in Visual Studio

10 comments

      1. Hello,

        It looks like you are using Visual Studio 2010. I have tried this using Visual Studio 2013 also and it is working.
        Since the project is originally designed for VS2005 this can be a issue related to the project conversion process to VS2010. Did you allow the VS2010 to properly convert the project?
        As soon as you open the application this fault occurs is it?
        If possible can you try and use VS2013 to see whether the issue persists? VS2010 has many bugs in my experience and that is why I do not use it. VS 2013 is really good.

        In the joystick_hidapiDlg.cpp there is a function called OnInitDialog(). Can you put a break-point there and check where it is failing?

        I will try to install VS2010 here (Let me know the exact version used).

  1. Hi. I just bought those n64 usb controllers, but I have an issue. The D pad and the middle stick, they have the same function, both digitals, there is no sensitivity, just like an playstation controller with the “analog” button turned off. I opened the controller and there it was the stick with the potenciometers, meaning it should be analog, I even used a voltimeter and saw the voltage variation by moving the stick. My guess is that the controller should have a analog toggle button, but it doesnt.
    Wondering if its possible to edit the controller firmware to keep the analog mode always on. Could you help me?

    Thanks a lot.

    1. Hello Danilo,

      I don’t have an N64 USB controller, but I can certainly give it a try using the PS2 type controller which I have. Give me a day or two. And yes, I can certainly help you.

      Cheers.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s