libusb 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.gitignore +8 -0
  2. data/.travis.yml +10 -0
  3. data/.yardopts +6 -1
  4. data/Gemfile +16 -0
  5. data/{History.txt → History.md} +28 -16
  6. data/README.md +144 -0
  7. data/Rakefile +28 -24
  8. data/ext/extconf.rb +33 -0
  9. data/ext/libusbx-1.0.14/AUTHORS +50 -0
  10. data/ext/libusbx-1.0.14/COPYING +504 -0
  11. data/ext/libusbx-1.0.14/ChangeLog +139 -0
  12. data/ext/libusbx-1.0.14/INSTALL +234 -0
  13. data/ext/libusbx-1.0.14/Makefile.am +23 -0
  14. data/ext/libusbx-1.0.14/Makefile.in +803 -0
  15. data/ext/libusbx-1.0.14/NEWS +2 -0
  16. data/ext/libusbx-1.0.14/PORTING +94 -0
  17. data/ext/libusbx-1.0.14/README +28 -0
  18. data/ext/libusbx-1.0.14/THANKS +7 -0
  19. data/ext/libusbx-1.0.14/TODO +2 -0
  20. data/ext/libusbx-1.0.14/aclocal.m4 +9480 -0
  21. data/ext/libusbx-1.0.14/compile +143 -0
  22. data/ext/libusbx-1.0.14/config.guess +1501 -0
  23. data/ext/libusbx-1.0.14/config.h.in +116 -0
  24. data/ext/libusbx-1.0.14/config.sub +1705 -0
  25. data/ext/libusbx-1.0.14/configure +14818 -0
  26. data/ext/libusbx-1.0.14/configure.ac +230 -0
  27. data/ext/libusbx-1.0.14/depcomp +630 -0
  28. data/ext/libusbx-1.0.14/doc/Makefile.am +9 -0
  29. data/ext/libusbx-1.0.14/doc/Makefile.in +380 -0
  30. data/ext/libusbx-1.0.14/doc/doxygen.cfg.in +1288 -0
  31. data/ext/libusbx-1.0.14/examples/Makefile.am +18 -0
  32. data/ext/libusbx-1.0.14/examples/Makefile.in +596 -0
  33. data/ext/libusbx-1.0.14/examples/dpfp.c +506 -0
  34. data/ext/libusbx-1.0.14/examples/dpfp_threaded.c +544 -0
  35. data/ext/libusbx-1.0.14/examples/ezusb.c +616 -0
  36. data/ext/libusbx-1.0.14/examples/ezusb.h +107 -0
  37. data/ext/libusbx-1.0.14/examples/fxload.c +261 -0
  38. data/ext/libusbx-1.0.14/examples/getopt/getopt.c +1060 -0
  39. data/ext/libusbx-1.0.14/examples/getopt/getopt.h +180 -0
  40. data/ext/libusbx-1.0.14/examples/getopt/getopt1.c +188 -0
  41. data/ext/libusbx-1.0.14/examples/listdevs.c +63 -0
  42. data/ext/libusbx-1.0.14/examples/xusb.c +1036 -0
  43. data/ext/libusbx-1.0.14/install-sh +520 -0
  44. data/ext/libusbx-1.0.14/libusb-1.0.pc.in +11 -0
  45. data/ext/libusbx-1.0.14/libusb/Makefile.am +56 -0
  46. data/ext/libusbx-1.0.14/libusb/Makefile.in +721 -0
  47. data/ext/libusbx-1.0.14/libusb/core.c +1951 -0
  48. data/ext/libusbx-1.0.14/libusb/descriptor.c +731 -0
  49. data/ext/libusbx-1.0.14/libusb/io.c +2450 -0
  50. data/ext/libusbx-1.0.14/libusb/libusb-1.0.def +126 -0
  51. data/ext/libusbx-1.0.14/libusb/libusb-1.0.rc +59 -0
  52. data/ext/libusbx-1.0.14/libusb/libusb.h +1506 -0
  53. data/ext/libusbx-1.0.14/libusb/libusbi.h +910 -0
  54. data/ext/libusbx-1.0.14/libusb/os/darwin_usb.c +1807 -0
  55. data/ext/libusbx-1.0.14/libusb/os/darwin_usb.h +169 -0
  56. data/ext/libusbx-1.0.14/libusb/os/linux_usbfs.c +2569 -0
  57. data/ext/libusbx-1.0.14/libusb/os/linux_usbfs.h +149 -0
  58. data/ext/libusbx-1.0.14/libusb/os/openbsd_usb.c +727 -0
  59. data/ext/libusbx-1.0.14/libusb/os/poll_posix.h +10 -0
  60. data/ext/libusbx-1.0.14/libusb/os/poll_windows.c +747 -0
  61. data/ext/libusbx-1.0.14/libusb/os/poll_windows.h +114 -0
  62. data/ext/libusbx-1.0.14/libusb/os/threads_posix.c +80 -0
  63. data/ext/libusbx-1.0.14/libusb/os/threads_posix.h +50 -0
  64. data/ext/libusbx-1.0.14/libusb/os/threads_windows.c +211 -0
  65. data/ext/libusbx-1.0.14/libusb/os/threads_windows.h +87 -0
  66. data/ext/libusbx-1.0.14/libusb/os/windows_usb.c +4369 -0
  67. data/ext/libusbx-1.0.14/libusb/os/windows_usb.h +979 -0
  68. data/ext/libusbx-1.0.14/libusb/sync.c +321 -0
  69. data/ext/libusbx-1.0.14/libusb/version.h +18 -0
  70. data/ext/libusbx-1.0.14/libusb/version_nano.h +1 -0
  71. data/ext/libusbx-1.0.14/ltmain.sh +9636 -0
  72. data/ext/libusbx-1.0.14/missing +376 -0
  73. data/lib/libusb.rb +2 -3
  74. data/lib/libusb/call.rb +49 -7
  75. data/lib/libusb/compat.rb +15 -9
  76. data/lib/libusb/configuration.rb +15 -3
  77. data/lib/libusb/constants.rb +19 -6
  78. data/lib/libusb/context.rb +181 -3
  79. data/lib/libusb/dev_handle.rb +91 -40
  80. data/lib/libusb/endpoint.rb +41 -14
  81. data/lib/libusb/eventmachine.rb +183 -0
  82. data/lib/libusb/transfer.rb +21 -8
  83. data/lib/libusb/version_gem.rb +19 -0
  84. data/lib/libusb/{version.rb → version_struct.rb} +0 -0
  85. data/libusb.gemspec +31 -0
  86. data/test/test_libusb_compat.rb +1 -1
  87. data/test/test_libusb_compat_mass_storage.rb +2 -2
  88. data/test/test_libusb_descriptors.rb +1 -1
  89. data/test/test_libusb_event_machine.rb +118 -0
  90. data/test/test_libusb_iso_transfer.rb +6 -1
  91. data/test/test_libusb_mass_storage.rb +9 -3
  92. data/test/test_libusb_mass_storage2.rb +1 -1
  93. data/test/test_libusb_structs.rb +45 -0
  94. data/test/test_libusb_threads.rb +89 -0
  95. data/test/test_libusb_version.rb +4 -0
  96. metadata +109 -44
  97. data/.autotest +0 -23
  98. data/.gemtest +0 -0
  99. data/Manifest.txt +0 -3
  100. data/README.rdoc +0 -115
  101. data/test/test_libusb_keyboard.rb +0 -50
