usb 1.7.2 → 1.8.0-libusb.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitmodules +1 -1
- package/Readme.md +2 -2
- package/binding.gyp +2 -2
- package/libusb/.private/pre-commit.sh +7 -1
- package/libusb/.travis.yml +49 -0
- package/libusb/AUTHORS +44 -3
- package/libusb/Brewfile +4 -0
- package/libusb/ChangeLog +74 -2
- package/libusb/README.md +32 -0
- package/libusb/TODO +1 -1
- package/libusb/Xcode/common.xcconfig +12 -0
- package/libusb/Xcode/config.h +25 -0
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +959 -1
- package/libusb/android/README +4 -2
- package/libusb/android/config.h +75 -0
- package/libusb/appveyor.yml +41 -0
- package/libusb/appveyor_cygwin.bat +11 -0
- package/libusb/appveyor_minGW.bat +19 -0
- package/libusb/autogen.sh +1 -1
- package/libusb/bootstrap.sh +3 -16
- package/libusb/configure.ac +108 -80
- package/libusb/doc/doxygen.cfg.in +1785 -739
- package/libusb/examples/Makefile.am +1 -1
- package/libusb/examples/dpfp.c +3 -1
- package/libusb/examples/dpfp_threaded.c +23 -10
- package/libusb/examples/ezusb.c +3 -3
- package/libusb/examples/ezusb.h +2 -2
- package/libusb/examples/fxload.c +31 -9
- package/libusb/examples/hotplugtest.c +35 -7
- package/libusb/examples/listdevs.c +3 -1
- package/libusb/examples/sam3u_benchmark.c +3 -3
- package/libusb/examples/testlibusb.c +277 -0
- package/libusb/examples/xusb.c +40 -34
- package/libusb/libusb/Makefile.am +49 -23
- package/libusb/libusb/core.c +855 -457
- package/libusb/libusb/descriptor.c +72 -78
- package/libusb/libusb/hotplug.c +122 -76
- package/libusb/libusb/hotplug.h +42 -25
- package/libusb/libusb/io.c +625 -390
- package/libusb/libusb/libusb-1.0.def +12 -0
- package/libusb/libusb/libusb.h +218 -150
- package/libusb/libusb/libusbi.h +346 -176
- package/libusb/libusb/os/darwin_usb.c +604 -319
- package/libusb/libusb/os/darwin_usb.h +61 -20
- package/libusb/libusb/os/haiku_pollfs.cpp +367 -0
- package/libusb/libusb/os/haiku_usb.h +113 -0
- package/libusb/libusb/os/haiku_usb_backend.cpp +533 -0
- package/libusb/libusb/os/haiku_usb_raw.cpp +267 -0
- package/libusb/libusb/os/haiku_usb_raw.h +188 -0
- package/libusb/libusb/os/linux_netlink.c +186 -146
- package/libusb/libusb/os/linux_udev.c +36 -14
- package/libusb/libusb/os/linux_usbfs.c +426 -225
- package/libusb/libusb/os/linux_usbfs.h +5 -3
- package/libusb/libusb/os/netbsd_usb.c +21 -77
- package/libusb/libusb/os/openbsd_usb.c +32 -115
- package/libusb/libusb/os/poll_posix.c +38 -5
- package/libusb/libusb/os/poll_posix.h +3 -0
- package/libusb/libusb/os/poll_windows.c +277 -626
- package/libusb/libusb/os/poll_windows.h +11 -44
- package/libusb/libusb/os/sunos_usb.c +1695 -0
- package/libusb/libusb/os/sunos_usb.h +80 -0
- package/libusb/libusb/os/threads_posix.c +24 -26
- package/libusb/libusb/os/threads_posix.h +73 -21
- package/libusb/libusb/os/threads_windows.c +71 -157
- package/libusb/libusb/os/threads_windows.h +68 -44
- package/libusb/libusb/os/wince_usb.c +276 -420
- package/libusb/libusb/os/wince_usb.h +23 -28
- package/libusb/libusb/os/windows_common.h +78 -58
- package/libusb/libusb/os/windows_nt_common.c +1010 -0
- package/libusb/libusb/os/windows_nt_common.h +110 -0
- package/libusb/libusb/os/windows_nt_shared_types.h +147 -0
- package/libusb/libusb/os/windows_usbdk.c +830 -0
- package/libusb/libusb/os/windows_usbdk.h +103 -0
- package/libusb/libusb/os/windows_winusb.c +4391 -0
- package/libusb/libusb/os/windows_winusb.h +783 -0
- package/libusb/libusb/strerror.c +41 -7
- package/libusb/libusb/sync.c +41 -13
- package/libusb/libusb/version.h +1 -1
- package/libusb/libusb/version_nano.h +1 -1
- package/libusb/libusb-1.0.pc.in +1 -1
- package/libusb/msvc/appveyor.bat +27 -0
- package/libusb/msvc/config.h +5 -4
- package/libusb/msvc/ddk_build.cmd +87 -43
- package/libusb/msvc/fxload_2010.vcxproj +24 -104
- package/libusb/msvc/fxload_2012.vcxproj +24 -107
- package/libusb/msvc/fxload_2013.vcxproj +24 -107
- package/libusb/msvc/fxload_2015.vcxproj +91 -0
- package/libusb/msvc/fxload_2017.vcxproj +114 -0
- package/libusb/msvc/fxload_sources +1 -1
- package/libusb/msvc/getopt_2010.vcxproj +16 -75
- package/libusb/msvc/getopt_2012.vcxproj +16 -79
- package/libusb/msvc/getopt_2013.vcxproj +16 -79
- package/libusb/msvc/getopt_2015.vcxproj +73 -0
- package/libusb/msvc/getopt_2017.vcxproj +98 -0
- package/libusb/msvc/getopt_sources +6 -2
- package/libusb/msvc/hotplugtest_2010.vcxproj +18 -99
- package/libusb/msvc/hotplugtest_2012.vcxproj +18 -102
- package/libusb/msvc/hotplugtest_2013.vcxproj +18 -102
- package/libusb/msvc/hotplugtest_2015.vcxproj +83 -0
- package/libusb/msvc/hotplugtest_2017.vcxproj +106 -0
- package/libusb/msvc/hotplugtest_sources +1 -1
- package/libusb/msvc/libusb_2005.sln +20 -20
- package/libusb/msvc/libusb_2010.sln +57 -46
- package/libusb/msvc/libusb_2012.sln +57 -46
- package/libusb/msvc/libusb_2013.sln +57 -50
- package/libusb/msvc/libusb_2015.sln +59 -52
- package/libusb/msvc/libusb_2017.sln +186 -0
- package/libusb/msvc/libusb_dll.dsp +2 -2
- package/libusb/msvc/libusb_dll_2005.vcproj +30 -2
- package/libusb/msvc/libusb_dll_2010.vcxproj +26 -90
- package/libusb/msvc/libusb_dll_2012.vcxproj +28 -96
- package/libusb/msvc/libusb_dll_2013.vcxproj +28 -96
- package/libusb/msvc/libusb_dll_2015.vcxproj +107 -0
- package/libusb/msvc/libusb_dll_2017.vcxproj +134 -0
- package/libusb/msvc/libusb_dll_wince.vcproj +9 -1
- package/libusb/msvc/libusb_sources +10 -5
- package/libusb/msvc/libusb_static.dsp +2 -2
- package/libusb/msvc/libusb_static_2005.vcproj +32 -4
- package/libusb/msvc/libusb_static_2010.vcxproj +24 -83
- package/libusb/msvc/libusb_static_2012.vcxproj +25 -87
- package/libusb/msvc/libusb_static_2013.vcxproj +25 -87
- package/libusb/msvc/libusb_static_2015.vcxproj +98 -0
- package/libusb/msvc/libusb_static_2017.vcxproj +117 -0
- package/libusb/msvc/libusb_static_wince.vcproj +20 -26
- package/libusb/msvc/libusb_wince.sln +88 -88
- package/libusb/msvc/listdevs_2010.vcxproj +16 -99
- package/libusb/msvc/listdevs_2012.vcxproj +16 -102
- package/libusb/msvc/listdevs_2013.vcxproj +16 -102
- package/libusb/msvc/listdevs_2015.vcxproj +83 -0
- package/libusb/msvc/listdevs_2017.vcxproj +106 -0
- package/libusb/msvc/listdevs_sources +2 -1
- package/libusb/msvc/stress_2010.vcxproj +20 -101
- package/libusb/msvc/stress_2012.vcxproj +20 -104
- package/libusb/msvc/stress_2013.vcxproj +20 -104
- package/libusb/msvc/stress_2015.vcxproj +87 -0
- package/libusb/msvc/stress_2017.vcxproj +110 -0
- package/libusb/msvc/stress_sources +21 -0
- package/libusb/msvc/testlibusb_2010.vcxproj +82 -0
- package/libusb/msvc/testlibusb_2012.vcxproj +83 -0
- package/libusb/msvc/testlibusb_2013.vcxproj +83 -0
- package/libusb/msvc/testlibusb_2015.vcxproj +83 -0
- package/libusb/msvc/testlibusb_2017.vcxproj +106 -0
- package/libusb/msvc/testlibusb_sources +20 -0
- package/libusb/msvc/xusb_2010.vcxproj +17 -98
- package/libusb/msvc/xusb_2012.vcxproj +17 -101
- package/libusb/msvc/xusb_2013.vcxproj +17 -101
- package/libusb/msvc/xusb_2015.vcxproj +83 -0
- package/libusb/msvc/xusb_2017.vcxproj +106 -0
- package/libusb/msvc/xusb_sources +1 -1
- package/libusb/tests/stress.c +2 -2
- package/libusb/tests/testlib.c +0 -4
- package/libusb/travis-autogen.sh +39 -0
- package/libusb.gypi +13 -2
- package/package.json +20 -11
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-ia32/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/device.cc +1 -1
- package/usb.js +1 -1
- package/.github/workflows/prebuild.yml +0 -49
- package/libusb/INSTALL +0 -234
- package/libusb/README +0 -28
- package/libusb/libusb/os/windows_usb.c +0 -5347
- package/libusb/libusb/os/windows_usb.h +0 -971
- package/libusb/msvc/fxload_2010.vcxproj.filters +0 -25
- package/libusb/msvc/fxload_2012.vcxproj.filters +0 -25
- package/libusb/msvc/getopt_2010.vcxproj.filters +0 -26
- package/libusb/msvc/getopt_2012.vcxproj.filters +0 -26
- package/libusb/msvc/hotplugtest_2010.vcxproj.filters +0 -14
- package/libusb/msvc/hotplugtest_2012.vcxproj.filters +0 -14
- package/libusb/msvc/libusb_dll_2010.vcxproj.filters +0 -81
- package/libusb/msvc/libusb_dll_2012.vcxproj.filters +0 -84
- package/libusb/msvc/libusb_static_2010.vcxproj.filters +0 -74
- package/libusb/msvc/libusb_static_2012.vcxproj.filters +0 -74
- package/libusb/msvc/listdevs_2010.vcxproj.filters +0 -14
- package/libusb/msvc/listdevs_2012.vcxproj.filters +0 -14
- package/libusb/msvc/stress_2010.vcxproj.filters +0 -25
- package/libusb/msvc/stress_2012.vcxproj.filters +0 -25
- package/libusb/msvc/xusb_2010.vcxproj.filters +0 -14
- package/libusb/msvc/xusb_2012.vcxproj.filters +0 -14
|
@@ -0,0 +1,1695 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* Copyright (c) 2016, Oracle and/or its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This library is free software; you can redistribute it and/or
|
|
6
|
+
* modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
* License as published by the Free Software Foundation; either
|
|
8
|
+
* version 2.1 of the License, or (at your option) any later version.
|
|
9
|
+
*
|
|
10
|
+
* This library is distributed in the hope that it will be useful,
|
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
* Lesser General Public License for more details.
|
|
14
|
+
*
|
|
15
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
16
|
+
* License along with this library; if not, write to the Free Software
|
|
17
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
#include <config.h>
|
|
21
|
+
|
|
22
|
+
#include <sys/time.h>
|
|
23
|
+
#include <sys/types.h>
|
|
24
|
+
#include <sys/list.h>
|
|
25
|
+
#include <sys/stat.h>
|
|
26
|
+
#include <strings.h>
|
|
27
|
+
#include <errno.h>
|
|
28
|
+
#include <fcntl.h>
|
|
29
|
+
#include <stdio.h>
|
|
30
|
+
#include <stdlib.h>
|
|
31
|
+
#include <string.h>
|
|
32
|
+
#include <wait.h>
|
|
33
|
+
#include <unistd.h>
|
|
34
|
+
#include <aio.h>
|
|
35
|
+
#include <libdevinfo.h>
|
|
36
|
+
#include <sys/nvpair.h>
|
|
37
|
+
#include <sys/devctl.h>
|
|
38
|
+
#include <sys/usb/clients/ugen/usb_ugen.h>
|
|
39
|
+
#include <errno.h>
|
|
40
|
+
#include <sys/usb/usba.h>
|
|
41
|
+
#include <sys/pci.h>
|
|
42
|
+
|
|
43
|
+
#include "libusbi.h"
|
|
44
|
+
#include "sunos_usb.h"
|
|
45
|
+
|
|
46
|
+
#define UPDATEDRV_PATH "/usr/sbin/update_drv"
|
|
47
|
+
#define UPDATEDRV "update_drv"
|
|
48
|
+
|
|
49
|
+
typedef list_t string_list_t;
|
|
50
|
+
typedef struct string_node {
|
|
51
|
+
char *string;
|
|
52
|
+
list_node_t link;
|
|
53
|
+
} string_node_t;
|
|
54
|
+
|
|
55
|
+
/*
|
|
56
|
+
* Backend functions
|
|
57
|
+
*/
|
|
58
|
+
static int sunos_init(struct libusb_context *);
|
|
59
|
+
static void sunos_exit(struct libusb_context *);
|
|
60
|
+
static int sunos_get_device_list(struct libusb_context *,
|
|
61
|
+
struct discovered_devs **);
|
|
62
|
+
static int sunos_open(struct libusb_device_handle *);
|
|
63
|
+
static void sunos_close(struct libusb_device_handle *);
|
|
64
|
+
static int sunos_get_device_descriptor(struct libusb_device *,
|
|
65
|
+
uint8_t*, int *);
|
|
66
|
+
static int sunos_get_active_config_descriptor(struct libusb_device *,
|
|
67
|
+
uint8_t*, size_t, int *);
|
|
68
|
+
static int sunos_get_config_descriptor(struct libusb_device *, uint8_t,
|
|
69
|
+
uint8_t*, size_t, int *);
|
|
70
|
+
static int sunos_get_configuration(struct libusb_device_handle *, int *);
|
|
71
|
+
static int sunos_set_configuration(struct libusb_device_handle *, int);
|
|
72
|
+
static int sunos_claim_interface(struct libusb_device_handle *, int);
|
|
73
|
+
static int sunos_release_interface(struct libusb_device_handle *, int);
|
|
74
|
+
static int sunos_set_interface_altsetting(struct libusb_device_handle *,
|
|
75
|
+
int, int);
|
|
76
|
+
static int sunos_clear_halt(struct libusb_device_handle *, uint8_t);
|
|
77
|
+
static int sunos_reset_device(struct libusb_device_handle *);
|
|
78
|
+
static void sunos_destroy_device(struct libusb_device *);
|
|
79
|
+
static int sunos_submit_transfer(struct usbi_transfer *);
|
|
80
|
+
static int sunos_cancel_transfer(struct usbi_transfer *);
|
|
81
|
+
static void sunos_clear_transfer_priv(struct usbi_transfer *);
|
|
82
|
+
static int sunos_handle_transfer_completion(struct usbi_transfer *);
|
|
83
|
+
static int sunos_clock_gettime(int, struct timespec *);
|
|
84
|
+
static int sunos_kernel_driver_active(struct libusb_device_handle *, int interface);
|
|
85
|
+
static int sunos_detach_kernel_driver (struct libusb_device_handle *dev, int interface_number);
|
|
86
|
+
static int sunos_attach_kernel_driver (struct libusb_device_handle *dev, int interface_number);
|
|
87
|
+
static int sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv);
|
|
88
|
+
static int sunos_usb_ioctl(struct libusb_device *dev, int cmd);
|
|
89
|
+
|
|
90
|
+
static struct devctl_iocdata iocdata;
|
|
91
|
+
static int sunos_get_link(di_devlink_t devlink, void *arg)
|
|
92
|
+
{
|
|
93
|
+
walk_link_t *larg = (walk_link_t *)arg;
|
|
94
|
+
const char *p;
|
|
95
|
+
const char *q;
|
|
96
|
+
|
|
97
|
+
if (larg->path) {
|
|
98
|
+
char *content = (char *)di_devlink_content(devlink);
|
|
99
|
+
char *start = strstr(content, "/devices/");
|
|
100
|
+
start += strlen("/devices");
|
|
101
|
+
usbi_dbg("%s", start);
|
|
102
|
+
|
|
103
|
+
/* line content must have minor node */
|
|
104
|
+
if (start == NULL ||
|
|
105
|
+
strncmp(start, larg->path, larg->len) != 0 ||
|
|
106
|
+
start[larg->len] != ':')
|
|
107
|
+
return (DI_WALK_CONTINUE);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
p = di_devlink_path(devlink);
|
|
111
|
+
q = strrchr(p, '/');
|
|
112
|
+
usbi_dbg("%s", q);
|
|
113
|
+
|
|
114
|
+
*(larg->linkpp) = strndup(p, strlen(p) - strlen(q));
|
|
115
|
+
|
|
116
|
+
return (DI_WALK_TERMINATE);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
static int sunos_physpath_to_devlink(
|
|
121
|
+
const char *node_path, const char *match, char **link_path)
|
|
122
|
+
{
|
|
123
|
+
walk_link_t larg;
|
|
124
|
+
di_devlink_handle_t hdl;
|
|
125
|
+
|
|
126
|
+
*link_path = NULL;
|
|
127
|
+
larg.linkpp = link_path;
|
|
128
|
+
if ((hdl = di_devlink_init(NULL, 0)) == NULL) {
|
|
129
|
+
usbi_dbg("di_devlink_init failure");
|
|
130
|
+
return (-1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
larg.len = strlen(node_path);
|
|
134
|
+
larg.path = (char *)node_path;
|
|
135
|
+
|
|
136
|
+
(void) di_devlink_walk(hdl, match, NULL, DI_PRIMARY_LINK,
|
|
137
|
+
(void *)&larg, sunos_get_link);
|
|
138
|
+
|
|
139
|
+
(void) di_devlink_fini(&hdl);
|
|
140
|
+
|
|
141
|
+
if (*link_path == NULL) {
|
|
142
|
+
usbi_dbg("there is no devlink for this path");
|
|
143
|
+
return (-1);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return 0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
static int
|
|
150
|
+
sunos_usb_ioctl(struct libusb_device *dev, int cmd)
|
|
151
|
+
{
|
|
152
|
+
int fd;
|
|
153
|
+
nvlist_t *nvlist;
|
|
154
|
+
char *end;
|
|
155
|
+
char *phypath;
|
|
156
|
+
char *hubpath;
|
|
157
|
+
char path_arg[PATH_MAX];
|
|
158
|
+
sunos_dev_priv_t *dpriv;
|
|
159
|
+
devctl_ap_state_t devctl_ap_state;
|
|
160
|
+
|
|
161
|
+
dpriv = (sunos_dev_priv_t *)dev->os_priv;
|
|
162
|
+
phypath = dpriv->phypath;
|
|
163
|
+
|
|
164
|
+
end = strrchr(phypath, '/');
|
|
165
|
+
if (end == NULL)
|
|
166
|
+
return (-1);
|
|
167
|
+
hubpath = strndup(phypath, end - phypath);
|
|
168
|
+
if (hubpath == NULL)
|
|
169
|
+
return (-1);
|
|
170
|
+
|
|
171
|
+
end = strrchr(hubpath, '@');
|
|
172
|
+
if (end == NULL) {
|
|
173
|
+
free(hubpath);
|
|
174
|
+
return (-1);
|
|
175
|
+
}
|
|
176
|
+
end++;
|
|
177
|
+
usbi_dbg("unitaddr: %s", end);
|
|
178
|
+
|
|
179
|
+
nvlist_alloc(&nvlist, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP);
|
|
180
|
+
nvlist_add_int32(nvlist, "port", dev->port_number);
|
|
181
|
+
//find the hub path
|
|
182
|
+
snprintf(path_arg, sizeof(path_arg), "/devices%s:hubd", hubpath);
|
|
183
|
+
usbi_dbg("ioctl hub path: %s", path_arg);
|
|
184
|
+
|
|
185
|
+
fd = open(path_arg, O_RDONLY);
|
|
186
|
+
if (fd < 0) {
|
|
187
|
+
usbi_err(DEVICE_CTX(dev), "open failed: %d (%s)", errno, strerror(errno));
|
|
188
|
+
nvlist_free(nvlist);
|
|
189
|
+
free(hubpath);
|
|
190
|
+
return (-1);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
memset(&iocdata, 0, sizeof(iocdata));
|
|
194
|
+
memset(&devctl_ap_state, 0, sizeof(devctl_ap_state));
|
|
195
|
+
|
|
196
|
+
nvlist_pack(nvlist, (char **)&iocdata.nvl_user, &iocdata.nvl_usersz, NV_ENCODE_NATIVE, 0);
|
|
197
|
+
|
|
198
|
+
iocdata.cmd = DEVCTL_AP_GETSTATE;
|
|
199
|
+
iocdata.flags = 0;
|
|
200
|
+
iocdata.c_nodename = "hub";
|
|
201
|
+
iocdata.c_unitaddr = end;
|
|
202
|
+
iocdata.cpyout_buf = &devctl_ap_state;
|
|
203
|
+
usbi_dbg("%p, %d", iocdata.nvl_user, iocdata.nvl_usersz);
|
|
204
|
+
|
|
205
|
+
errno = 0;
|
|
206
|
+
if (ioctl(fd, DEVCTL_AP_GETSTATE, &iocdata) == -1) {
|
|
207
|
+
usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)",
|
|
208
|
+
fd, DEVCTL_AP_GETSTATE, errno, strerror(errno));
|
|
209
|
+
} else {
|
|
210
|
+
usbi_dbg("dev rstate: %d", devctl_ap_state.ap_rstate);
|
|
211
|
+
usbi_dbg("dev ostate: %d", devctl_ap_state.ap_ostate);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
errno = 0;
|
|
215
|
+
iocdata.cmd = cmd;
|
|
216
|
+
if (ioctl(fd, (int)cmd, &iocdata) != 0) {
|
|
217
|
+
usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)",
|
|
218
|
+
fd, cmd, errno, strerror(errno));
|
|
219
|
+
sleep(2);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
close(fd);
|
|
223
|
+
free(iocdata.nvl_user);
|
|
224
|
+
nvlist_free(nvlist);
|
|
225
|
+
free(hubpath);
|
|
226
|
+
|
|
227
|
+
return (-errno);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
static int
|
|
231
|
+
sunos_kernel_driver_active(struct libusb_device_handle *dev, int interface)
|
|
232
|
+
{
|
|
233
|
+
sunos_dev_priv_t *dpriv;
|
|
234
|
+
dpriv = (sunos_dev_priv_t *)dev->dev->os_priv;
|
|
235
|
+
|
|
236
|
+
usbi_dbg("%s", dpriv->ugenpath);
|
|
237
|
+
|
|
238
|
+
return (dpriv->ugenpath == NULL);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/*
|
|
242
|
+
* Private functions
|
|
243
|
+
*/
|
|
244
|
+
static int _errno_to_libusb(int);
|
|
245
|
+
static int sunos_usb_get_status(int fd);
|
|
246
|
+
|
|
247
|
+
static int sunos_init(struct libusb_context *ctx)
|
|
248
|
+
{
|
|
249
|
+
return (LIBUSB_SUCCESS);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
static void sunos_exit(struct libusb_context *ctx)
|
|
253
|
+
{
|
|
254
|
+
usbi_dbg("");
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
static string_list_t *
|
|
258
|
+
sunos_new_string_list(void)
|
|
259
|
+
{
|
|
260
|
+
string_list_t *list;
|
|
261
|
+
|
|
262
|
+
list = calloc(1, sizeof(*list));
|
|
263
|
+
if (list != NULL)
|
|
264
|
+
list_create(list, sizeof(string_node_t),
|
|
265
|
+
offsetof(string_node_t, link));
|
|
266
|
+
|
|
267
|
+
return (list);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
static int
|
|
271
|
+
sunos_append_to_string_list(string_list_t *list, const char *arg)
|
|
272
|
+
{
|
|
273
|
+
string_node_t *np;
|
|
274
|
+
|
|
275
|
+
np = calloc(1, sizeof(*np));
|
|
276
|
+
if (!np)
|
|
277
|
+
return (-1);
|
|
278
|
+
|
|
279
|
+
np->string = strdup(arg);
|
|
280
|
+
if (!np->string) {
|
|
281
|
+
free(np);
|
|
282
|
+
return (-1);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
list_insert_tail(list, np);
|
|
286
|
+
|
|
287
|
+
return (0);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
static void
|
|
291
|
+
sunos_free_string_list(string_list_t *list)
|
|
292
|
+
{
|
|
293
|
+
string_node_t *np;
|
|
294
|
+
|
|
295
|
+
while ((np = list_remove_head(list)) != NULL) {
|
|
296
|
+
free(np->string);
|
|
297
|
+
free(np);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
free(list);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
static char **
|
|
304
|
+
sunos_build_argv_list(string_list_t *list)
|
|
305
|
+
{
|
|
306
|
+
char **argv_list;
|
|
307
|
+
string_node_t *np;
|
|
308
|
+
int n;
|
|
309
|
+
|
|
310
|
+
n = 1; /* Start at 1 for NULL terminator */
|
|
311
|
+
for (np = list_head(list); np != NULL; np = list_next(list, np))
|
|
312
|
+
n++;
|
|
313
|
+
|
|
314
|
+
argv_list = calloc(n, sizeof(char *));
|
|
315
|
+
if (argv_list == NULL)
|
|
316
|
+
return NULL;
|
|
317
|
+
|
|
318
|
+
n = 0;
|
|
319
|
+
for (np = list_head(list); np != NULL; np = list_next(list, np))
|
|
320
|
+
argv_list[n++] = np->string;
|
|
321
|
+
|
|
322
|
+
return (argv_list);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
static int
|
|
327
|
+
sunos_exec_command(struct libusb_context *ctx, const char *path,
|
|
328
|
+
string_list_t *list)
|
|
329
|
+
{
|
|
330
|
+
pid_t pid;
|
|
331
|
+
int status;
|
|
332
|
+
int waitstat;
|
|
333
|
+
int exit_status;
|
|
334
|
+
char **argv_list;
|
|
335
|
+
|
|
336
|
+
argv_list = sunos_build_argv_list(list);
|
|
337
|
+
if (argv_list == NULL)
|
|
338
|
+
return (-1);
|
|
339
|
+
|
|
340
|
+
pid = fork();
|
|
341
|
+
if (pid == 0) {
|
|
342
|
+
/* child */
|
|
343
|
+
execv(path, argv_list);
|
|
344
|
+
_exit(127);
|
|
345
|
+
} else if (pid > 0) {
|
|
346
|
+
/* parent */
|
|
347
|
+
do {
|
|
348
|
+
waitstat = waitpid(pid, &status, 0);
|
|
349
|
+
} while ((waitstat == -1 && errno == EINTR) ||
|
|
350
|
+
(waitstat == 0 && !WIFEXITED(status) && !WIFSIGNALED(status)));
|
|
351
|
+
|
|
352
|
+
if (waitstat == 0) {
|
|
353
|
+
if (WIFEXITED(status))
|
|
354
|
+
exit_status = WEXITSTATUS(status);
|
|
355
|
+
else
|
|
356
|
+
exit_status = WTERMSIG(status);
|
|
357
|
+
} else {
|
|
358
|
+
usbi_err(ctx, "waitpid failed: errno %d (%s)", errno, strerror(errno));
|
|
359
|
+
exit_status = -1;
|
|
360
|
+
}
|
|
361
|
+
} else {
|
|
362
|
+
/* fork failed */
|
|
363
|
+
usbi_err(ctx, "fork failed: errno %d (%s)", errno, strerror(errno));
|
|
364
|
+
exit_status = -1;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
free(argv_list);
|
|
368
|
+
|
|
369
|
+
return (exit_status);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
static int
|
|
373
|
+
sunos_detach_kernel_driver(struct libusb_device_handle *dev_handle,
|
|
374
|
+
int interface_number)
|
|
375
|
+
{
|
|
376
|
+
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
|
377
|
+
string_list_t *list;
|
|
378
|
+
char path_arg[PATH_MAX];
|
|
379
|
+
sunos_dev_priv_t *dpriv;
|
|
380
|
+
int r;
|
|
381
|
+
|
|
382
|
+
dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv;
|
|
383
|
+
snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath);
|
|
384
|
+
usbi_dbg("%s", path_arg);
|
|
385
|
+
|
|
386
|
+
list = sunos_new_string_list();
|
|
387
|
+
if (list == NULL)
|
|
388
|
+
return (LIBUSB_ERROR_NO_MEM);
|
|
389
|
+
|
|
390
|
+
/* attach ugen driver */
|
|
391
|
+
r = 0;
|
|
392
|
+
r |= sunos_append_to_string_list(list, UPDATEDRV);
|
|
393
|
+
r |= sunos_append_to_string_list(list, "-a"); /* add rule */
|
|
394
|
+
r |= sunos_append_to_string_list(list, "-i"); /* specific device */
|
|
395
|
+
r |= sunos_append_to_string_list(list, path_arg); /* physical path */
|
|
396
|
+
r |= sunos_append_to_string_list(list, "ugen");
|
|
397
|
+
if (r) {
|
|
398
|
+
sunos_free_string_list(list);
|
|
399
|
+
return (LIBUSB_ERROR_NO_MEM);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
r = sunos_exec_command(ctx, UPDATEDRV_PATH, list);
|
|
403
|
+
sunos_free_string_list(list);
|
|
404
|
+
if (r < 0)
|
|
405
|
+
return (LIBUSB_ERROR_OTHER);
|
|
406
|
+
|
|
407
|
+
/* reconfigure the driver node */
|
|
408
|
+
r = 0;
|
|
409
|
+
r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT);
|
|
410
|
+
r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
|
|
411
|
+
if (r)
|
|
412
|
+
usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed");
|
|
413
|
+
|
|
414
|
+
snprintf(path_arg, sizeof(path_arg), "^usb/%x.%x", dpriv->dev_descr.idVendor,
|
|
415
|
+
dpriv->dev_descr.idProduct);
|
|
416
|
+
sunos_physpath_to_devlink(dpriv->phypath, path_arg, &dpriv->ugenpath);
|
|
417
|
+
|
|
418
|
+
if (access(dpriv->ugenpath, F_OK) == -1) {
|
|
419
|
+
usbi_err(HANDLE_CTX(dev_handle), "fail to detach kernel driver");
|
|
420
|
+
return (LIBUSB_ERROR_IO);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return sunos_usb_open_ep0((sunos_dev_handle_priv_t *)dev_handle->os_priv, dpriv);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
static int
|
|
427
|
+
sunos_attach_kernel_driver(struct libusb_device_handle *dev_handle,
|
|
428
|
+
int interface_number)
|
|
429
|
+
{
|
|
430
|
+
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
|
|
431
|
+
string_list_t *list;
|
|
432
|
+
char path_arg[PATH_MAX];
|
|
433
|
+
sunos_dev_priv_t *dpriv;
|
|
434
|
+
int r;
|
|
435
|
+
|
|
436
|
+
/* we open the dev in detach driver, so we need close it first. */
|
|
437
|
+
sunos_close(dev_handle);
|
|
438
|
+
|
|
439
|
+
dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv;
|
|
440
|
+
snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath);
|
|
441
|
+
usbi_dbg("%s", path_arg);
|
|
442
|
+
|
|
443
|
+
list = sunos_new_string_list();
|
|
444
|
+
if (list == NULL)
|
|
445
|
+
return (LIBUSB_ERROR_NO_MEM);
|
|
446
|
+
|
|
447
|
+
/* detach ugen driver */
|
|
448
|
+
r = 0;
|
|
449
|
+
r |= sunos_append_to_string_list(list, UPDATEDRV);
|
|
450
|
+
r |= sunos_append_to_string_list(list, "-d"); /* add rule */
|
|
451
|
+
r |= sunos_append_to_string_list(list, "-i"); /* specific device */
|
|
452
|
+
r |= sunos_append_to_string_list(list, path_arg); /* physical path */
|
|
453
|
+
r |= sunos_append_to_string_list(list, "ugen");
|
|
454
|
+
if (r) {
|
|
455
|
+
sunos_free_string_list(list);
|
|
456
|
+
return (LIBUSB_ERROR_NO_MEM);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
r = sunos_exec_command(ctx, UPDATEDRV_PATH, list);
|
|
460
|
+
sunos_free_string_list(list);
|
|
461
|
+
if (r < 0)
|
|
462
|
+
return (LIBUSB_ERROR_OTHER);
|
|
463
|
+
|
|
464
|
+
/* reconfigure the driver node */
|
|
465
|
+
r = 0;
|
|
466
|
+
r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
|
|
467
|
+
r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT);
|
|
468
|
+
r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
|
|
469
|
+
if (r)
|
|
470
|
+
usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed");
|
|
471
|
+
|
|
472
|
+
return 0;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
static int
|
|
476
|
+
sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
|
|
477
|
+
{
|
|
478
|
+
int proplen;
|
|
479
|
+
int *i, n, *addr, *port_prop;
|
|
480
|
+
char *phypath;
|
|
481
|
+
uint8_t *rdata;
|
|
482
|
+
struct libusb_device_descriptor *descr;
|
|
483
|
+
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
|
|
484
|
+
char match_str[PATH_MAX];
|
|
485
|
+
|
|
486
|
+
/* Device descriptors */
|
|
487
|
+
proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
|
|
488
|
+
"usb-dev-descriptor", &rdata);
|
|
489
|
+
if (proplen <= 0) {
|
|
490
|
+
|
|
491
|
+
return (LIBUSB_ERROR_IO);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
descr = (struct libusb_device_descriptor *)rdata;
|
|
495
|
+
bcopy(descr, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE);
|
|
496
|
+
dpriv->dev_descr.bcdUSB = libusb_cpu_to_le16(descr->bcdUSB);
|
|
497
|
+
dpriv->dev_descr.idVendor = libusb_cpu_to_le16(descr->idVendor);
|
|
498
|
+
dpriv->dev_descr.idProduct = libusb_cpu_to_le16(descr->idProduct);
|
|
499
|
+
dpriv->dev_descr.bcdDevice = libusb_cpu_to_le16(descr->bcdDevice);
|
|
500
|
+
|
|
501
|
+
/* Raw configuration descriptors */
|
|
502
|
+
proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
|
|
503
|
+
"usb-raw-cfg-descriptors", &rdata);
|
|
504
|
+
if (proplen <= 0) {
|
|
505
|
+
usbi_dbg("can't find raw config descriptors");
|
|
506
|
+
|
|
507
|
+
return (LIBUSB_ERROR_IO);
|
|
508
|
+
}
|
|
509
|
+
dpriv->raw_cfgdescr = calloc(1, proplen);
|
|
510
|
+
if (dpriv->raw_cfgdescr == NULL) {
|
|
511
|
+
return (LIBUSB_ERROR_NO_MEM);
|
|
512
|
+
} else {
|
|
513
|
+
bcopy(rdata, dpriv->raw_cfgdescr, proplen);
|
|
514
|
+
dpriv->cfgvalue = ((struct libusb_config_descriptor *)
|
|
515
|
+
rdata)->bConfigurationValue;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &port_prop);
|
|
519
|
+
|
|
520
|
+
if ((n != 1) || (*port_prop <= 0)) {
|
|
521
|
+
return (LIBUSB_ERROR_IO);
|
|
522
|
+
}
|
|
523
|
+
dev->port_number = *port_prop;
|
|
524
|
+
|
|
525
|
+
/* device physical path */
|
|
526
|
+
phypath = di_devfs_path(node);
|
|
527
|
+
if (phypath) {
|
|
528
|
+
dpriv->phypath = strdup(phypath);
|
|
529
|
+
snprintf(match_str, sizeof(match_str), "^usb/%x.%x", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct);
|
|
530
|
+
usbi_dbg("match is %s", match_str);
|
|
531
|
+
sunos_physpath_to_devlink(dpriv->phypath, match_str, &dpriv->ugenpath);
|
|
532
|
+
di_devfs_path_free(phypath);
|
|
533
|
+
|
|
534
|
+
} else {
|
|
535
|
+
free(dpriv->raw_cfgdescr);
|
|
536
|
+
|
|
537
|
+
return (LIBUSB_ERROR_IO);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/* address */
|
|
541
|
+
n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "assigned-address", &addr);
|
|
542
|
+
if (n != 1 || *addr == 0) {
|
|
543
|
+
usbi_dbg("can't get address");
|
|
544
|
+
} else {
|
|
545
|
+
dev->device_address = *addr;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/* speed */
|
|
549
|
+
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "low-speed", &i) >= 0) {
|
|
550
|
+
dev->speed = LIBUSB_SPEED_LOW;
|
|
551
|
+
} else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "high-speed", &i) >= 0) {
|
|
552
|
+
dev->speed = LIBUSB_SPEED_HIGH;
|
|
553
|
+
} else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "full-speed", &i) >= 0) {
|
|
554
|
+
dev->speed = LIBUSB_SPEED_FULL;
|
|
555
|
+
} else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "super-speed", &i) >= 0) {
|
|
556
|
+
dev->speed = LIBUSB_SPEED_SUPER;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
usbi_dbg("vid=%x pid=%x, path=%s, bus_nmber=0x%x, port_number=%d, "
|
|
560
|
+
"speed=%d", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct,
|
|
561
|
+
dpriv->phypath, dev->bus_number, dev->port_number, dev->speed);
|
|
562
|
+
|
|
563
|
+
return (LIBUSB_SUCCESS);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
static int
|
|
567
|
+
sunos_add_devices(di_devlink_t link, void *arg)
|
|
568
|
+
{
|
|
569
|
+
struct devlink_cbarg *largs = (struct devlink_cbarg *)arg;
|
|
570
|
+
struct node_args *nargs;
|
|
571
|
+
di_node_t myself, dn;
|
|
572
|
+
uint64_t session_id = 0;
|
|
573
|
+
uint64_t sid = 0;
|
|
574
|
+
uint64_t bdf = 0;
|
|
575
|
+
struct libusb_device *dev;
|
|
576
|
+
sunos_dev_priv_t *devpriv;
|
|
577
|
+
int n, *j;
|
|
578
|
+
int i = 0;
|
|
579
|
+
int *addr_prop;
|
|
580
|
+
uint8_t bus_number = 0;
|
|
581
|
+
uint32_t * regbuf = NULL;
|
|
582
|
+
uint32_t reg;
|
|
583
|
+
|
|
584
|
+
nargs = (struct node_args *)largs->nargs;
|
|
585
|
+
myself = largs->myself;
|
|
586
|
+
|
|
587
|
+
/*
|
|
588
|
+
* Construct session ID.
|
|
589
|
+
* session ID = dev_addr | hub addr |parent hub addr|...|root hub bdf
|
|
590
|
+
* 8 bits 8bits 8 bits 16bits
|
|
591
|
+
*/
|
|
592
|
+
if (myself == DI_NODE_NIL)
|
|
593
|
+
return (DI_WALK_CONTINUE);
|
|
594
|
+
|
|
595
|
+
dn = myself;
|
|
596
|
+
/* find the root hub */
|
|
597
|
+
while (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "root-hub", &j) != 0) {
|
|
598
|
+
usbi_dbg("find_root_hub:%s", di_devfs_path(dn));
|
|
599
|
+
n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn,
|
|
600
|
+
"assigned-address", &addr_prop);
|
|
601
|
+
session_id |= ((addr_prop[0] & 0xff) << i++ * 8);
|
|
602
|
+
dn = di_parent_node(dn);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/* dn is the root hub node */
|
|
606
|
+
n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", (int **)®buf);
|
|
607
|
+
reg = regbuf[0];
|
|
608
|
+
bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
|
|
609
|
+
/* bdf must larger than i*8 bits */
|
|
610
|
+
session_id |= (bdf << i * 8);
|
|
611
|
+
bus_number = (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
|
|
612
|
+
|
|
613
|
+
usbi_dbg("device bus address=%s:%x, name:%s",
|
|
614
|
+
di_bus_addr(myself), bus_number, di_node_name(dn));
|
|
615
|
+
usbi_dbg("session id org:%lx", session_id);
|
|
616
|
+
|
|
617
|
+
/* dn is the usb device */
|
|
618
|
+
for (dn = di_child_node(myself); dn != DI_NODE_NIL; dn = di_sibling_node(dn)) {
|
|
619
|
+
usbi_dbg("device path:%s", di_devfs_path(dn));
|
|
620
|
+
/* skip hub devices, because its driver can not been unload */
|
|
621
|
+
if (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "usb-port-count", &addr_prop) != -1)
|
|
622
|
+
continue;
|
|
623
|
+
/* usb_addr */
|
|
624
|
+
n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn,
|
|
625
|
+
"assigned-address", &addr_prop);
|
|
626
|
+
if ((n != 1) || (addr_prop[0] == 0)) {
|
|
627
|
+
usbi_dbg("cannot get valid usb_addr");
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
sid = (session_id << 8) | (addr_prop[0] & 0xff) ;
|
|
632
|
+
usbi_dbg("session id %lx", sid);
|
|
633
|
+
|
|
634
|
+
dev = usbi_get_device_by_session_id(nargs->ctx, sid);
|
|
635
|
+
if (dev == NULL) {
|
|
636
|
+
dev = usbi_alloc_device(nargs->ctx, sid);
|
|
637
|
+
if (dev == NULL) {
|
|
638
|
+
usbi_dbg("can't alloc device");
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
devpriv = (sunos_dev_priv_t *)dev->os_priv;
|
|
642
|
+
dev->bus_number = bus_number;
|
|
643
|
+
|
|
644
|
+
if (sunos_fill_in_dev_info(dn, dev) != LIBUSB_SUCCESS) {
|
|
645
|
+
libusb_unref_device(dev);
|
|
646
|
+
usbi_dbg("get infomation fail");
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
if (usbi_sanitize_device(dev) < 0) {
|
|
650
|
+
libusb_unref_device(dev);
|
|
651
|
+
usbi_dbg("sanatize failed: ");
|
|
652
|
+
return (DI_WALK_TERMINATE);
|
|
653
|
+
}
|
|
654
|
+
} else {
|
|
655
|
+
devpriv = (sunos_dev_priv_t *)dev->os_priv;
|
|
656
|
+
usbi_dbg("Dev %s exists", devpriv->ugenpath);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) {
|
|
660
|
+
usbi_dbg("cannot append device");
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/*
|
|
664
|
+
* we alloc and hence ref this dev. We don't need to ref it
|
|
665
|
+
* hereafter. Front end or app should take care of their ref.
|
|
666
|
+
*/
|
|
667
|
+
libusb_unref_device(dev);
|
|
668
|
+
|
|
669
|
+
usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x",
|
|
670
|
+
devpriv->ugenpath, di_devfs_path(dn), (uint64_t)sid,
|
|
671
|
+
(*nargs->discdevs)->len, bdf);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
return (DI_WALK_CONTINUE);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
static int
|
|
678
|
+
sunos_walk_minor_node_link(di_node_t node, void *args)
|
|
679
|
+
{
|
|
680
|
+
di_minor_t minor = DI_MINOR_NIL;
|
|
681
|
+
char *minor_path;
|
|
682
|
+
struct devlink_cbarg arg;
|
|
683
|
+
struct node_args *nargs = (struct node_args *)args;
|
|
684
|
+
di_devlink_handle_t devlink_hdl = nargs->dlink_hdl;
|
|
685
|
+
|
|
686
|
+
/* walk each minor to find usb devices */
|
|
687
|
+
while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
|
|
688
|
+
minor_path = di_devfs_minor_path(minor);
|
|
689
|
+
arg.nargs = args;
|
|
690
|
+
arg.myself = node;
|
|
691
|
+
arg.minor = minor;
|
|
692
|
+
(void) di_devlink_walk(devlink_hdl,
|
|
693
|
+
"^usb/hub[0-9]+", minor_path,
|
|
694
|
+
DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices);
|
|
695
|
+
di_devfs_path_free(minor_path);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/* switch to a different node */
|
|
699
|
+
nargs->last_ugenpath = NULL;
|
|
700
|
+
|
|
701
|
+
return (DI_WALK_CONTINUE);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
int
|
|
705
|
+
sunos_get_device_list(struct libusb_context * ctx,
|
|
706
|
+
struct discovered_devs **discdevs)
|
|
707
|
+
{
|
|
708
|
+
di_node_t root_node;
|
|
709
|
+
struct node_args args;
|
|
710
|
+
di_devlink_handle_t devlink_hdl;
|
|
711
|
+
|
|
712
|
+
args.ctx = ctx;
|
|
713
|
+
args.discdevs = discdevs;
|
|
714
|
+
args.last_ugenpath = NULL;
|
|
715
|
+
if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
|
|
716
|
+
usbi_dbg("di_int() failed: %s", strerror(errno));
|
|
717
|
+
return (LIBUSB_ERROR_IO);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
|
|
721
|
+
di_fini(root_node);
|
|
722
|
+
usbi_dbg("di_devlink_init() failed: %s", strerror(errno));
|
|
723
|
+
|
|
724
|
+
return (LIBUSB_ERROR_IO);
|
|
725
|
+
}
|
|
726
|
+
args.dlink_hdl = devlink_hdl;
|
|
727
|
+
|
|
728
|
+
/* walk each node to find USB devices */
|
|
729
|
+
if (di_walk_node(root_node, DI_WALK_SIBFIRST, &args,
|
|
730
|
+
sunos_walk_minor_node_link) == -1) {
|
|
731
|
+
usbi_dbg("di_walk_node() failed: %s", strerror(errno));
|
|
732
|
+
di_fini(root_node);
|
|
733
|
+
|
|
734
|
+
return (LIBUSB_ERROR_IO);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
di_fini(root_node);
|
|
738
|
+
di_devlink_fini(&devlink_hdl);
|
|
739
|
+
|
|
740
|
+
usbi_dbg("%d devices", (*discdevs)->len);
|
|
741
|
+
|
|
742
|
+
return ((*discdevs)->len);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
static int
|
|
746
|
+
sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv)
|
|
747
|
+
{
|
|
748
|
+
char filename[PATH_MAX + 1];
|
|
749
|
+
|
|
750
|
+
if (hpriv->eps[0].datafd > 0) {
|
|
751
|
+
|
|
752
|
+
return (LIBUSB_SUCCESS);
|
|
753
|
+
}
|
|
754
|
+
snprintf(filename, PATH_MAX, "%s/cntrl0", dpriv->ugenpath);
|
|
755
|
+
|
|
756
|
+
usbi_dbg("opening %s", filename);
|
|
757
|
+
hpriv->eps[0].datafd = open(filename, O_RDWR);
|
|
758
|
+
if (hpriv->eps[0].datafd < 0) {
|
|
759
|
+
return(_errno_to_libusb(errno));
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
snprintf(filename, PATH_MAX, "%s/cntrl0stat", dpriv->ugenpath);
|
|
763
|
+
hpriv->eps[0].statfd = open(filename, O_RDONLY);
|
|
764
|
+
if (hpriv->eps[0].statfd < 0) {
|
|
765
|
+
close(hpriv->eps[0].datafd);
|
|
766
|
+
hpriv->eps[0].datafd = -1;
|
|
767
|
+
|
|
768
|
+
return(_errno_to_libusb(errno));
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
return (LIBUSB_SUCCESS);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
static void
|
|
775
|
+
sunos_usb_close_all_eps(sunos_dev_handle_priv_t *hdev)
|
|
776
|
+
{
|
|
777
|
+
int i;
|
|
778
|
+
|
|
779
|
+
/* not close ep0 */
|
|
780
|
+
for (i = 1; i < USB_MAXENDPOINTS; i++) {
|
|
781
|
+
if (hdev->eps[i].datafd != -1) {
|
|
782
|
+
(void) close(hdev->eps[i].datafd);
|
|
783
|
+
hdev->eps[i].datafd = -1;
|
|
784
|
+
}
|
|
785
|
+
if (hdev->eps[i].statfd != -1) {
|
|
786
|
+
(void) close(hdev->eps[i].statfd);
|
|
787
|
+
hdev->eps[i].statfd = -1;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
static void
|
|
793
|
+
sunos_usb_close_ep0(sunos_dev_handle_priv_t *hdev, sunos_dev_priv_t *dpriv)
|
|
794
|
+
{
|
|
795
|
+
if (hdev->eps[0].datafd >= 0) {
|
|
796
|
+
close(hdev->eps[0].datafd);
|
|
797
|
+
close(hdev->eps[0].statfd);
|
|
798
|
+
hdev->eps[0].datafd = -1;
|
|
799
|
+
hdev->eps[0].statfd = -1;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
static uchar_t
|
|
804
|
+
sunos_usb_ep_index(uint8_t ep_addr)
|
|
805
|
+
{
|
|
806
|
+
return ((ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK) +
|
|
807
|
+
((ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? 16 : 0));
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
static int
|
|
811
|
+
sunos_find_interface(struct libusb_device_handle *hdev,
|
|
812
|
+
uint8_t endpoint, uint8_t *interface)
|
|
813
|
+
{
|
|
814
|
+
struct libusb_config_descriptor *config;
|
|
815
|
+
int r;
|
|
816
|
+
int iface_idx;
|
|
817
|
+
|
|
818
|
+
r = libusb_get_active_config_descriptor(hdev->dev, &config);
|
|
819
|
+
if (r < 0) {
|
|
820
|
+
return (LIBUSB_ERROR_INVALID_PARAM);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) {
|
|
824
|
+
const struct libusb_interface *iface =
|
|
825
|
+
&config->interface[iface_idx];
|
|
826
|
+
int altsetting_idx;
|
|
827
|
+
|
|
828
|
+
for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting;
|
|
829
|
+
altsetting_idx++) {
|
|
830
|
+
const struct libusb_interface_descriptor *altsetting =
|
|
831
|
+
&iface->altsetting[altsetting_idx];
|
|
832
|
+
int ep_idx;
|
|
833
|
+
|
|
834
|
+
for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints;
|
|
835
|
+
ep_idx++) {
|
|
836
|
+
const struct libusb_endpoint_descriptor *ep =
|
|
837
|
+
&altsetting->endpoint[ep_idx];
|
|
838
|
+
if (ep->bEndpointAddress == endpoint) {
|
|
839
|
+
*interface = iface_idx;
|
|
840
|
+
libusb_free_config_descriptor(config);
|
|
841
|
+
|
|
842
|
+
return (LIBUSB_SUCCESS);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
libusb_free_config_descriptor(config);
|
|
848
|
+
|
|
849
|
+
return (LIBUSB_ERROR_INVALID_PARAM);
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
static int
|
|
853
|
+
sunos_check_device_and_status_open(struct libusb_device_handle *hdl,
|
|
854
|
+
uint8_t ep_addr, int ep_type)
|
|
855
|
+
{
|
|
856
|
+
char filename[PATH_MAX + 1], statfilename[PATH_MAX + 1];
|
|
857
|
+
char cfg_num[16], alt_num[16];
|
|
858
|
+
int fd, fdstat, mode;
|
|
859
|
+
uint8_t ifc = 0;
|
|
860
|
+
uint8_t ep_index;
|
|
861
|
+
sunos_dev_handle_priv_t *hpriv;
|
|
862
|
+
|
|
863
|
+
usbi_dbg("open ep 0x%02x", ep_addr);
|
|
864
|
+
hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv;
|
|
865
|
+
ep_index = sunos_usb_ep_index(ep_addr);
|
|
866
|
+
/* ep already opened */
|
|
867
|
+
if ((hpriv->eps[ep_index].datafd > 0) &&
|
|
868
|
+
(hpriv->eps[ep_index].statfd > 0)) {
|
|
869
|
+
usbi_dbg("ep 0x%02x already opened, return success",
|
|
870
|
+
ep_addr);
|
|
871
|
+
|
|
872
|
+
return (0);
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
if (sunos_find_interface(hdl, ep_addr, &ifc) < 0) {
|
|
876
|
+
usbi_dbg("can't find interface for endpoint 0x%02x",
|
|
877
|
+
ep_addr);
|
|
878
|
+
|
|
879
|
+
return (EACCES);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/* create filename */
|
|
883
|
+
if (hpriv->config_index > 0) {
|
|
884
|
+
(void) snprintf(cfg_num, sizeof (cfg_num), "cfg%d",
|
|
885
|
+
hpriv->config_index + 1);
|
|
886
|
+
} else {
|
|
887
|
+
bzero(cfg_num, sizeof (cfg_num));
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (hpriv->altsetting[ifc] > 0) {
|
|
891
|
+
(void) snprintf(alt_num, sizeof (alt_num), ".%d",
|
|
892
|
+
hpriv->altsetting[ifc]);
|
|
893
|
+
} else {
|
|
894
|
+
bzero(alt_num, sizeof (alt_num));
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
(void) snprintf(filename, PATH_MAX, "%s/%sif%d%s%s%d",
|
|
898
|
+
hpriv->dpriv->ugenpath, cfg_num, ifc, alt_num,
|
|
899
|
+
(ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? "in" :
|
|
900
|
+
"out", (ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK));
|
|
901
|
+
(void) snprintf(statfilename, PATH_MAX, "%sstat", filename);
|
|
902
|
+
|
|
903
|
+
/*
|
|
904
|
+
* for interrupt IN endpoints, we need to enable one xfer
|
|
905
|
+
* mode before opening the endpoint
|
|
906
|
+
*/
|
|
907
|
+
if ((ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) &&
|
|
908
|
+
(ep_addr & LIBUSB_ENDPOINT_IN)) {
|
|
909
|
+
char control = USB_EP_INTR_ONE_XFER;
|
|
910
|
+
int count;
|
|
911
|
+
|
|
912
|
+
/* open the status device node for the ep first RDWR */
|
|
913
|
+
if ((fdstat = open(statfilename, O_RDWR)) == -1) {
|
|
914
|
+
usbi_dbg("can't open %s RDWR: %d",
|
|
915
|
+
statfilename, errno);
|
|
916
|
+
} else {
|
|
917
|
+
count = write(fdstat, &control, sizeof (control));
|
|
918
|
+
if (count != 1) {
|
|
919
|
+
/* this should have worked */
|
|
920
|
+
usbi_dbg("can't write to %s: %d",
|
|
921
|
+
statfilename, errno);
|
|
922
|
+
(void) close(fdstat);
|
|
923
|
+
|
|
924
|
+
return (errno);
|
|
925
|
+
}
|
|
926
|
+
/* close status node and open xfer node first */
|
|
927
|
+
close (fdstat);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/* open the xfer node first in case alt needs to be changed */
|
|
932
|
+
if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
|
|
933
|
+
mode = O_RDWR;
|
|
934
|
+
} else if (ep_addr & LIBUSB_ENDPOINT_IN) {
|
|
935
|
+
mode = O_RDONLY;
|
|
936
|
+
} else {
|
|
937
|
+
mode = O_WRONLY;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/*
|
|
941
|
+
* IMPORTANT: must open data xfer node first and then open stat node
|
|
942
|
+
* Otherwise, it will fail on multi-config or multi-altsetting devices
|
|
943
|
+
* with "Device Busy" error. See ugen_epxs_switch_cfg_alt() and
|
|
944
|
+
* ugen_epxs_check_alt_switch() in ugen driver source code.
|
|
945
|
+
*/
|
|
946
|
+
if ((fd = open(filename, mode)) == -1) {
|
|
947
|
+
usbi_dbg("can't open %s: %d(%s)", filename, errno,
|
|
948
|
+
strerror(errno));
|
|
949
|
+
|
|
950
|
+
return (errno);
|
|
951
|
+
}
|
|
952
|
+
/* open the status node */
|
|
953
|
+
if ((fdstat = open(statfilename, O_RDONLY)) == -1) {
|
|
954
|
+
usbi_dbg("can't open %s: %d", statfilename, errno);
|
|
955
|
+
|
|
956
|
+
(void) close(fd);
|
|
957
|
+
|
|
958
|
+
return (errno);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
hpriv->eps[ep_index].datafd = fd;
|
|
962
|
+
hpriv->eps[ep_index].statfd = fdstat;
|
|
963
|
+
usbi_dbg("ep=0x%02x datafd=%d, statfd=%d", ep_addr, fd, fdstat);
|
|
964
|
+
|
|
965
|
+
return (0);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
int
|
|
969
|
+
sunos_open(struct libusb_device_handle *handle)
|
|
970
|
+
{
|
|
971
|
+
sunos_dev_handle_priv_t *hpriv;
|
|
972
|
+
sunos_dev_priv_t *dpriv;
|
|
973
|
+
int i;
|
|
974
|
+
int ret;
|
|
975
|
+
|
|
976
|
+
hpriv = (sunos_dev_handle_priv_t *)handle->os_priv;
|
|
977
|
+
dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
|
|
978
|
+
hpriv->dpriv = dpriv;
|
|
979
|
+
|
|
980
|
+
/* set all file descriptors to "closed" */
|
|
981
|
+
for (i = 0; i < USB_MAXENDPOINTS; i++) {
|
|
982
|
+
hpriv->eps[i].datafd = -1;
|
|
983
|
+
hpriv->eps[i].statfd = -1;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
if (sunos_kernel_driver_active(handle, 0)) {
|
|
987
|
+
/* pretend we can open the device */
|
|
988
|
+
return (LIBUSB_SUCCESS);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) {
|
|
992
|
+
usbi_dbg("fail: %d", ret);
|
|
993
|
+
return (ret);
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
return (LIBUSB_SUCCESS);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
void
|
|
1000
|
+
sunos_close(struct libusb_device_handle *handle)
|
|
1001
|
+
{
|
|
1002
|
+
sunos_dev_handle_priv_t *hpriv;
|
|
1003
|
+
sunos_dev_priv_t *dpriv;
|
|
1004
|
+
|
|
1005
|
+
usbi_dbg("");
|
|
1006
|
+
if (!handle) {
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
hpriv = (sunos_dev_handle_priv_t *)handle->os_priv;
|
|
1011
|
+
if (!hpriv) {
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
|
|
1015
|
+
if (!dpriv) {
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
sunos_usb_close_all_eps(hpriv);
|
|
1020
|
+
sunos_usb_close_ep0(hpriv, dpriv);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
int
|
|
1024
|
+
sunos_get_device_descriptor(struct libusb_device *dev, uint8_t *buf,
|
|
1025
|
+
int *host_endian)
|
|
1026
|
+
{
|
|
1027
|
+
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
|
|
1028
|
+
|
|
1029
|
+
memcpy(buf, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE);
|
|
1030
|
+
*host_endian = 0;
|
|
1031
|
+
|
|
1032
|
+
return (LIBUSB_SUCCESS);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
int
|
|
1036
|
+
sunos_get_active_config_descriptor(struct libusb_device *dev,
|
|
1037
|
+
uint8_t *buf, size_t len, int *host_endian)
|
|
1038
|
+
{
|
|
1039
|
+
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
|
|
1040
|
+
struct libusb_config_descriptor *cfg;
|
|
1041
|
+
int proplen;
|
|
1042
|
+
di_node_t node;
|
|
1043
|
+
uint8_t *rdata;
|
|
1044
|
+
|
|
1045
|
+
/*
|
|
1046
|
+
* Keep raw configuration descriptors updated, in case config
|
|
1047
|
+
* has ever been changed through setCfg.
|
|
1048
|
+
*/
|
|
1049
|
+
if ((node = di_init(dpriv->phypath, DINFOCPYALL)) == DI_NODE_NIL) {
|
|
1050
|
+
usbi_dbg("di_int() failed: %s", strerror(errno));
|
|
1051
|
+
return (LIBUSB_ERROR_IO);
|
|
1052
|
+
}
|
|
1053
|
+
proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
|
|
1054
|
+
"usb-raw-cfg-descriptors", &rdata);
|
|
1055
|
+
if (proplen <= 0) {
|
|
1056
|
+
usbi_dbg("can't find raw config descriptors");
|
|
1057
|
+
|
|
1058
|
+
return (LIBUSB_ERROR_IO);
|
|
1059
|
+
}
|
|
1060
|
+
dpriv->raw_cfgdescr = realloc(dpriv->raw_cfgdescr, proplen);
|
|
1061
|
+
if (dpriv->raw_cfgdescr == NULL) {
|
|
1062
|
+
return (LIBUSB_ERROR_NO_MEM);
|
|
1063
|
+
} else {
|
|
1064
|
+
bcopy(rdata, dpriv->raw_cfgdescr, proplen);
|
|
1065
|
+
dpriv->cfgvalue = ((struct libusb_config_descriptor *)
|
|
1066
|
+
rdata)->bConfigurationValue;
|
|
1067
|
+
}
|
|
1068
|
+
di_fini(node);
|
|
1069
|
+
|
|
1070
|
+
cfg = (struct libusb_config_descriptor *)dpriv->raw_cfgdescr;
|
|
1071
|
+
len = MIN(len, libusb_le16_to_cpu(cfg->wTotalLength));
|
|
1072
|
+
memcpy(buf, dpriv->raw_cfgdescr, len);
|
|
1073
|
+
*host_endian = 0;
|
|
1074
|
+
usbi_dbg("path:%s len %d", dpriv->phypath, len);
|
|
1075
|
+
|
|
1076
|
+
return (len);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
int
|
|
1080
|
+
sunos_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
|
|
1081
|
+
uint8_t *buf, size_t len, int *host_endian)
|
|
1082
|
+
{
|
|
1083
|
+
/* XXX */
|
|
1084
|
+
return(sunos_get_active_config_descriptor(dev, buf, len, host_endian));
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
int
|
|
1088
|
+
sunos_get_configuration(struct libusb_device_handle *handle, int *config)
|
|
1089
|
+
{
|
|
1090
|
+
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
|
|
1091
|
+
|
|
1092
|
+
*config = dpriv->cfgvalue;
|
|
1093
|
+
|
|
1094
|
+
usbi_dbg("bConfigurationValue %d", *config);
|
|
1095
|
+
|
|
1096
|
+
return (LIBUSB_SUCCESS);
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
int
|
|
1100
|
+
sunos_set_configuration(struct libusb_device_handle *handle, int config)
|
|
1101
|
+
{
|
|
1102
|
+
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
|
|
1103
|
+
sunos_dev_handle_priv_t *hpriv;
|
|
1104
|
+
|
|
1105
|
+
usbi_dbg("bConfigurationValue %d", config);
|
|
1106
|
+
hpriv = (sunos_dev_handle_priv_t *)handle->os_priv;
|
|
1107
|
+
|
|
1108
|
+
if (dpriv->ugenpath == NULL)
|
|
1109
|
+
return (LIBUSB_ERROR_NOT_SUPPORTED);
|
|
1110
|
+
|
|
1111
|
+
if (config < 1 || config > dpriv->dev_descr.bNumConfigurations)
|
|
1112
|
+
return (LIBUSB_ERROR_INVALID_PARAM);
|
|
1113
|
+
|
|
1114
|
+
dpriv->cfgvalue = config;
|
|
1115
|
+
hpriv->config_index = config - 1;
|
|
1116
|
+
|
|
1117
|
+
return (LIBUSB_SUCCESS);
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
int
|
|
1121
|
+
sunos_claim_interface(struct libusb_device_handle *handle, int iface)
|
|
1122
|
+
{
|
|
1123
|
+
usbi_dbg("iface %d", iface);
|
|
1124
|
+
if (iface < 0) {
|
|
1125
|
+
return (LIBUSB_ERROR_INVALID_PARAM);
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
return (LIBUSB_SUCCESS);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
int
|
|
1132
|
+
sunos_release_interface(struct libusb_device_handle *handle, int iface)
|
|
1133
|
+
{
|
|
1134
|
+
sunos_dev_handle_priv_t *hpriv =
|
|
1135
|
+
(sunos_dev_handle_priv_t *)handle->os_priv;
|
|
1136
|
+
|
|
1137
|
+
usbi_dbg("iface %d", iface);
|
|
1138
|
+
if (iface < 0) {
|
|
1139
|
+
return (LIBUSB_ERROR_INVALID_PARAM);
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/* XXX: can we release it? */
|
|
1143
|
+
hpriv->altsetting[iface] = 0;
|
|
1144
|
+
|
|
1145
|
+
return (LIBUSB_SUCCESS);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
int
|
|
1149
|
+
sunos_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
|
|
1150
|
+
int altsetting)
|
|
1151
|
+
{
|
|
1152
|
+
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;
|
|
1153
|
+
sunos_dev_handle_priv_t *hpriv =
|
|
1154
|
+
(sunos_dev_handle_priv_t *)handle->os_priv;
|
|
1155
|
+
|
|
1156
|
+
usbi_dbg("iface %d, setting %d", iface, altsetting);
|
|
1157
|
+
|
|
1158
|
+
if (iface < 0 || altsetting < 0) {
|
|
1159
|
+
return (LIBUSB_ERROR_INVALID_PARAM);
|
|
1160
|
+
}
|
|
1161
|
+
if (dpriv->ugenpath == NULL)
|
|
1162
|
+
return (LIBUSB_ERROR_NOT_FOUND);
|
|
1163
|
+
|
|
1164
|
+
/* XXX: can we switch altsetting? */
|
|
1165
|
+
hpriv->altsetting[iface] = altsetting;
|
|
1166
|
+
|
|
1167
|
+
return (LIBUSB_SUCCESS);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
static void
|
|
1171
|
+
usb_dump_data(unsigned char *data, size_t size)
|
|
1172
|
+
{
|
|
1173
|
+
int i;
|
|
1174
|
+
|
|
1175
|
+
if (getenv("LIBUSB_DEBUG") == NULL) {
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
(void) fprintf(stderr, "data dump:");
|
|
1180
|
+
for (i = 0; i < size; i++) {
|
|
1181
|
+
if (i % 16 == 0) {
|
|
1182
|
+
(void) fprintf(stderr, "\n%08x ", i);
|
|
1183
|
+
}
|
|
1184
|
+
(void) fprintf(stderr, "%02x ", (uchar_t)data[i]);
|
|
1185
|
+
}
|
|
1186
|
+
(void) fprintf(stderr, "\n");
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
static void
|
|
1190
|
+
sunos_async_callback(union sigval arg)
|
|
1191
|
+
{
|
|
1192
|
+
struct sunos_transfer_priv *tpriv =
|
|
1193
|
+
(struct sunos_transfer_priv *)arg.sival_ptr;
|
|
1194
|
+
struct libusb_transfer *xfer = tpriv->transfer;
|
|
1195
|
+
struct aiocb *aiocb = &tpriv->aiocb;
|
|
1196
|
+
int ret;
|
|
1197
|
+
sunos_dev_handle_priv_t *hpriv;
|
|
1198
|
+
uint8_t ep;
|
|
1199
|
+
libusb_device_handle *dev_handle;
|
|
1200
|
+
|
|
1201
|
+
dev_handle = xfer->dev_handle;
|
|
1202
|
+
|
|
1203
|
+
/* libusb can forcibly interrupt transfer in do_close() */
|
|
1204
|
+
if (dev_handle != NULL) {
|
|
1205
|
+
hpriv = (sunos_dev_handle_priv_t *)dev_handle->os_priv;
|
|
1206
|
+
ep = sunos_usb_ep_index(xfer->endpoint);
|
|
1207
|
+
|
|
1208
|
+
ret = aio_error(aiocb);
|
|
1209
|
+
if (ret != 0) {
|
|
1210
|
+
xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd);
|
|
1211
|
+
} else {
|
|
1212
|
+
xfer->actual_length =
|
|
1213
|
+
LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred =
|
|
1214
|
+
aio_return(aiocb);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
usb_dump_data(xfer->buffer, xfer->actual_length);
|
|
1218
|
+
|
|
1219
|
+
usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length,
|
|
1220
|
+
xfer->actual_length);
|
|
1221
|
+
|
|
1222
|
+
/* async notification */
|
|
1223
|
+
usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer));
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
static int
|
|
1228
|
+
sunos_do_async_io(struct libusb_transfer *transfer)
|
|
1229
|
+
{
|
|
1230
|
+
int ret = -1;
|
|
1231
|
+
struct aiocb *aiocb;
|
|
1232
|
+
sunos_dev_handle_priv_t *hpriv;
|
|
1233
|
+
uint8_t ep;
|
|
1234
|
+
struct sunos_transfer_priv *tpriv;
|
|
1235
|
+
|
|
1236
|
+
usbi_dbg("");
|
|
1237
|
+
|
|
1238
|
+
tpriv = usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer));
|
|
1239
|
+
hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv;
|
|
1240
|
+
ep = sunos_usb_ep_index(transfer->endpoint);
|
|
1241
|
+
|
|
1242
|
+
tpriv->transfer = transfer;
|
|
1243
|
+
aiocb = &tpriv->aiocb;
|
|
1244
|
+
bzero(aiocb, sizeof (*aiocb));
|
|
1245
|
+
aiocb->aio_fildes = hpriv->eps[ep].datafd;
|
|
1246
|
+
aiocb->aio_buf = transfer->buffer;
|
|
1247
|
+
aiocb->aio_nbytes = transfer->length;
|
|
1248
|
+
aiocb->aio_lio_opcode =
|
|
1249
|
+
((transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) ==
|
|
1250
|
+
LIBUSB_ENDPOINT_IN) ? LIO_READ:LIO_WRITE;
|
|
1251
|
+
aiocb->aio_sigevent.sigev_notify = SIGEV_THREAD;
|
|
1252
|
+
aiocb->aio_sigevent.sigev_value.sival_ptr = tpriv;
|
|
1253
|
+
aiocb->aio_sigevent.sigev_notify_function = sunos_async_callback;
|
|
1254
|
+
|
|
1255
|
+
if (aiocb->aio_lio_opcode == LIO_READ) {
|
|
1256
|
+
ret = aio_read(aiocb);
|
|
1257
|
+
} else {
|
|
1258
|
+
ret = aio_write(aiocb);
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
return (ret);
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
/* return the number of bytes read/written */
|
|
1265
|
+
static int
|
|
1266
|
+
usb_do_io(int fd, int stat_fd, char *data, size_t size, int flag, int *status)
|
|
1267
|
+
{
|
|
1268
|
+
int error;
|
|
1269
|
+
int ret = -1;
|
|
1270
|
+
|
|
1271
|
+
usbi_dbg("usb_do_io(): datafd=%d statfd=%d size=0x%x flag=%s",
|
|
1272
|
+
fd, stat_fd, size, flag? "WRITE":"READ");
|
|
1273
|
+
|
|
1274
|
+
switch (flag) {
|
|
1275
|
+
case READ:
|
|
1276
|
+
errno = 0;
|
|
1277
|
+
ret = read(fd, data, size);
|
|
1278
|
+
usb_dump_data(data, size);
|
|
1279
|
+
break;
|
|
1280
|
+
case WRITE:
|
|
1281
|
+
usb_dump_data(data, size);
|
|
1282
|
+
errno = 0;
|
|
1283
|
+
ret = write(fd, data, size);
|
|
1284
|
+
break;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
usbi_dbg("usb_do_io(): amount=%d", ret);
|
|
1288
|
+
|
|
1289
|
+
if (ret < 0) {
|
|
1290
|
+
int save_errno = errno;
|
|
1291
|
+
|
|
1292
|
+
usbi_dbg("TID=%x io %s errno=%d(%s) ret=%d", pthread_self(),
|
|
1293
|
+
flag?"WRITE":"READ", errno, strerror(errno), ret);
|
|
1294
|
+
|
|
1295
|
+
/* sunos_usb_get_status will do a read and overwrite errno */
|
|
1296
|
+
error = sunos_usb_get_status(stat_fd);
|
|
1297
|
+
usbi_dbg("io status=%d errno=%d(%s)", error,
|
|
1298
|
+
save_errno, strerror(save_errno));
|
|
1299
|
+
|
|
1300
|
+
if (status) {
|
|
1301
|
+
*status = save_errno;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
return (save_errno);
|
|
1305
|
+
|
|
1306
|
+
} else if (status) {
|
|
1307
|
+
*status = 0;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
return (ret);
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
static int
|
|
1314
|
+
solaris_submit_ctrl_on_default(struct libusb_transfer *transfer)
|
|
1315
|
+
{
|
|
1316
|
+
int ret = -1, setup_ret;
|
|
1317
|
+
int status;
|
|
1318
|
+
sunos_dev_handle_priv_t *hpriv;
|
|
1319
|
+
struct libusb_device_handle *hdl = transfer->dev_handle;
|
|
1320
|
+
uint16_t wLength;
|
|
1321
|
+
uint8_t *data = transfer->buffer;
|
|
1322
|
+
|
|
1323
|
+
hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv;
|
|
1324
|
+
wLength = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
|
|
1325
|
+
|
|
1326
|
+
if (hpriv->eps[0].datafd == -1) {
|
|
1327
|
+
usbi_dbg("ep0 not opened");
|
|
1328
|
+
|
|
1329
|
+
return (LIBUSB_ERROR_NOT_FOUND);
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
if ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) {
|
|
1333
|
+
usbi_dbg("IN request");
|
|
1334
|
+
ret = usb_do_io(hpriv->eps[0].datafd,
|
|
1335
|
+
hpriv->eps[0].statfd, (char *)data, LIBUSB_CONTROL_SETUP_SIZE,
|
|
1336
|
+
WRITE, (int *)&status);
|
|
1337
|
+
} else {
|
|
1338
|
+
usbi_dbg("OUT request");
|
|
1339
|
+
ret = usb_do_io(hpriv->eps[0].datafd, hpriv->eps[0].statfd,
|
|
1340
|
+
transfer->buffer, transfer->length, WRITE,
|
|
1341
|
+
(int *)&transfer->status);
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
setup_ret = ret;
|
|
1345
|
+
if (ret < LIBUSB_CONTROL_SETUP_SIZE) {
|
|
1346
|
+
usbi_dbg("error sending control msg: %d", ret);
|
|
1347
|
+
|
|
1348
|
+
return (LIBUSB_ERROR_IO);
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
ret = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
|
|
1352
|
+
|
|
1353
|
+
/* Read the remaining bytes for IN request */
|
|
1354
|
+
if ((wLength) && ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) ==
|
|
1355
|
+
LIBUSB_ENDPOINT_IN)) {
|
|
1356
|
+
usbi_dbg("DATA: %d", transfer->length - setup_ret);
|
|
1357
|
+
ret = usb_do_io(hpriv->eps[0].datafd,
|
|
1358
|
+
hpriv->eps[0].statfd,
|
|
1359
|
+
(char *)transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE,
|
|
1360
|
+
wLength, READ, (int *)&transfer->status);
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
if (ret >= 0) {
|
|
1364
|
+
transfer->actual_length = ret;
|
|
1365
|
+
LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->transferred = ret;
|
|
1366
|
+
}
|
|
1367
|
+
usbi_dbg("Done: ctrl data bytes %d", ret);
|
|
1368
|
+
|
|
1369
|
+
/**
|
|
1370
|
+
* Sync transfer handling.
|
|
1371
|
+
* We should release transfer lock here and later get it back
|
|
1372
|
+
* as usbi_handle_transfer_completion() takes its own transfer lock.
|
|
1373
|
+
*/
|
|
1374
|
+
usbi_mutex_unlock(&LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->lock);
|
|
1375
|
+
ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer),
|
|
1376
|
+
transfer->status);
|
|
1377
|
+
usbi_mutex_lock(&LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->lock);
|
|
1378
|
+
|
|
1379
|
+
return (ret);
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
int
|
|
1383
|
+
sunos_clear_halt(struct libusb_device_handle *handle, uint8_t endpoint)
|
|
1384
|
+
{
|
|
1385
|
+
int ret;
|
|
1386
|
+
|
|
1387
|
+
usbi_dbg("endpoint=0x%02x", endpoint);
|
|
1388
|
+
|
|
1389
|
+
ret = libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT |
|
|
1390
|
+
LIBUSB_RECIPIENT_ENDPOINT | LIBUSB_REQUEST_TYPE_STANDARD,
|
|
1391
|
+
LIBUSB_REQUEST_CLEAR_FEATURE, 0, endpoint, NULL, 0, 1000);
|
|
1392
|
+
|
|
1393
|
+
usbi_dbg("ret=%d", ret);
|
|
1394
|
+
|
|
1395
|
+
return (ret);
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
int
|
|
1399
|
+
sunos_reset_device(struct libusb_device_handle *handle)
|
|
1400
|
+
{
|
|
1401
|
+
usbi_dbg("");
|
|
1402
|
+
|
|
1403
|
+
return (LIBUSB_ERROR_NOT_SUPPORTED);
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
void
|
|
1407
|
+
sunos_destroy_device(struct libusb_device *dev)
|
|
1408
|
+
{
|
|
1409
|
+
sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
|
|
1410
|
+
usbi_dbg("destroy everyting");
|
|
1411
|
+
free(dpriv->raw_cfgdescr);
|
|
1412
|
+
free(dpriv->ugenpath);
|
|
1413
|
+
free(dpriv->phypath);
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
int
|
|
1417
|
+
sunos_submit_transfer(struct usbi_transfer *itransfer)
|
|
1418
|
+
{
|
|
1419
|
+
struct libusb_transfer *transfer;
|
|
1420
|
+
struct libusb_device_handle *hdl;
|
|
1421
|
+
int err = 0;
|
|
1422
|
+
|
|
1423
|
+
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
1424
|
+
hdl = transfer->dev_handle;
|
|
1425
|
+
|
|
1426
|
+
err = sunos_check_device_and_status_open(hdl,
|
|
1427
|
+
transfer->endpoint, transfer->type);
|
|
1428
|
+
if (err < 0) {
|
|
1429
|
+
|
|
1430
|
+
return (_errno_to_libusb(err));
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
switch (transfer->type) {
|
|
1434
|
+
case LIBUSB_TRANSFER_TYPE_CONTROL:
|
|
1435
|
+
/* sync transfer */
|
|
1436
|
+
usbi_dbg("CTRL transfer: %d", transfer->length);
|
|
1437
|
+
err = solaris_submit_ctrl_on_default(transfer);
|
|
1438
|
+
break;
|
|
1439
|
+
|
|
1440
|
+
case LIBUSB_TRANSFER_TYPE_BULK:
|
|
1441
|
+
/* fallthru */
|
|
1442
|
+
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
|
|
1443
|
+
if (transfer->type == LIBUSB_TRANSFER_TYPE_BULK)
|
|
1444
|
+
usbi_dbg("BULK transfer: %d", transfer->length);
|
|
1445
|
+
else
|
|
1446
|
+
usbi_dbg("INTR transfer: %d", transfer->length);
|
|
1447
|
+
err = sunos_do_async_io(transfer);
|
|
1448
|
+
break;
|
|
1449
|
+
|
|
1450
|
+
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
|
|
1451
|
+
/* Isochronous/Stream is not supported */
|
|
1452
|
+
|
|
1453
|
+
/* fallthru */
|
|
1454
|
+
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
|
|
1455
|
+
if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS)
|
|
1456
|
+
usbi_dbg("ISOC transfer: %d", transfer->length);
|
|
1457
|
+
else
|
|
1458
|
+
usbi_dbg("BULK STREAM transfer: %d", transfer->length);
|
|
1459
|
+
err = LIBUSB_ERROR_NOT_SUPPORTED;
|
|
1460
|
+
break;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
return (err);
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
int
|
|
1467
|
+
sunos_cancel_transfer(struct usbi_transfer *itransfer)
|
|
1468
|
+
{
|
|
1469
|
+
sunos_xfer_priv_t *tpriv;
|
|
1470
|
+
sunos_dev_handle_priv_t *hpriv;
|
|
1471
|
+
struct libusb_transfer *transfer;
|
|
1472
|
+
struct aiocb *aiocb;
|
|
1473
|
+
uint8_t ep;
|
|
1474
|
+
int ret;
|
|
1475
|
+
|
|
1476
|
+
tpriv = usbi_transfer_get_os_priv(itransfer);
|
|
1477
|
+
aiocb = &tpriv->aiocb;
|
|
1478
|
+
transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
|
1479
|
+
hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv;
|
|
1480
|
+
ep = sunos_usb_ep_index(transfer->endpoint);
|
|
1481
|
+
|
|
1482
|
+
ret = aio_cancel(hpriv->eps[ep].datafd, aiocb);
|
|
1483
|
+
|
|
1484
|
+
usbi_dbg("aio->fd=%d fd=%d ret = %d, %s", aiocb->aio_fildes,
|
|
1485
|
+
hpriv->eps[ep].datafd, ret, (ret == AIO_CANCELED)?
|
|
1486
|
+
strerror(0):strerror(errno));
|
|
1487
|
+
|
|
1488
|
+
if (ret != AIO_CANCELED) {
|
|
1489
|
+
ret = _errno_to_libusb(errno);
|
|
1490
|
+
} else {
|
|
1491
|
+
/*
|
|
1492
|
+
* we don't need to call usbi_handle_transfer_cancellation(),
|
|
1493
|
+
* because we'll handle everything in sunos_async_callback.
|
|
1494
|
+
*/
|
|
1495
|
+
ret = LIBUSB_SUCCESS;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
return (ret);
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
void
|
|
1502
|
+
sunos_clear_transfer_priv(struct usbi_transfer *itransfer)
|
|
1503
|
+
{
|
|
1504
|
+
usbi_dbg("");
|
|
1505
|
+
|
|
1506
|
+
/* Nothing to do */
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
int
|
|
1510
|
+
sunos_handle_transfer_completion(struct usbi_transfer *itransfer)
|
|
1511
|
+
{
|
|
1512
|
+
return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
int
|
|
1516
|
+
sunos_clock_gettime(int clkid, struct timespec *tp)
|
|
1517
|
+
{
|
|
1518
|
+
if (clkid == USBI_CLOCK_REALTIME)
|
|
1519
|
+
return clock_gettime(CLOCK_REALTIME, tp);
|
|
1520
|
+
|
|
1521
|
+
if (clkid == USBI_CLOCK_MONOTONIC)
|
|
1522
|
+
return clock_gettime(CLOCK_MONOTONIC, tp);
|
|
1523
|
+
|
|
1524
|
+
return (LIBUSB_ERROR_INVALID_PARAM);
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
int
|
|
1528
|
+
_errno_to_libusb(int err)
|
|
1529
|
+
{
|
|
1530
|
+
usbi_dbg("error: %s (%d)", strerror(err), err);
|
|
1531
|
+
|
|
1532
|
+
switch (err) {
|
|
1533
|
+
case EIO:
|
|
1534
|
+
return (LIBUSB_ERROR_IO);
|
|
1535
|
+
case EACCES:
|
|
1536
|
+
return (LIBUSB_ERROR_ACCESS);
|
|
1537
|
+
case ENOENT:
|
|
1538
|
+
return (LIBUSB_ERROR_NO_DEVICE);
|
|
1539
|
+
case ENOMEM:
|
|
1540
|
+
return (LIBUSB_ERROR_NO_MEM);
|
|
1541
|
+
case ETIMEDOUT:
|
|
1542
|
+
return (LIBUSB_ERROR_TIMEOUT);
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
return (LIBUSB_ERROR_OTHER);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
/*
|
|
1549
|
+
* sunos_usb_get_status:
|
|
1550
|
+
* gets status of endpoint
|
|
1551
|
+
*
|
|
1552
|
+
* Returns: ugen's last cmd status
|
|
1553
|
+
*/
|
|
1554
|
+
static int
|
|
1555
|
+
sunos_usb_get_status(int fd)
|
|
1556
|
+
{
|
|
1557
|
+
int status, ret;
|
|
1558
|
+
|
|
1559
|
+
usbi_dbg("sunos_usb_get_status(): fd=%d", fd);
|
|
1560
|
+
|
|
1561
|
+
ret = read(fd, &status, sizeof (status));
|
|
1562
|
+
if (ret == sizeof (status)) {
|
|
1563
|
+
switch (status) {
|
|
1564
|
+
case USB_LC_STAT_NOERROR:
|
|
1565
|
+
usbi_dbg("No Error");
|
|
1566
|
+
break;
|
|
1567
|
+
case USB_LC_STAT_CRC:
|
|
1568
|
+
usbi_dbg("CRC Timeout Detected\n");
|
|
1569
|
+
break;
|
|
1570
|
+
case USB_LC_STAT_BITSTUFFING:
|
|
1571
|
+
usbi_dbg("Bit Stuffing Violation\n");
|
|
1572
|
+
break;
|
|
1573
|
+
case USB_LC_STAT_DATA_TOGGLE_MM:
|
|
1574
|
+
usbi_dbg("Data Toggle Mismatch\n");
|
|
1575
|
+
break;
|
|
1576
|
+
case USB_LC_STAT_STALL:
|
|
1577
|
+
usbi_dbg("End Point Stalled\n");
|
|
1578
|
+
break;
|
|
1579
|
+
case USB_LC_STAT_DEV_NOT_RESP:
|
|
1580
|
+
usbi_dbg("Device is Not Responding\n");
|
|
1581
|
+
break;
|
|
1582
|
+
case USB_LC_STAT_PID_CHECKFAILURE:
|
|
1583
|
+
usbi_dbg("PID Check Failure\n");
|
|
1584
|
+
break;
|
|
1585
|
+
case USB_LC_STAT_UNEXP_PID:
|
|
1586
|
+
usbi_dbg("Unexpected PID\n");
|
|
1587
|
+
break;
|
|
1588
|
+
case USB_LC_STAT_DATA_OVERRUN:
|
|
1589
|
+
usbi_dbg("Data Exceeded Size\n");
|
|
1590
|
+
break;
|
|
1591
|
+
case USB_LC_STAT_DATA_UNDERRUN:
|
|
1592
|
+
usbi_dbg("Less data received\n");
|
|
1593
|
+
break;
|
|
1594
|
+
case USB_LC_STAT_BUFFER_OVERRUN:
|
|
1595
|
+
usbi_dbg("Buffer Size Exceeded\n");
|
|
1596
|
+
break;
|
|
1597
|
+
case USB_LC_STAT_BUFFER_UNDERRUN:
|
|
1598
|
+
usbi_dbg("Buffer Underrun\n");
|
|
1599
|
+
break;
|
|
1600
|
+
case USB_LC_STAT_TIMEOUT:
|
|
1601
|
+
usbi_dbg("Command Timed Out\n");
|
|
1602
|
+
break;
|
|
1603
|
+
case USB_LC_STAT_NOT_ACCESSED:
|
|
1604
|
+
usbi_dbg("Not Accessed by h/w\n");
|
|
1605
|
+
break;
|
|
1606
|
+
case USB_LC_STAT_UNSPECIFIED_ERR:
|
|
1607
|
+
usbi_dbg("Unspecified Error\n");
|
|
1608
|
+
break;
|
|
1609
|
+
case USB_LC_STAT_NO_BANDWIDTH:
|
|
1610
|
+
usbi_dbg("No Bandwidth\n");
|
|
1611
|
+
break;
|
|
1612
|
+
case USB_LC_STAT_HW_ERR:
|
|
1613
|
+
usbi_dbg("Host Controller h/w Error\n");
|
|
1614
|
+
break;
|
|
1615
|
+
case USB_LC_STAT_SUSPENDED:
|
|
1616
|
+
usbi_dbg("Device was Suspended\n");
|
|
1617
|
+
break;
|
|
1618
|
+
case USB_LC_STAT_DISCONNECTED:
|
|
1619
|
+
usbi_dbg("Device was Disconnected\n");
|
|
1620
|
+
break;
|
|
1621
|
+
case USB_LC_STAT_INTR_BUF_FULL:
|
|
1622
|
+
usbi_dbg("Interrupt buffer was full\n");
|
|
1623
|
+
break;
|
|
1624
|
+
case USB_LC_STAT_INVALID_REQ:
|
|
1625
|
+
usbi_dbg("Request was Invalid\n");
|
|
1626
|
+
break;
|
|
1627
|
+
case USB_LC_STAT_INTERRUPTED:
|
|
1628
|
+
usbi_dbg("Request was Interrupted\n");
|
|
1629
|
+
break;
|
|
1630
|
+
case USB_LC_STAT_NO_RESOURCES:
|
|
1631
|
+
usbi_dbg("No resources available for "
|
|
1632
|
+
"request\n");
|
|
1633
|
+
break;
|
|
1634
|
+
case USB_LC_STAT_INTR_POLLING_FAILED:
|
|
1635
|
+
usbi_dbg("Failed to Restart Poll");
|
|
1636
|
+
break;
|
|
1637
|
+
default:
|
|
1638
|
+
usbi_dbg("Error Not Determined %d\n",
|
|
1639
|
+
status);
|
|
1640
|
+
break;
|
|
1641
|
+
}
|
|
1642
|
+
} else {
|
|
1643
|
+
usbi_dbg("read stat error: %s",strerror(errno));
|
|
1644
|
+
status = -1;
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
return (status);
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
#ifdef USBI_TIMERFD_AVAILABLE
|
|
1651
|
+
static clockid_t op_get_timerfd_clockid(void)
|
|
1652
|
+
{
|
|
1653
|
+
return CLOCK_MONOTONIC;
|
|
1654
|
+
}
|
|
1655
|
+
#endif
|
|
1656
|
+
|
|
1657
|
+
const struct usbi_os_backend usbi_backend = {
|
|
1658
|
+
.name = "Solaris",
|
|
1659
|
+
.caps = 0,
|
|
1660
|
+
.init = sunos_init,
|
|
1661
|
+
.exit = sunos_exit,
|
|
1662
|
+
.get_device_list = sunos_get_device_list,
|
|
1663
|
+
.get_device_descriptor = sunos_get_device_descriptor,
|
|
1664
|
+
.get_active_config_descriptor = sunos_get_active_config_descriptor,
|
|
1665
|
+
.get_config_descriptor = sunos_get_config_descriptor,
|
|
1666
|
+
.hotplug_poll = NULL,
|
|
1667
|
+
.open = sunos_open,
|
|
1668
|
+
.close = sunos_close,
|
|
1669
|
+
.get_configuration = sunos_get_configuration,
|
|
1670
|
+
.set_configuration = sunos_set_configuration,
|
|
1671
|
+
|
|
1672
|
+
.claim_interface = sunos_claim_interface,
|
|
1673
|
+
.release_interface = sunos_release_interface,
|
|
1674
|
+
.set_interface_altsetting = sunos_set_interface_altsetting,
|
|
1675
|
+
.clear_halt = sunos_clear_halt,
|
|
1676
|
+
.reset_device = sunos_reset_device, /* TODO */
|
|
1677
|
+
.alloc_streams = NULL,
|
|
1678
|
+
.free_streams = NULL,
|
|
1679
|
+
.kernel_driver_active = sunos_kernel_driver_active,
|
|
1680
|
+
.detach_kernel_driver = sunos_detach_kernel_driver,
|
|
1681
|
+
.attach_kernel_driver = sunos_attach_kernel_driver,
|
|
1682
|
+
.destroy_device = sunos_destroy_device,
|
|
1683
|
+
.submit_transfer = sunos_submit_transfer,
|
|
1684
|
+
.cancel_transfer = sunos_cancel_transfer,
|
|
1685
|
+
.handle_events = NULL,
|
|
1686
|
+
.clear_transfer_priv = sunos_clear_transfer_priv,
|
|
1687
|
+
.handle_transfer_completion = sunos_handle_transfer_completion,
|
|
1688
|
+
.clock_gettime = sunos_clock_gettime,
|
|
1689
|
+
#ifdef USBI_TIMERFD_AVAILABLE
|
|
1690
|
+
.get_timerfd_clockid = op_get_timerfd_clockid,
|
|
1691
|
+
#endif
|
|
1692
|
+
.device_priv_size = sizeof(sunos_dev_priv_t),
|
|
1693
|
+
.device_handle_priv_size = sizeof(sunos_dev_handle_priv_t),
|
|
1694
|
+
.transfer_priv_size = sizeof(sunos_xfer_priv_t),
|
|
1695
|
+
};
|