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,731 @@
1
+ /*
2
+ * USB descriptor handling functions for libusbx
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
+ #include <errno.h>
22
+ #include <stdint.h>
23
+ #include <stdlib.h>
24
+ #include <string.h>
25
+
26
+ #include "libusbi.h"
27
+
28
+ #define DESC_HEADER_LENGTH 2
29
+ #define DEVICE_DESC_LENGTH 18
30
+ #define CONFIG_DESC_LENGTH 9
31
+ #define INTERFACE_DESC_LENGTH 9
32
+ #define ENDPOINT_DESC_LENGTH 7
33
+ #define ENDPOINT_AUDIO_DESC_LENGTH 9
34
+
35
+ /** @defgroup desc USB descriptors
36
+ * This page details how to examine the various standard USB descriptors
37
+ * for detected devices
38
+ */
39
+
40
+ /* set host_endian if the w values are already in host endian format,
41
+ * as opposed to bus endian. */
42
+ int usbi_parse_descriptor(unsigned char *source, const char *descriptor,
43
+ void *dest, int host_endian)
44
+ {
45
+ unsigned char *sp = source, *dp = dest;
46
+ uint16_t w;
47
+ const char *cp;
48
+
49
+ for (cp = descriptor; *cp; cp++) {
50
+ switch (*cp) {
51
+ case 'b': /* 8-bit byte */
52
+ *dp++ = *sp++;
53
+ break;
54
+ case 'w': /* 16-bit word, convert from little endian to CPU */
55
+ dp += ((uintptr_t)dp & 1); /* Align to word boundary */
56
+
57
+ if (host_endian) {
58
+ memcpy(dp, sp, 2);
59
+ } else {
60
+ w = (sp[1] << 8) | sp[0];
61
+ *((uint16_t *)dp) = w;
62
+ }
63
+ sp += 2;
64
+ dp += 2;
65
+ break;
66
+ }
67
+ }
68
+
69
+ return (int) (sp - source);
70
+ }
71
+
72
+ static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint)
73
+ {
74
+ if (endpoint->extra)
75
+ free((unsigned char *) endpoint->extra);
76
+ }
77
+
78
+ static int parse_endpoint(struct libusb_context *ctx,
79
+ struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer,
80
+ int size, int host_endian)
81
+ {
82
+ struct usb_descriptor_header header;
83
+ unsigned char *extra;
84
+ unsigned char *begin;
85
+ int parsed = 0;
86
+ int len;
87
+
88
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
89
+
90
+ /* Everything should be fine being passed into here, but we sanity */
91
+ /* check JIC */
92
+ if (header.bLength > size) {
93
+ usbi_err(ctx, "ran out of descriptors parsing");
94
+ return -1;
95
+ }
96
+
97
+ if (header.bDescriptorType != LIBUSB_DT_ENDPOINT) {
98
+ usbi_err(ctx, "unexpected descriptor %x (expected %x)",
99
+ header.bDescriptorType, LIBUSB_DT_ENDPOINT);
100
+ return parsed;
101
+ }
102
+
103
+ if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH)
104
+ usbi_parse_descriptor(buffer, "bbbbwbbb", endpoint, host_endian);
105
+ else if (header.bLength >= ENDPOINT_DESC_LENGTH)
106
+ usbi_parse_descriptor(buffer, "bbbbwb", endpoint, host_endian);
107
+
108
+ buffer += header.bLength;
109
+ size -= header.bLength;
110
+ parsed += header.bLength;
111
+
112
+ /* Skip over the rest of the Class Specific or Vendor Specific */
113
+ /* descriptors */
114
+ begin = buffer;
115
+ while (size >= DESC_HEADER_LENGTH) {
116
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
117
+
118
+ if (header.bLength < 2) {
119
+ usbi_err(ctx, "invalid descriptor length %d", header.bLength);
120
+ return -1;
121
+ }
122
+
123
+ /* If we find another "proper" descriptor then we're done */
124
+ if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
125
+ (header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
126
+ (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
127
+ (header.bDescriptorType == LIBUSB_DT_DEVICE))
128
+ break;
129
+
130
+ usbi_dbg("skipping descriptor %x", header.bDescriptorType);
131
+ buffer += header.bLength;
132
+ size -= header.bLength;
133
+ parsed += header.bLength;
134
+ }
135
+
136
+ /* Copy any unknown descriptors into a storage area for drivers */
137
+ /* to later parse */
138
+ len = (int)(buffer - begin);
139
+ if (!len) {
140
+ endpoint->extra = NULL;
141
+ endpoint->extra_length = 0;
142
+ return parsed;
143
+ }
144
+
145
+ extra = malloc(len);
146
+ endpoint->extra = extra;
147
+ if (!extra) {
148
+ endpoint->extra_length = 0;
149
+ return LIBUSB_ERROR_NO_MEM;
150
+ }
151
+
152
+ memcpy(extra, begin, len);
153
+ endpoint->extra_length = len;
154
+
155
+ return parsed;
156
+ }
157
+
158
+ static void clear_interface(struct libusb_interface *usb_interface)
159
+ {
160
+ int i;
161
+ int j;
162
+
163
+ if (usb_interface->altsetting) {
164
+ for (i = 0; i < usb_interface->num_altsetting; i++) {
165
+ struct libusb_interface_descriptor *ifp =
166
+ (struct libusb_interface_descriptor *)
167
+ usb_interface->altsetting + i;
168
+ if (ifp->extra)
169
+ free((void *) ifp->extra);
170
+ if (ifp->endpoint) {
171
+ for (j = 0; j < ifp->bNumEndpoints; j++)
172
+ clear_endpoint((struct libusb_endpoint_descriptor *)
173
+ ifp->endpoint + j);
174
+ free((void *) ifp->endpoint);
175
+ }
176
+ }
177
+ free((void *) usb_interface->altsetting);
178
+ usb_interface->altsetting = NULL;
179
+ }
180
+
181
+ }
182
+
183
+ static int parse_interface(libusb_context *ctx,
184
+ struct libusb_interface *usb_interface, unsigned char *buffer, int size,
185
+ int host_endian)
186
+ {
187
+ int i;
188
+ int len;
189
+ int r;
190
+ int parsed = 0;
191
+ size_t tmp;
192
+ struct usb_descriptor_header header;
193
+ struct libusb_interface_descriptor *ifp;
194
+ unsigned char *begin;
195
+
196
+ usb_interface->num_altsetting = 0;
197
+
198
+ while (size >= INTERFACE_DESC_LENGTH) {
199
+ struct libusb_interface_descriptor *altsetting =
200
+ (struct libusb_interface_descriptor *) usb_interface->altsetting;
201
+ altsetting = usbi_reallocf(altsetting,
202
+ sizeof(struct libusb_interface_descriptor) *
203
+ (usb_interface->num_altsetting + 1));
204
+ if (!altsetting) {
205
+ r = LIBUSB_ERROR_NO_MEM;
206
+ goto err;
207
+ }
208
+ usb_interface->altsetting = altsetting;
209
+
210
+ ifp = altsetting + usb_interface->num_altsetting;
211
+ usb_interface->num_altsetting++;
212
+ usbi_parse_descriptor(buffer, "bbbbbbbbb", ifp, 0);
213
+ ifp->extra = NULL;
214
+ ifp->extra_length = 0;
215
+ ifp->endpoint = NULL;
216
+
217
+ /* Skip over the interface */
218
+ buffer += ifp->bLength;
219
+ parsed += ifp->bLength;
220
+ size -= ifp->bLength;
221
+
222
+ begin = buffer;
223
+
224
+ /* Skip over any interface, class or vendor descriptors */
225
+ while (size >= DESC_HEADER_LENGTH) {
226
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
227
+ if (header.bLength < 2) {
228
+ usbi_err(ctx, "invalid descriptor of length %d",
229
+ header.bLength);
230
+ r = LIBUSB_ERROR_IO;
231
+ goto err;
232
+ }
233
+
234
+ /* If we find another "proper" descriptor then we're done */
235
+ if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
236
+ (header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
237
+ (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
238
+ (header.bDescriptorType == LIBUSB_DT_DEVICE))
239
+ break;
240
+
241
+ buffer += header.bLength;
242
+ parsed += header.bLength;
243
+ size -= header.bLength;
244
+ }
245
+
246
+ /* Copy any unknown descriptors into a storage area for */
247
+ /* drivers to later parse */
248
+ len = (int)(buffer - begin);
249
+ if (len) {
250
+ ifp->extra = malloc(len);
251
+ if (!ifp->extra) {
252
+ r = LIBUSB_ERROR_NO_MEM;
253
+ goto err;
254
+ }
255
+ memcpy((unsigned char *) ifp->extra, begin, len);
256
+ ifp->extra_length = len;
257
+ }
258
+
259
+ /* Did we hit an unexpected descriptor? */
260
+ if (size >= DESC_HEADER_LENGTH) {
261
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
262
+ if ((header.bDescriptorType == LIBUSB_DT_CONFIG) ||
263
+ (header.bDescriptorType == LIBUSB_DT_DEVICE)) {
264
+ return parsed;
265
+ }
266
+ }
267
+
268
+ if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
269
+ usbi_err(ctx, "too many endpoints (%d)", ifp->bNumEndpoints);
270
+ r = LIBUSB_ERROR_IO;
271
+ goto err;
272
+ }
273
+
274
+ if (ifp->bNumEndpoints > 0) {
275
+ struct libusb_endpoint_descriptor *endpoint;
276
+ tmp = ifp->bNumEndpoints * sizeof(struct libusb_endpoint_descriptor);
277
+ endpoint = malloc(tmp);
278
+ ifp->endpoint = endpoint;
279
+ if (!endpoint) {
280
+ r = LIBUSB_ERROR_NO_MEM;
281
+ goto err;
282
+ }
283
+
284
+ memset(endpoint, 0, tmp);
285
+ for (i = 0; i < ifp->bNumEndpoints; i++) {
286
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
287
+
288
+ if (header.bLength > size) {
289
+ usbi_err(ctx, "ran out of descriptors parsing");
290
+ r = LIBUSB_ERROR_IO;
291
+ goto err;
292
+ }
293
+
294
+ r = parse_endpoint(ctx, endpoint + i, buffer, size,
295
+ host_endian);
296
+ if (r < 0)
297
+ goto err;
298
+
299
+ buffer += r;
300
+ parsed += r;
301
+ size -= r;
302
+ }
303
+ }
304
+
305
+ /* We check to see if it's an alternate to this one */
306
+ ifp = (struct libusb_interface_descriptor *) buffer;
307
+ if (size < LIBUSB_DT_INTERFACE_SIZE ||
308
+ ifp->bDescriptorType != LIBUSB_DT_INTERFACE ||
309
+ !ifp->bAlternateSetting)
310
+ return parsed;
311
+ }
312
+
313
+ return parsed;
314
+ err:
315
+ clear_interface(usb_interface);
316
+ return r;
317
+ }
318
+
319
+ static void clear_configuration(struct libusb_config_descriptor *config)
320
+ {
321
+ if (config->interface) {
322
+ int i;
323
+ for (i = 0; i < config->bNumInterfaces; i++)
324
+ clear_interface((struct libusb_interface *)
325
+ config->interface + i);
326
+ free((void *) config->interface);
327
+ }
328
+ if (config->extra)
329
+ free((void *) config->extra);
330
+ }
331
+
332
+ static int parse_configuration(struct libusb_context *ctx,
333
+ struct libusb_config_descriptor *config, unsigned char *buffer,
334
+ int host_endian)
335
+ {
336
+ int i;
337
+ int r;
338
+ int size;
339
+ size_t tmp;
340
+ struct usb_descriptor_header header;
341
+ struct libusb_interface *usb_interface;
342
+
343
+ usbi_parse_descriptor(buffer, "bbwbbbbb", config, host_endian);
344
+ size = config->wTotalLength;
345
+
346
+ if (config->bNumInterfaces > USB_MAXINTERFACES) {
347
+ usbi_err(ctx, "too many interfaces (%d)", config->bNumInterfaces);
348
+ return LIBUSB_ERROR_IO;
349
+ }
350
+
351
+ tmp = config->bNumInterfaces * sizeof(struct libusb_interface);
352
+ usb_interface = malloc(tmp);
353
+ config->interface = usb_interface;
354
+ if (!config->interface)
355
+ return LIBUSB_ERROR_NO_MEM;
356
+
357
+ memset(usb_interface, 0, tmp);
358
+ buffer += config->bLength;
359
+ size -= config->bLength;
360
+
361
+ config->extra = NULL;
362
+ config->extra_length = 0;
363
+
364
+ for (i = 0; i < config->bNumInterfaces; i++) {
365
+ int len;
366
+ unsigned char *begin;
367
+
368
+ /* Skip over the rest of the Class Specific or Vendor */
369
+ /* Specific descriptors */
370
+ begin = buffer;
371
+ while (size >= DESC_HEADER_LENGTH) {
372
+ usbi_parse_descriptor(buffer, "bb", &header, 0);
373
+
374
+ if ((header.bLength > size) ||
375
+ (header.bLength < DESC_HEADER_LENGTH)) {
376
+ usbi_err(ctx, "invalid descriptor length of %d",
377
+ header.bLength);
378
+ r = LIBUSB_ERROR_IO;
379
+ goto err;
380
+ }
381
+
382
+ /* If we find another "proper" descriptor then we're done */
383
+ if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
384
+ (header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
385
+ (header.bDescriptorType == LIBUSB_DT_CONFIG) ||
386
+ (header.bDescriptorType == LIBUSB_DT_DEVICE))
387
+ break;
388
+
389
+ usbi_dbg("skipping descriptor 0x%x\n", header.bDescriptorType);
390
+ buffer += header.bLength;
391
+ size -= header.bLength;
392
+ }
393
+
394
+ /* Copy any unknown descriptors into a storage area for */
395
+ /* drivers to later parse */
396
+ len = (int)(buffer - begin);
397
+ if (len) {
398
+ /* FIXME: We should realloc and append here */
399
+ if (!config->extra_length) {
400
+ config->extra = malloc(len);
401
+ if (!config->extra) {
402
+ r = LIBUSB_ERROR_NO_MEM;
403
+ goto err;
404
+ }
405
+
406
+ memcpy((unsigned char *) config->extra, begin, len);
407
+ config->extra_length = len;
408
+ }
409
+ }
410
+
411
+ r = parse_interface(ctx, usb_interface + i, buffer, size, host_endian);
412
+ if (r < 0)
413
+ goto err;
414
+
415
+ buffer += r;
416
+ size -= r;
417
+ }
418
+
419
+ return size;
420
+
421
+ err:
422
+ clear_configuration(config);
423
+ return r;
424
+ }
425
+
426
+ /** \ingroup desc
427
+ * Get the USB device descriptor for a given device.
428
+ *
429
+ * This is a non-blocking function; the device descriptor is cached in memory.
430
+ *
431
+ * \param dev the device
432
+ * \param desc output location for the descriptor data
433
+ * \returns 0 on success or a LIBUSB_ERROR code on failure
434
+ */
435
+ int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
436
+ struct libusb_device_descriptor *desc)
437
+ {
438
+ unsigned char raw_desc[DEVICE_DESC_LENGTH];
439
+ int host_endian = 0;
440
+ int r;
441
+
442
+ usbi_dbg("");
443
+ r = usbi_backend->get_device_descriptor(dev, raw_desc, &host_endian);
444
+ if (r < 0)
445
+ return r;
446
+
447
+ memcpy((unsigned char *) desc, raw_desc, sizeof(raw_desc));
448
+ if (!host_endian) {
449
+ desc->bcdUSB = libusb_le16_to_cpu(desc->bcdUSB);
450
+ desc->idVendor = libusb_le16_to_cpu(desc->idVendor);
451
+ desc->idProduct = libusb_le16_to_cpu(desc->idProduct);
452
+ desc->bcdDevice = libusb_le16_to_cpu(desc->bcdDevice);
453
+ }
454
+ return 0;
455
+ }
456
+
457
+ /** \ingroup desc
458
+ * Get the USB configuration descriptor for the currently active configuration.
459
+ * This is a non-blocking function which does not involve any requests being
460
+ * sent to the device.
461
+ *
462
+ * \param dev a device
463
+ * \param config output location for the USB configuration descriptor. Only
464
+ * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
465
+ * after use.
466
+ * \returns 0 on success
467
+ * \returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state
468
+ * \returns another LIBUSB_ERROR code on error
469
+ * \see libusb_get_config_descriptor
470
+ */
471
+ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
472
+ struct libusb_config_descriptor **config)
473
+ {
474
+ struct libusb_config_descriptor *_config = malloc(sizeof(*_config));
475
+ unsigned char tmp[8];
476
+ unsigned char *buf = NULL;
477
+ int host_endian = 0;
478
+ int r;
479
+
480
+ usbi_dbg("");
481
+ if (!_config)
482
+ return LIBUSB_ERROR_NO_MEM;
483
+
484
+ r = usbi_backend->get_active_config_descriptor(dev, tmp, sizeof(tmp),
485
+ &host_endian);
486
+ if (r < 0)
487
+ goto err;
488
+
489
+ _config->wTotalLength = 0;
490
+ usbi_parse_descriptor(tmp, "bbw", _config, host_endian);
491
+ if (_config->wTotalLength != 0)
492
+ buf = malloc(_config->wTotalLength);
493
+ if (!buf) {
494
+ r = LIBUSB_ERROR_NO_MEM;
495
+ goto err;
496
+ }
497
+
498
+ r = usbi_backend->get_active_config_descriptor(dev, buf,
499
+ _config->wTotalLength, &host_endian);
500
+ if (r < 0)
501
+ goto err;
502
+
503
+ r = parse_configuration(dev->ctx, _config, buf, host_endian);
504
+ if (r < 0) {
505
+ usbi_err(dev->ctx, "parse_configuration failed with error %d", r);
506
+ goto err;
507
+ } else if (r > 0) {
508
+ usbi_warn(dev->ctx, "descriptor data still left");
509
+ }
510
+
511
+ free(buf);
512
+ *config = _config;
513
+ return 0;
514
+
515
+ err:
516
+ free(_config);
517
+ if (buf)
518
+ free(buf);
519
+ return r;
520
+ }
521
+
522
+ /** \ingroup desc
523
+ * Get a USB configuration descriptor based on its index.
524
+ * This is a non-blocking function which does not involve any requests being
525
+ * sent to the device.
526
+ *
527
+ * \param dev a device
528
+ * \param config_index the index of the configuration you wish to retrieve
529
+ * \param config output location for the USB configuration descriptor. Only
530
+ * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
531
+ * after use.
532
+ * \returns 0 on success
533
+ * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
534
+ * \returns another LIBUSB_ERROR code on error
535
+ * \see libusb_get_active_config_descriptor()
536
+ * \see libusb_get_config_descriptor_by_value()
537
+ */
538
+ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
539
+ uint8_t config_index, struct libusb_config_descriptor **config)
540
+ {
541
+ struct libusb_config_descriptor *_config;
542
+ unsigned char tmp[8];
543
+ unsigned char *buf = NULL;
544
+ int host_endian = 0;
545
+ int r;
546
+
547
+ usbi_dbg("index %d", config_index);
548
+ if (config_index >= dev->num_configurations)
549
+ return LIBUSB_ERROR_NOT_FOUND;
550
+
551
+ _config = malloc(sizeof(*_config));
552
+ if (!_config)
553
+ return LIBUSB_ERROR_NO_MEM;
554
+
555
+ r = usbi_backend->get_config_descriptor(dev, config_index, tmp,
556
+ sizeof(tmp), &host_endian);
557
+ if (r < 0)
558
+ goto err;
559
+
560
+ usbi_parse_descriptor(tmp, "bbw", _config, host_endian);
561
+ buf = malloc(_config->wTotalLength);
562
+ if (!buf) {
563
+ r = LIBUSB_ERROR_NO_MEM;
564
+ goto err;
565
+ }
566
+
567
+ host_endian = 0;
568
+ r = usbi_backend->get_config_descriptor(dev, config_index, buf,
569
+ _config->wTotalLength, &host_endian);
570
+ if (r < 0)
571
+ goto err;
572
+
573
+ r = parse_configuration(dev->ctx, _config, buf, host_endian);
574
+ if (r < 0) {
575
+ usbi_err(dev->ctx, "parse_configuration failed with error %d", r);
576
+ goto err;
577
+ } else if (r > 0) {
578
+ usbi_warn(dev->ctx, "descriptor data still left");
579
+ }
580
+
581
+ free(buf);
582
+ *config = _config;
583
+ return 0;
584
+
585
+ err:
586
+ free(_config);
587
+ if (buf)
588
+ free(buf);
589
+ return r;
590
+ }
591
+
592
+ /* iterate through all configurations, returning the index of the configuration
593
+ * matching a specific bConfigurationValue in the idx output parameter, or -1
594
+ * if the config was not found.
595
+ * returns 0 or a LIBUSB_ERROR code
596
+ */
597
+ int usbi_get_config_index_by_value(struct libusb_device *dev,
598
+ uint8_t bConfigurationValue, int *idx)
599
+ {
600
+ uint8_t i;
601
+
602
+ usbi_dbg("value %d", bConfigurationValue);
603
+ for (i = 0; i < dev->num_configurations; i++) {
604
+ unsigned char tmp[6];
605
+ int host_endian;
606
+ int r = usbi_backend->get_config_descriptor(dev, i, tmp, sizeof(tmp),
607
+ &host_endian);
608
+ if (r < 0)
609
+ return r;
610
+ if (tmp[5] == bConfigurationValue) {
611
+ *idx = i;
612
+ return 0;
613
+ }
614
+ }
615
+
616
+ *idx = -1;
617
+ return 0;
618
+ }
619
+
620
+ /** \ingroup desc
621
+ * Get a USB configuration descriptor with a specific bConfigurationValue.
622
+ * This is a non-blocking function which does not involve any requests being
623
+ * sent to the device.
624
+ *
625
+ * \param dev a device
626
+ * \param bConfigurationValue the bConfigurationValue of the configuration you
627
+ * wish to retrieve
628
+ * \param config output location for the USB configuration descriptor. Only
629
+ * valid if 0 was returned. Must be freed with libusb_free_config_descriptor()
630
+ * after use.
631
+ * \returns 0 on success
632
+ * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist
633
+ * \returns another LIBUSB_ERROR code on error
634
+ * \see libusb_get_active_config_descriptor()
635
+ * \see libusb_get_config_descriptor()
636
+ */
637
+ int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev,
638
+ uint8_t bConfigurationValue, struct libusb_config_descriptor **config)
639
+ {
640
+ int idx;
641
+ int r = usbi_get_config_index_by_value(dev, bConfigurationValue, &idx);
642
+ if (r < 0)
643
+ return r;
644
+ else if (idx == -1)
645
+ return LIBUSB_ERROR_NOT_FOUND;
646
+ else
647
+ return libusb_get_config_descriptor(dev, (uint8_t) idx, config);
648
+ }
649
+
650
+ /** \ingroup desc
651
+ * Free a configuration descriptor obtained from
652
+ * libusb_get_active_config_descriptor() or libusb_get_config_descriptor().
653
+ * It is safe to call this function with a NULL config parameter, in which
654
+ * case the function simply returns.
655
+ *
656
+ * \param config the configuration descriptor to free
657
+ */
658
+ void API_EXPORTED libusb_free_config_descriptor(
659
+ struct libusb_config_descriptor *config)
660
+ {
661
+ if (!config)
662
+ return;
663
+
664
+ clear_configuration(config);
665
+ free(config);
666
+ }
667
+
668
+ /** \ingroup desc
669
+ * Retrieve a string descriptor in C style ASCII.
670
+ *
671
+ * Wrapper around libusb_get_string_descriptor(). Uses the first language
672
+ * supported by the device.
673
+ *
674
+ * \param dev a device handle
675
+ * \param desc_index the index of the descriptor to retrieve
676
+ * \param data output buffer for ASCII string descriptor
677
+ * \param length size of data buffer
678
+ * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
679
+ */
680
+ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
681
+ uint8_t desc_index, unsigned char *data, int length)
682
+ {
683
+ unsigned char tbuf[255]; /* Some devices choke on size > 255 */
684
+ int r, si, di;
685
+ uint16_t langid;
686
+
687
+ /* Asking for the zero'th index is special - it returns a string
688
+ * descriptor that contains all the language IDs supported by the
689
+ * device. Typically there aren't many - often only one. Language
690
+ * IDs are 16 bit numbers, and they start at the third byte in the
691
+ * descriptor. There's also no point in trying to read descriptor 0
692
+ * with this function. See USB 2.0 specification section 9.6.7 for
693
+ * more information.
694
+ */
695
+
696
+ if (desc_index == 0)
697
+ return LIBUSB_ERROR_INVALID_PARAM;
698
+
699
+ r = libusb_get_string_descriptor(dev, 0, 0, tbuf, sizeof(tbuf));
700
+ if (r < 0)
701
+ return r;
702
+
703
+ if (r < 4)
704
+ return LIBUSB_ERROR_IO;
705
+
706
+ langid = tbuf[2] | (tbuf[3] << 8);
707
+
708
+ r = libusb_get_string_descriptor(dev, desc_index, langid, tbuf,
709
+ sizeof(tbuf));
710
+ if (r < 0)
711
+ return r;
712
+
713
+ if (tbuf[1] != LIBUSB_DT_STRING)
714
+ return LIBUSB_ERROR_IO;
715
+
716
+ if (tbuf[0] > r)
717
+ return LIBUSB_ERROR_IO;
718
+
719
+ for (di = 0, si = 2; si < tbuf[0]; si += 2) {
720
+ if (di >= (length - 1))
721
+ break;
722
+
723
+ if (tbuf[si + 1]) /* high byte */
724
+ data[di++] = '?';
725
+ else
726
+ data[di++] = tbuf[si];
727
+ }
728
+
729
+ data[di] = 0;
730
+ return di;
731
+ }