rubyserial-with-blocking 0.2.3
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.
- checksums.yaml +7 -0
 - data/.gitignore +4 -0
 - data/.rspec +3 -0
 - data/.travis.yml +18 -0
 - data/Gemfile +5 -0
 - data/Guardfile +7 -0
 - data/LICENSE +13 -0
 - data/README.md +76 -0
 - data/Rakefile +2 -0
 - data/appveyor.yml +25 -0
 - data/lib/rubyserial.rb +21 -0
 - data/lib/rubyserial/linux_constants.rb +214 -0
 - data/lib/rubyserial/osx_constants.rb +181 -0
 - data/lib/rubyserial/posix.rb +140 -0
 - data/lib/rubyserial/version.rb +5 -0
 - data/lib/rubyserial/windows.rb +104 -0
 - data/lib/rubyserial/windows_constants.rb +275 -0
 - data/rubyserial.gemspec +21 -0
 - data/spec/lib/posix_spec.rb +150 -0
 - data/spec/rubyserial_spec.rb +138 -0
 - data/spec/spec_helper.rb +86 -0
 - metadata +95 -0
 
| 
         @@ -0,0 +1,140 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'ffi'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Serial
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              Defaults = {
         
     | 
| 
      
 6 
     | 
    
         
            +
                baude_rate: 9600, 
         
     | 
| 
      
 7 
     | 
    
         
            +
                data_bits: 8,
         
     | 
| 
      
 8 
     | 
    
         
            +
                vmin: 0,
         
     | 
| 
      
 9 
     | 
    
         
            +
              }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              attr_reader :config
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              # config value order is, in that order, from low to high: 
         
     | 
| 
      
 14 
     | 
    
         
            +
              # 
         
     | 
| 
      
 15 
     | 
    
         
            +
              #   config hash  -over-> baud_rate, data_bits -over->  Defaults
         
     | 
| 
      
 16 
     | 
    
         
            +
              #
         
     | 
| 
      
 17 
     | 
    
         
            +
              def initialize(address, baude_rate = nil, data_bits = nil, config = {})
         
     | 
| 
      
 18 
     | 
    
         
            +
                # XXX this is kind of ugly, but neccessary to preserve old orginal code
         
     | 
| 
      
 19 
     | 
    
         
            +
                # behaviour with default values
         
     | 
| 
      
 20 
     | 
    
         
            +
                config[:baude_rate] ||= (baude_rate || Defaults[:baude_rate])
         
     | 
| 
      
 21 
     | 
    
         
            +
                config[:data_bits] ||= (data_bits || Defaults[:data_bits])
         
     | 
| 
      
 22 
     | 
    
         
            +
                @config = Defaults.merge(config)
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                file_opts = RubySerial::Posix::O_RDWR | RubySerial::Posix::O_NOCTTY | RubySerial::Posix::O_NONBLOCK
         
     | 
| 
      
 25 
     | 
    
         
            +
                @fd = RubySerial::Posix.open(address, file_opts)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                if @fd == -1
         
     | 
| 
      
 28 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Posix::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 29 
     | 
    
         
            +
                else
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @open = true
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                fl = RubySerial::Posix.fcntl(@fd, RubySerial::Posix::F_GETFL, :int, 0)
         
     | 
| 
      
 34 
     | 
    
         
            +
                if fl == -1
         
     | 
| 
      
 35 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Posix::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                err = RubySerial::Posix.fcntl(@fd, RubySerial::Posix::F_SETFL, :int, ~RubySerial::Posix::O_NONBLOCK & fl)
         
     | 
| 
      
 39 
     | 
    
         
            +
                if err == -1
         
     | 
| 
      
 40 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Posix::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                termio = build_config(@config)
         
     | 
| 
      
 44 
     | 
    
         
            +
                err = RubySerial::Posix.tcsetattr(@fd, RubySerial::Posix::TCSANOW, termio)
         
     | 
| 
      
 45 
     | 
    
         
            +
                if err == -1
         
     | 
| 
      
 46 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Posix::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              def closed?
         
     | 
| 
      
 51 
     | 
    
         
            +
                !@open
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              # use the file descriptor, or IO object instance around it, for blocking read
         
     | 
| 
      
 55 
     | 
    
         
            +
              # with IO#select or for waiting on multiple i/o lines & events
         
     | 
| 
      
 56 
     | 
    
         
            +
              #
         
     | 
| 
      
 57 
     | 
    
         
            +
              attr_reader :fd
         
     | 
| 
      
 58 
     | 
    
         
            +
              def io; @io ||= IO.new(@fd); end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              def close
         
     | 
| 
      
 61 
     | 
    
         
            +
                err = RubySerial::Posix.close(@fd)
         
     | 
| 
      
 62 
     | 
    
         
            +
                if err == -1
         
     | 
| 
      
 63 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Posix::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 64 
     | 
    
         
            +
                else
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @open = false
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
              def write(data)
         
     | 
| 
      
 70 
     | 
    
         
            +
                data = data.to_s
         
     | 
| 
      
 71 
     | 
    
         
            +
                n =  0
         
     | 
| 
      
 72 
     | 
    
         
            +
                while data.size > n do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  buff = FFI::MemoryPointer.from_string(data[n..-1].to_s)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  i = RubySerial::Posix.write(@fd, buff, buff.size-1)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  if i == -1
         
     | 
| 
      
 76 
     | 
    
         
            +
                    raise RubySerial::Exception, RubySerial::Posix::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 77 
     | 
    
         
            +
                  else
         
     | 
| 
      
 78 
     | 
    
         
            +
                    n = n+i
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                # return number of bytes written
         
     | 
| 
      
 83 
     | 
    
         
            +
                n
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              def read(size)
         
     | 
| 
      
 87 
     | 
    
         
            +
                buff = FFI::MemoryPointer.new :char, size
         
     | 
| 
      
 88 
     | 
    
         
            +
                i = RubySerial::Posix.read(@fd, buff, size)
         
     | 
| 
      
 89 
     | 
    
         
            +
                if i == -1
         
     | 
| 
      
 90 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Posix::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
                buff.get_bytes(0, i)
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
              def getbyte
         
     | 
| 
      
 96 
     | 
    
         
            +
                buff = FFI::MemoryPointer.new :char, 1
         
     | 
