Last active
May 18, 2020 18:56
-
-
Save Raven24/2d4e3f83ed7e2799cf8114206e963bd3 to your computer and use it in GitHub Desktop.
olympus footswitch debug - libusb hid
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
cmake_minimum_required(VERSION 3.15) | |
project(UsbTest) | |
set(CMAKE_COLOR_MAKEFILE ON) | |
set(CMAKE_BUILD_TYPE Debug) | |
add_executable(test test.c) | |
find_package(PkgConfig) | |
pkg_check_modules(LIBUSB REQUIRED libusb-1.0) | |
include_directories(${LIBUSB_INCLUDE_DIRS}) | |
target_link_libraries(test ${LIBUSB_LIBRARIES}) |
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
/* | |
TEST PROGRAM FOR PROOF-OF-CONCEPT HANDLING FOR A OLYMPUS FOOTSWITCH HID DEVICE | |
*/ | |
#include <stdio.h> | |
#include <string.h> | |
#include <assert.h> | |
#include <stdlib.h> | |
#include "libusb.h" | |
// source: https://github.com/DIGImend/usbhid-dump/blob/master/src/usbhid-dump.c | |
static void dump(const uint8_t *ptr, size_t len) { | |
static const char xd[] = "0123456789ABCDEF"; | |
static char buf[] = " XX\n"; | |
size_t pos; | |
uint8_t b; | |
for(pos = 1; len > 0; len--, ptr++, pos++) { | |
b = *ptr; | |
buf[1] = xd[b >> 4]; | |
buf[2] = xd[b & 0xF]; | |
(void)fwrite(buf, ((pos % 16 == 0) ? 4 : 3), 1, stdout); | |
} | |
if (pos % 16 != 1) | |
fputc('\n', stdout); | |
fflush(stdout); | |
} | |
static void interrupt_cb(struct libusb_transfer *transfer) { | |
assert(transfer != NULL); | |
switch(transfer->status) { | |
case LIBUSB_TRANSFER_COMPLETED: | |
printf(" + DATA", transfer->actual_length); | |
dump(transfer->buffer, transfer->actual_length); | |
printf(" * re-submitting interrupt transfer\n"); | |
int t_res = libusb_submit_transfer(transfer); | |
if(t_res != LIBUSB_SUCCESS) { | |
fprintf(stderr, "failed submitting transfer\n"); | |
} | |
break; | |
case LIBUSB_TRANSFER_CANCELLED: | |
default: | |
break; | |
} | |
} | |
int main(int argc, char **argv[]) { | |
libusb_context* context = NULL; | |
libusb_device* device = NULL; | |
libusb_device_handle* handle = NULL; | |
struct libusb_device_descriptor desc; | |
struct libusb_transfer* ptransfer; | |
// DEVICE INFO - according to lsusb | |
uint16_t vendor = 0x07b4; | |
uint16_t product = 0x0218; | |
int iface = 0; | |
unsigned char endpoint = 0x81; | |
const size_t ep_len = 8; | |
int r = libusb_init(&context); | |
if(r != LIBUSB_SUCCESS) { | |
fprintf(stderr, "unable to init context\n"); | |
return r; | |
} | |
printf("Opening Device %04X:%04X\n", vendor, product); | |
handle = libusb_open_device_with_vid_pid(context, vendor, product); | |
if(handle == NULL) { | |
fprintf(stderr, "failed to get device handle\n"); | |
return -1; | |
} | |
printf(" * performing reset\n"); | |
r = libusb_reset_device(handle); | |
if(r != LIBUSB_SUCCESS) { | |
fprintf(stderr, "failed to reset device\n"); | |
return r; | |
} | |
device = libusb_get_device(handle); | |
int ret = libusb_get_device_descriptor(device, &desc); | |
if (ret != LIBUSB_SUCCESS) { | |
fprintf(stderr, "failed to get device descriptor\n"); | |
return ret; | |
} | |
unsigned char string[256]; | |
if (desc.iManufacturer) { | |
ret = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, string, sizeof(string)); | |
if (ret > 0) | |
printf(" Manufacturer: %s\n", (char *)string); | |
} | |
if (desc.iProduct) { | |
ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, string, sizeof(string)); | |
if (ret > 0) | |
printf(" Product: %s\n", (char *)string); | |
} | |
if (desc.iSerialNumber) { | |
ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, string, sizeof(string)); | |
if (ret > 0) | |
printf(" Serial Number: %s\n", (char *)string); | |
} | |
if(libusb_kernel_driver_active(handle, iface)) { | |
int res = libusb_detach_kernel_driver(handle, iface); | |
if(res != LIBUSB_SUCCESS && res != LIBUSB_ERROR_NOT_FOUND) { | |
fprintf(stderr, "failed to detach kernel driver: %s", libusb_strerror(res)); | |
return res; | |
} | |
} | |
int t_res; | |
// NECESSARY? | |
printf(" * setting report protocol\n"); | |
t_res = libusb_control_transfer( | |
handle, | |
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, | |
0x0B, // set protocol | |
0x01, // "report" | |
iface, | |
NULL, 0, | |
1000 // timeout | |
); | |
if(t_res != LIBUSB_SUCCESS) { | |
fprintf(stderr, "failed setting report protocol\n"); | |
return t_res; | |
} | |
// NECESSARY? | |
printf(" * setting idle duration\n"); | |
t_res = libusb_control_transfer( | |
handle, | |
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, | |
0x0A, // set idle | |
0, // "infinite" | |
iface, | |
NULL, 0, | |
1000 // timeout | |
); | |
if(t_res != LIBUSB_SUCCESS) { | |
fprintf(stderr, "failed setting report protocol\n"); | |
return t_res; | |
} | |
ptransfer = libusb_alloc_transfer(0); | |
if(ptransfer == NULL) { | |
fprintf(stderr, "failed allocating transfer\n"); | |
return -1; | |
} | |
ptransfer->user_data = NULL; | |
printf(" * preparing interrupt transfer\n"); | |
void *buf; | |
buf = malloc(ep_len); | |
libusb_fill_interrupt_transfer(ptransfer, | |
handle, | |
endpoint, | |
buf, ep_len, | |
interrupt_cb, | |
(void*)NULL, | |
5000); | |
ptransfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER; | |
printf(" * submitting interrupt transfer\n"); | |
t_res = libusb_submit_transfer(ptransfer); | |
if(t_res != LIBUSB_SUCCESS) { | |
fprintf(stderr, "failed submitting transfer\n"); | |
return t_res; | |
} | |
while(1) { | |
int err = libusb_handle_events(context); | |
if(err != LIBUSB_SUCCESS && err != LIBUSB_ERROR_INTERRUPTED) { | |
fprintf(stderr, "error handling events: %s\n", libusb_strerror(err)); | |
return err; | |
} | |
} | |
libusb_exit(context); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example output when running the test binary and pushing buttons -
the third byte of the data corresponds to what button is pressed
(bits are OR combined, according to the pressed button - 1=left, 2=right, 4=top)
I tried it with and without setting report protocol/idle duration, both seemed to work the same.