I'm currently trying to emulate the traffic sent to/from a HID device using libusb. The traffic is sniffed using wireshark and USBPcap. I emulated the first packets by requesting the descriptors and setting configuration etc. But at this point according to the log, the host sends a set idle request, get descriptor hid report and lastly a bunch of set reports. What functions in libusb corresponds to these packets? AFAIK the set report is basically the host transmitting some sort of settings to the device. I figured I could just copy the packet data and send my own reports exactly the same? Also is there a way to see exactly what the data does in the set report packets? I need to know how to properly set this up.
This is the packets i'm trying to emulate:
1 0.000000 host 2.41.0 USB 36 GET DESCRIPTOR Request DEVICE
2 0.000174 2.41.0 host USB 46 GET DESCRIPTOR Response DEVICE
3 0.000208 host 2.41.0 USB 36 GET DESCRIPTOR Request CONFIGURATION
4 0.000291 2.41.0 host USB 37 GET DESCRIPTOR Response CONFIGURATION
5 0.000304 host 2.41.0 USB 36 GET DESCRIPTOR Request CONFIGURATION
6 0.000395 2.41.0 host USB 62 GET DESCRIPTOR Response CONFIGURATION
7 0.000411 host 2.41.0 USB 36 SET CONFIGURATION Request
8 0.001150 2.41.0 host USB 28 SET CONFIGURATION Response
9 0.001167 host 2.41.0 USBHID 36 SET_IDLE Request
10 0.001239 2.41.0 host USBHID 28 SET_IDLE Response
11 0.001386 host 2.41.0 USBHID 36 GET DESCRIPTOR Request HID Report
12 0.001462 2.41.0 host USBHID 104 GET DESCRIPTOR Response HID Report
13 0.002620 host 2.41.1 USB 27 URB_INTERRUPT in
14 0.002645 host 2.41.1 USB 27 URB_INTERRUPT in
15 6.085037 2.41.1 host USB 27 URB_INTERRUPT in
16 6.085090 2.41.1 host USB 27 URB_INTERRUPT in
17 18.467828 host 2.41.0 USBHID 36 SET_IDLE Request
18 18.467993 2.41.0 host USBHID 28 SET_IDLE Response
19 18.468086 host 2.41.1 USB 27 URB_INTERRUPT in
20 18.468114 host 2.41.1 USB 27 URB_INTERRUPT in
21 18.468385 host 2.41.0 USB 36 GET DESCRIPTOR Request STRING
22 18.468537 2.41.0 host USB 86 GET DESCRIPTOR Response STRING
23 18.468595 host 2.41.0 USB 36 GET DESCRIPTOR Request STRING
24 18.468801 2.41.0 host USB 60 GET DESCRIPTOR Response STRING
25 18.475044 host 2.41.0 USBHID 53 SET_REPORT Request
26 18.475273 2.41.0 host USBHID 28 SET_REPORT Response
27 18.475834 host 2.41.0 USBHID 1061 SET_REPORT Request
28 18.476102 2.41.0 host USBHID 28 SET_REPORT Response
29 18.476571 host 2.41.0 USBHID 1061 SET_REPORT Request
30 18.476849 2.41.0 host USBHID 28 SET_REPORT Response
31 18.477280 host 2.41.0 USBHID 1061 SET_REPORT Request
32 18.477565 2.41.0 host USBHID 28 SET_REPORT Response
33 18.478085 host 2.41.0 USBHID 1061 SET_REPORT Request
34 18.478329 2.41.0 host USBHID 28 SET_REPORT Response
35 18.478700 host 2.41.0 USBHID 1061 SET_REPORT Request
I assume that I need to claim the interface and setup the endpoints. But I am having trouble understanding how to setup the system as hid class, setting the interrupts and polling correctly etc. At this point I have the config descriptor, the device descriptor and a device handle to work with.
#include <stdio.h>
#include "libusb.h"
#include <unistd.h>
#include <time.h>
static void print_devs(libusb_device **devs) //Taken from examples provided with libusb. Not used at this time
{
libusb_device *dev;
int i = 0, j = 0;
uint8_t path[8];
while ((dev = devs[i++]) != NULL) {
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) {
fprintf(stderr, "failed to get device descriptor");
return;
}
printf("%04x:%04x (bus %d, device %d)",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev));
r = libusb_get_port_numbers(dev, path, sizeof(path));
if (r > 0) {
printf(" path: %d", path[0]);
for (j = 1; j < r; j++)
printf(".%d", path[j]);
}
printf("\n");
}
}
int port_open (libusb_device* dev, libusb_device_handle** dev_handle){ //Homebrew func. Retries after failed libusb_open
int count = 0;
int err = 0;
printf("Attempting to open port...\n");
while (1){
printf(".\n");
err = libusb_open(dev, &dev_handle); //Attempts to open port
if (err == 0){
break;
}
if(count>TIMEOUT){ //5s without the port opening and it will throw error
printf(libusb_error_name(err));
return -1;
}
count++;
delay(1);
}
return 0;
}
static int target_find(libusb_device *dev){ //Check for device. Libusb already had this but it was done before I saw it.
struct libusb_device_descriptor my_dev;
libusb_get_device_descriptor(dev,&my_dev);
if ((my_dev.idVendor == VENDOR) && (my_dev.idProduct == PRODUCT)){
return 1;
}
return 0;
}
int main(void)
{
int r;
int err = 0;
err = libusb_init(NULL);
if (err != 0) {
printf("LIBUSB ERROR: Could not initialize\n");
return -1;
}
libusb_device **list;
libusb_device *found = NULL;
while(1){ //Finds device and opens port
ssize_t cnt = libusb_get_device_list(NULL, &list);
ssize_t i = 0;
err = 0;
if (cnt < 0){
printf("USB ERROR: Could not fetch device list\n");
return -1;
}
for (i = 0; i < cnt; i++) {
libusb_device *device = list[i];
if (target_find(device)) {
found = device;
break;
}
}
if (found) {
printf("Port found!\n");
struct libusb_device_descriptor desc;
struct libusb_config_descriptor config;
err = libusb_get_device_descriptor(found,&desc);
if (err){
printf(libusb_error_name(err));
return -1;
}
err = libusb_get_config_descriptor(found,0,&config);
if (err){
printf(libusb_error_name(err));
return -1;
}
libusb_device_handle *handle;
err = port_open(found, &handle);
if (err){
printf("\n Timeout ERROR: Could not open port\n");
return -1;
}
break;
}
libusb_free_device_list(list, 1); //Free device list so I can refresh. Unclear if this is needed though.
}
err = libusb_set_configuration(found, 0x1); //Set config 1 for device, should contain 1 interface with two endpoints. I think.
//The rest here I guess???
return 0;
}