Skip to content

Commit 5eb5544

Browse files
authored
libusb: Allow building using non-POSIX runtime (#582)
1 parent a88805e commit 5eb5544

File tree

2 files changed

+204
-99
lines changed

2 files changed

+204
-99
lines changed

libusb/hid.c

Lines changed: 30 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#include <sys/ioctl.h>
3838
#include <sys/utsname.h>
3939
#include <fcntl.h>
40-
#include <pthread.h>
4140
#include <wchar.h>
4241

4342
/* GNU / LibUSB */
@@ -51,66 +50,10 @@
5150

5251
#include "hidapi_libusb.h"
5352

54-
#if defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__
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-
53+
#ifndef HIDAPI_THREAD_MODEL_INCLUDE
54+
#define HIDAPI_THREAD_MODEL_INCLUDE "hidapi_thread_pthread.h"
11355
#endif
56+
#include HIDAPI_THREAD_MODEL_INCLUDE
11457

11558
#ifdef __cplusplus
11659
extern "C" {
@@ -168,10 +111,7 @@ struct hid_device_ {
168111
int blocking; /* boolean */
169112

170113
/* Read thread objects */
171-
pthread_t thread;
172-
pthread_mutex_t mutex; /* Protects input_reports */
173-
pthread_cond_t condition;
174-
pthread_barrier_t barrier; /* Ensures correct startup sequence */
114+
hidapi_thread_state thread_state;
175115
int shutdown_thread;
176116
int transfer_loop_finished;
177117
struct libusb_transfer *transfer;
@@ -201,19 +141,15 @@ static hid_device *new_hid_device(void)
201141
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
202142
dev->blocking = 1;
203143

204-
pthread_mutex_init(&dev->mutex, NULL);
205-
pthread_cond_init(&dev->condition, NULL);
206-
pthread_barrier_init(&dev->barrier, NULL, 2);
144+
hidapi_thread_state_init(&dev->thread_state);
207145

208146
return dev;
209147
}
210148

211149
static void free_hid_device(hid_device *dev)
212150
{
213151
/* Clean up the thread objects */
214-
pthread_barrier_destroy(&dev->barrier);
215-
pthread_cond_destroy(&dev->condition);
216-
pthread_mutex_destroy(&dev->mutex);
152+
hidapi_thread_state_destroy(&dev->thread_state);
217153

218154
hid_free_enumeration(dev->device_info);
219155

@@ -912,13 +848,13 @@ static void read_callback(struct libusb_transfer *transfer)
912848
rpt->len = transfer->actual_length;
913849
rpt->next = NULL;
914850

915-
pthread_mutex_lock(&dev->mutex);
851+
hidapi_thread_mutex_lock(&dev->thread_state);
916852

917853
/* Attach the new report object to the end of the list. */
918854
if (dev->input_reports == NULL) {
919855
/* The list is empty. Put it at the root. */
920856
dev->input_reports = rpt;
921-
pthread_cond_signal(&dev->condition);
857+
hidapi_thread_cond_signal(&dev->thread_state);
922858
}
923859
else {
924860
/* Find the end of the list and attach. */
@@ -937,7 +873,7 @@ static void read_callback(struct libusb_transfer *transfer)
937873
return_data(dev, NULL, 0);
938874
}
939875
}
940-
pthread_mutex_unlock(&dev->mutex);
876+
hidapi_thread_mutex_unlock(&dev->thread_state);
941877
}
942878
else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
943879
dev->shutdown_thread = 1;
@@ -996,7 +932,7 @@ static void *read_thread(void *param)
996932
}
997933

998934
/* Notify the main thread that the read thread is up and running. */
999-
pthread_barrier_wait(&dev->barrier);
935+
hidapi_thread_barrier_wait(&dev->thread_state);
1000936

1001937
/* Handle all the events. */
1002938
while (!dev->shutdown_thread) {
@@ -1028,15 +964,15 @@ static void *read_thread(void *param)
1028964
make sure that a thread which is about to go to sleep waiting on
1029965
the condition actually will go to sleep before the condition is
1030966
signaled. */
1031-
pthread_mutex_lock(&dev->mutex);
1032-
pthread_cond_broadcast(&dev->condition);
1033-
pthread_mutex_unlock(&dev->mutex);
967+
hidapi_thread_mutex_lock(&dev->thread_state);
968+
hidapi_thread_cond_broadcast(&dev->thread_state);
969+
hidapi_thread_mutex_unlock(&dev->thread_state);
1034970

1035971
/* The dev->transfer->buffer and dev->transfer objects are cleaned up
1036972
in hid_close(). They are not cleaned up here because this thread
1037973
could end either due to a disconnect or due to a user
1038974
call to hid_close(). In both cases the objects can be safely
1039-
cleaned up after the call to pthread_join() (in hid_close()), but
975+
cleaned up after the call to hidapi_thread_join() (in hid_close()), but
1040976
since hid_close() calls libusb_cancel_transfer(), on these objects,
1041977
they can not be cleaned up here. */
1042978

@@ -1128,10 +1064,10 @@ static int hidapi_initialize_device(hid_device *dev, int config_number, const st
11281064
}
11291065
}
11301066

