4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
26 * This library can either be used stand-alone or as plugin
27 * to the libusb wrapper library.
28 * The libusb API 0.1.0.10 has been implemented using all original code
29 * which was not derived from opensource.
32 * - timeout thru signal
33 * - usb_interrupt/bulk_write/read should have common code
49 #include <sys/usb/clients/ugen/usb_ugen.h>
51 #include "libusbugen_impl.h"
53 /* global variables */
54 usb_bus_t
*usb_busses
= NULL
;
55 const char *libusb_version
= "1.1";
58 static char usb_error_string
[1024];
59 static int usb_error_errno
;
60 static usb_error_type_t usb_error_type
= USB_ERROR_TYPE_NONE
;
63 static int libusb_debug
= DEBUG_NONE
;
66 static int libusb_api
= API_RELAXED
;
68 /* internal function prototypes */
69 static void usb_error_str(int x
, char *format
, ...);
70 static int usb_error(int x
);
71 static void usb_dprintf(int level
, char *format
, ...);
72 static void usb_dump_data(char *data
, int size
);
74 static int usb_open_ep0(usb_dev_handle_impl_t
*hdl
);
75 static void usb_close_ep0(usb_dev_handle_impl_t
*hdl
);
76 static int usb_check_access(usb_dev_handle
*dev
);
77 static int usb_search_dev_usb(usb_device_t
**new_devices
);
78 static int usb_do_io(int fd
, int stat_fd
, char *data
, size_t size
, int flag
);
79 static int usb_send_msg(int fd
, int stat_fd
, int requesttype
, int request
,
80 int value
, int index
, char *data
, int size
);
81 static int usb_check_device_and_status_open(usb_dev_handle
*dev
,
82 int ep
, int ep_type
, int mode
);
83 static int usb_get_status(int fd
);
84 static void usb_set_ep_iface_alts(usb_dev_handle_impl_t
*hdl
,
85 usb_dev_handle_info_t
*info
, int index
, int interface
, int alternate
);
87 static int usb_setup_all_configs(usb_dev_handle_impl_t
*hdl
);
88 static void usb_free_all_configs(usb_device_t
*device
);
89 static int usb_parse_config(usb_dev_handle_impl_t
*hdl
, uint_t index
);
90 static void usb_free_config(usb_device_t
*device
, uint_t index
);
91 static int usb_parse_interface(usb_dev_handle_impl_t
*hdl
, uint_t index
,
92 uint_t iface
, char *cloud
);
93 static void usb_free_interface(usb_device_t
*device
, uint_t index
,
95 static int usb_parse_alternate(usb_dev_handle_impl_t
*hdl
, uint_t index
,
96 uint_t iface
, uint_t alt
, char *cloud
);
97 static void usb_free_alternate(usb_device_t
*device
, uint_t index
,
98 uint_t iface
, uint_t alt
);
99 static int usb_parse_endpoint(usb_dev_handle_impl_t
*hdl
, int index
,
100 int iface
, int alt
, int ep
, char *cloud
);
101 static void usb_find_extra(uchar_t
*buf
, size_t buflen
,
102 unsigned char **extra
, int *extralen
);
104 static void usb_close_all_eps(usb_dev_handle_impl_t
*hdl
);
105 static void usb_add_device(usb_device_t
**list
, usb_device_t
*dev
);
106 static void usb_remove_device(usb_device_t
**list
, usb_device_t
*dev
);
107 static int usb_check_device_in_list(usb_device_t
*list
, usb_device_t
*dev
);
109 static void usb_free_dev(usb_device_t
*dev
);
110 static void usb_free_bus(usb_bus_t
*bus
);
112 static size_t usb_parse_dev_descr(uchar_t
*buf
, size_t buflen
,
113 struct usb_device_descriptor
*ret_descr
, size_t ret_buf_len
);
114 static size_t usb_parse_cfg_descr(uchar_t
*buf
, size_t buflen
,
115 usb_cfg_descr_t
*ret_descr
, size_t ret_buf_len
,
116 unsigned char **extra
, int *extralen
);
117 static size_t usb_parse_if_descr(uchar_t
*buf
, size_t buflen
,
118 uint_t if_number
, uint_t alt_if_setting
,
119 usb_if_descr_t
*ret_descr
, size_t ret_buf_len
,
120 unsigned char **extra
, int *extralen
);
121 static size_t usb_parse_ep_descr(uchar_t
*buf
, size_t buflen
,
122 uint_t if_number
, uint_t alt_if_setting
, uint_t ep_index
,
123 usb_ep_descr_t
*ret_descr
, size_t ret_buf_len
,
124 unsigned char **extra
, int *extralen
);
125 static uchar_t
usb_ep_index(uint8_t ep_addr
);
130 * Returns: 0 or ENOSUP if we cannot support any bus
141 * Returns: always returns 0
153 * sets debug level for tracing
156 usb_set_debug(int level
)
158 if (getenv("SUN_LIBUSBUGEN_DEBUG")) {
160 level
= atoi(getenv("SUN_LIBUSBUGEN_DEBUG"));
162 } else if (getenv("SUN_LIBUSB_DEBUG")) {
164 level
= atoi(getenv("SUN_LIBUSB_DEBUG"));
170 libusb_debug
= level
;
172 usb_dprintf(DEBUG_FUNCTIONS
, "usb_set_debug(): "
173 "Setting debugging level to %d (%s)\n",
174 level
, level
? "on" : "off");
179 * not much to initialize. just set debug level
184 if (getenv("LIBUSB_API_STRICT")) {
185 libusb_api
= API_STRICT
;
188 usb_set_debug(libusb_debug
);
190 usb_dprintf(DEBUG_FUNCTIONS
, "usb_init(): "
191 "libusb version=%s\n", libusb_version
);
196 * Returns: usb_busses pointer
206 * finds all busses in the system. On solaris we have
207 * only one flat name space, /dev/usb
209 * Returns: change in number of busses or negative errno
212 usb_find_busses(void)
216 /* we only have one name space for all USB busses */
217 if (usb_busses
== NULL
) {
219 if ((bus
= calloc(sizeof (*bus
), 1)) == NULL
) {
221 return (usb_error(ENOMEM
));
224 (void) strncpy(bus
->dirname
, "/dev/usb",
225 sizeof (bus
->dirname
));
227 usb_dprintf(DEBUG_FUNCTIONS
, "usb_find_busses(): "
228 "found %s\n", bus
->dirname
);
240 * finds all devices that have appeared and removes devices
241 * from the list that are no longer there
243 * Returns: change in number of devices or a negative errno
246 usb_find_devices(void)
250 usb_device_t
*new_devices
;
251 usb_device_t
*dev
, *next_dev
, *new, *next_new
;
255 rval
= usb_search_dev_usb(&new_devices
);
258 return (usb_error(rval
));
261 /* is any of devices on the new list also on the old list? */
262 for (dev
= usb_busses
->devices
; dev
!= NULL
; dev
= next_dev
) {
263 next_dev
= dev
->next
;
265 for (new = new_devices
; new != NULL
; new = next_new
) {
266 next_new
= new->next
;
267 if (strncmp(dev
->filename
, new->filename
,
268 sizeof (dev
->filename
)) == 0) {
269 usb_remove_device(&new_devices
, new);
276 /* the device must have been hot removed */
278 usb_remove_device(&usb_busses
->devices
, dev
);
283 /* add all new_devices to the old_devices list */
284 usb_dprintf(DEBUG_DETAILED
, "moving new to old\n");
286 for (new = new_devices
; new != NULL
; new = next_new
) {
287 next_new
= new->next
;
288 usb_remove_device(&new_devices
, new);
289 usb_add_device(&usb_busses
->devices
, new);
290 (void) usb_close(usb_open(new));
294 usb_dprintf(DEBUG_DETAILED
, "usb_devices list:\n");
295 for (i
= 0, dev
= usb_busses
->devices
; dev
!= NULL
;
296 i
++, dev
= next_dev
) {
297 next_dev
= dev
->next
;
298 usb_dprintf(DEBUG_DETAILED
, "%d: %s\n", i
, dev
->filename
);
306 * included because sane uses this
307 * Returns: usb_device structure associated with handle
310 usb_device(usb_dev_handle
*dev
)
312 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
314 return ((hdl
!= NULL
) ? hdl
->device
: NULL
);
319 * opens the device for access
321 * Returns: a usb device handle or NULL
324 usb_open(usb_device_t
*dev
)
326 usb_dev_handle_impl_t
*hdl
;
327 usb_dev_handle_info_t
*info
;
330 usb_dprintf(DEBUG_FUNCTIONS
, "usb_open():\n");
332 if (usb_check_device_in_list(usb_busses
->devices
,
334 usb_dprintf(DEBUG_ERRORS
, "usb_open(): "
335 "illegal usb_device pointer\n");
340 /* create a handle and info structure */
341 if ((hdl
= calloc(sizeof (*hdl
), 1)) == NULL
) {
346 if ((info
= calloc(sizeof (*info
), 1)) == NULL
) {
354 /* set all file descriptors to "closed" */
355 for (i
= 0; i
< USB_MAXENDPOINTS
; i
++) {
356 hdl
->info
->ep_fd
[i
] = -1;
357 hdl
->info
->ep_status_fd
[i
] = -1;
359 hdl
->info
->ep_interface
[i
] = -1;
363 /* open default control ep and keep it open */
364 if ((rval
= usb_open_ep0(hdl
)) != 0) {
365 usb_dprintf(DEBUG_ERRORS
, "usb_open_ep0 failed: %d\n", rval
);
373 * setup config info: trees of configs, interfaces, alternates
374 * and endpoints structures
376 if (usb_setup_all_configs(hdl
) != 0) {
377 usb_free_all_configs(hdl
->device
);
385 /* set when the app claims an interface */
386 info
->configuration_value
=
387 info
->claimed_interface
= info
->alternate
= -1;
389 usb_dprintf(DEBUG_FUNCTIONS
, "usb_open(): hdl=0x%x\n", (int)hdl
);
391 return ((usb_dev_handle
*)hdl
);
396 * closes the device and free resources
401 usb_close(usb_dev_handle
*dev
)
403 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
404 usb_dev_handle_info_t
*info
;
406 usb_dprintf(DEBUG_FUNCTIONS
, "usb_close(): hdl=0x%x\n", hdl
);
411 usb_dprintf(DEBUG_DETAILED
,
412 "usb_close(): claimed %d\n",
413 info
->claimed_interface
);
415 if (info
->claimed_interface
!= -1) {
416 (void) usb_release_interface(dev
,
417 info
->claimed_interface
);
419 usb_close_all_eps(hdl
);
428 return (usb_error(EINVAL
));
433 * sends a control message
435 * Returns: actual number of data bytes transferred or
440 usb_control_msg(usb_dev_handle
*dev
, int requesttype
, int request
,
441 int value
, int index
, char *data
, int size
, int timeout
)
443 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
444 usb_dev_handle_info_t
*info
;
448 usb_dprintf(DEBUG_FUNCTIONS
, "usb_control_msg():\n");
450 if ((hdl
== NULL
) || (size
< 0)) {
452 return (usb_error(EINVAL
));
457 * no need to do validation since ep0 is always open and
458 * we do not need to claim an interface first
460 * usb_send_msg returns #bytes xferred or negative errno
462 rval
= usb_send_msg(info
->ep_fd
[0], info
->ep_status_fd
[0],
463 requesttype
, request
, value
, index
, data
, size
);
465 /* less than setup bytes transferred? */
468 "error sending control message: %d", rval
);
470 return ((rval
>= 0) ?
471 usb_error(EIO
) : usb_error(-rval
));
474 rval
-= 8; /* substract setup length */
476 /* for IN requests, now transfer the remaining bytes */
477 if ((size
) && (requesttype
& USB_DEV_REQ_DEV_TO_HOST
)) {
478 additional
= usb_do_io(info
->ep_fd
[0],
479 info
->ep_status_fd
[0], data
, size
, READ
);
484 usb_dprintf(DEBUG_FUNCTIONS
,
485 "usb_control_msg(): additional 0x%x bytes\n", additional
);
492 * writes to a bulk endpoint
494 * Returns: actual number of data bytes transferred or negative errno
498 usb_bulk_write(usb_dev_handle
*dev
, int ep
, char *data
, int size
,
501 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
502 usb_dev_handle_info_t
*info
;
504 int ep_index
= usb_ep_index(ep
);
506 usb_dprintf(DEBUG_FUNCTIONS
, "usb_bulk_write(): ep=0x%x\n", ep
);
508 if ((hdl
== NULL
) || (data
== NULL
) || (size
<= 0)) {
509 usb_dprintf(DEBUG_ERRORS
,
510 "usb_bulk_write(): NULL handle or data\n");
512 return (usb_error(EINVAL
));
516 /* do some validation first */
517 if ((rval
= usb_check_device_and_status_open(dev
, ep
,
518 USB_ENDPOINT_TYPE_BULK
, O_WRONLY
)) != 0) {
519 usb_dprintf(DEBUG_ERRORS
,
520 "usb_check_device_and_status_open() failed\n");
522 return (usb_error(rval
));
525 /* now write out the bytes */
526 sent
= usb_do_io(info
->ep_fd
[ep_index
], info
->ep_status_fd
[ep_index
],
534 * reads from a bulk endpoint
536 * Returns: actual number of data bytes transferred or negative errno
540 usb_bulk_read(usb_dev_handle
*dev
, int ep
, char *data
, int size
,
543 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
544 usb_dev_handle_info_t
*info
;
545 int ep_index
, received
, rval
;
547 ep
|= USB_ENDPOINT_IN
;
548 ep_index
= usb_ep_index(ep
);
550 usb_dprintf(DEBUG_FUNCTIONS
, "usb_bulk_read(): ep=0x%x\n", ep
);
552 if ((hdl
== NULL
) || (data
== NULL
) || (size
<= 0)) {
553 usb_dprintf(DEBUG_ERRORS
,
554 "usb_bulk_read(): NULL handle or data\n");
556 return (usb_error(EINVAL
));
560 /* do some validation first */
561 if ((rval
= usb_check_device_and_status_open(dev
, ep
,
562 USB_ENDPOINT_TYPE_BULK
, O_RDONLY
)) != 0) {
563 usb_dprintf(DEBUG_ERRORS
,
564 "usb_check_device_and_status_open() failed\n");
566 return (usb_error(rval
));
569 /* now read in the bytes */
570 received
= usb_do_io(info
->ep_fd
[ep_index
],
571 info
->ep_status_fd
[ep_index
],
578 * usb_interrupt_write:
579 * writes data to an interrupt endpoint
581 * Returns: actual number of data bytes transferred or negative errno
585 usb_interrupt_write(usb_dev_handle
*dev
, int ep
, char *data
, int size
,
588 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
589 usb_dev_handle_info_t
*info
;
591 int ep_index
= usb_ep_index(ep
);
593 usb_dprintf(DEBUG_FUNCTIONS
, "usb_interrupt_write(): ep=0x%x\n", ep
);
595 if ((hdl
== NULL
) || (data
== NULL
) || (size
<= 0)) {
596 usb_dprintf(DEBUG_ERRORS
,
597 "usb_interrupt_write(): NULL handle or data\n");
599 return (usb_error(EINVAL
));
603 /* do some validation first */
604 if ((rval
= usb_check_device_and_status_open(dev
, ep
,
605 USB_ENDPOINT_TYPE_INTERRUPT
, O_WRONLY
)) != 0) {
606 usb_dprintf(DEBUG_ERRORS
,
607 "usb_check_device_and_status_open() failed\n");
609 return (usb_error(rval
));
612 /* now transfer the bytes */
613 sent
= usb_do_io(info
->ep_fd
[ep_index
],
614 info
->ep_status_fd
[ep_index
],
621 * usb_interrupt_read:
622 * reads data from an interrupt endpoint
624 * Returns: actual number of data bytes transferred or negative errno
628 usb_interrupt_read(usb_dev_handle
*dev
, int ep
, char *data
, int size
,
631 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
632 usb_dev_handle_info_t
*info
;
633 int ep_index
, received
, rval
;
635 ep
|= USB_ENDPOINT_IN
;
636 ep_index
= usb_ep_index(ep
);
638 usb_dprintf(DEBUG_FUNCTIONS
, "usb_interrrupt_read(): ep=0x%x\n", ep
);
640 if ((hdl
== NULL
) || (data
== NULL
) || (size
<= 0)) {
641 usb_dprintf(DEBUG_ERRORS
,
642 "usb_interrupt_read(): NULL handle or data\n");
644 return (usb_error(EINVAL
));
648 /* do some validation first */
649 if ((rval
= usb_check_device_and_status_open(dev
, ep
,
650 USB_ENDPOINT_TYPE_INTERRUPT
, O_RDONLY
)) != 0) {
651 usb_dprintf(DEBUG_ERRORS
,
652 "usb_check_device_and_status_open() failed\n");
654 return (usb_error(rval
));
657 /* now transfer the bytes */
658 received
= usb_do_io(info
->ep_fd
[ep_index
],
659 info
->ep_status_fd
[ep_index
],
662 /* close the endpoint so we stop polling the endpoint now */
663 (void) close(info
->ep_fd
[ep_index
]);
664 (void) close(info
->ep_status_fd
[ep_index
]);
665 info
->ep_fd
[ep_index
] = -1;
666 info
->ep_status_fd
[ep_index
] = -1;
673 * gets a raw unicode string
675 * Returns: number of bytes transferred or negative errno
678 usb_get_string(usb_dev_handle
*dev
, int index
, int langid
, char *buf
,
682 * We can't use usb_get_descriptor() because it's lacking the index
683 * parameter. This will be fixed in libusb 1.0
685 usb_dprintf(DEBUG_FUNCTIONS
,
686 "usb_get_string(): index=%d langid=0x%x len=%d\n",
687 index
, langid
, buflen
);
689 if ((dev
== NULL
) || (buf
== NULL
) || (buflen
== 0)) {
690 usb_dprintf(DEBUG_ERRORS
,
691 "usb_get_string(): NULL handle or data\n");
693 return (usb_error(EINVAL
));
697 return (usb_control_msg(dev
, USB_DEV_REQ_DEV_TO_HOST
,
698 USB_REQ_GET_DESCRIPTOR
, (USB_DT_STRING
<< 8) + index
,
699 langid
, buf
, (int)buflen
, 1000));
703 * usb_get_string_simple:
704 * gets a cooked ascii string
706 * Returns: number of bytes transferred or negative errno
709 usb_get_string_simple(usb_dev_handle
*dev
, int index
, char *buf
,
713 int ret
, langid
, si
, di
;
715 usb_dprintf(DEBUG_FUNCTIONS
, "usb_get_string_simple(): index=%d\n",
718 if ((dev
== NULL
) || (buf
== NULL
) || (buflen
== 0)) {
719 usb_dprintf(DEBUG_ERRORS
,
720 "usb_get_string_simple(): NULL handle or data\n");
722 return (usb_error(EINVAL
));
725 (void) memset(buf
, 0, buflen
);
728 * Asking for the zero'th index is special - it returns a string
729 * descriptor that contains all the language IDs supported by the
730 * device. Typically there aren't many - often only one. The
731 * language IDs are 16 bit numbers, and they start at the third byte
732 * in the descriptor. See USB 2.0 specification, section 9.6.7, for
733 * more information on this.
735 ret
= usb_get_string(dev
, index
, 0, tbuf
, sizeof (tbuf
));
736 usb_dprintf(DEBUG_DETAILED
, "usb_get_string() returned %d\n", ret
);
741 langid
= tbuf
[2] | (tbuf
[3] << 8);
744 usb_dprintf(DEBUG_DETAILED
, "using langid=0x%x\n", langid
);
746 ret
= usb_get_string(dev
, index
, langid
, tbuf
, sizeof (tbuf
));
751 if (tbuf
[1] != USB_DT_STRING
) {
760 for (di
= 0, si
= 2; si
< tbuf
[0]; si
+= 2) {
761 if (di
>= ((int)buflen
- 1)) {
765 if (tbuf
[si
+ 1]) { /* high byte */
768 buf
[di
++] = tbuf
[si
];
778 * usb_get_descriptor_by_endpoint:
779 * usb_get_descriptor:
780 * get a descriptor. by_endpoint does not appear to make
783 * Returns: number of bytes transferred or negative errno
786 usb_get_descriptor_by_endpoint(usb_dev_handle
*udev
, int ep
,
787 uchar_t type
, uchar_t index
, void *buf
, int size
)
789 if ((udev
== NULL
) || (buf
== NULL
) || (size
<= 0)) {
790 usb_dprintf(DEBUG_ERRORS
,
791 "usb_get_descriptor_by_endpoint(): "
792 "NULL handle or data\n");
794 return (usb_error(EINVAL
));
797 (void) memset(buf
, 0, size
);
799 return (usb_control_msg(udev
,
800 ep
| USB_ENDPOINT_IN
, USB_REQ_GET_DESCRIPTOR
,
801 (type
<< 8) + index
, 0, buf
, size
, 1000));
805 usb_get_descriptor(usb_dev_handle
*udev
, uchar_t type
,
806 uchar_t index
, void *buf
, int size
)
808 if ((udev
== NULL
) || (buf
== NULL
) || (size
<= 0)) {
809 usb_dprintf(DEBUG_ERRORS
,
810 "usb_get_string_simple(): NULL handle or data\n");
812 return (usb_error(EINVAL
));
815 (void) memset(buf
, 0, size
);
817 return (usb_control_msg(udev
,
818 USB_ENDPOINT_IN
, USB_REQ_GET_DESCRIPTOR
,
819 (type
<< 8) + index
, 0, buf
, size
, 1000));
823 * usb_set_altinterface:
824 * switches to the alternate interface for the device
825 * Note that ugen does not really need this. It does implicit
826 * cfg and alt switches when the endpoint is opened.
828 * Returns: 0 or negative errno
832 usb_set_altinterface(usb_dev_handle
*dev
, int alt
)
834 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
835 usb_dev_handle_info_t
*info
;
836 usb_device_specific_t
*dev_specific
;
837 int index
, iface
, err
;
839 usb_dprintf(DEBUG_FUNCTIONS
, "usb_set_altinterface(): "
840 "hdl=0x%x alt=%d\n", hdl
, alt
);
843 usb_dprintf(DEBUG_ERRORS
,
844 "usb_set_altinterface(): NULL handle\n");
846 return (usb_error(EINVAL
));
851 if (libusb_api
== API_RELAXED
) {
852 if (info
->claimed_interface
== -1) {
854 * usb_claim_interface() should always be called
855 * prior usb_set_altinterface(), but some apps
856 * do not do this, hence we call it here assuming
857 * the default interface.
859 if ((err
= usb_claim_interface(dev
, 0))) {
866 iface
= info
->claimed_interface
;
867 dev_specific
= (usb_device_specific_t
*)(hdl
->device
->dev
);
869 usb_dprintf(DEBUG_DETAILED
, "claimed=%d, cfgvalue=%d, hdl=0x%x\n",
870 info
->claimed_interface
, info
->configuration_value
,
871 dev_specific
->claimed_interfaces
[iface
], hdl
);
873 if ((info
->claimed_interface
== -1) ||
874 (info
->configuration_value
== -1) ||
875 (hdl
!= dev_specific
->claimed_interfaces
[iface
])) {
877 return (usb_error(EACCES
));
880 usb_close_all_eps(hdl
);
882 /* find the conf index */
883 for (index
= 0; index
< hdl
->device
->descriptor
.bNumConfigurations
;
885 if (info
->configuration_value
==
886 hdl
->device
->config
[index
].bConfigurationValue
) {
891 usb_dprintf(DEBUG_DETAILED
,
892 "cfg value=%d index=%d, iface=%d, alt=%d #alts=%d\n",
893 info
->configuration_value
, index
, iface
, alt
,
894 hdl
->device
->config
[index
].interface
[iface
].num_altsetting
);
896 if ((alt
< 0) || (alt
>= hdl
->device
->
897 config
[index
].interface
[iface
].num_altsetting
)) {
899 return (usb_error(EINVAL
));
902 info
->alternate
= alt
;
904 usb_set_ep_iface_alts(hdl
, info
, index
, iface
, alt
);
910 * usb_set_configuration:
911 * sets the configuration for the device.
912 * ugen implicitly switches configuration and rejects
913 * set configuration requests
919 usb_set_configuration(usb_dev_handle
*dev
, int configuration
)
921 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
922 usb_dev_handle_info_t
*info
;
925 usb_dprintf(DEBUG_FUNCTIONS
,
926 "usb_set_configuration(): config = %d\n", configuration
);
929 usb_dprintf(DEBUG_ERRORS
,
930 "usb_set_configuration(): NULL handle\n");
932 return (usb_error(EINVAL
));
936 /* find the conf index */
937 for (index
= 0; index
< hdl
->device
->descriptor
.bNumConfigurations
;
940 hdl
->device
->config
[index
].bConfigurationValue
) {
945 if (index
>= hdl
->device
->descriptor
.bNumConfigurations
) {
946 usb_dprintf(DEBUG_ERRORS
,
947 "usb_set_configuration(): invalid\n");
949 return (usb_error(EINVAL
));
952 usb_close_all_eps(hdl
);
953 info
->configuration_value
= configuration
;
954 info
->configuration_index
= index
;
956 /* reset ep arrays */
957 for (i
= 0; i
< USB_MAXENDPOINTS
; i
++) {
958 info
->ep_interface
[i
] = -1;
960 if (info
->claimed_interface
!= -1) {
961 (void) usb_release_interface(dev
, info
->claimed_interface
);
969 * clears a halted endpoint
970 * ugen has auto clearing but we send the request anyways
972 * Returns: 0 or negative errno
976 usb_clear_halt(usb_dev_handle
*dev
, unsigned int ep
)
979 int index
= usb_ep_index(ep
);
980 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
981 usb_dev_handle_info_t
*info
;
983 usb_dprintf(DEBUG_FUNCTIONS
, "usb_clear_halt(): ep=0x%x\n", ep
);
986 usb_dprintf(DEBUG_ERRORS
,
987 "usb_clear_halt(): NULL handle\n");
989 return (usb_error(EINVAL
));
993 usb_dprintf(DEBUG_DETAILED
, "index=0x%x, ep_intf=%d\n",
994 index
, info
->ep_interface
[index
]);
996 if (info
->ep_interface
[index
] == -1) {
998 return (usb_error(EINVAL
));
1002 /* only check for ep > 0 */
1003 if (ep
&& ((rval
= usb_check_access(dev
) != 0))) {
1005 return (usb_error(rval
));
1008 rval
= usb_control_msg(dev
,
1009 USB_DEV_REQ_HOST_TO_DEV
| USB_RECIP_ENDPOINT
,
1010 USB_REQ_CLEAR_FEATURE
, 0, ep
, NULL
, 0, 0);
1013 usb_error_str(errno
, "could not clear feature on ep=0x%x", ep
);
1020 * usb_claim_interface:
1021 * ugen does not have a claim interface concept but all endpoints
1022 * are opened exclusively. This provides some exclusion. However,
1023 * the interrupt IN endpoint is closed after the read
1025 * Returns: 0 or negative errno
1028 usb_claim_interface(usb_dev_handle
*dev
, int interface
)
1030 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
1031 usb_dev_handle_info_t
*info
;
1032 usb_device_specific_t
*dev_specific
;
1036 usb_dprintf(DEBUG_ERRORS
,
1037 "usb_claim_interface(): NULL handle\n");
1039 return (usb_error(EINVAL
));
1042 dev_specific
= (usb_device_specific_t
*)(hdl
->device
->dev
);
1044 usb_dprintf(DEBUG_FUNCTIONS
, "usb_claim_interface(): hdl=0x%x: "
1045 "interface = %d\n", hdl
, interface
);
1047 if (info
->configuration_value
== -1) {
1050 /* find the conf index */
1052 index
< hdl
->device
->descriptor
.bNumConfigurations
;
1054 if (info
->configuration_value
==
1055 hdl
->device
->config
[index
].bConfigurationValue
) {
1060 info
->configuration_value
=
1061 hdl
->device
->config
[index
].bConfigurationValue
;
1062 info
->configuration_index
= index
;
1064 usb_dprintf(DEBUG_DETAILED
, "configuration_value=%d, index=%d\n",
1065 info
->configuration_value
, index
);
1067 /* is this a valid interface? */
1068 if ((interface
< 0) || (interface
> 255) ||
1069 (interface
>= hdl
->device
->config
[index
].bNumInterfaces
)) {
1071 return (usb_error(EINVAL
));
1074 /* already claimed? */
1075 if (dev_specific
->claimed_interfaces
[interface
] == hdl
) {
1080 if (info
->claimed_interface
!= -1) {
1082 return (usb_error(EBUSY
));
1085 if (dev_specific
->claimed_interfaces
[interface
] != 0) {
1087 return (usb_error(EBUSY
));
1090 usb_dprintf(DEBUG_DETAILED
, "usb_claim_interface(): hdl=0x%x: "
1091 "interface = %d, claimed by this udev=%d, by hdl=0x%x\n",
1092 hdl
, interface
, info
->claimed_interface
,
1093 dev_specific
->claimed_interfaces
[interface
]);
1096 info
->claimed_interface
= interface
;
1097 info
->alternate
= 0;
1098 dev_specific
->claimed_interfaces
[interface
] = hdl
;
1100 usb_set_ep_iface_alts(hdl
, info
, index
, interface
, 0);
1106 * usb_release_interface:
1107 * releases the acquired interface
1109 * Returns: 0 or negative errno
1113 usb_release_interface(usb_dev_handle
*dev
, int interface
)
1115 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
1116 usb_dev_handle_info_t
*info
;
1117 usb_device_specific_t
*dev_specific
;
1120 usb_dprintf(DEBUG_ERRORS
,
1121 "usb_release_interface(): NULL handle\n");
1123 return (usb_error(EINVAL
));
1127 dev_specific
= (usb_device_specific_t
*)(hdl
->device
->dev
);
1129 usb_dprintf(DEBUG_FUNCTIONS
, "usb_release_interface(): hdl=0x%x: "
1130 "interface = %d\n", hdl
, interface
);
1132 if ((info
->claimed_interface
== -1) ||
1133 (info
->claimed_interface
!= interface
)) {
1135 return (usb_error(EINVAL
));
1138 usb_dprintf(DEBUG_DETAILED
, "usb_release_interface(): hdl=0x%x: "
1139 "interface = %d, claimed by this udev=%d, by hdl=0x%x\n",
1140 hdl
, interface
, info
->claimed_interface
,
1141 dev_specific
->claimed_interfaces
[interface
]);
1143 dev_specific
->claimed_interfaces
[interface
] = 0;
1144 info
->claimed_interface
= -1;
1151 * resets the endpoint
1153 * Returns: 0 or negative errno
1156 usb_resetep(usb_dev_handle
*dev
, unsigned int ep
)
1158 usb_dprintf(DEBUG_FUNCTIONS
, "usb_resetep(): ep=0x%x\n", ep
);
1160 return (usb_clear_halt(dev
, ep
));
1170 usb_reset(usb_dev_handle
* dev
)
1174 usb_dprintf(DEBUG_FUNCTIONS
, "usb_reset():\n");
1177 usb_dprintf(DEBUG_ERRORS
,
1178 "usb_reset(): NULL handle\n");
1180 return (usb_error(EINVAL
));
1183 if ((rval
= usb_check_access(dev
)) != 0) {
1185 return (usb_error(rval
));
1188 return (usb_error(ENOTSUP
));
1195 * creates setup data and send it
1197 * Returns: number of bytes transferred or negative errno
1200 usb_send_msg(int fd
, int stat_fd
, int requesttype
, int request
, int value
,
1201 int index
, char *data
, int size
)
1206 usb_dprintf(DEBUG_DETAILED
, "usb_send_msg():\n"
1207 "\trequesttype 0x%x\n"
1212 requesttype
, request
, value
, index
, size
);
1214 req
[0] = (uint8_t)requesttype
;
1215 req
[1] = (uint8_t)request
;
1216 req
[2] = (uint8_t)value
;
1217 req
[3] = (uint8_t)(value
>> 8);
1218 req
[4] = (uint8_t)index
;
1219 req
[5] = (uint8_t)(index
>> 8);
1220 req
[6] = (uint8_t)size
;
1221 req
[7] = (uint8_t)(size
>> 8);
1223 if (requesttype
& USB_DEV_REQ_DEV_TO_HOST
) {
1224 rval
= usb_do_io(fd
, stat_fd
, (char *)&req
,
1225 sizeof (req
), WRITE
);
1227 /* append the write data */
1230 if ((buffer
= malloc(size
+ 8)) == NULL
) {
1232 return (usb_error(ENOMEM
));
1235 (void) memcpy(buffer
, &req
, 8);
1236 (void) memcpy(&buffer
[8], data
, size
);
1237 rval
= usb_do_io(fd
, stat_fd
, buffer
,
1238 (uint_t
)sizeof (req
) + size
, WRITE
);
1241 usb_dprintf(DEBUG_FUNCTIONS
, "usb_send_msg(): rval=%d\n", rval
);
1248 * performs i/o to/from an endpoint and check the
1249 * status of the device if error or short xfer.
1251 * Returns: bytes transferred or negative errno
1254 usb_do_io(int fd
, int stat_fd
, char *data
, size_t size
, int flag
)
1259 usb_dprintf(DEBUG_FUNCTIONS
, "usb_do_io(): size=0x%x flag=%d\n",
1269 ret
= read(fd
, data
, size
);
1270 usb_dump_data(data
, (int)size
);
1273 usb_dump_data(data
, (int)size
);
1274 ret
= write(fd
, data
, size
);
1278 int save_errno
= errno
;
1280 /* usb_get_status will do a read and overwrite errno */
1281 error
= usb_get_status(stat_fd
);
1282 usb_error_str(save_errno
, "error %d doing io: errno=%d",
1285 return (-save_errno
);
1288 usb_dprintf(DEBUG_FUNCTIONS
, "usb_do_io(): amount=%d\n", ret
);
1295 * basically checks if the interface has been claimed
1297 * Returns: 0 or EACCES/EINVAL
1300 usb_check_access(usb_dev_handle
*dev
)
1302 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
1303 usb_dev_handle_info_t
*info
= hdl
->info
;
1311 usb_dprintf(DEBUG_FUNCTIONS
, "usb_check_access(): "
1312 "hdl=0x%x conf=%d claimed=%d alternate=%d\n",
1313 (int)hdl
, info
->configuration_value
,
1314 info
->claimed_interface
, info
->alternate
);
1316 if ((info
->configuration_value
== -1) ||
1317 (info
->claimed_interface
== -1) ||
1318 (info
->alternate
== -1)) {
1327 * usb_set_ep_iface_alts:
1328 * initialize ep_interface arrays
1331 usb_set_ep_iface_alts(usb_dev_handle_impl_t
*hdl
, usb_dev_handle_info_t
*info
,
1332 int index
, int interface
, int alternate
)
1334 struct usb_interface_descriptor
*if_descr
;
1335 struct usb_endpoint_descriptor
*ep_descr
;
1338 /* reinitialize endpoint arrays */
1339 for (i
= 0; i
< USB_MAXENDPOINTS
; i
++) {
1340 info
->ep_interface
[i
] = -1;
1344 * for the current config, this interface and alt,
1345 * which endpoints are available
1347 if_descr
= &hdl
->device
->config
[index
].interface
[interface
].
1348 altsetting
[alternate
];
1350 usb_dprintf(DEBUG_DETAILED
, "cfg%d.%d.%d has %d endpoints\n",
1351 info
->configuration_value
, interface
, alternate
,
1352 if_descr
->bNumEndpoints
);
1354 for (i
= 0; i
< if_descr
->bNumEndpoints
; i
++) {
1355 ep_descr
= &hdl
->device
->config
[index
].interface
[interface
].
1356 altsetting
[alternate
].endpoint
[i
];
1357 info
->ep_interface
[usb_ep_index(
1358 ep_descr
->bEndpointAddress
)] = interface
;
1361 usb_dprintf(DEBUG_DETAILED
, "ep_interface:\n");
1362 for (i
= 0; i
< USB_MAXENDPOINTS
; i
++) {
1363 usb_dprintf(DEBUG_DETAILED
, "%d ",
1364 info
->ep_interface
[i
]);
1366 usb_dprintf(DEBUG_DETAILED
, "\n");
1370 * usb_check_device_and_status_open:
1371 * Make sure that the endpoint and status device for the endpoint
1372 * can be opened, or have already been opened.
1377 usb_check_device_and_status_open(usb_dev_handle
*dev
, int ep
, int ep_type
,
1380 usb_dev_handle_impl_t
*hdl
= (usb_dev_handle_impl_t
*)dev
;
1381 usb_dev_handle_info_t
*info
= hdl
->info
;
1382 char *filename
, *statfilename
, cfg_num
[16], alt_num
[16];
1383 int fd
, fdstat
, index
, rval
;
1385 index
= usb_ep_index(ep
);
1387 usb_dprintf(DEBUG_FUNCTIONS
,
1388 "usb_check_device_and_status_open(): "
1389 "ep=0x%x mode=%d index=%d\n", ep
, mode
, index
);
1391 if ((rval
= usb_check_access(dev
)) != 0) {
1396 if ((index
< 0) || (index
> 31)) {
1401 usb_dprintf(DEBUG_DETAILED
, "claimed=%d ep_interface=%d\n",
1402 info
->claimed_interface
, info
->ep_interface
[index
]);
1404 if (info
->claimed_interface
!= info
->ep_interface
[index
]) {
1409 if ((info
->ep_fd
[index
] > 0) && (info
->ep_status_fd
[index
] > 0)) {
1415 /* should already be open */
1420 if ((filename
= malloc(PATH_MAX
+1)) == NULL
) {
1424 if ((statfilename
= malloc(PATH_MAX
+1)) == NULL
) {
1430 usb_dprintf(DEBUG_DETAILED
, "cfgvalue=%d\n",
1431 info
->configuration_value
);
1433 /* create filename */
1434 if (info
->configuration_index
> 0) {
1435 (void) snprintf(cfg_num
, sizeof (cfg_num
), "cfg%d",
1436 info
->configuration_value
);
1438 (void) memset(cfg_num
, 0, sizeof (cfg_num
));
1441 if (info
->alternate
> 0) {
1442 (void) snprintf(alt_num
, sizeof (alt_num
), ".%d",
1445 (void) memset(alt_num
, 0, sizeof (alt_num
));
1448 (void) snprintf(filename
, PATH_MAX
, "%s/%s/%sif%d%s%s%d",
1449 hdl
->device
->bus
->dirname
, hdl
->device
->filename
,
1450 cfg_num
, info
->ep_interface
[index
],
1451 alt_num
, (ep
& USB_EP_DIR_MASK
) ? "in" :
1452 "out", (ep
& USB_EP_NUM_MASK
));
1454 usb_dprintf(DEBUG_DETAILED
,
1455 "usb_check_device_and_status_open: %s\n", filename
);
1458 * for interrupt IN endpoints, we need to enable one xfer
1459 * mode before opening the endpoint
1461 (void) snprintf(statfilename
, PATH_MAX
, "%sstat", filename
);
1463 if ((ep_type
== USB_ENDPOINT_TYPE_INTERRUPT
) &&
1464 (ep
& USB_ENDPOINT_IN
)) {
1465 char control
= USB_EP_INTR_ONE_XFER
;
1468 /* open the status device node for the ep first RDWR */
1469 if ((fdstat
= open(statfilename
, O_RDWR
)) == -1) {
1470 usb_error_str(errno
, "can't open %s RDWR: %d",
1471 statfilename
, errno
);
1473 /* might be an older ugen version, try RDONLY */
1474 if ((fdstat
= open(statfilename
,
1476 usb_error_str(errno
,
1477 "can't open %s RDONLY: %d",
1485 count
= write(fdstat
, &control
, sizeof (control
));
1488 /* this should have worked */
1489 usb_error_str(errno
, "can't write to %s: %d",
1493 (void) close(fdstat
);
1499 if ((fdstat
= open(statfilename
, O_RDONLY
)) == -1) {
1500 usb_error_str(errno
, "can't open %s: %d",
1501 statfilename
, errno
);
1510 if ((fd
= open(filename
, mode
)) == -1) {
1511 usb_error_str(errno
, "can't open %s: %d",
1513 (void) close(fdstat
);
1522 info
->ep_fd
[index
] = fd
;
1523 info
->ep_status_fd
[index
] = fdstat
;
1531 * creates an index from endpoint address that can
1532 * be used to index into endpoint lists
1534 * Returns: ep index (a number between 0 and 31)
1537 usb_ep_index(uint8_t ep_addr
)
1539 return ((ep_addr
& USB_EP_NUM_MASK
) +
1540 ((ep_addr
& USB_EP_DIR_MASK
) ? 16 : 0));
1545 * opens default pipe
1550 usb_open_ep0(usb_dev_handle_impl_t
*hdl
)
1553 usb_device_specific_t
*dev_specific
=
1554 (usb_device_specific_t
*)(hdl
->device
->dev
);
1556 usb_dprintf(DEBUG_FUNCTIONS
, "usb_open_ep0():\n");
1558 if (dev_specific
->ep0_fd
) {
1559 dev_specific
->ref_count
++;
1560 hdl
->info
->ep_fd
[0] = dev_specific
->ep0_fd
;
1561 hdl
->info
->ep_status_fd
[0] = dev_specific
->ep0_fd_stat
;
1563 usb_dprintf(DEBUG_DETAILED
,
1564 "usb_open_ep0(): already open, ref=%d\n",
1565 dev_specific
->ref_count
);
1570 if ((filename
= malloc(PATH_MAX
+1)) == NULL
) {
1575 (void) snprintf(filename
, PATH_MAX
, "%s/%s/cntrl0",
1576 hdl
->device
->bus
->dirname
, hdl
->device
->filename
);
1578 usb_dprintf(DEBUG_DETAILED
, "opening %s\n", filename
);
1580 hdl
->info
->ep_fd
[0] = open(filename
, O_RDWR
);
1581 if (hdl
->info
->ep_fd
[0] < 0) {
1582 usb_dprintf(DEBUG_ERRORS
, "opening ep0 failed, %d\n",
1583 hdl
->info
->ep_fd
[0]);
1589 (void) snprintf(filename
, PATH_MAX
, "%s/%s/cntrl0stat",
1590 hdl
->device
->bus
->dirname
, hdl
->device
->filename
);
1592 usb_dprintf(DEBUG_DETAILED
, "opening %s\n", filename
);
1594 hdl
->info
->ep_status_fd
[0] = open(filename
, O_RDONLY
);
1595 if (hdl
->info
->ep_status_fd
[0] < 0) {
1601 /* allow sharing between multiple opens */
1602 dev_specific
->ep0_fd
= hdl
->info
->ep_fd
[0];
1603 dev_specific
->ep0_fd_stat
= hdl
->info
->ep_status_fd
[0];
1604 dev_specific
->ref_count
++;
1606 usb_dprintf(DEBUG_DETAILED
, "ep0 opened\n");
1615 * closes default ep0
1618 usb_close_ep0(usb_dev_handle_impl_t
*hdl
)
1620 usb_device_specific_t
*dev_specific
=
1621 (usb_device_specific_t
*)(hdl
->device
->dev
);
1623 usb_dprintf(DEBUG_FUNCTIONS
, "usb_close_ep0():\n");
1625 if (dev_specific
->ep0_fd
) {
1626 if (--(dev_specific
->ref_count
) > 0) {
1627 usb_dprintf(DEBUG_DETAILED
,
1628 "usb_close_ep0(): ref_count=%d\n",
1629 dev_specific
->ref_count
);
1635 if (hdl
->info
->ep_fd
[0] != -1) {
1636 (void) close(hdl
->info
->ep_fd
[0]);
1637 hdl
->info
->ep_fd
[0] = -1;
1639 if (hdl
->info
->ep_status_fd
[0] != -1) {
1640 (void) close(hdl
->info
->ep_status_fd
[0]);
1641 hdl
->info
->ep_status_fd
[0] = -1;
1643 dev_specific
->ep0_fd
= 0;
1644 dev_specific
->ep0_fd_stat
= 0;
1648 * usb_close_all_eps:
1649 * closes all open endpoints except 0
1652 usb_close_all_eps(usb_dev_handle_impl_t
*hdl
)
1656 usb_dprintf(DEBUG_FUNCTIONS
, "usb_close_all_eps():\n");
1658 for (i
= 1; i
< USB_MAXENDPOINTS
; i
++) {
1659 if (hdl
->info
->ep_fd
[i
] != -1) {
1660 (void) close(hdl
->info
->ep_fd
[i
]);
1661 hdl
->info
->ep_fd
[i
] = -1;
1663 if (hdl
->info
->ep_status_fd
[i
] != -1) {
1664 (void) close(hdl
->info
->ep_status_fd
[i
]);
1665 hdl
->info
->ep_status_fd
[i
] = -1;
1671 * usb_setup_all_configs:
1672 * parses config cloud for each config
1677 usb_setup_all_configs(usb_dev_handle_impl_t
*hdl
)
1679 char buffer
[USB_DEV_DESCR_SIZE
];
1683 if (hdl
->device
->config
) {
1688 usb_dprintf(DEBUG_FUNCTIONS
, "usb_setup_all_configs():\n");
1690 /* get device descriptor */
1691 rval
= usb_control_msg((usb_dev_handle
*)hdl
,
1692 USB_DEV_REQ_DEV_TO_HOST
| USB_TYPE_STANDARD
,
1693 USB_REQ_GET_DESCRIPTOR
, USB_DESCR_TYPE_SETUP_DEV
,
1694 0, buffer
, USB_DEV_DESCR_SIZE
, 0);
1696 usb_dprintf(DEBUG_DETAILED
, "dev descr rval=%d\n", rval
);
1698 if (rval
!= USB_DEV_DESCR_SIZE
) {
1703 /* parse device descriptor */
1704 rval
= (int)usb_parse_dev_descr((uchar_t
*)buffer
, sizeof (buffer
),
1705 (struct usb_device_descriptor
*)&hdl
->device
->descriptor
,
1706 sizeof (struct usb_device_descriptor
));
1708 usb_dprintf(DEBUG_DETAILED
, "parse dev descr rval=%d\n", rval
);
1710 if (rval
!= (int)sizeof (struct usb_device_descriptor
)) {
1715 /* allocate config array */
1716 len
= (int) sizeof (struct usb_config_descriptor
) *
1717 hdl
->device
->descriptor
.bNumConfigurations
;
1719 if ((hdl
->device
->config
= calloc(len
, 1)) == NULL
) {
1724 /* parse each config cloud */
1725 for (index
= 0; index
< hdl
->device
->descriptor
.bNumConfigurations
;
1727 if ((rval
= usb_parse_config(hdl
, index
)) != 0) {
1737 * usb_free_all_configs:
1738 * frees all allocated resources
1741 usb_free_all_configs(usb_device_t
*dev
)
1745 usb_dprintf(DEBUG_FUNCTIONS
, "usb_free_all_configs(): "
1746 "dev=0x%x config=0x%x #conf=%d\n",
1747 dev
, dev
->config
, dev
->descriptor
.bNumConfigurations
);
1750 for (index
= 0; index
< dev
->descriptor
.bNumConfigurations
;
1752 usb_free_config(dev
, index
);
1761 * parse config descriptor and get cloud
1766 usb_parse_config(usb_dev_handle_impl_t
*hdl
, uint_t index
)
1770 char buffer
[USB_CFG_DESCR_SIZE
];
1772 unsigned char *extra
;
1775 usb_dprintf(DEBUG_FUNCTIONS
, "usb_parse_config(): index=%d\n",
1778 rval
= usb_control_msg((usb_dev_handle
*)hdl
,
1779 USB_DEV_REQ_DEV_TO_HOST
| USB_TYPE_STANDARD
,
1780 USB_REQ_GET_DESCRIPTOR
, USB_DESCR_TYPE_SETUP_CFG
| index
,
1781 0, buffer
, USB_CFG_DESCR_SIZE
, 0);
1783 usb_dprintf(DEBUG_DETAILED
, "config descr rval=%d expecting %d\n",
1784 rval
, USB_CFG_DESCR_SIZE
);
1786 if (rval
< USB_CFG_DESCR_SIZE
) {
1791 rval
= (int)usb_parse_cfg_descr((uchar_t
*)buffer
, sizeof (buffer
),
1792 (usb_cfg_descr_t
*)&hdl
->device
->config
[index
],
1793 sizeof (usb_cfg_descr_t
), &extra
, &extralen
);
1795 usb_dprintf(DEBUG_DETAILED
, "config descr rval=%d expecting %d\n",
1796 rval
, sizeof (usb_cfg_descr_t
));
1798 if (rval
< USB_CFG_DESCR_SIZE
) {
1803 usb_dprintf(DEBUG_DETAILED
,
1804 "cfg%d: len=%d type=%d total=%d #if=%d cf=%d\n", index
,
1805 hdl
->device
->config
[index
].bLength
,
1806 hdl
->device
->config
[index
].bDescriptorType
,
1807 hdl
->device
->config
[index
].wTotalLength
,
1808 hdl
->device
->config
[index
].bNumInterfaces
,
1809 hdl
->device
->config
[index
].bConfigurationValue
);
1811 if ((cloud
= malloc(hdl
->device
->config
[index
].wTotalLength
)) ==
1817 /* get complete cloud */
1818 rval
= usb_control_msg((usb_dev_handle
*)hdl
,
1819 USB_DEV_REQ_DEV_TO_HOST
| USB_TYPE_STANDARD
,
1820 USB_REQ_GET_DESCRIPTOR
, USB_DESCR_TYPE_SETUP_CFG
| index
,
1822 hdl
->device
->config
[index
].wTotalLength
, 0);
1824 if (rval
!= hdl
->device
->config
[index
].wTotalLength
) {
1830 /* parse descriptor again to get extra descriptors */
1831 rval
= (int)usb_parse_cfg_descr((uchar_t
*)cloud
,
1832 hdl
->device
->config
[index
].wTotalLength
,
1833 (usb_cfg_descr_t
*)&hdl
->device
->config
[index
],
1834 sizeof (usb_cfg_descr_t
), &extra
, &extralen
);
1837 usb_dprintf(DEBUG_DETAILED
,
1838 "cfg%d: extra descriptors length=%d:\n",
1840 usb_dump_data((char *)extra
, extralen
);
1842 if ((hdl
->device
->config
[index
].extra
=
1843 calloc(extralen
, 1)) == NULL
) {
1849 (void) memcpy(hdl
->device
->config
[index
].extra
, extra
,
1851 hdl
->device
->config
[index
].extralen
= extralen
;
1854 /* allocate interface array */
1855 len
= hdl
->device
->config
[index
].bNumInterfaces
*
1856 (int)sizeof (struct usb_interface
);
1857 if ((hdl
->device
->config
[index
].interface
= calloc(len
, 1)) ==
1864 for (iface
= 0; iface
< hdl
->device
->config
[index
].bNumInterfaces
;
1866 rval
= usb_parse_interface(hdl
, index
, iface
, cloud
);
1880 * frees all allocated config resources
1883 usb_free_config(usb_device_t
*device
, uint_t index
)
1887 usb_dprintf(DEBUG_FUNCTIONS
, "usb_free_config(): index=%d\n",
1890 if (device
->config
[index
].interface
) {
1891 for (iface
= 0; iface
< device
->config
[index
].bNumInterfaces
;
1893 usb_free_interface(device
, index
, iface
);
1895 if (device
->config
[index
].extralen
) {
1896 free(device
->config
[index
].extra
);
1898 free(device
->config
[index
].interface
);
1903 * usb_parse_interface:
1904 * parse an interface descriptor
1909 usb_parse_interface(usb_dev_handle_impl_t
*hdl
, uint_t index
, uint_t iface
,
1912 usb_if_descr_t if_descr
;
1914 uint_t alt
, max_alt
, len
;
1915 unsigned char *extra
;
1918 usb_dprintf(DEBUG_FUNCTIONS
, "usb_parse_interface(): "
1919 "index=%d, iface=%d\n", index
, iface
);
1921 /* count the number of alternates for this interface */
1922 for (max_alt
= alt
= 0; alt
< USB_MAXALTSETTING
; alt
++) {
1923 rval
= (int)usb_parse_if_descr((uchar_t
*)cloud
,
1924 hdl
->device
->config
[index
].wTotalLength
,
1925 iface
, alt
, &if_descr
, sizeof (if_descr
),
1928 usb_dprintf(DEBUG_DETAILED
, "usb_parse_interface: "
1929 "alt %d: rval=%d expecting %d\n",
1930 alt
, rval
, sizeof (if_descr
));
1932 if (rval
!= (int)sizeof (if_descr
)) {
1939 usb_dprintf(DEBUG_DETAILED
,
1940 "usb_parse_interface: max_alt=%d\n", max_alt
);
1942 /* allocate alt interface setting array */
1943 len
= ++max_alt
* (int)sizeof (struct usb_interface_descriptor
);
1944 if ((hdl
->device
->config
[index
].interface
[iface
].altsetting
=
1945 calloc(len
, 1)) == NULL
) {
1949 hdl
->device
->config
[index
].interface
[iface
].num_altsetting
=
1951 for (alt
= 0; alt
< max_alt
; alt
++) {
1952 rval
= usb_parse_alternate(hdl
, index
, iface
, alt
, cloud
);
1963 * usb_free_interface:
1964 * frees interface resources
1969 usb_free_interface(usb_device_t
*device
, uint_t index
, uint_t iface
)
1971 uint_t alt
, max_alt
;
1973 usb_dprintf(DEBUG_FUNCTIONS
, "usb_free_interface(): "
1974 "index=%d, iface=%d\n", index
, iface
);
1976 if (device
->config
[index
].interface
[iface
].altsetting
) {
1977 max_alt
= device
->config
[index
].interface
[iface
].
1979 for (alt
= 0; alt
< max_alt
; alt
++) {
1980 usb_free_alternate(device
, index
, iface
, alt
);
1982 free(device
->config
[index
].interface
[iface
].altsetting
);
1987 * usb_parse_alternate:
1988 * parses each alternate descriptor
1993 usb_parse_alternate(usb_dev_handle_impl_t
*hdl
, uint_t index
, uint_t iface
,
1994 uint_t alt
, char *cloud
)
1997 usb_if_descr_t if_descr
;
1999 unsigned char *extra
;
2002 usb_dprintf(DEBUG_FUNCTIONS
, "usb_parse_alternate(): "
2003 "index=%d, iface=%d, alt=%d\n", index
, iface
, alt
);
2005 rval
= (int)usb_parse_if_descr((uchar_t
*)cloud
,
2006 hdl
->device
->config
[index
].wTotalLength
,
2007 iface
, alt
, &if_descr
, sizeof (if_descr
), &extra
, &extralen
);
2009 if (rval
!= (int)sizeof (if_descr
)) {
2010 usb_dprintf(DEBUG_ERRORS
, "usb_parse_alternate: rval=%d\n",
2016 usb_dprintf(DEBUG_DETAILED
,
2017 "cfg%d.if%d.%d: len=%d type=%d num=%d alt=%d #ep=%d c=%d"
2018 " sc=%d p=%d i=%d\n", index
, iface
, alt
,
2020 if_descr
.bDescriptorType
,
2021 if_descr
.bInterfaceNumber
,
2022 if_descr
.bAlternateSetting
,
2023 if_descr
.bNumEndpoints
,
2024 if_descr
.bInterfaceClass
,
2025 if_descr
.bInterfaceSubClass
,
2026 if_descr
.bInterfaceProtocol
,
2027 if_descr
.iInterface
);
2030 &hdl
->device
->config
[index
].interface
[iface
].altsetting
[alt
],
2031 &if_descr
, sizeof (if_descr
));
2034 usb_dprintf(DEBUG_DETAILED
,
2035 "cfg%d.if%d.%d: extralen=%d:\n", index
, iface
, alt
,
2037 usb_dump_data((char *)extra
, extralen
);
2039 if ((hdl
->device
->config
[index
].interface
[iface
].
2040 altsetting
[alt
].extra
= calloc(extralen
, 1)) == NULL
) {
2045 hdl
->device
->config
[index
].interface
[iface
].
2046 altsetting
[alt
].extra
, extra
, extralen
);
2047 hdl
->device
->config
[index
].interface
[iface
].
2048 altsetting
[alt
].extralen
= extralen
;
2051 if (if_descr
.bNumEndpoints
== 0) {
2056 /* allocate endpoint array for this alternate */
2057 len
= if_descr
.bNumEndpoints
*
2058 (int)sizeof (struct usb_endpoint_descriptor
);
2059 if ((hdl
->device
->config
[index
].interface
[iface
].altsetting
[alt
].
2060 endpoint
= calloc(len
, 1)) == NULL
) {
2065 for (ep
= 0; ep
< if_descr
.bNumEndpoints
; ep
++) {
2066 rval
= usb_parse_endpoint(hdl
, index
, iface
, alt
, ep
, cloud
);
2078 * usb_free_alternate:
2079 * frees all alternate resources
2082 usb_free_alternate(usb_device_t
*device
, uint_t index
, uint_t iface
,
2085 usb_dprintf(DEBUG_FUNCTIONS
, "usb_free_alternate(): "
2086 "index=%d, iface=%d, alt=%d\n", index
, iface
, alt
);
2088 if (device
->config
[index
].interface
[iface
].altsetting
[alt
].
2091 struct usb_interface_descriptor
*if_descr
=
2092 &device
->config
[index
].
2093 interface
[iface
].altsetting
[alt
];
2095 for (ep
= 0; ep
< if_descr
->bNumEndpoints
; ep
++) {
2096 if (if_descr
->extralen
) {
2097 free(if_descr
->extra
);
2101 if (device
->config
[index
].interface
[iface
].altsetting
[alt
].
2103 free(device
->config
[index
].interface
[iface
].
2104 altsetting
[alt
].extra
);
2106 free(device
->config
[index
].interface
[iface
].altsetting
[alt
].
2112 * usb_parse_endpoint:
2113 * parses an endpoint descriptor
2118 usb_parse_endpoint(usb_dev_handle_impl_t
*hdl
, int index
, int iface
,
2119 int alt
, int ep
, char *cloud
)
2121 usb_ep_descr_t ep_descr
;
2123 unsigned char *extra
;
2126 usb_dprintf(DEBUG_FUNCTIONS
, "usb_parse_endpoint(): "
2127 "index=%d, iface=%d, alt=%d, ep=0x%x\n",
2128 index
, iface
, alt
, ep
);
2130 rval
= (int)usb_parse_ep_descr((uchar_t
*)cloud
,
2131 hdl
->device
->config
[index
].wTotalLength
,
2132 iface
, alt
, ep
, &ep_descr
, sizeof (ep_descr
),
2135 if (rval
< USB_EP_DESCR_SIZE
) {
2136 usb_dprintf(DEBUG_ERRORS
, "usb_parse_endpoint: rval=%d, "
2137 "expecting %d\n", rval
, USB_EP_DESCR_SIZE
);
2142 usb_dprintf(DEBUG_DETAILED
,
2143 "\tl=%d t=%d a=0x%x attr=0x%x max=%d int=%d\n",
2144 ep_descr
.bLength
, ep_descr
.bDescriptorType
,
2145 ep_descr
.bEndpointAddress
, ep_descr
.bmAttributes
,
2146 ep_descr
.wMaxPacketSize
, ep_descr
.bInterval
);
2148 (void) memcpy(&hdl
->device
->
2149 config
[index
].interface
[iface
].altsetting
[alt
].endpoint
[ep
],
2150 &ep_descr
, sizeof (ep_descr
));
2153 usb_dprintf(DEBUG_DETAILED
,
2154 "cfg%d.if%d.%d.ep%d: extralen=%d:\n",
2155 index
, iface
, alt
, ep
, extralen
);
2156 usb_dump_data((char *)extra
, extralen
);
2158 if ((hdl
->device
->config
[index
].interface
[iface
].
2159 altsetting
[alt
].endpoint
[ep
].extra
=
2160 calloc(extralen
, 1)) == NULL
) {
2164 (void) memcpy(hdl
->device
->config
[index
].interface
[iface
].
2165 altsetting
[alt
].endpoint
[ep
].extra
, extra
, extralen
);
2166 hdl
->device
->config
[index
].interface
[iface
].
2167 altsetting
[alt
].endpoint
[ep
].extralen
= extralen
;
2175 * adds dev to the beginning of the list
2178 usb_add_device(usb_device_t
**list
, usb_device_t
*dev
)
2182 dev
->next
->prev
= dev
;
2191 * usb_remove_device:
2192 * removes dev from a list
2195 usb_remove_device(usb_device_t
**list
, usb_device_t
*dev
)
2198 dev
->prev
->next
= dev
->next
;
2203 dev
->next
->prev
= dev
->prev
;
2205 dev
->prev
= dev
->next
= NULL
;
2209 * usb_check_device_in_list:
2210 * checks if dev is in list
2212 * Returns: 1 (yes), 0 (no)
2215 usb_check_device_in_list(usb_device_t
*list
, usb_device_t
*dev
)
2217 usb_device_t
*d
= list
;
2232 * frees the entire bus structure, not used, just for
2236 usb_free_bus(usb_bus_t
*bus
)
2243 * frees all configs and then the device structure itself
2246 usb_free_dev(usb_device_t
*dev
)
2248 usb_dprintf(DEBUG_FUNCTIONS
, "usb_free_dev(): 0x%x\n", (int)dev
);
2250 usb_free_all_configs(dev
);
2256 * usb_get_device_status:
2257 * gets status of device
2259 * Returns: ugen dev status values
2262 usb_get_device_status(int fd
)
2266 usb_dprintf(DEBUG_FUNCTIONS
, "usb_get_device_status():\n");
2268 error
= (int)read(fd
, &status
, (size_t)sizeof (status
));
2269 if (error
!= (int)sizeof (status
)) {
2270 usb_error_str(errno
, "Could not read device status: %d",
2273 return (USB_DEV_STAT_UNAVAILABLE
);
2276 case USB_DEV_STAT_ONLINE
:
2277 usb_dprintf(DEBUG_DETAILED
, "Device is available\n");
2279 case USB_DEV_STAT_DISCONNECTED
:
2280 usb_dprintf(DEBUG_DETAILED
, "Device has been "
2283 case USB_DEV_STAT_RESUMED
:
2284 usb_dprintf(DEBUG_DETAILED
,
2285 "Device has been resumed\n");
2287 case USB_DEV_STAT_UNAVAILABLE
:
2288 usb_dprintf(DEBUG_DETAILED
,
2289 "Device is powered down\n");
2292 usb_dprintf(DEBUG_DETAILED
,
2293 "Device status=%d\n", status
);
2301 * usb_search_dev_usb:
2302 * finds all names of devices in the /usb/dev tree
2303 * this will be the VID/PID and instance no
2308 usb_search_dev_usb(usb_device_t
**new_devices
)
2311 struct dirent
*dir_entry
, *subdir_entry
;
2312 char *device
, *filename
;
2313 usb_bus_t
*bus
= usb_busses
;
2314 struct stat statbuf
;
2317 usb_dprintf(DEBUG_FUNCTIONS
, "usb_search_dev_usb():\n");
2319 if ((device
= malloc(PATH_MAX
+1)) == NULL
) {
2324 if ((filename
= malloc(PATH_MAX
+1)) == NULL
) {
2330 if (!(dir
= opendir(bus
->dirname
))) {
2334 usb_error_str(errno
,
2335 "couldn't opendir %s: %d", bus
->dirname
, errno
);
2340 /* make sure we only open ugen directories */
2341 if ((regcomp(®ex
, "/dev/usb/[0-9a-f]+[.][0-9a-f]+",
2342 REG_EXTENDED
) != 0)) {
2347 /* search for devices */
2348 while ((dir_entry
= readdir(dir
)) != NULL
) {
2350 usb_dprintf(DEBUG_FUNCTIONS
, "usb_search_dev_usb(): dir=%s\n",
2353 if (dir_entry
->d_name
[0] == '.') {
2356 (void) snprintf(device
, PATH_MAX
, "%s/%s", bus
->dirname
,
2360 * make sure we don't accidentily open /dev/usb/hid* nodes
2361 * which will get them unlinked from the virtual console
2363 if (lstat(device
, &statbuf
) == -1) {
2366 if (!S_ISDIR(statbuf
.st_mode
)) {
2370 if (regexec(®ex
, device
, 0, NULL
, 0) != 0) {
2374 usb_dprintf(DEBUG_FUNCTIONS
, "checking %s\n", device
);
2376 /* need to search instances */
2377 if (!(subdir
= opendir(device
))) {
2381 while ((subdir_entry
= readdir(subdir
)) != NULL
) {
2383 usb_device_specific_t
*dev_specific
;
2386 if (subdir_entry
->d_name
[0] == '.') {
2390 if ((dev
= calloc(sizeof (*dev
), 1)) == NULL
) {
2394 (void) closedir(subdir
);
2395 (void) closedir(dir
);
2399 if ((dev_specific
= calloc(sizeof (*dev_specific
),
2405 (void) closedir(subdir
);
2406 (void) closedir(dir
);
2411 dev
->dev
= (void *)dev_specific
;
2413 (void) snprintf(dev
->filename
, PATH_MAX
, "%s/%s",
2414 dir_entry
->d_name
, subdir_entry
->d_name
);
2416 /* See if the device is online */
2417 (void) snprintf(filename
, PATH_MAX
, "%s/%s/devstat",
2418 bus
->dirname
, dev
->filename
);
2420 usb_dprintf(DEBUG_DETAILED
, "filename %s\n", filename
);
2421 usb_dprintf(DEBUG_DETAILED
, "dev filename %s\n",
2424 if ((fd
= open(filename
, O_RDONLY
|O_EXCL
)) < 0) {
2425 usb_dprintf(DEBUG_ERRORS
,
2426 "usb_search_dev_usb: Couldn't open %s\n",
2432 if (usb_get_device_status(fd
) != USB_DEV_STAT_ONLINE
) {
2434 usb_error_str(EIO
, "Device %s is not online",
2443 usb_add_device(new_devices
, dev
);
2446 (void) closedir(subdir
);
2452 (void) closedir(dir
);
2459 * gets status of endpoint
2461 * Returns: ugen's last cmd status
2464 usb_get_status(int fd
)
2468 usb_dprintf(DEBUG_FUNCTIONS
, "usb_get_status(): fd=%d\n", fd
);
2470 error
= (int)read(fd
, &status
, sizeof (status
));
2471 if (error
== (int)sizeof (status
)) {
2473 case USB_LC_STAT_NOERROR
:
2474 usb_dprintf(DEBUG_DETAILED
, "No Error\n");
2476 case USB_LC_STAT_CRC
:
2477 usb_dprintf(DEBUG_ERRORS
, "CRC Timeout Detected\n");
2479 case USB_LC_STAT_BITSTUFFING
:
2480 usb_dprintf(DEBUG_ERRORS
, "Bit Stuffing Violation\n");
2482 case USB_LC_STAT_DATA_TOGGLE_MM
:
2483 usb_dprintf(DEBUG_ERRORS
, "Data Toggle Mismatch\n");
2485 case USB_LC_STAT_STALL
:
2486 usb_dprintf(DEBUG_ERRORS
, "End Point Stalled\n");
2488 case USB_LC_STAT_DEV_NOT_RESP
:
2489 usb_dprintf(DEBUG_ERRORS
, "Device is Not Responding\n");
2491 case USB_LC_STAT_PID_CHECKFAILURE
:
2492 usb_dprintf(DEBUG_ERRORS
, "PID Check Failure\n");
2494 case USB_LC_STAT_UNEXP_PID
:
2495 usb_dprintf(DEBUG_ERRORS
, "Unexpected PID\n");
2497 case USB_LC_STAT_DATA_OVERRUN
:
2498 usb_dprintf(DEBUG_ERRORS
, "Data Exceeded Size\n");
2500 case USB_LC_STAT_DATA_UNDERRUN
:
2501 usb_dprintf(DEBUG_ERRORS
, "Less data received\n");
2503 case USB_LC_STAT_BUFFER_OVERRUN
:
2504 usb_dprintf(DEBUG_ERRORS
, "Buffer Size Exceeded\n");
2506 case USB_LC_STAT_BUFFER_UNDERRUN
:
2507 usb_dprintf(DEBUG_ERRORS
, "Buffer Underrun\n");
2509 case USB_LC_STAT_TIMEOUT
:
2510 usb_dprintf(DEBUG_ERRORS
, "Command Timed Out\n");
2512 case USB_LC_STAT_NOT_ACCESSED
:
2513 usb_dprintf(DEBUG_ERRORS
, "Not Accessed by h/w\n");
2515 case USB_LC_STAT_UNSPECIFIED_ERR
:
2516 usb_dprintf(DEBUG_ERRORS
, "Unspecified Error\n");
2518 case USB_LC_STAT_NO_BANDWIDTH
:
2519 usb_dprintf(DEBUG_ERRORS
, "No Bandwidth\n");
2521 case USB_LC_STAT_HW_ERR
:
2522 usb_dprintf(DEBUG_ERRORS
,
2523 "Host Controller h/w Error\n");
2525 case USB_LC_STAT_SUSPENDED
:
2526 usb_dprintf(DEBUG_ERRORS
, "Device was Suspended\n");
2528 case USB_LC_STAT_DISCONNECTED
:
2529 usb_dprintf(DEBUG_ERRORS
, "Device was Disconnected\n");
2531 case USB_LC_STAT_INTR_BUF_FULL
:
2532 usb_dprintf(DEBUG_ERRORS
,
2533 "Interrupt buffer was full\n");
2535 case USB_LC_STAT_INVALID_REQ
:
2536 usb_dprintf(DEBUG_ERRORS
, "Request was Invalid\n");
2538 case USB_LC_STAT_INTERRUPTED
:
2539 usb_dprintf(DEBUG_ERRORS
, "Request was Interrupted\n");
2541 case USB_LC_STAT_NO_RESOURCES
:
2542 usb_dprintf(DEBUG_ERRORS
, "No resources available for "
2545 case USB_LC_STAT_INTR_POLLING_FAILED
:
2546 usb_dprintf(DEBUG_ERRORS
, "Failed to Restart Poll");
2549 usb_dprintf(DEBUG_ERRORS
, "Error Not Determined %d\n",
2559 * Descriptor parsing functions, taken from USBA code
2562 * take a raw buffer and pads it according to format
2564 * Returns: USB_PARSE_ERROR or length parsed
2567 usb_parse_data(char *format
, uchar_t
*data
, size_t datalen
,
2568 void *structure
, size_t structlen
)
2573 uchar_t
*dataend
= data
+ datalen
;
2574 char *structstart
= (char *)structure
;
2575 void *structend
= (void *)((intptr_t)structstart
+ structlen
);
2577 if ((format
== NULL
) || (data
== NULL
) || (structure
== NULL
)) {
2579 return (USB_PARSE_ERROR
);
2582 while ((fmt
= *format
) != '\0') {
2585 * Could some one pass a "format" that is greater than
2586 * the structlen? Conversely, one could pass a ret_buf_len
2587 * that is less than the "format" length.
2588 * If so, we need to protect against writing over memory.
2590 if (counter
++ > structlen
) {
2595 uint8_t *cp
= (uint8_t *)structure
;
2597 cp
= (uint8_t *)(((uintptr_t)cp
+ _CHAR_ALIGNMENT
- 1) &
2598 ~(_CHAR_ALIGNMENT
- 1));
2599 if (((data
+ 1) > dataend
) ||
2600 ((cp
+ 1) > (uint8_t *)structend
))
2604 structure
= (void *)cp
;
2608 if (multiplier
== 0) {
2611 } else if (fmt
== 's') {
2612 uint16_t *sp
= (uint16_t *)structure
;
2615 (((uintptr_t)sp
+ _SHORT_ALIGNMENT
- 1) &
2616 ~(_SHORT_ALIGNMENT
- 1));
2617 if (((data
+ 2) > dataend
) ||
2618 ((sp
+ 1) > (uint16_t *)structend
))
2621 *sp
++ = (data
[1] << 8) + data
[0];
2623 structure
= (void *)sp
;
2627 if (multiplier
== 0) {
2630 } else if (fmt
== 'l') {
2631 uint32_t *lp
= (uint32_t *)structure
;
2634 (((uintptr_t)lp
+ _INT_ALIGNMENT
- 1) &
2635 ~(_INT_ALIGNMENT
- 1));
2636 if (((data
+ 4) > dataend
) ||
2637 ((lp
+ 1) > (uint32_t *)structend
))
2641 (uint32_t)data
[3] << 8) | data
[2]) << 8) |
2642 data
[1]) << 8) | data
[0];
2644 structure
= (void *)lp
;
2648 if (multiplier
== 0) {
2651 } else if (fmt
== 'L') {
2652 uint64_t *llp
= (uint64_t *)structure
;
2655 (((uintptr_t)llp
+ _LONG_LONG_ALIGNMENT
- 1) &
2656 ~(_LONG_LONG_ALIGNMENT
- 1));
2657 if (((data
+ 8) > dataend
) ||
2658 ((llp
+ 1) >= (uint64_t *)structend
))
2661 *llp
++ = (((((((((((((data
[7] << 8) |
2662 data
[6]) << 8) | data
[5]) << 8) |
2663 data
[4]) << 8) | data
[3]) << 8) |
2664 data
[2]) << 8) | data
[1]) << 8) |
2667 structure
= (void *)llp
;
2671 if (multiplier
== 0) {
2674 } else if (isdigit(fmt
)) {
2675 multiplier
= (multiplier
* 10) + (fmt
- '0');
2684 return ((intptr_t)structure
- (intptr_t)structstart
);
2689 * finds pointer to n-th descriptor of
2690 * type descr_type, unless the end of the buffer or a descriptor
2691 * of type stop_descr_type1 or stop_descr_type2 is encountered first.
2693 * Returns: returns pointer to n-th descriptor
2696 usb_nth_descr(uchar_t
*buf
, size_t buflen
, int descr_type
, uint_t n
,
2697 int stop_descr_type1
, int stop_descr_type2
)
2699 uchar_t
*bufstart
= buf
;
2700 uchar_t
*bufend
= buf
+ buflen
;
2707 while (buf
+ 2 <= bufend
) {
2708 if ((buf
!= bufstart
) && ((buf
[1] == stop_descr_type1
) ||
2709 (buf
[1] == stop_descr_type2
))) {
2714 if ((descr_type
== USB_DESCR_TYPE_ANY
) ||
2715 (buf
[1] == descr_type
)) {
2723 * Check for a bad buffer.
2724 * If buf[0] is 0, then this will be an infite loop
2733 * usb_parse_dev_descr:
2734 * parse device descriptor
2736 * Returns: #bytes parsed
2739 usb_parse_dev_descr(uchar_t
*buf
, size_t buflen
,
2740 struct usb_device_descriptor
*ret_descr
, size_t ret_buf_len
)
2742 if ((buf
== NULL
) || (ret_descr
== NULL
) ||
2743 (buflen
< 2) || (buf
[1] != USB_DESCR_TYPE_DEV
)) {
2745 return (USB_PARSE_ERROR
);
2748 return (usb_parse_data("ccsccccssscccc",
2749 buf
, buflen
, ret_descr
, ret_buf_len
));
2753 * usb_parse_cfg_descr:
2754 * parse config descriptor
2756 * Returns: #bytes parsed
2759 usb_parse_cfg_descr(uchar_t
*buf
, size_t buflen
, usb_cfg_descr_t
*ret_descr
,
2760 size_t ret_buf_len
, unsigned char **extra
, int *extralen
)
2764 if ((buf
== NULL
) || (ret_descr
== NULL
) ||
2765 (buflen
< 2) || (buf
[1] != USB_DESCR_TYPE_CFG
)) {
2767 return (USB_PARSE_ERROR
);
2770 rval
= usb_parse_data("ccsccccc",
2771 buf
, buflen
, ret_descr
, ret_buf_len
);
2773 usb_find_extra(buf
, buflen
, extra
, extralen
);
2779 * usb_parse_if_descr:
2780 * parse interface descriptor
2782 * Returns: #bytes parsed
2785 usb_parse_if_descr(uchar_t
*buf
, size_t buflen
, uint_t if_number
,
2786 uint_t alt_if_setting
, usb_if_descr_t
*ret_descr
, size_t ret_buf_len
,
2787 unsigned char **extra
, int *extralen
)
2789 uchar_t
*bufend
= buf
+ buflen
;
2792 if ((buf
== NULL
) || (ret_descr
== NULL
)) {
2794 return (USB_PARSE_ERROR
);
2797 while (buf
+ 4 <= bufend
) {
2798 if ((buf
[1] == USB_DESCR_TYPE_IF
) &&
2799 (buf
[2] == if_number
) &&
2800 (buf
[3] == alt_if_setting
)) {
2802 rval
= usb_parse_data("ccccccccc",
2803 buf
, ((uintptr_t)bufend
- (uintptr_t)buf
),
2804 ret_descr
, ret_buf_len
);
2807 ((uintptr_t)bufend
- (uintptr_t)buf
),
2814 * Check for a bad buffer.
2815 * If buf[0] is 0, then this will be an infinite loop
2820 return (USB_PARSE_ERROR
);
2825 * usb_parse_ep_descr:
2826 * parse config descriptor
2827 * the endpoint index is relative to the interface. index 0 is
2828 * the first endpoint
2830 * Returns: #bytes parsed
2833 usb_parse_ep_descr(uchar_t
*buf
, size_t buflen
, uint_t if_number
,
2834 uint_t alt_if_setting
, uint_t ep_index
, usb_ep_descr_t
*ret_descr
,
2835 size_t ret_buf_len
, unsigned char **extra
, int *extralen
)
2837 uchar_t
*bufend
= buf
+ buflen
;
2840 if ((buf
== NULL
) || (ret_descr
== NULL
)) {
2842 return (USB_PARSE_ERROR
);
2845 while ((buf
+ 4) <= bufend
) {
2846 if (buf
[1] == USB_DESCR_TYPE_IF
&&
2847 buf
[2] == if_number
&&
2848 buf
[3] == alt_if_setting
) {
2849 if ((buf
= usb_nth_descr(buf
,
2850 (uintptr_t)bufend
- (uintptr_t)buf
,
2851 USB_DESCR_TYPE_EP
, ep_index
,
2852 USB_DESCR_TYPE_IF
, -1)) == NULL
) {
2857 rval
= usb_parse_data("ccccsccc", buf
,
2858 (uintptr_t)bufend
- (uintptr_t)buf
,
2859 ret_descr
, ret_buf_len
);
2860 usb_find_extra(buf
, (uintptr_t)bufend
- (uintptr_t)buf
,
2867 * Check for a bad buffer.
2868 * If buf[0] is 0, then this will be an infinite loop
2873 return (USB_PARSE_ERROR
);
2877 * extra descriptor handling
2880 * finds any non-standard descriptor after the current
2881 * standard descriptor and puts a pointer in extra argument
2882 * and the length in extralen
2885 usb_find_extra(uchar_t
*buf
, size_t buflen
,
2886 unsigned char **extra
, int *extralen
)
2888 uchar_t
*next
= buf
+ buf
[0];
2893 while (((uintptr_t)next
- (uintptr_t)buf
+ 1) < buflen
) {
2894 if ((next
[1] == USB_DT_CONFIG
) ||
2895 (next
[1] == USB_DT_INTERFACE
) ||
2896 (next
[1] == USB_DT_ENDPOINT
)) {
2897 *extralen
= (int)((uintptr_t)next
-
2898 (uintptr_t)buf
- buf
[0]);
2910 * lookup error string
2912 * Returns: error string
2917 usb_dprintf(DEBUG_FUNCTIONS
, "usb_strerror(): "
2918 "usb_error_type=%d, errno=%d\n", usb_error_type
, usb_error_errno
);
2920 switch (usb_error_type
) {
2921 case USB_ERROR_TYPE_NONE
:
2922 return ("No error");
2924 case USB_ERROR_TYPE_STRING
:
2925 return (usb_error_string
);
2927 case USB_ERROR_TYPE_ERRNO
:
2928 if (usb_error_errno
> 0) {
2930 return (strerror(usb_error_errno
));
2936 return ("Unknown error");
2941 * stores the error number in the global usb_error_errno
2943 * Returns: negative error number
2948 usb_dprintf(DEBUG_FUNCTIONS
, "usb_error(): error=%d\n", x
);
2950 usb_error_type
= USB_ERROR_TYPE_ERRNO
;
2951 usb_error_errno
= x
;
2958 * creates error string
2961 usb_error_str(int x
, char *format
, ...)
2965 va_start(ap
, format
);
2967 usb_error_type
= USB_ERROR_TYPE_ERRNO
;
2968 usb_error_errno
= x
;
2970 (void) vsnprintf(usb_error_string
, sizeof (usb_error_string
),
2973 usb_dprintf(DEBUG_ERRORS
, "USB error (%d): %s\n", x
, usb_error_string
);
2980 * prints out tracing messages according to level
2983 usb_dprintf(int level
, char *format
, ...)
2988 va_start(ap
, format
);
2990 (void) vsnprintf(buf
, sizeof (buf
), format
, ap
);
2991 if (libusb_debug
>= level
) {
2992 (void) fprintf(stderr
, buf
);
3002 usb_dump_data(char *data
, int size
)
3006 if (libusb_debug
>= DEBUG_DATA_DUMP
) {
3007 (void) fprintf(stderr
, "data dump:");
3008 for (i
= 0; i
< size
; i
++) {
3010 (void) fprintf(stderr
, "\n%08x ", i
);
3012 (void) fprintf(stderr
, "%02x ", (uchar_t
)data
[i
]);
3014 (void) fprintf(stderr
, "\n");