File Coverage

blib/lib/IO/Termios.pm
Criterion Covered Total %
statement 98 206 47.5
branch 13 88 14.7
condition 0 6 0.0
subroutine 28 54 51.8
pod 13 13 100.0
total 152 367 41.4


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2008-2024 -- leonerd@leonerd.org.uk
5              
6             package IO::Termios 0.10;
7              
8 2     2   810696 use v5.14;
  2         10  
9 2     2   15 use warnings;
  2         9  
  2         190  
10 2     2   16 use base qw( IO::Handle );
  2         4  
  2         1556  
11              
12 2     2   16394 use Carp;
  2         7  
  2         147  
13              
14 2     2   12 use Exporter ();
  2         3  
  2         49  
15              
16 2     2   8 use Fcntl qw( O_RDWR );
  2         3  
  2         134  
17 2     2   1259 use POSIX qw( TCSANOW );
  2         18146  
  2         17  
18 2     2   6191 use IO::Tty;
  2         15350  
  2         13  
19 2         647 use IO::Tty::Constant qw(
20             TIOCMGET TIOCMSET TIOCMBIC TIOCMBIS
21             TIOCM_DTR TIOCM_DSR TIOCM_RTS TIOCM_CTS TIOCM_CD TIOCM_RI
22 2     2   383 );
  2         4  
23              
24             # Linux can support finer-grained control of baud rates if we let it
25 2     2   17 use constant HAVE_LINUX_TERMIOS2 => eval { require Linux::Termios2; };
  2         6  
  2         4  
  2         3655  
