See More

/* * Copyright (C) 2013 Klaus Reimer ([email protected]) * Copyright (C) 2013 Luca Longinotti ([email protected]) * See LICENSE.md file for copying conditions */ #include "usb4java.h" #include #include JavaVM *jvm = NULL; jclass jClassLibUsb = NULL; jmethodID jMethodTriggerPollfdAdded = NULL; jmethodID jMethodTriggerPollfdRemoved = NULL; jmethodID jMethodHotplugCallback = NULL; jint illegalArgument(JNIEnv *env, const char *message, ...) { char tmp[256]; va_list args; va_start(args, message); vsnprintf(tmp, 256, message, args); va_end(args); return (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/IllegalArgumentException"), tmp); } jint illegalState(JNIEnv *env, const char *message, ...) { char tmp[256]; va_list args; va_start(args, message); vsnprintf(tmp, 256, message, args); va_end(args); return (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/IllegalStateException"), tmp); } jobject NewDirectReadOnlyByteBuffer(JNIEnv *env, const void *mem, int mem_length) { jobject buffer = (*env)->NewDirectByteBuffer(env, (void *) mem, mem_length); // Get a read-only buffer from this buffer. jclass cls = (*env)->GetObjectClass(env, buffer); jmethodID method = (*env)->GetMethodID(env, cls, "asReadOnlyBuffer", "()Ljava/nio/ByteBuffer;"); return (*env)->CallObjectMethod(env, buffer, method); } jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; jint getEnvResult; // Set JVM to the current one. jvm = vm; // Get the current environment. getEnvResult = (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6); if (getEnvResult != JNI_OK) { // Send unrecognized version to signal error and deny library load. return -1; } // Find classes and methods and cache them. // Persistence is guaranteed by global references. jClassLibUsb = (*env)->FindClass(env, CLASS_PATH("LibUsb")); jClassLibUsb = (*env)->NewGlobalRef(env, jClassLibUsb); jMethodTriggerPollfdAdded = (*env)->GetStaticMethodID(env, jClassLibUsb, "triggerPollfdAdded", "(Ljava/io/FileDescriptor;IJ)V"); jMethodTriggerPollfdRemoved = (*env)->GetStaticMethodID(env, jClassLibUsb, "triggerPollfdRemoved", "(Ljava/io/FileDescriptor;J)V"); jMethodHotplugCallback = (*env)->GetStaticMethodID(env, jClassLibUsb, "hotplugCallback", "(L"CLASS_PATH("Context;L")CLASS_PATH("Device;IJ)I")); return JNI_VERSION_1_6; } void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { // Get the current environment. JNIEnv *env; jint getEnvResult = (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6); if (getEnvResult != JNI_OK) { return; } // Cleanup all global references. (*env)->DeleteGlobalRef(env, jClassLibUsb); } /** * Wrap a C pointer with a wrapper Java class and returns the instance of * this wrapper class. When the C pointer is null or the wrapper class could * not be created then NULL is returned. * * @param env * The JNI environment. * @param ptr * The C pointer to wrap. * @param className * The class name of the wrapper class. * @param fieldName * The field name for storing the pointer in the wrapper class. * @return The instance of the wrapper class or null if C pointer is null or * the wrapper class could not be created. */ jobject wrapPointer(JNIEnv *env, const void *ptr, const char *className, const char *fieldName) { jclass cls; jmethodID constructor; jobject object; jfieldID field; if (!ptr) return NULL; cls = (*env)->FindClass(env, className); if (cls == NULL) return NULL; constructor = (*env)->GetMethodID(env, cls, "", "()V"); if (!constructor) return NULL; object = (*env)->NewObject(env, cls, constructor); field = (*env)->GetFieldID(env, cls, fieldName, "J"); (*env)->SetLongField(env, object, field, (jptr) ptr); return object; } /** * Unwraps a C pointer from a Java wrapper object. * * @param env * The JNI environment. * @param object * The Java wrapper object. * @param fieldName * The field name where the C pointer is stored in the wrapper * object. * @return The C pointer. */ void * unwrapPointer(JNIEnv *env, jobject object, const char *fieldName) { jptr ptr; jclass cls; jfieldID field; if (!object) return NULL; cls = (*env)->GetObjectClass(env, object); field = (*env)->GetFieldID(env, cls, fieldName, "J"); ptr = (jptr) (*env)->GetLongField(env, object, field); if (!ptr) illegalState(env, "%s is not initialized", fieldName); return (void *) ptr; }