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,359 @@
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 representing a USB device detected on the system.
20
+ #
21
+ # Devices of the system can be obtained with {Context#devices} .
22
+ class Device
23
+ include Comparable
24
+
25
+ # @return [Context] the context this device belongs to.
26
+ attr_reader :context
27
+
28
+ def initialize context, pDev
29
+ @context = context
30
+ def pDev.unref_device(id)
31
+ Call.libusb_unref_device(self)
32
+ end
33
+ ObjectSpace.define_finalizer(self, pDev.method(:unref_device))
34
+ Call.libusb_ref_device(pDev)
35
+ @pDev = pDev
36
+
37
+ @pDevDesc = Call::DeviceDescriptor.new
38
+ res = Call.libusb_get_device_descriptor(@pDev, @pDevDesc)
39
+ LIBUSB.raise_error res, "in libusb_get_device_descriptor" if res!=0
40
+ end
41
+
42
+ # Open the device and obtain a device handle.
43
+ #
44
+ # A handle allows you to perform I/O on the device in question.
45
+ # This is a non-blocking function; no requests are sent over the bus.
46
+ #
47
+ # If called with a block, the handle is passed to the block
48
+ # and is closed when the block has finished.
49
+ #
50
+ # You need proper device access:
51
+ # * Linux: read+write permissions to <tt>/dev/bus/usb/<bus>/<dev></tt>
52
+ # * Windows: by installing a WinUSB-driver for the device (see {file:README.rdoc#Usage_on_Windows} )
53
+ #
54
+ # @return [DevHandle] Handle to the device.
55
+ def open
56
+ ppHandle = FFI::MemoryPointer.new :pointer
57
+ res = Call.libusb_open(@pDev, ppHandle)
58
+ LIBUSB.raise_error res, "in libusb_open" if res!=0
59
+ handle = DevHandle.new self, ppHandle.read_pointer
60
+ return handle unless block_given?
61
+ begin
62
+ yield handle
63
+ ensure
64
+ handle.close
65
+ end
66
+ end
67
+
68
+ # Open the device and claim an interface.
69
+ #
70
+ # This is a convenience method to {Device#open} and {DevHandle#claim_interface}.
71
+ # Must be called with a block. When the block has finished, the interface
72
+ # will be released and the device will be closed.
73
+ #
74
+ # @param [Interface, Fixnum] interface the interface or it's bInterfaceNumber you wish to claim
75
+ def open_interface(interface)
76
+ open do |dev|
77
+ dev.claim_interface(interface) do
78
+ yield dev
79
+ end
80
+ end
81
+ end
82
+
83
+ # Get the number of the bus that a device is connected to.
84
+ def bus_number
85
+ Call.libusb_get_bus_number(@pDev)
86
+ end
87
+
88
+ # Get the address of the device on the bus it is connected to.
89
+ def device_address
90
+ Call.libusb_get_device_address(@pDev)
91
+ end
92
+
93
+ if Call.respond_to?(:libusb_get_port_number)
94
+ # Get the number of the port that a device is connected to.
95
+ # Available since libusb-1.0.12.
96
+ #
97
+ # @return [Fixnum, nil] the port number (+nil+ if not available)
98
+ # @see #port_path
99
+ def port_number
100
+ r = Call.libusb_get_port_number(@pDev)
101
+ r==0 ? nil : r
102
+ end
103
+
104
+ # Get the the parent from the specified device [EXPERIMENTAL].
105
+ # Available since libusb-1.0.12.
106
+ #
107
+ # @return [Device, nil] the device parent or +nil+ if not available
108
+ # @see #port_path
109
+ def parent
110
+ pppDevs = FFI::MemoryPointer.new :pointer
111
+ Call.libusb_get_device_list(@context.instance_variable_get(:@ctx), pppDevs)
112
+ ppDevs = pppDevs.read_pointer
113
+ pParent = Call.libusb_get_parent(@pDev)
114
+ parent = pParent.null? ? nil : Device.new(@context, pParent)
115
+ Call.libusb_free_device_list(ppDevs, 1)
116
+ parent
117
+ end
118
+
119
+ # Get the list of all port numbers from root for the specified device.
120
+ # Available since libusb-1.0.12.
121
+ #
122
+ # @return [Array<Fixnum>]
123
+ # @see #parent
124
+ # @see #port_number
125
+ def port_path
126
+ # As per the USB 3.0 specs, the current maximum limit for the depth is 7.
127
+ path_len = 7
128
+ pPath = FFI::MemoryPointer.new :pointer, path_len
129
+ l = Call.libusb_get_port_path(@context.instance_variable_get(:@ctx), @pDev, pPath, path_len)
130
+ pPath.read_array_of_uint8(l)
131
+ end
132
+ end
133
+
134
+ if Call.respond_to?(:libusb_get_device_speed)
135
+ # Get the negotiated connection speed for a device.
136
+ # Available since libusb-1.0.9.
137
+ #
138
+ # @return [Symbol] a {Call::Speeds Speeds} symbol, where +:SPEED_UNKNOWN+ means that
139
+ # the OS doesn't know or doesn't support returning the negotiated speed.
140
+ def device_speed
141
+ Call.libusb_get_device_speed(@pDev)
142
+ end
143
+ end
144
+
145
+ # Convenience function to retrieve the wMaxPacketSize value for a
146
+ # particular endpoint in the active device configuration.
147
+ #
148
+ # @param [Endpoint, Fixnum] endpoint (address of) the endpoint in question
149
+ # @return [Fixnum] the wMaxPacketSize value
150
+ def max_packet_size(endpoint)
151
+ endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
152
+ res = Call.libusb_get_max_packet_size(@pDev, endpoint)
153
+ LIBUSB.raise_error res, "in libusb_get_max_packet_size" unless res>=0
154
+ res
155
+ end
156
+
157
+ # Calculate the maximum packet size which a specific endpoint is capable is
158
+ # sending or receiving in the duration of 1 microframe.
159
+ #
160
+ # Only the active configution is examined. The calculation is based on the
161
+ # wMaxPacketSize field in the endpoint descriptor as described in section 9.6.6
162
+ # in the USB 2.0 specifications.
163
+ #
164
+ # If acting on an isochronous or interrupt endpoint, this function will
165
+ # multiply the value found in bits 0:10 by the number of transactions per
166
+ # microframe (determined by bits 11:12). Otherwise, this function just returns
167
+ # the numeric value found in bits 0:10.
168
+ #
169
+ # This function is useful for setting up isochronous transfers, for example
170
+ # you might use the return value from this function to call
171
+ # IsoPacket#alloc_buffer in order to set the length field
172
+ # of an isochronous packet in a transfer.
173
+ #
174
+ # @param [Endpoint, Fixnum] endpoint (address of) the endpoint in question
175
+ # @return [Fixnum] the maximum packet size which can be sent/received on this endpoint
176
+ def max_iso_packet_size(endpoint)
177
+ endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress
178
+ res = Call.libusb_get_max_iso_packet_size(@pDev, endpoint)
179
+ LIBUSB.raise_error res, "in libusb_get_max_iso_packet_size" unless res>=0
180
+ res
181
+ end
182
+
183
+ # Obtain a config descriptor of the device.
184
+ #
185
+ # @param [Fixnum] index number of the config descriptor
186
+ # @return Configuration
187
+ def config_descriptor(index)
188
+ ppConfig = FFI::MemoryPointer.new :pointer
189
+ res = Call.libusb_get_config_descriptor(@pDev, index, ppConfig)
190
+ LIBUSB.raise_error res, "in libusb_get_config_descriptor" if res!=0
191
+ pConfig = ppConfig.read_pointer
192
+ config = Configuration.new(self, pConfig)
193
+ config
194
+ end
195
+
196
+ # Size of the Descriptor in Bytes (18 bytes)
197
+ def bLength
198
+ @pDevDesc[:bLength]
199
+ end
200
+
201
+ # Device Descriptor (0x01)
202
+ def bDescriptorType
203
+ @pDevDesc[:bDescriptorType]
204
+ end
205
+
206
+ # USB specification release number which device complies too
207
+ #
208
+ # @return [Integer] in binary-coded decimal
209
+ def bcdUSB
210
+ @pDevDesc[:bcdUSB]
211
+ end
212
+
213
+ # USB-IF class code for the device (Assigned by USB Org)
214
+ #
215
+ # * If equal to 0x00, each interface specifies it's own class code
216
+ # * If equal to 0xFF, the class code is vendor specified
217
+ # * Otherwise field is valid Class Code
218
+ def bDeviceClass
219
+ @pDevDesc[:bDeviceClass]
220
+ end
221
+
222
+ # USB-IF subclass code for the device, qualified by the {Device#bDeviceClass}
223
+ # value (Assigned by USB Org)
224
+ def bDeviceSubClass
225
+ @pDevDesc[:bDeviceSubClass]
226
+ end
227
+
228
+ # USB-IF protocol code for the device, qualified by the {Device#bDeviceClass}
229
+ # and {Device#bDeviceSubClass} values (Assigned by USB Org)
230
+ def bDeviceProtocol
231
+ @pDevDesc[:bDeviceProtocol]
232
+ end
233
+
234
+ # Maximum Packet Size for Endpoint 0. Valid Sizes are 8, 16, 32, 64
235
+ def bMaxPacketSize0
236
+ @pDevDesc[:bMaxPacketSize0]
237
+ end
238
+
239
+ # USB-IF vendor ID (Assigned by USB Org)
240
+ def idVendor
241
+ @pDevDesc[:idVendor]
242
+ end
243
+
244
+ # USB-IF product ID (Assigned by Manufacturer)
245
+ def idProduct
246
+ @pDevDesc[:idProduct]
247
+ end
248
+
249
+ # Device release number in binary-coded decimal.
250
+ def bcdDevice
251
+ @pDevDesc[:bcdDevice]
252
+ end
253
+
254
+ # Index of string descriptor describing manufacturer.
255
+ def iManufacturer
256
+ @pDevDesc[:iManufacturer]
257
+ end
258
+
259
+ # Index of string descriptor describing product.
260
+ def iProduct
261
+ @pDevDesc[:iProduct]
262
+ end
263
+
264
+ # Index of string descriptor containing device serial number.
265
+ def iSerialNumber
266
+ @pDevDesc[:iSerialNumber]
267
+ end
268
+
269
+ # Number of Possible Configurations
270
+ def bNumConfigurations
271
+ @pDevDesc[:bNumConfigurations]
272
+ end
273
+
274
+
275
+ def inspect
276
+ attrs = []
277
+ attrs << "#{self.bus_number}/#{self.device_address}"
278
+ attrs << ("%04x:%04x" % [self.idVendor, self.idProduct])
279
+ attrs << self.manufacturer
280
+ attrs << self.product
281
+ attrs << self.serial_number
282
+ if self.bDeviceClass == LIBUSB::CLASS_PER_INTERFACE
283
+ devclass = self.settings.map {|i|
284
+ LIBUSB.dev_string(i.bInterfaceClass, i.bInterfaceSubClass, i.bInterfaceProtocol)
285
+ }.join(", ")
286
+ else
287
+ devclass = LIBUSB.dev_string(self.bDeviceClass, self.bDeviceSubClass, self.bDeviceProtocol)
288
+ end
289
+ attrs << "(#{devclass})"
290
+ attrs.compact!
291
+ "\#<#{self.class} #{attrs.join(' ')}>"
292
+ end
293
+
294
+ def try_string_descriptor_ascii(i)
295
+ begin
296
+ open{|h| h.string_descriptor_ascii(i) }
297
+ rescue
298
+ "?"
299
+ end
300
+ end
301
+
302
+ # Return manufacturer of the device
303
+ # @return String
304
+ def manufacturer
305
+ return @manufacturer if defined? @manufacturer
306
+ @manufacturer = try_string_descriptor_ascii(self.iManufacturer)
307
+ @manufacturer.strip! if @manufacturer
308
+ @manufacturer
309
+ end
310
+
311
+ # Return product name of the device.
312
+ # @return String
313
+ def product
314
+ return @product if defined? @product
315
+ @product = try_string_descriptor_ascii(self.iProduct)
316
+ @product.strip! if @product
317
+ @product
318
+ end
319
+
320
+ # Return serial number of the device.
321
+ # @return String
322
+ def serial_number
323
+ return @serial_number if defined? @serial_number
324
+ @serial_number = try_string_descriptor_ascii(self.iSerialNumber)
325
+ @serial_number.strip! if @serial_number
326
+ @serial_number
327
+ end
328
+
329
+ # Return configurations of the device.
330
+ # @return [Array<Configuration>]
331
+ def configurations
332
+ configs = []
333
+ bNumConfigurations.times do |config_index|
334
+ begin
335
+ configs << config_descriptor(config_index)
336
+ rescue RuntimeError
337
+ # On Windows some devices don't return it's configuration.
338
+ end
339
+ end
340
+ configs
341
+ end
342
+
343
+ # Return all interfaces of this device.
344
+ # @return [Array<Interface>]
345
+ def interfaces() self.configurations.map {|d| d.interfaces }.flatten end
346
+ # Return all interface decriptions of this device.
347
+ # @return [Array<Setting>]
348
+ def settings() self.interfaces.map {|d| d.settings }.flatten end
349
+ # Return all endpoints of all interfaces of this device.
350
+ # @return [Array<Endpoint>]
351
+ def endpoints() self.settings.map {|d| d.endpoints }.flatten end
352
+
353
+ def <=>(o)
354
+ t = bus_number<=>o.bus_number
355
+ t = device_address<=>o.device_address if t==0
356
+ t
357
+ end
358
+ end
359
+ end
@@ -0,0 +1,147 @@
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 Endpoint < FFI::Struct
20
+ include Comparable
21
+
22
+ layout :bLength, :uint8,
23
+ :bDescriptorType, :uint8,
24
+ :bEndpointAddress, :uint8,
25
+ :bmAttributes, :uint8,
26
+ :wMaxPacketSize, :uint16,
27
+ :bInterval, :uint8,
28
+ :bRefresh, :uint8,
29
+ :bSynchAddress, :uint8,
30
+ :extra, :pointer,
31
+ :extra_length, :int
32
+
33
+ # Size of Descriptor in Bytes (7 bytes)
34
+ def bLength
35
+ self[:bLength]
36
+ end
37
+
38
+ # Descriptor type (0x05)
39
+ def bDescriptorType
40
+ self[:bDescriptorType]
41
+ end
42
+
43
+ # The address of the endpoint described by this descriptor.
44
+ #
45
+ # * Bits 0..3: Endpoint Number.
46
+ # * Bits 4..6: Reserved. Set to Zero
47
+ # * Bits 7: Direction 0 = Out, 1 = In (Ignored for Control Endpoints)
48
+ #
49
+ # @return [Integer]
50
+ def bEndpointAddress
51
+ self[:bEndpointAddress]
52
+ end
53
+
54
+ # Attributes which apply to the endpoint when it is configured using the {Configuration#bConfigurationValue}.
55
+ #
56
+ # * Bits 0..1: Transfer Type
57
+ # * 00 = Control
58
+ # * 01 = Isochronous
59
+ # * 10 = Bulk
60
+ # * 11 = Interrupt
61
+ # * Bits 2..7: are reserved. If Isochronous endpoint,
62
+ # * Bits 3..2: Synchronisation Type (Iso Mode)
63
+ # * 00 = No Synchonisation
64
+ # * 01 = Asynchronous
65
+ # * 10 = Adaptive
66
+ # * 11 = Synchronous
67
+ # * Bits 5..4: Usage Type (Iso Mode)
68
+ # * 00 = Data Endpoint
69
+ # * 01 = Feedback Endpoint
70
+ # * 10 = Explicit Feedback Data Endpoint
71
+ # * 11 = Reserved
72
+ #
73
+ # @return [Integer]
74
+ def bmAttributes
75
+ self[:bmAttributes]
76
+ end
77
+
78
+ # Maximum Packet Size this endpoint is capable of sending or receiving
79
+ def wMaxPacketSize
80
+ self[:wMaxPacketSize]
81
+ end
82
+
83
+ # Interval for polling endpoint data transfers. Value in frame counts.
84
+ # Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field
85
+ # may range from 1 to 255 for interrupt endpoints.
86
+ #
87
+ # The interval is respected by the kernel driver, so user mode processes
88
+ # using libusb don't need to care about it.
89
+ def bInterval
90
+ self[:bInterval]
91
+ end
92
+
93
+ # For audio devices only: the rate at which synchronization feedback is provided.
94
+ def bRefresh
95
+ self[:bRefresh]
96
+ end
97
+
98
+ # For audio devices only: the address if the synch endpoint.
99
+ def bSynchAddress
100
+ self[:bSynchAddress]
101
+ end
102
+
103
+ # Extra descriptors.
104
+ #
105
+ # @return [String]
106
+ def extra
107
+ return if self[:extra].null?
108
+ self[:extra].read_string(self[:extra_length])
109
+ end
110
+
111
+ def initialize(setting, *args)
112
+ @setting = setting
113
+ super(*args)
114
+ end
115
+
116
+ # @return [Setting] the setting this endpoint belongs to.
117
+ attr_reader :setting
118
+
119
+ def inspect
120
+ endpoint_address = self.bEndpointAddress
121
+ num = endpoint_address & 0b00001111
122
+ inout = (endpoint_address & 0b10000000) == 0 ? "OUT" : "IN "
123
+ bits = self.bmAttributes
124
+ transfer_type = %w[Control Isochronous Bulk Interrupt][0b11 & bits]
125
+ type = [transfer_type]
126
+ if transfer_type == 'Isochronous'
127
+ synchronization_type = %w[NoSynchronization Asynchronous Adaptive Synchronous][(0b1100 & bits) >> 2]
128
+ usage_type = %w[Data Feedback ImplicitFeedback ?][(0b110000 & bits) >> 4]
129
+ type << synchronization_type << usage_type
130
+ end
131
+ "\#<#{self.class} #{num} #{inout} #{type.join(" ")}>"
132
+ end
133
+
134
+ # The {Device} this Endpoint belongs to.
135
+ def device() self.setting.interface.configuration.device end
136
+ # The {Configuration} this Endpoint belongs to.
137
+ def configuration() self.setting.interface.configuration end
138
+ # The {Interface} this Endpoint belongs to.
139
+ def interface() self.setting.interface end
140
+
141
+ def <=>(o)
142
+ t = setting<=>o.setting
143
+ t = bEndpointAddress<=>o.bEndpointAddress if t==0
144
+ t
145
+ end
146
+ end
147
+ end