Skip to content

Instantly share code, notes, and snippets.

@KunYi
Forked from xpn/libusb_xb_test.c
Last active May 2, 2024 04:49
Show Gist options
  • Save KunYi/d57918ff6973e2af6ddda92d3d17218c to your computer and use it in GitHub Desktop.
Save KunYi/d57918ff6973e2af6ddda92d3d17218c to your computer and use it in GitHub Desktop.
LibUSB test with XBOX One controller
// to code base on
// https://gist.github.com/xpn/9dca0c1663ecdee76ede
// and modify to another pid(0x0b12)
//
// build commands on Ubuntu 22.04
// gcc libusbxboxone.c -o test_xboxone -lusb-1.0
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <libusb-1.0/libusb.h>
#define VID (0x45e)
#define PID (0x0b12)
void printdev(libusb_device *dev) {
struct libusb_device_descriptor desc;
struct libusb_config_descriptor *config;
libusb_get_device_descriptor(dev, &desc);
printf("Vendor ID: %x\n", desc.idVendor);
printf("Product ID: %x\n", desc.idProduct);
libusb_get_config_descriptor(dev, 0, &config);
for(uint8_t i = 0; i < config->bNumInterfaces; i++) {
const struct libusb_interface* inter = &config->interface[i];
printf("Number of alternate settings: %d\n", inter->num_altsetting);
for(int j = 0; j < inter->num_altsetting; j++) {
const struct libusb_interface_descriptor* interdesc = &inter->altsetting[j];
printf("Interface Number: %d\n", (int)interdesc->bInterfaceNumber);
printf("Number of endpoints: %d\n", (int)interdesc->bNumEndpoints);
for(uint8_t k = 0; k < interdesc->bNumEndpoints; k++) {
const struct libusb_endpoint_descriptor* epdesc = &interdesc->endpoint[k];
printf("Descriptor Type: %d\n", (int)epdesc->bDescriptorType);
printf("EP Address: %d\n", (int)epdesc->bEndpointAddress);
}
}
}
}
int main(int argc, char **argv) {
libusb_context *ctx = NULL;
libusb_device **devs;
libusb_device_handle *dev_handle;
unsigned char data[512];
int actual;
printf("[Xbox Controller Test]: @KunYi \n\n");
memset(data, 0xFF, sizeof(data));
int r = libusb_init(&ctx);
if (r < 0) {
printf("[X] Error init libusb\n");
return 1;
}
libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, 3);
ssize_t cnt = libusb_get_device_list(ctx, &devs);
if (cnt < 0) {
printf("[X] libusb_get_device_list failed\n");
return 1;
}
for(ssize_t x=0; x < cnt; x++) {
printdev(devs[x]);
printf("-----------------------\n");
}
// Grab a handle to our XBONE controller
dev_handle = libusb_open_device_with_vid_pid(ctx, VID, PID);
if (dev_handle == NULL) {
printf("[X] Cannot open device, ensure XBOX controller is attached\n");
return 1;
}
if (libusb_kernel_driver_active(dev_handle, 0) == 1) {
printf("[i] Kernel has hold of this device, detaching kernel driver\n");
libusb_detach_kernel_driver(dev_handle, 0);
}
libusb_claim_interface(dev_handle, 0);
// Start our rumble test
// Thanks to https://github.com/quantus/xbox-one-controller-protocol
// unnecessary, to kernel driver will handle this,
// but you can to add xpad in module blacklist
printf("[!] Power On\r\n");
libusb_interrupt_transfer(dev_handle, 0x02, "\x05\x20\x00\x01\x00", 5, &actual, 5000);
sleep(3);
#if 0
printf("[!] Sending Rumble Test 1.. LT\n");
libusb_interrupt_transfer(dev_handle, 0x02, "\x09\x08\x00\x09\x00\x0f\x20\x04\x20\x20\xFF\x00", 12, &actual, 5000);
sleep(3);
printf("[!] Sending Rumble Test 1.. RT\n");
libusb_interrupt_transfer(dev_handle, 0x02, "\x09\x08\x00\x09\x00\x0f\x04\x20\x20\x20\xFF\x00", 12, &actual, 5000);
#endif
while(1) {
libusb_interrupt_transfer(dev_handle, 0x82, data, sizeof(data), &actual, 5000);
printf("Received %d bytes\n", actual);
for(int x = 0; x < actual; x++) {
printf("%02x ", data[x]);
}
printf("\n");
}
libusb_release_interface(dev_handle, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment