X-Git-Url: https://sigrok.org/gitweb/?p=sigrok-util.git;a=blobdiff_plain;f=cross-compile%2Fandroid%2Flibusb-1.0.patch;h=27070e618ddbb585ed28f75974864de6eac506eb;hp=5154bf01f054aa78b5dd2aca432e559b56cdb9cd;hb=b1181fe12749e653f74285f71edd09dd6fc859ff;hpb=13b2dfdc90c4533b3bd651ef79f5bc2c40422f5d diff --git a/cross-compile/android/libusb-1.0.patch b/cross-compile/android/libusb-1.0.patch index 5154bf0..27070e6 100644 --- a/cross-compile/android/libusb-1.0.patch +++ b/cross-compile/android/libusb-1.0.patch @@ -16,3 +16,383 @@ 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 * +--- libusb-1.0.19.orig/libusb/os/linux_usbfs.c 2014-05-30 11:18:28.000000000 +0200 ++++ libusb-1.0.19/libusb/os/linux_usbfs.c 2016-11-26 15:38:21.199383120 +0100 +@@ -37,11 +37,31 @@ + #include + #include + #include ++#ifdef __ANDROID__ ++#include ++#endif + + #include "libusb.h" + #include "libusbi.h" + #include "linux_usbfs.h" + ++#ifdef __ANDROID__ ++static JavaVM *g_jvm = NULL; ++static jclass usb_helper_class; ++static jclass usb_event_listener_class; ++static jmethodID usb_helper_open_mid; ++static jmethodID usb_helper_start_event_monitor_mid; ++static jmethodID usb_helper_stop_event_monitor_mid; ++static jmethodID usb_helper_scan_devices_mid; ++static jmethodID usb_event_listener_init_mid; ++static int usb_helper_open(const char *pathname, int flags); ++static int usb_helper_start_event_monitor(void); ++static int usb_helper_stop_event_monitor(void); ++static int usb_helper_scan_devices (struct libusb_context *ctx); ++static void usb_helper_hotplug_poll(void); ++static void usb_helper_on_usb_device_action(JNIEnv *env, jobject self, jstring name, jboolean removed); ++#endif ++ + /* sysfs vs usbfs: + * opening a usbfs node causes the device to be resumed, so we attempt to + * avoid this during enumeration. +@@ -193,6 +213,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 */ +@@ -369,6 +394,13 @@ + struct stat statbuf; + int r; + ++#ifdef __ANDROID__ ++ if (g_jvm) { ++ usbfs_path = "/dev/bus/usb"; ++ sysfs_can_relate_devices = 0; ++ sysfs_has_descriptors = 0; ++ } else ++#endif + usbfs_path = find_usbfs_path(); + if (!usbfs_path) { + usbi_err(ctx, "could not find usbfs"); +@@ -467,6 +499,10 @@ + + static int linux_start_event_monitor(void) + { ++#ifdef __ANDROID__ ++ if (g_jvm) ++ return usb_helper_start_event_monitor(); ++#endif + #if defined(USE_UDEV) + return linux_udev_start_event_monitor(); + #else +@@ -476,6 +512,10 @@ + + static int linux_stop_event_monitor(void) + { ++#ifdef __ANDROID__ ++ if (g_jvm) ++ return usb_helper_stop_event_monitor(); ++#endif + #if defined(USE_UDEV) + return linux_udev_stop_event_monitor(); + #else +@@ -489,6 +529,11 @@ + + usbi_mutex_static_lock(&linux_hotplug_lock); + ++#ifdef __ANDROID__ ++ if (g_jvm) ++ ret = usb_helper_scan_devices(ctx); ++ else ++#endif + #if defined(USE_UDEV) + ret = linux_udev_scan_devices(ctx); + #else +@@ -502,6 +547,11 @@ + + static void op_hotplug_poll(void) + { ++#ifdef __ANDROID__ ++ if (g_jvm) ++ usb_helper_hotplug_poll(); ++ else ++#endif + #if defined(USE_UDEV) + linux_udev_hotplug_poll(); + #else +@@ -994,6 +1044,10 @@ + /* XXX -- can we figure out the topology when using usbfs? */ + if (NULL == sysfs_dir || 0 == strncmp(sysfs_dir, "usb", 3)) { + /* either using usbfs or finding the parent of a root hub */ ++#ifdef __ANDROID__ ++ if (g_jvm) ++ dev->port_number = dev->device_address; ++#endif + return LIBUSB_SUCCESS; + } + +@@ -2693,3 +2747,262 @@ + .transfer_priv_size = sizeof(struct linux_transfer_priv), + .add_iso_packet_size = 0, + }; ++ ++#ifdef __ANDROID__ ++jint JNI_OnLoad(JavaVM *vm, void *reserved) ++{ ++ static JNINativeMethod jni_method = { ++ "onUsbDeviceAction", ++ "(Ljava/lang/String;Z)V", ++ (void*)usb_helper_on_usb_device_action ++ }; ++ ++ 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"); ++ jclass event_listener = (*env)->FindClass(env, "org/sigrok/androidutils/UsbEventListenerStub"); ++ ++ if (helper && event_listener) { ++ ++ usb_helper_class = (jclass)(*env)->NewGlobalRef(env, helper); ++ ++ usb_helper_open_mid = (*env)->GetStaticMethodID(env, helper, "open", ++ "(Ljava/lang/String;I)I"); ++ usb_helper_start_event_monitor_mid = (*env)->GetStaticMethodID(env, helper, "startEventMonitor", ++ "(Lorg/sigrok/androidutils/UsbEventListener;)V"); ++ usb_helper_stop_event_monitor_mid = (*env)->GetStaticMethodID(env, helper, "stopEventMonitor", ++ "()V"); ++ usb_helper_scan_devices_mid = (*env)->GetStaticMethodID(env, helper, "scanDevices", ++ "()[Ljava/lang/String;"); ++ (*env)->DeleteLocalRef(env, helper); ++ ++ usb_event_listener_class = (jclass)(*env)->NewGlobalRef(env, event_listener); ++ usb_event_listener_init_mid = (*env)->GetMethodID(env, event_listener, "", ++ "()V"); ++ if ((*env)->RegisterNatives(env, event_listener, &jni_method, 1) < 0) { ++ if ((*env)->ExceptionCheck(env)) { ++ (*env)->ExceptionClear(env); ++ } ++ g_jvm = NULL; ++ } ++ ++ (*env)->DeleteLocalRef(env, event_listener); ++ ++ } 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; ++ jclass event_listener = usb_event_listener_class; ++ usb_helper_class = NULL; ++ usb_event_listener_class = NULL; ++ if (helper) ++ (*env)->DeleteGlobalRef(env, helper); ++ if (event_listener) { ++ (*env)->UnregisterNatives(env, event_listener); ++ (*env)->DeleteGlobalRef(env, event_listener); ++ } ++ 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); ++ } ++ ++ if (res >= 0) { ++ /* Rewind so that descriptors can be read */ ++ lseek(res, SEEK_SET, 0); ++ } ++ ++ return res; ++} ++ ++static int usb_helper_start_event_monitor(void) ++{ ++ JNIEnv* env; ++ jint st; ++ int do_detach = 0; ++ int res = 0; ++ jobject usb_event_listener; ++ ++ if (g_jvm == NULL) { ++ return LIBUSB_ERROR_OTHER; ++ } ++ 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 LIBUSB_ERROR_OTHER; ++ } ++ ++ usb_event_listener = (*env)->NewObject(env, usb_event_listener_class, usb_event_listener_init_mid); ++ if (usb_event_listener == NULL) ++ res = LIBUSB_ERROR_OTHER; ++ else { ++ (*env)->CallStaticVoidMethod(env, usb_helper_class, usb_helper_start_event_monitor_mid, usb_event_listener); ++ (*env)->DeleteLocalRef(env, usb_event_listener); ++ } ++ ++ if (do_detach) { ++ (*g_jvm)->DetachCurrentThread(g_jvm); ++ } ++ ++ return res; ++} ++ ++static int usb_helper_stop_event_monitor(void) ++{ ++ JNIEnv* env; ++ jint st; ++ int do_detach = 0; ++ ++ if (g_jvm == NULL) { ++ return LIBUSB_ERROR_OTHER; ++ } ++ 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 LIBUSB_ERROR_OTHER; ++ } ++ ++ (*env)->CallStaticVoidMethod(env, usb_helper_class, usb_helper_stop_event_monitor_mid); ++ ++ if (do_detach) { ++ (*g_jvm)->DetachCurrentThread(g_jvm); ++ } ++ ++ return 0; ++} ++ ++static int usb_helper_scan_devices (struct libusb_context *ctx) ++{ ++ JNIEnv* env; ++ int res = 0; ++ jint st; ++ int do_detach = 0; ++ ++ if (g_jvm == NULL) { ++ return LIBUSB_ERROR_OTHER; ++ } ++ 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 LIBUSB_ERROR_OTHER; ++ } ++ ++ jobject arr = (*env)->CallStaticObjectMethod(env, usb_helper_class, usb_helper_scan_devices_mid); ++ ++ if (arr == NULL) ++ res = LIBUSB_ERROR_OTHER; ++ else { ++ jsize i, len = (*env)->GetArrayLength(env, arr); ++ for (i=0; iGetObjectArrayElement(env, arr, i); ++ if (str) { ++ const char *ustr = (*env)->GetStringUTFChars(env, str, NULL); ++ if (ustr) { ++ unsigned busnum, devaddr; ++ if (2 != sscanf(ustr, "/dev/bus/usb/%u/%u", ++ &busnum, &devaddr) || ++ linux_enumerate_device(ctx, busnum, devaddr, NULL)) { ++ usbi_dbg("failed to enumerate device %s", ustr); ++ } ++ (*env)->ReleaseStringUTFChars(env, str, ustr); ++ } else ++ res = LIBUSB_ERROR_OTHER; ++ (*env)->DeleteLocalRef(env, str); ++ } else ++ res = LIBUSB_ERROR_OTHER; ++ if (res) ++ break; ++ } ++ (*env)->DeleteLocalRef(env, arr); ++ } ++ ++ if (do_detach) { ++ (*g_jvm)->DetachCurrentThread(g_jvm); ++ } ++ ++ return res; ++} ++ ++static void usb_helper_hotplug_poll(void) ++{ ++} ++ ++static void usb_helper_on_usb_device_action(JNIEnv *env, jobject self, jstring name, jboolean removed) ++{ ++ usbi_mutex_static_lock(&linux_hotplug_lock); ++ if (name) { ++ const char *ustr = (*env)->GetStringUTFChars(env, name, NULL); ++ if (ustr) { ++ unsigned busnum, devaddr; ++ if (2 == sscanf(ustr, "/dev/bus/usb/%u/%u", ++ &busnum, &devaddr)) { ++ if (removed) ++ linux_device_disconnected(busnum, devaddr, NULL); ++ else ++ linux_hotplug_enumerate(busnum, devaddr, NULL); ++ } ++ (*env)->ReleaseStringUTFChars(env, name, ustr); ++ } ++ } ++ usbi_mutex_static_unlock(&linux_hotplug_lock); ++} ++#endif