20
20
https://github.com/libusb/hidapi .
21
21
********************************************************/
22
22
23
+ #ifndef HIDAPI_USING_SDL_RUNTIME
23
24
#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */
24
25
25
26
/* C */
37
38
#include <sys/ioctl.h>
38
39
#include <sys/utsname.h>
39
40
#include <fcntl.h>
40
- #include <pthread.h>
41
41
#include <wchar.h>
42
42
43
43
/* GNU / LibUSB */
48
48
#define ICONV_CONST
49
49
#endif
50
50
#endif
51
+ #endif /* HIDAPI_USING_SDL_RUNTIME */
51
52
52
53
#include "hidapi_libusb.h"
53
54
55
+ #ifdef __cplusplus
56
+ extern "C" {
57
+ #endif
58
+
59
+ #ifdef DEBUG_PRINTF
60
+ #define LOG (...) fprintf(stderr, __VA_ARGS__)
61
+ #else
62
+ #define LOG (...) do {} while (0)
63
+ #endif
64
+
65
+ #ifndef __FreeBSD__
66
+ #define DETACH_KERNEL_DRIVER
67
+ #endif
68
+
69
+ /* Uncomment to enable the retrieval of Usage and Usage Page in
70
+ hid_enumerate(). Warning, on platforms different from FreeBSD
71
+ this is very invasive as it requires the detach
72
+ and re-attach of the kernel driver. See comments inside hid_enumerate().
73
+ libusb HIDAPI programs are encouraged to use the interface number
74
+ instead to differentiate between interfaces on a composite HID device. */
75
+ /*#define INVASIVE_GET_USAGE*/
76
+
77
+ /* Linked List of input reports received from the device. */
78
+ struct input_report {
79
+ uint8_t * data ;
80
+ size_t len ;
81
+ struct input_report * next ;
82
+ };
83
+
84
+ #ifndef HIDAPI_THREAD_STATE_DEFINED
85
+
86
+ #include <pthread.h>
87
+
54
88
#if defined(__ANDROID__ ) && __ANDROID_API__ < __ANDROID_API_N__
55
89
56
90
/* Barrier implementation because Android/Bionic don't have pthread_barrier.
@@ -112,35 +146,85 @@ static int pthread_barrier_wait(pthread_barrier_t *barrier)
112
146
113
147
#endif
114
148
115
- #ifdef __cplusplus
116
- extern "C" {
117
- #endif
149
+ #define THREAD_STATE_WAIT_TIMED_OUT ETIMEDOUT
118
150
119
- #ifdef DEBUG_PRINTF
120
- #define LOG (...) fprintf(stderr, __VA_ARGS__)
121
- #else
122
- #define LOG (...) do {} while (0)
123
- #endif
151
+ typedef struct
152
+ {
153
+ pthread_t thread ;
154
+ pthread_mutex_t mutex ; /* Protects input_reports */
155
+ pthread_cond_t condition ;
156
+ pthread_barrier_t barrier ; /* Ensures correct startup sequence */
124
157
125
- #ifndef __FreeBSD__
126
- #define DETACH_KERNEL_DRIVER
127
- #endif
158
+ } hid_device_thread_state ;
128
159
129
- /* Uncomment to enable the retrieval of Usage and Usage Page in
130
- hid_enumerate(). Warning, on platforms different from FreeBSD
131
- this is very invasive as it requires the detach
132
- and re-attach of the kernel driver. See comments inside hid_enumerate().
133
- libusb HIDAPI programs are encouraged to use the interface number
134
- instead to differentiate between interfaces on a composite HID device. */
135
- /*#define INVASIVE_GET_USAGE*/
160
+ static void thread_state_init (hid_device_thread_state * state )
161
+ {
162
+ pthread_mutex_init (& state -> mutex , NULL );
163
+ pthread_cond_init (& state -> condition , NULL );
164
+ pthread_barrier_init (& state -> barrier , NULL , 2 );
165
+ }
136
166
137
- /* Linked List of input reports received from the device. */
138
- struct input_report {
139
- uint8_t * data ;
140
- size_t len ;
141
- struct input_report * next ;
142
- };
167
+ static void thread_state_free (hid_device_thread_state * state )
168
+ {
169
+ pthread_barrier_destroy (& state -> barrier );
170
+ pthread_cond_destroy (& state -> condition );
171
+ pthread_mutex_destroy (& state -> mutex );
172
+ }
173
+
174
+ #define thread_state_push_cleanup pthread_cleanup_push
175
+ #define thread_state_pop_cleanup pthread_cleanup_pop
176
+
177
+ static void thread_state_lock (hid_device_thread_state * state )
178
+ {
179
+ pthread_mutex_lock (& state -> mutex );
180
+ }
181
+
182
+ static void thread_state_unlock (hid_device_thread_state * state )
183
+ {
184
+ pthread_mutex_unlock (& state -> mutex );
185
+ }
186
+
187
+ static void thread_state_wait_condition (hid_device_thread_state * state )
188
+ {
189
+ pthread_cond_wait (& state -> condition , & state -> mutex );
190
+ }
143
191
192
+ static int thread_state_wait_condition_timeout (hid_device_thread_state * state , struct timespec * ts )
193
+ {
194
+ return pthread_cond_timedwait (& state -> condition , & state -> mutex , ts );
195
+ }
196
+
197
+ static void thread_state_signal_condition (hid_device_thread_state * state )
198
+ {
199
+ pthread_cond_signal (& state -> condition );
200
+ }
201
+
202
+ static void thread_state_broadcast_condition (hid_device_thread_state * state )
203
+ {
204
+ pthread_cond_broadcast (& state -> condition );
205
+ }
206
+
207
+ static void thread_state_wait_barrier (hid_device_thread_state * state )
208
+ {
209
+ pthread_barrier_wait (& state -> barrier );
210
+ }
211
+
212
+ static void thread_state_create_thread (hid_device_thread_state * state , void * (* func )(void * ), void * func_arg )
213
+ {
214
+ pthread_create (& state -> thread , NULL , func , func_arg );
215
+ }
216
+
217
+ static void thread_state_join_thread (hid_device_thread_state * state )
218
+ {
219
+ pthread_join (state -> thread , NULL );
220
+ }
221
+
222
+ static void thread_state_get_current_time (struct timespec * ts )
223
+ {
224
+ clock_gettime (CLOCK_REALTIME , ts );
225
+ }
226
+
227
+ #endif /* !HIDAPI_THREAD_STATE_DEFINED */
144
228
145
229
struct hid_device_ {
146
230
/* Handle to the actual device. */
@@ -168,10 +252,7 @@ struct hid_device_ {
168
252
int blocking ; /* boolean */
169
253
170
254
/* 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 */
255
+ hid_device_thread_state thread_state ;
175
256
int shutdown_thread ;
176
257
int transfer_loop_finished ;
177
258
struct libusb_transfer * transfer ;
@@ -201,19 +282,15 @@ static hid_device *new_hid_device(void)
201
282
hid_device * dev = (hid_device * ) calloc (1 , sizeof (hid_device ));
202
283
dev -> blocking = 1 ;
203
284
204
- pthread_mutex_init (& dev -> mutex , NULL );
205
- pthread_cond_init (& dev -> condition , NULL );
206
- pthread_barrier_init (& dev -> barrier , NULL , 2 );
285
+ thread_state_init (& dev -> thread_state );
207
286
208
287
return dev ;
209
288
}
210
289
211
290
static void free_hid_device (hid_device * dev )
212
291
{
213
292
/* Clean up the thread objects */
214
- pthread_barrier_destroy (& dev -> barrier );
215
- pthread_cond_destroy (& dev -> condition );
216
- pthread_mutex_destroy (& dev -> mutex );
293
+ thread_state_free (& dev -> thread_state );
217
294
218
295
hid_free_enumeration (dev -> device_info );
219
296
@@ -912,13 +989,13 @@ static void read_callback(struct libusb_transfer *transfer)
912
989
rpt -> len = transfer -> actual_length ;
913
990
rpt -> next = NULL ;
914
991
915
- pthread_mutex_lock (& dev -> mutex );
992
+ thread_state_lock (& dev -> thread_state );
916
993
917
994
/* Attach the new report object to the end of the list. */
918
995
if (dev -> input_reports == NULL ) {
919
996
/* The list is empty. Put it at the root. */
920
997
dev -> input_reports = rpt ;
921
- pthread_cond_signal (& dev -> condition );
998
+ thread_state_signal_condition (& dev -> thread_state );
922
999
}
923
1000
else {
924
1001
/* Find the end of the list and attach. */
@@ -937,7 +1014,7 @@ static void read_callback(struct libusb_transfer *transfer)
937
1014
return_data (dev , NULL , 0 );
938
1015
}
939
1016
}
940
- pthread_mutex_unlock (& dev -> mutex );
1017
+ thread_state_unlock (& dev -> thread_state );
941
1018
}
942
1019
else if (transfer -> status == LIBUSB_TRANSFER_CANCELLED ) {
943
1020
dev -> shutdown_thread = 1 ;
@@ -996,7 +1073,7 @@ static void *read_thread(void *param)
996
1073
}
997
1074
998
1075
/* Notify the main thread that the read thread is up and running. */
999
- pthread_barrier_wait (& dev -> barrier );
1076
+ thread_state_wait_barrier (& dev -> thread_state );
1000
1077
1001
1078
/* Handle all the events. */
1002
1079
while (!dev -> shutdown_thread ) {
@@ -1028,15 +1105,15 @@ static void *read_thread(void *param)
1028
1105
make sure that a thread which is about to go to sleep waiting on
1029
1106
the condition actually will go to sleep before the condition is
1030
1107
signaled. */
1031
- pthread_mutex_lock (& dev -> mutex );
1032
- pthread_cond_broadcast (& dev -> condition );
1033
- pthread_mutex_unlock (& dev -> mutex );
1108
+ thread_state_lock (& dev -> thread_state );
1109
+ thread_state_broadcast_condition (& dev -> thread_state );
1110
+ thread_state_unlock (& dev -> thread_state );
1034
1111
1035
1112
/* The dev->transfer->buffer and dev->transfer objects are cleaned up
1036
1113
in hid_close(). They are not cleaned up here because this thread
1037
1114
could end either due to a disconnect or due to a user
1038
1115
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
1116
+ cleaned up after the call to thread_state_join () (in hid_close()), but
1040
1117
since hid_close() calls libusb_cancel_transfer(), on these objects,
1041
1118
they can not be cleaned up here. */
1042
1119
@@ -1128,15 +1205,15 @@ static int hidapi_initialize_device(hid_device *dev, int config_number, const st
1128
1205
}
1129
1206
}
1130
1207
1131
- pthread_create (& dev -> thread , NULL , read_thread , dev );
1208
+ thread_state_create_thread (& dev -> thread_state , read_thread , dev );
1132
1209
1133
1210
/* Wait here for the read thread to be initialized. */
1134
- pthread_barrier_wait (& dev -> barrier );
1211
+ thread_state_wait_barrier (& dev -> thread_state );
1135
1212
return 1 ;
1136
1213
}
1137
1214
1138
1215
1139
- hid_device * HID_API_EXPORT hid_open_path (const char * path )
1216
+ HID_API_EXPORT hid_device * hid_open_path (const char * path )
1140
1217
{
1141
1218
hid_device * dev = NULL ;
1142
1219
@@ -1347,7 +1424,7 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length)
1347
1424
static void cleanup_mutex (void * param )
1348
1425
{
1349
1426
hid_device * dev = param ;
1350
- pthread_mutex_unlock (& dev -> mutex );
1427
+ thread_state_unlock (& dev -> thread_state );
1351
1428
}
1352
1429
1353
1430
@@ -1363,8 +1440,8 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
1363
1440
/* error: variable ‘bytes_read’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Werror=clobbered] */
1364
1441
int bytes_read ; /* = -1; */
1365
1442
1366
- pthread_mutex_lock (& dev -> mutex );
1367
- pthread_cleanup_push ( & cleanup_mutex , dev );
1443
+ thread_state_lock (& dev -> thread_state );
1444
+ thread_state_push_cleanup ( cleanup_mutex , dev );
1368
1445
1369
1446
bytes_read = -1 ;
1370
1447
@@ -1385,7 +1462,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
1385
1462
if (milliseconds == -1 ) {
1386
1463
/* Blocking */
1387
1464
while (!dev -> input_reports && !dev -> shutdown_thread ) {
1388
- pthread_cond_wait (& dev -> condition , & dev -> mutex );
1465
+ thread_state_wait_condition (& dev -> thread_state );
1389
1466
}
1390
1467
if (dev -> input_reports ) {
1391
1468
bytes_read = return_data (dev , data , length );
@@ -1395,7 +1472,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
1395
1472
/* Non-blocking, but called with timeout. */
1396
1473
int res ;
1397
1474
struct timespec ts ;
1398
- clock_gettime ( CLOCK_REALTIME , & ts );
1475
+ thread_state_get_current_time ( & ts );
1399
1476
ts .tv_sec += milliseconds / 1000 ;
1400
1477
ts .tv_nsec += (milliseconds % 1000 ) * 1000000 ;
1401
1478
if (ts .tv_nsec >= 1000000000L ) {
@@ -1404,7 +1481,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
1404
1481
}
1405
1482
1406
1483
while (!dev -> input_reports && !dev -> shutdown_thread ) {
1407
- res = pthread_cond_timedwait (& dev -> condition , & dev -> mutex , & ts );
1484
+ res = thread_state_wait_condition_timeout (& dev -> thread_state , & ts );
1408
1485
if (res == 0 ) {
1409
1486
if (dev -> input_reports ) {
1410
1487
bytes_read = return_data (dev , data , length );
@@ -1415,7 +1492,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
1415
1492
or the read thread was shutdown. Run the
1416
1493
loop again (ie: don't break). */
1417
1494
}
1418
- else if (res == ETIMEDOUT ) {
1495
+ else if (res == THREAD_STATE_WAIT_TIMED_OUT ) {
1419
1496
/* Timed out. */
1420
1497
bytes_read = 0 ;
1421
1498
break ;
@@ -1433,8 +1510,8 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
1433
1510
}
1434
1511
1435
1512
ret :
1436
- pthread_mutex_unlock (& dev -> mutex );
1437
- pthread_cleanup_pop (0 );
1513
+ thread_state_unlock (& dev -> thread_state );
1514
+ thread_state_pop_cleanup (0 );
1438
1515
1439
1516
return bytes_read ;
1440
1517
}
@@ -1552,7 +1629,7 @@ void HID_API_EXPORT hid_close(hid_device *dev)
1552
1629
libusb_cancel_transfer (dev -> transfer );
1553
1630
1554
1631
/* Wait for read_thread() to end. */
1555
- pthread_join ( dev -> thread , NULL );
1632
+ thread_state_join_thread ( & dev -> thread_state );
1556
1633
1557
1634
/* Clean up the Transfer objects allocated in read_thread(). */
1558
1635
free (dev -> transfer -> buffer );
@@ -1575,11 +1652,11 @@ void HID_API_EXPORT hid_close(hid_device *dev)
1575
1652
libusb_close (dev -> device_handle );
1576
1653
1577
1654
/* Clear out the queue of received reports. */
1578
- pthread_mutex_lock (& dev -> mutex );
1655
+ thread_state_lock (& dev -> thread_state );
1579
1656
while (dev -> input_reports ) {
1580
1657
return_data (dev , NULL , 0 );
1581
1658
}
1582
- pthread_mutex_unlock (& dev -> mutex );
1659
+ thread_state_unlock (& dev -> thread_state );
1583
1660
1584
1661
free_hid_device (dev );
1585
1662
}
0 commit comments