-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathusb4java.c
More file actions
157 lines (137 loc) · 4.65 KB
/
usb4java.c
File metadata and controls
157 lines (137 loc) · 4.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
* Copyright (C) 2013 Klaus Reimer (k@ailis.de)
* Copyright (C) 2013 Luca Longinotti (l@longi.li)
* See LICENSE.md file for copying conditions
*/
#include "usb4java.h"
#include <stdarg.h>
#include <stdio.h>
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, "<init>", "()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;
}