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