libusb 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Gemfile +1 -0
  5. data/History.md +10 -0
  6. data/README.md +19 -6
  7. data/Rakefile +1 -1
  8. data/ext/extconf.rb +17 -1
  9. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/AUTHORS +18 -6
  10. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/COPYING +0 -0
  11. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ChangeLog +58 -1
  12. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/INSTALL +0 -0
  13. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.am +6 -1
  14. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.in +248 -174
  15. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/NEWS +2 -2
  16. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/PORTING +0 -0
  17. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/README +2 -1
  18. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/TODO +0 -0
  19. data/ext/libusbx-1.0.17/Xcode/common.xcconfig +40 -0
  20. data/ext/libusbx-1.0.17/Xcode/config.h +28 -0
  21. data/ext/libusbx-1.0.17/Xcode/debug.xcconfig +29 -0
  22. data/ext/libusbx-1.0.17/Xcode/libusbx.xcconfig +21 -0
  23. data/ext/libusbx-1.0.17/Xcode/libusbx.xcodeproj/project.pbxproj +864 -0
  24. data/ext/libusbx-1.0.17/Xcode/libusbx_debug.xcconfig +21 -0
  25. data/ext/libusbx-1.0.17/Xcode/libusbx_release.xcconfig +21 -0
  26. data/ext/libusbx-1.0.17/Xcode/release.xcconfig +29 -0
  27. data/ext/libusbx-1.0.17/aclocal.m4 +1112 -0
  28. data/ext/libusbx-1.0.17/android/README +114 -0
  29. data/ext/libusbx-1.0.17/android/config.h +90 -0
  30. data/ext/libusbx-1.0.17/android/jni/Android.mk +23 -0
  31. data/ext/libusbx-1.0.17/android/jni/Application.mk +19 -0
  32. data/ext/libusbx-1.0.17/android/jni/examples.mk +134 -0
  33. data/ext/libusbx-1.0.17/android/jni/libusb.mk +54 -0
  34. data/ext/libusbx-1.0.17/android/jni/tests.mk +56 -0
  35. data/ext/libusbx-1.0.17/compile +347 -0
  36. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.guess +164 -130
  37. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.h.in +37 -1
  38. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.sub +174 -89
  39. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure +723 -302
  40. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure.ac +71 -20
  41. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/depcomp +345 -185
  42. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.am +0 -0
  43. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.in +95 -32
  44. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/doxygen.cfg.in +1 -1
  45. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.am +5 -4
  46. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.in +208 -104
  47. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp.c +1 -1
  48. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp_threaded.c +1 -1
  49. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.c +188 -8
  50. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.h +18 -5
  51. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/fxload.c +90 -64
  52. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.c +0 -0
  53. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.h +0 -0
  54. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt1.c +0 -0
  55. data/ext/libusbx-1.0.17/examples/hotplugtest.c +97 -0
  56. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/listdevs.c +12 -4
  57. data/ext/libusbx-1.0.17/examples/sam3u_benchmark.c +193 -0
  58. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/xusb.c +106 -49
  59. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/install-sh +21 -14
  60. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb-1.0.pc.in +1 -1
  61. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/Makefile.am +29 -10
  62. data/ext/libusbx-1.0.17/libusb/Makefile.in +914 -0
  63. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/core.c +378 -87
  64. data/ext/libusbx-1.0.17/libusb/descriptor.c +1199 -0
  65. data/ext/libusbx-1.0.17/libusb/hotplug.c +322 -0
  66. data/ext/libusbx-1.0.17/libusb/hotplug.h +82 -0
  67. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/io.c +182 -62
  68. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.def +32 -0
  69. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.rc +2 -0
  70. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb.h +481 -32
  71. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusbi.h +135 -38
  72. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.c +591 -496
  73. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.h +39 -46
  74. data/ext/libusbx-1.0.17/libusb/os/linux_netlink.c +345 -0
  75. data/ext/libusbx-1.0.17/libusb/os/linux_udev.c +306 -0
  76. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.c +653 -617
  77. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.h +32 -0
  78. data/ext/{libusbx-1.0.14/libusb/os/openbsd_usb.c → libusbx-1.0.17/libusb/os/netbsd_usb.c} +70 -63
  79. data/ext/libusbx-1.0.17/libusb/os/openbsd_usb.c +823 -0
  80. data/ext/libusbx-1.0.17/libusb/os/poll_posix.c +51 -0
  81. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_posix.h +2 -1
  82. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.c +85 -106
  83. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.h +14 -3
  84. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.c +3 -1
  85. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.h +0 -0
  86. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.c +6 -5
  87. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.h +0 -0
  88. data/ext/libusbx-1.0.17/libusb/os/wince_usb.c +1026 -0
  89. data/ext/libusbx-1.0.17/libusb/os/wince_usb.h +131 -0
  90. data/ext/libusbx-1.0.17/libusb/os/windows_common.h +108 -0
  91. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.c +92 -57
  92. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.h +2 -63
  93. data/ext/libusbx-1.0.17/libusb/strerror.c +184 -0
  94. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/sync.c +24 -38
  95. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/version.h +1 -1
  96. data/ext/libusbx-1.0.17/libusb/version_nano.h +1 -0
  97. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ltmain.sh +60 -41
  98. data/ext/{libusbx-1.0.14/aclocal.m4 → libusbx-1.0.17/m4/libtool.m4} +229 -1723
  99. data/ext/libusbx-1.0.17/m4/ltoptions.m4 +384 -0
  100. data/ext/libusbx-1.0.17/m4/ltsugar.m4 +123 -0
  101. data/ext/libusbx-1.0.17/m4/ltversion.m4 +23 -0
  102. data/ext/libusbx-1.0.17/m4/lt~obsolete.m4 +98 -0
  103. data/ext/libusbx-1.0.17/missing +215 -0
  104. data/ext/libusbx-1.0.17/tests/Makefile.am +6 -0
  105. data/ext/libusbx-1.0.17/tests/Makefile.in +583 -0
  106. data/ext/libusbx-1.0.17/tests/libusbx_testlib.h +107 -0
  107. data/ext/libusbx-1.0.17/tests/stress.c +160 -0
  108. data/ext/libusbx-1.0.17/tests/testlib.c +276 -0
  109. data/lib/libusb.rb +4 -0
  110. data/lib/libusb/call.rb +43 -1
  111. data/lib/libusb/constants.rb +5 -0
  112. data/lib/libusb/context.rb +100 -0
  113. data/lib/libusb/dev_handle.rb +27 -0
  114. data/lib/libusb/device.rb +10 -4
  115. data/lib/libusb/version_gem.rb +1 -1
  116. data/test/test_libusb_capability.rb +2 -2
  117. data/test/test_libusb_compat.rb +2 -2
  118. data/test/test_libusb_compat_mass_storage.rb +2 -2
  119. data/test/test_libusb_descriptors.rb +4 -2
  120. data/test/test_libusb_event_machine.rb +2 -2
  121. data/test/test_libusb_gc.rb +2 -2
  122. data/test/test_libusb_hotplug.rb +115 -0
  123. data/test/test_libusb_iso_transfer.rb +3 -3
  124. data/test/test_libusb_mass_storage.rb +6 -16
  125. data/test/test_libusb_mass_storage2.rb +26 -3
  126. data/test/test_libusb_structs.rb +2 -2
  127. data/test/test_libusb_threads.rb +2 -2
  128. data/test/test_libusb_version.rb +2 -2
  129. metadata +127 -68
  130. metadata.gz.sig +0 -0
  131. data/ext/libusbx-1.0.14/THANKS +0 -7
  132. data/ext/libusbx-1.0.14/compile +0 -143
  133. data/ext/libusbx-1.0.14/libusb/Makefile.in +0 -721
  134. data/ext/libusbx-1.0.14/libusb/descriptor.c +0 -731
  135. data/ext/libusbx-1.0.14/libusb/version_nano.h +0 -1
  136. data/ext/libusbx-1.0.14/missing +0 -376
