Fix issue 1) not recognizes some usb device, 2) reconnect when ffmpeg encoder error
[rtmpclient.git] / app / src / main / jni / libusb-1.0.22 / libusb / os / poll_windows.c
1 /*
2  * poll_windows: poll compatibility wrapper for Windows
3  * Copyright © 2017 Chris Dickens <christopher.a.dickens@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  */
20
21 /*
22  * poll() and pipe() Windows compatibility layer for libusb 1.0
23  *
24  * The way this layer works is by using OVERLAPPED with async I/O transfers, as
25  * OVERLAPPED have an associated event which is flagged for I/O completion.
26  *
27  * For USB pollable async I/O, you would typically:
28  * - obtain a Windows HANDLE to a file or device that has been opened in
29  *   OVERLAPPED mode
30  * - call usbi_create_fd with this handle to obtain a custom fd.
31  * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
32  *
33  * The pipe pollable synchronous I/O works using the overlapped event associated
34  * with a fake pipe. The read/write functions are only meant to be used in that
35  * context.
36  */
37 #include <config.h>
38
39 #include <assert.h>
40 #include <errno.h>
41 #include <stdlib.h>
42
43 #include "libusbi.h"
44 #include "windows_common.h"
45
46 // public fd data
47 const struct winfd INVALID_WINFD = { -1, NULL };
48
49 // private data
50 struct file_descriptor {
51         enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type;
52         OVERLAPPED overlapped;
53 };
54
55 static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER;
56 static struct file_descriptor *fd_table[MAX_FDS];
57
58 static struct file_descriptor *create_fd(enum fd_type type)
59 {
60         struct file_descriptor *fd = calloc(1, sizeof(*fd));
61         if (fd == NULL)
62                 return NULL;
63         fd->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
64         if (fd->overlapped.hEvent == NULL) {
65                 free(fd);
66                 return NULL;
67         }
68         fd->type = type;
69         return fd;
70 }
71
72 static void free_fd(struct file_descriptor *fd)
73 {
74         CloseHandle(fd->overlapped.hEvent);
75         free(fd);
76 }
77
78 /*
79  * Create both an fd and an OVERLAPPED, so that it can be used with our
80  * polling function
81  * The handle MUST support overlapped transfers (usually requires CreateFile
82  * with FILE_FLAG_OVERLAPPED)
83  * Return a pollable file descriptor struct, or INVALID_WINFD on error
84  *
85  * Note that the fd returned by this function is a per-transfer fd, rather
86  * than a per-session fd and cannot be used for anything else but our
87  * custom functions.
88  * if you plan to do R/W on the same handle, you MUST create 2 fds: one for
89  * read and one for write. Using a single R/W fd is unsupported and will
90  * produce unexpected results
91  */
92 struct winfd usbi_create_fd(void)
93 {
94         struct file_descriptor *fd;
95         struct winfd wfd;
96
97         fd = create_fd(FD_TYPE_TRANSFER);
98         if (fd == NULL)
99                 return INVALID_WINFD;
100
101         usbi_mutex_static_lock(&fd_table_lock);
102         for (wfd.fd = 0; wfd.fd < MAX_FDS; wfd.fd++) {
103                 if (fd_table[wfd.fd] != NULL)
104                         continue;
105                 fd_table[wfd.fd] = fd;
106                 break;
107         }
108         usbi_mutex_static_unlock(&fd_table_lock);
109
110         if (wfd.fd == MAX_FDS) {
111                 free_fd(fd);
112                 return INVALID_WINFD;
113         }
114
115         wfd.overlapped = &fd->overlapped;
116
117         return wfd;
118 }
119
120 static int check_pollfds(struct pollfd *fds, unsigned int nfds,
121         HANDLE *wait_handles, DWORD *nb_wait_handles)
122 {
123         struct file_descriptor *fd;
124         unsigned int n;
125         int nready = 0;
126
127         usbi_mutex_static_lock(&fd_table_lock);
128
129         for (n = 0; n < nfds; ++n) {
130                 fds[n].revents = 0;
131
132                 // Keep it simple - only allow either POLLIN *or* POLLOUT
133                 assert((fds[n].events == POLLIN) || (fds[n].events == POLLOUT));
134                 if ((fds[n].events != POLLIN) && (fds[n].events != POLLOUT)) {
135                         fds[n].revents = POLLNVAL;
136                         nready++;
137                         continue;
138                 }
139
140                 if ((fds[n].fd >= 0) && (fds[n].fd < MAX_FDS))
141                         fd = fd_table[fds[n].fd];
142                 else
143                         fd = NULL;
144
145                 assert(fd != NULL);
146                 if (fd == NULL) {
147                         fds[n].revents = POLLNVAL;
148                         nready++;
149                         continue;
150                 }
151
152                 if (HasOverlappedIoCompleted(&fd->overlapped)
153                                 && (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) {
154                         fds[n].revents = fds[n].events;
155                         nready++;
156                 } else if (wait_handles != NULL) {
157                         if (*nb_wait_handles == MAXIMUM_WAIT_OBJECTS) {
158                                 usbi_warn(NULL, "too many HANDLEs to wait on");
159                                 continue;
160                         }
161                         wait_handles[*nb_wait_handles] = fd->overlapped.hEvent;
162                         (*nb_wait_handles)++;
163                 }
164         }
165
166         usbi_mutex_static_unlock(&fd_table_lock);
167
168         return nready;
169 }
170 /*
171  * POSIX poll equivalent, using Windows OVERLAPPED
172  * Currently, this function only accepts one of POLLIN or POLLOUT per fd
173  * (but you can create multiple fds from the same handle for read and write)
174  */
175 int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
176 {
177         HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
178         DWORD nb_wait_handles = 0;
179         DWORD ret;
180         int nready;
181
182         nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles);
183
184         // If nothing was triggered, wait on all fds that require it
185         if ((nready == 0) && (nb_wait_handles != 0) && (timeout != 0)) {
186                 ret = WaitForMultipleObjects(nb_wait_handles, wait_handles,
187                         FALSE, (timeout < 0) ? INFINITE : (DWORD)timeout);
188                 if (ret < (WAIT_OBJECT_0 + nb_wait_handles)) {
189                         nready = check_pollfds(fds, nfds, NULL, NULL);
190                 } else if (ret != WAIT_TIMEOUT) {
191                         if (ret == WAIT_FAILED)
192                                 usbi_err(NULL, "WaitForMultipleObjects failed: %u", (unsigned int)GetLastError());
193                         nready = -1;
194                 }
195         }
196
197         return nready;
198 }
199
200 /*
201  * close a fake file descriptor
202  */
203 int usbi_close(int _fd)
204 {
205         struct file_descriptor *fd;
206
207         if (_fd < 0 || _fd >= MAX_FDS)
208                 goto err_badfd;
209
210         usbi_mutex_static_lock(&fd_table_lock);
211         fd = fd_table[_fd];
212         fd_table[_fd] = NULL;
213         usbi_mutex_static_unlock(&fd_table_lock);
214
215         if (fd == NULL)
216                 goto err_badfd;
217
218         if (fd->type == FD_TYPE_PIPE) {
219                 // InternalHigh is our reference count
220                 fd->overlapped.InternalHigh--;
221                 if (fd->overlapped.InternalHigh == 0)
222                         free_fd(fd);
223         } else {
224                 free_fd(fd);
225         }
226
227         return 0;
228
229 err_badfd:
230         errno = EBADF;
231         return -1;
232 }
233
234 /*
235 * Create a fake pipe.
236 * As libusb only uses pipes for signaling, all we need from a pipe is an
237 * event. To that extent, we create a single wfd and overlapped as a means
238 * to access that event.
239 */
240 int usbi_pipe(int filedes[2])
241 {
242         struct file_descriptor *fd;
243         int r_fd = -1, w_fd = -1;
244         int i;
245
246         fd = create_fd(FD_TYPE_PIPE);
247         if (fd == NULL) {
248                 errno = ENOMEM;
249                 return -1;
250         }
251
252         // Use InternalHigh as a reference count
253         fd->overlapped.Internal = STATUS_PENDING;
254         fd->overlapped.InternalHigh = 2;
255
256         usbi_mutex_static_lock(&fd_table_lock);
257         do {
258                 for (i = 0; i < MAX_FDS; i++) {
259                         if (fd_table[i] != NULL)
260                                 continue;
261                         if (r_fd == -1) {
262                                 r_fd = i;
263                         } else if (w_fd == -1) {
264                                 w_fd = i;
265                                 break;
266                         }
267                 }
268
269                 if (i == MAX_FDS)
270                         break;
271
272                 fd_table[r_fd] = fd;
273                 fd_table[w_fd] = fd;
274
275         } while (0);
276         usbi_mutex_static_unlock(&fd_table_lock);
277
278         if (i == MAX_FDS) {
279                 free_fd(fd);
280                 errno = EMFILE;
281                 return -1;
282         }
283
284         filedes[0] = r_fd;
285         filedes[1] = w_fd;
286
287         return 0;
288 }
289
290 /*
291  * synchronous write for fake "pipe" signaling
292  */
293 ssize_t usbi_write(int fd, const void *buf, size_t count)
294 {
295         int error = EBADF;
296
297         UNUSED(buf);
298
299         if (fd < 0 || fd >= MAX_FDS)
300                 goto err_out;
301
302         if (count != sizeof(unsigned char)) {
303                 usbi_err(NULL, "this function should only used for signaling");
304                 error = EINVAL;
305                 goto err_out;
306         }
307
308         usbi_mutex_static_lock(&fd_table_lock);
309         if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
310                 assert(fd_table[fd]->overlapped.Internal == STATUS_PENDING);
311                 assert(fd_table[fd]->overlapped.InternalHigh == 2);
312                 fd_table[fd]->overlapped.Internal = STATUS_WAIT_0;
313                 SetEvent(fd_table[fd]->overlapped.hEvent);
314                 error = 0;
315         }
316         usbi_mutex_static_unlock(&fd_table_lock);
317
318         if (error)
319                 goto err_out;
320
321         return sizeof(unsigned char);
322
323 err_out:
324         errno = error;
325         return -1;
326 }
327
328 /*
329  * synchronous read for fake "pipe" signaling
330  */
331 ssize_t usbi_read(int fd, void *buf, size_t count)
332 {
333         int error = EBADF;
334
335         UNUSED(buf);
336
337         if (fd < 0 || fd >= MAX_FDS)
338                 goto err_out;
339
340         if (count != sizeof(unsigned char)) {
341                 usbi_err(NULL, "this function should only used for signaling");
342                 error = EINVAL;
343                 goto err_out;
344         }
345
346         usbi_mutex_static_lock(&fd_table_lock);
347         if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
348                 assert(fd_table[fd]->overlapped.Internal == STATUS_WAIT_0);
349                 assert(fd_table[fd]->overlapped.InternalHigh == 2);
350                 fd_table[fd]->overlapped.Internal = STATUS_PENDING;
351                 ResetEvent(fd_table[fd]->overlapped.hEvent);
352                 error = 0;
353         }
354         usbi_mutex_static_unlock(&fd_table_lock);
355
356         if (error)
357                 goto err_out;
358
359         return sizeof(unsigned char);
360
361 err_out:
362         errno = error;
363         return -1;
364 }