serialport 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,29 @@
1
+ 0.7.4 => 10/12/2009: Conditional 1.8.6 & 1.9 support (POSIX only). MinGW support.
2
+
3
+ 0.7.3 => 10/09/2009: http://makrotopia.org/browser/makrosys/makrobe/ruby-serialport/patches/10-fix-for-ruby-1.9
4
+ applied for 1.9 support (POSIX only)
5
+
6
+ 0.7.2 => 02/09/2008: Fix several Windows and POSIX compilation problems.
7
+ Make GCC compile the code without any warnings.
8
+ Make RDoc not be so talkative during gem installation.
9
+
10
+ 0.7.1 => 31/08/2008: Change to gemspec creation and fix posix compilation.
11
+
12
+ 0.7.0 => 03/07/2008: Major Code Cleanup
13
+
14
+ 0.6.1 => 25/03/2003: Minor changes
15
+
16
+ 0.6 => 12/02/2003: Windows support
17
+ Get/set modem parameters
18
+ Read and write timeouts
19
+ Open method
20
+
21
+ 0.5 => 25/10/2002: Cygwin support
22
+
23
+ 0.4 => 19/09/2002: Added more serial ports (total of 8 ports)
24
+
25
+ 0.3 => 15/03/2002: Damn, another bug found
26
+
27
+ 0.2 => 14/03/2002: A bug fixed (read() was not blocking)
28
+
29
+ 0.1 => 14/03/2002: First release
@@ -0,0 +1,11 @@
1
+ CHANGELOG
2
+ README
3
+ MANIFEST
4
+ serialport.gemspec
5
+ extconf.rb
6
+ lib/serialport.rb
7
+ src/posix_serialport_impl.c
8
+ src/serialport.c
9
+ src/serialport.h
10
+ src/win_serialport_impl.c
11
+ test/miniterm.rb
data/README ADDED
@@ -0,0 +1,156 @@
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>
@@ -0,0 +1,19 @@
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']
13
+ gemspec.has_rdoc = false
14
+ gemspec.extensions << '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
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.7.4
@@ -0,0 +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
+
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','src')
@@ -0,0 +1,32 @@
1
+ require "serialport.so"
2
+
3
+ class SerialPort
4
+ private_class_method(:create)
5
+
6
+ def SerialPort::new(port, *params)
7
+ sp = create(port)
8
+ begin
9
+ sp.set_modem_params(*params)
10
+ rescue
11
+ sp.close
12
+ raise
13
+ end
14
+ return sp
15
+ end
16
+
17
+ def SerialPort::open(port, *params)
18
+ sp = create(port)
19
+ begin
20
+ sp.set_modem_params(*params)
21
+ if (block_given?)
22
+ yield sp
23
+ sp.close
24
+ return nil
25
+ end
26
+ rescue
27
+ sp.close
28
+ raise
29
+ end
30
+ return sp
31
+ end
32
+ end
@@ -0,0 +1,52 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{serialport}
8
+ s.version = "0.7.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Guillaume Pierronnet", "Alan Stern", "Daniel E. Shipton", "Tobin Richard"]
12
+ s.date = %q{2009-10-13}
13
+ s.description = %q{Ruby/SerialPort is a Ruby library that provides a class for using RS-232 serial ports.}
14
+ s.email = %q{hector@hectorparra.com}
15
+ s.extensions = ["extconf.rb"]
16
+ s.extra_rdoc_files = [
17
+ "README"
18
+ ]
19
+ s.files = [
20
+ "CHANGELOG",
21
+ "MANIFEST",
22
+ "README",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "extconf.rb",
26
+ "lib/serialport.rb",
27
+ "serialport.gemspec",
28
+ "src/posix_serialport_impl.c",
29
+ "src/serialport.c",
30
+ "src/serialport.h",
31
+ "src/win_serialport_impl.c",
32
+ "test/miniterm.rb"
33
+ ]
34
+ s.homepage = %q{http://github.com/hparra/ruby-serialport/}
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.5}
38
+ s.summary = %q{Library for using RS-232 serial ports.}
39
+ s.test_files = [
40
+ "test/miniterm.rb"
41
+ ]
42
+
43
+ if s.respond_to? :specification_version then
44
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
48
+ else
49
+ end
50
+ else
51
+ end
52
+ end
@@ -0,0 +1,687 @@
1
+ /* Ruby/SerialPort $Id$
2
+ * Guillaume Pierronnet <moumar@netcourrier.com>
3
+ * Alan Stern <stern@rowland.harvard.edu>
4
+ * Daniel E. Shipton <dshipton@redshiptechnologies.com>
5
+ *
6
+ * This code is hereby licensed for public consumption under either the
7
+ * GNU GPL v2 or greater.
8
+ *
9
+ * You should have received a copy of the GNU General Public License
10
+ * along with this program; if not, write to the Free Software
11
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
12
+ *
13
+ * For documentation on serial programming, see the excellent:
14
+ * "Serial Programming Guide for POSIX Operating Systems"
15
+ * written Michael R. Sweet.
16
+ * http://www.easysw.com/~mike/serial/
17
+ */
18
+
19
+ #include "serialport.h"
20
+
21
+ /* Check if we are on a posix compliant system. */
22
+ #if !defined(OS_MSWIN) && !defined(OS_BCCWIN) && !defined(OS_MINGW)
23
+
24
+ #include <stdio.h> /* Standard input/output definitions */
25
+ #include <unistd.h> /* UNIX standard function definitions */
26
+ #include <fcntl.h> /* File control definitions */
27
+ #include <errno.h> /* Error number definitions */
28
+ #include <termios.h> /* POSIX terminal control definitions */
29
+ #include <sys/ioctl.h>
30
+
31
+ #ifdef CRTSCTS
32
+ #define HAVE_FLOWCONTROL_HARD 1
33
+ #else
34
+ #undef HAVE_FLOWCONTROL_HARD
35
+ #endif
36
+
37
+
38
+ static char sTcgetattr[] = "tcgetattr";
39
+ static char sTcsetattr[] = "tcsetattr";
40
+ static char sIoctl[] = "ioctl";
41
+
42
+
43
+ int get_fd_helper(obj)
44
+ VALUE obj;
45
+ {
46
+ #if RUBY_VERSION >= '1.9.0'
47
+ rb_io_t *fptr;
48
+ #else
49
+ OpenFile *fptr;
50
+ #endif
51
+ GetOpenFile(obj, fptr);
52
+ #if RUBY_VERSION >= '1.9.0'
53
+ return (fptr->fd);
54
+ #else
55
+ return (fileno(fptr->f));
56
+ #endif
57
+ }
58
+
59
+ VALUE sp_create_impl(class, _port)
60
+ VALUE class, _port;
61
+ {
62
+ #if RUBY_VERSION >= '1.9.0'
63
+ rb_io_t *fp;
64
+ #else
65
+ OpenFile *fp;
66
+ #endif
67
+
68
+ int fd;
69
+ int num_port;
70
+ char *port;
71
+ char *ports[] = {
72
+ #if defined(OS_LINUX) || defined(OS_CYGWIN)
73
+ "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3",
74
+ "/dev/ttyS4", "/dev/ttyS5", "/dev/ttyS6", "/dev/ttyS7"
75
+ #elif defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD)
76
+ "/dev/cuaa0", "/dev/cuaa1", "/dev/cuaa2", "/dev/cuaa3",
77
+ "/dev/cuaa4", "/dev/cuaa5", "/dev/cuaa6", "/dev/cuaa7"
78
+ #elif defined(OS_SOLARIS)
79
+ "/dev/ttya", "/dev/ttyb", "/dev/ttyc", "/dev/ttyd",
80
+ "/dev/ttye", "/dev/ttyf", "/dev/ttyg", "/dev/ttyh"
81
+ #elif defined(OS_AIX)
82
+ "/dev/tty0", "/dev/tty1", "/dev/tty2", "/dev/tty3",
83
+ "/dev/tty4", "/dev/tty5", "/dev/tty6", "/dev/tty7"
84
+ #elif defined(OS_IRIX)
85
+ "/dev/ttyf1", "/dev/ttyf2", "/dev/ttyf3", "/dev/ttyf4",
86
+ "/dev/ttyf5", "/dev/ttyf6", "/dev/ttyf7", "/dev/ttyf8"
87
+ #endif
88
+ };
89
+ struct termios params;
90
+
91
+ NEWOBJ(sp, struct RFile);
92
+ rb_secure(4);
93
+ OBJSETUP(sp, class, T_FILE);
94
+ MakeOpenFile((VALUE) sp, fp);
95
+
96
+ switch(TYPE(_port))
97
+ {
98
+ case T_FIXNUM:
99
+ num_port = FIX2INT(_port);
100
+ if (num_port < 0 || num_port > sizeof(ports) / sizeof(ports[0]))
101
+ {
102
+ rb_raise(rb_eArgError, "illegal port number");
103
+ }
104
+ port = ports[num_port];
105
+ break;
106
+
107
+ case T_STRING:
108
+ Check_SafeStr(_port);
109
+ #if RUBY_VERSION >= '1.9.0'
110
+ port = RSTRING_PTR(_port);
111
+ #else
112
+ port = RSTRING(_port)->ptr;
113
+ #endif
114
+ break;
115
+
116
+ default:
117
+ rb_raise(rb_eTypeError, "wrong argument type");
118
+ break;
119
+ }
120
+
121
+ fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
122
+ if (fd == -1)
123
+ {
124
+ rb_sys_fail(port);
125
+ }
126
+
127
+ if (!isatty(fd))
128
+ {
129
+ close(fd);
130
+ rb_raise(rb_eArgError, "not a serial port");
131
+ }
132
+
133
+ /* enable blocking read */
134
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
135
+
136
+ if (tcgetattr(fd, &params) == -1)
137
+ {
138
+ close(fd);
139
+ rb_sys_fail(sTcgetattr);
140
+ }
141
+
142
+ params.c_oflag = 0;
143
+ params.c_lflag = 0;
144
+ params.c_iflag &= (IXON | IXOFF | IXANY);
145
+ params.c_cflag |= CLOCAL | CREAD;
146
+ params.c_cflag &= ~HUPCL;
147
+
148
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
149
+ {
150
+ close(fd);
151
+ rb_sys_fail(sTcsetattr);
152
+ }
153
+
154
+ #if RUBY_VERSION >= '1.9.0'
155
+ fp->fd = fd;
156
+ #else
157
+ fp->f = rb_fdopen(fd, "r+");
158
+ #endif
159
+ fp->mode = FMODE_READWRITE | FMODE_SYNC;
160
+
161
+ return (VALUE) sp;
162
+ }
163
+
164
+ VALUE sp_set_modem_params_impl(argc, argv, self)
165
+ int argc;
166
+ VALUE *argv, self;
167
+ {
168
+ int fd;
169
+ struct termios params;
170
+ VALUE _data_rate, _data_bits, _parity, _stop_bits;
171
+ int use_hash = 0;
172
+ int data_rate, data_bits;
173
+ _data_rate = _data_bits = _parity = _stop_bits = Qnil;
174
+
175
+ if (argc == 0)
176
+ {
177
+ return self;
178
+ }
179
+
180
+ if (argc == 1 && T_HASH == TYPE(argv[0]))
181
+ {
182
+ use_hash = 1;
183
+ _data_rate = rb_hash_aref(argv[0], sBaud);
184
+ _data_bits = rb_hash_aref(argv[0], sDataBits);
185
+ _stop_bits = rb_hash_aref(argv[0], sStopBits);
186
+ _parity = rb_hash_aref(argv[0], sParity);
187
+ }
188
+
189
+ fd = get_fd_helper(self);
190
+ if (tcgetattr(fd, &params) == -1)
191
+ {
192
+ rb_sys_fail(sTcgetattr);
193
+ }
194
+
195
+ if (!use_hash)
196
+ {
197
+ _data_rate = argv[0];
198
+ }
199
+
200
+ if (NIL_P(_data_rate))
201
+ {
202
+ goto SkipDataRate;
203
+ }
204
+ Check_Type(_data_rate, T_FIXNUM);
205
+
206
+ switch(FIX2INT(_data_rate))
207
+ {
208
+ case 50: data_rate = B50; break;
209
+ case 75: data_rate = B75; break;
210
+ case 110: data_rate = B110; break;
211
+ case 134: data_rate = B134; break;
212
+ case 150: data_rate = B150; break;
213
+ case 200: data_rate = B200; break;
214
+ case 300: data_rate = B300; break;
215
+ case 600: data_rate = B600; break;
216
+ case 1200: data_rate = B1200; break;
217
+ case 1800: data_rate = B1800; break;
218
+ case 2400: data_rate = B2400; break;
219
+ case 4800: data_rate = B4800; break;
220
+ case 9600: data_rate = B9600; break;
221
+ case 19200: data_rate = B19200; break;
222
+ case 38400: data_rate = B38400; break;
223
+ #ifdef B57600
224
+ case 57600: data_rate = B57600; break;
225
+ #endif
226
+ #ifdef B76800
227
+ case 76800: data_rate = B76800; break;
228
+ #endif
229
+ #ifdef B115200
230
+ case 115200: data_rate = B115200; break;
231
+ #endif
232
+ #ifdef B230400
233
+ case 230400: data_rate = B230400; break;
234
+ #endif
235
+
236
+ default:
237
+ rb_raise(rb_eArgError, "unknown baud rate");
238
+ break;
239
+ }
240
+ cfsetispeed(&params, data_rate);
241
+ cfsetospeed(&params, data_rate);
242
+
243
+ SkipDataRate:
244
+
245
+ if (!use_hash)
246
+ {
247
+ _data_bits = (argc >= 2 ? argv[1] : INT2FIX(8));
248
+ }
249
+
250
+ if (NIL_P(_data_bits))
251
+ {
252
+ goto SkipDataBits;
253
+ }
254
+ Check_Type(_data_bits, T_FIXNUM);
255
+
256
+ switch(FIX2INT(_data_bits))
257
+ {
258
+ case 5:
259
+ data_bits = CS5;
260
+ break;
261
+ case 6:
262
+ data_bits = CS6;
263
+ break;
264
+ case 7:
265
+ data_bits = CS7;
266
+ break;
267
+ case 8:
268
+ data_bits = CS8;
269
+ break;
270
+ default:
271
+ rb_raise(rb_eArgError, "unknown character size");
272
+ break;
273
+ }
274
+ params.c_cflag &= ~CSIZE;
275
+ params.c_cflag |= data_bits;
276
+
277
+ SkipDataBits:
278
+
279
+ if (!use_hash)
280
+ {
281
+ _stop_bits = (argc >= 3 ? argv[2] : INT2FIX(1));
282
+ }
283
+
284
+ if (NIL_P(_stop_bits))
285
+ {
286
+ goto SkipStopBits;
287
+ }
288
+
289
+ Check_Type(_stop_bits, T_FIXNUM);
290
+
291
+ switch(FIX2INT(_stop_bits))
292
+ {
293
+ case 1:
294
+ params.c_cflag &= ~CSTOPB;
295
+ break;
296
+ case 2:
297
+ params.c_cflag |= CSTOPB;
298
+ break;
299
+ default:
300
+ rb_raise(rb_eArgError, "unknown number of stop bits");
301
+ break;
302
+ }
303
+
304
+ SkipStopBits:
305
+
306
+ if (!use_hash)
307
+ {
308
+ _parity = (argc >= 4 ? argv[3] : ((params.c_cflag & CSIZE) == CS8 ?
309
+ INT2FIX(NONE) : INT2FIX(EVEN)));
310
+ }
311
+
312
+ if (NIL_P(_parity))
313
+ {
314
+ goto SkipParity;
315
+ }
316
+
317
+ Check_Type(_parity, T_FIXNUM);
318
+
319
+ switch(FIX2INT(_parity))
320
+ {
321
+ case EVEN:
322
+ params.c_cflag |= PARENB;
323
+ params.c_cflag &= ~PARODD;
324
+ break;
325
+
326
+ case ODD:
327
+ params.c_cflag |= PARENB;
328
+ params.c_cflag |= PARODD;
329
+ break;
330
+
331
+ case NONE:
332
+ params.c_cflag &= ~PARENB;
333
+ break;
334
+
335
+ default:
336
+ rb_raise(rb_eArgError, "unknown parity");
337
+ break;
338
+ }
339
+
340
+ SkipParity:
341
+
342
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
343
+ {
344
+ rb_sys_fail(sTcsetattr);
345
+ }
346
+ return argv[0];
347
+ }
348
+
349
+ void get_modem_params_impl(self, mp)
350
+ VALUE self;
351
+ struct modem_params *mp;
352
+ {
353
+ int fd;
354
+ struct termios params;
355
+
356
+ fd = get_fd_helper(self);
357
+ if (tcgetattr(fd, &params) == -1)
358
+ {
359
+ rb_sys_fail(sTcgetattr);
360
+ }
361
+
362
+ switch (cfgetospeed(&params))
363
+ {
364
+ case B50: mp->data_rate = 50; break;
365
+ case B75: mp->data_rate = 75; break;
366
+ case B110: mp->data_rate = 110; break;
367
+ case B134: mp->data_rate = 134; break;
368
+ case B150: mp->data_rate = 150; break;
369
+ case B200: mp->data_rate = 200; break;
370
+ case B300: mp->data_rate = 300; break;
371
+ case B600: mp->data_rate = 600; break;
372
+ case B1200: mp->data_rate = 1200; break;
373
+ case B1800: mp->data_rate = 1800; break;
374
+ case B2400: mp->data_rate = 2400; break;
375
+ case B4800: mp->data_rate = 4800; break;
376
+ case B9600: mp->data_rate = 9600; break;
377
+ case B19200: mp->data_rate = 19200; break;
378
+ case B38400: mp->data_rate = 38400; break;
379
+ #ifdef B57600
380
+ case B57600: mp->data_rate = 57600; break;
381
+ #endif
382
+ #ifdef B76800
383
+ case B76800: mp->data_rate = 76800; break;
384
+ #endif
385
+ #ifdef B115200
386
+ case B115200: mp->data_rate = 115200; break;
387
+ #endif
388
+ #ifdef B230400
389
+ case B230400: mp->data_rate = 230400; break;
390
+ #endif
391
+ }
392
+
393
+ switch(params.c_cflag & CSIZE)
394
+ {
395
+ case CS5:
396
+ mp->data_bits = 5;
397
+ break;
398
+ case CS6:
399
+ mp->data_bits = 6;
400
+ break;
401
+ case CS7:
402
+ mp->data_bits = 7;
403
+ break;
404
+ case CS8:
405
+ mp->data_bits = 8;
406
+ break;
407
+ default:
408
+ mp->data_bits = 0;
409
+ break;
410
+ }
411
+
412
+ mp->stop_bits = (params.c_cflag & CSTOPB ? 2 : 1);
413
+
414
+ if (!(params.c_cflag & PARENB))
415
+ {
416
+ mp->parity = NONE;
417
+ }
418
+ else if (params.c_cflag & PARODD)
419
+ {
420
+ mp->parity = ODD;
421
+ }
422
+ else
423
+ {
424
+ mp->parity = EVEN;
425
+ }
426
+ }
427
+
428
+ VALUE sp_set_flow_control_impl(self, val)
429
+ VALUE self, val;
430
+ {
431
+ int fd;
432
+ int flowc;
433
+ struct termios params;
434
+
435
+ Check_Type(val, T_FIXNUM);
436
+
437
+ fd = get_fd_helper(self);
438
+ if (tcgetattr(fd, &params) == -1)
439
+ {
440
+ rb_sys_fail(sTcgetattr);
441
+ }
442
+
443
+ flowc = FIX2INT(val);
444
+ if (flowc & HARD)
445
+ {
446
+ #ifdef HAVE_FLOWCONTROL_HARD
447
+ params.c_cflag |= CRTSCTS;
448
+ }
449
+ else
450
+ {
451
+ params.c_cflag &= ~CRTSCTS;
452
+ }
453
+ #else
454
+ rb_raise(rb_eIOError, "Hardware flow control not supported");
455
+ }
456
+ #endif
457
+
458
+ if (flowc & SOFT)
459
+ {
460
+ params.c_iflag |= (IXON | IXOFF | IXANY);
461
+ }
462
+ else
463
+ {
464
+ params.c_iflag &= ~(IXON | IXOFF | IXANY);
465
+ }
466
+
467
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
468
+ {
469
+ rb_sys_fail(sTcsetattr);
470
+ }
471
+
472
+ return val;
473
+ }
474
+
475
+ VALUE sp_get_flow_control_impl(self)
476
+ VALUE self;
477
+ {
478
+ int ret;
479
+ int fd;
480
+ struct termios params;
481
+
482
+ fd = get_fd_helper(self);
483
+ if (tcgetattr(fd, &params) == -1)
484
+ {
485
+ rb_sys_fail(sTcgetattr);
486
+ }
487
+
488
+ ret = 0;
489
+
490
+ #ifdef HAVE_FLOWCONTROL_HARD
491
+ if (params.c_cflag & CRTSCTS)
492
+ {
493
+ ret += HARD;
494
+ }
495
+ #endif
496
+
497
+ if (params.c_iflag & (IXON | IXOFF | IXANY))
498
+ {
499
+ ret += SOFT;
500
+ }
501
+
502
+ return INT2FIX(ret);
503
+ }
504
+
505
+ VALUE sp_set_read_timeout_impl(self, val)
506
+ VALUE self, val;
507
+ {
508
+ int timeout;
509
+ int fd;
510
+ struct termios params;
511
+
512
+ Check_Type(val, T_FIXNUM);
513
+ timeout = FIX2INT(val);
514
+
515
+ fd = get_fd_helper(self);
516
+ if (tcgetattr(fd, &params) == -1)
517
+ {
518
+ rb_sys_fail(sTcgetattr);
519
+ }
520
+
521
+ if (timeout < 0)
522
+ {
523
+ params.c_cc[VTIME] = 0;
524
+ params.c_cc[VMIN] = 0;
525
+ }
526
+ else if (timeout == 0)
527
+ {
528
+ params.c_cc[VTIME] = 0;
529
+ params.c_cc[VMIN] = 1;
530
+ }
531
+ else
532
+ {
533
+ params.c_cc[VTIME] = (timeout + 50) / 100;
534
+ params.c_cc[VMIN] = 0;
535
+ }
536
+
537
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
538
+ {
539
+ rb_sys_fail(sTcsetattr);
540
+ }
541
+
542
+ return val;
543
+ }
544
+
545
+ VALUE sp_get_read_timeout_impl(self)
546
+ VALUE self;
547
+ {
548
+ int fd;
549
+ struct termios params;
550
+
551
+ fd = get_fd_helper(self);
552
+ if (tcgetattr(fd, &params) == -1)
553
+ {
554
+ rb_sys_fail(sTcgetattr);
555
+ }
556
+
557
+ if (params.c_cc[VTIME] == 0 && params.c_cc[VMIN] == 0)
558
+ {
559
+ return INT2FIX(-1);
560
+ }
561
+
562
+ return INT2FIX(params.c_cc[VTIME] * 100);
563
+ }
564
+
565
+ VALUE sp_set_write_timeout_impl(self, val)
566
+ VALUE self, val;
567
+ {
568
+ rb_notimplement();
569
+ return self;
570
+ }
571
+
572
+ VALUE sp_get_write_timeout_impl(self)
573
+ VALUE self;
574
+ {
575
+ rb_notimplement();
576
+ return self;
577
+ }
578
+
579
+ VALUE sp_break_impl(self, time)
580
+ VALUE self, time;
581
+ {
582
+ int fd;
583
+
584
+ Check_Type(time, T_FIXNUM);
585
+
586
+ fd = get_fd_helper(self);
587
+
588
+ if (tcsendbreak(fd, FIX2INT(time) / 3) == -1)
589
+ {
590
+ rb_sys_fail("tcsendbreak");
591
+ }
592
+
593
+ return Qnil;
594
+ }
595
+
596
+ void get_line_signals_helper_impl(obj, ls)
597
+ VALUE obj;
598
+ struct line_signals *ls;
599
+ {
600
+ int fd, status;
601
+
602
+ fd = get_fd_helper(obj);
603
+
604
+ if (ioctl(fd, TIOCMGET, &status) == -1)
605
+ {
606
+ rb_sys_fail(sIoctl);
607
+ }
608
+
609
+ ls->rts = (status & TIOCM_RTS ? 1 : 0);
610
+ ls->dtr = (status & TIOCM_DTR ? 1 : 0);
611
+ ls->cts = (status & TIOCM_CTS ? 1 : 0);
612
+ ls->dsr = (status & TIOCM_DSR ? 1 : 0);
613
+ ls->dcd = (status & TIOCM_CD ? 1 : 0);
614
+ ls->ri = (status & TIOCM_RI ? 1 : 0);
615
+ }
616
+
617
+ VALUE set_signal_impl(obj, val, sig)
618
+ VALUE obj,val;
619
+ int sig;
620
+ {
621
+ int status;
622
+ int fd;
623
+ int set;
624
+
625
+ Check_Type(val, T_FIXNUM);
626
+ fd = get_fd_helper(obj);
627
+
628
+ if (ioctl(fd, TIOCMGET, &status) == -1)
629
+ {
630
+ rb_sys_fail(sIoctl);
631
+ }
632
+
633
+ set = FIX2INT(val);
634
+
635
+ if (set == 0)
636
+ {
637
+ status &= ~sig;
638
+ }
639
+ else if (set == 1)
640
+ {
641
+ status |= sig;
642
+ }
643
+ else
644
+ {
645
+ rb_raise(rb_eArgError, "invalid value");
646
+ }
647
+
648
+ if (ioctl(fd, TIOCMSET, &status) == -1)
649
+ {
650
+ rb_sys_fail(sIoctl);
651
+ }
652
+
653
+ return val;
654
+ }
655
+
656
+ VALUE sp_set_rts_impl(self, val)
657
+ VALUE self, val;
658
+ {
659
+ return set_signal_impl(self, val, TIOCM_RTS);
660
+ }
661
+
662
+ VALUE sp_set_dtr_impl(self, val)
663
+ VALUE self, val;
664
+ {
665
+ return set_signal_impl(self, val, TIOCM_DTR);
666
+ }
667
+
668
+ VALUE sp_get_rts_impl(self)
669
+ VALUE self;
670
+ {
671
+ struct line_signals ls;
672
+
673
+ get_line_signals_helper_impl(self, &ls);
674
+ return INT2FIX(ls.rts);
675
+ }
676
+
677
+ VALUE sp_get_dtr_impl(self)
678
+ VALUE self;
679
+ {
680
+ struct line_signals ls;
681
+
682
+ get_line_signals_helper_impl(self, &ls);
683
+
684
+ return INT2FIX(ls.dtr);
685
+ }
686
+
687
+ #endif /* !defined(OS_MSWIN) && !defined(OS_BCCWIN) && !defined(OS_MINGW) */