The absolute last piece where you finally get to send some non-control data is the USB pipe. This is represented by an instance of the UsbPipe interface. The getUsbPipe( ) method in UsbEndpoint returns the single pipe associated with that endpoint:
public UsbPipe getUsbPipe( )
USB I/O is packet-based like UDP, not stream-based like TCP. You do not get an InputStream or an OutputStream from a pipe. Instead, you send or receive IRPs. In Java, IRPs are represented by the javax.usb.UsbIrp class. This is a wrapper around a byte array containing the actual data sent to or received from the device.
You cannot send arbitrarily large byte arrays to a device. A low-speed device can accept at most eight bytes in each packet. A full-speed device can accept up to 1,023 bytes. A high-speed device can accept up to 1,024 bytes per packet.
This can be further restricted depending on the type of transfer: low-speed control transfers always use 8-byte packets; high-speed control transfers use 8-, 16-, 32-, or 64-byte packets; and full-speed control transfers always use 64-byte packets.
Writing to an output pipe to move data from the host to the device follows these steps:
Open the pipe by calling the open( ) method.
Stuff a data array into a UsbIrp.
Send the IRP down the pipe, either synchronously with syncSubmit( ) or asynchronously with asyncSubmit( ).
Close the pipe with the close( ) method.
Steps 2 and 3 may be repeated as many times as desired.
Reading from an input pipe to collect data from the device for the host follows these steps:
Open the pipe by calling the open( ) method.
Create a new empty UsbIrp to hold data received from the device.
Put an IRP on the pipe to receive the data from the device either synchronously with syncSubmit( ) or asynchronously with asyncSubmit( ).
Read the data out of the IRP you created in step 2.
Close the pipe with the close( ) method.
Steps 2 through 4 can be repeated as many times as necessary. A completed IRP can be reused provided you call setComplete(false) on each IRP before you resubmit it.
Before you can write to a pipe, you must open it by invoking the open( ) method:
public void open( ) throws UsbException, UsbNotActiveException, UsbNotClaimedException, UsbDisconnectedException
The interface the pipe belongs to must be both active and claimed. Otherwise, this method throws a UsbNotActiveException or a UsbNotClaimedException, respectively.
You send the IRPs to the device either synchronously (blocking) or asynchronously (nonblocking):
public void syncSubmit(UsbIrp irp) throws UsbException, UsbNotActiveException, IllegalArgumentException, UsbDisconnectedException public void asyncSubmit(UsbIrp irp) throws UsbException, UsbNotActiveException, UsbNotOpenException, IllegalArgumentException, UsbDisconnectedException
You can also submit a list of IRPs to be used in sequence:
public void syncSubmit(List list) throws UsbException, UsbNotActiveException, UsbNotOpenException, IllegalArgumentException, UsbDisconnectedException public void asyncSubmit(List list) throws UsbException, UsbNotSctiveException, UsbNotOpenException, IllegalArgumentException, UsbDisconnectedException
|
Finally, you can just submit the data array and let the pipe build the IRP for you. This is probably the simplest approach:
public void syncSubmit(byte[] data) throws UsbException, UsbNotActiveException, UsbNotOpenException, IllegalArgumentException, UsbDisconnectedException public void asyncSubmit(byte[] data) throws UsbException, UsbNotActiveException, UsbNotOpenException, IllegalArgumentException, UsbDisconnectedException
However, this does not give you all the options working with an actual UsbIrp object does.
All six variants throw a UsbNotOpenException if the pipe has not yet been opened. All six throw an IllegalArgumentException if the IRP or list of IRPs is not properly prepared for the pipe.
When you e finished with a pipe you should close it. This takes three steps:
Cancel all pending submissions.
Close the pipe.
Release the interface you claimed.
For example:
pipe.abortAllSubmissions( ); pipe.close( ); theInterface.release( );
It seems to be necessary to call abortAllSubmissions( ) even if you don have any pending submissions. Im not sure why, but when I skipped this step, I always got a UsbException with the message "Cannot close pipe with pending submissions."