26              
27             =head1 NAME
28              
29             C - supply F methods to C objects
30              
31             =head1 SYNOPSIS
32              
33             use IO::Termios;
34              
35             my $term = IO::Termios->open( "/dev/ttyS0", "9600,8,n,1" )
36             or die "Cannot open ttyS0 - $!";
37              
38             $term->print( "Hello world\n" ); # Still an IO::Handle
39              
40             while( <$term> ) {
41             print "A line from ttyS0: $_";
42             }
43              
44             =head1 DESCRIPTION
45              
46             This class extends the generic C object class by providing methods
47             which access the system's terminal control C operations. These
48             methods are primarily of interest when dealing with TTY devices, including
49             serial ports.
50              
51             The flag-setting methods will apply to any TTY device, such as a pseudo-tty,
52             and are useful for controlling such flags as the C flag, to disable
53             local echo.
54              
55             my $stdin = IO::Termios->new( \*STDIN );
56             $stdin->setflag_echo( 0 );
57              
58             When dealing with a serial port the line mode method is useful for setting the
59             basic serial parameters such as baud rate, and the modem line control methods
60             can be used to access the hardware handshaking lines.
61              
62             my $ttyS0 = IO::Termios->open( "/dev/ttyS0" );
63             $ttyS0->set_mode( "19200,8,n,1" );
64             $ttyS0->set_modem({ dsr => 1, cts => 1 });
65              
66             =head2 Upgrading STDIN/STDOUT/STDERR
67              
68             If you pass the C<-upgrade> option at C time, any of STDIN, STDOUT or
69             STDERR that are found to be TTY wrappers are automatically upgraded into
70             C instances.
71              
72             use IO::Termios -upgrade;
73              
74             STDIN->setflag_echo(0);
75              
76             =head2 Arbitrary Baud Rates on Linux
77              
78             F supports a non-POSIX extension to the usual C interface,
79             which allows arbitrary baud rates to be set. C can automatically
80             make use of this ability if the L module is installed. If so,
81             this will be used automatically and transparently, to allow the C
82             methods to set any rate allowed by the kernel/driver. If not, then only the
83             POSIX-compatible rates may be used.
84              
85             =cut
86              
87             sub import
88             {
89 1     1   14 my $pkg = shift;
90 1         3 my @symbols = @_;
91 1         3 my $caller = caller;
92              
93 1         2 my $upgrade;
94 1 0       3 @symbols = grep { $_ eq "-upgrade" ? ( $upgrade++, 0 ) : 1 } @symbols;
  0         0  
95              
96 1 50       47 if( $upgrade ) {
97 0         0 foreach my $fh ( *STDIN{IO}, *STDOUT{IO}, *STDERR{IO} ) {
98 0 0       0 IO::Termios::Attrs->new->getattr( $fh->fileno ) or next;
99              
100 0         0 bless $fh, __PACKAGE__;
101             }
102             }
103             }
104              
105             =head1 CONSTRUCTORS
106              
107             =cut
108              
109             =head2 new
110              
111             $term = IO::Termios->new();
112              
113             Construct a new C object around the terminal for the program.
114             This is found by checking if any of C, C or C are a
115             terminal. The first one that's found is used. An error occurs if no terminal
116             can be found by this method.
117              
118             =head2 new (handle)
119              
120             $term = IO::Termios->new( $handle );
121              
122             Construct a new C object around the given filehandle.
123              
124             =cut
125              
126             sub new
127             {
128 1     1 1 297305 my $class = shift;
129 1         3 my ( $handle ) = @_;
130              
131 1 50       6 if( not $handle ) {
132             # Try to find a terminal - STDIN, STDOUT, STDERR are good candidates
133 0 0       0 return $class->SUPER::new_from_fd( fileno STDIN, "w+" ) if -t STDIN;
134 0 0       0 return $class->SUPER::new_from_fd( fileno STDOUT, "w+" ) if -t STDOUT;
135 0 0       0 return $class->SUPER::new_from_fd( fileno STDERR, "w+" ) if -t STDERR;
136              
137 0         0 die "TODO: Need to find a terminal\n";
138             }
139              
140 1 50       6 croak '$handle is not a filehandle' unless defined fileno $handle;
141              
142 1         9 my $self = $class->SUPER::new_from_fd( $handle, "w+" );
143              
144 1         127 return $self;
145             }
146              
147             =head2 open
148              
149             $term = IO::Termios->open( $path, $modestr, $flags );
150              
151             Open the given path, and return a new C object around the
152             filehandle. If the C call fails, C is returned.
153              
154             If C<$modestr> is provided, the constructor will pass it to the C
155             method before returning.
156              
157             If C<$flags> is provided, it will be passed on to the underlying C
158             call used to open the filehandle. It should contain a bitwise-or combination
159             of C flags from the L module - for example C or
160             C. The value C will be added to this; the caller does not
161             need to specify it directly. For example:
162              
163             use Fcntl qw( O_NOCTTY O_NDELAY );
164              
165             $term = IO::Termios->open( "/dev/ttyS0", O_NOCTTY|O_NDELAY );
166             $term->setflag_clocal( 1 );
167             $term->blocking( 1 );
168              
169             =cut
170              
171             sub open
172             {
173 0     0 1 0 my $class = shift;
174 0         0 my ( $path, $modestr, $flags ) = @_;
175              
176 0   0     0 $flags //= 0;
177              
178 0 0       0 sysopen my $tty, $path, O_RDWR | $flags, or return undef;
179 0 0       0 my $self = $class->new( $tty ) or return undef;
180              
181 0 0       0 $self->set_mode( $modestr ) if defined $modestr;
182              
183 0         0 return $self;
184             }
185              
186             =head1 METHODS
187              
188             =cut
189              
190             =head2 getattr
191              
192             $attrs = $term->getattr;
193              
194             Makes a C call on the underlying filehandle, and returns a
195             C object.
196              
197             If the C call fails, C is returned.
198              
199             =cut
200              
201             sub getattr
202             {
203 15     15 1 21 my $self = shift;
204              
205 15         34 my $attrs = IO::Termios::Attrs->new;
206 15 50       34 $attrs->getattr( $self->fileno ) or return undef;
207              
208 15         169 return $attrs;
209             }
210              
211             =head2 setattr
212              
213             $term->setattr( $attrs );
214              
215             Makes a C call on the underlying file handle, setting attributes
216             from the given C object.
217              
218             If the C call fails, C is returned. Otherwise, a true
219             value is returned.
220              
221             =cut
222              
223             sub setattr
224             {
225 6     6 1 11 my $self = shift;
226 6         8 my ( $attrs ) = @_;
227              
228 6         14 return $attrs->setattr( $self->fileno, TCSANOW );
229             }
230              
231             =head2 set_mode
232              
233             =head2 get_mode
234              
235             $term->set_mode( $modestr );
236              
237             $modestr = $term->get_mode;
238              
239             Accessor for the derived "mode string", which is a comma-joined concatenation
240             of the baud rate, character size, parity mode, and stop size in a format such
241             as
242              
243             19200,8,n,1
244              
245             When setting the mode string, trailing components may be omitted meaning their
246             value will not be affected.
247              
248             =cut
249              
250             sub set_mode
251             {
252 0     0 1 0 my $self = shift;
253 0         0 my ( $modestr ) = @_;
254              
255 0         0 my ( $baud, $csize, $parity, $stop ) = split m/,/, $modestr;
256              
257 0         0 my $attrs = $self->getattr;
258              
259 0 0       0 $attrs->setbaud ( $baud ) if defined $baud;
260 0 0       0 $attrs->setcsize ( $csize ) if defined $csize;
261 0 0       0 $attrs->setparity( $parity ) if defined $parity;
262 0 0       0 $attrs->setstop ( $stop ) if defined $stop;
263              
264 0         0 $self->setattr( $attrs );
265             }
266              
267             sub get_mode
268             {
269 0     0 1 0 my $self = shift;
270              
271 0         0 my $attrs = $self->getattr;
272 0         0 return join ",",
273             $attrs->getibaud,
274             $attrs->getcsize,
275             $attrs->getparity,
276             $attrs->getstop;
277             }
278              
279             =head2 tiocmget
280              
281             =head2 tiocmset
282              
283             $bits = $term->tiocmget;
284              
285             $term->tiocmset( $bits );
286              
287             Accessor for the modem line control bits. Takes or returns a bitmask of
288             values.
289              
290             =cut
291              
292             sub tiocmget
293             {
294 0     0 1 0 my $self = shift;
295              
296 0         0 my $bitstr = pack "i!", 0;
297 0 0       0 ioctl( $self, TIOCMGET, $bitstr ) or
298             croak "Cannot ioctl(TIOCMGET) - $!";
299              
300 0         0 return unpack "i!", $bitstr;
301             }
302              
303             sub tiocmset
304             {
305 0     0 1 0 my $self = shift;
306 0         0 my ( $bits ) = @_;
307              
308 0         0 my $bitstr = pack "i!", $bits;
309 0 0       0 ioctl( $self, TIOCMSET, $bitstr )
310             or croak "Cannot ioctl(TIOCMSET) - $!";
311             }
312              
313             =head2 tiocmbic
314              
315             =head2 tiocmbis
316              
317             $term->tiocmbic( $bits );
318              
319             $term->tiocmbis( $bits );
320              
321             Bitwise mutator methods for the modem line control bits. C will
322             clear just the bits provided and leave the others unchanged; C will
323             set them.
324              
325             =cut
326              
327             sub tiocmbic
328             {
329 0     0 1 0 my $self = shift;
330 0         0 my ( $bits ) = @_;
331              
332 0         0 my $bitstr = pack "i!", $bits;
333 0 0       0 ioctl( $self, TIOCMBIC, $bitstr )
334             or croak "Cannot ioctl(TIOCMBIC) - $!";
335             }
336              
337             sub tiocmbis
338             {
339 0     0 1 0 my $self = shift;
340 0         0 my ( $bits ) = @_;
341              
342 0         0 my $bitstr = pack "i!", $bits;
343 0 0       0 ioctl( $self, TIOCMBIS, $bitstr )
344             or croak "Cannot ioctl(TIOCMBIS) - $!";
345             }
346              
347             my %_bit2modem;
348             my %_modem2bit;
349             foreach (qw( dtr dsr rts cts cd ri )) {
350             my $bit = IO::Tty::Constant->${\"TIOCM_\U$_"};
351             $_bit2modem{$bit} = $_;
352             $_modem2bit{$_} = $bit;
353              
354             my $getmodem = sub {
355 0     0   0 my $self = shift;
356 0         0 return !!($self->tiocmget & $bit);
357             };
358             my $setmodem = sub {
359 0     0   0 my $self = shift;
360 0         0 my ( $set ) = @_;
361 0 0       0 $set ? $self->tiocmbis( $bit )
362             : $self->tiocmbic( $bit );
363             };
364              
365 2     2   16 no strict 'refs';
  2         4  
  2         913  
366             *{"getmodem_$_"} = $getmodem;
367             *{"setmodem_$_"} = $setmodem;
368             }
369              
370             =head2 get_modem
371              
372             $flags = $term->get_modem;
373              
374             Returns a hash reference containing named flags corresponding to the modem
375             line control bits. Any bit that is set will yield a key in the returned hash
376             of the same name. The bit names are
377              
378             dtr dsr rts cts cd ri
379              
380             =cut
381              
382             sub get_modem
383             {
384 0     0 1 0 my $self = shift;
385 0         0 my $bits = $self->tiocmget;
386              
387             return +{
388 0 0       0 map { $bits & $_modem2bit{$_} ? ( $_ => 1 ) : () } keys %_modem2bit
  0         0  
389             };
390             }
391              
392             =head2 set_modem
393              
394             $term->set_modem( $flags );
395              
396             Changes the modem line control bit flags as given by the hash reference. Each
397             bit to be changed should be represented by a key in the C<$flags> hash of the
398             names given above. False values will be cleared, true values will be set.
399             Other flags will not be altered.
400              
401             =cut
402              
403             sub set_modem
404             {
405 0     0 1 0 my $self = shift;
406 0         0 my ( $flags ) = @_;
407              
408 0         0 my $bits = $self->tiocmget;
409 0         0 foreach ( keys %$flags ) {
410 0 0       0 my $bit = $_modem2bit{$_} or croak "Unrecognised modem line control bit $_";
411              
412 0 0       0 $flags->{$_} ? ( $bits |= $bit )
413             : ( $bits &= ~$bit );
414             }
415              
416 0         0 $self->tiocmset( $bits );
417             }
418              
419             =head2 getmodem_BIT
420              
421             =head2 setmodem_BIT
422              
423             $set = $term->getmodem_BIT;
424              
425             $term->setmodem_BIT( $set );
426              
427             Accessor methods for each of the modem line control bits. A set of methods
428             exists for each of the named modem control bits given above.
429              
430             =head1 FLAG-ACCESSOR METHODS
431              
432             Theses methods are implemented in terms of the lower level methods, but
433             provide an interface which is more abstract, and easier to re-implement on
434             other non-POSIX systems. These should be used in preference to the lower ones.
435              
436             For efficiency, when getting or setting a large number of flags, it may be
437             more efficient to call C, then operate on the returned object,
438             before possibly passing it to C. The returned C
439             object supports the same methods as documented here.
440              
441             The following two sections of code are therefore equivalent, though the latter
442             is more efficient as it only calls C once.
443              
444             $term->setbaud( 38400 );
445             $term->setcsize( 8 );
446             $term->setparity( 'n' );
447             $term->setstop( 1 );
448              
449             Z<>
450              
451             my $attrs = $term->getattr;
452             $attrs->setbaud( 38400 );
453             $attrs->setcsize( 8 );
454             $attrs->setparity( 'n' );
455             $attrs->setstop( 1 );
456             $term->setattr( $attrs );
457              
458             However, a convenient shortcut method is provided for the common case of
459             setting the baud rate, character size, parity and stop size all at the same
460             time. This is C:
461              
462             $term->set_mode( "38400,8,n,1" );
463              
464             =cut
465              
466             =head2 getibaud
467              
468             =head2 getobaud
469              
470             =head2 setibaud
471              
472             =head2 setobaud
473              
474             =head2 setbaud
475              
476             $baud = $term->getibaud;
477              
478             $baud = $term->getobaud;
479              
480             $term->setibaud( $baud );
481              
482             $term->setobaud( $baud );
483              
484             $term->setbaud( $baud );
485              
486             Convenience accessors for the C and C. C<$baud> is an integer
487             directly giving the line rate, instead of one of the C> constants.
488              
489             =head2 getcsize
490              
491             =head2 setcsize
492              
493             $bits = $term->getcsize;
494              
495             $term->setcsize( $bits );
496              
497             Convenience accessor for the C bits of C. C<$bits> is an
498             integer 5 to 8.
499              
500             =head2 getparity
501              
502             =head2 setparity
503              
504             $parity = $term->getparity;
505              
506             $term->setparity( $parity );
507              
508             Convenience accessor for the C and C bits of C.
509             C<$parity> is C, C or C.
510              
511             =head2 getstop
512              
513             =head2 setstop
514              
515             $stop = $term->getstop;
516              
517             $term->setstop( $stop );
518              
519             Convenience accessor for the C bit of C. C<$stop> is 1 or 2.
520              
521             =head2 cfmakeraw
522              
523             $term->cfmakeraw;
524              
525             I
526              
527             Adjusts several bit flags to put the terminal into a "raw" mode. Input is
528             available a character at a time, echo is disabled, and all special processing
529             of input and output characters is disabled.
530              
531             =cut
532              
533             foreach my $name (qw( ibaud obaud csize parity stop )) {
534             my $getmethod = "get$name";
535             my $setmethod = "set$name";
536              
537 2     2   27 no strict 'refs';
  2         5  
  2         566  
538             *$getmethod = sub {
539 0     0   0 my ( $self ) = @_;
540 0 0       0 my $attrs = $self->getattr or croak "Cannot getattr - $!";
541 0         0 return $attrs->$getmethod;
542             };
543             *$setmethod = sub {
544 0     0   0 my ( $self, $val ) = @_;
545 0 0       0 my $attrs = $self->getattr or croak "Cannot getattr - $!";
546 0         0 $attrs->$setmethod( $val );
547 0 0       0 $self->setattr( $attrs ) or croak "Cannot setattr - $!";
548             };
549             }
550              
551             foreach my $method (qw( setbaud cfmakeraw )) {
552 2     2   14 no strict 'refs';
  2         4  
  2         626  
553             *$method = sub {
554 0     0   0 my $self = shift;
555 0 0       0 my $attrs = $self->getattr or croak "Cannot getattr - $!";
556 0         0 $attrs->$method( @_ );
557 0 0       0 $self->setattr( $attrs ) or croak "Cannot setattr - $!";
558             };
559             }
560              
561             =head2 getflag_I
562              
563             =head2 setflag_I
564              
565             $mode = $term->getflag_FLAG;
566              
567             $term->setflag_FLAG( $mode );
568              
569             Accessors for various control flags. The following methods are defined for
570             specific flags:
571              
572             =head3 inlcr
573              
574             I
575              
576             The C bit of the C. This translates NL to CR on input.
577              
578             =head3 igncr
579              
580             I
581              
582             The C bit of the C. This ignores incoming CR characters.
583              
584             =head3 icrnl
585              
586             I
587              
588             The C bit of the C. This translates CR to NL on input, unless
589             C is also set.
590              
591             =head3 ignbrk
592              
593             I
594              
595             The C bit of the C. This controls whether incoming break
596             conditions are ignored entirely.
597              
598             =head3 brkint
599              
600             I
601              
602             The C bit of the C. This controls whether non-ignored
603             incoming break conditions result in a C signal being delivered to the
604             process. If not, such a condition reads as a nul byte.
605              
606             =head3 parmrk
607              
608             I
609              
610             The C bit of the C. This controls how parity errors and break
611             conditions are handled.
612              
613             =head3 opost
614              
615             I
616              
617             The C bit of the C. This enables system-specific
618             post-processing on output.
619              
620             =head3 cread
621              
622             The C bit of the C. This enables the receiver.
623              
624             =head3 hupcl
625              
626             The C bit of the C. This lowers the modem control lines after
627             the last process closes the device.
628              
629             =head3 clocal
630              
631             The C bit of the C. This controls whether local mode is
632             enabled; which if set, ignores modem control lines.
633              
634             =head3 icanon
635              
636             The C bit of C. This is called "canonical" mode and controls
637             whether the terminal's line-editing feature will be used to return a whole
638             line (if true), or if individual bytes from keystrokes will be returned as
639             they are available (if false).
640              
641             =head3 echo
642              
643             The C bit of C. This controls whether input characters are
644             echoed back to the terminal.
645              
646             =cut
647              
648             my @flags = (
649             # iflag
650             [ inlcr => qw( INLCR i ) ],
651             [ igncr => qw( IGNCR i ) ],
652             [ icrnl => qw( ICRNL i ) ],
653             [ ignbrk => qw( IGNBRK i ) ],
654             [ brkint => qw( BRKINT i ) ],
655             [ parmrk => qw( PARMRK i ) ],
656             # oflag
657             [ opost => qw( OPOST o ) ],
658             # cflag
659             [ cread => qw( CREAD c ) ],
660             [ clocal => qw( CLOCAL c ) ],
661             [ hupcl => qw( HUPCL c ) ],
662             # lflag
663             [ icanon => qw( ICANON l ) ],
664             [ echo => qw( ECHO l ) ],
665             );
666              
667             foreach ( @flags ) {
668             my ( $name ) = @$_;
669              
670             my $getmethod = "getflag_$name";
671             my $setmethod = "setflag_$name";
672              
673 2     2   21 no strict 'refs';
  2         4  
  2         1126  
674             *$getmethod = sub {
675 9     9   96 my ( $self ) = @_;
676 9 50       41 my $attrs = $self->getattr or croak "Cannot getattr - $!";
677 9         19 return $attrs->$getmethod;
678             };
679             *$setmethod = sub {
680 4     4   2018 my ( $self, $set ) = @_;
681 4 50       15 my $attrs = $self->getattr or croak "Cannot getattr - $!";
682 4         14 $attrs->$setmethod( $set );
683 4 50       9 $self->setattr( $attrs ) or croak "Cannot setattr - $!";
684             };
685             }
686              
687             =head2 setflags
688              
689             $term->setflags( @flags );
690              
691             I
692              
693             A convenient wrapper to calling multiple flag setting methods in a sequence.
694              
695             Each flag is specified by name, in lower case, prefixed by either a C<+>
696             symbol to enable it, or C<-> to disable. For example:
697              
698             $term->setflags( "+igncr", "+opost", "+clocal", "-echo" );
699              
700             =cut
701              
702             sub setflags
703             {
704 2     2 1 1058 my $self = shift;
705 2         6 my @flags = @_;
706              
707 2 50       5 my $attrs = $self->getattr or croak "Cannot getattr - $!";
708              
709 2         4 foreach my $flag ( @flags ) {
710 6         7 my $sense = 1;
711 6 100       12 $sense = 0 if $flag =~ s/^-//;
712 6         10 $flag =~ s/^\+//;
713              
714 6         6 my $method = "setflag_$flag";
715 6         11 $attrs->$method( $sense );
716             }
717              
718 2 50       5 $self->setattr( $attrs ) or croak "Cannot setattr - $!";
719             }
720              
721             package # hide from CPAN
722             IO::Termios::Attrs;
723              
724 2     2   22 use Carp;
  2         4  
  2         257  
