libusb 0.2.2 → 0.3.0

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 (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
+ }