serialport 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/MANIFEST CHANGED
@@ -1,13 +1,13 @@
1
- CHANGELOG
2
- MANIFEST
3
- README
4
- Rakefile
5
- serialport.gemspec
6
- VERSION
7
- ext/native/extconf.rb
8
- ext/native/posix_serialport_impl.c
9
- ext/native/serialport.c
10
- ext/native/serialport.h
11
- ext/native/win_serialport_impl.c
12
- lib/serialport.rb
1
+ CHANGELOG
2
+ MANIFEST
3
+ README
4
+ Rakefile
5
+ serialport.gemspec
6
+ VERSION
7
+ ext/native/extconf.rb
8
+ ext/native/posix_serialport_impl.c
9
+ ext/native/serialport.c
10
+ ext/native/serialport.h
11
+ ext/native/win_serialport_impl.c
12
+ lib/serialport.rb
13
13
  test/miniterm.rb
data/README CHANGED
@@ -1,157 +1,153 @@
1
- -----Ruby/SerialPort-----
2
-
3
- -- Description --
4
-
5
- Ruby/SerialPort is a Ruby library that provides a class for using
6
- RS-232 serial ports. This class also contains low-level functions to
7
- check and set the current state of the signals on the line.
8
-
9
- The native Windows version of this library supports Microsoft's Visual C++, Borland's C++, and MinGW compilers.
10
-
11
- -- Installation --
12
-
13
- This gem is hosted at Gemcutter. Before you can install this, or any other Gemcutter gem you must
14
- add it as a gem source:
15
- gem sources -a http://gemcutter.org
16
-
17
- Then you can install the gem as normal:
18
- sudo gem install serialport
19
-
20
- -- Testing --
21
-
22
- * test/miniterm.rb
23
-
24
- Ruby's copy of miniterm.c !
25
-
26
-
27
- -- API --
28
-
29
- **** Class SerialPort, Parent IO ****
30
-
31
- ** Class constants **
32
-
33
- VERSION -> aString (this release is "0.6")
34
- NONE, HARD, SOFT, SPACE, MARK, EVEN, ODD -> anInteger
35
-
36
- ** Class methods **
37
-
38
- * new(port_num [, modem_parameters]) -> aSerialPort
39
- * open(port_num [, modem_parameters]) -> aSerialPort
40
- * open(port_num [, modem_parameters]) {|aSerialPort| block} ->
41
- value of the block
42
-
43
- port_num -> anInteger: port number, 0 for first port which is
44
- "/dev/ttyS0" on GNU/Linux and "COM1" on Windows,
45
- or aString: file name of the device (example: "/dev/ttyS2")
46
-
47
- Optional modem_parameters:
48
-
49
- baudrate -> anInteger: from 50 to 256000, depends on platform.
50
-
51
- databits -> anInteger: from 5 to 8 (4 is allowed on Windows)
52
-
53
- stopbits -> anInteger: 1 or 2 (1.5 is not supported)
54
-
55
- parity -> anInteger: SerialPort::NONE, SerialPort::EVEN,
56
- SerialPort::ODD, SerialPort::MARK, SerialPort::SPACE
57
- (MARK and SPACE are not supported on Posix)
58
-
59
- Raise an argError on bad argument.
60
-
61
- SerialPort::new and SerialPort::open without a block return an
62
- instance of SerialPort. SerialPort::open with a block passes
63
- a SerialPort to the block and closes it when the block exits
64
- (like File::open).
65
-
66
-
67
- ** Instance methods **
68
-
69
- * modem_params() -> aHash
70
- * modem_params=(aHash) -> aHash
71
- * get_modem_params() -> aHash
72
- * set_modem_params(aHash) -> aHash
73
- * set_modem_params(baudrate [, databits [, stopbits [, parity]]])
74
-
75
- Get and set the modem parameters. Hash keys are "baud", "data_bits",
76
- "stop_bits", and "parity" (see above).
77
-
78
- Parameters not present in the hash or set to nil remain unchanged.
79
- Default parameter values for the set_modem_params method are:
80
- databits = 8, stopbits = 1, parity = (databits == 8 ?
81
- SerialPort::NONE : SerialPort::EVEN).
82
-
83
- * baud() -> anInteger
84
- * baud=(anInteger) -> anInteger
85
- * data_bits() -> 4, 5, 6, 7, or 8
86
- * data_bits=(anInteger) -> anInteger
87
- * stop_bits() -> 1 or 2
88
- * stop_bits=(anInteger) -> anInteger
89
- * parity() -> anInteger: SerialPort::NONE, SerialPort::EVEN,
90
- SerialPort::ODD, SerialPort::MARK, or SerialPort::SPACE
91
- * parity=(anInteger) -> anInteger
92
-
93
- Get and set the corresponding modem parameter.
94
-
95
- * flow_control() -> anInteger
96
- * flow_control=(anInteger) -> anInteger
97
-
98
- Get and set the flow control: SerialPort::NONE, SerialPort::HARD,
99
- SerialPort::SOFT, or (SerialPort::HARD | SerialPort::SOFT).
100
-
101
- Note: SerialPort::HARD mode is not supported on all platforms.
102
- SerialPort::HARD uses RTS/CTS handshaking; DSR/DTR is not
103
- supported.
104
-
105
- * read_timeout() -> anInteger
106
- * read_timeout=(anInteger) -> anInteger
107
- * write_timeout() -> anInteger
108
- * write_timeout=(anInteger) -> anInteger
109
-
110
- Get and set timeout values (in milliseconds) for reading and writing.
111
- A negative read timeout will return all the available data without
112
- waiting, a zero read timeout will not return until at least one
113
- byte is available, and a positive read timeout returns when the
114
- requested number of bytes is available or the interval between the
115
- arrival of two bytes exceeds the timeout value.
116
-
117
- Note: Read timeouts don't mix well with multi-threading.
118
-
119
- Note: Under Posix, write timeouts are not implemented.
120
-
121
- * break(time) -> nil
122
-
123
- Send a break for the given time.
124
-
125
- time -> anInteger: tenths-of-a-second for the break.
126
- Note: Under Posix, this value is very approximate.
127
-
128
- * signals() -> aHash
129
-
130
- Return a hash with the state of each line status bit. Keys are
131
- "rts", "dtr", "cts", "dsr", "dcd", and "ri".
132
-
133
- Note: Under Windows, the rts and dtr values are not included.
134
-
135
- * rts()
136
- * dtr()
137
- * cts()
138
- * dsr()
139
- * dcd()
140
- * ri() -> 0 or 1
141
-
142
- * rts=(0 or 1)
143
- * dtr=(0 or 1) -> 0 or 1
144
-
145
- Get and set the corresponding line status bit.
146
-
147
- Note: Under Windows, rts() and dtr() are not implemented.
148
-
149
- -- License --
150
-
151
- GPL
152
-
153
- Guillaume Pierronnet <moumar@netcourrier.com>
154
- Alan Stern <stern@rowland.harvard.edu>
155
- Tobin Richard <tobin.richard@gmail.com>
156
- Hector Parra <hector@hectorparra.com>
157
- Ryan C. Payne <rpayne-oss@bullittsystems.com>
1
+ -----Ruby/SerialPort-----
2
+
3
+ -- Description --
4
+
5
+ Ruby/SerialPort is a Ruby library that provides a class for using
6
+ RS-232 serial ports. This class also contains low-level functions to
7
+ check and set the current state of the signals on the line.
8
+
9
+ The native Windows version of this library supports Microsoft's Visual C++, Borland's C++, and MinGW compilers.
10
+
11
+ -- Installation --
12
+
13
+ Then you can install the gem as normal:
14
+ sudo gem install serialport
15
+
16
+ -- Testing --
17
+
18
+ * test/miniterm.rb
19
+
20
+ Ruby's copy of miniterm.c !
21
+
22
+
23
+ -- API --
24
+
25
+ **** Class SerialPort, Parent IO ****
26
+
27
+ ** Class constants **
28
+
29
+ VERSION -> aString (EX: this release is "0.6")
30
+ NONE, HARD, SOFT, SPACE, MARK, EVEN, ODD -> anInteger
31
+
32
+ ** Class methods **
33
+
34
+ * new(port_num [, modem_parameters]) -> aSerialPort
35
+ * open(port_num [, modem_parameters]) -> aSerialPort
36
+ * open(port_num [, modem_parameters]) {|aSerialPort| block} ->
37
+ value of the block
38
+
39
+ port_num -> anInteger: port number, 0 for first port which is
40
+ "/dev/ttyS0" on GNU/Linux and "COM1" on Windows,
41
+ or aString: file name of the device (example: "/dev/ttyS2")
42
+
43
+ Optional modem_parameters:
44
+
45
+ baudrate -> anInteger: from 50 to 1000000, depends on platform.
46
+
47
+ databits -> anInteger: from 5 to 8 (4 is allowed on Windows)
48
+
49
+ stopbits -> anInteger: 1 or 2 (1.5 is not supported)
50
+
51
+ parity -> anInteger: SerialPort::NONE, SerialPort::EVEN,
52
+ SerialPort::ODD, SerialPort::MARK, SerialPort::SPACE
53
+ (MARK and SPACE are not supported on Posix)
54
+
55
+ Raise an argError on bad argument.
56
+
57
+ SerialPort::new and SerialPort::open without a block return an
58
+ instance of SerialPort. SerialPort::open with a block passes
59
+ a SerialPort to the block and closes it when the block exits
60
+ (like File::open).
61
+
62
+
63
+ ** Instance methods **
64
+
65
+ * modem_params() -> aHash
66
+ * modem_params=(aHash) -> aHash
67
+ * get_modem_params() -> aHash
68
+ * set_modem_params(aHash) -> aHash
69
+ * set_modem_params(baudrate [, databits [, stopbits [, parity]]])
70
+
71
+ Get and set the modem parameters. Hash keys are "baud", "data_bits",
72
+ "stop_bits", and "parity" (see above).
73
+
74
+ Parameters not present in the hash or set to nil remain unchanged.
75
+ Default parameter values for the set_modem_params method are:
76
+ databits = 8, stopbits = 1, parity = (databits == 8 ?
77
+ SerialPort::NONE : SerialPort::EVEN).
78
+
79
+ * baud() -> anInteger
80
+ * baud=(anInteger) -> anInteger
81
+ * data_bits() -> 4, 5, 6, 7, or 8
82
+ * data_bits=(anInteger) -> anInteger
83
+ * stop_bits() -> 1 or 2
84
+ * stop_bits=(anInteger) -> anInteger
85
+ * parity() -> anInteger: SerialPort::NONE, SerialPort::EVEN,
86
+ SerialPort::ODD, SerialPort::MARK, or SerialPort::SPACE
87
+ * parity=(anInteger) -> anInteger
88
+
89
+ Get and set the corresponding modem parameter.
90
+
91
+ * flow_control() -> anInteger
92
+ * flow_control=(anInteger) -> anInteger
93
+
94
+ Get and set the flow control: SerialPort::NONE, SerialPort::HARD,
95
+ SerialPort::SOFT, or (SerialPort::HARD | SerialPort::SOFT).
96
+
97
+ Note: SerialPort::HARD mode is not supported on all platforms.
98
+ SerialPort::HARD uses RTS/CTS handshaking; DSR/DTR is not
99
+ supported.
100
+
101
+ * read_timeout() -> anInteger
102
+ * read_timeout=(anInteger) -> anInteger
103
+ * write_timeout() -> anInteger
104
+ * write_timeout=(anInteger) -> anInteger
105
+
106
+ Get and set timeout values (in milliseconds) for reading and writing.
107
+ A negative read timeout will return all the available data without
108
+ waiting, a zero read timeout will not return until at least one
109
+ byte is available, and a positive read timeout returns when the
110
+ requested number of bytes is available or the interval between the
111
+ arrival of two bytes exceeds the timeout value.
112
+
113
+ Note: Read timeouts don't mix well with multi-threading.
114
+
115
+ Note: Under Posix, write timeouts are not implemented.
116
+
117
+ * break(time) -> nil
118
+
119
+ Send a break for the given time.
120
+
121
+ time -> anInteger: tenths-of-a-second for the break.
122
+ Note: Under Posix, this value is very approximate.
123
+
124
+ * signals() -> aHash
125
+
126
+ Return a hash with the state of each line status bit. Keys are
127
+ "rts", "dtr", "cts", "dsr", "dcd", and "ri".
128
+
129
+ Note: Under Windows, the rts and dtr values are not included.
130
+
131
+ * rts()
132
+ * dtr()
133
+ * cts()
134
+ * dsr()
135
+ * dcd()
136
+ * ri() -> 0 or 1
137
+
138
+ * rts=(0 or 1)
139
+ * dtr=(0 or 1) -> 0 or 1
140
+
141
+ Get and set the corresponding line status bit.
142
+
143
+ Note: Under Windows, rts() and dtr() are not implemented.
144
+
145
+ -- License --
146
+
147
+ GPL
148
+
149
+ Guillaume Pierronnet <moumar@netcourrier.com>
150
+ Alan Stern <stern@rowland.harvard.edu>
151
+ Tobin Richard <tobin.richard@gmail.com>
152
+ Hector Parra <hector@hectorparra.com>
153
+ Ryan C. Payne <rpayne-oss@bullittsystems.com>
data/Rakefile CHANGED
@@ -1,24 +1,33 @@
1
- require 'rubygems'
2
- require 'rake'
3
-
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gemspec|
7
- gemspec.name = "serialport"
8
- gemspec.summary = "Library for using RS-232 serial ports."
9
- gemspec.description = "Ruby/SerialPort is a Ruby library that provides a class for using RS-232 serial ports."
10
- gemspec.email = "hector@hectorparra.com"
11
- gemspec.homepage = 'http://github.com/hparra/ruby-serialport/'
12
- gemspec.authors = ['Guillaume Pierronnet', 'Alan Stern', 'Daniel E. Shipton', 'Tobin Richard', 'Hector Parra', 'Ryan C. Payne']
13
- gemspec.has_rdoc = true
14
- gemspec.extensions << 'ext/native/extconf.rb'
15
- end
16
- Jeweler::GemcutterTasks.new
17
- rescue LoadError
18
- puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
19
- end
20
-
21
- task :clean do
22
- rm_rf(Dir['doc'], :verbose => true)
23
- rm_rf(Dir['pkg'], :verbose => true)
24
- end
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ gem 'rake-compiler', '>= 0.4.1'
5
+ require "rake/extensiontask"
6
+
7
+ begin
8
+ require 'jeweler'
9
+ Jeweler::Tasks.new do |gemspec|
10
+ gemspec.name = "serialport"
11
+ gemspec.summary = "Library for using RS-232 serial ports."
12
+ gemspec.description = "Ruby/SerialPort is a Ruby library that provides a class for using RS-232 serial ports."
13
+ gemspec.email = "hector@hectorparra.com"
14
+ gemspec.homepage = 'http://github.com/hparra/ruby-serialport/'
15
+ gemspec.authors = ['Guillaume Pierronnet', 'Alan Stern', 'Daniel E. Shipton', 'Tobin Richard', 'Hector Parra', 'Ryan C. Payne']
16
+ gemspec.has_rdoc = true
17
+ gemspec.extensions << 'ext/native/extconf.rb'
18
+
19
+ Rake::ExtensionTask.new "serialport", gemspec do |ext|
20
+ ext.lib_dir = File.join(*['lib', ENV['FAT_DIR']].compact)
21
+ ext.ext_dir = "ext/native"
22
+ end
23
+ end
24
+ Jeweler::GemcutterTasks.new
25
+ rescue LoadError
26
+ puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
27
+ end
28
+
29
+ task :clean do
30
+ rm_rf(Dir['doc'], :verbose => true)
31
+ rm_rf(Dir['pkg'], :verbose => true)
32
+ end
33
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.4
1
+ 1.1.0
@@ -1,14 +1,13 @@
1
- require 'mkmf'
2
-
3
- printf("checking for OS... ")
4
- STDOUT.flush
5
- os = /-([a-z]+)/.match(RUBY_PLATFORM)[1]
6
- puts(os)
7
- $CFLAGS += " -DOS_#{os.upcase}"
8
- $CFLAGS += " -DRUBY_1_9" if RUBY_VERSION =~ /^1\.9/
9
-
10
- if !(os == 'mswin' or os == 'bccwin' or os == 'mingw')
11
- exit(1) if not have_header("termios.h") or not have_header("unistd.h")
12
- end
13
-
14
- create_makefile('serialport')
1
+ require 'mkmf'
2
+
3
+ printf("checking for OS... ")
4
+ STDOUT.flush
5
+ os = /-([a-z]+)/.match(RUBY_PLATFORM)[1]
6
+ puts(os)
7
+ $CFLAGS += " -DOS_#{os.upcase}"
8
+
9
+ if !(os == 'mswin' or os == 'bccwin' or os == 'mingw')
10
+ exit(1) if not have_header("termios.h") or not have_header("unistd.h")
11
+ end
12
+
13
+ create_makefile('serialport')
@@ -1,688 +1,733 @@
1
- /* Ruby/SerialPort
2
- * Guillaume Pierronnet <moumar@netcourrier.com>
3
- * Alan Stern <stern@rowland.harvard.edu>
4
- * Daniel E. Shipton <dshipton@redshiptechnologies.com>
5
- * Ryan C. Payne <rpayne-oss@bullittsystems.com>
6
- *
7
- * This code is hereby licensed for public consumption under either the
8
- * GNU GPL v2 or greater.
9
- *
10
- * You should have received a copy of the GNU General Public License
11
- * along with this program; if not, write to the Free Software
12
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
13
- *
14
- * For documentation on serial programming, see the excellent:
15
- * "Serial Programming Guide for POSIX Operating Systems"
16
- * written Michael R. Sweet.
17
- * http://www.easysw.com/~mike/serial/
18
- */
19
-
20
- #include "serialport.h"
21
-
22
- /* Check if we are on a posix compliant system. */
23
- #if !defined(OS_MSWIN) && !defined(OS_BCCWIN) && !defined(OS_MINGW)
24
-
25
- #include <stdio.h> /* Standard input/output definitions */
26
- #include <unistd.h> /* UNIX standard function definitions */
27
- #include <fcntl.h> /* File control definitions */
28
- #include <errno.h> /* Error number definitions */
29
- #include <termios.h> /* POSIX terminal control definitions */
30
- #include <sys/ioctl.h>
31
-
32
- #ifdef CRTSCTS
33
- #define HAVE_FLOWCONTROL_HARD 1
34
- #else
35
- #undef HAVE_FLOWCONTROL_HARD
36
- #endif
37
-
38
-
39
- static char sTcgetattr[] = "tcgetattr";
40
- static char sTcsetattr[] = "tcsetattr";
41
- static char sIoctl[] = "ioctl";
42
-
43
-
44
- int get_fd_helper(obj)
45
- VALUE obj;
46
- {
47
- #ifdef RUBY_1_9
48
- rb_io_t *fptr;
49
- #else
50
- OpenFile *fptr;
51
- #endif
52
- GetOpenFile(obj, fptr);
53
- #ifdef RUBY_1_9
54
- return (fptr->fd);
55
- #else
56
- return (fileno(fptr->f));
57
- #endif
58
- }
59
-
60
- VALUE sp_create_impl(class, _port)
61
- VALUE class, _port;
62
- {
63
- #ifdef RUBY_1_9
64
- rb_io_t *fp;
65
- #else
66
- OpenFile *fp;
67
- #endif
68
-
69
- int fd;
70
- int num_port;
71
- char *port;
72
- char *ports[] = {
73
- #if defined(OS_LINUX) || defined(OS_CYGWIN)
74
- "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3",
75
- "/dev/ttyS4", "/dev/ttyS5", "/dev/ttyS6", "/dev/ttyS7"
76
- #elif defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DARWIN)
77
- "/dev/cuaa0", "/dev/cuaa1", "/dev/cuaa2", "/dev/cuaa3",
78
- "/dev/cuaa4", "/dev/cuaa5", "/dev/cuaa6", "/dev/cuaa7"
79
- #elif defined(OS_SOLARIS)
80
- "/dev/ttya", "/dev/ttyb", "/dev/ttyc", "/dev/ttyd",
81
- "/dev/ttye", "/dev/ttyf", "/dev/ttyg", "/dev/ttyh"
82
- #elif defined(OS_AIX)
83
- "/dev/tty0", "/dev/tty1", "/dev/tty2", "/dev/tty3",
84
- "/dev/tty4", "/dev/tty5", "/dev/tty6", "/dev/tty7"
85
- #elif defined(OS_IRIX)
86
- "/dev/ttyf1", "/dev/ttyf2", "/dev/ttyf3", "/dev/ttyf4",
87
- "/dev/ttyf5", "/dev/ttyf6", "/dev/ttyf7", "/dev/ttyf8"
88
- #endif
89
- };
90
- struct termios params;
91
-
92
- NEWOBJ(sp, struct RFile);
93
- rb_secure(4);
94
- OBJSETUP(sp, class, T_FILE);
95
- MakeOpenFile((VALUE) sp, fp);
96
-
97
- switch(TYPE(_port))
98
- {
99
- case T_FIXNUM:
100
- num_port = FIX2INT(_port);
101
- if (num_port < 0 || num_port > sizeof(ports) / sizeof(ports[0]))
102
- {
103
- rb_raise(rb_eArgError, "illegal port number");
104
- }
105
- port = ports[num_port];
106
- break;
107
-
108
- case T_STRING:
109
- Check_SafeStr(_port);
110
- #ifdef RUBY_1_9
111
- port = RSTRING_PTR(_port);
112
- #else
113
- port = RSTRING(_port)->ptr;
114
- #endif
115
- break;
116
-
117
- default:
118
- rb_raise(rb_eTypeError, "wrong argument type");
119
- break;
120
- }
121
-
122
- fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
123
- if (fd == -1)
124
- {
125
- rb_sys_fail(port);
126
- }
127
-
128
- if (!isatty(fd))
129
- {
130
- close(fd);
131
- rb_raise(rb_eArgError, "not a serial port");
132
- }
133
-
134
- /* enable blocking read */
135
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
136
-
137
- if (tcgetattr(fd, &params) == -1)
138
- {
139
- close(fd);
140
- rb_sys_fail(sTcgetattr);
141
- }
142
-
143
- params.c_oflag = 0;
144
- params.c_lflag = 0;
145
- params.c_iflag &= (IXON | IXOFF | IXANY);
146
- params.c_cflag |= CLOCAL | CREAD;
147
- params.c_cflag &= ~HUPCL;
148
-
149
- if (tcsetattr(fd, TCSANOW, &params) == -1)
150
- {
151
- close(fd);
152
- rb_sys_fail(sTcsetattr);
153
- }
154
-
155
- #ifdef RUBY_1_9
156
- fp->fd = fd;
157
- #else
158
- fp->f = rb_fdopen(fd, "r+");
159
- #endif
160
- fp->mode = FMODE_READWRITE | FMODE_SYNC;
161
-
162
- return (VALUE) sp;
163
- }
164
-
165
- VALUE sp_set_modem_params_impl(argc, argv, self)
166
- int argc;
167
- VALUE *argv, self;
168
- {
169
- int fd;
170
- struct termios params;
171
- VALUE _data_rate, _data_bits, _parity, _stop_bits;
172
- int use_hash = 0;
173
- int data_rate, data_bits;
174
- _data_rate = _data_bits = _parity = _stop_bits = Qnil;
175
-
176
- if (argc == 0)
177
- {
178
- return self;
179
- }
180
-
181
- if (argc == 1 && T_HASH == TYPE(argv[0]))
182
- {
183
- use_hash = 1;
184
- _data_rate = rb_hash_aref(argv[0], sBaud);
185
- _data_bits = rb_hash_aref(argv[0], sDataBits);
186
- _stop_bits = rb_hash_aref(argv[0], sStopBits);
187
- _parity = rb_hash_aref(argv[0], sParity);
188
- }
189
-
190
- fd = get_fd_helper(self);
191
- if (tcgetattr(fd, &params) == -1)
192
- {
193
- rb_sys_fail(sTcgetattr);
194
- }
195
-
196
- if (!use_hash)
197
- {
198
- _data_rate = argv[0];
199
- }
200
-
201
- if (NIL_P(_data_rate))
202
- {
203
- goto SkipDataRate;
204
- }
205
- Check_Type(_data_rate, T_FIXNUM);
206
-
207
- switch(FIX2INT(_data_rate))
208
- {
209
- case 50: data_rate = B50; break;
210
- case 75: data_rate = B75; break;
211
- case 110: data_rate = B110; break;
212
- case 134: data_rate = B134; break;
213
- case 150: data_rate = B150; break;
214
- case 200: data_rate = B200; break;
215
- case 300: data_rate = B300; break;
216
- case 600: data_rate = B600; break;
217
- case 1200: data_rate = B1200; break;
218
- case 1800: data_rate = B1800; break;
219
- case 2400: data_rate = B2400; break;
220
- case 4800: data_rate = B4800; break;
221
- case 9600: data_rate = B9600; break;
222
- case 19200: data_rate = B19200; break;
223
- case 38400: data_rate = B38400; break;
224
- #ifdef B57600
225
- case 57600: data_rate = B57600; break;
226
- #endif
227
- #ifdef B76800
228
- case 76800: data_rate = B76800; break;
229
- #endif
230
- #ifdef B115200
231
- case 115200: data_rate = B115200; break;
232
- #endif
233
- #ifdef B230400
234
- case 230400: data_rate = B230400; break;
235
- #endif
236
-
237
- default:
238
- rb_raise(rb_eArgError, "unknown baud rate");
239
- break;
240
- }
241
- cfsetispeed(&params, data_rate);
242
- cfsetospeed(&params, data_rate);
243
-
244
- SkipDataRate:
245
-
246
- if (!use_hash)
247
- {
248
- _data_bits = (argc >= 2 ? argv[1] : INT2FIX(8));
249
- }
250
-
251
- if (NIL_P(_data_bits))
252
- {
253
- goto SkipDataBits;
254
- }
255
- Check_Type(_data_bits, T_FIXNUM);
256
-
257
- switch(FIX2INT(_data_bits))
258
- {
259
- case 5:
260
- data_bits = CS5;
261
- break;
262
- case 6:
263
- data_bits = CS6;
264
- break;
265
- case 7:
266
- data_bits = CS7;
267
- break;
268
- case 8:
269
- data_bits = CS8;
270
- break;
271
- default:
272
- rb_raise(rb_eArgError, "unknown character size");
273
- break;
274
- }
275
- params.c_cflag &= ~CSIZE;
276
- params.c_cflag |= data_bits;
277
-
278
- SkipDataBits:
279
-
280
- if (!use_hash)
281
- {
282
- _stop_bits = (argc >= 3 ? argv[2] : INT2FIX(1));
283
- }
284
-
285
- if (NIL_P(_stop_bits))
286
- {
287
- goto SkipStopBits;
288
- }
289
-
290
- Check_Type(_stop_bits, T_FIXNUM);
291
-
292
- switch(FIX2INT(_stop_bits))
293
- {
294
- case 1:
295
- params.c_cflag &= ~CSTOPB;
296
- break;
297
- case 2:
298
- params.c_cflag |= CSTOPB;
299
- break;
300
- default:
301
- rb_raise(rb_eArgError, "unknown number of stop bits");
302
- break;
303
- }
304
-
305
- SkipStopBits:
306
-
307
- if (!use_hash)
308
- {
309
- _parity = (argc >= 4 ? argv[3] : ((params.c_cflag & CSIZE) == CS8 ?
310
- INT2FIX(NONE) : INT2FIX(EVEN)));
311
- }
312
-
313
- if (NIL_P(_parity))
314
- {
315
- goto SkipParity;
316
- }
317
-
318
- Check_Type(_parity, T_FIXNUM);
319
-
320
- switch(FIX2INT(_parity))
321
- {
322
- case EVEN:
323
- params.c_cflag |= PARENB;
324
- params.c_cflag &= ~PARODD;
325
- break;
326
-
327
- case ODD:
328
- params.c_cflag |= PARENB;
329
- params.c_cflag |= PARODD;
330
- break;
331
-
332
- case NONE:
333
- params.c_cflag &= ~PARENB;
334
- break;
335
-
336
- default:
337
- rb_raise(rb_eArgError, "unknown parity");
338
- break;
339
- }
340
-
341
- SkipParity:
342
-
343
- if (tcsetattr(fd, TCSANOW, &params) == -1)
344
- {
345
- rb_sys_fail(sTcsetattr);
346
- }
347
- return argv[0];
348
- }
349
-
350
- void get_modem_params_impl(self, mp)
351
- VALUE self;
352
- struct modem_params *mp;
353
- {
354
- int fd;
355
- struct termios params;
356
-
357
- fd = get_fd_helper(self);
358
- if (tcgetattr(fd, &params) == -1)
359
- {
360
- rb_sys_fail(sTcgetattr);
361
- }
362
-
363
- switch (cfgetospeed(&params))
364
- {
365
- case B50: mp->data_rate = 50; break;
366
- case B75: mp->data_rate = 75; break;
367
- case B110: mp->data_rate = 110; break;
368
- case B134: mp->data_rate = 134; break;
369
- case B150: mp->data_rate = 150; break;
370
- case B200: mp->data_rate = 200; break;
371
- case B300: mp->data_rate = 300; break;
372
- case B600: mp->data_rate = 600; break;
373
- case B1200: mp->data_rate = 1200; break;
374
- case B1800: mp->data_rate = 1800; break;
375
- case B2400: mp->data_rate = 2400; break;
376
- case B4800: mp->data_rate = 4800; break;
377
- case B9600: mp->data_rate = 9600; break;
378
- case B19200: mp->data_rate = 19200; break;
379
- case B38400: mp->data_rate = 38400; break;
380
- #ifdef B57600
381
- case B57600: mp->data_rate = 57600; break;
382
- #endif
383
- #ifdef B76800
384
- case B76800: mp->data_rate = 76800; break;
385
- #endif
386
- #ifdef B115200
387
- case B115200: mp->data_rate = 115200; break;
388
- #endif
389
- #ifdef B230400
390
- case B230400: mp->data_rate = 230400; break;
391
- #endif
392
- }
393
-
394
- switch(params.c_cflag & CSIZE)
395
- {
396
- case CS5:
397
- mp->data_bits = 5;
398
- break;
399
- case CS6:
400
- mp->data_bits = 6;
401
- break;
402
- case CS7:
403
- mp->data_bits = 7;
404
- break;
405
- case CS8:
406
- mp->data_bits = 8;
407
- break;
408
- default:
409
- mp->data_bits = 0;
410
- break;
411
- }
412
-
413
- mp->stop_bits = (params.c_cflag & CSTOPB ? 2 : 1);
414
-
415
- if (!(params.c_cflag & PARENB))
416
- {
417
- mp->parity = NONE;
418
- }
419
- else if (params.c_cflag & PARODD)
420
- {
421
- mp->parity = ODD;
422
- }
423
- else
424
- {
425
- mp->parity = EVEN;
426
- }
427
- }
428
-
429
- VALUE sp_set_flow_control_impl(self, val)
430
- VALUE self, val;
431
- {
432
- int fd;
433
- int flowc;
434
- struct termios params;
435
-
436
- Check_Type(val, T_FIXNUM);
437
-
438
- fd = get_fd_helper(self);
439
- if (tcgetattr(fd, &params) == -1)
440
- {
441
- rb_sys_fail(sTcgetattr);
442
- }
443
-
444
- flowc = FIX2INT(val);
445
- if (flowc & HARD)
446
- {
447
- #ifdef HAVE_FLOWCONTROL_HARD
448
- params.c_cflag |= CRTSCTS;
449
- }
450
- else
451
- {
452
- params.c_cflag &= ~CRTSCTS;
453
- }
454
- #else
455
- rb_raise(rb_eIOError, "Hardware flow control not supported");
456
- }
457
- #endif
458
-
459
- if (flowc & SOFT)
460
- {
461
- params.c_iflag |= (IXON | IXOFF | IXANY);
462
- }
463
- else
464
- {
465
- params.c_iflag &= ~(IXON | IXOFF | IXANY);
466
- }
467
-
468
- if (tcsetattr(fd, TCSANOW, &params) == -1)
469
- {
470
- rb_sys_fail(sTcsetattr);
471
- }
472
-
473
- return val;
474
- }
475
-
476
- VALUE sp_get_flow_control_impl(self)
477
- VALUE self;
478
- {
479
- int ret;
480
- int fd;
481
- struct termios params;
482
-
483
- fd = get_fd_helper(self);
484
- if (tcgetattr(fd, &params) == -1)
485
- {
486
- rb_sys_fail(sTcgetattr);
487
- }
488
-
489
- ret = 0;
490
-
491
- #ifdef HAVE_FLOWCONTROL_HARD
492
- if (params.c_cflag & CRTSCTS)
493
- {
494
- ret += HARD;
495
- }
496
- #endif
497
-
498
- if (params.c_iflag & (IXON | IXOFF | IXANY))
499
- {
500
- ret += SOFT;
501
- }
502
-
503
- return INT2FIX(ret);
504
- }
505
-
506
- VALUE sp_set_read_timeout_impl(self, val)
507
- VALUE self, val;
508
- {
509
- int timeout;
510
- int fd;
511
- struct termios params;
512
-
513
- Check_Type(val, T_FIXNUM);
514
- timeout = FIX2INT(val);
515
-
516
- fd = get_fd_helper(self);
517
- if (tcgetattr(fd, &params) == -1)
518
- {
519
- rb_sys_fail(sTcgetattr);
520
- }
521
-
522
- if (timeout < 0)
523
- {
524
- params.c_cc[VTIME] = 0;
525
- params.c_cc[VMIN] = 0;
526
- }
527
- else if (timeout == 0)
528
- {
529
- params.c_cc[VTIME] = 0;
530
- params.c_cc[VMIN] = 1;
531
- }
532
- else
533
- {
534
- params.c_cc[VTIME] = (timeout + 50) / 100;
535
- params.c_cc[VMIN] = 0;
536
- }
537
-
538
- if (tcsetattr(fd, TCSANOW, &params) == -1)
539
- {
540
- rb_sys_fail(sTcsetattr);
541
- }
542
-
543
- return val;
544
- }
545
-
546
- VALUE sp_get_read_timeout_impl(self)
547
- VALUE self;
548
- {
549
- int fd;
550
- struct termios params;
551
-
552
- fd = get_fd_helper(self);
553
- if (tcgetattr(fd, &params) == -1)
554
- {
555
- rb_sys_fail(sTcgetattr);
556
- }
557
-
558
- if (params.c_cc[VTIME] == 0 && params.c_cc[VMIN] == 0)
559
- {
560
- return INT2FIX(-1);
561
- }
562
-
563
- return INT2FIX(params.c_cc[VTIME] * 100);
564
- }
565
-
566
- VALUE sp_set_write_timeout_impl(self, val)
567
- VALUE self, val;
568
- {
569
- rb_notimplement();
570
- return self;
571
- }
572
-
573
- VALUE sp_get_write_timeout_impl(self)
574
- VALUE self;
575
- {
576
- rb_notimplement();
577
- return self;
578
- }
579
-
580
- VALUE sp_break_impl(self, time)
581
- VALUE self, time;
582
- {
583
- int fd;
584
-
585
- Check_Type(time, T_FIXNUM);
586
-
587
- fd = get_fd_helper(self);
588
-
589
- if (tcsendbreak(fd, FIX2INT(time) / 3) == -1)
590
- {
591
- rb_sys_fail("tcsendbreak");
592
- }
593
-
594
- return Qnil;
595
- }
596
-
597
- void get_line_signals_helper_impl(obj, ls)
598
- VALUE obj;
599
- struct line_signals *ls;
600
- {
601
- int fd, status;
602
-
603
- fd = get_fd_helper(obj);
604
-
605
- if (ioctl(fd, TIOCMGET, &status) == -1)
606
- {
607
- rb_sys_fail(sIoctl);
608
- }
609
-
610
- ls->rts = (status & TIOCM_RTS ? 1 : 0);
611
- ls->dtr = (status & TIOCM_DTR ? 1 : 0);
612
- ls->cts = (status & TIOCM_CTS ? 1 : 0);
613
- ls->dsr = (status & TIOCM_DSR ? 1 : 0);
614
- ls->dcd = (status & TIOCM_CD ? 1 : 0);
615
- ls->ri = (status & TIOCM_RI ? 1 : 0);
616
- }
617
-
618
- VALUE set_signal_impl(obj, val, sig)
619
- VALUE obj,val;
620
- int sig;
621
- {
622
- int status;
623
- int fd;
624
- int set;
625
-
626
- Check_Type(val, T_FIXNUM);
627
- fd = get_fd_helper(obj);
628
-
629
- if (ioctl(fd, TIOCMGET, &status) == -1)
630
- {
631
- rb_sys_fail(sIoctl);
632
- }
633
-
634
- set = FIX2INT(val);
635
-
636
- if (set == 0)
637
- {
638
- status &= ~sig;
639
- }
640
- else if (set == 1)
641
- {
642
- status |= sig;
643
- }
644
- else
645
- {
646
- rb_raise(rb_eArgError, "invalid value");
647
- }
648
-
649
- if (ioctl(fd, TIOCMSET, &status) == -1)
650
- {
651
- rb_sys_fail(sIoctl);
652
- }
653
-
654
- return val;
655
- }
656
-
657
- VALUE sp_set_rts_impl(self, val)
658
- VALUE self, val;
659
- {
660
- return set_signal_impl(self, val, TIOCM_RTS);
661
- }
662
-
663
- VALUE sp_set_dtr_impl(self, val)
664
- VALUE self, val;
665
- {
666
- return set_signal_impl(self, val, TIOCM_DTR);
667
- }
668
-
669
- VALUE sp_get_rts_impl(self)
670
- VALUE self;
671
- {
672
- struct line_signals ls;
673
-
674
- get_line_signals_helper_impl(self, &ls);
675
- return INT2FIX(ls.rts);
676
- }
677
-
678
- VALUE sp_get_dtr_impl(self)
679
- VALUE self;
680
- {
681
- struct line_signals ls;
682
-
683
- get_line_signals_helper_impl(self, &ls);
684
-
685
- return INT2FIX(ls.dtr);
686
- }
687
-
688
- #endif /* !defined(OS_MSWIN) && !defined(OS_BCCWIN) && !defined(OS_MINGW) */
1
+ /* Ruby/SerialPort
2
+ * Guillaume Pierronnet <moumar@netcourrier.com>
3
+ * Alan Stern <stern@rowland.harvard.edu>
4
+ * Daniel E. Shipton <dshipton@redshiptechnologies.com>
5
+ * Ryan C. Payne <rpayne-oss@bullittsystems.com>
6
+ *
7
+ * This code is hereby licensed for public consumption under either the
8
+ * GNU GPL v2 or greater.
9
+ *
10
+ * You should have received a copy of the GNU General Public License
11
+ * along with this program; if not, write to the Free Software
12
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
13
+ *
14
+ * For documentation on serial programming, see the excellent:
15
+ * "Serial Programming Guide for POSIX Operating Systems"
16
+ * written Michael R. Sweet.
17
+ * http://www.easysw.com/~mike/serial/
18
+ */
19
+
20
+ #include "serialport.h"
21
+
22
+ /* Check if we are on a posix compliant system. */
23
+ #if !defined(OS_MSWIN) && !defined(OS_BCCWIN) && !defined(OS_MINGW)
24
+
25
+ #include <stdio.h> /* Standard input/output definitions */
26
+ #include <unistd.h> /* UNIX standard function definitions */
27
+ #include <fcntl.h> /* File control definitions */
28
+ #include <errno.h> /* Error number definitions */
29
+ #include <termios.h> /* POSIX terminal control definitions */
30
+ #include <sys/ioctl.h>
31
+
32
+ #ifdef CRTSCTS
33
+ #define HAVE_FLOWCONTROL_HARD 1
34
+ #else
35
+ #undef HAVE_FLOWCONTROL_HARD
36
+ #endif
37
+
38
+ /* on mac os x, not all baud rates are defined in termios.h but
39
+ they are mapped to the numeric value anyway, so we define them here */
40
+ #ifdef __APPLE__
41
+ #ifndef B460800
42
+ #define B460800 460800
43
+ #endif
44
+ #ifndef B500000
45
+ #define B500000 500000
46
+ #endif
47
+ #ifndef B576000
48
+ #define B576000 576000
49
+ #endif
50
+ #ifndef B921600
51
+ #define B921600 921600
52
+ #endif
53
+ #ifndef B1000000
54
+ #define B1000000 1000000
55
+ #endif
56
+ #endif
57
+
58
+ static char sTcgetattr[] = "tcgetattr";
59
+ static char sTcsetattr[] = "tcsetattr";
60
+ static char sIoctl[] = "ioctl";
61
+
62
+
63
+ int get_fd_helper(obj)
64
+ VALUE obj;
65
+ {
66
+ #ifdef HAVE_RUBY_IO_H
67
+ rb_io_t *fptr;
68
+ #else
69
+ OpenFile *fptr;
70
+ #endif
71
+ GetOpenFile(obj, fptr);
72
+ #ifdef HAVE_RUBY_IO_H
73
+ return (fptr->fd);
74
+ #else
75
+ return (fileno(fptr->f));
76
+ #endif
77
+ }
78
+
79
+ VALUE sp_create_impl(class, _port)
80
+ VALUE class, _port;
81
+ {
82
+ #ifdef HAVE_RUBY_IO_H
83
+ rb_io_t *fp;
84
+ #else
85
+ OpenFile *fp;
86
+ #endif
87
+
88
+ int fd;
89
+ int num_port;
90
+ char *port;
91
+ char *ports[] = {
92
+ #if defined(OS_LINUX) || defined(OS_CYGWIN)
93
+ "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3",
94
+ "/dev/ttyS4", "/dev/ttyS5", "/dev/ttyS6", "/dev/ttyS7"
95
+ #elif defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DARWIN)
96
+ "/dev/cuaa0", "/dev/cuaa1", "/dev/cuaa2", "/dev/cuaa3",
97
+ "/dev/cuaa4", "/dev/cuaa5", "/dev/cuaa6", "/dev/cuaa7"
98
+ #elif defined(OS_SOLARIS)
99
+ "/dev/ttya", "/dev/ttyb", "/dev/ttyc", "/dev/ttyd",
100
+ "/dev/ttye", "/dev/ttyf", "/dev/ttyg", "/dev/ttyh"
101
+ #elif defined(OS_AIX)
102
+ "/dev/tty0", "/dev/tty1", "/dev/tty2", "/dev/tty3",
103
+ "/dev/tty4", "/dev/tty5", "/dev/tty6", "/dev/tty7"
104
+ #elif defined(OS_IRIX)
105
+ "/dev/ttyf1", "/dev/ttyf2", "/dev/ttyf3", "/dev/ttyf4",
106
+ "/dev/ttyf5", "/dev/ttyf6", "/dev/ttyf7", "/dev/ttyf8"
107
+ #endif
108
+ };
109
+ struct termios params;
110
+
111
+ NEWOBJ(sp, struct RFile);
112
+ rb_secure(4);
113
+ OBJSETUP(sp, class, T_FILE);
114
+ MakeOpenFile((VALUE) sp, fp);
115
+
116
+ switch(TYPE(_port))
117
+ {
118
+ case T_FIXNUM:
119
+ num_port = FIX2INT(_port);
120
+ if (num_port < 0 || num_port > sizeof(ports) / sizeof(ports[0]))
121
+ {
122
+ rb_raise(rb_eArgError, "illegal port number");
123
+ }
124
+ port = ports[num_port];
125
+ break;
126
+
127
+ case T_STRING:
128
+ Check_SafeStr(_port);
129
+ port = RSTRING_PTR(_port);
130
+ break;
131
+
132
+ default:
133
+ rb_raise(rb_eTypeError, "wrong argument type");
134
+ break;
135
+ }
136
+
137
+ fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
138
+ if (fd == -1)
139
+ {
140
+ rb_sys_fail(port);
141
+ }
142
+
143
+ if (!isatty(fd))
144
+ {
145
+ close(fd);
146
+ rb_raise(rb_eArgError, "not a serial port");
147
+ }
148
+
149
+ /* enable blocking read */
150
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
151
+
152
+ if (tcgetattr(fd, &params) == -1)
153
+ {
154
+ close(fd);
155
+ rb_sys_fail(sTcgetattr);
156
+ }
157
+
158
+ params.c_oflag = 0;
159
+ params.c_lflag = 0;
160
+ params.c_iflag &= (IXON | IXOFF | IXANY);
161
+ params.c_cflag |= CLOCAL | CREAD;
162
+ params.c_cflag &= ~HUPCL;
163
+
164
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
165
+ {
166
+ close(fd);
167
+ rb_sys_fail(sTcsetattr);
168
+ }
169
+
170
+ #ifdef HAVE_RUBY_IO_H
171
+ fp->fd = fd;
172
+ #else
173
+ fp->f = rb_fdopen(fd, "r+");
174
+ #endif
175
+ fp->mode = FMODE_READWRITE | FMODE_SYNC;
176
+
177
+ return (VALUE) sp;
178
+ }
179
+
180
+ VALUE sp_set_modem_params_impl(argc, argv, self)
181
+ int argc;
182
+ VALUE *argv, self;
183
+ {
184
+ int fd;
185
+ struct termios params;
186
+ VALUE _data_rate, _data_bits, _parity, _stop_bits;
187
+ int use_hash = 0;
188
+ int data_rate, data_bits;
189
+ _data_rate = _data_bits = _parity = _stop_bits = Qnil;
190
+
191
+ if (argc == 0)
192
+ {
193
+ return self;
194
+ }
195
+
196
+ if (argc == 1 && T_HASH == TYPE(argv[0]))
197
+ {
198
+ use_hash = 1;
199
+ _data_rate = rb_hash_aref(argv[0], sBaud);
200
+ _data_bits = rb_hash_aref(argv[0], sDataBits);
201
+ _stop_bits = rb_hash_aref(argv[0], sStopBits);
202
+ _parity = rb_hash_aref(argv[0], sParity);
203
+ }
204
+
205
+ fd = get_fd_helper(self);
206
+ if (tcgetattr(fd, &params) == -1)
207
+ {
208
+ rb_sys_fail(sTcgetattr);
209
+ }
210
+
211
+ if (!use_hash)
212
+ {
213
+ _data_rate = argv[0];
214
+ }
215
+
216
+ if (NIL_P(_data_rate))
217
+ {
218
+ goto SkipDataRate;
219
+ }
220
+ Check_Type(_data_rate, T_FIXNUM);
221
+
222
+ switch(FIX2INT(_data_rate))
223
+ {
224
+ case 50: data_rate = B50; break;
225
+ case 75: data_rate = B75; break;
226
+ case 110: data_rate = B110; break;
227
+ case 134: data_rate = B134; break;
228
+ case 150: data_rate = B150; break;
229
+ case 200: data_rate = B200; break;
230
+ case 300: data_rate = B300; break;
231
+ case 600: data_rate = B600; break;
232
+ case 1200: data_rate = B1200; break;
233
+ case 1800: data_rate = B1800; break;
234
+ case 2400: data_rate = B2400; break;
235
+ case 4800: data_rate = B4800; break;
236
+ case 9600: data_rate = B9600; break;
237
+ case 19200: data_rate = B19200; break;
238
+ case 38400: data_rate = B38400; break;
239
+ #ifdef B57600
240
+ case 57600: data_rate = B57600; break;
241
+ #endif
242
+ #ifdef B76800
243
+ case 76800: data_rate = B76800; break;
244
+ #endif
245
+ #ifdef B115200
246
+ case 115200: data_rate = B115200; break;
247
+ #endif
248
+ #ifdef B230400
249
+ case 230400: data_rate = B230400; break;
250
+ #endif
251
+ #ifdef B460800
252
+ case 460800: data_rate = B460800; break;
253
+ #endif
254
+ #ifdef B500000
255
+ case 500000: data_rate = B500000; break;
256
+ #endif
257
+ #ifdef B576000
258
+ case 576000: data_rate = B576000; break;
259
+ #endif
260
+ #ifdef B921600
261
+ case 921600: data_rate = B921600; break;
262
+ #endif
263
+ #ifdef B1000000
264
+ case 1000000: data_rate = B1000000; break;
265
+ #endif
266
+
267
+ default:
268
+ rb_raise(rb_eArgError, "unknown baud rate");
269
+ break;
270
+ }
271
+ cfsetispeed(&params, data_rate);
272
+ cfsetospeed(&params, data_rate);
273
+
274
+ SkipDataRate:
275
+
276
+ if (!use_hash)
277
+ {
278
+ _data_bits = (argc >= 2 ? argv[1] : INT2FIX(8));
279
+ }
280
+
281
+ if (NIL_P(_data_bits))
282
+ {
283
+ goto SkipDataBits;
284
+ }
285
+ Check_Type(_data_bits, T_FIXNUM);
286
+
287
+ switch(FIX2INT(_data_bits))
288
+ {
289
+ case 5:
290
+ data_bits = CS5;
291
+ break;
292
+ case 6:
293
+ data_bits = CS6;
294
+ break;
295
+ case 7:
296
+ data_bits = CS7;
297
+ break;
298
+ case 8:
299
+ data_bits = CS8;
300
+ break;
301
+ default:
302
+ rb_raise(rb_eArgError, "unknown character size");
303
+ break;
304
+ }
305
+ params.c_cflag &= ~CSIZE;
306
+ params.c_cflag |= data_bits;
307
+
308
+ SkipDataBits:
309
+
310
+ if (!use_hash)
311
+ {
312
+ _stop_bits = (argc >= 3 ? argv[2] : INT2FIX(1));
313
+ }
314
+
315
+ if (NIL_P(_stop_bits))
316
+ {
317
+ goto SkipStopBits;
318
+ }
319
+
320
+ Check_Type(_stop_bits, T_FIXNUM);
321
+
322
+ switch(FIX2INT(_stop_bits))
323
+ {
324
+ case 1:
325
+ params.c_cflag &= ~CSTOPB;
326
+ break;
327
+ case 2:
328
+ params.c_cflag |= CSTOPB;
329
+ break;
330
+ default:
331
+ rb_raise(rb_eArgError, "unknown number of stop bits");
332
+ break;
333
+ }
334
+
335
+ SkipStopBits:
336
+
337
+ if (!use_hash)
338
+ {
339
+ _parity = (argc >= 4 ? argv[3] : ((params.c_cflag & CSIZE) == CS8 ?
340
+ INT2FIX(NONE) : INT2FIX(EVEN)));
341
+ }
342
+
343
+ if (NIL_P(_parity))
344
+ {
345
+ goto SkipParity;
346
+ }
347
+
348
+ Check_Type(_parity, T_FIXNUM);
349
+
350
+ switch(FIX2INT(_parity))
351
+ {
352
+ case EVEN:
353
+ params.c_cflag |= PARENB;
354
+ params.c_cflag &= ~PARODD;
355
+ break;
356
+
357
+ case ODD:
358
+ params.c_cflag |= PARENB;
359
+ params.c_cflag |= PARODD;
360
+ break;
361
+
362
+ case NONE:
363
+ params.c_cflag &= ~PARENB;
364
+ break;
365
+
366
+ default:
367
+ rb_raise(rb_eArgError, "unknown parity");
368
+ break;
369
+ }
370
+
371
+ SkipParity:
372
+
373
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
374
+ {
375
+ rb_sys_fail(sTcsetattr);
376
+ }
377
+ return argv[0];
378
+ }
379
+
380
+ void get_modem_params_impl(self, mp)
381
+ VALUE self;
382
+ struct modem_params *mp;
383
+ {
384
+ int fd;
385
+ struct termios params;
386
+
387
+ fd = get_fd_helper(self);
388
+ if (tcgetattr(fd, &params) == -1)
389
+ {
390
+ rb_sys_fail(sTcgetattr);
391
+ }
392
+
393
+ switch (cfgetospeed(&params))
394
+ {
395
+ case B50: mp->data_rate = 50; break;
396
+ case B75: mp->data_rate = 75; break;
397
+ case B110: mp->data_rate = 110; break;
398
+ case B134: mp->data_rate = 134; break;
399
+ case B150: mp->data_rate = 150; break;
400
+ case B200: mp->data_rate = 200; break;
401
+ case B300: mp->data_rate = 300; break;
402
+ case B600: mp->data_rate = 600; break;
403
+ case B1200: mp->data_rate = 1200; break;
404
+ case B1800: mp->data_rate = 1800; break;
405
+ case B2400: mp->data_rate = 2400; break;
406
+ case B4800: mp->data_rate = 4800; break;
407
+ case B9600: mp->data_rate = 9600; break;
408
+ case B19200: mp->data_rate = 19200; break;
409
+ case B38400: mp->data_rate = 38400; break;
410
+ #ifdef B57600
411
+ case B57600: mp->data_rate = 57600; break;
412
+ #endif
413
+ #ifdef B76800
414
+ case B76800: mp->data_rate = 76800; break;
415
+ #endif
416
+ #ifdef B115200
417
+ case B115200: mp->data_rate = 115200; break;
418
+ #endif
419
+ #ifdef B230400
420
+ case B230400: mp->data_rate = 230400; break;
421
+ #endif
422
+ #ifdef B460800
423
+ case B460800: mp->data_rate = 460800; break;
424
+ #endif
425
+ #ifdef B500000
426
+ case B500000: mp->data_rate = 500000; break;
427
+ #endif
428
+ #ifdef B576000
429
+ case B576000: mp->data_rate = 576000; break;
430
+ #endif
431
+ #ifdef B921600
432
+ case B921600: mp->data_rate = 921600; break;
433
+ #endif
434
+ #ifdef B1000000
435
+ case B1000000: mp->data_rate = 1000000; break;
436
+ #endif
437
+ }
438
+
439
+ switch(params.c_cflag & CSIZE)
440
+ {
441
+ case CS5:
442
+ mp->data_bits = 5;
443
+ break;
444
+ case CS6:
445
+ mp->data_bits = 6;
446
+ break;
447
+ case CS7:
448
+ mp->data_bits = 7;
449
+ break;
450
+ case CS8:
451
+ mp->data_bits = 8;
452
+ break;
453
+ default:
454
+ mp->data_bits = 0;
455
+ break;
456
+ }
457
+
458
+ mp->stop_bits = (params.c_cflag & CSTOPB ? 2 : 1);
459
+
460
+ if (!(params.c_cflag & PARENB))
461
+ {
462
+ mp->parity = NONE;
463
+ }
464
+ else if (params.c_cflag & PARODD)
465
+ {
466
+ mp->parity = ODD;
467
+ }
468
+ else
469
+ {
470
+ mp->parity = EVEN;
471
+ }
472
+ }
473
+
474
+ VALUE sp_set_flow_control_impl(self, val)
475
+ VALUE self, val;
476
+ {
477
+ int fd;
478
+ int flowc;
479
+ struct termios params;
480
+
481
+ Check_Type(val, T_FIXNUM);
482
+
483
+ fd = get_fd_helper(self);
484
+ if (tcgetattr(fd, &params) == -1)
485
+ {
486
+ rb_sys_fail(sTcgetattr);
487
+ }
488
+
489
+ flowc = FIX2INT(val);
490
+ if (flowc & HARD)
491
+ {
492
+ #ifdef HAVE_FLOWCONTROL_HARD
493
+ params.c_cflag |= CRTSCTS;
494
+ }
495
+ else
496
+ {
497
+ params.c_cflag &= ~CRTSCTS;
498
+ }
499
+ #else
500
+ rb_raise(rb_eIOError, "Hardware flow control not supported");
501
+ }
502
+ #endif
503
+
504
+ if (flowc & SOFT)
505
+ {
506
+ params.c_iflag |= (IXON | IXOFF | IXANY);
507
+ }
508
+ else
509
+ {
510
+ params.c_iflag &= ~(IXON | IXOFF | IXANY);
511
+ }
512
+
513
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
514
+ {
515
+ rb_sys_fail(sTcsetattr);
516
+ }
517
+
518
+ return val;
519
+ }
520
+
521
+ VALUE sp_get_flow_control_impl(self)
522
+ VALUE self;
523
+ {
524
+ int ret;
525
+ int fd;
526
+ struct termios params;
527
+
528
+ fd = get_fd_helper(self);
529
+ if (tcgetattr(fd, &params) == -1)
530
+ {
531
+ rb_sys_fail(sTcgetattr);
532
+ }
533
+
534
+ ret = 0;
535
+
536
+ #ifdef HAVE_FLOWCONTROL_HARD
537
+ if (params.c_cflag & CRTSCTS)
538
+ {
539
+ ret += HARD;
540
+ }
541
+ #endif
542
+
543
+ if (params.c_iflag & (IXON | IXOFF | IXANY))
544
+ {
545
+ ret += SOFT;
546
+ }
547
+
548
+ return INT2FIX(ret);
549
+ }
550
+
551
+ VALUE sp_set_read_timeout_impl(self, val)
552
+ VALUE self, val;
553
+ {
554
+ int timeout;
555
+ int fd;
556
+ struct termios params;
557
+
558
+ Check_Type(val, T_FIXNUM);
559
+ timeout = FIX2INT(val);
560
+
561
+ fd = get_fd_helper(self);
562
+ if (tcgetattr(fd, &params) == -1)
563
+ {
564
+ rb_sys_fail(sTcgetattr);
565
+ }
566
+
567
+ if (timeout < 0)
568
+ {
569
+ params.c_cc[VTIME] = 0;
570
+ params.c_cc[VMIN] = 0;
571
+ }
572
+ else if (timeout == 0)
573
+ {
574
+ params.c_cc[VTIME] = 0;
575
+ params.c_cc[VMIN] = 1;
576
+ }
577
+ else
578
+ {
579
+ params.c_cc[VTIME] = (timeout + 50) / 100;
580
+ params.c_cc[VMIN] = 0;
581
+ }
582
+
583
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
584
+ {
585
+ rb_sys_fail(sTcsetattr);
586
+ }
587
+
588
+ return val;
589
+ }
590
+
591
+ VALUE sp_get_read_timeout_impl(self)
592
+ VALUE self;
593
+ {
594
+ int fd;
595
+ struct termios params;
596
+
597
+ fd = get_fd_helper(self);
598
+ if (tcgetattr(fd, &params) == -1)
599
+ {
600
+ rb_sys_fail(sTcgetattr);
601
+ }
602
+
603
+ if (params.c_cc[VTIME] == 0 && params.c_cc[VMIN] == 0)
604
+ {
605
+ return INT2FIX(-1);
606
+ }
607
+
608
+ return INT2FIX(params.c_cc[VTIME] * 100);
609
+ }
610
+
611
+ VALUE sp_set_write_timeout_impl(self, val)
612
+ VALUE self, val;
613
+ {
614
+ rb_notimplement();
615
+ return self;
616
+ }
617
+
618
+ VALUE sp_get_write_timeout_impl(self)
619
+ VALUE self;
620
+ {
621
+ rb_notimplement();
622
+ return self;
623
+ }
624
+
625
+ VALUE sp_break_impl(self, time)
626
+ VALUE self, time;
627
+ {
628
+ int fd;
629
+
630
+ Check_Type(time, T_FIXNUM);
631
+
632
+ fd = get_fd_helper(self);
633
+
634
+ if (tcsendbreak(fd, FIX2INT(time) / 3) == -1)
635
+ {
636
+ rb_sys_fail("tcsendbreak");
637
+ }
638
+
639
+ return Qnil;
640
+ }
641
+
642
+ void get_line_signals_helper_impl(obj, ls)
643
+ VALUE obj;
644
+ struct line_signals *ls;
645
+ {
646
+ int fd, status;
647
+
648
+ fd = get_fd_helper(obj);
649
+
650
+ if (ioctl(fd, TIOCMGET, &status) == -1)
651
+ {
652
+ rb_sys_fail(sIoctl);
653
+ }
654
+
655
+ ls->rts = (status & TIOCM_RTS ? 1 : 0);
656
+ ls->dtr = (status & TIOCM_DTR ? 1 : 0);
657
+ ls->cts = (status & TIOCM_CTS ? 1 : 0);
658
+ ls->dsr = (status & TIOCM_DSR ? 1 : 0);
659
+ ls->dcd = (status & TIOCM_CD ? 1 : 0);
660
+ ls->ri = (status & TIOCM_RI ? 1 : 0);
661
+ }
662
+
663
+ VALUE set_signal_impl(obj, val, sig)
664
+ VALUE obj,val;
665
+ int sig;
666
+ {
667
+ int status;
668
+ int fd;
669
+ int set;
670
+
671
+ Check_Type(val, T_FIXNUM);
672
+ fd = get_fd_helper(obj);
673
+
674
+ if (ioctl(fd, TIOCMGET, &status) == -1)
675
+ {
676
+ rb_sys_fail(sIoctl);
677
+ }
678
+
679
+ set = FIX2INT(val);
680
+
681
+ if (set == 0)
682
+ {
683
+ status &= ~sig;
684
+ }
685
+ else if (set == 1)
686
+ {
687
+ status |= sig;
688
+ }
689
+ else
690
+ {
691
+ rb_raise(rb_eArgError, "invalid value");
692
+ }
693
+
694
+ if (ioctl(fd, TIOCMSET, &status) == -1)
695
+ {
696
+ rb_sys_fail(sIoctl);
697
+ }
698
+
699
+ return val;
700
+ }
701
+
702
+ VALUE sp_set_rts_impl(self, val)
703
+ VALUE self, val;
704
+ {
705
+ return set_signal_impl(self, val, TIOCM_RTS);
706
+ }
707
+
708
+ VALUE sp_set_dtr_impl(self, val)
709
+ VALUE self, val;
710
+ {
711
+ return set_signal_impl(self, val, TIOCM_DTR);
712
+ }
713
+
714
+ VALUE sp_get_rts_impl(self)
715
+ VALUE self;
716
+ {
717
+ struct line_signals ls;
718
+
719
+ get_line_signals_helper_impl(self, &ls);
720
+ return INT2FIX(ls.rts);
721
+ }
722
+
723
+ VALUE sp_get_dtr_impl(self)
724
+ VALUE self;
725
+ {
726
+ struct line_signals ls;
727
+
728
+ get_line_signals_helper_impl(self, &ls);
729
+
730
+ return INT2FIX(ls.dtr);
731
+ }
732
+
733
+ #endif /* !defined(OS_MSWIN) && !defined(OS_BCCWIN) && !defined(OS_MINGW) */