ffi-serial 1.0.3 → 1.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 171e00de20624479f57c484dde3675d6020564af
4
- data.tar.gz: 72cd514955beeb975a37afe754d45e2684b2459d
3
+ metadata.gz: 7f14f5fa7b1ce50d9e803e54e5b58973e346f451
4
+ data.tar.gz: 626100a1daf9c5116556e7178300e08c0ac99ace
5
5
  SHA512:
6
- metadata.gz: 5ffa5a7365668b12655c78042db290c60f617ed9e9c128c1b384b3bcbc9eabb643c98c111d8a6fe421c3f603704b4144212825a727f1a8021b088e98eb62d36e
7
- data.tar.gz: 648ae77871fb16e3317e8f3815eedd95a6823ca1b5bf51cb06b3251ff0c5a24a629d4e4f44bed79e3b72d7a497c3c2393bd7a8ecbb918a3c3405916d031b5655
6
+ metadata.gz: a7f948d7807357304a2d237896287c2a61b488aa01a12a9a5c7682c87dad4738180f4cefd9bc77c32bbd0c8eba896b11b691ef57fdf0848e2691820cf72c22ed
7
+ data.tar.gz: ff9f571d42ec5859a97754ee12a8af9d014715169f8eeb38b4b00fefdd7066daa55967ada9d546d3742c1bd22385266c8051f3ade1add937c5f90e0a4a3bb25e
@@ -22,6 +22,14 @@ module Serial
22
22
  # :attr_reader: parity
23
23
  # Determine the current serial port parity by querying the underlying operating system
24
24
 
25
+ ##
26
+ # :attr_accessor: read_timeout
27
+ # Get/Set the read_timeout
28
+ #
29
+ # - 0< nonblocking IO
30
+ # - 0 - blocking IO
31
+ # - >0 - Timeout in seconds (Float)
32
+
25
33
  ##
26
34
  # Create a new Ruby IO configured with the serial port parameters
27
35
  #
@@ -49,6 +49,10 @@ module Serial #:nodoc:
49
49
  termios[:c_iflag] = (termios[:c_iflag] | LIBC::CONSTANTS['IXON'] | LIBC::CONSTANTS['IXOFF'] | LIBC::CONSTANTS['IXANY'])
50
50
  termios[:c_cflag] = (termios[:c_cflag] | LIBC::CONSTANTS['CLOCAL'] | LIBC::CONSTANTS['CREAD'] | LIBC::CONSTANTS['HUPCL'])
51
51
 
52
+ # Blocking read
53
+ termios[:cc_c][LIBC::CONSTANTS['VMIN']] = 1
54
+ termios[:cc_c][LIBC::CONSTANTS['VTIME']] = 0
55
+
52
56
  LIBC.tcsetattr(io, termios)
53
57
  io.extend(self)
54
58
  rescue Exception
@@ -58,16 +62,32 @@ module Serial #:nodoc:
58
62
  io
59
63
  end
60
64
 
61
- # It seems like VMIN and VTIME is broken :(
62
- # So this seems to be the only way to implement read the way it should be
63
- def read(length = nil, buffer = nil) #:nodoc:
64
- IO.select([self]) # Block
65
- super(length, buffer)
65
+ def read_timeout #:nodoc:
66
+ termios = LIBC.tcgetattr(self)
67
+ return 0 unless (0 == termios[:cc_c][LIBC::CONSTANTS['VMIN']])
68
+ vtime = termios[:cc_c][LIBC::CONSTANTS['VTIME']]
69
+ return -1 if (0 == vtime)
70
+ (vtime.to_f / 10.0)
66
71
  end
67
72
 
68
- def readpartial(length, buffer = nil) #:nodoc:
69
- IO.select([self]) # Block
70
- super(length, buffer)
73
+ def read_timeout=(val) #:nodoc:
74
+ val = Float(val)
75
+ termios = LIBC.tcgetattr(self)
76
+ if (0 > val)
77
+ termios[:cc_c][LIBC::CONSTANTS['VMIN']] = 0
78
+ termios[:cc_c][LIBC::CONSTANTS['VTIME']] = 0
79
+ val = -1
80
+ elsif (0 == val)
81
+ termios[:cc_c][LIBC::CONSTANTS['VMIN']] = 1
82
+ termios[:cc_c][LIBC::CONSTANTS['VTIME']] = 0
83
+ val = 0
84
+ else
85
+ val = (val * 10.0).to_i
86
+ termios[:cc_c][LIBC::CONSTANTS['VMIN']] = 0
87
+ termios[:cc_c][LIBC::CONSTANTS['VTIME']] = val
88
+ val = (val.to_f / 10.0)
89
+ end
90
+ LIBC.tcsetattr(self, termios); val
71
91
  end
