Skip to content

Commit

Permalink
Fix speed detection for USB 3.0 SuperSpeed devices
Browse files Browse the repository at this point in the history
Without proper speed detection, the client may reject devices for invalid EP max packet sizes
  • Loading branch information
cgutman committed May 13, 2024
1 parent 8bea4f6 commit bde6fa1
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class UsbIpDevice {
public static final int USB_SPEED_FULL = 2;
public static final int USB_SPEED_HIGH = 3;
public static final int USB_SPEED_VARIABLE = 4;
public static final int USB_SPEED_SUPER = 5;

public static final int BUS_ID_SIZE = 32;
public static final int DEV_PATH_SIZE = 256;
Expand Down
47 changes: 32 additions & 15 deletions app/src/main/java/org/cgutman/usbip/service/UsbIpService.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,12 @@ public IBinder onBind(Intent intent) {
private final static int FLAG_POSSIBLE_SPEED_LOW = 0x01;
private final static int FLAG_POSSIBLE_SPEED_FULL = 0x02;
private final static int FLAG_POSSIBLE_SPEED_HIGH = 0x04;
private final static int FLAG_POSSIBLE_SPEED_SUPER = 0x08;
private int detectSpeed(UsbDevice dev, UsbDeviceDescriptor devDesc) {
int possibleSpeeds = FLAG_POSSIBLE_SPEED_LOW |
FLAG_POSSIBLE_SPEED_FULL |
FLAG_POSSIBLE_SPEED_HIGH;
FLAG_POSSIBLE_SPEED_HIGH |
FLAG_POSSIBLE_SPEED_SUPER;

for (int i = 0; i < dev.getInterfaceCount(); i++) {
UsbInterface iface = dev.getInterface(i);
Expand All @@ -216,6 +218,10 @@ private int detectSpeed(UsbDevice dev, UsbDeviceDescriptor devDesc) {
// High speed devices can't use control transfer sizes smaller than 64 bytes
possibleSpeeds &= ~FLAG_POSSIBLE_SPEED_HIGH;
}
if (endpoint.getMaxPacketSize() < 512) {
// Super speed devices can't use control transfer sizes smaller than 512 bytes
possibleSpeeds &= ~FLAG_POSSIBLE_SPEED_SUPER;
}
}
else if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
if (endpoint.getMaxPacketSize() > 8) {
Expand All @@ -226,23 +232,27 @@ else if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
// Full speed devices can't use interrupt transfer sizes larger than 64 bytes
possibleSpeeds &= ~FLAG_POSSIBLE_SPEED_FULL;
}
if (endpoint.getMaxPacketSize() > 512) {
// High speed devices can't use interrupt transfer sizes larger than 512 bytes
possibleSpeeds &= ~FLAG_POSSIBLE_SPEED_HIGH;
}
}
else if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
// A bulk endpoint alone can accurately distiniguish between
// full and high speed devices
if (endpoint.getMaxPacketSize() == 512) {
// High speed devices can only use 512 byte bulk transfers
possibleSpeeds = FLAG_POSSIBLE_SPEED_HIGH;
}
else {
// Otherwise it must be full speed
possibleSpeeds = FLAG_POSSIBLE_SPEED_FULL;
}
}
else if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_ISOC) {
// If the transfer size is 1024, it must be high speed
if (endpoint.getMaxPacketSize() == 1024) {
possibleSpeeds = FLAG_POSSIBLE_SPEED_HIGH;
// full, high, and super speed devices
switch (endpoint.getMaxPacketSize()) {
case 512:
// High speed devices can only use 512 byte bulk transfers
possibleSpeeds = FLAG_POSSIBLE_SPEED_HIGH;
break;
case 1024:
// Super speed devices can only use 1024 byte bulk transfers
possibleSpeeds = FLAG_POSSIBLE_SPEED_SUPER;
break;
default:
// Otherwise it must be full speed
possibleSpeeds = FLAG_POSSIBLE_SPEED_FULL;
break;
}
}
}
Expand All @@ -253,6 +263,10 @@ else if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_ISOC) {
// High speed only supported on USB 2.0 or higher
possibleSpeeds &= ~FLAG_POSSIBLE_SPEED_HIGH;
}
if (devDesc.bcdUSB < 0x300) {
// Super speed only supported on USB 3.0 or higher
possibleSpeeds &= ~FLAG_POSSIBLE_SPEED_SUPER;
}
}

// Return the lowest speed that we're compatible with
Expand All @@ -268,6 +282,9 @@ else if ((possibleSpeeds & FLAG_POSSIBLE_SPEED_FULL) != 0) {
else if ((possibleSpeeds & FLAG_POSSIBLE_SPEED_HIGH) != 0) {
return UsbIpDevice.USB_SPEED_HIGH;
}
else if ((possibleSpeeds & FLAG_POSSIBLE_SPEED_SUPER) != 0) {
return UsbIpDevice.USB_SPEED_SUPER;
}
else {
// Something went very wrong in speed detection
return UsbIpDevice.USB_SPEED_UNKNOWN;
Expand Down

0 comments on commit bde6fa1

Please sign in to comment.