ribusb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/COPYING +340 -0
  2. data/README +27 -0
  3. data/extconf.rb +10 -0
  4. data/ribusb.c +2344 -0
  5. metadata +58 -0
data/COPYING ADDED
@@ -0,0 +1,340 @@
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ Preamble
10
+
11
+ The licenses for most software are designed to take away your
12
+ freedom to share and change it. By contrast, the GNU General Public
13
+ License is intended to guarantee your freedom to share and change free
14
+ software--to make sure the software is free for all its users. This
15
+ General Public License applies to most of the Free Software
16
+ Foundation's software and to any other program whose authors commit to
17
+ using it. (Some other Free Software Foundation software is covered by
18
+ the GNU Library General Public License instead.) You can apply it to
19
+ your programs, too.
20
+
21
+ When we speak of free software, we are referring to freedom, not
22
+ price. Our General Public Licenses are designed to make sure that you
23
+ have the freedom to distribute copies of free software (and charge for
24
+ this service if you wish), that you receive source code or can get it
25
+ if you want it, that you can change the software or use pieces of it
26
+ in new free programs; and that you know you can do these things.
27
+
28
+ To protect your rights, we need to make restrictions that forbid
29
+ anyone to deny you these rights or to ask you to surrender the rights.
30
+ These restrictions translate to certain responsibilities for you if you
31
+ distribute copies of the software, or if you modify it.
32
+
33
+ For example, if you distribute copies of such a program, whether
34
+ gratis or for a fee, you must give the recipients all the rights that
35
+ you have. You must make sure that they, too, receive or can get the
36
+ source code. And you must show them these terms so they know their
37
+ rights.
38
+
39
+ We protect your rights with two steps: (1) copyright the software, and
40
+ (2) offer you this license which gives you legal permission to copy,
41
+ distribute and/or modify the software.
42
+
43
+ Also, for each author's protection and ours, we want to make certain
44
+ that everyone understands that there is no warranty for this free
45
+ software. If the software is modified by someone else and passed on, we
46
+ want its recipients to know that what they have is not the original, so
47
+ that any problems introduced by others will not reflect on the original
48
+ authors' reputations.
49
+
50
+ Finally, any free program is threatened constantly by software
51
+ patents. We wish to avoid the danger that redistributors of a free
52
+ program will individually obtain patent licenses, in effect making the
53
+ program proprietary. To prevent this, we have made it clear that any
54
+ patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ GNU GENERAL PUBLIC LICENSE
60
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+ 0. This License applies to any program or other work which contains
63
+ a notice placed by the copyright holder saying it may be distributed
64
+ under the terms of this General Public License. The "Program", below,
65
+ refers to any such program or work, and a "work based on the Program"
66
+ means either the Program or any derivative work under copyright law:
67
+ that is to say, a work containing the Program or a portion of it,
68
+ either verbatim or with modifications and/or translated into another
69
+ language. (Hereinafter, translation is included without limitation in
70
+ the term "modification".) Each licensee is addressed as "you".
71
+
72
+ Activities other than copying, distribution and modification are not
73
+ covered by this License; they are outside its scope. The act of
74
+ running the Program is not restricted, and the output from the Program
75
+ is covered only if its contents constitute a work based on the
76
+ Program (independent of having been made by running the Program).
77
+ Whether that is true depends on what the Program does.
78
+
79
+ 1. You may copy and distribute verbatim copies of the Program's
80
+ source code as you receive it, in any medium, provided that you
81
+ conspicuously and appropriately publish on each copy an appropriate
82
+ copyright notice and disclaimer of warranty; keep intact all the
83
+ notices that refer to this License and to the absence of any warranty;
84
+ and give any other recipients of the Program a copy of this License
85
+ along with the Program.
86
+
87
+ You may charge a fee for the physical act of transferring a copy, and
88
+ you may at your option offer warranty protection in exchange for a fee.
89
+
90
+ 2. You may modify your copy or copies of the Program or any portion
91
+ of it, thus forming a work based on the Program, and copy and
92
+ distribute such modifications or work under the terms of Section 1
93
+ above, provided that you also meet all of these conditions:
94
+
95
+ a) You must cause the modified files to carry prominent notices
96
+ stating that you changed the files and the date of any change.
97
+
98
+ b) You must cause any work that you distribute or publish, that in
99
+ whole or in part contains or is derived from the Program or any
100
+ part thereof, to be licensed as a whole at no charge to all third
101
+ parties under the terms of this License.
102
+
103
+ c) If the modified program normally reads commands interactively
104
+ when run, you must cause it, when started running for such
105
+ interactive use in the most ordinary way, to print or display an
106
+ announcement including an appropriate copyright notice and a
107
+ notice that there is no warranty (or else, saying that you provide
108
+ a warranty) and that users may redistribute the program under
109
+ these conditions, and telling the user how to view a copy of this
110
+ License. (Exception: if the Program itself is interactive but
111
+ does not normally print such an announcement, your work based on
112
+ the Program is not required to print an announcement.)
113
+
114
+ These requirements apply to the modified work as a whole. If
115
+ identifiable sections of that work are not derived from the Program,
116
+ and can be reasonably considered independent and separate works in
117
+ themselves, then this License, and its terms, do not apply to those
118
+ sections when you distribute them as separate works. But when you
119
+ distribute the same sections as part of a whole which is a work based
120
+ on the Program, the distribution of the whole must be on the terms of
121
+ this License, whose permissions for other licensees extend to the
122
+ entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+ Thus, it is not the intent of this section to claim rights or contest
125
+ your rights to work written entirely by you; rather, the intent is to
126
+ exercise the right to control the distribution of derivative or
127
+ collective works based on the Program.
128
+
129
+ In addition, mere aggregation of another work not based on the Program
130
+ with the Program (or with a work based on the Program) on a volume of
131
+ a storage or distribution medium does not bring the other work under
132
+ the scope of this License.
133
+
134
+ 3. You may copy and distribute the Program (or a work based on it,
135
+ under Section 2) in object code or executable form under the terms of
136
+ Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+ a) Accompany it with the complete corresponding machine-readable
139
+ source code, which must be distributed under the terms of Sections
140
+ 1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+ b) Accompany it with a written offer, valid for at least three
143
+ years, to give any third party, for a charge no more than your
144
+ cost of physically performing source distribution, a complete
145
+ machine-readable copy of the corresponding source code, to be
146
+ distributed under the terms of Sections 1 and 2 above on a medium
147
+ customarily used for software interchange; or,
148
+
149
+ c) Accompany it with the information you received as to the offer
150
+ to distribute corresponding source code. (This alternative is
151
+ allowed only for noncommercial distribution and only if you
152
+ received the program in object code or executable form with such
153
+ an offer, in accord with Subsection b above.)
154
+
155
+ The source code for a work means the preferred form of the work for
156
+ making modifications to it. For an executable work, complete source
157
+ code means all the source code for all modules it contains, plus any
158
+ associated interface definition files, plus the scripts used to
159
+ control compilation and installation of the executable. However, as a
160
+ special exception, the source code distributed need not include
161
+ anything that is normally distributed (in either source or binary
162
+ form) with the major components (compiler, kernel, and so on) of the
163
+ operating system on which the executable runs, unless that component
164
+ itself accompanies the executable.
165
+
166
+ If distribution of executable or object code is made by offering
167
+ access to copy from a designated place, then offering equivalent
168
+ access to copy the source code from the same place counts as
169
+ distribution of the source code, even though third parties are not
170
+ compelled to copy the source along with the object code.
171
+
172
+ 4. You may not copy, modify, sublicense, or distribute the Program
173
+ except as expressly provided under this License. Any attempt
174
+ otherwise to copy, modify, sublicense or distribute the Program is
175
+ void, and will automatically terminate your rights under this License.
176
+ However, parties who have received copies, or rights, from you under
177
+ this License will not have their licenses terminated so long as such
178
+ parties remain in full compliance.
179
+
180
+ 5. You are not required to accept this License, since you have not
181
+ signed it. However, nothing else grants you permission to modify or
182
+ distribute the Program or its derivative works. These actions are
183
+ prohibited by law if you do not accept this License. Therefore, by
184
+ modifying or distributing the Program (or any work based on the
185
+ Program), you indicate your acceptance of this License to do so, and
186
+ all its terms and conditions for copying, distributing or modifying
187
+ the Program or works based on it.
188
+
189
+ 6. Each time you redistribute the Program (or any work based on the
190
+ Program), the recipient automatically receives a license from the
191
+ original licensor to copy, distribute or modify the Program subject to
192
+ these terms and conditions. You may not impose any further
193
+ restrictions on the recipients' exercise of the rights granted herein.
194
+ You are not responsible for enforcing compliance by third parties to
195
+ this License.
196
+
197
+ 7. If, as a consequence of a court judgment or allegation of patent
198
+ infringement or for any other reason (not limited to patent issues),
199
+ conditions are imposed on you (whether by court order, agreement or
200
+ otherwise) that contradict the conditions of this License, they do not
201
+ excuse you from the conditions of this License. If you cannot
202
+ distribute so as to satisfy simultaneously your obligations under this
203
+ License and any other pertinent obligations, then as a consequence you
204
+ may not distribute the Program at all. For example, if a patent
205
+ license would not permit royalty-free redistribution of the Program by
206
+ all those who receive copies directly or indirectly through you, then
207
+ the only way you could satisfy both it and this License would be to
208
+ refrain entirely from distribution of the Program.
209
+
210
+ If any portion of this section is held invalid or unenforceable under
211
+ any particular circumstance, the balance of the section is intended to
212
+ apply and the section as a whole is intended to apply in other
213
+ circumstances.
214
+
215
+ It is not the purpose of this section to induce you to infringe any
216
+ patents or other property right claims or to contest validity of any
217
+ such claims; this section has the sole purpose of protecting the
218
+ integrity of the free software distribution system, which is
219
+ implemented by public license practices. Many people have made
220
+ generous contributions to the wide range of software distributed
221
+ through that system in reliance on consistent application of that
222
+ system; it is up to the author/donor to decide if he or she is willing
223
+ to distribute software through any other system and a licensee cannot
224
+ impose that choice.
225
+
226
+ This section is intended to make thoroughly clear what is believed to
227
+ be a consequence of the rest of this License.
228
+
229
+ 8. If the distribution and/or use of the Program is restricted in
230
+ certain countries either by patents or by copyrighted interfaces, the
231
+ original copyright holder who places the Program under this License
232
+ may add an explicit geographical distribution limitation excluding
233
+ those countries, so that distribution is permitted only in or among
234
+ countries not thus excluded. In such case, this License incorporates
235
+ the limitation as if written in the body of this License.
236
+
237
+ 9. The Free Software Foundation may publish revised and/or new versions
238
+ of the General Public License from time to time. Such new versions will
239
+ be similar in spirit to the present version, but may differ in detail to
240
+ address new problems or concerns.
241
+
242
+ Each version is given a distinguishing version number. If the Program
243
+ specifies a version number of this License which applies to it and "any
244
+ later version", you have the option of following the terms and conditions
245
+ either of that version or of any later version published by the Free
246
+ Software Foundation. If the Program does not specify a version number of
247
+ this License, you may choose any version ever published by the Free Software
248
+ Foundation.
249
+
250
+ 10. If you wish to incorporate parts of the Program into other free
251
+ programs whose distribution conditions are different, write to the author
252
+ to ask for permission. For software which is copyrighted by the Free
253
+ Software Foundation, write to the Free Software Foundation; we sometimes
254
+ make exceptions for this. Our decision will be guided by the two goals
255
+ of preserving the free status of all derivatives of our free software and
256
+ of promoting the sharing and reuse of software generally.
257
+
258
+ NO WARRANTY
259
+
260
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+ REPAIR OR CORRECTION.
269
+
270
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+ POSSIBILITY OF SUCH DAMAGES.
279
+
280
+ END OF TERMS AND CONDITIONS
281
+
282
+ How to Apply These Terms to Your New Programs
283
+
284
+ If you develop a new program, and you want it to be of the greatest
285
+ possible use to the public, the best way to achieve this is to make it
286
+ free software which everyone can redistribute and change under these terms.
287
+
288
+ To do so, attach the following notices to the program. It is safest
289
+ to attach them to the start of each source file to most effectively
290
+ convey the exclusion of warranty; and each file should have at least
291
+ the "copyright" line and a pointer to where the full notice is found.
292
+
293
+ <one line to give the program's name and a brief idea of what it does.>
294
+ Copyright (C) <year> <name of author>
295
+
296
+ This program is free software; you can redistribute it and/or modify
297
+ it under the terms of the GNU General Public License as published by
298
+ the Free Software Foundation; either version 2 of the License, or
299
+ (at your option) any later version.
300
+
301
+ This program is distributed in the hope that it will be useful,
302
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304
+ GNU General Public License for more details.
305
+
306
+ You should have received a copy of the GNU General Public License
307
+ along with this program; if not, write to the Free Software
308
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
309
+
310
+
311
+ Also add information on how to contact you by electronic and paper mail.
312
+
313
+ If the program is interactive, make it output a short notice like this
314
+ when it starts in an interactive mode:
315
+
316
+ Gnomovision version 69, Copyright (C) year name of author
317
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318
+ This is free software, and you are welcome to redistribute it
319
+ under certain conditions; type `show c' for details.
320
+
321
+ The hypothetical commands `show w' and `show c' should show the appropriate
322
+ parts of the General Public License. Of course, the commands you use may
323
+ be called something other than `show w' and `show c'; they could even be
324
+ mouse-clicks or menu items--whatever suits your program.
325
+
326
+ You should also get your employer (if you work as a programmer) or your
327
+ school, if any, to sign a "copyright disclaimer" for the program, if
328
+ necessary. Here is a sample; alter the names:
329
+
330
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
332
+
333
+ <signature of Ty Coon>, 1 April 1989
334
+ Ty Coon, President of Vice
335
+
336
+ This General Public License does not permit incorporating your program into
337
+ proprietary programs. If your program is a subroutine library, you may
338
+ consider it more useful to permit linking proprietary applications with the
339
+ library. If this is what you want to do, use the GNU Library General
340
+ Public License instead of this License.
data/README ADDED
@@ -0,0 +1,27 @@
1
+ This is RibUSB, a Ruby extension giving full access to the libusb library, API version 1.0.
2
+
3
+
4
+
5
+ INSTALLATION
6
+
7
+ In order to install RibUSB from source code, you need a working Ruby installation, including its
8
+ header files and build utilities (on Debian and Ubuntu systems, part the ruby-dev package). Also,
9
+ you need a C compiler (usually gcc), and make. The libusb-1.0 library along with its header files
10
+ must naturally be present (on Debian and Ubuntu system, install the libusb-1.0-0-dev package).
11
+
12
+ To install, execute these commands to configure RibUSB and to build it:
13
+
14
+ sh extconf.rb
15
+ make
16
+
17
+ Unless you have built and installed your own private copy of Ruby (as non-root user), become
18
+ super user and install the extension:
19
+
20
+ make install
21
+
22
+ From now on, you can use the RibUSB extension from any instance of Ruby on that computer by
23
+ "requiring" it from within your Ruby program:
24
+
25
+ require "ribusb"
26
+
27
+ Please browse the documentation on the website for example uses of RibUSB. Have fun.
data/extconf.rb ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require "mkmf"
4
+
5
+ dir_config("ribusb")
6
+
7
+ pkg_config("libusb-1.0")
8
+ $CFLAGS += " -Wall"
9
+
10
+ create_makefile("ribusb")
data/ribusb.c ADDED
@@ -0,0 +1,2344 @@
1
+ /* ========================================================================= */
2
+ /*
3
+ RibUSB -- Ruby bindings to libusb.
4
+
5
+ This program is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU General Public License as
7
+ published by the Free Software Foundation; version 2 of the License.
8
+
9
+ This program is distributed in the hope that it will be useful, but
10
+ WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program; if not, write to the Free Software
16
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
17
+ MA 02111-1307, USA.
18
+
19
+ This program is copyright by Andr�s G. Major, 2009.
20
+ Please visit the project website at http://ribusb.rubyforge.org/
21
+ for support.
22
+ */
23
+ /* ========================================================================= */
24
+
25
+ #include <ruby.h>
26
+ #include <libusb.h>
27
+
28
+ /******************************************************
29
+ * global variables *
30
+ ******************************************************/
31
+
32
+ static VALUE RibUSB;
33
+ static VALUE Bus;
34
+ static VALUE Device;
35
+ static VALUE ConfigDescriptor;
36
+ static VALUE Interface;
37
+ static VALUE InterfaceDescriptor;
38
+ static VALUE EndpointDescriptor;
39
+ static VALUE Transfer;
40
+
41
+
42
+
43
+ /******************************************************
44
+ * structures for classes *
45
+ ******************************************************/
46
+
47
+ /*
48
+ * Opaque structure for the RibUSB::Bus class
49
+ */
50
+ struct usb_t {
51
+ struct libusb_context *context;
52
+ };
53
+
54
+ /*
55
+ * Opaque structure for the RibUSB::Device class
56
+ */
57
+ struct device_t {
58
+ struct libusb_device *device;
59
+ struct libusb_device_handle *handle;
60
+ struct libusb_device_descriptor *descriptor;
61
+ };
62
+
63
+ /*
64
+ * Opaque structure for the RibUSB::ConfigDescriptor class
65
+ */
66
+ struct config_descriptor_t {
67
+ struct libusb_config_descriptor *descriptor;
68
+ };
69
+
70
+ /*
71
+ * Opaque structure for the RibUSB::Interface class
72
+ */
73
+ struct interface_t {
74
+ struct libusb_interface *interface;
75
+ };
76
+
77
+ /*
78
+ * Opaque structure for the RibUSB::InterfaceDescriptor class
79
+ */
80
+ struct interface_descriptor_t {
81
+ struct libusb_interface_descriptor *descriptor;
82
+ };
83
+
84
+ /*
85
+ * Opaque structure for the RibUSB::EndpointDescriptor class
86
+ */
87
+ struct endpoint_descriptor_t {
88
+ struct libusb_endpoint_descriptor *descriptor;
89
+ };
90
+
91
+ /*
92
+ * Opaque structure for the RibUSB::Transfer class
93
+ */
94
+ struct transfer_t {
95
+ struct libusb_transfer *transfer;
96
+ unsigned char *buffer;
97
+ VALUE proc;
98
+ };
99
+
100
+
101
+
102
+ /******************************************************
103
+ * internal prototypes *
104
+ ******************************************************/
105
+ static VALUE cDevice_new (struct libusb_device *device);
106
+ void cTransfer_free (struct transfer_t *t);
107
+ static VALUE cConfigDescriptor_new (struct libusb_config_descriptor *descriptor);
108
+ static VALUE cInterface_new (struct libusb_interface *interface);
109
+ static VALUE cInterfaceDescriptor_new (struct libusb_interface_descriptor *descriptor);
110
+ static VALUE cEndpointDescriptor_new (struct libusb_endpoint_descriptor *descriptor);
111
+
112
+
113
+
114
+ /******************************************************
115
+ * internal functions *
116
+ ******************************************************/
117
+
118
+ static void callback_wrapper (struct libusb_transfer *transfer)
119
+ {
120
+ struct transfer_t *t;
121
+
122
+ Data_Get_Struct ((struct transfer_t *) (transfer->user_data), struct transfer_t, t);
123
+ rb_funcall (t->proc, rb_intern("call"), 1, (VALUE *) transfer->user_data);
124
+ }
125
+
126
+ VALUE get_opt (VALUE hash, char *key, int mandatory)
127
+ {
128
+ VALUE opt;
129
+
130
+ opt = rb_hash_lookup (hash, ID2SYM(rb_intern (key)));
131
+ if (mandatory && (opt == Qnil)) {
132
+ rb_raise (rb_eRuntimeError, "Option :%s not specified.", key);
133
+ return Qnil;
134
+ }
135
+ return opt;
136
+ }
137
+
138
+
139
+
140
+ /******************************************************
141
+ * RibUSB method definitions *
142
+ ******************************************************/
143
+
144
+ int get_error (int number, char **name, char **text)
145
+ {
146
+ struct error_t {
147
+ int number;
148
+ char *name;
149
+ char *text;
150
+ };
151
+ static const struct error_t error_list[] = {
152
+ { LIBUSB_SUCCESS, "LIBUSB_SUCCESS", "success (no error)" },
153
+ { LIBUSB_ERROR_IO, "LIBUSB_ERROR_IO", "input/output error" },
154
+ { LIBUSB_ERROR_INVALID_PARAM, "LIBUSB_ERROR_INVALID_PARAM", "invalid parameter" },
155
+ { LIBUSB_ERROR_ACCESS, "LIBUSB_ERROR_ACCESS", "access denied (insuffucient permissions)" },
156
+ { LIBUSB_ERROR_NO_DEVICE, "LIBUSB_ERROR_NO_DEVICE", "no such device" },
157
+ { LIBUSB_ERROR_NOT_FOUND, "LIBUSB_ERROR_NOT_FOUND", "entity not found" },
158
+ { LIBUSB_ERROR_BUSY, "LIBUSB_ERROR_BUSY", "resource busy" },
159
+ { LIBUSB_ERROR_TIMEOUT, "LIBUSB_ERROR_TIMEOUT", "operation timed out" },
160
+ { LIBUSB_ERROR_OVERFLOW, "LIBUSB_ERROR_OVERFLOW", "overflow" },
161
+ { LIBUSB_ERROR_PIPE, "LIBUSB_ERROR_PIPE", "pipe error" },
162
+ { LIBUSB_ERROR_INTERRUPTED, "LIBUSB_ERROR_INTERRUPTED", "system call interrupted (perhaps due to signal)" },
163
+ { LIBUSB_ERROR_NO_MEM, "LIBUSB_ERROR_NO_MEM", "insufficient memory" },
164
+ { LIBUSB_ERROR_NOT_SUPPORTED, "LIBUSB_ERROR_NOT_SUPPORTED", "operation not supported or unimplemented on this platform" },
165
+ { LIBUSB_ERROR_OTHER, "LIBUSB_ERROR_OTHER", "other error" }
166
+ };
167
+ static const int n_error_list = sizeof (error_list) / sizeof (struct error_t);
168
+ static int i;
169
+
170
+ for (i = 0; i < n_error_list; i ++)
171
+ if (number == error_list[i].number) {
172
+ if (name)
173
+ *name = error_list[i].name;
174
+ if (text)
175
+ *text = error_list[i].text;
176
+ return 1;
177
+ break;
178
+ }
179
+ return 0;
180
+ }
181
+
182
+ char *get_error_text (int number)
183
+ {
184
+ char *text;
185
+ static char unknown[] = "unknown error number";
186
+
187
+ if (get_error (number, NULL, &text))
188
+ return text;
189
+ else
190
+ return unknown;
191
+ }
192
+
193
+ /*
194
+ * call-seq:
195
+ * RibUSB.getError(number) -> [name, text]
196
+ *
197
+ * Get the textual error description corresponding to a _libusb_ error code.
198
+ *
199
+ * - +number+ is an integer containing the error returned by a _libusb_ function.
200
+ * - +name+ is a +String+ containing the name of the error as used in the C header file <tt>libusb.h</tt>.
201
+ * - +text+ is a verbose description of the error, in English, using lower-case letters and no punctuation.
202
+ *
203
+ * On success (if the error number is valid), returns an array of two strings, otherwise raises an exception and returns +nil+. A value <tt>0</tt> for +number+ is a valid error number. All valid values for +number+ are non-positive.
204
+ */
205
+ static VALUE mRibUSB_getError (VALUE self, VALUE number)
206
+ {
207
+ int error;
208
+ char *name, *text;
209
+ VALUE array;
210
+
211
+ error = NUM2INT(number);
212
+ if (get_error (error, &name, &text)) {
213
+ array = rb_ary_new2 (2);
214
+ rb_ary_store (array, 0, rb_str_new2 (name));
215
+ rb_ary_store (array, 1, rb_str_new2 (text));
216
+ return array;
217
+ } else {
218
+ rb_raise (rb_eRuntimeError, "Error number %i does not exist.", error);
219
+ return Qnil;
220
+ }
221
+ }
222
+
223
+
224
+
225
+ /******************************************************
226
+ * RibUSB::Bus method definitions *
227
+ ******************************************************/
228
+
229
+ void cBus_free (struct usb_t *u)
230
+ {
231
+ libusb_exit (u->context);
232
+
233
+ free (u);
234
+ }
235
+
236
+ /*
237
+ * call-seq:
238
+ * RibUSB::Bus.new -> bus
239
+ *
240
+ * Create an instance of RibUSB::Bus.
241
+ *
242
+ * Effectively creates a _libusb_ context (the context itself being stored in an opaque structure). The memory associated with the bus is automatically freed on garbage collection when possible.
243
+ *
244
+ * If successful, returns the bus object, otherwise raises an exception and returns either +nil+ or the _libusb_ error code (+FixNum+).
245
+ */
246
+ static VALUE cBus_new (VALUE self)
247
+ {
248
+ struct libusb_context *context;
249
+ struct usb_t *u;
250
+ int res;
251
+ VALUE object;
252
+
253
+ res = libusb_init (&context);
254
+ if (res) {
255
+ rb_raise (rb_eRuntimeError, "Failed to initialize libusb: %s.", get_error_text (res));
256
+ return INT2NUM(res);
257
+ }
258
+ u = (struct usb_t *) malloc (sizeof (struct usb_t));
259
+ if (!u) {
260
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for RibUSB::Bus object.");
261
+ return Qnil;
262
+ }
263
+ u->context = context;
264
+ object = Data_Wrap_Struct (Bus, NULL, cBus_free, u);
265
+ rb_obj_call_init (object, 0, 0);
266
+ return object;
267
+ }
268
+
269
+ /*
270
+ * call-seq:
271
+ * bus.setDebug(level) -> nil
272
+ * bus.debug=level -> nil
273
+ *
274
+ * Set the debug level of the current _libusb_ context.
275
+ *
276
+ * - +level+ is a +FixNum+ with a sensible range from 0 to 3.
277
+ *
278
+ * Returns +nil+ and never raises an exception.
279
+ */
280
+ static VALUE cBus_setDebug (VALUE self, VALUE level)
281
+ {
282
+ struct usb_t *u;
283
+
284
+ Data_Get_Struct (self, struct usb_t, u);
285
+ libusb_set_debug (u->context, NUM2INT(level));
286
+ return Qnil;
287
+ }
288
+
289
+ /*
290
+ * call-seq:
291
+ * bus.find -> list
292
+ * bus.find {block} -> list
293
+ * bus.find(hash) -> list
294
+ * bus.find(hash) {block} -> list
295
+ *
296
+ * Obtain a list of devices currently attached to the USB system, optionally matching certain criteria.
297
+ *
298
+ * Criteria can, optionally, be supplied in the form of a hash, or in a block, or both.
299
+ * - In the hash, a number of simple criteria can be defined. If a criterion is not specified or its value is +nil+, any device will match that criterion.
300
+ * * <tt>:idVendor</tt>, <tt>:idProduct</tt> (+FixNum+) for the vendor/product ID;
301
+ * * <tt>:bcdUSB</tt>, <tt>:bcdDevice</tt> (+FixNum+) for the USB and device release numbers;
302
+ * * <tt>:bDeviceClass</tt>, <tt>:bDeviceSubClass</tt>, <tt>:bDeviceProtocol</tt>, <tt>:bMaxPacketSize0</tt> (+FixNum+) for the device type.
303
+ * - The block is called for all devices that match the criteria specified in the hash.
304
+ * - The block is passed a single argument: the RibUSB::Device instance of the device. The device is included in the resulting list if and only if the block returns non-+false+.
305
+ * - If the block is not specified, all devices matching the hash criteria are returned.
306
+ *
307
+ * On success, returns an array of RibUSB::Device with one entry for each device, otherwise raises an exception and returns the _libusb_ error code (+FixNum+).
308
+ *
309
+ * Note: this list provides no information whatsoever on whether or not any given device can be accessed. Insufficient privilege and use by other software can prevent access to any device.
310
+ */
311
+ static VALUE cBus_find (int argc, VALUE *argv, VALUE self)
312
+ {
313
+ struct usb_t *u;
314
+ struct libusb_device **list;
315
+ struct device_t *d;
316
+ ssize_t res;
317
+ VALUE device, array;
318
+ int i;
319
+ VALUE v;
320
+ uint8_t bDeviceClass = 0, bDeviceSubClass = 0, bDeviceProtocol = 0, bMaxPacketSize0 = 0;
321
+ uint16_t bcdUSB = 0, idVendor = 0, idProduct = 0, bcdDevice = 0;
322
+ uint16_t mask = 0;
323
+ VALUE hash, proc;
324
+
325
+ rb_scan_args (argc, argv, "01&", &hash, &proc);
326
+ if (!NIL_P(hash)) {
327
+ if (rb_type(hash) == T_HASH) {
328
+ v = rb_hash_lookup (hash, ID2SYM(rb_intern ("bDeviceClass")));
329
+ if (!NIL_P(v)) {
330
+ bDeviceClass = NUM2INT(v);
331
+ mask |= 0x01;
332
+ }
333
+ v = rb_hash_lookup (hash, ID2SYM(rb_intern ("bDeviceSubClass")));
334
+ if (!NIL_P(v)) {
335
+ bDeviceSubClass = NUM2INT(v);
336
+ mask |= 0x02;
337
+ }
338
+ v = rb_hash_lookup (hash, ID2SYM(rb_intern ("bDeviceProtocol")));
339
+ if (!NIL_P(v)) {
340
+ bDeviceProtocol = NUM2INT(v);
341
+ mask |= 0x04;
342
+ }
343
+ v = rb_hash_lookup (hash, ID2SYM(rb_intern ("bMaxPacketSize0")));
344
+ if (!NIL_P(v)) {
345
+ bMaxPacketSize0 = NUM2INT(v);
346
+ mask |= 0x08;
347
+ }
348
+ v = rb_hash_lookup (hash, ID2SYM(rb_intern ("bcdUSB")));
349
+ if (!NIL_P(v)) {
350
+ bcdUSB = NUM2INT(v);
351
+ mask |= 0x10;
352
+ }
353
+ v = rb_hash_lookup (hash, ID2SYM(rb_intern ("idVendor")));
354
+ if (!NIL_P(v)) {
355
+ idVendor = NUM2INT(v);
356
+ mask |= 0x20;
357
+ }
358
+ v = rb_hash_lookup (hash, ID2SYM(rb_intern ("idProduct")));
359
+ if (!NIL_P(v)) {
360
+ idProduct = NUM2INT(v);
361
+ mask |= 0x40;
362
+ }
363
+ v = rb_hash_lookup (hash, ID2SYM(rb_intern ("bcdDevice")));
364
+ if (!NIL_P(v)) {
365
+ bcdDevice = NUM2INT(v);
366
+ mask |= 0x80;
367
+ }
368
+ } else
369
+ rb_raise (rb_eRuntimeError, "Argument to RibUSB::Bus#find must be a hash or nil, if specified.");
370
+ }
371
+
372
+ Data_Get_Struct (self, struct usb_t, u);
373
+
374
+ res = libusb_get_device_list (u->context, &list);
375
+
376
+ if (res < 0) {
377
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for list of devices: %s.", get_error_text (res));
378
+ return INT2NUM(res);
379
+ }
380
+
381
+ array = rb_ary_new ();
382
+
383
+ for (i = 0; i < res; i ++) {
384
+ device = cDevice_new (list[i]); /* XXX not very nice */
385
+ Data_Get_Struct (device, struct device_t, d); /* XXX not very nice */
386
+ if ((mask & 0x01) && (bDeviceClass != d->descriptor->bDeviceClass))
387
+ continue;
388
+ if ((mask & 0x02) && (bDeviceSubClass != d->descriptor->bDeviceSubClass))
389
+ continue;
390
+ if ((mask & 0x04) && (bDeviceProtocol != d->descriptor->bDeviceProtocol))
391
+ continue;
392
+ if ((mask & 0x08) && (bMaxPacketSize0 != d->descriptor->bMaxPacketSize0))
393
+ continue;
394
+ if ((mask & 0x10) && (bcdUSB != d->descriptor->bcdUSB))
395
+ continue;
396
+ if ((mask & 0x20) && (idVendor != d->descriptor->idVendor))
397
+ continue;
398
+ if ((mask & 0x40) && (idProduct != d->descriptor->idProduct))
399
+ continue;
400
+ if ((mask & 0x80) && (bcdDevice != d->descriptor->bcdDevice))
401
+ continue;
402
+
403
+ if (!NIL_P(proc))
404
+ if (rb_funcall (proc, rb_intern ("call"), 1, device) == Qfalse)
405
+ continue;
406
+
407
+ rb_ary_push (array, device);
408
+ }
409
+
410
+ libusb_free_device_list (list, 1);
411
+
412
+ return array;
413
+ }
414
+
415
+ /*
416
+ * call-seq:
417
+ * RibUSB::Bus.handleEvents -> nil
418
+ *
419
+ * Handles all pending USB events on the bus.
420
+ *
421
+ * If successful, returns +nil+, otherwise raises an exception and returns either the _libusb_ error code (+FixNum+).
422
+ */
423
+ static VALUE cBus_handleEvents (VALUE self)
424
+ {
425
+ struct usb_t *u;
426
+ int res;
427
+
428
+ Data_Get_Struct (self, struct usb_t, u);
429
+ res = libusb_handle_events (u->context);
430
+ if (res) {
431
+ rb_raise (rb_eRuntimeError, "Failed to handle pending USB events: %s.", get_error_text (res));
432
+ return INT2NUM(res);
433
+ }
434
+ return Qnil;
435
+ }
436
+
437
+
438
+
439
+ /******************************************************
440
+ * RibUSB::Device method definitions *
441
+ ******************************************************/
442
+
443
+ void cDevice_free (struct device_t *d)
444
+ {
445
+ if (d->handle)
446
+ libusb_close (d->handle);
447
+
448
+ libusb_unref_device (d->device);
449
+
450
+ free (d);
451
+ }
452
+
453
+ /* XXXXXX does this need to be a separate function??? */
454
+ static VALUE cDevice_new (struct libusb_device *device)
455
+ {
456
+ struct device_t *d;
457
+ VALUE object;
458
+ int res;
459
+
460
+ d = (struct device_t *) malloc (sizeof (struct device_t));
461
+ if (!d) {
462
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for RibUSB::Device object.");
463
+ return Qnil;
464
+ }
465
+ libusb_ref_device (device);
466
+ d->device = device;
467
+ d->handle = NULL;
468
+ d->descriptor = (struct libusb_device_descriptor *) malloc (sizeof (struct libusb_device_descriptor));
469
+ if (!(d->descriptor)) {
470
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for struct libusb_device_descriptor.");
471
+ return Qnil;
472
+ }
473
+ res = libusb_get_device_descriptor (d->device, d->descriptor);
474
+ if (res < 0)
475
+ rb_raise (rb_eRuntimeError, "Failed to retrieve device descriptor: %s.", get_error_text (res));
476
+
477
+ object = Data_Wrap_Struct (Device, NULL, cDevice_free, d);
478
+ rb_obj_call_init (object, 0, 0);
479
+ return object;
480
+ }
481
+
482
+ /*
483
+ * call-seq:
484
+ * device.getBusNumber -> bus_number
485
+ * device.busNumber -> bus_number
486
+ *
487
+ * Get bus number.
488
+ *
489
+ * On success, returns the USB bus number (+FixNum+) the device is connected to, otherwise raises an exception and returns the _libusb_ error code (+FixNum+).
490
+ */
491
+ static VALUE cDevice_getBusNumber (VALUE self)
492
+ {
493
+ struct device_t *d;
494
+ int res;
495
+
496
+ Data_Get_Struct (self, struct device_t, d);
497
+ res = libusb_get_bus_number (d->device);
498
+ if (res < 0)
499
+ rb_raise (rb_eRuntimeError, "Failed to retrieve device bus number: %s.", get_error_text (res));
500
+ return INT2NUM(res);
501
+ }
502
+
503
+ /*
504
+ * call-seq:
505
+ * device.getDeviceAddress -> address
506
+ * device.deviceAddress -> address
507
+ *
508
+ * Get device address.
509
+ *
510
+ * On success, returns the USB address on the bus (+FixNum+), otherwise raises an exception and returns the _libusb_ error code (+FixNum+).
511
+ */
512
+ static VALUE cDevice_getDeviceAddress (VALUE self)
513
+ {
514
+ struct device_t *d;
515
+ int res;
516
+
517
+ Data_Get_Struct (self, struct device_t, d);
518
+ res = libusb_get_device_address (d->device);
519
+ if (res < 0)
520
+ rb_raise (rb_eRuntimeError, "Failed to retrieve device address: %s.", get_error_text (res));
521
+ return INT2NUM(res);
522
+ }
523
+
524
+ /*
525
+ * call-seq:
526
+ * device.getMaxPacketSize(endpoint) -> max_packet_size
527
+ * device.maxPacketSize(endpoint) -> max_packet_size
528
+ *
529
+ * Get maximum packet size.
530
+ *
531
+ * - +endpoint+ is a +FixNum+ containing the endpoint number.
532
+ *
533
+ * On success, returns the maximum packet size of the endpoint (+FixNum+), otherwise raises an exception and returns the _libusb_ error code (+FixNum+).
534
+ */
535
+ static VALUE cDevice_getMaxPacketSize (VALUE self, VALUE endpoint)
536
+ {
537
+ struct device_t *d;
538
+ int res;
539
+
540
+ Data_Get_Struct (self, struct device_t, d);
541
+ res = libusb_get_max_packet_size (d->device, NUM2INT(endpoint));
542
+ if (res < 0)
543
+ rb_raise (rb_eRuntimeError, "Failed to retrieve maximum packet size of endpoint: %s.", get_error_text (res));
544
+ return INT2NUM(res);
545
+ }
546
+
547
+ /*
548
+ * call-seq:
549
+ * device.getConfiguration -> configuration
550
+ * device.configuration -> configuration
551
+ *
552
+ * Get currently active configuration.
553
+ *
554
+ * On success, returns the bConfigurationValue of the active configuration of the device (+FixNum+), otherwise raises an exception and returns the _libusb_ error code (+FixNum+).
555
+ */
556
+ static VALUE cDevice_getConfiguration (VALUE self)
557
+ {
558
+ struct device_t *d;
559
+ int res;
560
+ int c;
561
+
562
+ Data_Get_Struct (self, struct device_t, d);
563
+ if (d->handle == NULL) {
564
+ res = libusb_open (d->device, &(d->handle));
565
+ if (res < 0) {
566
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
567
+ return INT2NUM(res);
568
+ }
569
+ }
570
+ res = libusb_get_configuration (d->handle, &c);
571
+ if (res < 0)
572
+ rb_raise (rb_eRuntimeError, "Failed to obtain configuration value: %s.", get_error_text (res));
573
+ return INT2NUM(c);
574
+ }
575
+
576
+ /*
577
+ * call-seq:
578
+ * device.setConfiguration(configuration) -> nil
579
+ * device.configuration=(configuration) -> nil
580
+ *
581
+ * Set active configuration.
582
+ *
583
+ * - +configuration+ is a +FixNum+ containing the configuration number.
584
+ *
585
+ * Returns +nil+ in any case, and raises an exception on failure.
586
+ */
587
+ static VALUE cDevice_setConfiguration (VALUE self, VALUE configuration)
588
+ {
589
+ struct device_t *d;
590
+ int res;
591
+
592
+ Data_Get_Struct (self, struct device_t, d);
593
+ if (d->handle == NULL) {
594
+ res = libusb_open (d->device, &(d->handle));
595
+ if (res < 0) {
596
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
597
+ return INT2NUM(res);
598
+ }
599
+ }
600
+ res = libusb_set_configuration (d->handle, NUM2INT(configuration));
601
+ if (res < 0)
602
+ rb_raise (rb_eRuntimeError, "Failed to set configuration: %s.", get_error_text (res));
603
+ return INT2NUM(res);
604
+ }
605
+
606
+ /*
607
+ * call-seq:
608
+ * device.claimInterface(interface) -> nil
609
+ *
610
+ * Claim interface.
611
+ *
612
+ * - +interface+ is a +FixNum+ containing the interface number.
613
+ *
614
+ * Returns +nil+ in any case, and raises an exception on failure.
615
+ */
616
+ static VALUE cDevice_claimInterface (VALUE self, VALUE interface)
617
+ {
618
+ struct device_t *d;
619
+ int res;
620
+
621
+ Data_Get_Struct (self, struct device_t, d);
622
+ if (d->handle == NULL) {
623
+ res = libusb_open (d->device, &(d->handle));
624
+ if (res < 0) {
625
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
626
+ return INT2NUM(res);
627
+ }
628
+ }
629
+ res = libusb_claim_interface (d->handle, NUM2INT(interface));
630
+ if (res < 0)
631
+ rb_raise (rb_eRuntimeError, "Failed to claim interface: %s.", get_error_text (res));
632
+ return INT2NUM(res);
633
+ }
634
+
635
+ /*
636
+ * call-seq:
637
+ * device.releaseInterface(interface) -> nil
638
+ * Release interface.
639
+ *
640
+ * - +interface+ is a +FixNum+ containing the interface number.
641
+ *
642
+ * Returns +nil+ in any case, and raises an exception on failure.
643
+ */
644
+ static VALUE cDevice_releaseInterface (VALUE self, VALUE interface)
645
+ {
646
+ struct device_t *d;
647
+ int res;
648
+
649
+ Data_Get_Struct (self, struct device_t, d);
650
+ if (d->handle == NULL) {
651
+ res = libusb_open (d->device, &(d->handle));
652
+ if (res < 0) {
653
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
654
+ return INT2NUM(res);
655
+ }
656
+ }
657
+ res = libusb_release_interface (d->handle, NUM2INT(interface));
658
+ if (res < 0)
659
+ rb_raise (rb_eRuntimeError, "Failed to release interface: %s.", get_error_text (res));
660
+ return INT2NUM(res);
661
+ }
662
+
663
+ /*
664
+ * call-seq:
665
+ * device.setInterfaceAltSetting(interface, setting) -> nil
666
+ *
667
+ * Set alternate setting for an interface.
668
+ *
669
+ * - +interface+ is a +FixNum+ containing the interface number.
670
+ * - +setting+ is a +FixNum+ containing the alternate setting number.
671
+ *
672
+ * Returns +nil+ in any case, and raises an exception on failure.
673
+ */
674
+ static VALUE cDevice_setInterfaceAltSetting (VALUE self, VALUE interface, VALUE setting)
675
+ {
676
+ struct device_t *d;
677
+ int res;
678
+
679
+ Data_Get_Struct (self, struct device_t, d);
680
+ if (d->handle == NULL) {
681
+ res = libusb_open (d->device, &(d->handle));
682
+ if (res < 0) {
683
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
684
+ return INT2NUM(res);
685
+ }
686
+ }
687
+ res = libusb_set_interface_alt_setting (d->handle, NUM2INT(interface), NUM2INT(setting));
688
+ if (res < 0)
689
+ rb_raise (rb_eRuntimeError, "Failed to set interface alternate setting: %s.", get_error_text (res));
690
+ return INT2NUM(res);
691
+ }
692
+
693
+ /*
694
+ * call-seq:
695
+ * device.clearHalt(endpoint) -> nil
696
+ *
697
+ * Clear halt/stall condition for an endpoint.
698
+ *
699
+ * - +endpoint+ is a +FixNum+ containing the endpoint number.
700
+ *
701
+ * Returns +nil+ in any case, and raises an exception on failure.
702
+ */
703
+ static VALUE cDevice_clearHalt (VALUE self, VALUE endpoint)
704
+ {
705
+ struct device_t *d;
706
+ int res;
707
+
708
+ Data_Get_Struct (self, struct device_t, d);
709
+ if (d->handle == NULL) {
710
+ res = libusb_open (d->device, &(d->handle));
711
+ if (res < 0) {
712
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
713
+ return INT2NUM(res);
714
+ }
715
+ }
716
+ res = libusb_clear_halt (d->handle, NUM2INT(endpoint));
717
+ if (res < 0)
718
+ rb_raise (rb_eRuntimeError, "Failed to clear halt/stall condition: %s.", get_error_text (res));
719
+ return INT2NUM(res);
720
+ }
721
+
722
+ /*
723
+ * call-seq: device.resetDevice -> nil
724
+ *
725
+ * Reset device.
726
+ *
727
+ * Returns +nil+ in any case, and raises an exception on failure.
728
+ */
729
+ static VALUE cDevice_resetDevice (VALUE self)
730
+ {
731
+ struct device_t *d;
732
+ int res;
733
+
734
+ Data_Get_Struct (self, struct device_t, d);
735
+ if (d->handle == NULL) {
736
+ res = libusb_open (d->device, &(d->handle));
737
+ if (res < 0) {
738
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
739
+ return INT2NUM(res);
740
+ }
741
+ }
742
+ res = libusb_reset_device (d->handle);
743
+ if (res < 0)
744
+ rb_raise (rb_eRuntimeError, "Failed to reset device: %s.", get_error_text (res));
745
+ return INT2NUM(res);
746
+ }
747
+
748
+ /*
749
+ * call-seq:
750
+ * device.kernelDriverActive?(interface) -> result
751
+ *
752
+ * Determine if a kernel driver is active on a given interface.
753
+ *
754
+ * - +interface+ is a +FixNum+ containing the interface number.
755
+ *
756
+ * On success, returns whether or not the device interface is claimed by a kernel driver (+true+ or +false+), otherwise raises an exception and returns the _libusb_ error code (+FixNum+).
757
+ */
758
+ static VALUE cDevice_kernelDriverActiveQ (VALUE self, VALUE interface)
759
+ {
760
+ struct device_t *d;
761
+ int res;
762
+
763
+ Data_Get_Struct (self, struct device_t, d);
764
+ if (d->handle == NULL) {
765
+ res = libusb_open (d->device, &(d->handle));
766
+ if (res < 0) {
767
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
768
+ return INT2NUM(res);
769
+ }
770
+ }
771
+ res = libusb_kernel_driver_active (d->handle, NUM2INT(interface));
772
+ if (res < 0) {
773
+ rb_raise (rb_eRuntimeError, "Failed to determine whether a kernel driver is active on interface: %s.", get_error_text (res));
774
+ return INT2NUM(res);
775
+ } else if (res == 1)
776
+ return Qtrue;
777
+ else
778
+ return Qfalse;
779
+ }
780
+
781
+ /*
782
+ * call-seq:
783
+ * device.detachKernelDriver(interface) -> nil
784
+ *
785
+ * Detach a kernel driver from an interface.
786
+ *
787
+ * - +interface+ is a +FixNum+ containing the interface number.
788
+ *
789
+ * Returns +nil+ in any case, and raises an exception on failure.
790
+ */
791
+ static VALUE cDevice_detachKernelDriver (VALUE self, VALUE interface)
792
+ {
793
+ struct device_t *d;
794
+ int res;
795
+
796
+ Data_Get_Struct (self, struct device_t, d);
797
+ if (d->handle == NULL) {
798
+ res = libusb_open (d->device, &(d->handle));
799
+ if (res < 0) {
800
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
801
+ return INT2NUM(res);
802
+ }
803
+ }
804
+ res = libusb_detach_kernel_driver (d->handle, NUM2INT(interface));
805
+ if (res < 0)
806
+ rb_raise (rb_eRuntimeError, "Failed to detach kernel driver: %s.", get_error_text (res));
807
+ return INT2NUM(res);
808
+ }
809
+
810
+ /*
811
+ * call-seq:
812
+ * device.attachKernelDriver(interface) -> nil
813
+ *
814
+ * Re-attach a kernel driver from an interface.
815
+ *
816
+ * - +interface+ is a +FixNum+ containing the interface number.
817
+ *
818
+ * Returns +nil+ in any case, and raises an exception on failure.
819
+ */
820
+ static VALUE cDevice_attachKernelDriver (VALUE self, VALUE interface)
821
+ {
822
+ struct device_t *d;
823
+ int res;
824
+
825
+ Data_Get_Struct (self, struct device_t, d);
826
+ if (d->handle == NULL) {
827
+ res = libusb_open (d->device, &(d->handle));
828
+ if (res < 0) {
829
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
830
+ return INT2NUM(res);
831
+ }
832
+ }
833
+ res = libusb_attach_kernel_driver (d->handle, NUM2INT(interface));
834
+ if (res < 0)
835
+ rb_raise (rb_eRuntimeError, "Failed to re-attach kernel driver: %s.", get_error_text (res));
836
+ return INT2NUM(res);
837
+ }
838
+
839
+ /*
840
+ * call-seq:
841
+ * device.getStringDescriptorASCII(index) -> desc
842
+ * device.stringDescriptorASCII(index) -> desc
843
+ *
844
+ * - +index+ is a +FixNum+ specifying the index of the descriptor string.
845
+ *
846
+ * Retrieve an ASCII descriptor string from the device.
847
+ *
848
+ * On success, returns the ASCII descriptor string of given index (+String+), otherwise raises an exception and returns the _libusb_ error code (+FixNum+).
849
+ */
850
+ static VALUE cDevice_getStringDescriptorASCII (VALUE self, VALUE index)
851
+ {
852
+ struct device_t *d;
853
+ int res;
854
+ char c[256];
855
+
856
+ Data_Get_Struct (self, struct device_t, d);
857
+ if (d->handle == NULL) {
858
+ res = libusb_open (d->device, &(d->handle));
859
+ if (res < 0) {
860
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
861
+ return INT2NUM(res);
862
+ }
863
+ }
864
+ res = libusb_get_string_descriptor_ascii (d->handle, NUM2INT(index), (unsigned char *) c, sizeof (c));
865
+ if (res < 0)
866
+ rb_raise (rb_eRuntimeError, "Failed to retrieve descriptor string: %s.", get_error_text (res));
867
+ return rb_str_new(c, res);
868
+ }
869
+
870
+ /*
871
+ * call-seq:
872
+ * device.getStringDescriptor(index, langid) -> desc
873
+ * device.stringDescriptor(index, langid) -> desc
874
+ *
875
+ * - +index+ is a +FixNum+ specifying the index of the descriptor string.
876
+ * - +langid+ is a +FixNum+ specifying the ID of the language to be retrieved
877
+ *
878
+ * Retrieve a descriptor string from the device.
879
+ *
880
+ * On success, returns the descriptor string of given index in given language (+String+), otherwise raises an exception and returns the _libusb_ error code (+FixNum+).
881
+ */
882
+ static VALUE cDevice_getStringDescriptor (VALUE self, VALUE index, VALUE langid)
883
+ {
884
+ struct device_t *d;
885
+ int res;
886
+ char c[256];
887
+
888
+ Data_Get_Struct (self, struct device_t, d);
889
+ if (d->handle == NULL) {
890
+ res = libusb_open (d->device, &(d->handle));
891
+ if (res < 0) {
892
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
893
+ return INT2NUM(res);
894
+ }
895
+ }
896
+ res = libusb_get_string_descriptor (d->handle, NUM2INT(index), NUM2INT(langid), (unsigned char *) c, sizeof (c));
897
+ if (res < 0)
898
+ rb_raise (rb_eRuntimeError, "Failed to retrieve descriptor string: %s.", get_error_text (res));
899
+ return rb_str_new(c, res);
900
+ }
901
+
902
+ /*
903
+ * call-seq:
904
+ * device.controlTransfer(args) -> count
905
+ * device.controlTransfer(args) -> data
906
+ * device.controlTransfer(args) {block} -> transfer
907
+ *
908
+ * Perform or prepare a control transfer.
909
+ *
910
+ * - +args+ is a +Hash+ containing all options, which are mandatory unless otherwise specified:
911
+ * * <tt>:bmRequestType</tt> is a +FixNum+ specifying the 8-bit request type field of the setup packet (note that the direction bit is ignored).
912
+ * * <tt>:bRequest</tt> is a +FixNum+ specifying the 8-bit request field of the setup packet.
913
+ * * <tt>:wValue</tt> is a +FixNum+ specifying the 16-bit value field of the setup packet.
914
+ * * <tt>:wIndex</tt> is a +FixNum+ specifying the 16-bit index field of the setup packet.
915
+ * * <tt>:dataIn</tt> is optional and either a +String+ or a +FixNum+, see below.
916
+ * * <tt>:dataOut</tt> is an optional +String+, see below.
917
+ * * <tt>:timeout</tt> is an optional +FixNum+ specifying the timeout for this transfer in milliseconds; default is 1000.
918
+ * - <tt>:dataIn</tt> and <tt>:dataOut</tt> are mutually exclusive but neither is mandatory.
919
+ * - The type and direction of the transfer is determined as follows:
920
+ * * If a block is passed, the transfer is asynchronous and the method returns immediately. Otherwise, the transfer is synchronous and the method returns when the transfer has completed or timed out.
921
+ * * If neither <tt>:dataIn</tt> nor <tt>:dataOut</tt> is specified, the transfer will only contain the setup packet but no data packet.
922
+ * * If <tt>:dataIn</tt> is a +Fixnum+, an +in+ transfer is started; its value must be between 1 and 64 and specifies the size of the data packet. A new +String+ is created for the data received if the transfer is successful.
923
+ * * If <tt>:dataIn</tt> is a +String+ and no block is present, an +in+ transfer is started; its size must be between 1 and 64 and specifies the size of the data packet; data received is stored in this +String+.
924
+ * * Specifying <tt>:dataIn</tt> as a +String+ while passing a block is invalid and results in an error.
925
+ * * If <tt>:dataOut</tt> is a +String+, an +out+ transfer is started; its size must be between 1 and 64 and specifies the size of the data packet; the contents of this +String+ are sent as the data packet.
926
+ * - If no block is passed, perform the transfer immediately and block until the transfer has completed or timed out, or until any other error occurs.
927
+ * - If a block is passed, prepare and return a RibUSB::Transfer without starting any USB transaction.
928
+ *
929
+ * On success, returns one of the following, otherwise raises an exception and returns +nil+ or the _libusb_ error code (+FixNum+):
930
+ * - a RibUSB::Transfer if the transfer is asynchronous;
931
+ * - <tt>0</tt> if neither <tt>:dataIn</tt> nor <tt>:dataOut</tt> is specified;
932
+ * - the number of bytes transferred if either <tt>:dataIn</tt> or <tt>:dataOut</tt> is a +String+;
933
+ * - a +String+ containing the data packet if <tt>:dataIn</tt> is a +Fixnum+.
934
+ */
935
+ static VALUE cDevice_controlTransfer (VALUE self, VALUE hash)
936
+ {
937
+ struct device_t *d;
938
+ uint8_t bmRequestType, bRequest;
939
+ uint16_t wValue, wIndex;
940
+ VALUE dataIn, dataOut;
941
+ unsigned char *data;
942
+ int foreign_data_in = 1;
943
+ uint16_t wLength;
944
+ unsigned int timeout;
945
+ VALUE v;
946
+ int res;
947
+ struct transfer_t *t;
948
+ VALUE object;
949
+
950
+ Data_Get_Struct (self, struct device_t, d);
951
+ if (d->handle == NULL) {
952
+ res = libusb_open (d->device, &(d->handle));
953
+ if (res < 0) {
954
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
955
+ return INT2NUM(res);
956
+ }
957
+ }
958
+
959
+ bmRequestType = NUM2INT(get_opt (hash, "bmRequestType", 1));
960
+ bRequest = NUM2INT(get_opt (hash, "bRequest", 1));
961
+ wValue = NUM2INT(get_opt (hash, "wValue", 1));
962
+ wIndex = NUM2INT(get_opt (hash, "wIndex", 1));
963
+ dataIn = get_opt (hash, "dataIn", 0);
964
+ dataOut = get_opt (hash, "dataOut", 0);
965
+
966
+ if ((!NIL_P(dataIn)) && (NIL_P(dataOut))) {
967
+ bmRequestType |= 0x80; /* in transfer */
968
+ switch (TYPE(dataIn)) {
969
+ case T_STRING:
970
+ if (rb_block_given_p ()) {
971
+ rb_raise (rb_eRuntimeError, "Invalid parameters to RibUSB::Device#controlTransfer: :dataIn must not be a String when a block is passed.");
972
+ return Qnil;
973
+ }
974
+ data = (unsigned char *) (RSTRING(dataIn)->ptr);
975
+ wLength = RSTRING(dataIn)->len;
976
+ foreign_data_in = 1;
977
+ break;
978
+ case T_FIXNUM:
979
+ wLength = NUM2INT(dataIn);
980
+ if (rb_block_given_p ()) {
981
+ data = NULL;
982
+ } else {
983
+ data = (unsigned char *) malloc (wLength);
984
+ if (!data)
985
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for data packet in RibUSB::Device#controlTransfer.");
986
+ }
987
+ foreign_data_in = 0;
988
+ break;
989
+ default:
990
+ rb_raise (rb_eRuntimeError, "Option :dataIn must be either a String or a Fixnum in RibUSB::Device#controlTransfer.");
991
+ break;
992
+ }
993
+ } else if ((NIL_P(dataIn)) && (!NIL_P(dataOut))) {
994
+ bmRequestType &= 0x7f; /* out transfer */
995
+ data = (unsigned char *) (RSTRING(dataOut)->ptr);
996
+ wLength = RSTRING(dataOut)->len;
997
+ } else if ((NIL_P(dataIn)) && (NIL_P(dataOut))) {
998
+ bmRequestType &= 0x7f; /* out transfer */
999
+ data = NULL;
1000
+ wLength = 0;
1001
+ } else
1002
+ rb_raise (rb_eRuntimeError, "Options :dataIn and :dataOut must not both be non-nil in RibUSB::Device#controlTransfer.");
1003
+
1004
+ v = get_opt (hash, "timeout", 0);
1005
+ if (NIL_P(v))
1006
+ timeout = 1000;
1007
+ else
1008
+ timeout = NUM2INT(v);
1009
+
1010
+ if (rb_block_given_p ()) {
1011
+ t = (struct transfer_t *) malloc (sizeof (struct transfer_t));
1012
+ if (!t) {
1013
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for RibUSB::Transfer object.");
1014
+ return Qnil;
1015
+ }
1016
+ t->proc = rb_block_proc ();
1017
+ t->transfer = libusb_alloc_transfer (0);
1018
+ if (!(t->transfer)) {
1019
+ rb_raise (rb_eRuntimeError, "Failed to allocate control transfer.");
1020
+ return Qnil;
1021
+ }
1022
+ t->buffer = (unsigned char *) malloc (LIBUSB_CONTROL_SETUP_SIZE + wLength);
1023
+ if (!(t->buffer)) {
1024
+ rb_raise (rb_eRuntimeError, "Failed to allocate data buffer for control transfer.");
1025
+ return Qnil;
1026
+ }
1027
+ libusb_fill_control_setup (t->buffer, bmRequestType, bRequest, wValue, wIndex, wLength);
1028
+ if (data) {
1029
+ memcpy(t->buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength);
1030
+ }
1031
+ object = Data_Wrap_Struct (Transfer, NULL, cTransfer_free, t);
1032
+ libusb_fill_control_transfer (t->transfer, d->handle, t->buffer, callback_wrapper, (void *) object, timeout);
1033
+
1034
+ rb_obj_call_init (object, 0, 0);
1035
+ return object;
1036
+ } else {
1037
+ res = libusb_control_transfer (d->handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout);
1038
+ if (res < 0) {
1039
+ rb_raise (rb_eRuntimeError, "Synchronous control transfer failed: %s.", get_error_text (res));
1040
+ return INT2NUM(res);
1041
+ }
1042
+ if (foreign_data_in)
1043
+ return INT2NUM(res);
1044
+ else {
1045
+ v = rb_str_new ((char *) data, wLength);
1046
+ free (data);
1047
+ return v;
1048
+ }
1049
+ }
1050
+ }
1051
+
1052
+ /*
1053
+ * call-seq:
1054
+ * device.bulkTransfer(args) -> count
1055
+ * device.bulkTransfer(args) -> data
1056
+ * device.bulkTransfer(args) {block} -> transfer
1057
+ *
1058
+ * Perform or prepare a bulk transfer.
1059
+ *
1060
+ * - +args+ is a +Hash+ containing all options, which are mandatory unless otherwise specified:
1061
+ * * <tt>:endpoint</tt> is a +FixNum+ specifying the USB endpoint (note that the direction bit is ignored).
1062
+ * * <tt>:dataIn</tt> is optional and either a +String+ or a +FixNum+, see below.
1063
+ * * <tt>:dataOut</tt> is an optional +String+, see below.
1064
+ * * <tt>:timeout</tt> is an optional +FixNum+ specifying the timeout for this transfer in milliseconds; default is 1000.
1065
+ * - Exactly one of <tt>:dataIn</tt> and <tt>:dataOut</tt> must be specified.
1066
+ * - The type and direction of the transfer is determined as follows:
1067
+ * * If a block is passed, the transfer is asynchronous and the method returns immediately. Otherwise, the transfer is synchronous and the method returns when the transfer has completed or timed out.
1068
+ * * If <tt>:dataIn</tt> is a +Fixnum+, an +in+ transfer is started; its value specifies the size of the data packet. A new +String+ is created for the data received if the transfer is successful.
1069
+ * * If <tt>:dataIn</tt> is a +String+ and no block is present, an +in+ transfer is started; its size specifies the size of the data packet; data received is stored in this +String+.
1070
+ * * Specifying <tt>:dataIn</tt> as a +String+ while passing a block is invalid and results in an error.
1071
+ * * If <tt>:dataOut</tt> is a +String+, an +out+ transfer is started; its size specifies the size of the data packet; the contents of this +String+ are sent as the data packet.
1072
+ * - If no block is passed, perform the transfer immediately and block until the transfer has completed or timed out, or until any other error occurs.
1073
+ * - If a block is passed, prepare and return a RibUSB::Transfer without starting any USB transaction.
1074
+ *
1075
+ * On success, returns one of the following, otherwise raises an exception and returns +nil+ or the _libusb_ error code (+FixNum+):
1076
+ * - a RibUSB::Transfer if the transfer is asynchronous;
1077
+ * - the number of bytes transferred if either <tt>:dataIn</tt> or <tt>:dataOut</tt> is a +String+;
1078
+ * - a +String+ containing the data packet if <tt>:dataIn</tt> is a +Fixnum+.
1079
+ */
1080
+ static VALUE cDevice_bulkTransfer (VALUE self, VALUE hash)
1081
+ {
1082
+ struct device_t *d;
1083
+ unsigned char endpoint;
1084
+ VALUE dataIn, dataOut;
1085
+ unsigned char *data;
1086
+ int foreign_data_in = 1;
1087
+ uint16_t wLength;
1088
+ unsigned int timeout;
1089
+ VALUE v;
1090
+ int res, transferred;
1091
+ struct transfer_t *t;
1092
+ VALUE object;
1093
+
1094
+ Data_Get_Struct (self, struct device_t, d);
1095
+ if (d->handle == NULL) {
1096
+ res = libusb_open (d->device, &(d->handle));
1097
+ if (res < 0) {
1098
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
1099
+ return INT2NUM(res);
1100
+ }
1101
+ }
1102
+
1103
+ endpoint = NUM2INT(get_opt (hash, "endpoint", 1));
1104
+ dataIn = get_opt (hash, "dataIn", 0);
1105
+ dataOut = get_opt (hash, "dataOut", 0);
1106
+
1107
+ if ((!NIL_P(dataIn)) && (NIL_P(dataOut))) {
1108
+ endpoint |= 0x80; /* in transfer */
1109
+ switch (TYPE(dataIn)) {
1110
+ case T_STRING:
1111
+ if (rb_block_given_p ()) {
1112
+ rb_raise (rb_eRuntimeError, "Invalid parameters to RibUSB::Device#bulkTransfer: :dataIn must not be a String when a block is passed.");
1113
+ return Qnil;
1114
+ }
1115
+ data = (unsigned char *) (RSTRING(dataIn)->ptr);
1116
+ wLength = RSTRING(dataIn)->len;
1117
+ foreign_data_in = 1;
1118
+ break;
1119
+ case T_FIXNUM:
1120
+ wLength = NUM2INT(dataIn);
1121
+ if (rb_block_given_p ()) {
1122
+ data = NULL;
1123
+ } else {
1124
+ data = (unsigned char *) malloc (wLength);
1125
+ if (!data)
1126
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for data packet in RibUSB::Device#bulkTransfer.");
1127
+ }
1128
+ foreign_data_in = 0;
1129
+ break;
1130
+ default:
1131
+ rb_raise (rb_eRuntimeError, "Option :dataIn must be either a String or a Fixnum in RibUSB::Device#bulkTransfer.");
1132
+ break;
1133
+ }
1134
+ } else if ((NIL_P(dataIn)) && (!NIL_P(dataOut))) {
1135
+ endpoint &= 0x7f; /* out transfer */
1136
+ data = (unsigned char *) (RSTRING(dataOut)->ptr);
1137
+ wLength = RSTRING(dataOut)->len;
1138
+ } else
1139
+ rb_raise (rb_eRuntimeError, "Exactly one of :dataIn and :dataOut must be non-nil in RibUSB::Device#bulkTransfer.");
1140
+
1141
+ v = get_opt (hash, "timeout", 0);
1142
+ if (NIL_P(v))
1143
+ timeout = 1000;
1144
+ else
1145
+ timeout = NUM2INT(v);
1146
+
1147
+ if (rb_block_given_p ()) {
1148
+ t = (struct transfer_t *) malloc (sizeof (struct transfer_t));
1149
+ if (!t) {
1150
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for RibUSB::Transfer object.");
1151
+ return Qnil;
1152
+ }
1153
+ t->proc = rb_block_proc ();
1154
+ t->transfer = libusb_alloc_transfer (0);
1155
+ if (!(t->transfer)) {
1156
+ rb_raise (rb_eRuntimeError, "Failed to allocate bulk transfer.");
1157
+ return Qnil;
1158
+ }
1159
+ t->buffer = (unsigned char *) malloc (wLength);
1160
+ if (!(t->buffer)) {
1161
+ rb_raise (rb_eRuntimeError, "Failed to allocate data buffer for bulk transfer.");
1162
+ return Qnil;
1163
+ }
1164
+ if (data) {
1165
+ memcpy(t->buffer, data, wLength); /* XXXXXX do we really need to copy the data? */
1166
+ }
1167
+ object = Data_Wrap_Struct (Transfer, NULL, cTransfer_free, t);
1168
+ libusb_fill_bulk_transfer (t->transfer, d->handle, endpoint, t->buffer, wLength, callback_wrapper, (void *) object, timeout);
1169
+
1170
+ rb_obj_call_init (object, 0, 0);
1171
+ return object;
1172
+ } else {
1173
+ res = libusb_bulk_transfer (d->handle, endpoint, data, wLength, &transferred, timeout);
1174
+ if (res < 0) {
1175
+ rb_raise (rb_eRuntimeError, "Synchronous bulk transfer failed: %s.", get_error_text (res));
1176
+ return INT2NUM(res);
1177
+ }
1178
+ if (foreign_data_in)
1179
+ return INT2NUM(transferred);
1180
+ else {
1181
+ v = rb_str_new ((char *) data, wLength);
1182
+ free (data);
1183
+ return v;
1184
+ }
1185
+ }
1186
+ }
1187
+
1188
+ /*
1189
+ * call-seq:
1190
+ * device.interruptTransfer(args) -> count
1191
+ * device.interruptTransfer(args) -> data
1192
+ * device.interruptTransfer(args) {block} -> transfer
1193
+ *
1194
+ * Perform or prepare a interrupt transfer.
1195
+ *
1196
+ * - +args+ is a +Hash+ containing all options, which are mandatory unless otherwise specified:
1197
+ * * <tt>:endpoint</tt> is a +FixNum+ specifying the USB endpoint (note that the direction bit is ignored).
1198
+ * * <tt>:dataIn</tt> is optional and either a +String+ or a +FixNum+, see below.
1199
+ * * <tt>:dataOut</tt> is an optional +String+, see below.
1200
+ * * <tt>:timeout</tt> is an optional +FixNum+ specifying the timeout for this transfer in milliseconds; default is 1000.
1201
+ * - Exactly one of <tt>:dataIn</tt> and <tt>:dataOut</tt> must be specified.
1202
+ * - The type and direction of the transfer is determined as follows:
1203
+ * * If a block is passed, the transfer is asynchronous and the method returns immediately. Otherwise, the transfer is synchronous and the method returns when the transfer has completed or timed out.
1204
+ * * If <tt>:dataIn</tt> is a +Fixnum+, an +in+ transfer is started; its value specifies the size of the data packet. A new +String+ is created for the data received if the transfer is successful.
1205
+ * * If <tt>:dataIn</tt> is a +String+ and no block is present, an +in+ transfer is started; its size specifies the size of the data packet; data received is stored in this +String+.
1206
+ * * Specifying <tt>:dataIn</tt> as a +String+ while passing a block is invalid and results in an error.
1207
+ * * If <tt>:dataOut</tt> is a +String+, an +out+ transfer is started; its size specifies the size of the data packet; the contents of this +String+ are sent as the data packet.
1208
+ * - If no block is passed, perform the transfer immediately and block until the transfer has completed or timed out, or until any other error occurs.
1209
+ * - If a block is passed, prepare and return a RibUSB::Transfer without starting any USB transaction.
1210
+ *
1211
+ * On success, returns one of the following, otherwise raises an exception and returns +nil+ or the _libusb_ error code (+FixNum+):
1212
+ * - a RibUSB::Transfer if the transfer is asynchronous;
1213
+ * - the number of bytes transferred if either <tt>:dataIn</tt> or <tt>:dataOut</tt> is a +String+;
1214
+ * - a +String+ containing the data packet if <tt>:dataIn</tt> is a +Fixnum+.
1215
+ */
1216
+ static VALUE cDevice_interruptTransfer (VALUE self, VALUE hash)
1217
+ {
1218
+ struct device_t *d;
1219
+ unsigned char endpoint;
1220
+ VALUE dataIn, dataOut;
1221
+ unsigned char *data;
1222
+ int foreign_data_in = 1;
1223
+ uint16_t wLength;
1224
+ unsigned int timeout;
1225
+ VALUE v;
1226
+ int res, transferred;
1227
+ struct transfer_t *t;
1228
+ VALUE object;
1229
+
1230
+ Data_Get_Struct (self, struct device_t, d);
1231
+ if (d->handle == NULL) {
1232
+ res = libusb_open (d->device, &(d->handle));
1233
+ if (res < 0) {
1234
+ rb_raise (rb_eRuntimeError, "Failed to open USB device: %s.", get_error_text (res));
1235
+ return INT2NUM(res);
1236
+ }
1237
+ }
1238
+
1239
+ endpoint = NUM2INT(get_opt (hash, "endpoint", 1));
1240
+ dataIn = get_opt (hash, "dataIn", 0);
1241
+ dataOut = get_opt (hash, "dataOut", 0);
1242
+
1243
+ if ((!NIL_P(dataIn)) && (NIL_P(dataOut))) {
1244
+ endpoint |= 0x80; /* in transfer */
1245
+ switch (TYPE(dataIn)) {
1246
+ case T_STRING:
1247
+ if (rb_block_given_p ()) {
1248
+ rb_raise (rb_eRuntimeError, "Invalid parameters to RibUSB::Device#interruptTransfer: :dataIn must not be a String when a block is passed.");
1249
+ return Qnil;
1250
+ }
1251
+ data = (unsigned char *) (RSTRING(dataIn)->ptr);
1252
+ wLength = RSTRING(dataIn)->len;
1253
+ foreign_data_in = 1;
1254
+ break;
1255
+ case T_FIXNUM:
1256
+ wLength = NUM2INT(dataIn);
1257
+ if (rb_block_given_p ()) {
1258
+ data = NULL;
1259
+ } else {
1260
+ data = (unsigned char *) malloc (wLength);
1261
+ if (!data)
1262
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for data packet in RibUSB::Device#interruptTransfer.");
1263
+ }
1264
+ foreign_data_in = 0;
1265
+ break;
1266
+ default:
1267
+ rb_raise (rb_eRuntimeError, "Option :dataIn must be either a String or a Fixnum in RibUSB::Device#interruptTransfer.");
1268
+ break;
1269
+ }
1270
+ } else if ((NIL_P(dataIn)) && (!NIL_P(dataOut))) {
1271
+ endpoint &= 0x7f; /* out transfer */
1272
+ data = (unsigned char *) (RSTRING(dataOut)->ptr);
1273
+ wLength = RSTRING(dataOut)->len;
1274
+ } else
1275
+ rb_raise (rb_eRuntimeError, "Exactly one of :dataIn and :dataOut must be non-nil in RibUSB::Device#interruptTransfer.");
1276
+
1277
+ v = get_opt (hash, "timeout", 0);
1278
+ if (NIL_P(v))
1279
+ timeout = 1000;
1280
+ else
1281
+ timeout = NUM2INT(v);
1282
+
1283
+ if (rb_block_given_p ()) {
1284
+ t = (struct transfer_t *) malloc (sizeof (struct transfer_t));
1285
+ if (!t) {
1286
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for RibUSB::Transfer object.");
1287
+ return Qnil;
1288
+ }
1289
+ t->proc = rb_block_proc ();
1290
+ t->transfer = libusb_alloc_transfer (0);
1291
+ if (!(t->transfer)) {
1292
+ rb_raise (rb_eRuntimeError, "Failed to allocate interrupt transfer.");
1293
+ return Qnil;
1294
+ }
1295
+ t->buffer = (unsigned char *) malloc (wLength);
1296
+ if (!(t->buffer)) {
1297
+ rb_raise (rb_eRuntimeError, "Failed to allocate data buffer for interrupt transfer.");
1298
+ return Qnil;
1299
+ }
1300
+ if (data) {
1301
+ memcpy(t->buffer, data, wLength); /* XXXXXX do we really need to copy the data? */
1302
+ }
1303
+ object = Data_Wrap_Struct (Transfer, NULL, cTransfer_free, t);
1304
+ libusb_fill_interrupt_transfer (t->transfer, d->handle, endpoint, t->buffer, wLength, callback_wrapper, (void *) object, timeout);
1305
+
1306
+ rb_obj_call_init (object, 0, 0);
1307
+ return object;
1308
+ } else {
1309
+ res = libusb_interrupt_transfer (d->handle, endpoint, data, wLength, &transferred, timeout);
1310
+ if (res < 0) {
1311
+ rb_raise (rb_eRuntimeError, "Synchronous interrupt transfer failed: %s.", get_error_text (res));
1312
+ return INT2NUM(res);
1313
+ }
1314
+ if (foreign_data_in)
1315
+ return INT2NUM(transferred);
1316
+ else {
1317
+ v = rb_str_new ((char *) data, wLength);
1318
+ free (data);
1319
+ return v;
1320
+ }
1321
+ }
1322
+ }
1323
+
1324
+ /*
1325
+ * call-seq:
1326
+ * device.bcdUSB -> bcdUSB
1327
+ *
1328
+ * Get the USB specification release number in binary-coded decimal.
1329
+ *
1330
+ * Returns a +FixNum+ and never raises an exception.
1331
+ */
1332
+ static VALUE cDevice_bcdUSB (VALUE self)
1333
+ {
1334
+ struct device_t *d;
1335
+
1336
+ Data_Get_Struct (self, struct device_t, d);
1337
+ return INT2NUM(d->descriptor->bcdUSB);
1338
+ }
1339
+
1340
+ /*
1341
+ * call-seq:
1342
+ * device.bDeviceClass -> bDeviceClass
1343
+ *
1344
+ * Get the USB class code.
1345
+ *
1346
+ * Returns a +FixNum+ and never raises an exception.
1347
+ */
1348
+ static VALUE cDevice_bDeviceClass (VALUE self)
1349
+ {
1350
+ struct device_t *d;
1351
+
1352
+ Data_Get_Struct (self, struct device_t, d);
1353
+ return INT2NUM(d->descriptor->bDeviceClass);
1354
+ }
1355
+
1356
+ /*
1357
+ * call-seq:
1358
+ * device.bDeviceSubClass -> bDeviceSubClass
1359
+ *
1360
+ * Get the USB subclass code.
1361
+ *
1362
+ * Returns a +FixNum+ and never raises an exception.
1363
+ */
1364
+ static VALUE cDevice_bDeviceSubClass (VALUE self)
1365
+ {
1366
+ struct device_t *d;
1367
+
1368
+ Data_Get_Struct (self, struct device_t, d);
1369
+ return INT2NUM(d->descriptor->bDeviceSubClass);
1370
+ }
1371
+
1372
+ /*
1373
+ * call-seq:
1374
+ * device.bDeviceProtocol -> bDeviceProtocol
1375
+ *
1376
+ * Get the USB protocol code.
1377
+ *
1378
+ * Returns a +FixNum+ and never raises an exception.
1379
+ */
1380
+ static VALUE cDevice_bDeviceProtocol (VALUE self)
1381
+ {
1382
+ struct device_t *d;
1383
+
1384
+ Data_Get_Struct (self, struct device_t, d);
1385
+ return INT2NUM(d->descriptor->bDeviceProtocol);
1386
+ }
1387
+
1388
+ /*
1389
+ * call-seq:
1390
+ * device.bMaxPacketSize0 -> bMaxPacketSize0
1391
+ *
1392
+ * Get the maximum packet size for endpoint 0.
1393
+ *
1394
+ * Returns a +FixNum+ and never raises an exception.
1395
+ */
1396
+ static VALUE cDevice_bMaxPacketSize0 (VALUE self)
1397
+ {
1398
+ struct device_t *d;
1399
+
1400
+ Data_Get_Struct (self, struct device_t, d);
1401
+ return INT2NUM(d->descriptor->bMaxPacketSize0);
1402
+ }
1403
+
1404
+ /*
1405
+ * call-seq:
1406
+ * device.idVendor -> idVendor
1407
+ *
1408
+ * Get the vendor ID.
1409
+ *
1410
+ * Returns a +FixNum+ and never raises an exception.
1411
+ */
1412
+ static VALUE cDevice_idVendor (VALUE self)
1413
+ {
1414
+ struct device_t *d;
1415
+
1416
+ Data_Get_Struct (self, struct device_t, d);
1417
+ return INT2NUM(d->descriptor->idVendor);
1418
+ }
1419
+
1420
+ /*
1421
+ * call-seq:
1422
+ * device.idProduct -> idProduct
1423
+ *
1424
+ * Get the product ID.
1425
+ *
1426
+ * Returns a +FixNum+ and never raises an exception.
1427
+ */
1428
+ static VALUE cDevice_idProduct (VALUE self)
1429
+ {
1430
+ struct device_t *d;
1431
+
1432
+ Data_Get_Struct (self, struct device_t, d);
1433
+ return INT2NUM(d->descriptor->idProduct);
1434
+ }
1435
+
1436
+ /*
1437
+ * call-seq:
1438
+ * device.bcdDevice -> bcdDevice
1439
+ *
1440
+ * Get the device release number in binary-coded decimal.
1441
+ *
1442
+ * Returns a +FixNum+ and never raises an exception.
1443
+ */
1444
+ static VALUE cDevice_bcdDevice (VALUE self)
1445
+ {
1446
+ struct device_t *d;
1447
+
1448
+ Data_Get_Struct (self, struct device_t, d);
1449
+ return INT2NUM(d->descriptor->bcdDevice);
1450
+ }
1451
+
1452
+ /*
1453
+ * call-seq:
1454
+ * device.iManufacturer -> iManufacturer
1455
+ *
1456
+ * Get the index of the manufacturer string.
1457
+ *
1458
+ * Returns a +FixNum+ and never raises an exception.
1459
+ */
1460
+ static VALUE cDevice_iManufacturer (VALUE self)
1461
+ {
1462
+ struct device_t *d;
1463
+
1464
+ Data_Get_Struct (self, struct device_t, d);
1465
+ return INT2NUM(d->descriptor->iManufacturer);
1466
+ }
1467
+
1468
+ /*
1469
+ * call-seq:
1470
+ * device.iProduct -> iProduct
1471
+ *
1472
+ * Get the index of the product string.
1473
+ *
1474
+ * Returns a +FixNum+ and never raises an exception.
1475
+ */
1476
+ static VALUE cDevice_iProduct (VALUE self)
1477
+ {
1478
+ struct device_t *d;
1479
+
1480
+ Data_Get_Struct (self, struct device_t, d);
1481
+ return INT2NUM(d->descriptor->iProduct);
1482
+ }
1483
+
1484
+ /*
1485
+ * call-seq:
1486
+ * device.iSerialNumber -> iSerialNumber
1487
+ *
1488
+ * Get the index of the serial number string.
1489
+ *
1490
+ * Returns a +FixNum+ and never raises an exception.
1491
+ */
1492
+ static VALUE cDevice_iSerialNumber (VALUE self)
1493
+ {
1494
+ struct device_t *d;
1495
+
1496
+ Data_Get_Struct (self, struct device_t, d);
1497
+ return INT2NUM(d->descriptor->iSerialNumber);
1498
+ }
1499
+
1500
+ /*
1501
+ * call-seq:
1502
+ * device.bNumConfigurations -> bNumConfigurations
1503
+ *
1504
+ * Get the number of configurations of the device.
1505
+ *
1506
+ * Returns a +FixNum+ and never raises an exception.
1507
+ */
1508
+ static VALUE cDevice_bNumConfigurations (VALUE self)
1509
+ {
1510
+ struct device_t *d;
1511
+
1512
+ Data_Get_Struct (self, struct device_t, d);
1513
+ return INT2NUM(d->descriptor->bNumConfigurations);
1514
+ }
1515
+
1516
+
1517
+
1518
+ /******************************************************
1519
+ * RibUSB::Transfer method definitions *
1520
+ ******************************************************/
1521
+
1522
+ void cTransfer_free (struct transfer_t *t)
1523
+ {
1524
+ libusb_free_transfer (t->transfer);
1525
+ free (t->buffer);
1526
+ free (t);
1527
+ }
1528
+
1529
+ /*
1530
+ * call-seq:
1531
+ * transfer.submit -> nil
1532
+ *
1533
+ * Submit the asynchronous transfer.
1534
+ *
1535
+ * On success, returns +nil+, otherwise raises an exception and returns the _libusb_ error code (+FixNum+).
1536
+ */
1537
+ static VALUE cTransfer_submit (VALUE self)
1538
+ {
1539
+ struct transfer_t *t;
1540
+ int res;
1541
+
1542
+ Data_Get_Struct (self, struct transfer_t, t);
1543
+ res = libusb_submit_transfer (t->transfer);
1544
+ if (res) {
1545
+ rb_raise (rb_eRuntimeError, "Failed to submit asynchronous transfer: %s.", get_error_text (res));
1546
+ return INT2NUM(res);
1547
+ } else
1548
+ return Qnil;
1549
+ }
1550
+
1551
+ /*
1552
+ * call-seq:
1553
+ * transfer.cancel -> nil
1554
+ *
1555
+ * Cancel the asynchronous transfer.
1556
+ *
1557
+ * On success, returns +nil+, otherwise raises an exception and returns the _libusb_ error code (+FixNum+).
1558
+ */
1559
+ static VALUE cTransfer_cancel (VALUE self)
1560
+ {
1561
+ struct transfer_t *t;
1562
+ int res;
1563
+
1564
+ Data_Get_Struct (self, struct transfer_t, t);
1565
+ res = libusb_cancel_transfer (t->transfer);
1566
+ if (res) {
1567
+ rb_raise (rb_eRuntimeError, "Failed to cancel asynchronous transfer: %s.", get_error_text (res));
1568
+ return INT2NUM(res);
1569
+ } else
1570
+ return Qnil;
1571
+ }
1572
+
1573
+ /*
1574
+ * call-seq:
1575
+ * transfer.status -> status
1576
+ *
1577
+ * Retrieve the status of the asynchronous transfer.
1578
+ *
1579
+ * XXX describe status
1580
+ *
1581
+ * Use outside of an asynchronous transfer callback block leads to undefined behaviour.
1582
+ *
1583
+ * Returns a +Symbol+ and never raises an exception.
1584
+ */
1585
+ static VALUE cTransfer_status (VALUE self)
1586
+ {
1587
+ struct transfer_t *t;
1588
+
1589
+ Data_Get_Struct (self, struct transfer_t, t);
1590
+ switch (t->transfer->status) {
1591
+ case LIBUSB_TRANSFER_COMPLETED:
1592
+ return ID2SYM(rb_intern (":completed"));
1593
+ break;
1594
+ case LIBUSB_TRANSFER_ERROR:
1595
+ return ID2SYM(rb_intern (":error"));
1596
+ break;
1597
+ case LIBUSB_TRANSFER_TIMED_OUT:
1598
+ return ID2SYM(rb_intern (":timed_out"));
1599
+ break;
1600
+ case LIBUSB_TRANSFER_CANCELLED:
1601
+ return ID2SYM(rb_intern (":cancelled"));
1602
+ break;
1603
+ case LIBUSB_TRANSFER_STALL:
1604
+ return ID2SYM(rb_intern (":stall"));
1605
+ break;
1606
+ case LIBUSB_TRANSFER_NO_DEVICE:
1607
+ return ID2SYM(rb_intern (":no_device"));
1608
+ break;
1609
+ case LIBUSB_TRANSFER_OVERFLOW:
1610
+ return ID2SYM(rb_intern (":overflow"));
1611
+ break;
1612
+ default:
1613
+ rb_raise (rb_eRuntimeError, "Invalid transfer status: %i.", t->transfer->status);
1614
+ break;
1615
+ }
1616
+ }
1617
+
1618
+
1619
+
1620
+ /******************************************************
1621
+ * RibUSB::ConfigDescriptor method definitions *
1622
+ ******************************************************/
1623
+
1624
+ void cConfigDescriptor_free (struct config_descriptor_t *c)
1625
+ {
1626
+ libusb_free_config_descriptor (c->descriptor);
1627
+
1628
+ free (c);
1629
+ }
1630
+
1631
+ static VALUE cConfigDescriptor_new (struct libusb_config_descriptor *descriptor)
1632
+ {
1633
+ struct config_descriptor_t *d;
1634
+ VALUE object;
1635
+
1636
+ d = (struct config_descriptor_t *) malloc (sizeof (struct config_descriptor_t));
1637
+ if (!d) {
1638
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for RibUSB::ConfigDescriptor object.");
1639
+ return Qnil;
1640
+ }
1641
+ d->descriptor = descriptor;
1642
+ object = Data_Wrap_Struct (ConfigDescriptor, NULL, cConfigDescriptor_free, d);
1643
+ rb_obj_call_init (object, 0, 0);
1644
+ return object;
1645
+ }
1646
+
1647
+ /*
1648
+ * call-seq:
1649
+ * descriptor.bLength -> bLength
1650
+ *
1651
+ * Get the size in bytes of the descriptor.
1652
+ *
1653
+ * Returns a +FixNum+ and never raises an exception.
1654
+ */
1655
+ static VALUE cConfigDescriptor_bLength (VALUE self)
1656
+ {
1657
+ struct config_descriptor_t *d;
1658
+
1659
+ Data_Get_Struct (self, struct config_descriptor_t, d);
1660
+ return INT2NUM(d->descriptor->bLength);
1661
+ }
1662
+
1663
+ /*
1664
+ * call-seq:
1665
+ * descriptor.bDescriptorType -> bDescriptorType
1666
+ *
1667
+ * Get the type of the descriptor.
1668
+ *
1669
+ * Returns a +FixNum+ and never raises an exception.
1670
+ */
1671
+ static VALUE cConfigDescriptor_bDescriptorType (VALUE self)
1672
+ {
1673
+ struct config_descriptor_t *d;
1674
+
1675
+ Data_Get_Struct (self, struct config_descriptor_t, d);
1676
+ return INT2NUM(d->descriptor->bDescriptorType);
1677
+ }
1678
+
1679
+ /*
1680
+ * call-seq:
1681
+ * descriptor.wTotalLength -> wTotalLength
1682
+ *
1683
+ * Get the total length of the data of this configuration.
1684
+ *
1685
+ * Returns a +FixNum+ and never raises an exception.
1686
+ */
1687
+ static VALUE cConfigDescriptor_wTotalLength (VALUE self)
1688
+ {
1689
+ struct config_descriptor_t *d;
1690
+
1691
+ Data_Get_Struct (self, struct config_descriptor_t, d);
1692
+ return INT2NUM(d->descriptor->wTotalLength);
1693
+ }
1694
+
1695
+ /*
1696
+ * call-seq:
1697
+ * descriptor.bNumInterfaces -> bNumInterfaces
1698
+ *
1699
+ * Get the number of interfaces available in this configuration.
1700
+ *
1701
+ * Returns a +FixNum+ and never raises an exception.
1702
+ */
1703
+ static VALUE cConfigDescriptor_bNumInterfaces (VALUE self)
1704
+ {
1705
+ struct config_descriptor_t *d;
1706
+
1707
+ Data_Get_Struct (self, struct config_descriptor_t, d);
1708
+ return INT2NUM(d->descriptor->bNumInterfaces);
1709
+ }
1710
+
1711
+ /*
1712
+ * call-seq:
1713
+ * descriptor.bConfigurationValue -> bConfigurationValue
1714
+ *
1715
+ * Get the configuration number.
1716
+ *
1717
+ * Returns a +FixNum+ and never raises an exception.
1718
+ */
1719
+ static VALUE cConfigDescriptor_bConfigurationValue (VALUE self)
1720
+ {
1721
+ struct config_descriptor_t *d;
1722
+
1723
+ Data_Get_Struct (self, struct config_descriptor_t, d);
1724
+ return INT2NUM(d->descriptor->bConfigurationValue);
1725
+ }
1726
+
1727
+ /*
1728
+ * call-seq:
1729
+ * descriptor.iConfiguration -> iConfiguration
1730
+ *
1731
+ * Get the index of the configuration string.
1732
+ *
1733
+ * Returns a +FixNum+ and never raises an exception.
1734
+ */
1735
+ static VALUE cConfigDescriptor_iConfiguration (VALUE self)
1736
+ {
1737
+ struct config_descriptor_t *d;
1738
+
1739
+ Data_Get_Struct (self, struct config_descriptor_t, d);
1740
+ return INT2NUM(d->descriptor->iConfiguration);
1741
+ }
1742
+
1743
+ /*
1744
+ * call-seq:
1745
+ * descriptor.bmAttributes -> bmAttributes
1746
+ *
1747
+ * Get the configuration characteristics.
1748
+ *
1749
+ * Returns a +FixNum+ and never raises an exception.
1750
+ */
1751
+ static VALUE cConfigDescriptor_bmAttributes (VALUE self)
1752
+ {
1753
+ struct config_descriptor_t *d;
1754
+
1755
+ Data_Get_Struct (self, struct config_descriptor_t, d);
1756
+ return INT2NUM(d->descriptor->bmAttributes);
1757
+ }
1758
+
1759
+ /*
1760
+ * call-seq:
1761
+ * descriptor.maxPower -> maxPower
1762
+ *
1763
+ * Get the maximum current drawn by the device in this configuration, in units of 2mA.
1764
+ *
1765
+ * Returns a +FixNum+ and never raises an exception.
1766
+ */
1767
+ static VALUE cConfigDescriptor_maxPower (VALUE self)
1768
+ {
1769
+ struct config_descriptor_t *d;
1770
+
1771
+ Data_Get_Struct (self, struct config_descriptor_t, d);
1772
+ return INT2NUM(d->descriptor->MaxPower);
1773
+ }
1774
+
1775
+ /*
1776
+ * call-seq:
1777
+ * descriptor.interfaceList -> interfaceList
1778
+ *
1779
+ * Retrieve the list of interfaces in this configuration.
1780
+ *
1781
+ * Returns an array of +RibUSB::Interface+ and never raises an exception.
1782
+ */
1783
+ static VALUE cConfigDescriptor_interfaceList (VALUE self)
1784
+ {
1785
+ struct config_descriptor_t *d;
1786
+ VALUE array;
1787
+ int n_array, i;
1788
+
1789
+ Data_Get_Struct (self, struct config_descriptor_t, d);
1790
+
1791
+ n_array = d->descriptor->bNumInterfaces;
1792
+ array = rb_ary_new2 (n_array);
1793
+
1794
+ for (i = 0; i < n_array; i ++)
1795
+ rb_ary_store (array, i, cInterface_new (&(((struct libusb_interface *)d->descriptor->interface)[i])));
1796
+
1797
+ return array;
1798
+ }
1799
+
1800
+ /*
1801
+ * call-seq:
1802
+ * descriptor.extra -> extra
1803
+ *
1804
+ * Get the extra descriptors defined by this configuration, as a string.
1805
+ *
1806
+ * Returns a +String+ and never raises an exception.
1807
+ */
1808
+ static VALUE cConfigDescriptor_extra (VALUE self)
1809
+ {
1810
+ struct config_descriptor_t *d;
1811
+
1812
+ Data_Get_Struct (self, struct config_descriptor_t, d);
1813
+ return rb_str_new((char *) d->descriptor->extra, d->descriptor->extra_length);
1814
+ }
1815
+
1816
+
1817
+
1818
+ /******************************************************
1819
+ * RibUSB::Interface method definitions *
1820
+ ******************************************************/
1821
+
1822
+ static VALUE cInterface_new (struct libusb_interface *interface)
1823
+ {
1824
+ struct interface_t *i;
1825
+ VALUE object;
1826
+
1827
+ i = (struct interface_t *) malloc (sizeof (struct interface_t));
1828
+ if (!i) {
1829
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for RibUSB::Interface object.");
1830
+ return Qnil;
1831
+ }
1832
+ i->interface = interface;
1833
+ object = Data_Wrap_Struct (Interface, NULL, free, i);
1834
+ rb_obj_call_init (object, 0, 0);
1835
+ return object;
1836
+ }
1837
+
1838
+ /*
1839
+ * call-seq:
1840
+ * interface.altSettingList -> altSettingList
1841
+ *
1842
+ * Retrieve the list of interface descriptors.
1843
+ *
1844
+ * Returns an array of +RibUSB::Interface+ and never raises an exception.
1845
+ */
1846
+ static VALUE cInterface_altSettingList (VALUE self)
1847
+ {
1848
+ struct interface_t *d;
1849
+ VALUE array;
1850
+ int n_array, i;
1851
+
1852
+ Data_Get_Struct (self, struct interface_t, d);
1853
+
1854
+ n_array = d->interface->num_altsetting;
1855
+ array = rb_ary_new2 (n_array);
1856
+
1857
+ for (i = 0; i < n_array; i ++)
1858
+ rb_ary_store (array, i, cInterfaceDescriptor_new (&(((struct libusb_interface_descriptor *)d->interface->altsetting)[i])));
1859
+
1860
+ return array;
1861
+ }
1862
+
1863
+
1864
+
1865
+ /******************************************************
1866
+ * RibUSB::InterfaceDescriptor method definitions *
1867
+ ******************************************************/
1868
+
1869
+ static VALUE cInterfaceDescriptor_new (struct libusb_interface_descriptor *descriptor)
1870
+ {
1871
+ struct interface_descriptor_t *d;
1872
+ VALUE object;
1873
+
1874
+ d = (struct interface_descriptor_t *) malloc (sizeof (struct interface_descriptor_t));
1875
+ if (!d) {
1876
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for RibUSB::InterfaceDescriptor object.");
1877
+ return Qnil;
1878
+ }
1879
+ d->descriptor = descriptor;
1880
+ object = Data_Wrap_Struct (InterfaceDescriptor, NULL, free, d);
1881
+ rb_obj_call_init (object, 0, 0);
1882
+ return object;
1883
+ }
1884
+
1885
+ /*
1886
+ * call-seq:
1887
+ * descriptor.bLength -> bLength
1888
+ *
1889
+ * Get the size in bytes of the descriptor.
1890
+ *
1891
+ * Returns a +FixNum+ and never raises an exception.
1892
+ */
1893
+ static VALUE cInterfaceDescriptor_bLength (VALUE self)
1894
+ {
1895
+ struct interface_descriptor_t *d;
1896
+
1897
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
1898
+ return INT2NUM(d->descriptor->bLength);
1899
+ }
1900
+
1901
+ /*
1902
+ * call-seq:
1903
+ * descriptor.bDescriptorType -> bDescriptorType
1904
+ *
1905
+ * Get the type of the descriptor.
1906
+ *
1907
+ * Returns a +FixNum+ and never raises an exception.
1908
+ */
1909
+ static VALUE cInterfaceDescriptor_bDescriptorType (VALUE self)
1910
+ {
1911
+ struct interface_descriptor_t *d;
1912
+
1913
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
1914
+ return INT2NUM(d->descriptor->bDescriptorType);
1915
+ }
1916
+
1917
+ /*
1918
+ * call-seq:
1919
+ * descriptor.bInterfaceNumber -> bInterfaceNumber
1920
+ *
1921
+ * Get the interface number.
1922
+ *
1923
+ * Returns a +FixNum+ and never raises an exception.
1924
+ */
1925
+ static VALUE cInterfaceDescriptor_bInterfaceNumber (VALUE self)
1926
+ {
1927
+ struct interface_descriptor_t *d;
1928
+
1929
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
1930
+ return INT2NUM(d->descriptor->bInterfaceNumber);
1931
+ }
1932
+
1933
+ /*
1934
+ * call-seq:
1935
+ * descriptor.bAlternateSetting -> bAlternateSetting
1936
+ *
1937
+ * Get the number of the active alternate setting.
1938
+ *
1939
+ * Returns a +FixNum+ and never raises an exception.
1940
+ */
1941
+ static VALUE cInterfaceDescriptor_bAlternateSetting (VALUE self)
1942
+ {
1943
+ struct interface_descriptor_t *d;
1944
+
1945
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
1946
+ return INT2NUM(d->descriptor->bAlternateSetting);
1947
+ }
1948
+
1949
+ /*
1950
+ * call-seq:
1951
+ * descriptor.bNumEndpoints -> bNumEndpoints
1952
+ *
1953
+ * Get the number of endpoints available in this interface.
1954
+ *
1955
+ * Returns a +FixNum+ and never raises an exception.
1956
+ */
1957
+ static VALUE cInterfaceDescriptor_bNumEndpoints (VALUE self)
1958
+ {
1959
+ struct interface_descriptor_t *d;
1960
+
1961
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
1962
+ return INT2NUM(d->descriptor->bNumEndpoints);
1963
+ }
1964
+
1965
+ /*
1966
+ * call-seq:
1967
+ * descriptor.bInterfaceClass -> bInterfaceClass
1968
+ *
1969
+ * Get the interface class code.
1970
+ *
1971
+ * Returns a +FixNum+ and never raises an exception.
1972
+ */
1973
+ static VALUE cInterfaceDescriptor_bInterfaceClass (VALUE self)
1974
+ {
1975
+ struct interface_descriptor_t *d;
1976
+
1977
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
1978
+ return INT2NUM(d->descriptor->bInterfaceClass);
1979
+ }
1980
+
1981
+ /*
1982
+ * call-seq:
1983
+ * descriptor.bInterfaceSubClass -> bInterfaceSubClass
1984
+ *
1985
+ * Get the interface subclass code.
1986
+ *
1987
+ * Returns a +FixNum+ and never raises an exception.
1988
+ */
1989
+ static VALUE cInterfaceDescriptor_bInterfaceSubClass (VALUE self)
1990
+ {
1991
+ struct interface_descriptor_t *d;
1992
+
1993
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
1994
+ return INT2NUM(d->descriptor->bInterfaceSubClass);
1995
+ }
1996
+
1997
+ /*
1998
+ * call-seq:
1999
+ * descriptor.bInterfaceProtocol -> bInterfaceProtocol
2000
+ *
2001
+ * Get the interface protocol code.
2002
+ *
2003
+ * Returns a +FixNum+ and never raises an exception.
2004
+ */
2005
+ static VALUE cInterfaceDescriptor_bInterfaceProtocol (VALUE self)
2006
+ {
2007
+ struct interface_descriptor_t *d;
2008
+
2009
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
2010
+ return INT2NUM(d->descriptor->bInterfaceProtocol);
2011
+ }
2012
+
2013
+ /*
2014
+ * call-seq:
2015
+ * descriptor.iInterface -> iInterface
2016
+ *
2017
+ * Get the index of interface string.
2018
+ *
2019
+ * Returns a +FixNum+ and never raises an exception.
2020
+ */
2021
+ static VALUE cInterfaceDescriptor_iInterface (VALUE self)
2022
+ {
2023
+ struct interface_descriptor_t *d;
2024
+
2025
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
2026
+ return INT2NUM(d->descriptor->iInterface);
2027
+ }
2028
+
2029
+ /*
2030
+ * call-seq:
2031
+ * descriptor.endpointList -> endpointList
2032
+ *
2033
+ * Retrieve the list of endpoints in this interface.
2034
+ *
2035
+ * Returns an array of +RibUSB::Endpoint+ and never raises an exception.
2036
+ */
2037
+ static VALUE cInterfaceDescriptor_endpointList (VALUE self)
2038
+ {
2039
+ struct interface_descriptor_t *d;
2040
+ VALUE array;
2041
+ int n_array, i;
2042
+
2043
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
2044
+
2045
+ n_array = d->descriptor->bNumEndpoints;
2046
+ array = rb_ary_new2 (n_array);
2047
+
2048
+ for (i = 0; i < n_array; i ++)
2049
+ rb_ary_store (array, i, cEndpointDescriptor_new (&(((struct libusb_endpoint_descriptor *)d->descriptor->endpoint)[i])));
2050
+
2051
+ return array;
2052
+ }
2053
+
2054
+ /*
2055
+ * call-seq:
2056
+ * descriptor.extra -> extra
2057
+ *
2058
+ * Get the extra descriptors defined by this interface, as a string.
2059
+ *
2060
+ * Returns a +String+ and never raises an exception.
2061
+ */
2062
+ static VALUE cInterfaceDescriptor_extra (VALUE self)
2063
+ {
2064
+ struct interface_descriptor_t *d;
2065
+
2066
+ Data_Get_Struct (self, struct interface_descriptor_t, d);
2067
+ return rb_str_new((char *) d->descriptor->extra, d->descriptor->extra_length);
2068
+ }
2069
+
2070
+
2071
+
2072
+ /******************************************************
2073
+ * RibUSB::EndpointDescriptor method definitions *
2074
+ ******************************************************/
2075
+
2076
+ static VALUE cEndpointDescriptor_new (struct libusb_endpoint_descriptor *descriptor)
2077
+ {
2078
+ struct endpoint_descriptor_t *d;
2079
+ VALUE object;
2080
+
2081
+ d = (struct endpoint_descriptor_t *) malloc (sizeof (struct endpoint_descriptor_t));
2082
+ if (!d) {
2083
+ rb_raise (rb_eRuntimeError, "Failed to allocate memory for RibUSB::EndpointDescriptor object.");
2084
+ return Qnil;
2085
+ }
2086
+ d->descriptor = descriptor;
2087
+ object = Data_Wrap_Struct (EndpointDescriptor, NULL, free, d);
2088
+ rb_obj_call_init (object, 0, 0);
2089
+ return object;
2090
+ }
2091
+
2092
+ /*
2093
+ * call-seq:
2094
+ * descriptor.bLength -> bLength
2095
+ *
2096
+ * Get the size in bytes of the descriptor.
2097
+ *
2098
+ * Returns a +FixNum+ and never raises an exception.
2099
+ */
2100
+ static VALUE cEndpointDescriptor_bLength (VALUE self)
2101
+ {
2102
+ struct endpoint_descriptor_t *d;
2103
+
2104
+ Data_Get_Struct (self, struct endpoint_descriptor_t, d);
2105
+ return INT2NUM(d->descriptor->bLength);
2106
+ }
2107
+
2108
+ /*
2109
+ * call-seq:
2110
+ * descriptor.bDescriptorType -> bDescriptorType
2111
+ *
2112
+ * Get the type of the descriptor.
2113
+ *
2114
+ * Returns a +FixNum+ and never raises an exception.
2115
+ */
2116
+ static VALUE cEndpointDescriptor_bDescriptorType (VALUE self)
2117
+ {
2118
+ struct endpoint_descriptor_t *d;
2119
+
2120
+ Data_Get_Struct (self, struct endpoint_descriptor_t, d);
2121
+ return INT2NUM(d->descriptor->bDescriptorType);
2122
+ }
2123
+
2124
+ /*
2125
+ * call-seq:
2126
+ * descriptor.bEndpointAddress -> bEndpointAddress
2127
+ *
2128
+ * Get the endpoint address.
2129
+ *
2130
+ * Returns a +FixNum+ and never raises an exception.
2131
+ */
2132
+ static VALUE cEndpointDescriptor_bEndpointAddress (VALUE self)
2133
+ {
2134
+ struct endpoint_descriptor_t *d;
2135
+
2136
+ Data_Get_Struct (self, struct endpoint_descriptor_t, d);
2137
+ return INT2NUM(d->descriptor->bEndpointAddress);
2138
+ }
2139
+
2140
+ /*
2141
+ * call-seq:
2142
+ * descriptor.bmAttributes -> bmAttributes
2143
+ *
2144
+ * Get the endpoint attributes.
2145
+ *
2146
+ * Returns a +FixNum+ and never raises an exception.
2147
+ */
2148
+ static VALUE cEndpointDescriptor_bmAttributes (VALUE self)
2149
+ {
2150
+ struct endpoint_descriptor_t *d;
2151
+
2152
+ Data_Get_Struct (self, struct endpoint_descriptor_t, d);
2153
+ return INT2NUM(d->descriptor->bmAttributes);
2154
+ }
2155
+
2156
+ /*
2157
+ * call-seq:
2158
+ * descriptor.wMaxPacketSize -> wMaxPacketSize
2159
+ *
2160
+ * Get the maximum packet size of the endpoint.
2161
+ *
2162
+ * Returns a +FixNum+ and never raises an exception.
2163
+ */
2164
+ static VALUE cEndpointDescriptor_wMaxPacketSize (VALUE self)
2165
+ {
2166
+ struct endpoint_descriptor_t *d;
2167
+
2168
+ Data_Get_Struct (self, struct endpoint_descriptor_t, d);
2169
+ return INT2NUM(d->descriptor->wMaxPacketSize);
2170
+ }
2171
+
2172
+ /*
2173
+ * call-seq:
2174
+ * descriptor.bInterval -> bInterval
2175
+ *
2176
+ * Get the polling interval for data transfers on this endpoint.
2177
+ *
2178
+ * Returns a +FixNum+ and never raises an exception.
2179
+ */
2180
+ static VALUE cEndpointDescriptor_bInterval (VALUE self)
2181
+ {
2182
+ struct endpoint_descriptor_t *d;
2183
+
2184
+ Data_Get_Struct (self, struct endpoint_descriptor_t, d);
2185
+ return INT2NUM(d->descriptor->bInterval);
2186
+ }
2187
+
2188
+ /*
2189
+ * call-seq:
2190
+ * descriptor.bRefresh -> bRefresh
2191
+ *
2192
+ * Get the rate of synchronization feedback for audio devices.
2193
+ *
2194
+ * Returns a +FixNum+ and never raises an exception.
2195
+ */
2196
+ static VALUE cEndpointDescriptor_bRefresh (VALUE self)
2197
+ {
2198
+ struct endpoint_descriptor_t *d;
2199
+
2200
+ Data_Get_Struct (self, struct endpoint_descriptor_t, d);
2201
+ return INT2NUM(d->descriptor->bRefresh);
2202
+ }
2203
+
2204
+ /*
2205
+ * call-seq:
2206
+ * descriptor.bSynchAddress -> bSynchAddress
2207
+ *
2208
+ * Get the address of the synchronization endpoint for audio devices.
2209
+ *
2210
+ * Returns a +FixNum+ and never raises an exception.
2211
+ */
2212
+ static VALUE cEndpointDescriptor_bSynchAddress (VALUE self)
2213
+ {
2214
+ struct endpoint_descriptor_t *d;
2215
+
2216
+ Data_Get_Struct (self, struct endpoint_descriptor_t, d);
2217
+ return INT2NUM(d->descriptor->bSynchAddress);
2218
+ }
2219
+
2220
+ /*
2221
+ * call-seq:
2222
+ * descriptor.extra -> extra
2223
+ *
2224
+ * Get the extra descriptors defined by this endpoint, as a string.
2225
+ *
2226
+ * Returns a +String+ and never raises an exception.
2227
+ */
2228
+ static VALUE cEndpointDescriptor_extra (VALUE self)
2229
+ {
2230
+ struct endpoint_descriptor_t *d;
2231
+
2232
+ Data_Get_Struct (self, struct endpoint_descriptor_t, d);
2233
+ return rb_str_new((char *) d->descriptor->extra, d->descriptor->extra_length);
2234
+ }
2235
+
2236
+
2237
+
2238
+ /******************************************************
2239
+ * RibUSB -- an interface to _libusb_, API version 1.0
2240
+ ******************************************************/
2241
+ void Init_ribusb()
2242
+ {
2243
+ RibUSB = rb_define_module ("RibUSB");
2244
+
2245
+ rb_define_singleton_method (RibUSB, "getError", mRibUSB_getError, 1);
2246
+
2247
+ /* RibUSB::Bus -- a class for _libusb_ bus-handling sessions */
2248
+ Bus = rb_define_class_under (RibUSB, "Bus", rb_cObject);
2249
+ rb_define_singleton_method (Bus, "new", cBus_new, 0);
2250
+ rb_define_method (Bus, "setDebug", cBus_setDebug, 1);
2251
+ rb_define_alias (Bus, "debug=", "setDebug");
2252
+ rb_define_method (Bus, "find", cBus_find, -1);
2253
+ rb_define_method (Bus, "handleEvents", cBus_handleEvents, 0);
2254
+
2255
+ /* RibUSB::Device -- a class for individual USB devices accessed through _libusb_ */
2256
+ Device = rb_define_class_under (RibUSB, "Device", rb_cObject);
2257
+ rb_define_method (Device, "getBusNumber", cDevice_getBusNumber, 0);
2258
+ rb_define_alias (Device, "busNumber", "getBusNumber");
2259
+ rb_define_method (Device, "getDeviceAddress", cDevice_getDeviceAddress, 0);
2260
+ rb_define_alias (Device, "deviceAddress", "getDeviceAddress");
2261
+ rb_define_method (Device, "getMaxPacketSize", cDevice_getMaxPacketSize, 1);
2262
+ rb_define_alias (Device, "maxPacketSize", "getMaxPacketSize");
2263
+ rb_define_method (Device, "getConfiguration", cDevice_getConfiguration, 0);
2264
+ rb_define_alias (Device, "configuration", "getConfiguration");
2265
+ rb_define_method (Device, "setConfiguration", cDevice_setConfiguration, 1);
2266
+ rb_define_alias (Device, "configuration=", "setConfiguration");
2267
+ rb_define_method (Device, "claimInterface", cDevice_claimInterface, 1);
2268
+ rb_define_method (Device, "releaseInterface", cDevice_releaseInterface, 1);
2269
+ rb_define_method (Device, "setInterfaceAltSetting", cDevice_setInterfaceAltSetting, 2);
2270
+ rb_define_method (Device, "clearHalt", cDevice_clearHalt, 1);
2271
+ rb_define_method (Device, "resetDevice", cDevice_resetDevice, 0);
2272
+ rb_define_method (Device, "kernelDriverActive?", cDevice_kernelDriverActiveQ, 1);
2273
+ rb_define_method (Device, "detachKernelDriver", cDevice_detachKernelDriver, 1);
2274
+ rb_define_method (Device, "attachKernelDriver", cDevice_attachKernelDriver, 1);
2275
+ rb_define_method (Device, "getStringDescriptorASCII", cDevice_getStringDescriptorASCII, 1);
2276
+ rb_define_alias (Device, "stringDescriptorASCII", "getStringDescriptorASCII");
2277
+ rb_define_method (Device, "getStringDescriptor", cDevice_getStringDescriptor, 2);
2278
+ rb_define_alias (Device, "stringDescriptor", "getStringDescriptor");
2279
+ rb_define_method (Device, "controlTransfer", cDevice_controlTransfer, 1);
2280
+ rb_define_method (Device, "bulkTransfer", cDevice_bulkTransfer, 1);
2281
+ rb_define_method (Device, "interruptTransfer", cDevice_interruptTransfer, 1);
2282
+
2283
+ rb_define_method (Device, "bcdUSB", cDevice_bcdUSB, 0);
2284
+ rb_define_method (Device, "bDeviceClass", cDevice_bDeviceClass, 0);
2285
+ rb_define_method (Device, "bDeviceSubClass", cDevice_bDeviceSubClass, 0);
2286
+ rb_define_method (Device, "bDeviceProtocol", cDevice_bDeviceProtocol, 0);
2287
+ rb_define_method (Device, "bMaxPacketSize0", cDevice_bMaxPacketSize0, 0);
2288
+ rb_define_method (Device, "idVendor", cDevice_idVendor, 0);
2289
+ rb_define_method (Device, "idProduct", cDevice_idProduct, 0);
2290
+ rb_define_method (Device, "bcdDevice", cDevice_bcdDevice, 0);
2291
+ rb_define_method (Device, "iManufacturer", cDevice_iManufacturer, 0);
2292
+ rb_define_method (Device, "iProduct", cDevice_iProduct, 0);
2293
+ rb_define_method (Device, "iSerialNumber", cDevice_iSerialNumber, 0);
2294
+ rb_define_method (Device, "bNumConfigurations", cDevice_bNumConfigurations, 0);
2295
+
2296
+ /* RibUSB::Transfer -- a class for asynchronous USB transfers */
2297
+ Transfer = rb_define_class_under (RibUSB, "Transfer", rb_cObject);
2298
+ rb_define_method (Transfer, "submit", cTransfer_submit, 0);
2299
+ rb_define_method (Transfer, "cancel", cTransfer_cancel, 0);
2300
+ rb_define_method (Transfer, "status", cTransfer_status, 0);
2301
+
2302
+ /* RibUSB::ConfigDescriptor -- a class for USB config descriptors */
2303
+ ConfigDescriptor = rb_define_class_under (RibUSB, "ConfigDescriptor", rb_cObject);
2304
+ rb_define_method (ConfigDescriptor, "bLength", cConfigDescriptor_bLength, 0);
2305
+ rb_define_method (ConfigDescriptor, "bDescriptorType", cConfigDescriptor_bDescriptorType, 0);
2306
+ rb_define_method (ConfigDescriptor, "wTotalLength", cConfigDescriptor_wTotalLength, 0);
2307
+ rb_define_method (ConfigDescriptor, "bNumInterfaces", cConfigDescriptor_bNumInterfaces, 0);
2308
+ rb_define_method (ConfigDescriptor, "bConfigurationValue", cConfigDescriptor_bConfigurationValue, 0);
2309
+ rb_define_method (ConfigDescriptor, "iConfiguration", cConfigDescriptor_iConfiguration, 0);
2310
+ rb_define_method (ConfigDescriptor, "bmAttributes", cConfigDescriptor_bmAttributes, 0);
2311
+ rb_define_method (ConfigDescriptor, "maxPower", cConfigDescriptor_maxPower, 0);
2312
+ rb_define_method (ConfigDescriptor, "interfaceList", cConfigDescriptor_interfaceList, 0);
2313
+ rb_define_method (ConfigDescriptor, "extra", cConfigDescriptor_extra, 0);
2314
+
2315
+ /* RibUSB::Interface -- a class for USB interfaces */
2316
+ Interface = rb_define_class_under (RibUSB, "Interface", rb_cObject);
2317
+ rb_define_method (Interface, "altSettingList", cInterface_altSettingList, 0);
2318
+
2319
+ /* RibUSB::InterfaceDescriptor -- a class for USB interface descriptors */
2320
+ InterfaceDescriptor = rb_define_class_under (RibUSB, "InterfaceDescriptor", rb_cObject);
2321
+ rb_define_method (InterfaceDescriptor, "bLength", cInterfaceDescriptor_bLength, 0);
2322
+ rb_define_method (InterfaceDescriptor, "bDescriptorType", cInterfaceDescriptor_bDescriptorType, 0);
2323
+ rb_define_method (InterfaceDescriptor, "bInterfaceNumber", cInterfaceDescriptor_bInterfaceNumber, 0);
2324
+ rb_define_method (InterfaceDescriptor, "bAlternateSetting", cInterfaceDescriptor_bAlternateSetting, 0);
2325
+ rb_define_method (InterfaceDescriptor, "bNumEndpoints", cInterfaceDescriptor_bNumEndpoints, 0);
2326
+ rb_define_method (InterfaceDescriptor, "bInterfaceClass", cInterfaceDescriptor_bInterfaceClass, 0);
2327
+ rb_define_method (InterfaceDescriptor, "bInterfaceSubClass", cInterfaceDescriptor_bInterfaceSubClass, 0);
2328
+ rb_define_method (InterfaceDescriptor, "bInterfaceProtocol", cInterfaceDescriptor_bInterfaceProtocol, 0);
2329
+ rb_define_method (InterfaceDescriptor, "iInterface", cInterfaceDescriptor_iInterface, 0);
2330
+ rb_define_method (InterfaceDescriptor, "endpointList", cInterfaceDescriptor_endpointList, 0);
2331
+ rb_define_method (InterfaceDescriptor, "extra", cInterfaceDescriptor_extra, 0);
2332
+
2333
+ /* RibUSB::EndpointDescriptor -- a class for USB endpoint descriptors */
2334
+ EndpointDescriptor = rb_define_class_under (RibUSB, "EndpointDescriptor", rb_cObject);
2335
+ rb_define_method (EndpointDescriptor, "bLength", cEndpointDescriptor_bLength, 0);
2336
+ rb_define_method (EndpointDescriptor, "bDescriptorType", cEndpointDescriptor_bDescriptorType, 0);
2337
+ rb_define_method (EndpointDescriptor, "bEndpointAddress", cEndpointDescriptor_bEndpointAddress, 0);
2338
+ rb_define_method (EndpointDescriptor, "bmAttributes", cEndpointDescriptor_bmAttributes, 0);
2339
+ rb_define_method (EndpointDescriptor, "wMaxPacketSize", cEndpointDescriptor_wMaxPacketSize, 0);
2340
+ rb_define_method (EndpointDescriptor, "bInterval", cEndpointDescriptor_bInterval, 0);
2341
+ rb_define_method (EndpointDescriptor, "bRefresh", cEndpointDescriptor_bRefresh, 0);
2342
+ rb_define_method (EndpointDescriptor, "bSynchAddress", cEndpointDescriptor_bSynchAddress, 0);
2343
+ rb_define_method (EndpointDescriptor, "extra", cEndpointDescriptor_extra, 0);
2344
+ }