libusb 0.3.3-x64-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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