1131-
pthread_create(&dev->thread, NULL, read_thread, dev);
1067+
hidapi_thread_create(&dev->thread_state, read_thread, dev);
11321068

11331069
/* Wait here for the read thread to be initialized. */
1134-
pthread_barrier_wait(&dev->barrier);
1070+
hidapi_thread_barrier_wait(&dev->thread_state);
11351071
return 1;
11361072
}
11371073

@@ -1347,7 +1283,7 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length)
13471283
static void cleanup_mutex(void *param)
13481284
{
13491285
hid_device *dev = param;
1350-
pthread_mutex_unlock(&dev->mutex);
1286+
hidapi_thread_mutex_unlock(&dev->thread_state);
13511287
}
13521288

13531289

@@ -1363,8 +1299,8 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
13631299
/* error: variable ‘bytes_read’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Werror=clobbered] */
13641300
int bytes_read; /* = -1; */
13651301

1366-
pthread_mutex_lock(&dev->mutex);
1367-
pthread_cleanup_push(&cleanup_mutex, dev);
1302+
hidapi_thread_mutex_lock(&dev->thread_state);
1303+
hidapi_thread_cleanup_push(cleanup_mutex, dev);
13681304

13691305
bytes_read = -1;
13701306

@@ -1385,7 +1321,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
13851321
if (milliseconds == -1) {
13861322
/* Blocking */
13871323
while (!dev->input_reports && !dev->shutdown_thread) {
1388-
pthread_cond_wait(&dev->condition, &dev->mutex);
1324+
hidapi_thread_cond_wait(&dev->thread_state);
13891325
}
13901326
if (dev->input_reports) {
13911327
bytes_read = return_data(dev, data, length);
@@ -1394,17 +1330,12 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
13941330
else if (milliseconds > 0) {
13951331
/* Non-blocking, but called with timeout. */
13961332
int res;
1397-
struct timespec ts;
1398-
clock_gettime(CLOCK_REALTIME, &ts);
1399-
ts.tv_sec += milliseconds / 1000;
1400-
ts.tv_nsec += (milliseconds % 1000) * 1000000;
1401-
if (ts.tv_nsec >= 1000000000L) {
1402-
ts.tv_sec++;
1403-
ts.tv_nsec -= 1000000000L;
1404-
}
1333+
hidapi_timespec ts;
1334+
hidapi_thread_gettime(&ts);
1335+
hidapi_thread_addtime(&ts, milliseconds);
14051336

14061337
while (!dev->input_reports && !dev->shutdown_thread) {
1407-
res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts);
1338+
res = hidapi_thread_cond_timedwait(&dev->thread_state, &ts);
14081339
if (res == 0) {
14091340
if (dev->input_reports) {
14101341
bytes_read = return_data(dev, data, length);
@@ -1415,7 +1346,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
14151346
or the read thread was shutdown. Run the
14161347
loop again (ie: don't break). */
14171348
}
1418-
else if (res == ETIMEDOUT) {
1349+
else if (res == HIDAPI_THREAD_TIMED_OUT) {
14191350
/* Timed out. */
14201351
bytes_read = 0;
14211352
break;
@@ -1433,8 +1364,8 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
14331364
}
14341365

14351366
ret:
1436-
pthread_mutex_unlock(&dev->mutex);
1437-
pthread_cleanup_pop(0);
1367+
hidapi_thread_mutex_unlock(&dev->thread_state);
1368+
hidapi_thread_cleanup_pop(0);
14381369

14391370
return bytes_read;
14401371
}
@@ -1552,7 +1483,7 @@ void HID_API_EXPORT hid_close(hid_device *dev)
15521483
libusb_cancel_transfer(dev->transfer);
15531484

15541485
/* Wait for read_thread() to end. */
1555-
pthread_join(dev->thread, NULL);
1486+
hidapi_thread_join(&dev->thread_state);
15561487

15571488
/* Clean up the Transfer objects allocated in read_thread(). */
15581489
free(dev->transfer->buffer);
@@ -1575,11 +1506,11 @@ void HID_API_EXPORT hid_close(hid_device *dev)
15751506
libusb_close(dev->device_handle);
15761507

15771508
/* Clear out the queue of received reports. */
1578-
pthread_mutex_lock(&dev->mutex);
1509+
hidapi_thread_mutex_lock(&dev->thread_state);
15791510
while (dev->input_reports) {
15801511
return_data(dev, NULL, 0);
15811512
}
1582-
pthread_mutex_unlock(&dev->mutex);
1513+
hidapi_thread_mutex_unlock(&dev->thread_state);
15831514

15841515
free_hid_device(dev);
15851516
}

0 commit comments

Comments
 (0)