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.
Files changed (188) hide show
  1. package/.gitmodules +1 -1
  2. package/Readme.md +2 -2
  3. package/binding.gyp +2 -2
  4. package/libusb/.private/pre-commit.sh +7 -1
  5. package/libusb/.travis.yml +49 -0
  6. package/libusb/AUTHORS +44 -3
  7. package/libusb/Brewfile +4 -0
  8. package/libusb/ChangeLog +74 -2
  9. package/libusb/README.md +32 -0
  10. package/libusb/TODO +1 -1
  11. package/libusb/Xcode/common.xcconfig +12 -0
  12. package/libusb/Xcode/config.h +25 -0
  13. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +959 -1
  14. package/libusb/android/README +4 -2
  15. package/libusb/android/config.h +75 -0
  16. package/libusb/appveyor.yml +41 -0
  17. package/libusb/appveyor_cygwin.bat +11 -0
  18. package/libusb/appveyor_minGW.bat +19 -0
  19. package/libusb/autogen.sh +1 -1
  20. package/libusb/bootstrap.sh +3 -16
  21. package/libusb/configure.ac +108 -80
  22. package/libusb/doc/doxygen.cfg.in +1785 -739
  23. package/libusb/examples/Makefile.am +1 -1
  24. package/libusb/examples/dpfp.c +3 -1
  25. package/libusb/examples/dpfp_threaded.c +23 -10
  26. package/libusb/examples/ezusb.c +3 -3
  27. package/libusb/examples/ezusb.h +2 -2
  28. package/libusb/examples/fxload.c +31 -9
  29. package/libusb/examples/hotplugtest.c +35 -7
  30. package/libusb/examples/listdevs.c +3 -1
  31. package/libusb/examples/sam3u_benchmark.c +3 -3
  32. package/libusb/examples/testlibusb.c +277 -0
  33. package/libusb/examples/xusb.c +40 -34
  34. package/libusb/libusb/Makefile.am +49 -23
  35. package/libusb/libusb/core.c +855 -457
  36. package/libusb/libusb/descriptor.c +72 -78
  37. package/libusb/libusb/hotplug.c +122 -76
  38. package/libusb/libusb/hotplug.h +42 -25
  39. package/libusb/libusb/io.c +625 -390
  40. package/libusb/libusb/libusb-1.0.def +12 -0
  41. package/libusb/libusb/libusb.h +218 -150
  42. package/libusb/libusb/libusbi.h +346 -176
  43. package/libusb/libusb/os/darwin_usb.c +604 -319
  44. package/libusb/libusb/os/darwin_usb.h +61 -20
  45. package/libusb/libusb/os/haiku_pollfs.cpp +367 -0
  46. package/libusb/libusb/os/haiku_usb.h +113 -0
  47. package/libusb/libusb/os/haiku_usb_backend.cpp +533 -0
  48. package/libusb/libusb/os/haiku_usb_raw.cpp +267 -0
  49. package/libusb/libusb/os/haiku_usb_raw.h +188 -0
  50. package/libusb/libusb/os/linux_netlink.c +186 -146
  51. package/libusb/libusb/os/linux_udev.c +36 -14
  52. package/libusb/libusb/os/linux_usbfs.c +426 -225
  53. package/libusb/libusb/os/linux_usbfs.h +5 -3
  54. package/libusb/libusb/os/netbsd_usb.c +21 -77
  55. package/libusb/libusb/os/openbsd_usb.c +32 -115
  56. package/libusb/libusb/os/poll_posix.c +38 -5
  57. package/libusb/libusb/os/poll_posix.h +3 -0
  58. package/libusb/libusb/os/poll_windows.c +277 -626
  59. package/libusb/libusb/os/poll_windows.h +11 -44
  60. package/libusb/libusb/os/sunos_usb.c +1695 -0
  61. package/libusb/libusb/os/sunos_usb.h +80 -0
  62. package/libusb/libusb/os/threads_posix.c +24 -26
  63. package/libusb/libusb/os/threads_posix.h +73 -21
  64. package/libusb/libusb/os/threads_windows.c +71 -157
  65. package/libusb/libusb/os/threads_windows.h +68 -44
  66. package/libusb/libusb/os/wince_usb.c +276 -420
  67. package/libusb/libusb/os/wince_usb.h +23 -28
  68. package/libusb/libusb/os/windows_common.h +78 -58
  69. package/libusb/libusb/os/windows_nt_common.c +1010 -0
  70. package/libusb/libusb/os/windows_nt_common.h +110 -0
  71. package/libusb/libusb/os/windows_nt_shared_types.h +147 -0
  72. package/libusb/libusb/os/windows_usbdk.c +830 -0
  73. package/libusb/libusb/os/windows_usbdk.h +103 -0
  74. package/libusb/libusb/os/windows_winusb.c +4391 -0
  75. package/libusb/libusb/os/windows_winusb.h +783 -0
  76. package/libusb/libusb/strerror.c +41 -7
  77. package/libusb/libusb/sync.c +41 -13
  78. package/libusb/libusb/version.h +1 -1
  79. package/libusb/libusb/version_nano.h +1 -1
  80. package/libusb/libusb-1.0.pc.in +1 -1
  81. package/libusb/msvc/appveyor.bat +27 -0
  82. package/libusb/msvc/config.h +5 -4
  83. package/libusb/msvc/ddk_build.cmd +87 -43
  84. package/libusb/msvc/fxload_2010.vcxproj +24 -104
  85. package/libusb/msvc/fxload_2012.vcxproj +24 -107
  86. package/libusb/msvc/fxload_2013.vcxproj +24 -107
  87. package/libusb/msvc/fxload_2015.vcxproj +91 -0
  88. package/libusb/msvc/fxload_2017.vcxproj +114 -0
  89. package/libusb/msvc/fxload_sources +1 -1
  90. package/libusb/msvc/getopt_2010.vcxproj +16 -75
  91. package/libusb/msvc/getopt_2012.vcxproj +16 -79
  92. package/libusb/msvc/getopt_2013.vcxproj +16 -79
  93. package/libusb/msvc/getopt_2015.vcxproj +73 -0
  94. package/libusb/msvc/getopt_2017.vcxproj +98 -0
  95. package/libusb/msvc/getopt_sources +6 -2
  96. package/libusb/msvc/hotplugtest_2010.vcxproj +18 -99
  97. package/libusb/msvc/hotplugtest_2012.vcxproj +18 -102
  98. package/libusb/msvc/hotplugtest_2013.vcxproj +18 -102
  99. package/libusb/msvc/hotplugtest_2015.vcxproj +83 -0
  100. package/libusb/msvc/hotplugtest_2017.vcxproj +106 -0
  101. package/libusb/msvc/hotplugtest_sources +1 -1
  102. package/libusb/msvc/libusb_2005.sln +20 -20
  103. package/libusb/msvc/libusb_2010.sln +57 -46
  104. package/libusb/msvc/libusb_2012.sln +57 -46
  105. package/libusb/msvc/libusb_2013.sln +57 -50
  106. package/libusb/msvc/libusb_2015.sln +59 -52
  107. package/libusb/msvc/libusb_2017.sln +186 -0
  108. package/libusb/msvc/libusb_dll.dsp +2 -2
  109. package/libusb/msvc/libusb_dll_2005.vcproj +30 -2
  110. package/libusb/msvc/libusb_dll_2010.vcxproj +26 -90
  111. package/libusb/msvc/libusb_dll_2012.vcxproj +28 -96
  112. package/libusb/msvc/libusb_dll_2013.vcxproj +28 -96
  113. package/libusb/msvc/libusb_dll_2015.vcxproj +107 -0
  114. package/libusb/msvc/libusb_dll_2017.vcxproj +134 -0
  115. package/libusb/msvc/libusb_dll_wince.vcproj +9 -1
  116. package/libusb/msvc/libusb_sources +10 -5
  117. package/libusb/msvc/libusb_static.dsp +2 -2
  118. package/libusb/msvc/libusb_static_2005.vcproj +32 -4
  119. package/libusb/msvc/libusb_static_2010.vcxproj +24 -83
  120. package/libusb/msvc/libusb_static_2012.vcxproj +25 -87
  121. package/libusb/msvc/libusb_static_2013.vcxproj +25 -87
  122. package/libusb/msvc/libusb_static_2015.vcxproj +98 -0
  123. package/libusb/msvc/libusb_static_2017.vcxproj +117 -0
  124. package/libusb/msvc/libusb_static_wince.vcproj +20 -26
  125. package/libusb/msvc/libusb_wince.sln +88 -88
  126. package/libusb/msvc/listdevs_2010.vcxproj +16 -99
  127. package/libusb/msvc/listdevs_2012.vcxproj +16 -102
  128. package/libusb/msvc/listdevs_2013.vcxproj +16 -102
  129. package/libusb/msvc/listdevs_2015.vcxproj +83 -0
  130. package/libusb/msvc/listdevs_2017.vcxproj +106 -0
  131. package/libusb/msvc/listdevs_sources +2 -1
  132. package/libusb/msvc/stress_2010.vcxproj +20 -101
  133. package/libusb/msvc/stress_2012.vcxproj +20 -104
  134. package/libusb/msvc/stress_2013.vcxproj +20 -104
  135. package/libusb/msvc/stress_2015.vcxproj +87 -0
  136. package/libusb/msvc/stress_2017.vcxproj +110 -0
  137. package/libusb/msvc/stress_sources +21 -0
  138. package/libusb/msvc/testlibusb_2010.vcxproj +82 -0
  139. package/libusb/msvc/testlibusb_2012.vcxproj +83 -0
  140. package/libusb/msvc/testlibusb_2013.vcxproj +83 -0
  141. package/libusb/msvc/testlibusb_2015.vcxproj +83 -0
  142. package/libusb/msvc/testlibusb_2017.vcxproj +106 -0
  143. package/libusb/msvc/testlibusb_sources +20 -0
  144. package/libusb/msvc/xusb_2010.vcxproj +17 -98
  145. package/libusb/msvc/xusb_2012.vcxproj +17 -101
  146. package/libusb/msvc/xusb_2013.vcxproj +17 -101
  147. package/libusb/msvc/xusb_2015.vcxproj +83 -0
  148. package/libusb/msvc/xusb_2017.vcxproj +106 -0
  149. package/libusb/msvc/xusb_sources +1 -1
  150. package/libusb/tests/stress.c +2 -2
  151. package/libusb/tests/testlib.c +0 -4
  152. package/libusb/travis-autogen.sh +39 -0
  153. package/libusb.gypi +13 -2
  154. package/package.json +20 -11
  155. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  156. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  157. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  158. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  159. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  160. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  161. package/prebuilds/linux-ia32/node.napi.node +0 -0
  162. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  163. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  164. package/prebuilds/win32-ia32/node.napi.node +0 -0
  165. package/prebuilds/win32-x64/node.napi.node +0 -0
  166. package/src/device.cc +1 -1
  167. package/usb.js +1 -1
  168. package/.github/workflows/prebuild.yml +0 -49
  169. package/libusb/INSTALL +0 -234
  170. package/libusb/README +0 -28
  171. package/libusb/libusb/os/windows_usb.c +0 -5347
  172. package/libusb/libusb/os/windows_usb.h +0 -971
  173. package/libusb/msvc/fxload_2010.vcxproj.filters +0 -25
  174. package/libusb/msvc/fxload_2012.vcxproj.filters +0 -25
  175. package/libusb/msvc/getopt_2010.vcxproj.filters +0 -26
  176. package/libusb/msvc/getopt_2012.vcxproj.filters +0 -26
  177. package/libusb/msvc/hotplugtest_2010.vcxproj.filters +0 -14
  178. package/libusb/msvc/hotplugtest_2012.vcxproj.filters +0 -14
  179. package/libusb/msvc/libusb_dll_2010.vcxproj.filters +0 -81
  180. package/libusb/msvc/libusb_dll_2012.vcxproj.filters +0 -84
  181. package/libusb/msvc/libusb_static_2010.vcxproj.filters +0 -74
  182. package/libusb/msvc/libusb_static_2012.vcxproj.filters +0 -74
  183. package/libusb/msvc/listdevs_2010.vcxproj.filters +0 -14
  184. package/libusb/msvc/listdevs_2012.vcxproj.filters +0 -14
  185. package/libusb/msvc/stress_2010.vcxproj.filters +0 -25
  186. package/libusb/msvc/stress_2012.vcxproj.filters +0 -25
  187. package/libusb/msvc/xusb_2010.vcxproj.filters +0 -14
  188. 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 **)&regbuf);
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
+ };