ccutrer-serialport 1.0.0 → 1.1.0

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
  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