libusb10_io.c (c500e4dd03b53b2f9d020fee096d971e231f3c77) libusb10_io.c (390065b18e0ee636279b106ff06f0a1463589ab1)
1/* $FreeBSD$ */
2/*-
3 * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 10 unchanged lines hidden (view full) ---

19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
1/* $FreeBSD$ */
2/*-
3 * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 10 unchanged lines hidden (view full) ---

19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/queue.h>
28#include <stdlib.h>
29#include <unistd.h>
30#include <stdio.h>
31#include <poll.h>
32#include <pthread.h>
33#include <time.h>
34#include <errno.h>
27#include <stdlib.h>
28#include <unistd.h>
29#include <stdio.h>
30#include <poll.h>
31#include <pthread.h>
32#include <time.h>
33#include <errno.h>
34#include <sys/queue.h>
35
36#include "libusb20.h"
37#include "libusb20_desc.h"
38#include "libusb20_int.h"
39#include "libusb.h"
40#include "libusb10.h"
41
35
36#include "libusb20.h"
37#include "libusb20_desc.h"
38#include "libusb20_int.h"
39#include "libusb.h"
40#include "libusb10.h"
41
42UNEXPORTED int
43usb_add_pollfd(libusb_context *ctx, int fd, short events)
42UNEXPORTED void
43libusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd,
44 struct libusb20_device *pdev, int fd, short events)
44{
45{
45 struct usb_pollfd *pollfd;
46
47 if (ctx == NULL)
46 if (ctx == NULL)
48 return (LIBUSB_ERROR_INVALID_PARAM);
49
50 pollfd = malloc(sizeof(*pollfd));
51 if (pollfd == NULL)
52 return (LIBUSB_ERROR_NO_MEM);
47 return; /* invalid */
53
48
49 if (pollfd->entry.tqe_prev != NULL)
50 return; /* already queued */
51
52 if (fd < 0)
53 return; /* invalid */
54
55 pollfd->pdev = pdev;
54 pollfd->pollfd.fd = fd;
55 pollfd->pollfd.events = events;
56
56 pollfd->pollfd.fd = fd;
57 pollfd->pollfd.events = events;
58
57 pthread_mutex_lock(&ctx->pollfds_lock);
58 TAILQ_INSERT_TAIL(&ctx->pollfds, pollfd, list);
59 pthread_mutex_unlock(&ctx->pollfds_lock);
59 CTX_LOCK(ctx);
60 TAILQ_INSERT_TAIL(&ctx->pollfds, pollfd, entry);
61 CTX_UNLOCK(ctx);
60
61 if (ctx->fd_added_cb)
62 ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data);
62
63 if (ctx->fd_added_cb)
64 ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data);
63 return (0);
64}
65
66UNEXPORTED void
65}
66
67UNEXPORTED void
67usb_remove_pollfd(libusb_context *ctx, int fd)
68libusb10_remove_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd)
68{
69{
69 struct usb_pollfd *pollfd;
70 int found;
70 if (ctx == NULL)
71 return; /* invalid */
71
72
72 found = 0;
73 pthread_mutex_lock(&ctx->pollfds_lock);
73 if (pollfd->entry.tqe_prev == NULL)
74 return; /* already dequeued */
74
75
75 TAILQ_FOREACH(pollfd, &ctx->pollfds, list) {
76 if (pollfd->pollfd.fd == fd) {
77 found = 1;
78 break ;
79 }
80 }
76 CTX_LOCK(ctx);
77 TAILQ_REMOVE(&ctx->pollfds, pollfd, entry);
78 pollfd->entry.tqe_prev = NULL;
79 CTX_UNLOCK(ctx);
81
80
82 if (found == 0) {
83 pthread_mutex_unlock(&ctx->pollfds_lock);
84 return ;
85 }
86
87 TAILQ_REMOVE(&ctx->pollfds, pollfd, list);
88 pthread_mutex_unlock(&ctx->pollfds_lock);
89 free(pollfd);
90
91 if (ctx->fd_removed_cb)
81 if (ctx->fd_removed_cb)
92 ctx->fd_removed_cb(fd, ctx->fd_cb_user_data);
82 ctx->fd_removed_cb(pollfd->pollfd.fd, ctx->fd_cb_user_data);
93}
94
83}
84
95UNEXPORTED void
96usb_handle_transfer_completion(struct usb_transfer *uxfer,
97 enum libusb_transfer_status status)
98{
99 libusb_transfer *xfer;
100 libusb_context *ctx;
101 int len;
85/* This function must be called locked */
102
86
103 xfer = (struct libusb_transfer *) ((uint8_t *)uxfer +
104 sizeof(struct usb_transfer));
105 ctx = xfer->dev_handle->dev->ctx;
106
107 pthread_mutex_lock(&ctx->flying_transfers_lock);
108 TAILQ_REMOVE(&ctx->flying_transfers, uxfer, list);
109 pthread_mutex_unlock(&ctx->flying_transfers_lock);
110
111 if (status == LIBUSB_TRANSFER_COMPLETED && xfer->flags &
112 LIBUSB_TRANSFER_SHORT_NOT_OK) {
113 len = xfer->length;
114 if (xfer->type == LIBUSB_TRANSFER_TYPE_CONTROL)
115 len -= sizeof(libusb_control_setup);
116 if (len != uxfer->transferred) {
117 status = LIBUSB_TRANSFER_ERROR;
118 }
119 }
120
121 xfer->status = status;
122 xfer->actual_length = uxfer->transferred;
123
124 if (xfer->callback)
125 xfer->callback(xfer);
126 if (xfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER)
127 libusb_free_transfer(xfer);
128
129 pthread_mutex_lock(&ctx->event_waiters_lock);
130 pthread_cond_broadcast(&ctx->event_waiters_cond);
131 pthread_mutex_unlock(&ctx->event_waiters_lock);
132}
133
134UNEXPORTED void
135usb_handle_disconnect(struct libusb_device_handle *devh)
87static int
88libusb10_handle_events_sub(struct libusb_context *ctx, struct timeval *tv)
136{
89{
137 struct libusb_context *ctx;
138 struct libusb_transfer *xfer;
139 struct usb_transfer *cur;
140 struct usb_transfer *to_cancel;
141
142 ctx = devh->dev->ctx;
143
144 while (1) {
145 pthread_mutex_lock(&ctx->flying_transfers_lock);
146 to_cancel = NULL;
147 TAILQ_FOREACH(cur, &ctx->flying_transfers, list) {
148 xfer = (struct libusb_transfer *) ((uint8_t *)cur +
149 sizeof(struct usb_transfer));
150 if (xfer->dev_handle == devh) {
151 to_cancel = cur;
152 break ;
153 }
154 }
155 pthread_mutex_unlock(&ctx->flying_transfers_lock);
156
157 if (to_cancel == NULL)
158 break ;
159
160 usb_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE);
161 }
162 return ;
163}
164
165UNEXPORTED int
166get_next_timeout(libusb_context *ctx, struct timeval *tv, struct timeval *out)
167{
168 struct timeval timeout;
169
170 if (libusb_get_next_timeout(ctx, &timeout)) {
171 if (timerisset(&timeout) == 0)
172 return 1;
173 if (timercmp(&timeout, tv, <) != 0)
174 *out = timeout;
175 else
176 *out = *tv;
177 } else {
178 *out = *tv;
179 }
180
181 return (0);
182}
183
184UNEXPORTED int
185handle_timeouts(struct libusb_context *ctx)
186{
187 struct timespec sys_ts;
188 struct timeval sys_tv;
189 struct timeval *cur_tv;
190 struct usb_transfer *xfer;
191 struct libusb_transfer *uxfer;
192 int ret;
193
194 GET_CONTEXT(ctx);
195 ret = 0;
196
197 pthread_mutex_lock(&ctx->flying_transfers_lock);
198 if (TAILQ_EMPTY(&ctx->flying_transfers))
199 goto out;
200
201 ret = clock_gettime(CLOCK_MONOTONIC, &sys_ts);
202 TIMESPEC_TO_TIMEVAL(&sys_tv, &sys_ts);
203
204 TAILQ_FOREACH(xfer, &ctx->flying_transfers, list) {
205 cur_tv = &xfer->timeout;
206
207 if (timerisset(cur_tv) == 0)
208 goto out;
209
210 if (xfer->flags & USB_TIMED_OUT)
211 continue;
212
213 if ((cur_tv->tv_sec > sys_tv.tv_sec) || (cur_tv->tv_sec == sys_tv.tv_sec &&
214 cur_tv->tv_usec > sys_tv.tv_usec))
215 goto out;
216
217 xfer->flags |= USB_TIMED_OUT;
218 uxfer = (libusb_transfer *) ((uint8_t *)xfer +
219 sizeof(struct usb_transfer));
220 ret = libusb_cancel_transfer(uxfer);
221 }
222out:
223 pthread_mutex_unlock(&ctx->flying_transfers_lock);
224 return (ret);
225}
226
227UNEXPORTED int
228handle_events(struct libusb_context *ctx, struct timeval *tv)
229{
230 struct libusb_pollfd *tmppollfd;
231 struct libusb_device_handle *devh;
232 struct usb_pollfd *ipollfd;
90 struct libusb_device *dev;
91 struct libusb20_device **ppdev;
92 struct libusb_super_pollfd *pfd;
233 struct pollfd *fds;
93 struct pollfd *fds;
234 struct pollfd *tfds;
94 struct libusb_super_transfer *sxfer;
95 struct libusb_transfer *uxfer;
235 nfds_t nfds;
96 nfds_t nfds;
236 int tmpfd;
237 int ret;
238 int timeout;
239 int i;
97 int timeout;
98 int i;
240
241 GET_CONTEXT(ctx);
242 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "handle_events enter");
99 int err;
243
100
101 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb10_handle_events_sub enter");
102
244 nfds = 0;
103 nfds = 0;
245 i = -1;
104 i = 0;
105 TAILQ_FOREACH(pfd, &ctx->pollfds, entry)
106 nfds++;
246
107
247 pthread_mutex_lock(&ctx->pollfds_lock);
248 TAILQ_FOREACH(ipollfd, &ctx->pollfds, list)
249 nfds++;
250
251 fds = alloca(sizeof(*fds) * nfds);
252 if (fds == NULL)
253 return (LIBUSB_ERROR_NO_MEM);
254
108 fds = alloca(sizeof(*fds) * nfds);
109 if (fds == NULL)
110 return (LIBUSB_ERROR_NO_MEM);
111
255 TAILQ_FOREACH(ipollfd, &ctx->pollfds, list) {
256 tmppollfd = &ipollfd->pollfd;
257 tmpfd = tmppollfd->fd;
258 i++;
259 fds[i].fd = tmpfd;
260 fds[i].events = tmppollfd->events;
112 ppdev = alloca(sizeof(*ppdev) * nfds);
113 if (ppdev == NULL)
114 return (LIBUSB_ERROR_NO_MEM);
115
116 TAILQ_FOREACH(pfd, &ctx->pollfds, entry) {
117 fds[i].fd = pfd->pollfd.fd;
118 fds[i].events = pfd->pollfd.events;
261 fds[i].revents = 0;
119 fds[i].revents = 0;
120 ppdev[i] = pfd->pdev;
121 if (pfd->pdev != NULL)
122 libusb_get_device(pfd->pdev)->refcnt++;
123 i++;
262 }
263
124 }
125
264 pthread_mutex_unlock(&ctx->pollfds_lock);
126 if (tv == NULL)
127 timeout = -1;
128 else
129 timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000);
265
130
266 timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000);
267 if (tv->tv_usec % 1000)
268 timeout++;
131 CTX_UNLOCK(ctx);
132 err = poll(fds, nfds, timeout);
133 CTX_LOCK(ctx);
269
134
270 ret = poll(fds, nfds, timeout);
271 if (ret == 0)
272 return (handle_timeouts(ctx));
273 else if (ret == -1 && errno == EINTR)
274 return (LIBUSB_ERROR_INTERRUPTED);
275 else if (ret < 0)
276 return (LIBUSB_ERROR_IO);
135 if ((err == -1) && (errno == EINTR))
136 err = LIBUSB_ERROR_INTERRUPTED;
137 else if (err < 0)
138 err = LIBUSB_ERROR_IO;
277
139
278 if (fds[0].revents) {
279 if (ret == 1){
280 ret = 0;
281 goto handled;
282 } else {
283 fds[0].revents = 0;
284 ret--;
140 if (err < 1) {
141 for (i = 0; i != nfds; i++) {
142 if (ppdev[i] != NULL) {
143 CTX_UNLOCK(ctx);
144 libusb_unref_device(libusb_get_device(ppdev[i]));
145 CTX_LOCK(ctx);
146 }
285 }
147 }
148 goto do_done;
286 }
149 }
150 for (i = 0; i != nfds; i++) {
151 if (fds[i].revents == 0)
152 continue;
153 if (ppdev[i] != NULL) {
154 dev = libusb_get_device(ppdev[i]);
287
155
288 pthread_mutex_lock(&ctx->open_devs_lock);
289 for (i = 0, devh = NULL ; i < nfds && ret > 0 ; i++) {
156 err = libusb20_dev_process(ppdev[i]);
157 if (err) {
158 /* cancel all transfers - device is gone */
159 libusb10_cancel_all_transfer(dev);
160 /*
161 * make sure we don't go into an infinite
162 * loop
163 */
164 libusb10_remove_pollfd(dev->ctx, &dev->dev_poll);
165 }
166 CTX_UNLOCK(ctx);
167 libusb_unref_device(dev);
168 CTX_LOCK(ctx);
290
169
291 tfds = &fds[i];
292 if (!tfds->revents)
293 continue;
170 } else {
171 uint8_t dummy;
294
172
295 ret--;
296 TAILQ_FOREACH(devh, &ctx->open_devs, list) {
297 if (libusb20_dev_get_fd(devh->os_priv) == tfds->fd)
298 break ;
173 while (1) {
174 if (read(fds[i].fd, &dummy, 1) != 1)
175 break;
176 }
299 }
177 }
178 }
300
179
301 if (tfds->revents & POLLERR) {
302 usb_remove_pollfd(ctx, libusb20_dev_get_fd(devh->os_priv));
303 if (devh != NULL)
304 usb_handle_disconnect(devh);
305 continue ;
306 }
180 err = 0;
307
181
182do_done:
308
183
309 pthread_mutex_lock(&libusb20_lock);
310 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20_PROCESS");
311 if (devh != NULL)
312 ret = libusb20_dev_process(devh->os_priv);
313 pthread_mutex_unlock(&libusb20_lock);
184 /* Do all done callbacks */
314
185
186 while ((sxfer = TAILQ_FIRST(&ctx->tr_done))) {
187 TAILQ_REMOVE(&ctx->tr_done, sxfer, entry);
188 sxfer->entry.tqe_prev = NULL;
315
189
316 if (ret == 0 || ret == LIBUSB20_ERROR_NO_DEVICE)
317 continue;
318 else if (ret < 0)
319 goto out;
190 ctx->tr_done_ref++;
191
192 CTX_UNLOCK(ctx);
193
194 uxfer = (struct libusb_transfer *)(
195 ((uint8_t *)sxfer) + sizeof(*sxfer));
196
197 if (uxfer->callback != NULL)
198 (uxfer->callback) (uxfer);
199
200 if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER)
201 free(uxfer->buffer);
202
203 if (uxfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER)
204 libusb_free_transfer(uxfer);
205
206 CTX_LOCK(ctx);
207
208 ctx->tr_done_ref--;
209 ctx->tr_done_gen++;
320 }
321
210 }
211
322 ret = 0;
323out:
324 pthread_mutex_unlock(&ctx->open_devs_lock);
212 /* Wakeup other waiters */
213 pthread_cond_broadcast(&ctx->ctx_cond);
325
214
326handled:
327 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "handle_events leave");
328 return ret;
215 return (err);
329}
330
331/* Polling and timing */
332
333int
216}
217
218/* Polling and timing */
219
220int
334libusb_try_lock_events(libusb_context * ctx)
221libusb_try_lock_events(libusb_context *ctx)
335{
222{
336 int ret;
223 int err;
337
224
338 GET_CONTEXT(ctx);
339 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_try_lock_events enter");
340
341 pthread_mutex_lock(&ctx->pollfd_modify_lock);
342 ret = ctx->pollfd_modify;
343 pthread_mutex_unlock(&ctx->pollfd_modify_lock);
344
345 if (ret != 0)
225 ctx = GET_CONTEXT(ctx);
226 if (ctx == NULL)
346 return (1);
347
227 return (1);
228
348 ret = pthread_mutex_trylock(&ctx->events_lock);
349
350 if (ret != 0)
229 err = CTX_TRYLOCK(ctx);
230 if (err)
351 return (1);
231 return (1);
352
353 ctx->event_handler_active = 1;
354
232
355 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_try_lock_events leave");
356 return (0);
233 err = (ctx->ctx_handler != NO_THREAD);
234 if (err)
235 CTX_UNLOCK(ctx);
236 else
237 ctx->ctx_handler = pthread_self();
238
239 return (err);
357}
358
359void
240}
241
242void
360libusb_lock_events(libusb_context * ctx)
243libusb_lock_events(libusb_context *ctx)
361{
244{
362 GET_CONTEXT(ctx);
363 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_events enter");
364
365 pthread_mutex_lock(&ctx->events_lock);
366 ctx->event_handler_active = 1;
367
368 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_events leave");
245 ctx = GET_CONTEXT(ctx);
246 CTX_LOCK(ctx);
247 if (ctx->ctx_handler == NO_THREAD)
248 ctx->ctx_handler = pthread_self();
369}
370
371void
249}
250
251void
372libusb_unlock_events(libusb_context * ctx)
252libusb_unlock_events(libusb_context *ctx)
373{
253{
374 GET_CONTEXT(ctx);
375 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_events enter");
376
377 ctx->event_handler_active = 0;
378 pthread_mutex_unlock(&ctx->events_lock);
379
380 pthread_mutex_lock(&ctx->event_waiters_lock);
381 pthread_cond_broadcast(&ctx->event_waiters_cond);
382 pthread_mutex_unlock(&ctx->event_waiters_lock);
383
384 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_events leave");
254 ctx = GET_CONTEXT(ctx);
255 if (ctx->ctx_handler == pthread_self()) {
256 ctx->ctx_handler = NO_THREAD;
257 pthread_cond_broadcast(&ctx->ctx_cond);
258 }
259 CTX_UNLOCK(ctx);
385}
386
387int
260}
261
262int
388libusb_event_handling_ok(libusb_context * ctx)
263libusb_event_handling_ok(libusb_context *ctx)
389{
264{
390 int ret;
391
392 GET_CONTEXT(ctx);
393 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handling_ok enter");
394
395 pthread_mutex_lock(&ctx->pollfd_modify_lock);
396 ret = ctx->pollfd_modify;
397 pthread_mutex_unlock(&ctx->pollfd_modify_lock);
398
399 if (ret != 0)
400 return (0);
401
402 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handling_ok leave");
403 return (1);
265 ctx = GET_CONTEXT(ctx);
266 return (ctx->ctx_handler == pthread_self());
404}
405
406int
267}
268
269int
407libusb_event_handler_active(libusb_context * ctx)
270libusb_event_handler_active(libusb_context *ctx)
408{
271{
409 int ret;
410
411 GET_CONTEXT(ctx);
412 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handler_active enter");
413
414 pthread_mutex_lock(&ctx->pollfd_modify_lock);
415 ret = ctx->pollfd_modify;
416 pthread_mutex_unlock(&ctx->pollfd_modify_lock);
417
418 if (ret != 0)
419 return (1);
420
421 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handler_active leave");
422 return (ctx->event_handler_active);
272 ctx = GET_CONTEXT(ctx);
273 return (ctx->ctx_handler != NO_THREAD);
423}
424
425void
274}
275
276void
426libusb_lock_event_waiters(libusb_context * ctx)
277libusb_lock_event_waiters(libusb_context *ctx)
427{
278{
428 GET_CONTEXT(ctx);
429 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_event_waiters enter");
430
431 pthread_mutex_lock(&ctx->event_waiters_lock);
432
433 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_event_waiters leave");
279 ctx = GET_CONTEXT(ctx);
280 CTX_LOCK(ctx);
434}
435
436void
281}
282
283void
437libusb_unlock_event_waiters(libusb_context * ctx)
284libusb_unlock_event_waiters(libusb_context *ctx)
438{
285{
439 GET_CONTEXT(ctx);
440 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_event_waiters enter");
441
442 pthread_mutex_unlock(&ctx->event_waiters_lock);
443
444 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_event_waiters leave");
286 ctx = GET_CONTEXT(ctx);
287 CTX_UNLOCK(ctx);
445}
446
447int
288}
289
290int
448libusb_wait_for_event(libusb_context * ctx, struct timeval *tv)
291libusb_wait_for_event(libusb_context *ctx, struct timeval *tv)
449{
292{
450 int ret;
451 struct timespec ts;
293 struct timespec ts;
294 int err;
452
295
453 GET_CONTEXT(ctx);
296 ctx = GET_CONTEXT(ctx);
454 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter");
455
456 if (tv == NULL) {
297 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter");
298
299 if (tv == NULL) {
457 pthread_cond_wait(&ctx->event_waiters_cond,
458 &ctx->event_waiters_lock);
300 pthread_cond_wait(&ctx->ctx_cond,
301 &ctx->ctx_lock);
459 return (0);
460 }
302 return (0);
303 }
461
462 ret = clock_gettime(CLOCK_REALTIME, &ts);
463 if (ret < 0)
304 err = clock_gettime(CLOCK_REALTIME, &ts);
305 if (err < 0)
464 return (LIBUSB_ERROR_OTHER);
465
466 ts.tv_sec = tv->tv_sec;
467 ts.tv_nsec = tv->tv_usec * 1000;
306 return (LIBUSB_ERROR_OTHER);
307
308 ts.tv_sec = tv->tv_sec;
309 ts.tv_nsec = tv->tv_usec * 1000;
468 if (ts.tv_nsec > 1000000000) {
310 if (ts.tv_nsec >= 1000000000) {
469 ts.tv_nsec -= 1000000000;
470 ts.tv_sec++;
471 }
311 ts.tv_nsec -= 1000000000;
312 ts.tv_sec++;
313 }
314 err = pthread_cond_timedwait(&ctx->ctx_cond,
315 &ctx->ctx_lock, &ts);
472
316
473 ret = pthread_cond_timedwait(&ctx->event_waiters_cond,
474 &ctx->event_waiters_lock, &ts);
475
476 if (ret == ETIMEDOUT)
317 if (err == ETIMEDOUT)
477 return (1);
478
318 return (1);
319
479 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event leave");
480 return (0);
481}
482
483int
320 return (0);
321}
322
323int
484libusb_handle_events_timeout(libusb_context * ctx, struct timeval *tv)
324libusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv)
485{
325{
486 struct timeval poll_timeout;
487 int ret;
488
489 GET_CONTEXT(ctx);
326 int err;
327
328 ctx = GET_CONTEXT(ctx);
329
490 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout enter");
491
330 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout enter");
331
492 ret = get_next_timeout(ctx, tv, &poll_timeout);
493 if (ret != 0) {
494 return handle_timeouts(ctx);
495 }
496retry:
497 if (libusb_try_lock_events(ctx) == 0) {
498 ret = handle_events(ctx, &poll_timeout);
499 libusb_unlock_events(ctx);
500 return ret;
501 }
332 libusb_lock_events(ctx);
502
333
503 libusb_lock_event_waiters(ctx);
504 if (libusb_event_handler_active(ctx) == 0) {
505 libusb_unlock_event_waiters(ctx);
506 goto retry;
507 }
508
509 ret = libusb_wait_for_event(ctx, &poll_timeout);
510 libusb_unlock_event_waiters(ctx);
334 err = libusb_handle_events_locked(ctx, tv);
511
335
512 if (ret < 0)
513 return ret;
514 else if (ret == 1)
515 return (handle_timeouts(ctx));
336 libusb_unlock_events(ctx);
516
517 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout leave");
337
338 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout leave");
518 return (0);
339
340 return (err);
519}
520
521int
341}
342
343int
522libusb_handle_events(libusb_context * ctx)
344libusb_handle_events(libusb_context *ctx)
523{
345{
524 struct timeval tv;
525 int ret;
526
527 GET_CONTEXT(ctx);
528 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events enter");
529
530 tv.tv_sec = 2;
531 tv.tv_usec = 0;
532 ret = libusb_handle_events_timeout(ctx, &tv);
533
534 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events leave");
535 return (ret);
346 return (libusb_handle_events_timeout(ctx, NULL));
536}
537
538int
347}
348
349int
539libusb_handle_events_locked(libusb_context * ctx, struct timeval *tv)
350libusb_handle_events_locked(libusb_context *ctx, struct timeval *tv)
540{
351{
541 int ret;
542 struct timeval poll_tv;
352 int err;
543
353
544 GET_CONTEXT(ctx);
545 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_locked enter");
354 ctx = GET_CONTEXT(ctx);
546
355
547 ret = get_next_timeout(ctx, tv, &poll_tv);
548 if (ret != 0) {
549 return handle_timeouts(ctx);
356 if (libusb_event_handling_ok(ctx)) {
357 err = libusb10_handle_events_sub(ctx, tv);
358 } else {
359 libusb_wait_for_event(ctx, tv);
360 err = 0;
550 }
361 }
551
552 ret = handle_events(ctx, &poll_tv);
553
554 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_locked leave");
555 return (ret);
362 return (err);
556}
557
558int
363}
364
365int
559libusb_get_next_timeout(libusb_context * ctx, struct timeval *tv)
366libusb_get_next_timeout(libusb_context *ctx, struct timeval *tv)
560{
367{
561 struct usb_transfer *xfer;
562 struct timeval *next_tv;
563 struct timeval cur_tv;
564 struct timespec cur_ts;
565 int found;
566 int ret;
567
568 GET_CONTEXT(ctx);
569 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_next_timeout enter");
570
571 found = 0;
572 pthread_mutex_lock(&ctx->flying_transfers_lock);
573 if (TAILQ_EMPTY(&ctx->flying_transfers)) {
574 pthread_mutex_unlock(&ctx->flying_transfers_lock);
575 return (0);
576 }
577
578 TAILQ_FOREACH(xfer, &ctx->flying_transfers, list) {
579 if (!(xfer->flags & USB_TIMED_OUT)) {
580 found = 1;
581 break ;
582 }
583 }
584 pthread_mutex_unlock(&ctx->flying_transfers_lock);
585
586 if (found == 0) {
587 return 0;
588 }
589
590 next_tv = &xfer->timeout;
591 if (timerisset(next_tv) == 0)
592 return (0);
593
594 ret = clock_gettime(CLOCK_MONOTONIC, &cur_ts);
595 if (ret < 0)
596 return (LIBUSB_ERROR_OTHER);
597 TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts);
598
599 if (timercmp(&cur_tv, next_tv, >=) != 0)
600 timerclear(tv);
601 else
602 timersub(next_tv, &cur_tv, tv);
603
604 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_next_timeout leave");
605 return (1);
368 /* all timeouts are currently being done by the kernel */
369 timerclear(tv);
370 return (0);
606}
607
608void
371}
372
373void
609libusb_set_pollfd_notifiers(libusb_context * ctx,
374libusb_set_pollfd_notifiers(libusb_context *ctx,
610 libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
611 void *user_data)
612{
375 libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
376 void *user_data)
377{
613 GET_CONTEXT(ctx);
614 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_pollfd_notifiers enter");
378 ctx = GET_CONTEXT(ctx);
615
616 ctx->fd_added_cb = added_cb;
617 ctx->fd_removed_cb = removed_cb;
618 ctx->fd_cb_user_data = user_data;
379
380 ctx->fd_added_cb = added_cb;
381 ctx->fd_removed_cb = removed_cb;
382 ctx->fd_cb_user_data = user_data;
619
620 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_pollfd_notifiers leave");
621}
622
623struct libusb_pollfd **
383}
384
385struct libusb_pollfd **
624libusb_get_pollfds(libusb_context * ctx)
386libusb_get_pollfds(libusb_context *ctx)
625{
387{
626 struct usb_pollfd *pollfd;
388 struct libusb_super_pollfd *pollfd;
627 libusb_pollfd **ret;
628 int i;
629
389 libusb_pollfd **ret;
390 int i;
391
630 GET_CONTEXT(ctx);
631 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_pollfds enter");
392 ctx = GET_CONTEXT(ctx);
632
393
394 CTX_LOCK(ctx);
395
633 i = 0;
396 i = 0;
634 pthread_mutex_lock(&ctx->pollfds_lock);
635 TAILQ_FOREACH(pollfd, &ctx->pollfds, list)
636 i++;
397 TAILQ_FOREACH(pollfd, &ctx->pollfds, entry)
398 i++;
637
399
638 ret = calloc(i + 1 , sizeof(struct libusb_pollfd *));
639 if (ret == NULL) {
640 pthread_mutex_unlock(&ctx->pollfds_lock);
641 return (ret);
642 }
400 ret = calloc(i + 1, sizeof(struct libusb_pollfd *));
401 if (ret == NULL)
402 goto done;
643
644 i = 0;
403
404 i = 0;
645 TAILQ_FOREACH(pollfd, &ctx->pollfds, list)
646 ret[i++] = (struct libusb_pollfd *) pollfd;
405 TAILQ_FOREACH(pollfd, &ctx->pollfds, entry)
406 ret[i++] = &pollfd->pollfd;
647 ret[i] = NULL;
648
407 ret[i] = NULL;
408
649 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_pollfds leave");
409done:
410 CTX_UNLOCK(ctx);
650 return (ret);
651}
652
653
654/* Synchronous device I/O */
655
411 return (ret);
412}
413
414
415/* Synchronous device I/O */
416
656static void ctrl_tr_cb(struct libusb_transfer *transfer)
657{
658 libusb_context *ctx;
659 int *complet;
660
661 ctx = NULL;
662 GET_CONTEXT(ctx);
663 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "CALLBACK ENTER");
664
665 complet = transfer->user_data;
666 *complet = 1;
667}
668
669int
417int
670libusb_control_transfer(libusb_device_handle * devh,
418libusb_control_transfer(libusb_device_handle *devh,
671 uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
419 uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
672 unsigned char *data, uint16_t wLength, unsigned int timeout)
420 uint8_t *data, uint16_t wLength, unsigned int timeout)
673{
421{
674 struct libusb_transfer *xfer;
675 struct libusb_control_setup *ctr;
676 libusb_context *ctx;
677 unsigned char *buff;
678 int complet;
679 int ret;
422 struct LIBUSB20_CONTROL_SETUP_DECODED req;
423 int err;
424 uint16_t actlen;
680
425
681 ctx = devh->dev->ctx;
682 GET_CONTEXT(ctx);
683 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_control_transfer enter");
426 if (devh == NULL)
427 return (LIBUSB_ERROR_INVALID_PARAM);
684
428
685 if (devh == NULL || data == NULL)
686 return (LIBUSB_ERROR_NO_MEM);
429 if ((wLength != 0) && (data == NULL))
430 return (LIBUSB_ERROR_INVALID_PARAM);
687
431
688 xfer = libusb_alloc_transfer(0);
689 if (xfer == NULL)
690 return (LIBUSB_ERROR_NO_MEM);
432 LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
691
433
692 buff = malloc(sizeof(libusb_control_setup) + wLength);
693 if (buff == NULL) {
694 libusb_free_transfer(xfer);
695 return (LIBUSB_ERROR_NO_MEM);
696 }
434 req.bmRequestType = bmRequestType;
435 req.bRequest = bRequest;
436 req.wValue = wValue;
437 req.wIndex = wIndex;
438 req.wLength = wLength;
697
439
698 ctr = (libusb_control_setup *)buff;
699 ctr->bmRequestType = bmRequestType;
700 ctr->bRequest = bRequest;
701 ctr->wValue = wValue;
702 ctr->wIndex = wIndex;
703 ctr->wLength = wLength;
704 if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
705 memcpy(buff + sizeof(libusb_control_setup), data, wLength);
440 err = libusb20_dev_request_sync(devh, &req, data,
441 &actlen, timeout, 0);
706
442
707 xfer->dev_handle = devh;
708 xfer->endpoint = 0;
709 xfer->type = LIBUSB_TRANSFER_TYPE_CONTROL;
710 xfer->timeout = timeout;
711 xfer->buffer = buff;
712 xfer->length = sizeof(libusb_control_setup) + wLength;
713 xfer->user_data = &complet;
714 xfer->callback = ctrl_tr_cb;
715 xfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
716 complet = 0;
443 if (err == LIBUSB20_ERROR_PIPE)
444 return (LIBUSB_ERROR_PIPE);
445 else if (err == LIBUSB20_ERROR_TIMEOUT)
446 return (LIBUSB_ERROR_TIMEOUT);
447 else if (err)
448 return (LIBUSB_ERROR_NO_DEVICE);
717
449
718 if ((ret = libusb_submit_transfer(xfer)) < 0) {
719 libusb_free_transfer(xfer);
720 return (ret);
721 }
450 return (actlen);
451}
722
452
723 while (complet == 0)
724 if ((ret = libusb_handle_events(ctx)) < 0) {
725 libusb_cancel_transfer(xfer);
726 while (complet == 0)
727 if (libusb_handle_events(ctx) < 0) {
728 break;
729 }
730 libusb_free_transfer(xfer);
731 return (ret);
732 }
453static void
454libusb10_do_transfer_cb(struct libusb_transfer *transfer)
455{
456 libusb_context *ctx;
457 int *pdone;
733
458
459 ctx = GET_CONTEXT(NULL);
734
460
735 if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
736 memcpy(data, buff + sizeof(libusb_control_setup), wLength);
461 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "sync I/O done");
737
462
738 switch (xfer->status) {
739 case LIBUSB_TRANSFER_COMPLETED:
740 ret = xfer->actual_length;
741 break;
742 case LIBUSB_TRANSFER_TIMED_OUT:
743 case LIBUSB_TRANSFER_STALL:
744 case LIBUSB_TRANSFER_NO_DEVICE:
745 ret = xfer->status;
746 break;
747 default:
748 ret = LIBUSB_ERROR_OTHER;
749 }
750 libusb_free_transfer(xfer);
751
752 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_control_transfer leave");
753 return (ret);
463 pdone = transfer->user_data;
464 *pdone = 1;
754}
755
465}
466
467/*
468 * TODO: Replace the following function. Allocating and freeing on a
469 * per-transfer basis is slow. --HPS
470 */
756static int
471static int
757do_transfer(struct libusb_device_handle *devh,
758 unsigned char endpoint, unsigned char *data, int length,
472libusb10_do_transfer(libusb_device_handle *devh,
473 uint8_t endpoint, uint8_t *data, int length,
759 int *transferred, unsigned int timeout, int type)
760{
474 int *transferred, unsigned int timeout, int type)
475{
761 struct libusb_transfer *xfer;
762 libusb_context *ctx;
476 libusb_context *ctx;
763 int complet;
477 struct libusb_transfer *xfer;
478 volatile int complet;
764 int ret;
765
479 int ret;
480
766 if (devh == NULL || data == NULL)
767 return (LIBUSB_ERROR_NO_MEM);
481 if (devh == NULL)
482 return (LIBUSB_ERROR_INVALID_PARAM);
768
483
484 if ((length != 0) && (data == NULL))
485 return (LIBUSB_ERROR_INVALID_PARAM);
486
769 xfer = libusb_alloc_transfer(0);
770 if (xfer == NULL)
771 return (LIBUSB_ERROR_NO_MEM);
772
487 xfer = libusb_alloc_transfer(0);
488 if (xfer == NULL)
489 return (LIBUSB_ERROR_NO_MEM);
490
773 ctx = devh->dev->ctx;
774 GET_CONTEXT(ctx);
491 ctx = libusb_get_device(devh)->ctx;
775
776 xfer->dev_handle = devh;
777 xfer->endpoint = endpoint;
778 xfer->type = type;
779 xfer->timeout = timeout;
780 xfer->buffer = data;
781 xfer->length = length;
492
493 xfer->dev_handle = devh;
494 xfer->endpoint = endpoint;
495 xfer->type = type;
496 xfer->timeout = timeout;
497 xfer->buffer = data;
498 xfer->length = length;
782 xfer->user_data = &complet;
783 xfer->callback = ctrl_tr_cb;
499 xfer->user_data = (void *)&complet;
500 xfer->callback = libusb10_do_transfer_cb;
784 complet = 0;
785
501 complet = 0;
502
786 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "SUBMIT_TRANSFER");
787 if ((ret = libusb_submit_transfer(xfer)) < 0) {
788 libusb_free_transfer(xfer);
503 if ((ret = libusb_submit_transfer(xfer)) < 0) {
504 libusb_free_transfer(xfer);
789 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "SUBMIT_TRANSFER FAILED %i", ret);
790 return (ret);
791 }
505 return (ret);
506 }
792
793 while (complet == 0) {
794 if ((ret = libusb_handle_events(ctx)) < 0) {
795 libusb_cancel_transfer(xfer);
507 while (complet == 0) {
508 if ((ret = libusb_handle_events(ctx)) < 0) {
509 libusb_cancel_transfer(xfer);
796 libusb_free_transfer(xfer);
797 while (complet == 0) {
798 if (libusb_handle_events(ctx) < 0)
799 break ;
800 }
801 return (ret);
510 usleep(1000); /* nice it */
802 }
803 }
804
805 *transferred = xfer->actual_length;
511 }
512 }
513
514 *transferred = xfer->actual_length;
806 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "xfer->status %i", xfer->status);
515
807 switch (xfer->status) {
808 case LIBUSB_TRANSFER_COMPLETED:
516 switch (xfer->status) {
517 case LIBUSB_TRANSFER_COMPLETED:
809 ret = xfer->actual_length;
518 ret = 0;
810 break;
811 case LIBUSB_TRANSFER_TIMED_OUT:
519 break;
520 case LIBUSB_TRANSFER_TIMED_OUT:
521 ret = LIBUSB_ERROR_TIMEOUT;
522 break;
812 case LIBUSB_TRANSFER_OVERFLOW:
523 case LIBUSB_TRANSFER_OVERFLOW:
524 ret = LIBUSB_ERROR_OVERFLOW;
525 break;
813 case LIBUSB_TRANSFER_STALL:
526 case LIBUSB_TRANSFER_STALL:
527 ret = LIBUSB_ERROR_PIPE;
528 break;
814 case LIBUSB_TRANSFER_NO_DEVICE:
529 case LIBUSB_TRANSFER_NO_DEVICE:
815 ret = xfer->status;
530 ret = LIBUSB_ERROR_NO_DEVICE;
816 break;
817 default:
818 ret = LIBUSB_ERROR_OTHER;
531 break;
532 default:
533 ret = LIBUSB_ERROR_OTHER;
534 break;
819 }
820
821 libusb_free_transfer(xfer);
822 return (ret);
823}
824
825int
535 }
536
537 libusb_free_transfer(xfer);
538 return (ret);
539}
540
541int
826libusb_bulk_transfer(struct libusb_device_handle *devh,
827 unsigned char endpoint, unsigned char *data, int length,
542libusb_bulk_transfer(libusb_device_handle *devh,
543 uint8_t endpoint, uint8_t *data, int length,
828 int *transferred, unsigned int timeout)
829{
830 libusb_context *ctx;
831 int ret;
544 int *transferred, unsigned int timeout)
545{
546 libusb_context *ctx;
547 int ret;
832
833 ctx = NULL;
834 GET_CONTEXT(ctx);
548
549 ctx = GET_CONTEXT(NULL);
835 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter");
836
550 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter");
551
837 ret = do_transfer(devh, endpoint, data, length, transferred,
552 ret = libusb10_do_transfer(devh, endpoint, data, length, transferred,
838 timeout, LIBUSB_TRANSFER_TYPE_BULK);
839
840 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave");
841 return (ret);
842}
843
553 timeout, LIBUSB_TRANSFER_TYPE_BULK);
554
555 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave");
556 return (ret);
557}
558
844/*
845 * Need to fix xfer->type
846 */
847int
559int
848libusb_interrupt_transfer(struct libusb_device_handle *devh,
849 unsigned char endpoint, unsigned char *data, int length,
560libusb_interrupt_transfer(libusb_device_handle *devh,
561 uint8_t endpoint, uint8_t *data, int length,
850 int *transferred, unsigned int timeout)
851{
852 libusb_context *ctx;
853 int ret;
854
562 int *transferred, unsigned int timeout)
563{
564 libusb_context *ctx;
565 int ret;
566
855 ctx = NULL;
856 GET_CONTEXT(ctx);
567 ctx = GET_CONTEXT(NULL);
857 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter");
858
568 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter");
569
859 ret = do_transfer(devh, endpoint, data, length, transferred,
570 ret = libusb10_do_transfer(devh, endpoint, data, length, transferred,
860 timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
861
862 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave");
863 return (ret);
864}
571 timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
572
573 DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave");
574 return (ret);
575}