libusb10.c revision 194676
1/* $FreeBSD: head/lib/libusb/libusb10.c 194676 2009-06-23 01:04:58Z thompsa $ */
2/*-
3 * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/queue.h>
28#include <stdlib.h>
29#include <unistd.h>
30#include <stdio.h>
31#include <poll.h>
32#include <pthread.h>
33#include <time.h>
34#include <errno.h>
35
36#include "libusb20.h"
37#include "libusb20_desc.h"
38#include "libusb20_int.h"
39#include "libusb.h"
40#include "libusb10.h"
41
42static pthread_mutex_t default_context_lock = PTHREAD_MUTEX_INITIALIZER;
43struct libusb_context *usbi_default_context = NULL;
44pthread_mutex_t libusb20_lock = PTHREAD_MUTEX_INITIALIZER;
45
46/*  Library initialisation / deinitialisation */
47
48void
49libusb_set_debug(libusb_context * ctx, int level)
50{
51	GET_CONTEXT(ctx);
52	if (ctx)
53		ctx->debug = level;
54}
55
56int
57libusb_init(libusb_context ** context)
58{
59	struct libusb_context *ctx;
60	char * debug;
61	int ret;
62
63	ctx = malloc(sizeof(*ctx));
64	if (!ctx)
65		return (LIBUSB_ERROR_INVALID_PARAM);
66
67	memset(ctx, 0, sizeof(*ctx));
68
69	debug = getenv("LIBUSB_DEBUG");
70	if (debug != NULL) {
71		ctx->debug = atoi(debug);
72		if (ctx->debug != 0)
73			ctx->debug_fixed = 1;
74	}
75
76	pthread_mutex_init(&ctx->usb_devs_lock, NULL);
77	pthread_mutex_init(&ctx->open_devs_lock, NULL);
78	USB_LIST_INIT(&ctx->usb_devs);
79	USB_LIST_INIT(&ctx->open_devs);
80
81	pthread_mutex_init(&ctx->flying_transfers_lock, NULL);
82	pthread_mutex_init(&ctx->pollfds_lock, NULL);
83	pthread_mutex_init(&ctx->pollfd_modify_lock, NULL);
84	pthread_mutex_init(&ctx->events_lock, NULL);
85	pthread_mutex_init(&ctx->event_waiters_lock, NULL);
86	pthread_cond_init(&ctx->event_waiters_cond, NULL);
87
88	USB_LIST_INIT(&ctx->flying_transfers);
89	USB_LIST_INIT(&ctx->pollfds);
90
91	ret = pipe(ctx->ctrl_pipe);
92	if (ret < 0) {
93		usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
94		close(ctx->ctrl_pipe[0]);
95		close(ctx->ctrl_pipe[1]);
96		free(ctx);
97		return (LIBUSB_ERROR_OTHER);
98	}
99
100	ret = usb_add_pollfd(ctx, ctx->ctrl_pipe[0], POLLIN);
101	if (ret < 0) {
102		usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
103		close(ctx->ctrl_pipe[0]);
104		close(ctx->ctrl_pipe[1]);
105		free(ctx);
106		return ret;
107	}
108
109	pthread_mutex_lock(&default_context_lock);
110	if (usbi_default_context == NULL) {
111		usbi_default_context = ctx;
112	}
113	pthread_mutex_unlock(&default_context_lock);
114
115	if (context)
116		*context = ctx;
117
118	return (0);
119}
120
121void
122libusb_exit(libusb_context * ctx)
123{
124	GET_CONTEXT(ctx);
125
126	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_exit enter");
127	usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
128	close(ctx->ctrl_pipe[0]);
129	close(ctx->ctrl_pipe[1]);
130
131	pthread_mutex_lock(&default_context_lock);
132	if (ctx == usbi_default_context) {
133		usbi_default_context = NULL;
134	}
135	pthread_mutex_unlock(&default_context_lock);
136
137	free(ctx);
138	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_exit leave");
139}
140
141/* Device handling and initialisation. */
142
143ssize_t
144libusb_get_device_list(libusb_context * ctx, libusb_device *** list)
145{
146	struct libusb20_device *pdev;
147	struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
148	struct libusb_device *dev;
149	struct libusb20_backend *usb_backend;
150	int i;
151
152	GET_CONTEXT(ctx);
153	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_list enter");
154
155	usb_backend = libusb20_be_alloc_default();
156	if (usb_backend == NULL)
157		return (-1);
158
159	pdev = NULL;
160	i = 0;
161	while ((pdev = libusb20_be_device_foreach(usb_backend, pdev)))
162		i++;
163
164	if (list == NULL) {
165		libusb20_be_free(usb_backend);
166		return (LIBUSB_ERROR_INVALID_PARAM);
167	}
168	*list = malloc((i + 1) * sizeof(void *));
169	if (*list == NULL) {
170		libusb20_be_free(usb_backend);
171		return (LIBUSB_ERROR_NO_MEM);
172	}
173	i = 0;
174	while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) {
175		/* get device into libUSB v1.0 list */
176		libusb20_be_dequeue_device(usb_backend, pdev);
177
178		ddesc = libusb20_dev_get_device_desc(pdev);
179		dev = malloc(sizeof(*dev));
180		if (dev == NULL) {
181			free(*list);
182			libusb20_be_free(usb_backend);
183			return (LIBUSB_ERROR_NO_MEM);
184		}
185		memset(dev, 0, sizeof(*dev));
186
187		pthread_mutex_init(&dev->lock, NULL);
188		dev->ctx = ctx;
189		dev->bus_number = pdev->bus_number;
190		dev->device_address = pdev->device_address;
191		dev->num_configurations = ddesc->bNumConfigurations;
192
193		/* link together the two structures */
194		dev->os_priv = pdev;
195
196		pthread_mutex_lock(&ctx->usb_devs_lock);
197		LIST_ADD(&dev->list, &ctx->usb_devs);
198		pthread_mutex_unlock(&ctx->usb_devs_lock);
199
200		(*list)[i] = libusb_ref_device(dev);
201		i++;
202	}
203	(*list)[i] = NULL;
204
205	libusb20_be_free(usb_backend);
206	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_list leave");
207	return (i);
208}
209
210/*
211 * In this function we cant free all the device contained into list because
212 * open_with_pid_vid use some node of list after the free_device_list.
213 */
214void
215libusb_free_device_list(libusb_device **list, int unref_devices)
216{
217	int i;
218	libusb_context *ctx;
219
220	ctx = NULL;
221	GET_CONTEXT(ctx);
222	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_device_list enter");
223
224	if (list == NULL)
225		return ;
226
227	if (unref_devices) {
228		for (i = 0; list[i] != NULL; i++)
229			libusb_unref_device(list[i]);
230	}
231	free(list);
232	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_device_list leave");
233}
234
235uint8_t
236libusb_get_bus_number(libusb_device * dev)
237{
238	libusb_context *ctx;
239
240	ctx = NULL;
241	GET_CONTEXT(ctx);
242	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_bus_number enter");
243
244	if (dev == NULL)
245		return (LIBUSB_ERROR_NO_DEVICE);
246	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_bus_number leave");
247	return (dev->bus_number);
248}
249
250uint8_t
251libusb_get_device_address(libusb_device * dev)
252{
253	libusb_context *ctx;
254
255	ctx = NULL;
256	GET_CONTEXT(ctx);
257	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_address enter");
258
259	if (dev == NULL)
260		return (LIBUSB_ERROR_NO_DEVICE);
261	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device_address leave");
262	return (dev->device_address);
263}
264
265int
266libusb_get_max_packet_size(libusb_device *dev, unsigned char endpoint)
267{
268	struct libusb_config_descriptor *pdconf;
269	struct libusb_interface *pinf;
270	struct libusb_interface_descriptor *pdinf;
271	struct libusb_endpoint_descriptor *pdend;
272	libusb_context *ctx;
273	int i, j, k, ret;
274
275	ctx = NULL;
276	GET_CONTEXT(ctx);
277	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_max_packet_size enter");
278
279	if (dev == NULL)
280		return (LIBUSB_ERROR_NO_DEVICE);
281
282	if (libusb_get_active_config_descriptor(dev, &pdconf) < 0)
283		return (LIBUSB_ERROR_OTHER);
284
285	ret = LIBUSB_ERROR_NOT_FOUND;
286	for (i = 0 ; i < pdconf->bNumInterfaces ; i++) {
287		pinf = &pdconf->interface[i];
288		for (j = 0 ; j < pinf->num_altsetting ; j++) {
289			pdinf = &pinf->altsetting[j];
290			for (k = 0 ; k < pdinf->bNumEndpoints ; k++) {
291				pdend = &pdinf->endpoint[k];
292				if (pdend->bEndpointAddress == endpoint) {
293					ret = pdend->wMaxPacketSize;
294					goto out;
295				}
296			}
297		}
298	}
299
300out:
301	libusb_free_config_descriptor(pdconf);
302	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_max_packet_size leave");
303	return (ret);
304}
305
306libusb_device *
307libusb_ref_device(libusb_device * dev)
308{
309	libusb_context *ctx;
310
311	ctx = NULL;
312	GET_CONTEXT(ctx);
313	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_ref_device enter");
314
315	if (dev == NULL)
316		return (NULL);
317
318	pthread_mutex_lock(&dev->lock);
319	dev->refcnt++;
320	pthread_mutex_unlock(&dev->lock);
321
322	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_ref_device leave");
323	return (dev);
324}
325
326void
327libusb_unref_device(libusb_device * dev)
328{
329	libusb_context *ctx;
330
331	ctx = NULL;
332	GET_CONTEXT(ctx);
333	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unref_device enter");
334
335	if (dev == NULL)
336		return;
337
338	pthread_mutex_lock(&dev->lock);
339	dev->refcnt--;
340	pthread_mutex_unlock(&dev->lock);
341
342	if (dev->refcnt == 0) {
343		pthread_mutex_lock(&dev->ctx->usb_devs_lock);
344		LIST_DEL(&dev->list);
345		pthread_mutex_unlock(&dev->ctx->usb_devs_lock);
346
347		libusb20_dev_free(dev->os_priv);
348		free(dev);
349	}
350	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unref_device leave");
351}
352
353int
354libusb_open(libusb_device * dev, libusb_device_handle **devh)
355{
356	libusb_context *ctx = dev->ctx;
357	struct libusb20_device *pdev = dev->os_priv;
358	libusb_device_handle *hdl;
359	unsigned char dummy;
360	int err;
361
362	GET_CONTEXT(ctx);
363	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open enter");
364
365	dummy = 1;
366	if (devh == NULL)
367		return (LIBUSB_ERROR_INVALID_PARAM);
368
369	hdl = malloc(sizeof(*hdl));
370	if (hdl == NULL)
371		return (LIBUSB_ERROR_NO_MEM);
372
373	err = libusb20_dev_open(pdev, 16 * 4 /* number of endpoints */ );
374	if (err) {
375		free(hdl);
376		return (LIBUSB_ERROR_NO_MEM);
377	}
378	memset(hdl, 0, sizeof(*hdl));
379	pthread_mutex_init(&hdl->lock, NULL);
380
381	hdl->dev = libusb_ref_device(dev);
382	hdl->claimed_interfaces = 0;
383	hdl->os_priv = dev->os_priv;
384	err = usb_add_pollfd(ctx, libusb20_dev_get_fd(pdev), POLLIN |
385	    POLLOUT | POLLRDNORM | POLLWRNORM);
386	if (err < 0) {
387		libusb_unref_device(dev);
388		free(hdl);
389		return (err);
390	}
391
392	pthread_mutex_lock(&ctx->open_devs_lock);
393	LIST_ADD(&hdl->list, &ctx->open_devs);
394	pthread_mutex_unlock(&ctx->open_devs_lock);
395
396	*devh = hdl;
397
398	pthread_mutex_lock(&ctx->pollfd_modify_lock);
399	ctx->pollfd_modify++;
400	pthread_mutex_unlock(&ctx->pollfd_modify_lock);
401
402	err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
403	if (err <= 0) {
404		pthread_mutex_lock(&ctx->pollfd_modify_lock);
405		ctx->pollfd_modify--;
406		pthread_mutex_unlock(&ctx->pollfd_modify_lock);
407		return 0;
408	}
409
410	libusb_lock_events(ctx);
411	read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy));
412	pthread_mutex_lock(&ctx->pollfd_modify_lock);
413	ctx->pollfd_modify--;
414	pthread_mutex_unlock(&ctx->pollfd_modify_lock);
415	libusb_unlock_events(ctx);
416
417	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open leave");
418	return (0);
419}
420
421libusb_device_handle *
422libusb_open_device_with_vid_pid(libusb_context * ctx, uint16_t vendor_id,
423    uint16_t product_id)
424{
425	struct libusb_device **devs;
426	struct libusb_device_handle *devh;
427	struct libusb20_device *pdev;
428	struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
429	int i, j;
430
431	GET_CONTEXT(ctx);
432	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid enter");
433
434	devh = NULL;
435
436	if ((i = libusb_get_device_list(ctx, &devs)) < 0)
437		return (NULL);
438
439	for (j = 0; j < i; j++) {
440		pdev = (struct libusb20_device *)devs[j]->os_priv;
441		pdesc = libusb20_dev_get_device_desc(pdev);
442		if (pdesc->idVendor == vendor_id &&
443		    pdesc->idProduct == product_id)
444			if (libusb_open(devs[j], &devh) < 0)
445				devh = NULL;
446	}
447
448	libusb_free_device_list(devs, 1);
449	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_width_vid_pid leave");
450	return (devh);
451}
452
453void
454libusb_close(libusb_device_handle * devh)
455{
456	libusb_context *ctx;
457	struct libusb20_device *pdev;
458	unsigned char dummy = 1;
459	int err;
460
461	if (devh == NULL)
462		return ;
463
464	ctx = devh->dev->ctx;
465	pdev = devh->os_priv;
466
467	GET_CONTEXT(ctx);
468	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close enter");
469
470	pthread_mutex_lock(&ctx->pollfd_modify_lock);
471	ctx->pollfd_modify++;
472	pthread_mutex_unlock(&ctx->pollfd_modify_lock);
473
474	err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
475
476	if (err <= 0) {
477		pthread_mutex_lock(&ctx->open_devs_lock);
478		LIST_DEL(&devh->list);
479		pthread_mutex_unlock(&ctx->open_devs_lock);
480
481		usb_remove_pollfd(ctx, libusb20_dev_get_fd(pdev));
482		libusb_unref_device(devh->dev);
483		libusb20_dev_close(pdev);
484		free(devh);
485
486		pthread_mutex_lock(&ctx->pollfd_modify_lock);
487		ctx->pollfd_modify--;
488		pthread_mutex_unlock(&ctx->pollfd_modify_lock);
489		return ;
490	}
491	libusb_lock_events(ctx);
492
493	read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy));
494	pthread_mutex_lock(&ctx->open_devs_lock);
495	LIST_DEL(&devh->list);
496	pthread_mutex_unlock(&ctx->open_devs_lock);
497
498	usb_remove_pollfd(ctx, libusb20_dev_get_fd(pdev));
499	libusb_unref_device(devh->dev);
500	libusb20_dev_close(pdev);
501	free(devh);
502
503	pthread_mutex_lock(&ctx->pollfd_modify_lock);
504	ctx->pollfd_modify--;
505	pthread_mutex_unlock(&ctx->pollfd_modify_lock);
506
507	libusb_unlock_events(ctx);
508	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close leave");
509}
510
511libusb_device *
512libusb_get_device(libusb_device_handle * devh)
513{
514	libusb_context *ctx;
515
516	ctx = NULL;
517	GET_CONTEXT(ctx);
518	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device enter");
519
520	if (devh == NULL)
521		return (NULL);
522
523	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_device leave");
524	return (devh->dev);
525}
526
527int
528libusb_get_configuration(libusb_device_handle * devh, int *config)
529{
530	libusb_context *ctx;
531
532	ctx = NULL;
533	GET_CONTEXT(ctx);
534	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_configuration enter");
535
536	if (devh == NULL || config == NULL)
537		return (LIBUSB_ERROR_INVALID_PARAM);
538
539	*config = libusb20_dev_get_config_index((struct libusb20_device *)
540	    devh->dev->os_priv);
541
542	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_configuration leave");
543	return (0);
544}
545
546/*
547 *	XXX this code is wrong. need update.
548 */
549
550int
551libusb_set_configuration(libusb_device_handle * devh, int configuration)
552{
553	struct libusb20_device *pdev;
554	libusb_context *ctx;
555
556	ctx = NULL;
557	GET_CONTEXT(ctx);
558	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_configuration enter");
559
560	if (devh == NULL)
561		return (LIBUSB_ERROR_INVALID_PARAM);
562
563	pdev = (struct libusb20_device *)devh->dev->os_priv;
564
565	libusb20_dev_set_alt_index(pdev, libusb20_dev_get_config_index(pdev),
566	    configuration);
567	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_configuration leave");
568	return (0);
569}
570
571int
572libusb_claim_interface(libusb_device_handle * dev, int interface_number)
573{
574	libusb_context *ctx;
575	int ret = 0;
576
577	ctx = NULL;
578	GET_CONTEXT(ctx);
579	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_claim_interface enter");
580
581	if (dev == NULL)
582		return (LIBUSB_ERROR_INVALID_PARAM);
583
584	if (interface_number >= sizeof(dev->claimed_interfaces) * 8)
585		return (LIBUSB_ERROR_INVALID_PARAM);
586
587	pthread_mutex_lock(&(dev->lock));
588	if (dev->claimed_interfaces & (1 << interface_number))
589		ret = LIBUSB_ERROR_BUSY;
590
591	if (!ret)
592		dev->claimed_interfaces |= (1 << interface_number);
593	pthread_mutex_unlock(&(dev->lock));
594
595	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_claim_interface leave");
596	return (ret);
597}
598
599int
600libusb_release_interface(libusb_device_handle * dev, int interface_number)
601{
602	libusb_context *ctx;
603	int ret;
604
605	ctx = NULL;
606	GET_CONTEXT(ctx);
607	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_release_interface enter");
608
609	ret = 0;
610	if (dev == NULL)
611		return (LIBUSB_ERROR_INVALID_PARAM);
612
613	if (interface_number >= sizeof(dev->claimed_interfaces) * 8)
614		return (LIBUSB_ERROR_INVALID_PARAM);
615
616	pthread_mutex_lock(&(dev->lock));
617	if (!(dev->claimed_interfaces & (1 << interface_number)))
618		ret = LIBUSB_ERROR_NOT_FOUND;
619
620	if (!ret)
621		dev->claimed_interfaces &= ~(1 << interface_number);
622	pthread_mutex_unlock(&(dev->lock));
623
624	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_release_interface leave");
625	return (ret);
626}
627
628int
629libusb_set_interface_alt_setting(libusb_device_handle * dev,
630    int interface_number, int alternate_setting)
631{
632	libusb_context *ctx;
633	int ret;
634
635	ctx = NULL;
636	GET_CONTEXT(ctx);
637	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_interface_alt_setting enter");
638
639	if (dev == NULL)
640		return (LIBUSB_ERROR_INVALID_PARAM);
641
642	if (interface_number >= sizeof(dev->claimed_interfaces) *8)
643		return (LIBUSB_ERROR_INVALID_PARAM);
644
645	pthread_mutex_lock(&dev->lock);
646	if (!(dev->claimed_interfaces & (1 << interface_number))) {
647		pthread_mutex_unlock(&dev->lock);
648		return (LIBUSB_ERROR_NOT_FOUND);
649	}
650	pthread_mutex_unlock(&dev->lock);
651
652	if (libusb20_dev_set_alt_index(dev->os_priv, interface_number,
653	    alternate_setting) != 0)
654		return (LIBUSB_ERROR_OTHER);
655
656	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_interface_alt_setting leave");
657	return (0);
658}
659
660int
661libusb_clear_halt(libusb_device_handle * devh, unsigned char endpoint)
662{
663	struct libusb20_transfer *xfer;
664	libusb_context *ctx;
665	int ret;
666
667	ctx = NULL;
668	GET_CONTEXT(ctx);
669	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_clear_halt enter");
670
671	GET_XFER(xfer, endpoint, devh->os_priv);
672
673	pthread_mutex_lock(&libusb20_lock);
674	ret = libusb20_tr_open(xfer, 0, 0, endpoint);
675	if (ret != 0 && ret != LIBUSB20_ERROR_BUSY) {
676		pthread_mutex_unlock(&libusb20_lock);
677		return (LIBUSB_ERROR_OTHER);
678	}
679
680	libusb20_tr_clear_stall_sync(xfer);
681	if (ret == 0) /* check if we have open the device */
682		libusb20_tr_close(xfer);
683	pthread_mutex_unlock(&libusb20_lock);
684
685	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_clear_halt leave");
686	return (0);
687}
688
689int
690libusb_reset_device(libusb_device_handle * dev)
691{
692	libusb_context *ctx;
693
694	ctx = NULL;
695	GET_CONTEXT(ctx);
696	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_reset_device enter");
697
698	if (dev == NULL)
699		return (LIBUSB20_ERROR_INVALID_PARAM);
700
701	libusb20_dev_reset(dev->os_priv);
702	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_reset_device leave");
703	return (0);
704}
705
706int
707libusb_kernel_driver_active(libusb_device_handle * devh, int interface)
708{
709	libusb_context *ctx;
710
711	ctx = NULL;
712	GET_CONTEXT(ctx);
713	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_kernel_driver_active enter");
714
715	if (devh == NULL)
716		return (LIBUSB_ERROR_INVALID_PARAM);
717
718	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_kernel_driver_active leave");
719	return (libusb20_dev_kernel_driver_active(devh->os_priv, interface));
720}
721
722int
723libusb_detach_kernel_driver(libusb_device_handle * devh, int interface)
724{
725	struct libusb20_device *pdev;
726	libusb_context *ctx;
727
728	ctx = NULL;
729	GET_CONTEXT(ctx);
730	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_detach_kernel_driver enter");
731
732	if (devh == NULL)
733		return (LIBUSB_ERROR_INVALID_PARAM);
734
735	pdev = (struct libusb20_device *)devh->dev->os_priv;
736	if (libusb20_dev_detach_kernel_driver(pdev, interface) == LIBUSB20_ERROR_OTHER)
737		return (LIBUSB_ERROR_OTHER);
738
739	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_detach_kernel_driver leave");
740	return (0);
741}
742
743/*
744 * stub function.
745 * libusb20 doesn't support this feature.
746 */
747int
748libusb_attach_kernel_driver(libusb_device_handle * devh, int interface)
749{
750	libusb_context *ctx;
751
752	ctx = NULL;
753	GET_CONTEXT(ctx);
754	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_attach_kernel_driver enter");
755
756	if (devh == NULL)
757		return (LIBUSB_ERROR_INVALID_PARAM);
758
759	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_attach_kernel_driver leave");
760	return (0);
761}
762
763/* Asynchronous device I/O */
764
765struct libusb_transfer *
766libusb_alloc_transfer(int iso_packets)
767{
768	struct libusb_transfer *xfer;
769	struct usb_transfer *bxfer;
770	libusb_context *ctx;
771	int len;
772
773	ctx = NULL;
774	GET_CONTEXT(ctx);
775	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_alloc_transfer enter");
776
777	len = sizeof(struct libusb_transfer) +
778	    sizeof(struct usb_transfer) +
779	    (iso_packets * sizeof(libusb_iso_packet_descriptor));
780
781	bxfer = malloc(len);
782	if (bxfer == NULL)
783		return (NULL);
784
785	memset(bxfer, 0, len);
786	bxfer->num_iso_packets = iso_packets;
787
788	xfer = (struct libusb_transfer *) ((uint8_t *)bxfer +
789	    sizeof(struct usb_transfer));
790
791	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_alloc_transfer leave");
792	return (xfer);
793}
794
795void
796libusb_free_transfer(struct libusb_transfer *xfer)
797{
798	struct usb_transfer *bxfer;
799	libusb_context *ctx;
800
801	ctx = NULL;
802	GET_CONTEXT(ctx);
803	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_transfer enter");
804
805	if (xfer == NULL)
806		return ;
807
808	bxfer = (struct usb_transfer *) ((uint8_t *)xfer -
809	    sizeof(struct usb_transfer));
810
811	free(bxfer);
812	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_free_transfer leave");
813	return;
814}
815
816static void
817libusb10_proxy(struct libusb20_transfer *xfer)
818{
819	struct usb_transfer *usb_backend;
820	struct libusb20_device *pdev;
821	libusb_transfer *usb_xfer;
822	libusb_context *ctx;
823	uint8_t status;
824	uint32_t iso_packets;
825	int i;
826
827	status = libusb20_tr_get_status(xfer);
828	usb_xfer = libusb20_tr_get_priv_sc0(xfer);
829	usb_backend = (struct usb_transfer *) ((uint8_t *)usb_xfer -
830	    sizeof(struct usb_transfer));
831	pdev = usb_xfer->dev_handle->dev->os_priv;
832	ctx = usb_xfer->dev_handle->dev->ctx;
833	GET_CONTEXT(ctx);
834
835	switch (status) {
836	case LIBUSB20_TRANSFER_COMPLETED:
837		dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20 SUBMIT");
838		usb_xfer->actual_length += libusb20_tr_get_actual_length(xfer);
839		usb_xfer->callback(usb_xfer);
840
841		pthread_mutex_lock(&ctx->flying_transfers_lock);
842		LIST_DEL(&usb_backend->list);
843		pthread_mutex_unlock(&ctx->flying_transfers_lock);
844		break ;
845	case LIBUSB20_TRANSFER_START:
846		dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20 START");
847		usb_xfer->actual_length = 0;
848		switch (usb_xfer->type) {
849			case LIBUSB_TRANSFER_TYPE_CONTROL:
850				dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "TYPE CTR");
851				libusb20_tr_setup_control(xfer, usb_xfer->buffer,
852				    (void *)(((uint8_t *) usb_xfer->buffer) +
853			            sizeof(libusb_control_setup)),
854				    usb_xfer->timeout);
855				break ;
856			case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
857				dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "TYPE ISO");
858				iso_packets = libusb20_tr_get_max_frames(xfer);
859				if (usb_xfer->num_iso_packets > iso_packets)
860					usb_xfer->num_iso_packets = iso_packets;
861				for (i = 0 ; i < usb_xfer->num_iso_packets ; i++) {
862					libusb20_tr_setup_isoc(xfer,
863					    usb_xfer->buffer, usb_xfer->length, i);
864				}
865				libusb20_tr_set_total_frames(xfer, i);
866				break ;
867			case LIBUSB_TRANSFER_TYPE_BULK:
868				dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "TYPE BULK");
869				libusb20_tr_setup_bulk(xfer, usb_xfer->buffer,
870				    usb_xfer->length, usb_xfer->timeout);
871				break ;
872			case LIBUSB_TRANSFER_TYPE_INTERRUPT:
873				dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "TYPE INTR");
874				libusb20_tr_setup_intr(xfer, usb_xfer->buffer,
875				    usb_xfer->length, usb_xfer->timeout);
876				break ;
877		}
878		libusb20_tr_submit(xfer);
879		dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20 SUBMITED");
880		break ;
881	default:
882		if (ctx->debug == LIBUSB_DEBUG_TRANSFER)
883			printf("LIBUSB TRANSFER DEFAULT 0x%x\n", status);
884		usb_xfer->actual_length = 0;
885		usb_xfer->status = LIBUSB_TRANSFER_CANCELLED;
886
887		pthread_mutex_lock(&ctx->flying_transfers_lock);
888		LIST_DEL(&usb_backend->list);
889		pthread_mutex_unlock(&ctx->flying_transfers_lock);
890		usb_xfer->callback(usb_xfer);
891
892		break ;
893	}
894
895	switch (status) {
896	case LIBUSB20_TRANSFER_COMPLETED:
897		dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS COMPLETED");
898		usb_xfer->status = LIBUSB_TRANSFER_COMPLETED;
899		break ;
900	case LIBUSB20_TRANSFER_OVERFLOW:
901		dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS TR OVERFLOW");
902		usb_xfer->status = LIBUSB_TRANSFER_OVERFLOW;
903		break ;
904	case LIBUSB20_TRANSFER_NO_DEVICE:
905		dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS TR NO DEVICE");
906		usb_xfer->status = LIBUSB_TRANSFER_NO_DEVICE;
907		break ;
908	case LIBUSB20_TRANSFER_STALL:
909		dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS TR STALL");
910		usb_xfer->status = LIBUSB_TRANSFER_STALL;
911		break ;
912	case LIBUSB20_TRANSFER_CANCELLED:
913		dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS TR CANCELLED");
914		usb_xfer->status = LIBUSB_TRANSFER_CANCELLED;
915		break ;
916	case LIBUSB20_TRANSFER_TIMED_OUT:
917		dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "STATUS TR TIMEOUT");
918		usb_xfer->status = LIBUSB_TRANSFER_TIMED_OUT;
919		break ;
920	case LIBUSB20_TRANSFER_ERROR:
921		dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "ERROR");
922		usb_xfer->status = LIBUSB_TRANSFER_ERROR;
923		break ;
924	}
925}
926
927static int
928libusb_get_maxframe(struct libusb20_device *pdev, libusb_transfer *xfer)
929{
930	int ret;
931	int usb_speed;
932
933	usb_speed = libusb20_dev_get_speed(pdev);
934
935	switch (xfer->type) {
936	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
937		switch (usb_speed) {
938		case LIBUSB20_SPEED_LOW:
939		case LIBUSB20_SPEED_FULL:
940			ret = 60 * 1;
941			break ;
942		default :
943			ret = 60 * 8;
944			break ;
945		}
946		break ;
947	case LIBUSB_TRANSFER_TYPE_CONTROL:
948		ret = 2;
949		break ;
950	default:
951		ret = 1;
952		break ;
953	}
954
955	return ret;
956}
957
958static int
959libusb_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer)
960{
961	int ret;
962	int usb_speed;
963
964	usb_speed = libusb20_dev_get_speed(pdev);
965
966	switch (xfer->type) {
967	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
968		ret = 0;
969		break ;
970	case LIBUSB_TRANSFER_TYPE_CONTROL:
971		switch (usb_speed) {
972			case LIBUSB20_SPEED_LOW:
973				ret = 8;
974				break ;
975			case LIBUSB20_SPEED_FULL:
976				ret = 64;
977				break ;
978			case LIBUSB20_SPEED_HIGH:
979				ret = 64;
980				break ;
981		}
982		/*add */
983		ret += 8;
984		break ;
985	default :
986		switch (usb_speed) {
987			case LIBUSB20_SPEED_LOW:
988				ret = 256;
989				break ;
990			case LIBUSB20_SPEED_FULL:
991				ret = 4096;
992				break ;
993			default:
994				ret = 16384;
995				break ;
996		}
997		break ;
998	}
999
1000	return ret;
1001}
1002
1003int
1004libusb_submit_transfer(struct libusb_transfer *xfer)
1005{
1006	struct libusb20_transfer **usb20_xfer;
1007	struct usb_transfer *usb_backend;
1008	struct usb_transfer *usb_node;
1009	struct libusb20_device *pdev;
1010	struct libusb_context *ctx;
1011	struct timespec cur_ts;
1012	struct timeval *cur_tv;
1013	int maxframe;
1014	int buffsize;
1015	int num_frame;
1016	int ep_idx;
1017	int ret;
1018	int i;
1019
1020	if (xfer == NULL)
1021		return (LIBUSB_ERROR_NO_MEM);
1022
1023	usb20_xfer = malloc(2 * sizeof(struct libusb20_transfer *));
1024	if (usb20_xfer == NULL)
1025		return (LIBUSB_ERROR_NO_MEM);
1026
1027	ctx = xfer->dev_handle->dev->ctx;
1028	pdev = xfer->dev_handle->os_priv;
1029
1030	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer enter");
1031
1032	usb_backend = (struct usb_transfer *) ((uint8_t *)xfer -
1033	    sizeof(struct usb_transfer));
1034	usb_backend->transferred = 0;
1035	usb_backend->flags = 0;
1036
1037	if (xfer->timeout != 0) {
1038		clock_gettime(CLOCK_MONOTONIC, &cur_ts);
1039		cur_ts.tv_sec += xfer->timeout / 1000;
1040		cur_ts.tv_nsec += (xfer->timeout % 1000) * 1000000;
1041
1042		if (cur_ts.tv_nsec > 1000000000) {
1043			cur_ts.tv_nsec -= 1000000000;
1044			cur_ts.tv_sec++;
1045		}
1046
1047		TIMESPEC_TO_TIMEVAL(&usb_backend->timeout, &cur_ts);
1048	}
1049
1050	/*Add to flying list*/
1051	pthread_mutex_lock(&ctx->flying_transfers_lock);
1052	if (USB_LIST_EMPTY(&ctx->flying_transfers)) {
1053		LIST_ADD(&usb_backend->list, &ctx->flying_transfers);
1054		goto out;
1055	}
1056	if (timerisset(&usb_backend->timeout) == 0) {
1057		LIST_ADD_TAIL(&usb_backend->list, &ctx->flying_transfers);
1058		goto out;
1059	}
1060	LIST_FOREACH_ENTRY(usb_node, &ctx->flying_transfers, list) {
1061		cur_tv = &usb_node->timeout;
1062		if (timerisset(cur_tv) == 0 ||
1063		    (cur_tv->tv_sec > usb_backend->timeout.tv_sec) ||
1064		    (cur_tv->tv_sec == usb_backend->timeout.tv_sec &&
1065		    cur_tv->tv_usec > usb_backend->timeout.tv_usec)) {
1066			LIST_ADD_TAIL(&usb_backend->list, &usb_node->list);
1067			goto out;
1068		}
1069	}
1070	LIST_ADD_TAIL(&usb_backend->list, &ctx->flying_transfers);
1071
1072out:
1073	pthread_mutex_unlock(&ctx->flying_transfers_lock);
1074
1075	usb20_xfer[0] = libusb20_tr_get_pointer(pdev,
1076	    ((xfer->endpoint / 0x40) | (xfer->endpoint * 4)) % (16 * 4));
1077	usb20_xfer[1] = libusb20_tr_get_pointer(pdev,
1078	    (((xfer->endpoint / 0x40) | (xfer->endpoint * 4)) % (16 * 4)) + 1);
1079
1080	if (usb20_xfer[0] == NULL)
1081		return (LIBUSB_ERROR_OTHER);
1082
1083	xfer->os_priv = usb20_xfer;
1084
1085	pthread_mutex_lock(&libusb20_lock);
1086
1087	buffsize = libusb_get_buffsize(pdev, xfer);
1088	maxframe = libusb_get_maxframe(pdev, xfer);
1089
1090	ret = libusb20_tr_open(usb20_xfer[0], buffsize,
1091	    maxframe, xfer->endpoint);
1092	if (xfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS)
1093		ret |= libusb20_tr_open(usb20_xfer[1], buffsize,
1094		    maxframe, xfer->endpoint);
1095
1096	if (ret != 0) {
1097		pthread_mutex_unlock(&libusb20_lock);
1098		pthread_mutex_lock(&ctx->flying_transfers_lock);
1099		LIST_DEL(&usb_backend->list);
1100		pthread_mutex_unlock(&ctx->flying_transfers_lock);
1101		return (LIBUSB_ERROR_OTHER);
1102	}
1103
1104	libusb20_tr_set_priv_sc0(usb20_xfer[0], xfer);
1105	libusb20_tr_set_callback(usb20_xfer[0], libusb10_proxy);
1106	if (xfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
1107		libusb20_tr_set_priv_sc0(usb20_xfer[1], xfer);
1108		libusb20_tr_set_callback(usb20_xfer[1], libusb10_proxy);
1109	}
1110
1111	libusb20_tr_start(usb20_xfer[0]);
1112	if (xfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS)
1113		libusb20_tr_start(usb20_xfer[1]);
1114
1115	pthread_mutex_unlock(&libusb20_lock);
1116
1117	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer leave");
1118	return (0);
1119}
1120
1121int
1122libusb_cancel_transfer(struct libusb_transfer *xfer)
1123{
1124	libusb_context *ctx;
1125
1126	ctx = NULL;
1127	GET_CONTEXT(ctx);
1128	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter");
1129
1130	if (xfer == NULL)
1131		return (LIBUSB_ERROR_NO_MEM);
1132
1133	pthread_mutex_lock(&libusb20_lock);
1134	libusb20_tr_stop(xfer->os_priv);
1135	pthread_mutex_unlock(&libusb20_lock);
1136
1137	dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave");
1138	return (0);
1139}
1140
1141