Class: LIBUSB::Transfer
- Inherits:
-
Object
- Object
- LIBUSB::Transfer
- Defined in:
- lib/libusb/transfer.rb
Overview
Abstract base class for USB transfers. Use ControlTransfer, BulkTransfer, InterruptTransfer, IsochronousTransfer to do transfers.
There are convenience methods for DevHandle#bulk_transfer, DevHandle#control_transfer and DevHandle#interrupt_transfer, that fit for most use cases. Using Transfer derived classes directly, however, is needed for isochronous transfers and allows a more advanced buffer management.
Direct Known Subclasses
BulkTransfer, ControlTransfer, InterruptTransfer, IsochronousTransfer
Constant Summary collapse
- TransferStatusToError =
{ :TRANSFER_ERROR => LIBUSB::ERROR_IO, :TRANSFER_TIMED_OUT => LIBUSB::ERROR_TIMEOUT, :TRANSFER_CANCELLED => LIBUSB::ERROR_INTERRUPTED, :TRANSFER_STALL => LIBUSB::ERROR_PIPE, :TRANSFER_NO_DEVICE => LIBUSB::ERROR_NO_DEVICE, :TRANSFER_OVERFLOW => LIBUSB::ERROR_OVERFLOW, }
Instance Method Summary collapse
-
#actual_buffer(offset = 0) ⇒ Object
Retrieve the data actually transferred.
-
#actual_length ⇒ Object
The number of bytes actually transferred.
-
#alloc_buffer(len, data = nil) ⇒ Object
Allocate
lenbytes of data buffer for input transfer. -
#buffer ⇒ Object
Retrieve the current data buffer.
-
#buffer=(data) ⇒ Object
Set output data that should be sent.
-
#callback=(proc) ⇒ Object
Set the block that will be invoked when the transfer completes, fails, or is cancelled.
-
#cancel! ⇒ Object
Asynchronously cancel a previously submitted transfer.
-
#dev_handle=(dev) ⇒ Object
Set the handle for the device to communicate with.
-
#endpoint=(endpoint) ⇒ Object
Set the address of a valid endpoint to communicate with.
-
#free_buffer ⇒ Object
Clear the current data buffer.
-
#status ⇒ Object
The status of the transfer.
-
#submit!(&block) ⇒ Object
Submit a transfer.
-
#submit_and_wait ⇒ Object
Submit the transfer and wait until the transfer completes or fails.
-
#submit_and_wait! ⇒ Object
Submit the transfer and wait until the transfer completes or fails.
-
#timeout=(value) ⇒ Object
Timeout for this transfer in millseconds.
Instance Method Details
#actual_buffer(offset = 0) ⇒ Object
Retrieve the data actually transferred.
102 103 104 |
# File 'lib/libusb/transfer.rb', line 102 def actual_buffer(offset=0) @transfer[:buffer].get_bytes(offset, @transfer[:actual_length]) end |
#actual_length ⇒ Object
The number of bytes actually transferred.
95 96 97 |
# File 'lib/libusb/transfer.rb', line 95 def actual_length @transfer[:actual_length] end |
#alloc_buffer(len, data = nil) ⇒ Object
Allocate len bytes of data buffer for input transfer.
84 85 86 87 88 89 90 91 92 |
# File 'lib/libusb/transfer.rb', line 84 def alloc_buffer(len, data=nil) if !@buffer || len>@buffer.size free_buffer @buffer = FFI::MemoryPointer.new(len, 1, false) end @buffer.put_bytes(0, data) if data @transfer[:buffer] = @buffer @transfer[:length] = len end |
#buffer ⇒ Object
Retrieve the current data buffer.
66 67 68 |
# File 'lib/libusb/transfer.rb', line 66 def buffer @transfer[:buffer].read_string(@transfer[:length]) end |
#buffer=(data) ⇒ Object
Set output data that should be sent.
55 56 57 58 59 60 61 62 63 |
# File 'lib/libusb/transfer.rb', line 55 def buffer=(data) if !@buffer || data.bytesize>@buffer.size free_buffer @buffer = FFI::MemoryPointer.new(data.bytesize, 1, false) end @buffer.put_bytes(0, data) @transfer[:buffer] = @buffer @transfer[:length] = data.bytesize end |
#callback=(proc) ⇒ Object
Set the block that will be invoked when the transfer completes, fails, or is cancelled.
110 111 112 113 114 115 116 117 |
# File 'lib/libusb/transfer.rb', line 110 def callback=(proc) # Save proc to instance variable so that GC doesn't free # the proc object before the transfer. @callback_proc = proc do |pTrans| proc.call(self) end @transfer[:callback] = @callback_proc end |
#cancel! ⇒ Object
Asynchronously cancel a previously submitted transfer.
This function returns immediately, but this does not indicate cancellation is complete. Your callback function will be invoked at some later time with a transfer status of :TRANSFER_CANCELLED.
149 150 151 152 |
# File 'lib/libusb/transfer.rb', line 149 def cancel! res = Call.libusb_cancel_transfer( @transfer ) LIBUSB.raise_error res, "in libusb_cancel_transfer" if res!=0 end |
#dev_handle=(dev) ⇒ Object
Set the handle for the device to communicate with.
36 37 38 39 |
# File 'lib/libusb/transfer.rb', line 36 def dev_handle=(dev) @dev_handle = dev @transfer[:dev_handle] = @dev_handle.pHandle end |
#endpoint=(endpoint) ⇒ Object
Set the address of a valid endpoint to communicate with.
49 50 51 52 |
# File 'lib/libusb/transfer.rb', line 49 def endpoint=(endpoint) endpoint = endpoint.bEndpointAddress if endpoint.respond_to? :bEndpointAddress @transfer[:endpoint] = endpoint end |
#free_buffer ⇒ Object
Clear the current data buffer.
71 72 73 74 75 76 77 78 |
# File 'lib/libusb/transfer.rb', line 71 def free_buffer if @buffer @buffer.free @buffer = nil @transfer[:buffer] = nil @transfer[:length] = 0 end end |
#status ⇒ Object
The status of the transfer.
Only for use within transfer callback function or after the callback was called.
If this is an isochronous transfer, this field may read :TRANSFER_COMPLETED even if there were errors in the frames. Use the status field in each packet to determine if errors occurred.
126 127 128 |
# File 'lib/libusb/transfer.rb', line 126 def status @transfer[:status] end |
#submit!(&block) ⇒ Object
Submit a transfer.
This function will fire off the USB transfer and then return immediately. This method can be called with block. It is called when the transfer completes, fails, or is cancelled.
135 136 137 138 139 140 141 142 |
# File 'lib/libusb/transfer.rb', line 135 def submit!(&block) self.callback = block if block_given? # 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}" res = Call.libusb_submit_transfer( @transfer ) LIBUSB.raise_error res, "in libusb_submit_transfer" if res!=0 end |
#submit_and_wait ⇒ Object
Submit the transfer and wait until the transfer completes or fails.
Inspect #status to check for transfer errors.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/libusb/transfer.rb', line 166 def submit_and_wait @completion_flag.completed = false submit! do |tr2| @completion_flag.completed = true end until @completion_flag.completed? begin @dev_handle.device.context.handle_events nil, @completion_flag rescue ERROR_INTERRUPTED next rescue LIBUSB::Error cancel! until @completion_flag.completed? @dev_handle.device.context.handle_events nil, @completion_flag end raise end end end |
#submit_and_wait! ⇒ Object
Submit the transfer and wait until the transfer completes or fails.
A proper Error is raised, in case the transfer did not complete.
190 191 192 193 194 |
# File 'lib/libusb/transfer.rb', line 190 def submit_and_wait! submit_and_wait raise( TransferStatusToError[status] || ERROR_OTHER, "error #{status}") unless status==:TRANSFER_COMPLETED end |
#timeout=(value) ⇒ Object
Timeout for this transfer in millseconds.
A value of 0 indicates no timeout.
44 45 46 |
# File 'lib/libusb/transfer.rb', line 44 def timeout=(value) @transfer[:timeout] = value end |