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