Implement support for USB 2.0 extension descriptor.

This commit is contained in:
Klaus Reimer 2013-07-13 22:24:40 +02:00
parent 5efc4f8573
commit 5369719bf3
10 changed files with 454 additions and 2 deletions

View File

@ -28,7 +28,8 @@
Implement support for SuperSpeed Endpoint Companion Descriptor.
</action>
<action dev="kayahr" type="add" date="2013-07-13">
Implement support for BOS Descriptor.
Implement support for BOS Descriptor, BOS Device Capability
Descriptor and USB 2.0 Extension Descriptor.
</action>
<action dev="kayahr" type="add" date="2013-07-13">
Using uninitialized descriptors now throw an IllegalStateException

View File

@ -10,5 +10,7 @@
jobjectArray wrapBOSDevCapabilityDescriptors(JNIEnv*, int,
struct libusb_bos_dev_capability_descriptor**);
struct libusb_bos_dev_capability_descriptor
*unwrapBOSDevCapabilityDescriptor(JNIEnv *, jobject);
#endif

View File

@ -24,6 +24,8 @@
#include "EndpointDescriptor.h"
#include "SSEndpointCompanionDescriptor.h"
#include "BOSDescriptor.h"
#include "BOSDevCapabilityDescriptor.h"
#include "Usb20ExtensionDescriptor.h"
#include "Transfer.h"
static JavaVM *jvm;
@ -781,6 +783,45 @@ JNIEXPORT void JNICALL METHOD_NAME(LibUsb, freeBOSDescriptor)
resetBOSDescriptor(env, bosDescriptor);
}
/**
* int getUsb20ExtensionDescriptor(Context, BOSDevCapabilityDescriptor, Usb20ExtensionDescriptor)
*/
JNIEXPORT jint JNICALL METHOD_NAME(LibUsb, getUsb20ExtensionDescriptor)
(
JNIEnv *env, jclass class, jobject context, jobject devCapDescriptor,
jobject extensionDescriptor
)
{
NOT_NULL(env, devCapDescriptor, return 0);
NOT_NULL(env, extensionDescriptor, return 0);
libusb_context *ctx = unwrapContext(env, context);
struct libusb_bos_dev_capability_descriptor *devcap_descriptor =
unwrapBOSDevCapabilityDescriptor(env, devCapDescriptor);
if (!devcap_descriptor) return 0;
struct libusb_usb_2_0_extension_descriptor *extension_descriptor;
int result = libusb_get_usb_2_0_extension_descriptor(ctx,
devcap_descriptor, &extension_descriptor);
if (!result) setUsb20ExtensionDescriptor(env, extension_descriptor,
extensionDescriptor);
return result;
}
/**
* void freeUsb20ExtensionDescriptor(Usb20ExtensionDescriptor)
*/
JNIEXPORT void JNICALL METHOD_NAME(LibUsb, freeUsb20ExtensionDescriptor)
(
JNIEnv *env, jclass class, jobject extensionDescriptor
)
{
if (!extensionDescriptor) return;
struct libusb_usb_2_0_extension_descriptor *extension_descriptor =
unwrapUsb20ExtensionDescriptor(env, extensionDescriptor);
if (!extension_descriptor) return;
libusb_free_usb_2_0_extension_descriptor(extension_descriptor);
resetUsb20ExtensionDescriptor(env, extensionDescriptor);
}
/**
* int getDescriptor(DeviceHandle, int, int, ByteBuffer)
*/

View File

@ -20,4 +20,5 @@ libusb4java_la_SOURCES = \
Transfer.c \
SSEndpointCompanionDescriptor.c \
BOSDescriptor.c \
BOSDevCapabilityDescriptor.c
BOSDevCapabilityDescriptor.c \
Usb20ExtensionDescriptor.c

View File

