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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/ccutrer-serialport.rb +6 -1
- data/lib/ccutrer/serial_port.rb +111 -23
- data/lib/ccutrer/serial_port/linux.rb +29 -28
- data/lib/ccutrer/serial_port/osx.rb +26 -25
- data/lib/ccutrer/serial_port/posix.rb +10 -0
- data/lib/ccutrer/serial_port/termios.rb +6 -0
- data/lib/ccutrer/serial_port/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69c3b68becbcef8f755d29da38ddd0d1532efabb76daa1f4397b6fbc713f0893
|
4
|
+
data.tar.gz: ff3d20273bd129636c01836f5e29a5a4ac82ac16ae9840c63e6fa79f16537184
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f30d416a29cd1bab53072caeff2bfd2ade151ba1d0f687bae4b3217493a0dc63979def24e4fca3d68528af7570abf0df85bb9d9542b4ec0261fb8b4edf92ba5
|
7
|
+
data.tar.gz: 3da04dcfa3ad985c233f6a8a7732b0b4abed9e5a41cba72804753bdab38a9b07cf3a5ba66f1b401f9f0356e3eea7e8fabd8a02d800ae06a1234098089caf7af2
|
data/Gemfile.lock
CHANGED
data/lib/ccutrer-serialport.rb
CHANGED
@@ -10,11 +10,16 @@ module CCutrer
|
|
10
10
|
|
11
11
|
if ON_WINDOWS
|
12
12
|
raise "rubyserial is not currently supported on windows"
|
13
|
-
|
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
|
|
data/lib/ccutrer/serial_port.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'fcntl'
|
4
4
|
|
5
5
|
class CCutrer::SerialPort < File
|
6
|
-
def initialize(address, baud:
|
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
|
-
@
|
14
|
+
@termios = Termios::Termios.new
|
15
|
+
refresh
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
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::
|
4
|
-
|
5
|
-
|
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
|
-
|
9
|
-
|
19
|
+
VMIN = 6
|
20
|
+
|
21
|
+
# c_iflag bits
|
10
22
|
IGNPAR = 0000004
|
11
|
-
|
12
|
-
|
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
|
-
:
|
62
|
-
:
|
63
|
-
:
|
74
|
+
none: 0000000,
|
75
|
+
even: PARENB,
|
76
|
+
odd: PARENB | PARODD,
|
64
77
|
}
|
65
78
|
|
66
|
-
|
67
|
-
1 =>
|
79
|
+
STOP_BITS = {
|
80
|
+
1 => 0000000,
|
68
81
|
2 => CSTOPB
|
69
82
|
}
|
70
83
|
|
71
|
-
|
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::
|
4
|
-
|
5
|
-
ffi_lib FFI::Library::LIBC
|
3
|
+
module CCutrer::SerialPort::Termios
|
4
|
+
NCCS = 20
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
71
|
+
STOP_BITS = {
|
59
72
|
1 => 0x00000000,
|
60
73
|
2 => CSTOPB
|
61
74
|
}
|
62
75
|
|
63
|
-
|
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
|
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.
|
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:
|
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.
|
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
|