xref: /freebsd/lib/libusb/libusb10_io.c (revision 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
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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 <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 
42 UNEXPORTED void
43 libusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd,
44     struct libusb20_device *pdev, int fd, short events)
45 {
46 	if (ctx == NULL)
47 		return;			/* invalid */
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;
56 	pollfd->pollfd.fd = fd;
57 	pollfd->pollfd.events = events;
58 
59 	CTX_LOCK(ctx);
60 	TAILQ_INSERT_TAIL(&ctx->pollfds, pollfd, entry);
61 	CTX_UNLOCK(ctx);
62 
63 	if (ctx->fd_added_cb)
64 		ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data);
65 }
66 
67 UNEXPORTED void
68 libusb10_remove_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd)
69 {
70 	if (ctx == NULL)
71 		return;			/* invalid */
72 
73 	if (pollfd->entry.tqe_prev == NULL)
74 		return;			/* already dequeued */
75 
76 	CTX_LOCK(ctx);
77 	TAILQ_REMOVE(&ctx->pollfds, pollfd, entry);
78 	pollfd->entry.tqe_prev = NULL;
79 	CTX_UNLOCK(ctx);
80 
81 	if (ctx->fd_removed_cb)
82 		ctx->fd_removed_cb(pollfd->pollfd.fd, ctx->fd_cb_user_data);
83 }
84 
85 /* This function must be called locked */
86 
87 static int
88 libusb10_handle_events_sub(struct libusb_context *ctx, struct timeval *tv)
89 {
90 	struct libusb_device *dev;
91 	struct libusb20_device **ppdev;
92 	struct libusb_super_pollfd *pfd;
93 	struct pollfd *fds;
94 	struct libusb_super_transfer *sxfer;
95 	struct libusb_transfer *uxfer;
96 	nfds_t nfds;
97 	int timeout;
98 	int i;
99 	int err;
100 
101 	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb10_handle_events_sub enter");
102 
103 	nfds = 0;
104 	i = 0;
105 	TAILQ_FOREACH(pfd, &ctx->pollfds, entry)
106 	    nfds++;
107 
108 	fds = alloca(sizeof(*fds) * nfds);
109 	if (fds == NULL)
110 		return (LIBUSB_ERROR_NO_MEM);
111 
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;
119 		fds[i].revents = 0;
120 		ppdev[i] = pfd->pdev;
121 		if (pfd->pdev != NULL)
122 			libusb_get_device(pfd->pdev)->refcnt++;
123 		i++;
124 	}
125 
126 	if (tv == NULL)
127 		timeout = -1;
128 	else
129 		timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000);
130 
131 	CTX_UNLOCK(ctx);
132 	err = poll(fds, nfds, timeout);
133 	CTX_LOCK(ctx);
134 
135 	if ((err == -1) && (errno == EINTR))
136 		err = LIBUSB_ERROR_INTERRUPTED;
137 	else if (err < 0)
138 		err = LIBUSB_ERROR_IO;
139 
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 			}
147 		}
148 		goto do_done;
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]);
155 
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);
169 
170 		} else {
171 			uint8_t dummy;
172 
173 			while (1) {
174 				if (read(fds[i].fd, &dummy, 1) != 1)
175 					break;
176 			}
177 		}
178 	}
179 
180 	err = 0;
181 
182 do_done:
183 
184 	/* Do all done callbacks */
185 
186 	while ((sxfer = TAILQ_FIRST(&ctx->tr_done))) {
187 		TAILQ_REMOVE(&ctx->tr_done, sxfer, entry);
188 		sxfer->entry.tqe_prev = NULL;
189 
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++;
210 	}
211 
212 	/* Wakeup other waiters */
213 	pthread_cond_broadcast(&ctx->ctx_cond);
214 
215 	return (err);
216 }
217 
218 /* Polling and timing */
219 
220 int
221 libusb_try_lock_events(libusb_context *ctx)
222 {
223 	int err;
224 
225 	ctx = GET_CONTEXT(ctx);
226 	if (ctx == NULL)
227 		return (1);
228 
229 	err = CTX_TRYLOCK(ctx);
230 	if (err)
231 		return (1);
232 
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);
240 }
241 
242 void
243 libusb_lock_events(libusb_context *ctx)
244 {
245 	ctx = GET_CONTEXT(ctx);
246 	CTX_LOCK(ctx);
247 	if (ctx->ctx_handler == NO_THREAD)
248 		ctx->ctx_handler = pthread_self();
249 }
250 
251 void
252 libusb_unlock_events(libusb_context *ctx)
253 {
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);
260 }
261 
262 int
263 libusb_event_handling_ok(libusb_context *ctx)
264 {
265 	ctx = GET_CONTEXT(ctx);
266 	return (ctx->ctx_handler == pthread_self());
267 }
268 
269 int
270 libusb_event_handler_active(libusb_context *ctx)
271 {
272 	ctx = GET_CONTEXT(ctx);
273 	return (ctx->ctx_handler != NO_THREAD);
274 }
275 
276 void
277 libusb_lock_event_waiters(libusb_context *ctx)
278 {
279 	ctx = GET_CONTEXT(ctx);
280 	CTX_LOCK(ctx);
281 }
282 
283 void
284 libusb_unlock_event_waiters(libusb_context *ctx)
285 {
286 	ctx = GET_CONTEXT(ctx);
287 	CTX_UNLOCK(ctx);
288 }
289 
290 int
291 libusb_wait_for_event(libusb_context *ctx, struct timeval *tv)
292 {
293 	struct timespec ts;
294 	int err;
295 
296 	ctx = GET_CONTEXT(ctx);
297 	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter");
298 
299 	if (tv == NULL) {
300 		pthread_cond_wait(&ctx->ctx_cond,
301 		    &ctx->ctx_lock);
302 		return (0);
303 	}
304 	err = clock_gettime(CLOCK_REALTIME, &ts);
305 	if (err < 0)
306 		return (LIBUSB_ERROR_OTHER);
307 
308 	ts.tv_sec = tv->tv_sec;
309 	ts.tv_nsec = tv->tv_usec * 1000;
310 	if (ts.tv_nsec >= 1000000000) {
311 		ts.tv_nsec -= 1000000000;
312 		ts.tv_sec++;
313 	}
314 	err = pthread_cond_timedwait(&ctx->ctx_cond,
315 	    &ctx->ctx_lock, &ts);
316 
317 	if (err == ETIMEDOUT)
318 		return (1);
319 
320 	return (0);
321 }
322 
323 int
324 libusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv)
325 {
326 	int err;
327 
328 	ctx = GET_CONTEXT(ctx);
329 
330 	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout enter");
331 
332 	libusb_lock_events(ctx);
333 
334 	err = libusb_handle_events_locked(ctx, tv);
335 
336 	libusb_unlock_events(ctx);
337 
338 	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout leave");
339 
340 	return (err);
341 }
342 
343 int
344 libusb_handle_events(libusb_context *ctx)
345 {
346 	return (libusb_handle_events_timeout(ctx, NULL));
347 }
348 
349 int
350 libusb_handle_events_locked(libusb_context *ctx, struct timeval *tv)
351 {
352 	int err;
353 
354 	ctx = GET_CONTEXT(ctx);
355 
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;
361 	}
362 	return (err);
363 }
364 
365 int
366 libusb_get_next_timeout(libusb_context *ctx, struct timeval *tv)
367 {
368 	/* all timeouts are currently being done by the kernel */
369 	timerclear(tv);
370 	return (0);
371 }
372 
373 void
374 libusb_set_pollfd_notifiers(libusb_context *ctx,
375     libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
376     void *user_data)
377 {
378 	ctx = GET_CONTEXT(ctx);
379 
380 	ctx->fd_added_cb = added_cb;
381 	ctx->fd_removed_cb = removed_cb;
382 	ctx->fd_cb_user_data = user_data;
383 }
384 
385 struct libusb_pollfd **
386 libusb_get_pollfds(libusb_context *ctx)
387 {
388 	struct libusb_super_pollfd *pollfd;
389 	libusb_pollfd **ret;
390 	int i;
391 
392 	ctx = GET_CONTEXT(ctx);
393 
394 	CTX_LOCK(ctx);
395 
396 	i = 0;
397 	TAILQ_FOREACH(pollfd, &ctx->pollfds, entry)
398 	    i++;
399 
400 	ret = calloc(i + 1, sizeof(struct libusb_pollfd *));
401 	if (ret == NULL)
402 		goto done;
403 
404 	i = 0;
405 	TAILQ_FOREACH(pollfd, &ctx->pollfds, entry)
406 	    ret[i++] = &pollfd->pollfd;
407 	ret[i] = NULL;
408 
409 done:
410 	CTX_UNLOCK(ctx);
411 	return (ret);
412 }
413 
414 
415 /* Synchronous device I/O */
416 
417 int
418 libusb_control_transfer(libusb_device_handle *devh,
419     uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
420     uint8_t *data, uint16_t wLength, unsigned int timeout)
421 {
422 	struct LIBUSB20_CONTROL_SETUP_DECODED req;
423 	int err;
424 	uint16_t actlen;
425 
426 	if (devh == NULL)
427 		return (LIBUSB_ERROR_INVALID_PARAM);
428 
429 	if ((wLength != 0) && (data == NULL))
430 		return (LIBUSB_ERROR_INVALID_PARAM);
431 
432 	LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
433 
434 	req.bmRequestType = bmRequestType;
435 	req.bRequest = bRequest;
436 	req.wValue = wValue;
437 	req.wIndex = wIndex;
438 	req.wLength = wLength;
439 
440 	err = libusb20_dev_request_sync(devh, &req, data,
441 	    &actlen, timeout, 0);
442 
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);
449 
450 	return (actlen);
451 }
452 
453 static void
454 libusb10_do_transfer_cb(struct libusb_transfer *transfer)
455 {
456 	libusb_context *ctx;
457 	int *pdone;
458 
459 	ctx = GET_CONTEXT(NULL);
460 
461 	DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "sync I/O done");
462 
463 	pdone = transfer->user_data;
464 	*pdone = 1;
465 }
466 
467 /*
468  * TODO: Replace the following function. Allocating and freeing on a
469  * per-transfer basis is slow.  --HPS
470  */
471 static int
472 libusb10_do_transfer(libusb_device_handle *devh,
473     uint8_t endpoint, uint8_t *data, int length,
474     int *transferred, unsigned int timeout, int type)
475 {
476 	libusb_context *ctx;
477 	struct libusb_transfer *xfer;
478 	volatile int complet;
479 	int ret;
480 
481 	if (devh == NULL)
482 		return (LIBUSB_ERROR_INVALID_PARAM);
483 
484 	if ((length != 0) && (data == NULL))
485 		return (LIBUSB_ERROR_INVALID_PARAM);
486 
487 	xfer = libusb_alloc_transfer(0);
488 	if (xfer == NULL)
489 		return (LIBUSB_ERROR_NO_MEM);
490 
491 	ctx = libusb_get_device(devh)->ctx;
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;
499 	xfer->user_data = (void *)&complet;
500 	xfer->callback = libusb10_do_transfer_cb;
501 	complet = 0;
502 
503 	if ((ret = libusb_submit_transfer(xfer)) < 0) {
504 		libusb_free_transfer(xfer);
505 		return (ret);
506 	}
507 	while (complet == 0) {
508 		if ((ret = libusb_handle_events(ctx)) < 0) {
509 			libusb_cancel_transfer(xfer);
510 			usleep(1000);	/* nice it */
511 		}
512 	}
513 
514 	*transferred = xfer->actual_length;
515 
516 	switch (xfer->status) {
517 	case LIBUSB_TRANSFER_COMPLETED:
518 		ret = 0;
519 		break;
520 	case LIBUSB_TRANSFER_TIMED_OUT:
521 		ret = LIBUSB_ERROR_TIMEOUT;
522 		break;
523 	case LIBUSB_TRANSFER_OVERFLOW:
524 		ret = LIBUSB_ERROR_OVERFLOW;
525 		break;
526 	case LIBUSB_TRANSFER_STALL:
527 		ret = LIBUSB_ERROR_PIPE;
528 		break;
529 	case LIBUSB_TRANSFER_NO_DEVICE:
530 		ret = LIBUSB_ERROR_NO_DEVICE;
531 		break;
532 	default:
533 		ret = LIBUSB_ERROR_OTHER;
534 		break;
535 	}
536 
537 	libusb_free_transfer(xfer);
538 	return (ret);
539 }
540 
541 int
542 libusb_bulk_transfer(libusb_device_handle *devh,
543     uint8_t endpoint, uint8_t *data, int length,
544     int *transferred, unsigned int timeout)
545 {
546 	libusb_context *ctx;
547 	int ret;
548 
549 	ctx = GET_CONTEXT(NULL);
550 	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter");
551 
552 	ret = libusb10_do_transfer(devh, endpoint, data, length, transferred,
553 	    timeout, LIBUSB_TRANSFER_TYPE_BULK);
554 
555 	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave");
556 	return (ret);
557 }
558 
559 int
560 libusb_interrupt_transfer(libusb_device_handle *devh,
561     uint8_t endpoint, uint8_t *data, int length,
562     int *transferred, unsigned int timeout)
563 {
564 	libusb_context *ctx;
565 	int ret;
566 
567 	ctx = GET_CONTEXT(NULL);
568 	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter");
569 
570 	ret = libusb10_do_transfer(devh, endpoint, data, length, transferred,
571 	    timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
572 
573 	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave");
574 	return (ret);
575 }
576