18c8fff31SAndrew Thompson /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro F. Giffuni *
48c8fff31SAndrew Thompson * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
58c8fff31SAndrew Thompson *
68c8fff31SAndrew Thompson * Redistribution and use in source and binary forms, with or without
78c8fff31SAndrew Thompson * modification, are permitted provided that the following conditions
88c8fff31SAndrew Thompson * are met:
98c8fff31SAndrew Thompson * 1. Redistributions of source code must retain the above copyright
108c8fff31SAndrew Thompson * notice, this list of conditions and the following disclaimer.
118c8fff31SAndrew Thompson * 2. Redistributions in binary form must reproduce the above copyright
128c8fff31SAndrew Thompson * notice, this list of conditions and the following disclaimer in the
138c8fff31SAndrew Thompson * documentation and/or other materials provided with the distribution.
148c8fff31SAndrew Thompson *
158c8fff31SAndrew Thompson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
168c8fff31SAndrew Thompson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
178c8fff31SAndrew Thompson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
188c8fff31SAndrew Thompson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
198c8fff31SAndrew Thompson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
208c8fff31SAndrew Thompson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
218c8fff31SAndrew Thompson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
228c8fff31SAndrew Thompson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
238c8fff31SAndrew Thompson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
248c8fff31SAndrew Thompson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
258c8fff31SAndrew Thompson * SUCH DAMAGE.
268c8fff31SAndrew Thompson */
278c8fff31SAndrew Thompson
2866194130SHans Petter Selasky #ifdef LIBUSB_GLOBAL_INCLUDE_FILE
2966194130SHans Petter Selasky #include LIBUSB_GLOBAL_INCLUDE_FILE
3066194130SHans Petter Selasky #else
31f3cba95cSWojciech A. Koszek #include <errno.h>
328c8fff31SAndrew Thompson #include <poll.h>
338c8fff31SAndrew Thompson #include <pthread.h>
34f3cba95cSWojciech A. Koszek #include <stdio.h>
35f3cba95cSWojciech A. Koszek #include <stdlib.h>
3666194130SHans Petter Selasky #include <string.h>
378c8fff31SAndrew Thompson #include <time.h>
38f3cba95cSWojciech A. Koszek #include <unistd.h>
3966194130SHans Petter Selasky #include <sys/queue.h>
4066194130SHans Petter Selasky #include <sys/endian.h>
4166194130SHans Petter Selasky #endif
428c8fff31SAndrew Thompson
439c087c5aSAndrew Thompson #define libusb_device_handle libusb20_device
449c087c5aSAndrew Thompson
458c8fff31SAndrew Thompson #include "libusb20.h"
468c8fff31SAndrew Thompson #include "libusb20_desc.h"
478c8fff31SAndrew Thompson #include "libusb20_int.h"
488c8fff31SAndrew Thompson #include "libusb.h"
498c8fff31SAndrew Thompson #include "libusb10.h"
508c8fff31SAndrew Thompson
51390065b1SAlfred Perlstein UNEXPORTED void
libusb10_add_pollfd(libusb_context * ctx,struct libusb_super_pollfd * pollfd,struct libusb20_device * pdev,int fd,short events)52390065b1SAlfred Perlstein libusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd,
53390065b1SAlfred Perlstein struct libusb20_device *pdev, int fd, short events)
54c500e4ddSAndrew Thompson {
55c500e4ddSAndrew Thompson if (ctx == NULL)
56390065b1SAlfred Perlstein return; /* invalid */
57c500e4ddSAndrew Thompson
58390065b1SAlfred Perlstein if (pollfd->entry.tqe_prev != NULL)
59390065b1SAlfred Perlstein return; /* already queued */
60c500e4ddSAndrew Thompson
61390065b1SAlfred Perlstein if (fd < 0)
62390065b1SAlfred Perlstein return; /* invalid */
63390065b1SAlfred Perlstein
64390065b1SAlfred Perlstein pollfd->pdev = pdev;
65c500e4ddSAndrew Thompson pollfd->pollfd.fd = fd;
66c500e4ddSAndrew Thompson pollfd->pollfd.events = events;
67c500e4ddSAndrew Thompson
68390065b1SAlfred Perlstein CTX_LOCK(ctx);
69390065b1SAlfred Perlstein TAILQ_INSERT_TAIL(&ctx->pollfds, pollfd, entry);
70390065b1SAlfred Perlstein CTX_UNLOCK(ctx);
71c500e4ddSAndrew Thompson
72c500e4ddSAndrew Thompson if (ctx->fd_added_cb)
73c500e4ddSAndrew Thompson ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data);
74c500e4ddSAndrew Thompson }
75c500e4ddSAndrew Thompson
76c500e4ddSAndrew Thompson UNEXPORTED void
libusb10_remove_pollfd(libusb_context * ctx,struct libusb_super_pollfd * pollfd)77390065b1SAlfred Perlstein libusb10_remove_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd)
78c500e4ddSAndrew Thompson {
79390065b1SAlfred Perlstein if (ctx == NULL)
80390065b1SAlfred Perlstein return; /* invalid */
81c500e4ddSAndrew Thompson
82390065b1SAlfred Perlstein if (pollfd->entry.tqe_prev == NULL)
83390065b1SAlfred Perlstein return; /* already dequeued */
84c500e4ddSAndrew Thompson
85390065b1SAlfred Perlstein CTX_LOCK(ctx);
86390065b1SAlfred Perlstein TAILQ_REMOVE(&ctx->pollfds, pollfd, entry);
87390065b1SAlfred Perlstein pollfd->entry.tqe_prev = NULL;
88390065b1SAlfred Perlstein CTX_UNLOCK(ctx);
89c500e4ddSAndrew Thompson
90c500e4ddSAndrew Thompson if (ctx->fd_removed_cb)
91390065b1SAlfred Perlstein ctx->fd_removed_cb(pollfd->pollfd.fd, ctx->fd_cb_user_data);
92c500e4ddSAndrew Thompson }
93c500e4ddSAndrew Thompson
94390065b1SAlfred Perlstein /* This function must be called locked */
95390065b1SAlfred Perlstein
96390065b1SAlfred Perlstein static int
libusb10_handle_events_sub(struct libusb_context * ctx,struct timeval * tv)97390065b1SAlfred Perlstein libusb10_handle_events_sub(struct libusb_context *ctx, struct timeval *tv)
98c500e4ddSAndrew Thompson {
99390065b1SAlfred Perlstein struct libusb_device *dev;
100390065b1SAlfred Perlstein struct libusb20_device **ppdev;
101390065b1SAlfred Perlstein struct libusb_super_pollfd *pfd;
1028c8fff31SAndrew Thompson struct pollfd *fds;
103390065b1SAlfred Perlstein struct libusb_super_transfer *sxfer;
104390065b1SAlfred Perlstein struct libusb_transfer *uxfer;
1058c8fff31SAndrew Thompson nfds_t nfds;
1068c8fff31SAndrew Thompson int timeout;
1078c8fff31SAndrew Thompson int i;
108390065b1SAlfred Perlstein int err;
1098c8fff31SAndrew Thompson
110390065b1SAlfred Perlstein DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb10_handle_events_sub enter");
1118c8fff31SAndrew Thompson
1128c8fff31SAndrew Thompson nfds = 0;
113390065b1SAlfred Perlstein i = 0;
114390065b1SAlfred Perlstein TAILQ_FOREACH(pfd, &ctx->pollfds, entry)
1158c8fff31SAndrew Thompson nfds++;
1168c8fff31SAndrew Thompson
117c500e4ddSAndrew Thompson fds = alloca(sizeof(*fds) * nfds);
1188c8fff31SAndrew Thompson if (fds == NULL)
1198c8fff31SAndrew Thompson return (LIBUSB_ERROR_NO_MEM);
1208c8fff31SAndrew Thompson
121390065b1SAlfred Perlstein ppdev = alloca(sizeof(*ppdev) * nfds);
122390065b1SAlfred Perlstein if (ppdev == NULL)
123390065b1SAlfred Perlstein return (LIBUSB_ERROR_NO_MEM);
124390065b1SAlfred Perlstein
125390065b1SAlfred Perlstein TAILQ_FOREACH(pfd, &ctx->pollfds, entry) {
126390065b1SAlfred Perlstein fds[i].fd = pfd->pollfd.fd;
127390065b1SAlfred Perlstein fds[i].events = pfd->pollfd.events;
1288c8fff31SAndrew Thompson fds[i].revents = 0;
129390065b1SAlfred Perlstein ppdev[i] = pfd->pdev;
130390065b1SAlfred Perlstein if (pfd->pdev != NULL)
131390065b1SAlfred Perlstein libusb_get_device(pfd->pdev)->refcnt++;
132390065b1SAlfred Perlstein i++;
1338c8fff31SAndrew Thompson }
1348c8fff31SAndrew Thompson
135390065b1SAlfred Perlstein if (tv == NULL)
136390065b1SAlfred Perlstein timeout = -1;
137390065b1SAlfred Perlstein else
138390065b1SAlfred Perlstein timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000);
1398c8fff31SAndrew Thompson
140390065b1SAlfred Perlstein CTX_UNLOCK(ctx);
141390065b1SAlfred Perlstein err = poll(fds, nfds, timeout);
142390065b1SAlfred Perlstein CTX_LOCK(ctx);
1438c8fff31SAndrew Thompson
144390065b1SAlfred Perlstein if ((err == -1) && (errno == EINTR))
145390065b1SAlfred Perlstein err = LIBUSB_ERROR_INTERRUPTED;
146390065b1SAlfred Perlstein else if (err < 0)
147390065b1SAlfred Perlstein err = LIBUSB_ERROR_IO;
1488c8fff31SAndrew Thompson
149390065b1SAlfred Perlstein if (err < 1) {
150a1221549SHans Petter Selasky for (i = 0; i != (int)nfds; i++) {
151390065b1SAlfred Perlstein if (ppdev[i] != NULL) {
152390065b1SAlfred Perlstein CTX_UNLOCK(ctx);
153390065b1SAlfred Perlstein libusb_unref_device(libusb_get_device(ppdev[i]));
154390065b1SAlfred Perlstein CTX_LOCK(ctx);
1558c8fff31SAndrew Thompson }
1568c8fff31SAndrew Thompson }
157390065b1SAlfred Perlstein goto do_done;
158390065b1SAlfred Perlstein }
159a1221549SHans Petter Selasky for (i = 0; i != (int)nfds; i++) {
160390065b1SAlfred Perlstein if (ppdev[i] != NULL) {
161390065b1SAlfred Perlstein dev = libusb_get_device(ppdev[i]);
1628c8fff31SAndrew Thompson
163540c7229SHans Petter Selasky if (fds[i].revents != 0) {
164390065b1SAlfred Perlstein err = libusb20_dev_process(ppdev[i]);
165ccef4ddfSAndrew Thompson
166390065b1SAlfred Perlstein if (err) {
1676847ea50SHans Petter Selasky /*
1686847ea50SHans Petter Selasky * When the device is opened
1696847ea50SHans Petter Selasky * set the "device_is_gone"
1706847ea50SHans Petter Selasky * flag. This prevents the
1716847ea50SHans Petter Selasky * client from submitting new
1726847ea50SHans Petter Selasky * USB transfers to a detached
1736847ea50SHans Petter Selasky * device.
1746847ea50SHans Petter Selasky */
1756847ea50SHans Petter Selasky if (ppdev[i]->is_opened)
176540c7229SHans Petter Selasky dev->device_is_gone = 1;
177ccef4ddfSAndrew Thompson
178ccef4ddfSAndrew Thompson /* remove USB device from polling loop */
179390065b1SAlfred Perlstein libusb10_remove_pollfd(dev->ctx, &dev->dev_poll);
180540c7229SHans Petter Selasky
181540c7229SHans Petter Selasky /* cancel all pending transfers */
182540c7229SHans Petter Selasky libusb10_cancel_all_transfer_locked(ppdev[i], dev);
183540c7229SHans Petter Selasky }
184390065b1SAlfred Perlstein }
185390065b1SAlfred Perlstein CTX_UNLOCK(ctx);
186390065b1SAlfred Perlstein libusb_unref_device(dev);
187390065b1SAlfred Perlstein CTX_LOCK(ctx);
188390065b1SAlfred Perlstein
189390065b1SAlfred Perlstein } else {
190390065b1SAlfred Perlstein uint8_t dummy;
191390065b1SAlfred Perlstein
192540c7229SHans Petter Selasky while (read(fds[i].fd, &dummy, 1) == 1)
193540c7229SHans Petter Selasky ;
194390065b1SAlfred Perlstein }
1958c8fff31SAndrew Thompson }
1968c8fff31SAndrew Thompson
197390065b1SAlfred Perlstein err = 0;
1988c8fff31SAndrew Thompson
199390065b1SAlfred Perlstein do_done:
2008c8fff31SAndrew Thompson
201390065b1SAlfred Perlstein /* Do all done callbacks */
2028c8fff31SAndrew Thompson
203390065b1SAlfred Perlstein while ((sxfer = TAILQ_FIRST(&ctx->tr_done))) {
20431f7072cSHans Petter Selasky uint8_t flags;
20531f7072cSHans Petter Selasky
206390065b1SAlfred Perlstein TAILQ_REMOVE(&ctx->tr_done, sxfer, entry);
207390065b1SAlfred Perlstein sxfer->entry.tqe_prev = NULL;
208390065b1SAlfred Perlstein
209390065b1SAlfred Perlstein ctx->tr_done_ref++;
210390065b1SAlfred Perlstein
211390065b1SAlfred Perlstein CTX_UNLOCK(ctx);
212390065b1SAlfred Perlstein
213390065b1SAlfred Perlstein uxfer = (struct libusb_transfer *)(
214390065b1SAlfred Perlstein ((uint8_t *)sxfer) + sizeof(*sxfer));
215390065b1SAlfred Perlstein
21631f7072cSHans Petter Selasky /* Allow the callback to free the transfer itself. */
21731f7072cSHans Petter Selasky flags = uxfer->flags;
21831f7072cSHans Petter Selasky
219390065b1SAlfred Perlstein if (uxfer->callback != NULL)
220390065b1SAlfred Perlstein (uxfer->callback) (uxfer);
221390065b1SAlfred Perlstein
22231f7072cSHans Petter Selasky /* Check if the USB transfer should be automatically freed. */
22331f7072cSHans Petter Selasky if (flags & LIBUSB_TRANSFER_FREE_TRANSFER)
224390065b1SAlfred Perlstein libusb_free_transfer(uxfer);
225390065b1SAlfred Perlstein
226390065b1SAlfred Perlstein CTX_LOCK(ctx);
227390065b1SAlfred Perlstein
228390065b1SAlfred Perlstein ctx->tr_done_ref--;
229390065b1SAlfred Perlstein ctx->tr_done_gen++;
2308c8fff31SAndrew Thompson }
2318c8fff31SAndrew Thompson
232390065b1SAlfred Perlstein /* Wakeup other waiters */
233390065b1SAlfred Perlstein pthread_cond_broadcast(&ctx->ctx_cond);
2348c8fff31SAndrew Thompson
235390065b1SAlfred Perlstein return (err);
2368c8fff31SAndrew Thompson }
2378c8fff31SAndrew Thompson
2388c8fff31SAndrew Thompson /* Polling and timing */
2398c8fff31SAndrew Thompson
2408c8fff31SAndrew Thompson int
libusb_try_lock_events(libusb_context * ctx)2418c8fff31SAndrew Thompson libusb_try_lock_events(libusb_context *ctx)
2428c8fff31SAndrew Thompson {
243390065b1SAlfred Perlstein int err;
2448c8fff31SAndrew Thompson
245390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
246390065b1SAlfred Perlstein if (ctx == NULL)
2478c8fff31SAndrew Thompson return (1);
2488c8fff31SAndrew Thompson
249390065b1SAlfred Perlstein err = CTX_TRYLOCK(ctx);
250390065b1SAlfred Perlstein if (err)
2518c8fff31SAndrew Thompson return (1);
2528c8fff31SAndrew Thompson
253390065b1SAlfred Perlstein err = (ctx->ctx_handler != NO_THREAD);
254390065b1SAlfred Perlstein if (err)
255390065b1SAlfred Perlstein CTX_UNLOCK(ctx);
256390065b1SAlfred Perlstein else
257390065b1SAlfred Perlstein ctx->ctx_handler = pthread_self();
2588c8fff31SAndrew Thompson
259390065b1SAlfred Perlstein return (err);
2608c8fff31SAndrew Thompson }
2618c8fff31SAndrew Thompson
2628c8fff31SAndrew Thompson void
libusb_lock_events(libusb_context * ctx)2638c8fff31SAndrew Thompson libusb_lock_events(libusb_context *ctx)
2648c8fff31SAndrew Thompson {
265390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
266390065b1SAlfred Perlstein CTX_LOCK(ctx);
267390065b1SAlfred Perlstein if (ctx->ctx_handler == NO_THREAD)
268390065b1SAlfred Perlstein ctx->ctx_handler = pthread_self();
2698c8fff31SAndrew Thompson }
2708c8fff31SAndrew Thompson
2718c8fff31SAndrew Thompson void
libusb_unlock_events(libusb_context * ctx)2728c8fff31SAndrew Thompson libusb_unlock_events(libusb_context *ctx)
2738c8fff31SAndrew Thompson {
274390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
275390065b1SAlfred Perlstein if (ctx->ctx_handler == pthread_self()) {
276390065b1SAlfred Perlstein ctx->ctx_handler = NO_THREAD;
277390065b1SAlfred Perlstein pthread_cond_broadcast(&ctx->ctx_cond);
278390065b1SAlfred Perlstein }
279390065b1SAlfred Perlstein CTX_UNLOCK(ctx);
2808c8fff31SAndrew Thompson }
2818c8fff31SAndrew Thompson
2828c8fff31SAndrew Thompson int
libusb_event_handling_ok(libusb_context * ctx)2838c8fff31SAndrew Thompson libusb_event_handling_ok(libusb_context *ctx)
2848c8fff31SAndrew Thompson {
285390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
286390065b1SAlfred Perlstein return (ctx->ctx_handler == pthread_self());
2878c8fff31SAndrew Thompson }
2888c8fff31SAndrew Thompson
2898c8fff31SAndrew Thompson int
libusb_event_handler_active(libusb_context * ctx)2908c8fff31SAndrew Thompson libusb_event_handler_active(libusb_context *ctx)
2918c8fff31SAndrew Thompson {
292390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
293390065b1SAlfred Perlstein return (ctx->ctx_handler != NO_THREAD);
2948c8fff31SAndrew Thompson }
2958c8fff31SAndrew Thompson
2968c8fff31SAndrew Thompson void
libusb_lock_event_waiters(libusb_context * ctx)2978c8fff31SAndrew Thompson libusb_lock_event_waiters(libusb_context *ctx)
2988c8fff31SAndrew Thompson {
299390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
300390065b1SAlfred Perlstein CTX_LOCK(ctx);
3018c8fff31SAndrew Thompson }
3028c8fff31SAndrew Thompson
3038c8fff31SAndrew Thompson void
libusb_unlock_event_waiters(libusb_context * ctx)3048c8fff31SAndrew Thompson libusb_unlock_event_waiters(libusb_context *ctx)
3058c8fff31SAndrew Thompson {
306390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
307390065b1SAlfred Perlstein CTX_UNLOCK(ctx);
3088c8fff31SAndrew Thompson }
3098c8fff31SAndrew Thompson
3108c8fff31SAndrew Thompson int
libusb_wait_for_event(libusb_context * ctx,struct timeval * tv)3118c8fff31SAndrew Thompson libusb_wait_for_event(libusb_context *ctx, struct timeval *tv)
3128c8fff31SAndrew Thompson {
3138c8fff31SAndrew Thompson struct timespec ts;
314390065b1SAlfred Perlstein int err;
3158c8fff31SAndrew Thompson
316390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
317c500e4ddSAndrew Thompson DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter");
3188c8fff31SAndrew Thompson
3198c8fff31SAndrew Thompson if (tv == NULL) {
320390065b1SAlfred Perlstein pthread_cond_wait(&ctx->ctx_cond,
321390065b1SAlfred Perlstein &ctx->ctx_lock);
32226829924SHans Petter Selasky /* try to grab polling of actual events, if any */
32326829924SHans Petter Selasky if (ctx->ctx_handler == NO_THREAD)
32426829924SHans Petter Selasky ctx->ctx_handler = pthread_self();
3258c8fff31SAndrew Thompson return (0);
3268c8fff31SAndrew Thompson }
327f7287225SHans Petter Selasky err = clock_gettime(CLOCK_MONOTONIC, &ts);
328390065b1SAlfred Perlstein if (err < 0)
3298c8fff31SAndrew Thompson return (LIBUSB_ERROR_OTHER);
3308c8fff31SAndrew Thompson
331f7287225SHans Petter Selasky /*
332f7287225SHans Petter Selasky * The "tv" arguments points to a relative time structure and
333f7287225SHans Petter Selasky * not an absolute time structure.
334f7287225SHans Petter Selasky */
335f7287225SHans Petter Selasky ts.tv_sec += tv->tv_sec;
336f7287225SHans Petter Selasky ts.tv_nsec += tv->tv_usec * 1000;
337390065b1SAlfred Perlstein if (ts.tv_nsec >= 1000000000) {
3388c8fff31SAndrew Thompson ts.tv_nsec -= 1000000000;
3398c8fff31SAndrew Thompson ts.tv_sec++;
3408c8fff31SAndrew Thompson }
341390065b1SAlfred Perlstein err = pthread_cond_timedwait(&ctx->ctx_cond,
342390065b1SAlfred Perlstein &ctx->ctx_lock, &ts);
34326829924SHans Petter Selasky /* try to grab polling of actual events, if any */
34426829924SHans Petter Selasky if (ctx->ctx_handler == NO_THREAD)
34526829924SHans Petter Selasky ctx->ctx_handler = pthread_self();
3468c8fff31SAndrew Thompson
347390065b1SAlfred Perlstein if (err == ETIMEDOUT)
3488c8fff31SAndrew Thompson return (1);
3498c8fff31SAndrew Thompson
3508c8fff31SAndrew Thompson return (0);
3518c8fff31SAndrew Thompson }
3528c8fff31SAndrew Thompson
3538c8fff31SAndrew Thompson int
libusb_handle_events_timeout_completed(libusb_context * ctx,struct timeval * tv,int * completed)35403205428SHans Petter Selasky libusb_handle_events_timeout_completed(libusb_context *ctx,
35503205428SHans Petter Selasky struct timeval *tv, int *completed)
3568c8fff31SAndrew Thompson {
35703205428SHans Petter Selasky int err = 0;
3588c8fff31SAndrew Thompson
359390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
360390065b1SAlfred Perlstein
36103205428SHans Petter Selasky DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout_completed enter");
3628c8fff31SAndrew Thompson
363390065b1SAlfred Perlstein libusb_lock_events(ctx);
364390065b1SAlfred Perlstein
36503205428SHans Petter Selasky while (1) {
36603205428SHans Petter Selasky if (completed != NULL) {
36703205428SHans Petter Selasky if (*completed != 0 || err != 0)
36803205428SHans Petter Selasky break;
36903205428SHans Petter Selasky }
370390065b1SAlfred Perlstein err = libusb_handle_events_locked(ctx, tv);
37103205428SHans Petter Selasky if (completed == NULL)
37203205428SHans Petter Selasky break;
37303205428SHans Petter Selasky }
374390065b1SAlfred Perlstein
3758c8fff31SAndrew Thompson libusb_unlock_events(ctx);
3768c8fff31SAndrew Thompson
37703205428SHans Petter Selasky DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout_completed exit");
378390065b1SAlfred Perlstein
379390065b1SAlfred Perlstein return (err);
3808c8fff31SAndrew Thompson }
3818c8fff31SAndrew Thompson
3828c8fff31SAndrew Thompson int
libusb_handle_events_completed(libusb_context * ctx,int * completed)38303205428SHans Petter Selasky libusb_handle_events_completed(libusb_context *ctx, int *completed)
38403205428SHans Petter Selasky {
38503205428SHans Petter Selasky return (libusb_handle_events_timeout_completed(ctx, NULL, completed));
38603205428SHans Petter Selasky }
38703205428SHans Petter Selasky
38803205428SHans Petter Selasky int
libusb_handle_events_timeout(libusb_context * ctx,struct timeval * tv)38903205428SHans Petter Selasky libusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv)
39003205428SHans Petter Selasky {
39103205428SHans Petter Selasky return (libusb_handle_events_timeout_completed(ctx, tv, NULL));
39203205428SHans Petter Selasky }
39303205428SHans Petter Selasky
39403205428SHans Petter Selasky int
libusb_handle_events(libusb_context * ctx)3958c8fff31SAndrew Thompson libusb_handle_events(libusb_context *ctx)
3968c8fff31SAndrew Thompson {
39703205428SHans Petter Selasky return (libusb_handle_events_timeout_completed(ctx, NULL, NULL));
3988c8fff31SAndrew Thompson }
3998c8fff31SAndrew Thompson
4008c8fff31SAndrew Thompson int
libusb_handle_events_locked(libusb_context * ctx,struct timeval * tv)4018c8fff31SAndrew Thompson libusb_handle_events_locked(libusb_context *ctx, struct timeval *tv)
4028c8fff31SAndrew Thompson {
403390065b1SAlfred Perlstein int err;
4048c8fff31SAndrew Thompson
405390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
4068c8fff31SAndrew Thompson
407390065b1SAlfred Perlstein if (libusb_event_handling_ok(ctx)) {
408390065b1SAlfred Perlstein err = libusb10_handle_events_sub(ctx, tv);
409390065b1SAlfred Perlstein } else {
41003205428SHans Petter Selasky err = libusb_wait_for_event(ctx, tv);
41103205428SHans Petter Selasky if (err != 0)
41203205428SHans Petter Selasky err = LIBUSB_ERROR_TIMEOUT;
4138c8fff31SAndrew Thompson }
414390065b1SAlfred Perlstein return (err);
4158c8fff31SAndrew Thompson }
4168c8fff31SAndrew Thompson
4178c8fff31SAndrew Thompson int
libusb_get_next_timeout(libusb_context * ctx,struct timeval * tv)4188c8fff31SAndrew Thompson libusb_get_next_timeout(libusb_context *ctx, struct timeval *tv)
4198c8fff31SAndrew Thompson {
420390065b1SAlfred Perlstein /* all timeouts are currently being done by the kernel */
4218c8fff31SAndrew Thompson timerclear(tv);
422390065b1SAlfred Perlstein return (0);
4238c8fff31SAndrew Thompson }
4248c8fff31SAndrew Thompson
4258c8fff31SAndrew Thompson void
libusb_set_pollfd_notifiers(libusb_context * ctx,libusb_pollfd_added_cb added_cb,libusb_pollfd_removed_cb removed_cb,void * user_data)4268c8fff31SAndrew Thompson libusb_set_pollfd_notifiers(libusb_context *ctx,
4278c8fff31SAndrew Thompson libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
4288c8fff31SAndrew Thompson void *user_data)
4298c8fff31SAndrew Thompson {
430390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
4318c8fff31SAndrew Thompson
4328c8fff31SAndrew Thompson ctx->fd_added_cb = added_cb;
4338c8fff31SAndrew Thompson ctx->fd_removed_cb = removed_cb;
4348c8fff31SAndrew Thompson ctx->fd_cb_user_data = user_data;
4358c8fff31SAndrew Thompson }
4368c8fff31SAndrew Thompson
43722a962c9SEd Maste const struct libusb_pollfd **
libusb_get_pollfds(libusb_context * ctx)4388c8fff31SAndrew Thompson libusb_get_pollfds(libusb_context *ctx)
4398c8fff31SAndrew Thompson {
440390065b1SAlfred Perlstein struct libusb_super_pollfd *pollfd;
4418c8fff31SAndrew Thompson libusb_pollfd **ret;
4428c8fff31SAndrew Thompson int i;
4438c8fff31SAndrew Thompson
444390065b1SAlfred Perlstein ctx = GET_CONTEXT(ctx);
445390065b1SAlfred Perlstein
446390065b1SAlfred Perlstein CTX_LOCK(ctx);
4478c8fff31SAndrew Thompson
4488c8fff31SAndrew Thompson i = 0;
449390065b1SAlfred Perlstein TAILQ_FOREACH(pollfd, &ctx->pollfds, entry)
4508c8fff31SAndrew Thompson i++;
4518c8fff31SAndrew Thompson
4528c8fff31SAndrew Thompson ret = calloc(i + 1, sizeof(struct libusb_pollfd *));
453390065b1SAlfred Perlstein if (ret == NULL)
454390065b1SAlfred Perlstein goto done;
4558c8fff31SAndrew Thompson
4568c8fff31SAndrew Thompson i = 0;
457390065b1SAlfred Perlstein TAILQ_FOREACH(pollfd, &ctx->pollfds, entry)
458390065b1SAlfred Perlstein ret[i++] = &pollfd->pollfd;
4598c8fff31SAndrew Thompson ret[i] = NULL;
4608c8fff31SAndrew Thompson
461390065b1SAlfred Perlstein done:
462390065b1SAlfred Perlstein CTX_UNLOCK(ctx);
46322a962c9SEd Maste return ((const struct libusb_pollfd **)ret);
4648c8fff31SAndrew Thompson }
4658c8fff31SAndrew Thompson
4668c8fff31SAndrew Thompson
4678c8fff31SAndrew Thompson /* Synchronous device I/O */
4688c8fff31SAndrew Thompson
4698c8fff31SAndrew Thompson int
libusb_control_transfer(libusb_device_handle * devh,uint8_t bmRequestType,uint8_t bRequest,uint16_t wValue,uint16_t wIndex,uint8_t * data,uint16_t wLength,unsigned int timeout)4708c8fff31SAndrew Thompson libusb_control_transfer(libusb_device_handle *devh,
4718c8fff31SAndrew Thompson uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
472390065b1SAlfred Perlstein uint8_t *data, uint16_t wLength, unsigned int timeout)
4738c8fff31SAndrew Thompson {
474390065b1SAlfred Perlstein struct LIBUSB20_CONTROL_SETUP_DECODED req;
475390065b1SAlfred Perlstein int err;
476390065b1SAlfred Perlstein uint16_t actlen;
477390065b1SAlfred Perlstein
478390065b1SAlfred Perlstein if (devh == NULL)
479390065b1SAlfred Perlstein return (LIBUSB_ERROR_INVALID_PARAM);
480390065b1SAlfred Perlstein
481390065b1SAlfred Perlstein if ((wLength != 0) && (data == NULL))
482390065b1SAlfred Perlstein return (LIBUSB_ERROR_INVALID_PARAM);
483390065b1SAlfred Perlstein
484390065b1SAlfred Perlstein LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
485390065b1SAlfred Perlstein
486390065b1SAlfred Perlstein req.bmRequestType = bmRequestType;
487390065b1SAlfred Perlstein req.bRequest = bRequest;
488390065b1SAlfred Perlstein req.wValue = wValue;
489390065b1SAlfred Perlstein req.wIndex = wIndex;
490390065b1SAlfred Perlstein req.wLength = wLength;
491390065b1SAlfred Perlstein
492390065b1SAlfred Perlstein err = libusb20_dev_request_sync(devh, &req, data,
493390065b1SAlfred Perlstein &actlen, timeout, 0);
494390065b1SAlfred Perlstein
495390065b1SAlfred Perlstein if (err == LIBUSB20_ERROR_PIPE)
496390065b1SAlfred Perlstein return (LIBUSB_ERROR_PIPE);
497390065b1SAlfred Perlstein else if (err == LIBUSB20_ERROR_TIMEOUT)
498390065b1SAlfred Perlstein return (LIBUSB_ERROR_TIMEOUT);
499390065b1SAlfred Perlstein else if (err)
500390065b1SAlfred Perlstein return (LIBUSB_ERROR_NO_DEVICE);
501390065b1SAlfred Perlstein
502390065b1SAlfred Perlstein return (actlen);
503390065b1SAlfred Perlstein }
504390065b1SAlfred Perlstein
5055b21ba5cSHans Petter Selasky static libusb_context *
libusb10_get_context_by_device_handle(libusb_device_handle * devh)5065b21ba5cSHans Petter Selasky libusb10_get_context_by_device_handle(libusb_device_handle *devh)
5075b21ba5cSHans Petter Selasky {
5085b21ba5cSHans Petter Selasky libusb_context *ctx;
5095b21ba5cSHans Petter Selasky
5105b21ba5cSHans Petter Selasky if (devh != NULL)
5115b21ba5cSHans Petter Selasky ctx = libusb_get_device(devh)->ctx;
5125b21ba5cSHans Petter Selasky else
5135b21ba5cSHans Petter Selasky ctx = NULL;
5145b21ba5cSHans Petter Selasky
5155b21ba5cSHans Petter Selasky return (GET_CONTEXT(ctx));
5165b21ba5cSHans Petter Selasky }
5175b21ba5cSHans Petter Selasky
518390065b1SAlfred Perlstein static void
libusb10_do_transfer_cb(struct libusb_transfer * transfer)519390065b1SAlfred Perlstein libusb10_do_transfer_cb(struct libusb_transfer *transfer)
520390065b1SAlfred Perlstein {
5218c8fff31SAndrew Thompson libusb_context *ctx;
522390065b1SAlfred Perlstein int *pdone;
5238c8fff31SAndrew Thompson
5245b21ba5cSHans Petter Selasky ctx = libusb10_get_context_by_device_handle(transfer->dev_handle);
5258c8fff31SAndrew Thompson
526390065b1SAlfred Perlstein DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "sync I/O done");
5278c8fff31SAndrew Thompson
528390065b1SAlfred Perlstein pdone = transfer->user_data;
529390065b1SAlfred Perlstein *pdone = 1;
5308c8fff31SAndrew Thompson }
5318c8fff31SAndrew Thompson
532390065b1SAlfred Perlstein /*
533390065b1SAlfred Perlstein * TODO: Replace the following function. Allocating and freeing on a
534390065b1SAlfred Perlstein * per-transfer basis is slow. --HPS
535390065b1SAlfred Perlstein */
5368c8fff31SAndrew Thompson static int
libusb10_do_transfer(libusb_device_handle * devh,uint8_t endpoint,uint8_t * data,int length,int * transferred,unsigned int timeout,int type)537390065b1SAlfred Perlstein libusb10_do_transfer(libusb_device_handle *devh,
538390065b1SAlfred Perlstein uint8_t endpoint, uint8_t *data, int length,
5398c8fff31SAndrew Thompson int *transferred, unsigned int timeout, int type)
5408c8fff31SAndrew Thompson {
5418c8fff31SAndrew Thompson libusb_context *ctx;
542390065b1SAlfred Perlstein struct libusb_transfer *xfer;
543d81535d1SHans Petter Selasky int done;
5448c8fff31SAndrew Thompson int ret;
5458c8fff31SAndrew Thompson
546390065b1SAlfred Perlstein if (devh == NULL)
547390065b1SAlfred Perlstein return (LIBUSB_ERROR_INVALID_PARAM);
548390065b1SAlfred Perlstein
549390065b1SAlfred Perlstein if ((length != 0) && (data == NULL))
550390065b1SAlfred Perlstein return (LIBUSB_ERROR_INVALID_PARAM);
5518c8fff31SAndrew Thompson
5528c8fff31SAndrew Thompson xfer = libusb_alloc_transfer(0);
5538c8fff31SAndrew Thompson if (xfer == NULL)
5548c8fff31SAndrew Thompson return (LIBUSB_ERROR_NO_MEM);
5558c8fff31SAndrew Thompson
556390065b1SAlfred Perlstein ctx = libusb_get_device(devh)->ctx;
5578c8fff31SAndrew Thompson
5588c8fff31SAndrew Thompson xfer->dev_handle = devh;
5598c8fff31SAndrew Thompson xfer->endpoint = endpoint;
5608c8fff31SAndrew Thompson xfer->type = type;
5618c8fff31SAndrew Thompson xfer->timeout = timeout;
5628c8fff31SAndrew Thompson xfer->buffer = data;
5638c8fff31SAndrew Thompson xfer->length = length;
564d81535d1SHans Petter Selasky xfer->user_data = (void *)&done;
565390065b1SAlfred Perlstein xfer->callback = libusb10_do_transfer_cb;
566d81535d1SHans Petter Selasky done = 0;
5678c8fff31SAndrew Thompson
5688c8fff31SAndrew Thompson if ((ret = libusb_submit_transfer(xfer)) < 0) {
5698c8fff31SAndrew Thompson libusb_free_transfer(xfer);
5708c8fff31SAndrew Thompson return (ret);
5718c8fff31SAndrew Thompson }
572d81535d1SHans Petter Selasky while (done == 0) {
5738c8fff31SAndrew Thompson if ((ret = libusb_handle_events(ctx)) < 0) {
5748c8fff31SAndrew Thompson libusb_cancel_transfer(xfer);
575390065b1SAlfred Perlstein usleep(1000); /* nice it */
5768c8fff31SAndrew Thompson }
5778c8fff31SAndrew Thompson }
5788c8fff31SAndrew Thompson
5798c8fff31SAndrew Thompson *transferred = xfer->actual_length;
580390065b1SAlfred Perlstein
5818c8fff31SAndrew Thompson switch (xfer->status) {
5828c8fff31SAndrew Thompson case LIBUSB_TRANSFER_COMPLETED:
583390065b1SAlfred Perlstein ret = 0;
5848c8fff31SAndrew Thompson break;
5858c8fff31SAndrew Thompson case LIBUSB_TRANSFER_TIMED_OUT:
586390065b1SAlfred Perlstein ret = LIBUSB_ERROR_TIMEOUT;
587390065b1SAlfred Perlstein break;
5888c8fff31SAndrew Thompson case LIBUSB_TRANSFER_OVERFLOW:
589390065b1SAlfred Perlstein ret = LIBUSB_ERROR_OVERFLOW;
590390065b1SAlfred Perlstein break;
5918c8fff31SAndrew Thompson case LIBUSB_TRANSFER_STALL:
592390065b1SAlfred Perlstein ret = LIBUSB_ERROR_PIPE;
593390065b1SAlfred Perlstein break;
5948c8fff31SAndrew Thompson case LIBUSB_TRANSFER_NO_DEVICE:
595390065b1SAlfred Perlstein ret = LIBUSB_ERROR_NO_DEVICE;
5968c8fff31SAndrew Thompson break;
5978c8fff31SAndrew Thompson default:
5988c8fff31SAndrew Thompson ret = LIBUSB_ERROR_OTHER;
599390065b1SAlfred Perlstein break;
6008c8fff31SAndrew Thompson }
6018c8fff31SAndrew Thompson
6028c8fff31SAndrew Thompson libusb_free_transfer(xfer);
6038c8fff31SAndrew Thompson return (ret);
6048c8fff31SAndrew Thompson }
6058c8fff31SAndrew Thompson
6068c8fff31SAndrew Thompson int
libusb_bulk_transfer(libusb_device_handle * devh,uint8_t endpoint,uint8_t * data,int length,int * transferred,unsigned int timeout)607390065b1SAlfred Perlstein libusb_bulk_transfer(libusb_device_handle *devh,
608390065b1SAlfred Perlstein uint8_t endpoint, uint8_t *data, int length,
6098c8fff31SAndrew Thompson int *transferred, unsigned int timeout)
6108c8fff31SAndrew Thompson {
6118c8fff31SAndrew Thompson libusb_context *ctx;
6128c8fff31SAndrew Thompson int ret;
6138c8fff31SAndrew Thompson
6145b21ba5cSHans Petter Selasky ctx = libusb10_get_context_by_device_handle(devh);
6155b21ba5cSHans Petter Selasky
616c500e4ddSAndrew Thompson DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter");
6178c8fff31SAndrew Thompson
618390065b1SAlfred Perlstein ret = libusb10_do_transfer(devh, endpoint, data, length, transferred,
6198c8fff31SAndrew Thompson timeout, LIBUSB_TRANSFER_TYPE_BULK);
6208c8fff31SAndrew Thompson
621c500e4ddSAndrew Thompson DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave");
6228c8fff31SAndrew Thompson return (ret);
6238c8fff31SAndrew Thompson }
6248c8fff31SAndrew Thompson
6258c8fff31SAndrew Thompson int
libusb_interrupt_transfer(libusb_device_handle * devh,uint8_t endpoint,uint8_t * data,int length,int * transferred,unsigned int timeout)626390065b1SAlfred Perlstein libusb_interrupt_transfer(libusb_device_handle *devh,
627390065b1SAlfred Perlstein uint8_t endpoint, uint8_t *data, int length,
6288c8fff31SAndrew Thompson int *transferred, unsigned int timeout)
6298c8fff31SAndrew Thompson {
6308c8fff31SAndrew Thompson libusb_context *ctx;
6318c8fff31SAndrew Thompson int ret;
6328c8fff31SAndrew Thompson
6335b21ba5cSHans Petter Selasky ctx = libusb10_get_context_by_device_handle(devh);
6345b21ba5cSHans Petter Selasky
635c500e4ddSAndrew Thompson DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter");
6368c8fff31SAndrew Thompson
637390065b1SAlfred Perlstein ret = libusb10_do_transfer(devh, endpoint, data, length, transferred,
6388c8fff31SAndrew Thompson timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
6398c8fff31SAndrew Thompson
640c500e4ddSAndrew Thompson DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave");
6418c8fff31SAndrew Thompson return (ret);
6428c8fff31SAndrew Thompson }
643ccef4ddfSAndrew Thompson
644ccef4ddfSAndrew Thompson uint8_t *
libusb_get_iso_packet_buffer(struct libusb_transfer * transfer,uint32_t off)645d81535d1SHans Petter Selasky libusb_get_iso_packet_buffer(struct libusb_transfer *transfer, uint32_t off)
646ccef4ddfSAndrew Thompson {
647ccef4ddfSAndrew Thompson uint8_t *ptr;
648ccef4ddfSAndrew Thompson uint32_t n;
649ccef4ddfSAndrew Thompson
650ccef4ddfSAndrew Thompson if (transfer->num_iso_packets < 0)
651ccef4ddfSAndrew Thompson return (NULL);
652ccef4ddfSAndrew Thompson
653d81535d1SHans Petter Selasky if (off >= (uint32_t)transfer->num_iso_packets)
654ccef4ddfSAndrew Thompson return (NULL);
655ccef4ddfSAndrew Thompson
656ccef4ddfSAndrew Thompson ptr = transfer->buffer;
657ccef4ddfSAndrew Thompson if (ptr == NULL)
658ccef4ddfSAndrew Thompson return (NULL);
659ccef4ddfSAndrew Thompson
660d81535d1SHans Petter Selasky for (n = 0; n != off; n++) {
661ccef4ddfSAndrew Thompson ptr += transfer->iso_packet_desc[n].length;
662ccef4ddfSAndrew Thompson }
663ccef4ddfSAndrew Thompson return (ptr);
664ccef4ddfSAndrew Thompson }
665ccef4ddfSAndrew Thompson
666ccef4ddfSAndrew Thompson uint8_t *
libusb_get_iso_packet_buffer_simple(struct libusb_transfer * transfer,uint32_t off)667d81535d1SHans Petter Selasky libusb_get_iso_packet_buffer_simple(struct libusb_transfer *transfer, uint32_t off)
668ccef4ddfSAndrew Thompson {
669ccef4ddfSAndrew Thompson uint8_t *ptr;
670ccef4ddfSAndrew Thompson
671ccef4ddfSAndrew Thompson if (transfer->num_iso_packets < 0)
672ccef4ddfSAndrew Thompson return (NULL);
673ccef4ddfSAndrew Thompson
674d81535d1SHans Petter Selasky if (off >= (uint32_t)transfer->num_iso_packets)
675ccef4ddfSAndrew Thompson return (NULL);
676ccef4ddfSAndrew Thompson
677ccef4ddfSAndrew Thompson ptr = transfer->buffer;
678ccef4ddfSAndrew Thompson if (ptr == NULL)
679ccef4ddfSAndrew Thompson return (NULL);
680ccef4ddfSAndrew Thompson
681d81535d1SHans Petter Selasky ptr += transfer->iso_packet_desc[0].length * off;
682ccef4ddfSAndrew Thompson
683ccef4ddfSAndrew Thompson return (ptr);
684ccef4ddfSAndrew Thompson }
685ccef4ddfSAndrew Thompson
686ccef4ddfSAndrew Thompson void
libusb_set_iso_packet_lengths(struct libusb_transfer * transfer,uint32_t length)687ccef4ddfSAndrew Thompson libusb_set_iso_packet_lengths(struct libusb_transfer *transfer, uint32_t length)
688ccef4ddfSAndrew Thompson {
689ccef4ddfSAndrew Thompson int n;
690ccef4ddfSAndrew Thompson
691ccef4ddfSAndrew Thompson if (transfer->num_iso_packets < 0)
692ccef4ddfSAndrew Thompson return;
693ccef4ddfSAndrew Thompson
694ccef4ddfSAndrew Thompson for (n = 0; n != transfer->num_iso_packets; n++)
695ccef4ddfSAndrew Thompson transfer->iso_packet_desc[n].length = length;
696ccef4ddfSAndrew Thompson }
697ccef4ddfSAndrew Thompson
698ccef4ddfSAndrew Thompson uint8_t *
libusb_control_transfer_get_data(struct libusb_transfer * transfer)699ccef4ddfSAndrew Thompson libusb_control_transfer_get_data(struct libusb_transfer *transfer)
700ccef4ddfSAndrew Thompson {
701ccef4ddfSAndrew Thompson if (transfer->buffer == NULL)
702ccef4ddfSAndrew Thompson return (NULL);
703ccef4ddfSAndrew Thompson
704ccef4ddfSAndrew Thompson return (transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE);
705ccef4ddfSAndrew Thompson }
706ccef4ddfSAndrew Thompson
707ccef4ddfSAndrew Thompson struct libusb_control_setup *
libusb_control_transfer_get_setup(struct libusb_transfer * transfer)708ccef4ddfSAndrew Thompson libusb_control_transfer_get_setup(struct libusb_transfer *transfer)
709ccef4ddfSAndrew Thompson {
710ccef4ddfSAndrew Thompson return ((struct libusb_control_setup *)transfer->buffer);
711ccef4ddfSAndrew Thompson }
712ccef4ddfSAndrew Thompson
713ccef4ddfSAndrew Thompson void
libusb_fill_control_setup(uint8_t * buf,uint8_t bmRequestType,uint8_t bRequest,uint16_t wValue,uint16_t wIndex,uint16_t wLength)714ccef4ddfSAndrew Thompson libusb_fill_control_setup(uint8_t *buf, uint8_t bmRequestType,
715ccef4ddfSAndrew Thompson uint8_t bRequest, uint16_t wValue,
716ccef4ddfSAndrew Thompson uint16_t wIndex, uint16_t wLength)
717ccef4ddfSAndrew Thompson {
718ccef4ddfSAndrew Thompson struct libusb_control_setup *req = (struct libusb_control_setup *)buf;
719ccef4ddfSAndrew Thompson
720ccef4ddfSAndrew Thompson /* The alignment is OK for all fields below. */
721ccef4ddfSAndrew Thompson req->bmRequestType = bmRequestType;
722ccef4ddfSAndrew Thompson req->bRequest = bRequest;
723ccef4ddfSAndrew Thompson req->wValue = htole16(wValue);
724ccef4ddfSAndrew Thompson req->wIndex = htole16(wIndex);
725ccef4ddfSAndrew Thompson req->wLength = htole16(wLength);
726ccef4ddfSAndrew Thompson }
727ccef4ddfSAndrew Thompson
728ccef4ddfSAndrew Thompson void
libusb_fill_control_transfer(struct libusb_transfer * transfer,libusb_device_handle * devh,uint8_t * buf,libusb_transfer_cb_fn callback,void * user_data,uint32_t timeout)729ccef4ddfSAndrew Thompson libusb_fill_control_transfer(struct libusb_transfer *transfer,
730ccef4ddfSAndrew Thompson libusb_device_handle *devh, uint8_t *buf,
731ccef4ddfSAndrew Thompson libusb_transfer_cb_fn callback, void *user_data,
732ccef4ddfSAndrew Thompson uint32_t timeout)
733ccef4ddfSAndrew Thompson {
734ccef4ddfSAndrew Thompson struct libusb_control_setup *setup = (struct libusb_control_setup *)buf;
735ccef4ddfSAndrew Thompson
736ccef4ddfSAndrew Thompson transfer->dev_handle = devh;
737ccef4ddfSAndrew Thompson transfer->endpoint = 0;
738ccef4ddfSAndrew Thompson transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL;
739ccef4ddfSAndrew Thompson transfer->timeout = timeout;
740ccef4ddfSAndrew Thompson transfer->buffer = buf;
741ccef4ddfSAndrew Thompson if (setup != NULL)
742ccef4ddfSAndrew Thompson transfer->length = LIBUSB_CONTROL_SETUP_SIZE
743ccef4ddfSAndrew Thompson + le16toh(setup->wLength);
744ccef4ddfSAndrew Thompson else
745ccef4ddfSAndrew Thompson transfer->length = 0;
746ccef4ddfSAndrew Thompson transfer->user_data = user_data;
747ccef4ddfSAndrew Thompson transfer->callback = callback;
748ccef4ddfSAndrew Thompson
749ccef4ddfSAndrew Thompson }
750ccef4ddfSAndrew Thompson
751ccef4ddfSAndrew Thompson void
libusb_fill_bulk_transfer(struct libusb_transfer * transfer,libusb_device_handle * devh,uint8_t endpoint,uint8_t * buf,int length,libusb_transfer_cb_fn callback,void * user_data,uint32_t timeout)752ccef4ddfSAndrew Thompson libusb_fill_bulk_transfer(struct libusb_transfer *transfer,
753ccef4ddfSAndrew Thompson libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf,
754ccef4ddfSAndrew Thompson int length, libusb_transfer_cb_fn callback, void *user_data,
755ccef4ddfSAndrew Thompson uint32_t timeout)
756ccef4ddfSAndrew Thompson {
757ccef4ddfSAndrew Thompson transfer->dev_handle = devh;
758ccef4ddfSAndrew Thompson transfer->endpoint = endpoint;
759ccef4ddfSAndrew Thompson transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
760ccef4ddfSAndrew Thompson transfer->timeout = timeout;
761ccef4ddfSAndrew Thompson transfer->buffer = buf;
762ccef4ddfSAndrew Thompson transfer->length = length;
763ccef4ddfSAndrew Thompson transfer->user_data = user_data;
764ccef4ddfSAndrew Thompson transfer->callback = callback;
765ccef4ddfSAndrew Thompson }
766ccef4ddfSAndrew Thompson
767ccef4ddfSAndrew Thompson void
libusb_fill_interrupt_transfer(struct libusb_transfer * transfer,libusb_device_handle * devh,uint8_t endpoint,uint8_t * buf,int length,libusb_transfer_cb_fn callback,void * user_data,uint32_t timeout)768ccef4ddfSAndrew Thompson libusb_fill_interrupt_transfer(struct libusb_transfer *transfer,
769ccef4ddfSAndrew Thompson libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf,
770ccef4ddfSAndrew Thompson int length, libusb_transfer_cb_fn callback, void *user_data,
771ccef4ddfSAndrew Thompson uint32_t timeout)
772ccef4ddfSAndrew Thompson {
773ccef4ddfSAndrew Thompson transfer->dev_handle = devh;
774ccef4ddfSAndrew Thompson transfer->endpoint = endpoint;
775ccef4ddfSAndrew Thompson transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT;
776ccef4ddfSAndrew Thompson transfer->timeout = timeout;
777ccef4ddfSAndrew Thompson transfer->buffer = buf;
778ccef4ddfSAndrew Thompson transfer->length = length;
779ccef4ddfSAndrew Thompson transfer->user_data = user_data;
780ccef4ddfSAndrew Thompson transfer->callback = callback;
781ccef4ddfSAndrew Thompson }
782ccef4ddfSAndrew Thompson
783ccef4ddfSAndrew Thompson void
libusb_fill_iso_transfer(struct libusb_transfer * transfer,libusb_device_handle * devh,uint8_t endpoint,uint8_t * buf,int length,int npacket,libusb_transfer_cb_fn callback,void * user_data,uint32_t timeout)784ccef4ddfSAndrew Thompson libusb_fill_iso_transfer(struct libusb_transfer *transfer,
785ccef4ddfSAndrew Thompson libusb_device_handle *devh, uint8_t endpoint, uint8_t *buf,
786ccef4ddfSAndrew Thompson int length, int npacket, libusb_transfer_cb_fn callback,
787ccef4ddfSAndrew Thompson void *user_data, uint32_t timeout)
788ccef4ddfSAndrew Thompson {
789ccef4ddfSAndrew Thompson transfer->dev_handle = devh;
790ccef4ddfSAndrew Thompson transfer->endpoint = endpoint;
791ccef4ddfSAndrew Thompson transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
792ccef4ddfSAndrew Thompson transfer->timeout = timeout;
793ccef4ddfSAndrew Thompson transfer->buffer = buf;
794ccef4ddfSAndrew Thompson transfer->length = length;
795ccef4ddfSAndrew Thompson transfer->num_iso_packets = npacket;
796ccef4ddfSAndrew Thompson transfer->user_data = user_data;
797ccef4ddfSAndrew Thompson transfer->callback = callback;
798ccef4ddfSAndrew Thompson }
799ccef4ddfSAndrew Thompson
800a0c93fa3SHans Petter Selasky int
libusb_alloc_streams(libusb_device_handle * dev,uint32_t num_streams,unsigned char * endpoints,int num_endpoints)801a0c93fa3SHans Petter Selasky libusb_alloc_streams(libusb_device_handle *dev, uint32_t num_streams,
802a0c93fa3SHans Petter Selasky unsigned char *endpoints, int num_endpoints)
803a0c93fa3SHans Petter Selasky {
804a0c93fa3SHans Petter Selasky if (num_streams > 1)
805a0c93fa3SHans Petter Selasky return (LIBUSB_ERROR_INVALID_PARAM);
806a0c93fa3SHans Petter Selasky return (0);
807a0c93fa3SHans Petter Selasky }
808a0c93fa3SHans Petter Selasky
809a0c93fa3SHans Petter Selasky int
libusb_free_streams(libusb_device_handle * dev,unsigned char * endpoints,int num_endpoints)810a0c93fa3SHans Petter Selasky libusb_free_streams(libusb_device_handle *dev, unsigned char *endpoints, int num_endpoints)
811a0c93fa3SHans Petter Selasky {
812a0c93fa3SHans Petter Selasky
813a0c93fa3SHans Petter Selasky return (0);
814a0c93fa3SHans Petter Selasky }
815a0c93fa3SHans Petter Selasky
816a0c93fa3SHans Petter Selasky void
libusb_transfer_set_stream_id(struct libusb_transfer * transfer,uint32_t stream_id)817a0c93fa3SHans Petter Selasky libusb_transfer_set_stream_id(struct libusb_transfer *transfer, uint32_t stream_id)
818a0c93fa3SHans Petter Selasky {
819a0c93fa3SHans Petter Selasky struct libusb_super_transfer *sxfer;
820a0c93fa3SHans Petter Selasky
821a0c93fa3SHans Petter Selasky if (transfer == NULL)
822a0c93fa3SHans Petter Selasky return;
823a0c93fa3SHans Petter Selasky
824a0c93fa3SHans Petter Selasky sxfer = (struct libusb_super_transfer *)(
825a0c93fa3SHans Petter Selasky ((uint8_t *)transfer) - sizeof(*sxfer));
826a0c93fa3SHans Petter Selasky
827a0c93fa3SHans Petter Selasky /* set stream ID */
828a0c93fa3SHans Petter Selasky sxfer->stream_id = stream_id;
829a0c93fa3SHans Petter Selasky }
830a0c93fa3SHans Petter Selasky
831a0c93fa3SHans Petter Selasky uint32_t
libusb_transfer_get_stream_id(struct libusb_transfer * transfer)832a0c93fa3SHans Petter Selasky libusb_transfer_get_stream_id(struct libusb_transfer *transfer)
833a0c93fa3SHans Petter Selasky {
834a0c93fa3SHans Petter Selasky struct libusb_super_transfer *sxfer;
835a0c93fa3SHans Petter Selasky
836a0c93fa3SHans Petter Selasky if (transfer == NULL)
837a0c93fa3SHans Petter Selasky return (0);
838a0c93fa3SHans Petter Selasky
839a0c93fa3SHans Petter Selasky sxfer = (struct libusb_super_transfer *)(
840a0c93fa3SHans Petter Selasky ((uint8_t *)transfer) - sizeof(*sxfer));
841a0c93fa3SHans Petter Selasky
842a0c93fa3SHans Petter Selasky /* get stream ID */
843a0c93fa3SHans Petter Selasky return (sxfer->stream_id);
844a0c93fa3SHans Petter Selasky }
845