Skip to content

Commit d47c2bd

Browse files
committed
device descriptor as byte array
1 parent b852efe commit d47c2bd

File tree

16 files changed

+119
-63
lines changed

16 files changed

+119
-63
lines changed

java-does-usb/.mvn/wrapper/maven-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.3/apache-maven-3.9.3-bin.zip
17+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip
1818
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

java-does-usb/src/main/java/net/codecrete/usb/USBDevice.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,13 @@ default InputStream openInputStream(int endpointNumber) {
452452
*/
453453
void clearHalt(USBDirection direction, int endpointNumber);
454454

455+
/**
456+
* Gets the device descriptor.
457+
*
458+
* @return the device descriptor (as a byte array)
459+
*/
460+
byte[] deviceDescriptor();
461+
455462
/**
456463
* Gets the configuration descriptor.
457464
*

java-does-usb/src/main/java/net/codecrete/usb/common/USBDeviceImpl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public abstract class USBDeviceImpl implements USBDevice {
3131

3232
protected List<USBInterface> interfaceList;
3333

34+
protected byte[] rawDeviceDescriptor;
35+
3436
protected byte[] rawConfigurationDescriptor;
3537

3638
// Information from the device descriptor
@@ -137,6 +139,11 @@ public byte[] configurationDescriptor() {
137139
return rawConfigurationDescriptor;
138140
}
139141

142+
@Override
143+
public byte[] deviceDescriptor() {
144+
return rawDeviceDescriptor;
145+
}
146+
140147
public Object getUniqueId() {
141148
return uniqueDeviceId;
142149
}
@@ -147,6 +154,7 @@ public Object getUniqueId() {
147154
* @param descriptor the device descriptor
148155
*/
149156
public void setFromDeviceDescriptor(MemorySegment descriptor) {
157+
rawDeviceDescriptor = descriptor.toArray(JAVA_BYTE);
150158
var deviceDescriptor = new DeviceDescriptor(descriptor);
151159
deviceClass = deviceDescriptor.deviceClass() & 255;
152160
deviceSubclass = deviceDescriptor.deviceSubClass() & 255;

java-does-usb/src/main/java/net/codecrete/usb/linux/IO.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ private IO() {
2323
private static final Linker linker = Linker.nativeLinker();
2424
private static final FunctionDescriptor ioctl$FUNC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_LONG, ADDRESS);
2525
private static final MethodHandle ioctl$MH = linker.downcallHandle(linker.defaultLookup().find("ioctl").get(),
26-
ioctl$FUNC, Linux.ERRNO_STATE);
26+
ioctl$FUNC, Linux.ERRNO_STATE, Linker.Option.firstVariadicArg(2));
2727
private static final FunctionDescriptor open$FUNC = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT);
2828
private static final MethodHandle open$MH = linker.downcallHandle(linker.defaultLookup().find("open").get(),
2929
open$FUNC, Linux.ERRNO_STATE);

java-does-usb/src/main/java/net/codecrete/usb/macos/IoKitUSB.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,14 @@ static int CreateInterfaceIterator(MemorySegment self, MemorySegment req, Memory
8181
return IOUSBDeviceStruct187.CreateInterfaceIterator(getVtable(self), Arena.global()).apply(self, req, iter);
8282
}
8383

84+
// IOReturn (* DeviceRequest)(void* self, IOUSBDevRequest* req)
85+
static int DeviceRequest(MemorySegment self, MemorySegment deviceRequest) {
86+
return IOUSBDeviceStruct187.DeviceRequest(getVtable(self), Arena.global()).apply(self, deviceRequest);
87+
}
88+
8489
// IOReturn (* DeviceRequestAsync)(void* self, IOUSBDevRequest* req, IOAsyncCallback1 callback, void* refCon)
8590
static int DeviceRequestAsync(MemorySegment self, MemorySegment deviceRequest, MemorySegment callback,
86-
MemorySegment refCon) {
91+
MemorySegment refCon) {
8792
return IOUSBDeviceStruct187.DeviceRequestAsync(getVtable(self), Arena.global()).apply(self, deviceRequest,
8893
callback, refCon);
8994
}

java-does-usb/src/main/java/net/codecrete/usb/macos/MacosUSBDevice.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77

