libusb 0.1.3-x86-mingw32 → 0.2.0-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -0
- data/History.txt +8 -0
- data/Manifest.txt +2 -15
- data/README.rdoc +22 -16
- data/Rakefile +26 -10
- data/lib/libusb-1.0.dll +0 -0
- data/lib/libusb.rb +27 -1767
- data/lib/libusb/call.rb +271 -0
- data/lib/libusb/compat.rb +2 -2
- data/lib/libusb/configuration.rb +139 -0
- data/lib/libusb/constants.rb +138 -0
- data/lib/libusb/context.rb +127 -0
- data/lib/libusb/dev_handle.rb +399 -0
- data/lib/libusb/device.rb +359 -0
- data/lib/libusb/endpoint.rb +147 -0
- data/lib/libusb/interface.rb +51 -0
- data/lib/libusb/setting.rb +132 -0
- data/lib/libusb/transfer.rb +269 -0
- data/lib/libusb/version.rb +63 -0
- data/test/test_libusb_capability.rb +23 -0
- data/test/test_libusb_descriptors.rb +13 -0
- data/test/test_libusb_version.rb +36 -0
- metadata +30 -18
- data/test/test_libusb_keyboard.rb +0 -50
data/lib/libusb/call.rb
ADDED
@@ -0,0 +1,271 @@
|
|
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 'rubygems'
|
17
|
+
require 'ffi'
|
18
|
+
|
19
|
+
module LIBUSB
|
20
|
+
# C level interface
|
21
|
+
module Call
|
22
|
+
extend FFI::Library
|
23
|
+
|
24
|
+
if FFI::Platform.windows?
|
25
|
+
bundled_dll = File.join(File.dirname(__FILE__), '..', 'libusb-1.0.dll')
|
26
|
+
ffi_lib(['libusb-1.0', bundled_dll])
|
27
|
+
else
|
28
|
+
ffi_lib 'libusb-1.0'
|
29
|
+
end
|
30
|
+
|
31
|
+
ClassCodes = enum :libusb_class_code, [
|
32
|
+
:CLASS_PER_INTERFACE, 0,
|
33
|
+
:CLASS_AUDIO, 1,
|
34
|
+
:CLASS_COMM, 2,
|
35
|
+
:CLASS_HID, 3,
|
36
|
+
:CLASS_PRINTER, 7,
|
37
|
+
:CLASS_PTP, 6,
|
38
|
+
:CLASS_MASS_STORAGE, 8,
|
39
|
+
:CLASS_HUB, 9,
|
40
|
+
:CLASS_DATA, 10,
|
41
|
+
:CLASS_WIRELESS, 0xe0,
|
42
|
+
:CLASS_APPLICATION, 0xfe,
|
43
|
+
:CLASS_VENDOR_SPEC, 0xff
|
44
|
+
]
|
45
|
+
|
46
|
+
Errors = enum :libusb_error, [
|
47
|
+
:SUCCESS, 0,
|
48
|
+
:ERROR_IO, -1,
|
49
|
+
:ERROR_INVALID_PARAM, -2,
|
50
|
+
:ERROR_ACCESS, -3,
|
51
|
+
:ERROR_NO_DEVICE, -4,
|
52
|
+
:ERROR_NOT_FOUND, -5,
|
53
|
+
:ERROR_BUSY, -6,
|
54
|
+
:ERROR_TIMEOUT, -7,
|
55
|
+
:ERROR_OVERFLOW, -8,
|
56
|
+
:ERROR_PIPE, -9,
|
57
|
+
:ERROR_INTERRUPTED, -10,
|
58
|
+
:ERROR_NO_MEM, -11,
|
59
|
+
:ERROR_NOT_SUPPORTED, -12,
|
60
|
+
:ERROR_OTHER, -99,
|
61
|
+
]
|
62
|
+
|
63
|
+
# Transfer status codes
|
64
|
+
TransferStatus = enum :libusb_transfer_status, [
|
65
|
+
:TRANSFER_COMPLETED,
|
66
|
+
:TRANSFER_ERROR,
|
67
|
+
:TRANSFER_TIMED_OUT,
|
68
|
+
:TRANSFER_CANCELLED,
|
69
|
+
:TRANSFER_STALL,
|
70
|
+
:TRANSFER_NO_DEVICE,
|
71
|
+
:TRANSFER_OVERFLOW,
|
72
|
+
]
|
73
|
+
|
74
|
+
# libusb_transfer.flags values
|
75
|
+
TransferFlags = enum :libusb_transfer_flags, [
|
76
|
+
:TRANSFER_SHORT_NOT_OK, 1 << 0,
|
77
|
+
:TRANSFER_FREE_BUFFER, 1 << 1,
|
78
|
+
:TRANSFER_FREE_TRANSFER, 1 << 2,
|
79
|
+
:TRANSFER_ADD_ZERO_PACKET, 1 << 3,
|
80
|
+
]
|
81
|
+
|
82
|
+
TransferTypes = enum :libusb_transfer_type, [
|
83
|
+
:TRANSFER_TYPE_CONTROL, 0,
|
84
|
+
:TRANSFER_TYPE_ISOCHRONOUS, 1,
|
85
|
+
:TRANSFER_TYPE_BULK, 2,
|
86
|
+
:TRANSFER_TYPE_INTERRUPT, 3,
|
87
|
+
]
|
88
|
+
|
89
|
+
StandardRequests = enum :libusb_standard_request, [
|
90
|
+
:REQUEST_GET_STATUS, 0x00,
|
91
|
+
:REQUEST_CLEAR_FEATURE, 0x01,
|
92
|
+
:REQUEST_SET_FEATURE, 0x03,
|
93
|
+
:REQUEST_SET_ADDRESS, 0x05,
|
94
|
+
:REQUEST_GET_DESCRIPTOR, 0x06,
|
95
|
+
:REQUEST_SET_DESCRIPTOR, 0x07,
|
96
|
+
:REQUEST_GET_CONFIGURATION, 0x08,
|
97
|
+
:REQUEST_SET_CONFIGURATION, 0x09,
|
98
|
+
:REQUEST_GET_INTERFACE, 0x0A,
|
99
|
+
:REQUEST_SET_INTERFACE, 0x0B,
|
100
|
+
:REQUEST_SYNCH_FRAME, 0x0C,
|
101
|
+
]
|
102
|
+
|
103
|
+
EndpointDirections = enum :libusb_endpoint_direction, [
|
104
|
+
:ENDPOINT_IN, 0x80,
|
105
|
+
:ENDPOINT_OUT, 0x00,
|
106
|
+
]
|
107
|
+
|
108
|
+
DescriptorTypes = enum :libusb_descriptor_type, [
|
109
|
+
:DT_DEVICE, 0x01,
|
110
|
+
:DT_CONFIG, 0x02,
|
111
|
+
:DT_STRING, 0x03,
|
112
|
+
:DT_INTERFACE, 0x04,
|
113
|
+
:DT_ENDPOINT, 0x05,
|
114
|
+
:DT_HID, 0x21,
|
115
|
+
:DT_REPORT, 0x22,
|
116
|
+
:DT_PHYSICAL, 0x23,
|
117
|
+
:DT_HUB, 0x29,
|
118
|
+
]
|
119
|
+
|
120
|
+
RequestTypes = enum :libusb_request_type, [
|
121
|
+
:REQUEST_TYPE_STANDARD, (0x00 << 5),
|
122
|
+
:REQUEST_TYPE_CLASS, (0x01 << 5),
|
123
|
+
:REQUEST_TYPE_VENDOR, (0x02 << 5),
|
124
|
+
:REQUEST_TYPE_RESERVED, (0x03 << 5),
|
125
|
+
]
|
126
|
+
|
127
|
+
RequestRecipients = enum :libusb_request_recipient, [
|
128
|
+
:RECIPIENT_DEVICE, 0x00,
|
129
|
+
:RECIPIENT_INTERFACE, 0x01,
|
130
|
+
:RECIPIENT_ENDPOINT, 0x02,
|
131
|
+
:RECIPIENT_OTHER, 0x03,
|
132
|
+
]
|
133
|
+
|
134
|
+
IsoSyncTypes = enum :libusb_iso_sync_type, [
|
135
|
+
:ISO_SYNC_TYPE_NONE, 0,
|
136
|
+
:ISO_SYNC_TYPE_ASYNC, 1,
|
137
|
+
:ISO_SYNC_TYPE_ADAPTIVE, 2,
|
138
|
+
:ISO_SYNC_TYPE_SYNC, 3,
|
139
|
+
]
|
140
|
+
|
141
|
+
Speeds = enum :libusb_speed, [
|
142
|
+
:SPEED_UNKNOWN, 0,
|
143
|
+
:SPEED_LOW, 1,
|
144
|
+
:SPEED_FULL, 2,
|
145
|
+
:SPEED_HIGH, 3,
|
146
|
+
:SPEED_SUPER, 4,
|
147
|
+
]
|
148
|
+
|
149
|
+
Capabilities = enum :libusb_capability, [
|
150
|
+
:CAP_HAS_CAPABILITY, 0,
|
151
|
+
]
|
152
|
+
|
153
|
+
typedef :pointer, :libusb_context
|
154
|
+
typedef :pointer, :libusb_device_handle
|
155
|
+
|
156
|
+
def self.try_attach_function(method, *args)
|
157
|
+
if ffi_libraries.find{|lib| lib.find_function(method) }
|
158
|
+
attach_function method, *args
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
try_attach_function 'libusb_get_version', [], :pointer
|
163
|
+
|
164
|
+
attach_function 'libusb_init', [ :pointer ], :int
|
165
|
+
attach_function 'libusb_exit', [ :pointer ], :void
|
166
|
+
attach_function 'libusb_set_debug', [:pointer, :int], :void
|
167
|
+
try_attach_function 'libusb_has_capability', [:libusb_capability], :int
|
168
|
+
|
169
|
+
attach_function 'libusb_get_device_list', [:pointer, :pointer], :size_t
|
170
|
+
attach_function 'libusb_free_device_list', [:pointer, :int], :void
|
171
|
+
attach_function 'libusb_ref_device', [:pointer], :pointer
|
172
|
+
attach_function 'libusb_unref_device', [:pointer], :void
|
173
|
+
|
174
|
+
attach_function 'libusb_get_device_descriptor', [:pointer, :pointer], :int
|
175
|
+
attach_function 'libusb_get_active_config_descriptor', [:pointer, :pointer], :int
|
176
|
+
attach_function 'libusb_get_config_descriptor', [:pointer, :uint8, :pointer], :int
|
177
|
+
attach_function 'libusb_get_config_descriptor_by_value', [:pointer, :uint8, :pointer], :int
|
178
|
+
attach_function 'libusb_free_config_descriptor', [:pointer], :void
|
179
|
+
attach_function 'libusb_get_bus_number', [:pointer], :uint8
|
180
|
+
try_attach_function 'libusb_get_port_number', [:pointer], :uint8
|
181
|
+
try_attach_function 'libusb_get_parent', [:pointer], :pointer
|
182
|
+
try_attach_function 'libusb_get_port_path', [:pointer, :pointer, :pointer, :uint8], :uint8
|
183
|
+
attach_function 'libusb_get_device_address', [:pointer], :uint8
|
184
|
+
try_attach_function 'libusb_get_device_speed', [:pointer], :libusb_speed
|
185
|
+
attach_function 'libusb_get_max_packet_size', [:pointer, :uint8], :int
|
186
|
+
attach_function 'libusb_get_max_iso_packet_size', [:pointer, :uint8], :int
|
187
|
+
|
188
|
+
attach_function 'libusb_open', [:pointer, :pointer], :int
|
189
|
+
attach_function 'libusb_close', [:pointer], :void
|
190
|
+
attach_function 'libusb_get_device', [:libusb_device_handle], :pointer
|
191
|
+
|
192
|
+
attach_function 'libusb_set_configuration', [:libusb_device_handle, :int], :int, :blocking=>true
|
193
|
+
attach_function 'libusb_claim_interface', [:libusb_device_handle, :int], :int
|
194
|
+
attach_function 'libusb_release_interface', [:libusb_device_handle, :int], :int, :blocking=>true
|
195
|
+
|
196
|
+
attach_function 'libusb_open_device_with_vid_pid', [:pointer, :int, :int], :pointer
|
197
|
+
|
198
|
+
attach_function 'libusb_set_interface_alt_setting', [:libusb_device_handle, :int, :int], :int, :blocking=>true
|
199
|
+
attach_function 'libusb_clear_halt', [:libusb_device_handle, :int], :int, :blocking=>true
|
200
|
+
attach_function 'libusb_reset_device', [:libusb_device_handle], :int, :blocking=>true
|
201
|
+
|
202
|
+
attach_function 'libusb_kernel_driver_active', [:libusb_device_handle, :int], :int
|
203
|
+
attach_function 'libusb_detach_kernel_driver', [:libusb_device_handle, :int], :int
|
204
|
+
attach_function 'libusb_attach_kernel_driver', [:libusb_device_handle, :int], :int
|
205
|
+
|
206
|
+
attach_function 'libusb_get_string_descriptor_ascii', [:pointer, :uint8, :pointer, :int], :int
|
207
|
+
|
208
|
+
attach_function 'libusb_alloc_transfer', [:int], :pointer
|
209
|
+
attach_function 'libusb_submit_transfer', [:pointer], :int
|
210
|
+
attach_function 'libusb_cancel_transfer', [:pointer], :int
|
211
|
+
attach_function 'libusb_free_transfer', [:pointer], :void
|
212
|
+
|
213
|
+
attach_function 'libusb_handle_events', [:libusb_context], :int, :blocking=>true
|
214
|
+
|
215
|
+
|
216
|
+
callback :libusb_transfer_cb_fn, [:pointer], :void
|
217
|
+
|
218
|
+
class IsoPacketDescriptor < FFI::Struct
|
219
|
+
layout :length, :uint,
|
220
|
+
:actual_length, :uint,
|
221
|
+
:status, :libusb_transfer_status
|
222
|
+
end
|
223
|
+
|
224
|
+
# Setup packet for control transfers.
|
225
|
+
class ControlSetup < FFI::Struct
|
226
|
+
layout :bmRequestType, :uint8,
|
227
|
+
:bRequest, :uint8,
|
228
|
+
:wValue, :uint16,
|
229
|
+
:wIndex, :uint16,
|
230
|
+
:wLength, :uint16
|
231
|
+
end
|
232
|
+
|
233
|
+
class Transfer < FFI::ManagedStruct
|
234
|
+
layout :dev_handle, :libusb_device_handle,
|
235
|
+
:flags, :uint8,
|
236
|
+
:endpoint, :uchar,
|
237
|
+
:type, :uchar,
|
238
|
+
:timeout, :uint,
|
239
|
+
:status, :libusb_transfer_status,
|
240
|
+
:length, :int,
|
241
|
+
:actual_length, :int,
|
242
|
+
:callback, :libusb_transfer_cb_fn,
|
243
|
+
:user_data, :pointer,
|
244
|
+
:buffer, :pointer,
|
245
|
+
:num_iso_packets, :int
|
246
|
+
|
247
|
+
def self.release(ptr)
|
248
|
+
Call.libusb_free_transfer(ptr)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
class DeviceDescriptor < FFI::Struct
|
253
|
+
include Comparable
|
254
|
+
|
255
|
+
layout :bLength, :uint8,
|
256
|
+
:bDescriptorType, :uint8,
|
257
|
+
:bcdUSB, :uint16,
|
258
|
+
:bDeviceClass, :uint8,
|
259
|
+
:bDeviceSubClass, :uint8,
|
260
|
+
:bDeviceProtocol, :uint8,
|
261
|
+
:bMaxPacketSize0, :uint8,
|
262
|
+
:idVendor, :uint16,
|
263
|
+
:idProduct, :uint16,
|
264
|
+
:bcdDevice, :uint16,
|
265
|
+
:iManufacturer, :uint8,
|
266
|
+
:iProduct, :uint8,
|
267
|
+
:iSerialNumber, :uint8,
|
268
|
+
:bNumConfigurations, :uint8
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
data/lib/libusb/compat.rb
CHANGED
@@ -97,8 +97,8 @@ module USB
|
|
97
97
|
USB_RECIP_ENDPOINT = LIBUSB::RECIPIENT_ENDPOINT
|
98
98
|
USB_RECIP_OTHER = LIBUSB::RECIPIENT_OTHER
|
99
99
|
|
100
|
-
HAS_GET_DRIVER_NP =
|
101
|
-
HAS_DETACH_KERNEL_DRIVER_NP =
|
100
|
+
HAS_GET_DRIVER_NP = !FFI::Platform.windows?
|
101
|
+
HAS_DETACH_KERNEL_DRIVER_NP = !FFI::Platform.windows?
|
102
102
|
|
103
103
|
# not defined by libusb-1.0, but typical values are:
|
104
104
|
USB_MAXENDPOINTS = 32
|
@@ -0,0 +1,139 @@
|
|
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 Configuration < FFI::ManagedStruct
|
20
|
+
include Comparable
|
21
|
+
|
22
|
+
layout :bLength, :uint8,
|
23
|
+
:bDescriptorType, :uint8,
|
24
|
+
:wTotalLength, :uint16,
|
25
|
+
:bNumInterfaces, :uint8,
|
26
|
+
:bConfigurationValue, :uint8,
|
27
|
+
:iConfiguration, :uint8,
|
28
|
+
:bmAttributes, :uint8,
|
29
|
+
:maxPower, :uint8,
|
30
|
+
:interface, :pointer,
|
31
|
+
:extra, :pointer,
|
32
|
+
:extra_length, :int
|
33
|
+
|
34
|
+
# Size of this descriptor (in bytes).
|
35
|
+
def bLength
|
36
|
+
self[:bLength]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Descriptor type (0x02)
|
40
|
+
def bDescriptorType
|
41
|
+
self[:bDescriptorType]
|
42
|
+
end
|
43
|
+
|
44
|
+
# Total length of data returned for this configuration.
|
45
|
+
def wTotalLength
|
46
|
+
self[:wTotalLength]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Number of interfaces supported by this configuration.
|
50
|
+
def bNumInterfaces
|
51
|
+
self[:bNumInterfaces]
|
52
|
+
end
|
53
|
+
|
54
|
+
# Identifier value for this configuration.
|
55
|
+
def bConfigurationValue
|
56
|
+
self[:bConfigurationValue]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Index of string descriptor describing this configuration.
|
60
|
+
def iConfiguration
|
61
|
+
self[:iConfiguration]
|
62
|
+
end
|
63
|
+
|
64
|
+
# Configuration characteristics.
|
65
|
+
#
|
66
|
+
# * Bit 7: Reserved, set to 1. (USB 1.0 Bus Powered)
|
67
|
+
# * Bit 6: Self Powered
|
68
|
+
# * Bit 5: Remote Wakeup
|
69
|
+
# * Bit 4..0: Reserved, set to 0.
|
70
|
+
#
|
71
|
+
# @return [Integer]
|
72
|
+
def bmAttributes
|
73
|
+
self[:bmAttributes]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Maximum power consumption of the USB device from this bus in this configuration when the device is fully opreation.
|
77
|
+
#
|
78
|
+
# @return [Integer] Maximum Power Consumption in 2mA units
|
79
|
+
def maxPower
|
80
|
+
self[:maxPower]
|
81
|
+
end
|
82
|
+
|
83
|
+
# Extra descriptors.
|
84
|
+
#
|
85
|
+
# @return [String]
|
86
|
+
def extra
|
87
|
+
return if self[:extra].null?
|
88
|
+
self[:extra].read_string(self[:extra_length])
|
89
|
+
end
|
90
|
+
|
91
|
+
def initialize(device, *args)
|
92
|
+
@device = device
|
93
|
+
super(*args)
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.release(ptr)
|
97
|
+
Call.libusb_free_config_descriptor(ptr)
|
98
|
+
end
|
99
|
+
|
100
|
+
# @return [Device] the device this configuration belongs to.
|
101
|
+
attr_reader :device
|
102
|
+
|
103
|
+
def interfaces
|
104
|
+
ifs = []
|
105
|
+
self[:bNumInterfaces].times do |i|
|
106
|
+
ifs << Interface.new(self, self[:interface] + i*Interface.size)
|
107
|
+
end
|
108
|
+
return ifs
|
109
|
+
end
|
110
|
+
|
111
|
+
def inspect
|
112
|
+
attrs = []
|
113
|
+
attrs << self.bConfigurationValue.to_s
|
114
|
+
bits = self.bmAttributes
|
115
|
+
attrs << "SelfPowered" if (bits & 0b1000000) != 0
|
116
|
+
attrs << "RemoteWakeup" if (bits & 0b100000) != 0
|
117
|
+
desc = self.description
|
118
|
+
attrs << desc if desc != '?'
|
119
|
+
"\#<#{self.class} #{attrs.join(' ')}>"
|
120
|
+
end
|
121
|
+
|
122
|
+
# Return name of this configuration as String.
|
123
|
+
def description
|
124
|
+
return @description if defined? @description
|
125
|
+
@description = device.try_string_descriptor_ascii(self.iConfiguration)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Return all interface decriptions of the configuration as Array of {Setting}s.
|
129
|
+
def settings() self.interfaces.map {|d| d.settings }.flatten end
|
130
|
+
# Return all endpoints of all interfaces of the configuration as Array of {Endpoint}s.
|
131
|
+
def endpoints() self.settings.map {|d| d.endpoints }.flatten end
|
132
|
+
|
133
|
+
def <=>(o)
|
134
|
+
t = device<=>o.device
|
135
|
+
t = bConfigurationValue<=>o.bConfigurationValue if t==0
|
136
|
+
t
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,138 @@
|
|
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
|
+
Call::ClassCodes.to_h.each{|k,v| const_set(k,v) }
|
20
|
+
Call::TransferTypes.to_h.each{|k,v| const_set(k,v) }
|
21
|
+
Call::StandardRequests.to_h.each{|k,v| const_set(k,v) }
|
22
|
+
Call::RequestTypes.to_h.each{|k,v| const_set(k,v) }
|
23
|
+
Call::DescriptorTypes.to_h.each{|k,v| const_set(k,v) }
|
24
|
+
Call::EndpointDirections.to_h.each{|k,v| const_set(k,v) }
|
25
|
+
Call::RequestRecipients.to_h.each{|k,v| const_set(k,v) }
|
26
|
+
Call::IsoSyncTypes.to_h.each{|k,v| const_set(k,v) }
|
27
|
+
Call::Speeds.to_h.each{|k,v| const_set(k,v) }
|
28
|
+
Call::Capabilities.to_h.each{|k,v| const_set(k,v) }
|
29
|
+
|
30
|
+
# Base class of libusb errors
|
31
|
+
class Error < RuntimeError
|
32
|
+
end
|
33
|
+
# @private
|
34
|
+
ErrorClassForResult = {}
|
35
|
+
|
36
|
+
# define an exception class for each error code
|
37
|
+
Call::Errors.to_h.each do |k,v|
|
38
|
+
klass = Class.new(Error)
|
39
|
+
klass.send(:define_method, :code){ v }
|
40
|
+
const_set(k, klass)
|
41
|
+
ErrorClassForResult[v] = klass
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.raise_error(res, text)
|
45
|
+
klass = ErrorClassForResult[res]
|
46
|
+
raise klass, "#{klass} #{text}"
|
47
|
+
end
|
48
|
+
|
49
|
+
CONTROL_SETUP_SIZE = 8
|
50
|
+
DT_DEVICE_SIZE = 18
|
51
|
+
DT_CONFIG_SIZE = 9
|
52
|
+
DT_INTERFACE_SIZE = 9
|
53
|
+
DT_ENDPOINT_SIZE = 7
|
54
|
+
DT_ENDPOINT_AUDIO_SIZE = 9 # Audio extension
|
55
|
+
DT_HUB_NONVAR_SIZE = 7
|
56
|
+
|
57
|
+
ENDPOINT_ADDRESS_MASK = 0x0f # in bEndpointAddress
|
58
|
+
ENDPOINT_DIR_MASK = 0x80
|
59
|
+
TRANSFER_TYPE_MASK = 0x03 # in bmAttributes
|
60
|
+
ISO_SYNC_TYPE_MASK = 0x0C
|
61
|
+
ISO_USAGE_TYPE_MASK = 0x30
|
62
|
+
|
63
|
+
|
64
|
+
# http://www.usb.org/developers/defined_class
|
65
|
+
# @private
|
66
|
+
CLASS_CODES = [
|
67
|
+
[0x01, nil, nil, "Audio"],
|
68
|
+
[0x02, nil, nil, "Comm"],
|
69
|
+
[0x03, nil, nil, "HID"],
|
70
|
+
[0x05, nil, nil, "Physical"],
|
71
|
+
[0x06, 0x01, 0x01, "StillImaging"],
|
72
|
+
[0x06, nil, nil, "Image"],
|
73
|
+
[0x07, nil, nil, "Printer"],
|
74
|
+
[0x08, 0x01, nil, "MassStorage RBC Bluk-Only"],
|
75
|
+
[0x08, 0x02, 0x50, "MassStorage ATAPI Bluk-Only"],
|
76
|
+
[0x08, 0x03, 0x50, "MassStorage QIC-157 Bluk-Only"],
|
77
|
+
[0x08, 0x04, nil, "MassStorage UFI"],
|
78
|
+
[0x08, 0x05, 0x50, "MassStorage SFF-8070i Bluk-Only"],
|
79
|
+
[0x08, 0x06, 0x50, "MassStorage SCSI Bluk-Only"],
|
80
|
+
[0x08, nil, nil, "MassStorage"],
|
81
|
+
[0x09, 0x00, 0x00, "Full speed Hub"],
|
82
|
+
[0x09, 0x00, 0x01, "Hi-speed Hub with single TT"],
|
83
|
+
[0x09, 0x00, 0x02, "Hi-speed Hub with multiple TTs"],
|
84
|
+
[0x09, nil, nil, "Hub"],
|
85
|
+
[0x0a, nil, nil, "CDC"],
|
86
|
+
[0x0b, nil, nil, "SmartCard"],
|
87
|
+
[0x0d, 0x00, 0x00, "ContentSecurity"],
|
88
|
+
[0x0e, nil, nil, "Video"],
|
89
|
+
[0xdc, 0x01, 0x01, "Diagnostic USB2"],
|
90
|
+
[0xdc, nil, nil, "Diagnostic"],
|
91
|
+
[0xe0, 0x01, 0x01, "Bluetooth"],
|
92
|
+
[0xe0, 0x01, 0x02, "UWB"],
|
93
|
+
[0xe0, 0x01, 0x03, "RemoteNDIS"],
|
94
|
+
[0xe0, 0x02, 0x01, "Host Wire Adapter Control/Data"],
|
95
|
+
[0xe0, 0x02, 0x02, "Device Wire Adapter Control/Data"],
|
96
|
+
[0xe0, 0x02, 0x03, "Device Wire Adapter Isochronous"],
|
97
|
+
[0xe0, nil, nil, "Wireless Controller"],
|
98
|
+
[0xef, 0x01, 0x01, "Active Sync"],
|
99
|
+
[0xef, 0x01, 0x02, "Palm Sync"],
|
100
|
+
[0xef, 0x02, 0x01, "Interface Association Descriptor"],
|
101
|
+
[0xef, 0x02, 0x02, "Wire Adapter Multifunction Peripheral"],
|
102
|
+
[0xef, 0x03, 0x01, "Cable Based Association Framework"],
|
103
|
+
[0xef, nil, nil, "Miscellaneous"],
|
104
|
+
[0xfe, 0x01, 0x01, "Device Firmware Upgrade"],
|
105
|
+
[0xfe, 0x02, 0x00, "IRDA Bridge"],
|
106
|
+
[0xfe, 0x03, 0x00, "USB Test and Measurement"],
|
107
|
+
[0xfe, 0x03, 0x01, "USB Test and Measurement (USBTMC USB488)"],
|
108
|
+
[0xfe, nil, nil, "Application Specific"],
|
109
|
+
[0xff, nil, nil, "Vendor specific"],
|
110
|
+
]
|
111
|
+
# @private
|
112
|
+
CLASS_CODES_HASH1 = {}
|
113
|
+
# @private
|
114
|
+
CLASS_CODES_HASH2 = {}
|
115
|
+
# @private
|
116
|
+
CLASS_CODES_HASH3 = {}
|
117
|
+
CLASS_CODES.each {|base_class, sub_class, protocol, desc|
|
118
|
+
if protocol
|
119
|
+
CLASS_CODES_HASH3[[base_class, sub_class, protocol]] = desc
|
120
|
+
elsif sub_class
|
121
|
+
CLASS_CODES_HASH2[[base_class, sub_class]] = desc
|
122
|
+
else
|
123
|
+
CLASS_CODES_HASH1[base_class] = desc
|
124
|
+
end
|
125
|
+
}
|
126
|
+
|
127
|
+
def self.dev_string(base_class, sub_class, protocol)
|
128
|
+
if desc = CLASS_CODES_HASH3[[base_class, sub_class, protocol]]
|
129
|
+
desc
|
130
|
+
elsif desc = CLASS_CODES_HASH2[[base_class, sub_class]]
|
131
|
+
desc + " (%02x)" % [protocol]
|
132
|
+
elsif desc = CLASS_CODES_HASH1[base_class]
|
133
|
+
desc + " (%02x,%02x)" % [sub_class, protocol]
|
134
|
+
else
|
135
|
+
"Unkonwn(%02x,%02x,%02x)" % [base_class, sub_class, protocol]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|