Controlling Devices
Data is written to and read from USB devices in IRPs. More complex devices send IRPs in either bulk transfer, isochronous, or interrupt mode. However, the simplest low-speed devices operate with just the control channel and send a special kind of control IRP. Before we delve into the details of talking over other kinds of channels, lets go over preparing and submitting IRPs over the control channel.
Four methods in the UsbDevice send control IRPs to a device:
public void syncSubmit(UsbControlIrp irp) throws UsbException, IllegalArgumentException, UsbDisconnectedException public void asyncSubmit(UsbControlIrp irp) throws UsbException, IllegalArgumentException, UsbDisconnectedException public void syncSubmit(List list) throws UsbException, IllegalArgumentException, UsbDisconnectedException public void asyncSubmit(List list) throws UsbException, IllegalArgumentException, UsbDisconnectedException
The choice of method depends on whether you want to send the IRPs in blocking or nonblocking mode, and how many you want to send. The syncSubmit( ) methods submit the IRPs and wait for the device to respond. The asyncSubmit( ) methods submit the IRPs and return immediately. You can submit either one IRP at a time, or a list of IRPs to be used in sequence.
Each IRP has a header and a data buffer. In Java, the data buffer appears to be a byte array. If you e writing to the device, youll set the header, put the information you want to send in the IRPs data buffer, and submit it. If you e reading data from the device, youll set the header, put an empty array in the data buffer, submit a packet, wait for the device to put some data in the buffer, and then read the values out of the array.
These methods each throw a UsbDisconnectedException if the device you e sending to has been removed from the bus. This is a runtime exception, so you don have to catch it, but you probably should anyway since its an external condition beyond the control of your program.
These methods can all throw a UsbException if the bus is having trouble and can respond quickly or correctly. This can be caused by a misbehaving device, an overloaded bus without enough bandwidth for all the connected devices, an underpowered bus, or any of several other reasons. This is a checked exception, so you have to catch it or declare that you throw it. These methods also throw an IllegalArgumentException if you pass a malformed IRP to one of them.
For each control IRP you must provide five pieces of information:
bmRequestType
-
A 1-byte bitmap that classifies the request as follows:
- Bit 7 is the direction of the packet: 0 for host to device, 1 for device to host.
- Bits 5-6 are a 2-bit little-endian int that specifies the type of the control packet: 0 for standard, 1 for class, and 2 for vendor (3 is unused at the current time).
- Bits 0-4 are a 5-bit int indicating the recipient for which the packet is intended: 0 is a device, 1 is an interface, 2 is an endpoint, 3 is "other," and all other values are reserved. (Well get to devices, interfaces, and endpoints shortly.)
bRequest
A 1-byte request code. The USB spec outlines standard request codesfor instance, the value 3 sets a featureas well as device-specific request codes. For example, in HID devices, request code 2 means get the idle rate and request code 3 means set the idle rate. (The idle rate is the amount of time that the device waits before repeating data if nothing has changed.)
wValue
A 2-byte little-endian short whose meaning depends on the request.
wIndex
Also a 2-byte little-endian short whose meaning depends on the request. However, this one points to the actual data found elsewhere in the packet.
data
A byte array containing the content of this request (output) or a buffer into which the device places its response (input). You can also set an offset and a length to select a slice of this array.
IRPs sent over the control channel are represented by instances of the UsbControlIrp interface. You can implement this interface yourself if you like, or you can construct an instance of the javax.usb.util.DefaultUsbControlIrp class, but its normally simplest to ask the UsbDevice to create a control IRP for you with its createUsbControlIrp( ) method. This factory method requires you to specify the first four values:
public UsbControlIrp createUsbControlIrp(byte bmRequestType, byte bRequest, short wValue, short wIndex)
The data array is then supplied using the setData( ) methods inherited from the superinterface, UsbIrp. If you e sending data to the device, youll put the data in the array before setting it. If you e reading data from the device, youll put an empty array in the device and then read the data the device put in the IRP from that same array.
Категории |