aarontc-serialport 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,12 @@
1
+ CHANGELOG
2
+ MANIFEST
3
+ README.md
4
+ Rakefile
5
+ serialport.gemspec
6
+ ext/native/extconf.rb
7
+ ext/native/posix_serialport_impl.c
8
+ ext/native/serialport.c
9
+ ext/native/serialport.h
10
+ ext/native/win_serialport_impl.c
11
+ lib/serialport.rb
12
+ test/miniterm.rb
@@ -0,0 +1,43 @@
1
+ # Ruby/SerialPort
2
+
3
+ [![Build Status](https://travis-ci.org/hparra/ruby-serialport.png?branch=v1.2.2)](https://travis-ci.org/hparra/ruby-serialport)
4
+
5
+ ## Description
6
+
7
+ Ruby/SerialPort is a Ruby library that provides a class for using RS-232 serial ports. This class also contains low-level functions to check and set the current state of the signals on the line.
8
+
9
+ The native Windows version of this library supports the Microsoft Visual C++, Borland C++, and MinGW compilers.
10
+
11
+ There is an alternative gem with MRI, JRuby, and Rubinius support. See below.
12
+
13
+ ## Installation
14
+
15
+ Install the gem as normal: `sudo gem install serialport`
16
+
17
+ ## Testing
18
+
19
+ Use Ruby's version of miniterm: `ruby test/miniterm.rb`
20
+
21
+ ## API
22
+
23
+ See <http://rubydoc.info/gems/serialport/SerialPort> or run `yard`
24
+
25
+ ## Issues
26
+
27
+ See <https://github.com/hparra/ruby-serialport/issues>
28
+
29
+ ## Alternatives
30
+
31
+ The [Hybrid Group](http://hybridgroup.com/)'s MRI, JRuby, & Rubinius compatible [rubyserial](https://github.com/hybridgroup/rubyserial) gem may provide improved compatibilty in modern environments.
32
+
33
+ ## License
34
+
35
+ GPL
36
+
37
+ ## Authors
38
+
39
+ * Guillaume Pierronnet <moumar@netcourrier.com>
40
+ * Alan Stern <stern@rowland.harvard.edu>
41
+ * Tobin Richard <tobin.richard@gmail.com>
42
+ * Hector Parra <hector@hectorparra.com>
43
+ * Ryan C. Payne <rpayne-oss@bullittsystems.com>
@@ -0,0 +1,27 @@
1
+
2
+ # :build
3
+ # :install
4
+ # :release
5
+ require "bundler/gem_tasks"
6
+
7
+ # :clean
8
+ # :clobber
9
+ # :compile
10
+ # :compile:serialport
11
+ require "rake/extensiontask"
12
+
13
+ CLOBBER << FileList["doc"]
14
+ CLOBBER << FileList["pkg"]
15
+
16
+ GEMSPEC = eval File.read File.expand_path("../serialport.gemspec", __FILE__)
17
+
18
+ Rake::ExtensionTask.new "serialport", GEMSPEC do |ext|
19
+ ext.lib_dir = File.join(*['lib', ENV['FAT_DIR']].compact)
20
+ ext.ext_dir = "ext/native"
21
+ end
22
+
23
+ # add your default gem packing task
24
+ Gem::PackageTask.new(GEMSPEC) do |pkg|
25
+ end
26
+
27
+ task :default => [:clean, :clobber, :compile, :test]
@@ -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')
@@ -0,0 +1,790 @@
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
+ * Manuel "MaG" A. Güílamo <maguilamo.c@gmail.com>
7
+ *
8
+ * This code is hereby licensed for public consumption under either the
9
+ * GNU GPL v2 or greater.
10
+ *
11
+ * You should have received a copy of the GNU General Public License
12
+ * along with this program; if not, write to the Free Software
13
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
14
+ *
15
+ * For documentation on serial programming, see the excellent:
16
+ * "Serial Programming Guide for POSIX Operating Systems"
17
+ * written Michael R. Sweet.
18
+ * http://www.easysw.com/~mike/serial/
19
+ */
20
+
21
+ #include "serialport.h"
22
+
23
+ /* Check if we are on a posix compliant system. */
24
+ #if !defined(OS_MSWIN) && !defined(OS_BCCWIN) && !defined(OS_MINGW)
25
+
26
+ #include <stdio.h> /* Standard input/output definitions */
27
+ #include <unistd.h> /* UNIX standard function definitions */
28
+ #include <fcntl.h> /* File control definitions */
29
+ #include <errno.h> /* Error number definitions */
30
+ #include <termios.h> /* POSIX terminal control definitions */
31
+ #include <sys/ioctl.h>
32
+
33
+ #ifdef CRTSCTS
34
+ #define HAVE_FLOWCONTROL_HARD 1
35
+ #else
36
+ #undef HAVE_FLOWCONTROL_HARD
37
+ #endif
38
+
39
+ /* on mac os x, not all baud rates are defined in termios.h but
40
+ they are mapped to the numeric value anyway, so we define them here */
41
+ #ifdef __APPLE__
42
+ #ifndef B460800
43
+ #define B460800 460800
44
+ #endif
45
+ #ifndef B500000
46
+ #define B500000 500000
47
+ #endif
48
+ #ifndef B576000
49
+ #define B576000 576000
50
+ #endif
51
+ #ifndef B921600
52
+ #define B921600 921600
53
+ #endif
54
+ #ifndef B1000000
55
+ #define B1000000 1000000
56
+ #endif
57
+ #endif
58
+
59
+ static char sTcgetattr[] = "tcgetattr";
60
+ static char sTcsetattr[] = "tcsetattr";
61
+ static char sIoctl[] = "ioctl";
62
+
63
+
64
+ int get_fd_helper(obj)
65
+ VALUE obj;
66
+ {
67
+ #ifdef HAVE_RUBY_IO_H
68
+ rb_io_t *fptr;
69
+ #else
70
+ OpenFile *fptr;
71
+ #endif
72
+ GetOpenFile(obj, fptr);
73
+ #ifdef HAVE_RUBY_IO_H
74
+ return (fptr->fd);
75
+ #else
76
+ return (fileno(fptr->f));
77
+ #endif
78
+ }
79
+
80
+ VALUE sp_create_impl(class, _port)
81
+ VALUE class, _port;
82
+ {
83
+ #ifdef HAVE_RUBY_IO_H
84
+ rb_io_t *fp;
85
+ #else
86
+ OpenFile *fp;
87
+ #endif
88
+
89
+ int fd;
90
+ int num_port;
91
+ char *port;
92
+ char *ports[] = {
93
+ #if defined(OS_LINUX) || defined(OS_CYGWIN)
94
+ "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3",
95
+ "/dev/ttyS4", "/dev/ttyS5", "/dev/ttyS6", "/dev/ttyS7"
96
+ #elif defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DARWIN)
97
+ "/dev/cuaa0", "/dev/cuaa1", "/dev/cuaa2", "/dev/cuaa3",
98
+ "/dev/cuaa4", "/dev/cuaa5", "/dev/cuaa6", "/dev/cuaa7"
99
+ #elif defined(OS_SOLARIS)
100
+ "/dev/ttya", "/dev/ttyb", "/dev/ttyc", "/dev/ttyd",
101
+ "/dev/ttye", "/dev/ttyf", "/dev/ttyg", "/dev/ttyh"
102
+ #elif defined(OS_AIX)
103
+ "/dev/tty0", "/dev/tty1", "/dev/tty2", "/dev/tty3",
104
+ "/dev/tty4", "/dev/tty5", "/dev/tty6", "/dev/tty7"
105
+ #elif defined(OS_IRIX)
106
+ "/dev/ttyf1", "/dev/ttyf2", "/dev/ttyf3", "/dev/ttyf4",
107
+ "/dev/ttyf5", "/dev/ttyf6", "/dev/ttyf7", "/dev/ttyf8"
108
+ #endif
109
+ };
110
+ struct termios params;
111
+
112
+ NEWOBJ(sp, struct RFile);
113
+ rb_secure(3);
114
+ OBJSETUP(sp, class, T_FILE);
115
+ MakeOpenFile((VALUE) sp, fp);
116
+
117
+ switch(TYPE(_port))
118
+ {
119
+ case T_FIXNUM:
120
+ num_port = FIX2INT(_port);
121
+ if (num_port < 0 || num_port > sizeof(ports) / sizeof(ports[0]))
122
+ {
123
+ rb_raise(rb_eArgError, "illegal port number");
124
+ }
125
+ port = ports[num_port];
126
+ break;
127
+
128
+ case T_STRING:
129
+ port = StringValueCStr(_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
+ #ifdef CMSPAR
356
+ params.c_cflag &= ~CMSPAR;
357
+ #endif
358
+ break;
359
+
360
+ case ODD:
361
+ params.c_cflag |= PARENB;
362
+ params.c_cflag |= PARODD;
363
+ #ifdef CMSPAR
364
+ params.c_cflag &= ~CMSPAR;
365
+ #endif
366
+ break;
367
+
368
+ #ifdef CMSPAR
369
+ case SPACE:
370
+ params.c_cflag |= PARENB;
371
+ params.c_cflag &= ~PARODD;
372
+ params.c_cflag |= CMSPAR;
373
+ break;
374
+
375
+ case MARK:
376
+ params.c_cflag |= PARENB;
377
+ params.c_cflag |= PARODD;
378
+ params.c_cflag |= CMSPAR;
379
+ break;
380
+ #endif
381
+
382
+ case NONE:
383
+ params.c_cflag &= ~PARENB;
384
+ #ifdef CMSPAR
385
+ params.c_cflag &= ~CMSPAR;
386
+ #endif
387
+ break;
388
+
389
+ default:
390
+ rb_raise(rb_eArgError, "unknown parity");
391
+ break;
392
+ }
393
+
394
+ SkipParity:
395
+
396
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
397
+ {
398
+ rb_sys_fail(sTcsetattr);
399
+ }
400
+ return argv[0];
401
+ }
402
+
403
+ void get_modem_params_impl(self, mp)
404
+ VALUE self;
405
+ struct modem_params *mp;
406
+ {
407
+ int fd;
408
+ struct termios params;
409
+
410
+ fd = get_fd_helper(self);
411
+ if (tcgetattr(fd, &params) == -1)
412
+ {
413
+ rb_sys_fail(sTcgetattr);
414
+ }
415
+
416
+ switch (cfgetospeed(&params))
417
+ {
418
+ case B50: mp->data_rate = 50; break;
419
+ case B75: mp->data_rate = 75; break;
420
+ case B110: mp->data_rate = 110; break;
421
+ case B134: mp->data_rate = 134; break;
422
+ case B150: mp->data_rate = 150; break;
423
+ case B200: mp->data_rate = 200; break;
424
+ case B300: mp->data_rate = 300; break;
425
+ case B600: mp->data_rate = 600; break;
426
+ case B1200: mp->data_rate = 1200; break;
427
+ case B1800: mp->data_rate = 1800; break;
428
+ case B2400: mp->data_rate = 2400; break;
429
+ case B4800: mp->data_rate = 4800; break;
430
+ case B9600: mp->data_rate = 9600; break;
431
+ case B19200: mp->data_rate = 19200; break;
432
+ case B38400: mp->data_rate = 38400; break;
433
+ #ifdef B57600
434
+ case B57600: mp->data_rate = 57600; break;
435
+ #endif
436
+ #ifdef B76800
437
+ case B76800: mp->data_rate = 76800; break;
438
+ #endif
439
+ #ifdef B115200
440
+ case B115200: mp->data_rate = 115200; break;
441
+ #endif
442
+ #ifdef B230400
443
+ case B230400: mp->data_rate = 230400; break;
444
+ #endif
445
+ #ifdef B460800
446
+ case B460800: mp->data_rate = 460800; break;
447
+ #endif
448
+ #ifdef B500000
449
+ case B500000: mp->data_rate = 500000; break;
450
+ #endif
451
+ #ifdef B576000
452
+ case B576000: mp->data_rate = 576000; break;
453
+ #endif
454
+ #ifdef B921600
455
+ case B921600: mp->data_rate = 921600; break;
456
+ #endif
457
+ #ifdef B1000000
458
+ case B1000000: mp->data_rate = 1000000; break;
459
+ #endif
460
+ }
461
+
462
+ switch(params.c_cflag & CSIZE)
463
+ {
464
+ case CS5:
465
+ mp->data_bits = 5;
466
+ break;
467
+ case CS6:
468
+ mp->data_bits = 6;
469
+ break;
470
+ case CS7:
471
+ mp->data_bits = 7;
472
+ break;
473
+ case CS8:
474
+ mp->data_bits = 8;
475
+ break;
476
+ default:
477
+ mp->data_bits = 0;
478
+ break;
479
+ }
480
+
481
+ mp->stop_bits = (params.c_cflag & CSTOPB ? 2 : 1);
482
+
483
+ if (!(params.c_cflag & PARENB))
484
+ {
485
+ mp->parity = NONE;
486
+ }
487
+ else if (params.c_cflag & PARODD)
488
+ {
489
+ mp->parity = ODD;
490
+ }
491
+ else
492
+ {
493
+ mp->parity = EVEN;
494
+ }
495
+ }
496
+
497
+ VALUE sp_set_flow_control_impl(self, val)
498
+ VALUE self, val;
499
+ {
500
+ int fd;
501
+ int flowc;
502
+ struct termios params;
503
+
504
+ Check_Type(val, T_FIXNUM);
505
+
506
+ fd = get_fd_helper(self);
507
+ if (tcgetattr(fd, &params) == -1)
508
+ {
509
+ rb_sys_fail(sTcgetattr);
510
+ }
511
+
512
+ flowc = FIX2INT(val);
513
+ if (flowc & HARD)
514
+ {
515
+ #ifdef HAVE_FLOWCONTROL_HARD
516
+ params.c_cflag |= CRTSCTS;
517
+ }
518
+ else
519
+ {
520
+ params.c_cflag &= ~CRTSCTS;
521
+ }
522
+ #else
523
+ rb_raise(rb_eIOError, "Hardware flow control not supported");
524
+ }
525
+ #endif
526
+
527
+ if (flowc & SOFT)
528
+ {
529
+ params.c_iflag |= (IXON | IXOFF | IXANY);
530
+ }
531
+ else
532
+ {
533
+ params.c_iflag &= ~(IXON | IXOFF | IXANY);
534
+ }
535
+
536
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
537
+ {
538
+ rb_sys_fail(sTcsetattr);
539
+ }
540
+
541
+ return val;
542
+ }
543
+
544
+ VALUE sp_get_flow_control_impl(self)
545
+ VALUE self;
546
+ {
547
+ int ret;
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
+ ret = 0;
558
+
559
+ #ifdef HAVE_FLOWCONTROL_HARD
560
+ if (params.c_cflag & CRTSCTS)
561
+ {
562
+ ret += HARD;
563
+ }
564
+ #endif
565
+
566
+ if (params.c_iflag & (IXON | IXOFF | IXANY))
567
+ {
568
+ ret += SOFT;
569
+ }
570
+
571
+ return INT2FIX(ret);
572
+ }
573
+
574
+ VALUE sp_set_read_timeout_impl(self, val)
575
+ VALUE self, val;
576
+ {
577
+ int timeout;
578
+ int fd;
579
+ struct termios params;
580
+
581
+ Check_Type(val, T_FIXNUM);
582
+ timeout = FIX2INT(val);
583
+
584
+ fd = get_fd_helper(self);
585
+ if (tcgetattr(fd, &params) == -1)
586
+ {
587
+ rb_sys_fail(sTcgetattr);
588
+ }
589
+
590
+ if (timeout < 0)
591
+ {
592
+ params.c_cc[VTIME] = 0;
593
+ params.c_cc[VMIN] = 0;
594
+ }
595
+ else if (timeout == 0)
596
+ {
597
+ params.c_cc[VTIME] = 0;
598
+ params.c_cc[VMIN] = 1;
599
+ }
600
+ else
601
+ {
602
+ params.c_cc[VTIME] = (timeout + 50) / 100;
603
+ params.c_cc[VMIN] = 0;
604
+ }
605
+
606
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
607
+ {
608
+ rb_sys_fail(sTcsetattr);
609
+ }
610
+
611
+ return val;
612
+ }
613
+
614
+ VALUE sp_get_read_timeout_impl(self)
615
+ VALUE self;
616
+ {
617
+ int fd;
618
+ struct termios params;
619
+
620
+ fd = get_fd_helper(self);
621
+ if (tcgetattr(fd, &params) == -1)
622
+ {
623
+ rb_sys_fail(sTcgetattr);
624
+ }
625
+
626
+ if (params.c_cc[VTIME] == 0 && params.c_cc[VMIN] == 0)
627
+ {
628
+ return INT2FIX(-1);
629
+ }
630
+
631
+ return INT2FIX(params.c_cc[VTIME] * 100);
632
+ }
633
+
634
+ VALUE sp_set_write_timeout_impl(self, val)
635
+ VALUE self, val;
636
+ {
637
+ rb_notimplement();
638
+ return self;
639
+ }
640
+
641
+ VALUE sp_get_write_timeout_impl(self)
642
+ VALUE self;
643
+ {
644
+ rb_notimplement();
645
+ return self;
646
+ }
647
+
648
+ VALUE sp_break_impl(self, time)
649
+ VALUE self, time;
650
+ {
651
+ int fd;
652
+
653
+ Check_Type(time, T_FIXNUM);
654
+
655
+ fd = get_fd_helper(self);
656
+
657
+ if (tcsendbreak(fd, FIX2INT(time) / 3) == -1)
658
+ {
659
+ rb_sys_fail("tcsendbreak");
660
+ }
661
+
662
+ return Qnil;
663
+ }
664
+
665
+ void get_line_signals_helper_impl(obj, ls)
666
+ VALUE obj;
667
+ struct line_signals *ls;
668
+ {
669
+ int fd, status;
670
+
671
+ fd = get_fd_helper(obj);
672
+
673
+ if (ioctl(fd, TIOCMGET, &status) == -1)
674
+ {
675
+ rb_sys_fail(sIoctl);
676
+ }
677
+
678
+ ls->rts = (status & TIOCM_RTS ? 1 : 0);
679
+ ls->dtr = (status & TIOCM_DTR ? 1 : 0);
680
+ ls->cts = (status & TIOCM_CTS ? 1 : 0);
681
+ ls->dsr = (status & TIOCM_DSR ? 1 : 0);
682
+ ls->dcd = (status & TIOCM_CD ? 1 : 0);
683
+ ls->ri = (status & TIOCM_RI ? 1 : 0);
684
+ }
685
+
686
+ VALUE set_signal_impl(obj, val, sig)
687
+ VALUE obj,val;
688
+ int sig;
689
+ {
690
+ int status;
691
+ int fd;
692
+ int set;
693
+
694
+ Check_Type(val, T_FIXNUM);
695
+ fd = get_fd_helper(obj);
696
+
697
+ if (ioctl(fd, TIOCMGET, &status) == -1)
698
+ {
699
+ rb_sys_fail(sIoctl);
700
+ }
701
+
702
+ set = FIX2INT(val);
703
+
704
+ if (set == 0)
705
+ {
706
+ status &= ~sig;
707
+ }
708
+ else if (set == 1)
709
+ {
710
+ status |= sig;
711
+ }
712
+ else
713
+ {
714
+ rb_raise(rb_eArgError, "invalid value");
715
+ }
716
+
717
+ if (ioctl(fd, TIOCMSET, &status) == -1)
718
+ {
719
+ rb_sys_fail(sIoctl);
720
+ }
721
+
722
+ return val;
723
+ }
724
+
725
+ VALUE sp_set_rts_impl(self, val)
726
+ VALUE self, val;
727
+ {
728
+ return set_signal_impl(self, val, TIOCM_RTS);
729
+ }
730
+
731
+ VALUE sp_set_dtr_impl(self, val)
732
+ VALUE self, val;
733
+ {
734
+ return set_signal_impl(self, val, TIOCM_DTR);
735
+ }
736
+
737
+ VALUE sp_get_rts_impl(self)
738
+ VALUE self;
739
+ {
740
+ struct line_signals ls;
741
+
742
+ get_line_signals_helper_impl(self, &ls);
743
+ return INT2FIX(ls.rts);
744
+ }
745
+
746
+ VALUE sp_get_dtr_impl(self)
747
+ VALUE self;
748
+ {
749
+ struct line_signals ls;
750
+
751
+ get_line_signals_helper_impl(self, &ls);
752
+
753
+ return INT2FIX(ls.dtr);
754
+ }
755
+
756
+ VALUE sp_flush_input_data_impl(self)
757
+ VALUE self;
758
+ {
759
+ int fd;
760
+ int ret;
761
+
762
+ fd = get_fd_helper(self);
763
+
764
+ ret = tcflush(fd, TCIFLUSH);
765
+ if(ret<0) {
766
+ return Qfalse;
767
+ }
768
+
769
+ return Qtrue;
770
+ }
771
+
772
+ VALUE sp_flush_output_data_impl(self)
773
+ VALUE self;
774
+ {
775
+ int fd;
776
+ int ret;
777
+
778
+ fd = get_fd_helper(self);
779
+
780
+ ret = tcflush(fd, TCOFLUSH);
781
+ if(ret<0) {
782
+ return Qfalse;
783
+ }
784
+
785
+ return Qtrue;
786
+ }
787
+
788
+
789
+
790
+ #endif /* !defined(OS_MSWIN) && !defined(OS_BCCWIN) && !defined(OS_MINGW) */