]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - lib/libusb/libusb20.c
MFC r348797:
[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         int flags;
798
799         /* make sure memory is initialised */
800         memset(ptr, 0, len);
801
802         if (len < 4) {
803                 /* invalid length */
804                 return (LIBUSB20_ERROR_INVALID_PARAM);
805         }
806         LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
807
808         /*
809          * We need to read the USB string in two steps else some USB
810          * devices will complain.
811          */
812         req.bmRequestType =
813             LIBUSB20_REQUEST_TYPE_STANDARD |
814             LIBUSB20_RECIPIENT_DEVICE |
815             LIBUSB20_ENDPOINT_IN;
816         req.bRequest = LIBUSB20_REQUEST_GET_DESCRIPTOR;
817         req.wValue = (LIBUSB20_DT_STRING << 8) | str_index;
818         req.wIndex = langid;
819         req.wLength = 4;                /* bytes */
820
821         error = libusb20_dev_request_sync(pdev, &req,
822             ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK);
823         if (error) {
824                 /* try to request full string */
825                 req.wLength = 255;
826                 flags = 0;
827         } else {
828                 /* extract length and request full string */
829                 req.wLength = *(uint8_t *)ptr;
830                 flags = LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK;
831         }
832         if (req.wLength > len) {
833                 /* partial string read */
834                 req.wLength = len;
835         }
836         error = libusb20_dev_request_sync(pdev, &req, ptr, NULL, 1000, flags);
837         if (error)
838                 return (error);
839
840         if (((uint8_t *)ptr)[1] != LIBUSB20_DT_STRING)
841                 return (LIBUSB20_ERROR_OTHER);
842         return (0);                     /* success */
843 }
844
845 int
846 libusb20_dev_req_string_simple_sync(struct libusb20_device *pdev,
847     uint8_t str_index, void *ptr, uint16_t len)
848 {
849         char *buf;
850         int error;
851         uint16_t langid;
852         uint16_t n;
853         uint16_t i;
854         uint16_t c;
855         uint8_t temp[255];
856         uint8_t swap;
857
858         /* the following code derives from the FreeBSD USB kernel */
859
860         if ((len < 1) || (ptr == NULL)) {
861                 /* too short buffer */
862                 return (LIBUSB20_ERROR_INVALID_PARAM);
863         }
864         error = libusb20_dev_req_string_sync(pdev,
865             0, 0, temp, sizeof(temp));
866         if (error < 0) {
867                 *(uint8_t *)ptr = 0;    /* zero terminate */
868                 return (error);
869         }
870         langid = temp[2] | (temp[3] << 8);
871
872         error = libusb20_dev_req_string_sync(pdev, str_index,
873             langid, temp, sizeof(temp));
874         if (error < 0) {
875                 *(uint8_t *)ptr = 0;    /* zero terminate */
876                 return (error);
877         }
878         if (temp[0] < 2) {
879                 /* string length is too short */
880                 *(uint8_t *)ptr = 0;    /* zero terminate */
881                 return (LIBUSB20_ERROR_OTHER);
882         }
883         /* reserve one byte for terminating zero */
884         len--;
885
886         /* find maximum length */
887         n = (temp[0] / 2) - 1;
888         if (n > len) {
889                 n = len;
890         }
891         /* reset swap state */
892         swap = 3;
893
894         /* setup output buffer pointer */
895         buf = ptr;
896
897         /* convert and filter */
898         for (i = 0; (i != n); i++) {
899                 c = temp[(2 * i) + 2] | (temp[(2 * i) + 3] << 8);
900
901                 /* convert from Unicode, handle buggy strings */
902                 if (((c & 0xff00) == 0) && (swap & 1)) {
903                         /* Little Endian, default */
904                         *buf = c;
905                         swap = 1;
906                 } else if (((c & 0x00ff) == 0) && (swap & 2)) {
907                         /* Big Endian */
908                         *buf = c >> 8;
909                         swap = 2;
910                 } else {
911                         /* skip invalid character */
912                         continue;
913                 }
914                 /*
915                  * Filter by default - we don't allow greater and less than
916                  * signs because they might confuse the dmesg printouts!
917                  */
918                 if ((*buf == '<') || (*buf == '>') || (!isprint(*buf))) {
919                         /* skip invalid character */
920                         continue;
921                 }
922                 buf++;
923         }
924         *buf = 0;                       /* zero terminate string */
925
926         return (0);
927 }
928
929 struct libusb20_config *
930 libusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t configIndex)
931 {
932         struct libusb20_config *retval = NULL;
933         uint8_t *ptr;
934         uint16_t len;
935         uint8_t do_close;
936         int error;
937
938         /*
939          * Catch invalid configuration descriptor reads early on to
940          * avoid issues with devices that don't check for a valid USB
941          * configuration read request.
942          */
943         if (configIndex >= pdev->ddesc.bNumConfigurations)
944                 return (NULL);
945
946         if (!pdev->is_opened) {
947                 error = libusb20_dev_open(pdev, 0);
948                 if (error) {
949                         return (NULL);
950                 }
951                 do_close = 1;
952         } else {
953                 do_close = 0;
954         }
955         error = pdev->methods->get_config_desc_full(pdev,
956             &ptr, &len, configIndex);
957
958         if (error) {
959                 goto done;
960         }
961         /* parse new config descriptor */
962         retval = libusb20_parse_config_desc(ptr);
963
964         /* free config descriptor */
965         free(ptr);
966
967 done:
968         if (do_close) {
969                 error = libusb20_dev_close(pdev);
970         }
971         return (retval);
972 }
973
974 struct libusb20_device *
975 libusb20_dev_alloc(void)
976 {
977         struct libusb20_device *pdev;
978
979         pdev = malloc(sizeof(*pdev));
980         if (pdev == NULL) {
981                 return (NULL);
982         }
983         memset(pdev, 0, sizeof(*pdev));
984
985         pdev->file = -1;
986         pdev->file_ctrl = -1;
987         pdev->methods = &libusb20_dummy_methods;
988         return (pdev);
989 }
990
991 uint8_t
992 libusb20_dev_get_config_index(struct libusb20_device *pdev)
993 {
994         int error;
995         uint8_t cfg_index;
996         uint8_t do_close;
997
998         if (!pdev->is_opened) {
999                 error = libusb20_dev_open(pdev, 0);
1000                 if (error == 0) {
1001                         do_close = 1;
1002                 } else {
1003                         do_close = 0;
1004                 }
1005         } else {
1006                 do_close = 0;
1007         }
1008
1009         error = pdev->methods->get_config_index(pdev, &cfg_index);
1010         if (error)
1011                 cfg_index = 0xFF;       /* current config index */
1012         if (do_close) {
1013                 if (libusb20_dev_close(pdev)) {
1014                         /* ignore */
1015                 }
1016         }
1017         return (cfg_index);
1018 }
1019
1020 uint8_t
1021 libusb20_dev_get_mode(struct libusb20_device *pdev)
1022 {
1023         return (pdev->usb_mode);
1024 }
1025
1026 uint8_t
1027 libusb20_dev_get_speed(struct libusb20_device *pdev)
1028 {
1029         return (pdev->usb_speed);
1030 }
1031
1032 /* if this function returns an error, the device is gone */
1033 int
1034 libusb20_dev_process(struct libusb20_device *pdev)
1035 {
1036         int error;
1037
1038         error = pdev->methods->process(pdev);
1039         return (error);
1040 }
1041
1042 void
1043 libusb20_dev_wait_process(struct libusb20_device *pdev, int timeout)
1044 {
1045         struct pollfd pfd[1];
1046
1047         if (!pdev->is_opened) {
1048                 return;
1049         }
1050         pfd[0].fd = pdev->file;
1051         pfd[0].events = (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM);
1052         pfd[0].revents = 0;
1053
1054         if (poll(pfd, 1, timeout)) {
1055                 /* ignore any error */
1056         }
1057         return;
1058 }
1059
1060 void
1061 libusb20_dev_free(struct libusb20_device *pdev)
1062 {
1063         if (pdev == NULL) {
1064                 /* be NULL safe */
1065                 return;
1066         }
1067         if (pdev->is_opened) {
1068                 if (libusb20_dev_close(pdev)) {
1069                         /* ignore any errors */
1070                 }
1071         }
1072         free(pdev);
1073         return;
1074 }
1075
1076 int
1077 libusb20_dev_get_info(struct libusb20_device *pdev,
1078     struct usb_device_info *pinfo)
1079 {
1080         if (pinfo == NULL)
1081                 return (LIBUSB20_ERROR_INVALID_PARAM);
1082
1083         return (pdev->beMethods->dev_get_info(pdev, pinfo));
1084 }
1085
1086 const char *
1087 libusb20_dev_get_backend_name(struct libusb20_device *pdev)
1088 {
1089         return (pdev->beMethods->get_backend_name());
1090 }
1091
1092 const char *
1093 libusb20_dev_get_desc(struct libusb20_device *pdev)
1094 {
1095         return (pdev->usb_desc);
1096 }
1097
1098 void
1099 libusb20_dev_set_debug(struct libusb20_device *pdev, int debug)
1100 {
1101         pdev->debug = debug;
1102         return;
1103 }
1104
1105 int
1106 libusb20_dev_get_debug(struct libusb20_device *pdev)
1107 {
1108         return (pdev->debug);
1109 }
1110
1111 uint8_t
1112 libusb20_dev_get_address(struct libusb20_device *pdev)
1113 {
1114         return (pdev->device_address);
1115 }
1116
1117 uint8_t
1118 libusb20_dev_get_parent_address(struct libusb20_device *pdev)
1119 {
1120         return (pdev->parent_address);
1121 }
1122
1123 uint8_t
1124 libusb20_dev_get_parent_port(struct libusb20_device *pdev)
1125 {
1126         return (pdev->parent_port);
1127 }
1128
1129 uint8_t
1130 libusb20_dev_get_bus_number(struct libusb20_device *pdev)
1131 {
1132         return (pdev->bus_number);
1133 }
1134
1135 int
1136 libusb20_dev_get_iface_desc(struct libusb20_device *pdev, 
1137     uint8_t iface_index, char *buf, uint8_t len)
1138 {
1139         if ((buf == NULL) || (len == 0))
1140                 return (LIBUSB20_ERROR_INVALID_PARAM);
1141
1142         buf[0] = 0;             /* set default string value */
1143
1144         return (pdev->beMethods->dev_get_iface_desc(
1145             pdev, iface_index, buf, len));
1146 }
1147
1148 /* USB backend operations */
1149
1150 int
1151 libusb20_be_get_dev_quirk(struct libusb20_backend *pbe,
1152     uint16_t quirk_index, struct libusb20_quirk *pq)
1153 {
1154         return (pbe->methods->root_get_dev_quirk(pbe, quirk_index, pq));
1155 }
1156
1157 int
1158 libusb20_be_get_quirk_name(struct libusb20_backend *pbe,
1159     uint16_t quirk_index, struct libusb20_quirk *pq)
1160 {
1161         return (pbe->methods->root_get_quirk_name(pbe, quirk_index, pq));
1162 }
1163
1164 int
1165 libusb20_be_add_dev_quirk(struct libusb20_backend *pbe,
1166     struct libusb20_quirk *pq)
1167 {
1168         return (pbe->methods->root_add_dev_quirk(pbe, pq));
1169 }
1170
1171 int
1172 libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe,
1173     struct libusb20_quirk *pq)
1174 {
1175         return (pbe->methods->root_remove_dev_quirk(pbe, pq));
1176 }
1177
1178 int
1179 libusb20_be_set_template(struct libusb20_backend *pbe, int temp)
1180 {
1181         return (pbe->methods->root_set_template(pbe, temp));
1182 }
1183
1184 int
1185 libusb20_be_get_template(struct libusb20_backend *pbe, int *ptemp)
1186 {
1187         int temp;
1188
1189         if (ptemp == NULL)
1190                 ptemp = &temp;
1191
1192         return (pbe->methods->root_get_template(pbe, ptemp));
1193 }
1194
1195 struct libusb20_device *
1196 libusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev)
1197 {
1198         if (pbe == NULL) {
1199                 pdev = NULL;
1200         } else if (pdev == NULL) {
1201                 pdev = TAILQ_FIRST(&(pbe->usb_devs));
1202         } else {
1203                 pdev = TAILQ_NEXT(pdev, dev_entry);
1204         }
1205         return (pdev);
1206 }
1207
1208 struct libusb20_backend *
1209 libusb20_be_alloc(const struct libusb20_backend_methods *methods)
1210 {
1211         struct libusb20_backend *pbe;
1212
1213         pbe = malloc(sizeof(*pbe));
1214         if (pbe == NULL) {
1215                 return (NULL);
1216         }
1217         memset(pbe, 0, sizeof(*pbe));
1218
1219         TAILQ_INIT(&(pbe->usb_devs));
1220
1221         pbe->methods = methods;         /* set backend methods */
1222
1223         /* do the initial device scan */
1224         if (pbe->methods->init_backend) {
1225                 pbe->methods->init_backend(pbe);
1226         }
1227         return (pbe);
1228 }
1229
1230 struct libusb20_backend *
1231 libusb20_be_alloc_linux(void)
1232 {
1233         return (NULL);
1234 }
1235
1236 struct libusb20_backend *
1237 libusb20_be_alloc_ugen20(void)
1238 {
1239         return (libusb20_be_alloc(&libusb20_ugen20_backend));
1240 }
1241
1242 struct libusb20_backend *
1243 libusb20_be_alloc_default(void)
1244 {
1245         struct libusb20_backend *pbe;
1246
1247 #ifdef __linux__
1248         pbe = libusb20_be_alloc_linux();
1249         if (pbe) {
1250                 return (pbe);
1251         }
1252 #endif
1253         pbe = libusb20_be_alloc_ugen20();
1254         if (pbe) {
1255                 return (pbe);
1256         }
1257         return (NULL);                  /* no backend found */
1258 }
1259
1260 void
1261 libusb20_be_free(struct libusb20_backend *pbe)
1262 {
1263         struct libusb20_device *pdev;
1264
1265         if (pbe == NULL) {
1266                 /* be NULL safe */
1267                 return;
1268         }
1269         while ((pdev = libusb20_be_device_foreach(pbe, NULL))) {
1270                 libusb20_be_dequeue_device(pbe, pdev);
1271                 libusb20_dev_free(pdev);
1272         }
1273         if (pbe->methods->exit_backend) {
1274                 pbe->methods->exit_backend(pbe);
1275         }
1276         /* free backend */
1277         free(pbe);
1278 }
1279
1280 void
1281 libusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev)
1282 {
1283         pdev->beMethods = pbe->methods; /* copy backend methods */
1284         TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry);
1285 }
1286
1287 void
1288 libusb20_be_dequeue_device(struct libusb20_backend *pbe,
1289     struct libusb20_device *pdev)
1290 {
1291         TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry);
1292 }
1293
1294 const char *
1295 libusb20_strerror(int code)
1296 {
1297         switch (code) {
1298         case LIBUSB20_SUCCESS:
1299                 return ("Success");
1300         case LIBUSB20_ERROR_IO:
1301                 return ("I/O error");
1302         case LIBUSB20_ERROR_INVALID_PARAM:
1303                 return ("Invalid parameter");
1304         case LIBUSB20_ERROR_ACCESS:
1305                 return ("Permissions error");
1306         case LIBUSB20_ERROR_NO_DEVICE:
1307                 return ("No device");
1308         case LIBUSB20_ERROR_NOT_FOUND:
1309                 return ("Not found");
1310         case LIBUSB20_ERROR_BUSY:
1311                 return ("Device busy");
1312         case LIBUSB20_ERROR_TIMEOUT:
1313                 return ("Timeout");
1314         case LIBUSB20_ERROR_OVERFLOW:
1315                 return ("Overflow");
1316         case LIBUSB20_ERROR_PIPE:
1317                 return ("Pipe error");
1318         case LIBUSB20_ERROR_INTERRUPTED:
1319                 return ("Interrupted");
1320         case LIBUSB20_ERROR_NO_MEM:
1321                 return ("Out of memory");
1322         case LIBUSB20_ERROR_NOT_SUPPORTED:
1323                 return ("Not supported");
1324         case LIBUSB20_ERROR_OTHER:
1325                 return ("Other error");
1326         default:
1327                 return ("Unknown error");
1328         }
1329 }
1330
1331 const char *
1332 libusb20_error_name(int code)
1333 {
1334         switch (code) {
1335         case LIBUSB20_SUCCESS:
1336                 return ("LIBUSB20_SUCCESS");
1337         case LIBUSB20_ERROR_IO:
1338                 return ("LIBUSB20_ERROR_IO");
1339         case LIBUSB20_ERROR_INVALID_PARAM:
1340                 return ("LIBUSB20_ERROR_INVALID_PARAM");
1341         case LIBUSB20_ERROR_ACCESS:
1342                 return ("LIBUSB20_ERROR_ACCESS");
1343         case LIBUSB20_ERROR_NO_DEVICE:
1344                 return ("LIBUSB20_ERROR_NO_DEVICE");
1345         case LIBUSB20_ERROR_NOT_FOUND:
1346                 return ("LIBUSB20_ERROR_NOT_FOUND");
1347         case LIBUSB20_ERROR_BUSY:
1348                 return ("LIBUSB20_ERROR_BUSY");
1349         case LIBUSB20_ERROR_TIMEOUT:
1350                 return ("LIBUSB20_ERROR_TIMEOUT");
1351         case LIBUSB20_ERROR_OVERFLOW:
1352                 return ("LIBUSB20_ERROR_OVERFLOW");
1353         case LIBUSB20_ERROR_PIPE:
1354                 return ("LIBUSB20_ERROR_PIPE");
1355         case LIBUSB20_ERROR_INTERRUPTED:
1356                 return ("LIBUSB20_ERROR_INTERRUPTED");
1357         case LIBUSB20_ERROR_NO_MEM:
1358                 return ("LIBUSB20_ERROR_NO_MEM");
1359         case LIBUSB20_ERROR_NOT_SUPPORTED:
1360                 return ("LIBUSB20_ERROR_NOT_SUPPORTED");
1361         case LIBUSB20_ERROR_OTHER:
1362                 return ("LIBUSB20_ERROR_OTHER");
1363         default:
1364                 return ("LIBUSB20_ERROR_UNKNOWN");
1365         }
1366 }