libusb 0.1.3-x86-mingw32 → 0.2.0-x86-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,51 @@
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 Interface < FFI::Struct
20
+ include Comparable
21
+
22
+ layout :altsetting, :pointer,
23
+ :num_altsetting, :int
24
+
25
+ def initialize(configuration, *args)
26
+ @configuration = configuration
27
+ super(*args)
28
+ end
29
+
30
+ # @return [Configuration] the configuration this interface belongs to.
31
+ attr_reader :configuration
32
+
33
+ def alt_settings
34
+ ifs = []
35
+ self[:num_altsetting].times do |i|
36
+ ifs << Setting.new(self, self[:altsetting] + i*Setting.size)
37
+ end
38
+ return ifs
39
+ end
40
+ alias settings alt_settings
41
+
42
+ # The {Device} this Interface belongs to.
43
+ def device() self.configuration.device end
44
+ # Return all endpoints of all alternative settings as Array of {Endpoint}s.
45
+ def endpoints() self.alt_settings.map {|d| d.endpoints }.flatten end
46
+
47
+ def <=>(o)
48
+ configuration<=>o.configuration
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,132 @@
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 Setting < FFI::Struct
20
+ include Comparable
21
+
22
+ layout :bLength, :uint8,
23
+ :bDescriptorType, :uint8,
24
+ :bInterfaceNumber, :uint8,
25
+ :bAlternateSetting, :uint8,
26
+ :bNumEndpoints, :uint8,
27
+ :bInterfaceClass, :uint8,
28
+ :bInterfaceSubClass, :uint8,
29
+ :bInterfaceProtocol, :uint8,
30
+ :iInterface, :uint8,
31
+ :endpoint, :pointer,
32
+ :extra, :pointer,
33
+ :extra_length, :int
34
+
35
+ # Size of this descriptor (in bytes).
36
+ def bLength
37
+ self[:bLength]
38
+ end
39
+
40
+ # Descriptor type (0x04)
41
+ def bDescriptorType
42
+ self[:bDescriptorType]
43
+ end
44
+
45
+ # Number of this interface.
46
+ def bInterfaceNumber
47
+ self[:bInterfaceNumber]
48
+ end
49
+
50
+ # Value used to select this alternate setting for this interface.
51
+ def bAlternateSetting
52
+ self[:bAlternateSetting]
53
+ end
54
+
55
+ # Number of endpoints used by this interface (excluding the control endpoint).
56
+ def bNumEndpoints
57
+ self[:bNumEndpoints]
58
+ end
59
+
60
+ # USB-IF class code for this interface.
61
+ def bInterfaceClass
62
+ self[:bInterfaceClass]
63
+ end
64
+
65
+ # USB-IF subclass code for this interface, qualified by the {Setting#bInterfaceClass} value.
66
+ def bInterfaceSubClass
67
+ self[:bInterfaceSubClass]
68
+ end
69
+
70
+ # USB-IF protocol code for this interface, qualified by the {Setting#bInterfaceClass} and {Setting#bInterfaceSubClass} values.
71
+ def bInterfaceProtocol
72
+ self[:bInterfaceProtocol]
73
+ end
74
+
75
+ # Index of string descriptor describing this interface.
76
+ def iInterface
77
+ self[:iInterface]
78
+ end
79
+
80
+ # Extra descriptors.
81
+ #
82
+ # @return [String]
83
+ def extra
84
+ return if self[:extra].null?
85
+ self[:extra].read_string(self[:extra_length])
86
+ end
87
+
88
+ def initialize(interface, *args)
89
+ @interface = interface
90
+ super(*args)
91
+ end
92
+
93
+ # @return [Interface] the interface this setting belongs to.
94
+ attr_reader :interface
95
+
96
+ def endpoints
97
+ ifs = []
98
+ self[:bNumEndpoints].times do |i|
99
+ ifs << Endpoint.new(self, self[:endpoint] + i*Endpoint.size)
100
+ end
101
+ return ifs
102
+ end
103
+
104
+ def inspect
105
+ attrs = []
106
+ attrs << self.bAlternateSetting.to_s
107
+ devclass = LIBUSB.dev_string(self.bInterfaceClass, self.bInterfaceSubClass, self.bInterfaceProtocol)
108
+ attrs << devclass
109
+ desc = self.description
110
+ attrs << desc if desc != '?'
111
+ "\#<#{self.class} #{attrs.join(' ')}>"
112
+ end
113
+
114
+ # Return name of this interface as String.
115
+ def description
116
+ return @description if defined? @description
117
+ @description = device.try_string_descriptor_ascii(self.iInterface)
118
+ end
119
+
120
+ # The {Device} this Setting belongs to.
121
+ def device() self.interface.configuration.device end
122
+ # The {Configuration} this Setting belongs to.
123
+ def configuration() self.interface.configuration end
124
+
125
+ def <=>(o)
126
+ t = interface<=>o.interface
127
+ t = bInterfaceNumber<=>o.bInterfaceNumber if t==0
128
+ t = bAlternateSetting<=>o.bAlternateSetting if t==0
129
+ t
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,269 @@
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
+ class Transfer
23
+ def initialize(args={})
24
+ args.each{|k,v| send("#{k}=", v) }
25
+ @buffer = nil
26
+ end
27
+ private :initialize
28
+
29
+ # Set the handle for the device to communicate with.
30
+ def dev_handle=(dev)
31
+ @dev_handle = dev
32
+ @transfer[:dev_handle] = @dev_handle.pHandle
33
+ end
34
+
35
+ # Timeout for this transfer in millseconds.
36
+ #
37
+ # A value of 0 indicates no timeout.
38
+ def timeout=(value)
39
+ @transfer[:timeout] = value
40
+ end
41
+
42
+ # Set the address of a valid endpoint to communicate with.
43
+ def endpoint=(endpoint)
44
+ endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
45
+ @transfer[:endpoint] = endpoint
46
+ end
47
+
48
+ # Set output data that should be sent.
49
+ def buffer=(data)
50
+ if !@buffer || data.bytesize>@buffer.size
51
+ free_buffer
52
+ @buffer = FFI::MemoryPointer.new(data.bytesize, 1, false)
53
+ end
54
+ @buffer.put_bytes(0, data)
55
+ @transfer[:buffer] = @buffer
56
+ @transfer[:length] = data.bytesize
57
+ end
58
+
59
+ # Retrieve the current data buffer.
60
+ def buffer
61
+ @transfer[:buffer].read_string(@transfer[:length])
62
+ end
63
+
64
+ # Clear the current data buffer.
65
+ def free_buffer
66
+ if @buffer
67
+ @buffer.free
68
+ @buffer = nil
69
+ @transfer[:buffer] = nil
70
+ @transfer[:length] = 0
71
+ end
72
+ end
73
+
74
+ # Allocate +len+ bytes of data buffer for input transfer.
75
+ #
76
+ # @param [Fixnum] len Number of bytes to allocate
77
+ # @param [String, nil] data some data to initialize the buffer with
78
+ def alloc_buffer(len, data=nil)
79
+ if !@buffer || len>@buffer.size
80
+ free_buffer
81
+ @buffer = FFI::MemoryPointer.new(len, 1, false)
82
+ end
83
+ @buffer.put_bytes(0, data) if data
84
+ @transfer[:buffer] = @buffer
85
+ @transfer[:length] = len
86
+ end
87
+
88
+ # The number of bytes actually transferred.
89
+ def actual_length
90
+ @transfer[:actual_length]
91
+ end
92
+
93
+ # Retrieve the data actually transferred.
94
+ #
95
+ # @param [Fixnum] offset optional offset of the retrieved data in the buffer.
96
+ def actual_buffer(offset=0)
97
+ @transfer[:buffer].get_bytes(offset, @transfer[:actual_length])
98
+ end
99
+
100
+ # Set the block that will be invoked when the transfer completes,
101
+ # fails, or is cancelled.
102
+ #
103
+ # @param [Proc] proc The block that should be called
104
+ def callback=(proc)
105
+ # Save proc to instance variable so that GC doesn't free
106
+ # the proc object before the transfer.
107
+ @callback_proc = proc do |pTrans|
108
+ proc.call(self)
109
+ end
110
+ @transfer[:callback] = @callback_proc
111
+ end
112
+
113
+ # The status of the transfer.
114
+ #
115
+ # Only for use within transfer callback function or after the callback was called.
116
+ #
117
+ # If this is an isochronous transfer, this field may read :TRANSFER_COMPLETED even if there
118
+ # were errors in the frames. Use the status field in each packet to determine if
119
+ # errors occurred.
120
+ def status
121
+ @transfer[:status]
122
+ end
123
+
124
+ # Submit a transfer.
125
+ #
126
+ # This function will fire off the USB transfer and then return immediately.
127
+ # This method can be called with block. It is called when the transfer completes,
128
+ # fails, or is cancelled.
129
+ def submit!(&block)
130
+ self.callback = block if block_given?
131
+
132
+ # 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}"
133
+
134
+ res = Call.libusb_submit_transfer( @transfer )
135
+ LIBUSB.raise_error res, "in libusb_submit_transfer" if res!=0
136
+ end
137
+
138
+ # Asynchronously cancel a previously submitted transfer.
139
+ #
140
+ # This function returns immediately, but this does not indicate cancellation is
141
+ # complete. Your callback function will be invoked at some later time with a
142
+ # transfer status of :TRANSFER_CANCELLED.
143
+ def cancel!
144
+ res = Call.libusb_cancel_transfer( @transfer )
145
+ LIBUSB.raise_error res, "in libusb_cancel_transfer" if res!=0
146
+ end
147
+
148
+ TransferStatusToError = {
149
+ :TRANSFER_ERROR => LIBUSB::ERROR_IO,
150
+ :TRANSFER_TIMED_OUT => LIBUSB::ERROR_TIMEOUT,
151
+ :TRANSFER_CANCELLED => LIBUSB::ERROR_INTERRUPTED,
152
+ :TRANSFER_STALL => LIBUSB::ERROR_PIPE,
153
+ :TRANSFER_NO_DEVICE => LIBUSB::ERROR_NO_DEVICE,
154
+ :TRANSFER_OVERFLOW => LIBUSB::ERROR_OVERFLOW,
155
+ }
156
+
157
+ # Submit the transfer and wait until the transfer completes or fails.
158
+ #
159
+ # A proper {LIBUSB::Error} is raised, in case the transfer did not complete.
160
+ def submit_and_wait!
161
+ completed = false
162
+ submit! do |tr2|
163
+ completed = true
164
+ end
165
+
166
+ until completed
167
+ begin
168
+ @dev_handle.device.context.handle_events
169
+ rescue ERROR_INTERRUPTED
170
+ next
171
+ rescue LIBUSB::Error
172
+ cancel!
173
+ until completed
174
+ @dev_handle.device.context.handle_events
175
+ end
176
+ raise
177
+ end
178
+ end
179
+
180
+ raise( TransferStatusToError[status] || ERROR_OTHER, "error #{status}") unless status==:TRANSFER_COMPLETED
181
+ end
182
+ end
183
+
184
+ class BulkTransfer < Transfer
185
+ def initialize(args={})
186
+ @transfer = Call::Transfer.new Call.libusb_alloc_transfer(0)
187
+ @transfer[:type] = TRANSFER_TYPE_BULK
188
+ @transfer[:timeout] = 1000
189
+ super
190
+ end
191
+ end
192
+
193
+ class ControlTransfer < Transfer
194
+ def initialize(args={})
195
+ @transfer = Call::Transfer.new Call.libusb_alloc_transfer(0)
196
+ @transfer[:type] = TRANSFER_TYPE_CONTROL
197
+ @transfer[:timeout] = 1000
198
+ super
199
+ end
200
+ end
201
+
202
+ class InterruptTransfer < Transfer
203
+ def initialize(args={})
204
+ @transfer = Call::Transfer.new Call.libusb_alloc_transfer(0)
205
+ @transfer[:type] = TRANSFER_TYPE_INTERRUPT
206
+ @transfer[:timeout] = 1000
207
+ super
208
+ end
209
+ end
210
+
211
+ class IsoPacket
212
+ def initialize(ptr, pkg_nr)
213
+ @packet = Call::IsoPacketDescriptor.new ptr
214
+ @pkg_nr = pkg_nr
215
+ end
216
+
217
+ def status
218
+ @packet[:status]
219
+ end
220
+
221
+ def length
222
+ @packet[:length]
223
+ end
224
+ def length=(len)
225
+ @packet[:length] = len
226
+ end
227
+
228
+ def actual_length
229
+ @packet[:actual_length]
230
+ end
231
+ end
232
+
233
+ class IsochronousTransfer < Transfer
234
+ def initialize(num_packets, args={})
235
+ @ptr = Call.libusb_alloc_transfer(num_packets)
236
+ @transfer = Call::Transfer.new @ptr
237
+ @transfer[:type] = TRANSFER_TYPE_ISOCHRONOUS
238
+ @transfer[:timeout] = 1000
239
+ @transfer[:num_iso_packets] = num_packets
240
+ super(args)
241
+ end
242
+
243
+ def num_packets
244
+ @transfer[:num_iso_packets]
245
+ end
246
+ def num_packets=(number)
247
+ @transfer[:num_iso_packets] = number
248
+ end
249
+
250
+ def [](nr)
251
+ IsoPacket.new( @ptr + Call::Transfer.size + nr*Call::IsoPacketDescriptor.size, nr)
252
+ end
253
+
254
+ # Convenience function to set the length of all packets in an
255
+ # isochronous transfer, based on {IsochronousTransfer#num_packets}.
256
+ def packet_lengths=(len)
257
+ ptr = @ptr + Call::Transfer.size
258
+ num_packets.times do
259
+ ptr.write_uint(len)
260
+ ptr += Call::IsoPacketDescriptor.size
261
+ end
262
+ end
263
+
264
+ # The actual_length field of the transfer is meaningless and should not
265
+ # be examined; instead you must refer to the actual_length field of
266
+ # each individual packet.
267
+ private :actual_length, :actual_buffer
268
+ end
269
+ end