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 */
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
11659extern "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
211149static 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)
13471283static 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
14351366ret :
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