@@ -0,0 +1,1199 @@
1
+ /* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */
2
+ /*
3
+ * USB descriptor handling functions for libusbx
4
+ * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
5
+ * Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
+ */
21
+
22
+ #include <errno.h>
23
+ #include <stdint.h>
24
+ #include <stdlib.h>
25
+ #include <string.h>
26
+
27
+ #include "libusbi.h"
28
+
29
+ #define DESC_HEADER_LENGTH 2
30
+ #define DEVICE_DESC_LENGTH 18
31
+ #define CONFIG_DESC_LENGTH 9
32
+ #define INTERFACE_DESC_LENGTH 9
33
+ #define ENDPOINT_DESC_LENGTH 7
34
+ #define ENDPOINT_AUDIO_DESC_LENGTH 9
35
+
36
+ /** @defgroup desc USB descriptors
37
+ * This page details how to examine the various standard USB descriptors
38
+ * for detected devices
39
+ */
40
+
41
+ /* set host_endian if the w values are already in host endian format,
42
+ * as opposed to bus endian. */
43
+ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor,
44
+ void *dest, int host_endian)
45
+ {
46
+ const unsigned char *sp = source;
47
+ unsigned char *dp = dest;
48
+ uint16_t w;
49
+ const char *cp;
50
+ uint32_t d;
51
+
52
+ for (cp = descriptor; *cp; cp++) {
53
+ switch (*cp) {
54
+ case 'b': /* 8-bit byte */
55
+ *dp++ = *sp++;
56
+ break;
57
+ case 'w': /* 16-bit word, convert from little endian to CPU */
58
+ dp += ((uintptr_t)dp & 1); /* Align to word boundary */
59
+
60
+ if (host_endian) {
61
+ memcpy(dp, sp, 2);
62
+ } else {
63
+ w = (sp[1] << 8) | sp[0];
64
+ *((uint16_t *)dp) = w;
65
+ }
66
+ sp += 2;
67
+ dp += 2;
68
+ break;
69
+ case 'd': /* 32-bit word, convert from little endian to CPU */
70
+ dp += ((uintptr_t)dp & 1); /* Align to word boundary */
71
+
72
+ if (host_endian) {
73
+ memcpy(dp, sp, 4);
74
+ } else {
75
+ d = (sp[3] << 24) | (sp[2] << 16) |
76
+ (sp[1] << 8) | sp[0];
77
+ *((uint32_t *)dp) = d;
78
+ }
79
+ sp += 4;
80
+ dp += 4;
81
+ break;
82
+ case 'u': /* 16 byte UUID */
83
+ memcpy(dp, sp, 16);
84
+ sp += 16;
85
+ dp += 16;
86
+ break;
87
+ }
88
+ }
89
+
90
+ return (int) (sp - source);
91
+ }
92
+
93
+ static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
94
+ {
95
+ if (endpoint->extra)
96
+ free((unsigned char *) endpoint->extra);
97
+ }
98
+
99
+ static int parse_endpoint(struct libusb_context *ctx,
100
+ struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer,
101
+ int size, int host_endian)
102
+ {
103
+ struct usb_descriptor_header header;
104
+ unsigned char *extra;
105
+ unsigned char *begin;
106
+ int parsed = 0;
107
+ int len;
108
+
109
+ if (size < DESC_HEADER_LENGTH) {
110
+ usbi_err(ctx, "short endpoint descriptor read %d/%d",
111
+ size, DESC_HEADER_LENGTH);
112
+ return LIBUSB_ERROR_IO;
113
+ }
114
+
115
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
116
+ if (header.bDescriptorType != LIBUSB_DT_ENDPOINT) {
117
+ usbi_err(ctx, "unexpected descriptor %x (expected %x)",
118
+ header.bDescriptorType, LIBUSB_DT_ENDPOINT);
119
+ return parsed;
120
+ }
121
+ if (header.bLength > size) {
122
+ usbi_warn(ctx, "short endpoint descriptor read %d/%d",
123
+ size, header.bLength);
124
+ return parsed;
125
+ }
126
+ if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH)
127
+ usbi_parse_descriptor(buffer, "bbbbwbbb", endpoint, host_endian);
128
+ else if (header.bLength >= ENDPOINT_DESC_LENGTH)
129
+ usbi_parse_descriptor(buffer, "bbbbwb", endpoint, host_endian);
130
+ else {
131
+ usbi_err(ctx, "invalid endpoint bLength (%d)", header.bLength);
132
+ return LIBUSB_ERROR_IO;
133
+ }
134
+
135
+ buffer += header.bLength;
136
+ size -= header.bLength;
137
+ parsed += header.bLength;
138
+
139
+ /* Skip over the rest of the Class Specific or Vendor Specific */
140
+ /* descriptors */
141
+ begin = buffer;
142
+ while (size >= DESC_HEADER_LENGTH) {
143
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
144
+ if (header.bLength < DESC_HEADER_LENGTH) {
145
+ usbi_err(ctx, "invalid extra ep desc len (%d)",
146
+ header.bLength);
147
+ return LIBUSB_ERROR_IO;
148
+ } else if (header.bLength > size) {
149
+ usbi_warn(ctx, "short extra ep desc read %d/%d",
150
+ size, header.bLength);
151
+ return parsed;
152
+ }
153
+
154
+ /* If we find another "proper" descriptor then we're done */
155
+ if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
156
+ (header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
157
+ (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
158
+ (header.bDescriptorType == LIBUSB_DT_DEVICE))
159
+ break;
160
+
161
+ usbi_dbg("skipping descriptor %x", header.bDescriptorType);
162
+ buffer += header.bLength;
163
+ size -= header.bLength;
164
+ parsed += header.bLength;
165
+ }
166
+
167
+ /* Copy any unknown descriptors into a storage area for drivers */
168
+ /* to later parse */
169
+ len = (int)(buffer - begin);
170
+ if (!len) {
171
+ endpoint->extra = NULL;
172
+ endpoint->extra_length = 0;
173
+ return parsed;
174
+ }
175
+
176
+ extra = malloc(len);
177
+ endpoint->extra = extra;
178
+ if (!extra) {
179
+ endpoint->extra_length = 0;
180
+ return LIBUSB_ERROR_NO_MEM;
181
+ }
182
+
183
+ memcpy(extra, begin, len);
184
+ endpoint->extra_length = len;
185
+
186
+ return parsed;
187
+ }
188
+
189
+ static void clear_interface(struct libusb_interface *usb_interface)
190
+ {
191
+ int i;
192
+ int j;
193
+
194
+ if (usb_interface->altsetting) {
195
+ for (i = 0; i < usb_interface->num_altsetting; i++) {
196
+ struct libusb_interface_descriptor *ifp =
197
+ (struct libusb_interface_descriptor *)
198
+ usb_interface->altsetting + i;
199
+ if (ifp->extra)
200
+ free((void *) ifp->extra);
201
+ if (ifp->endpoint) {
202
+ for (j = 0; j < ifp->bNumEndpoints; j++)
203
+ clear_endpoint((struct libusb_endpoint_descriptor *)
204
+ ifp->endpoint + j);
205
+ free((void *) ifp->endpoint);
206
+ }
207
+ }
208
+ free((void *) usb_interface->altsetting);
209
+ usb_interface->altsetting = NULL;
210
+ }
211
+
212
+ }
213
+
214
+ static int parse_interface(libusb_context *ctx,
215
+ struct libusb_interface *usb_interface, unsigned char *buffer, int size,
216
+ int host_endian)
217
+ {
218
+ int i;
219
+ int len;
220
+ int r;
221
+ int parsed = 0;
222
+ int interface_number = -1;
223
+ size_t tmp;
224
+ struct usb_descriptor_header header;
225
+ struct libusb_interface_descriptor *ifp;
226
+ unsigned char *begin;
227
+
228
+ usb_interface->num_altsetting = 0;
229
+
230
+ while (size >= INTERFACE_DESC_LENGTH) {
231
+ struct libusb_interface_descriptor *altsetting =
232
+ (struct libusb_interface_descriptor *) usb_interface->altsetting;
233
+ altsetting = usbi_reallocf(altsetting,
234
+ sizeof(struct libusb_interface_descriptor) *
235
+ (usb_interface->num_altsetting + 1));
236
+ if (!altsetting) {
237
+ r = LIBUSB_ERROR_NO_MEM;
238
+ goto err;
239
+ }
240
+ usb_interface->altsetting = altsetting;
241
+
242
+ ifp = altsetting + usb_interface->num_altsetting;
243
+ usbi_parse_descriptor(buffer, "bbbbbbbbb", ifp, 0);
244
+ if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) {
245
+ usbi_err(ctx, "unexpected descriptor %x (expected %x)",
246
+ ifp->bDescriptorType, LIBUSB_DT_INTERFACE);
247
+ return parsed;
248
+ }
249
+ if (ifp->bLength < INTERFACE_DESC_LENGTH) {
250
+ usbi_err(ctx, "invalid interface bLength (%d)",
251
+ ifp->bLength);
252
+ r = LIBUSB_ERROR_IO;
253
+ goto err;
254
+ }
255
+ if (ifp->bLength > size) {
256
+ usbi_warn(ctx, "short intf descriptor read %d/%d",
257
+ size, ifp->bLength);
258
+ return parsed;
259
+ }
260
+ if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
261
+ usbi_err(ctx, "too many endpoints (%d)", ifp->bNumEndpoints);
262
+ r = LIBUSB_ERROR_IO;
263
+ goto err;
264
+ }
265
+
266
+ usb_interface->num_altsetting++;
267
+ ifp->extra = NULL;
268
+ ifp->extra_length = 0;
269
+ ifp->endpoint = NULL;
270
+
271
+ if (interface_number == -1)
272
+ interface_number = ifp->bInterfaceNumber;
273
+
274
+ /* Skip over the interface */
275
+ buffer += ifp->bLength;
276
+ parsed += ifp->bLength;
277
+ size -= ifp->bLength;
278
+
279
+ begin = buffer;
280
+
281
+ /* Skip over any interface, class or vendor descriptors */
282
+ while (size >= DESC_HEADER_LENGTH) {
283
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
284
+ if (header.bLength < DESC_HEADER_LENGTH) {
285
+ usbi_err(ctx,
286
+ "invalid extra intf desc len (%d)",
287
+ header.bLength);
288
+ r = LIBUSB_ERROR_IO;
289
+ goto err;
290
+ } else if (header.bLength > size) {
291
+ usbi_warn(ctx,
292
+ "short extra intf desc read %d/%d",
293
+ size, header.bLength);
294
+ return parsed;
295
+ }
296
+
297
+ /* If we find another "proper" descriptor then we're done */
298
+ if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
299
+ (header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
300
+ (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
301
+ (header.bDescriptorType == LIBUSB_DT_DEVICE))
302
+ break;
303
+
304
+ buffer += header.bLength;
305
+ parsed += header.bLength;
306
+ size -= header.bLength;
307
+ }
308
+
309
+ /* Copy any unknown descriptors into a storage area for */
310
+ /* drivers to later parse */
311
+ len = (int)(buffer - begin);
312
+ if (len) {
313
+ ifp->extra = malloc(len);
314
+ if (!ifp->extra) {
315
+ r = LIBUSB_ERROR_NO_MEM;
316
+ goto err;
317
+ }
318
+ memcpy((unsigned char *) ifp->extra, begin, len);
319
+ ifp->extra_length = len;
320
+ }
321
+
322
+ if (ifp->bNumEndpoints > 0) {
323
+ struct libusb_endpoint_descriptor *endpoint;
324
+ tmp = ifp->bNumEndpoints * sizeof(struct libusb_endpoint_descriptor);
325
+ endpoint = malloc(tmp);
326
+ ifp->endpoint = endpoint;
327
+ if (!endpoint) {
328
+ r = LIBUSB_ERROR_NO_MEM;
329
+ goto err;
330
+ }
331
+
332
+ memset(endpoint, 0, tmp);
333
+ for (i = 0; i < ifp->bNumEndpoints; i++) {
334
+ r = parse_endpoint(ctx, endpoint + i, buffer, size,
335
+ host_endian);
336
+ if (r < 0)
337
+ goto err;
338
+ if (r == 0) {
339
+ ifp->bNumEndpoints = (uint8_t)i;
340
+ break;;
341
+ }
342
+
343
+ buffer += r;
344
+ parsed += r;
345
+ size -= r;
346
+ }
347
+ }
348
+
349
+ /* We check to see if it's an alternate to this one */
350
+ ifp = (struct libusb_interface_descriptor *) buffer;
351
+ if (size < LIBUSB_DT_INTERFACE_SIZE ||
352
+ ifp->bDescriptorType != LIBUSB_DT_INTERFACE ||
353
+ ifp->bInterfaceNumber != interface_number)
354
+ return parsed;
355
+ }
356
+
357
+ return parsed;
358
+ err:
359
+ clear_interface(usb_interface);
360
+ return r;
361
+ }
362
+
363
+ static void clear_configuration(struct libusb_config_descriptor *config)
364
+ {
365
+ if (config->interface) {
366
+ int i;
367
+ for (i = 0; i < config->bNumInterfaces; i++)
368
+ clear_interface((struct libusb_interface *)
369
+ config->interface + i);
370
+ free((void *) config->interface);
371
+ }
372
+ if (config->extra)
373
+ free((void *) config->extra);
374
+ }
375
+
376
+ static int parse_configuration(struct libusb_context *ctx,
377
+ struct libusb_config_descriptor *config, unsigned char *buffer,
378
+ int size, int host_endian)
379
+ {
380
+ int i;
381
+ int r;
382
+ size_t tmp;
383
+ struct usb_descriptor_header header;
384
+ struct libusb_interface *usb_interface;
385
+
386
+ if (size < LIBUSB_DT_CONFIG_SIZE) {
387
+ usbi_err(ctx, "short config descriptor read %d/%d",
388
+ size, LIBUSB_DT_CONFIG_SIZE);
389
+ return LIBUSB_ERROR_IO;
390
+ }
391
+
392
+ usbi_parse_descriptor(buffer, "bbwbbbbb", config, host_endian);
393
+ if (config->bDescriptorType != LIBUSB_DT_CONFIG) {
394
+ usbi_err(ctx, "unexpected descriptor %x (expected %x)",
395
+ config->bDescriptorType, LIBUSB_DT_CONFIG);
396
+ return LIBUSB_ERROR_IO;
397
+ }
398
+ if (config->bLength < LIBUSB_DT_CONFIG_SIZE) {
399
+ usbi_err(ctx, "invalid config bLength (%d)", config->bLength);
400
+ return LIBUSB_ERROR_IO;
401
+ }
402
+ if (config->bLength > size) {
403
+ usbi_err(ctx, "short config descriptor read %d/%d",
404
+ size, config->bLength);
405
+ return LIBUSB_ERROR_IO;
406
+ }
407
+ if (config->bNumInterfaces > USB_MAXINTERFACES) {
408
+ usbi_err(ctx, "too many interfaces (%d)", config->bNumInterfaces);
409
+ return LIBUSB_ERROR_IO;
410
+ }
411
+
412
+ tmp = config->bNumInterfaces * sizeof(struct libusb_interface);
413
+ usb_interface = malloc(tmp);
414
+ config->interface = usb_interface;
415
+ if (!config->interface)
416
+ return LIBUSB_ERROR_NO_MEM;
417
+
418
+ memset(usb_interface, 0, tmp);
419
+ buffer += config->bLength;
420
+ size -= config->bLength;
421
+
422
+ config->extra = NULL;
423
+ config->extra_length = 0;
424
+
425
+ for (i = 0; i < config->bNumInterfaces; i++) {
426
+ int len;
427
+ unsigned char *begin;
428
+
429
+ /* Skip over the rest of the Class Specific or Vendor */
430
+ /* Specific descriptors */
431
+ begin = buffer;
432
+ while (size >= DESC_HEADER_LENGTH) {
433
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
434
+
435
+ if (header.bLength < DESC_HEADER_LENGTH) {
436
+ usbi_err(ctx,
437
+ "invalid extra config desc len (%d)",
438
+ header.bLength);
439
+ r = LIBUSB_ERROR_IO;
440
+ goto err;
441
+ } else if (header.bLength > size) {
442
+ usbi_warn(ctx,
443
+ "short extra config desc read %d/%d",
444
+ size, header.bLength);
445
+ config->bNumInterfaces = (uint8_t)i;
446
+ return size;
447
+ }
448
+
449
+ /* If we find another "proper" descriptor then we're done */
450
+ if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
451
+ (header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
452
+ (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
453
+ (header.bDescriptorType == LIBUSB_DT_DEVICE))
454
+ break;
455
+
456
+ usbi_dbg("skipping descriptor 0x%x\n", header.bDescriptorType);
457
+ buffer += header.bLength;
458
+ size -= header.bLength;
459
+ }
460
+
461
+ /* Copy any unknown descriptors into a storage area for */
462
+ /* drivers to later parse */
463
+ len = (int)(buffer - begin);
464
+ if (len) {
465
+ /* FIXME: We should realloc and append here */
466
+ if (!config->extra_length) {
467
+ config->extra = malloc(len);
468
+ if (!config->extra) {
469
+ r = LIBUSB_ERROR_NO_MEM;
470
+ goto err;
471
+ }
472
+
473
+ memcpy((unsigned char *) config->extra, begin, len);
474
+ config->extra_length = len;
475
+ }
476
+ }
477
+
478
+ r = parse_interface(ctx, usb_interface + i, buffer, size, host_endian);
479
+ if (r < 0)
480
+ goto err;
481
+ if (r == 0) {
482
+ config->bNumInterfaces = (uint8_t)i;
483
+ break;
484
+ }
485
+
486
+ buffer += r;
487
+ size -= r;
488
+ }
489
+
490
+ return size;
491
+
492
+ err:
493
+ clear_configuration(config);
494
+ return r;
495
+ }
496
+
497
+ static int raw_desc_to_config(struct libusb_context *ctx,
498
+ unsigned char *buf, int size, int host_endian,
499
+ struct libusb_config_descriptor **config)
500
+ {
501
+ struct libusb_config_descriptor *_config = malloc(sizeof(*_config));
502
+ int r;
503
+
504
+ if (!_config)
505
+ return LIBUSB_ERROR_NO_MEM;
506
+
507
+ r = parse_configuration(ctx, _config, buf, size, host_endian);
508
+ if (r < 0) {
509
+ usbi_err(ctx, "parse_configuration failed with error %d", r);
510
+ free(_config);
511
+ return r;
512
+ } else if (r > 0) {
513
+ usbi_warn(ctx, "still %d bytes of descriptor data left", r);
514
+ }
515
+
516
+ *config = _config;
517
+ return LIBUSB_SUCCESS;
518
+ }
519
+
520
+ int usbi_device_cache_descriptor(libusb_device *dev)
521
+ {
522
+ int r, host_endian = 0;
523
+
524
+ r = usbi_backend->get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor,
525
+ &host_endian);
526
+ if (r < 0)
527
+ return r;
528
+
529
+ if (!host_endian) {
530
+ dev->device_descriptor.bcdUSB = libusb_le16_to_cpu(dev->device_descriptor.bcdUSB);
531
+ dev->device_descriptor.idVendor = libusb_le16_to_cpu(dev->device_descriptor.idVendor);
532
+ dev->device_descriptor.idProduct = libusb_le16_to_cpu(dev->device_descriptor.idProduct);
533
+ dev->device_descriptor.bcdDevice = libusb_le16_to_cpu(dev->device_descriptor.bcdDevice);
534
+ }
535
+
536
+ return LIBUSB_SUCCESS;
537
+ }
538
+
539
+ /** \ingroup desc
540
+ * Get the USB device descriptor for a given device.
541
+ *
542
+ * This is a non-blocking function; the device descriptor is cached in memory.
543
+ *
544
+ * Note since libusbx-1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102, this
545
+ * function always succeeds.
546
+ *
547
+ * \param dev the device
548
+ * \param desc output location for the descriptor data
549
+ * \returns 0 on success or a LIBUSB_ERROR code on failure
550
+ */
551
+ int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
552
+ struct libusb_device_descriptor *desc)
553
+ {
554
+ usbi_dbg("");
555
+ memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor,
556
+ sizeof (dev->device_descriptor));
557
+ return 0;
558
+ }
559
+
560
+ /** \ingroup desc
561
+ * Get the USB configuration descriptor for the currently active configuration.
562
+ * This is a non-blocking function which does not involve any requests being
563
+ * sent to the device.
564
+ *
565
+ * \param dev a device
566
+ * \param config output location for the USB configuration descriptor. Only
567
+ * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
568
+ * after use.
569
+ * \returns 0 on success
570
+ * \returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state
571
+ * \returns another LIBUSB_ERROR code on error
572
+ * \see libusb_get_config_descriptor
573
+ */
574
+ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
575
+ struct libusb_config_descriptor **config)
576
+ {
577
+ struct libusb_config_descriptor _config;
578
+ unsigned char tmp[LIBUSB_DT_CONFIG_SIZE];
579
+ unsigned char *buf = NULL;
580
+ int host_endian = 0;
581
+ int r;
582
+
583
+ r = usbi_backend->get_active_config_descriptor(dev, tmp,
584
+ LIBUSB_DT_CONFIG_SIZE, &host_endian);
585
+ if (r < 0)
586
+ return r;
587
+ if (r < LIBUSB_DT_CONFIG_SIZE) {
588
+ usbi_err(dev->ctx, "short config descriptor read %d/%d",
589
+ r, LIBUSB_DT_CONFIG_SIZE);
590
+ return LIBUSB_ERROR_IO;
591
+ }
592
+
593
+ usbi_parse_descriptor(tmp, "bbw", &_config, host_endian);
594
+ buf = malloc(_config.wTotalLength);
595
+ if (!buf)
596
+ return LIBUSB_ERROR_NO_MEM;
597
+
598
+ r = usbi_backend->get_active_config_descriptor(dev, buf,
599
+ _config.wTotalLength, &host_endian);
600
+ if (r >= 0)
601
+ r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
602
+
603
+ free(buf);
604
+ return r;
605
+ }
606
+
607
+ /** \ingroup desc
608
+ * Get a USB configuration descriptor based on its index.
609
+ * This is a non-blocking function which does not involve any requests being
610
+ * sent to the device.
611
+ *
612
+ * \param dev a device
613
+ * \param config_index the index of the configuration you wish to retrieve
614
+ * \param config output location for the USB configuration descriptor. Only
615
+ * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
616
+ * after use.
617
+ * \returns 0 on success
618
+ * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
619
+ * \returns another LIBUSB_ERROR code on error
620
+ * \see libusb_get_active_config_descriptor()
621
+ * \see libusb_get_config_descriptor_by_value()
622
+ */
623
+ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
624
+ uint8_t config_index, struct libusb_config_descriptor **config)
625
+ {
626
+ struct libusb_config_descriptor _config;
627
+ unsigned char tmp[LIBUSB_DT_CONFIG_SIZE];
628
+ unsigned char *buf = NULL;
629
+ int host_endian = 0;
630
+ int r;
631
+
632
+ usbi_dbg("index %d", config_index);
633
+ if (config_index >= dev->num_configurations)
634
+ return LIBUSB_ERROR_NOT_FOUND;
635
+
636
+ r = usbi_backend->get_config_descriptor(dev, config_index, tmp,
637
+ LIBUSB_DT_CONFIG_SIZE, &host_endian);
638
+ if (r < 0)
639
+ return r;
640
+ if (r < LIBUSB_DT_CONFIG_SIZE) {
641
+ usbi_err(dev->ctx, "short config descriptor read %d/%d",
642
+ r, LIBUSB_DT_CONFIG_SIZE);
643
+ return LIBUSB_ERROR_IO;
644
+ }
645
+
646
+ usbi_parse_descriptor(tmp, "bbw", &_config, host_endian);
647
+ buf = malloc(_config.wTotalLength);
648
+ if (!buf)
649
+ return LIBUSB_ERROR_NO_MEM;
650
+
651
+ r = usbi_backend->get_config_descriptor(dev, config_index, buf,
652
+ _config.wTotalLength, &host_endian);
653
+ if (r >= 0)
654
+ r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
655
+
656
+ free(buf);
657
+ return r;
658
+ }
659
+
660
+ /* iterate through all configurations, returning the index of the configuration
661
+ * matching a specific bConfigurationValue in the idx output parameter, or -1
662
+ * if the config was not found.
663
+ * returns 0 on success or a LIBUSB_ERROR code
664
+ */
665
+ int usbi_get_config_index_by_value(struct libusb_device *dev,
666
+ uint8_t bConfigurationValue, int *idx)
667
+ {
668
+ uint8_t i;
669
+
670
+ usbi_dbg("value %d", bConfigurationValue);
671
+ for (i = 0; i < dev->num_configurations; i++) {
672
+ unsigned char tmp[6];
673
+ int host_endian;
674
+ int r = usbi_backend->get_config_descriptor(dev, i, tmp, sizeof(tmp),
675
+ &host_endian);
676
+ if (r < 0) {
677
+ *idx = -1;
678
+ return r;
679
+ }
680
+ if (tmp[5] == bConfigurationValue) {
681
+ *idx = i;
682
+ return 0;
683
+ }
684
+ }
685
+
686
+ *idx = -1;
687
+ return 0;
688
+ }
689
+
690
+ /** \ingroup desc
691
+ * Get a USB configuration descriptor with a specific bConfigurationValue.
692
+ * This is a non-blocking function which does not involve any requests being
693
+ * sent to the device.
694
+ *
695
+ * \param dev a device
696
+ * \param bConfigurationValue the bConfigurationValue of the configuration you
697
+ * wish to retrieve
698
+ * \param config output location for the USB configuration descriptor. Only
699
+ * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
700
+ * after use.
701
+ * \returns 0 on success
702
+ * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
703
+ * \returns another LIBUSB_ERROR code on error
704
+ * \see libusb_get_active_config_descriptor()
705
+ * \see libusb_get_config_descriptor()
706
+ */
707
+ int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev,
708
+ uint8_t bConfigurationValue, struct libusb_config_descriptor **config)
709
+ {
710
+ int r, idx, host_endian;
711
+ unsigned char *buf = NULL;
712
+
713
+ if (usbi_backend->get_config_descriptor_by_value) {
714
+ r = usbi_backend->get_config_descriptor_by_value(dev,
715
+ bConfigurationValue, &buf, &host_endian);
716
+ if (r < 0)
717
+ return r;
718
+ return raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
719
+ }
720
+
721
+ r = usbi_get_config_index_by_value(dev, bConfigurationValue, &idx);
722
+ if (r < 0)
723
+ return r;
724
+ else if (idx == -1)
725
+ return LIBUSB_ERROR_NOT_FOUND;
726
+ else
727
+ return libusb_get_config_descriptor(dev, (uint8_t) idx, config);
728
+ }
729
+
730
+ /** \ingroup desc
731
+ * Free a configuration descriptor obtained from
732
+ * libusb_get_active_config_descriptor() or libusb_get_config_descriptor().
733
+ * It is safe to call this function with a NULL config parameter, in which
734
+ * case the function simply returns.
735
+ *
736
+ * \param config the configuration descriptor to free
737
+ */
738
+ void API_EXPORTED libusb_free_config_descriptor(
739
+ struct libusb_config_descriptor *config)
740
+ {
741
+ if (!config)
742
+ return;
743
+
744
+ clear_configuration(config);
745
+ free(config);
746
+ }
747
+
748
+ /** \ingroup desc
749
+ * Get an endpoints superspeed endpoint companion descriptor (if any)
750
+ *
751
+ * \param ctx the context to operate on, or NULL for the default context
752
+ * \param endpoint endpoint descriptor from which to get the superspeed
753
+ * endpoint companion descriptor
754
+ * \param ep_comp output location for the superspeed endpoint companion
755
+ * descriptor. Only valid if 0 was returned. Must be freed with
756
+ * libusb_free_ss_endpoint_companion_descriptor() after use.
757
+ * \returns 0 on success
758
+ * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
759
+ * \returns another LIBUSB_ERROR code on error
760
+ */
761
+ int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor(
762
+ struct libusb_context *ctx,
763
+ const struct libusb_endpoint_descriptor *endpoint,
764
+ struct libusb_ss_endpoint_companion_descriptor **ep_comp)
765
+ {
766
+ struct usb_descriptor_header header;
767
+ int size = endpoint->extra_length;
768
+ const unsigned char *buffer = endpoint->extra;
769
+
770
+ *ep_comp = NULL;
771
+
772
+ while (size >= DESC_HEADER_LENGTH) {
773
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
774
+ if (header.bLength < 2 || header.bLength > size) {
775
+ usbi_err(ctx, "invalid descriptor length %d",
776
+ header.bLength);
777
+ return LIBUSB_ERROR_IO;
778
+ }
779
+ if (header.bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) {
780
+ buffer += header.bLength;
781
+ size -= header.bLength;
782
+ continue;
783
+ }
784
+ if (header.bLength < LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE) {
785
+ usbi_err(ctx, "invalid ss-ep-comp-desc length %d",
786
+ header.bLength);
787
+ return LIBUSB_ERROR_IO;
788
+ }
789
+ *ep_comp = malloc(sizeof(**ep_comp));
790
+ if (*ep_comp == NULL)
791
+ return LIBUSB_ERROR_NO_MEM;
792
+ usbi_parse_descriptor(buffer, "bbbbw", *ep_comp, 0);
793
+ return LIBUSB_SUCCESS;
794
+ }
795
+ return LIBUSB_ERROR_NOT_FOUND;
796
+ }
797
+
798
+ /** \ingroup desc
799
+ * Free a superspeed endpoint companion descriptor obtained from
800
+ * libusb_get_ss_endpoint_companion_descriptor().
801
+ * It is safe to call this function with a NULL ep_comp parameter, in which
802
+ * case the function simply returns.
803
+ *
804
+ * \param ep_comp the superspeed endpoint companion descriptor to free
805
+ */
806
+ void API_EXPORTED libusb_free_ss_endpoint_companion_descriptor(
807
+ struct libusb_ss_endpoint_companion_descriptor *ep_comp)
808
+ {
809
+ free(ep_comp);
810
+ }
811
+
812
+ static int parse_bos(struct libusb_context *ctx,
813
+ struct libusb_bos_descriptor **bos,
814
+ unsigned char *buffer, int size, int host_endian)
815
+ {
816
+ struct libusb_bos_descriptor bos_header, *_bos;
817
+ struct libusb_bos_dev_capability_descriptor dev_cap;
818
+ int i;
819
+
820
+ if (size < LIBUSB_DT_BOS_SIZE) {
821
+ usbi_err(ctx, "short bos descriptor read %d/%d",
822
+ size, LIBUSB_DT_BOS_SIZE);
823
+ return LIBUSB_ERROR_IO;
824
+ }
825
+
826
+ usbi_parse_descriptor(buffer, "bbwb", &bos_header, host_endian);
827
+ if (bos_header.bDescriptorType != LIBUSB_DT_BOS) {
828
+ usbi_err(ctx, "unexpected descriptor %x (expected %x)",
829
+ bos_header.bDescriptorType, LIBUSB_DT_BOS);
830
+ return LIBUSB_ERROR_IO;
831
+ }
832
+ if (bos_header.bLength < LIBUSB_DT_BOS_SIZE) {
833
+ usbi_err(ctx, "invalid bos bLength (%d)", bos_header.bLength);
834
+ return LIBUSB_ERROR_IO;
835
+ }
836
+ if (bos_header.bLength > size) {
837
+ usbi_err(ctx, "short bos descriptor read %d/%d",
838
+ size, bos_header.bLength);
839
+ return LIBUSB_ERROR_IO;
840
+ }
841
+
842
+ _bos = calloc (1,
843
+ sizeof(*_bos) + bos_header.bNumDeviceCaps * sizeof(void *));
844
+ if (!_bos)
845
+ return LIBUSB_ERROR_NO_MEM;
846
+
847
+ usbi_parse_descriptor(buffer, "bbwb", _bos, host_endian);
848
+ buffer += bos_header.bLength;
849
+ size -= bos_header.bLength;
850
+
851
+ /* Get the device capability descriptors */
852
+ for (i = 0; i < bos_header.bNumDeviceCaps; i++) {
853
+ if (size < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
854
+ usbi_warn(ctx, "short dev-cap descriptor read %d/%d",
855
+ size, LIBUSB_DT_DEVICE_CAPABILITY_SIZE);
856
+ break;
857
+ }
858
+ usbi_parse_descriptor(buffer, "bbb", &dev_cap, host_endian);
859
+ if (dev_cap.bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) {
860
+ usbi_warn(ctx, "unexpected descriptor %x (expected %x)",
861
+ dev_cap.bDescriptorType, LIBUSB_DT_DEVICE_CAPABILITY);
862
+ break;
863
+ }
864
+ if (dev_cap.bLength < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) {
865
+ usbi_err(ctx, "invalid dev-cap bLength (%d)",
866
+ dev_cap.bLength);
867
+ libusb_free_bos_descriptor(_bos);
868
+ return LIBUSB_ERROR_IO;
869
+ }
870
+ if (dev_cap.bLength > size) {
871
+ usbi_warn(ctx, "short dev-cap descriptor read %d/%d",
872
+ size, dev_cap.bLength);
873
+ break;
874
+ }
875
+
876
+ _bos->dev_capability[i] = malloc(dev_cap.bLength);
877
+ if (!_bos->dev_capability[i]) {
878
+ libusb_free_bos_descriptor(_bos);
879
+ return LIBUSB_ERROR_NO_MEM;
880
+ }
881
+ memcpy(_bos->dev_capability[i], buffer, dev_cap.bLength);
882
+ buffer += dev_cap.bLength;
883
+ size -= dev_cap.bLength;
884
+ }
885
+ _bos->bNumDeviceCaps = (uint8_t)i;
886
+ *bos = _bos;
887
+
888
+ return LIBUSB_SUCCESS;
889
+ }
890
+
891
+ /** \ingroup desc
892
+ * Get a Binary Object Store (BOS) descriptor
893
+ * This is a BLOCKING function, which will send requests to the device.
894
+ *
895
+ * \param handle the handle of an open libusb device
896
+ * \param bos output location for the BOS descriptor. Only valid if 0 was returned.
897
+ * Must be freed with \ref libusb_free_bos_descriptor() after use.
898
+ * \returns 0 on success
899
+ * \returns LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor
900
+ * \returns another LIBUSB_ERROR code on error
901
+ */
902
+ int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *handle,
903
+ struct libusb_bos_descriptor **bos)
904
+ {
905
+ struct libusb_bos_descriptor _bos;
906
+ uint8_t bos_header[LIBUSB_DT_BOS_SIZE] = {0};
907
+ unsigned char *bos_data = NULL;
908
+ const int host_endian = 0;
909
+ int r;
910
+
911
+ /* Read the BOS. This generates 2 requests on the bus,
912
+ * one for the header, and one for the full BOS */
913
+ r = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, bos_header,
914
+ LIBUSB_DT_BOS_SIZE);
915
+ if (r < 0) {
916
+ if (r != LIBUSB_ERROR_PIPE)
917
+ usbi_err(handle->dev->ctx, "failed to read BOS (%d)", r);
918
+ return r;
919
+ }
920
+ if (r < LIBUSB_DT_BOS_SIZE) {
921
+ usbi_err(handle->dev->ctx, "short BOS read %d/%d",
922
+ r, LIBUSB_DT_BOS_SIZE);
923
+ return LIBUSB_ERROR_IO;
924
+ }
925
+
926
+ usbi_parse_descriptor(bos_header, "bbwb", &_bos, host_endian);
927
+ usbi_dbg("found BOS descriptor: size %d bytes, %d capabilities",
928
+ _bos.wTotalLength, _bos.bNumDeviceCaps);
929
+ bos_data = calloc(_bos.wTotalLength, 1);
930
+ if (bos_data == NULL)
931
+ return LIBUSB_ERROR_NO_MEM;
932
+
933
+ r = libusb_get_descriptor(handle, LIBUSB_DT_BOS, 0, bos_data,
934
+ _bos.wTotalLength);
935
+ if (r >= 0)
936
+ r = parse_bos(handle->dev->ctx, bos, bos_data, r, host_endian);
937
+ else
938
+ usbi_err(handle->dev->ctx, "failed to read BOS (%d)", r);
939
+
940
+ free(bos_data);
941
+ return r;
942
+ }
943
+
944
+ /** \ingroup desc
945
+ * Free a BOS descriptor obtained from libusb_get_bos_descriptor().
946
+ * It is safe to call this function with a NULL bos parameter, in which
947
+ * case the function simply returns.
948
+ *
949
+ * \param bos the BOS descriptor to free
950
+ */
951
+ void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos)
952
+ {
953
+ int i;
954
+
955
+ if (!bos)
956
+ return;
957
+
958
+ for (i = 0; i < bos->bNumDeviceCaps; i++)
959
+ free(bos->dev_capability[i]);
960
+ free(bos);
961
+ }
962
+
963
+ /** \ingroup desc
964
+ * Get an USB 2.0 Extension descriptor
965
+ *
966
+ * \param ctx the context to operate on, or NULL for the default context
967
+ * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
968
+ * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION
969
+ * LIBUSB_BT_USB_2_0_EXTENSION
970
+ * \param usb_2_0_extension output location for the USB 2.0 Extension
971
+ * descriptor. Only valid if 0 was returned. Must be freed with
972
+ * libusb_free_usb_2_0_extension_descriptor() after use.
973
+ * \returns 0 on success
974
+ * \returns a LIBUSB_ERROR code on error
975
+ */
976
+ int API_EXPORTED libusb_get_usb_2_0_extension_descriptor(
977
+ struct libusb_context *ctx,
978
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
979
+ struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension)
980
+ {
981
+ struct libusb_usb_2_0_extension_descriptor *_usb_2_0_extension;
982
+ const int host_endian = 0;
983
+
984
+ if (dev_cap->bDevCapabilityType != LIBUSB_BT_USB_2_0_EXTENSION) {
985
+ usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)",
986
+ dev_cap->bDevCapabilityType,
987
+ LIBUSB_BT_USB_2_0_EXTENSION);
988
+ return LIBUSB_ERROR_INVALID_PARAM;
989
+ }
990
+ if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) {
991
+ usbi_err(ctx, "short dev-cap descriptor read %d/%d",
992
+ dev_cap->bLength, LIBUSB_BT_USB_2_0_EXTENSION_SIZE);
993
+ return LIBUSB_ERROR_IO;
994
+ }
995
+
996
+ _usb_2_0_extension = malloc(sizeof(*_usb_2_0_extension));
997
+ if (!_usb_2_0_extension)
998
+ return LIBUSB_ERROR_NO_MEM;
999
+
1000
+ usbi_parse_descriptor((unsigned char *)dev_cap, "bbbd",
1001
+ _usb_2_0_extension, host_endian);
1002
+
1003
+ *usb_2_0_extension = _usb_2_0_extension;
1004
+ return LIBUSB_SUCCESS;
1005
+ }
1006
+
1007
+ /** \ingroup desc
1008
+ * Free a USB 2.0 Extension descriptor obtained from
1009
+ * libusb_get_usb_2_0_extension_descriptor().
1010
+ * It is safe to call this function with a NULL usb_2_0_extension parameter,
1011
+ * in which case the function simply returns.
1012
+ *
1013
+ * \param usb_2_0_extension the USB 2.0 Extension descriptor to free
1014
+ */
1015
+ void API_EXPORTED libusb_free_usb_2_0_extension_descriptor(
1016
+ struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension)
1017
+ {
1018
+ free(usb_2_0_extension);
1019
+ }
1020
+
1021
+ /** \ingroup desc
1022
+ * Get a SuperSpeed USB Device Capability descriptor
1023
+ *
1024
+ * \param ctx the context to operate on, or NULL for the default context
1025
+ * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
1026
+ * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
1027
+ * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
1028
+ * \param ss_usb_device_cap output location for the SuperSpeed USB Device
1029
+ * Capability descriptor. Only valid if 0 was returned. Must be freed with
1030
+ * libusb_free_ss_usb_device_capability_descriptor() after use.
1031
+ * \returns 0 on success
1032
+ * \returns a LIBUSB_ERROR code on error
1033
+ */
1034
+ int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor(
1035
+ struct libusb_context *ctx,
1036
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
1037
+ struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap)
1038
+ {
1039
+ struct libusb_ss_usb_device_capability_descriptor *_ss_usb_device_cap;
1040
+ const int host_endian = 0;
1041
+
1042
+ if (dev_cap->bDevCapabilityType != LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) {
1043
+ usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)",
1044
+ dev_cap->bDevCapabilityType,
1045
+ LIBUSB_BT_SS_USB_DEVICE_CAPABILITY);
1046
+ return LIBUSB_ERROR_INVALID_PARAM;
1047
+ }
1048
+ if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) {
1049
+ usbi_err(ctx, "short dev-cap descriptor read %d/%d",
1050
+ dev_cap->bLength, LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE);
1051
+ return LIBUSB_ERROR_IO;
1052
+ }
1053
+
1054
+ _ss_usb_device_cap = malloc(sizeof(*_ss_usb_device_cap));
1055
+ if (!_ss_usb_device_cap)
1056
+ return LIBUSB_ERROR_NO_MEM;
1057
+
1058
+ usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbwbbw",
1059
+ _ss_usb_device_cap, host_endian);
1060
+
1061
+ *ss_usb_device_cap = _ss_usb_device_cap;
1062
+ return LIBUSB_SUCCESS;
1063
+ }
1064
+
1065
+ /** \ingroup desc
1066
+ * Free a SuperSpeed USB Device Capability descriptor obtained from
1067
+ * libusb_get_ss_usb_device_capability_descriptor().
1068
+ * It is safe to call this function with a NULL ss_usb_device_cap
1069
+ * parameter, in which case the function simply returns.
1070
+ *
1071
+ * \param ss_usb_device_cap the USB 2.0 Extension descriptor to free
1072
+ */
1073
+ void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor(
1074
+ struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap)
1075
+ {
1076
+ free(ss_usb_device_cap);
1077
+ }
1078
+
1079
+ /** \ingroup desc
1080
+ * Get a Container ID descriptor
1081
+ *
1082
+ * \param ctx the context to operate on, or NULL for the default context
1083
+ * \param dev_cap Device Capability descriptor with a bDevCapabilityType of
1084
+ * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID
1085
+ * LIBUSB_BT_CONTAINER_ID
1086
+ * \param container_id output location for the Container ID descriptor.
1087
+ * Only valid if 0 was returned. Must be freed with
1088
+ * libusb_free_container_id_descriptor() after use.
1089
+ * \returns 0 on success
1090
+ * \returns a LIBUSB_ERROR code on error
1091
+ */
1092
+ int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx,
1093
+ struct libusb_bos_dev_capability_descriptor *dev_cap,
1094
+ struct libusb_container_id_descriptor **container_id)
1095
+ {
1096
+ struct libusb_container_id_descriptor *_container_id;
1097
+ const int host_endian = 0;
1098
+
1099
+ if (dev_cap->bDevCapabilityType != LIBUSB_BT_CONTAINER_ID) {
1100
+ usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)",
1101
+ dev_cap->bDevCapabilityType,
1102
+ LIBUSB_BT_CONTAINER_ID);
1103
+ return LIBUSB_ERROR_INVALID_PARAM;
1104
+ }
1105
+ if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) {
1106
+ usbi_err(ctx, "short dev-cap descriptor read %d/%d",
1107
+ dev_cap->bLength, LIBUSB_BT_CONTAINER_ID_SIZE);
1108
+ return LIBUSB_ERROR_IO;
1109
+ }
1110
+
1111
+ _container_id = malloc(sizeof(*_container_id));
1112
+ if (!_container_id)
1113
+ return LIBUSB_ERROR_NO_MEM;
1114
+
1115
+ usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbu",
1116
+ _container_id, host_endian);
1117
+
1118
+ *container_id = _container_id;
1119
+ return LIBUSB_SUCCESS;
1120
+ }
1121
+
1122
+ /** \ingroup desc
1123
+ * Free a Container ID descriptor obtained from
1124
+ * libusb_get_container_id_descriptor().
1125
+ * It is safe to call this function with a NULL container_id parameter,
1126
+ * in which case the function simply returns.
1127
+ *
1128
+ * \param container_id the USB 2.0 Extension descriptor to free
1129
+ */
1130
+ void API_EXPORTED libusb_free_container_id_descriptor(
1131
+ struct libusb_container_id_descriptor *container_id)
1132
+ {
1133
+ free(container_id);
1134
+ }
1135
+
1136
+ /** \ingroup desc
1137
+ * Retrieve a string descriptor in C style ASCII.
1138
+ *
1139
+ * Wrapper around libusb_get_string_descriptor(). Uses the first language
1140
+ * supported by the device.
1141
+ *
1142
+ * \param dev a device handle
1143
+ * \param desc_index the index of the descriptor to retrieve
1144
+ * \param data output buffer for ASCII string descriptor
1145
+ * \param length size of data buffer
1146
+ * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
1147
+ */
1148
+ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
1149
+ uint8_t desc_index, unsigned char *data, int length)
1150
+ {
1151
+ unsigned char tbuf[255]; /* Some devices choke on size > 255 */
1152
+ int r, si, di;
1153
+ uint16_t langid;
1154
+
1155
+ /* Asking for the zero'th index is special - it returns a string
1156
+ * descriptor that contains all the language IDs supported by the
1157
+ * device. Typically there aren't many - often only one. Language
1158
+ * IDs are 16 bit numbers, and they start at the third byte in the
1159
+ * descriptor. There's also no point in trying to read descriptor 0
1160
+ * with this function. See USB 2.0 specification section 9.6.7 for
1161
+ * more information.
1162
+ */
1163
+
1164
+ if (desc_index == 0)
1165
+ return LIBUSB_ERROR_INVALID_PARAM;
1166
+
1167
+ r = libusb_get_string_descriptor(dev, 0, 0, tbuf, sizeof(tbuf));
1168
+ if (r < 0)
1169
+ return r;
1170
+
1171
+ if (r < 4)
1172
+ return LIBUSB_ERROR_IO;
1173
+
1174
+ langid = tbuf[2] | (tbuf[3] << 8);
1175
+
1176
+ r = libusb_get_string_descriptor(dev, desc_index, langid, tbuf,
1177
+ sizeof(tbuf));
1178
+ if (r < 0)
1179
+ return r;
1180
+
1181
+ if (tbuf[1] != LIBUSB_DT_STRING)
1182
+ return LIBUSB_ERROR_IO;
1183
+
1184
+ if (tbuf[0] > r)
1185
+ return LIBUSB_ERROR_IO;
1186
+
1187
+ for (di = 0, si = 2; si < tbuf[0]; si += 2) {
1188
+ if (di >= (length - 1))
1189
+ break;
1190
+
1191
+ if ((tbuf[si] & 0x80) || (tbuf[si + 1])) /* non-ASCII */
1192
+ data[di++] = '?';
1193
+ else
1194
+ data[di++] = tbuf[si];
1195
+ }
1196
+
1197
+ data[di] = 0;
1198
+ return di;
1199
+ }