@ -0,0 +1,83 @@
/*
* Copyright (C) 2013 Klaus Reimer (k@ailis.de)
* See COPYING file for copying conditions
*/
#include "Usb20ExtensionDescriptor.h"
void setUsb20ExtensionDescriptor(JNIEnv* env,
struct libusb_usb_2_0_extension_descriptor* descriptor, jobject object)
{
SET_POINTER(env, descriptor, object, "usb20ExtensionDescriptorPointer");
}
struct libusb_usb_2_0_extension_descriptor* unwrapUsb20ExtensionDescriptor(
JNIEnv* env, jobject descriptor)
{
UNWRAP_POINTER(env, descriptor,
struct libusb_usb_2_0_extension_descriptor*,
"usb20ExtensionDescriptorPointer");
}
void resetUsb20ExtensionDescriptor(JNIEnv* env, jobject obj)
{
RESET_POINTER(env, obj, "usb20ExtensionDescriptorPointer");
}
/**
* byte bLength()
*/
JNIEXPORT jbyte JNICALL METHOD_NAME(Usb20ExtensionDescriptor, bLength)
(
JNIEnv *env, jobject this
)
{
struct libusb_usb_2_0_extension_descriptor *descriptor =
unwrapUsb20ExtensionDescriptor(env, this);
if (!descriptor) return 0;
return descriptor->bLength;
}
/**
* byte bDescriptorType()
*/
JNIEXPORT jbyte JNICALL METHOD_NAME(Usb20ExtensionDescriptor, bDescriptorType)
(
JNIEnv *env, jobject this
)
{
struct libusb_usb_2_0_extension_descriptor *descriptor =
unwrapUsb20ExtensionDescriptor(env, this);
if (!descriptor) return 0;
return descriptor->bDescriptorType;
}
/**
* byte bDevCapabilityType()
*/
JNIEXPORT jbyte JNICALL METHOD_NAME(Usb20ExtensionDescriptor,
bDevCapabilityType)
(
JNIEnv *env, jobject this
)
{
struct libusb_usb_2_0_extension_descriptor *descriptor =
unwrapUsb20ExtensionDescriptor(env, this);
if (!descriptor) return 0;
return descriptor->bDevCapabilityType;
}
/**
* int bDevCapabilityType()
*/
JNIEXPORT jint JNICALL METHOD_NAME(Usb20ExtensionDescriptor,
bmAttributes)
(
JNIEnv *env, jobject this
)
{
struct libusb_usb_2_0_extension_descriptor *descriptor =
unwrapUsb20ExtensionDescriptor(env, this);
if (!descriptor) return 0;
return descriptor->bmAttributes;
}

View File

@ -0,0 +1,17 @@
/*
* Copyright (C) 2013 Klaus Reimer (k@ailis.de)
* See COPYING file for copying conditions
*/
#ifndef USB4JAVA_USB_2_0_EXTENSION_DESCRIPTOR_H
#define USB4JAVA_USB_2_0_EXTENSION_DESCRIPTOR_H
#include "usb4java.h"
void setUsb20ExtensionDescriptor(JNIEnv*,
struct libusb_usb_2_0_extension_descriptor*, jobject);
struct libusb_usb_2_0_extension_descriptor*
unwrapUsb20ExtensionDescriptor(JNIEnv*, jobject);
void resetUsb20ExtensionDescriptor(JNIEnv*, jobject);
#endif

View File

