libusb10.c revision 301956
1194676Sthompsa/* $FreeBSD: head/lib/libusb/libusb10.c 301956 2016-06-16 07:48:21Z hselasky $ */
2194676Sthompsa/*-
3194676Sthompsa * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
4195957Salfred * Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
5194676Sthompsa *
6194676Sthompsa * Redistribution and use in source and binary forms, with or without
7194676Sthompsa * modification, are permitted provided that the following conditions
8194676Sthompsa * are met:
9194676Sthompsa * 1. Redistributions of source code must retain the above copyright
10194676Sthompsa *    notice, this list of conditions and the following disclaimer.
11194676Sthompsa * 2. Redistributions in binary form must reproduce the above copyright
12194676Sthompsa *    notice, this list of conditions and the following disclaimer in the
13194676Sthompsa *    documentation and/or other materials provided with the distribution.
14194676Sthompsa *
15194676Sthompsa * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16194676Sthompsa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17194676Sthompsa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18194676Sthompsa * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19194676Sthompsa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20194676Sthompsa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21194676Sthompsa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22194676Sthompsa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23194676Sthompsa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24194676Sthompsa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25194676Sthompsa * SUCH DAMAGE.
26194676Sthompsa */
27194676Sthompsa
28248236Shselasky#ifdef LIBUSB_GLOBAL_INCLUDE_FILE
29248236Shselasky#include LIBUSB_GLOBAL_INCLUDE_FILE
30248236Shselasky#else
31203774Swkoszek#include <assert.h>
32203815Swkoszek#include <errno.h>
33203815Swkoszek#include <poll.h>
34203815Swkoszek#include <pthread.h>
35203815Swkoszek#include <stdio.h>
36194676Sthompsa#include <stdlib.h>
37248236Shselasky#include <string.h>
38194676Sthompsa#include <unistd.h>
39248236Shselasky#include <time.h>
40248236Shselasky#include <sys/fcntl.h>
41248236Shselasky#include <sys/ioctl.h>
42248236Shselasky#include <sys/queue.h>
43248236Shselasky#include <sys/endian.h>
44248236Shselasky#endif
45194676Sthompsa
46208020Sthompsa#define	libusb_device_handle libusb20_device
47208020Sthompsa
48194676Sthompsa#include "libusb20.h"
49194676Sthompsa#include "libusb20_desc.h"
50194676Sthompsa#include "libusb20_int.h"
51194676Sthompsa#include "libusb.h"
52194676Sthompsa#include "libusb10.h"
53194676Sthompsa
54301842Shselasky#define	LIBUSB_NUM_SW_ENDPOINTS	(16 * 4)
55301842Shselasky
56194676Sthompsastatic pthread_mutex_t default_context_lock = PTHREAD_MUTEX_INITIALIZER;
57194676Sthompsastruct libusb_context *usbi_default_context = NULL;
58194676Sthompsa
59195957Salfred/* Prototypes */
60195957Salfred
61195957Salfredstatic struct libusb20_transfer *libusb10_get_transfer(struct libusb20_device *, uint8_t, uint8_t);
62195957Salfredstatic int libusb10_get_buffsize(struct libusb20_device *, libusb_transfer *);
63195957Salfredstatic int libusb10_convert_error(uint8_t status);
64195957Salfredstatic void libusb10_complete_transfer(struct libusb20_transfer *, struct libusb_super_transfer *, int);
65195957Salfredstatic void libusb10_isoc_proxy(struct libusb20_transfer *);
66195957Salfredstatic void libusb10_bulk_intr_proxy(struct libusb20_transfer *);
67195957Salfredstatic void libusb10_ctrl_proxy(struct libusb20_transfer *);
68195957Salfredstatic void libusb10_submit_transfer_sub(struct libusb20_device *, uint8_t);
69195957Salfred
70194676Sthompsa/*  Library initialisation / deinitialisation */
71194676Sthompsa
72301956Shselaskystatic const struct libusb_version libusb_version = {
73301956Shselasky	.major = 1,
74301956Shselasky	.minor = 0,
75301956Shselasky	.micro = 0,
76301956Shselasky	.nano = 2016,
77301956Shselasky	.rc = "",
78301956Shselasky	.describe = "http://www.freebsd.org"
79301956Shselasky};
80301956Shselasky
81301956Shselaskyconst struct libusb_version *
82301956Shselaskylibusb_get_version(void)
83301956Shselasky{
84301956Shselasky
85301956Shselasky	return (&libusb_version);
86301956Shselasky}
87301956Shselasky
88194676Sthompsavoid
89195957Salfredlibusb_set_debug(libusb_context *ctx, int level)
90194676Sthompsa{
91195957Salfred	ctx = GET_CONTEXT(ctx);
92194676Sthompsa	if (ctx)
93194676Sthompsa		ctx->debug = level;
94194676Sthompsa}
95194676Sthompsa
96213853Shselaskystatic void
97213853Shselaskylibusb_set_nonblocking(int f)
98213853Shselasky{
99213853Shselasky	int flags;
100213853Shselasky
101213853Shselasky	/*
102213853Shselasky	 * We ignore any failures in this function, hence the
103213853Shselasky	 * non-blocking flag is not critical to the operation of
104213853Shselasky	 * libUSB. We use F_GETFL and F_SETFL to be compatible with
105213853Shselasky	 * Linux.
106213853Shselasky	 */
107213853Shselasky
108213853Shselasky	flags = fcntl(f, F_GETFL, NULL);
109213853Shselasky	if (flags == -1)
110213853Shselasky		return;
111213853Shselasky	flags |= O_NONBLOCK;
112213853Shselasky	fcntl(f, F_SETFL, flags);
113213853Shselasky}
114213853Shselasky
115194676Sthompsaint
116195957Salfredlibusb_init(libusb_context **context)
117194676Sthompsa{
118194676Sthompsa	struct libusb_context *ctx;
119236944Shselasky	pthread_condattr_t attr;
120195957Salfred	char *debug;
121194676Sthompsa	int ret;
122194676Sthompsa
123194676Sthompsa	ctx = malloc(sizeof(*ctx));
124194676Sthompsa	if (!ctx)
125194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
126194676Sthompsa
127194676Sthompsa	memset(ctx, 0, sizeof(*ctx));
128194676Sthompsa
129194676Sthompsa	debug = getenv("LIBUSB_DEBUG");
130194676Sthompsa	if (debug != NULL) {
131194676Sthompsa		ctx->debug = atoi(debug);
132194676Sthompsa		if (ctx->debug != 0)
133194676Sthompsa			ctx->debug_fixed = 1;
134194676Sthompsa	}
135195957Salfred	TAILQ_INIT(&ctx->pollfds);
136195957Salfred	TAILQ_INIT(&ctx->tr_done);
137194676Sthompsa
138236944Shselasky	if (pthread_mutex_init(&ctx->ctx_lock, NULL) != 0) {
139236944Shselasky		free(ctx);
140236944Shselasky		return (LIBUSB_ERROR_NO_MEM);
141236944Shselasky	}
142236944Shselasky	if (pthread_condattr_init(&attr) != 0) {
143236944Shselasky		pthread_mutex_destroy(&ctx->ctx_lock);
144236944Shselasky		free(ctx);
145236944Shselasky		return (LIBUSB_ERROR_NO_MEM);
146236944Shselasky	}
147236944Shselasky	if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) != 0) {
148236944Shselasky		pthread_mutex_destroy(&ctx->ctx_lock);
149236944Shselasky		pthread_condattr_destroy(&attr);
150236944Shselasky		free(ctx);
151236944Shselasky		return (LIBUSB_ERROR_OTHER);
152236944Shselasky	}
153236944Shselasky	if (pthread_cond_init(&ctx->ctx_cond, &attr) != 0) {
154236944Shselasky		pthread_mutex_destroy(&ctx->ctx_lock);
155236944Shselasky		pthread_condattr_destroy(&attr);
156236944Shselasky		free(ctx);
157236944Shselasky		return (LIBUSB_ERROR_NO_MEM);
158236944Shselasky	}
159236944Shselasky	pthread_condattr_destroy(&attr);
160194676Sthompsa
161195957Salfred	ctx->ctx_handler = NO_THREAD;
162194676Sthompsa
163194676Sthompsa	ret = pipe(ctx->ctrl_pipe);
164194676Sthompsa	if (ret < 0) {
165195957Salfred		pthread_mutex_destroy(&ctx->ctx_lock);
166195957Salfred		pthread_cond_destroy(&ctx->ctx_cond);
167194676Sthompsa		free(ctx);
168194676Sthompsa		return (LIBUSB_ERROR_OTHER);
169194676Sthompsa	}
170195957Salfred	/* set non-blocking mode on the control pipe to avoid deadlock */
171213853Shselasky	libusb_set_nonblocking(ctx->ctrl_pipe[0]);
172213853Shselasky	libusb_set_nonblocking(ctx->ctrl_pipe[1]);
173194676Sthompsa
174195957Salfred	libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->ctrl_pipe[0], POLLIN);
175194676Sthompsa
176194676Sthompsa	pthread_mutex_lock(&default_context_lock);
177194676Sthompsa	if (usbi_default_context == NULL) {
178194676Sthompsa		usbi_default_context = ctx;
179194676Sthompsa	}
180194676Sthompsa	pthread_mutex_unlock(&default_context_lock);
181194676Sthompsa
182194676Sthompsa	if (context)
183194676Sthompsa		*context = ctx;
184194676Sthompsa
185195957Salfred	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_init complete");
186195957Salfred
187194676Sthompsa	return (0);
188194676Sthompsa}
189194676Sthompsa
190194676Sthompsavoid
191195957Salfredlibusb_exit(libusb_context *ctx)
192194676Sthompsa{
193195957Salfred	ctx = GET_CONTEXT(ctx);
194194676Sthompsa
195195957Salfred	if (ctx == NULL)
196195957Salfred		return;
197195957Salfred
198195957Salfred	/* XXX cleanup devices */
199195957Salfred
200195957Salfred	libusb10_remove_pollfd(ctx, &ctx->ctx_poll);
201194676Sthompsa	close(ctx->ctrl_pipe[0]);
202194676Sthompsa	close(ctx->ctrl_pipe[1]);
203195957Salfred	pthread_mutex_destroy(&ctx->ctx_lock);
204195957Salfred	pthread_cond_destroy(&ctx->ctx_cond);
205194676Sthompsa
206194676Sthompsa	pthread_mutex_lock(&default_context_lock);
207194676Sthompsa	if (ctx == usbi_default_context) {
208194676Sthompsa		usbi_default_context = NULL;
209194676Sthompsa	}
210194676Sthompsa	pthread_mutex_unlock(&default_context_lock);
211194676Sthompsa
212194676Sthompsa	free(ctx);
213194676Sthompsa}
214194676Sthompsa
215194676Sthompsa/* Device handling and initialisation. */
216194676Sthompsa
217194676Sthompsassize_t
218195957Salfredlibusb_get_device_list(libusb_context *ctx, libusb_device ***list)
219194676Sthompsa{
220195957Salfred	struct libusb20_backend *usb_backend;
221194676Sthompsa	struct libusb20_device *pdev;
222194676Sthompsa	struct libusb_device *dev;
223194676Sthompsa	int i;
224194676Sthompsa
225195957Salfred	ctx = GET_CONTEXT(ctx);
226194676Sthompsa
227195957Salfred	if (ctx == NULL)
228195957Salfred		return (LIBUSB_ERROR_INVALID_PARAM);
229195957Salfred
230195957Salfred	if (list == NULL)
231195957Salfred		return (LIBUSB_ERROR_INVALID_PARAM);
232195957Salfred
233194676Sthompsa	usb_backend = libusb20_be_alloc_default();
234194676Sthompsa	if (usb_backend == NULL)
235195957Salfred		return (LIBUSB_ERROR_NO_MEM);
236194676Sthompsa
237195957Salfred	/* figure out how many USB devices are present */
238194676Sthompsa	pdev = NULL;
239194676Sthompsa	i = 0;
240194676Sthompsa	while ((pdev = libusb20_be_device_foreach(usb_backend, pdev)))
241194676Sthompsa		i++;
242194676Sthompsa
243195957Salfred	/* allocate device pointer list */
244194676Sthompsa	*list = malloc((i + 1) * sizeof(void *));
245194676Sthompsa	if (*list == NULL) {
246194676Sthompsa		libusb20_be_free(usb_backend);
247194676Sthompsa		return (LIBUSB_ERROR_NO_MEM);
248194676Sthompsa	}
249195957Salfred	/* create libusb v1.0 compliant devices */
250194676Sthompsa	i = 0;
251194676Sthompsa	while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) {
252194676Sthompsa
253194676Sthompsa		dev = malloc(sizeof(*dev));
254194676Sthompsa		if (dev == NULL) {
255195560Sthompsa			while (i != 0) {
256195560Sthompsa				libusb_unref_device((*list)[i - 1]);
257195560Sthompsa				i--;
258195560Sthompsa			}
259194676Sthompsa			free(*list);
260195957Salfred			*list = NULL;
261194676Sthompsa			libusb20_be_free(usb_backend);
262194676Sthompsa			return (LIBUSB_ERROR_NO_MEM);
263194676Sthompsa		}
264199055Sthompsa		/* get device into libUSB v1.0 list */
265199055Sthompsa		libusb20_be_dequeue_device(usb_backend, pdev);
266199055Sthompsa
267194676Sthompsa		memset(dev, 0, sizeof(*dev));
268194676Sthompsa
269195957Salfred		/* init transfer queues */
270195957Salfred		TAILQ_INIT(&dev->tr_head);
271195957Salfred
272195957Salfred		/* set context we belong to */
273194676Sthompsa		dev->ctx = ctx;
274194676Sthompsa
275194676Sthompsa		/* link together the two structures */
276194676Sthompsa		dev->os_priv = pdev;
277195957Salfred		pdev->privLuData = dev;
278194676Sthompsa
279194676Sthompsa		(*list)[i] = libusb_ref_device(dev);
280194676Sthompsa		i++;
281194676Sthompsa	}
282194676Sthompsa	(*list)[i] = NULL;
283194676Sthompsa
284194676Sthompsa	libusb20_be_free(usb_backend);
285194676Sthompsa	return (i);
286194676Sthompsa}
287194676Sthompsa
288194676Sthompsavoid
289194676Sthompsalibusb_free_device_list(libusb_device **list, int unref_devices)
290194676Sthompsa{
291194676Sthompsa	int i;
292194676Sthompsa
293194676Sthompsa	if (list == NULL)
294195957Salfred		return;			/* be NULL safe */
295194676Sthompsa
296194676Sthompsa	if (unref_devices) {
297194676Sthompsa		for (i = 0; list[i] != NULL; i++)
298194676Sthompsa			libusb_unref_device(list[i]);
299194676Sthompsa	}
300194676Sthompsa	free(list);
301194676Sthompsa}
302194676Sthompsa
303194676Sthompsauint8_t
304195957Salfredlibusb_get_bus_number(libusb_device *dev)
305194676Sthompsa{
306194676Sthompsa	if (dev == NULL)
307195957Salfred		return (0);		/* should not happen */
308195957Salfred	return (libusb20_dev_get_bus_number(dev->os_priv));
309194676Sthompsa}
310194676Sthompsa
311250342Semasteint
312251495Semastelibusb_get_port_numbers(libusb_device *dev, uint8_t *buf, uint8_t bufsize)
313251495Semaste{
314251495Semaste	return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize));
315251495Semaste}
316251495Semaste
317251495Semasteint
318250342Semastelibusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t *buf,
319250342Semaste    uint8_t bufsize)
320250342Semaste{
321250342Semaste	return (libusb20_dev_get_port_path(dev->os_priv, buf, bufsize));
322250342Semaste}
323250342Semaste
324194676Sthompsauint8_t
325195957Salfredlibusb_get_device_address(libusb_device *dev)
326194676Sthompsa{
327194676Sthompsa	if (dev == NULL)
328195957Salfred		return (0);		/* should not happen */
329195957Salfred	return (libusb20_dev_get_address(dev->os_priv));
330194676Sthompsa}
331194676Sthompsa
332224903Shselaskyenum libusb_speed
333224903Shselaskylibusb_get_device_speed(libusb_device *dev)
334224903Shselasky{
335224903Shselasky	if (dev == NULL)
336225035Shselasky		return (LIBUSB_SPEED_UNKNOWN);	/* should not happen */
337224903Shselasky
338224903Shselasky	switch (libusb20_dev_get_speed(dev->os_priv)) {
339224903Shselasky	case LIBUSB20_SPEED_LOW:
340224903Shselasky		return (LIBUSB_SPEED_LOW);
341224903Shselasky	case LIBUSB20_SPEED_FULL:
342224903Shselasky		return (LIBUSB_SPEED_FULL);
343224903Shselasky	case LIBUSB20_SPEED_HIGH:
344224903Shselasky		return (LIBUSB_SPEED_HIGH);
345224903Shselasky	case LIBUSB20_SPEED_SUPER:
346224903Shselasky		return (LIBUSB_SPEED_SUPER);
347224903Shselasky	default:
348224903Shselasky		break;
349224903Shselasky	}
350224903Shselasky	return (LIBUSB_SPEED_UNKNOWN);
351224903Shselasky}
352224903Shselasky
353194676Sthompsaint
354195957Salfredlibusb_get_max_packet_size(libusb_device *dev, uint8_t endpoint)
355194676Sthompsa{
356194676Sthompsa	struct libusb_config_descriptor *pdconf;
357194676Sthompsa	struct libusb_interface *pinf;
358194676Sthompsa	struct libusb_interface_descriptor *pdinf;
359194676Sthompsa	struct libusb_endpoint_descriptor *pdend;
360195957Salfred	int i;
361195957Salfred	int j;
362195957Salfred	int k;
363195957Salfred	int ret;
364194676Sthompsa
365194676Sthompsa	if (dev == NULL)
366194676Sthompsa		return (LIBUSB_ERROR_NO_DEVICE);
367194676Sthompsa
368195957Salfred	ret = libusb_get_active_config_descriptor(dev, &pdconf);
369195957Salfred	if (ret < 0)
370195957Salfred		return (ret);
371195957Salfred
372194676Sthompsa	ret = LIBUSB_ERROR_NOT_FOUND;
373195957Salfred	for (i = 0; i < pdconf->bNumInterfaces; i++) {
374194676Sthompsa		pinf = &pdconf->interface[i];
375195957Salfred		for (j = 0; j < pinf->num_altsetting; j++) {
376194676Sthompsa			pdinf = &pinf->altsetting[j];
377195957Salfred			for (k = 0; k < pdinf->bNumEndpoints; k++) {
378194676Sthompsa				pdend = &pdinf->endpoint[k];
379194676Sthompsa				if (pdend->bEndpointAddress == endpoint) {
380194676Sthompsa					ret = pdend->wMaxPacketSize;
381194676Sthompsa					goto out;
382194676Sthompsa				}
383194676Sthompsa			}
384194676Sthompsa		}
385194676Sthompsa	}
386194676Sthompsa
387194676Sthompsaout:
388194676Sthompsa	libusb_free_config_descriptor(pdconf);
389194676Sthompsa	return (ret);
390194676Sthompsa}
391194676Sthompsa
392234193Shselaskyint
393234193Shselaskylibusb_get_max_iso_packet_size(libusb_device *dev, uint8_t endpoint)
394234193Shselasky{
395234193Shselasky	int multiplier;
396234193Shselasky	int ret;
397234193Shselasky
398234193Shselasky	ret = libusb_get_max_packet_size(dev, endpoint);
399234193Shselasky
400234193Shselasky	switch (libusb20_dev_get_speed(dev->os_priv)) {
401234193Shselasky	case LIBUSB20_SPEED_LOW:
402234193Shselasky	case LIBUSB20_SPEED_FULL:
403234193Shselasky		break;
404234193Shselasky	default:
405234193Shselasky		if (ret > -1) {
406234193Shselasky			multiplier = (1 + ((ret >> 11) & 3));
407234193Shselasky			if (multiplier > 3)
408234193Shselasky				multiplier = 3;
409234193Shselasky			ret = (ret & 0x7FF) * multiplier;
410234193Shselasky		}
411234193Shselasky		break;
412234193Shselasky	}
413234193Shselasky	return (ret);
414234193Shselasky}
415234193Shselasky
416194676Sthompsalibusb_device *
417195957Salfredlibusb_ref_device(libusb_device *dev)
418194676Sthompsa{
419194676Sthompsa	if (dev == NULL)
420195957Salfred		return (NULL);		/* be NULL safe */
421194676Sthompsa
422195957Salfred	CTX_LOCK(dev->ctx);
423194676Sthompsa	dev->refcnt++;
424195957Salfred	CTX_UNLOCK(dev->ctx);
425194676Sthompsa
426194676Sthompsa	return (dev);
427194676Sthompsa}
428194676Sthompsa
429194676Sthompsavoid
430195957Salfredlibusb_unref_device(libusb_device *dev)
431194676Sthompsa{
432194676Sthompsa	if (dev == NULL)
433195957Salfred		return;			/* be NULL safe */
434194676Sthompsa
435195957Salfred	CTX_LOCK(dev->ctx);
436194676Sthompsa	dev->refcnt--;
437195957Salfred	CTX_UNLOCK(dev->ctx);
438194676Sthompsa
439194676Sthompsa	if (dev->refcnt == 0) {
440194676Sthompsa		libusb20_dev_free(dev->os_priv);
441194676Sthompsa		free(dev);
442194676Sthompsa	}
443194676Sthompsa}
444194676Sthompsa
445194676Sthompsaint
446195957Salfredlibusb_open(libusb_device *dev, libusb_device_handle **devh)
447194676Sthompsa{
448194676Sthompsa	libusb_context *ctx = dev->ctx;
449194676Sthompsa	struct libusb20_device *pdev = dev->os_priv;
450195957Salfred	uint8_t dummy;
451194676Sthompsa	int err;
452194676Sthompsa
453194676Sthompsa	if (devh == NULL)
454194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
455194676Sthompsa
456195957Salfred	/* set default device handle value */
457195957Salfred	*devh = NULL;
458194676Sthompsa
459195957Salfred	dev = libusb_ref_device(dev);
460195957Salfred	if (dev == NULL)
461195957Salfred		return (LIBUSB_ERROR_INVALID_PARAM);
462195957Salfred
463301842Shselasky	err = libusb20_dev_open(pdev, LIBUSB_NUM_SW_ENDPOINTS);
464194676Sthompsa	if (err) {
465195957Salfred		libusb_unref_device(dev);
466194676Sthompsa		return (LIBUSB_ERROR_NO_MEM);
467194676Sthompsa	}
468195957Salfred	libusb10_add_pollfd(ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN |
469194676Sthompsa	    POLLOUT | POLLRDNORM | POLLWRNORM);
470194676Sthompsa
471195957Salfred	/* make sure our event loop detects the new device */
472195957Salfred	dummy = 0;
473194676Sthompsa	err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
474213853Shselasky	if (err < (int)sizeof(dummy)) {
475195957Salfred		/* ignore error, if any */
476195957Salfred		DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open write failed!");
477194676Sthompsa	}
478195957Salfred	*devh = pdev;
479194676Sthompsa
480194676Sthompsa	return (0);
481194676Sthompsa}
482194676Sthompsa
483194676Sthompsalibusb_device_handle *
484195957Salfredlibusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id,
485194676Sthompsa    uint16_t product_id)
486194676Sthompsa{
487194676Sthompsa	struct libusb_device **devs;
488194676Sthompsa	struct libusb20_device *pdev;
489194676Sthompsa	struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
490195957Salfred	int i;
491195957Salfred	int j;
492194676Sthompsa
493195957Salfred	ctx = GET_CONTEXT(ctx);
494195957Salfred	if (ctx == NULL)
495195957Salfred		return (NULL);		/* be NULL safe */
496195957Salfred
497195560Sthompsa	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid enter");
498194676Sthompsa
499194676Sthompsa	if ((i = libusb_get_device_list(ctx, &devs)) < 0)
500194676Sthompsa		return (NULL);
501194676Sthompsa
502228236Shselasky	pdev = NULL;
503194676Sthompsa	for (j = 0; j < i; j++) {
504228236Shselasky		struct libusb20_device *tdev;
505228236Shselasky
506228236Shselasky		tdev = devs[j]->os_priv;
507228236Shselasky		pdesc = libusb20_dev_get_device_desc(tdev);
508195957Salfred		/*
509195957Salfred		 * NOTE: The USB library will automatically swap the
510195957Salfred		 * fields in the device descriptor to be of host
511195957Salfred		 * endian type!
512195957Salfred		 */
513194676Sthompsa		if (pdesc->idVendor == vendor_id &&
514195560Sthompsa		    pdesc->idProduct == product_id) {
515228235Shselasky			libusb_open(devs[j], &pdev);
516195957Salfred			break;
517195560Sthompsa		}
518194676Sthompsa	}
519194676Sthompsa
520194676Sthompsa	libusb_free_device_list(devs, 1);
521195560Sthompsa	DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid leave");
522195957Salfred	return (pdev);
523194676Sthompsa}
524194676Sthompsa
525194676Sthompsavoid
526195957Salfredlibusb_close(struct libusb20_device *pdev)
527194676Sthompsa{
528194676Sthompsa	libusb_context *ctx;
529195957Salfred	struct libusb_device *dev;
530195957Salfred	uint8_t dummy;
531194676Sthompsa	int err;
532194676Sthompsa
533195957Salfred	if (pdev == NULL)
534195957Salfred		return;			/* be NULL safe */
535194676Sthompsa
536195957Salfred	dev = libusb_get_device(pdev);
537195957Salfred	ctx = dev->ctx;
538194676Sthompsa
539195957Salfred	libusb10_remove_pollfd(ctx, &dev->dev_poll);
540194676Sthompsa
541195957Salfred	libusb20_dev_close(pdev);
542199055Sthompsa
543199055Sthompsa	/* unref will free the "pdev" when the refcount reaches zero */
544195957Salfred	libusb_unref_device(dev);
545194676Sthompsa
546195957Salfred	/* make sure our event loop detects the closed device */
547195957Salfred	dummy = 0;
548194676Sthompsa	err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
549213853Shselasky	if (err < (int)sizeof(dummy)) {
550195957Salfred		/* ignore error, if any */
551195957Salfred		DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close write failed!");
552194676Sthompsa	}
553194676Sthompsa}
554194676Sthompsa
555194676Sthompsalibusb_device *
556195957Salfredlibusb_get_device(struct libusb20_device *pdev)
557194676Sthompsa{
558195957Salfred	if (pdev == NULL)
559194676Sthompsa		return (NULL);
560195957Salfred	return ((libusb_device *)pdev->privLuData);
561194676Sthompsa}
562194676Sthompsa
563194676Sthompsaint
564195957Salfredlibusb_get_configuration(struct libusb20_device *pdev, int *config)
565194676Sthompsa{
566195957Salfred	struct libusb20_config *pconf;
567194676Sthompsa
568195957Salfred	if (pdev == NULL || config == NULL)
569194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
570194676Sthompsa
571195957Salfred	pconf = libusb20_dev_alloc_config(pdev, libusb20_dev_get_config_index(pdev));
572195957Salfred	if (pconf == NULL)
573195957Salfred		return (LIBUSB_ERROR_NO_MEM);
574194676Sthompsa
575195957Salfred	*config = pconf->desc.bConfigurationValue;
576195957Salfred
577195957Salfred	free(pconf);
578195957Salfred
579194676Sthompsa	return (0);
580194676Sthompsa}
581194676Sthompsa
582194676Sthompsaint
583195957Salfredlibusb_set_configuration(struct libusb20_device *pdev, int configuration)
584194676Sthompsa{
585195957Salfred	struct libusb20_config *pconf;
586195957Salfred	struct libusb_device *dev;
587195957Salfred	int err;
588195957Salfred	uint8_t i;
589194676Sthompsa
590195957Salfred	dev = libusb_get_device(pdev);
591195957Salfred	if (dev == NULL)
592194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
593194676Sthompsa
594195957Salfred	if (configuration < 1) {
595195957Salfred		/* unconfigure */
596195957Salfred		i = 255;
597195957Salfred	} else {
598195957Salfred		for (i = 0; i != 255; i++) {
599195957Salfred			uint8_t found;
600194676Sthompsa
601195957Salfred			pconf = libusb20_dev_alloc_config(pdev, i);
602195957Salfred			if (pconf == NULL)
603195957Salfred				return (LIBUSB_ERROR_INVALID_PARAM);
604195957Salfred			found = (pconf->desc.bConfigurationValue
605195957Salfred			    == configuration);
606195957Salfred			free(pconf);
607195957Salfred
608195957Salfred			if (found)
609195957Salfred				goto set_config;
610195957Salfred		}
611195957Salfred		return (LIBUSB_ERROR_INVALID_PARAM);
612195957Salfred	}
613195957Salfred
614195957Salfredset_config:
615195957Salfred
616195957Salfred	libusb10_cancel_all_transfer(dev);
617195957Salfred
618195957Salfred	libusb10_remove_pollfd(dev->ctx, &dev->dev_poll);
619195957Salfred
620195957Salfred	err = libusb20_dev_set_config_index(pdev, i);
621195957Salfred
622195957Salfred	libusb10_add_pollfd(dev->ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN |
623195957Salfred	    POLLOUT | POLLRDNORM | POLLWRNORM);
624195957Salfred
625195957Salfred	return (err ? LIBUSB_ERROR_INVALID_PARAM : 0);
626194676Sthompsa}
627194676Sthompsa
628194676Sthompsaint
629195957Salfredlibusb_claim_interface(struct libusb20_device *pdev, int interface_number)
630194676Sthompsa{
631195957Salfred	libusb_device *dev;
632194676Sthompsa
633195957Salfred	dev = libusb_get_device(pdev);
634194676Sthompsa	if (dev == NULL)
635194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
636194676Sthompsa
637195957Salfred	if (interface_number < 0 || interface_number > 31)
638194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
639194676Sthompsa
640195957Salfred	CTX_LOCK(dev->ctx);
641261224Shselasky	dev->claimed_interfaces |= (1 << interface_number);
642261224Shselasky	CTX_UNLOCK(dev->ctx);
643194676Sthompsa
644261224Shselasky	return (0);
645194676Sthompsa}
646194676Sthompsa
647194676Sthompsaint
648195957Salfredlibusb_release_interface(struct libusb20_device *pdev, int interface_number)
649194676Sthompsa{
650195957Salfred	libusb_device *dev;
651195957Salfred	int err = 0;
652194676Sthompsa
653195957Salfred	dev = libusb_get_device(pdev);
654194676Sthompsa	if (dev == NULL)
655194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
656194676Sthompsa
657195957Salfred	if (interface_number < 0 || interface_number > 31)
658194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
659194676Sthompsa
660195957Salfred	CTX_LOCK(dev->ctx);
661194676Sthompsa	if (!(dev->claimed_interfaces & (1 << interface_number)))
662195957Salfred		err = LIBUSB_ERROR_NOT_FOUND;
663194676Sthompsa
664195957Salfred	if (!err)
665194676Sthompsa		dev->claimed_interfaces &= ~(1 << interface_number);
666195957Salfred	CTX_UNLOCK(dev->ctx);
667195957Salfred	return (err);
668194676Sthompsa}
669194676Sthompsa
670194676Sthompsaint
671195957Salfredlibusb_set_interface_alt_setting(struct libusb20_device *pdev,
672194676Sthompsa    int interface_number, int alternate_setting)
673194676Sthompsa{
674195957Salfred	libusb_device *dev;
675195957Salfred	int err = 0;
676194676Sthompsa
677195957Salfred	dev = libusb_get_device(pdev);
678194676Sthompsa	if (dev == NULL)
679194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
680194676Sthompsa
681195957Salfred	if (interface_number < 0 || interface_number > 31)
682194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
683194676Sthompsa
684195957Salfred	CTX_LOCK(dev->ctx);
685195957Salfred	if (!(dev->claimed_interfaces & (1 << interface_number)))
686195957Salfred		err = LIBUSB_ERROR_NOT_FOUND;
687195957Salfred	CTX_UNLOCK(dev->ctx);
688194676Sthompsa
689195957Salfred	if (err)
690195957Salfred		return (err);
691195957Salfred
692195957Salfred	libusb10_cancel_all_transfer(dev);
693195957Salfred
694195957Salfred	libusb10_remove_pollfd(dev->ctx, &dev->dev_poll);
695195957Salfred
696195957Salfred	err = libusb20_dev_set_alt_index(pdev,
697195957Salfred	    interface_number, alternate_setting);
698195957Salfred
699195957Salfred	libusb10_add_pollfd(dev->ctx, &dev->dev_poll,
700195957Salfred	    pdev, libusb20_dev_get_fd(pdev),
701195957Salfred	    POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM);
702195957Salfred
703195957Salfred	return (err ? LIBUSB_ERROR_OTHER : 0);
704194676Sthompsa}
705194676Sthompsa
706195957Salfredstatic struct libusb20_transfer *
707195957Salfredlibusb10_get_transfer(struct libusb20_device *pdev,
708234491Shselasky    uint8_t endpoint, uint8_t xfer_index)
709195957Salfred{
710234491Shselasky	xfer_index &= 1;	/* double buffering */
711195957Salfred
712234491Shselasky	xfer_index |= (endpoint & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 4;
713195957Salfred
714195957Salfred	if (endpoint & LIBUSB20_ENDPOINT_DIR_MASK) {
715195957Salfred		/* this is an IN endpoint */
716234491Shselasky		xfer_index |= 2;
717195957Salfred	}
718234491Shselasky	return (libusb20_tr_get_pointer(pdev, xfer_index));
719195957Salfred}
720195957Salfred
721194676Sthompsaint
722195957Salfredlibusb_clear_halt(struct libusb20_device *pdev, uint8_t endpoint)
723194676Sthompsa{
724194676Sthompsa	struct libusb20_transfer *xfer;
725195957Salfred	struct libusb_device *dev;
726195957Salfred	int err;
727194676Sthompsa
728195957Salfred	xfer = libusb10_get_transfer(pdev, endpoint, 0);
729195560Sthompsa	if (xfer == NULL)
730195957Salfred		return (LIBUSB_ERROR_INVALID_PARAM);
731194676Sthompsa
732195957Salfred	dev = libusb_get_device(pdev);
733213853Shselasky	if (dev == NULL)
734213853Shselasky		return (LIBUSB_ERROR_INVALID_PARAM);
735195957Salfred
736195957Salfred	CTX_LOCK(dev->ctx);
737223642Shselasky	err = libusb20_tr_open(xfer, 0, 1, endpoint);
738195957Salfred	CTX_UNLOCK(dev->ctx);
739195957Salfred
740195957Salfred	if (err != 0 && err != LIBUSB20_ERROR_BUSY)
741194676Sthompsa		return (LIBUSB_ERROR_OTHER);
742194676Sthompsa
743194676Sthompsa	libusb20_tr_clear_stall_sync(xfer);
744195957Salfred
745195957Salfred	/* check if we opened the transfer */
746195957Salfred	if (err == 0) {
747195957Salfred		CTX_LOCK(dev->ctx);
748194676Sthompsa		libusb20_tr_close(xfer);
749195957Salfred		CTX_UNLOCK(dev->ctx);
750195957Salfred	}
751195957Salfred	return (0);			/* success */
752194676Sthompsa}
753194676Sthompsa
754194676Sthompsaint
755195957Salfredlibusb_reset_device(struct libusb20_device *pdev)
756194676Sthompsa{
757195957Salfred	libusb_device *dev;
758195957Salfred	int err;
759194676Sthompsa
760195957Salfred	dev = libusb_get_device(pdev);
761194676Sthompsa	if (dev == NULL)
762213853Shselasky		return (LIBUSB_ERROR_INVALID_PARAM);
763194676Sthompsa
764195957Salfred	libusb10_cancel_all_transfer(dev);
765195957Salfred
766195957Salfred	libusb10_remove_pollfd(dev->ctx, &dev->dev_poll);
767195957Salfred
768195957Salfred	err = libusb20_dev_reset(pdev);
769195957Salfred
770195957Salfred	libusb10_add_pollfd(dev->ctx, &dev->dev_poll,
771195957Salfred	    pdev, libusb20_dev_get_fd(pdev),
772195957Salfred	    POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM);
773195957Salfred
774195957Salfred	return (err ? LIBUSB_ERROR_OTHER : 0);
775194676Sthompsa}
776194676Sthompsa
777194676Sthompsaint
778213848Shselaskylibusb_check_connected(struct libusb20_device *pdev)
779213848Shselasky{
780213848Shselasky	libusb_device *dev;
781213848Shselasky	int err;
782213848Shselasky
783213848Shselasky	dev = libusb_get_device(pdev);
784213848Shselasky	if (dev == NULL)
785213848Shselasky		return (LIBUSB_ERROR_INVALID_PARAM);
786213848Shselasky
787213848Shselasky	err = libusb20_dev_check_connected(pdev);
788213848Shselasky
789213848Shselasky	return (err ? LIBUSB_ERROR_NO_DEVICE : 0);
790213848Shselasky}
791213848Shselasky
792213848Shselaskyint
793195957Salfredlibusb_kernel_driver_active(struct libusb20_device *pdev, int interface)
794194676Sthompsa{
795195957Salfred	if (pdev == NULL)
796194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
797194676Sthompsa
798226220Shselasky	if (libusb20_dev_kernel_driver_active(pdev, interface))
799226220Shselasky		return (0);		/* no kernel driver is active */
800226220Shselasky	else
801226220Shselasky		return (1);		/* kernel driver is active */
802194676Sthompsa}
803194676Sthompsa
804194676Sthompsaint
805213853Shselaskylibusb_get_driver_np(struct libusb20_device *pdev, int interface,
806213853Shselasky    char *name, int namelen)
807213853Shselasky{
808213853Shselasky	return (libusb_get_driver(pdev, interface, name, namelen));
809213853Shselasky}
810213853Shselasky
811213853Shselaskyint
812213853Shselaskylibusb_get_driver(struct libusb20_device *pdev, int interface,
813213853Shselasky    char *name, int namelen)
814213853Shselasky{
815213853Shselasky	char *ptr;
816213853Shselasky	int err;
817213853Shselasky
818213853Shselasky	if (pdev == NULL)
819213853Shselasky		return (LIBUSB_ERROR_INVALID_PARAM);
820213853Shselasky	if (namelen < 1)
821213853Shselasky		return (LIBUSB_ERROR_INVALID_PARAM);
822224085Shselasky	if (namelen > 255)
823224085Shselasky		namelen = 255;
824213853Shselasky
825213853Shselasky	err = libusb20_dev_get_iface_desc(
826213853Shselasky	    pdev, interface, name, namelen);
827213853Shselasky
828213853Shselasky	if (err != 0)
829213853Shselasky		return (LIBUSB_ERROR_OTHER);
830213853Shselasky
831213853Shselasky	/* we only want the driver name */
832213853Shselasky	ptr = strstr(name, ":");
833213853Shselasky	if (ptr != NULL)
834213853Shselasky		*ptr = 0;
835213853Shselasky
836213853Shselasky	return (0);
837213853Shselasky}
838213853Shselasky
839213853Shselaskyint
840213853Shselaskylibusb_detach_kernel_driver_np(struct libusb20_device *pdev, int interface)
841213853Shselasky{
842213853Shselasky	return (libusb_detach_kernel_driver(pdev, interface));
843213853Shselasky}
844213853Shselasky
845213853Shselaskyint
846195957Salfredlibusb_detach_kernel_driver(struct libusb20_device *pdev, int interface)
847194676Sthompsa{
848195957Salfred	int err;
849194676Sthompsa
850195957Salfred	if (pdev == NULL)
851194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
852194676Sthompsa
853195957Salfred	err = libusb20_dev_detach_kernel_driver(
854195957Salfred	    pdev, interface);
855194676Sthompsa
856213853Shselasky	return (err ? LIBUSB_ERROR_OTHER : 0);
857194676Sthompsa}
858194676Sthompsa
859194676Sthompsaint
860195957Salfredlibusb_attach_kernel_driver(struct libusb20_device *pdev, int interface)
861194676Sthompsa{
862195957Salfred	if (pdev == NULL)
863194676Sthompsa		return (LIBUSB_ERROR_INVALID_PARAM);
864195957Salfred	/* stub - currently not supported by libusb20 */
865194676Sthompsa	return (0);
866194676Sthompsa}
867194676Sthompsa
868194676Sthompsa/* Asynchronous device I/O */
869194676Sthompsa
870194676Sthompsastruct libusb_transfer *
871194676Sthompsalibusb_alloc_transfer(int iso_packets)
872194676Sthompsa{
873195957Salfred	struct libusb_transfer *uxfer;
874195957Salfred	struct libusb_super_transfer *sxfer;
875194676Sthompsa	int len;
876194676Sthompsa
877194676Sthompsa	len = sizeof(struct libusb_transfer) +
878195957Salfred	    sizeof(struct libusb_super_transfer) +
879194676Sthompsa	    (iso_packets * sizeof(libusb_iso_packet_descriptor));
880194676Sthompsa
881195957Salfred	sxfer = malloc(len);
882195957Salfred	if (sxfer == NULL)
883194676Sthompsa		return (NULL);
884194676Sthompsa
885195957Salfred	memset(sxfer, 0, len);
886194676Sthompsa
887195957Salfred	uxfer = (struct libusb_transfer *)(
888195957Salfred	    ((uint8_t *)sxfer) + sizeof(*sxfer));
889194676Sthompsa
890195957Salfred	/* set default value */
891195957Salfred	uxfer->num_iso_packets = iso_packets;
892195957Salfred
893195957Salfred	return (uxfer);
894194676Sthompsa}
895194676Sthompsa
896194676Sthompsavoid
897195957Salfredlibusb_free_transfer(struct libusb_transfer *uxfer)
898194676Sthompsa{
899195957Salfred	struct libusb_super_transfer *sxfer;
900194676Sthompsa
901195957Salfred	if (uxfer == NULL)
902195957Salfred		return;			/* be NULL safe */
903194676Sthompsa
904215253Shselasky	/* check if we should free the transfer buffer */
905215253Shselasky	if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER)
906215253Shselasky		free(uxfer->buffer);
907215253Shselasky
908195957Salfred	sxfer = (struct libusb_super_transfer *)(
909195957Salfred	    (uint8_t *)uxfer - sizeof(*sxfer));
910194676Sthompsa
911195957Salfred	free(sxfer);
912194676Sthompsa}
913194676Sthompsa
914219100Shselaskystatic uint32_t
915195957Salfredlibusb10_get_maxframe(struct libusb20_device *pdev, libusb_transfer *xfer)
916195560Sthompsa{
917219100Shselasky	uint32_t ret;
918195560Sthompsa
919195560Sthompsa	switch (xfer->type) {
920195560Sthompsa	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
921219100Shselasky		ret = 60 | LIBUSB20_MAX_FRAME_PRE_SCALE;	/* 60ms */
922195957Salfred		break;
923195560Sthompsa	case LIBUSB_TRANSFER_TYPE_CONTROL:
924195560Sthompsa		ret = 2;
925195957Salfred		break;
926195560Sthompsa	default:
927195560Sthompsa		ret = 1;
928195957Salfred		break;
929195560Sthompsa	}
930195957Salfred	return (ret);
931195560Sthompsa}
932195560Sthompsa
933195560Sthompsastatic int
934195957Salfredlibusb10_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer)
935195560Sthompsa{
936195560Sthompsa	int ret;
937195560Sthompsa	int usb_speed;
938195560Sthompsa
939195560Sthompsa	usb_speed = libusb20_dev_get_speed(pdev);
940195560Sthompsa
941195560Sthompsa	switch (xfer->type) {
942195560Sthompsa	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
943195957Salfred		ret = 0;		/* kernel will auto-select */
944195957Salfred		break;
945195560Sthompsa	case LIBUSB_TRANSFER_TYPE_CONTROL:
946195957Salfred		ret = 1024;
947195957Salfred		break;
948195957Salfred	default:
949195560Sthompsa		switch (usb_speed) {
950195957Salfred		case LIBUSB20_SPEED_LOW:
951195957Salfred			ret = 256;
952195957Salfred			break;
953195957Salfred		case LIBUSB20_SPEED_FULL:
954195957Salfred			ret = 4096;
955195957Salfred			break;
956264344Shselasky		case LIBUSB20_SPEED_SUPER:
957264344Shselasky			ret = 65536;
958264344Shselasky			break;
959195957Salfred		default:
960195957Salfred			ret = 16384;
961195957Salfred			break;
962195560Sthompsa		}
963195957Salfred		break;
964195560Sthompsa	}
965195957Salfred	return (ret);
966195560Sthompsa}
967195560Sthompsa
968195957Salfredstatic int
969195957Salfredlibusb10_convert_error(uint8_t status)
970195957Salfred{
971195957Salfred	;				/* indent fix */
972195957Salfred
973195957Salfred	switch (status) {
974195957Salfred	case LIBUSB20_TRANSFER_START:
975195957Salfred	case LIBUSB20_TRANSFER_COMPLETED:
976195957Salfred		return (LIBUSB_TRANSFER_COMPLETED);
977195957Salfred	case LIBUSB20_TRANSFER_OVERFLOW:
978195957Salfred		return (LIBUSB_TRANSFER_OVERFLOW);
979195957Salfred	case LIBUSB20_TRANSFER_NO_DEVICE:
980195957Salfred		return (LIBUSB_TRANSFER_NO_DEVICE);
981195957Salfred	case LIBUSB20_TRANSFER_STALL:
982195957Salfred		return (LIBUSB_TRANSFER_STALL);
983195957Salfred	case LIBUSB20_TRANSFER_CANCELLED:
984195957Salfred		return (LIBUSB_TRANSFER_CANCELLED);
985195957Salfred	case LIBUSB20_TRANSFER_TIMED_OUT:
986195957Salfred		return (LIBUSB_TRANSFER_TIMED_OUT);
987195957Salfred	default:
988195957Salfred		return (LIBUSB_TRANSFER_ERROR);
989195957Salfred	}
990195957Salfred}
991195957Salfred
992195957Salfred/* This function must be called locked */
993195957Salfred
994194676Sthompsastatic void
995195957Salfredlibusb10_complete_transfer(struct libusb20_transfer *pxfer,
996195957Salfred    struct libusb_super_transfer *sxfer, int status)
997194676Sthompsa{
998195957Salfred	struct libusb_transfer *uxfer;
999195957Salfred	struct libusb_device *dev;
1000195957Salfred
1001195957Salfred	uxfer = (struct libusb_transfer *)(
1002195957Salfred	    ((uint8_t *)sxfer) + sizeof(*sxfer));
1003195957Salfred
1004195957Salfred	if (pxfer != NULL)
1005195957Salfred		libusb20_tr_set_priv_sc1(pxfer, NULL);
1006195957Salfred
1007199575Sthompsa	/* set transfer status */
1008195957Salfred	uxfer->status = status;
1009195957Salfred
1010199575Sthompsa	/* update super transfer state */
1011199575Sthompsa	sxfer->state = LIBUSB_SUPER_XFER_ST_NONE;
1012199575Sthompsa
1013195957Salfred	dev = libusb_get_device(uxfer->dev_handle);
1014195957Salfred
1015195957Salfred	TAILQ_INSERT_TAIL(&dev->ctx->tr_done, sxfer, entry);
1016195957Salfred}
1017195957Salfred
1018195957Salfred/* This function must be called locked */
1019195957Salfred
1020195957Salfredstatic void
1021195957Salfredlibusb10_isoc_proxy(struct libusb20_transfer *pxfer)
1022195957Salfred{
1023195957Salfred	struct libusb_super_transfer *sxfer;
1024195957Salfred	struct libusb_transfer *uxfer;
1025195957Salfred	uint32_t actlen;
1026195957Salfred	uint16_t iso_packets;
1027195957Salfred	uint16_t i;
1028194676Sthompsa	uint8_t status;
1029194676Sthompsa
1030195957Salfred	status = libusb20_tr_get_status(pxfer);
1031195957Salfred	sxfer = libusb20_tr_get_priv_sc1(pxfer);
1032195957Salfred	actlen = libusb20_tr_get_actual_length(pxfer);
1033195957Salfred	iso_packets = libusb20_tr_get_max_frames(pxfer);
1034194676Sthompsa
1035195957Salfred	if (sxfer == NULL)
1036284744Saraujo		return; /* cancelled - nothing to do */
1037195957Salfred
1038195957Salfred	uxfer = (struct libusb_transfer *)(
1039195957Salfred	    ((uint8_t *)sxfer) + sizeof(*sxfer));
1040195957Salfred
1041195957Salfred	if (iso_packets > uxfer->num_iso_packets)
1042195957Salfred		iso_packets = uxfer->num_iso_packets;
1043195957Salfred
1044195957Salfred	if (iso_packets == 0)
1045284744Saraujo		return; /* nothing to do */
1046195957Salfred
1047195957Salfred	/* make sure that the number of ISOCHRONOUS packets is valid */
1048195957Salfred	uxfer->num_iso_packets = iso_packets;
1049195957Salfred
1050194676Sthompsa	switch (status) {
1051194676Sthompsa	case LIBUSB20_TRANSFER_COMPLETED:
1052195957Salfred		/* update actual length */
1053195957Salfred		uxfer->actual_length = actlen;
1054195957Salfred		for (i = 0; i != iso_packets; i++) {
1055195957Salfred			uxfer->iso_packet_desc[i].actual_length =
1056195957Salfred			    libusb20_tr_get_length(pxfer, i);
1057195957Salfred		}
1058195957Salfred		libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED);
1059195957Salfred		break;
1060194676Sthompsa	case LIBUSB20_TRANSFER_START:
1061195957Salfred		/* setup length(s) */
1062195957Salfred		actlen = 0;
1063195957Salfred		for (i = 0; i != iso_packets; i++) {
1064195957Salfred			libusb20_tr_setup_isoc(pxfer,
1065195957Salfred			    &uxfer->buffer[actlen],
1066195957Salfred			    uxfer->iso_packet_desc[i].length, i);
1067195957Salfred			actlen += uxfer->iso_packet_desc[i].length;
1068194676Sthompsa		}
1069195957Salfred
1070195957Salfred		/* no remainder */
1071195957Salfred		sxfer->rem_len = 0;
1072195957Salfred
1073195957Salfred		libusb20_tr_set_total_frames(pxfer, iso_packets);
1074195957Salfred		libusb20_tr_submit(pxfer);
1075195957Salfred
1076195957Salfred		/* fork another USB transfer, if any */
1077195957Salfred		libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint);
1078195957Salfred		break;
1079194676Sthompsa	default:
1080195957Salfred		libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status));
1081195957Salfred		break;
1082194676Sthompsa	}
1083195957Salfred}
1084194676Sthompsa
1085195957Salfred/* This function must be called locked */
1086195957Salfred
1087195957Salfredstatic void
1088195957Salfredlibusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer)
1089195957Salfred{
1090195957Salfred	struct libusb_super_transfer *sxfer;
1091195957Salfred	struct libusb_transfer *uxfer;
1092195957Salfred	uint32_t max_bulk;
1093195957Salfred	uint32_t actlen;
1094195957Salfred	uint8_t status;
1095195957Salfred	uint8_t flags;
1096195957Salfred
1097195957Salfred	status = libusb20_tr_get_status(pxfer);
1098195957Salfred	sxfer = libusb20_tr_get_priv_sc1(pxfer);
1099195957Salfred	max_bulk = libusb20_tr_get_max_total_length(pxfer);
1100195957Salfred	actlen = libusb20_tr_get_actual_length(pxfer);
1101195957Salfred
1102195957Salfred	if (sxfer == NULL)
1103195957Salfred		return;			/* cancelled - nothing to do */
1104195957Salfred
1105195957Salfred	uxfer = (struct libusb_transfer *)(
1106195957Salfred	    ((uint8_t *)sxfer) + sizeof(*sxfer));
1107195957Salfred
1108195957Salfred	flags = uxfer->flags;
1109195957Salfred
1110194676Sthompsa	switch (status) {
1111194676Sthompsa	case LIBUSB20_TRANSFER_COMPLETED:
1112195957Salfred
1113195957Salfred		uxfer->actual_length += actlen;
1114195957Salfred
1115195957Salfred		/* check for short packet */
1116195957Salfred		if (sxfer->last_len != actlen) {
1117195957Salfred			if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) {
1118195957Salfred				libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR);
1119195957Salfred			} else {
1120195957Salfred				libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED);
1121195957Salfred			}
1122195957Salfred			break;
1123195957Salfred		}
1124195957Salfred		/* check for end of data */
1125195957Salfred		if (sxfer->rem_len == 0) {
1126195957Salfred			libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED);
1127195957Salfred			break;
1128195957Salfred		}
1129195957Salfred		/* FALLTHROUGH */
1130195957Salfred
1131195957Salfred	case LIBUSB20_TRANSFER_START:
1132195957Salfred		if (max_bulk > sxfer->rem_len) {
1133195957Salfred			max_bulk = sxfer->rem_len;
1134195957Salfred		}
1135195957Salfred		/* setup new BULK or INTERRUPT transaction */
1136195957Salfred		libusb20_tr_setup_bulk(pxfer,
1137195957Salfred		    sxfer->curr_data, max_bulk, uxfer->timeout);
1138195957Salfred
1139195957Salfred		/* update counters */
1140195957Salfred		sxfer->last_len = max_bulk;
1141195957Salfred		sxfer->curr_data += max_bulk;
1142195957Salfred		sxfer->rem_len -= max_bulk;
1143195957Salfred
1144195957Salfred		libusb20_tr_submit(pxfer);
1145195957Salfred
1146195957Salfred		/* check if we can fork another USB transfer */
1147195957Salfred		if (sxfer->rem_len == 0)
1148195957Salfred			libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint);
1149195957Salfred		break;
1150195957Salfred
1151195957Salfred	default:
1152195957Salfred		libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status));
1153195957Salfred		break;
1154194676Sthompsa	}
1155194676Sthompsa}
1156194676Sthompsa
1157195957Salfred/* This function must be called locked */
1158195957Salfred
1159195957Salfredstatic void
1160195957Salfredlibusb10_ctrl_proxy(struct libusb20_transfer *pxfer)
1161194676Sthompsa{
1162195957Salfred	struct libusb_super_transfer *sxfer;
1163195957Salfred	struct libusb_transfer *uxfer;
1164195957Salfred	uint32_t max_bulk;
1165195957Salfred	uint32_t actlen;
1166195957Salfred	uint8_t status;
1167195957Salfred	uint8_t flags;
1168194676Sthompsa
1169195957Salfred	status = libusb20_tr_get_status(pxfer);
1170195957Salfred	sxfer = libusb20_tr_get_priv_sc1(pxfer);
1171195957Salfred	max_bulk = libusb20_tr_get_max_total_length(pxfer);
1172195957Salfred	actlen = libusb20_tr_get_actual_length(pxfer);
1173194676Sthompsa
1174195957Salfred	if (sxfer == NULL)
1175195957Salfred		return;			/* cancelled - nothing to do */
1176194676Sthompsa
1177195957Salfred	uxfer = (struct libusb_transfer *)(
1178195957Salfred	    ((uint8_t *)sxfer) + sizeof(*sxfer));
1179194676Sthompsa
1180195957Salfred	flags = uxfer->flags;
1181194676Sthompsa
1182195957Salfred	switch (status) {
1183195957Salfred	case LIBUSB20_TRANSFER_COMPLETED:
1184194676Sthompsa
1185195957Salfred		uxfer->actual_length += actlen;
1186195957Salfred
1187195957Salfred		/* subtract length of SETUP packet, if any */
1188195957Salfred		actlen -= libusb20_tr_get_length(pxfer, 0);
1189195957Salfred
1190195957Salfred		/* check for short packet */
1191195957Salfred		if (sxfer->last_len != actlen) {
1192195957Salfred			if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) {
1193195957Salfred				libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR);
1194195957Salfred			} else {
1195195957Salfred				libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED);
1196195957Salfred			}
1197195957Salfred			break;
1198194676Sthompsa		}
1199195957Salfred		/* check for end of data */
1200195957Salfred		if (sxfer->rem_len == 0) {
1201195957Salfred			libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED);
1202195957Salfred			break;
1203195957Salfred		}
1204195957Salfred		/* FALLTHROUGH */
1205194676Sthompsa
1206195957Salfred	case LIBUSB20_TRANSFER_START:
1207195957Salfred		if (max_bulk > sxfer->rem_len) {
1208195957Salfred			max_bulk = sxfer->rem_len;
1209195957Salfred		}
1210195957Salfred		/* setup new CONTROL transaction */
1211195957Salfred		if (status == LIBUSB20_TRANSFER_COMPLETED) {
1212195957Salfred			/* next fragment - don't send SETUP packet */
1213195957Salfred			libusb20_tr_set_length(pxfer, 0, 0);
1214195957Salfred		} else {
1215195957Salfred			/* first fragment - send SETUP packet */
1216195957Salfred			libusb20_tr_set_length(pxfer, 8, 0);
1217195957Salfred			libusb20_tr_set_buffer(pxfer, uxfer->buffer, 0);
1218195957Salfred		}
1219195957Salfred
1220195957Salfred		if (max_bulk != 0) {
1221195957Salfred			libusb20_tr_set_length(pxfer, max_bulk, 1);
1222195957Salfred			libusb20_tr_set_buffer(pxfer, sxfer->curr_data, 1);
1223195957Salfred			libusb20_tr_set_total_frames(pxfer, 2);
1224195957Salfred		} else {
1225195957Salfred			libusb20_tr_set_total_frames(pxfer, 1);
1226195957Salfred		}
1227195957Salfred
1228195957Salfred		/* update counters */
1229195957Salfred		sxfer->last_len = max_bulk;
1230195957Salfred		sxfer->curr_data += max_bulk;
1231195957Salfred		sxfer->rem_len -= max_bulk;
1232195957Salfred
1233195957Salfred		libusb20_tr_submit(pxfer);
1234195957Salfred
1235195957Salfred		/* check if we can fork another USB transfer */
1236195957Salfred		if (sxfer->rem_len == 0)
1237195957Salfred			libusb10_submit_transfer_sub(libusb20_tr_get_priv_sc0(pxfer), uxfer->endpoint);
1238195957Salfred		break;
1239195957Salfred
1240195957Salfred	default:
1241195957Salfred		libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status));
1242195957Salfred		break;
1243194676Sthompsa	}
1244195957Salfred}
1245195957Salfred
1246195957Salfred/* The following function must be called locked */
1247195957Salfred
1248195957Salfredstatic void
1249195957Salfredlibusb10_submit_transfer_sub(struct libusb20_device *pdev, uint8_t endpoint)
1250195957Salfred{
1251195957Salfred	struct libusb20_transfer *pxfer0;
1252195957Salfred	struct libusb20_transfer *pxfer1;
1253195957Salfred	struct libusb_super_transfer *sxfer;
1254195957Salfred	struct libusb_transfer *uxfer;
1255195957Salfred	struct libusb_device *dev;
1256195957Salfred	int err;
1257195957Salfred	int buffsize;
1258195957Salfred	int maxframe;
1259195957Salfred	int temp;
1260195957Salfred	uint8_t dummy;
1261195957Salfred
1262195957Salfred	dev = libusb_get_device(pdev);
1263195957Salfred
1264195957Salfred	pxfer0 = libusb10_get_transfer(pdev, endpoint, 0);
1265195957Salfred	pxfer1 = libusb10_get_transfer(pdev, endpoint, 1);
1266195957Salfred
1267195957Salfred	if (pxfer0 == NULL || pxfer1 == NULL)
1268195957Salfred		return;			/* shouldn't happen */
1269195957Salfred
1270195957Salfred	temp = 0;
1271195957Salfred	if (libusb20_tr_pending(pxfer0))
1272195957Salfred		temp |= 1;
1273195957Salfred	if (libusb20_tr_pending(pxfer1))
1274195957Salfred		temp |= 2;
1275195957Salfred
1276195957Salfred	switch (temp) {
1277195957Salfred	case 3:
1278195957Salfred		/* wait till one of the transfers complete */
1279195957Salfred		return;
1280195957Salfred	case 2:
1281195957Salfred		sxfer = libusb20_tr_get_priv_sc1(pxfer1);
1282199575Sthompsa		if (sxfer == NULL)
1283199575Sthompsa			return;		/* cancelling */
1284195957Salfred		if (sxfer->rem_len)
1285195957Salfred			return;		/* cannot queue another one */
1286195957Salfred		/* swap transfers */
1287195957Salfred		pxfer1 = pxfer0;
1288195957Salfred		break;
1289195957Salfred	case 1:
1290195957Salfred		sxfer = libusb20_tr_get_priv_sc1(pxfer0);
1291199575Sthompsa		if (sxfer == NULL)
1292199575Sthompsa			return;		/* cancelling */
1293195957Salfred		if (sxfer->rem_len)
1294195957Salfred			return;		/* cannot queue another one */
1295195957Salfred		/* swap transfers */
1296195957Salfred		pxfer0 = pxfer1;
1297195957Salfred		break;
1298195957Salfred	default:
1299195957Salfred		break;
1300194676Sthompsa	}
1301195957Salfred
1302195957Salfred	/* find next transfer on same endpoint */
1303195957Salfred	TAILQ_FOREACH(sxfer, &dev->tr_head, entry) {
1304195957Salfred
1305195957Salfred		uxfer = (struct libusb_transfer *)(
1306195957Salfred		    ((uint8_t *)sxfer) + sizeof(*sxfer));
1307195957Salfred
1308195957Salfred		if (uxfer->endpoint == endpoint) {
1309195957Salfred			TAILQ_REMOVE(&dev->tr_head, sxfer, entry);
1310195957Salfred			sxfer->entry.tqe_prev = NULL;
1311195957Salfred			goto found;
1312194676Sthompsa		}
1313195957Salfred	}
1314195957Salfred	return;				/* success */
1315194676Sthompsa
1316195957Salfredfound:
1317194676Sthompsa
1318195957Salfred	libusb20_tr_set_priv_sc0(pxfer0, pdev);
1319195957Salfred	libusb20_tr_set_priv_sc1(pxfer0, sxfer);
1320194676Sthompsa
1321195957Salfred	/* reset super transfer state */
1322195957Salfred	sxfer->rem_len = uxfer->length;
1323195957Salfred	sxfer->curr_data = uxfer->buffer;
1324195957Salfred	uxfer->actual_length = 0;
1325194676Sthompsa
1326195957Salfred	switch (uxfer->type) {
1327195957Salfred	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
1328195957Salfred		libusb20_tr_set_callback(pxfer0, libusb10_isoc_proxy);
1329195957Salfred		break;
1330195957Salfred	case LIBUSB_TRANSFER_TYPE_BULK:
1331195957Salfred	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
1332195957Salfred		libusb20_tr_set_callback(pxfer0, libusb10_bulk_intr_proxy);
1333195957Salfred		break;
1334195957Salfred	case LIBUSB_TRANSFER_TYPE_CONTROL:
1335195957Salfred		libusb20_tr_set_callback(pxfer0, libusb10_ctrl_proxy);
1336195957Salfred		if (sxfer->rem_len < 8)
1337195957Salfred			goto failure;
1338194676Sthompsa
1339195957Salfred		/* remove SETUP packet from data */
1340195957Salfred		sxfer->rem_len -= 8;
1341195957Salfred		sxfer->curr_data += 8;
1342195957Salfred		break;
1343195957Salfred	default:
1344195957Salfred		goto failure;
1345195560Sthompsa	}
1346195957Salfred
1347195957Salfred	buffsize = libusb10_get_buffsize(pdev, uxfer);
1348195957Salfred	maxframe = libusb10_get_maxframe(pdev, uxfer);
1349195957Salfred
1350195957Salfred	/* make sure the transfer is opened */
1351195957Salfred	err = libusb20_tr_open(pxfer0, buffsize, maxframe, endpoint);
1352195957Salfred	if (err && (err != LIBUSB20_ERROR_BUSY)) {
1353195957Salfred		goto failure;
1354194676Sthompsa	}
1355195957Salfred	libusb20_tr_start(pxfer0);
1356195957Salfred	return;
1357194676Sthompsa
1358195957Salfredfailure:
1359195957Salfred	libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR);
1360194676Sthompsa
1361195957Salfred	/* make sure our event loop spins the done handler */
1362195957Salfred	dummy = 0;
1363248236Shselasky	err = write(dev->ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
1364195957Salfred}
1365194676Sthompsa
1366195957Salfred/* The following function must be called unlocked */
1367194676Sthompsa
1368195957Salfredint
1369195957Salfredlibusb_submit_transfer(struct libusb_transfer *uxfer)
1370195957Salfred{
1371195957Salfred	struct libusb20_transfer *pxfer0;
1372195957Salfred	struct libusb20_transfer *pxfer1;
1373195957Salfred	struct libusb_super_transfer *sxfer;
1374195957Salfred	struct libusb_device *dev;
1375234684Shselasky	uint8_t endpoint;
1376195957Salfred	int err;
1377195957Salfred
1378195957Salfred	if (uxfer == NULL)
1379195957Salfred		return (LIBUSB_ERROR_INVALID_PARAM);
1380195957Salfred
1381195957Salfred	if (uxfer->dev_handle == NULL)
1382195957Salfred		return (LIBUSB_ERROR_INVALID_PARAM);
1383195957Salfred
1384195957Salfred	endpoint = uxfer->endpoint;
1385195957Salfred
1386195957Salfred	dev = libusb_get_device(uxfer->dev_handle);
1387195957Salfred
1388195957Salfred	DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer enter");
1389195957Salfred
1390195957Salfred	sxfer = (struct libusb_super_transfer *)(
1391195957Salfred	    (uint8_t *)uxfer - sizeof(*sxfer));
1392195957Salfred
1393195957Salfred	CTX_LOCK(dev->ctx);
1394195957Salfred
1395195957Salfred	pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0);
1396195957Salfred	pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1);
1397195957Salfred
1398195957Salfred	if (pxfer0 == NULL || pxfer1 == NULL) {
1399195957Salfred		err = LIBUSB_ERROR_OTHER;
1400195957Salfred	} else if ((sxfer->entry.tqe_prev != NULL) ||
1401199575Sthompsa	    (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) ||
1402195957Salfred	    (libusb20_tr_get_priv_sc1(pxfer1) == sxfer)) {
1403195957Salfred		err = LIBUSB_ERROR_BUSY;
1404195957Salfred	} else {
1405199575Sthompsa
1406199575Sthompsa		/* set pending state */
1407199575Sthompsa		sxfer->state = LIBUSB_SUPER_XFER_ST_PEND;
1408199575Sthompsa
1409199575Sthompsa		/* insert transfer into transfer head list */
1410195957Salfred		TAILQ_INSERT_TAIL(&dev->tr_head, sxfer, entry);
1411195957Salfred
1412199575Sthompsa		/* start work transfers */
1413195957Salfred		libusb10_submit_transfer_sub(
1414195957Salfred		    uxfer->dev_handle, endpoint);
1415195957Salfred
1416195957Salfred		err = 0;		/* success */
1417195957Salfred	}
1418195957Salfred
1419195957Salfred	CTX_UNLOCK(dev->ctx);
1420195957Salfred
1421195957Salfred	DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer leave %d", err);
1422195957Salfred
1423195957Salfred	return (err);
1424194676Sthompsa}
1425194676Sthompsa
1426195957Salfred/* Asynchronous transfer cancel */
1427195957Salfred
1428194676Sthompsaint
1429195957Salfredlibusb_cancel_transfer(struct libusb_transfer *uxfer)
1430194676Sthompsa{
1431195957Salfred	struct libusb20_transfer *pxfer0;
1432195957Salfred	struct libusb20_transfer *pxfer1;
1433195957Salfred	struct libusb_super_transfer *sxfer;
1434195957Salfred	struct libusb_device *dev;
1435234684Shselasky	uint8_t endpoint;
1436199575Sthompsa	int retval;
1437194676Sthompsa
1438195957Salfred	if (uxfer == NULL)
1439195957Salfred		return (LIBUSB_ERROR_INVALID_PARAM);
1440194676Sthompsa
1441199575Sthompsa	/* check if not initialised */
1442195957Salfred	if (uxfer->dev_handle == NULL)
1443199575Sthompsa		return (LIBUSB_ERROR_NOT_FOUND);
1444194676Sthompsa
1445195957Salfred	endpoint = uxfer->endpoint;
1446194676Sthompsa
1447195957Salfred	dev = libusb_get_device(uxfer->dev_handle);
1448195957Salfred
1449195957Salfred	DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter");
1450195957Salfred
1451195957Salfred	sxfer = (struct libusb_super_transfer *)(
1452195957Salfred	    (uint8_t *)uxfer - sizeof(*sxfer));
1453195957Salfred
1454199575Sthompsa	retval = 0;
1455199575Sthompsa
1456195957Salfred	CTX_LOCK(dev->ctx);
1457195957Salfred
1458195957Salfred	pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0);
1459195957Salfred	pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1);
1460195957Salfred
1461199575Sthompsa	if (sxfer->state != LIBUSB_SUPER_XFER_ST_PEND) {
1462199575Sthompsa		/* only update the transfer status */
1463199575Sthompsa		uxfer->status = LIBUSB_TRANSFER_CANCELLED;
1464199575Sthompsa		retval = LIBUSB_ERROR_NOT_FOUND;
1465199575Sthompsa	} else if (sxfer->entry.tqe_prev != NULL) {
1466195957Salfred		/* we are lucky - transfer is on a queue */
1467195957Salfred		TAILQ_REMOVE(&dev->tr_head, sxfer, entry);
1468195957Salfred		sxfer->entry.tqe_prev = NULL;
1469199575Sthompsa		libusb10_complete_transfer(NULL,
1470199575Sthompsa		    sxfer, LIBUSB_TRANSFER_CANCELLED);
1471195957Salfred	} else if (pxfer0 == NULL || pxfer1 == NULL) {
1472195957Salfred		/* not started */
1473199575Sthompsa		retval = LIBUSB_ERROR_NOT_FOUND;
1474195957Salfred	} else if (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) {
1475199575Sthompsa		libusb10_complete_transfer(pxfer0,
1476199575Sthompsa		    sxfer, LIBUSB_TRANSFER_CANCELLED);
1477195957Salfred		libusb20_tr_stop(pxfer0);
1478195957Salfred		/* make sure the queue doesn't stall */
1479195957Salfred		libusb10_submit_transfer_sub(
1480195957Salfred		    uxfer->dev_handle, endpoint);
1481195957Salfred	} else if (libusb20_tr_get_priv_sc1(pxfer1) == sxfer) {
1482199575Sthompsa		libusb10_complete_transfer(pxfer1,
1483199575Sthompsa		    sxfer, LIBUSB_TRANSFER_CANCELLED);
1484195957Salfred		libusb20_tr_stop(pxfer1);
1485195957Salfred		/* make sure the queue doesn't stall */
1486195957Salfred		libusb10_submit_transfer_sub(
1487195957Salfred		    uxfer->dev_handle, endpoint);
1488195957Salfred	} else {
1489195957Salfred		/* not started */
1490199575Sthompsa		retval = LIBUSB_ERROR_NOT_FOUND;
1491195957Salfred	}
1492195957Salfred
1493195957Salfred	CTX_UNLOCK(dev->ctx);
1494195957Salfred
1495195957Salfred	DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave");
1496195957Salfred
1497199575Sthompsa	return (retval);
1498194676Sthompsa}
1499194676Sthompsa
1500195957SalfredUNEXPORTED void
1501195957Salfredlibusb10_cancel_all_transfer(libusb_device *dev)
1502195957Salfred{
1503301842Shselasky	struct libusb20_device *pdev = dev->os_priv;
1504301842Shselasky	unsigned x;
1505301842Shselasky
1506301842Shselasky	for (x = 0; x != LIBUSB_NUM_SW_ENDPOINTS; x++) {
1507301842Shselasky		struct libusb20_transfer *xfer;
1508301842Shselasky
1509301842Shselasky		xfer = libusb20_tr_get_pointer(pdev, x);
1510301842Shselasky		if (xfer == NULL)
1511301842Shselasky			continue;
1512301842Shselasky		libusb20_tr_close(xfer);
1513301842Shselasky	}
1514195957Salfred}
1515199055Sthompsa
1516199055Sthompsauint16_t
1517199055Sthompsalibusb_cpu_to_le16(uint16_t x)
1518199055Sthompsa{
1519199055Sthompsa	return (htole16(x));
1520199055Sthompsa}
1521199055Sthompsa
1522199055Sthompsauint16_t
1523199055Sthompsalibusb_le16_to_cpu(uint16_t x)
1524199055Sthompsa{
1525199055Sthompsa	return (le16toh(x));
1526199055Sthompsa}
1527199055Sthompsa
1528213853Shselaskyconst char *
1529213853Shselaskylibusb_strerror(int code)
1530213853Shselasky{
1531225659Shselasky	switch (code) {
1532225659Shselasky	case LIBUSB_SUCCESS:
1533225659Shselasky		return ("Success");
1534225659Shselasky	case LIBUSB_ERROR_IO:
1535225659Shselasky		return ("I/O error");
1536225659Shselasky	case LIBUSB_ERROR_INVALID_PARAM:
1537225659Shselasky		return ("Invalid parameter");
1538225659Shselasky	case LIBUSB_ERROR_ACCESS:
1539225659Shselasky		return ("Permissions error");
1540225659Shselasky	case LIBUSB_ERROR_NO_DEVICE:
1541225659Shselasky		return ("No device");
1542225659Shselasky	case LIBUSB_ERROR_NOT_FOUND:
1543225659Shselasky		return ("Not found");
1544225659Shselasky	case LIBUSB_ERROR_BUSY:
1545225659Shselasky		return ("Device busy");
1546225659Shselasky	case LIBUSB_ERROR_TIMEOUT:
1547225659Shselasky		return ("Timeout");
1548225659Shselasky	case LIBUSB_ERROR_OVERFLOW:
1549225659Shselasky		return ("Overflow");
1550225659Shselasky	case LIBUSB_ERROR_PIPE:
1551225659Shselasky		return ("Pipe error");
1552225659Shselasky	case LIBUSB_ERROR_INTERRUPTED:
1553225659Shselasky		return ("Interrupted");
1554225659Shselasky	case LIBUSB_ERROR_NO_MEM:
1555225659Shselasky		return ("Out of memory");
1556225659Shselasky	case LIBUSB_ERROR_NOT_SUPPORTED:
1557225659Shselasky		return ("Not supported");
1558225659Shselasky	case LIBUSB_ERROR_OTHER:
1559225659Shselasky		return ("Other error");
1560225659Shselasky	default:
1561225659Shselasky		return ("Unknown error");
1562225659Shselasky	}
1563213853Shselasky}
1564225659Shselasky
1565225659Shselaskyconst char *
1566225659Shselaskylibusb_error_name(int code)
1567225659Shselasky{
1568225659Shselasky	switch (code) {
1569225659Shselasky	case LIBUSB_SUCCESS:
1570225659Shselasky		return ("LIBUSB_SUCCESS");
1571225659Shselasky	case LIBUSB_ERROR_IO:
1572225659Shselasky		return ("LIBUSB_ERROR_IO");
1573225659Shselasky	case LIBUSB_ERROR_INVALID_PARAM:
1574225659Shselasky		return ("LIBUSB_ERROR_INVALID_PARAM");
1575225659Shselasky	case LIBUSB_ERROR_ACCESS:
1576225659Shselasky		return ("LIBUSB_ERROR_ACCESS");
1577225659Shselasky	case LIBUSB_ERROR_NO_DEVICE:
1578225659Shselasky		return ("LIBUSB_ERROR_NO_DEVICE");
1579225659Shselasky	case LIBUSB_ERROR_NOT_FOUND:
1580225659Shselasky		return ("LIBUSB_ERROR_NOT_FOUND");
1581225659Shselasky	case LIBUSB_ERROR_BUSY:
1582225659Shselasky		return ("LIBUSB_ERROR_BUSY");
1583225659Shselasky	case LIBUSB_ERROR_TIMEOUT:
1584225659Shselasky		return ("LIBUSB_ERROR_TIMEOUT");
1585225659Shselasky	case LIBUSB_ERROR_OVERFLOW:
1586225659Shselasky		return ("LIBUSB_ERROR_OVERFLOW");
1587225659Shselasky	case LIBUSB_ERROR_PIPE:
1588225659Shselasky		return ("LIBUSB_ERROR_PIPE");
1589225659Shselasky	case LIBUSB_ERROR_INTERRUPTED:
1590225659Shselasky		return ("LIBUSB_ERROR_INTERRUPTED");
1591225659Shselasky	case LIBUSB_ERROR_NO_MEM:
1592225659Shselasky		return ("LIBUSB_ERROR_NO_MEM");
1593225659Shselasky	case LIBUSB_ERROR_NOT_SUPPORTED:
1594225659Shselasky		return ("LIBUSB_ERROR_NOT_SUPPORTED");
1595225659Shselasky	case LIBUSB_ERROR_OTHER:
1596225659Shselasky		return ("LIBUSB_ERROR_OTHER");
1597225659Shselasky	default:
1598225659Shselasky		return ("LIBUSB_ERROR_UNKNOWN");
1599225659Shselasky	}
1600225659Shselasky}
1601