x11/components/mesa: fix erroneous dri-drivers-path
[oi-userland.git] / components / library / libusb / ugen / src / libusbugen.c
blobf07afb0c215c756a375af1ffd25ec397073c7ca4
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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.
31 * XXX issues:
32 * - timeout thru signal
33 * - usb_interrupt/bulk_write/read should have common code
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <errno.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <fcntl.h>
42 #include <sys/time.h>
43 #include <dirent.h>
44 #include <stdarg.h>
45 #include <strings.h>
46 #include <sys/stat.h>
47 #include <regex.h>
49 #include <sys/usb/clients/ugen/usb_ugen.h>
50 #include "usb.h"
51 #include "libusbugen_impl.h"
53 /* global variables */
54 usb_bus_t *usb_busses = NULL;
55 const char *libusb_version = "1.1";
57 /* error handling */
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;
62 /* debugging */
63 static int libusb_debug = DEBUG_NONE;
65 /* api binding */
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,
94 uint_t iface);
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);
128 * libusb_init:
130 * Returns: 0 or ENOSUP if we cannot support any bus
133 libusb_init(void)
135 return (0);
139 * libusb_fini:
141 * Returns: always returns 0
144 libusb_fini(void)
146 return (0);
150 * Entry points:
152 * usb_set_debug:
153 * sets debug level for tracing
155 void
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"));
167 if (level < 0)
168 return;
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");
178 * usb_init:
179 * not much to initialize. just set debug level
181 void
182 usb_init(void)
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);
195 * usb_get_busses:
196 * Returns: usb_busses pointer
198 usb_bus_t *
199 usb_get_busses(void)
201 return (usb_busses);
205 * usb_find_busses:
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)
214 usb_bus_t *bus;
216 /* we only have one name space for all USB busses */
217 if (usb_busses == NULL) {
218 /* never freed */
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);
230 usb_busses = bus;
232 return (1);
235 return (0);
239 * usb_find_devices:
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)
248 int i, rval, found;
249 int changes = 0;
250 usb_device_t *new_devices;
251 usb_device_t *dev, *next_dev, *new, *next_new;
253 new_devices = NULL;
255 rval = usb_search_dev_usb(&new_devices);
256 if (rval != 0) {
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;
264 found = 0;
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);
270 usb_free_dev(new);
271 found++;
272 break;
276 /* the device must have been hot removed */
277 if (!found) {
278 usb_remove_device(&usb_busses->devices, dev);
279 usb_free_dev(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));
291 changes++;
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);
301 return (changes);
305 * usb_device:
306 * included because sane uses this
307 * Returns: usb_device structure associated with handle
309 struct usb_device *
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);
318 * usb_open:
319 * opens the device for access
321 * Returns: a usb device handle or NULL
323 usb_dev_handle *
324 usb_open(usb_device_t *dev)
326 usb_dev_handle_impl_t *hdl;
327 usb_dev_handle_info_t *info;
328 int i, rval;
330 usb_dprintf(DEBUG_FUNCTIONS, "usb_open():\n");
332 if (usb_check_device_in_list(usb_busses->devices,
333 dev) == 0) {
334 usb_dprintf(DEBUG_ERRORS, "usb_open(): "
335 "illegal usb_device pointer\n");
337 return (NULL);
340 /* create a handle and info structure */
341 if ((hdl = calloc(sizeof (*hdl), 1)) == NULL) {
343 return (NULL);
345 hdl->device = dev;
346 if ((info = calloc(sizeof (*info), 1)) == NULL) {
347 free(hdl);
349 return (NULL);
352 hdl->info = info;
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;
358 if (i > 0) {
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);
366 free(info);
367 free(hdl);
369 return (NULL);
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);
378 usb_close_ep0(hdl);
379 free(info);
380 free(hdl);
382 return (NULL);
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);
395 * usb_close:
396 * closes the device and free resources
398 * Returns: 0
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);
408 if (hdl) {
409 info = hdl->info;
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);
420 usb_close_ep0(hdl);
422 free(info);
423 free(hdl);
425 return (0);
428 return (usb_error(EINVAL));
432 * usb_control_msg:
433 * sends a control message
435 * Returns: actual number of data bytes transferred or
436 * a negative errno
438 /*ARGSUSED*/
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;
445 int additional;
446 int rval;
448 usb_dprintf(DEBUG_FUNCTIONS, "usb_control_msg():\n");
450 if ((hdl == NULL) || (size < 0)) {
452 return (usb_error(EINVAL));
454 info = hdl->info;
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? */
466 if (rval < 8) {
467 usb_error_str(errno,
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);
480 } else {
481 additional = rval;
484 usb_dprintf(DEBUG_FUNCTIONS,
485 "usb_control_msg(): additional 0x%x bytes\n", additional);
487 return (additional);
491 * usb_bulk_write:
492 * writes to a bulk endpoint
494 * Returns: actual number of data bytes transferred or negative errno
496 /* ARGSUSED */
498 usb_bulk_write(usb_dev_handle *dev, int ep, char *data, int size,
499 int timeout)
501 usb_dev_handle_impl_t *hdl = (usb_dev_handle_impl_t *)dev;
502 usb_dev_handle_info_t *info;
503 int sent, rval;
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));
514 info = hdl->info;
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],
527 data, size, WRITE);
529 return (sent);
533 * usb_bulk_read:
534 * reads from a bulk endpoint
536 * Returns: actual number of data bytes transferred or negative errno
538 /* ARGSUSED */
540 usb_bulk_read(usb_dev_handle *dev, int ep, char *data, int size,
541 int timeout)
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));
558 info = hdl->info;
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],
572 data, size, READ);
574 return (received);
578 * usb_interrupt_write:
579 * writes data to an interrupt endpoint
581 * Returns: actual number of data bytes transferred or negative errno
583 /* ARGSUSED */
585 usb_interrupt_write(usb_dev_handle *dev, int ep, char *data, int size,
586 int timeout)
588 usb_dev_handle_impl_t *hdl = (usb_dev_handle_impl_t *)dev;
589 usb_dev_handle_info_t *info;
590 int sent, rval;
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));
601 info = hdl->info;
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],
615 data, size, WRITE);
617 return (sent);
621 * usb_interrupt_read:
622 * reads data from an interrupt endpoint
624 * Returns: actual number of data bytes transferred or negative errno
626 /* ARGSUSED */
628 usb_interrupt_read(usb_dev_handle *dev, int ep, char *data, int size,
629 int timeout)
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));
646 info = hdl->info;
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],
660 data, size, READ);
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;
668 return (received);
672 * usb_get_string:
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,
679 size_t buflen)
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,
710 size_t buflen)
712 char tbuf[256];
713 int ret, langid, si, di;
715 usb_dprintf(DEBUG_FUNCTIONS, "usb_get_string_simple(): index=%d\n",
716 index);
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);
738 if (ret < 4) {
739 langid = 0x409;
740 } else {
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));
747 if (ret < 0) {
749 return (ret);
751 if (tbuf[1] != USB_DT_STRING) {
753 return (-EIO);
755 if (tbuf[0] > ret) {
757 return (-EFBIG);
760 for (di = 0, si = 2; si < tbuf[0]; si += 2) {
761 if (di >= ((int)buflen - 1)) {
762 break;
765 if (tbuf[si + 1]) { /* high byte */
766 buf[di++] = '?';
767 } else {
768 buf[di++] = tbuf[si];
772 buf[di] = 0;
774 return (di);
778 * usb_get_descriptor_by_endpoint:
779 * usb_get_descriptor:
780 * get a descriptor. by_endpoint does not appear to make
781 * much sense.
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
830 /* ARGSUSED */
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);
842 if (hdl == NULL) {
843 usb_dprintf(DEBUG_ERRORS,
844 "usb_set_altinterface(): NULL handle\n");
846 return (usb_error(EINVAL));
849 info = hdl->info;
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))) {
861 return (err);
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;
884 index++) {
885 if (info->configuration_value ==
886 hdl->device->config[index].bConfigurationValue) {
887 break;
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);
906 return (0);
910 * usb_set_configuration:
911 * sets the configuration for the device.
912 * ugen implicitly switches configuration and rejects
913 * set configuration requests
915 * Returns: 0
917 /* ARGSUSED */
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;
923 int index, i;
925 usb_dprintf(DEBUG_FUNCTIONS,
926 "usb_set_configuration(): config = %d\n", configuration);
928 if (hdl == NULL) {
929 usb_dprintf(DEBUG_ERRORS,
930 "usb_set_configuration(): NULL handle\n");
932 return (usb_error(EINVAL));
934 info = hdl->info;
936 /* find the conf index */
937 for (index = 0; index < hdl->device->descriptor.bNumConfigurations;
938 index++) {
939 if (configuration ==
940 hdl->device->config[index].bConfigurationValue) {
941 break;
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);
964 return (0);
968 * usb_clear_halt:
969 * clears a halted endpoint
970 * ugen has auto clearing but we send the request anyways
972 * Returns: 0 or negative errno
974 /* ARGSUSED */
976 usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
978 int rval;
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);
985 if (dev == NULL) {
986 usb_dprintf(DEBUG_ERRORS,
987 "usb_clear_halt(): NULL handle\n");
989 return (usb_error(EINVAL));
991 info = hdl->info;
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);
1012 if (rval < 0) {
1013 usb_error_str(errno, "could not clear feature on ep=0x%x", ep);
1016 return (rval);
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;
1033 int index;
1035 if (hdl == NULL) {
1036 usb_dprintf(DEBUG_ERRORS,
1037 "usb_claim_interface(): NULL handle\n");
1039 return (usb_error(EINVAL));
1041 info = hdl->info;
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) {
1048 index = 0;
1049 } else {
1050 /* find the conf index */
1051 for (index = 0;
1052 index < hdl->device->descriptor.bNumConfigurations;
1053 index++) {
1054 if (info->configuration_value ==
1055 hdl->device->config[index].bConfigurationValue) {
1056 break;
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) {
1077 return (0);
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);
1102 return (0);
1106 * usb_release_interface:
1107 * releases the acquired interface
1109 * Returns: 0 or negative errno
1111 /* ARGSUSED */
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;
1119 if (hdl == NULL) {
1120 usb_dprintf(DEBUG_ERRORS,
1121 "usb_release_interface(): NULL handle\n");
1123 return (usb_error(EINVAL));
1126 info = hdl->info;
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;
1146 return (0);
1150 * usb_resetep
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));
1164 * usb_reset:
1165 * resets the device
1166 * Returns: -ENOTSUP
1168 /* ARGSUSED */
1170 usb_reset(usb_dev_handle * dev)
1172 int rval;
1174 usb_dprintf(DEBUG_FUNCTIONS, "usb_reset():\n");
1176 if (dev == NULL) {
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));
1192 * Helper functions
1194 * usb_send_msg:
1195 * creates setup data and send it
1197 * Returns: number of bytes transferred or negative errno
1199 static int
1200 usb_send_msg(int fd, int stat_fd, int requesttype, int request, int value,
1201 int index, char *data, int size)
1203 uint8_t req[8];
1204 int rval;
1206 usb_dprintf(DEBUG_DETAILED, "usb_send_msg():\n"
1207 "\trequesttype 0x%x\n"
1208 "\trequest 0x%x\n"
1209 "\tvalue 0x%x\n"
1210 "\tindex 0x%x\n"
1211 "\tsize 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);
1226 } else {
1227 /* append the write data */
1228 char *buffer;
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);
1239 free(buffer);
1241 usb_dprintf(DEBUG_FUNCTIONS, "usb_send_msg(): rval=%d\n", rval);
1243 return (rval);
1247 * usb_do_io:
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
1253 static int
1254 usb_do_io(int fd, int stat_fd, char *data, size_t size, int flag)
1256 int error;
1257 ssize_t ret;
1259 usb_dprintf(DEBUG_FUNCTIONS, "usb_do_io(): size=0x%x flag=%d\n",
1260 size, flag);
1262 if (size == 0) {
1264 return (0);
1267 switch (flag) {
1268 case READ:
1269 ret = read(fd, data, size);
1270 usb_dump_data(data, (int)size);
1271 break;
1272 case WRITE:
1273 usb_dump_data(data, (int)size);
1274 ret = write(fd, data, size);
1275 break;
1277 if (ret < 0) {
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",
1283 error, save_errno);
1285 return (-save_errno);
1288 usb_dprintf(DEBUG_FUNCTIONS, "usb_do_io(): amount=%d\n", ret);
1290 return ((int)ret);
1294 * usb_check_access:
1295 * basically checks if the interface has been claimed
1297 * Returns: 0 or EACCES/EINVAL
1299 static int
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;
1305 if (hdl == NULL) {
1307 return (EINVAL);
1309 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)) {
1320 return (EACCES);
1323 return (0);
1327 * usb_set_ep_iface_alts:
1328 * initialize ep_interface arrays
1330 static void
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;
1336 int i;
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.
1374 * Returns: errno
1376 static int
1377 usb_check_device_and_status_open(usb_dev_handle *dev, int ep, int ep_type,
1378 int mode)
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) {
1393 return (rval);
1396 if ((index < 0) || (index > 31)) {
1398 return (EINVAL);
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]) {
1406 return (EINVAL);
1409 if ((info->ep_fd[index] > 0) && (info->ep_status_fd[index] > 0)) {
1411 return (0);
1414 if (ep == 0) {
1415 /* should already be open */
1417 return (0);
1420 if ((filename = malloc(PATH_MAX+1)) == NULL) {
1422 return (ENOMEM);
1424 if ((statfilename = malloc(PATH_MAX+1)) == NULL) {
1425 free(filename);
1427 return (ENOMEM);
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);
1437 } else {
1438 (void) memset(cfg_num, 0, sizeof (cfg_num));
1441 if (info->alternate > 0) {
1442 (void) snprintf(alt_num, sizeof (alt_num), ".%d",
1443 info->alternate);
1444 } else {
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;
1466 ssize_t count;
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,
1475 O_RDONLY)) == -1) {
1476 usb_error_str(errno,
1477 "can't open %s RDONLY: %d",
1478 filename, errno);
1479 free(filename);
1480 free(statfilename);
1482 return (errno);
1484 } else {
1485 count = write(fdstat, &control, sizeof (control));
1487 if (count != 1) {
1488 /* this should have worked */
1489 usb_error_str(errno, "can't write to %s: %d",
1490 filename, errno);
1491 free(filename);
1492 free(statfilename);
1493 (void) close(fdstat);
1495 return (errno);
1498 } else {
1499 if ((fdstat = open(statfilename, O_RDONLY)) == -1) {
1500 usb_error_str(errno, "can't open %s: %d",
1501 statfilename, errno);
1502 free(filename);
1503 free(statfilename);
1505 return (errno);
1509 /* open the ep */
1510 if ((fd = open(filename, mode)) == -1) {
1511 usb_error_str(errno, "can't open %s: %d",
1512 filename, errno);
1513 (void) close(fdstat);
1514 free(filename);
1515 free(statfilename);
1517 return (errno);
1520 free(filename);
1521 free(statfilename);
1522 info->ep_fd[index] = fd;
1523 info->ep_status_fd[index] = fdstat;
1526 return (0);
1530 * usb_ep_index:
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)
1536 static uchar_t
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));
1544 * usb_open_ep0:
1545 * opens default pipe
1547 * Returns: errno
1549 static int
1550 usb_open_ep0(usb_dev_handle_impl_t *hdl)
1552 char *filename;
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);
1567 return (0);
1570 if ((filename = malloc(PATH_MAX+1)) == NULL) {
1572 return (ENOMEM);
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]);
1584 free(filename);
1586 return (errno);
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) {
1596 free(filename);
1598 return (errno);
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");
1608 free(filename);
1610 return (0);
1614 * usb_close_ep0:
1615 * closes default ep0
1617 static void
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);
1631 return;
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
1651 static void
1652 usb_close_all_eps(usb_dev_handle_impl_t *hdl)
1654 int i;
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
1674 * Returns: errno
1676 static int
1677 usb_setup_all_configs(usb_dev_handle_impl_t *hdl)
1679 char buffer[USB_DEV_DESCR_SIZE];
1680 int rval, len;
1681 uint_t index;
1683 if (hdl->device->config) {
1685 return (0);
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) {
1700 return (EIO);
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)) {
1712 return (EIO);
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) {
1721 return (ENOMEM);
1724 /* parse each config cloud */
1725 for (index = 0; index < hdl->device->descriptor.bNumConfigurations;
1726 index++) {
1727 if ((rval = usb_parse_config(hdl, index)) != 0) {
1729 return (rval);
1733 return (0);
1737 * usb_free_all_configs:
1738 * frees all allocated resources
1740 static void
1741 usb_free_all_configs(usb_device_t *dev)
1743 uint_t index;
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);
1749 if (dev->config) {
1750 for (index = 0; index < dev->descriptor.bNumConfigurations;
1751 index++) {
1752 usb_free_config(dev, index);
1754 free(dev->config);
1755 dev->config = NULL;
1760 * usb_parse_config:
1761 * parse config descriptor and get cloud
1763 * Returns: errno
1765 static int
1766 usb_parse_config(usb_dev_handle_impl_t *hdl, uint_t index)
1768 int rval;
1769 uint_t iface, len;
1770 char buffer[USB_CFG_DESCR_SIZE];
1771 char *cloud;
1772 unsigned char *extra;
1773 int extralen;
1775 usb_dprintf(DEBUG_FUNCTIONS, "usb_parse_config(): index=%d\n",
1776 index);
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) {
1788 return (EIO);
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) {
1800 return (EIO);
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)) ==
1812 NULL) {
1814 return (ENOMEM);
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,
1821 0, (char *)cloud,
1822 hdl->device->config[index].wTotalLength, 0);
1824 if (rval != hdl->device->config[index].wTotalLength) {
1825 free(cloud);
1827 return (EIO);
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);
1836 if (extralen) {
1837 usb_dprintf(DEBUG_DETAILED,
1838 "cfg%d: extra descriptors length=%d:\n",
1839 index, extralen);
1840 usb_dump_data((char *)extra, extralen);
1842 if ((hdl->device->config[index].extra =
1843 calloc(extralen, 1)) == NULL) {
1844 free(cloud);
1846 return (ENOMEM);
1849 (void) memcpy(hdl->device->config[index].extra, extra,
1850 extralen);
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)) ==
1858 NULL) {
1859 free(cloud);
1861 return (ENOMEM);
1864 for (iface = 0; iface < hdl->device->config[index].bNumInterfaces;
1865 iface++) {
1866 rval = usb_parse_interface(hdl, index, iface, cloud);
1867 if (rval != 0) {
1868 free(cloud);
1870 return (rval);
1873 free(cloud);
1875 return (0);
1879 * usb_free_config:
1880 * frees all allocated config resources
1882 static void
1883 usb_free_config(usb_device_t *device, uint_t index)
1885 uint_t iface;
1887 usb_dprintf(DEBUG_FUNCTIONS, "usb_free_config(): index=%d\n",
1888 index);
1890 if (device->config[index].interface) {
1891 for (iface = 0; iface < device->config[index].bNumInterfaces;
1892 iface++) {
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
1906 * Returns: errno
1908 static int
1909 usb_parse_interface(usb_dev_handle_impl_t *hdl, uint_t index, uint_t iface,
1910 char *cloud)
1912 usb_if_descr_t if_descr;
1913 int rval;
1914 uint_t alt, max_alt, len;
1915 unsigned char *extra;
1916 int extralen;
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),
1926 &extra, &extralen);
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)) {
1934 break;
1936 max_alt = alt;
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) {
1947 return (ENOMEM);
1949 hdl->device->config[index].interface[iface].num_altsetting =
1950 max_alt;
1951 for (alt = 0; alt < max_alt; alt++) {
1952 rval = usb_parse_alternate(hdl, index, iface, alt, cloud);
1953 if (rval != 0) {
1955 return (rval);
1959 return (0);
1963 * usb_free_interface:
1964 * frees interface resources
1966 * Returns: errno
1968 static void
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].
1978 num_altsetting;
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
1990 * Returns: errno
1992 static int
1993 usb_parse_alternate(usb_dev_handle_impl_t *hdl, uint_t index, uint_t iface,
1994 uint_t alt, char *cloud)
1996 uint_t ep, len;
1997 usb_if_descr_t if_descr;
1998 int rval;
1999 unsigned char *extra;
2000 int extralen;
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",
2011 rval);
2013 return (EIO);
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,
2019 if_descr.bLength,
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);
2029 (void) memcpy(
2030 &hdl->device->config[index].interface[iface].altsetting[alt],
2031 &if_descr, sizeof (if_descr));
2033 if (extralen) {
2034 usb_dprintf(DEBUG_DETAILED,
2035 "cfg%d.if%d.%d: extralen=%d:\n", index, iface, alt,
2036 extralen);
2037 usb_dump_data((char *)extra, extralen);
2039 if ((hdl->device->config[index].interface[iface].
2040 altsetting[alt].extra = calloc(extralen, 1)) == NULL) {
2042 return (ENOMEM);
2044 (void) memcpy(
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) {
2053 return (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) {
2062 return (ENOMEM);
2065 for (ep = 0; ep < if_descr.bNumEndpoints; ep++) {
2066 rval = usb_parse_endpoint(hdl, index, iface, alt, ep, cloud);
2068 if (rval != 0) {
2070 return (rval);
2074 return (0);
2078 * usb_free_alternate:
2079 * frees all alternate resources
2081 static void
2082 usb_free_alternate(usb_device_t *device, uint_t index, uint_t iface,
2083 uint_t alt)
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].
2089 endpoint) {
2090 uint_t ep;
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].
2102 extralen) {
2103 free(device->config[index].interface[iface].
2104 altsetting[alt].extra);
2106 free(device->config[index].interface[iface].altsetting[alt].
2107 endpoint);
2112 * usb_parse_endpoint:
2113 * parses an endpoint descriptor
2115 * Returns: errno
2117 static int
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;
2122 int rval;
2123 unsigned char *extra;
2124 int extralen;
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),
2133 &extra, &extralen);
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);
2139 return (rval);
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));
2152 if (extralen) {
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) {
2162 return (ENOMEM);
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;
2170 return (0);
2174 * usb_add_device:
2175 * adds dev to the beginning of the list
2177 static void
2178 usb_add_device(usb_device_t **list, usb_device_t *dev)
2180 if (*list) {
2181 dev->next = *list;
2182 dev->next->prev = dev;
2183 } else {
2184 dev->next = NULL;
2186 dev->prev = NULL;
2187 *list = dev;
2191 * usb_remove_device:
2192 * removes dev from a list
2194 static void
2195 usb_remove_device(usb_device_t **list, usb_device_t *dev)
2197 if (dev->prev) {
2198 dev->prev->next = dev->next;
2199 } else {
2200 *list = dev->next;
2202 if (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)
2214 static int
2215 usb_check_device_in_list(usb_device_t *list, usb_device_t *dev)
2217 usb_device_t *d = list;
2219 while (d != NULL) {
2220 if (d == dev) {
2222 return (1);
2224 d = d->next;
2227 return (0);
2231 * usb_free_bus:
2232 * frees the entire bus structure, not used, just for
2233 * completeness
2235 static void
2236 usb_free_bus(usb_bus_t *bus)
2238 free(bus);
2242 * usb_free_dev:
2243 * frees all configs and then the device structure itself
2245 static void
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);
2251 free(dev->dev);
2252 free(dev);
2256 * usb_get_device_status:
2257 * gets status of device
2259 * Returns: ugen dev status values
2261 static int
2262 usb_get_device_status(int fd)
2264 int status, error;
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",
2271 error);
2273 return (USB_DEV_STAT_UNAVAILABLE);
2274 } else {
2275 switch (status) {
2276 case USB_DEV_STAT_ONLINE:
2277 usb_dprintf(DEBUG_DETAILED, "Device is available\n");
2278 break;
2279 case USB_DEV_STAT_DISCONNECTED:
2280 usb_dprintf(DEBUG_DETAILED, "Device has been "
2281 "disconnected\n");
2282 break;
2283 case USB_DEV_STAT_RESUMED:
2284 usb_dprintf(DEBUG_DETAILED,
2285 "Device has been resumed\n");
2286 break;
2287 case USB_DEV_STAT_UNAVAILABLE:
2288 usb_dprintf(DEBUG_DETAILED,
2289 "Device is powered down\n");
2290 break;
2291 default:
2292 usb_dprintf(DEBUG_DETAILED,
2293 "Device status=%d\n", status);
2297 return (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
2305 * Returns: errno
2307 static int
2308 usb_search_dev_usb(usb_device_t **new_devices)
2310 DIR *dir, *subdir;
2311 struct dirent *dir_entry, *subdir_entry;
2312 char *device, *filename;
2313 usb_bus_t *bus = usb_busses;
2314 struct stat statbuf;
2315 regex_t regex;
2317 usb_dprintf(DEBUG_FUNCTIONS, "usb_search_dev_usb():\n");
2319 if ((device = malloc(PATH_MAX+1)) == NULL) {
2321 return (ENOMEM);
2324 if ((filename = malloc(PATH_MAX+1)) == NULL) {
2325 free(device);
2327 return (ENOMEM);
2330 if (!(dir = opendir(bus->dirname))) {
2331 free(device);
2332 free(filename);
2334 usb_error_str(errno,
2335 "couldn't opendir %s: %d", bus->dirname, errno);
2337 return (errno);
2340 /* make sure we only open ugen directories */
2341 if ((regcomp(&regex, "/dev/usb/[0-9a-f]+[.][0-9a-f]+",
2342 REG_EXTENDED) != 0)) {
2344 return (EINVAL);
2347 /* search for devices */
2348 while ((dir_entry = readdir(dir)) != NULL) {
2350 usb_dprintf(DEBUG_FUNCTIONS, "usb_search_dev_usb(): dir=%s\n",
2351 dir_entry->d_name);
2353 if (dir_entry->d_name[0] == '.') {
2354 continue;
2356 (void) snprintf(device, PATH_MAX, "%s/%s", bus->dirname,
2357 dir_entry->d_name);
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) {
2364 continue;
2366 if (!S_ISDIR(statbuf.st_mode)) {
2367 continue;
2370 if (regexec(&regex, device, 0, NULL, 0) != 0) {
2371 continue;
2374 usb_dprintf(DEBUG_FUNCTIONS, "checking %s\n", device);
2376 /* need to search instances */
2377 if (!(subdir = opendir(device))) {
2378 continue;
2381 while ((subdir_entry = readdir(subdir)) != NULL) {
2382 usb_device_t *dev;
2383 usb_device_specific_t *dev_specific;
2384 int fd;
2386 if (subdir_entry->d_name[0] == '.') {
2387 continue;
2390 if ((dev = calloc(sizeof (*dev), 1)) == NULL) {
2391 free(device);
2392 free(filename);
2393 regfree(&regex);
2394 (void) closedir(subdir);
2395 (void) closedir(dir);
2397 return (ENOMEM);
2399 if ((dev_specific = calloc(sizeof (*dev_specific),
2400 1)) == NULL) {
2401 free(device);
2402 free(filename);
2403 free(dev);
2404 regfree(&regex);
2405 (void) closedir(subdir);
2406 (void) closedir(dir);
2408 return (ENOMEM);
2411 dev->dev = (void *)dev_specific;
2412 dev->bus = bus;
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",
2422 dev->filename);
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",
2427 filename);
2428 free(dev_specific);
2429 free(dev);
2430 continue;
2432 if (usb_get_device_status(fd) != USB_DEV_STAT_ONLINE) {
2433 (void) close(fd);
2434 usb_error_str(EIO, "Device %s is not online",
2435 dev->filename);
2437 free(dev_specific);
2438 free(dev);
2439 continue;
2441 (void) close(fd);
2443 usb_add_device(new_devices, dev);
2446 (void) closedir(subdir);
2449 regfree(&regex);
2450 free(filename);
2451 free(device);
2452 (void) closedir(dir);
2454 return (0);
2458 * usb_get_status:
2459 * gets status of endpoint
2461 * Returns: ugen's last cmd status
2463 static int
2464 usb_get_status(int fd)
2466 int status, error;
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)) {
2472 switch (status) {
2473 case USB_LC_STAT_NOERROR:
2474 usb_dprintf(DEBUG_DETAILED, "No Error\n");
2475 break;
2476 case USB_LC_STAT_CRC:
2477 usb_dprintf(DEBUG_ERRORS, "CRC Timeout Detected\n");
2478 break;
2479 case USB_LC_STAT_BITSTUFFING:
2480 usb_dprintf(DEBUG_ERRORS, "Bit Stuffing Violation\n");
2481 break;
2482 case USB_LC_STAT_DATA_TOGGLE_MM:
2483 usb_dprintf(DEBUG_ERRORS, "Data Toggle Mismatch\n");
2484 break;
2485 case USB_LC_STAT_STALL:
2486 usb_dprintf(DEBUG_ERRORS, "End Point Stalled\n");
2487 break;
2488 case USB_LC_STAT_DEV_NOT_RESP:
2489 usb_dprintf(DEBUG_ERRORS, "Device is Not Responding\n");
2490 break;
2491 case USB_LC_STAT_PID_CHECKFAILURE:
2492 usb_dprintf(DEBUG_ERRORS, "PID Check Failure\n");
2493 break;
2494 case USB_LC_STAT_UNEXP_PID:
2495 usb_dprintf(DEBUG_ERRORS, "Unexpected PID\n");
2496 break;
2497 case USB_LC_STAT_DATA_OVERRUN:
2498 usb_dprintf(DEBUG_ERRORS, "Data Exceeded Size\n");
2499 break;
2500 case USB_LC_STAT_DATA_UNDERRUN:
2501 usb_dprintf(DEBUG_ERRORS, "Less data received\n");
2502 break;
2503 case USB_LC_STAT_BUFFER_OVERRUN:
2504 usb_dprintf(DEBUG_ERRORS, "Buffer Size Exceeded\n");
2505 break;
2506 case USB_LC_STAT_BUFFER_UNDERRUN:
2507 usb_dprintf(DEBUG_ERRORS, "Buffer Underrun\n");
2508 break;
2509 case USB_LC_STAT_TIMEOUT:
2510 usb_dprintf(DEBUG_ERRORS, "Command Timed Out\n");
2511 break;
2512 case USB_LC_STAT_NOT_ACCESSED:
2513 usb_dprintf(DEBUG_ERRORS, "Not Accessed by h/w\n");
2514 break;
2515 case USB_LC_STAT_UNSPECIFIED_ERR:
2516 usb_dprintf(DEBUG_ERRORS, "Unspecified Error\n");
2517 break;
2518 case USB_LC_STAT_NO_BANDWIDTH:
2519 usb_dprintf(DEBUG_ERRORS, "No Bandwidth\n");
2520 break;
2521 case USB_LC_STAT_HW_ERR:
2522 usb_dprintf(DEBUG_ERRORS,
2523 "Host Controller h/w Error\n");
2524 break;
2525 case USB_LC_STAT_SUSPENDED:
2526 usb_dprintf(DEBUG_ERRORS, "Device was Suspended\n");
2527 break;
2528 case USB_LC_STAT_DISCONNECTED:
2529 usb_dprintf(DEBUG_ERRORS, "Device was Disconnected\n");
2530 break;
2531 case USB_LC_STAT_INTR_BUF_FULL:
2532 usb_dprintf(DEBUG_ERRORS,
2533 "Interrupt buffer was full\n");
2534 break;
2535 case USB_LC_STAT_INVALID_REQ:
2536 usb_dprintf(DEBUG_ERRORS, "Request was Invalid\n");
2537 break;
2538 case USB_LC_STAT_INTERRUPTED:
2539 usb_dprintf(DEBUG_ERRORS, "Request was Interrupted\n");
2540 break;
2541 case USB_LC_STAT_NO_RESOURCES:
2542 usb_dprintf(DEBUG_ERRORS, "No resources available for "
2543 "request\n");
2544 break;
2545 case USB_LC_STAT_INTR_POLLING_FAILED:
2546 usb_dprintf(DEBUG_ERRORS, "Failed to Restart Poll");
2547 break;
2548 default:
2549 usb_dprintf(DEBUG_ERRORS, "Error Not Determined %d\n",
2550 status);
2551 break;
2555 return (status);
2559 * Descriptor parsing functions, taken from USBA code
2561 * usb_parse_data:
2562 * take a raw buffer and pads it according to format
2564 * Returns: USB_PARSE_ERROR or length parsed
2566 static size_t
2567 usb_parse_data(char *format, uchar_t *data, size_t datalen,
2568 void *structure, size_t structlen)
2570 int fmt;
2571 size_t counter = 1;
2572 int multiplier = 0;
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) {
2591 break;
2594 if (fmt == 'c') {
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))
2601 break;
2603 *cp++ = *data++;
2604 structure = (void *)cp;
2605 if (multiplier) {
2606 multiplier--;
2608 if (multiplier == 0) {
2609 format++;
2611 } else if (fmt == 's') {
2612 uint16_t *sp = (uint16_t *)structure;
2614 sp = (uint16_t *)
2615 (((uintptr_t)sp + _SHORT_ALIGNMENT - 1) &
2616 ~(_SHORT_ALIGNMENT - 1));
2617 if (((data + 2) > dataend) ||
2618 ((sp + 1) > (uint16_t *)structend))
2619 break;
2621 *sp++ = (data[1] << 8) + data[0];
2622 data += 2;
2623 structure = (void *)sp;
2624 if (multiplier) {
2625 multiplier--;
2627 if (multiplier == 0) {
2628 format++;
2630 } else if (fmt == 'l') {
2631 uint32_t *lp = (uint32_t *)structure;
2633 lp = (uint32_t *)
2634 (((uintptr_t)lp + _INT_ALIGNMENT - 1) &
2635 ~(_INT_ALIGNMENT - 1));
2636 if (((data + 4) > dataend) ||
2637 ((lp + 1) > (uint32_t *)structend))
2638 break;
2640 *lp++ = (((((
2641 (uint32_t)data[3] << 8) | data[2]) << 8) |
2642 data[1]) << 8) | data[0];
2643 data += 4;
2644 structure = (void *)lp;
2645 if (multiplier) {
2646 multiplier--;
2648 if (multiplier == 0) {
2649 format++;
2651 } else if (fmt == 'L') {
2652 uint64_t *llp = (uint64_t *)structure;
2654 llp = (uint64_t *)
2655 (((uintptr_t)llp + _LONG_LONG_ALIGNMENT - 1) &
2656 ~(_LONG_LONG_ALIGNMENT - 1));
2657 if (((data + 8) > dataend) ||
2658 ((llp + 1) >= (uint64_t *)structend))
2659 break;
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) |
2665 data[0];
2666 data += 8;
2667 structure = (void *)llp;
2668 if (multiplier) {
2669 multiplier--;
2671 if (multiplier == 0) {
2672 format++;
2674 } else if (isdigit(fmt)) {
2675 multiplier = (multiplier * 10) + (fmt - '0');
2676 counter--;
2677 format++;
2678 } else {
2679 multiplier = 0;
2680 break;
2684 return ((intptr_t)structure - (intptr_t)structstart);
2688 * usb_nth_descr:
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
2695 static uchar_t *
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;
2702 if (buf == NULL) {
2704 return (NULL);
2707 while (buf + 2 <= bufend) {
2708 if ((buf != bufstart) && ((buf[1] == stop_descr_type1) ||
2709 (buf[1] == stop_descr_type2))) {
2711 return (NULL);
2714 if ((descr_type == USB_DESCR_TYPE_ANY) ||
2715 (buf[1] == descr_type)) {
2716 if (n-- == 0) {
2718 return (buf);
2723 * Check for a bad buffer.
2724 * If buf[0] is 0, then this will be an infite loop
2726 INCREMENT_BUF(buf);
2729 return (NULL);
2733 * usb_parse_dev_descr:
2734 * parse device descriptor
2736 * Returns: #bytes parsed
2738 static size_t
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
2758 static size_t
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)
2762 size_t rval;
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);
2775 return (rval);
2779 * usb_parse_if_descr:
2780 * parse interface descriptor
2782 * Returns: #bytes parsed
2784 static size_t
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;
2790 size_t rval;
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);
2806 usb_find_extra(buf,
2807 ((uintptr_t)bufend - (uintptr_t)buf),
2808 extra, extralen);
2810 return (rval);
2814 * Check for a bad buffer.
2815 * If buf[0] is 0, then this will be an infinite loop
2817 INCREMENT_BUF(buf);
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
2832 size_t
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;
2838 size_t rval;
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) {
2854 break;
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,
2861 extra, extralen);
2863 return (rval);
2867 * Check for a bad buffer.
2868 * If buf[0] is 0, then this will be an infinite loop
2870 INCREMENT_BUF(buf);
2873 return (USB_PARSE_ERROR);
2877 * extra descriptor handling
2879 * usb_find_extra:
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
2884 static void
2885 usb_find_extra(uchar_t *buf, size_t buflen,
2886 unsigned char **extra, int *extralen)
2888 uchar_t *next = buf + buf[0];
2890 *extralen = 0;
2891 *extra = next;
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]);
2900 return;
2902 next += next[0];
2907 * error handling
2909 * usb_strerror:
2910 * lookup error string
2912 * Returns: error string
2914 char *
2915 usb_strerror(void)
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));
2932 default:
2933 break;
2936 return ("Unknown error");
2940 * usb_error:
2941 * stores the error number in the global usb_error_errno
2943 * Returns: negative error number
2945 static int
2946 usb_error(int x)
2948 usb_dprintf(DEBUG_FUNCTIONS, "usb_error(): error=%d\n", x);
2950 usb_error_type = USB_ERROR_TYPE_ERRNO;
2951 usb_error_errno = x;
2953 return (-x);
2957 * usb_error_str:
2958 * creates error string
2960 static void
2961 usb_error_str(int x, char *format, ...)
2963 va_list ap;
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),
2971 format, ap);
2973 usb_dprintf(DEBUG_ERRORS, "USB error (%d): %s\n", x, usb_error_string);
2975 va_end(ap);
2979 * usb_dprintf:
2980 * prints out tracing messages according to level
2982 static void
2983 usb_dprintf(int level, char *format, ...)
2985 va_list ap;
2986 char buf[512];
2988 va_start(ap, format);
2990 (void) vsnprintf(buf, sizeof (buf), format, ap);
2991 if (libusb_debug >= level) {
2992 (void) fprintf(stderr, buf);
2994 va_end(ap);
2998 * usb_dump_data:
2999 * print data buffer
3001 static void
3002 usb_dump_data(char *data, int size)
3004 int i;
3006 if (libusb_debug >= DEBUG_DATA_DUMP) {
3007 (void) fprintf(stderr, "data dump:");
3008 for (i = 0; i < size; i++) {
3009 if (i % 16 == 0) {
3010 (void) fprintf(stderr, "\n%08x ", i);
3012 (void) fprintf(stderr, "%02x ", (uchar_t)data[i]);
3014 (void) fprintf(stderr, "\n");