| 
      
 97 
     | 
    
         
            +
                i = RubySerial::Posix.read(@fd, buff, 1)
         
     | 
| 
      
 98 
     | 
    
         
            +
                if i == -1
         
     | 
| 
      
 99 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Posix::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                if i == 0
         
     | 
| 
      
 103 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 104 
     | 
    
         
            +
                else
         
     | 
| 
      
 105 
     | 
    
         
            +
                  buff.get_bytes(0,1).bytes.first
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
              def gets(sep=$/, limit=nil)
         
     | 
| 
      
 110 
     | 
    
         
            +
                sep = "\n\n" if sep == ''
         
     | 
| 
      
 111 
     | 
    
         
            +
                # This allows the method signature to be (sep) or (limit)
         
     | 
| 
      
 112 
     | 
    
         
            +
                (limit = sep; sep="\n") if sep.is_a? Integer
         
     | 
| 
      
 113 
     | 
    
         
            +
                bytes = []
         
     | 
| 
      
 114 
     | 
    
         
            +
                loop do
         
     | 
| 
      
 115 
     | 
    
         
            +
                  current_byte = getbyte
         
     | 
| 
      
 116 
     | 
    
         
            +
                  bytes << current_byte unless current_byte.nil?
         
     | 
| 
      
 117 
     | 
    
         
            +
                  break if (bytes.last(sep.bytes.to_a.size) == sep.bytes.to_a) || ((bytes.size == limit) if limit)
         
     | 
| 
      
 118 
     | 
    
         
            +
                end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                bytes.map { |e| e.chr }.join
         
     | 
| 
      
 121 
     | 
    
         
            +
              end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
              private
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
              def build_config(opts)
         
     | 
| 
      
 126 
     | 
    
         
            +
                termio = RubySerial::Posix::Termios.new
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                termio[:c_iflag]  = RubySerial::Posix::IGNPAR
         
     | 
| 
      
 129 
     | 
    
         
            +
                termio[:c_ispeed] = RubySerial::Posix::BAUDE_RATES[opts[:baude_rate]]
         
     | 
| 
      
 130 
     | 
    
         
            +
                termio[:c_ospeed] = RubySerial::Posix::BAUDE_RATES[opts[:baude_rate]]
         
     | 
| 
      
 131 
     | 
    
         
            +
                termio[:c_cflag]  = RubySerial::Posix::DATA_BITS[opts[:data_bits]] |
         
     | 
| 
      
 132 
     | 
    
         
            +
                  RubySerial::Posix::CREAD |
         
     | 
| 
      
 133 
     | 
    
         
            +
                  RubySerial::Posix::CLOCAL |
         
     | 
| 
      
 134 
     | 
    
         
            +
                  RubySerial::Posix::BAUDE_RATES[opts[:baude_rate]]
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                termio[:cc_c][RubySerial::Posix::VMIN] = opts[:vmin]
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                termio
         
     | 
| 
      
 139 
     | 
    
         
            +
              end
         
     | 
| 
      
 140 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,104 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'ffi'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Serial
         
     | 
| 
      
 4 
     | 
    
         
            +
              def initialize(address, baude_rate=9600, data_bits=8)
         
     | 
| 
      
 5 
     | 
    
         
            +
                file_opts = RubySerial::Win32::GENERIC_READ | RubySerial::Win32::GENERIC_WRITE
         
     | 
| 
      
 6 
     | 
    
         
            +
                @fd = RubySerial::Win32.CreateFileA("\\\\.\\#{address}", file_opts, 0, nil, RubySerial::Win32::OPEN_EXISTING, 0, nil)
         
     | 
| 
      
 7 
     | 
    
         
            +
                err = FFI.errno
         
     | 
| 
      
 8 
     | 
    
         
            +
                if err != 0
         
     | 
| 
      
 9 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Win32::ERROR_CODES[err]
         
     | 
| 
      
 10 
     | 
    
         
            +
                else
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @open = true
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                RubySerial::Win32::DCB.new.tap do |dcb|
         
     | 
| 
      
 15 
     | 
    
         
            +
                  dcb[:dcblength] = RubySerial::Win32::DCB::Sizeof
         
     | 
| 
      
 16 
     | 
    
         
            +
                  err = RubySerial::Win32.GetCommState @fd, dcb
         
     | 
| 
      
 17 
     | 
    
         
            +
                  if err == 0
         
     | 
| 
      
 18 
     | 
    
         
            +
                    raise RubySerial::Exception, RubySerial::Win32::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  dcb[:baudrate] = baude_rate
         
     | 
| 
      
 21 
     | 
    
         
            +
                  dcb[:bytesize] = data_bits
         
     | 
| 
      
 22 
     | 
    
         
            +
                  dcb[:stopbits] = RubySerial::Win32::DCB::ONESTOPBIT
         
     | 
| 
      
 23 
     | 
    
         
            +
                  dcb[:parity]   = RubySerial::Win32::DCB::NOPARITY
         
     | 
| 
      
 24 
     | 
    
         
            +
                  err = RubySerial::Win32.SetCommState @fd, dcb
         
     | 
| 
      
 25 
     | 
    
         
            +
                  if err == 0
         
     | 
| 
      
 26 
     | 
    
         
            +
                    raise RubySerial::Exception, RubySerial::Win32::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                RubySerial::Win32::CommTimeouts.new.tap do |timeouts|
         
     | 
| 
      
 31 
     | 
    
         
            +
                  timeouts[:read_interval_timeout]          = 10
         
     | 
| 
      
 32 
     | 
    
         
            +
                  timeouts[:read_total_timeout_multiplier]  = 1
         
     | 
| 
      
 33 
     | 
    
         
            +
                  timeouts[:read_total_timeout_constant]    = 10
         
     | 
| 
      
 34 
     | 
    
         
            +
                  timeouts[:write_total_timeout_multiplier] = 1
         
     | 
| 
      
 35 
     | 
    
         
            +
                  timeouts[:write_total_timeout_constant]   = 10
         
     | 
| 
      
 36 
     | 
    
         
            +
                  err = RubySerial::Win32.SetCommTimeouts @fd, timeouts
         
     | 
| 
      
 37 
     | 
    
         
            +
                  if err == 0
         
     | 
| 
      
 38 
     | 
    
         
            +
                    raise RubySerial::Exception, RubySerial::Win32::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              def read(size)
         
     | 
