Improve documentation
This commit is contained in:
parent
c84c5fad92
commit
6a5da7a004
@ -1,206 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
Quick start
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Quick start
|
||||
|
||||
* Choose an API
|
||||
|
||||
usb4java provides two different APIs you can work with:
|
||||
|
||||
* The low-level (libusb) API
|
||||
|
||||
* The high-level (javax.usb) API
|
||||
|
||||
[]
|
||||
|
||||
The high-level API simply implements the
|
||||
{{{http://javax-usb.sourceforge.net/}javax.usb (JSR80) API}}. One advantage
|
||||
of this API is that it is implementation-independent. So it is easy to
|
||||
switch to a different javax.usb implementation later without changing your
|
||||
code. Another advantage is that this API is object oriented and is much
|
||||
easier to use for Java developers. The disadvantage is that the javax.usb
|
||||
project is pretty old and currently looks inactive, maybe even dead.
|
||||
|
||||
The low-level API closely follows the C API of the
|
||||
{{{http://libusb.info/}libusb}} project. This API has the advantage that it
|
||||
provides the same functionality as libusb does. And if you know the C API of
|
||||
libusb then you will most likely feel right at home when using this API
|
||||
with usb4java. The disadvantage is that you will have a hard time changing
|
||||
your code when you later switch to a different Java USB library.
|
||||
|
||||
* The low-level (libusb) API
|
||||
|
||||
** API design
|
||||
|
||||
The low-level API of usb4java closely follows the C API of the
|
||||
{{{http://libusb.info/}libusb}} project. All global functions and
|
||||
constants of <libusb> are defined as static members of the class
|
||||
{{{./apidocs/org/usb4java/LibUsb.html}org.usb4java.LibUsb}}.
|
||||
All structures of <libusb> are defined in separate classes which are named
|
||||
similar to the original struct names but without underscores, with upper
|
||||
case names and with the <libusb> prefix removed. For example the struct
|
||||
<libusb_device_handle> is defined in the class
|
||||
{{{./apidocs/org/usb4java/DeviceHandle.html}DeviceHandle}}. Struct
|
||||
members are represented by static methods in the corresponding class.
|
||||
|
||||
The following notable differences exists between the <libusb 1.0 API> and
|
||||
the <usb4java> API:
|
||||
|
||||
* <interface> in the configuration descriptor is named <iface> because
|
||||
<interface> is a reserved word in Java.
|
||||
|
||||
* <MaxPower> in the configuration descriptor is named <bMaxPower> to
|
||||
be compatible to the USB specification and because method names starting
|
||||
with upper-case letters are quite unusual in Java.
|
||||
|
||||
* Whenever libusb expects a byte pointer and a length you have to use
|
||||
a direct Java NIO ByteBuffer instead.
|
||||
|
||||
* Methods which are returning a string through a byte buffer which was
|
||||
passed as argument have additional simplified overloaded method
|
||||
equivalents which are returning a Java String directly.
|
||||
|
||||
[]
|
||||
|
||||
** Initialization/deinitialization
|
||||
|
||||
Before using any usb4java functionality you must initialize libusb:
|
||||
|
||||
----
|
||||
final Context context = new Context();
|
||||
int result = LibUsb.init(context);
|
||||
if (result < 0) throw new RuntimeException("Unable to initialize libusb. Result=" + result);
|
||||
----
|
||||
|
||||
Specifiying a context is optional. If your application only needs a single
|
||||
libusb context then you can specify <null> as context.
|
||||
|
||||
Before your application terminates you should deinitialize libusb:
|
||||
|
||||
----
|
||||
LibUsb.exit(context);
|
||||
----
|
||||
|
||||
|
||||
** Find your device
|
||||
|
||||
Your program most likely wants to communicate with a specific device so first
|
||||
of all you have to find it. You have to get a list of all connected USB
|
||||
devices and then check the vendor/product ids. Here is a method which can
|
||||
be used for this purpose:
|
||||
|
||||
----
|
||||
public Device findDevice(short vendorId, short productId)
|
||||
{
|
||||
// Read the USB device list
|
||||
DeviceList list = new DeviceList();
|
||||
int result = LibUsb.getDeviceList(null, list);
|
||||
if (result < 0) throw new LibUsbException("Unable to get device list", result);
|
||||
|
||||
try
|
||||
{
|
||||
// Iterate over all devices and scan for the right one
|
||||
for (Device device: list)
|
||||
{
|
||||
DeviceDescriptor descriptor = new DeviceDescriptor();
|
||||
result = LibUsb.getDeviceDescriptor(device, descriptor);
|
||||
if (result < 0) throw new LibUsbException("Unable to read device descriptor", result);
|
||||
if (descriptor.idVendor() == vendorId && descriptor.idProduct() == productId) return device;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure the allocated device list is freed
|
||||
LibUsb.freeDeviceList(list, true);
|
||||
}
|
||||
|
||||
// Device not found
|
||||
return null;
|
||||
}
|
||||
----
|
||||
|
||||
In your application it might be a little bit more complicated. Maybe you
|
||||
have more than one device of the same type so you may need a list of devices.
|
||||
Or you have to identify your device by the product or vendor string
|
||||
descriptor instead of just checking the ID (In case you are using a
|
||||
shared vendor/product ID). But this example should bring you on the right
|
||||
track.
|
||||
|
||||
** Device handles
|
||||
|
||||
For the real USB communication you must open a new device handle and you
|
||||
must close it again when you are finished communicating with the device.
|
||||
Example:
|
||||
|
||||
----
|
||||
DeviceHandle handle = new DeviceHandle();
|
||||
int result = LibUsb.open(device, handle);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to open USB device", result);
|
||||
try
|
||||
{
|
||||
// Use device handle here
|
||||
}
|
||||
finally
|
||||
{
|
||||
LibUsb.close(handle);
|
||||
}
|
||||
----
|
||||
|
||||
** Interfaces
|
||||
|
||||
Usually you are communicating with an interface provided by the USB device and
|
||||
you have to claim this interface before using it and you have to release it
|
||||
when you are finished. Example:
|
||||
|
||||
----
|
||||
int result = LibUsb.claimInterface(handle, interfaceNumber);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to claim interface", result);
|
||||
try
|
||||
{
|
||||
// Use interface here
|
||||
}
|
||||
finally
|
||||
{
|
||||
result = LibUsb.releaseInterface(handle, interfaceNumber);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to release interface", result);
|
||||
}
|
||||
----
|
||||
|
||||
** Communication
|
||||
|
||||
For the actual USB communication you usually have to create a direct
|
||||
byte buffer for the data to send or receive. Here is an example which
|
||||
sends 8 bytes to a claimed interface unsing a control transfer:
|
||||
|
||||
----
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(8);
|
||||
buffer.put(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 });
|
||||
int transfered = LibUsb.controlTransfer(handle,
|
||||
(byte) (LibUsb.REQUEST_TYPE_CLASS | LibUsb.RECIPIENT_INTERFACE),
|
||||
(byte) 0x09, (short) 2, (short) 1, buffer, 2500);
|
||||
if (transfered < 0)
|
||||
throw new LibUsbException("Control transfer failed", transfered);
|
||||
if (transfered != message.length)
|
||||
throw new RuntimeException("Not all data was sent to device");
|
||||
----
|
||||
|
||||
You may also want to use
|
||||
{{{./apidocs/org/usb4java/LibUsb.html##bulkTransfer(org.usb4java.DeviceHandle, byte, java.nio.ByteBuffer, java.nio.IntBuffer, long)}bulkTransfer}} or
|
||||
{{{./apidocs/org/usb4java/LibUsb.html##interruptTransfer(org.usb4java.DeviceHandle, byte, java.nio.ByteBuffer, java.nio.IntBuffer, long)}interruptTransfer}}
|
||||
instead of
|
||||
{{{./apidocs/org/usb4java/LibUsb.html##controlTransfer(org.usb4java.DeviceHandle, byte, byte, short, short, java.nio.ByteBuffer, long)}controlTransfer}}
|
||||
|
||||
The parameters needed for the transfer calls are completely
|
||||
device dependent so you have to check the device documentation for details.
|
||||
|
||||
* See also
|
||||
|
||||
* {{{./apidocs/org/usb4java/package-summary.html}API documentation of usb4java}}
|
||||
|
||||
* {{{http://javax-usb.sourceforge.net/jdoc/}javax.usb (JSR80) API documentation}}
|
||||
|
||||
* {{{http://libusb.sourceforge.net/api-1.0/}API documentation of libusb}}
|
||||
|
||||
[]
|
||||
|
||||
37
src/site/apt/quickstart/index.apt
Normal file
37
src/site/apt/quickstart/index.apt
Normal file
@ -0,0 +1,37 @@
|
||||
-----------------------------------------------------------------------------
|
||||
Quick start
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Quick start
|
||||
|
||||
* Choose an API
|
||||
|
||||
usb4java provides two different APIs you can choose from:
|
||||
|
||||
* {{{./libusb.html}The low-level (libusb) API}}
|
||||
|
||||
* {{{./javax-usb.html}The high-level (javax-usb) API}}
|
||||
|
||||
[]
|
||||
|
||||
The low-level API closely follows the C API of the
|
||||
{{{http://libusb.info/}libusb}} project. This API has the advantage that it
|
||||
provides the same functionality as libusb does. And if you know the C API of
|
||||
libusb then you will most likely feel right at home when using this API
|
||||
with usb4java. It is also easy to convert existing C libusb programs into
|
||||
Java. The disadvantage is that you will have a hard time changing
|
||||
your code when you later switch to a different Java USB library. And as a
|
||||
pure Java developer you may dislike the API because it is too low-level (For
|
||||
example most methods return error codes instead of throwing exceptions).
|
||||
|
||||
The high-level API simply implements the
|
||||
{{{http://javax-usb.sourceforge.net/}javax-usb (JSR80) API}}. One advantage
|
||||
of this API is that it is implementation-independent. So it is easy to
|
||||
switch to a different javax-usb implementation later without changing your
|
||||
code. Another advantage is that this API is object oriented and is much
|
||||
easier to use for Java developers. The disadvantage is that the javax-usb
|
||||
specification is pretty old and may lack support for some newer USB
|
||||
techniques provided by the low-level API.
|
||||
|
||||
|
||||
|
||||
188
src/site/apt/quickstart/javax-usb.apt
Normal file
188
src/site/apt/quickstart/javax-usb.apt
Normal file
@ -0,0 +1,188 @@
|
||||
-----------------------------------------------------------------------------
|
||||
High-level (javax-usb) API
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
High-level (javax-usb) API
|
||||
|
||||
The high-level API implements the
|
||||
{{{http://javax-usb.sourceforge.net/}javax-usb (JSR-80)}} standard. This API
|
||||
is object-oriented, event-driven and uses exceptions for error-handling
|
||||
instead of negative return values like the low-level API. Another advantage
|
||||
is that you may switch to a different <javax-usb> implementation later
|
||||
without changing your code. For example instead of using <usb4java> you may
|
||||
try out the reference implementation for Linux and Windows.
|
||||
|
||||
|
||||
* Configuration
|
||||
|
||||
To use the <usb4java> implementation you have to create a file named
|
||||
<{{{./configuration.html}javax.usb.properties}}> in the root of your class
|
||||
path with the following content:
|
||||
|
||||
+-----------------------------------------------------------------------------+
|
||||
javax.usb.services = org.usb4java.javax.Services
|
||||
+-----------------------------------------------------------------------------+
|
||||
|
||||
|
||||
* Finding USB devices
|
||||
|
||||
USB devices are managed in a tree. The root of this tree is a virtual
|
||||
USB hub to which all physical root hubs are connected. More hubs can be
|
||||
connected to these root hubs and any hub can have a number of connected
|
||||
USB devices.
|
||||
|
||||
Often you need to search for a specific device before working with it. Here
|
||||
is an example how to scan the device tree for the first device with a
|
||||
specific vendor and product id. It can be easily expanded to check for
|
||||
specific device classes or whatever:
|
||||
|
||||
+-----------------------------------------------------------------------------+
|
||||
public UsbDevice findDevice(UsbHub hub, short vendorId, short productId)
|
||||
{
|
||||
for (UsbDevice device : (List<UsbDevice>) hub.getAttachedUsbDevices())
|
||||
{
|
||||
UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();
|
||||
if (desc.idVendor() == vendorId && desc.idProduct() == productId) return device;
|
||||
if (device.isUsbHub())
|
||||
{
|
||||
device = findDevice((UsbHub) device, vendorId, productId);
|
||||
if (device != null) return device;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
+-----------------------------------------------------------------------------+
|
||||
|
||||
|
||||
* Control requests
|
||||
|
||||
This example reads the current configuration number from a device by
|
||||
using a control request:
|
||||
|
||||
+-----------------------------------------------------------------------------+
|
||||
UsbControlIrp irp = device.createUsbControlIrp(
|
||||
(byte) (UsbConst.REQUESTTYPE_DIRECTION_IN
|
||||
| UsbConst.REQUESTTYPE_TYPE_STANDARD
|
||||
| UsbConst.REQUESTTYPE_RECIPIENT_DEVICE),
|
||||
UsbConst.REQUEST_GET_CONFIGURATION,
|
||||
(short) 0,
|
||||
(short) 0
|
||||
);
|
||||
irp.setData(new byte[1]);
|
||||
device.syncSubmit(irp);
|
||||
System.out.println(irp.getData()[0]);
|
||||
+-----------------------------------------------------------------------------+
|
||||
|
||||
|
||||
* Interfaces
|
||||
|
||||
When you want to communicate with an interface or with endpoints of this
|
||||
interface then you have to claim it before using it and you have to
|
||||
release it when you are finished. Example:
|
||||
|
||||
----
|
||||
UsbConfiguration configuration = device.getActiveUsbConfiguration();
|
||||
UsbInterface iface = configuration.getUsbInterface((byte) 1);
|
||||
iface.claim();
|
||||
try
|
||||
{
|
||||
... Communicate with the interface or endpoints ...
|
||||
}
|
||||
finally
|
||||
{
|
||||
iface.release();
|
||||
}
|
||||
----
|
||||
|
||||
It is possible that the interface you want to communicate with is already
|
||||
used by a kernel driver. In this case you can try to force the claiming by
|
||||
passing an interface policy to the <<<claim>>> method:
|
||||
|
||||
----
|
||||
iface.claim(new UsbInterfacePolicy()
|
||||
{
|
||||
@Override
|
||||
public boolean forceClaim(UsbInterface usbInterface)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
----
|
||||
|
||||
Please note that interface policies are just a hint for the underlying USB
|
||||
implementation. In case of <usb4java> the policy will be ignored on Windows
|
||||
because <libusb> doesn't support detaching drivers on Windows.
|
||||
|
||||
* Synchronous I/O
|
||||
|
||||
This example sends 8 bytes to endpoint 0x03:
|
||||
|
||||
----
|
||||
UsbEndpoint endpoint = iface.getUsbEndpoint(0x03);
|
||||
UsbPipe pipe = endpoint.getUsbPipe();
|
||||
pipe.open();
|
||||
try
|
||||
{
|
||||
int sent = pipe.syncSubmit(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 });
|
||||
System.out.println(sent + " bytes sent");
|
||||
}
|
||||
finally
|
||||
{
|
||||
pipe.close();
|
||||
}
|
||||
----
|
||||
|
||||
This example reads 8 bytes from endpoint 0x83:
|
||||
|
||||
----
|
||||
UsbEndpoint endpoint = iface.getUsbEndpoint((byte) 0x83);
|
||||
UsbPipe pipe = endpoint.getUsbPipe();
|
||||
pipe.open();
|
||||
try
|
||||
{
|
||||
byte[] data = new byte[8];
|
||||
int received = pipe.syncSubmit(data);
|
||||
System.out.println(received + " bytes received");
|
||||
}
|
||||
finally
|
||||
{
|
||||
pipe.close();
|
||||
}
|
||||
----
|
||||
|
||||
* Asynchronous I/O
|
||||
|
||||
Asynchronous I/O works pretty much the same as synchronous I/O. You just
|
||||
use the <<<asyncSubmit>>> methods instead of the <<<syncSubmit>>> methods.
|
||||
While <<<syncSubmit>>> blocks until the request is complete
|
||||
<<<asyncSubmit>>> does not block and return immediately. To
|
||||
receive the response you have to add a listener to the pipe like this:
|
||||
|
||||
----
|
||||
pipe.addUsbPipeListener(new UsbPipeListener()
|
||||
{
|
||||
@Override
|
||||
public void errorEventOccurred(UsbPipeErrorEvent event)
|
||||
{
|
||||
UsbException error = event.getUsbException();
|
||||
... Handle error ...
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataEventOccurred(UsbPipeDataEvent event)
|
||||
{
|
||||
byte[] data = event.getData();
|
||||
... Process received data ...
|
||||
}
|
||||
});
|
||||
----
|
||||
|
||||
* See also
|
||||
|
||||
* {{{../usb4java-javax/apidocs/index.html}API documentation of usb4java-javax}}
|
||||
|
||||
* {{{https://github.com/usb4java/usb4java-javax-examples/}usb4java-javax examples}}
|
||||
|
||||
* {{{http://javax-usb.sourceforge.net/}javax-usb website}}
|
||||
|
||||
[]
|
||||
327
src/site/apt/quickstart/libusb.apt
Normal file
327
src/site/apt/quickstart/libusb.apt
Normal file
@ -0,0 +1,327 @@
|
||||
-----------------------------------------------------------------------------
|
||||
Low-level (libusb) API
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Low-level (libusb) API
|
||||
|
||||
* API design
|
||||
|
||||
The low-level API of usb4java closely follows the C API of the
|
||||
{{{http://libusb.info/}libusb}} project. All global functions and
|
||||
constants of <libusb> are defined as static members of the class
|
||||
{{{../apidocs/org/usb4java/LibUsb.html}org.usb4java.LibUsb}}.
|
||||
All structures of <libusb> are defined in separate classes which are named
|
||||
similar to the original struct names but without underscores, with camel-case
|
||||
names and with the <libusb> prefix removed. For example the struct
|
||||
<libusb_device_handle> is defined in the class
|
||||
{{{../apidocs/org/usb4java/DeviceHandle.html}DeviceHandle}}. Struct
|
||||
members are represented by static methods in the corresponding class.
|
||||
|
||||
The following notable differences exists between the <libusb 1.0 API> and
|
||||
the <usb4java> API:
|
||||
|
||||
* <interface> in the configuration descriptor is named <iface> because
|
||||
<interface> is a reserved word in Java.
|
||||
|
||||
* <MaxPower> in the configuration descriptor is named <bMaxPower> to
|
||||
be compatible to the USB specification and because method names starting
|
||||
with upper-case letters are quite unusual in Java.
|
||||
|
||||
* Whenever libusb expects a byte pointer and a length you have to use
|
||||
a direct Java NIO ByteBuffer instead.
|
||||
|
||||
* Methods which are returning a string through a byte buffer which was
|
||||
passed as argument have additional simplified overloaded method
|
||||
equivalents which are returning a Java String directly.
|
||||
|
||||
[]
|
||||
|
||||
* Initialization/deinitialization
|
||||
|
||||
Before using any usb4java functionality you must initialize libusb:
|
||||
|
||||
----
|
||||
Context context = new Context();
|
||||
int result = LibUsb.init(context);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to initialize libusb.", result);
|
||||
----
|
||||
|
||||
Specifiying a context is optional. If your application only needs a single
|
||||
libusb context then you can specify <null> as context.
|
||||
|
||||
Before your application terminates you should deinitialize libusb:
|
||||
|
||||
----
|
||||
LibUsb.exit(context);
|
||||
----
|
||||
|
||||
Related libusb documentation:
|
||||
|
||||
* {{{http://libusb.sourceforge.net/api-1.0/group__lib.html}Library initialization/deinitialization}}
|
||||
|
||||
[]
|
||||
|
||||
* Finding USB devices
|
||||
|
||||
Your program most likely wants to communicate with a specific device so first
|
||||
of all you have to find it. You have to get a list of all connected USB
|
||||
devices and then check the vendor/product ids. Here is a method which can
|
||||
be used for this purpose:
|
||||
|
||||
----
|
||||
public Device findDevice(short vendorId, short productId)
|
||||
{
|
||||
// Read the USB device list
|
||||
DeviceList list = new DeviceList();
|
||||
int result = LibUsb.getDeviceList(null, list);
|
||||
if (result < 0) throw new LibUsbException("Unable to get device list", result);
|
||||
|
||||
try
|
||||
{
|
||||
// Iterate over all devices and scan for the right one
|
||||
for (Device device: list)
|
||||
{
|
||||
DeviceDescriptor descriptor = new DeviceDescriptor();
|
||||
result = LibUsb.getDeviceDescriptor(device, descriptor);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to read device descriptor", result);
|
||||
if (descriptor.idVendor() == vendorId && descriptor.idProduct() == productId) return device;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure the allocated device list is freed
|
||||
LibUsb.freeDeviceList(list, true);
|
||||
}
|
||||
|
||||
// Device not found
|
||||
return null;
|
||||
}
|
||||
----
|
||||
|
||||
In your application it might be a little bit more complicated. Maybe you
|
||||
have more than one device of the same type so you may need a list of devices.
|
||||
Or you have to identify your device by the product or vendor string
|
||||
descriptor instead of just checking the ID (In case you are using a
|
||||
shared vendor/product ID). But this example should bring you on the right
|
||||
track.
|
||||
|
||||
Related libusb documentation:
|
||||
|
||||
* {{{http://libusb.sourceforge.net/api-1.0/group__dev.html}Device handling and enumeration}}
|
||||
|
||||
[]
|
||||
|
||||
* Device handles
|
||||
|
||||
For the real USB communication you must open a new device handle and you
|
||||
must close it again when you are finished communicating with the device.
|
||||
Example:
|
||||
|
||||
----
|
||||
DeviceHandle handle = new DeviceHandle();
|
||||
int result = LibUsb.open(device, handle);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to open USB device", result);
|
||||
try
|
||||
{
|
||||
// Use device handle here
|
||||
}
|
||||
finally
|
||||
{
|
||||
LibUsb.close(handle);
|
||||
}
|
||||
----
|
||||
|
||||
* Interfaces
|
||||
|
||||
When you want to communicate with an interface or with endpoints of this
|
||||
interface then you have to claim it before using it and you have to
|
||||
release it when you are finished. Example:
|
||||
|
||||
----
|
||||
int result = LibUsb.claimInterface(handle, interfaceNumber);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to claim interface", result);
|
||||
try
|
||||
{
|
||||
// Use interface here
|
||||
}
|
||||
finally
|
||||
{
|
||||
result = LibUsb.releaseInterface(handle, interfaceNumber);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to release interface", result);
|
||||
}
|
||||
----
|
||||
|
||||
It is possible that the interface you want to communicate with is already
|
||||
used by a kernel driver. In this case you have to detach the kernel driver
|
||||
from the interface before claiming it. Example:
|
||||
|
||||
----
|
||||
// Check if kernel driver must be detached
|
||||
boolean detach = LibUsb.hasCapability(LibUsb.CAP_SUPPORTS_DETACH_KERNEL_DRIVER)
|
||||
&& LibUsb.kernelDriverActive(handle, interfaceNumber);
|
||||
|
||||
// Detach the kernel driver
|
||||
if (detach)
|
||||
{
|
||||
int result = LibUsb.detachKernelDriver(handle, interfaceNumber);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to detach kernel driver", result);
|
||||
}
|
||||
|
||||
// Communicate with the device
|
||||
...
|
||||
|
||||
// Attach the kernel driver again if needed
|
||||
if (detach)
|
||||
{
|
||||
int result = LibUsb.attachKernelDriver(handle, interfaceNumber);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to re-attach kernel driver", result);
|
||||
}
|
||||
----
|
||||
|
||||
Please note that detaching kernel drivers is not supported on Windows.
|
||||
|
||||
* Synchronous I/O
|
||||
|
||||
For the actual USB communication you usually have to create a direct
|
||||
byte buffer for the data to send or receive.
|
||||
|
||||
This examples sends 8 bytes to a claimed interface using a control transfer:
|
||||
|
||||
----
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(8);
|
||||
buffer.put(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 });
|
||||
int transfered = LibUsb.controlTransfer(handle,
|
||||
(byte) (LibUsb.REQUEST_TYPE_CLASS | LibUsb.RECIPIENT_INTERFACE),
|
||||
(byte) 0x09, (short) 2, (short) 1, buffer, timeout);
|
||||
if (transfered < 0) throw new LibUsbException("Control transfer failed", transfered);
|
||||
System.out.println(transfered + " bytes sent");
|
||||
----
|
||||
|
||||
This example sends 8 bytes to endpoint 0x03 of the claimed interface using a
|
||||
bulk transfer:
|
||||
|
||||
----
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(8);
|
||||
buffer.put(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 });
|
||||
IntBuffer transfered = IntBuffer.allocate(1);
|
||||
int result = LibUsb.bulkTransfer(handle, 0x03, buffer, transfered, timeout);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Control transfer failed", transfered);
|
||||
System.out.println(transfered.get() + " bytes sent");
|
||||
----
|
||||
|
||||
Related libusb documentation:
|
||||
|
||||
* {{{http://libusb.sourceforge.net/api-1.0/group__syncio.html}Synchronous device I/O}}
|
||||
|
||||
[]
|
||||
|
||||
* Asynchronous I/O
|
||||
|
||||
Asynchronous I/O is a little bit more complex than synchronous I/O. That's
|
||||
because libusb doesn't start its own thread to
|
||||
handle the actual background tasks. Instead you have to create you own
|
||||
worker thread like this:
|
||||
|
||||
----
|
||||
class EventHandlingThread extends Thread
|
||||
{
|
||||
/** If thread should abort. */
|
||||
private volatile boolean abort;
|
||||
|
||||
/**
|
||||
* Aborts the event handling thread.
|
||||
*/
|
||||
public void abort()
|
||||
{
|
||||
this.abort = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while (!this.abort)
|
||||
{
|
||||
int result = LibUsb.handleEventsTimeout(null, 250000);
|
||||
if (result != LibUsb.SUCCESS)
|
||||
throw new LibUsbException("Unable to handle events", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
This simple thread implementation doesn't use a specific libusb context so
|
||||
it specified <<<null>>> as context. If you need contexts then you may want
|
||||
to pass it to the thread somehow.
|
||||
|
||||
The thread must be started after you have initialized libusb:
|
||||
|
||||
----
|
||||
EventHandlingThread thread = new EventHandlingThread();
|
||||
thread.start();
|
||||
----
|
||||
|
||||
And it must be stopped before deinitializing libusb:
|
||||
|
||||
----
|
||||
thread.abort();
|
||||
thread.join();
|
||||
----
|
||||
|
||||
So now with this thread running in the background you can use the
|
||||
asynchronous functions of libusb. If you don't like this thread and your
|
||||
program already has some kind of application loop then you can also simply
|
||||
call <<<LibUsb.handleEventsTimeout(null, 0)>>> inside the loop. This call
|
||||
returns immediately if there are no events to process.
|
||||
|
||||
An actual asynchronous transfer is submitted like this (In this case
|
||||
an outgoing bulk transfer to endpoint <0x03>):
|
||||
|
||||
----
|
||||
ByteBuffer buffer = BufferUtils.allocateByteBuffer(8);
|
||||
buffer.put(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 });
|
||||
Transfer transfer = LibUsb.allocTransfer();
|
||||
LibUsb.fillBulkTransfer(transfer, handle, 0x03, buffer, callback, null, timeout);
|
||||
int result = LibUsb.submitTransfer(transfer);
|
||||
if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to submit transfer", result);
|
||||
----
|
||||
|
||||
The <<<callback>>> is an object implementing the
|
||||
{{{../apidocs/org/usb4java/TransferCallback.html}TransferCallback}} interface.
|
||||
Here is an example of such a callback:
|
||||
|
||||
----
|
||||
TransferCallback callback = new TransferCallback()
|
||||
{
|
||||
@Override
|
||||
public void processTransfer(Transfer transfer)
|
||||
{
|
||||
System.out.println(transfer.actualLength() + " bytes sent");
|
||||
LibUsb.freeTransfer(transfer);
|
||||
}
|
||||
};
|
||||
----
|
||||
|
||||
Related libusb documentation:
|
||||
|
||||
* {{{http://libusb.sourceforge.net/api-1.0/group__asyncio.html}Asynchronous device I/O}}
|
||||
|
||||
* {{{http://libusb.sourceforge.net/api-1.0/mtasync.html}Multi-threaded applications and asynchronous I/O}}
|
||||
|
||||
* {{{http://libusb.sourceforge.net/api-1.0/io.html}Synchronous and asynchronous device I/O}}
|
||||
|
||||
* {{{http://libusb.sourceforge.net/api-1.0/group__poll.html}Polling and timing}}
|
||||
|
||||
[]
|
||||
|
||||
|
||||
|
||||
* See also
|
||||
|
||||
* {{{../apidocs/org/usb4java/package-summary.html}API documentation of usb4java}}
|
||||
|
||||
* {{{https://github.com/usb4java/usb4java-examples/}usb4java examples}}
|
||||
|
||||
* {{{http://libusb.sourceforge.net/api-1.0/}API documentation of libusb}}
|
||||
|
||||
[]
|
||||
|
||||
@ -31,7 +31,10 @@
|
||||
|
||||
<menu name="usb4java">
|
||||
<item name="About" href="./index.html" />
|
||||
<item name="Quick start" href="./quickstart.html" />
|
||||
<item name="Quick start" href="./quickstart/index.html" collapse="true">
|
||||
<item name="Low-level (libusb) API" href="./quickstart/libusb.html" />
|
||||
<item name="High-level (javax-usb) API" href="./quickstart/javax-usb.html" />
|
||||
</item>
|
||||
<item name="FAQ" href="./faq.html" />
|
||||
<item name="Configuration" href="./configuration.html" />
|
||||
<item name="Native libs" href="./nativelibs.html" />
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
the native <a href="http://libusb.info/">libusb 1.0</a> library
|
||||
and uses Java NIO buffers for data exchange between libusb and Java.
|
||||
usb4java also supports the
|
||||
<a href="http://javax-usb.sourceforge.net/">javax.usb standard (JSR-80)</a>
|
||||
<a href="http://javax-usb.sourceforge.net/">javax-usb standard (JSR-80)</a>
|
||||
through the <a href="usb4java-javax/">usb4java-javax extension</a>.
|
||||
</p>
|
||||
<p>
|
||||
@ -30,7 +30,7 @@
|
||||
<strong><a href="${artifactBaseUrl}.zip">${project.artifactId}-${project.version}.zip</a></strong><br />
|
||||
</li>
|
||||
<li>
|
||||
javax.usb extension:<br />
|
||||
javax-usb extension:<br />
|
||||
<strong><a href="${artifactBaseUrl}.tar.bz2">${project.artifactId}-javax-${usb4javaJavaxVersion}.tar.bz2</a></strong><br />
|
||||
<strong><a href="${artifactBaseUrl}.zip">${project.artifactId}-javax-${usb4javaJavaxVersion}.zip</a></strong><br />
|
||||
</li>
|
||||
@ -52,7 +52,7 @@
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<-- For using just usb4java without javax.usb -->
|
||||
<-- For using just usb4java without javax-usb -->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
@ -61,7 +61,7 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<-- For using usb4java with javax.usb -->
|
||||
<-- For using usb4java with javax-usb -->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
@ -89,11 +89,11 @@
|
||||
|
||||
<section name="Getting started">
|
||||
<p>
|
||||
Read the <a href="quickstart.html">quick start guide</a> and the
|
||||
Read the <a href="quickstart/index.html">quick start guide</a> and the
|
||||
<a href="faq.html">FAQ</a>. There are also some
|
||||
<a href="https://github.com/usb4java/usb4java-examples/">low-level (libusb) examples</a>
|
||||
and
|
||||
<a href="https://github.com/usb4java/usb4java-javax-examples/">high-level (javax.usb) examples</a>
|
||||
<a href="https://github.com/usb4java/usb4java-javax-examples/">high-level (javax-usb) examples</a>
|
||||
available.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user