components/libusb-1/patches/libusb.patch
changeset 5851 9f4a6f531294
parent 5850 cf101610be7c
child 5852 243e80c77b4a
equal deleted inserted replaced
5850:cf101610be7c 5851:9f4a6f531294
     1 Solaris support for libusb 1.0, see upstream bug https://github.com/libusb/libusb/issues/169
       
     2 
       
     3 diff -Naur libusb-1.0.20/configure.ac libusb-1.0.20.new/configure.ac
       
     4 --- libusb-1.0.20/configure.ac	2015-09-05 10:20:40.000000000 -0700
       
     5 +++ libusb-1.0.20.new/configure.ac	2016-03-10 00:35:25.712129055 -0800
       
     6 @@ -95,6 +95,12 @@
       
     7  	backend="haiku"
       
     8  	threads="posix"
       
     9  	;;
       
    10 +*-solaris*)
       
    11 +	AC_MSG_RESULT([SunOS])
       
    12 +	backend="sunos"
       
    13 +	threads="posix"
       
    14 +	;;
       
    15 +
       
    16  *)
       
    17  	AC_MSG_ERROR([unsupported operating system])
       
    18  esac
       
    19 @@ -157,6 +163,16 @@
       
    20  	AC_CHECK_HEADERS([poll.h])
       
    21  	AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
       
    22  	;;
       
    23 +
       
    24 +sunos)
       
    25 +	AC_DEFINE(OS_SUNOS, 1, [SunOS backend])
       
    26 +	AC_SUBST(OS_SUNOS)
       
    27 +	THREAD_CFLAGS="-pthread"
       
    28 +	LIBS="-pthread -ldevinfo"
       
    29 +	AC_CHECK_HEADERS([poll.h])
       
    30 +	AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
       
    31 +	;;
       
    32 +
       
    33  netbsd)
       
    34  	AC_DEFINE(OS_NETBSD, 1, [NetBSD backend])
       
    35  	AC_SUBST(OS_NETBSD)
       
    36 @@ -187,6 +203,7 @@
       
    37  AM_CONDITIONAL(OS_LINUX, test "x$backend" = xlinux)
       
    38  AM_CONDITIONAL(OS_DARWIN, test "x$backend" = xdarwin)
       
    39  AM_CONDITIONAL(OS_OPENBSD, test "x$backend" = xopenbsd)
       
    40 +AM_CONDITIONAL(OS_SUNOS, test "x$backend" = xsunos)
       
    41  AM_CONDITIONAL(OS_NETBSD, test "x$backend" = xnetbsd)
       
    42  AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows)
       
    43  AM_CONDITIONAL(OS_HAIKU, test "x$backend" = xhaiku)
       
    44 diff -Naur libusb-1.0.20/libusb/Makefile.am libusb-1.0.20.new/libusb/Makefile.am
       
    45 --- libusb-1.0.20/libusb/Makefile.am	2015-09-05 10:20:40.000000000 -0700
       
    46 +++ libusb-1.0.20.new/libusb/Makefile.am	2016-03-10 00:19:22.549380102 -0800
       
    47 @@ -9,6 +9,7 @@
       
    48  DARWIN_USB_SRC = os/darwin_usb.c
       
    49  OPENBSD_USB_SRC = os/openbsd_usb.c
       
    50  NETBSD_USB_SRC = os/netbsd_usb.c
       
    51 +SUNOS_USB_SRC = os/sunos_usb.c os/sunos_usb.h
       
    52  WINDOWS_USB_SRC = os/poll_windows.c os/windows_usb.c libusb-1.0.rc libusb-1.0.def
       
    53  WINCE_USB_SRC = os/wince_usb.c os/wince_usb.h
       
    54  
       
    55 @@ -49,6 +50,10 @@
       
    56  OS_SRC = $(NETBSD_USB_SRC) $(POSIX_POLL_SRC)
       
    57  endif
       
    58  
       
    59 +if OS_SUNOS
       
    60 +OS_SRC = $(SUNOS_USB_SRC) $(POSIX_POLL_SRC)
       
    61 +endif
       
    62 +
       
    63  if OS_HAIKU
       
    64  OS_SRC = $(POSIX_POLL_SRC)
       
    65  SUBDIRS = os/haiku
       
    66 diff -Naur libusb-1.0.20/libusb/core.c libusb-1.0.20.new/libusb/core.c
       
    67 --- libusb-1.0.20/libusb/core.c	2015-09-05 10:30:43.000000000 -0700
       
    68 +++ libusb-1.0.20.new/libusb/core.c	2016-03-10 00:20:40.154945235 -0800
       
    69 @@ -58,6 +58,8 @@
       
    70  const struct usbi_os_backend * const usbi_backend = &wince_backend;
       
    71  #elif defined(OS_HAIKU)
       
    72  const struct usbi_os_backend * const usbi_backend = &haiku_usb_raw_backend;
       
    73 +#elif defined(OS_SUNOS)
       
    74 +const struct usbi_os_backend * const usbi_backend = &sunos_backend;
       
    75  #else
       
    76  #error "Unsupported OS"
       
    77  #endif
       
    78 diff -Naur libusb-1.0.20/libusb/libusbi.h libusb-1.0.20.new/libusb/libusbi.h
       
    79 --- libusb-1.0.20/libusb/libusbi.h	2015-09-13 17:36:19.000000000 -0700
       
    80 +++ libusb-1.0.20.new/libusb/libusbi.h	2016-03-10 00:23:08.647355689 -0800
       
    81 @@ -493,7 +493,8 @@
       
    82  int usbi_clear_event(struct libusb_context *ctx);
       
    83  
       
    84  /* Internal abstraction for poll (needs struct usbi_transfer on Windows) */
       
    85 -#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_HAIKU)
       
    86 +#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) || \
       
    87 +	defined(OS_HAIKU) || defined(OS_SUNOS)
       
    88  #include <unistd.h>
       
    89  #include "os/poll_posix.h"
       
    90  #elif defined(OS_WINDOWS) || defined(OS_WINCE)
       
    91 @@ -1091,6 +1092,7 @@
       
    92  extern const struct usbi_os_backend windows_backend;
       
    93  extern const struct usbi_os_backend wince_backend;
       
    94  extern const struct usbi_os_backend haiku_usb_raw_backend;
       
    95 +extern const struct usbi_os_backend sunos_backend;
       
    96  
       
    97  extern struct list_head active_contexts_list;
       
    98  extern usbi_mutex_static_t active_contexts_lock;
       
    99 diff -Naur libusb-1.0.20/libusb/os/sunos_usb.c libusb-1.0.20.new/libusb/os/sunos_usb.c
       
   100 --- libusb-1.0.20/libusb/os/sunos_usb.c	1969-12-31 16:00:00.000000000 -0800
       
   101 +++ libusb-1.0.20.new/libusb/os/sunos_usb.c	2016-03-10 00:24:36.641449583 -0800
       
   102 @@ -0,0 +1,1259 @@
       
   103 +/*
       
   104 + *
       
   105 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
       
   106 + *
       
   107 + * This library is free software; you can redistribute it and/or
       
   108 + * modify it under the terms of the GNU Lesser General Public
       
   109 + * License as published by the Free Software Foundation; either
       
   110 + * version 2.1 of the License, or (at your option) any later version.
       
   111 + *
       
   112 + * This library is distributed in the hope that it will be useful,
       
   113 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
   114 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
   115 + * Lesser General Public License for more details.
       
   116 + *
       
   117 + * You should have received a copy of the GNU Lesser General Public
       
   118 + * License along with this library; if not, write to the Free Software
       
   119 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
       
   120 + */
       
   121 +
       
   122 +#include <config.h>
       
   123 +
       
   124 +#include <sys/time.h>
       
   125 +#include <sys/types.h>
       
   126 +#include <sys/stat.h>
       
   127 +#include <strings.h>
       
   128 +#include <errno.h>
       
   129 +#include <fcntl.h>
       
   130 +#include <stdio.h>
       
   131 +#include <stdlib.h>
       
   132 +#include <string.h>
       
   133 +#include <unistd.h>
       
   134 +#include <aio.h>
       
   135 +#include <libdevinfo.h>
       
   136 +#include <sys/usb/clients/ugen/usb_ugen.h>
       
   137 +#include <sys/usb/usba.h>
       
   138 +#include <sys/pci.h>
       
   139 +
       
   140 +#include "libusbi.h"
       
   141 +#include "sunos_usb.h"
       
   142 +
       
   143 +/*
       
   144 + * Backend functions
       
   145 + */
       
   146 +static int sunos_init(struct libusb_context *);
       
   147 +static void sunos_exit(void);
       
   148 +static int sunos_get_device_list(struct libusb_context *,
       
   149 +    struct discovered_devs **);
       
   150 +static int sunos_open(struct libusb_device_handle *);
       
   151 +static void sunos_close(struct libusb_device_handle *);
       
   152 +static int sunos_get_device_descriptor(struct libusb_device *,
       
   153 +    uint8_t*, int *);
       
   154 +static int sunos_get_active_config_descriptor(struct libusb_device *,
       
   155 +    uint8_t*, size_t, int *);
       
   156 +static int sunos_get_config_descriptor(struct libusb_device *, uint8_t,
       
   157 +    uint8_t*, size_t, int *);
       
   158 +static int sunos_get_configuration(struct libusb_device_handle *, int *);
       
   159 +static int sunos_set_configuration(struct libusb_device_handle *, int);
       
   160 +static int sunos_claim_interface(struct libusb_device_handle *, int);
       
   161 +static int sunos_release_interface(struct libusb_device_handle *, int);
       
   162 +static int sunos_set_interface_altsetting(struct libusb_device_handle *,
       
   163 +    int, int);
       
   164 +static int sunos_clear_halt(struct libusb_device_handle *, uint8_t);
       
   165 +static int sunos_reset_device(struct libusb_device_handle *);
       
   166 +static void sunos_destroy_device(struct libusb_device *);
       
   167 +static int sunos_submit_transfer(struct usbi_transfer *);
       
   168 +static int sunos_cancel_transfer(struct usbi_transfer *);
       
   169 +static void sunos_clear_transfer_priv(struct usbi_transfer *);
       
   170 +static int sunos_handle_transfer_completion(struct usbi_transfer *);
       
   171 +static int sunos_clock_gettime(int, struct timespec *);
       
   172 +
       
   173 +/*
       
   174 + * Private functions
       
   175 + */
       
   176 +static int _errno_to_libusb(int);
       
   177 +static int sunos_usb_get_status(int fd);
       
   178 +
       
   179 +static int sunos_init(struct libusb_context *ctx)
       
   180 +{
       
   181 +	return (LIBUSB_SUCCESS);
       
   182 +}
       
   183 +
       
   184 +static void sunos_exit(void)
       
   185 +{
       
   186 +	usbi_dbg("");
       
   187 +}
       
   188 +
       
   189 +static int
       
   190 +sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
       
   191 +{
       
   192 +	int	proplen;
       
   193 +	int	n, *addr, *port_prop;
       
   194 +	char	*phypath;
       
   195 +	uint8_t	*rdata;
       
   196 +	struct libusb_device_descriptor	*descr;
       
   197 +	sunos_dev_priv_t	*dpriv = (sunos_dev_priv_t *)dev->os_priv;
       
   198 +
       
   199 +	/* Device descriptors */
       
   200 +	proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
       
   201 +	    "usb-dev-descriptor", &rdata);
       
   202 +	if (proplen <= 0) {
       
   203 +
       
   204 +		return (LIBUSB_ERROR_IO);
       
   205 +	}
       
   206 +
       
   207 +	descr = (struct libusb_device_descriptor *)rdata;
       
   208 +	bcopy(descr, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE);
       
   209 +	dpriv->dev_descr.bcdUSB = libusb_cpu_to_le16(descr->bcdUSB);
       
   210 +	dpriv->dev_descr.idVendor = libusb_cpu_to_le16(descr->idVendor);
       
   211 +	dpriv->dev_descr.idProduct = libusb_cpu_to_le16(descr->idProduct);
       
   212 +	dpriv->dev_descr.bcdDevice = libusb_cpu_to_le16(descr->bcdDevice);
       
   213 +
       
   214 +	/* Raw configuration descriptors */
       
   215 +	proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
       
   216 +	    "usb-raw-cfg-descriptors", &rdata);
       
   217 +	if (proplen <= 0) {
       
   218 +		usbi_dbg("can't find raw config descriptors");
       
   219 +
       
   220 +		return (LIBUSB_ERROR_IO);
       
   221 +	}
       
   222 +	dpriv->raw_cfgdescr = calloc(1, proplen);
       
   223 +	if (dpriv->raw_cfgdescr == NULL) {
       
   224 +		return (LIBUSB_ERROR_NO_MEM);
       
   225 +	} else {
       
   226 +		bcopy(rdata, dpriv->raw_cfgdescr, proplen);
       
   227 +	}
       
   228 +
       
   229 +	n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &port_prop);
       
   230 +
       
   231 +	if ((n != 1) || (*port_prop <= 0)) {
       
   232 +		return (LIBUSB_ERROR_IO);
       
   233 +	}
       
   234 +	dev->port_number = *port_prop;
       
   235 +
       
   236 +	/* device physical path */
       
   237 +	phypath = di_devfs_path(node);
       
   238 +	if (phypath) {
       
   239 +		dpriv->phypath = strdup(phypath);
       
   240 +		di_devfs_path_free(phypath);
       
   241 +	} else {
       
   242 +		free(dpriv->raw_cfgdescr);
       
   243 +
       
   244 +		return (LIBUSB_ERROR_IO);
       
   245 +	}
       
   246 +
       
   247 +	/* address */
       
   248 +	n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "assigned-address", &addr);
       
   249 +	if (n != 1 || *addr == 0) {
       
   250 +		usbi_dbg("can't get address");
       
   251 +	} else {
       
   252 +		dev->device_address = *addr;
       
   253 +	}
       
   254 +
       
   255 +	/* speed */
       
   256 +	if (di_prop_exists(DDI_DEV_T_ANY, node, "low-speed") == 1) {
       
   257 +		dev->speed = LIBUSB_SPEED_LOW;
       
   258 +	} else if (di_prop_exists(DDI_DEV_T_ANY, node, "high-speed") == 1) {
       
   259 +		dev->speed = LIBUSB_SPEED_HIGH;
       
   260 +	} else if (di_prop_exists(DDI_DEV_T_ANY, node, "full-speed") == 1) {
       
   261 +		dev->speed = LIBUSB_SPEED_FULL;
       
   262 +	} else if (di_prop_exists(DDI_DEV_T_ANY, node, "super-speed") == 1) {
       
   263 +		dev->speed = LIBUSB_SPEED_SUPER;
       
   264 +	}
       
   265 +
       
   266 +	usbi_dbg("vid=%x pid=%x, path=%s, bus_nmber=0x%x, port_number=%d, "
       
   267 +	    "speed=%d", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct,
       
   268 +	    dpriv->phypath, dev->bus_number, dev->port_number, dev->speed);
       
   269 +
       
   270 +	return (LIBUSB_SUCCESS);
       
   271 +}
       
   272 +
       
   273 +
       
   274 +static int
       
   275 +sunos_add_devices(di_devlink_t link, void *arg)
       
   276 +{
       
   277 +	struct devlink_cbarg	*largs = (struct devlink_cbarg *)arg;
       
   278 +	struct node_args	*nargs;
       
   279 +	di_node_t		myself, pnode;
       
   280 +	uint64_t		session_id = 0;
       
   281 +	uint16_t		bdf = 0;
       
   282 +	struct libusb_device	*dev;
       
   283 +	sunos_dev_priv_t	*devpriv;
       
   284 +	const char		*path, *newpath;
       
   285 +	int			 n, i;
       
   286 +	int			*addr_prop;
       
   287 +	uint8_t			bus_number = 0;
       
   288 +
       
   289 +	nargs = (struct node_args *)largs->nargs;
       
   290 +	myself = largs->myself;
       
   291 +	if (nargs->last_ugenpath) {
       
   292 +		/* the same node's links */
       
   293 +		return (DI_WALK_CONTINUE);
       
   294 +	}
       
   295 +
       
   296 +	/*
       
   297 +	 * Construct session ID.
       
   298 +	 * session ID = ...parent hub addr|hub addr|dev addr.
       
   299 +	 */
       
   300 +	pnode = myself;
       
   301 +	i = 0;
       
   302 +	while (pnode != DI_NODE_NIL) {
       
   303 +		if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) {
       
   304 +			/* walk to root */
       
   305 +			uint32_t *regbuf = NULL;
       
   306 +			uint32_t reg;
       
   307 +
       
   308 +			n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg",
       
   309 +			    (int **)&regbuf);
       
   310 +			reg = regbuf[0];
       
   311 +			bdf = (PCI_REG_BUS_G(reg) << 8) |
       
   312 +			    (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
       
   313 +			session_id |= (bdf << i * 8);
       
   314 +
       
   315 +			/* same as 'unit-address' property */
       
   316 +			bus_number =
       
   317 +			    (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
       
   318 +
       
   319 +			usbi_dbg("device bus address=%s:%x",
       
   320 +			    di_bus_addr(pnode), bus_number);
       
   321 +
       
   322 +			break;
       
   323 +		}
       
   324 +
       
   325 +		/* usb_addr */
       
   326 +		n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode,
       
   327 +		    "assigned-address", &addr_prop);
       
   328 +		if ((n != 1) || (addr_prop[0] == 0)) {
       
   329 +			usbi_dbg("cannot get valid usb_addr");
       
   330 +
       
   331 +			return (DI_WALK_CONTINUE);
       
   332 +		}
       
   333 +
       
   334 +		session_id |= ((addr_prop[0] & 0xff) << i * 8);
       
   335 +		if (++i > 7)
       
   336 +			break;
       
   337 +
       
   338 +		pnode = di_parent_node(pnode);
       
   339 +	}
       
   340 +
       
   341 +	path = di_devlink_path(link);
       
   342 +	dev = usbi_get_device_by_session_id(nargs->ctx, session_id);
       
   343 +	if (dev == NULL) {
       
   344 +		dev = usbi_alloc_device(nargs->ctx, session_id);
       
   345 +		if (dev == NULL) {
       
   346 +			usbi_dbg("can't alloc device");
       
   347 +
       
   348 +			return (DI_WALK_TERMINATE);
       
   349 +		}
       
   350 +		devpriv = (sunos_dev_priv_t *)dev->os_priv;
       
   351 +		if ((newpath = strrchr(path, '/')) == NULL) {
       
   352 +			libusb_unref_device(dev);
       
   353 +
       
   354 +			return (DI_WALK_TERMINATE);
       
   355 +		}
       
   356 +		devpriv->ugenpath = strndup(path, strlen(path) -
       
   357 +		    strlen(newpath));
       
   358 +		dev->bus_number = bus_number;
       
   359 +
       
   360 +		if (sunos_fill_in_dev_info(myself, dev) != LIBUSB_SUCCESS) {
       
   361 +			libusb_unref_device(dev);
       
   362 +
       
   363 +			return (DI_WALK_TERMINATE);
       
   364 +		}
       
   365 +		if (usbi_sanitize_device(dev) < 0) {
       
   366 +			libusb_unref_device(dev);
       
   367 +			usbi_dbg("sanatize failed: ");
       
   368 +			return (DI_WALK_TERMINATE);
       
   369 +		}
       
   370 +	} else {
       
   371 +		usbi_dbg("Dev %s exists", path);
       
   372 +	}
       
   373 +
       
   374 +	devpriv = (sunos_dev_priv_t *)dev->os_priv;
       
   375 +	if (nargs->last_ugenpath == NULL) {
       
   376 +		/* first device */
       
   377 +		nargs->last_ugenpath = devpriv->ugenpath;
       
   378 +
       
   379 +		if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) {
       
   380 +			usbi_dbg("cannot append device");
       
   381 +		}
       
   382 +
       
   383 +		/*
       
   384 +		 * we alloc and hence ref this dev. We don't need to ref it
       
   385 +		 * hereafter. Front end or app should take care of their ref.
       
   386 +		 */
       
   387 +		libusb_unref_device(dev);
       
   388 +	}
       
   389 +
       
   390 +	usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x",
       
   391 +	    devpriv->ugenpath, path, (uint64_t)session_id,
       
   392 +	    (*nargs->discdevs)->len, bdf);
       
   393 +
       
   394 +	return (DI_WALK_CONTINUE);
       
   395 +}
       
   396 +
       
   397 +static int
       
   398 +sunos_walk_minor_node_link(di_node_t node, void *args)
       
   399 +{
       
   400 +        di_minor_t minor = DI_MINOR_NIL;
       
   401 +        char *minor_path;
       
   402 +        struct devlink_cbarg arg;
       
   403 +	struct node_args *nargs = (struct node_args *)args;
       
   404 +	di_devlink_handle_t devlink_hdl = nargs->dlink_hdl;
       
   405 +
       
   406 +	/* walk each minor to find ugen devices */
       
   407 +        while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
       
   408 +                minor_path = di_devfs_minor_path(minor);
       
   409 +                arg.nargs = args;
       
   410 +		arg.myself = node;
       
   411 +                arg.minor = minor;
       
   412 +                (void) di_devlink_walk(devlink_hdl,
       
   413 +		    "^usb/[0-9a-f]+[.][0-9a-f]+", minor_path,
       
   414 +		    DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices);
       
   415 +                di_devfs_path_free(minor_path);
       
   416 +        }
       
   417 +
       
   418 +	/* switch to a different node */
       
   419 +	nargs->last_ugenpath = NULL;
       
   420 +
       
   421 +	return (DI_WALK_CONTINUE);
       
   422 +}
       
   423 +
       
   424 +int
       
   425 +sunos_get_device_list(struct libusb_context * ctx,
       
   426 +	struct discovered_devs **discdevs)
       
   427 +{
       
   428 +	di_node_t root_node;
       
   429 +	struct node_args args;
       
   430 +	di_devlink_handle_t devlink_hdl;
       
   431 +
       
   432 +	args.ctx = ctx;
       
   433 +	args.discdevs = discdevs;
       
   434 +	args.last_ugenpath = NULL;
       
   435 +	if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
       
   436 +		usbi_dbg("di_int() failed: %s", strerror(errno));
       
   437 +		return (LIBUSB_ERROR_IO);
       
   438 +	}
       
   439 +
       
   440 +	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
       
   441 +		di_fini(root_node);
       
   442 +		usbi_dbg("di_devlink_init() failed: %s", strerror(errno));
       
   443 +
       
   444 +		return (LIBUSB_ERROR_IO);
       
   445 +	}
       
   446 +	args.dlink_hdl = devlink_hdl;
       
   447 +
       
   448 +	/* walk each node to find USB devices */
       
   449 +	if (di_walk_node(root_node, DI_WALK_SIBFIRST, &args,
       
   450 +	    sunos_walk_minor_node_link) == -1) {
       
   451 +		usbi_dbg("di_walk_node() failed: %s", strerror(errno));
       
   452 +		di_fini(root_node);
       
   453 +
       
   454 +		return (LIBUSB_ERROR_IO);
       
   455 +	}
       
   456 +
       
   457 +	di_fini(root_node);
       
   458 +	di_devlink_fini(&devlink_hdl);
       
   459 +
       
   460 +	usbi_dbg("%d devices", (*discdevs)->len);
       
   461 +
       
   462 +	return ((*discdevs)->len);
       
   463 +}
       
   464 +
       
   465 +static int
       
   466 +sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv)
       
   467 +{
       
   468 +	char filename[PATH_MAX + 1];
       
   469 +
       
   470 +	if (hpriv->eps[0].datafd > 0) {
       
   471 +
       
   472 +		return (LIBUSB_SUCCESS);
       
   473 +	}
       
   474 +	snprintf(filename, PATH_MAX, "%s/cntrl0", dpriv->ugenpath);
       
   475 +
       
   476 +	usbi_dbg("opening %s", filename);
       
   477 +	hpriv->eps[0].datafd = open(filename, O_RDWR);
       
   478 +	if (hpriv->eps[0].datafd < 0) {
       
   479 +		return(_errno_to_libusb(errno));
       
   480 +	}
       
   481 +
       
   482 +	snprintf(filename, PATH_MAX, "%s/cntrl0stat", dpriv->ugenpath);
       
   483 +	hpriv->eps[0].statfd = open(filename, O_RDONLY);
       
   484 +	if (hpriv->eps[0].statfd < 0) {
       
   485 +		close(hpriv->eps[0].datafd);
       
   486 +		hpriv->eps[0].datafd = -1;
       
   487 +
       
   488 +		return(_errno_to_libusb(errno));
       
   489 +	}
       
   490 +
       
   491 +	return (LIBUSB_SUCCESS);
       
   492 +}
       
   493 +
       
   494 +static void
       
   495 +sunos_usb_close_all_eps(sunos_dev_handle_priv_t *hdev)
       
   496 +{
       
   497 +	int i;
       
   498 +
       
   499 +	/* not close ep0 */
       
   500 +	for (i = 1; i < USB_MAXENDPOINTS; i++) {
       
   501 +		if (hdev->eps[i].datafd != -1) {
       
   502 +			(void) close(hdev->eps[i].datafd);
       
   503 +			hdev->eps[i].datafd = -1;
       
   504 +		}
       
   505 +		if (hdev->eps[i].statfd != -1) {
       
   506 +			(void) close(hdev->eps[i].statfd);
       
   507 +			hdev->eps[i].statfd = -1;
       
   508 +		}
       
   509 +	}
       
   510 +}
       
   511 +
       
   512 +static void
       
   513 +sunos_usb_close_ep0(sunos_dev_handle_priv_t *hdev, sunos_dev_priv_t *dpriv)
       
   514 +{
       
   515 +	if (hdev->eps[0].datafd >= 0) {
       
   516 +		close(hdev->eps[0].datafd);
       
   517 +		close(hdev->eps[0].statfd);
       
   518 +		hdev->eps[0].datafd = -1;
       
   519 +		hdev->eps[0].statfd = -1;
       
   520 +	}
       
   521 +}
       
   522 +
       
   523 +static uchar_t
       
   524 +sunos_usb_ep_index(uint8_t ep_addr)
       
   525 +{
       
   526 +	return ((ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK) +
       
   527 +	    ((ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? 16 : 0));
       
   528 +}
       
   529 +
       
   530 +static int
       
   531 +sunos_find_interface(struct libusb_device_handle *hdev,
       
   532 +    uint8_t endpoint, uint8_t *interface)
       
   533 +{
       
   534 +	struct libusb_config_descriptor *config;
       
   535 +	int r;
       
   536 +	int iface_idx;
       
   537 +
       
   538 +	r = libusb_get_active_config_descriptor(hdev->dev, &config);
       
   539 +	if (r < 0) {
       
   540 +		return (LIBUSB_ERROR_INVALID_PARAM);
       
   541 +	}
       
   542 +
       
   543 +	for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) {
       
   544 +		const struct libusb_interface *iface =
       
   545 +		    &config->interface[iface_idx];
       
   546 +		int altsetting_idx;
       
   547 +
       
   548 +		for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting;
       
   549 +		    altsetting_idx++) {
       
   550 +			const struct libusb_interface_descriptor *altsetting =
       
   551 +			    &iface->altsetting[altsetting_idx];
       
   552 +			int ep_idx;
       
   553 +
       
   554 +			for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints;
       
   555 +			    ep_idx++) {
       
   556 +				const struct libusb_endpoint_descriptor *ep =
       
   557 +					&altsetting->endpoint[ep_idx];
       
   558 +				if (ep->bEndpointAddress == endpoint) {
       
   559 +					*interface = iface_idx;
       
   560 +					libusb_free_config_descriptor(config);
       
   561 +
       
   562 +					return (LIBUSB_SUCCESS);
       
   563 +				}
       
   564 +			}
       
   565 +		}
       
   566 +	}
       
   567 +	libusb_free_config_descriptor(config);
       
   568 +
       
   569 +	return (LIBUSB_ERROR_INVALID_PARAM);
       
   570 +}
       
   571 +
       
   572 +static int
       
   573 +sunos_check_device_and_status_open(struct libusb_device_handle *hdl,
       
   574 +    uint8_t ep_addr, int ep_type)
       
   575 +{
       
   576 +	char	filename[PATH_MAX + 1], statfilename[PATH_MAX + 1];
       
   577 +	char	cfg_num[16], alt_num[16];
       
   578 +	int	fd, fdstat, mode;
       
   579 +	uint8_t	ifc = 0;
       
   580 +	uint8_t	ep_index;
       
   581 +	sunos_dev_handle_priv_t *hpriv;
       
   582 +
       
   583 +	usbi_dbg("open ep 0x%02x", ep_addr);
       
   584 +	hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv;
       
   585 +	ep_index = sunos_usb_ep_index(ep_addr);
       
   586 +	/* ep already opened */
       
   587 +	if ((hpriv->eps[ep_index].datafd > 0) &&
       
   588 +	    (hpriv->eps[ep_index].statfd > 0)) {
       
   589 +		usbi_dbg("ep 0x%02x already opened, return success",
       
   590 +			ep_addr);
       
   591 +
       
   592 +		return (0);
       
   593 +	}
       
   594 +
       
   595 +	if (sunos_find_interface(hdl, ep_addr, &ifc) < 0) {
       
   596 +		usbi_dbg("can't find interface for endpoint 0x%02x",
       
   597 +		    ep_addr);
       
   598 +
       
   599 +		return (LIBUSB_ERROR_ACCESS);
       
   600 +	}
       
   601 +
       
   602 +	/* create filename */
       
   603 +	if (hpriv->config_index > 0) {
       
   604 +		(void) snprintf(cfg_num, sizeof (cfg_num), "cfg%d",
       
   605 +		    hpriv->config_index + 1);
       
   606 +	} else {
       
   607 +		bzero(cfg_num, sizeof (cfg_num));
       
   608 +	}
       
   609 +
       
   610 +	if (hpriv->altsetting[ifc] > 0) {
       
   611 +		(void) snprintf(alt_num, sizeof (alt_num), ".%d",
       
   612 +		    hpriv->altsetting[ifc]);
       
   613 +	} else {
       
   614 +		bzero(alt_num, sizeof (alt_num));
       
   615 +	}
       
   616 +
       
   617 +	(void) snprintf(filename, PATH_MAX, "%s/%sif%d%s%s%d",
       
   618 +	    hpriv->dpriv->ugenpath, cfg_num, ifc, alt_num,
       
   619 +	    (ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? "in" :
       
   620 +	    "out", (ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK));
       
   621 +	(void) snprintf(statfilename, PATH_MAX, "%sstat", filename);
       
   622 +
       
   623 +	/*
       
   624 +	 * for interrupt IN endpoints, we need to enable one xfer
       
   625 +	 * mode before opening the endpoint
       
   626 +	 */
       
   627 +	if ((ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) &&
       
   628 +	    (ep_addr & LIBUSB_ENDPOINT_IN)) {
       
   629 +		char	control = USB_EP_INTR_ONE_XFER;
       
   630 +		int	count;
       
   631 +
       
   632 +		/* open the status device node for the ep first RDWR */
       
   633 +		if ((fdstat = open(statfilename, O_RDWR)) == -1) {
       
   634 +			usbi_dbg("can't open %s RDWR: %d",
       
   635 +				statfilename, errno);
       
   636 +		} else {
       
   637 +			count = write(fdstat, &control, sizeof (control));
       
   638 +			if (count != 1) {
       
   639 +				/* this should have worked */
       
   640 +				usbi_dbg("can't write to %s: %d",
       
   641 +					statfilename, errno);
       
   642 +				(void) close(fdstat);
       
   643 +
       
   644 +				return (errno);
       
   645 +			}
       
   646 +			/* close status node and open xfer node first */
       
   647 +			close (fdstat);
       
   648 +		}
       
   649 +	}
       
   650 +
       
   651 +	/* open the xfer node first in case alt needs to be changed */
       
   652 +	if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
       
   653 +		mode = O_RDWR;
       
   654 +	} else if (ep_addr & LIBUSB_ENDPOINT_IN) {
       
   655 +		mode = O_RDONLY;
       
   656 +	} else {
       
   657 +		mode = O_WRONLY;
       
   658 +	}
       
   659 +
       
   660 +	/*
       
   661 +	 * IMPORTANT: must open data xfer node first and then open stat node
       
   662 +	 * Otherwise, it will fail on multi-config or multi-altsetting devices
       
   663 +	 * with "Device Busy" error. See ugen_epxs_switch_cfg_alt() and
       
   664 +	 * ugen_epxs_check_alt_switch() in ugen driver source code.
       
   665 +	 */
       
   666 +	if ((fd = open(filename, mode)) == -1) {
       
   667 +		usbi_dbg("can't open %s: %d(%s)", filename, errno,
       
   668 +		    strerror(errno));
       
   669 +
       
   670 +		return (errno);
       
   671 +	}
       
   672 +	/* open the status node */
       
   673 +	if ((fdstat = open(statfilename, O_RDONLY)) == -1) {
       
   674 +		usbi_dbg("can't open %s: %d", statfilename, errno);
       
   675 +
       
   676 +		(void) close(fd);
       
   677 +
       
   678 +		return (errno);
       
   679 +	}
       
   680 +
       
   681 +	hpriv->eps[ep_index].datafd = fd;
       
   682 +	hpriv->eps[ep_index].statfd = fdstat;
       
   683 +	usbi_dbg("ep=0x%02x datafd=%d, statfd=%d", ep_addr, fd, fdstat);
       
   684 +
       
   685 +	return (0);
       
   686 +}
       
   687 +
       
   688 +int
       
   689 +sunos_open(struct libusb_device_handle *handle)
       
   690 +{
       
   691 +	sunos_dev_handle_priv_t	*hpriv;
       
   692 +	sunos_dev_priv_t	*dpriv;
       
   693 +	int	i;
       
   694 +	int	ret;
       
   695 +
       
   696 +	hpriv = (sunos_dev_handle_priv_t *)handle->os_priv;
       
   697 +	dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
       
   698 +	hpriv->dpriv = dpriv;
       
   699 +
       
   700 +	/* set all file descriptors to "closed" */
       
   701 +	for (i = 0; i < USB_MAXENDPOINTS; i++) {
       
   702 +		hpriv->eps[i].datafd = -1;
       
   703 +		hpriv->eps[i].statfd = -1;
       
   704 +	}
       
   705 +
       
   706 +	if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) {
       
   707 +		usbi_dbg("fail: %d", ret);
       
   708 +		return (ret);
       
   709 +	}
       
   710 +
       
   711 +	return (LIBUSB_SUCCESS);
       
   712 +}
       
   713 +
       
   714 +void
       
   715 +sunos_close(struct libusb_device_handle *handle)
       
   716 +{
       
   717 +	sunos_dev_handle_priv_t *hpriv;
       
   718 +	sunos_dev_priv_t *dpriv;
       
   719 +
       
   720 +	usbi_dbg("");
       
   721 +	if (!handle) {
       
   722 +		return;
       
   723 +	}
       
   724 +
       
   725 +	hpriv = (sunos_dev_handle_priv_t *)handle->os_priv;
       
   726 +	if (!hpriv) {
       
   727 +		return;
       
   728 +	}
       
   729 +	dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
       
   730 +	if (!dpriv) {
       
   731 +		return;
       
   732 +	}
       
   733 +
       
   734 +	sunos_usb_close_all_eps(hpriv);
       
   735 +	sunos_usb_close_ep0(hpriv, dpriv);
       
   736 +}
       
   737 +
       
   738 +int
       
   739 +sunos_get_device_descriptor(struct libusb_device *dev, uint8_t *buf,
       
   740 +    int *host_endian)
       
   741 +{
       
   742 +	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
       
   743 +
       
   744 +	memcpy(buf, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE);
       
   745 +	*host_endian = 0;
       
   746 +
       
   747 +	return (LIBUSB_SUCCESS);
       
   748 +}
       
   749 +
       
   750 +int
       
   751 +sunos_get_active_config_descriptor(struct libusb_device *dev,
       
   752 +    uint8_t *buf, size_t len, int *host_endian)
       
   753 +{
       
   754 +	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
       
   755 +	struct libusb_config_descriptor *cfg;
       
   756 +
       
   757 +	cfg = (struct libusb_config_descriptor *)dpriv->raw_cfgdescr;
       
   758 +	len = MIN(len, libusb_le16_to_cpu(cfg->wTotalLength));
       
   759 +	memcpy(buf, dpriv->raw_cfgdescr, len);
       
   760 +	*host_endian = 0;
       
   761 +	usbi_dbg("len %d", len);
       
   762 +
       
   763 +	return (len);
       
   764 +}
       
   765 +
       
   766 +int
       
   767 +sunos_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
       
   768 +    uint8_t *buf, size_t len, int *host_endian)
       
   769 +{
       
   770 +	/* XXX */
       
   771 +	return(sunos_get_active_config_descriptor(dev, buf, len, host_endian));
       
   772 +}
       
   773 +
       
   774 +int
       
   775 +sunos_get_configuration(struct libusb_device_handle *handle, int *config)
       
   776 +{
       
   777 +	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
       
   778 +
       
   779 +	*config = dpriv->cfgvalue;
       
   780 +
       
   781 +	usbi_dbg("bConfigurationValue %d", *config);
       
   782 +
       
   783 +	return (LIBUSB_SUCCESS);
       
   784 +}
       
   785 +
       
   786 +int
       
   787 +sunos_set_configuration(struct libusb_device_handle *handle, int config)
       
   788 +{
       
   789 +	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
       
   790 +	usbi_dbg("bConfigurationValue %d", config);
       
   791 +
       
   792 +	if (dpriv->ugenpath == NULL)
       
   793 +		return (LIBUSB_ERROR_NOT_SUPPORTED);
       
   794 +
       
   795 +	if (config < 1 || config > dpriv->dev_descr.bNumConfigurations)
       
   796 +		return (LIBUSB_ERROR_INVALID_PARAM);
       
   797 +
       
   798 +	dpriv->cfgvalue = config;
       
   799 +
       
   800 +	return (LIBUSB_SUCCESS);
       
   801 +}
       
   802 +
       
   803 +int
       
   804 +sunos_claim_interface(struct libusb_device_handle *handle, int iface)
       
   805 +{
       
   806 +	usbi_dbg("iface %d", iface);
       
   807 +	if (iface < 0) {
       
   808 +		return (LIBUSB_ERROR_INVALID_PARAM);
       
   809 +	}
       
   810 +
       
   811 +	return (LIBUSB_SUCCESS);
       
   812 +}
       
   813 +
       
   814 +int
       
   815 +sunos_release_interface(struct libusb_device_handle *handle, int iface)
       
   816 +{
       
   817 +	sunos_dev_handle_priv_t *hpriv =
       
   818 +	    (sunos_dev_handle_priv_t *)handle->os_priv;
       
   819 +
       
   820 +	usbi_dbg("iface %d", iface);
       
   821 +	if (iface < 0) {
       
   822 +		return (LIBUSB_ERROR_INVALID_PARAM);
       
   823 +	}
       
   824 +
       
   825 +	/* XXX: can we release it? */
       
   826 +	hpriv->altsetting[iface] = 0;
       
   827 +
       
   828 +	return (LIBUSB_SUCCESS);
       
   829 +}
       
   830 +
       
   831 +int
       
   832 +sunos_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
       
   833 +    int altsetting)
       
   834 +{
       
   835 +	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
       
   836 +	sunos_dev_handle_priv_t *hpriv =
       
   837 +	    (sunos_dev_handle_priv_t *)handle->os_priv;
       
   838 +
       
   839 +	usbi_dbg("iface %d, setting %d", iface, altsetting);
       
   840 +
       
   841 +	if (iface < 0 || altsetting < 0) {
       
   842 +		return (LIBUSB_ERROR_INVALID_PARAM);
       
   843 +	}
       
   844 +	if (dpriv->ugenpath == NULL)
       
   845 +		return (LIBUSB_ERROR_NOT_FOUND);
       
   846 +
       
   847 +	/* XXX: can we switch altsetting? */
       
   848 +	hpriv->altsetting[iface] = altsetting;
       
   849 +
       
   850 +	return (LIBUSB_SUCCESS);
       
   851 +}
       
   852 +
       
   853 +static void
       
   854 +usb_dump_data(unsigned char *data, size_t size)
       
   855 +{
       
   856 +	int i;
       
   857 +
       
   858 +	if (getenv("LIBUSB_DEBUG") == NULL) {
       
   859 +		return;
       
   860 +	}
       
   861 +
       
   862 +	(void) fprintf(stderr, "data dump:");
       
   863 +	for (i = 0; i < size; i++) {
       
   864 +		if (i % 16 == 0) {
       
   865 +			(void) fprintf(stderr, "\n%08x	", i);
       
   866 +		}
       
   867 +		(void) fprintf(stderr, "%02x ", (uchar_t)data[i]);
       
   868 +	}
       
   869 +	(void) fprintf(stderr, "\n");
       
   870 +}
       
   871 +
       
   872 +static void
       
   873 +sunos_async_callback(union sigval arg)
       
   874 +{
       
   875 +	struct sunos_transfer_priv *tpriv =
       
   876 +	    (struct sunos_transfer_priv *)arg.sival_ptr;
       
   877 +	struct libusb_transfer *xfer = tpriv->transfer;
       
   878 +	struct aiocb *aiocb = &tpriv->aiocb;
       
   879 +	int ret;
       
   880 +	sunos_dev_handle_priv_t *hpriv;
       
   881 +	uint8_t ep;
       
   882 +
       
   883 +	hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv;
       
   884 +	ep = sunos_usb_ep_index(xfer->endpoint);
       
   885 +
       
   886 +	ret = aio_error(aiocb);
       
   887 +	if (ret != 0) {
       
   888 +		xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd);
       
   889 +	} else {
       
   890 +		xfer->actual_length =
       
   891 +		    LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred =
       
   892 +		    aio_return(aiocb);
       
   893 +	}
       
   894 +
       
   895 +	usb_dump_data(xfer->buffer, xfer->actual_length);
       
   896 +
       
   897 +	usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length,
       
   898 +	    xfer->actual_length);
       
   899 +
       
   900 +	/* async notification */
       
   901 +	usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer));
       
   902 +	free(aiocb);
       
   903 +}
       
   904 +
       
   905 +static int
       
   906 +sunos_do_async_io(struct libusb_transfer *transfer)
       
   907 +{
       
   908 +	int ret = -1;
       
   909 +	struct aiocb *aiocb;
       
   910 +	sunos_dev_handle_priv_t *hpriv;
       
   911 +	uint8_t ep;
       
   912 +	struct sunos_transfer_priv *tpriv;
       
   913 +
       
   914 +	usbi_dbg("");
       
   915 +
       
   916 +	tpriv = usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer));
       
   917 +	hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv;
       
   918 +	ep = sunos_usb_ep_index(transfer->endpoint);
       
   919 +
       
   920 +	tpriv->transfer = transfer;
       
   921 +	aiocb = &tpriv->aiocb;
       
   922 +	bzero(aiocb, sizeof (*aiocb));
       
   923 +	aiocb->aio_fildes = hpriv->eps[ep].datafd;
       
   924 +	aiocb->aio_buf = transfer->buffer;
       
   925 +	aiocb->aio_nbytes = transfer->length;
       
   926 +	aiocb->aio_lio_opcode =
       
   927 +	    ((transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) ==
       
   928 +	    LIBUSB_ENDPOINT_IN) ? LIO_READ:LIO_WRITE;
       
   929 +	aiocb->aio_sigevent.sigev_notify = SIGEV_THREAD;
       
   930 +	aiocb->aio_sigevent.sigev_value.sival_ptr = tpriv;
       
   931 +	aiocb->aio_sigevent.sigev_notify_function = sunos_async_callback;
       
   932 +
       
   933 +	if (aiocb->aio_lio_opcode == LIO_READ) {
       
   934 +		ret = aio_read(aiocb);
       
   935 +	} else {
       
   936 +		ret = aio_write(aiocb);
       
   937 +	}
       
   938 +
       
   939 +	return (ret);
       
   940 +}
       
   941 +
       
   942 +/* return the number of bytes read/written */
       
   943 +static int
       
   944 +usb_do_io(int fd, int stat_fd, char *data, size_t size, int flag, int *status)
       
   945 +{
       
   946 +	int error;
       
   947 +	int ret = -1;
       
   948 +
       
   949 +	usbi_dbg("usb_do_io(): datafd=%d statfd=%d size=0x%x flag=%s",
       
   950 +	    fd, stat_fd, size, flag? "WRITE":"READ");
       
   951 +
       
   952 +	switch (flag) {
       
   953 +	case READ:
       
   954 +		errno = 0;
       
   955 +		ret = read(fd, data, size);
       
   956 +		usb_dump_data(data, size);
       
   957 +		break;
       
   958 +	case WRITE:
       
   959 +		usb_dump_data(data, size);
       
   960 +		errno = 0;
       
   961 +		ret = write(fd, data, size);
       
   962 +		break;
       
   963 +	}
       
   964 +
       
   965 +	usbi_dbg("usb_do_io(): amount=%d", ret);
       
   966 +
       
   967 +	if (ret < 0) {
       
   968 +		int save_errno = errno;
       
   969 +
       
   970 +		usbi_dbg("TID=%x io %s errno=%d(%s) ret=%d", pthread_self(),
       
   971 +		    flag?"WRITE":"READ", errno, strerror(errno), ret);
       
   972 +
       
   973 +		/* sunos_usb_get_status will do a read and overwrite errno */
       
   974 +		error = sunos_usb_get_status(stat_fd);
       
   975 +		usbi_dbg("io status=%d errno=%d(%s)", error,
       
   976 +			save_errno, strerror(save_errno));
       
   977 +
       
   978 +		if (status) {
       
   979 +			*status = save_errno;
       
   980 +		}
       
   981 +
       
   982 +		return (save_errno);
       
   983 +
       
   984 +	} else if (status) {
       
   985 +		*status = 0;
       
   986 +	}
       
   987 +
       
   988 +	return (ret);
       
   989 +}
       
   990 +
       
   991 +static int
       
   992 +solaris_submit_ctrl_on_default(struct libusb_transfer *transfer)
       
   993 +{
       
   994 +	int		ret = -1, setup_ret;
       
   995 +	int		status;
       
   996 +	sunos_dev_handle_priv_t *hpriv;
       
   997 +	struct		libusb_device_handle *hdl = transfer->dev_handle;
       
   998 +	uint16_t	wLength;
       
   999 +	uint8_t		*data = transfer->buffer;
       
  1000 +
       
  1001 +	hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv;
       
  1002 +	wLength = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
       
  1003 +
       
  1004 +	if (hpriv->eps[0].datafd == -1) {
       
  1005 +		usbi_dbg("ep0 not opened");
       
  1006 +
       
  1007 +		return (LIBUSB_ERROR_NOT_FOUND);
       
  1008 +	}
       
  1009 +
       
  1010 +	if ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) {
       
  1011 +		usbi_dbg("IN request");
       
  1012 +		ret = usb_do_io(hpriv->eps[0].datafd,
       
  1013 +		    hpriv->eps[0].statfd, (char *)data, LIBUSB_CONTROL_SETUP_SIZE,
       
  1014 +		    WRITE, (int *)&status);
       
  1015 +	} else {
       
  1016 +		usbi_dbg("OUT request");
       
  1017 +		ret = usb_do_io(hpriv->eps[0].datafd, hpriv->eps[0].statfd,
       
  1018 +		    transfer->buffer, transfer->length, WRITE,
       
  1019 +		    (int *)&transfer->status);
       
  1020 +	}
       
  1021 +
       
  1022 +	setup_ret = ret;
       
  1023 +	if (ret < LIBUSB_CONTROL_SETUP_SIZE) {
       
  1024 +		usbi_dbg("error sending control msg: %d", ret);
       
  1025 +
       
  1026 +		return (LIBUSB_ERROR_IO);
       
  1027 +	}
       
  1028 +
       
  1029 +	ret = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
       
  1030 +
       
  1031 +	/* Read the remaining bytes for IN request */
       
  1032 +	if ((wLength) && ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) ==
       
  1033 +	    LIBUSB_ENDPOINT_IN)) {
       
  1034 +		usbi_dbg("DATA: %d", transfer->length - setup_ret);
       
  1035 +		ret = usb_do_io(hpriv->eps[0].datafd,
       
  1036 +			hpriv->eps[0].statfd,
       
  1037 +			(char *)transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE,
       
  1038 +			wLength, READ, (int *)&transfer->status);
       
  1039 +	}
       
  1040 +
       
  1041 +	if (ret >= 0) {
       
  1042 +		transfer->actual_length = ret;
       
  1043 +		LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->transferred = ret;
       
  1044 +	}
       
  1045 +	usbi_dbg("Done: ctrl data bytes %d", ret);
       
  1046 +
       
  1047 +	/* sync transfer handling */
       
  1048 +	ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer),
       
  1049 +	    transfer->status);
       
  1050 +
       
  1051 +	return (ret);
       
  1052 +}
       
  1053 +
       
  1054 +int
       
  1055 +sunos_clear_halt(struct libusb_device_handle *handle, uint8_t endpoint)
       
  1056 +{
       
  1057 +	int ret;
       
  1058 +
       
  1059 +	usbi_dbg("endpoint=0x%02x", endpoint);
       
  1060 +
       
  1061 +	ret = libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT |
       
  1062 +	    LIBUSB_RECIPIENT_ENDPOINT | LIBUSB_REQUEST_TYPE_STANDARD,
       
  1063 +	    LIBUSB_REQUEST_CLEAR_FEATURE, 0, endpoint, NULL, 0, 1000);
       
  1064 +
       
  1065 +	usbi_dbg("ret=%d", ret);
       
  1066 +
       
  1067 +	return (ret);
       
  1068 +}
       
  1069 +
       
  1070 +int
       
  1071 +sunos_reset_device(struct libusb_device_handle *handle)
       
  1072 +{
       
  1073 +	usbi_dbg("");
       
  1074 +
       
  1075 +	return (LIBUSB_ERROR_NOT_SUPPORTED);
       
  1076 +}
       
  1077 +
       
  1078 +void
       
  1079 +sunos_destroy_device(struct libusb_device *dev)
       
  1080 +{
       
  1081 +	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
       
  1082 +
       
  1083 +	usbi_dbg("");
       
  1084 +
       
  1085 +	free(dpriv->raw_cfgdescr);
       
  1086 +	free(dpriv->ugenpath);
       
  1087 +	free(dpriv->phypath);
       
  1088 +}
       
  1089 +
       
  1090 +int
       
  1091 +sunos_submit_transfer(struct usbi_transfer *itransfer)
       
  1092 +{
       
  1093 +	struct	libusb_transfer *transfer;
       
  1094 +	struct	libusb_device_handle *hdl;
       
  1095 +	int	err = 0;
       
  1096 +
       
  1097 +	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
       
  1098 +	hdl = transfer->dev_handle;
       
  1099 +
       
  1100 +	err = sunos_check_device_and_status_open(hdl,
       
  1101 +	    transfer->endpoint, transfer->type);
       
  1102 +	if (err < 0) {
       
  1103 +
       
  1104 +		return (_errno_to_libusb(err));
       
  1105 +	}
       
  1106 +
       
  1107 +	switch (transfer->type) {
       
  1108 +	case LIBUSB_TRANSFER_TYPE_CONTROL:
       
  1109 +		/* sync transfer */
       
  1110 +		usbi_dbg("CTRL transfer: %d", transfer->length);
       
  1111 +		err = solaris_submit_ctrl_on_default(transfer);
       
  1112 +		break;
       
  1113 +
       
  1114 +	case LIBUSB_TRANSFER_TYPE_BULK:
       
  1115 +		/* fallthru */
       
  1116 +	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
       
  1117 +		if (transfer->type == LIBUSB_TRANSFER_TYPE_BULK)
       
  1118 +			usbi_dbg("BULK transfer: %d", transfer->length);
       
  1119 +		else
       
  1120 +			usbi_dbg("INTR transfer: %d", transfer->length);
       
  1121 +		err = sunos_do_async_io(transfer);
       
  1122 +		break;
       
  1123 +
       
  1124 +	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
       
  1125 +		/* Isochronous/Stream is not supported */
       
  1126 +
       
  1127 +		/* fallthru */
       
  1128 +	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
       
  1129 +		if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS)
       
  1130 +			usbi_dbg("ISOC transfer: %d", transfer->length);
       
  1131 +		else
       
  1132 +			usbi_dbg("BULK STREAM transfer: %d", transfer->length);
       
  1133 +		err = LIBUSB_ERROR_NOT_SUPPORTED;
       
  1134 +		break;
       
  1135 +	}
       
  1136 +
       
  1137 +	return (err);
       
  1138 +}
       
  1139 +
       
  1140 +int
       
  1141 +sunos_cancel_transfer(struct usbi_transfer *itransfer)
       
  1142 +{
       
  1143 +	sunos_xfer_priv_t	*tpriv;
       
  1144 +	sunos_dev_handle_priv_t	*hpriv;
       
  1145 +	struct libusb_transfer	*transfer;
       
  1146 +	struct aiocb	*aiocb;
       
  1147 +	uint8_t		ep;
       
  1148 +	int		ret;
       
  1149 +
       
  1150 +	tpriv = usbi_transfer_get_os_priv(itransfer);
       
  1151 +	aiocb = &tpriv->aiocb;
       
  1152 +	transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
       
  1153 +	hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv;
       
  1154 +	ep = sunos_usb_ep_index(transfer->endpoint);
       
  1155 +
       
  1156 +	ret = aio_cancel(hpriv->eps[ep].datafd, aiocb);
       
  1157 +
       
  1158 +	usbi_dbg("aio->fd=%d fd=%d ret = %d, %s", aiocb->aio_fildes,
       
  1159 +	    hpriv->eps[ep].datafd, ret, (ret == AIO_CANCELED)?
       
  1160 +	    strerror(0):strerror(errno));
       
  1161 +
       
  1162 +	if (ret != AIO_CANCELED) {
       
  1163 +		ret = _errno_to_libusb(errno);
       
  1164 +	} else {
       
  1165 +	/*
       
  1166 +	 * we don't need to call usbi_handle_transfer_cancellation(),
       
  1167 +	 * because we'll handle everything in sunos_async_callback.
       
  1168 +	 */
       
  1169 +		ret = LIBUSB_SUCCESS;
       
  1170 +	}
       
  1171 +
       
  1172 +	return (ret);
       
  1173 +}
       
  1174 +
       
  1175 +void
       
  1176 +sunos_clear_transfer_priv(struct usbi_transfer *itransfer)
       
  1177 +{
       
  1178 +	usbi_dbg("");
       
  1179 +
       
  1180 +	/* Nothing to do */
       
  1181 +}
       
  1182 +
       
  1183 +int
       
  1184 +sunos_handle_transfer_completion(struct usbi_transfer *itransfer)
       
  1185 +{
       
  1186 +	return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
       
  1187 +}
       
  1188 +
       
  1189 +int
       
  1190 +sunos_clock_gettime(int clkid, struct timespec *tp)
       
  1191 +{
       
  1192 +	usbi_dbg("clock %d", clkid);
       
  1193 +
       
  1194 +	if (clkid == USBI_CLOCK_REALTIME)
       
  1195 +		return clock_gettime(CLOCK_REALTIME, tp);
       
  1196 +
       
  1197 +	if (clkid == USBI_CLOCK_MONOTONIC)
       
  1198 +		return clock_gettime(CLOCK_MONOTONIC, tp);
       
  1199 +
       
  1200 +	return (LIBUSB_ERROR_INVALID_PARAM);
       
  1201 +}
       
  1202 +
       
  1203 +int
       
  1204 +_errno_to_libusb(int err)
       
  1205 +{
       
  1206 +	usbi_dbg("error: %s (%d)", strerror(err), err);
       
  1207 +
       
  1208 +	switch (err) {
       
  1209 +	case EIO:
       
  1210 +		return (LIBUSB_ERROR_IO);
       
  1211 +	case EACCES:
       
  1212 +		return (LIBUSB_ERROR_ACCESS);
       
  1213 +	case ENOENT:
       
  1214 +		return (LIBUSB_ERROR_NO_DEVICE);
       
  1215 +	case ENOMEM:
       
  1216 +		return (LIBUSB_ERROR_NO_MEM);
       
  1217 +	case ETIMEDOUT:
       
  1218 +		return (LIBUSB_ERROR_TIMEOUT);
       
  1219 +	}
       
  1220 +
       
  1221 +	return (LIBUSB_ERROR_OTHER);
       
  1222 +}
       
  1223 +
       
  1224 +/*
       
  1225 + * sunos_usb_get_status:
       
  1226 + *	gets status of endpoint
       
  1227 + *
       
  1228 + * Returns: ugen's last cmd status
       
  1229 + */
       
  1230 +static int
       
  1231 +sunos_usb_get_status(int fd)
       
  1232 +{
       
  1233 +	int status, ret;
       
  1234 +
       
  1235 +	usbi_dbg("sunos_usb_get_status(): fd=%d", fd);
       
  1236 +
       
  1237 +	ret = read(fd, &status, sizeof (status));
       
  1238 +	if (ret == sizeof (status)) {
       
  1239 +		switch (status) {
       
  1240 +		case USB_LC_STAT_NOERROR:
       
  1241 +			usbi_dbg("No Error");
       
  1242 +			break;
       
  1243 +		case USB_LC_STAT_CRC:
       
  1244 +			usbi_dbg("CRC Timeout Detected\n");
       
  1245 +			break;
       
  1246 +		case USB_LC_STAT_BITSTUFFING:
       
  1247 +			usbi_dbg("Bit Stuffing Violation\n");
       
  1248 +			break;
       
  1249 +		case USB_LC_STAT_DATA_TOGGLE_MM:
       
  1250 +			usbi_dbg("Data Toggle Mismatch\n");
       
  1251 +			break;
       
  1252 +		case USB_LC_STAT_STALL:
       
  1253 +			usbi_dbg("End Point Stalled\n");
       
  1254 +			break;
       
  1255 +		case USB_LC_STAT_DEV_NOT_RESP:
       
  1256 +			usbi_dbg("Device is Not Responding\n");
       
  1257 +			break;
       
  1258 +		case USB_LC_STAT_PID_CHECKFAILURE:
       
  1259 +			usbi_dbg("PID Check Failure\n");
       
  1260 +			break;
       
  1261 +		case USB_LC_STAT_UNEXP_PID:
       
  1262 +			usbi_dbg("Unexpected PID\n");
       
  1263 +			break;
       
  1264 +		case USB_LC_STAT_DATA_OVERRUN:
       
  1265 +			usbi_dbg("Data Exceeded Size\n");
       
  1266 +			break;
       
  1267 +		case USB_LC_STAT_DATA_UNDERRUN:
       
  1268 +			usbi_dbg("Less data received\n");
       
  1269 +			break;
       
  1270 +		case USB_LC_STAT_BUFFER_OVERRUN:
       
  1271 +			usbi_dbg("Buffer Size Exceeded\n");
       
  1272 +			break;
       
  1273 +		case USB_LC_STAT_BUFFER_UNDERRUN:
       
  1274 +			usbi_dbg("Buffer Underrun\n");
       
  1275 +			break;
       
  1276 +		case USB_LC_STAT_TIMEOUT:
       
  1277 +			usbi_dbg("Command Timed Out\n");
       
  1278 +			break;
       
  1279 +		case USB_LC_STAT_NOT_ACCESSED:
       
  1280 +			usbi_dbg("Not Accessed by h/w\n");
       
  1281 +			break;
       
  1282 +		case USB_LC_STAT_UNSPECIFIED_ERR:
       
  1283 +			usbi_dbg("Unspecified Error\n");
       
  1284 +			break;
       
  1285 +		case USB_LC_STAT_NO_BANDWIDTH:
       
  1286 +			usbi_dbg("No Bandwidth\n");
       
  1287 +			break;
       
  1288 +		case USB_LC_STAT_HW_ERR:
       
  1289 +			usbi_dbg("Host Controller h/w Error\n");
       
  1290 +			break;
       
  1291 +		case USB_LC_STAT_SUSPENDED:
       
  1292 +			usbi_dbg("Device was Suspended\n");
       
  1293 +			break;
       
  1294 +		case USB_LC_STAT_DISCONNECTED:
       
  1295 +			usbi_dbg("Device was Disconnected\n");
       
  1296 +			break;
       
  1297 +		case USB_LC_STAT_INTR_BUF_FULL:
       
  1298 +			usbi_dbg("Interrupt buffer was full\n");
       
  1299 +			break;
       
  1300 +		case USB_LC_STAT_INVALID_REQ:
       
  1301 +			usbi_dbg("Request was Invalid\n");
       
  1302 +			break;
       
  1303 +		case USB_LC_STAT_INTERRUPTED:
       
  1304 +			usbi_dbg("Request was Interrupted\n");
       
  1305 +			break;
       
  1306 +		case USB_LC_STAT_NO_RESOURCES:
       
  1307 +			usbi_dbg("No resources available for "
       
  1308 +			    "request\n");
       
  1309 +			break;
       
  1310 +		case USB_LC_STAT_INTR_POLLING_FAILED:
       
  1311 +			usbi_dbg("Failed to Restart Poll");
       
  1312 +			break;
       
  1313 +		default:
       
  1314 +			usbi_dbg("Error Not Determined %d\n",
       
  1315 +			    status);
       
  1316 +			break;
       
  1317 +		}
       
  1318 +	} else {
       
  1319 +		usbi_dbg("read stat error: %s",strerror(errno));
       
  1320 +		status = -1;
       
  1321 +	}
       
  1322 +
       
  1323 +	return (status);
       
  1324 +}
       
  1325 +
       
  1326 +const struct usbi_os_backend sunos_backend = {
       
  1327 +        .name = "Solaris",
       
  1328 +        .caps = 0,
       
  1329 +        .init = sunos_init,
       
  1330 +        .exit = sunos_exit,
       
  1331 +        .get_device_list = sunos_get_device_list,
       
  1332 +        .get_device_descriptor = sunos_get_device_descriptor,
       
  1333 +        .get_active_config_descriptor = sunos_get_active_config_descriptor,
       
  1334 +        .get_config_descriptor = sunos_get_config_descriptor,
       
  1335 +        .hotplug_poll = NULL,
       
  1336 +        .open = sunos_open,
       
  1337 +        .close = sunos_close,
       
  1338 +        .get_configuration = sunos_get_configuration,
       
  1339 +        .set_configuration = sunos_set_configuration,
       
  1340 +
       
  1341 +        .claim_interface = sunos_claim_interface,
       
  1342 +        .release_interface = sunos_release_interface,
       
  1343 +        .set_interface_altsetting = sunos_set_interface_altsetting,
       
  1344 +        .clear_halt = sunos_clear_halt,
       
  1345 +        .reset_device = sunos_reset_device, /* TODO */
       
  1346 +        .alloc_streams = NULL,
       
  1347 +        .free_streams = NULL,
       
  1348 +        .kernel_driver_active = NULL,
       
  1349 +        .detach_kernel_driver = NULL,
       
  1350 +        .attach_kernel_driver = NULL,
       
  1351 +        .destroy_device = sunos_destroy_device,
       
  1352 +        .submit_transfer = sunos_submit_transfer,
       
  1353 +        .cancel_transfer = sunos_cancel_transfer,
       
  1354 +	.handle_events = NULL,
       
  1355 +        .clear_transfer_priv = sunos_clear_transfer_priv,
       
  1356 +        .handle_transfer_completion = sunos_handle_transfer_completion,
       
  1357 +        .clock_gettime = sunos_clock_gettime,
       
  1358 +        .device_priv_size = sizeof(sunos_dev_priv_t),
       
  1359 +        .device_handle_priv_size = sizeof(sunos_dev_handle_priv_t),
       
  1360 +        .transfer_priv_size = sizeof(sunos_xfer_priv_t),
       
  1361 +};
       
  1362 diff -Naur libusb-1.0.20/libusb/os/sunos_usb.h libusb-1.0.20.new/libusb/os/sunos_usb.h
       
  1363 --- libusb-1.0.20/libusb/os/sunos_usb.h	1969-12-31 16:00:00.000000000 -0800
       
  1364 +++ libusb-1.0.20.new/libusb/os/sunos_usb.h	2016-03-10 00:24:37.910437590 -0800
       
  1365 @@ -0,0 +1,74 @@
       
  1366 +/*
       
  1367 + *
       
  1368 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
       
  1369 + *
       
  1370 + * This library is free software; you can redistribute it and/or
       
  1371 + * modify it under the terms of the GNU Lesser General Public
       
  1372 + * License as published by the Free Software Foundation; either
       
  1373 + * version 2.1 of the License, or (at your option) any later version.
       
  1374 + *
       
  1375 + * This library is distributed in the hope that it will be useful,
       
  1376 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
  1377 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
  1378 + * Lesser General Public License for more details.
       
  1379 + *
       
  1380 + * You should have received a copy of the GNU Lesser General Public
       
  1381 + * License along with this library; if not, write to the Free Software
       
  1382 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
       
  1383 + */
       
  1384 +
       
  1385 +#ifndef	__SUNOS_H__
       
  1386 +#define	__SUNOS_H__
       
  1387 +
       
  1388 +#include <libdevinfo.h>
       
  1389 +#include <pthread.h>
       
  1390 +#include "libusbi.h"
       
  1391 +
       
  1392 +#define	READ	0
       
  1393 +#define	WRITE	1
       
  1394 +
       
  1395 +typedef struct sunos_device_priv {
       
  1396 +	uint8_t	cfgvalue;		/* active config value */
       
  1397 +	uint8_t	*raw_cfgdescr;		/* active config descriptor */
       
  1398 +	struct libusb_device_descriptor	dev_descr;	/* usb device descriptor */
       
  1399 +	char	*ugenpath;		/* name of the ugen(4) node */
       
  1400 +	char	*phypath;		/* physical path */
       
  1401 +} sunos_dev_priv_t;
       
  1402 +
       
  1403 +typedef	struct endpoint {
       
  1404 +	int datafd;	/* data file */
       
  1405 +	int statfd;	/* state file */
       
  1406 +} sunos_ep_priv_t;
       
  1407 +
       
  1408 +typedef struct sunos_device_handle_priv {
       
  1409 +	uint8_t			altsetting[USB_MAXINTERFACES];	/* a interface's alt */
       
  1410 +	uint8_t			config_index;
       
  1411 +	sunos_ep_priv_t		eps[USB_MAXENDPOINTS];
       
  1412 +	sunos_dev_priv_t	*dpriv; /* device private */
       
  1413 +} sunos_dev_handle_priv_t;
       
  1414 +
       
  1415 +typedef	struct sunos_transfer_priv {
       
  1416 +	struct aiocb		aiocb;
       
  1417 +	struct libusb_transfer	*transfer;
       
  1418 +} sunos_xfer_priv_t;
       
  1419 +
       
  1420 +struct node_args {
       
  1421 +	struct libusb_context	*ctx;
       
  1422 +	struct discovered_devs	**discdevs;
       
  1423 +	const char		*last_ugenpath;
       
  1424 +	di_devlink_handle_t	dlink_hdl;
       
  1425 +};
       
  1426 +
       
  1427 +struct devlink_cbarg {
       
  1428 +	struct node_args	*nargs;	/* di node walk arguments */
       
  1429 +	di_node_t		myself;	/* the di node */
       
  1430 +	di_minor_t		minor;
       
  1431 +};
       
  1432 +
       
  1433 +/* AIO callback args */
       
  1434 +struct aio_callback_args{
       
  1435 +	struct libusb_transfer *transfer;
       
  1436 +	struct aiocb aiocb;
       
  1437 +};
       
  1438 +
       
  1439 +#endif /* __SUNOS_H__ */
       
  1440 diff -Naur libusb-1.0.20/libusb-1.0.pc.in libusb-1.0.20.new/libusb-1.0.pc.in
       
  1441 --- libusb-1.0.20/libusb-1.0.pc.in	2015-07-28 22:18:38.000000000 -0700
       
  1442 +++ libusb-1.0.20.new/libusb-1.0.pc.in	2016-03-10 00:17:29.567059098 -0800
       
  1443 @@ -4,7 +4,7 @@
       
  1444  includedir=@includedir@
       
  1445  
       
  1446  Name: libusb-1.0
       
  1447 -Description: C API for USB device access from Linux, Mac OS X, Windows and OpenBSD/NetBSD userspace
       
  1448 +Description: C API for USB device access from Linux, Mac OS X, Windows, OpenBSD/NetBSD and Solaris userspace
       
  1449  Version: @VERSION@
       
  1450  Libs: -L${libdir} -lusb-1.0
       
  1451  Libs.private: @LIBS@