| 
      
 44 
     | 
    
         
            +
                buff = FFI::MemoryPointer.new :char, size
         
     | 
| 
      
 45 
     | 
    
         
            +
                count = FFI::MemoryPointer.new :uint32, 1
         
     | 
| 
      
 46 
     | 
    
         
            +
                err = RubySerial::Win32.ReadFile(@fd, buff, size, count, nil)
         
     | 
| 
      
 47 
     | 
    
         
            +
                if err == 0
         
     | 
| 
      
 48 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Win32::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
                buff.get_bytes(0, count.read_int)
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              def getbyte
         
     | 
| 
      
 54 
     | 
    
         
            +
                buff = FFI::MemoryPointer.new :char, 1
         
     | 
| 
      
 55 
     | 
    
         
            +
                count = FFI::MemoryPointer.new :uint32, 1
         
     | 
| 
      
 56 
     | 
    
         
            +
                err = RubySerial::Win32.ReadFile(@fd, buff, 1, count, nil)
         
     | 
| 
      
 57 
     | 
    
         
            +
                if err == 0
         
     | 
| 
      
 58 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Win32::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                if count.read_int == 0
         
     | 
| 
      
 62 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 63 
     | 
    
         
            +
                else
         
     | 
| 
      
 64 
     | 
    
         
            +
                  buff.read_string.unpack('C').first
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              def write(data)
         
     | 
| 
      
 69 
     | 
    
         
            +
                buff = FFI::MemoryPointer.from_string(data.to_s)
         
     | 
| 
      
 70 
     | 
    
         
            +
                count = FFI::MemoryPointer.new :uint32, 1
         
     | 
| 
      
 71 
     | 
    
         
            +
                err = RubySerial::Win32.WriteFile(@fd, buff, buff.size-1, count, nil)
         
     | 
| 
      
 72 
     | 
    
         
            +
                if err == 0
         
     | 
| 
      
 73 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Win32::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
                count.read_int
         
     | 
| 
      
 76 
     | 
    
         
            +
              end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              def gets(sep=$/, limit=nil)
         
     | 
| 
      
 79 
     | 
    
         
            +
                sep = "\n\n" if sep == ''
         
     | 
| 
      
 80 
     | 
    
         
            +
                # This allows the method signature to be (sep) or (limit)
         
     | 
| 
      
 81 
     | 
    
         
            +
                (limit = sep; sep="\n") if sep.is_a? Integer
         
     | 
| 
      
 82 
     | 
    
         
            +
                bytes = []
         
     | 
| 
      
 83 
     | 
    
         
            +
                loop do
         
     | 
| 
      
 84 
     | 
    
         
            +
                  current_byte = getbyte
         
     | 
| 
      
 85 
     | 
    
         
            +
                  bytes << current_byte unless current_byte.nil?
         
     | 
| 
      
 86 
     | 
    
         
            +
                  break if (bytes.last(sep.bytes.to_a.size) == sep.bytes.to_a) || ((bytes.size == limit) if limit)
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                bytes.map { |e| e.chr }.join
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              def close
         
     | 
| 
      
 93 
     | 
    
         
            +
                err = RubySerial::Win32.CloseHandle(@fd)
         
     | 
| 
      
 94 
     | 
    
         
            +
                if err == 0
         
     | 
| 
      
 95 
     | 
    
         
            +
                  raise RubySerial::Exception, RubySerial::Win32::ERROR_CODES[FFI.errno]
         
     | 
| 
      
 96 
     | 
    
         
            +
                else
         
     | 
| 
      
 97 
     | 
    
         
            +
                  @open = false
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
              end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
              def closed?
         
     | 
| 
      
 102 
     | 
    
         
            +
                !@open
         
     | 
| 
      
 103 
     | 
    
         
            +
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,275 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'ffi'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RubySerial
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Win32
         
     | 
| 
      
 5 
     | 
    
         
            +
                extend FFI::Library
         
     | 
| 
      
 6 
     | 
    
         
            +
                ffi_lib 'kernel32'
         
     | 
| 
      
 7 
     | 
    
         
            +
                ffi_convention :stdcall
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                GENERIC_READ  = 0x80000000
         
     | 
| 
      
 10 
     | 
    
         
            +
                GENERIC_WRITE = 0x40000000
         
     | 
