]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libusb20/libusb20.c
Add a limit on namecache entries.
[FreeBSD/FreeBSD.git] / lib / libusb20 / libusb20.c
1 /* $FreeBSD$ */
2 /*-
3  * Copyright (c) 2008 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_claim_interface (void *)dummy_int
69 #define dummy_release_interface (void *)dummy_int
70 #define dummy_set_alt_index (void *)dummy_int
71 #define dummy_reset_device (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
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_pending) {
267                 /* transfer not pending */
268                 return;
269         }
270         if (xfer->is_cancel) {
271                 /* already cancelling */
272                 return;
273         }
274         xfer->is_cancel = 1;            /* we are cancelling */
275
276         (xfer->pdev->methods->tr_cancel_async) (xfer);
277         return;
278 }
279
280 void
281 libusb20_tr_drain(struct libusb20_transfer *xfer)
282 {
283         /* make sure that we are cancelling */
284         libusb20_tr_stop(xfer);
285
286         if (xfer->is_pending) {
287                 xfer->is_draining = 1;
288         }
289         return;
290 }
291
292 void
293 libusb20_tr_clear_stall_sync(struct libusb20_transfer *xfer)
294 {
295         (xfer->pdev->methods->tr_clear_stall_sync) (xfer);
296         return;
297 }
298
299 void
300 libusb20_tr_set_buffer(struct libusb20_transfer *xfer, void *buffer, uint16_t frIndex)
301 {
302         xfer->ppBuffer[frIndex] = buffer;
303         return;
304 }
305
306 void
307 libusb20_tr_set_callback(struct libusb20_transfer *xfer, libusb20_tr_callback_t *cb)
308 {
309         xfer->callback = cb;
310         return;
311 }
312
313 void
314 libusb20_tr_set_flags(struct libusb20_transfer *xfer, uint8_t flags)
315 {
316         xfer->flags = flags;
317         return;
318 }
319
320 void
321 libusb20_tr_set_length(struct libusb20_transfer *xfer, uint32_t length, uint16_t frIndex)
322 {
323         xfer->pLength[frIndex] = length;
324         return;
325 }
326
327 void
328 libusb20_tr_set_priv_sc0(struct libusb20_transfer *xfer, void *sc0)
329 {
330         xfer->priv_sc0 = sc0;
331         return;
332 }
333
334 void
335 libusb20_tr_set_priv_sc1(struct libusb20_transfer *xfer, void *sc1)
336 {
337         xfer->priv_sc1 = sc1;
338         return;
339 }
340
341 void
342 libusb20_tr_set_timeout(struct libusb20_transfer *xfer, uint32_t timeout)
343 {
344         xfer->timeout = timeout;
345         return;
346 }
347
348 void
349 libusb20_tr_set_total_frames(struct libusb20_transfer *xfer, uint32_t nFrames)
350 {
351         if (nFrames > xfer->maxFrames) {
352                 /* should not happen */
353                 nFrames = xfer->maxFrames;
354         }
355         xfer->nFrames = nFrames;
356         return;
357 }
358
359 void
360 libusb20_tr_setup_bulk(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout)
361 {
362         xfer->ppBuffer[0] = pBuf;
363         xfer->pLength[0] = length;
364         xfer->timeout = timeout;
365         xfer->nFrames = 1;
366         return;
367 }
368
369 void
370 libusb20_tr_setup_control(struct libusb20_transfer *xfer, void *psetup, void *pBuf, uint32_t timeout)
371 {
372         uint16_t len;
373
374         xfer->ppBuffer[0] = psetup;
375         xfer->pLength[0] = 8;           /* fixed */
376         xfer->timeout = timeout;
377
378         len = ((uint8_t *)psetup)[6] | (((uint8_t *)psetup)[7] << 8);
379
380         if (len != 0) {
381                 xfer->nFrames = 2;
382                 xfer->ppBuffer[1] = pBuf;
383                 xfer->pLength[1] = len;
384         } else {
385                 xfer->nFrames = 1;
386         }
387         return;
388 }
389
390 void
391 libusb20_tr_setup_intr(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout)
392 {
393         xfer->ppBuffer[0] = pBuf;
394         xfer->pLength[0] = length;
395         xfer->timeout = timeout;
396         xfer->nFrames = 1;
397         return;
398 }
399
400 void
401 libusb20_tr_setup_isoc(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint16_t frIndex)
402 {
403         if (frIndex >= xfer->maxFrames) {
404                 /* should not happen */
405                 return;
406         }
407         xfer->ppBuffer[frIndex] = pBuf;
408         xfer->pLength[frIndex] = length;
409         return;
410 }
411
412 void
413 libusb20_tr_submit(struct libusb20_transfer *xfer)
414 {
415         if (xfer->is_pending) {
416                 /* should not happen */
417                 return;
418         }
419         xfer->is_pending = 1;           /* we are pending */
420         xfer->is_cancel = 0;            /* not cancelling */
421         xfer->is_restart = 0;           /* not restarting */
422
423         (xfer->pdev->methods->tr_submit) (xfer);
424         return;
425 }
426
427 void
428 libusb20_tr_start(struct libusb20_transfer *xfer)
429 {
430         if (xfer->is_pending) {
431                 if (xfer->is_cancel) {
432                         /* cancelling - restart */
433                         xfer->is_restart = 1;
434                 }
435                 /* transfer not pending */
436                 return;
437         }
438         /* get into the callback */
439         libusb20_tr_callback_wrapper(xfer);
440         return;
441 }
442
443 /* USB device operations */
444
445 int
446 libusb20_dev_claim_interface(struct libusb20_device *pdev, uint8_t ifaceIndex)
447 {
448         int error;
449
450         if (ifaceIndex >= 32) {
451                 error = LIBUSB20_ERROR_INVALID_PARAM;
452         } else if (pdev->claimed_interfaces & (1 << ifaceIndex)) {
453                 error = LIBUSB20_ERROR_NOT_FOUND;
454         } else {
455                 error = (pdev->methods->claim_interface) (pdev, ifaceIndex);
456         }
457         if (!error) {
458                 pdev->claimed_interfaces |= (1 << ifaceIndex);
459         }
460         return (error);
461 }
462
463 int
464 libusb20_dev_close(struct libusb20_device *pdev)
465 {
466         struct libusb20_transfer *xfer;
467         uint16_t x;
468         int error = 0;
469
470         if (!pdev->is_opened) {
471                 return (LIBUSB20_ERROR_OTHER);
472         }
473         for (x = 0; x != pdev->nTransfer; x++) {
474                 xfer = pdev->pTransfer + x;
475
476                 libusb20_tr_drain(xfer);
477         }
478
479         if (pdev->pTransfer != NULL) {
480                 free(pdev->pTransfer);
481                 pdev->pTransfer = NULL;
482         }
483         error = (pdev->beMethods->close_device) (pdev);
484
485         pdev->methods = &libusb20_dummy_methods;
486
487         pdev->is_opened = 0;
488
489         pdev->claimed_interfaces = 0;
490
491         return (error);
492 }
493
494 int
495 libusb20_dev_detach_kernel_driver(struct libusb20_device *pdev, uint8_t ifaceIndex)
496 {
497         int error;
498
499         error = (pdev->methods->detach_kernel_driver) (pdev, ifaceIndex);
500         return (error);
501 }
502
503 struct LIBUSB20_DEVICE_DESC_DECODED *
504 libusb20_dev_get_device_desc(struct libusb20_device *pdev)
505 {
506         return (&(pdev->ddesc));
507 }
508
509 int
510 libusb20_dev_get_fd(struct libusb20_device *pdev)
511 {
512         return (pdev->file);
513 }
514
515 int
516 libusb20_dev_kernel_driver_active(struct libusb20_device *pdev, uint8_t ifaceIndex)
517 {
518         int error;
519
520         error = (pdev->methods->kernel_driver_active) (pdev, ifaceIndex);
521         return (error);
522 }
523
524 int
525 libusb20_dev_open(struct libusb20_device *pdev, uint16_t nTransferMax)
526 {
527         struct libusb20_transfer *xfer;
528         uint32_t size;
529         uint16_t x;
530         int error;
531
532         if (pdev->is_opened) {
533                 return (LIBUSB20_ERROR_BUSY);
534         }
535         if (nTransferMax >= 256) {
536                 return (LIBUSB20_ERROR_INVALID_PARAM);
537         } else if (nTransferMax != 0) {
538                 size = sizeof(pdev->pTransfer[0]) * nTransferMax;
539                 pdev->pTransfer = malloc(size);
540                 if (pdev->pTransfer == NULL) {
541                         return (LIBUSB20_ERROR_NO_MEM);
542                 }
543                 memset(pdev->pTransfer, 0, size);
544         }
545         /* initialise all transfers */
546         for (x = 0; x != nTransferMax; x++) {
547
548                 xfer = pdev->pTransfer + x;
549
550                 xfer->pdev = pdev;
551                 xfer->trIndex = x;
552                 xfer->callback = &dummy_callback;
553         }
554
555         /* set "nTransfer" early */
556         pdev->nTransfer = nTransferMax;
557
558         error = (pdev->beMethods->open_device) (pdev, nTransferMax);
559
560         if (error) {
561                 if (pdev->pTransfer != NULL) {
562                         free(pdev->pTransfer);
563                         pdev->pTransfer = NULL;
564                 }
565                 pdev->file = -1;
566                 pdev->file_ctrl = -1;
567                 pdev->nTransfer = 0;
568         } else {
569                 pdev->is_opened = 1;
570         }
571         return (error);
572 }
573
574 int
575 libusb20_dev_release_interface(struct libusb20_device *pdev, uint8_t ifaceIndex)
576 {
577         int error;
578
579         if (ifaceIndex >= 32) {
580                 error = LIBUSB20_ERROR_INVALID_PARAM;
581         } else if (!(pdev->claimed_interfaces & (1 << ifaceIndex))) {
582                 error = LIBUSB20_ERROR_NOT_FOUND;
583         } else {
584                 error = (pdev->methods->release_interface) (pdev, ifaceIndex);
585         }
586         if (!error) {
587                 pdev->claimed_interfaces &= ~(1 << ifaceIndex);
588         }
589         return (error);
590 }
591
592 int
593 libusb20_dev_reset(struct libusb20_device *pdev)
594 {
595         int error;
596
597         error = (pdev->methods->reset_device) (pdev);
598         return (error);
599 }
600
601 int
602 libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode)
603 {
604         int error;
605
606         error = (pdev->methods->set_power_mode) (pdev, power_mode);
607         return (error);
608 }
609
610 uint8_t
611 libusb20_dev_get_power_mode(struct libusb20_device *pdev)
612 {
613         int error;
614         uint8_t power_mode;
615
616         error = (pdev->methods->get_power_mode) (pdev, &power_mode);
617         if (error)
618                 power_mode = LIBUSB20_POWER_ON; /* fake power mode */
619         return (power_mode);
620 }
621
622 int
623 libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t ifaceIndex, uint8_t altIndex)
624 {
625         int error;
626
627         error = (pdev->methods->set_alt_index) (pdev, ifaceIndex, altIndex);
628         return (error);
629 }
630
631 int
632 libusb20_dev_set_config_index(struct libusb20_device *pdev, uint8_t configIndex)
633 {
634         int error;
635
636         error = (pdev->methods->set_config_index) (pdev, configIndex);
637         return (error);
638 }
639
640 int
641 libusb20_dev_request_sync(struct libusb20_device *pdev,
642     struct LIBUSB20_CONTROL_SETUP_DECODED *setup, void *data,
643     uint16_t *pactlen, uint32_t timeout, uint8_t flags)
644 {
645         int error;
646
647         error = (pdev->methods->do_request_sync) (pdev,
648             setup, data, pactlen, timeout, flags);
649         return (error);
650 }
651
652 int
653 libusb20_dev_req_string_sync(struct libusb20_device *pdev,
654     uint8_t str_index, uint16_t langid, void *ptr, uint16_t len)
655 {
656         struct LIBUSB20_CONTROL_SETUP_DECODED req;
657         int error;
658
659         if (len < 4) {
660                 /* invalid length */
661                 return (LIBUSB20_ERROR_INVALID_PARAM);
662         }
663         LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
664
665         /*
666          * We need to read the USB string in two steps else some USB
667          * devices will complain.
668          */
669         req.bmRequestType =
670             LIBUSB20_REQUEST_TYPE_STANDARD |
671             LIBUSB20_RECIPIENT_DEVICE |
672             LIBUSB20_ENDPOINT_IN;
673         req.bRequest = LIBUSB20_REQUEST_GET_DESCRIPTOR;
674         req.wValue = (LIBUSB20_DT_STRING << 8) | str_index;
675         req.wIndex = langid;
676         req.wLength = 4;                /* bytes */
677
678         error = libusb20_dev_request_sync(pdev, &req,
679             ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK);
680         if (error) {
681                 return (error);
682         }
683         req.wLength = *(uint8_t *)ptr;  /* bytes */
684         if (req.wLength > len) {
685                 /* partial string read */
686                 req.wLength = len;
687         }
688         error = libusb20_dev_request_sync(pdev, &req,
689             ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK);
690
691         if (error) {
692                 return (error);
693         }
694         if (((uint8_t *)ptr)[1] != LIBUSB20_DT_STRING) {
695                 return (LIBUSB20_ERROR_OTHER);
696         }
697         return (0);                     /* success */
698 }
699
700 int
701 libusb20_dev_req_string_simple_sync(struct libusb20_device *pdev,
702     uint8_t str_index, void *ptr, uint16_t len)
703 {
704         char *buf;
705         int error;
706         uint16_t langid;
707         uint16_t n;
708         uint16_t i;
709         uint16_t c;
710         uint8_t temp[255];
711         uint8_t swap;
712
713         /* the following code derives from the FreeBSD USB kernel */
714
715         if ((len < 1) || (ptr == NULL)) {
716                 /* too short buffer */
717                 return (LIBUSB20_ERROR_INVALID_PARAM);
718         }
719         error = libusb20_dev_req_string_sync(pdev,
720             0, 0, temp, sizeof(temp));
721         if (error < 0) {
722                 *(uint8_t *)ptr = 0;    /* zero terminate */
723                 return (error);
724         }
725         langid = temp[2] | (temp[3] << 8);
726
727         error = libusb20_dev_req_string_sync(pdev, str_index,
728             langid, temp, sizeof(temp));
729         if (error < 0) {
730                 *(uint8_t *)ptr = 0;    /* zero terminate */
731                 return (error);
732         }
733         if (temp[0] < 2) {
734                 /* string length is too short */
735                 *(uint8_t *)ptr = 0;    /* zero terminate */
736                 return (LIBUSB20_ERROR_OTHER);
737         }
738         /* reserve one byte for terminating zero */
739         len--;
740
741         /* find maximum length */
742         n = (temp[0] / 2) - 1;
743         if (n > len) {
744                 n = len;
745         }
746         /* reset swap state */
747         swap = 3;
748
749         /* setup output buffer pointer */
750         buf = ptr;
751
752         /* convert and filter */
753         for (i = 0; (i != n); i++) {
754                 c = temp[(2 * i) + 2] | (temp[(2 * i) + 3] << 8);
755
756                 /* convert from Unicode, handle buggy strings */
757                 if (((c & 0xff00) == 0) && (swap & 1)) {
758                         /* Little Endian, default */
759                         *buf = c;
760                         swap = 1;
761                 } else if (((c & 0x00ff) == 0) && (swap & 2)) {
762                         /* Big Endian */
763                         *buf = c >> 8;
764                         swap = 2;
765                 } else {
766                         /* skip invalid character */
767                         continue;
768                 }
769                 /*
770                  * Filter by default - we don't allow greater and less than
771                  * signs because they might confuse the dmesg printouts!
772                  */
773                 if ((*buf == '<') || (*buf == '>') || (!isprint(*buf))) {
774                         /* skip invalid character */
775                         continue;
776                 }
777                 buf++;
778         }
779         *buf = 0;                       /* zero terminate string */
780
781         return (0);
782 }
783
784 struct libusb20_config *
785 libusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t configIndex)
786 {
787         struct libusb20_config *retval = NULL;
788         uint8_t *ptr;
789         uint16_t len;
790         uint8_t do_close;
791         int error;
792
793         if (!pdev->is_opened) {
794                 error = libusb20_dev_open(pdev, 0);
795                 if (error) {
796                         return (NULL);
797                 }
798                 do_close = 1;
799         } else {
800                 do_close = 0;
801         }
802         error = (pdev->methods->get_config_desc_full) (pdev,
803             &ptr, &len, configIndex);
804
805         if (error) {
806                 goto done;
807         }
808         /* parse new config descriptor */
809         retval = libusb20_parse_config_desc(ptr);
810
811         /* free config descriptor */
812         free(ptr);
813
814 done:
815         if (do_close) {
816                 error = libusb20_dev_close(pdev);
817         }
818         return (retval);
819 }
820
821 struct libusb20_device *
822 libusb20_dev_alloc(void)
823 {
824         struct libusb20_device *pdev;
825
826         pdev = malloc(sizeof(*pdev));
827         if (pdev == NULL) {
828                 return (NULL);
829         }
830         memset(pdev, 0, sizeof(*pdev));
831
832         pdev->file = -1;
833         pdev->file_ctrl = -1;
834         pdev->methods = &libusb20_dummy_methods;
835         return (pdev);
836 }
837
838 uint8_t
839 libusb20_dev_get_config_index(struct libusb20_device *pdev)
840 {
841         int error;
842         uint8_t cfg_index;
843         uint8_t do_close;
844
845         if (!pdev->is_opened) {
846                 error = libusb20_dev_open(pdev, 0);
847                 if (error == 0) {
848                         do_close = 1;
849                 } else {
850                         do_close = 0;
851                 }
852         } else {
853                 do_close = 0;
854         }
855
856         error = (pdev->methods->get_config_index) (pdev, &cfg_index);
857         if (error) {
858                 cfg_index = 0 - 1;      /* current config index */
859         }
860         if (do_close) {
861                 if (libusb20_dev_close(pdev)) {
862                         /* ignore */
863                 }
864         }
865         return (cfg_index);
866 }
867
868 uint8_t
869 libusb20_dev_get_mode(struct libusb20_device *pdev)
870 {
871         return (pdev->usb_mode);
872 }
873
874 uint8_t
875 libusb20_dev_get_speed(struct libusb20_device *pdev)
876 {
877         return (pdev->usb_speed);
878 }
879
880 /* if this function returns an error, the device is gone */
881 int
882 libusb20_dev_process(struct libusb20_device *pdev)
883 {
884         int error;
885
886         error = (pdev->methods->process) (pdev);
887         return (error);
888 }
889
890 void
891 libusb20_dev_wait_process(struct libusb20_device *pdev, int timeout)
892 {
893         struct pollfd pfd[1];
894
895         if (!pdev->is_opened) {
896                 return;
897         }
898         pfd[0].fd = pdev->file;
899         pfd[0].events = (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM);
900         pfd[0].revents = 0;
901
902         if (poll(pfd, 1, timeout)) {
903                 /* ignore any error */
904         }
905         return;
906 }
907
908 void
909 libusb20_dev_free(struct libusb20_device *pdev)
910 {
911         if (pdev == NULL) {
912                 /* be NULL safe */
913                 return;
914         }
915         if (pdev->is_opened) {
916                 if (libusb20_dev_close(pdev)) {
917                         /* ignore any errors */
918                 }
919         }
920         free(pdev);
921         return;
922 }
923
924 const char *
925 libusb20_dev_get_backend_name(struct libusb20_device *pdev)
926 {
927         return ((pdev->beMethods->get_backend_name) ());
928 }
929
930 const char *
931 libusb20_dev_get_desc(struct libusb20_device *pdev)
932 {
933         return (pdev->usb_desc);
934 }
935
936 void
937 libusb20_dev_set_debug(struct libusb20_device *pdev, int debug)
938 {
939         pdev->debug = debug;
940         return;
941 }
942
943 int
944 libusb20_dev_get_debug(struct libusb20_device *pdev)
945 {
946         return (pdev->debug);
947 }
948
949 uint8_t
950 libusb20_dev_get_address(struct libusb20_device *pdev)
951 {
952         return (pdev->device_address);
953 }
954
955 uint8_t
956 libusb20_dev_get_bus_number(struct libusb20_device *pdev)
957 {
958         return (pdev->bus_number);
959 }
960
961 int
962 libusb20_dev_set_owner(struct libusb20_device *pdev, uid_t user, gid_t group)
963 {
964         return ((pdev->beMethods->dev_set_owner) (pdev, user, group));
965 }
966
967 int
968 libusb20_dev_set_perm(struct libusb20_device *pdev, mode_t mode)
969 {
970         return ((pdev->beMethods->dev_set_perm) (pdev, mode));
971 }
972
973 int
974 libusb20_dev_set_iface_owner(struct libusb20_device *pdev, uint8_t iface_index, uid_t user, gid_t group)
975 {
976         return ((pdev->beMethods->dev_set_iface_owner) (pdev, iface_index, user, group));
977 }
978
979 int
980 libusb20_dev_set_iface_perm(struct libusb20_device *pdev, uint8_t iface_index, mode_t mode)
981 {
982         return ((pdev->beMethods->dev_set_iface_perm) (pdev, iface_index, mode));
983 }
984
985 int
986 libusb20_dev_get_owner(struct libusb20_device *pdev, uid_t *user, gid_t *group)
987 {
988         uid_t a;
989         gid_t b;
990
991         if (user == NULL)
992                 user = &a;
993         if (group == NULL)
994                 group = &b;
995
996         return ((pdev->beMethods->dev_get_owner) (pdev, user, group));
997 }
998
999 int
1000 libusb20_dev_get_perm(struct libusb20_device *pdev, mode_t *mode)
1001 {
1002         mode_t a;
1003
1004         if (mode == NULL)
1005                 mode = &a;
1006         return ((pdev->beMethods->dev_get_perm) (pdev, mode));
1007 }
1008
1009 int
1010 libusb20_dev_get_iface_owner(struct libusb20_device *pdev, uint8_t iface_index, uid_t *user, gid_t *group)
1011 {
1012         uid_t a;
1013         gid_t b;
1014
1015         if (user == NULL)
1016                 user = &a;
1017         if (group == NULL)
1018                 group = &b;
1019
1020         return ((pdev->beMethods->dev_get_iface_owner) (pdev, iface_index, user, group));
1021 }
1022
1023 int
1024 libusb20_dev_get_iface_perm(struct libusb20_device *pdev, uint8_t iface_index, mode_t *mode)
1025 {
1026         mode_t a;
1027
1028         if (mode == NULL)
1029                 mode = &a;
1030         return ((pdev->beMethods->dev_get_iface_perm) (pdev, iface_index, mode));
1031 }
1032
1033 /* USB bus operations */
1034
1035 int
1036 libusb20_bus_set_owner(struct libusb20_backend *pbe, uint8_t bus, uid_t user, gid_t group)
1037 {
1038         return ((pbe->methods->bus_set_owner) (pbe, bus, user, group));
1039 }
1040
1041 int
1042 libusb20_bus_set_perm(struct libusb20_backend *pbe, uint8_t bus, mode_t mode)
1043 {
1044         return ((pbe->methods->bus_set_perm) (pbe, bus, mode));
1045 }
1046
1047 int
1048 libusb20_bus_get_owner(struct libusb20_backend *pbe, uint8_t bus, uid_t *user, gid_t *group)
1049 {
1050         uid_t a;
1051         gid_t b;
1052
1053         if (user == NULL)
1054                 user = &a;
1055         if (group == NULL)
1056                 group = &b;
1057         return ((pbe->methods->bus_get_owner) (pbe, bus, user, group));
1058 }
1059
1060 int
1061 libusb20_bus_get_perm(struct libusb20_backend *pbe, uint8_t bus, mode_t *mode)
1062 {
1063         mode_t a;
1064
1065         if (mode == NULL)
1066                 mode = &a;
1067         return ((pbe->methods->bus_get_perm) (pbe, bus, mode));
1068 }
1069
1070 /* USB backend operations */
1071
1072 int
1073 libusb20_be_get_dev_quirk(struct libusb20_backend *pbe,
1074     uint16_t quirk_index, struct libusb20_quirk *pq)
1075 {
1076         return ((pbe->methods->root_get_dev_quirk) (pbe, quirk_index, pq));
1077 }
1078
1079 int
1080 libusb20_be_get_quirk_name(struct libusb20_backend *pbe,
1081     uint16_t quirk_index, struct libusb20_quirk *pq)
1082 {
1083         return ((pbe->methods->root_get_quirk_name) (pbe, quirk_index, pq));
1084 }
1085
1086 int
1087 libusb20_be_add_dev_quirk(struct libusb20_backend *pbe,
1088     struct libusb20_quirk *pq)
1089 {
1090         return ((pbe->methods->root_add_dev_quirk) (pbe, pq));
1091 }
1092
1093 int
1094 libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe,
1095     struct libusb20_quirk *pq)
1096 {
1097         return ((pbe->methods->root_remove_dev_quirk) (pbe, pq));
1098 }
1099
1100 int
1101 libusb20_be_set_owner(struct libusb20_backend *pbe, uid_t user, gid_t group)
1102 {
1103         return ((pbe->methods->root_set_owner) (pbe, user, group));
1104 }
1105
1106 int
1107 libusb20_be_set_perm(struct libusb20_backend *pbe, mode_t mode)
1108 {
1109         return ((pbe->methods->root_set_perm) (pbe, mode));
1110 }
1111
1112 int
1113 libusb20_be_get_owner(struct libusb20_backend *pbe, uid_t *user, gid_t *group)
1114 {
1115         uid_t a;
1116         gid_t b;
1117
1118         if (user == NULL)
1119                 user = &a;
1120         if (group == NULL)
1121                 group = &b;
1122         return ((pbe->methods->root_get_owner) (pbe, user, group));
1123 }
1124
1125 int
1126 libusb20_be_get_perm(struct libusb20_backend *pbe, mode_t *mode)
1127 {
1128         mode_t a;
1129
1130         if (mode == NULL)
1131                 mode = &a;
1132         return ((pbe->methods->root_get_perm) (pbe, mode));
1133 }
1134
1135 struct libusb20_device *
1136 libusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev)
1137 {
1138         if (pbe == NULL) {
1139                 pdev = NULL;
1140         } else if (pdev == NULL) {
1141                 pdev = TAILQ_FIRST(&(pbe->usb_devs));
1142         } else {
1143                 pdev = TAILQ_NEXT(pdev, dev_entry);
1144         }
1145         return (pdev);
1146 }
1147
1148 struct libusb20_backend *
1149 libusb20_be_alloc(const struct libusb20_backend_methods *methods)
1150 {
1151         struct libusb20_backend *pbe;
1152
1153         pbe = malloc(sizeof(*pbe));
1154         if (pbe == NULL) {
1155                 return (NULL);
1156         }
1157         memset(pbe, 0, sizeof(*pbe));
1158
1159         TAILQ_INIT(&(pbe->usb_devs));
1160
1161         pbe->methods = methods;         /* set backend methods */
1162
1163         /* do the initial device scan */
1164         if (pbe->methods->init_backend) {
1165                 (pbe->methods->init_backend) (pbe);
1166         }
1167         return (pbe);
1168 }
1169
1170 struct libusb20_backend *
1171 libusb20_be_alloc_linux(void)
1172 {
1173         struct libusb20_backend *pbe;
1174
1175 #ifdef __linux__
1176         pbe = libusb20_be_alloc(&libusb20_linux_backend);
1177 #else
1178         pbe = NULL;
1179 #endif
1180         return (pbe);
1181 }
1182
1183 struct libusb20_backend *
1184 libusb20_be_alloc_ugen20(void)
1185 {
1186         struct libusb20_backend *pbe;
1187
1188 #ifdef __FreeBSD__
1189         pbe = libusb20_be_alloc(&libusb20_ugen20_backend);
1190 #else
1191         pbe = NULL;
1192 #endif
1193         return (pbe);
1194 }
1195
1196 struct libusb20_backend *
1197 libusb20_be_alloc_default(void)
1198 {
1199         struct libusb20_backend *pbe;
1200
1201         pbe = libusb20_be_alloc_linux();
1202         if (pbe) {
1203                 return (pbe);
1204         }
1205         pbe = libusb20_be_alloc_ugen20();
1206         if (pbe) {
1207                 return (pbe);
1208         }
1209         return (NULL);                  /* no backend found */
1210 }
1211
1212 void
1213 libusb20_be_free(struct libusb20_backend *pbe)
1214 {
1215         struct libusb20_device *pdev;
1216
1217         if (pbe == NULL) {
1218                 /* be NULL safe */
1219                 return;
1220         }
1221         while ((pdev = libusb20_be_device_foreach(pbe, NULL))) {
1222                 libusb20_be_dequeue_device(pbe, pdev);
1223                 libusb20_dev_free(pdev);
1224         }
1225         if (pbe->methods->exit_backend) {
1226                 (pbe->methods->exit_backend) (pbe);
1227         }
1228         return;
1229 }
1230
1231 void
1232 libusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev)
1233 {
1234         pdev->beMethods = pbe->methods; /* copy backend methods */
1235         TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry);
1236         return;
1237 }
1238
1239 void
1240 libusb20_be_dequeue_device(struct libusb20_backend *pbe,
1241     struct libusb20_device *pdev)
1242 {
1243         TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry);
1244         return;
1245 }