@ -1494,6 +1494,40 @@ public final class LibUsb
public static native void freeBOSDescriptor(final BOSDescriptor
descriptor);
/**
* Get an USB 2.0 Extension descriptor.
*
* @param context
* The context to operate on, or NULL for the default context.
* @param devCapDescriptor
* Device Capability descriptor with a bDevCapabilityType of
* {@link #BT_USB_2_0_EXTENSION}.
* @param extensionDescriptor
* Output location for the USB 2.0 Extension descriptor. Only
* valid if 0 was returned. Must be freed with
* {@link #freeUsb20ExtensionDescriptor(
* Usb20ExtensionDescriptor)} after use.
* @return 0 on success a LIBUSB_ERROR code on error
*/
public static native int getUsb20ExtensionDescriptor(
final Context context,
final BOSDevCapabilityDescriptor devCapDescriptor,
final Usb20ExtensionDescriptor extensionDescriptor);
/**
* Free a USB 2.0 Extension descriptor obtained from
* {@link #getUsb20ExtensionDescriptor(Context, BOSDevCapabilityDescriptor,
* Usb20ExtensionDescriptor)}.
*
* It is safe to call this function with a NULL parameter, in which case
* the function simply returns.
*
* @param extensionDescriptor
* The USB 2.0 Extension descriptor to free.
*/
public static native void freeUsb20ExtensionDescriptor(
final Usb20ExtensionDescriptor extensionDescriptor);
/**
* Retrieve a descriptor from the default control pipe.
*

View File

@ -0,0 +1,134 @@
/*
* Copyright 2013 Klaus Reimer <k@ailis.de>
* See LICENSE.md for licensing information.
*
* Based on libusb <http://www.libusb.org/>:
*
* Copyright 2001 Johannes Erdfelt <johannes@erdfelt.com>
* Copyright 2007-2009 Daniel Drake <dsd@gentoo.org>
* Copyright 2010-2012 Peter Stuge <peter@stuge.se>
* Copyright 2008-2011 Nathan Hjelm <hjelmn@users.sourceforge.net>
* Copyright 2009-2012 Pete Batard <pete@akeo.ie>
* Copyright 2009-2012 Ludovic Rousseau <ludovic.rousseau@gmail.com>
* Copyright 2010-2012 Michael Plante <michael.plante@gmail.com>
* Copyright 2011-2012 Hans de Goede <hdegoede@redhat.com>
* Copyright 2012 Martin Pieuchot <mpi@openbsd.org>
* Copyright 2012-2013 Toby Gray <toby.gray@realvnc.com>
*/
package de.ailis.usb4java.libusb;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
/**
* A structure representing the USB 2.0 Extension descriptor. This descriptor is
* documented in section 9.6.2.1 of the USB 3.0 specification.
*
* All multiple-byte fields are represented in host-endian format.
*
* @author Klaus Reimer (k@ailis.de)
*/
public final class Usb20ExtensionDescriptor
{
/** The native pointer to the descriptor structure. */
private long usb20ExtensionDescriptorPointer;
/**
* Constructs a new BOS descriptor which can be passed to the
* {@link LibUsb#getUsb20ExtensionDescriptor(Context,
* BOSDevCapabilityDescriptor, Usb20ExtensionDescriptor)} method.
*/
public Usb20ExtensionDescriptor()
{
// Empty
}
/**
* Returns the native pointer.
*
* @return The native pointer.
*/
public long getPointer()
{
return this.usb20ExtensionDescriptorPointer;
}
/**
* Returns the size of this descriptor (in bytes).
*
* @return The descriptor size in bytes;
*/
public native byte bLength();
/**
* Returns the descriptor type.
*
* @return The descriptor type.
*/
public native byte bDescriptorType();
/**
* Returns the device capability type.
*
* @return The device capability type.
*/
public native byte bDevCapabilityType();
/**
* Returns the bitmap of supported device level features.
*
* @return The supported device level features.
*/
public native int bmAttributes();
/**
* Returns a dump of this descriptor.
*
* @return The descriptor dump.
*/
public String dump()
{
return String.format("USB 2.0 Extension Descriptor:%n"
+ " bLength %18d%n"
+ " bDescriptorType %10d%n"
+ " bDevCapabilityType %7d%n"
+ " bmAttributes %13s%n",
bLength() & 0xff,
bDescriptorType() & 0xff,
bDevCapabilityType() & 0xff,
String.format("0x%08x", bmAttributes() & 0xffffffff));
}
@Override
public boolean equals(final Object obj)
{
if (obj == null) return false;
if (obj == this) return true;
if (obj.getClass() != getClass()) return false;
final Usb20ExtensionDescriptor other =
(Usb20ExtensionDescriptor) obj;
return new EqualsBuilder()
.append(bDescriptorType(), other.bDescriptorType())
.append(bLength(), other.bLength())
.append(bDevCapabilityType(), other.bDevCapabilityType())
.append(bmAttributes(), other.bmAttributes()).isEquals();
}
@Override
public int hashCode()
{
return new HashCodeBuilder()
.append(bLength())
.append(bDescriptorType())
.append(bDevCapabilityType())
.append(bmAttributes())
.toHashCode();
}
@Override
public String toString()
{
return dump();
}
}

