ffi-serial 1.0.3 → 1.0.4

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