| 
      
 11 
     | 
    
         
            +
                OPEN_EXISTING = 3
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                ERROR_CODES = {
         
     | 
| 
      
 14 
     | 
    
         
            +
                  5 => "ERROR_ACCESS_DENIED", 
         
     | 
| 
      
 15 
     | 
    
         
            +
                  57 => "ERROR_ADAP_HDW_ERR", 
         
     | 
| 
      
 16 
     | 
    
         
            +
                  85 => "ERROR_ALREADY_ASSIGNED", 
         
     | 
| 
      
 17 
     | 
    
         
            +
                  183 => "ERROR_ALREADY_EXISTS", 
         
     | 
| 
      
 18 
     | 
    
         
            +
                  7 => "ERROR_ARENA_TRASHED", 
         
     | 
| 
      
 19 
     | 
    
         
            +
                  174 => "ERROR_ATOMIC_LOCKS_NOT_SUPPORTED", 
         
     | 
| 
      
 20 
     | 
    
         
            +
                  199 => "ERROR_AUTODATASEG_EXCEEDS_64k", 
         
     | 
| 
      
 21 
     | 
    
         
            +
                  160 => "ERROR_BAD_ARGUMENTS", 
         
     | 
| 
      
 22 
     | 
    
         
            +
                  22 => "ERROR_BAD_COMMAND", 
         
     | 
| 
      
 23 
     | 
    
         
            +
                  66 => "ERROR_BAD_DEV_TYPE", 
         
     | 
| 
      
 24 
     | 
    
         
            +
                  119 => "ERROR_BAD_DRIVER_LEVEL", 
         
     | 
| 
      
 25 
     | 
    
         
            +
                  10 => "ERROR_BAD_ENVIRONMENT", 
         
     | 
| 
      
 26 
     | 
    
         
            +
                  193 => "ERROR_BAD_EXE_FORMAT", 
         
     | 
| 
      
 27 
     | 
    
         
            +
                  222 => "ERROR_BAD_FILE_TYPE", 
         
     | 
| 
      
 28 
     | 
    
         
            +
                  11 => "ERROR_BAD_FORMAT", 
         
     | 
| 
      
 29 
     | 
    
         
            +
                  24 => "ERROR_BAD_LENGTH", 
         
     | 
| 
      
 30 
     | 
    
         
            +
                  67 => "ERROR_BAD_NET_NAME", 
         
     | 
| 
      
 31 
     | 
    
         
            +
                  58 => "ERROR_BAD_NET_RESP", 
         
     | 
| 
      
 32 
     | 
    
         
            +
                  53 => "ERROR_BAD_NETPATH", 
         
     | 
| 
      
 33 
     | 
    
         
            +
                  161 => "ERROR_BAD_PATHNAME", 
         
     | 
| 
      
 34 
     | 
    
         
            +
                  230 => "ERROR_BAD_PIPE", 
         
     | 
| 
      
 35 
     | 
    
         
            +
                  60 => "ERROR_BAD_REM_ADAP", 
         
     | 
| 
      
 36 
     | 
    
         
            +
                  159 => "ERROR_BAD_THREADID_ADDR", 
         
     | 
| 
      
 37 
     | 
    
         
            +
                  20 => "ERROR_BAD_UNIT", 
         
     | 
| 
      
 38 
     | 
    
         
            +
                  109 => "ERROR_BROKEN_PIPE", 
         
     | 
| 
      
 39 
     | 
    
         
            +
                  111 => "ERROR_BUFFER_OVERFLOW", 
         
     | 
| 
      
 40 
     | 
    
         
            +
                  142 => "ERROR_BUSY_DRIVE", 
         
     | 
| 
      
 41 
     | 
    
         
            +
                  170 => "ERROR_BUSY", 
         
     | 
| 
      
 42 
     | 
    
         
            +
                  120 => "ERROR_CALL_NOT_IMPLEMENTED", 
         
     | 
| 
      
 43 
     | 
    
         
            +
                  173 => "ERROR_CANCEL_VIOLATION", 
         
     | 
| 
      
 44 
     | 
    
         
            +
                  266 => "ERROR_CANNOT_COPY", 
         
     | 
| 
      
 45 
     | 
    
         
            +
                  82 => "ERROR_CANNOT_MAKE", 
         
     | 
| 
      
 46 
     | 
    
         
            +
                  221 => "ERROR_CHECKOUT_REQUIRED", 
         
     | 
| 
      
 47 
     | 
    
         
            +
                  129 => "ERROR_CHILD_NOT_COMPLETE", 
         
     | 
| 
      
 48 
     | 
    
         
            +
                  23 => "ERROR_CRC", 
         
     | 
| 
      
 49 
     | 
    
         
            +
                  16 => "ERROR_CURRENT_DIRECTORY", 
         
     | 
| 
      
 50 
     | 
    
         
            +
                  303 => "ERROR_DELETE_PENDING", 
         
     | 
| 
      
 51 
     | 
    
         
            +
                  55 => "ERROR_DEV_NOT_EXIST", 
         
     | 
| 
      
 52 
     | 
    
         
            +
                  145 => "ERROR_DIR_NOT_EMPTY", 
         
     | 
| 
      
 53 
     | 
    
         
            +
                  144 => "ERROR_DIR_NOT_ROOT", 
         
     | 
| 
      
 54 
     | 
    
         
            +
                  130 => "ERROR_DIRECT_ACCESS_HANDLE", 
         
     | 
| 
      
 55 
     | 
    
         
            +
                  267 => "ERROR_DIRECTORY", 
         
     | 
| 
      
 56 
     | 
    
         
            +
                  157 => "ERROR_DISCARDED", 
         
     | 
| 
      
 57 
     | 
    
         
            +
                  107 => "ERROR_DISK_CHANGE", 
         
     | 
| 
      
 58 
     | 
    
         
            +
                  112 => "ERROR_DISK_FULL", 
         
     | 
| 
      
 59 
     | 
    
         
            +
                  302 => "ERROR_DISK_TOO_FRAGMENTED", 
         
     | 
| 
      
 60 
     | 
    
         
            +
                  108 => "ERROR_DRIVE_LOCKED", 
         
     | 
| 
      
 61 
     | 
    
         
            +
                  52 => "ERROR_DUP_NAME", 
         
     | 
| 
      
 62 
     | 
    
         
            +
                  196 => "ERROR_DYNLINK_FROM_INVALID_RING", 
         
     | 
| 
      
 63 
     | 
    
         
            +
                  276 => "ERROR_EA_FILE_CORRUPT", 
         
     | 
| 
      
 64 
     | 
    
         
            +
                  255 => "ERROR_EA_LIST_INCONSISTENT", 
         
     | 
| 
      
 65 
     | 
    
         
            +
                  277 => "ERROR_EA_TABLE_FULL", 
         
     | 
| 
      
 66 
     | 
    
         
            +
                  275 => "ERROR_EAS_DIDNT_FIT", 
         
     | 
| 
      
 67 
     | 
    
         
            +
                  282 => "ERROR_EAS_NOT_SUPPORTED", 
         
     | 
| 
      
 68 
     | 
    
         
            +
                  203 => "ERROR_ENVVAR_NOT_FOUND", 
         
     | 
| 
      
 69 
     | 
    
         
            +
                  101 => "ERROR_EXCL_SEM_ALREADY_OWNED", 
         
     | 
| 
      
 70 
     | 
    
         
            +
                  217 => "ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY", 
         
     | 
| 
      
 71 
     | 
    
         
            +
                  218 => "ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY", 
         
     | 
| 
      
 72 
     | 
    
         
            +
                  216 => "ERROR_EXE_MACHINE_TYPE_MISMATCH", 
         
     | 
| 
      
 73 
     | 
    
         
            +
                  192 => "ERROR_EXE_MARKED_INVALID", 
         
     | 
| 
      
 74 
     | 
    
         
            +
                  83 => "ERROR_FAIL_I24", 
         
     | 
| 
      
 75 
     | 
    
         
            +
                  350 => "ERROR_FAIL_NOACTION_REBOOT", 
         
     | 
| 
      
 76 
     | 
    
         
            +
                  352 => "ERROR_FAIL_RESTART", 
         
     | 
| 
      
 77 
     | 
    
         
            +
                  351 => "ERROR_FAIL_SHUTDOWN", 
         
     | 
| 
      
 78 
     | 
    
         
            +
                  220 => "ERROR_FILE_CHECKED_OUT", 
         
     | 
| 
      
 79 
     | 
    
         
            +
                  80 => "ERROR_FILE_EXISTS", 
         
     | 
| 
      
 80 
     | 
    
         
            +
                  2 => "ERROR_FILE_NOT_FOUND", 
         
     | 
| 
      
 81 
     | 
    
         
            +
                  223 => "ERROR_FILE_TOO_LARGE", 
         
     | 
| 
      
 82 
     | 
    
         
            +
                  206 => "ERROR_FILENAME_EXCED_RANGE", 
         
     | 
| 
      
 83 
     | 
    
         
            +
                  224 => "ERROR_FORMS_AUTH_REQUIRED", 
         
     | 
| 
      
 84 
     | 
    
         
            +
                  31 => "ERROR_GEN_FAILURE", 
         
     | 
| 
      
 85 
     | 
    
         
            +
                  39 => "ERROR_HANDLE_DISK_FULL", 
         
     | 
| 
      
 86 
     | 
    
         
            +
                  38 => "ERROR_HANDLE_EOF", 
         
     | 
| 
      
 87 
     | 
    
         
            +
                  308 => "ERROR_IMAGE_SUBSYSTEM_NOT_PRESENT", 
         
     | 
| 
      
 88 
     | 
    
         
            +
                  304 => "ERROR_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING", 
         
     | 
| 
      
 89 
     | 
    
         
            +
                  202 => "ERROR_INFLOOP_IN_RELOC_CHAIN", 
         
     | 
| 
      
 90 
     | 
    
         
            +
                  122 => "ERROR_INSUFFICIENT_BUFFER", 
         
     | 
| 
      
 91 
     | 
    
         
            +
                  12 => "ERROR_INVALID_ACCESS", 
         
     | 
| 
      
 92 
     | 
    
         
            +
                  487 => "ERROR_INVALID_ADDRESS", 
         
     | 
| 
      
 93 
     | 
    
         
            +
                  104 => "ERROR_INVALID_AT_INTERRUPT_TIME", 
         
     | 
| 
      
 94 
     | 
    
         
            +
                  9 => "ERROR_INVALID_BLOCK", 
         
     | 
| 
      
 95 
     | 
    
         
            +
                  117 => "ERROR_INVALID_CATEGORY", 
         
     | 
| 
      
 96 
     | 
    
         
            +
                  13 => "ERROR_INVALID_DATA", 
         
     | 
| 
      
 97 
     | 
    
         
            +
                  15 => "ERROR_INVALID_DRIVE", 
         
     | 
| 
      
 98 
     | 
    
         
            +
                  278 => "ERROR_INVALID_EA_HANDLE", 
         
     | 
| 
      
 99 
     | 
    
         
            +
                  254 => "ERROR_INVALID_EA_NAME", 
         
     | 
| 
      
 100 
     | 
    
         
            +
                  151 => "ERROR_INVALID_EVENT_COUNT", 
         
     | 
| 
      
 101 
     | 
    
         
            +
                  191 => "ERROR_INVALID_EXE_SIGNATURE", 
         
     | 
| 
      
 102 
     | 
    
         
            +
                  186 => "ERROR_INVALID_FLAG_NUMBER", 
         
     | 
| 
      
 103 
     | 
    
         
            +
                  1 => "ERROR_INVALID_FUNCTION", 
         
     | 
| 
      
 104 
     | 
    
         
            +
                  6 => "ERROR_INVALID_HANDLE", 
         
     | 
| 
      
 105 
     | 
    
         
            +
                  124 => "ERROR_INVALID_LEVEL", 
         
     | 
| 
      
 106 
     | 
    
         
            +
                  153 => "ERROR_INVALID_LIST_FORMAT", 
         
     | 
| 
      
 107 
     | 
    
         
            +
                  307 => "ERROR_INVALID_LOCK_RANGE", 
         
     | 
| 
      
 108 
     | 
    
         
            +
                  195 => "ERROR_INVALID_MINALLOCSIZE", 
         
     | 
| 
      
 109 
     | 
    
         
            +
                  190 => "ERROR_INVALID_MODULETYPE", 
         
     | 
| 
      
 110 
     | 
    
         
            +
                  123 => "ERROR_INVALID_NAME", 
         
     | 
| 
      
 111 
     | 
    
         
            +
                  301 => "ERROR_INVALID_OPLOCK_PROTOCOL", 
         
     | 
| 
      
 112 
     | 
    
         
            +
                  182 => "ERROR_INVALID_ORDINAL", 
         
     | 
| 
      
 113 
     | 
    
         
            +
                  87 => "ERROR_INVALID_PARAMETER", 
         
     | 
| 
      
 114 
     | 
    
         
            +
                  86 => "ERROR_INVALID_PASSWORD", 
         
     | 
| 
      
 115 
     | 
    
         
            +
                  198 => "ERROR_INVALID_SEGDPL", 
         
     | 
| 
      
 116 
     | 
    
         
            +
                  180 => "ERROR_INVALID_SEGMENT_NUMBER", 
         
     | 
| 
      
 117 
     | 
    
         
            +
                  209 => "ERROR_INVALID_SIGNAL_NUMBER", 
         
     | 
| 
      
 118 
     | 
    
         
            +
                  189 => "ERROR_INVALID_STACKSEG", 
         
     | 
| 
      
 119 
     | 
    
         
            +
                  188 => "ERROR_INVALID_STARTING_CODESEG", 
         
     | 
| 
      
 120 
     | 
    
         
            +
                  114 => "ERROR_INVALID_TARGET_HANDLE", 
         
     | 
| 
      
 121 
     | 
    
         
            +
                  118 => "ERROR_INVALID_VERIFY_SWITCH", 
         
     | 
| 
      
 122 
     | 
    
         
            +
                  197 => "ERROR_IOPL_NOT_ENABLED", 
         
     | 
| 
      
 123 
     | 
    
         
            +
                  147 => "ERROR_IS_JOIN_PATH", 
         
     | 
| 
      
 124 
     | 
    
         
            +
                  133 => "ERROR_IS_JOIN_TARGET", 
         
     | 
| 
      
 125 
     | 
    
         
            +
                  134 => "ERROR_IS_JOINED", 
         
     | 
| 
      
 126 
     | 
    
         
            +
                  146 => "ERROR_IS_SUBST_PATH", 
         
     | 
| 
      
 127 
     | 
    
         
            +
                  149 => "ERROR_IS_SUBST_TARGET", 
         
     | 
| 
      
 128 
     | 
    
         
            +
                  135 => "ERROR_IS_SUBSTED", 
         
     | 
| 
      
 129 
     | 
    
         
            +
                  194 => "ERROR_ITERATED_DATA_EXCEEDS_64k", 
         
     | 
| 
      
 130 
     | 
    
         
            +
                  138 => "ERROR_JOIN_TO_JOIN", 
         
     | 
| 
      
 131 
     | 
    
         
            +
                  140 => "ERROR_JOIN_TO_SUBST", 
         
     | 
| 
      
 132 
     | 
    
         
            +
                  154 => "ERROR_LABEL_TOO_LONG", 
         
     | 
| 
      
 133 
     | 
    
         
            +
                  167 => "ERROR_LOCK_FAILED", 
         
     | 
| 
      
 134 
     | 
    
         
            +
                  33 => "ERROR_LOCK_VIOLATION", 
         
     | 
| 
      
 135 
     | 
    
         
            +
                  212 => "ERROR_LOCKED", 
         
     | 
| 
      
 136 
     | 
    
         
            +
                  353 => "ERROR_MAX_SESSIONS_REACHED", 
         
     | 
| 
      
 137 
     | 
    
         
            +
                  164 => "ERROR_MAX_THRDS_REACHED", 
         
     | 
| 
      
 138 
     | 
    
         
            +
                  208 => "ERROR_META_EXPANSION_TOO_LONG", 
         
     | 
| 
      
 139 
     | 
    
         
            +
                  126 => "ERROR_MOD_NOT_FOUND", 
         
     | 
| 
      
 140 
     | 
    
         
            +
                  234 => "ERROR_MORE_DATA", 
         
     | 
| 
      
 141 
     | 
    
         
            +
                  317 => "ERROR_MR_MID_NOT_FOUND", 
         
     | 
| 
      
 142 
     | 
    
         
            +
                  131 => "ERROR_NEGATIVE_SEEK", 
         
     | 
| 
      
 143 
     | 
    
         
            +
                  215 => "ERROR_NESTING_NOT_ALLOWED", 
         
     | 
| 
      
 144 
     | 
    
         
            +
                  88 => "ERROR_NET_WRITE_FAULT", 
         
     | 
| 
      
 145 
     | 
    
         
            +
                  64 => "ERROR_NETNAME_DELETED", 
         
     | 
| 
      
 146 
     | 
    
         
            +
                  65 => "ERROR_NETWORK_ACCESS_DENIED", 
         
     | 
| 
      
 147 
     | 
    
         
            +
                  54 => "ERROR_NETWORK_BUSY", 
         
     | 
| 
      
 148 
     | 
    
         
            +
                  232 => "ERROR_NO_DATA", 
         
     | 
| 
      
 149 
     | 
    
         
            +
                  18 => "ERROR_NO_MORE_FILES", 
         
     | 
| 
      
 150 
     | 
    
         
            +
                  259 => "ERROR_NO_MORE_ITEMS", 
         
     | 
| 
      
 151 
     | 
    
         
            +
                  113 => "ERROR_NO_MORE_SEARCH_HANDLES", 
         
     | 
| 
      
 152 
     | 
    
         
            +
                  89 => "ERROR_NO_PROC_SLOTS", 
         
     | 
| 
      
 153 
     | 
    
         
            +
                  205 => "ERROR_NO_SIGNAL_SENT", 
         
     | 
| 
      
 154 
     | 
    
         
            +
                  62 => "ERROR_NO_SPOOL_SPACE", 
         
     | 
| 
      
 155 
     | 
    
         
            +
                  125 => "ERROR_NO_VOLUME_LABEL", 
         
     | 
| 
      
 156 
     | 
    
         
            +
                  26 => "ERROR_NOT_DOS_DISK", 
         
     | 
| 
      
 157 
     | 
    
         
            +
                  8 => "ERROR_NOT_ENOUGH_MEMORY", 
         
     | 
| 
      
 158 
     | 
    
         
            +
                  136 => "ERROR_NOT_JOINED", 
         
     | 
| 
      
 159 
     | 
    
         
            +
                  158 => "ERROR_NOT_LOCKED", 
         
     | 
| 
      
 160 
     | 
    
         
            +
                  288 => "ERROR_NOT_OWNER", 
         
     | 
| 
      
 161 
     | 
    
         
            +
                  21 => "ERROR_NOT_READY", 
         
     | 
| 
      
 162 
     | 
    
         
            +
                  17 => "ERROR_NOT_SAME_DEVICE", 
         
     | 
| 
      
 163 
     | 
    
         
            +
                  137 => "ERROR_NOT_SUBSTED", 
         
     | 
| 
      
 164 
     | 
    
         
            +
                  50 => "ERROR_NOT_SUPPORTED", 
         
     | 
| 
      
 165 
     | 
    
         
            +
                  309 => "ERROR_NOTIFICATION_GUID_ALREADY_DEFINED", 
         
     | 
| 
      
 166 
     | 
    
         
            +
                  110 => "ERROR_OPEN_FAILED", 
         
     | 
| 
      
 167 
     | 
    
         
            +
                  300 => "ERROR_OPLOCK_NOT_GRANTED", 
         
     | 
| 
      
 168 
     | 
    
         
            +
                  28 => "ERROR_OUT_OF_PAPER", 
         
     | 
| 
      
 169 
     | 
    
         
            +
                  84 => "ERROR_OUT_OF_STRUCTURES", 
         
     | 
| 
      
 170 
     | 
    
         
            +
                  14 => "ERROR_OUTOFMEMORY", 
         
     | 
| 
      
 171 
     | 
    
         
            +
                  299 => "ERROR_PARTIAL_COPY", 
         
     | 
| 
      
 172 
     | 
    
         
            +
                  148 => "ERROR_PATH_BUSY", 
         
     | 
| 
      
 173 
     | 
    
         
            +
                  3 => "ERROR_PATH_NOT_FOUND", 
         
     | 
| 
      
 174 
     | 
    
         
            +
                  231 => "ERROR_PIPE_BUSY", 
         
     | 
| 
      
 175 
     | 
    
         
            +
                  229 => "ERROR_PIPE_LOCAL", 
         
     | 
| 
      
 176 
     | 
    
         
            +
                  233 => "ERROR_PIPE_NOT_CONNECTED", 
         
     | 
| 
      
 177 
     | 
    
         
            +
                  63 => "ERROR_PRINT_CANCELLED", 
         
     | 
| 
      
 178 
     | 
    
         
            +
                  61 => "ERROR_PRINTQ_FULL", 
         
     | 
| 
      
 179 
     | 
    
         
            +
                  127 => "ERROR_PROC_NOT_FOUND", 
         
     | 
| 
      
 180 
     | 
    
         
            +
                  402 => "ERROR_PROCESS_MODE_ALREADY_BACKGROUND", 
         
     | 
| 
      
 181 
     | 
    
         
            +
                  403 => "ERROR_PROCESS_MODE_NOT_BACKGROUND", 
         
     | 
| 
      
 182 
     | 
    
         
            +
                  30 => "ERROR_READ_FAULT", 
         
     | 
| 
      
 183 
     | 
    
         
            +
                  72 => "ERROR_REDIR_PAUSED", 
         
     | 
| 
      
 184 
     | 
    
         
            +
                  201 => "ERROR_RELOC_CHAIN_XEEDS_SEGLIM", 
         
     | 
| 
      
 185 
     | 
    
         
            +
                  51 => "ERROR_REM_NOT_LIST", 
         
     | 
| 
      
 186 
     | 
    
         
            +
                  71 => "ERROR_REQ_NOT_ACCEP", 
         
     | 
| 
      
 187 
     | 
    
         
            +
                  207 => "ERROR_RING2_STACK_IN_USE", 
         
     | 
| 
      
 188 
     | 
    
         
            +
                  200 => "ERROR_RING2SEG_MUST_BE_MOVABLE", 
         
     | 
| 
      
 189 
     | 
    
         
            +
                  143 => "ERROR_SAME_DRIVE", 
         
     | 
| 
      
 190 
     | 
    
         
            +
                  318 => "ERROR_SCOPE_NOT_FOUND", 
         
     | 
| 
      
 191 
     | 
    
         
            +
                  27 => "ERROR_SECTOR_NOT_FOUND", 
         
     | 
| 
      
 192 
     | 
    
         
            +
                  306 => "ERROR_SECURITY_STREAM_IS_INCONSISTENT", 
         
     | 
| 
      
 193 
     | 
    
         
            +
                  132 => "ERROR_SEEK_ON_DEVICE", 
         
     | 
| 
      
 194 
     | 
    
         
            +
                  25 => "ERROR_SEEK", 
         
     | 
| 
      
 195 
     | 
    
         
            +
                  102 => "ERROR_SEM_IS_SET", 
         
     | 
| 
      
 196 
     | 
    
         
            +
                  187 => "ERROR_SEM_NOT_FOUND", 
         
     | 
| 
      
 197 
     | 
    
         
            +
                  105 => "ERROR_SEM_OWNER_DIED", 
         
     | 
| 
      
 198 
     | 
    
         
            +
                  121 => "ERROR_SEM_TIMEOUT", 
         
     | 
| 
      
 199 
     | 
    
         
            +
                  106 => "ERROR_SEM_USER_LIMIT", 
         
     | 
| 
      
 200 
     | 
    
         
            +
                  36 => "ERROR_SHARING_BUFFER_EXCEEDED", 
         
     | 
| 
      
 201 
     | 
    
         
            +
                  70 => "ERROR_SHARING_PAUSED", 
         
     | 
| 
      
 202 
     | 
    
         
            +
                  32 => "ERROR_SHARING_VIOLATION", 
         
     | 
| 
      
 203 
     | 
    
         
            +
                  305 => "ERROR_SHORT_NAMES_NOT_ENABLED_ON_VOLUME", 
         
     | 
| 
      
 204 
     | 
    
         
            +
                  162 => "ERROR_SIGNAL_PENDING", 
         
     | 
| 
      
 205 
     | 
    
         
            +
                  156 => "ERROR_SIGNAL_REFUSED", 
         
     | 
| 
      
 206 
     | 
    
         
            +
                  141 => "ERROR_SUBST_TO_JOIN", 
         
     | 
| 
      
 207 
     | 
    
         
            +
                  139 => "ERROR_SUBST_TO_SUBST", 
         
     | 
| 
      
 208 
     | 
    
         
            +
                  0 => "ERROR_SUCCESS", 
         
     | 
| 
      
 209 
     | 
    
         
            +
                  150 => "ERROR_SYSTEM_TRACE", 
         
     | 
| 
      
 210 
     | 
    
         
            +
                  210 => "ERROR_THREAD_1_INACTIVE", 
         
     | 
| 
      
 211 
     | 
    
         
            +
                  400 => "ERROR_THREAD_MODE_ALREADY_BACKGROUND", 
         
     | 
| 
      
 212 
     | 
    
         
            +
                  401 => "ERROR_THREAD_MODE_NOT_BACKGROUND", 
         
     | 
| 
      
 213 
     | 
    
         
            +
                  56 => "ERROR_TOO_MANY_CMDS", 
         
     | 
| 
      
 214 
     | 
    
         
            +
                  214 => "ERROR_TOO_MANY_MODULES", 
         
     | 
| 
      
 215 
     | 
    
         
            +
                  152 => "ERROR_TOO_MANY_MUXWAITERS", 
         
     | 
| 
      
 216 
     | 
    
         
            +
                  68 => "ERROR_TOO_MANY_NAMES", 
         
     | 
| 
      
 217 
     | 
    
         
            +
                  4 => "ERROR_TOO_MANY_OPEN_FILES", 
         
     | 
| 
      
 218 
     | 
    
         
            +
                  298 => "ERROR_TOO_MANY_POSTS", 
         
     | 
| 
      
 219 
     | 
    
         
            +
                  103 => "ERROR_TOO_MANY_SEM_REQUESTS", 
         
     | 
| 
      
 220 
     | 
    
         
            +
                  100 => "ERROR_TOO_MANY_SEMAPHORES", 
         
     | 
| 
      
 221 
     | 
    
         
            +
                  69 => "ERROR_TOO_MANY_SESS", 
         
     | 
| 
      
 222 
     | 
    
         
            +
                  155 => "ERROR_TOO_MANY_TCBS", 
         
     | 
| 
      
 223 
     | 
    
         
            +
                  59 => "ERROR_UNEXP_NET_ERR", 
         
     | 
| 
      
 224 
     | 
    
         
            +
                  240 => "ERROR_VC_DISCONNECTED", 
         
     | 
| 
      
 225 
     | 
    
         
            +
                  226 => "ERROR_VIRUS_DELETED", 
         
     | 
| 
      
 226 
     | 
    
         
            +
                  225 => "ERROR_VIRUS_INFECTED", 
         
     | 
| 
      
 227 
     | 
    
         
            +
                  128 => "ERROR_WAIT_NO_CHILDREN", 
         
     | 
| 
      
 228 
     | 
    
         
            +
                  29 => "ERROR_WRITE_FAULT", 
         
     | 
| 
      
 229 
     | 
    
         
            +
                  19 => "ERROR_WRITE_PROTECT", 
         
     | 
| 
      
 230 
     | 
    
         
            +
                  34 => "ERROR_WRONG_DISK", 
         
     | 
| 
      
 231 
     | 
    
         
            +
                  258 => "WAIT_TIMEOUT"
         
     | 
| 
      
 232 
     | 
    
         
            +
                }
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                class DCB < FFI::Struct
         
     | 