72
92
 
73
93
  def baud #:nodoc:
@@ -18,10 +18,8 @@ module Serial #:nodoc:
18
18
 
19
19
  io = File.open(com_port, IO::RDWR|IO::BINARY)
20
20
  begin
21
- io.instance_variable_set(:@__serial__port__, com_port[4..-1].to_s.freeze)
22
-
23
- io.extend(self)
24
21
  io.sync = true
22
+ io.instance_variable_set(:@__serial__port__, com_port[4..-1].to_s.freeze)
25
23
 
26
24
  # Sane defaults
27
25
  dcb[:Flags] = dcb[:Flags] | (Kernel32::CONSTANTS['FLAGS'].fetch('fDtrControl').fetch(:enable))
@@ -30,7 +28,17 @@ module Serial #:nodoc:
30
28
 
31
29
  Kernel32.SetCommState(io, dcb)
32
30
  Kernel32.ClearCommError(io)
33
- Kernel32.set_io_block(io)
31
+
32
+ # Blocking io
33
+ commtimeouts = Kernel32::COMMTIMEOUTS.new
34
+ commtimeouts[:ReadIntervalTimeout] = Kernel32::CONSTANTS['MAXDWORD']
35
+ commtimeouts[:ReadTotalTimeoutMultiplier] = Kernel32::CONSTANTS['MAXDWORD']
36
+ commtimeouts[:ReadTotalTimeoutConstant] = Kernel32::CONSTANTS['MAXDWORD'] - 1
37
+ commtimeouts[:WriteTotalTimeoutMultiplier] = 0
38
+ commtimeouts[:WriteTotalTimeoutConstant] = Kernel32::CONSTANTS['MAXDWORD'] - 1
39
+ Kernel32.SetCommTimeouts(io, commtimeouts)
40
+
41
+ io.extend(self)
34
42
  rescue Exception
35
43
  begin; io.close; rescue Exception; end
36
44
  raise
@@ -38,6 +46,36 @@ module Serial #:nodoc:
38
46
  io
39
47
  end
40
48
 
49
+ def read_timeout
50
+ commtimeouts = Kernel32.GetCommTimeouts(self)
51
+ return -1 if (0 == commtimeouts[:ReadTotalTimeoutConstant])
52
+ return 0 if (Kernel32::CONSTANTS['MAXDWORD'] == commtimeouts[:ReadIntervalTimeout])
53
+ Float(commtimeouts[:ReadTotalTimeoutConstant])/1000.0
54
+ end
55
+
56
+ def read_timeout=(val)
57
+ val = Float(val)
58
+ commtimeouts = Kernel32.GetCommTimeouts(self)
59
+ if (0 > val)
60
+ commtimeouts[:ReadIntervalTimeout] = Kernel32::CONSTANTS['MAXDWORD']
61
+ commtimeouts[:ReadTotalTimeoutMultiplier] = 0
62
+ commtimeouts[:ReadTotalTimeoutConstant] = 0
63
+ val = -1
64
+ elsif (0 == val)
65
+ commtimeouts[:ReadIntervalTimeout] = Kernel32::CONSTANTS['MAXDWORD']
66
+ commtimeouts[:ReadTotalTimeoutMultiplier] = Kernel32::CONSTANTS['MAXDWORD']
67
+ commtimeouts[:ReadTotalTimeoutConstant] = Kernel32::CONSTANTS['MAXDWORD'] - 1
68
+ val = 0
69
+ else
70
+ val = (val * 1000.0).to_i
71
+ commtimeouts[:ReadIntervalTimeout] = val
72
+ commtimeouts[:ReadTotalTimeoutMultiplier] = 0
73
+ commtimeouts[:ReadTotalTimeoutConstant] = val
74
+ val = (val / 1000.0)
75
+ end
76
+ Kernel32.SetCommTimeouts(self, commtimeouts); val
77
+ end
78
+
41
79
  def baud #:nodoc:
42
80
  Kernel32.GetCommState(self).baud
43
81
  end
@@ -55,13 +93,7 @@ module Serial #:nodoc:
55
93
  end
56
94
 
57
95
  def read_nonblock(maxlen, outbuf = nil, options = nil) #:nodoc:
