Last active
October 23, 2016 04:19
-
-
Save Fighter19/06ccb81015cdca95bb0b to your computer and use it in GitHub Desktop.
Accessing the Steam Controller through libusb; Attempt of reversing the protocol.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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, <); | |
strftime(res, sizeof(res), format, <); | |
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