]> sigrok.org Git - sigrok-util.git/blob - cross-compile/android/libusb-1.0.patch
sigrok-cross-mingw: Temporarily unbreak Windows CI builds in dirty ways.
[sigrok-util.git] / cross-compile / android / libusb-1.0.patch
1 diff -urp libusb-1.0.9.orig/libusb/io.c libusb-1.0.9/libusb/io.c
2 --- libusb-1.0.9.orig/libusb/io.c       2013-08-28 14:33:15.000000000 +0200
3 +++ libusb-1.0.9/libusb/io.c    2013-08-28 14:31:25.000000000 +0200
4 @@ -36,6 +36,14 @@
5  
6  #include "libusbi.h"
7  
8 +#ifndef TIMESPEC_TO_TIMEVAL
9 +#define TIMESPEC_TO_TIMEVAL(tv, ts)                                     \
10 +        do {                                                            \
11 +                (tv)->tv_sec = (ts)->tv_sec;                            \
12 +                (tv)->tv_usec = (ts)->tv_nsec / 1000;                   \
13 +        } while (0)
14 +#endif
15 +
16  /**
17   * \page io Synchronous and asynchronous device I/O
18   *
19 --- libusb-1.0.19.orig/libusb/os/linux_usbfs.c  2014-05-30 11:18:28.000000000 +0200
20 +++ libusb-1.0.19/libusb/os/linux_usbfs.c       2016-11-26 15:38:21.199383120 +0100
21 @@ -37,11 +37,31 @@
22  #include <sys/types.h>
23  #include <sys/utsname.h>
24  #include <unistd.h>
25 +#ifdef __ANDROID__
26 +#include <jni.h>
27 +#endif
28  
29  #include "libusb.h"
30  #include "libusbi.h"
31  #include "linux_usbfs.h"
32  
33 +#ifdef __ANDROID__
34 +static JavaVM *g_jvm = NULL;
35 +static jclass usb_helper_class;
36 +static jclass usb_event_listener_class;
37 +static jmethodID usb_helper_open_mid;
38 +static jmethodID usb_helper_start_event_monitor_mid;
39 +static jmethodID usb_helper_stop_event_monitor_mid;
40 +static jmethodID usb_helper_scan_devices_mid;
41 +static jmethodID usb_event_listener_init_mid;
42 +static int usb_helper_open(const char *pathname, int flags);
43 +static int usb_helper_start_event_monitor(void);
44 +static int usb_helper_stop_event_monitor(void);
45 +static int usb_helper_scan_devices (struct libusb_context *ctx);
46 +static void usb_helper_hotplug_poll(void);
47 +static void usb_helper_on_usb_device_action(JNIEnv *env, jobject self, jstring name, jboolean removed);
48 +#endif
49 +
50  /* sysfs vs usbfs:
51   * opening a usbfs node causes the device to be resumed, so we attempt to
52   * avoid this during enumeration.
53 @@ -193,6 +213,11 @@
54                 snprintf(path, PATH_MAX, "%s/%03d/%03d",
55                         usbfs_path, dev->bus_number, dev->device_address);
56  
57 +#ifdef __ANDROID__
58 +       if (g_jvm)
59 +               fd = usb_helper_open(path, mode);
60 +       else
61 +#endif
62         fd = open(path, mode);
63         if (fd != -1)
64                 return fd; /* Success */
65 @@ -369,6 +394,13 @@
66         struct stat statbuf;
67         int r;
68  
69 +#ifdef __ANDROID__
70 +       if (g_jvm) {
71 +               usbfs_path = "/dev/bus/usb";
72 +               sysfs_can_relate_devices = 0;
73 +               sysfs_has_descriptors = 0;
74 +       } else
75 +#endif
76         usbfs_path = find_usbfs_path();
77         if (!usbfs_path) {
78                 usbi_err(ctx, "could not find usbfs");
79 @@ -467,6 +499,10 @@
80  
81  static int linux_start_event_monitor(void)
82  {
83 +#ifdef __ANDROID__
84 +       if (g_jvm)
85 +               return usb_helper_start_event_monitor();
86 +#endif
87  #if defined(USE_UDEV)
88         return linux_udev_start_event_monitor();
89  #else
90 @@ -476,6 +512,10 @@
91  
92  static int linux_stop_event_monitor(void)
93  {
94 +#ifdef __ANDROID__
95 +       if (g_jvm)
96 +               return usb_helper_stop_event_monitor();
97 +#endif
98  #if defined(USE_UDEV)
99         return linux_udev_stop_event_monitor();
100  #else
101 @@ -489,6 +529,11 @@
102  
103         usbi_mutex_static_lock(&linux_hotplug_lock);
104  
105 +#ifdef __ANDROID__
106 +       if (g_jvm)
107 +               ret = usb_helper_scan_devices(ctx);
108 +       else
109 +#endif
110  #if defined(USE_UDEV)
111         ret = linux_udev_scan_devices(ctx);
112  #else
113 @@ -502,6 +547,11 @@
114  
115  static void op_hotplug_poll(void)
116  {
117 +#ifdef __ANDROID__
118 +       if (g_jvm)
119 +               usb_helper_hotplug_poll();
120 +       else
121 +#endif
122  #if defined(USE_UDEV)
123         linux_udev_hotplug_poll();
124  #else
125 @@ -994,6 +1044,10 @@
126         /* XXX -- can we figure out the topology when using usbfs? */
127         if (NULL == sysfs_dir || 0 == strncmp(sysfs_dir, "usb", 3)) {
128                 /* either using usbfs or finding the parent of a root hub */
129 +#ifdef __ANDROID__
130 +               if (g_jvm)
131 +                       dev->port_number = dev->device_address;
132 +#endif
133                 return LIBUSB_SUCCESS;
134         }
135  
136 @@ -2693,3 +2747,262 @@
137         .transfer_priv_size = sizeof(struct linux_transfer_priv),
138         .add_iso_packet_size = 0,
139  };
140 +
141 +#ifdef __ANDROID__
142 +jint JNI_OnLoad(JavaVM *vm, void *reserved)
143 +{
144 +       static JNINativeMethod jni_method = {
145 +               "onUsbDeviceAction",
146 +               "(Ljava/lang/String;Z)V",
147 +               (void*)usb_helper_on_usb_device_action
148 +       };
149 +
150 +       JNIEnv* env;
151 +       g_jvm = vm;
152 +       if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) {
153 +               return -1;
154 +       }
155 +
156 +       jclass helper = (*env)->FindClass(env, "org/sigrok/androidutils/UsbHelper");
157 +       jclass event_listener = (*env)->FindClass(env, "org/sigrok/androidutils/UsbEventListenerStub");
158 +
159 +       if (helper && event_listener) {
160 +
161 +               usb_helper_class = (jclass)(*env)->NewGlobalRef(env, helper);
162 +
163 +               usb_helper_open_mid = (*env)->GetStaticMethodID(env, helper, "open",
164 +                                                               "(Ljava/lang/String;I)I");
165 +               usb_helper_start_event_monitor_mid = (*env)->GetStaticMethodID(env, helper, "startEventMonitor",
166 +                                                                              "(Lorg/sigrok/androidutils/UsbEventListener;)V");
167 +               usb_helper_stop_event_monitor_mid = (*env)->GetStaticMethodID(env, helper, "stopEventMonitor",
168 +                                                                             "()V");
169 +               usb_helper_scan_devices_mid = (*env)->GetStaticMethodID(env, helper, "scanDevices",
170 +                                                                       "()[Ljava/lang/String;");
171 +               (*env)->DeleteLocalRef(env, helper);
172 +
173 +               usb_event_listener_class = (jclass)(*env)->NewGlobalRef(env, event_listener);
174 +               usb_event_listener_init_mid = (*env)->GetMethodID(env, event_listener, "<init>",
175 +                                                                       "()V");
176 +               if ((*env)->RegisterNatives(env, event_listener, &jni_method, 1) < 0) {
177 +                       if ((*env)->ExceptionCheck(env)) {
178 +                               (*env)->ExceptionClear(env);
179 +                       }
180 +                       g_jvm = NULL;
181 +               }
182 +
183 +               (*env)->DeleteLocalRef(env, event_listener);
184 +
185 +       } else {
186 +               if ((*env)->ExceptionCheck(env)) {
187 +                       (*env)->ExceptionClear(env);
188 +               }
189 +               g_jvm = NULL;
190 +       }
191 +
192 +       return JNI_VERSION_1_6;
193 +}
194 +
195 +void JNI_OnUnload(JavaVM *vm, void *reserved)
196 +{
197 +       JNIEnv* env;
198 +       if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) {
199 +               return;
200 +       }
201 +
202 +       jclass helper = usb_helper_class;
203 +       jclass event_listener = usb_event_listener_class;
204 +       usb_helper_class = NULL;
205 +       usb_event_listener_class = NULL;
206 +       if (helper)
207 +               (*env)->DeleteGlobalRef(env, helper);
208 +       if (event_listener) {
209 +               (*env)->UnregisterNatives(env, event_listener);
210 +               (*env)->DeleteGlobalRef(env, event_listener);
211 +       }
212 +       g_jvm = NULL;
213 +}
214 +
215 +static int usb_helper_open(const char *pathname, int flags)
216 +{
217 +       JNIEnv* env;
218 +       int res;
219 +       jint st;
220 +       int do_detach = 0;
221 +
222 +       if (g_jvm == NULL) {
223 +               return -1;
224 +       }
225 +       st = (*g_jvm)->GetEnv(g_jvm, (void **)&env, JNI_VERSION_1_6);
226 +
227 +       if (st == JNI_EDETACHED) {
228 +               st = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
229 +               do_detach = 1;
230 +       }
231 +
232 +       if (st != JNI_OK) {
233 +               return -1;
234 +       }
235 +
236 +       jstring string = (*env)->NewStringUTF(env, pathname);
237 +       res = (*env)->CallStaticIntMethod(env, usb_helper_class, usb_helper_open_mid, string, (jint)flags);
238 +       (*env)->DeleteLocalRef(env, string);
239 +
240 +       if (do_detach) {
241 +               (*g_jvm)->DetachCurrentThread(g_jvm);
242 +       }
243 +
244 +       if (res >= 0) {
245 +               /* Rewind so that descriptors can be read */
246 +               lseek(res, SEEK_SET, 0);
247 +       }
248 +
249 +       return res;
250 +}
251 +
252 +static int usb_helper_start_event_monitor(void)
253 +{
254 +       JNIEnv* env;
255 +       jint st;
256 +       int do_detach = 0;
257 +       int res = 0;
258 +       jobject usb_event_listener;
259 +
260 +       if (g_jvm == NULL) {
261 +               return LIBUSB_ERROR_OTHER;
262 +       }
263 +       st = (*g_jvm)->GetEnv(g_jvm, (void **)&env, JNI_VERSION_1_6);
264 +
265 +       if (st == JNI_EDETACHED) {
266 +               st = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
267 +               do_detach = 1;
268 +       }
269 +
270 +       if (st != JNI_OK) {
271 +               return LIBUSB_ERROR_OTHER;
272 +       }
273 +
274 +       usb_event_listener = (*env)->NewObject(env, usb_event_listener_class, usb_event_listener_init_mid);
275 +       if (usb_event_listener == NULL)
276 +               res = LIBUSB_ERROR_OTHER;
277 +       else {
278 +               (*env)->CallStaticVoidMethod(env, usb_helper_class, usb_helper_start_event_monitor_mid, usb_event_listener);
279 +               (*env)->DeleteLocalRef(env, usb_event_listener);
280 +       }
281 +
282 +       if (do_detach) {
283 +               (*g_jvm)->DetachCurrentThread(g_jvm);
284 +       }
285 +
286 +       return res;
287 +}
288 +
289 +static int usb_helper_stop_event_monitor(void)
290 +{
291 +       JNIEnv* env;
292 +       jint st;
293 +       int do_detach = 0;
294 +
295 +       if (g_jvm == NULL) {
296 +               return LIBUSB_ERROR_OTHER;
297 +       }
298 +       st = (*g_jvm)->GetEnv(g_jvm, (void **)&env, JNI_VERSION_1_6);
299 +
300 +       if (st == JNI_EDETACHED) {
301 +               st = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
302 +               do_detach = 1;
303 +       }
304 +
305 +       if (st != JNI_OK) {
306 +               return LIBUSB_ERROR_OTHER;
307 +       }
308 +
309 +       (*env)->CallStaticVoidMethod(env, usb_helper_class, usb_helper_stop_event_monitor_mid);
310 +
311 +       if (do_detach) {
312 +               (*g_jvm)->DetachCurrentThread(g_jvm);
313 +       }
314 +
315 +       return 0;
316 +}
317 +
318 +static int usb_helper_scan_devices (struct libusb_context *ctx)
319 +{
320 +       JNIEnv* env;
321 +       int res = 0;
322 +       jint st;
323 +       int do_detach = 0;
324 +
325 +       if (g_jvm == NULL) {
326 +               return LIBUSB_ERROR_OTHER;
327 +       }
328 +       st = (*g_jvm)->GetEnv(g_jvm, (void **)&env, JNI_VERSION_1_6);
329 +
330 +       if (st == JNI_EDETACHED) {
331 +               st = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
332 +               do_detach = 1;
333 +       }
334 +
335 +       if (st != JNI_OK) {
336 +               return LIBUSB_ERROR_OTHER;
337 +       }
338 +
339 +       jobject arr = (*env)->CallStaticObjectMethod(env, usb_helper_class, usb_helper_scan_devices_mid);
340 +
341 +       if (arr == NULL)
342 +               res = LIBUSB_ERROR_OTHER;
343 +       else {
344 +               jsize i, len = (*env)->GetArrayLength(env, arr);
345 +               for (i=0; i<len; i++) {
346 +                       jobject str = (*env)->GetObjectArrayElement(env, arr, i);
347 +                       if (str) {
348 +                               const char *ustr = (*env)->GetStringUTFChars(env, str, NULL);
349 +                               if (ustr) {
350 +                                       unsigned busnum, devaddr;
351 +                                       if (2 != sscanf(ustr, "/dev/bus/usb/%u/%u",
352 +                                                       &busnum, &devaddr) ||
353 +                                           linux_enumerate_device(ctx, busnum, devaddr, NULL)) {
354 +                                               usbi_dbg("failed to enumerate device %s", ustr);
355 +                                       }
356 +                                       (*env)->ReleaseStringUTFChars(env, str, ustr);
357 +                               } else
358 +                                       res = LIBUSB_ERROR_OTHER;
359 +                               (*env)->DeleteLocalRef(env, str);
360 +                       } else
361 +                               res = LIBUSB_ERROR_OTHER;
362 +                       if (res)
363 +                               break;
364 +               }
365 +               (*env)->DeleteLocalRef(env, arr);
366 +       }
367 +
368 +       if (do_detach) {
369 +               (*g_jvm)->DetachCurrentThread(g_jvm);
370 +       }
371 +
372 +       return res;
373 +}
374 +
375 +static void usb_helper_hotplug_poll(void)
376 +{
377 +}
378 +
379 +static void usb_helper_on_usb_device_action(JNIEnv *env, jobject self, jstring name, jboolean removed)
380 +{
381 +       usbi_mutex_static_lock(&linux_hotplug_lock);
382 +       if (name) {
383 +               const char *ustr = (*env)->GetStringUTFChars(env, name, NULL);
384 +               if (ustr) {
385 +                       unsigned busnum, devaddr;
386 +                       if (2 == sscanf(ustr, "/dev/bus/usb/%u/%u",
387 +                                       &busnum, &devaddr)) {
388 +                               if (removed)
389 +                                       linux_device_disconnected(busnum, devaddr, NULL);
390 +                               else
391 +                                       linux_hotplug_enumerate(busnum, devaddr, NULL);
392 +                       }
393 +                       (*env)->ReleaseStringUTFChars(env, name, ustr);
394 +               }
395 +       }
396 +       usbi_mutex_static_unlock(&linux_hotplug_lock);
397 +}
398 +#endif