Started using NIO buffers.
This commit is contained in:
parent
7851dfb34e
commit
9b6eb1aa07
@ -5,7 +5,8 @@
|
||||
|
||||
package de.ailis.usb4java;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
|
||||
/**
|
||||
@ -24,6 +25,12 @@ import java.io.UnsupportedEncodingException;
|
||||
|
||||
public class USB
|
||||
{
|
||||
/** The maximum size of a descriptor. */
|
||||
private static final int MAX_DESCRIPTOR_SIZE = 256;
|
||||
|
||||
/** The maximum size of a string. */
|
||||
private static final int MAX_STRING_SIZE = (MAX_DESCRIPTOR_SIZE - 2) / 2;
|
||||
|
||||
// === USB class constants ===============================================
|
||||
|
||||
/** Per interface class. */
|
||||
@ -218,13 +225,11 @@ public class USB
|
||||
* The language id.
|
||||
* @param buffer
|
||||
* The buffer to write the string to.
|
||||
* @param buflen
|
||||
* The maximum number of bytes to read.
|
||||
* @return The number of bytes read or < 0 on error.
|
||||
*/
|
||||
|
||||
public static native int usb_get_string(USB_Dev_Handle handle,
|
||||
int index, int langid, byte[] buffer, int buflen);
|
||||
int index, int langid, ByteBuffer buffer);
|
||||
|
||||
|
||||
/**
|
||||
@ -238,23 +243,35 @@ public class USB
|
||||
* The language id.
|
||||
* @param size
|
||||
* The maximum number of bytes to read.
|
||||
* @return The string or null if an error occurred.
|
||||
* @return The string descriptor or null if an error occurred.
|
||||
*/
|
||||
|
||||
public static String usb_get_string(final USB_Dev_Handle handle,
|
||||
public static USB_String_Descriptor usb_get_string(final USB_Dev_Handle handle,
|
||||
final int index, final int langid, final int size)
|
||||
{
|
||||
final byte[] buffer = new byte[size];
|
||||
final int len = usb_get_string(handle, index, langid, buffer, size);
|
||||
final ByteBuffer buffer = ByteBuffer.allocateDirect(size);
|
||||
final int len = usb_get_string(handle, index, langid, buffer);
|
||||
if (len < 0) return null;
|
||||
try
|
||||
{
|
||||
return new String(buffer, 0, len, "UTF-8");
|
||||
}
|
||||
catch (final UnsupportedEncodingException e)
|
||||
{
|
||||
return new String(buffer, 0, len);
|
||||
}
|
||||
return new USB_String_Descriptor(buffer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string descriptor from a device.
|
||||
*
|
||||
* @param handle
|
||||
* The USB device handle.
|
||||
* @param index
|
||||
* The string description index.
|
||||
* @param langid
|
||||
* The language id.
|
||||
* @return The string descriptor or null if an error occurred.
|
||||
*/
|
||||
|
||||
public static USB_String_Descriptor usb_get_string(final USB_Dev_Handle handle,
|
||||
final int index, final int langid)
|
||||
{
|
||||
return usb_get_string(handle, index, langid, MAX_STRING_SIZE * 2);
|
||||
}
|
||||
|
||||
|
||||
@ -272,40 +289,98 @@ public class USB
|
||||
* The string description index.
|
||||
* @param buffer
|
||||
* The buffer to write the string to.
|
||||
* @param buflen
|
||||
* The maximum number of bytes to read.
|
||||
* @return The number of bytes read or < 0 on error.
|
||||
*/
|
||||
|
||||
public static native int usb_get_string_simple(USB_Dev_Handle handle,
|
||||
int index, byte[] buffer, int buflen);
|
||||
int index, ByteBuffer buffer);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string descriptor from a device using the first language.
|
||||
* Unlike the native usb_get_string_simple() function this method returns
|
||||
* the string in correct unicode encoding.
|
||||
*
|
||||
* @param handle
|
||||
* The USB device handle.
|
||||
* @param index
|
||||
* The string description index.
|
||||
* @param size
|
||||
* The maximum number of bytes to read.
|
||||
* The maximum number of characters to read.
|
||||
* @return The string or null if an error occurred.
|
||||
*/
|
||||
|
||||
public static String usb_get_string_simple(final USB_Dev_Handle handle,
|
||||
final int index, final int size)
|
||||
{
|
||||
final byte[] buffer = new byte[size];
|
||||
final int len = usb_get_string_simple(handle, index, buffer, size);
|
||||
if (len < 0) return null;
|
||||
try
|
||||
{
|
||||
return new String(buffer, 0, len, "ISO-8859-15");
|
||||
}
|
||||
catch (final UnsupportedEncodingException e)
|
||||
{
|
||||
return new String(buffer, 0, len);
|
||||
}
|
||||
final short[] languages = usb_get_languages(handle);
|
||||
if (languages == null) return null;
|
||||
final short langid = languages.length == 0 ? 0 : languages[0];
|
||||
final USB_String_Descriptor descriptor = usb_get_string(handle, index, langid, size * 2);
|
||||
if (descriptor == null) return null;
|
||||
return descriptor.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string descriptor from a device using the first language.
|
||||
* Unlike the native usb_get_string_simple() function this method returns
|
||||
* the string in correct unicode encoding.
|
||||
*
|
||||
* @param handle
|
||||
* The USB device handle.
|
||||
* @param index
|
||||
* The string description index.
|
||||
* @return The string or null if an error occurred.
|
||||
*/
|
||||
|
||||
public static String usb_get_string_simple(final USB_Dev_Handle handle,
|
||||
final int index)
|
||||
{
|
||||
return usb_get_string_simple(handle, index, MAX_STRING_SIZE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the languages the specified device supports.
|
||||
*
|
||||
* @param handle
|
||||
* The USB device handle.
|
||||
* @return Array with supported language codes.
|
||||
*/
|
||||
|
||||
public static short[] usb_get_languages(final USB_Dev_Handle handle)
|
||||
{
|
||||
final ByteBuffer buffer = ByteBuffer
|
||||
.allocateDirect(MAX_DESCRIPTOR_SIZE);
|
||||
final int len = usb_get_descriptor(handle, USB_DT_STRING, 0, buffer);
|
||||
if (len < 0) return null;
|
||||
final short[] languages = new short[(len - 2) / 2];
|
||||
if (languages.length == 0) return languages;
|
||||
buffer.position(2);
|
||||
buffer.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(languages);
|
||||
return languages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a descriptor from a device's default control pipe.
|
||||
*
|
||||
* usb_get_descriptor retrieves a descriptor from the device identified by
|
||||
* the type and index of the descriptor from the default control pipe.
|
||||
* Returns number of bytes read for the descriptor or < 0 on error.
|
||||
*
|
||||
* @param handle
|
||||
* The device handle.
|
||||
* @param type
|
||||
* The descriptor type.
|
||||
* @param index
|
||||
* The descriptor index.
|
||||
* @param buffer
|
||||
* The buffer to put the read bytes in.
|
||||
* @return Number of bytes read or < 0 on error.
|
||||
*/
|
||||
|
||||
public static native int usb_get_descriptor(USB_Dev_Handle handle,
|
||||
int type, int index, ByteBuffer buffer);
|
||||
}
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Klaus Reimer <k@ailis.de>
|
||||
* See LICENSE.txt for licensing information.
|
||||
*/
|
||||
|
||||
package de.ailis.usb4java;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* All standard descriptors have the two fields bLength and bDescriptorType
|
||||
* in common. So this base class implements them.
|
||||
*
|
||||
* @author Klaus Reimer (k@ailis.de)
|
||||
*/
|
||||
|
||||
public abstract class USB_Descriptor_Header2
|
||||
{
|
||||
/** The descriptor data. */
|
||||
protected final ByteBuffer data;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param data
|
||||
* The descriptor data.
|
||||
*/
|
||||
|
||||
public USB_Descriptor_Header2(final ByteBuffer data)
|
||||
{
|
||||
this.data = data;
|
||||
this.data.limit(bLength());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the size of the descriptor in bytes.
|
||||
*
|
||||
* @return The size of the descriptor in bytes (unsigned byte).
|
||||
*/
|
||||
|
||||
public final int bLength()
|
||||
{
|
||||
return this.data.get(0) & 0xff;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the interface descriptor type.
|
||||
*
|
||||
* @return The interface descriptor type (unsigned byte).
|
||||
*/
|
||||
|
||||
public final int bDescriptorType()
|
||||
{
|
||||
return this.data.get(1) & 0xff;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Klaus Reimer <k@ailis.de>
|
||||
* See LICENSE.txt for licensing information.
|
||||
*/
|
||||
|
||||
package de.ailis.usb4java;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.CharBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A string descriptor.
|
||||
*
|
||||
* @author Klaus Reimer (k@ailis.de)
|
||||
*/
|
||||
|
||||
public class USB_String_Descriptor extends USB_Descriptor_Header2
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param data
|
||||
* The descriptor data.
|
||||
*/
|
||||
|
||||
USB_String_Descriptor(final ByteBuffer data)
|
||||
{
|
||||
super(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the string data in UTF-16 encoding.
|
||||
*
|
||||
* @return The string data.
|
||||
*/
|
||||
|
||||
public char[] wData()
|
||||
{
|
||||
this.data.position(2);
|
||||
final CharBuffer chars = this.data.order(ByteOrder.LITTLE_ENDIAN)
|
||||
.asCharBuffer();
|
||||
final char[] output = new char[chars.remaining()];
|
||||
chars.get(output);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return new String(wData());
|
||||
}
|
||||
}
|
||||
@ -213,12 +213,23 @@ public class Dump
|
||||
dump_device_descriptor(device.descriptor());
|
||||
level--;
|
||||
final USB_Dev_Handle handle = usb_open(device);
|
||||
final String manufacturer = usb_get_string_simple(handle, device.descriptor().iManufacturer(), 255);
|
||||
final String manufacturer = usb_get_string_simple(handle, device.descriptor().iManufacturer());
|
||||
indent(); System.out.format("Manufacturer: %s\n", manufacturer != null ? manufacturer : "Unknown");
|
||||
final String product = usb_get_string_simple(handle, device.descriptor().iProduct(), 255);
|
||||
final String product = usb_get_string_simple(handle, device.descriptor().iProduct());
|
||||
indent(); System.out.format("Product: %s\n", product != null ? product : "Unknown");
|
||||
final String serialNumber = usb_get_string_simple(handle, device.descriptor().iSerialNumber(), 255);
|
||||
final String serialNumber = usb_get_string_simple(handle, device.descriptor().iSerialNumber());
|
||||
indent(); System.out.format("Serial: %s\n", serialNumber != null ? serialNumber : "Unknown");
|
||||
indent(); System.out.print("Languages:");
|
||||
final short[] languages = USB.usb_get_languages(handle);
|
||||
if (languages != null)
|
||||
{
|
||||
for (final short language: languages)
|
||||
System.out.format(" 0x%04x", language);
|
||||
System.out.println();
|
||||
}
|
||||
else
|
||||
System.out.println("Unknown");
|
||||
|
||||
usb_close(handle);
|
||||
indent(); System.out.format("config descriptors:\n");
|
||||
level++;
|
||||
|
||||
@ -12,5 +12,6 @@ libusb4java_la_SOURCES = \
|
||||
USB_Dev_Handle.c \
|
||||
USB_Interface.c \
|
||||
USB_Interface_Descriptor.c \
|
||||
USB_Endpoint_Descriptor.c
|
||||
USB_Endpoint_Descriptor.c \
|
||||
USB_String_Descriptor.c
|
||||
|
||||
@ -105,41 +105,48 @@ JNIEXPORT jint JNICALL METHOD_NAME(USB, usb_1close)
|
||||
JNIEXPORT jint JNICALL METHOD_NAME(USB, usb_1get_1string)
|
||||
(
|
||||
JNIEnv *env, jclass class, jobject handle, jint index, jint langid,
|
||||
jbyteArray buffer, jint buflen
|
||||
jobject buffer
|
||||
)
|
||||
{
|
||||
char *buf = (char*) malloc(buflen);
|
||||
int result = usb_get_string(unwrap_usb_dev_handle(env, handle),
|
||||
index, langid, buf, buflen);
|
||||
if (result >= 0)
|
||||
{
|
||||
(*env)->SetByteArrayRegion(env, buffer, 0, result,
|
||||
(const jbyte *) buf);
|
||||
}
|
||||
free(buf);
|
||||
return result;
|
||||
void *buf = (*env)->GetDirectBufferAddress(env, buffer);
|
||||
if (!buf) return -1;
|
||||
jlong buflen = (*env)->GetDirectBufferCapacity(env, buffer);
|
||||
return usb_get_string(unwrap_usb_dev_handle(env, handle),
|
||||
index, langid, buf, buflen);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* int usb_get_simple_string(USB_Handle handle, int index, byte[] buffer,
|
||||
* int buflen)
|
||||
* int usb_get_simple_string(USB_Handle handle, int index, ByteBuffer buffer)
|
||||
*/
|
||||
|
||||
JNIEXPORT jint JNICALL METHOD_NAME(USB, usb_1get_1string_1simple)
|
||||
(
|
||||
JNIEnv *env, jclass class, jobject handle, jint index, jbyteArray buffer,
|
||||
jint buflen
|
||||
JNIEnv *env, jclass class, jobject handle, jint index, jobject buffer
|
||||
)
|
||||
{
|
||||
char *buf = (char*) malloc(buflen);
|
||||
int result = usb_get_string_simple(unwrap_usb_dev_handle(env, handle),
|
||||
index, buf, buflen);
|
||||
if (result >= 0)
|
||||
{
|
||||
(*env)->SetByteArrayRegion(env, buffer, 0, result,
|
||||
(const jbyte *) buf);
|
||||
}
|
||||
free(buf);
|
||||
return result;
|
||||
void *buf = (*env)->GetDirectBufferAddress(env, buffer);
|
||||
if (!buf) return -1;
|
||||
jlong buflen = (*env)->GetDirectBufferCapacity(env, buffer);
|
||||
return usb_get_string_simple(unwrap_usb_dev_handle(env, handle),
|
||||
index, buf, buflen);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* int usb_get_descriptor(USB_Dev_Handle handle, int type, int index,
|
||||
* ByteBuffer buffer);
|
||||
*/
|
||||
|
||||
JNIEXPORT jint JNICALL METHOD_NAME(USB, usb_1get_1descriptor)
|
||||
(
|
||||
JNIEnv *env, jclass class, jobject handle, int type, int index,
|
||||
jobject buffer
|
||||
)
|
||||
{
|
||||
void *buf = (*env)->GetDirectBufferAddress(env, buffer);
|
||||
if (!buf) return -1;
|
||||
jlong buflen = (*env)->GetDirectBufferCapacity(env, buffer);
|
||||
return usb_get_descriptor(unwrap_usb_dev_handle(env, handle),
|
||||
type, index, buf, buflen);
|
||||
}
|
||||
|
||||
77
usb4java-lib/src/main/c/USB_String_Descriptor.c
Normal file
77
usb4java-lib/src/main/c/USB_String_Descriptor.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Klaus Reimer (k@ailis.de)
|
||||
* See COPYING file for copying conditions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name USB_String_Descriptor
|
||||
*
|
||||
* Native methods for the USB_String_Descriptor class.
|
||||
*
|
||||
* @author Klaus Reimer <k@ailis.de>
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <usb.h>
|
||||
#include "usb4java.h"
|
||||
|
||||
/**
|
||||
* Creates and returns a new USB string descriptor wrapper object.
|
||||
*
|
||||
* @param env
|
||||
* The JNI environment.
|
||||
* @param device
|
||||
* The USB string descriptor.
|
||||
* @return The USB string descriptor wrapper object.
|
||||
*/
|
||||
|
||||
jobject wrap_usb_string_descriptor(JNIEnv *env,
|
||||
struct usb_string_descriptor *descriptor)
|
||||
{
|
||||
if (!descriptor) return NULL;
|
||||
jclass cls = (*env)->FindClass(env,
|
||||
PACKAGE_DIR"/USB_String_Descriptor");
|
||||
if (cls == NULL) return NULL;
|
||||
jmethodID constructor = (*env)->GetMethodID(env, cls, "<init>", "(J)V");
|
||||
if (constructor == NULL) return NULL;
|
||||
return (*env)->NewObject(env, cls, constructor, (long) descriptor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the wrapped USB string descriptor object from the specified
|
||||
* wrapper object.
|
||||
*
|
||||
* @param env
|
||||
* The JNI environment.
|
||||
* @param obj
|
||||
* The USB string descriptor wrapper object.
|
||||
* @return The USB string descriptor object.
|
||||
*/
|
||||
|
||||
struct usb_string_descriptor *unwrap_usb_string_descriptor(JNIEnv *env,
|
||||
jobject obj)
|
||||
{
|
||||
jclass cls = (*env)->GetObjectClass(env, obj);
|
||||
jfieldID field = (*env)->GetFieldID(env, cls, "pointer", "J");
|
||||
return (struct usb_string_descriptor *) ((*env)->GetLongField(env,
|
||||
obj, field));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* char[] wData()
|
||||
*/
|
||||
|
||||
JNIEXPORT jcharArray JNICALL METHOD_NAME(USB_1String_1Descriptor, wData)
|
||||
(
|
||||
JNIEnv *env, jobject this
|
||||
)
|
||||
{
|
||||
struct usb_string_descriptor *descriptor = unwrap_usb_string_descriptor(env, this);
|
||||
int size = (descriptor->bLength - 2) / 2;
|
||||
jcharArray array = (*env)->NewByteArray(env, size);
|
||||
(*env)->SetCharArrayRegion(env, array, 0, size,
|
||||
(const jchar *) descriptor->wData);
|
||||
return array;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user