File: hidapi_thread_pthread.h

package info (click to toggle)
python-hidapi 0.15.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,192 kB
  • sloc: ansic: 5,960; python: 264; makefile: 7
file content (174 lines) | stat: -rw-r--r-- 4,467 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*******************************************************
 HIDAPI - Multi-Platform library for
 communication with HID devices.

 Alan Ott
 Signal 11 Software

 libusb/hidapi Team

 Sam Lantinga

 Copyright 2023, All Rights Reserved.

 At the discretion of the user of this library,
 this software may be licensed under the terms of the
 GNU General Public License v3, a BSD-Style license, or the
 original HIDAPI license as outlined in the LICENSE.txt,
 LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
 files located at the root of the source distribution.
 These files may also be found in the public source
 code repository located at:
        https://github.com/libusb/hidapi .
********************************************************/

#include <pthread.h>

#if defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__

/* Barrier implementation because Android/Bionic don't have pthread_barrier.
   This implementation came from Brent Priddy and was posted on
   StackOverflow. It is used with his permission. */
typedef int pthread_barrierattr_t;
typedef struct pthread_barrier {
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    int count;
    int trip_count;
} pthread_barrier_t;

static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
{
	if(count == 0) {
		errno = EINVAL;
		return -1;
	}

	if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
		return -1;
	}
	if(pthread_cond_init(&barrier->cond, 0) < 0) {
		pthread_mutex_destroy(&barrier->mutex);
		return -1;
	}
	barrier->trip_count = count;
	barrier->count = 0;

	return 0;
}

static int pthread_barrier_destroy(pthread_barrier_t *barrier)
{
	pthread_cond_destroy(&barrier->cond);
	pthread_mutex_destroy(&barrier->mutex);
	return 0;
}

static int pthread_barrier_wait(pthread_barrier_t *barrier)
{
	pthread_mutex_lock(&barrier->mutex);
	++(barrier->count);
	if(barrier->count >= barrier->trip_count) {
		barrier->count = 0;
		pthread_cond_broadcast(&barrier->cond);
		pthread_mutex_unlock(&barrier->mutex);
		return 1;
	}
	else {
		pthread_cond_wait(&barrier->cond, &(barrier->mutex));
		pthread_mutex_unlock(&barrier->mutex);
		return 0;
	}
}

#endif

#define HIDAPI_THREAD_TIMED_OUT	ETIMEDOUT

typedef struct timespec hidapi_timespec;

typedef struct
{
	pthread_t thread;
	pthread_mutex_t mutex; /* Protects input_reports */
	pthread_cond_t condition;
	pthread_barrier_t barrier; /* Ensures correct startup sequence */

} hidapi_thread_state;

static void hidapi_thread_state_init(hidapi_thread_state *state)
{
	pthread_mutex_init(&state->mutex, NULL);
	pthread_cond_init(&state->condition, NULL);
	pthread_barrier_init(&state->barrier, NULL, 2);
}

static void hidapi_thread_state_destroy(hidapi_thread_state *state)
{
	pthread_barrier_destroy(&state->barrier);
	pthread_cond_destroy(&state->condition);
	pthread_mutex_destroy(&state->mutex);
}

#define hidapi_thread_cleanup_push	pthread_cleanup_push
#define hidapi_thread_cleanup_pop	pthread_cleanup_pop

static void hidapi_thread_mutex_lock(hidapi_thread_state *state)
{
	pthread_mutex_lock(&state->mutex);
}

static void hidapi_thread_mutex_unlock(hidapi_thread_state *state)
{
	pthread_mutex_unlock(&state->mutex);
}

static void hidapi_thread_cond_wait(hidapi_thread_state *state)
{
	pthread_cond_wait(&state->condition, &state->mutex);
}

static int hidapi_thread_cond_timedwait(hidapi_thread_state *state, hidapi_timespec *ts)
{
	return pthread_cond_timedwait(&state->condition, &state->mutex, ts);
}

static void hidapi_thread_cond_signal(hidapi_thread_state *state)
{
	pthread_cond_signal(&state->condition);
}

static void hidapi_thread_cond_broadcast(hidapi_thread_state *state)
{
	pthread_cond_broadcast(&state->condition);
}

static void hidapi_thread_barrier_wait(hidapi_thread_state *state)
{
	pthread_barrier_wait(&state->barrier);
}

static void hidapi_thread_create(hidapi_thread_state *state, void *(*func)(void*), void *func_arg)
{
	pthread_create(&state->thread, NULL, func, func_arg);
}

static void hidapi_thread_join(hidapi_thread_state *state)
{
	pthread_join(state->thread, NULL);
}

static void hidapi_thread_gettime(hidapi_timespec *ts)
{
	clock_gettime(CLOCK_REALTIME, ts);
}

static void hidapi_thread_addtime(hidapi_timespec *ts, int milliseconds)
{
    ts->tv_sec += milliseconds / 1000;
    ts->tv_nsec += (milliseconds % 1000) * 1000000;
    if (ts->tv_nsec >= 1000000000L) {
        ts->tv_sec++;
        ts->tv_nsec -= 1000000000L;
    }
}