Skip to content

Commit bdd465a

Browse files
committed
checkpoint
1 parent e3a448c commit bdd465a

17 files changed

Lines changed: 738 additions & 124 deletions

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>
99
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
1010
<uses-feature android:name="android.hardware.faketouch" android:required="false"/>
11+
<uses-feature android:name="android.hardware.usb.host" android:required="false"/>
1112
<uses-feature android:name="android.hardware.type.pc" android:required="false"/>
1213
<uses-feature android:name="android.software.app_widgets" android:required="false"/>
1314

hificore/src/main/cpp/libusb/async_usb_thread.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ Java_com_jwoolston_libusb_AsyncUSBThread_nativeHandleEvents(JNIEnv *env, jclass
3232
}
3333

3434
JNIEXPORT void JNICALL
35-
Java_com_jwoolston_libusb_AsyncUSBThread_nativeShutdown(JNIEnv *env, jclass clazz, jlong context) {
36-
struct libusb_context *ctx = (libusb_context *) context;
37-
libusb_lock_events(ctx);
35+
Java_com_jwoolston_libusb_AsyncUSBThread_nativeShutdown(JNIEnv *env, jclass clazz) {
3836
completed = 1;
39-
libusb_unlock_events(ctx);
4037
}

hificore/src/main/cpp/libusb/logging.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ void uacLog(jmethodID method, const char *tag, const char *fmt, va_list args) {
4141
vsnprintf(&message[0], sizeof(message), fmt, args);
4242
jstring messageString = (*jniEnv)->NewStringUTF(jniEnv, message);
4343

44-
jobject branch = (*jniEnv)->CallStaticObjectMethod(jniEnv, uac_logClass, method, tagString, messageString);
44+
(*jniEnv)->CallStaticVoidMethod(jniEnv, uac_logClass, method, tagString, messageString);
4545
if ((*jniEnv)->ExceptionOccurred(jniEnv)) {
4646
#ifdef __ANDROID__
4747
__android_log_print(ANDROID_LOG_ERROR, "Native Log", "Native logging failed");

hificore/src/main/cpp/libusb/usb_configuration.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,39 @@ Java_com_jwoolston_libusb_UsbConfiguration_nativeGetInterface(JNIEnv *env, jclas
4646
libusb_interface)));
4747
}
4848

