Skip to content
This repository was archived by the owner on Feb 26, 2020. It is now read-only.

Commit 417b2bf

Browse files
prusnaksignal11
authored andcommitted
libusb: Add Android support
This code originally came from Pekka Nikander <[email protected]>
1 parent ac6120b commit 417b2bf

File tree

2 files changed

+108
-3
lines changed

2 files changed

+108
-3
lines changed

android/jni/Android.mk

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
LOCAL_PATH:= $(call my-dir)
2+
3+
HIDAPI_ROOT_REL:= ../..
4+
HIDAPI_ROOT_ABS:= $(LOCAL_PATH)/../..
5+
6+
include $(CLEAR_VARS)
7+
8+
LOCAL_SRC_FILES := \
9+
$(HIDAPI_ROOT_REL)/libusb/hid.c
10+
11+
LOCAL_C_INCLUDES += \
12+
$(HIDAPI_ROOT_ABS)/hidapi \
13+
$(HIDAPI_ROOT_ABS)/android
14+
15+
LOCAL_SHARED_LIBRARIES := libusb1.0
16+
17+
LOCAL_MODULE := libhidapi
18+
19+
include $(BUILD_SHARED_LIBRARY)

libusb/hid.c

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,74 @@
4444
#include <wchar.h>
4545

4646
/* GNU / LibUSB */
47-
#include "libusb.h"
48-
#include "iconv.h"
47+
#include <libusb.h>
48+
#ifndef __ANDROID__
49+
#include <iconv.h>
50+
#endif
4951

5052
#include "hidapi.h"
5153

54+
#ifdef __ANDROID__
55+
56+
/* Barrier implementation because Android/Bionic don't have pthread_barrier.
57+
This implementation came from Brent Priddy and was posted on
58+
StackOverflow. It is used with his permission. */
59+
typedef int pthread_barrierattr_t;
60+
typedef struct pthread_barrier {
61+
pthread_mutex_t mutex;
62+
pthread_cond_t cond;
63+
int count;
64+
int trip_count;
65+
} pthread_barrier_t;
66+
67+
static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
68+
{
69+
if(count == 0) {
70+
errno = EINVAL;
71+
return -1;
72+
}
73+
74+
if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
75+
return -1;
76+
}
77+
if(pthread_cond_init(&barrier->cond, 0) < 0) {
78+
pthread_mutex_destroy(&barrier->mutex);
79+
return -1;
80+
}
81+
barrier->trip_count = count;
82+
barrier->count = 0;
83+
84+
return 0;
85+
}
86+
87+
static int pthread_barrier_destroy(pthread_barrier_t *barrier)
88+
{
89+
pthread_cond_destroy(&barrier->cond);
90+
pthread_mutex_destroy(&barrier->mutex);
91+
return 0;
92+
}
93+
94+
static int pthread_barrier_wait(pthread_barrier_t *barrier)
95+
{
96+
pthread_mutex_lock(&barrier->mutex);
97+
++(barrier->count);
98+
if(barrier->count >= barrier->trip_count)
99+
{
100+
barrier->count = 0;
101+
pthread_cond_broadcast(&barrier->cond);
102+
pthread_mutex_unlock(&barrier->mutex);
103+
return 1;
104+
}
105+
else
106+
{
107+
pthread_cond_wait(&barrier->cond, &(barrier->mutex));
108+
pthread_mutex_unlock(&barrier->mutex);
109+
return 0;
110+
}
111+
}
112+
113+
#endif
114+
52115
#ifdef __cplusplus
53116
extern "C" {
54117
#endif
@@ -326,8 +389,9 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
326389
char buf[512];
327390
int len;
328391
wchar_t *str = NULL;
329-
wchar_t wbuf[256];
330392

393+
#ifndef __ANDROID__ /* we don't use iconv on Android */
394+
wchar_t wbuf[256];
331395
/* iconv variables */
332396
iconv_t ic;
333397
size_t inbytes;
@@ -339,6 +403,7 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
339403
char *inptr;
340404
#endif
341405
char *outptr;
406+
#endif
342407

343408
/* Determine which language to use. */
344409
uint16_t lang;
@@ -355,6 +420,25 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
355420
if (len < 0)
356421
return NULL;
357422

423+
#ifdef __ANDROID__
424+
425+
/* Bionic does not have iconv support nor wcsdup() function, so it
426+
has to be done manually. The following code will only work for
427+
code points that can be represented as a single UTF-16 character,
428+
and will incorrectly convert any code points which require more
429+
than one UTF-16 character.
430+
431+
Skip over the first character (2-bytes). */
432+
len -= 2;
433+
str = malloc((len / 2 + 1) * sizeof(wchar_t));
434+
int i;
435+
for (i = 0; i < len / 2; i++) {
436+
str[i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8);
437+
}
438+
str[len / 2] = 0x00000000;
439+
440+
#else
441+
358442
/* buf does not need to be explicitly NULL-terminated because
359443
it is only passed into iconv() which does not need it. */
360444

@@ -388,6 +472,8 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
388472
err:
389473
iconv_close(ic);
390474

475+
#endif
476+
391477
return str;
392478
}
393479

0 commit comments

Comments
 (0)