libusb 0.3.3-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,282 @@
1
+ # This file is part of Libusb for Ruby.
2
+ #
3
+ # Libusb for Ruby is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # Libusb for Ruby is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'libusb/call'
17
+
18
+ module LIBUSB
19
+ # Abstract base class for USB transfers. Use
20
+ # {ControlTransfer}, {BulkTransfer}, {InterruptTransfer}, {IsochronousTransfer}
21
+ # to do transfers.
22
+ #
23
+ # There are convenience methods for {DevHandle#bulk_transfer}, {DevHandle#control_transfer}
24
+ # and {DevHandle#interrupt_transfer}, that fit for most use cases.
25
+ # Using {Transfer} derived classes directly, however, is needed for isochronous transfers and
26
+ # allows a more advanced buffer management.
27
+ class Transfer
28
+ def initialize(args={})
29
+ args.each{|k,v| send("#{k}=", v) }
30
+ @buffer = nil
31
+ @completion_flag = Context::CompletionFlag.new
32
+ end
33
+ private :initialize
34
+
35
+ # Set the handle for the device to communicate with.
36
+ def dev_handle=(dev)
37
+ @dev_handle = dev
38
+ @transfer[:dev_handle] = @dev_handle.pHandle
39
+ end
40
+
41
+ # Timeout for this transfer in millseconds.
42
+ #
43
+ # A value of 0 indicates no timeout.
44
+ def timeout=(value)
45
+ @transfer[:timeout] = value
46
+ end
47
+
48
+ # Set the address of a valid endpoint to communicate with.
49
+ def endpoint=(endpoint)
50
+ endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
51
+ @transfer[:endpoint] = endpoint
52
+ end
53
+
54
+ # Set output data that should be sent.
55
+ def buffer=(data)
56
+ if !@buffer || data.bytesize>@buffer.size
57
+ free_buffer
58
+ @buffer = FFI::MemoryPointer.new(data.bytesize, 1, false)
59
+ end
60
+ @buffer.put_bytes(0, data)
61
+ @transfer[:buffer] = @buffer
62
+ @transfer[:length] = data.bytesize
63
+ end
64
+
65
+ # Retrieve the current data buffer.
66
+ def buffer
67
+ @transfer[:buffer].read_string(@transfer[:length])
68
+ end
69
+
70
+ # Clear the current data buffer.
71
+ def free_buffer
72
+ if @buffer
73
+ @buffer.free
74
+ @buffer = nil
75
+ @transfer[:buffer] = nil
76
+ @transfer[:length] = 0
77
+ end
78
+ end
79
+
80
+ # Allocate +len+ bytes of data buffer for input transfer.
81
+ #
82
+ # @param [Fixnum] len Number of bytes to allocate
83
+ # @param [String, nil] data some data to initialize the buffer with
84
+ def alloc_buffer(len, data=nil)
85
+ if !@buffer || len>@buffer.size
86
+ free_buffer
87
+ @buffer = FFI::MemoryPointer.new(len, 1, false)
88
+ end
89
+ @buffer.put_bytes(0, data) if data
90
+ @transfer[:buffer] = @buffer
91
+ @transfer[:length] = len
92
+ end
93
+
94
+ # The number of bytes actually transferred.
95
+ def actual_length
96
+ @transfer[:actual_length]
97
+ end
98
+
99
+ # Retrieve the data actually transferred.
100
+ #
101
+ # @param [Fixnum] offset optional offset of the retrieved data in the buffer.
102
+ def actual_buffer(offset=0)
103
+ @transfer[:buffer].get_bytes(offset, @transfer[:actual_length])
104
+ end
105
+
106
+ # Set the block that will be invoked when the transfer completes,
107
+ # fails, or is cancelled.
108
+ #
109
+ # @param [Proc] proc The block that should be called
110
+ def callback=(proc)
111
+ # Save proc to instance variable so that GC doesn't free
112
+ # the proc object before the transfer.
113
+ @callback_proc = proc do |pTrans|
114
+ proc.call(self)
115
+ end
116
+ @transfer[:callback] = @callback_proc
117
+ end
118
+
119
+ # The status of the transfer.
120
+ #
121
+ # Only for use within transfer callback function or after the callback was called.
122
+ #
123
+ # If this is an isochronous transfer, this field may read :TRANSFER_COMPLETED even if there
124
+ # were errors in the frames. Use the status field in each packet to determine if
125
+ # errors occurred.
126
+ def status
127
+ @transfer[:status]
128
+ end
129
+
130
+ # Submit a transfer.
131
+ #
132
+ # This function will fire off the USB transfer and then return immediately.
133
+ # This method can be called with block. It is called when the transfer completes,
134
+ # fails, or is cancelled.
135
+ def submit!(&block)
136
+ self.callback = block if block_given?
137
+
138
+ # puts "submit transfer #{@transfer.inspect} buffer: #{@transfer[:buffer].inspect} length: #{@transfer[:length].inspect} status: #{@transfer[:status].inspect} callback: #{@transfer[:callback].inspect} dev_handle: #{@transfer[:dev_handle].inspect}"
139
+
140
+ res = Call.libusb_submit_transfer( @transfer )
141
+ LIBUSB.raise_error res, "in libusb_submit_transfer" if res!=0
142
+ end
143
+
144
+ # Asynchronously cancel a previously submitted transfer.
145
+ #
146
+ # This function returns immediately, but this does not indicate cancellation is
147
+ # complete. Your callback function will be invoked at some later time with a
148
+ # transfer status of :TRANSFER_CANCELLED.
149
+ def cancel!
150
+ res = Call.libusb_cancel_transfer( @transfer )
151
+ LIBUSB.raise_error res, "in libusb_cancel_transfer" if res!=0
152
+ end
153
+
154
+ TransferStatusToError = {
155
+ :TRANSFER_ERROR => LIBUSB::ERROR_IO,
156
+ :TRANSFER_TIMED_OUT => LIBUSB::ERROR_TIMEOUT,
157
+ :TRANSFER_CANCELLED => LIBUSB::ERROR_INTERRUPTED,
158
+ :TRANSFER_STALL => LIBUSB::ERROR_PIPE,
159
+ :TRANSFER_NO_DEVICE => LIBUSB::ERROR_NO_DEVICE,
160
+ :TRANSFER_OVERFLOW => LIBUSB::ERROR_OVERFLOW,
161
+ }
162
+
163
+ # Submit the transfer and wait until the transfer completes or fails.
164
+ #
165
+ # Inspect {#status} to check for transfer errors.
166
+ def submit_and_wait
167
+ @completion_flag.completed = false
168
+ submit! do |tr2|
169
+ @completion_flag.completed = true
170
+ end
171
+
172
+ until @completion_flag.completed?
173
+ begin
174
+ @dev_handle.device.context.handle_events nil, @completion_flag
175
+ rescue ERROR_INTERRUPTED
176
+ next
177
+ rescue LIBUSB::Error
178
+ cancel!
179
+ until @completion_flag.completed?
180
+ @dev_handle.device.context.handle_events nil, @completion_flag
181
+ end
182
+ raise
183
+ end
184
+ end
185
+ end
186
+
187
+ # Submit the transfer and wait until the transfer completes or fails.
188
+ #
189
+ # A proper {LIBUSB::Error} is raised, in case the transfer did not complete.
190
+ def submit_and_wait!
191
+ submit_and_wait
192
+
193
+ raise( TransferStatusToError[status] || ERROR_OTHER, "error #{status}") unless status==:TRANSFER_COMPLETED
194
+ end
195
+ end
196
+
197
+ class BulkTransfer < Transfer
198
+ def initialize(args={})
199
+ @transfer = Call::Transfer.new Call.libusb_alloc_transfer(0)
200
+ @transfer[:type] = TRANSFER_TYPE_BULK
201
+ @transfer[:timeout] = 1000
202
+ super
203
+ end
204
+ end
205
+
206
+ class ControlTransfer < Transfer
207
+ def initialize(args={})
208
+ @transfer = Call::Transfer.new Call.libusb_alloc_transfer(0)
209
+ @transfer[:type] = TRANSFER_TYPE_CONTROL
210
+ @transfer[:timeout] = 1000
211
+ super
212
+ end
213
+ end
214
+
215
+ class InterruptTransfer < Transfer
216
+ def initialize(args={})
217
+ @transfer = Call::Transfer.new Call.libusb_alloc_transfer(0)
218
+ @transfer[:type] = TRANSFER_TYPE_INTERRUPT
219
+ @transfer[:timeout] = 1000
220
+ super
221
+ end
222
+ end
223
+
224
+ class IsoPacket
225
+ def initialize(ptr, pkg_nr)
226
+ @packet = Call::IsoPacketDescriptor.new ptr
227
+ @pkg_nr = pkg_nr
228
+ end
229
+
230
+ def status
231
+ @packet[:status]
232
+ end
233
+
234
+ def length
235
+ @packet[:length]
236
+ end
237
+ def length=(len)
238
+ @packet[:length] = len
239
+ end
240
+
241
+ def actual_length
242
+ @packet[:actual_length]
243
+ end
244
+ end
245
+
246
+ class IsochronousTransfer < Transfer
247
+ def initialize(num_packets, args={})
248
+ @ptr = Call.libusb_alloc_transfer(num_packets)
249
+ @transfer = Call::Transfer.new @ptr
250
+ @transfer[:type] = TRANSFER_TYPE_ISOCHRONOUS
251
+ @transfer[:timeout] = 1000
252
+ @transfer[:num_iso_packets] = num_packets
253
+ super(args)
254
+ end
255
+
256
+ def num_packets
257
+ @transfer[:num_iso_packets]
258
+ end
259
+ def num_packets=(number)
260
+ @transfer[:num_iso_packets] = number
261
+ end
262
+
263
+ def [](nr)
264
+ IsoPacket.new( @ptr + Call::Transfer.size + nr*Call::IsoPacketDescriptor.size, nr)
265
+ end
266
+
267
+ # Convenience function to set the length of all packets in an
268
+ # isochronous transfer, based on {IsochronousTransfer#num_packets}.
269
+ def packet_lengths=(len)
270
+ ptr = @ptr + Call::Transfer.size
271
+ num_packets.times do
272
+ ptr.write_uint(len)
273
+ ptr += Call::IsoPacketDescriptor.size
274
+ end
275
+ end
276
+
277
+ # The actual_length field of the transfer is meaningless and should not
278
+ # be examined; instead you must refer to the actual_length field of
279
+ # each individual packet.
280
+ private :actual_length, :actual_buffer
281
+ end
282
+ end
@@ -0,0 +1,19 @@
1
+ # This file is part of Libusb for Ruby.
2
+ #
3
+ # Libusb for Ruby is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # Libusb for Ruby is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ module LIBUSB
17
+ # Library version of libusb for Ruby
18
+ VERSION = "0.3.3"
19
+ end
@@ -0,0 +1,63 @@
1
+ # This file is part of Libusb for Ruby.
2
+ #
3
+ # Libusb for Ruby is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # Libusb for Ruby is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'libusb/call'
17
+
18
+ module LIBUSB
19
+ class Version < FFI::Struct
20
+ layout :major, :uint16,
21
+ :minor, :uint16,
22
+ :micro, :uint16,
23
+ :nano, :uint16,
24
+ :rc, :pointer,
25
+ :describe, :pointer
26
+
27
+ # Library major version.
28
+ def major
29
+ self[:major]
30
+ end
31
+ # Library minor version.
32
+ def minor
33
+ self[:minor]
34
+ end
35
+ # Library micro version.
36
+ def micro
37
+ self[:micro]
38
+ end
39
+ # Library nano version.
40
+ def nano
41
+ self[:nano]
42
+ end
43
+
44
+ # Library release candidate suffix string, e.g. "-rc4".
45
+ def rc
46
+ self[:rc].read_string
47
+ end
48
+
49
+ # For ABI compatibility only.
50
+ def describe
51
+ self[:describe].read_string
52
+ end
53
+
54
+ # Version string, e.g. "1.2.3-rc4"
55
+ def to_s
56
+ "#{major}.#{minor}.#{micro}#{rc}"
57
+ end
58
+
59
+ def inspect
60
+ "\#<#{self.class} #{to_s}>"
61
+ end
62
+ end
63
+ end
data/libusb.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "libusb/version_gem"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "libusb"
7
+ s.version = LIBUSB::VERSION
8
+ s.authors = ["Lars Kanis"]
9
+ s.email = ["lars@greiz-reinsdorf.de"]
10
+ s.homepage = "http://github.com/larskanis/libusb"
11
+ s.summary = %q{Access USB devices from Ruby via libusb-1.0}
12
+ s.description = %q{LIBUSB is a Ruby binding that gives Ruby programmers access to arbitrary USB devices}
13
+ s.rdoc_options = %w[--main README.md --charset=UTF-8]
14
+
15
+ s.rubyforge_project = "libusb"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ s.extensions = ['ext/extconf.rb']
22
+
23
+ # travis currently runs a slightly older version of rbx,
24
+ # that needs a special ffi version.
25
+ unless ENV['TRAVIS'] && defined?(RUBY_ENGINE) && RUBY_ENGINE=='rbx'
26
+ s.add_runtime_dependency 'ffi', '>= 1.0'
27
+ end
28
+
29
+ s.add_development_dependency 'rake-compiler', '>= 0.6'
30
+ s.add_development_dependency 'bundler'
31
+ end
@@ -0,0 +1,23 @@
1
+ # This file is part of Libusb for Ruby.
2
+ #
3
+ # Libusb for Ruby is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # Libusb for Ruby is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require "test/unit"
17
+ require "libusb"
18
+
19
+ class TestLibusbCapability < Test::Unit::TestCase
20
+ def test_version_parts
21
+ assert LIBUSB.has_capability?(:CAP_HAS_CAPABILITY)
22
+ end
23
+ end
@@ -0,0 +1,78 @@
1
+ # This file is part of Libusb for Ruby.
2
+ #
3
+ # Libusb for Ruby is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # Libusb for Ruby is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public License
14
+ # along with Libusb for Ruby. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require "test/unit"
17
+ require "libusb/compat"
18
+
19
+ class TestLibusbCompat < Test::Unit::TestCase
20
+ include USB
21
+
22
+ attr_accessor :usb
23
+
24
+ def test_find
25
+ devlist = USB.devices
26
+ assert_kind_of Array, devlist, "Bus#find should return an Array"
27
+ assert_kind_of Device, devlist.first, "Bus#find should return Devices"
28
+ devlist.each do |dev|
29
+ assert_match( /Device/, dev.inspect, "Device#inspect should work")
30
+ end
31
+ end
32
+
33
+ def test_constants
34
+ assert_equal 7, USB_CLASS_PRINTER, "Printer class id should be defined"
35
+ assert_equal 32, USB_TYPE_CLASS, "type class should be defined"
36
+ end
37
+
38
+ def test_descriptors
39
+ USB.devices.each do |dev|
40
+ assert_match(/Device/, dev.inspect, "Device#inspect should work")
41
+ dev.configurations.each do |config_desc|
42
+ assert_match(/Configuration/, config_desc.inspect, "Configuration#inspect should work")
43
+ assert dev.configurations.include?(config_desc), "Device#configurations should include this one"
44
+
45
+ config_desc.interfaces.each do |interface|
46
+ assert_match(/Interface/, interface.inspect, "Interface#inspect should work")
47
+
48
+ assert dev.interfaces.include?(interface), "Device#interfaces should include this one"
49
+ assert config_desc.interfaces.include?(interface), "Configuration#interfaces should include this one"
50
+
51
+ interface.settings.each do |if_desc|
52
+ assert_match(/Setting/, if_desc.inspect, "Setting#inspect should work")
53
+
54
+ assert dev.settings.include?(if_desc), "Device#settings should include this one"
55
+ assert config_desc.settings.include?(if_desc), "Configuration#settings should include this one"
56
+ assert interface.settings.include?(if_desc), "Interface#settings should include this one"
57
+
58
+ if_desc.endpoints.each do |ep|
59
+ assert_match(/Endpoint/, ep.inspect, "Endpoint#inspect should work")
60
+
61
+ assert dev.endpoints.include?(ep), "Device#endpoints should include this one"
62
+ assert config_desc.endpoints.include?(ep), "Configuration#endpoints should include this one"
63
+ assert interface.endpoints.include?(ep), "Interface#endpoints should include this one"
64
+ assert if_desc.endpoints.include?(ep), "Setting#endpoints should include this one"
65
+
66
+ assert_equal if_desc, ep.setting, "backref should be correct"
67
+ assert_equal interface, ep.interface, "backref should be correct"
68
+ assert_equal config_desc, ep.configuration, "backref should be correct"
69
+ assert_equal dev, ep.device, "backref should be correct"
70
+
71
+ assert_operator 0, :<=, ep.wMaxPacketSize, "packet size should be > 0"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end