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