@@ -0,0 +1,149 @@
1
+ /*
2
+ * usbfs header structures
3
+ * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
4
+ * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+ #ifndef LIBUSB_USBFS_H
22
+ #define LIBUSB_USBFS_H
23
+
24
+ #include <linux/types.h>
25
+
26
+ #define SYSFS_DEVICE_PATH "/sys/bus/usb/devices"
27
+
28
+ struct usbfs_ctrltransfer {
29
+ /* keep in sync with usbdevice_fs.h:usbdevfs_ctrltransfer */
30
+ uint8_t bmRequestType;
31
+ uint8_t bRequest;
32
+ uint16_t wValue;
33
+ uint16_t wIndex;
34
+ uint16_t wLength;
35
+
36
+ uint32_t timeout; /* in milliseconds */
37
+
38
+ /* pointer to data */
39
+ void *data;
40
+ };
41
+
42
+ struct usbfs_bulktransfer {
43
+ /* keep in sync with usbdevice_fs.h:usbdevfs_bulktransfer */
44
+ unsigned int ep;
45
+ unsigned int len;
46
+ unsigned int timeout; /* in milliseconds */
47
+
48
+ /* pointer to data */
49
+ void *data;
50
+ };
51
+
52
+ struct usbfs_setinterface {
53
+ /* keep in sync with usbdevice_fs.h:usbdevfs_setinterface */
54
+ unsigned int interface;
55
+ unsigned int altsetting;
56
+ };
57
+
58
+ #define USBFS_MAXDRIVERNAME 255
59
+
60
+ struct usbfs_getdriver {
61
+ unsigned int interface;
62
+ char driver[USBFS_MAXDRIVERNAME + 1];
63
+ };
64
+
65
+ #define USBFS_URB_SHORT_NOT_OK 0x01
66
+ #define USBFS_URB_ISO_ASAP 0x02
67
+ #define USBFS_URB_BULK_CONTINUATION 0x04
68
+ #define USBFS_URB_QUEUE_BULK 0x10
69
+ #define USBFS_URB_ZERO_PACKET 0x40
70
+
71
+ enum usbfs_urb_type {
72
+ USBFS_URB_TYPE_ISO = 0,
73
+ USBFS_URB_TYPE_INTERRUPT = 1,
74
+ USBFS_URB_TYPE_CONTROL = 2,
75
+ USBFS_URB_TYPE_BULK = 3,
76
+ };
77
+
78
+ struct usbfs_iso_packet_desc {
79
+ unsigned int length;
80
+ unsigned int actual_length;
81
+ unsigned int status;
82
+ };
83
+
84
+ #define MAX_ISO_BUFFER_LENGTH 32768
85
+ #define MAX_BULK_BUFFER_LENGTH 16384
86
+ #define MAX_CTRL_BUFFER_LENGTH 4096
87
+
88
+ struct usbfs_urb {
89
+ unsigned char type;
90
+ unsigned char endpoint;
91
+ int status;
92
+ unsigned int flags;
93
+ void *buffer;
94
+ int buffer_length;
95
+ int actual_length;
96
+ int start_frame;
97
+ int number_of_packets;
98
+ int error_count;
99
+ unsigned int signr;
100
+ void *usercontext;
101
+ struct usbfs_iso_packet_desc iso_frame_desc[0];
102
+ };
103
+
104
+ struct usbfs_connectinfo {
105
+ unsigned int devnum;
106
+ unsigned char slow;
107
+ };
108
+
109
+ struct usbfs_ioctl {
110
+ int ifno; /* interface 0..N ; negative numbers reserved */
111
+ int ioctl_code; /* MUST encode size + direction of data so the
112
+ * macros in <asm/ioctl.h> give correct values */
113
+ void *data; /* param buffer (in, or out) */
114
+ };
115
+
116
+ struct usbfs_hub_portinfo {
117
+ unsigned char numports;
118
+ unsigned char port[127]; /* port to device num mapping */
119
+ };
120
+
121
+ #define USBFS_CAP_ZERO_PACKET 0x01
122
+ #define USBFS_CAP_BULK_CONTINUATION 0x02
123
+ #define USBFS_CAP_NO_PACKET_SIZE_LIM 0x04
124
+ #define USBFS_CAP_BULK_SCATTER_GATHER 0x08
125
+
126
+ #define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer)
127
+ #define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer)
128
+ #define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int)
129
+ #define IOCTL_USBFS_SETINTF _IOR('U', 4, struct usbfs_setinterface)
130
+ #define IOCTL_USBFS_SETCONFIG _IOR('U', 5, unsigned int)
131
+ #define IOCTL_USBFS_GETDRIVER _IOW('U', 8, struct usbfs_getdriver)
132
+ #define IOCTL_USBFS_SUBMITURB _IOR('U', 10, struct usbfs_urb)
133
+ #define IOCTL_USBFS_DISCARDURB _IO('U', 11)
134
+ #define IOCTL_USBFS_REAPURB _IOW('U', 12, void *)
135
+ #define IOCTL_USBFS_REAPURBNDELAY _IOW('U', 13, void *)
136
+ #define IOCTL_USBFS_CLAIMINTF _IOR('U', 15, unsigned int)
137
+ #define IOCTL_USBFS_RELEASEINTF _IOR('U', 16, unsigned int)
138
+ #define IOCTL_USBFS_CONNECTINFO _IOW('U', 17, struct usbfs_connectinfo)
139
+ #define IOCTL_USBFS_IOCTL _IOWR('U', 18, struct usbfs_ioctl)
140
+ #define IOCTL_USBFS_HUB_PORTINFO _IOR('U', 19, struct usbfs_hub_portinfo)
141
+ #define IOCTL_USBFS_RESET _IO('U', 20)
142
+ #define IOCTL_USBFS_CLEAR_HALT _IOR('U', 21, unsigned int)
143
+ #define IOCTL_USBFS_DISCONNECT _IO('U', 22)
144
+ #define IOCTL_USBFS_CONNECT _IO('U', 23)
145
+ #define IOCTL_USBFS_CLAIM_PORT _IOR('U', 24, unsigned int)
146
+ #define IOCTL_USBFS_RELEASE_PORT _IOR('U', 25, unsigned int)
147
+ #define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32)
148
+
149
+ #endif
@@ -0,0 +1,727 @@
1
+ /*
2
+ * Copyright © 2011 Martin Pieuchot <mpi@openbsd.org>
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+ */
18
+
19
+ #include <sys/time.h>
20
+ #include <sys/types.h>
21
+
22
+ #include <errno.h>
23
+ #include <fcntl.h>
24
+ #include <stdio.h>
25
+ #include <stdlib.h>
26
+ #include <string.h>
27
+ #include <unistd.h>
28
+
29
+ #include <dev/usb/usb.h>
30
+
31
+ #include "libusb.h"
32
+ #include "libusbi.h"
33
+
34
+ struct device_priv {
35
+ char devnode[16];
36
+ int fd;
37
+
38
+ unsigned char *cdesc; /* active config descriptor */
39
+ usb_device_descriptor_t ddesc; /* usb device descriptor */
40
+ };
41
+
42
+ struct handle_priv {
43
+ int pipe[2]; /* for event notification */
44
+ int endpoints[USB_MAX_ENDPOINTS];
45
+ };
46
+
47
+ /*
48
+ * Backend functions
49
+ */
50
+ static int obsd_get_device_list(struct libusb_context *,
51
+ struct discovered_devs **);
52
+ static int obsd_open(struct libusb_device_handle *);
53
+ static void obsd_close(struct libusb_device_handle *);
54
+
55
+ static int obsd_get_device_descriptor(struct libusb_device *, unsigned char *,
56
+ int *);
57
+ static int obsd_get_active_config_descriptor(struct libusb_device *,
58
+ unsigned char *, size_t, int *);
59
+ static int obsd_get_config_descriptor(struct libusb_device *, uint8_t,
60
+ unsigned char *, size_t, int *);
61
+
62
+ static int obsd_get_configuration(struct libusb_device_handle *, int *);
63
+ static int obsd_set_configuration(struct libusb_device_handle *, int);
64
+
65
+ static int obsd_claim_interface(struct libusb_device_handle *, int);
66
+ static int obsd_release_interface(struct libusb_device_handle *, int);
67
+
68
+ static int obsd_set_interface_altsetting(struct libusb_device_handle *, int,
69
+ int);
70
+ static int obsd_clear_halt(struct libusb_device_handle *, unsigned char);
71
+ static int obsd_reset_device(struct libusb_device_handle *);
72
+ static void obsd_destroy_device(struct libusb_device *);
73
+
74
+ static int obsd_submit_transfer(struct usbi_transfer *);
75
+ static int obsd_cancel_transfer(struct usbi_transfer *);
76
+ static void obsd_clear_transfer_priv(struct usbi_transfer *);
77
+ static int obsd_handle_events(struct libusb_context *ctx, struct pollfd *,
78
+ nfds_t, int);
79
+ static int obsd_clock_gettime(int, struct timespec *);
80
+
81
+ /*
82
+ * Private functions
83
+ */
84
+ static int _errno_to_libusb(int);
85
+ static int _cache_active_config_descriptor(struct libusb_device *, int);
86
+ static int _sync_control_transfer(struct usbi_transfer *);
87
+ static int _sync_gen_transfer(struct usbi_transfer *);
88
+ static int _access_endpoint(struct libusb_transfer *);
89
+
90
+ const struct usbi_os_backend openbsd_backend = {
91
+ "Synchronous OpenBSD backend",
92
+ NULL, /* init() */
93
+ NULL, /* exit() */
94
+ obsd_get_device_list,
95
+ obsd_open,
96
+ obsd_close,
97
+
98
+ obsd_get_device_descriptor,
99
+ obsd_get_active_config_descriptor,
100
+ obsd_get_config_descriptor,
101
+
102
+ obsd_get_configuration,
103
+ obsd_set_configuration,
104
+
105
+ obsd_claim_interface,
106
+ obsd_release_interface,
107
+
108
+ obsd_set_interface_altsetting,
109
+ obsd_clear_halt,
110
+ obsd_reset_device,
111
+
112
+ NULL, /* kernel_driver_active() */
113
+ NULL, /* detach_kernel_driver() */
114
+ NULL, /* attach_kernel_driver() */
115
+
116
+ obsd_destroy_device,
117
+
118
+ obsd_submit_transfer,
119
+ obsd_cancel_transfer,
120
+ obsd_clear_transfer_priv,
121
+
122
+ obsd_handle_events,
123
+
124
+ obsd_clock_gettime,
125
+ sizeof(struct device_priv),
126
+ sizeof(struct handle_priv),
127
+ 0, /* transfer_priv_size */
128
+ 0, /* add_iso_packet_size */
129
+ };
130
+
131
+ int
132
+ obsd_get_device_list(struct libusb_context * ctx,
133
+ struct discovered_devs **discdevs)
134
+ {
135
+ struct libusb_device *dev;
136
+ struct device_priv *dpriv;
137
+ struct usb_device_info di;
138
+ unsigned long session_id;
139
+ char devnode[16];
140
+ int fd, err, i;
141
+
142
+ usbi_dbg("");
143
+
144
+ /* Only ugen(4) is supported */
145
+ for (i = 0; i < USB_MAX_DEVICES; i++) {
146
+ /* Control endpoint is always .00 */
147
+ snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);
148
+
149
+ if ((fd = open(devnode, O_RDONLY)) < 0) {
150
+ if (errno != ENOENT && errno != ENXIO)
151
+ usbi_err(ctx, "could not open %s", devnode);
152
+ continue;
153
+ }
154
+
155
+ if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
156
+ continue;
157
+
158
+ session_id = (di.udi_bus << 8 | di.udi_addr);
159
+ dev = usbi_get_device_by_session_id(ctx, session_id);
160
+
161
+ if (dev == NULL) {
162
+ dev = usbi_alloc_device(ctx, session_id);
163
+ if (dev == NULL)
164
+ return (LIBUSB_ERROR_NO_MEM);
165
+
166
+ dev->bus_number = di.udi_bus;
167
+ dev->device_address = di.udi_addr;
168
+ dev->speed = di.udi_speed;
169
+
170
+ dpriv = (struct device_priv *)dev->os_priv;
171
+ strlcpy(dpriv->devnode, devnode, sizeof(devnode));
172
+ dpriv->fd = -1;
173
+
174
+ if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
175
+ err = errno;
176
+ goto error;
177
+ }
178
+
179
+ dpriv->cdesc = NULL;
180
+ if (_cache_active_config_descriptor(dev, fd)) {
181
+ err = errno;
182
+ goto error;
183
+ }
184
+
185
+ if ((err = usbi_sanitize_device(dev)))
186
+ goto error;
187
+ }
188
+ close(fd);
189
+
190
+ if (discovered_devs_append(*discdevs, dev) == NULL)
191
+ return (LIBUSB_ERROR_NO_MEM);
192
+ }
193
+
194
+ return (LIBUSB_SUCCESS);
195
+
196
+ error:
197
+ close(fd);
198
+ libusb_unref_device(dev);
199
+ return _errno_to_libusb(err);
200
+ }
201
+
202
+ int
203
+ obsd_open(struct libusb_device_handle *handle)
204
+ {
205
+ struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
206
+ struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
207
+
208
+ dpriv->fd = open(dpriv->devnode, O_RDWR);
209
+ if (dpriv->fd < 0) {
210
+ dpriv->fd = open(dpriv->devnode, O_RDONLY);
211
+ if (dpriv->fd < 0)
212
+ return _errno_to_libusb(errno);
213
+ }
214
+
215
+ usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
216
+
217
+ if (pipe(hpriv->pipe) < 0)
218
+ return _errno_to_libusb(errno);
219
+
220
+ return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN);
221
+ }
222
+
223
+ void
224
+ obsd_close(struct libusb_device_handle *handle)
225
+ {
226
+ struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
227
+ struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
228
+
229
+ usbi_dbg("close: fd %d", dpriv->fd);
230
+
231
+ close(dpriv->fd);
232
+ dpriv->fd = -1;
233
+
234
+ usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
235
+
236
+ close(hpriv->pipe[0]);
237
+ close(hpriv->pipe[1]);
238
+ }
239
+
240
+ int
241
+ obsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
242
+ int *host_endian)
243
+ {
244
+ struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
245
+
246
+ usbi_dbg("");
247
+
248
+ memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
249
+
250
+ *host_endian = 0;
251
+
252
+ return (LIBUSB_SUCCESS);
253
+ }
254
+
255
+ int
256
+ obsd_get_active_config_descriptor(struct libusb_device *dev,
257
+ unsigned char *buf, size_t len, int *host_endian)
258
+ {
259
+ struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
260
+ usb_config_descriptor_t *ucd;
261
+
262
+ ucd = (usb_config_descriptor_t *) dpriv->cdesc;
263
+ len = MIN(len, UGETW(ucd->wTotalLength));
264
+
265
+ usbi_dbg("len %d", len);
266
+
267
+ memcpy(buf, dpriv->cdesc, len);
268
+
269
+ *host_endian = 0;
270
+
271
+ return (LIBUSB_SUCCESS);
272
+ }
273
+
274
+ int
275
+ obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
276
+ unsigned char *buf, size_t len, int *host_endian)
277
+ {
278
+ struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
279
+ struct usb_full_desc ufd;
280
+ int fd, err;
281
+
282
+ usbi_dbg("index %d, len %d", idx, len);
283
+
284
+ /* A config descriptor may be requested before opening the device */
285
+ if (dpriv->fd >= 0) {
286
+ fd = dpriv->fd;
287
+ } else {
288
+ fd = open(dpriv->devnode, O_RDONLY);
289
+ if (fd < 0)
290
+ return _errno_to_libusb(errno);
291
+ }
292
+
293
+ ufd.ufd_config_index = idx;
294
+ ufd.ufd_size = len;
295
+ ufd.ufd_data = buf;
296
+
297
+ if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
298
+ err = errno;
299
+ if (dpriv->fd < 0)
300
+ close(fd);
301
+ return _errno_to_libusb(err);
302
+ }
303
+
304
+ if (dpriv->fd < 0)
305
+ close(fd);
306
+
307
+ *host_endian = 0;
308
+
309
+ return (LIBUSB_SUCCESS);
310
+ }
311
+
312
+ int
313
+ obsd_get_configuration(struct libusb_device_handle *handle, int *config)
314
+ {
315
+ struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
316
+
317
+ usbi_dbg("");
318
+
319
+ if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
320
+ return _errno_to_libusb(errno);
321
+
322
+ usbi_dbg("configuration %d", *config);
323
+
324
+ return (LIBUSB_SUCCESS);
325
+ }
326
+
327
+ int
328
+ obsd_set_configuration(struct libusb_device_handle *handle, int config)
329
+ {
330
+ struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
331
+
332
+ usbi_dbg("configuration %d", config);
333
+
334
+ if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
335
+ return _errno_to_libusb(errno);
336
+
337
+ return _cache_active_config_descriptor(handle->dev, dpriv->fd);
338
+ }
339
+
340
+ int
341
+ obsd_claim_interface(struct libusb_device_handle *handle, int iface)
342
+ {
343
+ struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
344
+ int i;
345
+
346
+ for (i = 0; i < USB_MAX_ENDPOINTS; i++)
347
+ hpriv->endpoints[i] = -1;
348
+
349
+ return (LIBUSB_SUCCESS);
350
+ }
351
+
352
+ int
353
+ obsd_release_interface(struct libusb_device_handle *handle, int iface)
354
+ {
355
+ struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
356
+ int i;
357
+
358
+ for (i = 0; i < USB_MAX_ENDPOINTS; i++)
359
+ if (hpriv->endpoints[i] >= 0)
360
+ close(hpriv->endpoints[i]);
361
+
362
+ return (LIBUSB_SUCCESS);
363
+ }
364
+
365
+ int
366
+ obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
367
+ int altsetting)
368
+ {
369
+ struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
370
+ struct usb_alt_interface intf;
371
+
372
+ usbi_dbg("iface %d, setting %d", iface, altsetting);
373
+
374
+ memset(&intf, 0, sizeof(intf));
375
+
376
+ intf.uai_interface_index = iface;
377
+ intf.uai_alt_no = altsetting;
378
+
379
+ if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
380
+ return _errno_to_libusb(errno);
381
+
382
+ return (LIBUSB_SUCCESS);
383
+ }
384
+
385
+ int
386
+ obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
387
+ {
388
+ struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
389
+ struct usb_ctl_request req;
390
+
391
+ usbi_dbg("");
392
+
393
+ req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
394
+ req.ucr_request.bRequest = UR_CLEAR_FEATURE;
395
+ USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
396
+ USETW(req.ucr_request.wIndex, endpoint);
397
+ USETW(req.ucr_request.wLength, 0);
398
+
399
+ if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
400
+ return _errno_to_libusb(errno);
401
+
402
+ return (LIBUSB_SUCCESS);
403
+ }
404
+
405
+ int
406
+ obsd_reset_device(struct libusb_device_handle *handle)
407
+ {
408
+ usbi_dbg("");
409
+
410
+ return (LIBUSB_ERROR_NOT_SUPPORTED);
411
+ }
412
+
413
+ void
414
+ obsd_destroy_device(struct libusb_device *dev)
415
+ {
416
+ struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
417
+
418
+ usbi_dbg("");
419
+
420
+ free(dpriv->cdesc);
421
+ }
422
+
423
+ int
424
+ obsd_submit_transfer(struct usbi_transfer *itransfer)
425
+ {
426
+ struct libusb_transfer *transfer;
427
+ struct handle_priv *hpriv;
428
+ int err = 0;
429
+
430
+ usbi_dbg("");
431
+
432
+ transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
433
+ hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
434
+
435
+ switch (transfer->type) {
436
+ case LIBUSB_TRANSFER_TYPE_CONTROL:
437
+ err = _sync_control_transfer(itransfer);
438
+ break;
439
+ case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
440
+ if (IS_XFEROUT(transfer)) {
441
+ /* Isochronous write is not supported */
442
+ err = LIBUSB_ERROR_NOT_SUPPORTED;
443
+ break;
444
+ }
445
+ err = _sync_gen_transfer(itransfer);
446
+ break;
447
+ case LIBUSB_TRANSFER_TYPE_BULK:
448
+ case LIBUSB_TRANSFER_TYPE_INTERRUPT:
449
+ if (IS_XFEROUT(transfer) &&
450
+ transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
451
+ err = LIBUSB_ERROR_NOT_SUPPORTED;
452
+ break;
453
+ }
454
+ err = _sync_gen_transfer(itransfer);
455
+ break;
456
+ }
457
+
458
+ if (err)
459
+ return (err);
460
+
461
+ if (write(hpriv->pipe[1], &itransfer, sizeof(itransfer)) < 0)
462
+ return _errno_to_libusb(errno);
463
+
464
+ return (LIBUSB_SUCCESS);
465
+ }
466
+
467
+ int
468
+ obsd_cancel_transfer(struct usbi_transfer *itransfer)
469
+ {
470
+ usbi_dbg("");
471
+
472
+ return (LIBUSB_ERROR_NOT_SUPPORTED);
473
+ }
474
+
475
+ void
476
+ obsd_clear_transfer_priv(struct usbi_transfer *itransfer)
477
+ {
478
+ usbi_dbg("");
479
+
480
+ /* Nothing to do */
481
+ }
482
+
483
+ int
484
+ obsd_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds,
485
+ int num_ready)
486
+ {
487
+ struct libusb_device_handle *handle;
488
+ struct handle_priv *hpriv = NULL;
489
+ struct usbi_transfer *itransfer;
490
+ struct pollfd *pollfd;
491
+ int i, err = 0;
492
+
493
+ usbi_dbg("");
494
+
495
+ pthread_mutex_lock(&ctx->open_devs_lock);
496
+ for (i = 0; i < nfds && num_ready > 0; i++) {
497
+ pollfd = &fds[i];
498
+
499
+ if (!pollfd->revents)
500
+ continue;
501
+
502
+ hpriv = NULL;
503
+ num_ready--;
504
+ list_for_each_entry(handle, &ctx->open_devs, list,
505
+ struct libusb_device_handle) {
506
+ hpriv = (struct handle_priv *)handle->os_priv;
507
+
508
+ if (hpriv->pipe[0] == pollfd->fd)
509
+ break;
510
+
511
+ hpriv = NULL;
512
+ }
513
+
514
+ if (NULL == hpriv) {
515
+ usbi_dbg("fd %d is not an event pipe!", pollfd->fd);
516
+ err = ENOENT;
517
+ break;
518
+ }
519
+
520
+ if (pollfd->revents & POLLERR) {
521
+ usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
522
+ usbi_handle_disconnect(handle);
523
+ continue;
524
+ }
525
+
526
+ if (read(hpriv->pipe[0], &itransfer, sizeof(itransfer)) < 0) {
527
+ err = errno;
528
+ break;
529
+ }
530
+
531
+ if ((err = usbi_handle_transfer_completion(itransfer,
532
+ LIBUSB_TRANSFER_COMPLETED)))
533
+ break;
534
+ }
535
+ pthread_mutex_unlock(&ctx->open_devs_lock);
536
+
537
+ if (err)
538
+ return _errno_to_libusb(err);
539
+
540
+ return (LIBUSB_SUCCESS);
541
+ }
542
+
543
+ int
544
+ obsd_clock_gettime(int clkid, struct timespec *tp)
545
+ {
546
+ usbi_dbg("clock %d", clkid);
547
+
548
+ if (clkid == USBI_CLOCK_REALTIME)
549
+ return clock_gettime(CLOCK_REALTIME, tp);
550
+
551
+ if (clkid == USBI_CLOCK_MONOTONIC)
552
+ return clock_gettime(CLOCK_MONOTONIC, tp);
553
+
554
+ return (LIBUSB_ERROR_INVALID_PARAM);
555
+ }
556
+
557
+ int
558
+ _errno_to_libusb(int err)
559
+ {
560
+ switch (err) {
561
+ case EIO:
562
+ return (LIBUSB_ERROR_IO);
563
+ case EACCES:
564
+ return (LIBUSB_ERROR_ACCESS);
565
+ case ENOENT:
566
+ return (LIBUSB_ERROR_NO_DEVICE);
567
+ case ENOMEM:
568
+ return (LIBUSB_ERROR_NO_MEM);
569
+ }
570
+
571
+ usbi_dbg("error: %s", strerror(err));
572
+
573
+ return (LIBUSB_ERROR_OTHER);
574
+ }
575
+
576
+ int
577
+ _cache_active_config_descriptor(struct libusb_device *dev, int fd)
578
+ {
579
+ struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
580
+ struct usb_config_desc ucd;
581
+ struct usb_full_desc ufd;
582
+ unsigned char* buf;
583
+ int len;
584
+
585
+ usbi_dbg("fd %d", fd);
586
+
587
+ ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX;
588
+
589
+ if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0)
590
+ return _errno_to_libusb(errno);
591
+
592
+ usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
593
+
594
+ len = UGETW(ucd.ucd_desc.wTotalLength);
595
+ buf = malloc(len);
596
+ if (buf == NULL)
597
+ return (LIBUSB_ERROR_NO_MEM);
598
+
599
+ ufd.ufd_config_index = ucd.ucd_config_index;
600
+ ufd.ufd_size = len;
601
+ ufd.ufd_data = buf;
602
+
603
+ usbi_dbg("index %d, len %d", ufd.ufd_config_index, len);
604
+
605
+ if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
606
+ free(buf);
607
+ return _errno_to_libusb(errno);
608
+ }
609
+
610
+ if (dpriv->cdesc)
611
+ free(dpriv->cdesc);
612
+ dpriv->cdesc = buf;
613
+
614
+ return (0);
615
+ }
616
+
617
+ int
618
+ _sync_control_transfer(struct usbi_transfer *itransfer)
619
+ {
620
+ struct libusb_transfer *transfer;
621
+ struct libusb_control_setup *setup;
622
+ struct device_priv *dpriv;
623
+ struct usb_ctl_request req;
624
+
625
+ transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
626
+ dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
627
+ setup = (struct libusb_control_setup *)transfer->buffer;
628
+
629
+ usbi_dbg("type %d request %d value %d index %d length %d timeout %d",
630
+ setup->bmRequestType, setup->bRequest,
631
+ libusb_le16_to_cpu(setup->wValue),
632
+ libusb_le16_to_cpu(setup->wIndex),
633
+ libusb_le16_to_cpu(setup->wLength), transfer->timeout);
634
+
635
+ req.ucr_request.bmRequestType = setup->bmRequestType;
636
+ req.ucr_request.bRequest = setup->bRequest;
637
+ /* Don't use USETW, libusbx already deals with the endianness */
638
+ (*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
639
+ (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
640
+ (*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
641
+ req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
642
+
643
+ if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
644
+ req.ucr_flags = USBD_SHORT_XFER_OK;
645
+
646
+ if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
647
+ return _errno_to_libusb(errno);
648
+
649
+ if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
650
+ return _errno_to_libusb(errno);
651
+
652
+ itransfer->transferred = req.ucr_actlen;
653
+
654
+ usbi_dbg("transferred %d", itransfer->transferred);
655
+
656
+ return (0);
657
+ }
658
+
659
+ int
660
+ _access_endpoint(struct libusb_transfer *transfer)
661
+ {
662
+ struct handle_priv *hpriv;
663
+ struct device_priv *dpriv;
664
+ char *s, devnode[16];
665
+ int fd, endpt;
666
+ mode_t mode;
667
+
668
+ hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
669
+ dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
670
+
671
+ endpt = UE_GET_ADDR(transfer->endpoint);
672
+ mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
673
+
674
+ usbi_dbg("endpoint %d mode %d", endpt, mode);
675
+
676
+ if (hpriv->endpoints[endpt] < 0) {
677
+ /* Pick the right node given the control one */
678
+ strlcpy(devnode, dpriv->devnode, sizeof(devnode));
679
+ s = strchr(devnode, '.');
680
+ snprintf(s, 4, ".%02d", endpt);
681
+
682
+ /* We may need to read/write to the same endpoint later. */
683
+ if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
684
+ if ((fd = open(devnode, mode)) < 0)
685
+ return (-1);
686
+
687
+ hpriv->endpoints[endpt] = fd;
688
+ }
689
+
690
+ return (hpriv->endpoints[endpt]);
691
+ }
692
+
693
+ int
694
+ _sync_gen_transfer(struct usbi_transfer *itransfer)
695
+ {
696
+ struct libusb_transfer *transfer;
697
+ int fd, nr = 1;
698
+
699
+ transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
700
+
701
+ /*
702
+ * Bulk, Interrupt or Isochronous transfer depends on the
703
+ * endpoint and thus the node to open.
704
+ */
705
+ if ((fd = _access_endpoint(transfer)) < 0)
706
+ return _errno_to_libusb(errno);
707
+
708
+ if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
709
+ return _errno_to_libusb(errno);
710
+
711
+ if (IS_XFERIN(transfer)) {
712
+ if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
713
+ if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
714
+ return _errno_to_libusb(errno);
715
+
716
+ nr = read(fd, transfer->buffer, transfer->length);
717
+ } else {
718
+ nr = write(fd, transfer->buffer, transfer->length);
719
+ }
720
+
721
+ if (nr < 0)
722
+ return _errno_to_libusb(errno);
723
+
724
+ itransfer->transferred = nr;
725
+
726
+ return (0);
727
+ }