hidapi_thread_pthread.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*******************************************************
  2. HIDAPI - Multi-Platform library for
  3. communication with HID devices.
  4. Alan Ott
  5. Signal 11 Software
  6. libusb/hidapi Team
  7. Sam Lantinga
  8. Copyright 2023, All Rights Reserved.
  9. At the discretion of the user of this library,
  10. this software may be licensed under the terms of the
  11. GNU General Public License v3, a BSD-Style license, or the
  12. original HIDAPI license as outlined in the LICENSE.txt,
  13. LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
  14. files located at the root of the source distribution.
  15. These files may also be found in the public source
  16. code repository located at:
  17. https://github.com/libusb/hidapi .
  18. ********************************************************/
  19. #include <pthread.h>
  20. #if defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__
  21. /* Barrier implementation because Android/Bionic don't have pthread_barrier.
  22. This implementation came from Brent Priddy and was posted on
  23. StackOverflow. It is used with his permission. */
  24. typedef int pthread_barrierattr_t;
  25. typedef struct pthread_barrier {
  26. pthread_mutex_t mutex;
  27. pthread_cond_t cond;
  28. int count;
  29. int trip_count;
  30. } pthread_barrier_t;
  31. static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
  32. {
  33. if(count == 0) {
  34. errno = EINVAL;
  35. return -1;
  36. }
  37. if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
  38. return -1;
  39. }
  40. if(pthread_cond_init(&barrier->cond, 0) < 0) {
  41. pthread_mutex_destroy(&barrier->mutex);
  42. return -1;
  43. }
  44. barrier->trip_count = count;
  45. barrier->count = 0;
  46. return 0;
  47. }
  48. static int pthread_barrier_destroy(pthread_barrier_t *barrier)
  49. {
  50. pthread_cond_destroy(&barrier->cond);
  51. pthread_mutex_destroy(&barrier->mutex);
  52. return 0;
  53. }
  54. static int pthread_barrier_wait(pthread_barrier_t *barrier)
  55. {
  56. pthread_mutex_lock(&barrier->mutex);
  57. ++(barrier->count);
  58. if(barrier->count >= barrier->trip_count) {
  59. barrier->count = 0;
  60. pthread_cond_broadcast(&barrier->cond);
  61. pthread_mutex_unlock(&barrier->mutex);
  62. return 1;
  63. }
  64. else {
  65. pthread_cond_wait(&barrier->cond, &(barrier->mutex));
  66. pthread_mutex_unlock(&barrier->mutex);
  67. return 0;
  68. }
  69. }
  70. #endif
  71. #define HIDAPI_THREAD_TIMED_OUT ETIMEDOUT
  72. typedef struct timespec hidapi_timespec;
  73. typedef struct
  74. {
  75. pthread_t thread;
  76. pthread_mutex_t mutex; /* Protects input_reports */
  77. pthread_cond_t condition;
  78. pthread_barrier_t barrier; /* Ensures correct startup sequence */
  79. } hidapi_thread_state;
  80. static void hidapi_thread_state_init(hidapi_thread_state *state)
  81. {
  82. pthread_mutex_init(&state->mutex, NULL);
  83. pthread_cond_init(&state->condition, NULL);
  84. pthread_barrier_init(&state->barrier, NULL, 2);
  85. }
  86. static void hidapi_thread_state_destroy(hidapi_thread_state *state)
  87. {
  88. pthread_barrier_destroy(&state->barrier);
  89. pthread_cond_destroy(&state->condition);
  90. pthread_mutex_destroy(&state->mutex);
  91. }
  92. #define hidapi_thread_cleanup_push pthread_cleanup_push
  93. #define hidapi_thread_cleanup_pop pthread_cleanup_pop
  94. static void hidapi_thread_mutex_lock(hidapi_thread_state *state)
  95. {
  96. pthread_mutex_lock(&state->mutex);
  97. }
  98. static void hidapi_thread_mutex_unlock(hidapi_thread_state *state)
  99. {
  100. pthread_mutex_unlock(&state->mutex);
  101. }
  102. static void hidapi_thread_cond_wait(hidapi_thread_state *state)
  103. {
  104. pthread_cond_wait(&state->condition, &state->mutex);
  105. }
  106. static int hidapi_thread_cond_timedwait(hidapi_thread_state *state, hidapi_timespec *ts)
  107. {
  108. return pthread_cond_timedwait(&state->condition, &state->mutex, ts);
  109. }
  110. static void hidapi_thread_cond_signal(hidapi_thread_state *state)
  111. {
  112. pthread_cond_signal(&state->condition);
  113. }
  114. static void hidapi_thread_cond_broadcast(hidapi_thread_state *state)
  115. {
  116. pthread_cond_broadcast(&state->condition);
  117. }
  118. static void hidapi_thread_barrier_wait(hidapi_thread_state *state)
  119. {
  120. pthread_barrier_wait(&state->barrier);
  121. }
  122. static void hidapi_thread_create(hidapi_thread_state *state, void *(*func)(void*), void *func_arg)
  123. {
  124. pthread_create(&state->thread, NULL, func, func_arg);
  125. }
  126. static void hidapi_thread_join(hidapi_thread_state *state)
  127. {
  128. pthread_join(state->thread, NULL);
  129. }
  130. static void hidapi_thread_gettime(hidapi_timespec *ts)
  131. {
  132. clock_gettime(CLOCK_REALTIME, ts);
  133. }
  134. static void hidapi_thread_addtime(hidapi_timespec *ts, int milliseconds)
  135. {
  136. ts->tv_sec += milliseconds / 1000;
  137. ts->tv_nsec += (milliseconds % 1000) * 1000000;
  138. if (ts->tv_nsec >= 1000000000L) {
  139. ts->tv_sec++;
  140. ts->tv_nsec -= 1000000000L;
  141. }
  142. }