Skip to content

Instantly share code, notes, and snippets.

@Fighter19
Last active October 23, 2016 04:19
Show Gist options
  • Save Fighter19/06ccb81015cdca95bb0b to your computer and use it in GitHub Desktop.
Save Fighter19/06ccb81015cdca95bb0b to your computer and use it in GitHub Desktop.
Accessing the Steam Controller through libusb; Attempt of reversing the protocol.
//Do what you want with this example
//Author: Fighter19
//Comment: I used Wireshark to get most of the values
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <usb.h>
#include <linux/usbdevice_fs.h>
#include <libusb-1.0/libusb.h>
/*
#DEFINE 0x000001 RT; //Right Trigger press
#DEFINE 0x000002 LT; //Left Trigger press
#DEFINE 0x000004 RB; //Right Bumper
#DEFINE 0x000008 LB; //Left Bumper
#DEFINE 0x000010 Y;
#DEFINE 0x000020 B;
#DEFINE 0x000040 X;
#DEFINE 0x000080 A;
#DEFINE 0x001000 SELECT;
#DEFINE 0x002000 LOGO; //Ohne 00 auf data[9]
#DEFINE 0x004000 START;
#DEFINE 0x008000 BL; //Back Left
#DEFINE 0x010000 BR; //Back Right
#DEFINE 0x020000 LS; //Left Stick press
*/
/*
#DEFINE RT 0x000001; //Right Trigger press
#DEFINE LT 0x000002; //Left Trigger press
#DEFINE RB 0x000004; //Right Bumper
#DEFINE LB 0x000008; //Left Bumper
#DEFINE Y 0x000010;
#DEFINE B 0x000020;
#DEFINE X 0x000040;
#DEFINE A 0x000080;
*/
#define SELECT 0x10 //on data[9]
#define LOGO 0x20
#define START 0x40
#define BL 0x80 //Back Left
//data[10]
#define BR 0x01 //Back Right
#define LS 0x02 //Left Stick press
/*
struct buttonData
{
unsigned int rt:1;
unsigned int lt:1;
unsigned int rb:1;
unsigned int lb:1;
unsigned int y:1;
unsigned int b:1;
unsigned int x:1;
unsigned int a:1;
unsigned int select:1;
unsigned int logo:1;
unsigned int start:1;
unsigned int bl:1;
unsigned int br:1;
unsigned int ls:1;
};
*/
//int getButtons(libusb_device_handle* handle)
struct buttonData* getButtons(void* data)
{
struct buttonData* buttons;
buttons = (struct buttonData*)data;
return buttons;
}
static const char default_format[] = "%a %b %d %Y %H:%M";
char* convertIntToChar(int time)
{
const char *format = default_format;
char res[32];
time_t t = time;
struct tm lt;
localtime_r(&t, &lt);
strftime(res, sizeof(res), format, &lt);
return res;
}
void printButtons(uint8_t data[])
{
if(data[9] & SELECT)
{
printf("Select Button pressed\n");
}
if(data[9] & START)
{
printf("Start Button pressed\n");
}
if(data[9] & LOGO)
{
printf("Big button in the middle pressed\n");
}
}
int main(int argc, char *argv[])
{
int result;
libusb_device_handle *d_udh = NULL;
//void* data;
int i=0;
//data = malloc(sizeof(unsigned char)*64);
//memset(data, 0, sizeof(data));
//memset(data, 0x83, 1);
int time;
int* bytesRead;
uint8_t data[64] = {0};
bytesRead = malloc(sizeof(int));
data[0] = 0x8f;//Also needs to be this specific value
data[1] = 0x07;//Can be changed
data[2] = 0x00;
data[3] = 0x58;
data[4] = 0x02;
data[5] = 0x00;
data[6] = 0x00;
data[7] = 0x01;//Has to be 1 for Vibration
result = libusb_init(NULL);
if (result < 0)
{
printf("libusb initialization failed:\n");
}
libusb_set_debug(NULL, 3);
d_udh = libusb_open_device_with_vid_pid(NULL, 0x28de, 0x1102);
printf ("Handle 0x%X\n", (unsigned int)d_udh);
result = d_udh ? 0 : -EIO;
//~ if ((fd = open(file, O_RDWR)) < 0)
if (result < 0)
{
printf("failed to open device:\n error: %s \n", strerror(errno)); //file
}
int err = libusb_claim_interface(d_udh, 2);
if (err)
{
printf ("Error: %s, errno: %s\n", libusb_error_name(err), strerror(errno));
return 1;
}
//Uncomment this to send one simple vibration signal
//libusb_control_transfer(d_udh, 0x21, 0x09, 0x0300, 0x0002, data, 64, 0);
//setServiceMode(d_udh);
/*for (i=0; i<64; i++)
{
printf("%#08x\n", data[i]);
//printf("troll");
}
*/
/*
for (i=22; i<(26); i++)
{
//(time >> (8*(i-22))) & 0xff = data[i];
// time[i] = data[i];
time = ((unsigned int)data[i] << (8*(i-22))) & 0xff;
}
*/
//time = getFirmwareDate(d_udh);
time = getFirmwareDate(d_udh);
printf ("Zeit in sekunden %i\n", time);
printf("Firmware Date: \t\t\t'%s'\n", convertIntToChar(time));
time = getUnknownDate(d_udh);
printf("Unknown Date (Production?): \t'%s'\n", convertIntToChar(time));
time = getUnknownDate2(d_udh);
printf("Unknown Date (FirstFirmware?): \t'%s'\n", convertIntToChar(time));
/*
while(1)
{
libusb_interrupt_transfer(d_udh, 3, data, 64, NULL, 0);
for (i=0; i<sizeof data/ sizeof data[0]; i++)
{
printf("Data %u: %X", i, data[i]);
}
}
*/
/*
libusb_interrupt_transfer(d_udh, 0x83, data, 64, bytesRead, 0);
for (i=0; i<sizeof data/ sizeof data[0]; i++)
{
printf("Data %u: %X\t", i, data[i]);
}
*/
//struct buttonData* buttons;
//Get the button states
libusb_interrupt_transfer(d_udh, 0x83, data, 64, bytesRead, 0);
// getButtons(data);
printButtons(data);
libusb_close(d_udh);
libusb_exit(NULL);
//libusb_control_transfer();
}
//To get the dates you need to be in Service Mode
int getFirmwareDate(libusb_device_handle* handle)
{
int i;
int time = 0;
uint8_t data[64] = {0};
uint8_t offset = 23;
libusb_control_transfer(handle, 0xa1, 0x01, 0x0300, 0x0002, data, 64, 0);
//printf ("Data: \n");
for (i=0; i<4; i++)
{
time += data[i+offset] << (8*(i));
}
//time = data[26] << 24 | data[25] << 16 | data[24] << 8 | data[23];
return time;
}
int getUnknownDate(libusb_device_handle* handle) //Assembly date?
{
int i;
int time = 0;
uint8_t data[64] = {0};
uint8_t offset = 18;
libusb_control_transfer(handle, 0xa1, 0x01, 0x0300, 0x0002, data, 64, 0);
//printf ("Data: \n");
/*
for (i=18; i<22; i++)
{
time += data[i] << (8*(i-18));
}
*/
for (i=0; i<4; i++)
{
time += data[i+offset] << (8*(i));
}
//time = data[26] << 24 | data[25] << 16 | data[24] << 8 | data[23];
return time;
}
int getUnknownDate2(libusb_device_handle* handle) //First Firmware Version?
{
int i;
int time = 0;
uint8_t data[64] = {0};
uint8_t offset = 28;
libusb_control_transfer(handle, 0xa1, 0x01, 0x0300, 0x0002, data, 64, 0);
//printf ("Data: \n");
/*
for (i=18; i<22; i++)
{
time += data[i] << (8*(i-18));
}
*/
for (i=0; i<4; i++)
{
time += data[i+offset] << (8*(i));
}
//time = data[26] << 24 | data[25] << 16 | data[24] << 8 | data[23];
return time;
}
int setServiceMode(libusb_device_handle* handle) //This allows to access dates and maybe more, is being set to normal mode by any normal request
{
uint8_t data[64] = {0};
data[0] = 0x83;//Service Mode, maybe also reset, however trackball feeling doesn't get reinitialized
return libusb_control_transfer(handle, 0x21, 0x09, 0x0300, 0x0002, data, 64, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment