1616import net .codecrete .usb .common .USBInterfaceImpl ;
1717import net .codecrete .usb .linux .gen .fcntl .fcntl ;
1818import net .codecrete .usb .linux .gen .unistd .unistd ;
19- import net .codecrete .usb .linux .gen .usbdevice_fs .usbdevfs_ctrltransfer ;
2019import net .codecrete .usb .linux .gen .usbdevice_fs .usbdevfs_setinterface ;
2120import net .codecrete .usb .usbstandard .DeviceDescriptor ;
21+ import net .codecrete .usb .usbstandard .SetupPacket ;
2222
2323import java .io .IOException ;
2424import java .io .InputStream ;
@@ -165,71 +165,74 @@ public synchronized void releaseInterface(int interfaceNumber) {
165165 }
166166 }
167167
168- private MemorySegment createCtrlTransfer (Arena arena , USBDirection direction , USBControlTransfer setup ,
169- MemorySegment data ) {
170- var ctrlTransfer = arena .allocate (usbdevfs_ctrltransfer .$LAYOUT ());
171- var bmRequest =
172- (direction == USBDirection .IN ? 0x80 : 0 ) | (setup .requestType ().ordinal () << 5 ) | setup .recipient ().ordinal ();
173- usbdevfs_ctrltransfer .bRequestType$set (ctrlTransfer , (byte ) bmRequest );
174- usbdevfs_ctrltransfer .bRequest$set (ctrlTransfer , (byte ) setup .request ());
175- usbdevfs_ctrltransfer .wValue$set (ctrlTransfer , (short ) setup .value ());
176- usbdevfs_ctrltransfer .wIndex$set (ctrlTransfer , (short ) setup .index ());
177- usbdevfs_ctrltransfer .wLength$set (ctrlTransfer , (short ) data .byteSize ());
178- usbdevfs_ctrltransfer .data$set (ctrlTransfer , data );
179- return ctrlTransfer ;
180- }
181-
182168 @ Override
183- public byte [] controlTransferIn (USBControlTransfer setup , int length ) {
169+ public void controlTransferOut (USBControlTransfer setup , byte [] data ) {
184170 try (var arena = Arena .openConfined ()) {
185- var data = arena .allocate (length );
186- var ctrlTransfer = createCtrlTransfer (arena , USBDirection .IN , setup , data );
187-
188- var errnoState = arena .allocate (Linux .ERRNO_STATE .layout ());
189- int res = IO .ioctl (fd , USBDevFS .CONTROL , ctrlTransfer , errnoState );
190- if (res < 0 )
191- throwLastError (errnoState , "Control IN transfer failed" );
171+ int dataLength = data != null ? data .length : 0 ;
172+ var transfer = createSyncCtrlTransfer (arena , USBDirection .OUT , setup , dataLength );
173+ if (dataLength != 0 )
174+ transfer .data .asSlice (8 ).copyFrom (MemorySegment .ofArray (data ));
192175
193- return data .asSlice (0 , res ).toArray (JAVA_BYTE );
176+ synchronized (transfer ) {
177+ submitTransfer (USBDirection .OUT , 0 , transfer );
178+ waitForTransfer (transfer , 0 , USBDirection .OUT , 0 );
179+ }
194180 }
195181 }
196182
197183 @ Override
198- public void controlTransferOut (USBControlTransfer setup , byte [] data ) {
184+ public byte [] controlTransferIn (USBControlTransfer setup , int length ) {
199185 try (var arena = Arena .openConfined ()) {
200- int dataLength = data != null ? data .length : 0 ;
201- var buffer = arena .allocate (dataLength );
202- if (dataLength != 0 )
203- buffer .copyFrom (MemorySegment .ofArray (data ));
204- var ctrlTransfer = createCtrlTransfer (arena , USBDirection .OUT , setup , buffer );
186+ var transfer = createSyncCtrlTransfer (arena , USBDirection .IN , setup , length );
205187
206- var errnoState = arena .allocate (Linux .ERRNO_STATE .layout ());
207- int res = IO .ioctl (fd , USBDevFS .CONTROL , ctrlTransfer , errnoState );
208- if (res < 0 )
209- throwLastError (errnoState , "Control OUT transfer failed" );
188+ synchronized (transfer ) {
189+ submitTransfer (USBDirection .IN , 0 , transfer );
190+ waitForTransfer (transfer , 0 , USBDirection .IN , 0 );
191+ }
192+
193+ return transfer .data .asSlice (8 , transfer .resultSize ).toArray (JAVA_BYTE );
210194 }
211195 }
212196
213- private LinuxTransfer createSyncTransfer (MemorySegment data ) {
197+ /**
198+ * Create transfer object for synchronous control request.
199+ *
200+ * @param arena arena for allocating memory
201+ * @param direction direction
202+ * @param setup setup data
203+ * @param dataLength data length (in addition to setup data)
204+ * @return transfer object
205+ */
206+ private LinuxTransfer createSyncCtrlTransfer (Arena arena , USBDirection direction , USBControlTransfer setup ,
207+ int dataLength ) {
208+ var bmRequest =
209+ (direction == USBDirection .IN ? 0x80 : 0 ) | (setup .requestType ().ordinal () << 5 ) | setup .recipient ().ordinal ();
210+ var buffer = arena .allocate (8 + dataLength , 8 );
211+ var setupPacket = new SetupPacket (buffer );
212+ setupPacket .setRequestType (bmRequest );
213+ setupPacket .setRequest (setup .request ());
214+ setupPacket .setValue (setup .value ());
215+ setupPacket .setIndex (setup .index ());
216+ setupPacket .setLength (dataLength );
217+
214218 var transfer = new LinuxTransfer ();
215- transfer .data = data ;
216- transfer .dataSize = (int ) data .byteSize ();
219+ transfer .data = buffer ;
220+ transfer .dataSize = (int ) buffer .byteSize ();
217221 transfer .resultSize = -1 ;
218222 transfer .completion = USBDeviceImpl ::onSyncTransferCompleted ;
223+
219224 return transfer ;
220225 }
221226
222227 @ Override
223228 public void transferOut (int endpointNumber , byte [] data , int timeout ) {
224- var endpoint = getEndpoint (USBDirection .OUT , endpointNumber , USBTransferType .BULK , USBTransferType .INTERRUPT );
225-
226229 try (var arena = Arena .openConfined ()) {
227230 var buffer = arena .allocate (data .length );
228231 buffer .copyFrom (MemorySegment .ofArray (data ));
229232 var transfer = createSyncTransfer (buffer );
230233
231234 synchronized (transfer ) {
232- asyncTask . submitBulkTransfer ( this , endpoint . endpointAddress () , transfer );
235+ submitTransfer ( USBDirection . OUT , endpointNumber , transfer );
233236 waitForTransfer (transfer , timeout , USBDirection .OUT , endpointNumber );
234237 }
235238 }
@@ -244,14 +247,32 @@ public byte[] transferIn(int endpointNumber, int timeout) {
244247 var transfer = createSyncTransfer (buffer );
245248
246249 synchronized (transfer ) {
247- asyncTask . submitBulkTransfer ( this , endpoint . endpointAddress () , transfer );
250+ submitTransfer ( USBDirection . IN , endpointNumber , transfer );
248251 waitForTransfer (transfer , timeout , USBDirection .IN , endpointNumber );
249252 }
250253
251254 return buffer .asSlice (0 , transfer .resultSize ).toArray (JAVA_BYTE );
252255 }
253256 }
254257
258+ private LinuxTransfer createSyncTransfer (MemorySegment data ) {
259+ var transfer = new LinuxTransfer ();
260+ transfer .data = data ;
261+ transfer .dataSize = (int ) data .byteSize ();
262+ transfer .resultSize = -1 ;
263+ transfer .completion = USBDeviceImpl ::onSyncTransferCompleted ;
264+ return transfer ;
265+ }
266+
267+ synchronized void submitTransfer (USBDirection direction , int endpointNumber , LinuxTransfer transfer ) {
268+ if (endpointNumber != 0 ) {
269+ var endpoint = getEndpoint (direction , endpointNumber , USBTransferType .BULK , USBTransferType .INTERRUPT );
270+ asyncTask .submitTransfer (this , endpoint .endpointAddress (), endpoint .transferType (), transfer );
271+ } else {
272+ asyncTask .submitTransfer (this , 0 , USBTransferType .CONTROL , transfer );
273+ }
274+ }
275+
255276 @ Override
256277 protected Transfer createTransfer () {
257278 return new LinuxTransfer ();
@@ -297,9 +318,4 @@ public OutputStream openOutputStream(int endpointNumber) {
297318
298319 return new LinuxEndpointOutputStream (this , endpointNumber );
299320 }
300-
301- synchronized void submitBulkTransfer (USBDirection direction , int endpointNumber , LinuxTransfer transfer ) {
302- var endpoint = getEndpoint (direction , endpointNumber , USBTransferType .BULK , null );
303- asyncTask .submitBulkTransfer (this , endpoint .endpointAddress (), transfer );
304- }
305321}
0 commit comments