| 
      
 235 
     | 
    
         
            +
                  layout  :dcblength,   :uint32,
         
     | 
| 
      
 236 
     | 
    
         
            +
                          :baudrate,    :uint32,
         
     | 
| 
      
 237 
     | 
    
         
            +
                          :flags,       :uint32,    # :flag is actually a bit fields compound:
         
     | 
| 
      
 238 
     | 
    
         
            +
                          :wreserved,   :uint16,    #   uint32 fBinary :1;
         
     | 
| 
      
 239 
     | 
    
         
            +
                          :xonlim,      :uint16,    #   uint32 fParity :1;
         
     | 
| 
      
 240 
     | 
    
         
            +
                          :xofflim,     :uint16,    #   uint32 fParity :1;
         
     | 
| 
      
 241 
     | 
    
         
            +
                          :bytesize,    :uint8,     #   uint32 fOutxCtsFlow :1;
         
     | 
| 
      
 242 
     | 
    
         
            +
                          :parity,      :uint8,     #   uint32 fOutxDsrFlow :1;
         
     | 
| 
      
 243 
     | 
    
         
            +
                          :stopbits,    :uint8,     #   uint32 fDtrControl :2;
         
     | 
| 
      
 244 
     | 
    
         
            +
                          :xonchar,     :int8,      #   uint32 fDsrSensitivity :1;
         
     | 
