]> sigrok.org Git - sigrok-util.git/commitdiff
sigrok-cross-android: Provide a USB open hook for libusb running under JVM
authorMarcus Comstedt <redacted>
Sun, 6 Jul 2014 14:55:19 +0000 (16:55 +0200)
committerUwe Hermann <redacted>
Mon, 25 Aug 2014 20:38:43 +0000 (22:38 +0200)
cross-compile/android/libusb-1.0.patch

index 5154bf01f054aa78b5dd2aca432e559b56cdb9cd..4e5aeacc9be1dfc2b6ded456c3ba706a4722bee0 100644 (file)
@@ -16,3 +16,120 @@ diff -urp libusb-1.0.9.orig/libusb/io.c libusb-1.0.9/libusb/io.c
  /**
   * \page io Synchronous and asynchronous device I/O
   *
+diff -urp libusbx-1.0.17.orig/libusb/os/linux_usbfs.c libusbx-1.0.17/libusb/os/linux_usbfs.c
+--- libusbx-1.0.17.orig/libusb/os/linux_usbfs.c        2014-07-05 23:14:45.487803220 +0200
++++ libusbx-1.0.17/libusb/os/linux_usbfs.c     2014-07-06 16:42:17.013481236 +0200
+@@ -37,11 +37,21 @@
+ #include <sys/types.h>
+ #include <sys/utsname.h>
+ #include <unistd.h>
++#ifdef __ANDROID__
++#include <jni.h>
++#endif
+ #include "libusb.h"
+ #include "libusbi.h"
+ #include "linux_usbfs.h"
++#ifdef __ANDROID__
++static JavaVM *g_jvm = NULL;
++static jclass usb_helper_class;
++static jmethodID usb_helper_open_mid;
++static int usb_helper_open(const char *pathname, int flags);
++#endif
++
+ /* sysfs vs usbfs:
+  * opening a usbfs node causes the device to be resumed, so we attempt to
+  * avoid this during enumeration.
+@@ -192,6 +202,11 @@
+               snprintf(path, PATH_MAX, "%s/%03d/%03d",
+                       usbfs_path, dev->bus_number, dev->device_address);
++#ifdef __ANDROID__
++      if (g_jvm)
++              fd = usb_helper_open(path, mode);
++      else
++#endif
+       fd = open(path, mode);
+       if (fd != -1)
+               return fd; /* Success */
+@@ -2603,3 +2618,79 @@
+       .transfer_priv_size = sizeof(struct linux_transfer_priv),
+       .add_iso_packet_size = 0,
+ };
++
++#ifdef __ANDROID__
++jint JNI_OnLoad(JavaVM *vm, void *reserved)
++{
++      JNIEnv* env;
++      g_jvm = vm;
++      if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) {
++              return -1;
++      }
++
++      jclass helper = (*env)->FindClass(env, "org/sigrok/androidutils/UsbHelper");
++
++      if (helper) {
++
++              usb_helper_class = (jclass)(*env)->NewGlobalRef(env, helper);
++
++              usb_helper_open_mid = (*env)->GetStaticMethodID(env, helper, "open",
++                                                              "(Ljava/lang/String;I)I");
++              (*env)->DeleteLocalRef(env, helper);
++
++      } else {
++              if ((*env)->ExceptionCheck(env)) {
++                      (*env)->ExceptionClear(env);
++              }
++              g_jvm = NULL;
++      }
++
++      return JNI_VERSION_1_6;
++}
++
++void JNI_OnUnload(JavaVM *vm, void *reserved)
++{
++      JNIEnv* env;
++      if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) {
++              return;
++      }
++
++      jclass helper = usb_helper_class;
++      usb_helper_class = NULL;
++      if (helper)
++              (*env)->DeleteGlobalRef(env, helper);
++      g_jvm = NULL;
++}
++
++static int usb_helper_open(const char *pathname, int flags)
++{
++      JNIEnv* env;
++      int res;
++      jint st;
++      int do_detach = 0;
++
++      if (g_jvm == NULL) {
++              return -1;
++      }
++      st = (*g_jvm)->GetEnv(g_jvm, (void **)&env, JNI_VERSION_1_6);
++
++      if (st == JNI_EDETACHED) {
++              st = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
++              do_detach = 1;
++      }
++
++      if (st != JNI_OK) {
++              return -1;
++      }
++
++      jstring string = (*env)->NewStringUTF(env, pathname);
++      res = (*env)->CallStaticIntMethod(env, usb_helper_class, usb_helper_open_mid, string, (jint)flags);
++      (*env)->DeleteLocalRef(env, string);
++
++      if (do_detach) {
++              (*g_jvm)->DetachCurrentThread(g_jvm);
++      }
++
++      return res;
++}
++#endif