View File

@ -731,6 +731,58 @@ public class LibUSBTest
LibUsb.freeBOSDescriptor(null);
}
/**
* Tests the
* {@link LibUsb#getUsb20ExtensionDescriptor(Context,
* BOSDevCapabilityDescriptor, Usb20ExtensionDescriptor)}
* method with uninitialized endpoint.
*/
@Test(expected = IllegalStateException.class)
public void testGetUsb20ExtensionDescriptorWithUninitializedEndpoint()
{
assumeUsbTestsEnabled();
LibUsb.getUsb20ExtensionDescriptor(null,
new BOSDevCapabilityDescriptor(),
new Usb20ExtensionDescriptor());
}
/**
* Tests the
* {@link LibUsb#getUsb20ExtensionDescriptor(Context,
* BOSDevCapabilityDescriptor, Usb20ExtensionDescriptor)}
* method without descriptors.
*/
@Test(expected = IllegalArgumentException.class)
public void testGetUsb20ExtensionDescriptorWithoutDescriptors()
{
assumeUsbTestsEnabled();
LibUsb.getUsb20ExtensionDescriptor(null, null, null);
}
/**
* Tests the
* {@link LibUsb#freeUsb20ExtensionDescriptor(Usb20ExtensionDescriptor)}
* method with uninitialized descriptor.
*/
@Test(expected = IllegalStateException.class)
public void testFreeUsb20ExtensionDescriptorWithUninitializedDescriptor()
{
assumeUsbTestsEnabled();
LibUsb.freeUsb20ExtensionDescriptor(new Usb20ExtensionDescriptor());
}
/**
* Tests the
* {@link LibUsb#freeUsb20ExtensionDescriptor(Usb20ExtensionDescriptor)}
* method with null parameter. Must do nothing.
*/
@Test
public void testFreeUsb20ExtensionDescriptorWithNull()
{
assumeUsbTestsEnabled();
LibUsb.freeUsb20ExtensionDescriptor(null);
}
/**
* Tests the
* {@link LibUsb#getDescriptor(DeviceHandle, int, int, ByteBuffer)} method

View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2013 Klaus Reimer <k@ailis.de>
* See LICENSE.md for licensing information.
*/
package de.ailis.usb4java.libusb;
import static de.ailis.usb4java.test.UsbAssume.assumeUsbTestsEnabled;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Tests the {@link Usb20ExtensionDescriptor} class.
*
* @author Klaus Reimer (k@ailis.de)
*/
public class Usb20ExtensionDescriptorTest
{
/** The test subject. */
private Usb20ExtensionDescriptor descriptor;
/**
* Setup test.
*/
@Before
public void setUp()
{
assumeUsbTestsEnabled();
LibUsb.init(null);
this.descriptor = new Usb20ExtensionDescriptor();
}
/**
* Tear down test.
*/
@After
public void tearDown()
{
LibUsb.exit(null);
}
/**
* Tests uninitialized access to
* {@link Usb20ExtensionDescriptor#bLength()}
*/
@Test(expected = IllegalStateException.class)
public void testUninitializedLength()
{
assumeUsbTestsEnabled();
this.descriptor.bLength();
}
/**
* Tests uninitialized access to
* {@link Usb20ExtensionDescriptor#bDescriptorType()}
*/
@Test(expected = IllegalStateException.class)
public void testUninitializedDescriptorType()
{
assumeUsbTestsEnabled();
this.descriptor.bDescriptorType();
}
/**
* Tests uninitialized access to
* {@link Usb20ExtensionDescriptor#bDevCapabilityType()}
*/
@Test(expected = IllegalStateException.class)
public void testUninitializedDevCapabilityType()
{
assumeUsbTestsEnabled();
this.descriptor.bDevCapabilityType();
}
/**
* Tests uninitialized access to
* {@link Usb20ExtensionDescriptor#bmAttributes()}
*/
@Test(expected = IllegalStateException.class)
public void testUninitializedAttributes()
{
assumeUsbTestsEnabled();
this.descriptor.bmAttributes();
}
}