ruby-serialport 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,25 @@
1
+ require "../serialport.so"
2
+
3
+
4
+ if ARGV.size < 4
5
+ STDERR.print <<EOF
6
+ Usage: ruby #{$0} num_port bps nbits stopb
7
+ EOF
8
+ exit(1)
9
+ end
10
+
11
+ sp = SerialPort.new(ARGV[0].to_i, ARGV[1].to_i, ARGV[2].to_i, ARGV[3].to_i, SerialPort::NONE)
12
+
13
+ open("/dev/tty", "r+") { |tty|
14
+ tty.sync = true
15
+ Thread.new {
16
+ while true do
17
+ tty.printf("%c", sp.getc)
18
+ end
19
+ }
20
+ while (l = tty.gets) do
21
+ sp.write(l.sub("\n", "\r"))
22
+ end
23
+ }
24
+
25
+ sp.close
@@ -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')
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,661 @@
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 <stdio.h> /* Standard input/output definitions */
20
+ #include <unistd.h> /* UNIX standard function definitions */
21
+ #include <fcntl.h> /* File control definitions */
22
+ #include <errno.h> /* Error number definitions */
23
+ #include <termios.h> /* POSIX terminal control definitions */
24
+ #include <sys/ioctl.h>
25
+
26
+ #ifdef CRTSCTS
27
+ #define HAVE_FLOWCONTROL_HARD 1
28
+ #else
29
+ #undef HAVE_FLOWCONTROL_HARD
30
+ #endif
31
+
32
+
33
+ static char sTcgetattr[] = "tcgetattr";
34
+ static char sTcsetattr[] = "tcsetattr";
35
+ static char sIoctl[] = "ioctl";
36
+
37
+
38
+ static int get_fd_helper(obj)
39
+ VALUE obj;
40
+ {
41
+ OpenFile *fptr;
42
+
43
+ GetOpenFile(obj, fptr);
44
+ return (fileno(fptr->f));
45
+ }
46
+
47
+ static VALUE sp_create_impl(class, _port)
48
+ VALUE class, _port;
49
+ {
50
+ OpenFile *fp;
51
+ int fd;
52
+ int num_port;
53
+ char *port;
54
+ char *ports[] = {
55
+ #if defined(OS_LINUX) || defined(OS_CYGWIN)
56
+ "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3",
57
+ "/dev/ttyS4", "/dev/ttyS5", "/dev/ttyS6", "/dev/ttyS7"
58
+ #elif defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DARWIN)
59
+ "/dev/cuaa0", "/dev/cuaa1", "/dev/cuaa2", "/dev/cuaa3",
60
+ "/dev/cuaa4", "/dev/cuaa5", "/dev/cuaa6", "/dev/cuaa7"
61
+ #elif defined(OS_SOLARIS)
62
+ "/dev/ttya", "/dev/ttyb", "/dev/ttyc", "/dev/ttyd",
63
+ "/dev/ttye", "/dev/ttyf", "/dev/ttyg", "/dev/ttyh"
64
+ #elif defined(OS_AIX)
65
+ "/dev/tty0", "/dev/tty1", "/dev/tty2", "/dev/tty3",
66
+ "/dev/tty4", "/dev/tty5", "/dev/tty6", "/dev/tty7"
67
+ #elif defined(OS_IRIX)
68
+ "/dev/ttyf1", "/dev/ttyf2", "/dev/ttyf3", "/dev/ttyf4",
69
+ "/dev/ttyf5", "/dev/ttyf6", "/dev/ttyf7", "/dev/ttyf8"
70
+ #endif
71
+ };
72
+ struct termios params;
73
+
74
+ NEWOBJ(sp, struct RFile);
75
+ rb_secure(4);
76
+ OBJSETUP(sp, class, T_FILE);
77
+ MakeOpenFile((VALUE) sp, fp);
78
+
79
+ switch(TYPE(_port))
80
+ {
81
+ case T_FIXNUM:
82
+ num_port = FIX2INT(_port);
83
+ if (num_port < 0 || num_port > sizeof(ports) / sizeof(ports[0]))
84
+ {
85
+ rb_raise(rb_eArgError, "illegal port number");
86
+ }
87
+ port = ports[num_port];
88
+ break;
89
+
90
+ case T_STRING:
91
+ Check_SafeStr(_port);
92
+ port = RSTRING(_port)->ptr;
93
+ break;
94
+
95
+ default:
96
+ rb_raise(rb_eTypeError, "wrong argument type");
97
+ break;
98
+ }
99
+
100
+ fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
101
+ if (fd == -1)
102
+ {
103
+ rb_sys_fail(port);
104
+ }
105
+
106
+ if (!isatty(fd))
107
+ {
108
+ close(fd);
109
+ rb_raise(rb_eArgError, "not a serial port");
110
+ }
111
+
112
+ /* enable blocking read */
113
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
114
+
115
+ if (tcgetattr(fd, &params) == -1)
116
+ {
117
+ close(fd);
118
+ rb_sys_fail(sTcgetattr);
119
+ }
120
+
121
+ params.c_oflag = 0;
122
+ params.c_lflag = 0;
123
+ params.c_iflag &= (IXON | IXOFF | IXANY);
124
+ params.c_cflag |= CLOCAL | CREAD;
125
+ params.c_cflag &= ~HUPCL;
126
+
127
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
128
+ {
129
+ close(fd);
130
+ rb_sys_fail(sTcsetattr);
131
+ }
132
+
133
+ fp->f = rb_fdopen(fd, "r+");
134
+ fp->mode = FMODE_READWRITE | FMODE_SYNC;
135
+
136
+ return (VALUE) sp;
137
+ }
138
+
139
+ static VALUE sp_set_modem_params_impl(argc, argv, self)
140
+ int argc;
141
+ VALUE *argv, self;
142
+ {
143
+ int fd;
144
+ struct termios params;
145
+ VALUE _data_rate, _data_bits, _parity, _stop_bits;
146
+ int use_hash = 0;
147
+ int data_rate, data_bits;
148
+ _data_rate = _data_bits = _parity = _stop_bits = Qnil;
149
+
150
+ if (argc == 0)
151
+ {
152
+ return self;
153
+ }
154
+
155
+ if (argc == 1 && T_HASH == TYPE(argv[0]))
156
+ {
157
+ use_hash = 1;
158
+ _data_rate = rb_hash_aref(argv[0], sBaud);
159
+ _data_bits = rb_hash_aref(argv[0], sDataBits);
160
+ _stop_bits = rb_hash_aref(argv[0], sStopBits);
161
+ _parity = rb_hash_aref(argv[0], sParity);
162
+ }
163
+
164
+ fd = get_fd_helper(self);
165
+ if (tcgetattr(fd, &params) == -1)
166
+ {
167
+ rb_sys_fail(sTcgetattr);
168
+ }
169
+
170
+ if (!use_hash)
171
+ {
172
+ _data_rate = argv[0];
173
+ }
174
+
175
+ if (NIL_P(_data_rate))
176
+ {
177
+ goto SkipDataRate;
178
+ }
179
+ Check_Type(_data_rate, T_FIXNUM);
180
+
181
+ switch(FIX2INT(_data_rate))
182
+ {
183
+ case 50: data_rate = B50; break;
184
+ case 75: data_rate = B75; break;
185
+ case 110: data_rate = B110; break;
186
+ case 134: data_rate = B134; break;
187
+ case 150: data_rate = B150; break;
188
+ case 200: data_rate = B200; break;
189
+ case 300: data_rate = B300; break;
190
+ case 600: data_rate = B600; break;
191
+ case 1200: data_rate = B1200; break;
192
+ case 1800: data_rate = B1800; break;
193
+ case 2400: data_rate = B2400; break;
194
+ case 4800: data_rate = B4800; break;
195
+ case 9600: data_rate = B9600; break;
196
+ case 19200: data_rate = B19200; break;
197
+ case 38400: data_rate = B38400; break;
198
+ #ifdef B57600
199
+ case 57600: data_rate = B57600; break;
200
+ #endif
201
+ #ifdef B76800
202
+ case 76800: data_rate = B76800; break;
203
+ #endif
204
+ #ifdef B115200
205
+ case 115200: data_rate = B115200; break;
206
+ #endif
207
+ #ifdef B230400
208
+ case 230400: data_rate = B230400; break;
209
+ #endif
210
+
211
+ default:
212
+ rb_raise(rb_eArgError, "unknown baud rate");
213
+ break;
214
+ }
215
+ cfsetispeed(&params, data_rate);
216
+ cfsetospeed(&params, data_rate);
217
+
218
+ SkipDataRate:
219
+
220
+ if (!use_hash)
221
+ {
222
+ _data_bits = (argc >= 2 ? argv[1] : INT2FIX(8));
223
+ }
224
+
225
+ if (NIL_P(_data_bits))
226
+ {
227
+ goto SkipDataBits;
228
+ }
229
+ Check_Type(_data_bits, T_FIXNUM);
230
+
231
+ switch(FIX2INT(_data_bits))
232
+ {
233
+ case 5:
234
+ data_bits = CS5;
235
+ break;
236
+ case 6:
237
+ data_bits = CS6;
238
+ break;
239
+ case 7:
240
+ data_bits = CS7;
241
+ break;
242
+ case 8:
243
+ data_bits = CS8;
244
+ break;
245
+ default:
246
+ rb_raise(rb_eArgError, "unknown character size");
247
+ break;
248
+ }
249
+ params.c_cflag &= ~CSIZE;
250
+ params.c_cflag |= data_bits;
251
+
252
+ SkipDataBits:
253
+
254
+ if (!use_hash)
255
+ {
256
+ _stop_bits = (argc >= 3 ? argv[2] : INT2FIX(1));
257
+ }
258
+
259
+ if (NIL_P(_stop_bits))
260
+ {
261
+ goto SkipStopBits;
262
+ }
263
+
264
+ Check_Type(_stop_bits, T_FIXNUM);
265
+
266
+ switch(FIX2INT(_stop_bits))
267
+ {
268
+ case 1:
269
+ params.c_cflag &= ~CSTOPB;
270
+ break;
271
+ case 2:
272
+ params.c_cflag |= CSTOPB;
273
+ break;
274
+ default:
275
+ rb_raise(rb_eArgError, "unknown number of stop bits");
276
+ break;
277
+ }
278
+
279
+ SkipStopBits:
280
+
281
+ if (!use_hash)
282
+ {
283
+ _parity = (argc >= 4 ? argv[3] : ((params.c_cflag & CSIZE) == CS8 ?
284
+ INT2FIX(NONE) : INT2FIX(EVEN)));
285
+ }
286
+
287
+ if (NIL_P(_parity))
288
+ {
289
+ goto SkipParity;
290
+ }
291
+
292
+ Check_Type(_parity, T_FIXNUM);
293
+
294
+ switch(FIX2INT(_parity))
295
+ {
296
+ case EVEN:
297
+ params.c_cflag |= PARENB;
298
+ params.c_cflag &= ~PARODD;
299
+ break;
300
+
301
+ case ODD:
302
+ params.c_cflag |= PARENB;
303
+ params.c_cflag |= PARODD;
304
+ break;
305
+
306
+ case NONE:
307
+ params.c_cflag &= ~PARENB;
308
+ break;
309
+
310
+ default:
311
+ rb_raise(rb_eArgError, "unknown parity");
312
+ break;
313
+ }
314
+
315
+ SkipParity:
316
+
317
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
318
+ {
319
+ rb_sys_fail(sTcsetattr);
320
+ }
321
+ return argv[0];
322
+ }
323
+
324
+ static void get_modem_params_impl(self, mp)
325
+ VALUE self;
326
+ struct modem_params *mp;
327
+ {
328
+ int fd;
329
+ struct termios params;
330
+
331
+ fd = get_fd_helper(self);
332
+ if (tcgetattr(fd, &params) == -1)
333
+ {
334
+ rb_sys_fail(sTcgetattr);
335
+ }
336
+
337
+ switch (cfgetospeed(&params))
338
+ {
339
+ case B50: mp->data_rate = 50; break;
340
+ case B75: mp->data_rate = 75; break;
341
+ case B110: mp->data_rate = 110; break;
342
+ case B134: mp->data_rate = 134; break;
343
+ case B150: mp->data_rate = 150; break;
344
+ case B200: mp->data_rate = 200; break;
345
+ case B300: mp->data_rate = 300; break;
346
+ case B600: mp->data_rate = 600; break;
347
+ case B1200: mp->data_rate = 1200; break;
348
+ case B1800: mp->data_rate = 1800; break;
349
+ case B2400: mp->data_rate = 2400; break;
350
+ case B4800: mp->data_rate = 4800; break;
351
+ case B9600: mp->data_rate = 9600; break;
352
+ case B19200: mp->data_rate = 19200; break;
353
+ case B38400: mp->data_rate = 38400; break;
354
+ #ifdef B57600
355
+ case B57600: mp->data_rate = 57600; break;
356
+ #endif
357
+ #ifdef B76800
358
+ case B76800: mp->data_rate = 76800; break;
359
+ #endif
360
+ #ifdef B115200
361
+ case B115200: mp->data_rate = 115200; break;
362
+ #endif
363
+ #ifdef B230400
364
+ case B230400: mp->data_rate = 230400; break;
365
+ #endif
366
+ }
367
+
368
+ switch(params.c_cflag & CSIZE)
369
+ {
370
+ case CS5:
371
+ mp->data_bits = 5;
372
+ break;
373
+ case CS6:
374
+ mp->data_bits = 6;
375
+ break;
376
+ case CS7:
377
+ mp->data_bits = 7;
378
+ break;
379
+ case CS8:
380
+ mp->data_bits = 8;
381
+ break;
382
+ default:
383
+ mp->data_bits = 0;
384
+ break;
385
+ }
386
+
387
+ mp->stop_bits = (params.c_cflag & CSTOPB ? 2 : 1);
388
+
389
+ if (!(params.c_cflag & PARENB))
390
+ {
391
+ mp->parity = NONE;
392
+ }
393
+ else if (params.c_cflag & PARODD)
394
+ {
395
+ mp->parity = ODD;
396
+ }
397
+ else
398
+ {
399
+ mp->parity = EVEN;
400
+ }
401
+ }
402
+
403
+ static VALUE sp_set_flow_control_impl(self, val)
404
+ VALUE self, val;
405
+ {
406
+ int fd;
407
+ int flowc;
408
+ struct termios params;
409
+
410
+ Check_Type(val, T_FIXNUM);
411
+
412
+ fd = get_fd_helper(self);
413
+ if (tcgetattr(fd, &params) == -1)
414
+ {
415
+ rb_sys_fail(sTcgetattr);
416
+ }
417
+
418
+ flowc = FIX2INT(val);
419
+ if (flowc & HARD)
420
+ {
421
+ #ifdef HAVE_FLOWCONTROL_HARD
422
+ params.c_cflag |= CRTSCTS;
423
+ }
424
+ else
425
+ {
426
+ params.c_cflag &= ~CRTSCTS;
427
+ }
428
+ #else
429
+ rb_raise(rb_eIOError, "Hardware flow control not supported");
430
+ }
431
+ #endif
432
+
433
+ if (flowc & SOFT)
434
+ {
435
+ params.c_iflag |= (IXON | IXOFF | IXANY);
436
+ }
437
+ else
438
+ {
439
+ params.c_iflag &= ~(IXON | IXOFF | IXANY);
440
+ }
441
+
442
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
443
+ {
444
+ rb_sys_fail(sTcsetattr);
445
+ }
446
+
447
+ return val;
448
+ }
449
+
450
+ static VALUE sp_get_flow_control_impl(self)
451
+ VALUE self;
452
+ {
453
+ int ret;
454
+ int fd;
455
+ struct termios params;
456
+
457
+ fd = get_fd_helper(self);
458
+ if (tcgetattr(fd, &params) == -1)
459
+ {
460
+ rb_sys_fail(sTcgetattr);
461
+ }
462
+
463
+ ret = 0;
464
+
465
+ #ifdef HAVE_FLOWCONTROL_HARD
466
+ if (params.c_cflag & CRTSCTS)
467
+ {
468
+ ret += HARD;
469
+ }
470
+ #endif
471
+
472
+ if (params.c_iflag & (IXON | IXOFF | IXANY))
473
+ {
474
+ ret += SOFT;
475
+ }
476
+
477
+ return INT2FIX(ret);
478
+ }
479
+
480
+ static VALUE sp_set_read_timeout_impl(self, val)
481
+ VALUE self, val;
482
+ {
483
+ int timeout;
484
+ int fd;
485
+ struct termios params;
486
+
487
+ Check_Type(val, T_FIXNUM);
488
+ timeout = FIX2INT(val);
489
+
490
+ fd = get_fd_helper(self);
491
+ if (tcgetattr(fd, &params) == -1)
492
+ {
493
+ rb_sys_fail(sTcgetattr);
494
+ }
495
+
496
+ if (timeout < 0)
497
+ {
498
+ params.c_cc[VTIME] = 0;
499
+ params.c_cc[VMIN] = 0;
500
+ }
501
+ else if (timeout == 0)
502
+ {
503
+ params.c_cc[VTIME] = 0;
504
+ params.c_cc[VMIN] = 1;
505
+ }
506
+ else
507
+ {
508
+ params.c_cc[VTIME] = (timeout + 50) / 100;
509
+ params.c_cc[VMIN] = 0;
510
+ }
511
+
512
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
513
+ {
514
+ rb_sys_fail(sTcsetattr);
515
+ }
516
+
517
+ return val;
518
+ }
519
+
520
+ static VALUE sp_get_read_timeout_impl(self)
521
+ VALUE self;
522
+ {
523
+ int fd;
524
+ struct termios params;
525
+
526
+ fd = get_fd_helper(self);
527
+ if (tcgetattr(fd, &params) == -1)
528
+ {
529
+ rb_sys_fail(sTcgetattr);
530
+ }
531
+
532
+ if (params.c_cc[VTIME] == 0 && params.c_cc[VMIN] == 0)
533
+ {
534
+ return INT2FIX(-1);
535
+ }
536
+
537
+ return INT2FIX(params.c_cc[VTIME] * 100);
538
+ }
539
+
540
+ static VALUE sp_set_write_timeout_impl(self, val)
541
+ VALUE self, val;
542
+ {
543
+ rb_notimplement();
544
+ return self;
545
+ }
546
+
547
+ static VALUE sp_get_write_timeout_impl(self)
548
+ VALUE self;
549
+ {
550
+ rb_notimplement();
551
+ return self;
552
+ }
553
+
554
+ static VALUE sp_break_impl(self, time)
555
+ VALUE self, time;
556
+ {
557
+ int fd;
558
+
559
+ Check_Type(time, T_FIXNUM);
560
+
561
+ fd = get_fd_helper(self);
562
+
563
+ if (tcsendbreak(fd, FIX2INT(time) / 3) == -1)
564
+ {
565
+ rb_sys_fail("tcsendbreak");
566
+ }
567
+
568
+ return Qnil;
569
+ }
570
+
571
+ static void get_line_signals_helper_impl(obj, ls)
572
+ VALUE obj;
573
+ struct line_signals *ls;
574
+ {
575
+ int fd, status;
576
+
577
+ fd = get_fd_helper(obj);
578
+
579
+ if (ioctl(fd, TIOCMGET, &status) == -1)
580
+ {
581
+ rb_sys_fail(sIoctl);
582
+ }
583
+
584
+ ls->rts = (status & TIOCM_RTS ? 1 : 0);
585
+ ls->dtr = (status & TIOCM_DTR ? 1 : 0);
586
+ ls->cts = (status & TIOCM_CTS ? 1 : 0);
587
+ ls->dsr = (status & TIOCM_DSR ? 1 : 0);
588
+ ls->dcd = (status & TIOCM_CD ? 1 : 0);
589
+ ls->ri = (status & TIOCM_RI ? 1 : 0);
590
+ }
591
+
592
+ static VALUE set_signal_impl(obj, val, sig)
593
+ VALUE obj,val;
594
+ int sig;
595
+ {
596
+ int status;
597
+ int fd;
598
+ int set;
599
+
600
+ Check_Type(val, T_FIXNUM);
601
+ fd = get_fd_helper(obj);
602
+
603
+ if (ioctl(fd, TIOCMGET, &status) == -1)
604
+ {
605
+ rb_sys_fail(sIoctl);
606
+ }
607
+
608
+ set = FIX2INT(val);
609
+
610
+ if (set == 0)
611
+ {
612
+ status &= ~sig;
613
+ }
614
+ else if (set == 1)
615
+ {
616
+ status |= sig;
617
+ }
618
+ else
619
+ {
620
+ rb_raise(rb_eArgError, "invalid value");
621
+ }
622
+
623
+ if (ioctl(fd, TIOCMSET, &status) == -1)
624
+ {
625
+ rb_sys_fail(sIoctl);
626
+ }
627
+
628
+ return val;
629
+ }
630
+
631
+ static VALUE sp_set_rts_impl(self, val)
632
+ VALUE self, val;
633
+ {
634
+ return set_signal(self, val, TIOCM_RTS);
635
+ }
636
+
637
+ static VALUE sp_set_dtr_impl(self, val)
638
+ VALUE self, val;
639
+ {
640
+ return set_signal(self, val, TIOCM_DTR);
641
+ }
642
+
643
+ static VALUE sp_get_rts_impl(self)
644
+ VALUE self;
645
+ {
646
+ struct line_signals ls;
647
+
648
+ get_line_signals_helper(self, &ls);
649
+ return INT2FIX(ls.rts);
650
+ }
651
+
652
+ static VALUE sp_get_dtr_impl(self)
653
+ VALUE self;
654
+ {
655
+ struct line_signals ls;
656
+
657
+ get_line_signals_helper(self, &ls);
658
+
659
+ return INT2FIX(ls.dtr);
660
+ }
661
+