| 
      
 245 
     | 
    
         
            +
                          :xoffchar,    :int8,      #   uint32 fTXContinueOnXoff :1;
         
     | 
| 
      
 246 
     | 
    
         
            +
                          :errorchar,   :int8,      #   uint32 fOutX :1;
         
     | 
| 
      
 247 
     | 
    
         
            +
                          :eofchar,     :int8,      #   uint32 fInX :1;
         
     | 
| 
      
 248 
     | 
    
         
            +
                          :evtchar,     :int8,      #   uint32 fErrorChar :1;
         
     | 
| 
      
 249 
     | 
    
         
            +
                          :wreserved1,  :uint16     #   uint32 fNull :1;
         
     | 
| 
      
 250 
     | 
    
         
            +
                                                    #   uint32 fRtsControl :2;
         
     | 
| 
      
 251 
     | 
    
         
            +
                                                    #   uint32 fAbortOnError :1;
         
     | 
| 
      
 252 
     | 
    
         
            +
                                                    #   uint32 fDummy2 :17;
         
     | 
| 
      
 253 
     | 
    
         
            +
                  Sizeof      = 28 
         
     | 
| 
      
 254 
     | 
    
         
            +
                  ONESTOPBIT  = 0  
         
     | 
| 
      
 255 
     | 
    
         
            +
                  NOPARITY    = 0
         
     | 
