Class: Seriamp::Backend::FFIBackend::Device

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/seriamp/backend/ffi.rb

Defined Under Namespace

Modules: C Classes: IntPtr

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(device, logger: nil) ⇒ Device

Returns a new instance of Device.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/seriamp/backend/ffi.rb', line 13

def initialize(device, logger: nil)
  @logger = logger

  if @f
    yield
  else
    logger&.debug("Opening device #{device}")
    File.open(device, 'r+') do |f|
      unless f.isatty
        raise BadDevice, "#{device} is not a TTY"
      end
      @f = f
      set_rts

      if IO.select([f], nil, nil, 0)
        logger&.warn("Serial device readable without having been written to - concurrent access?")
      end

      tries = 0
      begin
        do_status
      rescue Timeout::Error
        tries += 1
        if tries < 5
          logger&.warn("Timeout handshaking with the receiver - will retry")
          retry
        else
          raise
        end
      end
      yield.tap do
        @f = nil
      end
    end
  end
rescue IOError => e
  if @f
    logger&.warn("#{e.class}: #{e} while operating, closing the device")
    @f.close
    raise
  end
end

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



56
57
58
# File 'lib/seriamp/backend/ffi.rb', line 56

def logger
  @logger
end

Instance Method Details

#set_rtsObject



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/seriamp/backend/ffi.rb', line 59

def set_rts
  ptr = IntPtr.new
  C.ioctl_p(@f.fileno, TIOCMGET, ptr)
  if logger&.level <= Logger::DEBUG
    flags = []
    %w(DTR RTS CTS).each do |bit|
      if ptr[:value] & self.class.const_get("TIOCM_#{bit}") > 0
        flags << bit
      end
    end
    if flags.empty?
      flags = ['(none)']
    end
    logger&.debug("Initial flags: #{flags.join(' ')}")
  end
  unless ptr[:value] & TIOCM_RTS
    logger&.debug("Setting RTS on #{device}")
    ptr[:value] |= TIOCM_RTS
    C.ioctl_p(@f.fileno, TIOCMSET, ptr)
  end
end