]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libusb/libusb20.c
Merge branch 'releng/11.3' into releng-CDN/11.3
[FreeBSD/FreeBSD.git] / lib / libusb / libusb20.c
1 /* $FreeBSD$ */
2 /*-
3  * Copyright (c) 2008-2009 Hans Petter Selasky. 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 #ifdef LIBUSB_GLOBAL_INCLUDE_FILE
28 #include LIBUSB_GLOBAL_INCLUDE_FILE
29 #else
30 #include <ctype.h>
31 #include <poll.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <time.h>
36 #include <sys/queue.h>
37 #endif
38
39 #include "libusb20.h"
40 #include "libusb20_desc.h"
41 #include "libusb20_int.h"
42
43 static int
44 dummy_int(void)
45 {
46         return (LIBUSB20_ERROR_NOT_SUPPORTED);
47 }
48
49 static void
50 dummy_void(void)
51 {
52         return;
53 }
54
55 static void
56 dummy_callback(struct libusb20_transfer *xfer)
57 {
58         ;                               /* style fix */
59         switch (libusb20_tr_get_status(xfer)) {
60         case LIBUSB20_TRANSFER_START:
61                 libusb20_tr_submit(xfer);
62                 break;
63         default:
64                 /* complete or error */
65                 break;
66         }
67         return;
68 }
69
70 #define dummy_get_config_desc_full (void *)dummy_int
71 #define dummy_get_config_index (void *)dummy_int
72 #define dummy_set_config_index (void *)dummy_int
73 #define dummy_set_alt_index (void *)dummy_int
74 #define dummy_reset_device (void *)dummy_int
75 #define dummy_check_connected (void *)dummy_int
76 #define dummy_set_power_mode (void *)dummy_int
77 #define dummy_get_power_mode (void *)dummy_int
78 #define dummy_get_power_usage (void *)dummy_int
79 #define dummy_kernel_driver_active (void *)dummy_int
80 #define dummy_detach_kernel_driver (void *)dummy_int
81 #define dummy_do_request_sync (void *)dummy_int
82 #define dummy_tr_open (void *)dummy_int
83 #define dummy_tr_close (void *)dummy_int
84 #define dummy_tr_clear_stall_sync (void *)dummy_int
85 #define dummy_process (void *)dummy_int
86 #define dummy_dev_info (void *)dummy_int
87 #define dummy_dev_get_iface_driver (void *)dummy_int
88
89 #define dummy_tr_submit (void *)dummy_void
90 #define dummy_tr_cancel_async (void *)dummy_void
91
92 static const struct libusb20_device_methods libusb20_dummy_methods = {
93         LIBUSB20_DEVICE(LIBUSB20_DECLARE, dummy)
94 };
95
96 void
97 libusb20_tr_callback_wrapper(struct libusb20_transfer *xfer)
98 {
99         ;                               /* style fix */
100
101 repeat:
102
103         if (!xfer->is_pending) {
104                 xfer->status = LIBUSB20_TRANSFER_START;
105         } else {
106                 xfer->is_pending = 0;
107         }
108
109         xfer->callback(xfer);
110
111         if (xfer->is_restart) {
112                 xfer->is_restart = 0;
113                 goto repeat;
114         }
115         if (xfer->is_draining &&
116             (!xfer->is_pending)) {
117                 xfer->is_draining = 0;
118                 xfer->status = LIBUSB20_TRANSFER_DRAINED;
119                 xfer->callback(xfer);
120         }
121         return;
122 }
123
124 int
125 libusb20_tr_close(struct libusb20_transfer *xfer)
126 {
127         int error;
128
129         if (!xfer->is_opened) {
130                 return (LIBUSB20_ERROR_OTHER);
131         }
132         error = xfer->pdev->methods->tr_close(xfer);
133
134         if (xfer->pLength) {
135                 free(xfer->pLength);
136         }
137         if (xfer->ppBuffer) {
138                 free(xfer->ppBuffer);
139         }
140         /* reset variable fields in case the transfer is opened again */
141         xfer->priv_sc0 = NULL;
142         xfer->priv_sc1 = NULL;
143         xfer->is_opened = 0;
144         xfer->is_pending = 0;
145         xfer->is_cancel = 0;
146         xfer->is_draining = 0;
147         xfer->is_restart = 0;
148         xfer->status = 0;
149         xfer->flags = 0;
150         xfer->nFrames = 0;
151         xfer->aFrames = 0;
152         xfer->timeout = 0;
153         xfer->maxFrames = 0;
154         xfer->maxTotalLength = 0;
155         xfer->maxPacketLen = 0;
156         return (error);
157 }
158
159 int
160 libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
161     uint32_t MaxFrameCount, uint8_t ep_no)
162 {
163         return (libusb20_tr_open_stream(xfer, MaxBufSize, MaxFrameCount, ep_no, 0));
164 }
165
166 int
167 libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
168     uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id)
169 {
170         uint32_t size;
171         uint8_t pre_scale;
172         int error;
173
174         if (xfer->is_opened)
175                 return (LIBUSB20_ERROR_BUSY);
176         if (MaxFrameCount & LIBUSB20_MAX_FRAME_PRE_SCALE) {
177                 MaxFrameCount &= ~LIBUSB20_MAX_FRAME_PRE_SCALE;
178                 /*
179                  * The kernel can setup 8 times more frames when
180                  * pre-scaling ISOCHRONOUS transfers. Make sure the
181                  * length and pointer buffers are big enough:
182                  */
183                 MaxFrameCount *= 8;
184                 pre_scale = 1;
185         } else {
186                 pre_scale = 0;
187         }
188         if (MaxFrameCount == 0)
189                 return (LIBUSB20_ERROR_INVALID_PARAM);
190
191         xfer->maxFrames = MaxFrameCount;
192
193         size = MaxFrameCount * sizeof(xfer->pLength[0]);
194         xfer->pLength = malloc(size);
195         if (xfer->pLength == NULL) {
196                 return (LIBUSB20_ERROR_NO_MEM);
197         }
198         memset(xfer->pLength, 0, size);
199
200         size = MaxFrameCount * sizeof(xfer->ppBuffer[0]);
201         xfer->ppBuffer = malloc(size);
202         if (xfer->ppBuffer == NULL) {
203                 free(xfer->pLength);
204                 return (LIBUSB20_ERROR_NO_MEM);
205         }
206         memset(xfer->ppBuffer, 0, size);
207
208         if (pre_scale) {
209                 error = xfer->pdev->methods->tr_open(xfer, MaxBufSize,
210                     MaxFrameCount / 8, ep_no, stream_id, 1);
211         } else {
212                 error = xfer->pdev->methods->tr_open(xfer, MaxBufSize,
213                     MaxFrameCount, ep_no, stream_id, 0);
214         }
215
216         if (error) {
217                 free(xfer->ppBuffer);
218                 free(xfer->pLength);
219         } else {
220                 xfer->is_opened = 1;
221         }
222         return (error);
223 }
224
225 struct libusb20_transfer *
226 libusb20_tr_get_pointer(struct libusb20_device *pdev, uint16_t trIndex)
227 {
228         if (trIndex >= pdev->nTransfer) {
229                 return (NULL);
230         }
231         return (pdev->pTransfer + trIndex);
232 }
233
234 uint32_t
235 libusb20_tr_get_actual_frames(struct libusb20_transfer *xfer)
236 {
237         return (xfer->aFrames);
238 }
239
240 uint16_t
241 libusb20_tr_get_time_complete(struct libusb20_transfer *xfer)
242 {
243         return (xfer->timeComplete);
244 }
245
246 uint32_t
247 libusb20_tr_get_actual_length(struct libusb20_transfer *xfer)
248 {
249         uint32_t x;
250         uint32_t actlen = 0;
251
252         for (x = 0; x != xfer->aFrames; x++) {
253                 actlen += xfer->pLength[x];
254         }
255         return (actlen);
256 }
257
258 uint32_t
259 libusb20_tr_get_max_frames(struct libusb20_transfer *xfer)
260 {
261         return (xfer->maxFrames);
262 }
263
264 uint32_t
265 libusb20_tr_get_max_packet_length(struct libusb20_transfer *xfer)
266 {
267         /*
268          * Special Case NOTE: If the packet multiplier is non-zero for
269          * High Speed USB, the value returned is equal to
270          * "wMaxPacketSize * multiplier" !
271          */
272         return (xfer->maxPacketLen);
273 }
274
275 uint32_t
276 libusb20_tr_get_max_total_length(struct libusb20_transfer *xfer)
277 {
278         return (xfer->maxTotalLength);
279 }
280
281 uint8_t
282 libusb20_tr_get_status(struct libusb20_transfer *xfer)
283 {
284         return (xfer->status);
285 }
286
287 uint8_t
288 libusb20_tr_pending(struct libusb20_transfer *xfer)
289 {
290         return (xfer->is_pending);
291 }
292
293 void   *
294 libusb20_tr_get_priv_sc0(struct libusb20_transfer *xfer)
295 {
296         return (xfer->priv_sc0);
297 }
298
299 void   *
300 libusb20_tr_get_priv_sc1(struct libusb20_transfer *xfer)
301 {
302         return (xfer->priv_sc1);
303 }
304
305 void
306 libusb20_tr_stop(struct libusb20_transfer *xfer)
307 {
308         if (!xfer->is_opened) {
309                 /* transfer is not opened */
310                 return;
311         }
312         if (!xfer->is_pending) {
313                 /* transfer not pending */
314                 return;
315         }
316         if (xfer->is_cancel) {
317                 /* already cancelling */
318                 return;
319         }
320         xfer->is_cancel = 1;            /* we are cancelling */
321
322         xfer->pdev->methods->tr_cancel_async(xfer);
323         return;
324 }
325
326 void
327 libusb20_tr_drain(struct libusb20_transfer *xfer)
328 {
329         if (!xfer->is_opened) {
330                 /* transfer is not opened */
331                 return;
332         }
333         /* make sure that we are cancelling */
334         libusb20_tr_stop(xfer);
335
336         if (xfer->is_pending) {
337                 xfer->is_draining = 1;
338         }
339         return;
340 }
341
342 void
343 libusb20_tr_clear_stall_sync(struct libusb20_transfer *xfer)
344 {
345         xfer->pdev->methods->tr_clear_stall_sync(xfer);
346         return;
347 }
348
349 void
350 libusb20_tr_set_buffer(struct libusb20_transfer *xfer, void *buffer, uint16_t frIndex)
351 {
352         xfer->ppBuffer[frIndex] = libusb20_pass_ptr(buffer);
353         return;
354 }
355
356 void
357 libusb20_tr_set_callback(struct libusb20_transfer *xfer, libusb20_tr_callback_t *cb)
358 {
359         xfer->callback = cb;
360         return;
361 }
362
363 void
364 libusb20_tr_set_flags(struct libusb20_transfer *xfer, uint8_t flags)
365 {
366         xfer->flags = flags;
367         return;
368 }
369
370 uint32_t
371 libusb20_tr_get_length(struct libusb20_transfer *xfer, uint16_t frIndex)
372 {
373         return (xfer->pLength[frIndex]);
374 }
375
376 void
377 libusb20_tr_set_length(struct libusb20_transfer *xfer, uint32_t length, uint16_t frIndex)
378 {
379         xfer->pLength[frIndex] = length;
380         return;
381 }
382
383 void
384 libusb20_tr_set_priv_sc0(struct libusb20_transfer *xfer, void *sc0)
385 {
386         xfer->priv_sc0 = sc0;
387         return;
388 }
389
390 void
391 libusb20_tr_set_priv_sc1(struct libusb20_transfer *xfer, void *sc1)
392 {
393         xfer->priv_sc1 = sc1;
394         return;
395 }
396
397 void
398 libusb20_tr_set_timeout(struct libusb20_transfer *xfer, uint32_t timeout)
399 {
400         xfer->timeout = timeout;
401         return;
402 }
403
404 void
405 libusb20_tr_set_total_frames(struct libusb20_transfer *xfer, uint32_t nFrames)
406 {
407         if (nFrames > xfer->maxFrames) {
408                 /* should not happen */
409                 nFrames = xfer->maxFrames;
410         }
411         xfer->nFrames = nFrames;
412         return;
413 }
414
415 void
416 libusb20_tr_setup_bulk(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout)
417 {
418         xfer->ppBuffer[0] = libusb20_pass_ptr(pBuf);
419         xfer->pLength[0] = length;
420         xfer->timeout = timeout;
421         xfer->nFrames = 1;
422         return;
423 }
424
425 void
426 libusb20_tr_setup_control(struct libusb20_transfer *xfer, void *psetup, void *pBuf, uint32_t timeout)
427 {
428         uint16_t len;
429
430         xfer->ppBuffer[0] = libusb20_pass_ptr(psetup);
431         xfer->pLength[0] = 8;           /* fixed */
432         xfer->timeout = timeout;
433
434         len = ((uint8_t *)psetup)[6] | (((uint8_t *)psetup)[7] << 8);
435
436         if (len != 0) {
437                 xfer->nFrames = 2;
438                 xfer->ppBuffer[1] = libusb20_pass_ptr(pBuf);
439                 xfer->pLength[1] = len;
440         } else {
441                 xfer->nFrames = 1;
442         }
443         return;
444 }
445
446 void
447 libusb20_tr_setup_intr(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout)
448 {
449         xfer->ppBuffer[0] = libusb20_pass_ptr(pBuf);
450         xfer->pLength[0] = length;
451         xfer->timeout = timeout;
452         xfer->nFrames = 1;
453         return;
454 }
455
456 void
457 libusb20_tr_setup_isoc(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint16_t frIndex)
458 {
459         if (frIndex >= xfer->maxFrames) {
460                 /* should not happen */
461                 return;
462         }
463         xfer->ppBuffer[frIndex] = libusb20_pass_ptr(pBuf);
464         xfer->pLength[frIndex] = length;
465         return;
466 }
467
468 uint8_t
469 libusb20_tr_bulk_intr_sync(struct libusb20_transfer *xfer,
470     void *pbuf, uint32_t length, uint32_t *pactlen,
471     uint32_t timeout)
472 {
473         struct libusb20_device *pdev = xfer->pdev;
474         uint32_t transfer_max;
475         uint32_t transfer_act;
476         uint8_t retval;
477
478         /* set some sensible default value */
479         if (pactlen != NULL)
480                 *pactlen = 0;
481
482         /* check for error condition */
483         if (libusb20_tr_pending(xfer))
484                 return (LIBUSB20_ERROR_OTHER);
485
486         do {
487                 /* compute maximum transfer length */
488                 transfer_max = 
489                     libusb20_tr_get_max_total_length(xfer);
490
491                 if (transfer_max > length)
492                         transfer_max = length;
493
494                 /* setup bulk or interrupt transfer */
495                 libusb20_tr_setup_bulk(xfer, pbuf, 
496                     transfer_max, timeout);
497
498                 /* start the transfer */
499                 libusb20_tr_start(xfer);
500
501                 /* wait for transfer completion */
502                 while (libusb20_dev_process(pdev) == 0) {
503
504                         if (libusb20_tr_pending(xfer) == 0)
505                                 break;
506
507                         libusb20_dev_wait_process(pdev, -1);
508                 }
509
510                 transfer_act = libusb20_tr_get_actual_length(xfer);
511
512                 /* update actual length, if any */
513                 if (pactlen != NULL)
514                         pactlen[0] += transfer_act;
515
516                 /* check transfer status */
517                 retval = libusb20_tr_get_status(xfer);
518                 if (retval)
519                         break;
520
521                 /* check for short transfer */
522                 if (transfer_act != transfer_max)
523                         break;
524
525                 /* update buffer pointer and length */
526                 pbuf = ((uint8_t *)pbuf) + transfer_max;
527                 length = length - transfer_max;
528
529         } while (length != 0);
530
531         return (retval);
532 }
533
534 void
535 libusb20_tr_submit(struct libusb20_transfer *xfer)
536 {
537         if (!xfer->is_opened) {
538                 /* transfer is not opened */
539                 return;
540         }
541         if (xfer->is_pending) {
542                 /* should not happen */
543                 return;
544         }
545         xfer->is_pending = 1;           /* we are pending */
546         xfer->is_cancel = 0;            /* not cancelling */
547         xfer->is_restart = 0;           /* not restarting */
548
549         xfer->pdev->methods->tr_submit(xfer);
550         return;
551 }
552
553 void
554 libusb20_tr_start(struct libusb20_transfer *xfer)
555 {
556         if (!xfer->is_opened) {
557                 /* transfer is not opened */
558                 return;
559         }
560         if (xfer->is_pending) {
561                 if (xfer->is_cancel) {
562                         /* cancelling - restart */
563                         xfer->is_restart = 1;
564                 }
565                 /* transfer not pending */
566                 return;
567         }
568         /* get into the callback */
569         libusb20_tr_callback_wrapper(xfer);
570         return;
571 }
572
573 /* USB device operations */
574
575 int
576 libusb20_dev_close(struct libusb20_device *pdev)
577 {
578         struct libusb20_transfer *xfer;
579         uint16_t x;
580         int error = 0;
581
582         if (!pdev->is_opened) {
583                 return (LIBUSB20_ERROR_OTHER);
584         }
585         for (x = 0; x != pdev->nTransfer; x++) {
586                 xfer = pdev->pTransfer + x;
587
588                 if (!xfer->is_opened) {
589                         /* transfer is not opened */
590                         continue;
591                 }
592
593                 libusb20_tr_drain(xfer);
594
595                 libusb20_tr_close(xfer);
596         }
597
598         if (pdev->pTransfer != NULL) {
599                 free(pdev->pTransfer);
600                 pdev->pTransfer = NULL;
601         }
602         error = pdev->beMethods->close_device(pdev);
603
604         pdev->methods = &libusb20_dummy_methods;
605
606         pdev->is_opened = 0;
607
608         /* 
609          * The following variable is only used by the libusb v0.1
610          * compat layer:
611          */
612         pdev->claimed_interface = 0;
613
614         /*
615          * The following variable is only used by the libusb v1.0
616          * compat layer:
617          */
618         pdev->auto_detach = 0;
619
620         return (error);
621 }
622
623 int
624 libusb20_dev_detach_kernel_driver(struct libusb20_device *pdev, uint8_t ifaceIndex)
625 {
626         int error;
627
628         error = pdev->methods->detach_kernel_driver(pdev, ifaceIndex);
629         return (error);
630 }
631
632 struct LIBUSB20_DEVICE_DESC_DECODED *
633 libusb20_dev_get_device_desc(struct libusb20_device *pdev)
634 {
635         return (&(pdev->ddesc));
636 }
637
638 int
639 libusb20_dev_get_fd(struct libusb20_device *pdev)
640 {
641         return (pdev->file);
642 }
643
644 int
645 libusb20_dev_kernel_driver_active(struct libusb20_device *pdev, uint8_t ifaceIndex)
646 {
647         int error;
648
649         error = pdev->methods->kernel_driver_active(pdev, ifaceIndex);
650         return (error);
651 }
652
653 int
654 libusb20_dev_open(struct libusb20_device *pdev, uint16_t nTransferMax)
655 {
656         struct libusb20_transfer *xfer;
657         uint32_t size;
658         uint16_t x;
659         int error;
660
661         if (pdev->is_opened) {
662                 return (LIBUSB20_ERROR_BUSY);
663         }
664         if (nTransferMax >= 256) {
665                 return (LIBUSB20_ERROR_INVALID_PARAM);
666         } else if (nTransferMax != 0) {
667                 size = sizeof(pdev->pTransfer[0]) * nTransferMax;
668                 pdev->pTransfer = malloc(size);
669                 if (pdev->pTransfer == NULL) {
670                         return (LIBUSB20_ERROR_NO_MEM);
671                 }
672                 memset(pdev->pTransfer, 0, size);
673         }
674         /* initialise all transfers */
675         for (x = 0; x != nTransferMax; x++) {
676
677                 xfer = pdev->pTransfer + x;
678
679                 xfer->pdev = pdev;
680                 xfer->trIndex = x;
681                 xfer->callback = &dummy_callback;
682         }
683
684         /* set "nTransfer" early */
685         pdev->nTransfer = nTransferMax;
686
687         error = pdev->beMethods->open_device(pdev, nTransferMax);
688
689         if (error) {
690                 if (pdev->pTransfer != NULL) {
691                         free(pdev->pTransfer);
692                         pdev->pTransfer = NULL;
693                 }
694                 pdev->file = -1;
695                 pdev->file_ctrl = -1;
696                 pdev->nTransfer = 0;
697         } else {
698                 pdev->is_opened = 1;
699         }
700         return (error);
701 }
702
703 int
704 libusb20_dev_reset(struct libusb20_device *pdev)
705 {
706         int error;
707
708         error = pdev->methods->reset_device(pdev);
709         return (error);
710 }
711
712 int
713 libusb20_dev_check_connected(struct libusb20_device *pdev)
714 {
715         int error;
716
717         error = pdev->methods->check_connected(pdev);
718         return (error);
719 }
720
721 int
722 libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode)
723 {
724         int error;
725
726         error = pdev->methods->set_power_mode(pdev, power_mode);
727         return (error);
728 }
729
730 uint8_t
731 libusb20_dev_get_power_mode(struct libusb20_device *pdev)
732 {
733         int error;
734         uint8_t power_mode;
735
736         error = pdev->methods->get_power_mode(pdev, &power_mode);
737         if (error)
738                 power_mode = LIBUSB20_POWER_ON; /* fake power mode */
739         return (power_mode);
740 }
741
742 int
743 libusb20_dev_get_port_path(struct libusb20_device *pdev, uint8_t *buf, uint8_t bufsize)
744 {
745
746         if (pdev->port_level == 0) {
747                 /*
748                  * Fallback for backends without port path:
749                  */
750                 if (bufsize < 2)
751                         return (LIBUSB20_ERROR_OVERFLOW);
752                 buf[0] = pdev->parent_address;
753                 buf[1] = pdev->parent_port;
754                 return (2);
755         }
756
757         /* check if client buffer is too small */
758         if (pdev->port_level > bufsize)
759                 return (LIBUSB20_ERROR_OVERFLOW);
760
761         /* copy port number information */
762         memcpy(buf, pdev->port_path, pdev->port_level);
763
764         return (pdev->port_level);      /* success */
765 }
766
767 uint16_t
768 libusb20_dev_get_power_usage(struct libusb20_device *pdev)
769 {
770         int error;
771         uint16_t power_usage;
772
773         error = pdev->methods->get_power_usage(pdev, &power_usage);
774         if (error)
775                 power_usage = 0;
776         return (power_usage);
777 }
778
779 int
780 libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t ifaceIndex, uint8_t altIndex)
781 {
782         int error;
783
784         error = pdev->methods->set_alt_index(pdev, ifaceIndex, altIndex);
785         return (error);
786 }
787
788 int
789 libusb20_dev_set_config_index(struct libusb20_device *pdev, uint8_t configIndex)
790 {
791         int error;
792
793         error = pdev->methods->set_config_index(pdev, configIndex);
794         return (error);
795 }
796
797 int
798 libusb20_dev_request_sync(struct libusb20_device *pdev,
799     struct LIBUSB20_CONTROL_SETUP_DECODED *setup, void *data,
800     uint16_t *pactlen, uint32_t timeout, uint8_t flags)
801 {
802         int error;
803
804         error = pdev->methods->do_request_sync(pdev,
805             setup, data, pactlen, timeout, flags);
806         return (error);
807 }
808
809 int
810 libusb20_dev_req_string_sync(struct libusb20_device *pdev,
811     uint8_t str_index, uint16_t langid, void *ptr, uint16_t len)
812 {
813         struct LIBUSB20_CONTROL_SETUP_DECODED req;
814         int error;
815         int flags;
816
817         /* make sure memory is initialised */
818         memset(ptr, 0, len);
819
820         if (len < 4) {
821                 /* invalid length */
822                 return (LIBUSB20_ERROR_INVALID_PARAM);
823         }
824         LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
825
826         /*
827          * We need to read the USB string in two steps else some USB
828          * devices will complain.
829          */
830         req.bmRequestType =
831             LIBUSB20_REQUEST_TYPE_STANDARD |
832             LIBUSB20_RECIPIENT_DEVICE |
833             LIBUSB20_ENDPOINT_IN;
834         req.bRequest = LIBUSB20_REQUEST_GET_DESCRIPTOR;
835         req.wValue = (LIBUSB20_DT_STRING << 8) | str_index;
836         req.wIndex = langid;
837         req.wLength = 4;                /* bytes */
838
839         error = libusb20_dev_request_sync(pdev, &req,
840             ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK);
841         if (error) {
842                 /* try to request full string */
843                 req.wLength = 255;
844                 flags = 0;
845         } else {
846                 /* extract length and request full string */
847                 req.wLength = *(uint8_t *)ptr;
848                 flags = LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK;
849         }
850         if (req.wLength > len) {
851                 /* partial string read */
852                 req.wLength = len;
853         }
854         error = libusb20_dev_request_sync(pdev, &req, ptr, NULL, 1000, flags);
855         if (error)
856                 return (error);
857
858         if (((uint8_t *)ptr)[1] != LIBUSB20_DT_STRING)
859                 return (LIBUSB20_ERROR_OTHER);
860         return (0);                     /* success */
861 }
862
863 int
864 libusb20_dev_req_string_simple_sync(struct libusb20_device *pdev,
865     uint8_t str_index, void *ptr, uint16_t len)
866 {
867         char *buf;
868         int error;
869         uint16_t langid;
870         uint16_t n;
871         uint16_t i;
872         uint16_t c;
873         uint8_t temp[255];
874         uint8_t swap;
875
876         /* the following code derives from the FreeBSD USB kernel */
877
878         if ((len < 1) || (ptr == NULL)) {
879                 /* too short buffer */
880                 return (LIBUSB20_ERROR_INVALID_PARAM);
881         }
882         error = libusb20_dev_req_string_sync(pdev,
883             0, 0, temp, sizeof(temp));
884         if (error < 0) {
885                 *(uint8_t *)ptr = 0;    /* zero terminate */
886                 return (error);
887         }
888         langid = temp[2] | (temp[3] << 8);
889
890         error = libusb20_dev_req_string_sync(pdev, str_index,
891             langid, temp, sizeof(temp));
892         if (error < 0) {
893                 *(uint8_t *)ptr = 0;    /* zero terminate */
894                 return (error);
895         }
896         if (temp[0] < 2) {
897                 /* string length is too short */
898                 *(uint8_t *)ptr = 0;    /* zero terminate */
899                 return (LIBUSB20_ERROR_OTHER);
900         }
901         /* reserve one byte for terminating zero */
902         len--;
903
904         /* find maximum length */
905         n = (temp[0] / 2) - 1;
906         if (n > len) {
907                 n = len;
908         }
909         /* reset swap state */
910         swap = 3;
911
912         /* setup output buffer pointer */
913         buf = ptr;
914
915         /* convert and filter */
916         for (i = 0; (i != n); i++) {
917                 c = temp[(2 * i) + 2] | (temp[(2 * i) + 3] << 8);
918
919                 /* convert from Unicode, handle buggy strings */
920                 if (((c & 0xff00) == 0) && (swap & 1)) {
921                         /* Little Endian, default */
922                         *buf = c;
923                         swap = 1;
924                 } else if (((c & 0x00ff) == 0) && (swap & 2)) {
925                         /* Big Endian */
926                         *buf = c >> 8;
927                         swap = 2;
928                 } else {
929                         /* skip invalid character */
930                         continue;
931                 }
932                 /*
933                  * Filter by default - we don't allow greater and less than
934                  * signs because they might confuse the dmesg printouts!
935                  */
936                 if ((*buf == '<') || (*buf == '>') || (!isprint(*buf))) {
937                         /* skip invalid character */
938                         continue;
939                 }
940                 buf++;
941         }
942         *buf = 0;                       /* zero terminate string */
943
944         return (0);
945 }
946
947 struct libusb20_config *
948 libusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t configIndex)
949 {
950         struct libusb20_config *retval = NULL;
951         uint8_t *ptr;
952         uint16_t len;
953         uint8_t do_close;
954         int error;
955
956         /*
957          * Catch invalid configuration descriptor reads early on to
958          * avoid issues with devices that don't check for a valid USB
959          * configuration read request.
960          */
961         if (configIndex >= pdev->ddesc.bNumConfigurations)
962                 return (NULL);
963
964         if (!pdev->is_opened) {
965                 error = libusb20_dev_open(pdev, 0);
966                 if (error) {
967                         return (NULL);
968                 }
969                 do_close = 1;
970         } else {
971                 do_close = 0;
972         }
973         error = pdev->methods->get_config_desc_full(pdev,
974             &ptr, &len, configIndex);
975
976         if (error) {
977                 goto done;
978         }
979         /* parse new config descriptor */
980         retval = libusb20_parse_config_desc(ptr);
981
982         /* free config descriptor */
983         free(ptr);
984
985 done:
986         if (do_close) {
987                 error = libusb20_dev_close(pdev);
988         }
989         return (retval);
990 }
991
992 struct libusb20_device *
993 libusb20_dev_alloc(void)
994 {
995         struct libusb20_device *pdev;
996
997         pdev = malloc(sizeof(*pdev));
998         if (pdev == NULL) {
999                 return (NULL);
1000         }
1001         memset(pdev, 0, sizeof(*pdev));
1002
1003         pdev->file = -1;
1004         pdev->file_ctrl = -1;
1005         pdev->methods = &libusb20_dummy_methods;
1006         return (pdev);
1007 }
1008
1009 uint8_t
1010 libusb20_dev_get_config_index(struct libusb20_device *pdev)
1011 {
1012         int error;
1013         uint8_t cfg_index;
1014         uint8_t do_close;
1015
1016         if (!pdev->is_opened) {
1017                 error = libusb20_dev_open(pdev, 0);
1018                 if (error == 0) {
1019                         do_close = 1;
1020                 } else {
1021                         do_close = 0;
1022                 }
1023         } else {
1024                 do_close = 0;
1025         }
1026
1027         error = pdev->methods->get_config_index(pdev, &cfg_index);
1028         if (error)
1029                 cfg_index = 0xFF;       /* current config index */
1030         if (do_close) {
1031                 if (libusb20_dev_close(pdev)) {
1032                         /* ignore */
1033                 }
1034         }
1035         return (cfg_index);
1036 }
1037
1038 uint8_t
1039 libusb20_dev_get_mode(struct libusb20_device *pdev)
1040 {
1041         return (pdev->usb_mode);
1042 }
1043
1044 uint8_t
1045 libusb20_dev_get_speed(struct libusb20_device *pdev)
1046 {
1047         return (pdev->usb_speed);
1048 }
1049
1050 /* if this function returns an error, the device is gone */
1051 int
1052 libusb20_dev_process(struct libusb20_device *pdev)
1053 {
1054         int error;
1055
1056         error = pdev->methods->process(pdev);
1057         return (error);
1058 }
1059
1060 void
1061 libusb20_dev_wait_process(struct libusb20_device *pdev, int timeout)
1062 {
1063         struct pollfd pfd[1];
1064
1065         if (!pdev->is_opened) {
1066                 return;
1067         }
1068         pfd[0].fd = pdev->file;
1069         pfd[0].events = (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM);
1070         pfd[0].revents = 0;
1071
1072         if (poll(pfd, 1, timeout)) {
1073                 /* ignore any error */
1074         }
1075         return;
1076 }
1077
1078 void
1079 libusb20_dev_free(struct libusb20_device *pdev)
1080 {
1081         if (pdev == NULL) {
1082                 /* be NULL safe */
1083                 return;
1084         }
1085         if (pdev->is_opened) {
1086                 if (libusb20_dev_close(pdev)) {
1087                         /* ignore any errors */
1088                 }
1089         }
1090         free(pdev);
1091         return;
1092 }
1093
1094 int
1095 libusb20_dev_get_info(struct libusb20_device *pdev,
1096     struct usb_device_info *pinfo)
1097 {
1098         if (pinfo == NULL)
1099                 return (LIBUSB20_ERROR_INVALID_PARAM);
1100
1101         return (pdev->beMethods->dev_get_info(pdev, pinfo));
1102 }
1103
1104 const char *
1105 libusb20_dev_get_backend_name(struct libusb20_device *pdev)
1106 {
1107         return (pdev->beMethods->get_backend_name());
1108 }
1109
1110 const char *
1111 libusb20_dev_get_desc(struct libusb20_device *pdev)
1112 {
1113         return (pdev->usb_desc);
1114 }
1115
1116 void
1117 libusb20_dev_set_debug(struct libusb20_device *pdev, int debug)
1118 {
1119         pdev->debug = debug;
1120         return;
1121 }
1122
1123 int
1124 libusb20_dev_get_debug(struct libusb20_device *pdev)
1125 {
1126         return (pdev->debug);
1127 }
1128
1129 uint8_t
1130 libusb20_dev_get_address(struct libusb20_device *pdev)
1131 {
1132         return (pdev->device_address);
1133 }
1134
1135 uint8_t
1136 libusb20_dev_get_parent_address(struct libusb20_device *pdev)
1137 {
1138         return (pdev->parent_address);
1139 }
1140
1141 uint8_t
1142 libusb20_dev_get_parent_port(struct libusb20_device *pdev)
1143 {
1144         return (pdev->parent_port);
1145 }
1146
1147 uint8_t
1148 libusb20_dev_get_bus_number(struct libusb20_device *pdev)
1149 {
1150         return (pdev->bus_number);
1151 }
1152
1153 int
1154 libusb20_dev_get_iface_desc(struct libusb20_device *pdev, 
1155     uint8_t iface_index, char *buf, uint8_t len)
1156 {
1157         if ((buf == NULL) || (len == 0))
1158                 return (LIBUSB20_ERROR_INVALID_PARAM);
1159
1160         buf[0] = 0;             /* set default string value */
1161
1162         return (pdev->beMethods->dev_get_iface_desc(
1163             pdev, iface_index, buf, len));
1164 }
1165
1166 /* USB backend operations */
1167
1168 int
1169 libusb20_be_get_dev_quirk(struct libusb20_backend *pbe,
1170     uint16_t quirk_index, struct libusb20_quirk *pq)
1171 {
1172         return (pbe->methods->root_get_dev_quirk(pbe, quirk_index, pq));
1173 }
1174
1175 int
1176 libusb20_be_get_quirk_name(struct libusb20_backend *pbe,
1177     uint16_t quirk_index, struct libusb20_quirk *pq)
1178 {
1179         return (pbe->methods->root_get_quirk_name(pbe, quirk_index, pq));
1180 }
1181
1182 int
1183 libusb20_be_add_dev_quirk(struct libusb20_backend *pbe,
1184     struct libusb20_quirk *pq)
1185 {
1186         return (pbe->methods->root_add_dev_quirk(pbe, pq));
1187 }
1188
1189 int
1190 libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe,
1191     struct libusb20_quirk *pq)
1192 {
1193         return (pbe->methods->root_remove_dev_quirk(pbe, pq));
1194 }
1195
1196 int
1197 libusb20_be_set_template(struct libusb20_backend *pbe, int temp)
1198 {
1199         return (pbe->methods->root_set_template(pbe, temp));
1200 }
1201
1202 int
1203 libusb20_be_get_template(struct libusb20_backend *pbe, int *ptemp)
1204 {
1205         int temp;
1206
1207         if (ptemp == NULL)
1208                 ptemp = &temp;
1209
1210         return (pbe->methods->root_get_template(pbe, ptemp));
1211 }
1212
1213 struct libusb20_device *
1214 libusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev)
1215 {
1216         if (pbe == NULL) {
1217                 pdev = NULL;
1218         } else if (pdev == NULL) {
1219                 pdev = TAILQ_FIRST(&(pbe->usb_devs));
1220         } else {
1221                 pdev = TAILQ_NEXT(pdev, dev_entry);
1222         }
1223         return (pdev);
1224 }
1225
1226 struct libusb20_backend *
1227 libusb20_be_alloc(const struct libusb20_backend_methods *methods)
1228 {
1229         struct libusb20_backend *pbe;
1230
1231         pbe = malloc(sizeof(*pbe));
1232         if (pbe == NULL) {
1233                 return (NULL);
1234         }
1235         memset(pbe, 0, sizeof(*pbe));
1236
1237         TAILQ_INIT(&(pbe->usb_devs));
1238
1239         pbe->methods = methods;         /* set backend methods */
1240
1241         /* do the initial device scan */
1242         if (pbe->methods->init_backend) {
1243                 pbe->methods->init_backend(pbe);
1244         }
1245         return (pbe);
1246 }
1247
1248 struct libusb20_backend *
1249 libusb20_be_alloc_linux(void)
1250 {
1251         return (NULL);
1252 }
1253
1254 struct libusb20_backend *
1255 libusb20_be_alloc_ugen20(void)
1256 {
1257         return (libusb20_be_alloc(&libusb20_ugen20_backend));
1258 }
1259
1260 struct libusb20_backend *
1261 libusb20_be_alloc_default(void)
1262 {
1263         struct libusb20_backend *pbe;
1264
1265 #ifdef __linux__
1266         pbe = libusb20_be_alloc_linux();
1267         if (pbe) {
1268                 return (pbe);
1269         }
1270 #endif
1271         pbe = libusb20_be_alloc_ugen20();
1272         if (pbe) {
1273                 return (pbe);
1274         }
1275         return (NULL);                  /* no backend found */
1276 }
1277
1278 void
1279 libusb20_be_free(struct libusb20_backend *pbe)
1280 {
1281         struct libusb20_device *pdev;
1282
1283         if (pbe == NULL) {
1284                 /* be NULL safe */
1285                 return;
1286         }
1287         while ((pdev = libusb20_be_device_foreach(pbe, NULL))) {
1288                 libusb20_be_dequeue_device(pbe, pdev);
1289                 libusb20_dev_free(pdev);
1290         }
1291         if (pbe->methods->exit_backend) {
1292                 pbe->methods->exit_backend(pbe);
1293         }
1294         /* free backend */
1295         free(pbe);
1296 }
1297
1298 void
1299 libusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev)
1300 {
1301         pdev->beMethods = pbe->methods; /* copy backend methods */
1302         TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry);
1303 }
1304
1305 void
1306 libusb20_be_dequeue_device(struct libusb20_backend *pbe,
1307     struct libusb20_device *pdev)
1308 {
1309         TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry);
1310 }
1311
1312 const char *
1313 libusb20_strerror(int code)
1314 {
1315         switch (code) {
1316         case LIBUSB20_SUCCESS:
1317                 return ("Success");
1318         case LIBUSB20_ERROR_IO:
1319                 return ("I/O error");
1320         case LIBUSB20_ERROR_INVALID_PARAM:
1321                 return ("Invalid parameter");
1322         case LIBUSB20_ERROR_ACCESS:
1323                 return ("Permissions error");
1324         case LIBUSB20_ERROR_NO_DEVICE:
1325                 return ("No device");
1326         case LIBUSB20_ERROR_NOT_FOUND:
1327                 return ("Not found");
1328         case LIBUSB20_ERROR_BUSY:
1329                 return ("Device busy");
1330         case LIBUSB20_ERROR_TIMEOUT:
1331                 return ("Timeout");
1332         case LIBUSB20_ERROR_OVERFLOW:
1333                 return ("Overflow");
1334         case LIBUSB20_ERROR_PIPE:
1335                 return ("Pipe error");
1336         case LIBUSB20_ERROR_INTERRUPTED:
1337                 return ("Interrupted");
1338         case LIBUSB20_ERROR_NO_MEM:
1339                 return ("Out of memory");
1340         case LIBUSB20_ERROR_NOT_SUPPORTED:
1341                 return ("Not supported");
1342         case LIBUSB20_ERROR_OTHER:
1343                 return ("Other error");
1344         default:
1345                 return ("Unknown error");
1346         }
1347 }
1348
1349 const char *
1350 libusb20_error_name(int code)
1351 {
1352         switch (code) {
1353         case LIBUSB20_SUCCESS:
1354                 return ("LIBUSB20_SUCCESS");
1355         case LIBUSB20_ERROR_IO:
1356                 return ("LIBUSB20_ERROR_IO");
1357         case LIBUSB20_ERROR_INVALID_PARAM:
1358                 return ("LIBUSB20_ERROR_INVALID_PARAM");
1359         case LIBUSB20_ERROR_ACCESS:
1360                 return ("LIBUSB20_ERROR_ACCESS");
1361         case LIBUSB20_ERROR_NO_DEVICE:
1362                 return ("LIBUSB20_ERROR_NO_DEVICE");
1363         case LIBUSB20_ERROR_NOT_FOUND:
1364                 return ("LIBUSB20_ERROR_NOT_FOUND");
1365         case LIBUSB20_ERROR_BUSY:
1366                 return ("LIBUSB20_ERROR_BUSY");
1367         case LIBUSB20_ERROR_TIMEOUT:
1368                 return ("LIBUSB20_ERROR_TIMEOUT");
1369         case LIBUSB20_ERROR_OVERFLOW:
1370                 return ("LIBUSB20_ERROR_OVERFLOW");
1371         case LIBUSB20_ERROR_PIPE:
1372                 return ("LIBUSB20_ERROR_PIPE");
1373         case LIBUSB20_ERROR_INTERRUPTED:
1374                 return ("LIBUSB20_ERROR_INTERRUPTED");
1375         case LIBUSB20_ERROR_NO_MEM:
1376                 return ("LIBUSB20_ERROR_NO_MEM");
1377         case LIBUSB20_ERROR_NOT_SUPPORTED:
1378                 return ("LIBUSB20_ERROR_NOT_SUPPORTED");
1379         case LIBUSB20_ERROR_OTHER:
1380                 return ("LIBUSB20_ERROR_OTHER");
1381         default:
1382                 return ("LIBUSB20_ERROR_UNKNOWN");
1383         }
1384 }