88
package net.codecrete.usb.macos;
99

10-
import net.codecrete.usb.USBControlTransfer;
11-
import net.codecrete.usb.USBDirection;
12-
import net.codecrete.usb.USBTransferType;
10+
import net.codecrete.usb.*;
1311
import net.codecrete.usb.common.ScopeCleanup;
1412
import net.codecrete.usb.common.Transfer;
1513
import net.codecrete.usb.common.USBDeviceImpl;
1614
import net.codecrete.usb.macos.gen.iokit.IOKit;
1715
import net.codecrete.usb.macos.gen.iokit.IOUSBDevRequest;
1816
import net.codecrete.usb.macos.gen.iokit.IOUSBFindInterfaceRequest;
1917
import net.codecrete.usb.usbstandard.ConfigurationDescriptor;
18+
import net.codecrete.usb.usbstandard.Constants;
19+
import net.codecrete.usb.usbstandard.DeviceDescriptor;
2020

2121
import java.io.InputStream;
2222
import java.io.OutputStream;
@@ -159,11 +159,23 @@ synchronized void closeFully() {
159159
private void loadDescription(MemorySegment device) {
160160
try (var arena = Arena.ofConfined()) {
161161

162+
var data = arena.allocate(DeviceDescriptor.LAYOUT.byteSize());
163+
var ret = IoKitUSB.DeviceRequest(device, createDeviceRequest(arena, USBDirection.IN, new USBControlTransfer(
164+
USBRequestType.STANDARD,
165+
USBRecipient.DEVICE,
166+
6, // get descriptor
167+
Constants.DEVICE_DESCRIPTOR_TYPE << 8,
168+
0
169+
), data));
170+
if (ret != 0)
171+
throwException(ret, "querying device descriptor failed");
172+
rawDeviceDescriptor = data.toArray(JAVA_BYTE);
173+
162174
configurationValue = 0;
163175

164176
// retrieve information of first configuration
165177
var descPtrHolder = arena.allocate(ADDRESS);
166-
var ret = IoKitUSB.GetConfigurationDescriptorPtr(device, (byte) 0, descPtrHolder);
178+
ret = IoKitUSB.GetConfigurationDescriptorPtr(device, (byte) 0, descPtrHolder);
167179
if (ret != 0)
168180
throwException(ret, "querying first configuration failed");
169181

java-does-usb/src/test/java/net/codecrete/usb/AlternateInterfaceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void selectInvalidAlternateIntf_fails() {
4747
void transferOnValidEndpoint_succeeds() {
4848
testDevice.selectAlternateSetting(LOOPBACK_INTF_LOOPBACK, 1);
4949

50-
byte[] sampleData = generateRandomBytes(12, 293872394);
50+
var sampleData = generateRandomBytes(12, 293872394);
5151
testDevice.transferOut(LOOPBACK_EP_OUT, sampleData);
5252
var received = testDevice.transferIn(LOOPBACK_EP_IN);
5353
assertArrayEquals(sampleData, received);

java-does-usb/src/test/java/net/codecrete/usb/BulkTransferTest.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,29 @@ class BulkTransferTest extends TestDeviceBase {
2121

2222
@Test
2323
void smallTransfer_succeeds() {
24-
byte[] sampleData = generateRandomBytes(12, 293872394);
24+
var sampleData = generateRandomBytes(12, 293872394);
2525
writeBytes(sampleData);
26-
byte[] data = readBytes(sampleData.length);
26+
var data = readBytes(sampleData.length);
2727
assertArrayEquals(sampleData, data);
2828
}
2929

3030
@Test
3131
void mediumTransfer_succeeds() {
3232
// This synchronous approach should work as the test device
3333
// has an internal buffer of about 500 bytes.
34-
byte[] sampleData = generateRandomBytes(140, 97333894);
34+
var sampleData = generateRandomBytes(140, 97333894);
3535
writeBytes(sampleData);
36-
byte[] data = readBytes(sampleData.length);
36+
var data = readBytes(sampleData.length);
3737
assertArrayEquals(sampleData, data);
3838
}
3939

4040
@Test
4141
void transferWithZLP_succeeds() {
4242
var inEndpoint = testDevice.getEndpoint(USBDirection.IN, LOOPBACK_EP_IN);
43-
byte[] sampleData = generateRandomBytes(inEndpoint.packetSize(), 97333894);
43+
var sampleData = generateRandomBytes(inEndpoint.packetSize(), 97333894);
4444
testDevice.transferOut(LOOPBACK_EP_OUT, sampleData);
4545
testDevice.transferOut(LOOPBACK_EP_OUT, new byte[0]);
46-
byte[] data = testDevice.transferIn(LOOPBACK_EP_IN);
46+
var data = testDevice.transferIn(LOOPBACK_EP_IN);
4747
assertArrayEquals(sampleData, data);
4848
data = testDevice.transferIn(LOOPBACK_EP_IN);
4949
assertNotNull(data);
@@ -52,8 +52,8 @@ void transferWithZLP_succeeds() {
5252

5353
@Test
5454
void largeTransfer_succeeds() throws Throwable {
55-
final int numBytes = 230763;
56-
byte[] sampleData = generateRandomBytes(numBytes, 3829007493L);
55+
final var numBytes = 230763;
56+
var sampleData = generateRandomBytes(numBytes, 3829007493L);
5757
var writer = CompletableFuture.runAsync(() -> writeBytes(sampleData));
5858
var reader = CompletableFuture.supplyAsync(() -> readBytes(numBytes));
5959
CompletableFuture.allOf(writer, reader).join();
@@ -63,19 +63,19 @@ void largeTransfer_succeeds() throws Throwable {
6363
}
6464

6565
static void writeBytes(byte[] data) {
66-
final int chunkSize = 100;
67-
int numBytes = 0;
66+
final var chunkSize = 100;
67+
var numBytes = 0;
6868
while (numBytes < data.length) {
69-
int size = Math.min(chunkSize, data.length - numBytes);
69+
var size = Math.min(chunkSize, data.length - numBytes);
7070
testDevice.transferOut(LOOPBACK_EP_OUT, Arrays.copyOfRange(data, numBytes, numBytes + size));
7171
numBytes += size;
7272
}
7373
}
7474
static byte[] readBytes(int numBytes) {
7575
var buffer = new ByteArrayOutputStream();
76-
int bytesRead = 0;
76+
var bytesRead = 0;
7777
while (bytesRead < numBytes) {
78-
byte[] data = testDevice.transferIn(LOOPBACK_EP_IN);
78+
var data = testDevice.transferIn(LOOPBACK_EP_IN);
7979
buffer.writeBytes(data);
8080
bytesRead += data.length;
8181
}

java-does-usb/src/test/java/net/codecrete/usb/DescriptionTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ void deviceInfo_isCorrect() {
3636
assertEquals(0x00, testDevice.protocolCode());
3737
}
3838

39-
boolean isComposite = isCompositeDevce();
39+
var isComposite = isCompositeDevce();
4040

4141
assertEquals(2, testDevice.usbVersion().major());
4242
assertEquals(isComposite ? 1 : 0, testDevice.usbVersion().minor());
@@ -132,9 +132,9 @@ void endpointDescriptors_areCorrect() {
132132

133133
@Test
134134
void configurationDescription_isAvailable() {
135-
int expectedLength = isLoopbackDevice() ? 69 : 98;
135+
var expectedLength = isLoopbackDevice() ? 69 : 98;
136136

137-
byte[] configDesc = testDevice.configurationDescriptor();
137+
var configDesc = testDevice.configurationDescriptor();
138138
assertNotNull(configDesc);
139139
assertEquals(expectedLength, configDesc.length);
140140
assertEquals(2, configDesc[1]);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package net.codecrete.usb;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.assertEquals;
6+
import static org.junit.jupiter.api.Assertions.assertTrue;
7+
8+
class DescriptorTest extends TestDeviceBase {
9+
10+
@Test
11+
void deviceDescriptor_isAvailable() {
12+
var desc = testDevice.deviceDescriptor();
13+
assertEquals(18, desc.length);
14+
assertEquals(0x01, desc[1]);
15+
}
16+
17+
@Test
18+
void configurationDescriptor_isAvailable() {
19+
var desc = testDevice.configurationDescriptor();
20+
assertTrue(desc.length > 60);
21+
assertEquals(0x02, desc[1]);
22+
}
23+
}

0 commit comments

Comments
 (0)