
net.codecrete.usb.UsbDevice Maven / Gradle / Ivy
//
// Java Does USB
// Copyright (c) 2022 Manuel Bleichenbacher
// Licensed under MIT License
// https://opensource.org/licenses/MIT
//
package net.codecrete.usb;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
/**
* USB device.
*
* In order to make control requests and transfer data, the device must be
* opened and an interface must be claimed. In the open state, this current
* process has exclusive access to the device.
*
*
* Information about the device can be queried in both the open and the
* closed state.
*
*/
public interface UsbDevice {
/**
* USB product ID.
*
* @return product ID
*/
int getProductId();
/**
* USB vendor ID.
*
* @return vendor ID
*/
int getVendorId();
/**
* Product name.
*
* @return product name or {@code null} if not provided by the device
*/
String getProduct();
/**
* Manufacturer name
*
* @return manufacturer name or {@code null} if not provided by the device
*/
String getManufacturer();
/**
* Serial number
*
* Even though this is supposed to be a human-readable string,
* some devices are known to provide binary data.
*
*
* @return serial number or {@code null} if not provided by the device
*/
String getSerialNumber();
/**
* USB device class code ({@code bDeviceClass} from device descriptor).
*
* @return class code
*/
int getClassCode();
/**
* USB device subclass code ({@code bDeviceSubClass} from device descriptor).
*
* @return subclass code
*/
int getSubclassCode();
/**
* USB device protocol ({@code bDeviceProtocol} from device descriptor).
*
* @return protocol code
*/
int getProtocolCode();
/**
* USB protocol version supported by this device.
*
* @return version
*/
@NotNull Version getUsbVersion();
/**
* Device version (as declared by the manufacturer).
*
* @return version
*/
@NotNull Version getDeviceVersion();
/**
* Detaches the standard operating-system drivers of this device.
*
* By detaching the standard drivers, the operating system releases the exclusive access to the device
* and/or some or all of the device's interfaces. This allows the application to open the device and claim
* interfaces. It is relevant for device and interfaces implementing standard USB classes, such as HID, CDC
* and mass storage.
*
*
* This method should be called before the device is opened. After the device has been closed,
* {@link #attachStandardDrivers()} should be called to restore the previous state.
*
*
* On macOS, all device drivers are immediately detached from the device. To execute it, the application must
* be run as root. Without root privileges, the method does nothing.
*
*
* On Linux, this method changes the behavior of {@link #claimInterface(int)} for this device. The standard drivers
* will be detached interface by interface when the interface is claimed.
*
*
* On Windows, this method does nothing. It is not possible to temporarily change the drivers.
*
*/
void detachStandardDrivers();
/**
* Reattaches the standard operating-system drivers to this device.
*
* By attaching the standard drivers, the operating system claims the device and/or its interfaces if they
* implement standard USB classes, such as HID, CDC and mass storage. It is used to restore the state before
* calling {@link #detachStandardDrivers()}.
*
*
* This method should be called after the device has been closed.
*
*
* On macOS, the application must be run as root. Without root privileges, the method does nothing.
*
*
* On Linux, this method changes the behavior of {@link #claimInterface(int)}. Standard drivers will no longer be
* detached when the interface is claimed. Standard drivers are automatically reattached when the interfaces
* are released, at the lasted when the device is closed.
*
*
* On Windows, this method does nothing.
*
*/
void attachStandardDrivers();
/**
* Indicates if the device is connected.
*
* When a {@link UsbDevice} instance is initially returned by {@link Usb#getDevices()} and related methods,
* it is connected. When the user unplugs the device, the application can still hold on to instance of
* {@link UsbDevice} even though the actual USB device is gone. This method can be used to check if the
* device is still connected.
*
* @return {@code true} if the device is connected, {@code false} if it is no longer connected
*/
boolean isConnected();
/**
* Opens the device for communication.
*/
void open();
/**
* Indicates if the device is open.
*
* @return {@code true} if the device is open, {@code false} if it is closed.
*/
boolean isOpened();
/**
* Closes the device.
*/
void close();
/**
* Gets the interfaces of this device.
*
* The returned list is sorted by interface number.
*
*
* @return a list of USB interfaces
*/
@NotNull @Unmodifiable List getInterfaces();
/**
* Gets the interface with the specified number.
*
* @param interfaceNumber the interface number
* @return the interface
* @exception UsbException if the interface does not exist
*/
@NotNull UsbInterface getInterface(int interfaceNumber);
/**
* Gets the endpoint with the specified number.
*
* @param direction the endpoint direction
* @param endpointNumber the endpoint number (between 1 and 127)
* @return the endpoint
* @exception UsbException if the endpoint does not exist
*/
@NotNull UsbEndpoint getEndpoint(UsbDirection direction, int endpointNumber);
/**
* Claims the specified interface for exclusive use.
*
* @param interfaceNumber the interface number
*/
void claimInterface(int interfaceNumber);
/**
* Selects the alternate settings for the specified interface.
*
* The device must be open and the interface must be claimed for exclusive access.
*
*
* @param interfaceNumber interface number
* @param alternateNumber alternate setting number
*/
void selectAlternateSetting(int interfaceNumber, int alternateNumber);
/**
* Releases the specified interface from exclusive use.
*
* @param interfaceNumber the interface number
*/
void releaseInterface(int interfaceNumber);
/**
* Requests data from the control endpoint.
*
* This method blocks until the device has responded or an error has occurred.
*
*
* The control transfer request is sent to endpoint 0. The transfer is expected to
* have a Data In stage.
*
*
* Requests with an interface or an endpoint as recipient are expected to
* have the interface and endpoint number, respectively, in the lower byte of
* {@code wIndex}. This convention is enforced by Windows. The addressed interface
* or the interface of the addressed endpoint must have been claimed.
*
*
* @param transfer control transfer setup parameters
* @param length maximum length of expected data
* @return received data.
*/
byte @NotNull [] controlTransferIn(@NotNull UsbControlTransfer transfer, int length);
/**
* Executes a control transfer request and optionally sends data.
*
* This method blocks until the device has acknowledge the request or an error has occurred.
*
*
* The control transfer request is sent to endpoint 0. The transfer is expected to either have
* no data stage or a Data Out stage.
*
*
* Requests with an interface or an endpoint as recipient are expected to
* have the interface and endpoint number, respectively, in the lower byte of
* {@code wIndex}. This convention is enforced by Windows. The addressed interface
* or the interface of the addressed endpoint must have been claimed.
*
*
* @param transfer control transfer setup parameters
* @param data data to send, or {@code null} if the transfer has no data stage.
*/
void controlTransferOut(@NotNull UsbControlTransfer transfer, byte[] data);
/**
* Sends data to this device.
*
* This method blocks until the data has been sent or an error has occurred.
*
*
* This method can send data to bulk and interrupt endpoints.
*
*
* If the sent data length is a multiple of the packet size, it is often
* required to send an additional zero-length packet (ZLP) for the device
* to actually process the data. This method will not do it automatically.
*
*
* @param endpointNumber endpoint number (in the range between 1 and 127)
* @param data data to send
*/
void transferOut(int endpointNumber, byte @NotNull [] data);
/**
* Sends data to this device.
*
* This method blocks until the data has been sent, the timeout period has expired
* or an error has occurred. If the timeout expires, a {@link UsbTimeoutException} is thrown.
*
*
* This method can send data to bulk and interrupt endpoints.
*
*
* If the sent data length is a multiple of the packet size, it is often
* required to send an additional zero-length packet (ZLP) for the device
* to actually process the data. This method will not do it automatically.
*
*
* @param endpointNumber the endpoint number (in the range between 1 and 127)
* @param data data to send
* @param timeout the timeout period, in milliseconds (0 for no timeout)
*/
void transferOut(int endpointNumber, byte @NotNull [] data, int timeout);
/**
* Sends data to this device.
*
* This method blocks until the data has been sent, the timeout period has expired
* or an error has occurred. If the timeout expires, a {@link UsbTimeoutException} is thrown.
*
*
* This method can send data to bulk and interrupt endpoints.
*
*
* If the sent data length is a multiple of the packet size, it is often
* required to send an additional zero-length packet (ZLP) for the device
* to actually process the data. This method will not do it automatically.
*
*
* @param endpointNumber the endpoint number (in the range between 1 and 127)
* @param data buffer containing data to send
* @param offset offset of the first byte to send
* @param length number of bytes to send
* @param timeout the timeout period, in milliseconds (0 for no timeout)
*/
void transferOut(int endpointNumber, byte @NotNull [] data, int offset, int length, int timeout);
/**
* Receives data from this device.
*
* This method blocks until at least a packet has been received or an error has occurred.
*
*
* The returned data is the payload of a packet. It can have a length of 0 if the USB device
* sends zero-length packets to indicate the end of a data unit.
*
*
* This method can receive data from bulk and interrupt endpoints.
*
*
* @param endpointNumber endpoint number (in the range between 1 and 127, i.e. without the direction bit)
* @return received data
*/
byte @NotNull [] transferIn(int endpointNumber);
/**
* Receives data from this device.
*
* This method blocks until at least a packet has been received, the timeout period has expired
* or an error has occurred. If the timeout expired, a {@link UsbTimeoutException} is thrown.
*
*
* The returned data is the payload of a packet. It can have a length of 0 if the USB device
* sends zero-length packets to indicate the end of a data unit.
*
*
* This method can receive data from bulk and interrupt endpoints.
*
*
* @param endpointNumber the endpoint number (in the range between 1 and 127, i.e. without the direction bit)
* @param timeout the timeout period, in milliseconds (0 for no timeout)
* @return received data
*/
byte @NotNull [] transferIn(int endpointNumber, int timeout);
/**
* Opens a new output stream to send data to a bulk endpoint.
*
* All data written to this output stream is sent to the specified bulk endpoint.
* Buffering and concurrent IO requests are used to achieve a high throughput.
*
*
* The stream will insert zero-length packets if {@link OutputStream#flush()} is called
* and the last packet size was equal to maximum packet size of the endpoint.
*
*
* If {@link #transferOut(int, byte[])} and a output stream or multiple output streams
* are used concurrently for the same endpoint, the behavior is unpredictable.
*
*
* @param endpointNumber bulk endpoint number (in the range between 1 and 127)
* @param bufferSize approximate buffer size (in bytes)
* @return the new output stream
*/
@NotNull OutputStream openOutputStream(int endpointNumber, int bufferSize);
/**
* Opens a new output stream to send data to a bulk endpoint.
*
* The buffer is configured with minimal size. In all other aspects, this method
* works like {@link #openOutputStream(int, int)}.
*
* @param endpointNumber bulk endpoint number (in the range between 1 and 127)
* @return the new output stream
*/
default @NotNull OutputStream openOutputStream(int endpointNumber) {
return openOutputStream(endpointNumber, 1);
}
/**
* Opens a new input stream to receive data from a bulk endpoint.
*
* All data received from the specified bulk endpoint can be read using this input stream.
* Buffering and concurrent IO requests are used to achieve a high throughput.
*
*
* If the buffers contain data when the stream is closed, this data will be discarded.
* If {@link #transferIn(int)} and an input stream or multiple input streams
* are used concurrently for the same endpoint, the behavior is unpredictable.
*
*
* @param endpointNumber bulk endpoint number (in the range between 1 and 127, i.e. without the direction bit)
* @param bufferSize approximate buffer size (in bytes)
* @return the new input stream
*/
@NotNull InputStream openInputStream(int endpointNumber, int bufferSize);
/**
* Opens a new input stream to receive data from a bulk endpoint.
*
* The buffer is configured with minimal size. In all other aspects, this method
* works like {@link #openInputStream(int, int)}.
*
*
* @param endpointNumber bulk endpoint number (in the range between 1 and 127, i.e. without the direction bit)
* @return the new input stream
*/
default @NotNull InputStream openInputStream(int endpointNumber) {
return openInputStream(endpointNumber, 1);
}
/**
* Aborts all transfers on an endpoint.
*
* This operation is not valid on the control endpoint 0.
*
*
* @param direction endpoint direction
* @param endpointNumber endpoint number (in the range between 1 and 127)
*/
void abortTransfers(UsbDirection direction, int endpointNumber);
/**
* Clears an endpoint's halt condition.
*
* An endpoint is halted (aka stalled) if an error occurs in the communication. Before the
* communication can resume, the halt condition must be cleared. A halt condition can exist
* in a single direction only.
*
*
* Control endpoint 0 will never be halted.
*
*
* @param direction endpoint direction
* @param endpointNumber endpoint number (in the range between 1 and 127)
*/
void clearHalt(UsbDirection direction, int endpointNumber);
/**
* Gets the device descriptor.
*
* @return the device descriptor (as a byte array)
*/
byte @NotNull [] getDeviceDescriptor();
/**
* Gets the configuration descriptor.
*
* @return the configuration descriptor (as a byte array)
*/
byte @NotNull [] getConfigurationDescriptor();
}