rmodbus 0.1.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/AUTHORS CHANGED
@@ -1,3 +1,2 @@
1
1
  Timin Aleksey
2
-
3
- Dilshod Samatov
2
+ James Sanders
data/CHANGES CHANGED
@@ -1,2 +1,8 @@
1
1
  2008-25-01 Release-0.1.1
2
2
  - fixed bug in function "read discrete inputs (0x2)" of ModBus client
3
+
4
+ 2009-30-01 Release-0.2
5
+ - add ModBus-TCP server
6
+ - add retries for tcp connection and read, default of 10 retries, still 1 second timeout
7
+ - fix typos
8
+
data/README CHANGED
File without changes
data/ext/extconf.rb ADDED
@@ -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 += " -D#{os}"
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")
data/ext/serialport.c ADDED
@@ -0,0 +1,1312 @@
1
+ /* Ruby/SerialPort $Id: serialport.c,v 1.15 2003/02/13 19:55:48 moumar Exp $
2
+ * Guillaume Pierronnet <moumar@netcourrier.com>
3
+ * Alan Stern <stern@rowland.harvard.edu>
4
+ *
5
+ * This code is hereby licensed for public consumption under either the
6
+ * GNU GPL v2 or greater.
7
+ *
8
+ * You should have received a copy of the GNU General Public License
9
+ * along with this program; if not, write to the Free Software
10
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
11
+ *
12
+ * For documentation on serial programming, see the excellent:
13
+ * "Serial Programming Guide for POSIX Operating Systems"
14
+ * written Michael R. Sweet.
15
+ * http://www.easysw.com/~mike/serial/
16
+ */
17
+
18
+ #define VERSION "0.6"
19
+
20
+ #include <ruby.h> /* ruby inclusion */
21
+ #include <rubyio.h> /* ruby io inclusion */
22
+
23
+ struct modem_params {
24
+ int data_rate;
25
+ int data_bits;
26
+ int stop_bits;
27
+ int parity;
28
+ };
29
+
30
+ struct line_signals {
31
+ int rts;
32
+ int dtr;
33
+ int cts;
34
+ int dsr;
35
+ int dcd;
36
+ int ri;
37
+ };
38
+
39
+ VALUE cSerialPort; /* serial port class */
40
+
41
+ static VALUE sBaud, sDataBits, sStopBits, sParity; /* strings */
42
+ static VALUE sRts, sDtr, sCts, sDsr, sDcd, sRi;
43
+
44
+
45
+ #if defined(mswin) || defined(bccwin)
46
+
47
+
48
+ #include <stdio.h> /* Standard input/output definitions */
49
+ #include <io.h> /* Low-level I/O definitions */
50
+ #include <fcntl.h> /* File control definitions */
51
+ #include <windows.h> /* Windows standard function definitions */
52
+
53
+ #define NONE 0
54
+ #define HARD 1
55
+ #define SOFT 2
56
+
57
+ #define SPACE SPACEPARITY
58
+ #define MARK MARKPARITY
59
+ #define EVEN EVENPARITY
60
+ #define ODD ODDPARITY
61
+
62
+ static char sGetCommState[] = "GetCommState";
63
+ static char sSetCommState[] = "SetCommState";
64
+ static char sGetCommTimeouts[] = "GetCommTimeouts";
65
+ static char sSetCommTimeouts[] = "SetCommTimeouts";
66
+
67
+
68
+ static HANDLE sp_get_handle(obj)
69
+ VALUE obj;
70
+ {
71
+ OpenFile *fptr;
72
+
73
+ GetOpenFile(obj, fptr);
74
+ return (HANDLE) _get_osfhandle(fileno(fptr->f));
75
+ }
76
+
77
+ static VALUE sp_create(class, _port)
78
+ VALUE class, _port;
79
+ {
80
+ OpenFile *fp;
81
+ int fd;
82
+ HANDLE fh;
83
+ int num_port;
84
+ char *port;
85
+ char *ports[] = {
86
+ "COM1", "COM2", "COM3", "COM4",
87
+ "COM5", "COM6", "COM7", "COM8"
88
+ };
89
+ DCB dcb;
90
+
91
+ NEWOBJ(sp, struct RFile);
92
+ rb_secure(4);
93
+ OBJSETUP(sp, class, T_FILE);
94
+ MakeOpenFile(sp, fp);
95
+
96
+ switch(TYPE(_port)) {
97
+ case T_FIXNUM:
98
+ num_port = FIX2INT(_port);
99
+ if (num_port < 0 || num_port > sizeof(ports) / sizeof(ports[0]))
100
+ rb_raise(rb_eArgError, "illegal port number");
101
+ port = ports[num_port];
102
+ break;
103
+
104
+ case T_STRING:
105
+ Check_SafeStr(_port);
106
+ port = RSTRING(_port)->ptr;
107
+ break;
108
+
109
+ default:
110
+ rb_raise(rb_eTypeError, "wrong argument type");
111
+ break;
112
+ }
113
+
114
+ fd = open(port, O_BINARY | O_RDWR);
115
+ if (fd == -1)
116
+ rb_sys_fail(port);
117
+ fh = (HANDLE) _get_osfhandle(fd);
118
+ if (SetupComm(fh, 1024, 1024) == 0) {
119
+ close(fd);
120
+ rb_raise(rb_eArgError, "not a serial port");
121
+ }
122
+
123
+ dcb.DCBlength = sizeof(dcb);
124
+ if (GetCommState(fh, &dcb) == 0) {
125
+ close(fd);
126
+ rb_sys_fail(sGetCommState);
127
+ }
128
+ dcb.fBinary = TRUE;
129
+ dcb.fParity = FALSE;
130
+ dcb.fOutxDsrFlow = FALSE;
131
+ dcb.fDtrControl = DTR_CONTROL_ENABLE;
132
+ dcb.fDsrSensitivity = FALSE;
133
+ dcb.fTXContinueOnXoff = FALSE;
134
+ dcb.fErrorChar = FALSE;
135
+ dcb.fNull = FALSE;
136
+ dcb.fAbortOnError = FALSE;
137
+ dcb.XonChar = 17;
138
+ dcb.XoffChar = 19;
139
+ if (SetCommState(fh, &dcb) == 0) {
140
+ close(fd);
141
+ rb_sys_fail(sSetCommState);
142
+ }
143
+
144
+ fp->f = rb_fdopen(fd, "rb+");
145
+ fp->mode = FMODE_READWRITE | FMODE_BINMODE | FMODE_SYNC;
146
+ return (VALUE) sp;
147
+ }
148
+
149
+ static VALUE sp_set_modem_params(argc, argv, self)
150
+ int argc;
151
+ VALUE *argv, self;
152
+ {
153
+ HANDLE fh;
154
+ DCB dcb;
155
+ VALUE _data_rate, _data_bits, _parity, _stop_bits;
156
+ int use_hash = 0;
157
+ int data_rate, data_bits, parity;
158
+
159
+ if (argc == 0)
160
+ return self;
161
+ if (argc == 1 && T_HASH == TYPE(argv[0])) {
162
+ use_hash = 1;
163
+ _data_rate = rb_hash_aref(argv[0], sBaud);
164
+ _data_bits = rb_hash_aref(argv[0], sDataBits);
165
+ _stop_bits = rb_hash_aref(argv[0], sStopBits);
166
+ _parity = rb_hash_aref(argv[0], sParity);
167
+ }
168
+
169
+ fh = sp_get_handle(self);
170
+ dcb.DCBlength = sizeof(dcb);
171
+ if (GetCommState(fh, &dcb) == 0)
172
+ rb_sys_fail(sGetCommState);
173
+
174
+ if (!use_hash)
175
+ _data_rate = argv[0];
176
+ if (NIL_P(_data_rate))
177
+ goto SkipDataRate;
178
+ Check_Type(_data_rate, T_FIXNUM);
179
+
180
+ data_rate = FIX2INT(_data_rate);
181
+ switch (data_rate) {
182
+ case 110:
183
+ case 300:
184
+ case 600:
185
+ case 1200:
186
+ case 2400:
187
+ case 4800:
188
+ case 9600:
189
+ case 14400:
190
+ case 19200:
191
+ case 38400:
192
+ case 56000:
193
+ case 57600:
194
+ case 115200:
195
+ case 128000:
196
+ case 256000:
197
+ dcb.BaudRate = data_rate;
198
+ break;
199
+
200
+ default:
201
+ rb_raise(rb_eArgError, "unknown baud rate");
202
+ break;
203
+ }
204
+ SkipDataRate:
205
+
206
+ if (!use_hash)
207
+ _data_bits = (argc >= 2 ? argv[1] : INT2FIX(8));
208
+ if (NIL_P(_data_bits))
209
+ goto SkipDataBits;
210
+ Check_Type(_data_bits, T_FIXNUM);
211
+
212
+ data_bits = FIX2INT(_data_bits);
213
+ if (4 <= data_bits && data_bits <= 8)
214
+ dcb.ByteSize = data_bits;
215
+ else
216
+ rb_raise(rb_eArgError, "unknown character size");
217
+ SkipDataBits:
218
+
219
+ if (!use_hash)
220
+ _stop_bits = (argc >= 3 ? argv[2] : INT2FIX(1));
221
+ if (NIL_P(_stop_bits))
222
+ goto SkipStopBits;
223
+ Check_Type(_stop_bits, T_FIXNUM);
224
+
225
+ switch (FIX2INT(_stop_bits)) {
226
+ case 1:
227
+ dcb.StopBits = ONESTOPBIT;
228
+ break;
229
+ case 2:
230
+ dcb.StopBits = TWOSTOPBITS;
231
+ break;
232
+ default:
233
+ rb_raise(rb_eArgError, "unknown number of stop bits");
234
+ break;
235
+ }
236
+ SkipStopBits:
237
+
238
+ if (!use_hash)
239
+ _parity = (argc >= 4 ? argv[3] : (dcb.ByteSize == 8 ?
240
+ INT2FIX(NOPARITY) : INT2FIX(EVENPARITY)));
241
+ if (NIL_P(_parity))
242
+ goto SkipParity;
243
+ Check_Type(_parity, T_FIXNUM);
244
+
245
+ parity = FIX2INT(_parity);
246
+ switch (parity) {
247
+ case EVENPARITY:
248
+ case ODDPARITY:
249
+ case MARKPARITY:
250
+ case SPACEPARITY:
251
+ case NOPARITY:
252
+ dcb.Parity = parity;
253
+ break;
254
+
255
+ default:
256
+ rb_raise(rb_eArgError, "unknown parity");
257
+ break;
258
+ }
259
+ SkipParity:
260
+
261
+ if (SetCommState(fh, &dcb) == 0)
262
+ rb_sys_fail(sSetCommState);
263
+ return self;
264
+ }
265
+
266
+ static void get_modem_params(self, mp)
267
+ VALUE self;
268
+ struct modem_params *mp;
269
+ {
270
+ HANDLE fh;
271
+ DCB dcb;
272
+
273
+ fh = sp_get_handle(self);
274
+ dcb.DCBlength = sizeof(dcb);
275
+ if (GetCommState(fh, &dcb) == 0)
276
+ rb_sys_fail(sGetCommState);
277
+
278
+ mp->data_rate = dcb.BaudRate;
279
+ mp->data_bits = dcb.ByteSize;
280
+ mp->stop_bits = (dcb.StopBits == ONESTOPBIT ? 1 : 2);
281
+ mp->parity = dcb.Parity;
282
+ }
283
+
284
+ static VALUE sp_set_flow_control(self, val)
285
+ VALUE self, val;
286
+ {
287
+ HANDLE fh;
288
+ int flowc;
289
+ DCB dcb;
290
+
291
+ Check_Type(val, T_FIXNUM);
292
+
293
+ fh = sp_get_handle(self);
294
+ dcb.DCBlength = sizeof(dcb);
295
+ if (GetCommState(fh, &dcb) == 0)
296
+ rb_sys_fail(sGetCommState);
297
+
298
+ flowc = FIX2INT(val);
299
+ if (flowc & HARD) {
300
+ dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
301
+ dcb.fOutxCtsFlow = TRUE;
302
+ } else {
303
+ dcb.fRtsControl = RTS_CONTROL_ENABLE;
304
+ dcb.fOutxCtsFlow = FALSE;
305
+ }
306
+ if (flowc & SOFT)
307
+ dcb.fOutX = dcb.fInX = TRUE;
308
+ else
309
+ dcb.fOutX = dcb.fInX = FALSE;
310
+
311
+ if (SetCommState(fh, &dcb) == 0)
312
+ rb_sys_fail(sSetCommState);
313
+ return self;
314
+ }
315
+
316
+ static VALUE sp_get_flow_control(self)
317
+ VALUE self;
318
+ {
319
+ HANDLE fh;
320
+ int ret;
321
+ DCB dcb;
322
+
323
+ fh = sp_get_handle(self);
324
+ dcb.DCBlength = sizeof(dcb);
325
+ if (GetCommState(fh, &dcb) == 0)
326
+ rb_sys_fail(sGetCommState);
327
+
328
+ ret = 0;
329
+ if (dcb.fOutxCtsFlow)
330
+ ret += HARD;
331
+ if (dcb.fOutX)
332
+ ret += SOFT;
333
+
334
+ return INT2FIX(ret);
335
+ }
336
+
337
+ static VALUE sp_set_read_timeout(self, val)
338
+ VALUE self, val;
339
+ {
340
+ int timeout;
341
+ HANDLE fh;
342
+ COMMTIMEOUTS ctout;
343
+
344
+ Check_Type(val, T_FIXNUM);
345
+ timeout = FIX2INT(val);
346
+
347
+ fh = sp_get_handle(self);
348
+ if (GetCommTimeouts(fh, &ctout) == 0)
349
+ rb_sys_fail(sGetCommTimeouts);
350
+
351
+ if (timeout < 0) {
352
+ ctout.ReadIntervalTimeout = MAXDWORD;
353
+ ctout.ReadTotalTimeoutMultiplier = 0;
354
+ ctout.ReadTotalTimeoutConstant = 0;
355
+ } else if (timeout == 0) {
356
+ ctout.ReadIntervalTimeout = MAXDWORD;
357
+ ctout.ReadTotalTimeoutMultiplier = MAXDWORD;
358
+ ctout.ReadTotalTimeoutConstant = MAXDWORD - 1;
359
+ } else {
360
+ ctout.ReadIntervalTimeout = timeout;
361
+ ctout.ReadTotalTimeoutMultiplier = 0;
362
+ ctout.ReadTotalTimeoutConstant = timeout;
363
+ }
364
+
365
+ if (SetCommTimeouts(fh, &ctout) == 0)
366
+ rb_sys_fail(sSetCommTimeouts);
367
+ return self;
368
+ }
369
+
370
+ static VALUE sp_get_read_timeout(self)
371
+ VALUE self;
372
+ {
373
+ HANDLE fh;
374
+ COMMTIMEOUTS ctout;
375
+
376
+ fh = sp_get_handle(self);
377
+ if (GetCommTimeouts(fh, &ctout) == 0)
378
+ rb_sys_fail(sGetCommTimeouts);
379
+ switch (ctout.ReadTotalTimeoutConstant) {
380
+ case 0:
381
+ return INT2FIX(-1);
382
+ case MAXDWORD:
383
+ return INT2FIX(0);
384
+ }
385
+ return INT2FIX(ctout.ReadTotalTimeoutConstant);
386
+ }
387
+
388
+ static VALUE sp_set_write_timeout(self, val)
389
+ VALUE self, val;
390
+ {
391
+ int timeout;
392
+ HANDLE fh;
393
+ COMMTIMEOUTS ctout;
394
+
395
+ Check_Type(val, T_FIXNUM);
396
+ timeout = FIX2INT(val);
397
+
398
+ fh = sp_get_handle(self);
399
+ if (GetCommTimeouts(fh, &ctout) == 0)
400
+ rb_sys_fail(sGetCommTimeouts);
401
+
402
+ if (timeout <= 0) {
403
+ ctout.WriteTotalTimeoutMultiplier = 0;
404
+ ctout.WriteTotalTimeoutConstant = 0;
405
+ } else {
406
+ ctout.WriteTotalTimeoutMultiplier = timeout;
407
+ ctout.WriteTotalTimeoutConstant = 0;
408
+ }
409
+
410
+ if (SetCommTimeouts(fh, &ctout) == 0)
411
+ rb_sys_fail(sSetCommTimeouts);
412
+ return self;
413
+ }
414
+
415
+ static VALUE sp_get_write_timeout(self)
416
+ VALUE self;
417
+ {
418
+ HANDLE fh;
419
+ COMMTIMEOUTS ctout;
420
+
421
+ fh = sp_get_handle(self);
422
+ if (GetCommTimeouts(fh, &ctout) == 0)
423
+ rb_sys_fail(sGetCommTimeouts);
424
+ return INT2FIX(ctout.WriteTotalTimeoutMultiplier);
425
+ }
426
+
427
+ static void delay_ms(time)
428
+ int time;
429
+ {
430
+ HANDLE ev;
431
+
432
+ ev = CreateEvent(NULL, FALSE, FALSE, NULL);
433
+ if (!ev)
434
+ rb_sys_fail("CreateEvent");
435
+ if (WaitForSingleObject(ev, time) == WAIT_FAILED)
436
+ rb_sys_fail("WaitForSingleObject");
437
+ CloseHandle(ev);
438
+ }
439
+
440
+ static VALUE sp_break(self, time)
441
+ VALUE self, time;
442
+ {
443
+ HANDLE fh;
444
+
445
+ Check_Type(time, T_FIXNUM);
446
+
447
+ fh = sp_get_handle(self);
448
+ if (SetCommBreak(fh) == 0)
449
+ rb_sys_fail("SetCommBreak");
450
+ delay_ms(FIX2INT(time) * 100);
451
+ ClearCommBreak(fh);
452
+ return Qnil;
453
+ }
454
+
455
+ static void get_line_signals(obj, ls)
456
+ VALUE obj;
457
+ struct line_signals *ls;
458
+ {
459
+ HANDLE fh;
460
+ int status;
461
+
462
+ fh = sp_get_handle(obj);
463
+ if (GetCommModemStatus(fh, &status) == 0)
464
+ rb_sys_fail("GetCommModemStatus");
465
+
466
+ ls->cts = (status & MS_CTS_ON ? 1 : 0);
467
+ ls->dsr = (status & MS_DSR_ON ? 1 : 0);
468
+ ls->dcd = (status & MS_RLSD_ON ? 1 : 0);
469
+ ls->ri = (status & MS_RING_ON ? 1 : 0);
470
+ }
471
+
472
+ static VALUE set_signal(obj, val, sigoff, sigon)
473
+ VALUE obj,val;
474
+ int sigoff, sigon;
475
+ {
476
+ HANDLE fh;
477
+ int set, sig;
478
+
479
+ Check_Type(val, T_FIXNUM);
480
+ fh = sp_get_handle(obj);
481
+
482
+ set = FIX2INT(val);
483
+ if (set == 0)
484
+ sig = sigoff;
485
+ else if (set == 1)
486
+ sig = sigon;
487
+ else
488
+ rb_raise(rb_eArgError, "invalid value");
489
+
490
+ if (EscapeCommFunction(fh, sig) == 0)
491
+ rb_sys_fail("EscapeCommFunction");
492
+ return obj;
493
+ }
494
+
495
+ static VALUE sp_set_rts(self, val)
496
+ VALUE self, val;
497
+ {
498
+ return set_signal(self, val, CLRRTS, SETRTS);
499
+ }
500
+
501
+ static VALUE sp_set_dtr(self, val)
502
+ VALUE self, val;
503
+ {
504
+ return set_signal(self, val, CLRDTR, SETDTR);
505
+ }
506
+
507
+ static VALUE sp_get_rts(self)
508
+ VALUE self;
509
+ {
510
+ rb_notimplement();
511
+ return self;
512
+ }
513
+
514
+ static VALUE sp_get_dtr(self)
515
+ VALUE self;
516
+ {
517
+ rb_notimplement();
518
+ return self;
519
+ }
520
+
521
+
522
+ #else /* defined(mswin) || defined(bccwin) */
523
+
524
+
525
+ #include <stdio.h> /* Standard input/output definitions */
526
+ #include <unistd.h> /* UNIX standard function definitions */
527
+ #include <fcntl.h> /* File control definitions */
528
+ #include <errno.h> /* Error number definitions */
529
+ #include <termios.h> /* POSIX terminal control definitions */
530
+ #include <sys/ioctl.h>
531
+
532
+ #ifdef CRTSCTS
533
+ #define HAVE_FLOWCONTROL_HARD 1
534
+ #else
535
+ #undef HAVE_FLOWCONTROL_HARD
536
+ #endif
537
+
538
+ #define NONE 0
539
+ #define HARD 1
540
+ #define SOFT 2
541
+
542
+ #define SPACE 0
543
+ #define MARK 0
544
+ #define EVEN 1
545
+ #define ODD 2
546
+
547
+ static char sTcgetattr[] = "tcgetattr";
548
+ static char sTcsetattr[] = "tcsetattr";
549
+ static char sIoctl[] = "ioctl";
550
+
551
+
552
+ static int sp_get_fd(obj)
553
+ VALUE obj;
554
+ {
555
+ OpenFile *fptr;
556
+
557
+ GetOpenFile(obj, fptr);
558
+ return (fileno(fptr->f));
559
+ }
560
+
561
+ static VALUE sp_create(class, _port)
562
+ VALUE class, _port;
563
+ {
564
+ OpenFile *fp;
565
+ int fd;
566
+ int num_port;
567
+ char *port;
568
+ char *ports[] = {
569
+ #if defined(linux) || defined(cygwin)
570
+ "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3",
571
+ "/dev/ttyS4", "/dev/ttyS5", "/dev/ttyS6", "/dev/ttyS7"
572
+ #elif defined(freebsd) || defined(netbsd) || defined(openbsd)
573
+ "/dev/cuaa0", "/dev/cuaa1", "/dev/cuaa2", "/dev/cuaa3",
574
+ "/dev/cuaa4", "/dev/cuaa5", "/dev/cuaa6", "/dev/cuaa7"
575
+ #elif defined(solaris)
576
+ "/dev/ttya", "/dev/ttyb", "/dev/ttyc", "/dev/ttyd",
577
+ "/dev/ttye", "/dev/ttyf", "/dev/ttyg", "/dev/ttyh"
578
+ #elif defined(aix)
579
+ "/dev/tty0", "/dev/tty1", "/dev/tty2", "/dev/tty3",
580
+ "/dev/tty4", "/dev/tty5", "/dev/tty6", "/dev/tty7"
581
+ #elif defined(irix)
582
+ "/dev/ttyf1", "/dev/ttyf2", "/dev/ttyf3", "/dev/ttyf4",
583
+ "/dev/ttyf5", "/dev/ttyf6", "/dev/ttyf7", "/dev/ttyf8"
584
+ #endif
585
+ };
586
+ struct termios params;
587
+
588
+ NEWOBJ(sp, struct RFile);
589
+ rb_secure(4);
590
+ OBJSETUP(sp, class, T_FILE);
591
+ MakeOpenFile(sp, fp);
592
+
593
+ switch(TYPE(_port)) {
594
+ case T_FIXNUM:
595
+ num_port = FIX2INT(_port);
596
+ if (num_port < 0 || num_port > sizeof(ports) / sizeof(ports[0]))
597
+ rb_raise(rb_eArgError, "illegal port number");
598
+ port = ports[num_port];
599
+ break;
600
+
601
+ case T_STRING:
602
+ Check_SafeStr(_port);
603
+ port = RSTRING(_port)->ptr;
604
+ break;
605
+
606
+ default:
607
+ rb_raise(rb_eTypeError, "wrong argument type");
608
+ break;
609
+ }
610
+
611
+ fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
612
+ if (fd == -1)
613
+ rb_sys_fail(port);
614
+ if (!isatty(fd)) {
615
+ close(fd);
616
+ rb_raise(rb_eArgError, "not a serial port");
617
+ }
618
+
619
+ /* enable blocking read */
620
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
621
+
622
+ if (tcgetattr(fd, &params) == -1) {
623
+ close(fd);
624
+ rb_sys_fail(sTcgetattr);
625
+ }
626
+ params.c_oflag = 0;
627
+ params.c_lflag = 0;
628
+ params.c_iflag &= (IXON | IXOFF | IXANY);
629
+ params.c_cflag |= CLOCAL | CREAD;
630
+ params.c_cflag &= ~HUPCL;
631
+ if (tcsetattr(fd, TCSANOW, &params) == -1) {
632
+ close(fd);
633
+ rb_sys_fail(sTcsetattr);
634
+ }
635
+
636
+ fp->f = rb_fdopen(fd, "r+");
637
+ fp->mode = FMODE_READWRITE | FMODE_SYNC;
638
+ return (VALUE) sp;
639
+ }
640
+
641
+ static VALUE sp_set_modem_params(argc, argv, self)
642
+ int argc;
643
+ VALUE *argv, self;
644
+ {
645
+ int fd;
646
+ struct termios params;
647
+ VALUE _data_rate, _data_bits, _parity, _stop_bits;
648
+ int use_hash = 0;
649
+ int data_rate, data_bits;
650
+
651
+ if (argc == 0)
652
+ return self;
653
+ if (argc == 1 && T_HASH == TYPE(argv[0])) {
654
+ use_hash = 1;
655
+ _data_rate = rb_hash_aref(argv[0], sBaud);
656
+ _data_bits = rb_hash_aref(argv[0], sDataBits);
657
+ _stop_bits = rb_hash_aref(argv[0], sStopBits);
658
+ _parity = rb_hash_aref(argv[0], sParity);
659
+ }
660
+
661
+ fd = sp_get_fd(self);
662
+ if (tcgetattr(fd, &params) == -1)
663
+ rb_sys_fail(sTcgetattr);
664
+
665
+ if (!use_hash)
666
+ _data_rate = argv[0];
667
+ if (NIL_P(_data_rate))
668
+ goto SkipDataRate;
669
+ Check_Type(_data_rate, T_FIXNUM);
670
+
671
+ switch(FIX2INT(_data_rate)) {
672
+ case 50: data_rate = B50; break;
673
+ case 75: data_rate = B75; break;
674
+ case 110: data_rate = B110; break;
675
+ case 134: data_rate = B134; break;
676
+ case 150: data_rate = B150; break;
677
+ case 200: data_rate = B200; break;
678
+ case 300: data_rate = B300; break;
679
+ case 600: data_rate = B600; break;
680
+ case 1200: data_rate = B1200; break;
681
+ case 1800: data_rate = B1800; break;
682
+ case 2400: data_rate = B2400; break;
683
+ case 4800: data_rate = B4800; break;
684
+ case 9600: data_rate = B9600; break;
685
+ case 19200: data_rate = B19200; break;
686
+ case 38400: data_rate = B38400; break;
687
+ #ifdef B57600
688
+ case 57600: data_rate = B57600; break;
689
+ #endif
690
+ #ifdef B76800
691
+ case 76800: data_rate = B76800; break;
692
+ #endif
693
+ #ifdef B115200
694
+ case 115200: data_rate = B115200; break;
695
+ #endif
696
+ #ifdef B230400
697
+ case 230400: data_rate = B230400; break;
698
+ #endif
699
+
700
+ default:
701
+ rb_raise(rb_eArgError, "unknown baud rate");
702
+ break;
703
+ }
704
+ cfsetispeed(&params, data_rate);
705
+ cfsetospeed(&params, data_rate);
706
+ SkipDataRate:
707
+
708
+ if (!use_hash)
709
+ _data_bits = (argc >= 2 ? argv[1] : INT2FIX(8));
710
+ if (NIL_P(_data_bits))
711
+ goto SkipDataBits;
712
+ Check_Type(_data_bits, T_FIXNUM);
713
+
714
+ switch(FIX2INT(_data_bits)) {
715
+ case 5:
716
+ data_bits = CS5;
717
+ break;
718
+ case 6:
719
+ data_bits = CS6;
720
+ break;
721
+ case 7:
722
+ data_bits = CS7;
723
+ break;
724
+ case 8:
725
+ data_bits = CS8;
726
+ break;
727
+ default:
728
+ rb_raise(rb_eArgError, "unknown character size");
729
+ break;
730
+ }
731
+ params.c_cflag &= ~CSIZE;
732
+ params.c_cflag |= data_bits;
733
+ SkipDataBits:
734
+
735
+ if (!use_hash)
736
+ _stop_bits = (argc >= 3 ? argv[2] : INT2FIX(1));
737
+ if (NIL_P(_stop_bits))
738
+ goto SkipStopBits;
739
+ Check_Type(_stop_bits, T_FIXNUM);
740
+
741
+ switch(FIX2INT(_stop_bits)) {
742
+ case 1:
743
+ params.c_cflag &= ~CSTOPB;
744
+ break;
745
+ case 2:
746
+ params.c_cflag |= CSTOPB;
747
+ break;
748
+ default:
749
+ rb_raise(rb_eArgError, "unknown number of stop bits");
750
+ break;
751
+ }
752
+ SkipStopBits:
753
+
754
+ if (!use_hash)
755
+ _parity = (argc >= 4 ? argv[3] : ((params.c_cflag & CSIZE) == CS8 ?
756
+ INT2FIX(NONE) : INT2FIX(EVEN)));
757
+ if (NIL_P(_parity))
758
+ goto SkipParity;
759
+ Check_Type(_parity, T_FIXNUM);
760
+
761
+ switch(FIX2INT(_parity)) {
762
+ case EVEN:
763
+ params.c_cflag |= PARENB;
764
+ params.c_cflag &= ~PARODD;
765
+ break;
766
+
767
+ case ODD:
768
+ params.c_cflag |= PARENB;
769
+ params.c_cflag |= PARODD;
770
+ break;
771
+
772
+ case NONE:
773
+ params.c_cflag &= ~PARENB;
774
+ break;
775
+
776
+ default:
777
+ rb_raise(rb_eArgError, "unknown parity");
778
+ break;
779
+ }
780
+ SkipParity:
781
+
782
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
783
+ rb_sys_fail(sTcsetattr);
784
+ return self;
785
+ }
786
+
787
+ static void get_modem_params(self, mp)
788
+ VALUE self;
789
+ struct modem_params *mp;
790
+ {
791
+ int fd;
792
+ struct termios params;
793
+
794
+ fd = sp_get_fd(self);
795
+ if (tcgetattr(fd, &params) == -1)
796
+ rb_sys_fail(sTcgetattr);
797
+
798
+ switch (cfgetospeed(&params)) {
799
+ case B50: mp->data_rate = 50; break;
800
+ case B75: mp->data_rate = 75; break;
801
+ case B110: mp->data_rate = 110; break;
802
+ case B134: mp->data_rate = 134; break;
803
+ case B150: mp->data_rate = 150; break;
804
+ case B200: mp->data_rate = 200; break;
805
+ case B300: mp->data_rate = 300; break;
806
+ case B600: mp->data_rate = 600; break;
807
+ case B1200: mp->data_rate = 1200; break;
808
+ case B1800: mp->data_rate = 1800; break;
809
+ case B2400: mp->data_rate = 2400; break;
810
+ case B4800: mp->data_rate = 4800; break;
811
+ case B9600: mp->data_rate = 9600; break;
812
+ case B19200: mp->data_rate = 19200; break;
813
+ case B38400: mp->data_rate = 38400; break;
814
+ #ifdef B57600
815
+ case B57600: mp->data_rate = 57600; break;
816
+ #endif
817
+ #ifdef B76800
818
+ case B76800: mp->data_rate = 76800; break;
819
+ #endif
820
+ #ifdef B115200
821
+ case B115200: mp->data_rate = 115200; break;
822
+ #endif
823
+ #ifdef B230400
824
+ case B230400: mp->data_rate = 230400; break;
825
+ #endif
826
+ }
827
+
828
+ switch(params.c_cflag & CSIZE) {
829
+ case CS5:
830
+ mp->data_bits = 5;
831
+ break;
832
+ case CS6:
833
+ mp->data_bits = 6;
834
+ break;
835
+ case CS7:
836
+ mp->data_bits = 7;
837
+ break;
838
+ case CS8:
839
+ mp->data_bits = 8;
840
+ break;
841
+ default:
842
+ mp->data_bits = 0;
843
+ break;
844
+ }
845
+
846
+ mp->stop_bits = (params.c_cflag & CSTOPB ? 2 : 1);
847
+
848
+ if (!(params.c_cflag & PARENB))
849
+ mp->parity = NONE;
850
+ else if (params.c_cflag & PARODD)
851
+ mp->parity = ODD;
852
+ else
853
+ mp->parity = EVEN;
854
+ }
855
+
856
+ static VALUE sp_set_flow_control(self, val)
857
+ VALUE self, val;
858
+ {
859
+ int fd;
860
+ int flowc;
861
+ struct termios params;
862
+
863
+ Check_Type(val, T_FIXNUM);
864
+
865
+ fd = sp_get_fd(self);
866
+ if (tcgetattr(fd, &params) == -1)
867
+ rb_sys_fail(sTcgetattr);
868
+
869
+ flowc = FIX2INT(val);
870
+ if (flowc & HARD)
871
+ #ifdef HAVE_FLOWCONTROL_HARD
872
+ params.c_cflag |= CRTSCTS;
873
+ else
874
+ params.c_cflag &= ~CRTSCTS;
875
+ #else
876
+ rb_raise(rb_eIOError, "Hardware flow control not supported");
877
+ #endif
878
+ if (flowc & SOFT)
879
+ params.c_iflag |= (IXON | IXOFF | IXANY);
880
+ else
881
+ params.c_iflag &= ~(IXON | IXOFF | IXANY);
882
+
883
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
884
+ rb_sys_fail(sTcsetattr);
885
+ return self;
886
+ }
887
+
888
+ static VALUE sp_get_flow_control(self)
889
+ VALUE self;
890
+ {
891
+ int ret;
892
+ int fd;
893
+ struct termios params;
894
+
895
+ fd = sp_get_fd(self);
896
+ if (tcgetattr(fd, &params) == -1)
897
+ rb_sys_fail(sTcgetattr);
898
+
899
+ ret = 0;
900
+ #ifdef HAVE_FLOWCONTROL_HARD
901
+ if (params.c_cflag & CRTSCTS)
902
+ ret += HARD;
903
+ #endif
904
+ if (params.c_iflag & (IXON | IXOFF | IXANY))
905
+ ret += SOFT;
906
+
907
+ return INT2FIX(ret);
908
+ }
909
+
910
+ static VALUE sp_set_read_timeout(self, val)
911
+ VALUE self, val;
912
+ {
913
+ int timeout;
914
+ int fd;
915
+ struct termios params;
916
+
917
+ Check_Type(val, T_FIXNUM);
918
+ timeout = FIX2INT(val);
919
+
920
+ fd = sp_get_fd(self);
921
+ if (tcgetattr(fd, &params) == -1)
922
+ rb_sys_fail(sTcgetattr);
923
+
924
+ if (timeout < 0) {
925
+ params.c_cc[VTIME] = 0;
926
+ params.c_cc[VMIN] = 0;
927
+ } else if (timeout == 0) {
928
+ params.c_cc[VTIME] = 0;
929
+ params.c_cc[VMIN] = 1;
930
+ } else {
931
+ params.c_cc[VTIME] = (timeout + 50) / 100;
932
+ params.c_cc[VMIN] = 0;
933
+ }
934
+
935
+ if (tcsetattr(fd, TCSANOW, &params) == -1)
936
+ rb_sys_fail(sTcsetattr);
937
+ return self;
938
+ }
939
+
940
+ static VALUE sp_get_read_timeout(self)
941
+ VALUE self;
942
+ {
943
+ int fd;
944
+ struct termios params;
945
+
946
+ fd = sp_get_fd(self);
947
+ if (tcgetattr(fd, &params) == -1)
948
+ rb_sys_fail(sTcgetattr);
949
+ if (params.c_cc[VTIME] == 0 && params.c_cc[VMIN] == 0)
950
+ return INT2FIX(-1);
951
+ return INT2FIX(params.c_cc[VTIME] * 100);
952
+ }
953
+
954
+ static VALUE sp_set_write_timeout(self, val)
955
+ VALUE self, val;
956
+ {
957
+ rb_notimplement();
958
+ return self;
959
+ }
960
+
961
+ static VALUE sp_get_write_timeout(self)
962
+ VALUE self;
963
+ {
964
+ rb_notimplement();
965
+ return self;
966
+ }
967
+
968
+ static VALUE sp_break(self, time)
969
+ VALUE self, time;
970
+ {
971
+ int fd;
972
+
973
+ Check_Type(time, T_FIXNUM);
974
+
975
+ fd = sp_get_fd(self);
976
+ if (tcsendbreak(fd, FIX2INT(time) / 3) == -1)
977
+ rb_sys_fail("tcsendbreak");
978
+ return Qnil;
979
+ }
980
+
981
+ static void get_line_signals(obj, ls)
982
+ VALUE obj;
983
+ struct line_signals *ls;
984
+ {
985
+ int fd, status;
986
+
987
+ fd = sp_get_fd(obj);
988
+ if (ioctl(fd, TIOCMGET, &status) == -1)
989
+ rb_sys_fail(sIoctl);
990
+
991
+ ls->rts = (status & TIOCM_RTS ? 1 : 0);
992
+ ls->dtr = (status & TIOCM_DTR ? 1 : 0);
993
+ ls->cts = (status & TIOCM_CTS ? 1 : 0);
994
+ ls->dsr = (status & TIOCM_DSR ? 1 : 0);
995
+ ls->dcd = (status & TIOCM_CD ? 1 : 0);
996
+ ls->ri = (status & TIOCM_RI ? 1 : 0);
997
+ }
998
+
999
+ static VALUE set_signal(obj, val, sig)
1000
+ VALUE obj,val;
1001
+ int sig;
1002
+ {
1003
+ int status;
1004
+ int fd;
1005
+ int set;
1006
+
1007
+ Check_Type(val, T_FIXNUM);
1008
+ fd = sp_get_fd(obj);
1009
+ if (ioctl(fd, TIOCMGET, &status) == -1)
1010
+ rb_sys_fail(sIoctl);
1011
+
1012
+ set = FIX2INT(val);
1013
+ if (set == 0)
1014
+ status &= ~sig;
1015
+ else if (set == 1)
1016
+ status |= sig;
1017
+ else
1018
+ rb_raise(rb_eArgError, "invalid value");
1019
+
1020
+ if (ioctl(fd, TIOCMSET, &status) == -1)
1021
+ rb_sys_fail(sIoctl);
1022
+ return obj;
1023
+ }
1024
+
1025
+ static VALUE sp_set_rts(self, val)
1026
+ VALUE self, val;
1027
+ {
1028
+ return set_signal(self, val, TIOCM_RTS);
1029
+ }
1030
+
1031
+ static VALUE sp_set_dtr(self, val)
1032
+ VALUE self, val;
1033
+ {
1034
+ return set_signal(self, val, TIOCM_DTR);
1035
+ }
1036
+
1037
+ static VALUE sp_get_rts(self)
1038
+ VALUE self;
1039
+ {
1040
+ struct line_signals ls;
1041
+
1042
+ get_line_signals(self, &ls);
1043
+ return INT2FIX(ls.rts);
1044
+ }
1045
+
1046
+ static VALUE sp_get_dtr(self)
1047
+ VALUE self;
1048
+ {
1049
+ struct line_signals ls;
1050
+
1051
+ get_line_signals(self, &ls);
1052
+ return INT2FIX(ls.dtr);
1053
+ }
1054
+
1055
+
1056
+ #endif /* defined(mswin) || defined(bccwin) */
1057
+
1058
+
1059
+ static VALUE sp_set_data_rate(self, data_rate)
1060
+ VALUE self, data_rate;
1061
+ {
1062
+ VALUE argv[4];
1063
+
1064
+ argv[0] = data_rate;
1065
+ argv[1] = argv[2] = argv[3] = Qnil;
1066
+ return sp_set_modem_params(4, argv, self);
1067
+ }
1068
+
1069
+ static VALUE sp_set_data_bits(self, data_bits)
1070
+ VALUE self, data_bits;
1071
+ {
1072
+ VALUE argv[4];
1073
+
1074
+ argv[1] = data_bits;
1075
+ argv[0] = argv[2] = argv[3] = Qnil;
1076
+ return sp_set_modem_params(4, argv, self);
1077
+ }
1078
+
1079
+ static VALUE sp_set_stop_bits(self, stop_bits)
1080
+ VALUE self, stop_bits;
1081
+ {
1082
+ VALUE argv[4];
1083
+
1084
+ argv[2] = stop_bits;
1085
+ argv[0] = argv[1] = argv[3] = Qnil;
1086
+ return sp_set_modem_params(4, argv, self);
1087
+ }
1088
+
1089
+ static VALUE sp_set_parity(self, parity)
1090
+ VALUE self, parity;
1091
+ {
1092
+ VALUE argv[4];
1093
+
1094
+ argv[3] = parity;
1095
+ argv[0] = argv[1] = argv[2] = Qnil;
1096
+ return sp_set_modem_params(4, argv, self);
1097
+ }
1098
+
1099
+ static VALUE sp_get_data_rate(self)
1100
+ VALUE self;
1101
+ {
1102
+ struct modem_params mp;
1103
+
1104
+ get_modem_params(self, &mp);
1105
+ return INT2FIX(mp.data_rate);
1106
+ }
1107
+
1108
+ static VALUE sp_get_data_bits(self)
1109
+ VALUE self;
1110
+ {
1111
+ struct modem_params mp;
1112
+
1113
+ get_modem_params(self, &mp);
1114
+ return INT2FIX(mp.data_bits);
1115
+ }
1116
+
1117
+ static VALUE sp_get_stop_bits(self)
1118
+ VALUE self;
1119
+ {
1120
+ struct modem_params mp;
1121
+
1122
+ get_modem_params(self, &mp);
1123
+ return INT2FIX(mp.stop_bits);
1124
+ }
1125
+
1126
+ static VALUE sp_get_parity(self)
1127
+ VALUE self;
1128
+ {
1129
+ struct modem_params mp;
1130
+
1131
+ get_modem_params(self, &mp);
1132
+ return INT2FIX(mp.parity);
1133
+ }
1134
+
1135
+ static VALUE sp_get_modem_params(self)
1136
+ VALUE self;
1137
+ {
1138
+ struct modem_params mp;
1139
+ VALUE hash;
1140
+
1141
+ get_modem_params(self, &mp);
1142
+ hash = rb_hash_new();
1143
+ rb_hash_aset(hash, sBaud, INT2FIX(mp.data_rate));
1144
+ rb_hash_aset(hash, sDataBits, INT2FIX(mp.data_bits));
1145
+ rb_hash_aset(hash, sStopBits, INT2FIX(mp.stop_bits));
1146
+ rb_hash_aset(hash, sParity, INT2FIX(mp.parity));
1147
+ return hash;
1148
+ }
1149
+
1150
+ static VALUE sp_get_cts(self)
1151
+ VALUE self;
1152
+ {
1153
+ struct line_signals ls;
1154
+
1155
+ get_line_signals(self, &ls);
1156
+ return INT2FIX(ls.cts);
1157
+ }
1158
+
1159
+ static VALUE sp_get_dsr(self)
1160
+ VALUE self;
1161
+ {
1162
+ struct line_signals ls;
1163
+
1164
+ get_line_signals(self, &ls);
1165
+ return INT2FIX(ls.dsr);
1166
+ }
1167
+
1168
+ static VALUE sp_get_dcd(self)
1169
+ VALUE self;
1170
+ {
1171
+ struct line_signals ls;
1172
+
1173
+ get_line_signals(self, &ls);
1174
+ return INT2FIX(ls.dcd);
1175
+ }
1176
+
1177
+ static VALUE sp_get_ri(self)
1178
+ VALUE self;
1179
+ {
1180
+ struct line_signals ls;
1181
+
1182
+ get_line_signals(self, &ls);
1183
+ return INT2FIX(ls.ri);
1184
+ }
1185
+
1186
+ static VALUE
1187
+ sp_signals(self)
1188
+ VALUE self;
1189
+ {
1190
+ struct line_signals ls;
1191
+ VALUE hash;
1192
+
1193
+ get_line_signals(self, &ls);
1194
+ hash = rb_hash_new();
1195
+ #if !(defined(mswin) || defined(bccwin))
1196
+ rb_hash_aset(hash, sRts, INT2FIX(ls.rts));
1197
+ rb_hash_aset(hash, sDtr, INT2FIX(ls.dtr));
1198
+ #endif
1199
+ rb_hash_aset(hash, sCts, INT2FIX(ls.cts));
1200
+ rb_hash_aset(hash, sDsr, INT2FIX(ls.dsr));
1201
+ rb_hash_aset(hash, sDcd, INT2FIX(ls.dcd));
1202
+ rb_hash_aset(hash, sRi, INT2FIX(ls.ri));
1203
+ return hash;
1204
+ }
1205
+
1206
+ void Init_serialport() {
1207
+ sBaud = rb_str_new2("baud");
1208
+ sDataBits = rb_str_new2("data_bits");
1209
+ sStopBits = rb_str_new2("stop_bits");
1210
+ sParity = rb_str_new2("parity");
1211
+ sRts = rb_str_new2("rts");
1212
+ sDtr = rb_str_new2("dtr");
1213
+ sCts = rb_str_new2("cts");
1214
+ sDsr = rb_str_new2("dsr");
1215
+ sDcd = rb_str_new2("dcd");
1216
+ sRi = rb_str_new2("ri");
1217
+
1218
+ rb_gc_register_address(&sBaud);
1219
+ rb_gc_register_address(&sDataBits);
1220
+ rb_gc_register_address(&sStopBits);
1221
+ rb_gc_register_address(&sParity);
1222
+ rb_gc_register_address(&sRts);
1223
+ rb_gc_register_address(&sDtr);
1224
+ rb_gc_register_address(&sCts);
1225
+ rb_gc_register_address(&sDsr);
1226
+ rb_gc_register_address(&sDcd);
1227
+ rb_gc_register_address(&sRi);
1228
+
1229
+ cSerialPort = rb_define_class("SerialPort", rb_cIO);
1230
+ rb_define_singleton_method(cSerialPort, "create", sp_create, 1);
1231
+
1232
+ rb_define_method(cSerialPort, "get_modem_params", sp_get_modem_params, 0);
1233
+ rb_define_method(cSerialPort, "set_modem_params", sp_set_modem_params, -1);
1234
+ rb_define_method(cSerialPort, "modem_params", sp_get_modem_params, 0);
1235
+ rb_define_method(cSerialPort, "modem_params=", sp_set_modem_params, -1);
1236
+ rb_define_method(cSerialPort, "baud", sp_get_data_rate, 0);
1237
+ rb_define_method(cSerialPort, "baud=", sp_set_data_rate, 1);
1238
+ rb_define_method(cSerialPort, "data_bits", sp_get_data_bits, 0);
1239
+ rb_define_method(cSerialPort, "data_bits=", sp_set_data_bits, 1);
1240
+ rb_define_method(cSerialPort, "stop_bits", sp_get_stop_bits, 0);
1241
+ rb_define_method(cSerialPort, "stop_bits=", sp_set_stop_bits, 1);
1242
+ rb_define_method(cSerialPort, "parity", sp_get_parity, 0);
1243
+ rb_define_method(cSerialPort, "parity=", sp_set_parity, 1);
1244
+
1245
+ rb_define_method(cSerialPort, "flow_control=", sp_set_flow_control, 1);
1246
+ rb_define_method(cSerialPort, "flow_control", sp_get_flow_control, 0);
1247
+
1248
+ rb_define_method(cSerialPort, "read_timeout", sp_get_read_timeout, 0);
1249
+ rb_define_method(cSerialPort, "read_timeout=", sp_set_read_timeout, 1);
1250
+ rb_define_method(cSerialPort, "write_timeout", sp_get_write_timeout, 0);
1251
+ rb_define_method(cSerialPort, "write_timeout=", sp_set_write_timeout, 1);
1252
+
1253
+ rb_define_method(cSerialPort, "break", sp_break, 1);
1254
+
1255
+ rb_define_method(cSerialPort, "signals", sp_signals, 0);
1256
+ rb_define_method(cSerialPort, "get_signals", sp_signals, 0);
1257
+ rb_define_method(cSerialPort, "rts", sp_get_rts, 0);
1258
+ rb_define_method(cSerialPort, "rts=", sp_set_rts, 1);
1259
+ rb_define_method(cSerialPort, "dtr", sp_get_dtr, 0);
1260
+ rb_define_method(cSerialPort, "dtr=", sp_set_dtr, 1);
1261
+ rb_define_method(cSerialPort, "cts", sp_get_cts, 0);
1262
+ rb_define_method(cSerialPort, "dsr", sp_get_dsr, 0);
1263
+ rb_define_method(cSerialPort, "dcd", sp_get_dcd, 0);
1264
+ rb_define_method(cSerialPort, "ri", sp_get_ri, 0);
1265
+
1266
+ rb_define_const(cSerialPort, "NONE", INT2FIX(NONE));
1267
+ rb_define_const(cSerialPort, "HARD", INT2FIX(HARD));
1268
+ rb_define_const(cSerialPort, "SOFT", INT2FIX(SOFT));
1269
+
1270
+ rb_define_const(cSerialPort, "SPACE", INT2FIX(SPACE));
1271
+ rb_define_const(cSerialPort, "MARK", INT2FIX(MARK));
1272
+ rb_define_const(cSerialPort, "EVEN", INT2FIX(EVEN));
1273
+ rb_define_const(cSerialPort, "ODD", INT2FIX(ODD));
1274
+
1275
+ rb_define_const(cSerialPort, "VERSION", rb_str_new2(VERSION));
1276
+
1277
+ /* The following definitions are more easily carried out in Ruby */
1278
+ rb_eval_string(
1279
+ "class SerialPort\n"
1280
+
1281
+ "private_class_method(:create)\n"
1282
+
1283
+ "def SerialPort::new(port, *params)\n"
1284
+ "sp = create(port)\n"
1285
+ "begin\n"
1286
+ "sp.set_modem_params(*params)\n"
1287
+ "rescue\n"
1288
+ "sp.close\n"
1289
+ "raise\n"
1290
+ "end\n"
1291
+ "return sp\n"
1292
+ "end\n"
1293
+
1294
+ "def SerialPort::open(port, *params)\n"
1295
+ "sp = create(port)\n"
1296
+ "begin\n"
1297
+ "sp.set_modem_params(*params)\n"
1298
+ "if (block_given?)\n"
1299
+ "yield sp\n"
1300
+ "sp.close\n"
1301
+ "return nil\n"
1302
+ "end\n"
1303
+ "rescue\n"
1304
+ "sp.close\n"
1305
+ "raise\n"
1306
+ "end\n"
1307
+ "return sp\n"
1308
+ "end\n"
1309
+
1310
+ "end\n"
1311
+ );
1312
+ }