58
- Kernel32.set_io_nonblock(self)
59
- result = begin
60
- outbuf.nil? ? read(maxlen) : read(maxlen, outbuf)
61
- ensure
62
- Kernel32.set_io_block(self)
63
- end
64
-
96
+ result = Kernel32.nonblock_io(self) { outbuf.nil? ? self.read(maxlen) : self.read(maxlen, outbuf) }
65
97
  if result.nil? || (0 == result.length)
66
98
  if ((!options.nil?) && (false == options[:exception]))
67
99
  return :wait_readable
@@ -77,28 +109,19 @@ module Serial #:nodoc:
77
109
  return ch
78
110
  end
79
111
  self.ungetc(ch)
80
- Kernel32.set_io_nonblock(self)
81
- outbuf.nil? ? read(maxlen) : read(maxlen, outbuf)
82
- ensure
83
- Kernel32.set_io_block(self)
112
+ Kernel32.nonblock_io(self) { outbuf.nil? ? self.read(maxlen) : self.read(maxlen, outbuf) }
84
113
  end
85
114
 
86
115
  def readbyte #:nodoc:
87
- Kernel32.set_io_nonblock(self); super
88
- ensure
89
- Kernel32.set_io_block(self)
116
+ Kernel32.nonblock_io(self) { super }
90
117
  end
91
118
 
92
119
  def getc #:nodoc:
93
- Kernel32.set_io_nonblock(self); super
94
- ensure
95
- Kernel32.set_io_block(self)
120
+ Kernel32.nonblock_io(self) { super }
96
121
  end
97
122
 
98
123
  def readchar #:nodoc:
99
- Kernel32.set_io_nonblock(self); super
100
- ensure
101
- Kernel32.set_io_block(self)
124
+ Kernel32.nonblock_io(self) { super }
102
125
  end
103
126
 
104
127
  def to_s #:nodoc:
@@ -134,7 +157,7 @@ module Serial #:nodoc:
134
157
 
135
158
  def self.GetCommTimeouts(ruby_io) #:nodoc:
136
159
  commtimeouts = COMMTIMEOUTS.new
137
- return commtimeouts unless (0 == c_GetCommTimeouts(LIBC._get_osfhandle(fd), commtimeouts))
160
+ return commtimeouts unless (0 == c_GetCommTimeouts(LIBC._get_osfhandle(ruby_io), commtimeouts))
138
161
  raise ERRNO[FFI.errno].new
139
162
  end
140
163
 
@@ -148,19 +171,9 @@ module Serial #:nodoc:
148
171
  raise ERRNO[FFI.errno].new
149
172
  end
150
173
 
151
- def self.set_io_block(ruby_io) #:nodoc:
152
- self.SetCommTimeouts(ruby_io, (@@read_block_io ||= begin
153
- timeouts = COMMTIMEOUTS.new
154
- timeouts[:ReadIntervalTimeout] = CONSTANTS['MAXDWORD']
155
- timeouts[:ReadTotalTimeoutMultiplier] = CONSTANTS['MAXDWORD']
156
- timeouts[:ReadTotalTimeoutConstant] = CONSTANTS['MAXDWORD'] - 1
157
- timeouts[:WriteTotalTimeoutMultiplier] = 0
158
- timeouts[:WriteTotalTimeoutConstant] = CONSTANTS['MAXDWORD'] - 1
159
- timeouts
160
- end))
161
- end
162
-
163
- def self.set_io_nonblock(ruby_io) #:nodoc:
174
+ def self.nonblock_io(ruby_io, &blk)
175
+ return nil if blk.nil?
176
+ commtimeouts = self.GetCommTimeouts(ruby_io)
164
177
  self.SetCommTimeouts(ruby_io, (@@read_nonblock_io ||= begin
165
178
  timeouts = COMMTIMEOUTS.new
166
179
  timeouts[:ReadIntervalTimeout] = CONSTANTS['MAXDWORD']
@@ -170,6 +183,11 @@ module Serial #:nodoc:
170
183
  timeouts[:WriteTotalTimeoutConstant] = 1
171
184
  timeouts
172
185
  end))
186
+ begin
187
+ blk.yield
188
+ ensure
189
+ self.SetCommTimeouts(ruby_io, commtimeouts)
190
+ end
173
191
  end
174
192
 
175
193
  class DCB < FFI::Struct #:nodoc:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-serial
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johan van der Vyver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-03 00:00:00.000000000 Z
11
+ date: 2016-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi