ccutrer-serialport 1.0.0 → 1.1.0

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
  SHA256:
3
- metadata.gz: 5883d7fba69f81de31f8f8d2a21f25e1734fb25adce3a3ec9f873a67c9e96b43
4
- data.tar.gz: 780c226269254d5d413445159cdd8a3603d5e835c315eb00cc9c50557d1b1fbf
3
+ metadata.gz: 69c3b68becbcef8f755d29da38ddd0d1532efabb76daa1f4397b6fbc713f0893
4
+ data.tar.gz: ff3d20273bd129636c01836f5e29a5a4ac82ac16ae9840c63e6fa79f16537184
5
5
  SHA512:
6
- metadata.gz: 27f8bb29ca45fff55a30b0825dc1087f74259de5a81bb1a6671f90c95a52bf4e832f21ca40c79e84e1e486d5da362199d631a90134df34e09ce4b2162721acdc
7
- data.tar.gz: '08619960bba97f86e4752a14587b3b9d2a9b68723a76e681d7afe1e6f1f72a490c7cc23c9d43fc0155cc582db2e98e1323be9fcff23c45ce17a4d33dad711d1b'
6
+ metadata.gz: 2f30d416a29cd1bab53072caeff2bfd2ade151ba1d0f687bae4b3217493a0dc63979def24e4fca3d68528af7570abf0df85bb9d9542b4ec0261fb8b4edf92ba5
7
+ data.tar.gz: 3da04dcfa3ad985c233f6a8a7732b0b4abed9e5a41cba72804753bdab38a9b07cf3a5ba66f1b401f9f0356e3eea7e8fabd8a02d800ae06a1234098089caf7af2
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ccutrer-serialport (1.0.0)
4
+ ccutrer-serialport (1.1.0)
5
5
  ffi (~> 1.9, >= 1.9.3)
6
6
 
7
7
  GEM
@@ -10,11 +10,16 @@ module CCutrer
10
10
 
11
11
  if ON_WINDOWS
12
12
  raise "rubyserial is not currently supported on windows"
13
- elsif ON_LINUX
13
+ end
14
+
15
+ # order is important here
16
+ require 'ccutrer/serial_port/termios'
17
+ if ON_LINUX
14
18
  require 'ccutrer/serial_port/linux'
15
19
  else
16
20
  require 'ccutrer/serial_port/osx'
17
21
  end
22
+ require 'ccutrer/serial_port/posix'
18
23
  end
19
24
  end
20
25
 
@@ -3,7 +3,7 @@
3
3
  require 'fcntl'
4
4
 
5
5
  class CCutrer::SerialPort < File
6
- def initialize(address, baud: 9600, data_bits: 8, parity: :none, stop_bits: 1)
6
+ def initialize(address, baud: nil, data_bits: nil, parity: nil, stop_bits: nil)
7
7
  super(address, IO::RDWR | IO::NOCTTY | IO::NONBLOCK)
8
8
 
9
9
  raise IOError, "Not a serial port" unless tty?
@@ -11,35 +11,123 @@ class CCutrer::SerialPort < File
11
11
  fl = fcntl(Fcntl::F_GETFL, 0)
12
12
  fcntl(Fcntl::F_SETFL, ~Fcntl::O_NONBLOCK & fl)
13
13
 
14
- @config = build_config(baud, data_bits, parity, stop_bits)
14
+ @termios = Termios::Termios.new
15
+ refresh
15
16
 
16
- err = Posix.tcsetattr(fileno, Posix::TCSANOW, @config)
17
- if err == -1
18
- raise SystemCallError, FFI.errno
17
+ # base config
18
+ @termios[:c_iflag] = Termios::IGNPAR
19
+ @termios[:c_oflag] = 0
20
+ @termios[:c_cflag] =
21
+ Termios::CREAD |
22
+ Termios::CLOCAL
23
+ @termios[:c_lflag] = 0
24
+
25
+ @termios[:c_cc][Termios::VTIME] = 0
26
+ @termios[:c_cc][Termios::VMIN] = 0
27
+
28
+ configure do
29
+ self.baud = baud if baud
30
+ self.data_bits = data_bits if data_bits
31
+ self.parity = parity if parity
32
+ self.stop_bits = stop_bits if stop_bits
19
33
  end
34
+ raise Errno::EINVAL if baud && baud != self.baud
35
+ raise Errno::EINVAL if data_bits && data_bits != self.data_bits
36
+ raise Errno::EINVAL if parity && parity != self.parity
37
+ raise Errno::EINVAL if stop_bits && stop_bits != self.stop_bits
38
+ end
39
+
40
+ def configure
41
+ @configuring = true
42
+ yield
43
+ @configuring = false
44
+ apply
45
+ refresh
46
+ ensure
47
+ @configuring = false
48
+ end
49
+
50
+ def baud
51
+ Termios::BAUD_RATES.invert[Termios.cfgetispeed(@termios)]
52
+ end
53
+
54
+ def baud=(baud)
55
+ raise ArgumentError, "Invalid baud" unless Termios::BAUD_RATES.key?(baud)
56
+
57
+ err = Termios.cfsetispeed(@termios, Termios::BAUD_RATES[baud])
58
+ raise SystemCallError, FFI.errno if err == -1
59
+ err = Termios.cfsetospeed(@termios, Termios::BAUD_RATES[baud])
60
+ raise SystemCallError, FFI.errno if err == -1
61
+ apply
62
+ refresh
63
+ self.baud
64
+ end
65
+
66
+ def data_bits
67
+ Termios::DATA_BITS.invert[@termios[:c_cflag] & Termios::CSIZE]
68
+ end
69
+
70
+ def data_bits=(data_bits)
71
+ raise ArgumentError, "Invalid data bits" unless Termios::DATA_BITS.key?(data_bits)
72
+
73
+ @termios[:c_cflag] &= ~Termios::CSIZE
74
+ @termios[:c_cflag] |= Termios::DATA_BITS[data_bits]
75
+ apply
76
+ refresh
77
+ self.data_bits
78
+ end
79
+
80
+ def parity
81
+ Termios::PARITY.invert[@termios[:c_cflag] & Termios::PARITY[:odd]]
82
+ end
83
+
84
+ def parity=(parity)
85
+ raise ArgumentError, "Invalid parity" unless Termios::PARITY.key?(parity)
86
+
87
+ @termios[:c_cflag] &= ~Termios::PARITY[:odd]
88
+ @termios[:c_cflag] |= Termios::PARITY[parity]
89
+ apply
90
+ refresh
91
+ self.parity
92
+ end
93
+
94
+ def stop_bits
95
+ (@termios[:c_cflag] & Termios::CSTOPB) != 0 ? 2 : 1
96
+ end
97
+
98
+ def stop_bits=(stop_bits)
99
+ raise ArgumentError, "Invalid stop bits" unless Termios::STOP_BITS.key?(stop_bits)
100
+
101
+ @termios[:c_cflag] &= ~Termios::CSTOPB
102
+ @termios[:c_cflag] |= Termios::STOP_BITS[stop_bits]
103
+ apply
104
+ refresh
105
+ self.stop_bits
106
+ end
107
+
108
+ def inspect
109
+ "#<#{self.class.name}:#{path} #{baud} #{data_bits}#{parity.to_s[0].upcase}#{stop_bits}>"
20
110
  end
21
111
 
22
112
  private
23
113
 
24
- def build_config(baud_rate, data_bits, parity, stop_bits)
25
- config = Posix::Termios.new
26
-
27
- config[:c_iflag] = Posix::IGNPAR
28
- config[:c_ispeed] = Posix::BAUD_RATES[baud_rate]
29
- config[:c_ospeed] = Posix::BAUD_RATES[baud_rate]
30
- config[:c_cflag] = Posix::DATA_BITS[data_bits] |
31
- Posix::CREAD |
32
- Posix::CLOCAL |
33
- Posix::PARITY[parity] |
34
- Posix::STOPBITS[stop_bits]
35
-
36
- # Masking in baud rate on OS X would corrupt the settings.
37
- if ON_LINUX
38
- config[:c_cflag] = config[:c_cflag] | Posix::BAUD_RATES[baud_rate]
114
+ def apply
115
+ return if @configuring
116
+ err = Termios.tcsetattr(fileno, Termios::TCSANOW, @termios)
117
+ raise SystemCallError, FFI.errno if err == -1
118
+ self
119
+ rescue SystemCallError
120
+ begin
121
+ refresh
122
+ rescue SystemCallError
39
123
  end
124
+ raise
125
+ end
40
126
 
41
- config[:cc_c][Posix::VMIN] = 0
42
-
43
- config
127
+ def refresh
128
+ return if @configuring
129
+ err = Termios.tcgetattr(fileno, @termios)
130
+ raise SystemCallError, FFI.errno if err == -1
131
+ self
44
132
  end
45
133
  end
@@ -1,20 +1,33 @@
1
- # Copyright (c) 2014-2016 The Hybrid Group, 2020 Cody Cutrer
1
+ # Copyright (c) 2014-2016 The Hybrid Group, 2020-2021 Cody Cutrer
2
2
 
3
- module CCutrer::SerialPort::Posix
4
- extend FFI::Library
5
- ffi_lib FFI::Library::LIBC
3
+ module CCutrer::SerialPort::Termios
4
+ NCCS = 32
5
+
6
+ class Termios < FFI::Struct
7
+ layout :c_iflag, :uint,
8
+ :c_oflag, :uint,
9
+ :c_cflag, :uint,
10
+ :c_lflag, :uint,
11
+ :c_line, :uchar,
12
+ :c_cc, [ :uchar, NCCS ],
13
+ :c_ispeed, :uint,
14
+ :c_ospeed, :uint
15
+ end
6
16
 
17
+ # c_cc characters
7
18
  VTIME = 5
8
- TCSANOW = 0
9
- TCSETS = 0x5402
19
+ VMIN = 6
20
+
21
+ # c_iflag bits
10
22
  IGNPAR = 0000004
11
- PARENB = 0000400
12
- PARODD = 0001000
23
+
24
+ # c_cflag bits
25
+ CSIZE = 0000060
13
26
  CSTOPB = 0000100
14
27
  CREAD = 0000200
28
+ PARENB = 0000400
29
+ PARODD = 0001000
15
30
  CLOCAL = 0004000
16
- VMIN = 6
17
- NCCS = 32
18
31
 
19
32
  DATA_BITS = {
20
33
  5 => 0000000,
@@ -58,27 +71,15 @@ module CCutrer::SerialPort::Posix
58
71
  }
59
72
 
60
73
  PARITY = {
61
- :none => 0000000,
62
- :even => PARENB,
63
- :odd => PARENB | PARODD,
74
+ none: 0000000,
75
+ even: PARENB,
76
+ odd: PARENB | PARODD,
64
77
  }
65
78
 
66
- STOPBITS = {
67
- 1 => 0x00000000,
79
+ STOP_BITS = {
80
+ 1 => 0000000,
68
81
  2 => CSTOPB
69
82
  }
70
83
 
71
- class Termios < FFI::Struct
72
- layout :c_iflag, :uint,
73
- :c_oflag, :uint,
74
- :c_cflag, :uint,
75
- :c_lflag, :uint,
76
- :c_line, :uchar,
77
- :cc_c, [ :uchar, NCCS ],
78
- :c_ispeed, :uint,
79
- :c_ospeed, :uint
80
- end
81
-
82
- attach_function :tcsetattr, [ :int, :int, Termios ], :int, blocking: true
83
- attach_function :tcgetattr, [ :int, Termios ], :int, blocking: true
84
+ TCSANOW = 0
84
85
  end
@@ -1,20 +1,33 @@
1
- # Copyright (c) 2014-2016 The Hybrid Group, 2020 Cody Cutrer
1
+ # Copyright (c) 2014-2016 The Hybrid Group, 2020-2021 Cody Cutrer
2
2
 
3
- module CCutrer::SerialPort::Posix
4
- extend FFI::Library
5
- ffi_lib FFI::Library::LIBC
3
+ module CCutrer::SerialPort::Termios
4
+ NCCS = 20
6
5
 
7
- IGNPAR = 0x00000004
8
- PARENB = 0x00001000
9
- PARODD = 0x00002000
6
+ class Termios < FFI::Struct
7
+ layout :c_iflag, :ulong,
8
+ :c_oflag, :ulong,
9
+ :c_cflag, :ulong,
10
+ :c_lflag, :ulong,
11
+ :c_line, :uchar,
12
+ :c_cc, [ :uchar, NCCS ],
13
+ :c_ispeed, :ulong,
14
+ :c_ospeed, :ulong
15
+ end
16
+
17
+ # c_cc characters
10
18
  VMIN = 16
11
19
  VTIME = 17
12
- CLOCAL = 0x00008000
20
+
21
+ # c_iflag bits
22
+ IGNPAR = 0x00000004
23
+
24
+ # c_cflag bits
25
+ CSIZE = 0x00000700
13
26
  CSTOPB = 0x00000400
14
27
  CREAD = 0x00000800
15
- CCTS_OFLOW = 0x00010000 # Clearing this disables RTS AND CTS.
16
- TCSANOW = 0
17
- NCCS = 20
28
+ PARENB = 0x00001000
29
+ PARODD = 0x00002000
30
+ CLOCAL = 0x00008000
18
31
 
19
32
  DATA_BITS = {
20
33
  5 => 0x00000000,
@@ -55,22 +68,10 @@ module CCutrer::SerialPort::Posix
55
68
  :odd => PARENB | PARODD,
56
69
  }
57
70
 
58
- STOPBITS = {
71
+ STOP_BITS = {
59
72
  1 => 0x00000000,
60
73
  2 => CSTOPB
61
74
  }
62
75
 
63
- class Termios < FFI::Struct
64
- layout :c_iflag, :ulong,
65
- :c_oflag, :ulong,
66
- :c_cflag, :ulong,
67
- :c_lflag, :ulong,
68
- :c_line, :uchar,
69
- :cc_c, [ :uchar, NCCS ],
70
- :c_ispeed, :ulong,
71
- :c_ospeed, :ulong
72
- end
73
-
74
- attach_function :tcsetattr, [ :int, :int, Termios ], :int, blocking: true
75
- attach_function :tcgetattr, [ :int, Termios ], :int, blocking: true
76
+ TCSANOW = 0
76
77
  end
@@ -0,0 +1,10 @@
1
+ # Copyright (c) 2014-2016 The Hybrid Group, 2020-2021 Cody Cutrer
2
+
3
+ module CCutrer::SerialPort::Termios
4
+ attach_function :cfgetispeed, [ Termios ], :uint, blocking: true
5
+ attach_function :cfgetospeed, [ Termios ], :uint, blocking: true
6
+ attach_function :cfsetispeed, [ Termios, :uint ], :int, blocking: true
7
+ attach_function :cfsetospeed, [ Termios, :uint ], :int, blocking: true
8
+ attach_function :tcsetattr, [ :int, :int, Termios ], :int, blocking: true
9
+ attach_function :tcgetattr, [ :int, Termios ], :int, blocking: true
10
+ end
@@ -0,0 +1,6 @@
1
+ # Copyright (c) 2014-2016 The Hybrid Group, 2020-2021 Cody Cutrer
2
+
3
+ module CCutrer::SerialPort::Termios
4
+ extend FFI::Library
5
+ ffi_lib FFI::Library::LIBC
6
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module CCutrer
4
4
  class SerialPort < File
5
- VERSION = "1.0.0"
5
+ VERSION = "1.1.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ccutrer-serialport
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-25 00:00:00.000000000 Z
11
+ date: 2021-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -78,6 +78,8 @@ files:
78
78
  - lib/ccutrer/serial_port.rb
79
79
  - lib/ccutrer/serial_port/linux.rb
80
80
  - lib/ccutrer/serial_port/osx.rb
81
+ - lib/ccutrer/serial_port/posix.rb
82
+ - lib/ccutrer/serial_port/termios.rb
81
83
  - lib/ccutrer/serial_port/version.rb
82
84
  - spec/serialport_spec.rb
83
85
  - spec/spec_helper.rb
@@ -100,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
102
  - !ruby/object:Gem::Version
101
103
  version: '0'
102
104
  requirements: []
103
- rubygems_version: 3.1.2
105
+ rubygems_version: 3.1.4
104
106
  signing_key:
105
107
  specification_version: 4
106
108
  summary: Linux/OS X RS-232 serial port communication