725 2         17 use POSIX qw(
726             CSIZE CS5 CS6 CS7 CS8 PARENB PARODD CSTOPB
727             IGNBRK BRKINT PARMRK ISTRIP INLCR IGNCR ICRNL IXON OPOST ECHO ECHONL ICANON ISIG IEXTEN
728 2     2   26 );
  2         5  
729             # IO::Tty has more B<\d> constants than POSIX has
730 2     2   473 use IO::Tty;
  2         6  
  2         13  
731              
732             # Simple XS-implemented classes tend not to respect subclassing
733             sub new
734             {
735 15     15   17 my $class = shift;
736 15         53 my $self = $class->SUPER::new;
737 15         21 bless $self, $class;
738 15         22 return $self;
739             }
740              
741             if( IO::Termios::HAVE_LINUX_TERMIOS2 ) {
742             our @ISA = qw( Linux::Termios2 );
743              
744             # baud is directly applicable
745             *getibaud = __PACKAGE__->can( 'getispeed' );
746             *getobaud = __PACKAGE__->can( 'getospeed' );
747              
748             *setibaud = __PACKAGE__->can( 'setispeed' );
749             *setobaud = __PACKAGE__->can( 'setospeed' );
750             }
751             else {
752             our @ISA = qw( POSIX::Termios );
753              
754             # baud needs converting to/from the speed_t constants
755              
756             my %_speed2baud = map { IO::Tty::Constant->${\"B$_"} => $_ }
757             qw( 0 50 75 110 134 150 200 300 600 1200 2400 4800 9600 19200 38400 57600 115200 230400 );
758             my %_baud2speed = reverse %_speed2baud;
759              
760 0     0   0 *getibaud = sub { $_speed2baud{ $_[0]->getispeed } };
761 0     0   0 *getobaud = sub { $_speed2baud{ $_[0]->getospeed } };
762              
763             *setibaud = sub {
764 0   0 0   0 $_[0]->setispeed( $_baud2speed{$_[1]} // die "Unrecognised baud rate" );
765             };
766             *setobaud = sub {
767 0   0 0   0 $_[0]->setospeed( $_baud2speed{$_[1]} // die "Unrecognised baud rate" );
768             };
769              
770             }
771              
772             sub setbaud
773             {
774 0     0   0 $_[0]->setibaud( $_[1] ); $_[0]->setobaud( $_[1] );
  0         0  
775             }
776              
777             foreach ( @flags ) {
778             my ( $name, $const, $member ) = @$_;
779              
780             $const = POSIX->$const();
781              
782             my $getmethod = "getflag_$name";
783             my $getflag = "get${member}flag";
784              
785             my $setmethod = "setflag_$name";
786             my $setflag = "set${member}flag";
787              
788 2     2   1777 no strict 'refs';
  2         4  
  2         2077  
789             *$getmethod = sub {
790 9     9   14 my ( $self ) = @_;
791 9         47 $self->$getflag & $const
792             };
793             *$setmethod = sub {
794 10     10   16 my ( $self, $set ) = @_;
795 10 100       60 $set ? $self->$setflag( $self->$getflag | $const )
796             : $self->$setflag( $self->$getflag & ~$const );
797             };
798             }
799              
800             sub getcsize
801             {
802 0     0     my $self = shift;
803 0           my $cflag = $self->getcflag;
804             return {
805             CS5, 5,
806             CS6, 6,
807             CS7, 7,
808             CS8, 8,
809 0           }->{ $cflag & CSIZE };
810             }
811              
812             sub setcsize
813             {
814 0     0     my $self = shift;
815 0           my ( $bits ) = @_;
816 0           my $cflag = $self->getcflag;
817              
818 0           $cflag &= ~CSIZE;
819             $cflag |= {
820             5, CS5,
821             6, CS6,
822             7, CS7,
823             8, CS8,
824 0           }->{ $bits };
825              
826 0           $self->setcflag( $cflag );
827             }
828              
829             sub getparity
830             {
831 0     0     my $self = shift;
832 0           my $cflag = $self->getcflag;
833 0 0         return 'n' unless $cflag & PARENB;
834 0 0         return 'o' if $cflag & PARODD;
835 0           return 'e';
836             }
837              
838             sub setparity
839             {
840 0     0     my $self = shift;
841 0           my ( $parity ) = @_;
842 0           my $cflag = $self->getcflag;
843              
844 0 0         $parity eq 'n' ? $cflag &= ~PARENB :
    0          
    0          
845             $parity eq 'o' ? $cflag |= PARENB|PARODD :
846             $parity eq 'e' ? ($cflag |= PARENB) &= ~PARODD :
847             croak "Unrecognised parity '$parity'";
848              
849 0           $self->setcflag( $cflag );
850             }
851              
852             sub getstop
853             {
854 0     0     my $self = shift;
855 0 0         return 2 if $self->getcflag & CSTOPB;
856 0           return 1;
857             }
858              
859             sub setstop
860             {
861 0     0     my $self = shift;
862 0           my ( $stop ) = @_;
863 0           my $cflag = $self->getcflag;
864              
865 0 0         $stop == 1 ? $cflag &= ~CSTOPB :
    0          
866             $stop == 2 ? $cflag |= CSTOPB :
867             croak "Unrecognised stop '$stop'";
868              
869 0           $self->setcflag( $cflag );
870             }
871              
872             sub cfmakeraw
873             {
874 0     0     my $self = shift;
875              
876             # Coped from bit manipulations in termios(3)
877 0           $self->setiflag( $self->getiflag & ~( IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON ) );
878 0           $self->setoflag( $self->getoflag & ~( OPOST ) );
879 0           $self->setlflag( $self->getlflag & ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN ) );
880 0           $self->setcflag( $self->getcflag & ~( CSIZE | PARENB ) | CS8 );
881             }
882              
883             =head1 TODO
884              
885             =over 4
886              
887             =item *
888              
889             Adding more getflag_*/setflag_* convenience wrappers
890              
891             =back
892              
893             =head1 SEE ALSO
894              
895             =over 4
896              
897             =item *
898              
899             L - Import Tty control constants
900              
901             =back
902              
903             =head1 AUTHOR
904              
905             Paul Evans
906              
907             =cut
908              
909             0x55AA;