From 13e83fd59e840d76216c5e002578bbb9392fccd2 Mon Sep 17 00:00:00 2001 From: Luca Longinotti Date: Tue, 11 Jun 2013 15:48:16 +0200 Subject: [PATCH] Add isochronous transfer functions and async transfer fill functions. They are implemented directly in Java since they are static inline convenience functions in libusb.h and don't really need to call into C via JNI at all to work, this keeps the JNI layer simple and minimal. Only fill_control/get_control is still outstanding. getDescriptor() and getStringDescriptor() were removed from native JNI, since they are static inline convenience functions in libusb.h and don't do anything more than calling the appropriate real function. --- src/main/c/src/LibUsb.c | 38 ------- .../java/de/ailis/usb4java/libusb/LibUsb.java | 106 ++++++++++++++++-- .../de/ailis/usb4java/utils/BufferUtils.java | 17 +++ 3 files changed, 115 insertions(+), 46 deletions(-) diff --git a/src/main/c/src/LibUsb.c b/src/main/c/src/LibUsb.c index 2a76b50..fc762ae 100644 --- a/src/main/c/src/LibUsb.c +++ b/src/main/c/src/LibUsb.c @@ -722,44 +722,6 @@ JNIEXPORT void JNICALL METHOD_NAME(LibUsb, freeConfigDescriptor) resetConfigDescriptor(env, descriptor); } -/** - * int getDescriptor(DeviceHandle, int, int, ByteBuffer) - */ -JNIEXPORT jint JNICALL METHOD_NAME(LibUsb, getDescriptor) -( - JNIEnv *env, jclass class, jobject handle, jint type, jint index, - jobject data -) -{ - NOT_NULL(env, handle, return 0); - NOT_NULL(env, data, return 0); - DIRECT_BUFFER(env, data, data_ptr, return 0); - libusb_device_handle *dev_handle = unwrapDeviceHandle(env, handle); - if (!dev_handle) return 0; - - jlong data_size = (*env)->GetDirectBufferCapacity(env, data); - return libusb_get_descriptor(dev_handle, type, index, data_ptr, data_size); -} - -/** - * int getStringDescriptor(DeviceHandle, int, int, ByteBuffer) - */ -JNIEXPORT jint JNICALL METHOD_NAME(LibUsb, getStringDescriptor) -( - JNIEnv *env, jclass class, jobject handle, jint index, jint langId, - jobject data -) -{ - NOT_NULL(env, handle, return 0); - NOT_NULL(env, data, return 0); - DIRECT_BUFFER(env, data, data_ptr, return 0); - libusb_device_handle *dev_handle = unwrapDeviceHandle(env, handle); - if (!dev_handle) return 0; - - jlong data_size = (*env)->GetDirectBufferCapacity(env, data); - return libusb_get_string_descriptor(dev_handle, index, langId, data_ptr, data_size); -} - /** * int controlTransfer(DeviceHandle, int, int, int, int, ByteBuffer, int) */ diff --git a/src/main/java/de/ailis/usb4java/libusb/LibUsb.java b/src/main/java/de/ailis/usb4java/libusb/LibUsb.java index bbb439b..afc45cb 100644 --- a/src/main/java/de/ailis/usb4java/libusb/LibUsb.java +++ b/src/main/java/de/ailis/usb4java/libusb/LibUsb.java @@ -16,6 +16,8 @@ import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; +import de.ailis.usb4java.utils.BufferUtils; + /** * Static class providing the constants and functions of libusbx. * @@ -695,10 +697,8 @@ public final class LibUsb * * This function is useful for setting up isochronous transfers, for example * you might pass the return value from this function to - * libusb_set_iso_packet_lengths() in order to set the length field of every - * isochronous packet in a transfer. - * - * TODO Link to libusb_set_iso_packet_lengths when implemented + * {@link #setIsoPacketLengths(Transfer, int)} in order to set the length + * field of every isochronous packet in a transfer. * * @param device * A device. @@ -1288,8 +1288,12 @@ public final class LibUsb * @return number of bytes returned in data, or ERROR code on failure * */ - public static native int getDescriptor(final DeviceHandle handle, - final int type, final int index, final ByteBuffer data); + public static int getDescriptor(final DeviceHandle handle, final int type, + final int index, final ByteBuffer data) + { + return controlTransfer(handle, ENDPOINT_IN, REQUEST_GET_DESCRIPTOR, + (type << 8) | index, 0, data, 1000); + } /** * Retrieve a descriptor from a device. @@ -1309,8 +1313,12 @@ public final class LibUsb * @return number of bytes returned in data, or LIBUSB_ERROR code on failure * @see #getStringDescriptorAscii(DeviceHandle, int, StringBuffer) */ - public static native int getStringDescriptor(final DeviceHandle handle, - final int index, final int langId, final ByteBuffer data); + public static int getStringDescriptor(final DeviceHandle handle, + final int index, final int langId, final ByteBuffer data) + { + return controlTransfer(handle, ENDPOINT_IN, REQUEST_GET_DESCRIPTOR, + (DT_STRING << 8) | index, langId, data, 1000); + } /** * Perform a USB control transfer. @@ -1961,4 +1969,86 @@ public final class LibUsb * already complete or cancelled. Another LIBUSB_ERROR code on failure. */ public static native int cancelTransfer(final Transfer transfer); + + public static void fillBulkTransfer(Transfer transfer, DeviceHandle handle, + int endpoint, ByteBuffer buffer, TransferCallback callback, + Object userData, int timeout) + { + transfer.setDevHandle(handle); + transfer.setEndpoint(endpoint); + transfer.setType(TRANSFER_TYPE_BULK); + transfer.setTimeout(timeout); + transfer.setBuffer(buffer); + transfer.setUserData(userData); + transfer.setCallback(callback); + } + + public static void fillInterruptTransfer(Transfer transfer, + DeviceHandle handle, int endpoint, ByteBuffer buffer, + TransferCallback callback, Object userData, int timeout) + { + transfer.setDevHandle(handle); + transfer.setEndpoint(endpoint); + transfer.setType(TRANSFER_TYPE_INTERRUPT); + transfer.setTimeout(timeout); + transfer.setBuffer(buffer); + transfer.setUserData(userData); + transfer.setCallback(callback); + } + + public static void fillIsoTransfer(Transfer transfer, DeviceHandle handle, + int endpoint, ByteBuffer buffer, int numIsoPackets, + TransferCallback callback, Object userData, int timeout) + { + transfer.setDevHandle(handle); + transfer.setEndpoint(endpoint); + transfer.setType(TRANSFER_TYPE_ISOCHRONOUS); + transfer.setTimeout(timeout); + transfer.setBuffer(buffer); + transfer.setNumIsoPackets(numIsoPackets); + transfer.setUserData(userData); + transfer.setCallback(callback); + } + + public static void setIsoPacketLengths(Transfer transfer, int length) + { + for (IsoPacketDescriptor isoDesc: transfer.isoPacketDesc()) + { + isoDesc.setLength(length); + } + } + + public static ByteBuffer getIsoPacketBuffer(Transfer transfer, int packet) + { + if (packet >= transfer.numIsoPackets()) + { + return null; + } + + IsoPacketDescriptor isoDescriptors[] = transfer.isoPacketDesc(); + int offset = 0; + + for (int i = 0; i < packet; i++) + { + offset += isoDescriptors[i].length(); + } + + return BufferUtils.slice(transfer.buffer(), offset, + isoDescriptors[packet].length()); + } + + public static ByteBuffer getIsoPacketBufferSimple(Transfer transfer, + int packet) + { + if (packet >= transfer.numIsoPackets()) + { + return null; + } + + IsoPacketDescriptor isoDescriptors[] = transfer.isoPacketDesc(); + int offset = isoDescriptors[0].length() * packet; + + return BufferUtils.slice(transfer.buffer(), offset, + isoDescriptors[packet].length()); + } } diff --git a/src/main/java/de/ailis/usb4java/utils/BufferUtils.java b/src/main/java/de/ailis/usb4java/utils/BufferUtils.java index 4a83b9d..8626598 100644 --- a/src/main/java/de/ailis/usb4java/utils/BufferUtils.java +++ b/src/main/java/de/ailis/usb4java/utils/BufferUtils.java @@ -23,4 +23,21 @@ public final class BufferUtils { return ByteBuffer.allocateDirect(longSize).asLongBuffer(); } + + public static ByteBuffer slice(final ByteBuffer buffer, final int offset, + final int length) + { + int oldPosition = buffer.position(); + int oldLimit = buffer.limit(); + + buffer.position(offset); + buffer.limit(offset + length); + + final ByteBuffer slice = buffer.slice(); + + buffer.position(oldPosition); + buffer.limit(oldLimit); + + return slice; + } }