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,180 @@
1
+ /* Declarations for getopt.
2
+ Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc.
3
+ This file is part of the GNU C Library.
4
+
5
+ The GNU C Library is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU Lesser General Public
7
+ License as published by the Free Software Foundation; either
8
+ version 2.1 of the License, or (at your option) any later version.
9
+
10
+ The GNU C Library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public
16
+ License along with the GNU C Library; if not, write to the Free
17
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18
+ 02111-1307 USA. */
19
+
20
+ #ifndef _GETOPT_H
21
+
22
+ #ifndef __need_getopt
23
+ # define _GETOPT_H 1
24
+ #endif
25
+
26
+ /* If __GNU_LIBRARY__ is not already defined, either we are being used
27
+ standalone, or this is the first header included in the source file.
28
+ If we are being used with glibc, we need to include <features.h>, but
29
+ that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
30
+ not defined, include <ctype.h>, which will pull in <features.h> for us
31
+ if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
32
+ doesn't flood the namespace with stuff the way some other headers do.) */
33
+ #if !defined __GNU_LIBRARY__
34
+ # include <ctype.h>
35
+ #endif
36
+
37
+ #ifdef __cplusplus
38
+ extern "C" {
39
+ #endif
40
+
41
+ /* For communication from `getopt' to the caller.
42
+ When `getopt' finds an option that takes an argument,
43
+ the argument value is returned here.
44
+ Also, when `ordering' is RETURN_IN_ORDER,
45
+ each non-option ARGV-element is returned here. */
46
+
47
+ extern char *optarg;
48
+
49
+ /* Index in ARGV of the next element to be scanned.
50
+ This is used for communication to and from the caller
51
+ and for communication between successive calls to `getopt'.
52
+
53
+ On entry to `getopt', zero means this is the first call; initialize.
54
+
55
+ When `getopt' returns -1, this is the index of the first of the
56
+ non-option elements that the caller should itself scan.
57
+
58
+ Otherwise, `optind' communicates from one call to the next
59
+ how much of ARGV has been scanned so far. */
60
+
61
+ extern int optind;
62
+
63
+ /* Callers store zero here to inhibit the error message `getopt' prints
64
+ for unrecognized options. */
65
+
66
+ extern int opterr;
67
+
68
+ /* Set to an option character which was unrecognized. */
69
+
70
+ extern int optopt;
71
+
72
+ #ifndef __need_getopt
73
+ /* Describe the long-named options requested by the application.
74
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
75
+ of `struct option' terminated by an element containing a name which is
76
+ zero.
77
+
78
+ The field `has_arg' is:
79
+ no_argument (or 0) if the option does not take an argument,
80
+ required_argument (or 1) if the option requires an argument,
81
+ optional_argument (or 2) if the option takes an optional argument.
82
+
83
+ If the field `flag' is not NULL, it points to a variable that is set
84
+ to the value given in the field `val' when the option is found, but
85
+ left unchanged if the option is not found.
86
+
87
+ To have a long-named option do something other than set an `int' to
88
+ a compiled-in constant, such as set a value from `optarg', set the
89
+ option's `flag' field to zero and its `val' field to a nonzero
90
+ value (the equivalent single-letter option character, if there is
91
+ one). For long options that have a zero `flag' field, `getopt'
92
+ returns the contents of the `val' field. */
93
+
94
+ struct option
95
+ {
96
+ # if (defined __STDC__ && __STDC__) || defined __cplusplus
97
+ const char *name;
98
+ # else
99
+ char *name;
100
+ # endif
101
+ /* has_arg can't be an enum because some compilers complain about
102
+ type mismatches in all the code that assumes it is an int. */
103
+ int has_arg;
104
+ int *flag;
105
+ int val;
106
+ };
107
+
108
+ /* Names for the values of the `has_arg' field of `struct option'. */
109
+
110
+ # define no_argument 0
111
+ # define required_argument 1
112
+ # define optional_argument 2
113
+ #endif /* need getopt */
114
+
115
+
116
+ /* Get definitions and prototypes for functions to process the
117
+ arguments in ARGV (ARGC of them, minus the program name) for
118
+ options given in OPTS.
119
+
120
+ Return the option character from OPTS just read. Return -1 when
121
+ there are no more options. For unrecognized options, or options
122
+ missing arguments, `optopt' is set to the option letter, and '?' is
123
+ returned.
124
+
125
+ The OPTS string is a list of characters which are recognized option
126
+ letters, optionally followed by colons, specifying that that letter
127
+ takes an argument, to be placed in `optarg'.
128
+
129
+ If a letter in OPTS is followed by two colons, its argument is
130
+ optional. This behavior is specific to the GNU `getopt'.
131
+
132
+ The argument `--' causes premature termination of argument
133
+ scanning, explicitly telling `getopt' that there are no more
134
+ options.
135
+
136
+ If OPTS begins with `--', then non-option arguments are treated as
137
+ arguments to the option '\0'. This behavior is specific to the GNU
138
+ `getopt'. */
139
+
140
+ #if (defined __STDC__ && __STDC__) || defined __cplusplus
141
+ # ifdef __GNU_LIBRARY__
142
+ /* Many other libraries have conflicting prototypes for getopt, with
143
+ differences in the consts, in stdlib.h. To avoid compilation
144
+ errors, only prototype getopt for the GNU C library. */
145
+ extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
146
+ # else /* not __GNU_LIBRARY__ */
147
+ extern int getopt ();
148
+ # endif /* __GNU_LIBRARY__ */
149
+
150
+ # ifndef __need_getopt
151
+ extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
152
+ const struct option *__longopts, int *__longind);
153
+ extern int getopt_long_only (int __argc, char *const *__argv,
154
+ const char *__shortopts,
155
+ const struct option *__longopts, int *__longind);
156
+
157
+ /* Internal only. Users should not call this directly. */
158
+ extern int _getopt_internal (int __argc, char *const *__argv,
159
+ const char *__shortopts,
160
+ const struct option *__longopts, int *__longind,
161
+ int __long_only);
162
+ # endif
163
+ #else /* not __STDC__ */
164
+ extern int getopt ();
165
+ # ifndef __need_getopt
166
+ extern int getopt_long ();
167
+ extern int getopt_long_only ();
168
+
169
+ extern int _getopt_internal ();
170
+ # endif
171
+ #endif /* __STDC__ */
172
+
173
+ #ifdef __cplusplus
174
+ }
175
+ #endif
176
+
177
+ /* Make sure we later can get all the definitions and declarations. */
178
+ #undef __need_getopt
179
+
180
+ #endif /* getopt.h */
@@ -0,0 +1,188 @@
1
+ /* getopt_long and getopt_long_only entry points for GNU getopt.
2
+ Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
3
+ Free Software Foundation, Inc.
4
+ This file is part of the GNU C Library.
5
+
6
+ The GNU C 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
+ The GNU C 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 the GNU C Library; if not, write to the Free
18
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19
+ 02111-1307 USA. */
20
+
21
+ #ifdef HAVE_CONFIG_H
22
+ #include <config.h>
23
+ #endif
24
+
25
+ #include "getopt.h"
26
+
27
+ #if !defined __STDC__ || !__STDC__
28
+ /* This is a separate conditional since some stdc systems
29
+ reject `defined (const)'. */
30
+ #ifndef const
31
+ #define const
32
+ #endif
33
+ #endif
34
+
35
+ #include <stdio.h>
36
+
37
+ /* Comment out all this code if we are using the GNU C Library, and are not
38
+ actually compiling the library itself. This code is part of the GNU C
39
+ Library, but also included in many other GNU distributions. Compiling
40
+ and linking in this code is a waste when using the GNU C library
41
+ (especially if it is a shared library). Rather than having every GNU
42
+ program understand `configure --with-gnu-libc' and omit the object files,
43
+ it is simpler to just do this in the source for each such file. */
44
+
45
+ #define GETOPT_INTERFACE_VERSION 2
46
+ #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
47
+ #include <gnu-versions.h>
48
+ #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
49
+ #define ELIDE_CODE
50
+ #endif
51
+ #endif
52
+
53
+ #ifndef ELIDE_CODE
54
+
55
+
56
+ /* This needs to come after some library #include
57
+ to get __GNU_LIBRARY__ defined. */
58
+ #ifdef __GNU_LIBRARY__
59
+ #include <stdlib.h>
60
+ #endif
61
+
62
+ #ifndef NULL
63
+ #define NULL 0
64
+ #endif
65
+
66
+ int
67
+ getopt_long (argc, argv, options, long_options, opt_index)
68
+ int argc;
69
+ char *const *argv;
70
+ const char *options;
71
+ const struct option *long_options;
72
+ int *opt_index;
73
+ {
74
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
75
+ }
76
+
77
+ /* Like getopt_long, but '-' as well as '--' can indicate a long option.
78
+ If an option that starts with '-' (not '--') doesn't match a long option,
79
+ but does match a short option, it is parsed as a short option
80
+ instead. */
81
+
82
+ int
83
+ getopt_long_only (argc, argv, options, long_options, opt_index)
84
+ int argc;
85
+ char *const *argv;
86
+ const char *options;
87
+ const struct option *long_options;
88
+ int *opt_index;
89
+ {
90
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
91
+ }
92
+
93
+
94
+ #endif /* Not ELIDE_CODE. */
95
+
96
+ #ifdef TEST
97
+
98
+ #include <stdio.h>
99
+
100
+ int
101
+ main (argc, argv)
102
+ int argc;
103
+ char **argv;
104
+ {
105
+ int c;
106
+ int digit_optind = 0;
107
+
108
+ while (1)
109
+ {
110
+ int this_option_optind = optind ? optind : 1;
111
+ int option_index = 0;
112
+ static struct option long_options[] =
113
+ {
114
+ {"add", 1, 0, 0},
115
+ {"append", 0, 0, 0},
116
+ {"delete", 1, 0, 0},
117
+ {"verbose", 0, 0, 0},
118
+ {"create", 0, 0, 0},
119
+ {"file", 1, 0, 0},
120
+ {0, 0, 0, 0}
121
+ };
122
+
123
+ c = getopt_long (argc, argv, "abc:d:0123456789",
124
+ long_options, &option_index);
125
+ if (c == -1)
126
+ break;
127
+
128
+ switch (c)
129
+ {
130
+ case 0:
131
+ printf ("option %s", long_options[option_index].name);
132
+ if (optarg)
133
+ printf (" with arg %s", optarg);
134
+ printf ("\n");
135
+ break;
136
+
137
+ case '0':
138
+ case '1':
139
+ case '2':
140
+ case '3':
141
+ case '4':
142
+ case '5':
143
+ case '6':
144
+ case '7':
145
+ case '8':
146
+ case '9':
147
+ if (digit_optind != 0 && digit_optind != this_option_optind)
148
+ printf ("digits occur in two different argv-elements.\n");
149
+ digit_optind = this_option_optind;
150
+ printf ("option %c\n", c);
151
+ break;
152
+
153
+ case 'a':
154
+ printf ("option a\n");
155
+ break;
156
+
157
+ case 'b':
158
+ printf ("option b\n");
159
+ break;
160
+
161
+ case 'c':
162
+ printf ("option c with value `%s'\n", optarg);
163
+ break;
164
+
165
+ case 'd':
166
+ printf ("option d with value `%s'\n", optarg);
167
+ break;
168
+
169
+ case '?':
170
+ break;
171
+
172
+ default:
173
+ printf ("?? getopt returned character code 0%o ??\n", c);
174
+ }
175
+ }
176
+
177
+ if (optind < argc)
178
+ {
179
+ printf ("non-option ARGV-elements: ");
180
+ while (optind < argc)
181
+ printf ("%s ", argv[optind++]);
182
+ printf ("\n");
183
+ }
184
+
185
+ exit (0);
186
+ }
187
+
188
+ #endif /* TEST */
@@ -0,0 +1,63 @@
1
+ /*
2
+ * libusbx example program to list devices on the bus
3
+ * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+ #include <stdio.h>
21
+ #include <sys/types.h>
22
+
23
+ #include <libusb.h>
24
+
25
+ static void print_devs(libusb_device **devs)
26
+ {
27
+ libusb_device *dev;
28
+ int i = 0;
29
+
30
+ while ((dev = devs[i++]) != NULL) {
31
+ struct libusb_device_descriptor desc;
32
+ int r = libusb_get_device_descriptor(dev, &desc);
33
+ if (r < 0) {
34
+ fprintf(stderr, "failed to get device descriptor");
35
+ return;
36
+ }
37
+
38
+ printf("%04x:%04x (bus %d, device %d)\n",
39
+ desc.idVendor, desc.idProduct,
40
+ libusb_get_bus_number(dev), libusb_get_device_address(dev));
41
+ }
42
+ }
43
+
44
+ int main(void)
45
+ {
46
+ libusb_device **devs;
47
+ int r;
48
+ ssize_t cnt;
49
+
50
+ r = libusb_init(NULL);
51
+ if (r < 0)
52
+ return r;
53
+
54
+ cnt = libusb_get_device_list(NULL, &devs);
55
+ if (cnt < 0)
56
+ return (int) cnt;
57
+
58
+ print_devs(devs);
59
+ libusb_free_device_list(devs, 1);
60
+
61
+ libusb_exit(NULL);
62
+ return 0;
63
+ }
@@ -0,0 +1,1036 @@
1
+ /*
2
+ * xusb: Generic USB test program
3
+ * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
4
+ * Contributions to Mass Storage by Alan Stern.
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 <stdio.h>
22
+ #include <stdint.h>
23
+ #include <stdlib.h>
24
+ #include <string.h>
25
+ #include <stdarg.h>
26
+
27
+ #include "libusb.h"
28
+
29
+ #if defined(_WIN32)
30
+ #define msleep(msecs) Sleep(msecs)
31
+ #else
32
+ #include <unistd.h>
33
+ #define msleep(msecs) usleep(1000*msecs)
34
+ #endif
35
+
36
+ #if !defined(_MSC_VER) || _MSC_VER<=1200
37
+ #define sscanf_s sscanf
38
+ #endif
39
+
40
+ #if !defined(bool)
41
+ #define bool int
42
+ #endif
43
+ #if !defined(true)
44
+ #define true (1 == 1)
45
+ #endif
46
+ #if !defined(false)
47
+ #define false (!true)
48
+ #endif
49
+
50
+
51
+ // Future versions of libusbx will use usb_interface instead of interface
52
+ // in libusb_config_descriptor => catter for that
53
+ #define usb_interface interface
54
+
55
+ // Global variables
56
+ bool binary_dump = false;
57
+ bool extra_info = false;
58
+ const char* binary_name = NULL;
59
+
60
+ static int perr(char const *format, ...)
61
+ {
62
+ va_list args;
63
+ int r;
64
+
65
+ va_start (args, format);
66
+ r = vfprintf(stderr, format, args);
67
+ va_end(args);
68
+
69
+ return r;
70
+ }
71
+
72
+ #define ERR_EXIT(errcode) do { perr(" %s\n", libusb_error_name((enum libusb_error)errcode)); return -1; } while (0)
73
+ #define CALL_CHECK(fcall) do { r=fcall; if (r < 0) ERR_EXIT(r); } while (0);
74
+ #define B(x) (((x)!=0)?1:0)
75
+ #define be_to_int32(buf) (((buf)[0]<<24)|((buf)[1]<<16)|((buf)[2]<<8)|(buf)[3])
76
+
77
+ #define RETRY_MAX 5
78
+ #define REQUEST_SENSE_LENGTH 0x12
79
+ #define INQUIRY_LENGTH 0x24
80
+ #define READ_CAPACITY_LENGTH 0x08
81
+
82
+ // HID Class-Specific Requests values. See section 7.2 of the HID specifications
83
+ #define HID_GET_REPORT 0x01
84
+ #define HID_GET_IDLE 0x02
85
+ #define HID_GET_PROTOCOL 0x03
86
+ #define HID_SET_REPORT 0x09
87
+ #define HID_SET_IDLE 0x0A
88
+ #define HID_SET_PROTOCOL 0x0B
89
+ #define HID_REPORT_TYPE_INPUT 0x01
90
+ #define HID_REPORT_TYPE_OUTPUT 0x02
91
+ #define HID_REPORT_TYPE_FEATURE 0x03
92
+
93
+ // Mass Storage Requests values. See section 3 of the Bulk-Only Mass Storage Class specifications
94
+ #define BOMS_RESET 0xFF
95
+ #define BOMS_GET_MAX_LUN 0xFE
96
+
97
+ // Section 5.1: Command Block Wrapper (CBW)
98
+ struct command_block_wrapper {
99
+ uint8_t dCBWSignature[4];
100
+ uint32_t dCBWTag;
101
+ uint32_t dCBWDataTransferLength;
102
+ uint8_t bmCBWFlags;
103
+ uint8_t bCBWLUN;
104
+ uint8_t bCBWCBLength;
105
+ uint8_t CBWCB[16];
106
+ };
107
+
108
+ // Section 5.2: Command Status Wrapper (CSW)
109
+ struct command_status_wrapper {
110
+ uint8_t dCSWSignature[4];
111
+ uint32_t dCSWTag;
112
+ uint32_t dCSWDataResidue;
113
+ uint8_t bCSWStatus;
114
+ };
115
+
116
+ static uint8_t cdb_length[256] = {
117
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
118
+ 06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,06, // 0
119
+ 06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,06, // 1
120
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 2
121
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 3
122
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 4
123
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 5
124
+ 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // 6
125
+ 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // 7
126
+ 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, // 8
127
+ 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, // 9
128
+ 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, // A
129
+ 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, // B
130
+ 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // C
131
+ 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // D
132
+ 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // E
133
+ 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // F
134
+ };
135
+
136
+ enum test_type {
137
+ USE_GENERIC,
138
+ USE_PS3,
139
+ USE_XBOX,
140
+ USE_SCSI,
141
+ USE_HID,
142
+ } test_mode;
143
+ uint16_t VID, PID;
144
+
145
+ static void display_buffer_hex(unsigned char *buffer, unsigned size)
146
+ {
147
+ unsigned i, j, k;
148
+
149
+ for (i=0; i<size; i+=16) {
150
+ printf("\n %08x ", i);
151
+ for(j=0,k=0; k<16; j++,k++) {
152
+ if (i+j < size) {
153
+ printf("%02x", buffer[i+j]);
154
+ } else {
155
+ printf(" ");
156
+ }
157
+ printf(" ");
158
+ }
159
+ printf(" ");
160
+ for(j=0,k=0; k<16; j++,k++) {
161
+ if (i+j < size) {
162
+ if ((buffer[i+j] < 32) || (buffer[i+j] > 126)) {
163
+ printf(".");
164
+ } else {
165
+ printf("%c", buffer[i+j]);
166
+ }
167
+ }
168
+ }
169
+ }
170
+ printf("\n" );
171
+ }
172
+
173
+ // The PS3 Controller is really a HID device that got its HID Report Descriptors
174
+ // removed by Sony
175
+ static int display_ps3_status(libusb_device_handle *handle)
176
+ {
177
+ int r;
178
+ uint8_t input_report[49];
179
+ uint8_t master_bt_address[8];
180
+ uint8_t device_bt_address[18];
181
+
182
+ // Get the controller's bluetooth address of its master device
183
+ CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
184
+ HID_GET_REPORT, 0x03f5, 0, master_bt_address, sizeof(master_bt_address), 100));
185
+ printf("\nMaster's bluetooth address: %02X:%02X:%02X:%02X:%02X:%02X\n", master_bt_address[2], master_bt_address[3],
186
+ master_bt_address[4], master_bt_address[5], master_bt_address[6], master_bt_address[7]);
187
+
188
+ // Get the controller's bluetooth address
189
+ CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
190
+ HID_GET_REPORT, 0x03f2, 0, device_bt_address, sizeof(device_bt_address), 100));
191
+ printf("\nMaster's bluetooth address: %02X:%02X:%02X:%02X:%02X:%02X\n", device_bt_address[4], device_bt_address[5],
192
+ device_bt_address[6], device_bt_address[7], device_bt_address[8], device_bt_address[9]);
193
+
194
+ // Get the status of the controller's buttons via its HID report
195
+ printf("\nReading PS3 Input Report...\n");
196
+ CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
197
+ HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x01, 0, input_report, sizeof(input_report), 1000));
198
+ switch(input_report[2]){ /** Direction pad plus start, select, and joystick buttons */
199
+ case 0x01:
200
+ printf("\tSELECT pressed\n");
201
+ break;
202
+ case 0x02:
203
+ printf("\tLEFT 3 pressed\n");
204
+ break;
205
+ case 0x04:
206
+ printf("\tRIGHT 3 pressed\n");
207
+ break;
208
+ case 0x08:
209
+ printf("\tSTART presed\n");
210
+ break;
211
+ case 0x10:
212
+ printf("\tUP pressed\n");
213
+ break;
214
+ case 0x20:
215
+ printf("\tRIGHT pressed\n");
216
+ break;
217
+ case 0x40:
218
+ printf("\tDOWN pressed\n");
219
+ break;
220
+ case 0x80:
221
+ printf("\tLEFT pressed\n");
222
+ break;
223
+ }
224
+ switch(input_report[3]){ /** Shapes plus top right and left buttons */
225
+ case 0x01:
226
+ printf("\tLEFT 2 pressed\n");
227
+ break;
228
+ case 0x02:
229
+ printf("\tRIGHT 2 pressed\n");
230
+ break;
231
+ case 0x04:
232
+ printf("\tLEFT 1 pressed\n");
233
+ break;
234
+ case 0x08:
235
+ printf("\tRIGHT 1 presed\n");
236
+ break;
237
+ case 0x10:
238
+ printf("\tTRIANGLE pressed\n");
239
+ break;
240
+ case 0x20:
241
+ printf("\tCIRCLE pressed\n");
242
+ break;
243
+ case 0x40:
244
+ printf("\tCROSS pressed\n");
245
+ break;
246
+ case 0x80:
247
+ printf("\tSQUARE pressed\n");
248
+ break;
249
+ }
250
+ printf("\tPS button: %d\n", input_report[4]);
251
+ printf("\tLeft Analog (X,Y): (%d,%d)\n", input_report[6], input_report[7]);
252
+ printf("\tRight Analog (X,Y): (%d,%d)\n", input_report[8], input_report[9]);
253
+ printf("\tL2 Value: %d\tR2 Value: %d\n", input_report[18], input_report[19]);
254
+ printf("\tL1 Value: %d\tR1 Value: %d\n", input_report[20], input_report[21]);
255
+ printf("\tRoll (x axis): %d Yaw (y axis): %d Pitch (z axis) %d\n",
256
+ //(((input_report[42] + 128) % 256) - 128),
257
+ (int8_t)(input_report[42]),
258
+ (int8_t)(input_report[44]),
259
+ (int8_t)(input_report[46]));
260
+ printf("\tAcceleration: %d\n\n", (int8_t)(input_report[48]));
261
+ return 0;
262
+ }
263
+ // The XBOX Controller is really a HID device that got its HID Report Descriptors
264
+ // removed by Microsoft.
265
+ // Input/Output reports described at http://euc.jp/periphs/xbox-controller.ja.html
266
+ static int display_xbox_status(libusb_device_handle *handle)
267
+ {
268
+ int r;
269
+ uint8_t input_report[20];
270
+ printf("\nReading XBox Input Report...\n");
271
+ CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
272
+ HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, input_report, 20, 1000));
273
+ printf(" D-pad: %02X\n", input_report[2]&0x0F);
274
+ printf(" Start:%d, Back:%d, Left Stick Press:%d, Right Stick Press:%d\n", B(input_report[2]&0x10), B(input_report[2]&0x20),
275
+ B(input_report[2]&0x40), B(input_report[2]&0x80));
276
+ // A, B, X, Y, Black, White are pressure sensitive
277
+ printf(" A:%d, B:%d, X:%d, Y:%d, White:%d, Black:%d\n", input_report[4], input_report[5],
278
+ input_report[6], input_report[7], input_report[9], input_report[8]);
279
+ printf(" Left Trigger: %d, Right Trigger: %d\n", input_report[10], input_report[11]);
280
+ printf(" Left Analog (X,Y): (%d,%d)\n", (int16_t)((input_report[13]<<8)|input_report[12]),
281
+ (int16_t)((input_report[15]<<8)|input_report[14]));
282
+ printf(" Right Analog (X,Y): (%d,%d)\n", (int16_t)((input_report[17]<<8)|input_report[16]),
283
+ (int16_t)((input_report[19]<<8)|input_report[18]));
284
+ return 0;
285
+ }
286
+
287
+ static int set_xbox_actuators(libusb_device_handle *handle, uint8_t left, uint8_t right)
288
+ {
289
+ int r;
290
+ uint8_t output_report[6];
291
+
292
+ printf("\nWriting XBox Controller Output Report...\n");
293
+
294
+ memset(output_report, 0, sizeof(output_report));
295
+ output_report[1] = sizeof(output_report);
296
+ output_report[3] = left;
297
+ output_report[5] = right;
298
+
299
+ CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
300
+ HID_SET_REPORT, (HID_REPORT_TYPE_OUTPUT<<8)|0x00, 0, output_report, 06, 1000));
301
+ return 0;
302
+ }
303
+
304
+ static int send_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint, uint8_t lun,
305
+ uint8_t *cdb, uint8_t direction, int data_length, uint32_t *ret_tag)
306
+ {
307
+ static uint32_t tag = 1;
308
+ uint8_t cdb_len;
309
+ int i, r, size;
310
+ struct command_block_wrapper cbw;
311
+
312
+ if (cdb == NULL) {
313
+ return -1;
314
+ }
315
+
316
+ if (endpoint & LIBUSB_ENDPOINT_IN) {
317
+ perr("send_mass_storage_command: cannot send command on IN endpoint\n");
318
+ return -1;
319
+ }
320
+
321
+ cdb_len = cdb_length[cdb[0]];
322
+ if ((cdb_len == 0) || (cdb_len > sizeof(cbw.CBWCB))) {
323
+ perr("send_mass_storage_command: don't know how to handle this command (%02X, length %d)\n",
324
+ cdb[0], cdb_len);
325
+ return -1;
326
+ }
327
+
328
+ memset(&cbw, 0, sizeof(cbw));
329
+ cbw.dCBWSignature[0] = 'U';
330
+ cbw.dCBWSignature[1] = 'S';
331
+ cbw.dCBWSignature[2] = 'B';
332
+ cbw.dCBWSignature[3] = 'C';
333
+ *ret_tag = tag;
334
+ cbw.dCBWTag = tag++;
335
+ cbw.dCBWDataTransferLength = data_length;
336
+ cbw.bmCBWFlags = direction;
337
+ cbw.bCBWLUN = lun;
338
+ // Subclass is 1 or 6 => cdb_len
339
+ cbw.bCBWCBLength = cdb_len;
340
+ memcpy(cbw.CBWCB, cdb, cdb_len);
341
+
342
+ i = 0;
343
+ do {
344
+ // The transfer length must always be exactly 31 bytes.
345
+ r = libusb_bulk_transfer(handle, endpoint, (unsigned char*)&cbw, 31, &size, 1000);
346
+ if (r == LIBUSB_ERROR_PIPE) {
347
+ libusb_clear_halt(handle, endpoint);
348
+ }
349
+ i++;
350
+ } while ((r == LIBUSB_ERROR_PIPE) && (i<RETRY_MAX));
351
+ if (r != LIBUSB_SUCCESS) {
352
+ perr(" send_mass_storage_command: %s\n", libusb_error_name(r));
353
+ return -1;
354
+ }
355
+
356
+ printf(" sent %d CDB bytes\n", cdb_len);
357
+ return 0;
358
+ }
359
+
360
+ static int get_mass_storage_status(libusb_device_handle *handle, uint8_t endpoint, uint32_t expected_tag)
361
+ {
362
+ int i, r, size;
363
+ struct command_status_wrapper csw;
364
+
365
+ // The device is allowed to STALL this transfer. If it does, you have to
366
+ // clear the stall and try again.
367
+ i = 0;
368
+ do {
369
+ r = libusb_bulk_transfer(handle, endpoint, (unsigned char*)&csw, 13, &size, 1000);
370
+ if (r == LIBUSB_ERROR_PIPE) {
371
+ libusb_clear_halt(handle, endpoint);
372
+ }
373
+ i++;
374
+ } while ((r == LIBUSB_ERROR_PIPE) && (i<RETRY_MAX));
375
+ if (r != LIBUSB_SUCCESS) {
376
+ perr(" get_mass_storage_status: %s\n", libusb_error_name(r));
377
+ return -1;
378
+ }
379
+ if (size != 13) {
380
+ perr(" get_mass_storage_status: received %d bytes (expected 13)\n", size);
381
+ return -1;
382
+ }
383
+ if (csw.dCSWTag != expected_tag) {
384
+ perr(" get_mass_storage_status: mismatched tags (expected %08X, received %08X)\n",
385
+ expected_tag, csw.dCSWTag);
386
+ return -1;
387
+ }
388
+ // For this test, we ignore the dCSWSignature check for validity...
389
+ printf(" Mass Storage Status: %02X (%s)\n", csw.bCSWStatus, csw.bCSWStatus?"FAILED":"Success");
390
+ if (csw.dCSWTag != expected_tag)
391
+ return -1;
392
+ if (csw.bCSWStatus) {
393
+ // REQUEST SENSE is appropriate only if bCSWStatus is 1, meaning that the
394
+ // command failed somehow. Larger values (2 in particular) mean that
395
+ // the command couldn't be understood.
396
+ if (csw.bCSWStatus == 1)
397
+ return -2; // request Get Sense
398
+ else
399
+ return -1;
400
+ }
401
+
402
+ // In theory we also should check dCSWDataResidue. But lots of devices
403
+ // set it wrongly.
404
+ return 0;
405
+ }
406
+
407
+ static void get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_out)
408
+ {
409
+ uint8_t cdb[16]; // SCSI Command Descriptor Block
410
+ uint8_t sense[18];
411
+ uint32_t expected_tag;
412
+ int size;
413
+
414
+ // Request Sense
415
+ printf("Request Sense:\n");
416
+ memset(sense, 0, sizeof(sense));
417
+ memset(cdb, 0, sizeof(cdb));
418
+ cdb[0] = 0x03; // Request Sense
419
+ cdb[4] = REQUEST_SENSE_LENGTH;
420
+
421
+ send_mass_storage_command(handle, endpoint_out, 0, cdb, LIBUSB_ENDPOINT_IN, REQUEST_SENSE_LENGTH, &expected_tag);
422
+ libusb_bulk_transfer(handle, endpoint_in, (unsigned char*)&sense, REQUEST_SENSE_LENGTH, &size, 1000);
423
+ printf(" received %d bytes\n", size);
424
+
425
+ if ((sense[0] != 0x70) && (sense[0] != 0x71)) {
426
+ perr(" ERROR No sense data\n");
427
+ } else {
428
+ perr(" ERROR Sense: %02X %02X %02X\n", sense[2]&0x0F, sense[12], sense[13]);
429
+ }
430
+ // Strictly speaking, the get_mass_storage_status() call should come
431
+ // before these perr() lines. If the status is nonzero then we must
432
+ // assume there's no data in the buffer. For xusb it doesn't matter.
433
+ get_mass_storage_status(handle, endpoint_in, expected_tag);
434
+ }
435
+
436
+ // Mass Storage device to test bulk transfers (non destructive test)
437
+ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_out)
438
+ {
439
+ int r, size;
440
+ uint8_t lun;
441
+ uint32_t expected_tag;
442
+ uint32_t i, max_lba, block_size;
443
+ double device_size;
444
+ uint8_t cdb[16]; // SCSI Command Descriptor Block
445
+ uint8_t buffer[64];
446
+ char vid[9], pid[9], rev[5];
447
+ unsigned char *data;
448
+ FILE *fd;
449
+
450
+ printf("Reading Max LUN:\n");
451
+ r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
452
+ BOMS_GET_MAX_LUN, 0, 0, &lun, 1, 1000);
453
+ // Some devices send a STALL instead of the actual value.
454
+ // In such cases we should set lun to 0.
455
+ if (r == 0) {
456
+ lun = 0;
457
+ } else if (r < 0) {
458
+ perr(" Failed: %s", libusb_error_name((enum libusb_error)r));
459
+ }
460
+ printf(" Max LUN = %d\n", lun);
461
+
462
+ // Send Inquiry
463
+ printf("Sending Inquiry:\n");
464
+ memset(buffer, 0, sizeof(buffer));
465
+ memset(cdb, 0, sizeof(cdb));
466
+ cdb[0] = 0x12; // Inquiry
467
+ cdb[4] = INQUIRY_LENGTH;
468
+
469
+ send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOINT_IN, INQUIRY_LENGTH, &expected_tag);
470
+ CALL_CHECK(libusb_bulk_transfer(handle, endpoint_in, (unsigned char*)&buffer, INQUIRY_LENGTH, &size, 1000));
471
+ printf(" received %d bytes\n", size);
472
+ // The following strings are not zero terminated
473
+ for (i=0; i<8; i++) {
474
+ vid[i] = buffer[8+i];
475
+ pid[i] = buffer[16+i];
476
+ rev[i/2] = buffer[32+i/2]; // instead of another loop
477
+ }
478
+ vid[8] = 0;
479
+ pid[8] = 0;
480
+ rev[4] = 0;
481
+ printf(" VID:PID:REV \"%8s\":\"%8s\":\"%4s\"\n", vid, pid, rev);
482
+ if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) {
483
+ get_sense(handle, endpoint_in, endpoint_out);
484
+ }
485
+
486
+ // Read capacity
487
+ printf("Reading Capacity:\n");
488
+ memset(buffer, 0, sizeof(buffer));
489
+ memset(cdb, 0, sizeof(cdb));
490
+ cdb[0] = 0x25; // Read Capacity
491
+
492
+ send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOINT_IN, READ_CAPACITY_LENGTH, &expected_tag);
493
+ CALL_CHECK(libusb_bulk_transfer(handle, endpoint_in, (unsigned char*)&buffer, READ_CAPACITY_LENGTH, &size, 1000));
494
+ printf(" received %d bytes\n", size);
495
+ max_lba = be_to_int32(&buffer[0]);
496
+ block_size = be_to_int32(&buffer[4]);
497
+ device_size = ((double)(max_lba+1))*block_size/(1024*1024*1024);
498
+ printf(" Max LBA: %08X, Block Size: %08X (%.2f GB)\n", max_lba, block_size, device_size);
499
+ if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) {
500
+ get_sense(handle, endpoint_in, endpoint_out);
501
+ }
502
+
503
+ data = (unsigned char*) calloc(1, block_size);
504
+ if (data == NULL) {
505
+ perr(" unable to allocate data buffer\n");
506
+ return -1;
507
+ }
508
+
509
+ // Send Read
510
+ printf("Attempting to read %d bytes:\n", block_size);
511
+ memset(cdb, 0, sizeof(cdb));
512
+
513
+ cdb[0] = 0x28; // Read(10)
514
+ cdb[8] = 0x01; // 1 block
515
+
516
+ send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOINT_IN, block_size, &expected_tag);
517
+ libusb_bulk_transfer(handle, endpoint_in, data, block_size, &size, 5000);
518
+ printf(" READ: received %d bytes\n", size);
519
+ if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) {
520
+ get_sense(handle, endpoint_in, endpoint_out);
521
+ } else {
522
+ display_buffer_hex(data, size);
523
+ if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) {
524
+ if (fwrite(data, 1, (size_t)size, fd) != (unsigned int)size) {
525
+ perr(" unable to write binary data\n");
526
+ }
527
+ fclose(fd);
528
+ }
529
+ }
530
+ free(data);
531
+
532
+ return 0;
533
+ }
534
+
535
+ // HID
536
+ static int get_hid_record_size(uint8_t *hid_report_descriptor, int size, int type)
537
+ {
538
+ uint8_t i, j = 0;
539
+ uint8_t offset;
540
+ int record_size[3] = {0, 0, 0};
541
+ int nb_bits = 0, nb_items = 0;
542
+ bool found_record_marker;
543
+
544
+ found_record_marker = false;
545
+ for (i = hid_report_descriptor[0]+1; i < size; i += offset) {
546
+ offset = (hid_report_descriptor[i]&0x03) + 1;
547
+ if (offset == 4)
548
+ offset = 5;
549
+ switch (hid_report_descriptor[i] & 0xFC) {
550
+ case 0x74: // bitsize
551
+ nb_bits = hid_report_descriptor[i+1];
552
+ break;
553
+ case 0x94: // count
554
+ nb_items = 0;
555
+ for (j=1; j<offset; j++) {
556
+ nb_items = ((uint32_t)hid_report_descriptor[i+j]) << (8*(j-1));
557
+ }
558
+ break;
559
+ case 0x80: // input
560
+ found_record_marker = true;
561
+ j = 0;
562
+ break;
563
+ case 0x90: // output
564
+ found_record_marker = true;
565
+ j = 1;
566
+ break;
567
+ case 0xb0: // feature
568
+ found_record_marker = true;
569
+ j = 2;
570
+ break;
571
+ case 0xC0: // end of collection
572
+ nb_items = 0;
573
+ nb_bits = 0;
574
+ break;
575
+ default:
576
+ continue;
577
+ }
578
+ if (found_record_marker) {
579
+ found_record_marker = false;
580
+ record_size[j] += nb_items*nb_bits;
581
+ }
582
+ }
583
+ if ((type < HID_REPORT_TYPE_INPUT) || (type > HID_REPORT_TYPE_FEATURE)) {
584
+ return 0;
585
+ } else {
586
+ return (record_size[type - HID_REPORT_TYPE_INPUT]+7)/8;
587
+ }
588
+ }
589
+
590
+ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
591
+ {
592
+ int r, size, descriptor_size;
593
+ uint8_t hid_report_descriptor[256];
594
+ uint8_t *report_buffer;
595
+ FILE *fd;
596
+
597
+ printf("\nReading HID Report Descriptors:\n");
598
+ descriptor_size = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_STANDARD|LIBUSB_RECIPIENT_INTERFACE,
599
+ LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_REPORT<<8, 0, hid_report_descriptor, sizeof(hid_report_descriptor), 1000);
600
+ if (descriptor_size < 0) {
601
+ printf(" Failed\n");
602
+ return -1;
603
+ }
604
+ display_buffer_hex(hid_report_descriptor, descriptor_size);
605
+ if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) {
606
+ if (fwrite(hid_report_descriptor, 1, descriptor_size, fd) != descriptor_size) {
607
+ printf(" Error writing descriptor to file\n");
608
+ }
609
+ fclose(fd);
610
+ }
611
+
612
+ size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_FEATURE);
613
+ if (size <= 0) {
614
+ printf("\nSkipping Feature Report readout (None detected)\n");
615
+ } else {
616
+ report_buffer = (uint8_t*) calloc(size, 1);
617
+ if (report_buffer == NULL) {
618
+ return -1;
619
+ }
620
+
621
+ printf("\nReading Feature Report (length %d)...\n", size);
622
+ r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
623
+ HID_GET_REPORT, (HID_REPORT_TYPE_FEATURE<<8)|0, 0, report_buffer, (uint16_t)size, 5000);
624
+ if (r >= 0) {
625
+ display_buffer_hex(report_buffer, size);
626
+ } else {
627
+ switch(r) {
628
+ case LIBUSB_ERROR_NOT_FOUND:
629
+ printf(" No Feature Report available for this device\n");
630
+ break;
631
+ case LIBUSB_ERROR_PIPE:
632
+ printf(" Detected stall - resetting pipe...\n");
633
+ libusb_clear_halt(handle, 0);
634
+ break;
635
+ default:
636
+ printf(" Error: %s\n", libusb_error_name(r));
637
+ break;
638
+ }
639
+ }
640
+ free(report_buffer);
641
+ }
642
+
643
+ size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_INPUT);
644
+ if (size <= 0) {
645
+ printf("\nSkipping Input Report readout (None detected)\n");
646
+ } else {
647
+ report_buffer = (uint8_t*) calloc(size, 1);
648
+ if (report_buffer == NULL) {
649
+ return -1;
650
+ }
651
+
652
+ printf("\nReading Input Report (length %d)...\n", size);
653
+ r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
654
+ HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, report_buffer, (uint16_t)size, 5000);
655
+ if (r >= 0) {
656
+ display_buffer_hex(report_buffer, size);
657
+ } else {
658
+ switch(r) {
659
+ case LIBUSB_ERROR_TIMEOUT:
660
+ printf(" Timeout! Please make sure you act on the device within the 5 seconds allocated...\n");
661
+ break;
662
+ case LIBUSB_ERROR_PIPE:
663
+ printf(" Detected stall - resetting pipe...\n");
664
+ libusb_clear_halt(handle, 0);
665
+ break;
666
+ default:
667
+ printf(" Error: %s\n", libusb_error_name(r));
668
+ break;
669
+ }
670
+ }
671
+
672
+ // Attempt a bulk read from endpoint 0 (this should just return a raw input report)
673
+ printf("\nTesting interrupt read using endpoint %02X...\n", endpoint_in);
674
+ r = libusb_interrupt_transfer(handle, endpoint_in, report_buffer, size, &size, 5000);
675
+ if (r >= 0) {
676
+ display_buffer_hex(report_buffer, size);
677
+ } else {
678
+ printf(" %s\n", libusb_error_name(r));
679
+ }
680
+
681
+ free(report_buffer);
682
+ }
683
+ return 0;
684
+ }
685
+
686
+ // Read the MS WinUSB Feature Descriptors, that are used on Windows 8 for automated driver installation
687
+ static void read_ms_winsub_feature_descriptors(libusb_device_handle *handle, uint8_t bRequest, int iface_number)
688
+ {
689
+ #define MAX_OS_FD_LENGTH 256
690
+ int i, r;
691
+ uint8_t os_desc[MAX_OS_FD_LENGTH];
692
+ uint32_t length;
693
+ void* le_type_punning_IS_fine;
694
+ struct {
695
+ const char* desc;
696
+ uint16_t index;
697
+ uint16_t header_size;
698
+ } os_fd[2] = {
699
+ {"Extended Compat ID", 0x0004, 0x10},
700
+ {"Extended Properties", 0x0005, 0x0A}
701
+ };
702
+
703
+ if (iface_number < 0) return;
704
+
705
+ for (i=0; i<2; i++) {
706
+ printf("\nReading %s OS Feature Descriptor (wIndex = 0x%04d):\n", os_fd[i].desc, os_fd[i].index);
707
+
708
+ // Read the header part
709
+ r = libusb_control_transfer(handle, (uint8_t)(LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_VENDOR|LIBUSB_RECIPIENT_DEVICE),
710
+ bRequest, (uint16_t)(((iface_number)<< 8)|0x00), os_fd[i].index, os_desc, os_fd[i].header_size, 1000);
711
+ if (r < os_fd[i].header_size) {
712
+ perr(" Failed: %s", (r<0)?libusb_error_name((enum libusb_error)r):"header size is too small");
713
+ return;
714
+ }
715
+ le_type_punning_IS_fine = (void*)os_desc;
716
+ length = *((uint32_t*)le_type_punning_IS_fine);
717
+ if (length > MAX_OS_FD_LENGTH) {
718
+ length = MAX_OS_FD_LENGTH;
719
+ }
720
+
721
+ // Read the full feature descriptor
722
+ r = libusb_control_transfer(handle, (uint8_t)(LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_VENDOR|LIBUSB_RECIPIENT_DEVICE),
723
+ bRequest, (uint16_t)(((iface_number)<< 8)|0x00), os_fd[i].index, os_desc, (uint16_t)length, 1000);
724
+ if (r < 0) {
725
+ perr(" Failed: %s", libusb_error_name((enum libusb_error)r));
726
+ return;
727
+ } else {
728
+ display_buffer_hex(os_desc, r);
729
+ }
730
+ }
731
+ }
732
+
733
+ static int test_device(uint16_t vid, uint16_t pid)
734
+ {
735
+ libusb_device_handle *handle;
736
+ libusb_device *dev;
737
+ uint8_t bus, port_path[8];
738
+ struct libusb_config_descriptor *conf_desc;
739
+ const struct libusb_endpoint_descriptor *endpoint;
740
+ int i, j, k, r;
741
+ int iface, nb_ifaces, first_iface = -1;
742
+ #if defined(__linux__)
743
+ // Attaching/detaching the kernel driver is only relevant for Linux
744
+ int iface_detached = -1;
745
+ #endif
746
+ struct libusb_device_descriptor dev_desc;
747
+ const char* speed_name[5] = { "Unknown", "1.5 Mbit/s (USB LowSpeed)", "12 Mbit/s (USB FullSpeed)",
748
+ "480 Mbit/s (USB HighSpeed)", "5000 Mbit/s (USB SuperSpeed)"};
749
+ char string[128];
750
+ uint8_t string_index[3]; // indexes of the string descriptors
751
+ uint8_t endpoint_in = 0, endpoint_out = 0; // default IN and OUT endpoints
752
+
753
+ printf("Opening device %04X:%04X...\n", vid, pid);
754
+ handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
755
+
756
+ if (handle == NULL) {
757
+ perr(" Failed.\n");
758
+ return -1;
759
+ }
760
+
761
+ dev = libusb_get_device(handle);
762
+ bus = libusb_get_bus_number(dev);
763
+ if (extra_info) {
764
+ r = libusb_get_port_path(NULL, dev, port_path, sizeof(port_path));
765
+ if (r > 0) {
766
+ printf("\nDevice properties:\n");
767
+ printf(" bus number: %d\n", bus);
768
+ printf(" port path: %d", port_path[0]);
769
+ for (i=1; i<r; i++) {
770
+ printf("->%d", port_path[i]);
771
+ }
772
+ printf(" (from root hub)\n");
773
+ }
774
+ r = libusb_get_device_speed(dev);
775
+ if ((r<0) || (r>4)) r=0;
776
+ printf(" speed: %s\n", speed_name[r]);
777
+ }
778
+
779
+ printf("\nReading device descriptor:\n");
780
+ CALL_CHECK(libusb_get_device_descriptor(dev, &dev_desc));
781
+ printf(" length: %d\n", dev_desc.bLength);
782
+ printf(" device class: %d\n", dev_desc.bDeviceClass);
783
+ printf(" S/N: %d\n", dev_desc.iSerialNumber);
784
+ printf(" VID:PID: %04X:%04X\n", dev_desc.idVendor, dev_desc.idProduct);
785
+ printf(" bcdDevice: %04X\n", dev_desc.bcdDevice);
786
+ printf(" iMan:iProd:iSer: %d:%d:%d\n", dev_desc.iManufacturer, dev_desc.iProduct, dev_desc.iSerialNumber);
787
+ printf(" nb confs: %d\n", dev_desc.bNumConfigurations);
788
+ // Copy the string descriptors for easier parsing
789
+ string_index[0] = dev_desc.iManufacturer;
790
+ string_index[1] = dev_desc.iProduct;
791
+ string_index[2] = dev_desc.iSerialNumber;
792
+
793
+ printf("\nReading configuration descriptors:\n");
794
+ CALL_CHECK(libusb_get_config_descriptor(dev, 0, &conf_desc));
795
+ nb_ifaces = conf_desc->bNumInterfaces;
796
+ printf(" nb interfaces: %d\n", nb_ifaces);
797
+ if (nb_ifaces > 0)
798
+ first_iface = conf_desc->usb_interface[0].altsetting[0].bInterfaceNumber;
799
+ for (i=0; i<nb_ifaces; i++) {
800
+ printf(" interface[%d]: id = %d\n", i,
801
+ conf_desc->usb_interface[i].altsetting[0].bInterfaceNumber);
802
+ for (j=0; j<conf_desc->usb_interface[i].num_altsetting; j++) {
803
+ printf("interface[%d].altsetting[%d]: num endpoints = %d\n",
804
+ i, j, conf_desc->usb_interface[i].altsetting[j].bNumEndpoints);
805
+ printf(" Class.SubClass.Protocol: %02X.%02X.%02X\n",
806
+ conf_desc->usb_interface[i].altsetting[j].bInterfaceClass,
807
+ conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass,
808
+ conf_desc->usb_interface[i].altsetting[j].bInterfaceProtocol);
809
+ if ( (conf_desc->usb_interface[i].altsetting[j].bInterfaceClass == LIBUSB_CLASS_MASS_STORAGE)
810
+ && ( (conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass == 0x01)
811
+ || (conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass == 0x06) )
812
+ && (conf_desc->usb_interface[i].altsetting[j].bInterfaceProtocol == 0x50) ) {
813
+ // Mass storage devices that can use basic SCSI commands
814
+ test_mode = USE_SCSI;
815
+ }
816
+ for (k=0; k<conf_desc->usb_interface[i].altsetting[j].bNumEndpoints; k++) {
817
+ endpoint = &conf_desc->usb_interface[i].altsetting[j].endpoint[k];
818
+ printf(" endpoint[%d].address: %02X\n", k, endpoint->bEndpointAddress);
819
+ // Use the first interrupt or bulk IN/OUT endpoints as default for testing
820
+ if ((endpoint->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) & (LIBUSB_TRANSFER_TYPE_BULK | LIBUSB_TRANSFER_TYPE_INTERRUPT)) {
821
+ if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
822
+ if (!endpoint_in)
823
+ endpoint_in = endpoint->bEndpointAddress;
824
+ } else {
825
+ if (!endpoint_out)
826
+ endpoint_out = endpoint->bEndpointAddress;
827
+ }
828
+ }
829
+ printf(" max packet size: %04X\n", endpoint->wMaxPacketSize);
830
+ printf(" polling interval: %02X\n", endpoint->bInterval);
831
+ }
832
+ }
833
+ }
834
+ libusb_free_config_descriptor(conf_desc);
835
+
836
+ for (iface = 0; iface < nb_ifaces; iface++)
837
+ {
838
+ printf("\nClaiming interface %d...\n", iface);
839
+ r = libusb_claim_interface(handle, iface);
840
+ #if defined(__linux__)
841
+ if ((r != LIBUSB_SUCCESS) && (iface == 0)) {
842
+ // Maybe we need to detach the driver
843
+ perr(" Failed. Trying to detach driver...\n");
844
+ libusb_detach_kernel_driver(handle, iface);
845
+ iface_detached = iface;
846
+ printf(" Claiming interface again...\n");
847
+ r = libusb_claim_interface(handle, iface);
848
+ }
849
+ #endif
850
+ if (r != LIBUSB_SUCCESS) {
851
+ perr(" Failed.\n");
852
+ }
853
+ }
854
+
855
+ printf("\nReading string descriptors:\n");
856
+ for (i=0; i<3; i++) {
857
+ if (string_index[i] == 0) {
858
+ continue;
859
+ }
860
+ if (libusb_get_string_descriptor_ascii(handle, string_index[i], (unsigned char*)string, 128) >= 0) {
861
+ printf(" String (0x%02X): \"%s\"\n", string_index[i], string);
862
+ }
863
+ }
864
+ // Read the OS String Descriptor
865
+ if (libusb_get_string_descriptor_ascii(handle, 0xEE, (unsigned char*)string, 128) >= 0) {
866
+ printf(" String (0x%02X): \"%s\"\n", 0xEE, string);
867
+ // If this is a Microsoft OS String Descriptor,
868
+ // attempt to read the WinUSB extended Feature Descriptors
869
+ if (strncmp(string, "MSFT100", 7) == 0)
870
+ read_ms_winsub_feature_descriptors(handle, string[7], first_iface);
871
+ }
872
+
873
+ switch(test_mode) {
874
+ case USE_PS3:
875
+ CALL_CHECK(display_ps3_status(handle));
876
+ break;
877
+ case USE_XBOX:
878
+ CALL_CHECK(display_xbox_status(handle));
879
+ CALL_CHECK(set_xbox_actuators(handle, 128, 222));
880
+ msleep(2000);
881
+ CALL_CHECK(set_xbox_actuators(handle, 0, 0));
882
+ break;
883
+ case USE_HID:
884
+ test_hid(handle, endpoint_in);
885
+ break;
886
+ case USE_SCSI:
887
+ CALL_CHECK(test_mass_storage(handle, endpoint_in, endpoint_out));
888
+ case USE_GENERIC:
889
+ break;
890
+ }
891
+
892
+ printf("\n");
893
+ for (iface = 0; iface<nb_ifaces; iface++) {
894
+ printf("Releasing interface %d...\n", iface);
895
+ libusb_release_interface(handle, iface);
896
+ }
897
+
898
+ #if defined(__linux__)
899
+ if (iface_detached >= 0) {
900
+ printf("Re-attaching kernel driver...\n");
901
+ libusb_attach_kernel_driver(handle, iface_detached);
902
+ }
903
+ #endif
904
+
905
+ printf("Closing device...\n");
906
+ libusb_close(handle);
907
+
908
+ return 0;
909
+ }
910
+
911
+ int main(int argc, char** argv)
912
+ {
913
+ bool show_help = false;
914
+ bool debug_mode = false;
915
+ const struct libusb_version* version;
916
+ int j, r;
917
+ size_t i, arglen;
918
+ unsigned tmp_vid, tmp_pid;
919
+ uint16_t endian_test = 0xBE00;
920
+
921
+ // Default to generic, expecting VID:PID
922
+ VID = 0;
923
+ PID = 0;
924
+ test_mode = USE_GENERIC;
925
+
926
+ if (((uint8_t*)&endian_test)[0] == 0xBE) {
927
+ printf("Despite their natural superiority for end users, big endian\n"
928
+ "CPUs are not supported with this program, sorry.\n");
929
+ return 0;
930
+ }
931
+
932
+ if (argc >= 2) {
933
+ for (j = 1; j<argc; j++) {
934
+ arglen = strlen(argv[j]);
935
+ if ( ((argv[j][0] == '-') || (argv[j][0] == '/'))
936
+ && (arglen >= 2) ) {
937
+ switch(argv[j][1]) {
938
+ case 'd':
939
+ debug_mode = true;
940
+ break;
941
+ case 'i':
942
+ extra_info = true;
943
+ break;
944
+ case 'b':
945
+ if ((j+1 >= argc) || (argv[j+1][0] == '-') || (argv[j+1][0] == '/')) {
946
+ printf(" Option -b requires a file name");
947
+ return 1;
948
+ }
949
+ binary_name = argv[++j];
950
+ binary_dump = true;
951
+ break;
952
+ case 'j':
953
+ // OLIMEX ARM-USB-TINY JTAG, 2 channel composite device - 2 interfaces
954
+ if (!VID && !PID) {
955
+ VID = 0x15BA;
956
+ PID = 0x0004;
957
+ }
958
+ break;
959
+ case 'k':
960
+ // Generic 2 GB USB Key (SCSI Transparent/Bulk Only) - 1 interface
961
+ if (!VID && !PID) {
962
+ VID = 0x0204;
963
+ PID = 0x6025;
964
+ }
965
+ break;
966
+ // The following tests will force VID:PID if already provided
967
+ case 'p':
968
+ // Sony PS3 Controller - 1 interface
969
+ VID = 0x054C;
970
+ PID = 0x0268;
971
+ test_mode = USE_PS3;
972
+ break;
973
+ case 's':
974
+ // Microsoft Sidewinder Precision Pro Joystick - 1 HID interface
975
+ VID = 0x045E;
976
+ PID = 0x0008;
977
+ test_mode = USE_HID;
978
+ break;
979
+ case 'x':
980
+ // Microsoft XBox Controller Type S - 1 interface
981
+ VID = 0x045E;
982
+ PID = 0x0289;
983
+ test_mode = USE_XBOX;
984
+ break;
985
+ default:
986
+ show_help = true;
987
+ break;
988
+ }
989
+ } else {
990
+ for (i=0; i<arglen; i++) {
991
+ if (argv[j][i] == ':')
992
+ break;
993
+ }
994
+ if (i != arglen) {
995
+ if (sscanf_s(argv[j], "%x:%x" , &tmp_vid, &tmp_pid) != 2) {
996
+ printf(" Please specify VID & PID as \"vid:pid\" in hexadecimal format\n");
997
+ return 1;
998
+ }
999
+ VID = (uint16_t)tmp_vid;
1000
+ PID = (uint16_t)tmp_pid;
1001
+ } else {
1002
+ show_help = true;
1003
+ }
1004
+ }
1005
+ }
1006
+ }
1007
+
1008
+ if ((show_help) || (argc == 1) || (argc > 7)) {
1009
+ printf("usage: %s [-h] [-d] [-i] [-k] [-b file] [-j] [-x] [-s] [-p] [vid:pid]\n", argv[0]);
1010
+ printf(" -h : display usage\n");
1011
+ printf(" -d : enable debug output\n");
1012
+ printf(" -i : print topology and speed info\n");
1013
+ printf(" -j : test composite FTDI based JTAG device\n");
1014
+ printf(" -k : test Mass Storage device\n");
1015
+ printf(" -b file : dump Mass Storage data to file 'file'\n");
1016
+ printf(" -p : test Sony PS3 SixAxis controller\n");
1017
+ printf(" -s : test Microsoft Sidewinder Precision Pro (HID)\n");
1018
+ printf(" -x : test Microsoft XBox Controller Type S\n");
1019
+ printf("If only the vid:pid is provided, xusb attempts to run the most appropriate test\n");
1020
+ return 0;
1021
+ }
1022
+
1023
+ version = libusb_get_version();
1024
+ printf("Using libusbx v%d.%d.%d.%d\n\n", version->major, version->minor, version->micro, version->nano);
1025
+ r = libusb_init(NULL);
1026
+ if (r < 0)
1027
+ return r;
1028
+
1029
+ libusb_set_debug(NULL, debug_mode?LIBUSB_LOG_LEVEL_DEBUG:LIBUSB_LOG_LEVEL_INFO);
1030
+
1031
+ test_device(VID, PID);
1032
+
1033
+ libusb_exit(NULL);
1034
+
1035
+ return 0;
1036
+ }