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