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