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