Skip to content

Instantly share code, notes, and snippets.

@shinyquagsire23
Created April 12, 2017 04:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shinyquagsire23/70920eab2e6c16b7eb774fb19cf271d1 to your computer and use it in GitHub Desktop.
Save shinyquagsire23/70920eab2e6c16b7eb774fb19cf271d1 to your computer and use it in GitHub Desktop.
Pro Controller hidtest, maybe
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <chrono>
#include <ctime>
#include <cstring>
#include <hidapi/hidapi.h>
// Uncomment for spam or SPI dumping
//#define DEBUG_PRINT
//#define DUMP_SPI
//#define REPLAY
#define INPUT_LOOP
void hex_dump(unsigned char *buf, int len)
{
for (int i = 0; i < len; i++)
printf("%02x ", buf[i]);
printf("\n");
}
void hid_exchange(hid_device *handle, unsigned char *buf, int len)
{
if(!handle) return; //TODO: idk I just don't like this to be honest
hid_write(handle, buf, len);
int res = hid_read(handle, buf, 0x41);
#ifdef DEBUG_PRINT
hex_dump(buf, 0x40);
#endif
}
void hid_dual_exchange(hid_device *handle_l, hid_device *handle_r, unsigned char *buf_l, unsigned char *buf_r, int len)
{
hid_set_nonblocking(handle_r, 1);
hid_write(handle_r, buf_r, len);
hid_read(handle_r, buf_r, 65);
#ifdef DEBUG_PRINT
hex_dump(buf_r, 0x40);
#endif
hid_set_nonblocking(handle_r, 0);
}
void spi_flash_dump(hid_device *handle, char *out_path)
{
unsigned char buf[0x40];
unsigned char spi_read[0x39] = {0x80, 0x92, 0x0, 0x31, 0x0, 0x0, 0xd4, 0xe6, 0x1, 0xc, 0x0, 0x1, 0x40, 0x40, 0x0, 0x1, 0x40, 0x40, 0x10, 0x00, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
FILE *dump = fopen(out_path, "wb");
for(*(uint32_t*)(&spi_read[0x13]) = 0; *(uint32_t*)(&spi_read[0x13]) < 0x80000; *(uint32_t*)(&spi_read[0x13]) += 0x1C)
{
memcpy(buf, spi_read, 0x39);
hid_exchange(handle, buf, 0x39);
fwrite(buf + 0x1E * sizeof(char), 0x1C, 1, dump);
}
fclose(dump);
}
int main(int argc, char* argv[])
{
int res;
unsigned char buf_l[0x40];
unsigned char buf_r[0x40];
hid_device *handle_l, *handle_r;
struct hid_device_info *devs, *dev_iter;
res = hid_init();
devs = hid_enumerate(0x057e, 0x2009); //TODO: Pro Controller? Will probably need changes to init...
dev_iter = devs;
while (dev_iter)
{
if(dev_iter->interface_number == 0)
handle_r = hid_open_path(dev_iter->path);
else if(dev_iter->interface_number == 1)
handle_l = hid_open_path(dev_iter->path);
dev_iter = dev_iter->next;
}
hid_free_enumeration(devs);
if(!handle_r)
{
fprintf(stderr, "Could not get handle(s) for Joy-Con! Handles L %08x, R %08x\n", handle_l, handle_r);
return -1;
}
//Get MAC Right
memset(buf_r, 0x00, 0x40);
buf_r[0] = 0x80;
buf_r[1] = 0x01;
hid_exchange(handle_r, buf_r, 0x2);
if(buf_r[2] == 0x3)
{
fprintf(stderr, "Right Joy-Con disconnected! Cannot initialize without both Joy-Con!\n");
return -1;
}
else
{
printf("Found Joy-Con (R), MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", buf_l[9], buf_l[8], buf_l[7], buf_l[6], buf_l[5], buf_l[4]);
}
memset(buf_r, 0x00, 0x40);
buf_r[0] = 0x80;
buf_r[1] = 0x02;
hid_exchange(handle_r, buf_r, 0x2);
printf("Switching baudrate...\n");
memset(buf_r, 0x00, 0x40);
buf_r[0] = 0x80;
buf_r[1] = 0x03;
hid_exchange(handle_r, buf_r, 0x2);
memset(buf_r, 0x00, 0x40);
buf_r[0] = 0x80;
buf_r[1] = 0x02;
hid_exchange(handle_r, buf_r, 0x2);
#ifdef DUMP_SPI
printf("Dumping Joy-Con SPI flashes...");
spi_flash_dump(handle_r, "right_joycon_dump.bin");
#endif
#ifdef INPUT_LOOP
printf("Start input poll loop\n");
unsigned long last = std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1);
while(1) {
printf("%02llums delay, left ", (std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1)) - last);
last = std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1);
buf_l[0] = 0x80; // 80 Do custom command
buf_l[1] = 0x92; // 92 Post-handshake type command
buf_l[2] = 0x00; // 0001 u16 second part size
buf_l[3] = 0x01;
buf_l[8] = 0x1F; // 1F Get input command
memcpy(buf_r, buf_l, 0x9);
hid_dual_exchange(handle_l, handle_r, buf_l, buf_r, 0x9);
hex_dump(buf_l, 0x3D);
printf(" right ");
hex_dump(buf_r, 0x3D);
}
#endif
hid_close(handle_r);
// Finalize the hidapi library
res = hid_exit();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment