rubyserial-with-blocking 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|