49+
JNIEXPORT jobject JNICALL
50+
Java_com_jwoolston_libusb_UsbConfiguration_nativeGetInterfaceAssociationArray(JNIEnv *env, jclass type, jlong device,
51+
jint configuration) {
52+
struct libusb_device_handle *deviceHandle = (struct libusb_device_handle *) device;
53+
54+
struct libusb_interface_association_descriptor_array* out = NULL;
55+
int ret = libusb_get_interface_association_descriptors(libusb_get_device(deviceHandle),
56+
configuration, &out);
57+
if (ret != LIBUSB_SUCCESS) {
58+
LOGE("Failed to get IAD: %d", ret);
59+
return NULL;
60+
}
61+
62+
return ((*env)->NewDirectByteBuffer(env, (void *) (out), out->length));
63+
}
64+
65+
JNIEXPORT jobject JNICALL
66+
Java_com_jwoolston_libusb_UsbConfiguration_nativeGetInterfaceAssociation(JNIEnv *env, jclass type, jobject array,
67+
jint index) {
68+
struct libusb_interface_association_descriptor_array* arrayPtr =
69+
(*env)->GetDirectBufferAddress(env, array);
70+
71+
return ((*env)->NewDirectByteBuffer(env, (void *) (&arrayPtr->iad[index]),
72+
sizeof(struct libusb_interface_association_descriptor)));
73+
}
74+
75+
JNIEXPORT void JNICALL
76+
Java_com_jwoolston_libusb_UsbConfiguration_nativeDestroyInterfaceAssociationArray(JNIEnv *env, jclass type, jobject array) {
77+
struct libusb_interface_association_descriptor_array* arrayPtr =
78+
(*env)->GetDirectBufferAddress(env, array);
79+
libusb_free_interface_association_descriptors(arrayPtr);
80+
}
81+
4982
JNIEXPORT jobject JNICALL
5083
Java_com_jwoolston_libusb_UsbConfiguration_nativeGetExtra(JNIEnv *env, jclass type, jobject nativeObject) {
5184
struct libusb_config_descriptor *config = (struct libusb_config_descriptor *)

hificore/src/main/cpp/libusb/usb_device.c

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -304,27 +304,6 @@ JNIEXPORT void JNICALL
304304
Java_com_jwoolston_libusb_UsbDevice_nativeClose(JNIEnv *env, jobject instance, jlong device) {
305305
struct libusb_device_handle *deviceHandle = (struct libusb_device_handle *) device;
306306
libusb_close(deviceHandle);
307-
if (deviceHandle != NULL) {
308-
free(deviceHandle);
309-
}
310-
}
311-
312-
JNIEXPORT jbyteArray JNICALL
313-
Java_com_jwoolston_libusb_UsbDevice_nativeGetRawDescriptor(JNIEnv *env, jobject instance, jint fd) {
314-
char buffer[16384];
315-
if (fd < 0) return NULL;
316-
lseek(fd, 0, SEEK_SET);
317-
int length = read(fd, buffer, sizeof(buffer));
318-
if (length < 0) return NULL;
319-
jbyteArray ret = (*env)->NewByteArray(env, length);
320-
if (ret) {
321-
jbyte *bytes = (jbyte *) (*env)->GetPrimitiveArrayCritical(env, ret, 0);
322-
if (bytes) {
323-
memcpy(bytes, buffer, (size_t) length);
324-
(*env)->ReleasePrimitiveArrayCritical(env, ret, bytes, 0);
325-
}
326-
}
327-
return ret;
328307
}
329308

330309
JNIEXPORT jint JNICALL
@@ -336,27 +315,37 @@ Java_com_jwoolston_libusb_UsbDevice_nativeClearStall(JNIEnv *env, jobject instan
336315

337316
JNIEXPORT jint JNICALL
338317
Java_com_jwoolston_libusb_UsbDevice_nativeClaimInterface(JNIEnv *env, jobject instance,
339-
jlong device, jint interfaceID,
340-
jboolean force) {
318+
jlong device, jint interfaceID) {
341319
struct libusb_device_handle *deviceHandle = (struct libusb_device_handle *) device;
342-
jint ret = libusb_claim_interface(deviceHandle, interfaceID);
343-
if (ret == LIBUSB_ERROR_BUSY && force) {
344-
libusb_detach_kernel_driver(deviceHandle, interfaceID);
345-
ret = libusb_claim_interface(deviceHandle, interfaceID);
346-
}
347-
return ret;
320+
return libusb_claim_interface(deviceHandle, interfaceID);
348321
}
349322

350323
JNIEXPORT jint JNICALL
351324
Java_com_jwoolston_libusb_UsbDevice_nativeReleaseInterface(JNIEnv *env, jobject instance,
352-
jlong device, jint interfaceID,
353-
jboolean force) {
325+
jlong device, jint interfaceID) {
354326
struct libusb_device_handle *deviceHandle = (struct libusb_device_handle *) device;
355-
int ret = libusb_release_interface(deviceHandle, interfaceID);
356-
if ((ret == LIBUSB_SUCCESS || ret == LIBUSB_ERROR_NOT_FOUND) && force) {
357-
ret = libusb_attach_kernel_driver(deviceHandle, interfaceID);
358-
}
359-
return ret;
327+
return libusb_release_interface(deviceHandle, interfaceID);
328+
}
329+
330+
JNIEXPORT jint JNICALL
331+
Java_com_jwoolston_libusb_UsbDevice_nativeHasKernelDriver(JNIEnv *env, jobject thiz,
332+
jlong device, jint interface_id) {
333+
struct libusb_device_handle *deviceHandle = (struct libusb_device_handle *) device;
334+
return libusb_kernel_driver_active(deviceHandle, interface_id);
335+
}
336+
337+
JNIEXPORT jint JNICALL
338+
Java_com_jwoolston_libusb_UsbDevice_nativeAttachKernelDriver(JNIEnv *env, jobject thiz,
339+
jlong device, jint interface_id) {
340+
struct libusb_device_handle *deviceHandle = (struct libusb_device_handle *) device;
341+
return libusb_attach_kernel_driver(deviceHandle, interface_id);
342+
}
343+
344+
JNIEXPORT jint JNICALL
345+
Java_com_jwoolston_libusb_UsbDevice_nativeDetachKernelDriver(JNIEnv *env, jobject thiz,
346+
jlong device, jint interface_id) {
347+
struct libusb_device_handle *deviceHandle = (struct libusb_device_handle *) device;
348+
return libusb_detach_kernel_driver(deviceHandle, interface_id);
360349
}
361350

362351
JNIEXPORT jint JNICALL
@@ -366,6 +355,18 @@ Java_com_jwoolston_libusb_UsbDevice_nativeSetInterface(JNIEnv *env, jobject inst
366355
return libusb_set_interface_alt_setting(deviceHandle, interfaceID, alternateSetting);
367356
}
368357

358+
JNIEXPORT jint JNICALL
359+
Java_com_jwoolston_libusb_UsbDevice_nativeGetConfiguration(JNIEnv *env, jobject instance,
360+
jlong device) {
361+
struct libusb_device_handle *deviceHandle = (struct libusb_device_handle *) device;
362+
int config;
363+
int ret = libusb_get_configuration(deviceHandle, &config);
364+
if (ret < 0) {
365+
return ret;
366+
}
367+
return config;
368+
}
369+
369370
JNIEXPORT jint JNICALL
370371
Java_com_jwoolston_libusb_UsbDevice_nativeSetConfiguration(JNIEnv *env, jobject instance,
371372
jlong device, jint configurationID) {

hificore/src/main/cpp/libusb/usb_manager.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,25 @@
2020
#include "common.h"
2121

2222
#define LOG_TAG "UsbManager-Native"
23+
#define LOG_CB_TAG "libusb"
24+
25+
void log_cb(libusb_context *ctx, enum libusb_log_level level, const char *str) {
26+
switch (level) {
27+
case LIBUSB_LOG_LEVEL_ERROR:
28+
__uac_log_error(LOG_CB_TAG, "%s", str);
29+
break;
30+
case LIBUSB_LOG_LEVEL_WARNING:
31+
default:
32+
__uac_log_warn(LOG_CB_TAG, "%s", str);
33+
break;
34+
case LIBUSB_LOG_LEVEL_INFO:
35+
__uac_log_info(LOG_CB_TAG, "%s", str);
36+
break;
37+
case LIBUSB_LOG_LEVEL_DEBUG:
38+
__uac_log_debug(LOG_CB_TAG, "%s", str);
39+
break;
40+
}
41+
}
2342

2443
JNIEXPORT jlong JNICALL
2544
Java_com_jwoolston_libusb_UsbManager_nativeInitialize(JNIEnv *env, jobject instance) {
@@ -34,6 +53,7 @@ Java_com_jwoolston_libusb_UsbManager_nativeInitialize(JNIEnv *env, jobject insta
3453
LOGE("Initialization returned: %i", r);
3554
return 0;
3655
} else {
56+
libusb_set_log_cb(ctx, log_cb, LIBUSB_LOG_CB_CONTEXT);
3757
return (jlong)ctx;
3858
}
3959
}

hificore/src/main/java/com/jwoolston/libusb/AsyncUSBThread.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ public class AsyncUSBThread extends Thread {
3636
}
3737

3838
void shutdown() {
39-
nativeShutdown(context.getNativeObject());
39+
nativeShutdown();
4040
}
4141

4242
@Override
4343
public void run() {
4444
nativeHandleEvents(context.getNativeObject());
4545
}
4646

47-
private static native void nativeShutdown(long context);
47+
private static native void nativeShutdown();
4848
private static native void nativeHandleEvents(long context);
4949
}

hificore/src/main/java/com/jwoolston/libusb/UsbConfiguration.java

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,24 @@ public class UsbConfiguration implements Parcelable {
5757
@NotNull
5858
UsbInterface[] interfaces;
5959

60+
/**
61+
* All interface associations for this config
62+
*/
63+
@NotNull
64+
UsbInterfaceAssociation[] interfaceAssociations;
65+
6066
final byte[] extra;
6167

6268
/**
6369
* UsbConfiguration should only be instantiated by UsbService implementation
6470
*/
65-
public UsbConfiguration(int id, @Nullable String name, int attributes, int maxPower, UsbInterface[] interfaces, byte[] extra) {
71+
private UsbConfiguration(int id, @Nullable String name, int attributes, int maxPower, UsbInterface[] interfaces, UsbInterfaceAssociation[] interfaceAssociations, byte[] extra) {
6672
this.id = id;
6773
this.name = name;
6874
this.attributes = attributes;
6975
this.maxPower = maxPower;
7076
this.interfaces = interfaces;
77+
this.interfaceAssociations = interfaceAssociations;
7178
this.extra = extra;
7279
}
7380

@@ -139,6 +146,25 @@ UsbInterface getInterface(int index) {
139146
return interfaces[index];
140147
}
141148

149+
/**
150+
* Returns the number of {@link UsbInterfaceAssociation}s this configuration contains.
151+
*
152+
* @return the number of endpoints
153+
*/
154+
public int getInterfaceAssociationCount() {
155+
return interfaceAssociations.length;
156+
}
157+
158+
/**
159+
* Returns the {@link UsbInterface} at the given index.
160+
*
161+
* @return the interface
162+
*/
163+
public @NotNull
164+
UsbInterfaceAssociation getInterfaceAssociation(int index) {
165+
return interfaceAssociations[index];
166+
}
167+
142168
public byte[] getExtra() {
143169
return extra;
144170
}
@@ -152,6 +178,7 @@ public String toString() {
152178
", attributes=" + attributes +
153179
", maxPower=" + maxPower +
154180
", interfaces=" + Arrays.toString(interfaces) +
181+
", interfaceAssociations=" + Arrays.toString(interfaceAssociations) +
155182
", extra=" + Arrays.toString(extra) +
156183
'}';
157184
}
@@ -164,8 +191,9 @@ public UsbConfiguration createFromParcel(Parcel in) {
164191
int attributes = in.readInt();
165192
int maxPower = in.readInt();
166193
UsbInterface[] interfaces = (UsbInterface[]) in.readParcelableArray(UsbInterface.class.getClassLoader());
194+
UsbInterfaceAssociation[] interfaceAssociations = (UsbInterfaceAssociation[]) in.readParcelableArray(UsbInterfaceAssociation.class.getClassLoader());
167195
byte[] extra = in.createByteArray();
168-
UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower, interfaces, extra);
196+
UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower, interfaces, interfaceAssociations, extra);
169197
return configuration;
170198
}
171199

@@ -186,6 +214,7 @@ public void writeToParcel(Parcel parcel, int flags) {
186214
parcel.writeInt(attributes);
187215
parcel.writeInt(maxPower);
188216
parcel.writeParcelableArray((Parcelable[]) interfaces, 0);
217+
parcel.writeParcelableArray((Parcelable[]) interfaceAssociations, 0);
189218
parcel.writeByteArray(extra);
190219
}
191220

@@ -213,11 +242,26 @@ static UsbConfiguration fromNativeObject(@NotNull UsbDevice device, int configur
213242
List<UsbInterface> usbInterface = UsbInterface.fromNativeObject(device, nativeInterface);
214243
usbInterfaces.addAll(usbInterface);
215244
}
245+
final List<UsbInterfaceAssociation> usbInterfaceAssociations = new ArrayList<>();
246+
// Get the native IAD array. Make sure you free it!
247+
final ByteBuffer associationArray = nativeGetInterfaceAssociationArray(device.getNativeObject(), configuration);
248+
if (associationArray == null) {
249+
nativeDestroy(nativeObject);
250+
throw new IllegalStateException("Failed to get Interface Association Descriptor Array");
251+
}
252+
// using ByteBuffer's length / capacity here is a bit hacky, but native plays along
253+
for (int i = 0; i < associationArray.capacity(); ++i) {
254+
ByteBuffer nativeInterface = nativeGetInterfaceAssociation(associationArray, i);
255+
UsbInterfaceAssociation usbInterface = UsbInterfaceAssociation.fromNativeDescriptor(device, nativeInterface);
256+
usbInterfaceAssociations.add(usbInterface);
257+
}
258+
nativeDestroyInterfaceAssociationArray(associationArray);
216259
ByteBuffer extraTmp = nativeGetExtra(nativeObject);
217260
ByteBuffer extra = ByteBuffer.allocate(extraTmp.capacity());
218261
extra.put(extraTmp);
219262
final UsbConfiguration usbConfiguration = new UsbConfiguration(id, name, attributes,
220-
maxPower, usbInterfaces.toArray(new UsbInterface[0]), extra.array());
263+
maxPower, usbInterfaces.toArray(new UsbInterface[0]),
264+
usbInterfaceAssociations.toArray(new UsbInterfaceAssociation[0]), extra.array());
221265

222266
// Destroy the native configuration object
223267
nativeDestroy(nativeObject);
@@ -234,6 +278,13 @@ static UsbConfiguration fromNativeObject(@NotNull UsbDevice device, int configur
234278
*/
235279
private static native ByteBuffer nativeGetInterface(@NonNull ByteBuffer nativeObject, int interfaceIndex);
236280

281+
@Nullable
282+
private static native ByteBuffer nativeGetInterfaceAssociationArray(long device, int interfaceIndex);
283+
284+
private static native ByteBuffer nativeGetInterfaceAssociation(@NonNull ByteBuffer nativeObject, int interfaceIndex);
285+
286+
private static native void nativeDestroyInterfaceAssociationArray(@NonNull ByteBuffer nativeObject);
287+
237288
private static native ByteBuffer nativeGetExtra(@NonNull ByteBuffer nativeObject);
238289

239290
private static native void nativeDestroy(@NonNull ByteBuffer nativeObject);

0 commit comments

Comments
 (0)