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