| 
      
 256 
     | 
    
         
            +
                end
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
                class CommTimeouts < FFI::Struct
         
     | 
| 
      
 259 
     | 
    
         
            +
                  layout  :read_interval_timeout,           :uint32,
         
     | 
| 
      
 260 
     | 
    
         
            +
                          :read_total_timeout_multiplier,   :uint32,
         
     | 
| 
      
 261 
     | 
    
         
            +
                          :read_total_timeout_constant,     :uint32,
         
     | 
| 
      
 262 
     | 
    
         
            +
                          :write_total_timeout_multiplier,  :uint32,
         
     | 
| 
      
 263 
     | 
    
         
            +
                          :write_total_timeout_constant,    :uint32
         
     | 
| 
      
 264 
     | 
    
         
            +
                end
         
     | 
| 
      
 265 
     | 
    
         
            +
             
     | 
| 
      
 266 
     | 
    
         
            +
                attach_function :CreateFileA,     [:pointer, :uint32, :uint32, :pointer, :uint32, :uint32, :pointer], :pointer
         
     | 
| 
      
 267 
     | 
    
         
            +
                attach_function :CloseHandle,     [:pointer], :int
         
     | 
| 
      
 268 
     | 
    
         
            +
                attach_function :ReadFile,        [:pointer, :pointer, :uint32, :pointer, :pointer], :int32
         
     | 
| 
      
 269 
     | 
    
         
            +
                attach_function :WriteFile,       [:pointer, :pointer, :uint32, :pointer, :pointer], :int32
         
     | 
| 
      
 270 
     | 
    
         
            +
                attach_function :GetCommState,    [:pointer, RubySerial::Win32::DCB], :int32
         
     | 
| 
      
 271 
     | 
    
         
            +
                attach_function :SetCommState,    [:pointer, RubySerial::Win32::DCB], :int32
         
     | 
| 
      
 272 
     | 
    
         
            +
                attach_function :GetCommTimeouts, [:pointer, RubySerial::Win32::CommTimeouts], :int32
         
     | 
| 
      
 273 
     | 
    
         
            +
                attach_function :SetCommTimeouts, [:pointer, RubySerial::Win32::CommTimeouts], :int32
         
     | 
| 
      
 274 
     | 
    
         
            +
              end
         
     | 
| 
      
 275 
     | 
    
         
            +
            end
         
     |