|
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 **)®buf); |
|
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@ |