1 /* $FreeBSD: head/lib/libusb/libusb20.c 253339 2013-07-14 10:22:00Z hselasky $ */
3 * Copyright (c) 2008-2009 Hans Petter Selasky. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #ifdef LIBUSB_GLOBAL_INCLUDE_FILE
28 #include LIBUSB_GLOBAL_INCLUDE_FILE
36 #include <sys/queue.h>
40 #include "libusb20_desc.h"
41 #include "libusb20_int.h"
46 return (LIBUSB20_ERROR_NOT_SUPPORTED
);
56 dummy_callback(struct libusb20_transfer
*xfer
)
59 switch (libusb20_tr_get_status(xfer
)) {
60 case LIBUSB20_TRANSFER_START
:
61 libusb20_tr_submit(xfer
);
64 /* complete or error */
70 #define dummy_get_config_desc_full (void *)dummy_int
71 #define dummy_get_config_index (void *)dummy_int
72 #define dummy_set_config_index (void *)dummy_int
73 #define dummy_set_alt_index (void *)dummy_int
74 #define dummy_reset_device (void *)dummy_int
75 #define dummy_check_connected (void *)dummy_int
76 #define dummy_set_power_mode (void *)dummy_int
77 #define dummy_get_power_mode (void *)dummy_int
78 #define dummy_get_port_path (void *)dummy_int
79 #define dummy_get_power_usage (void *)dummy_int
80 #define dummy_kernel_driver_active (void *)dummy_int
81 #define dummy_detach_kernel_driver (void *)dummy_int
82 #define dummy_do_request_sync (void *)dummy_int
83 #define dummy_tr_open (void *)dummy_int
84 #define dummy_tr_close (void *)dummy_int
85 #define dummy_tr_clear_stall_sync (void *)dummy_int
86 #define dummy_process (void *)dummy_int
87 #define dummy_dev_info (void *)dummy_int
88 #define dummy_dev_get_iface_driver (void *)dummy_int
90 #define dummy_tr_submit (void *)dummy_void
91 #define dummy_tr_cancel_async (void *)dummy_void
93 static const struct libusb20_device_methods libusb20_dummy_methods
= {
94 LIBUSB20_DEVICE(LIBUSB20_DECLARE
, dummy
)
98 libusb20_tr_callback_wrapper(struct libusb20_transfer
*xfer
)
104 if (!xfer
->is_pending
) {
105 xfer
->status
= LIBUSB20_TRANSFER_START
;
107 xfer
->is_pending
= 0;
110 xfer
->callback(xfer
);
112 if (xfer
->is_restart
) {
113 xfer
->is_restart
= 0;
116 if (xfer
->is_draining
&&
117 (!xfer
->is_pending
)) {
118 xfer
->is_draining
= 0;
119 xfer
->status
= LIBUSB20_TRANSFER_DRAINED
;
120 xfer
->callback(xfer
);
126 libusb20_tr_close(struct libusb20_transfer
*xfer
)
130 if (!xfer
->is_opened
) {
131 return (LIBUSB20_ERROR_OTHER
);
133 error
= xfer
->pdev
->methods
->tr_close(xfer
);
138 if (xfer
->ppBuffer
) {
139 free(xfer
->ppBuffer
);
141 /* reset variable fields in case the transfer is opened again */
145 xfer
->is_pending
= 0;
147 xfer
->is_draining
= 0;
148 xfer
->is_restart
= 0;
155 xfer
->maxTotalLength
= 0;
156 xfer
->maxPacketLen
= 0;
161 libusb20_tr_open(struct libusb20_transfer
*xfer
, uint32_t MaxBufSize
,
162 uint32_t MaxFrameCount
, uint8_t ep_no
)
164 return (libusb20_tr_open_stream(xfer
, MaxBufSize
, MaxFrameCount
, ep_no
, 0));
168 libusb20_tr_open_stream(struct libusb20_transfer
*xfer
, uint32_t MaxBufSize
,
169 uint32_t MaxFrameCount
, uint8_t ep_no
, uint16_t stream_id
)
176 return (LIBUSB20_ERROR_BUSY
);
177 if (MaxFrameCount
& LIBUSB20_MAX_FRAME_PRE_SCALE
) {
178 MaxFrameCount
&= ~LIBUSB20_MAX_FRAME_PRE_SCALE
;
183 if (MaxFrameCount
== 0)
184 return (LIBUSB20_ERROR_INVALID_PARAM
);
186 xfer
->maxFrames
= MaxFrameCount
;
188 size
= MaxFrameCount
* sizeof(xfer
->pLength
[0]);
189 xfer
->pLength
= malloc(size
);
190 if (xfer
->pLength
== NULL
) {
191 return (LIBUSB20_ERROR_NO_MEM
);
193 memset(xfer
->pLength
, 0, size
);
195 size
= MaxFrameCount
* sizeof(xfer
->ppBuffer
[0]);
196 xfer
->ppBuffer
= malloc(size
);
197 if (xfer
->ppBuffer
== NULL
) {
199 return (LIBUSB20_ERROR_NO_MEM
);
201 memset(xfer
->ppBuffer
, 0, size
);
203 error
= xfer
->pdev
->methods
->tr_open(xfer
, MaxBufSize
,
204 MaxFrameCount
, ep_no
, stream_id
, pre_scale
);
207 free(xfer
->ppBuffer
);
215 struct libusb20_transfer
*
216 libusb20_tr_get_pointer(struct libusb20_device
*pdev
, uint16_t trIndex
)
218 if (trIndex
>= pdev
->nTransfer
) {
221 return (pdev
->pTransfer
+ trIndex
);
225 libusb20_tr_get_actual_frames(struct libusb20_transfer
*xfer
)
227 return (xfer
->aFrames
);
231 libusb20_tr_get_time_complete(struct libusb20_transfer
*xfer
)
233 return (xfer
->timeComplete
);
237 libusb20_tr_get_actual_length(struct libusb20_transfer
*xfer
)
242 for (x
= 0; x
!= xfer
->aFrames
; x
++) {
243 actlen
+= xfer
->pLength
[x
];
249 libusb20_tr_get_max_frames(struct libusb20_transfer
*xfer
)
251 return (xfer
->maxFrames
);
255 libusb20_tr_get_max_packet_length(struct libusb20_transfer
*xfer
)
258 * Special Case NOTE: If the packet multiplier is non-zero for
259 * High Speed USB, the value returned is equal to
260 * "wMaxPacketSize * multiplier" !
262 return (xfer
->maxPacketLen
);
266 libusb20_tr_get_max_total_length(struct libusb20_transfer
*xfer
)
268 return (xfer
->maxTotalLength
);
272 libusb20_tr_get_status(struct libusb20_transfer
*xfer
)
274 return (xfer
->status
);
278 libusb20_tr_pending(struct libusb20_transfer
*xfer
)
280 return (xfer
->is_pending
);
284 libusb20_tr_get_priv_sc0(struct libusb20_transfer
*xfer
)
286 return (xfer
->priv_sc0
);
290 libusb20_tr_get_priv_sc1(struct libusb20_transfer
*xfer
)
292 return (xfer
->priv_sc1
);
296 libusb20_tr_stop(struct libusb20_transfer
*xfer
)
298 if (!xfer
->is_opened
) {
299 /* transfer is not opened */
302 if (!xfer
->is_pending
) {
303 /* transfer not pending */
306 if (xfer
->is_cancel
) {
307 /* already cancelling */
310 xfer
->is_cancel
= 1; /* we are cancelling */
312 xfer
->pdev
->methods
->tr_cancel_async(xfer
);
317 libusb20_tr_drain(struct libusb20_transfer
*xfer
)
319 if (!xfer
->is_opened
) {
320 /* transfer is not opened */
323 /* make sure that we are cancelling */
324 libusb20_tr_stop(xfer
);
326 if (xfer
->is_pending
) {
327 xfer
->is_draining
= 1;
333 libusb20_tr_clear_stall_sync(struct libusb20_transfer
*xfer
)
335 xfer
->pdev
->methods
->tr_clear_stall_sync(xfer
);
340 libusb20_tr_set_buffer(struct libusb20_transfer
*xfer
, void *buffer
, uint16_t frIndex
)
342 xfer
->ppBuffer
[frIndex
] = libusb20_pass_ptr(buffer
);
347 libusb20_tr_set_callback(struct libusb20_transfer
*xfer
, libusb20_tr_callback_t
*cb
)
354 libusb20_tr_set_flags(struct libusb20_transfer
*xfer
, uint8_t flags
)
361 libusb20_tr_get_length(struct libusb20_transfer
*xfer
, uint16_t frIndex
)
363 return (xfer
->pLength
[frIndex
]);
367 libusb20_tr_set_length(struct libusb20_transfer
*xfer
, uint32_t length
, uint16_t frIndex
)
369 xfer
->pLength
[frIndex
] = length
;
374 libusb20_tr_set_priv_sc0(struct libusb20_transfer
*xfer
, void *sc0
)
376 xfer
->priv_sc0
= sc0
;
381 libusb20_tr_set_priv_sc1(struct libusb20_transfer
*xfer
, void *sc1
)
383 xfer
->priv_sc1
= sc1
;
388 libusb20_tr_set_timeout(struct libusb20_transfer
*xfer
, uint32_t timeout
)
390 xfer
->timeout
= timeout
;
395 libusb20_tr_set_total_frames(struct libusb20_transfer
*xfer
, uint32_t nFrames
)
397 if (nFrames
> xfer
->maxFrames
) {
398 /* should not happen */
399 nFrames
= xfer
->maxFrames
;
401 xfer
->nFrames
= nFrames
;
406 libusb20_tr_setup_bulk(struct libusb20_transfer
*xfer
, void *pBuf
, uint32_t length
, uint32_t timeout
)
408 xfer
->ppBuffer
[0] = libusb20_pass_ptr(pBuf
);
409 xfer
->pLength
[0] = length
;
410 xfer
->timeout
= timeout
;
416 libusb20_tr_setup_control(struct libusb20_transfer
*xfer
, void *psetup
, void *pBuf
, uint32_t timeout
)
420 xfer
->ppBuffer
[0] = libusb20_pass_ptr(psetup
);
421 xfer
->pLength
[0] = 8; /* fixed */
422 xfer
->timeout
= timeout
;
424 len
= ((uint8_t *)psetup
)[6] | (((uint8_t *)psetup
)[7] << 8);
428 xfer
->ppBuffer
[1] = libusb20_pass_ptr(pBuf
);
429 xfer
->pLength
[1] = len
;
437 libusb20_tr_setup_intr(struct libusb20_transfer
*xfer
, void *pBuf
, uint32_t length
, uint32_t timeout
)
439 xfer
->ppBuffer
[0] = libusb20_pass_ptr(pBuf
);
440 xfer
->pLength
[0] = length
;
441 xfer
->timeout
= timeout
;
447 libusb20_tr_setup_isoc(struct libusb20_transfer
*xfer
, void *pBuf
, uint32_t length
, uint16_t frIndex
)
449 if (frIndex
>= xfer
->maxFrames
) {
450 /* should not happen */
453 xfer
->ppBuffer
[frIndex
] = libusb20_pass_ptr(pBuf
);
454 xfer
->pLength
[frIndex
] = length
;
459 libusb20_tr_bulk_intr_sync(struct libusb20_transfer
*xfer
,
460 void *pbuf
, uint32_t length
, uint32_t *pactlen
,
463 struct libusb20_device
*pdev
= xfer
->pdev
;
464 uint32_t transfer_max
;
465 uint32_t transfer_act
;
468 /* set some sensible default value */
472 /* check for error condition */
473 if (libusb20_tr_pending(xfer
))
474 return (LIBUSB20_ERROR_OTHER
);
477 /* compute maximum transfer length */
479 libusb20_tr_get_max_total_length(xfer
);
481 if (transfer_max
> length
)
482 transfer_max
= length
;
484 /* setup bulk or interrupt transfer */
485 libusb20_tr_setup_bulk(xfer
, pbuf
,
486 transfer_max
, timeout
);
488 /* start the transfer */
489 libusb20_tr_start(xfer
);
491 /* wait for transfer completion */
492 while (libusb20_dev_process(pdev
) == 0) {
494 if (libusb20_tr_pending(xfer
) == 0)
497 libusb20_dev_wait_process(pdev
, -1);
500 transfer_act
= libusb20_tr_get_actual_length(xfer
);
502 /* update actual length, if any */
504 pactlen
[0] += transfer_act
;
506 /* check transfer status */
507 retval
= libusb20_tr_get_status(xfer
);
511 /* check for short transfer */
512 if (transfer_act
!= transfer_max
)
515 /* update buffer pointer and length */
516 pbuf
= ((uint8_t *)pbuf
) + transfer_max
;
517 length
= length
- transfer_max
;
519 } while (length
!= 0);
525 libusb20_tr_submit(struct libusb20_transfer
*xfer
)
527 if (!xfer
->is_opened
) {
528 /* transfer is not opened */
531 if (xfer
->is_pending
) {
532 /* should not happen */
535 xfer
->is_pending
= 1; /* we are pending */
536 xfer
->is_cancel
= 0; /* not cancelling */
537 xfer
->is_restart
= 0; /* not restarting */
539 xfer
->pdev
->methods
->tr_submit(xfer
);
544 libusb20_tr_start(struct libusb20_transfer
*xfer
)
546 if (!xfer
->is_opened
) {
547 /* transfer is not opened */
550 if (xfer
->is_pending
) {
551 if (xfer
->is_cancel
) {
552 /* cancelling - restart */
553 xfer
->is_restart
= 1;
555 /* transfer not pending */
558 /* get into the callback */
559 libusb20_tr_callback_wrapper(xfer
);
563 /* USB device operations */
566 libusb20_dev_close(struct libusb20_device
*pdev
)
568 struct libusb20_transfer
*xfer
;
572 if (!pdev
->is_opened
) {
573 return (LIBUSB20_ERROR_OTHER
);
575 for (x
= 0; x
!= pdev
->nTransfer
; x
++) {
576 xfer
= pdev
->pTransfer
+ x
;
578 if (!xfer
->is_opened
) {
579 /* transfer is not opened */
583 libusb20_tr_drain(xfer
);
585 libusb20_tr_close(xfer
);
588 if (pdev
->pTransfer
!= NULL
) {
589 free(pdev
->pTransfer
);
590 pdev
->pTransfer
= NULL
;
592 error
= pdev
->beMethods
->close_device(pdev
);
594 pdev
->methods
= &libusb20_dummy_methods
;
599 * The following variable is only used by the libusb v0.1
602 pdev
->claimed_interface
= 0;
608 libusb20_dev_detach_kernel_driver(struct libusb20_device
*pdev
, uint8_t ifaceIndex
)
612 error
= pdev
->methods
->detach_kernel_driver(pdev
, ifaceIndex
);
616 struct LIBUSB20_DEVICE_DESC_DECODED
*
617 libusb20_dev_get_device_desc(struct libusb20_device
*pdev
)
619 return (&(pdev
->ddesc
));
623 libusb20_dev_get_fd(struct libusb20_device
*pdev
)
629 libusb20_dev_kernel_driver_active(struct libusb20_device
*pdev
, uint8_t ifaceIndex
)
633 error
= pdev
->methods
->kernel_driver_active(pdev
, ifaceIndex
);
638 libusb20_dev_open(struct libusb20_device
*pdev
, uint16_t nTransferMax
)
640 struct libusb20_transfer
*xfer
;
645 if (pdev
->is_opened
) {
646 return (LIBUSB20_ERROR_BUSY
);
648 if (nTransferMax
>= 256) {
649 return (LIBUSB20_ERROR_INVALID_PARAM
);
650 } else if (nTransferMax
!= 0) {
651 size
= sizeof(pdev
->pTransfer
[0]) * nTransferMax
;
652 pdev
->pTransfer
= malloc(size
);
653 if (pdev
->pTransfer
== NULL
) {
654 return (LIBUSB20_ERROR_NO_MEM
);
656 memset(pdev
->pTransfer
, 0, size
);
658 /* initialise all transfers */
659 for (x
= 0; x
!= nTransferMax
; x
++) {
661 xfer
= pdev
->pTransfer
+ x
;
665 xfer
->callback
= &dummy_callback
;
668 /* set "nTransfer" early */
669 pdev
->nTransfer
= nTransferMax
;
671 error
= pdev
->beMethods
->open_device(pdev
, nTransferMax
);
674 if (pdev
->pTransfer
!= NULL
) {
675 free(pdev
->pTransfer
);
676 pdev
->pTransfer
= NULL
;
679 pdev
->file_ctrl
= -1;
688 libusb20_dev_reset(struct libusb20_device
*pdev
)
692 error
= pdev
->methods
->reset_device(pdev
);
697 libusb20_dev_check_connected(struct libusb20_device
*pdev
)
701 error
= pdev
->methods
->check_connected(pdev
);
706 libusb20_dev_set_power_mode(struct libusb20_device
*pdev
, uint8_t power_mode
)
710 error
= pdev
->methods
->set_power_mode(pdev
, power_mode
);
715 libusb20_dev_get_power_mode(struct libusb20_device
*pdev
)
720 error
= pdev
->methods
->get_power_mode(pdev
, &power_mode
);
722 power_mode
= LIBUSB20_POWER_ON
; /* fake power mode */
727 libusb20_dev_get_port_path(struct libusb20_device
*pdev
, uint8_t *buf
, uint8_t bufsize
)
729 return (pdev
->methods
->get_port_path(pdev
, buf
, bufsize
));
733 libusb20_dev_get_power_usage(struct libusb20_device
*pdev
)
736 uint16_t power_usage
;
738 error
= pdev
->methods
->get_power_usage(pdev
, &power_usage
);
741 return (power_usage
);
745 libusb20_dev_set_alt_index(struct libusb20_device
*pdev
, uint8_t ifaceIndex
, uint8_t altIndex
)
749 error
= pdev
->methods
->set_alt_index(pdev
, ifaceIndex
, altIndex
);
754 libusb20_dev_set_config_index(struct libusb20_device
*pdev
, uint8_t configIndex
)
758 error
= pdev
->methods
->set_config_index(pdev
, configIndex
);
763 libusb20_dev_request_sync(struct libusb20_device
*pdev
,
764 struct LIBUSB20_CONTROL_SETUP_DECODED
*setup
, void *data
,
765 uint16_t *pactlen
, uint32_t timeout
, uint8_t flags
)
769 error
= pdev
->methods
->do_request_sync(pdev
,
770 setup
, data
, pactlen
, timeout
, flags
);
775 libusb20_dev_req_string_sync(struct libusb20_device
*pdev
,
776 uint8_t str_index
, uint16_t langid
, void *ptr
, uint16_t len
)
778 struct LIBUSB20_CONTROL_SETUP_DECODED req
;
781 /* make sure memory is initialised */
786 return (LIBUSB20_ERROR_INVALID_PARAM
);
788 LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP
, &req
);
791 * We need to read the USB string in two steps else some USB
792 * devices will complain.
795 LIBUSB20_REQUEST_TYPE_STANDARD
|
796 LIBUSB20_RECIPIENT_DEVICE
|
797 LIBUSB20_ENDPOINT_IN
;
798 req
.bRequest
= LIBUSB20_REQUEST_GET_DESCRIPTOR
;
799 req
.wValue
= (LIBUSB20_DT_STRING
<< 8) | str_index
;
801 req
.wLength
= 4; /* bytes */
803 error
= libusb20_dev_request_sync(pdev
, &req
,
804 ptr
, NULL
, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK
);
808 req
.wLength
= *(uint8_t *)ptr
; /* bytes */
809 if (req
.wLength
> len
) {
810 /* partial string read */
813 error
= libusb20_dev_request_sync(pdev
, &req
,
814 ptr
, NULL
, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK
);
819 if (((uint8_t *)ptr
)[1] != LIBUSB20_DT_STRING
) {
820 return (LIBUSB20_ERROR_OTHER
);
822 return (0); /* success */
826 libusb20_dev_req_string_simple_sync(struct libusb20_device
*pdev
,
827 uint8_t str_index
, void *ptr
, uint16_t len
)
838 /* the following code derives from the FreeBSD USB kernel */
840 if ((len
< 1) || (ptr
== NULL
)) {
841 /* too short buffer */
842 return (LIBUSB20_ERROR_INVALID_PARAM
);
844 error
= libusb20_dev_req_string_sync(pdev
,
845 0, 0, temp
, sizeof(temp
));
847 *(uint8_t *)ptr
= 0; /* zero terminate */
850 langid
= temp
[2] | (temp
[3] << 8);
852 error
= libusb20_dev_req_string_sync(pdev
, str_index
,
853 langid
, temp
, sizeof(temp
));
855 *(uint8_t *)ptr
= 0; /* zero terminate */
859 /* string length is too short */
860 *(uint8_t *)ptr
= 0; /* zero terminate */
861 return (LIBUSB20_ERROR_OTHER
);
863 /* reserve one byte for terminating zero */
866 /* find maximum length */
867 n
= (temp
[0] / 2) - 1;
871 /* reset swap state */
874 /* setup output buffer pointer */
877 /* convert and filter */
878 for (i
= 0; (i
!= n
); i
++) {
879 c
= temp
[(2 * i
) + 2] | (temp
[(2 * i
) + 3] << 8);
881 /* convert from Unicode, handle buggy strings */
882 if (((c
& 0xff00) == 0) && (swap
& 1)) {
883 /* Little Endian, default */
886 } else if (((c
& 0x00ff) == 0) && (swap
& 2)) {
891 /* skip invalid character */
895 * Filter by default - we don't allow greater and less than
896 * signs because they might confuse the dmesg printouts!
898 if ((*buf
== '<') || (*buf
== '>') || (!isprint(*buf
))) {
899 /* skip invalid character */
904 *buf
= 0; /* zero terminate string */
909 struct libusb20_config
*
910 libusb20_dev_alloc_config(struct libusb20_device
*pdev
, uint8_t configIndex
)
912 struct libusb20_config
*retval
= NULL
;
918 if (!pdev
->is_opened
) {
919 error
= libusb20_dev_open(pdev
, 0);
927 error
= pdev
->methods
->get_config_desc_full(pdev
,
928 &ptr
, &len
, configIndex
);
933 /* parse new config descriptor */
934 retval
= libusb20_parse_config_desc(ptr
);
936 /* free config descriptor */
941 error
= libusb20_dev_close(pdev
);
946 struct libusb20_device
*
947 libusb20_dev_alloc(void)
949 struct libusb20_device
*pdev
;
951 pdev
= malloc(sizeof(*pdev
));
955 memset(pdev
, 0, sizeof(*pdev
));
958 pdev
->file_ctrl
= -1;
959 pdev
->methods
= &libusb20_dummy_methods
;
964 libusb20_dev_get_config_index(struct libusb20_device
*pdev
)
970 if (!pdev
->is_opened
) {
971 error
= libusb20_dev_open(pdev
, 0);
981 error
= pdev
->methods
->get_config_index(pdev
, &cfg_index
);
983 cfg_index
= 0xFF; /* current config index */
985 if (libusb20_dev_close(pdev
)) {
993 libusb20_dev_get_mode(struct libusb20_device
*pdev
)
995 return (pdev
->usb_mode
);
999 libusb20_dev_get_speed(struct libusb20_device
*pdev
)
1001 return (pdev
->usb_speed
);
1004 /* if this function returns an error, the device is gone */
1006 libusb20_dev_process(struct libusb20_device
*pdev
)
1010 error
= pdev
->methods
->process(pdev
);
1015 libusb20_dev_wait_process(struct libusb20_device
*pdev
, int timeout
)
1017 struct pollfd pfd
[1];
1019 if (!pdev
->is_opened
) {
1022 pfd
[0].fd
= pdev
->file
;
1023 pfd
[0].events
= (POLLIN
| POLLOUT
| POLLRDNORM
| POLLWRNORM
);
1026 if (poll(pfd
, 1, timeout
)) {
1027 /* ignore any error */
1033 libusb20_dev_free(struct libusb20_device
*pdev
)
1039 if (pdev
->is_opened
) {
1040 if (libusb20_dev_close(pdev
)) {
1041 /* ignore any errors */
1049 libusb20_dev_get_info(struct libusb20_device
*pdev
,
1050 struct usb_device_info
*pinfo
)
1053 return (LIBUSB20_ERROR_INVALID_PARAM
);
1055 return (pdev
->beMethods
->dev_get_info(pdev
, pinfo
));
1059 libusb20_dev_get_backend_name(struct libusb20_device
*pdev
)
1061 return (pdev
->beMethods
->get_backend_name());
1065 libusb20_dev_get_desc(struct libusb20_device
*pdev
)
1067 return (pdev
->usb_desc
);
1071 libusb20_dev_set_debug(struct libusb20_device
*pdev
, int debug
)
1073 pdev
->debug
= debug
;
1078 libusb20_dev_get_debug(struct libusb20_device
*pdev
)
1080 return (pdev
->debug
);
1084 libusb20_dev_get_address(struct libusb20_device
*pdev
)
1086 return (pdev
->device_address
);
1090 libusb20_dev_get_parent_address(struct libusb20_device
*pdev
)
1092 return (pdev
->parent_address
);
1096 libusb20_dev_get_parent_port(struct libusb20_device
*pdev
)
1098 return (pdev
->parent_port
);
1102 libusb20_dev_get_bus_number(struct libusb20_device
*pdev
)
1104 return (pdev
->bus_number
);
1108 libusb20_dev_get_iface_desc(struct libusb20_device
*pdev
,
1109 uint8_t iface_index
, char *buf
, uint8_t len
)
1111 if ((buf
== NULL
) || (len
== 0))
1112 return (LIBUSB20_ERROR_INVALID_PARAM
);
1114 buf
[0] = 0; /* set default string value */
1116 return (pdev
->beMethods
->dev_get_iface_desc(
1117 pdev
, iface_index
, buf
, len
));
1120 /* USB backend operations */
1123 libusb20_be_get_dev_quirk(struct libusb20_backend
*pbe
,
1124 uint16_t quirk_index
, struct libusb20_quirk
*pq
)
1126 return (pbe
->methods
->root_get_dev_quirk(pbe
, quirk_index
, pq
));
1130 libusb20_be_get_quirk_name(struct libusb20_backend
*pbe
,
1131 uint16_t quirk_index
, struct libusb20_quirk
*pq
)
1133 return (pbe
->methods
->root_get_quirk_name(pbe
, quirk_index
, pq
));
1137 libusb20_be_add_dev_quirk(struct libusb20_backend
*pbe
,
1138 struct libusb20_quirk
*pq
)
1140 return (pbe
->methods
->root_add_dev_quirk(pbe
, pq
));
1144 libusb20_be_remove_dev_quirk(struct libusb20_backend
*pbe
,
1145 struct libusb20_quirk
*pq
)
1147 return (pbe
->methods
->root_remove_dev_quirk(pbe
, pq
));
1151 libusb20_be_set_template(struct libusb20_backend
*pbe
, int temp
)
1153 return (pbe
->methods
->root_set_template(pbe
, temp
));
1157 libusb20_be_get_template(struct libusb20_backend
*pbe
, int *ptemp
)
1164 return (pbe
->methods
->root_get_template(pbe
, ptemp
));
1167 struct libusb20_device
*
1168 libusb20_be_device_foreach(struct libusb20_backend
*pbe
, struct libusb20_device
*pdev
)
1172 } else if (pdev
== NULL
) {
1173 pdev
= TAILQ_FIRST(&(pbe
->usb_devs
));
1175 pdev
= TAILQ_NEXT(pdev
, dev_entry
);
1180 struct libusb20_backend
*
1181 libusb20_be_alloc(const struct libusb20_backend_methods
*methods
)
1183 struct libusb20_backend
*pbe
;
1185 pbe
= malloc(sizeof(*pbe
));
1189 memset(pbe
, 0, sizeof(*pbe
));
1191 TAILQ_INIT(&(pbe
->usb_devs
));
1193 pbe
->methods
= methods
; /* set backend methods */
1195 /* do the initial device scan */
1196 if (pbe
->methods
->init_backend
) {
1197 pbe
->methods
->init_backend(pbe
);
1202 struct libusb20_backend
*
1203 libusb20_be_alloc_linux(void)
1208 struct libusb20_backend
*
1209 libusb20_be_alloc_ugen20(void)
1211 return (libusb20_be_alloc(&libusb20_ugen20_backend
));
1214 struct libusb20_backend
*
1215 libusb20_be_alloc_default(void)
1217 struct libusb20_backend
*pbe
;
1220 pbe
= libusb20_be_alloc_linux();
1225 pbe
= libusb20_be_alloc_ugen20();
1229 return (NULL
); /* no backend found */
1233 libusb20_be_free(struct libusb20_backend
*pbe
)
1235 struct libusb20_device
*pdev
;
1241 while ((pdev
= libusb20_be_device_foreach(pbe
, NULL
))) {
1242 libusb20_be_dequeue_device(pbe
, pdev
);
1243 libusb20_dev_free(pdev
);
1245 if (pbe
->methods
->exit_backend
) {
1246 pbe
->methods
->exit_backend(pbe
);
1253 libusb20_be_enqueue_device(struct libusb20_backend
*pbe
, struct libusb20_device
*pdev
)
1255 pdev
->beMethods
= pbe
->methods
; /* copy backend methods */
1256 TAILQ_INSERT_TAIL(&(pbe
->usb_devs
), pdev
, dev_entry
);
1260 libusb20_be_dequeue_device(struct libusb20_backend
*pbe
,
1261 struct libusb20_device
*pdev
)
1263 TAILQ_REMOVE(&(pbe
->usb_devs
), pdev
, dev_entry
);
1267 libusb20_strerror(int code
)
1270 case LIBUSB20_SUCCESS
:
1272 case LIBUSB20_ERROR_IO
:
1273 return ("I/O error");
1274 case LIBUSB20_ERROR_INVALID_PARAM
:
1275 return ("Invalid parameter");
1276 case LIBUSB20_ERROR_ACCESS
:
1277 return ("Permissions error");
1278 case LIBUSB20_ERROR_NO_DEVICE
:
1279 return ("No device");
1280 case LIBUSB20_ERROR_NOT_FOUND
:
1281 return ("Not found");
1282 case LIBUSB20_ERROR_BUSY
:
1283 return ("Device busy");
1284 case LIBUSB20_ERROR_TIMEOUT
:
1286 case LIBUSB20_ERROR_OVERFLOW
:
1287 return ("Overflow");
1288 case LIBUSB20_ERROR_PIPE
:
1289 return ("Pipe error");
1290 case LIBUSB20_ERROR_INTERRUPTED
:
1291 return ("Interrupted");
1292 case LIBUSB20_ERROR_NO_MEM
:
1293 return ("Out of memory");
1294 case LIBUSB20_ERROR_NOT_SUPPORTED
:
1295 return ("Not supported");
1296 case LIBUSB20_ERROR_OTHER
:
1297 return ("Other error");
1299 return ("Unknown error");
1304 libusb20_error_name(int code
)
1307 case LIBUSB20_SUCCESS
:
1308 return ("LIBUSB20_SUCCESS");
1309 case LIBUSB20_ERROR_IO
:
1310 return ("LIBUSB20_ERROR_IO");
1311 case LIBUSB20_ERROR_INVALID_PARAM
:
1312 return ("LIBUSB20_ERROR_INVALID_PARAM");
1313 case LIBUSB20_ERROR_ACCESS
:
1314 return ("LIBUSB20_ERROR_ACCESS");
1315 case LIBUSB20_ERROR_NO_DEVICE
:
1316 return ("LIBUSB20_ERROR_NO_DEVICE");
1317 case LIBUSB20_ERROR_NOT_FOUND
:
1318 return ("LIBUSB20_ERROR_NOT_FOUND");
1319 case LIBUSB20_ERROR_BUSY
:
1320 return ("LIBUSB20_ERROR_BUSY");
1321 case LIBUSB20_ERROR_TIMEOUT
:
1322 return ("LIBUSB20_ERROR_TIMEOUT");
1323 case LIBUSB20_ERROR_OVERFLOW
:
1324 return ("LIBUSB20_ERROR_OVERFLOW");
1325 case LIBUSB20_ERROR_PIPE
:
1326 return ("LIBUSB20_ERROR_PIPE");
1327 case LIBUSB20_ERROR_INTERRUPTED
:
1328 return ("LIBUSB20_ERROR_INTERRUPTED");
1329 case LIBUSB20_ERROR_NO_MEM
:
1330 return ("LIBUSB20_ERROR_NO_MEM");
1331 case LIBUSB20_ERROR_NOT_SUPPORTED
:
1332 return ("LIBUSB20_ERROR_NOT_SUPPORTED");
1333 case LIBUSB20_ERROR_OTHER
:
1334 return ("LIBUSB20_ERROR_OTHER");
1336 return ("LIBUSB20_ERROR_UNKNOWN");