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,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 = RUBY_PLATFORM=~/mswin|mingw/ ? false : true
101
- HAS_DETACH_KERNEL_DRIVER_NP = RUBY_PLATFORM=~/mswin|mingw/ ? false : true
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