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,174 @@
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
+ #
51
+ # @see #endpoint_number
52
+ # @see #direction
53
+ def bEndpointAddress
54
+ self[:bEndpointAddress]
55
+ end
56
+
57
+ # @return [Integer]
58
+ def endpoint_number
59
+ bEndpointAddress & 0b1111
60
+ end
61
+
62
+ # @return [Symbol] Either +:in+ or +:out+
63
+ def direction
64
+ bEndpointAddress & ENDPOINT_IN == 0 ? :out : :in
65
+ end
66
+
67
+ # Attributes which apply to the endpoint when it is configured using the {Configuration#bConfigurationValue}.
68
+ #
69
+ # * Bits 1..0: Transfer Type
70
+ # * 00 = Control
71
+ # * 01 = Isochronous
72
+ # * 10 = Bulk
73
+ # * 11 = Interrupt
74
+ # * Bits 7..2: are reserved. If Isochronous endpoint,
75
+ # * Bits 3..2: Synchronisation Type (Iso Mode)
76
+ # * 00 = No Synchonisation
77
+ # * 01 = Asynchronous
78
+ # * 10 = Adaptive
79
+ # * 11 = Synchronous
80
+ # * Bits 5..4: Usage Type (Iso Mode)
81
+ # * 00 = Data Endpoint
82
+ # * 01 = Feedback Endpoint
83
+ # * 10 = Explicit Feedback Data Endpoint
84
+ # * 11 = Reserved
85
+ #
86
+ # @return [Integer]
87
+ #
88
+ # @see #transfer_type
89
+ # @see #usage_type
90
+ # @see #synchronization_type
91
+ def bmAttributes
92
+ self[:bmAttributes]
93
+ end
94
+
95
+ TransferTypes = [:control, :isochronous, :bulk, :interrupt]
96
+ # @return [Symbol] One of {TransferTypes}
97
+ def transfer_type
98
+ TransferTypes[bmAttributes & 0b11]
99
+ end
100
+
101
+ SynchronizationTypes = [:no_synchronization, :asynchronous, :adaptive, :synchronous]
102
+ # @return [Symbol] One of {SynchronizationTypes}
103
+ def synchronization_type
104
+ return unless transfer_type == :isochronous
105
+ SynchronizationTypes[(bmAttributes & 0b1100) >> 2]
106
+ end
107
+
108
+ UsageTypes = [:data, :feedback, :implicit_feedback, :unknown]
109
+ # @return [Symbol] One of {UsageTypes}
110
+ def usage_type
111
+ return unless transfer_type == :isochronous
112
+ UsageTypes[(bmAttributes & 0b110000) >> 4]
113
+ end
114
+
115
+ # Maximum Packet Size this endpoint is capable of sending or receiving
116
+ def wMaxPacketSize
117
+ self[:wMaxPacketSize]
118
+ end
119
+
120
+ # Interval for polling endpoint data transfers. Value in frame counts.
121
+ # Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field
122
+ # may range from 1 to 255 for interrupt endpoints.
123
+ #
124
+ # The interval is respected by the kernel driver, so user mode processes
125
+ # using libusb don't need to care about it.
126
+ def bInterval
127
+ self[:bInterval]
128
+ end
129
+
130
+ # For audio devices only: the rate at which synchronization feedback is provided.
131
+ def bRefresh
132
+ self[:bRefresh]
133
+ end
134
+
135
+ # For audio devices only: the address if the synch endpoint.
136
+ def bSynchAddress
137
+ self[:bSynchAddress]
138
+ end
139
+
140
+ # Extra descriptors.
141
+ #
142
+ # @return [String]
143
+ def extra
144
+ return if self[:extra].null?
145
+ self[:extra].read_string(self[:extra_length])
146
+ end
147
+
148
+ def initialize(setting, *args)
149
+ @setting = setting
150
+ super(*args)
151
+ end
152
+
153
+ # @return [Setting] the setting this endpoint belongs to.
154
+ attr_reader :setting
155
+
156
+ def inspect
157
+ type = [transfer_type, synchronization_type, usage_type].compact
158
+ "\#<#{self.class} #{endpoint_number} #{direction} #{type.join(" ")}>"
159
+ end
160
+
161
+ # The {Device} this Endpoint belongs to.
162
+ def device() self.setting.interface.configuration.device end
163
+ # The {Configuration} this Endpoint belongs to.
164
+ def configuration() self.setting.interface.configuration end
165
+ # The {Interface} this Endpoint belongs to.
166
+ def interface() self.setting.interface end
167
+
168
+ def <=>(o)
169
+ t = setting<=>o.setting
170
+ t = bEndpointAddress<=>o.bEndpointAddress if t==0
171
+ t
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,183 @@
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'
17
+ require 'eventmachine'
18
+
19
+ module LIBUSB
20
+ class Context
21
+ # Register libusb's file descriptors and timeouts to EventMachine.
22
+ #
23
+ # @example
24
+ # require 'libusb/eventmachine'
25
+ # context = LIBUSB::Context.new
26
+ # EventMachine.run do
27
+ # context.eventmachine_register
28
+ # end
29
+ #
30
+ # @see
31
+ # DevHandle#eventmachine_bulk_transfer
32
+ # DevHandle#eventmachine_control_transfer
33
+ # DevHandle#eventmachine_interrupt_transfer
34
+ def eventmachine_register
35
+ @eventmachine_attached_fds = {}
36
+ @eventmachine_timer = nil
37
+
38
+ pollfds = self.pollfds
39
+ if pollfds
40
+ pollfds.each do |pollfd|
41
+ eventmachine_add_pollfd(pollfd)
42
+ end
43
+
44
+ self.on_pollfd_added do |pollfd|
45
+ eventmachine_add_pollfd(pollfd)
46
+ end
47
+
48
+ self.on_pollfd_removed do |pollfd|
49
+ eventmachine_rm_pollfd(pollfd)
50
+ end
51
+ else
52
+ # Libusb pollfd API is not available on this platform.
53
+ # Use simple polling timer, instead:
54
+ EventMachine.add_periodic_timer(0.01) do
55
+ @eventmachine_timer = self.handle_events 0
56
+ end
57
+ end
58
+ end
59
+
60
+ def eventmachine_unregister
61
+ @eventmachine_timer.cancel if @eventmachine_timer
62
+ @eventmachine_attached_fds.each do |fd, watcher|
63
+ watcher.detach
64
+ end
65
+ end
66
+
67
+ class EMPollfdHandler < EventMachine::Connection
68
+ def initialize
69
+ @callbacks = []
70
+ super
71
+ end
72
+
73
+ def on_need_handle_events(&block)
74
+ @callbacks << block
75
+ end
76
+
77
+ def need_handle_events
78
+ @callbacks.each do |cb|
79
+ cb.call
80
+ end
81
+ end
82
+ alias notify_readable need_handle_events
83
+ alias notify_writable need_handle_events
84
+ end
85
+
86
+ private
87
+ def eventmachine_add_pollfd(pollfd)
88
+ conn = EventMachine.watch(pollfd.io, EMPollfdHandler)
89
+ conn.notify_readable = pollfd.pollin?
90
+ conn.notify_writable = pollfd.pollout?
91
+ cb = proc do
92
+ if @eventmachine_timer
93
+ @eventmachine_timer.cancel
94
+ @eventmachine_timer = nil
95
+ end
96
+
97
+ self.handle_events 0
98
+ timeout = self.next_timeout
99
+ # puts "libusb new timeout: #{timeout.inspect}"
100
+ if timeout
101
+ @eventmachine_timer = EventMachine.add_timer(timeout, &cb)
102
+ end
103
+ end
104
+ conn.on_need_handle_events(&cb)
105
+
106
+ @eventmachine_attached_fds[pollfd.fd] = conn
107
+ # puts "libusb pollfd added: #{pollfd.inspect}"
108
+ end
109
+
110
+ def eventmachine_rm_pollfd(pollfd)
111
+ @eventmachine_attached_fds[pollfd.fd].detach
112
+ # puts "libusb pollfd removed: #{pollfd.inspect}"
113
+ end
114
+ end
115
+
116
+ class DevHandle
117
+ class EMTransfer
118
+ include EM::Deferrable
119
+
120
+ def initialize(opts, dev_handle, transfer_method)
121
+ dev_handle.send(transfer_method, opts) do |res|
122
+ EM.next_tick do
123
+ if res.kind_of?(LIBUSB::Error)
124
+ fail res
125
+ else
126
+ succeed res
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ # Execute an eventmachine driven USB interrupt transfer.
134
+ #
135
+ # @see Context#eventmachine_register
136
+ # DevHandle#interrupt_transfer
137
+ def eventmachine_interrupt_transfer(opts={})
138
+ eventmachine_transfer(opts, :interrupt_transfer)
139
+ end
140
+
141
+ # Execute an eventmachine driven USB bulk transfer.
142
+ #
143
+ # @example
144
+ # tr = devh.eventmachine_bulk_transfer( :endpoint => 0x02, :dataOut => "data" )
145
+ # tr.callback do |data|
146
+ # puts "sent: #{data.inspect}"
147
+ # end
148
+ # tr.errback do |ex|
149
+ # puts "send-err: #{ex}"
150
+ # end
151
+ #
152
+ # @see Context#eventmachine_register
153
+ # DevHandle#bulk_transfer
154
+ def eventmachine_bulk_transfer(opts={})
155
+ eventmachine_transfer(opts, :bulk_transfer)
156
+ end
157
+
158
+ # Execute an eventmachine driven USB control transfer.
159
+ #
160
+ # @example
161
+ # tr = devh.eventmachine_control_transfer(
162
+ # :bmRequestType=>ENDPOINT_IN|REQUEST_TYPE_CLASS|RECIPIENT_INTERFACE,
163
+ # :bRequest=>0x01,
164
+ # :wValue=>0, :wIndex=>0, :dataIn=>1 )
165
+ # tr.callback do |data|
166
+ # puts "recved: #{data.inspect}"
167
+ # end
168
+ # tr.errback do |ex|
169
+ # puts "recv-err: #{ex}"
170
+ # end
171
+ #
172
+ # @see Context#eventmachine_register
173
+ # DevHandle#control_transfer
174
+ def eventmachine_control_transfer(opts={})
175
+ eventmachine_transfer(opts, :control_transfer)
176
+ end
177
+
178
+ private
179
+ def eventmachine_transfer(opts, method)
180
+ EMTransfer.new opts, self, method
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,60 @@
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
+ # Number of this interface.
26
+ def bInterfaceNumber
27
+ settings.first.bInterfaceNumber
28
+ end
29
+
30
+ def initialize(configuration, *args)
31
+ @configuration = configuration
32
+ super(*args)
33
+ end
34
+
35
+ # @return [Configuration] the configuration this interface belongs to.
36
+ attr_reader :configuration
37
+
38
+ def alt_settings
39
+ ifs = []
40
+ self[:num_altsetting].times do |i|
41
+ ifs << Setting.new(self, self[:altsetting] + i*Setting.size)
42
+ end
43
+ return ifs
44
+ end
45
+ alias settings alt_settings
46
+
47
+ def inspect
48
+ "\#<#{self.class} #{bInterfaceNumber}>"
49
+ end
50
+
51
+ # The {Device} this Interface belongs to.
52
+ def device() self.configuration.device end
53
+ # Return all endpoints of all alternative settings as Array of {Endpoint}s.
54
+ def endpoints() self.alt_settings.map {|d| d.endpoints }.flatten end
55
+
56
+ def <=>(o)
57
+ configuration<=>o.configuration
58
+ end
59
+ end
60
+ 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 the interface this setting belongs to.
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