]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - lib/libusb/libusb20.c
MFC r335669:
[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         if (!pdev->is_opened) {
939                 error = libusb20_dev_open(pdev, 0);
940                 if (error) {
941                         return (NULL);
942                 }
943                 do_close = 1;
944         } else {
945                 do_close = 0;
946         }
947         error = pdev->methods->get_config_desc_full(pdev,
948             &ptr, &len, configIndex);
949
950         if (error) {
951                 goto done;
952         }
953         /* parse new config descriptor */
954         retval = libusb20_parse_config_desc(ptr);
955
956         /* free config descriptor */
957         free(ptr);
958
959 done:
960         if (do_close) {
961                 error = libusb20_dev_close(pdev);
962         }
963         return (retval);
964 }
965
966 struct libusb20_device *
967 libusb20_dev_alloc(void)
968 {
969         struct libusb20_device *pdev;
970
971         pdev = malloc(sizeof(*pdev));
972         if (pdev == NULL) {
973                 return (NULL);
974         }
975         memset(pdev, 0, sizeof(*pdev));
976
977         pdev->file = -1;
978         pdev->file_ctrl = -1;
979         pdev->methods = &libusb20_dummy_methods;
980         return (pdev);
981 }
982
983 uint8_t
984 libusb20_dev_get_config_index(struct libusb20_device *pdev)
985 {
986         int error;
987         uint8_t cfg_index;
988         uint8_t do_close;
989
990         if (!pdev->is_opened) {
991                 error = libusb20_dev_open(pdev, 0);
992                 if (error == 0) {
993                         do_close = 1;
994                 } else {
995                         do_close = 0;
996                 }
997         } else {
998                 do_close = 0;
999         }
1000
1001         error = pdev->methods->get_config_index(pdev, &cfg_index);
1002         if (error)
1003                 cfg_index = 0xFF;       /* current config index */
1004         if (do_close) {
1005                 if (libusb20_dev_close(pdev)) {
1006                         /* ignore */
1007                 }
1008         }
1009         return (cfg_index);
1010 }
1011
1012 uint8_t
1013 libusb20_dev_get_mode(struct libusb20_device *pdev)
1014 {
1015         return (pdev->usb_mode);
1016 }
1017
1018 uint8_t
1019 libusb20_dev_get_speed(struct libusb20_device *pdev)
1020 {
1021         return (pdev->usb_speed);
1022 }
1023
1024 /* if this function returns an error, the device is gone */
1025 int
1026 libusb20_dev_process(struct libusb20_device *pdev)
1027 {
1028         int error;
1029
1030         error = pdev->methods->process(pdev);
1031         return (error);
1032 }
1033
1034 void
1035 libusb20_dev_wait_process(struct libusb20_device *pdev, int timeout)
1036 {
1037         struct pollfd pfd[1];
1038
1039         if (!pdev->is_opened) {
1040                 return;
1041         }
1042         pfd[0].fd = pdev->file;
1043         pfd[0].events = (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM);
1044         pfd[0].revents = 0;
1045
1046         if (poll(pfd, 1, timeout)) {
1047                 /* ignore any error */
1048         }
1049         return;
1050 }
1051
1052 void
1053 libusb20_dev_free(struct libusb20_device *pdev)
1054 {
1055         if (pdev == NULL) {
1056                 /* be NULL safe */
1057                 return;
1058         }
1059         if (pdev->is_opened) {
1060                 if (libusb20_dev_close(pdev)) {
1061                         /* ignore any errors */
1062                 }
1063         }
1064         free(pdev);
1065         return;
1066 }
1067
1068 int
1069 libusb20_dev_get_info(struct libusb20_device *pdev,
1070     struct usb_device_info *pinfo)
1071 {
1072         if (pinfo == NULL)
1073                 return (LIBUSB20_ERROR_INVALID_PARAM);
1074
1075         return (pdev->beMethods->dev_get_info(pdev, pinfo));
1076 }
1077
1078 const char *
1079 libusb20_dev_get_backend_name(struct libusb20_device *pdev)
1080 {
1081         return (pdev->beMethods->get_backend_name());
1082 }
1083
1084 const char *
1085 libusb20_dev_get_desc(struct libusb20_device *pdev)
1086 {
1087         return (pdev->usb_desc);
1088 }
1089
1090 void
1091 libusb20_dev_set_debug(struct libusb20_device *pdev, int debug)
1092 {
1093         pdev->debug = debug;
1094         return;
1095 }
1096
1097 int
1098 libusb20_dev_get_debug(struct libusb20_device *pdev)
1099 {
1100         return (pdev->debug);
1101 }
1102
1103 uint8_t
1104 libusb20_dev_get_address(struct libusb20_device *pdev)
1105 {
1106         return (pdev->device_address);
1107 }
1108
1109 uint8_t
1110 libusb20_dev_get_parent_address(struct libusb20_device *pdev)
1111 {
1112         return (pdev->parent_address);
1113 }
1114
1115 uint8_t
1116 libusb20_dev_get_parent_port(struct libusb20_device *pdev)
1117 {
1118         return (pdev->parent_port);
1119 }
1120
1121 uint8_t
1122 libusb20_dev_get_bus_number(struct libusb20_device *pdev)
1123 {
1124         return (pdev->bus_number);
1125 }
1126
1127 int
1128 libusb20_dev_get_iface_desc(struct libusb20_device *pdev, 
1129     uint8_t iface_index, char *buf, uint8_t len)
1130 {
1131         if ((buf == NULL) || (len == 0))
1132                 return (LIBUSB20_ERROR_INVALID_PARAM);
1133
1134         buf[0] = 0;             /* set default string value */
1135
1136         return (pdev->beMethods->dev_get_iface_desc(
1137             pdev, iface_index, buf, len));
1138 }
1139
1140 /* USB backend operations */
1141
1142 int
1143 libusb20_be_get_dev_quirk(struct libusb20_backend *pbe,
1144     uint16_t quirk_index, struct libusb20_quirk *pq)
1145 {
1146         return (pbe->methods->root_get_dev_quirk(pbe, quirk_index, pq));
1147 }
1148
1149 int
1150 libusb20_be_get_quirk_name(struct libusb20_backend *pbe,
1151     uint16_t quirk_index, struct libusb20_quirk *pq)
1152 {
1153         return (pbe->methods->root_get_quirk_name(pbe, quirk_index, pq));
1154 }
1155
1156 int
1157 libusb20_be_add_dev_quirk(struct libusb20_backend *pbe,
1158     struct libusb20_quirk *pq)
1159 {
1160         return (pbe->methods->root_add_dev_quirk(pbe, pq));
1161 }
1162
1163 int
1164 libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe,
1165     struct libusb20_quirk *pq)
1166 {
1167         return (pbe->methods->root_remove_dev_quirk(pbe, pq));
1168 }
1169
1170 int
1171 libusb20_be_set_template(struct libusb20_backend *pbe, int temp)
1172 {
1173         return (pbe->methods->root_set_template(pbe, temp));
1174 }
1175
1176 int
1177 libusb20_be_get_template(struct libusb20_backend *pbe, int *ptemp)
1178 {
1179         int temp;
1180
1181         if (ptemp == NULL)
1182                 ptemp = &temp;
1183
1184         return (pbe->methods->root_get_template(pbe, ptemp));
1185 }
1186
1187 struct libusb20_device *
1188 libusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev)
1189 {
1190         if (pbe == NULL) {
1191                 pdev = NULL;
1192         } else if (pdev == NULL) {
1193                 pdev = TAILQ_FIRST(&(pbe->usb_devs));
1194         } else {
1195                 pdev = TAILQ_NEXT(pdev, dev_entry);
1196         }
1197         return (pdev);
1198 }
1199
1200 struct libusb20_backend *
1201 libusb20_be_alloc(const struct libusb20_backend_methods *methods)
1202 {
1203         struct libusb20_backend *pbe;
1204
1205         pbe = malloc(sizeof(*pbe));
1206         if (pbe == NULL) {
1207                 return (NULL);
1208         }
1209         memset(pbe, 0, sizeof(*pbe));
1210
1211         TAILQ_INIT(&(pbe->usb_devs));
1212
1213         pbe->methods = methods;         /* set backend methods */
1214
1215         /* do the initial device scan */
1216         if (pbe->methods->init_backend) {
1217                 pbe->methods->init_backend(pbe);
1218         }
1219         return (pbe);
1220 }
1221
1222 struct libusb20_backend *
1223 libusb20_be_alloc_linux(void)
1224 {
1225         return (NULL);
1226 }
1227
1228 struct libusb20_backend *
1229 libusb20_be_alloc_ugen20(void)
1230 {
1231         return (libusb20_be_alloc(&libusb20_ugen20_backend));
1232 }
1233
1234 struct libusb20_backend *
1235 libusb20_be_alloc_default(void)
1236 {
1237         struct libusb20_backend *pbe;
1238
1239 #ifdef __linux__
1240         pbe = libusb20_be_alloc_linux();
1241         if (pbe) {
1242                 return (pbe);
1243         }
1244 #endif
1245         pbe = libusb20_be_alloc_ugen20();
1246         if (pbe) {
1247                 return (pbe);
1248         }
1249         return (NULL);                  /* no backend found */
1250 }
1251
1252 void
1253 libusb20_be_free(struct libusb20_backend *pbe)
1254 {
1255         struct libusb20_device *pdev;
1256
1257         if (pbe == NULL) {
1258                 /* be NULL safe */
1259                 return;
1260         }
1261         while ((pdev = libusb20_be_device_foreach(pbe, NULL))) {
1262                 libusb20_be_dequeue_device(pbe, pdev);
1263                 libusb20_dev_free(pdev);
1264         }
1265         if (pbe->methods->exit_backend) {
1266                 pbe->methods->exit_backend(pbe);
1267         }
1268         /* free backend */
1269         free(pbe);
1270 }
1271
1272 void
1273 libusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev)
1274 {
1275         pdev->beMethods = pbe->methods; /* copy backend methods */
1276         TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry);
1277 }
1278
1279 void
1280 libusb20_be_dequeue_device(struct libusb20_backend *pbe,
1281     struct libusb20_device *pdev)
1282 {
1283         TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry);
1284 }
1285
1286 const char *
1287 libusb20_strerror(int code)
1288 {
1289         switch (code) {
1290         case LIBUSB20_SUCCESS:
1291                 return ("Success");
1292         case LIBUSB20_ERROR_IO:
1293                 return ("I/O error");
1294         case LIBUSB20_ERROR_INVALID_PARAM:
1295                 return ("Invalid parameter");
1296         case LIBUSB20_ERROR_ACCESS:
1297                 return ("Permissions error");
1298         case LIBUSB20_ERROR_NO_DEVICE:
1299                 return ("No device");
1300         case LIBUSB20_ERROR_NOT_FOUND:
1301                 return ("Not found");
1302         case LIBUSB20_ERROR_BUSY:
1303                 return ("Device busy");
1304         case LIBUSB20_ERROR_TIMEOUT:
1305                 return ("Timeout");
1306         case LIBUSB20_ERROR_OVERFLOW:
1307                 return ("Overflow");
1308         case LIBUSB20_ERROR_PIPE:
1309                 return ("Pipe error");
1310         case LIBUSB20_ERROR_INTERRUPTED:
1311                 return ("Interrupted");
1312         case LIBUSB20_ERROR_NO_MEM:
1313                 return ("Out of memory");
1314         case LIBUSB20_ERROR_NOT_SUPPORTED:
1315                 return ("Not supported");
1316         case LIBUSB20_ERROR_OTHER:
1317                 return ("Other error");
1318         default:
1319                 return ("Unknown error");
1320         }
1321 }
1322
1323 const char *
1324 libusb20_error_name(int code)
1325 {
1326         switch (code) {
1327         case LIBUSB20_SUCCESS:
1328                 return ("LIBUSB20_SUCCESS");
1329         case LIBUSB20_ERROR_IO:
1330                 return ("LIBUSB20_ERROR_IO");
1331         case LIBUSB20_ERROR_INVALID_PARAM:
1332                 return ("LIBUSB20_ERROR_INVALID_PARAM");
1333         case LIBUSB20_ERROR_ACCESS:
1334                 return ("LIBUSB20_ERROR_ACCESS");
1335         case LIBUSB20_ERROR_NO_DEVICE:
1336                 return ("LIBUSB20_ERROR_NO_DEVICE");
1337         case LIBUSB20_ERROR_NOT_FOUND:
1338                 return ("LIBUSB20_ERROR_NOT_FOUND");
1339         case LIBUSB20_ERROR_BUSY:
1340                 return ("LIBUSB20_ERROR_BUSY");
1341         case LIBUSB20_ERROR_TIMEOUT:
1342                 return ("LIBUSB20_ERROR_TIMEOUT");
1343         case LIBUSB20_ERROR_OVERFLOW:
1344                 return ("LIBUSB20_ERROR_OVERFLOW");
1345         case LIBUSB20_ERROR_PIPE:
1346                 return ("LIBUSB20_ERROR_PIPE");
1347         case LIBUSB20_ERROR_INTERRUPTED:
1348                 return ("LIBUSB20_ERROR_INTERRUPTED");
1349         case LIBUSB20_ERROR_NO_MEM:
1350                 return ("LIBUSB20_ERROR_NO_MEM");
1351         case LIBUSB20_ERROR_NOT_SUPPORTED:
1352                 return ("LIBUSB20_ERROR_NOT_SUPPORTED");
1353         case LIBUSB20_ERROR_OTHER:
1354                 return ("LIBUSB20_ERROR_OTHER");
1355         default:
1356                 return ("LIBUSB20_ERROR_UNKNOWN");
1357         }
1358 }