AristoChen / usb-proxy

A USB proxy based on raw-gadget and libusb

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Modify faulty usb endpoint descriptor

pr8x opened this issue · comments

Is it possible to modify usb endpoint descriptors and change the length of a field? I am trying to fix an old USB device that sends a faulty endpoint descriptor (Most likely wrong WMaxPacketSize length). Since the descriptor is invalid it might not be enumerated by libusb, so would this even work with this library?

Yes, it is possible to modify the descriptor before sending to the host, you may try to modify or hardcode your preferred descriptor here

usb-proxy/usb-proxy.cpp

Lines 53 to 150 in b0ccd74

int setup_host_usb_desc() {
host_device_desc.device = {
.bLength = device_device_desc.bLength,
.bDescriptorType = device_device_desc.bDescriptorType,
.bcdUSB = device_device_desc.bcdUSB,
.bDeviceClass = device_device_desc.bDeviceClass,
.bDeviceSubClass = device_device_desc.bDeviceSubClass,
.bDeviceProtocol = device_device_desc.bDeviceProtocol,
.bMaxPacketSize0 = device_device_desc.bMaxPacketSize0,
.idVendor = device_device_desc.idVendor,
.idProduct = device_device_desc.idProduct,
.bcdDevice = device_device_desc.bcdDevice,
.iManufacturer = device_device_desc.iManufacturer,
.iProduct = device_device_desc.iProduct,
.iSerialNumber = device_device_desc.iSerialNumber,
.bNumConfigurations = device_device_desc.bNumConfigurations,
};
int bNumConfigurations = device_device_desc.bNumConfigurations;
host_device_desc.configs = new struct raw_gadget_config[bNumConfigurations];
for (int i = 0; i < bNumConfigurations; i++) {
struct usb_config_descriptor temp_config = {
.bLength = device_config_desc[i]->bLength,
.bDescriptorType = device_config_desc[i]->bDescriptorType,
.wTotalLength = device_config_desc[i]->wTotalLength,
.bNumInterfaces = device_config_desc[i]->bNumInterfaces,
.bConfigurationValue = device_config_desc[i]->bConfigurationValue,
.iConfiguration = device_config_desc[i]->iConfiguration,
.bmAttributes = device_config_desc[i]->bmAttributes,
.bMaxPower = device_config_desc[i]->MaxPower,
};
host_device_desc.configs[i].config = temp_config;
int bNumInterfaces = device_config_desc[i]->bNumInterfaces;
struct raw_gadget_interface *temp_interfaces =
new struct raw_gadget_interface[bNumInterfaces];
for (int j = 0; j < bNumInterfaces; j++) {
int num_altsetting = device_config_desc[i]->interface[j].num_altsetting;
struct raw_gadget_altsetting *temp_altsettings =
new struct raw_gadget_altsetting[num_altsetting];
for (int k = 0; k < num_altsetting; k++) {
const struct libusb_interface_descriptor temp_device_altsetting =
device_config_desc[i]->interface[j].altsetting[k];
struct usb_interface_descriptor temp_host_altsetting = {
.bLength = temp_device_altsetting.bLength,
.bDescriptorType = temp_device_altsetting.bDescriptorType,
.bInterfaceNumber = temp_device_altsetting.bInterfaceNumber,
.bAlternateSetting = temp_device_altsetting.bAlternateSetting,
.bNumEndpoints = temp_device_altsetting.bNumEndpoints,
.bInterfaceClass = temp_device_altsetting.bInterfaceClass,
.bInterfaceSubClass = temp_device_altsetting.bInterfaceSubClass,
.bInterfaceProtocol = temp_device_altsetting.bInterfaceProtocol,
.iInterface = temp_device_altsetting.iInterface,
};
temp_altsettings[k].interface = temp_host_altsetting;
if (!temp_device_altsetting.bNumEndpoints) {
printf("InterfaceNumber %x AlternateSetting %x has no endpoint, skip\n",
temp_device_altsetting.bInterfaceNumber,
temp_device_altsetting.bAlternateSetting);
continue;
}
int bNumEndpoints = temp_device_altsetting.bNumEndpoints;
struct raw_gadget_endpoint *temp_endpoints =
new struct raw_gadget_endpoint[bNumEndpoints];
for (int l = 0; l < bNumEndpoints; l++) {
struct usb_endpoint_descriptor temp_endpoint = {
.bLength = temp_device_altsetting.endpoint[l].bLength,
.bDescriptorType = temp_device_altsetting.endpoint[l].bDescriptorType,
.bEndpointAddress = temp_device_altsetting.endpoint[l].bEndpointAddress,
.bmAttributes = temp_device_altsetting.endpoint[l].bmAttributes,
.wMaxPacketSize = temp_device_altsetting.endpoint[l].wMaxPacketSize,
.bInterval = temp_device_altsetting.endpoint[l].bInterval,
.bRefresh = temp_device_altsetting.endpoint[l].bRefresh,
.bSynchAddress = temp_device_altsetting.endpoint[l].bSynchAddress,
};
temp_endpoints[l].endpoint = temp_endpoint;
temp_endpoints[l].thread_read = 0;
temp_endpoints[l].thread_write = 0;
memset((void *)&temp_endpoints[l].thread_info, 0,
sizeof(temp_endpoints[l].thread_info));
temp_endpoints[l].thread_info.ep_num = -1;
}
temp_altsettings[k].endpoints = temp_endpoints;
}
temp_interfaces[j].altsettings = temp_altsettings;
temp_interfaces[j].num_altsettings = device_config_desc[i]->interface[j].num_altsetting;
temp_interfaces[j].current_altsetting = 0;
}
host_device_desc.configs[i].interfaces = temp_interfaces;
}
host_device_desc.current_config = 0;
return 0;
}

Would this also work when the usb device is not recognized by the system due an error in the endpoint descriptor? Also, can the same be achieved via injection files?

Hi,

Are you able to see the usb device via lsusb command? if yes, then I guess should be able to work. However, I don't have such a usb device to test, so no gurantee that this project could work with it.

Currently, injection files might not be able to work with your use cases, I think this feature is complicated, I can add it to my to do list, and if more people are interested in this feature, I may try to figure it out sooner.

Good news, the device is listed by lsusb and it seems to be operable. However, when running usb-proxy I am not seeing the device forwarded to my PC:

sudo ./usb-proxy --device=20980000.usb --driver=20980000.usb --vendor XXX --product_id YYY

Device is: 20980000.usb
Driver is: 20980000.usb
vendor_id is: XXX
product_id is: YYY
Device opened successfully
Setup USB config successfully
Start for EP0, thread id(1663)
event: connect, length: 0
Start hotplug_monitor thread, thread id(1665)

I am using RPI Zero and the USB device is connected to it via an OTG host cable. The other micro usb port is connected to my Windows machine.

EDIT: Just realized that the second USB port is for power only 🤦‍♂️Ok, I guess I need a RPi 3 or something then...

If I remember correctly, there is no OTG port on RPi 3, you may want to try RPi 4

Ok managed to fix my problem by using a Teensy. Thanks for your help though!