File Coverage

lib/Test/Device/SerialPort.pm
Criterion Covered Total %
statement 404 522 77.3
branch 135 210 64.2
condition 21 41 51.2
subroutine 95 116 81.9
pod 0 90 0.0
total 655 979 66.9


line stmt bran cond sub pod time code
1             # $Id: $
2              
3             package Test::Device::SerialPort;
4              
5 3     3   99057 use Carp;
  3         12  
  3         340  
6 3     3   3991 use Data::Dumper;
  3         41205  
  3         416  
7              
8             BEGIN {
9 3 50 33 3   41 if ($^O eq "MSWin32" || $^O eq "cygwin") {
10 0         0 eval "use Win32";
11 0 0       0 warn "Timing Tests unavailable: $@\n" if ($@);
12             } else {
13 3     3   189 eval "use POSIX";
  3         3442  
  3         48234  
  3         25  
14             }
15             } # end BEGIN
16              
17 3     3   17835 use strict;
  3         7  
  3         404  
18 3     3   18 use warnings;
  3         6  
  3         2318  
19              
20             require Exporter;
21              
22             our $VERSION = '0.05';
23             our @ISA = qw(Exporter);
24             our @EXPORT= qw();
25             our @EXPORT_OK= qw();
26             our %EXPORT_TAGS = (STAT => [qw( MS_CTS_ON MS_DSR_ON
27             MS_RING_ON MS_RLSD_ON
28             MS_DTR_ON MS_RTS_ON
29             ST_BLOCK ST_INPUT
30             ST_OUTPUT ST_ERROR
31             TIOCM_CD TIOCM_RI
32             TIOCM_DSR TIOCM_DTR
33             TIOCM_CTS TIOCM_RTS
34             TIOCM_LE
35             )],
36              
37             PARAM => [qw( LONGsize SHORTsize OS_Error
38             nocarp yes_true )]);
39              
40             Exporter::export_ok_tags('STAT', 'PARAM');
41              
42             $EXPORT_TAGS{ALL} = \@EXPORT_OK;
43              
44             #### Package variable declarations ####
45              
46             my $cfg_file_sig="Test::Device::SerialPort_Configuration_File -- DO NOT EDIT --\n";
47              
48             my %Yes_resp = (
49             "YES" => 1,
50             "Y" => 1,
51             "ON" => 1,
52             "TRUE" => 1,
53             "T" => 1,
54             "1" => 1
55             );
56              
57             # mostly for test suite
58             my %Bauds = (
59             1200 => 1,
60             2400 => 1,
61             9600 => 1,
62             57600 => 1,
63             19200 => 1,
64             115200 => 1
65             );
66              
67             my %Handshakes = (
68             "none" => 1,
69             "rts" => 1,
70             "xoff" => 1
71             );
72              
73             my %Parities = (
74             "none" => 1,
75             "odd" => 1,
76             "even" => 1
77             );
78              
79             my %Databits = (
80             5 => 1,
81             6 => 1,
82             7 => 1,
83             8 => 1
84             );
85              
86             my %Stopbits = (
87             1 => 1,
88             2 => 1
89             );
90              
91             my @binary_opt = (0, 1);
92             my @byte_opt = (0, 255);
93              
94             ## undef forces computation on first usage
95             my $ms_per_tick=undef;
96              
97             my $Babble = 0;
98             my $testactive = 0; # test mode active
99              
100             # parameters that must be included in a "save" and "checking subs"
101              
102             my %validate = (
103             ALIAS => "alias",
104             BAUD => "baudrate",
105             BINARY => "binary",
106             DATA => "databits",
107             E_MSG => "error_msg",
108             EOFCHAR => "eof_char",
109             ERRCHAR => "error_char",
110             EVTCHAR => "event_char",
111             HSHAKE => "handshake",
112             PARITY => "parity",
113             PARITY_EN => "parity_enable",
114             RCONST => "read_const_time",
115             READBUF => "set_read_buf",
116             RINT => "read_interval",
117             RTOT => "read_char_time",
118             STOP => "stopbits",
119             U_MSG => "user_msg",
120             WCONST => "write_const_time",
121             WRITEBUF => "set_write_buf",
122             WTOT => "write_char_time",
123             XOFFCHAR => "xoff_char",
124             XOFFLIM => "xoff_limit",
125             XONCHAR => "xon_char",
126             XONLIM => "xon_limit",
127             );
128              
129             ## simplified from Device::SerialPort version since emulation can be imperfect
130             ## and only the test suite really uses this function
131             sub init_ms_per_tick
132             {
133 2     2 0 5 my $from_posix=undef;
134 2         5 my $errors="";
135              
136             # To find the real "CLK_TCK" value, it is *best* to query sysconf
137             # for it. However, this requires access to _SC_CLK_TCK. In
138             # modern versions of Perl (and libc) these this is correctly found
139             # in the POSIX module. Device::SerialPort tries several alternates
140             # but we won't.
141 2         5 eval { $from_posix = POSIX::sysconf(&POSIX::_SC_CLK_TCK); };
  2         18  
142 2 50       11 if ($@) {
143 0         0 warn "_SC_CLK_TCK not found during compilation: $@\n";
144             }
145 2 50       7 if ($from_posix) {
146 2         8 $ms_per_tick = 1000.0 / $from_posix;
147             }
148 2         6 $ms_per_tick = 10; # a plausible default for emulation
149             }
150              
151             sub get_tick_count {
152 24 50   24 0 4001190 if ($^O eq "MSWin32") {
153 0         0 return Win32::GetTickCount();
154             }
155             # POSIX clone of Win32::GetTickCount
156              
157 24 100       90 unless (defined($ms_per_tick)) {
158 2         9 init_ms_per_tick();
159             }
160              
161 24         296 my ($real2, $user2, $system2, $cuser2, $csystem2) = POSIX::times();
162 24         72 $real2 *= $ms_per_tick;
163             ## printf "real2 = %8.0f\n", $real2;
164 24         101 return int $real2;
165             }
166              
167 3     3   20 use constant SHORTsize => 0xffff; # mostly for AltPort test
  3         8  
  3         221  
168 3     3   15 use constant LONGsize => 0xffffffff;
  3         6  
  3         16057  
169              
170 15     15 0 394 sub nocarp { return $testactive }
171              
172             sub yes_true {
173 26     26 0 62 my $choice = uc shift;
174             ## warn "WCB choice=$choice\n";
175 26 100       131 return 1 if (exists $Yes_resp{$choice});
176 11         51 return 0;
177             }
178              
179             sub debug {
180             ## warn Dumper \@_;
181 27   100 27 0 725 my $self = shift || '';
182 27 100       69 return @binary_opt if (wantarray);
183 25 100       59 if (ref($self)) {
184 6 100       16 if (@_) { $self->{"_debug"} = yes_true ( shift ); }
  2         6  
185             else {
186 4         8 my $tmp = $self->{"_debug"};
187             ## warn "WCB-B, $tmp\n";
188 4 50       11 nocarp || carp "Debug level: $self->{ALIAS} = $tmp";
189 4         20 return $self->{"_debug"};
190             }
191             } else {
192             ## warn "WCB-C\n";
193 19 100       42 if ($self =~ /Port/) {
194             # in case someone uses the pseudo-hash calling style
195             # obj->debug on an "unblessed" $obj (old test cases)
196 1         3 $self = shift;
197             }
198 19 100       32 if ($self) { $Babble = yes_true ( $self ); }
  17         32  
199             else {
200 2 50       5 nocarp || carp "Debug Class = $Babble";
201 2         12 return $Babble;
202             }
203             }
204             }
205              
206              
207             sub new
208             {
209 3     3 0 671 my($ref, $port) = @_;
210 3   33     35 my $class = ref($ref) || $ref;
211             # real ports start with some values, these are just for init
212 3         101 my $self = {
213             _device => $port,
214             _alias => $port,
215             _are_match => [ "\n" ], # as programmed
216             _compiled_match => [ "\n" ], # with -re compiled using qr//
217             _baudrate => 9600,
218             _parity => 'none',
219             _handshake => 'none',
220             _databits => 8,
221             _stopbits => 1,
222             _user_msg => 0,
223             _error_msg => 0,
224             _read_char_time => 0,
225             _read_const_time => 0,
226             _no_random_data => 0, # for test suite only
227             _debug => 0, # for test suite only
228             _fake_status => 0, # for test suite only
229             _fake_input => chr(0xa5), # X10 CM11 wakeup
230             _rx_bufsize => 4096, # Win32 compatibility
231             _tx_bufsize => 4096,
232             _LOOK => "", # for lookfor and streamline
233             _LASTLOOK => "",
234             _LMATCH => "",
235             _LPATT => "",
236             _LATCH => 0, # for test suite only
237             _BLOCK => 0 # for test suite only
238             };
239 3 50 33     26 if ($^O eq "MSWin32" && $self->{_device} =~ /^COM\d+$/io) {
240 0         0 $self->{_device} = '\\\\.\\' . $self->{_device};
241             # required for Win32 COM10++, done for all to support testing
242             }
243 3         29 return bless ($self, $class);
244             }
245              
246             ## emulate the methods called by CM17.pm
247              
248 6     6 0 2261 sub dtr_active {1}
249              
250 6     6 0 5085 sub rts_active {1}
251              
252             sub pulse_break_on {
253 2     2 0 25 my $self = shift;
254 2   50     13 my $delay = shift || 1; # length of pulse, default to minimum
255 2         1000814 select (undef, undef, undef, $delay/500);
256 2         36 return 1;
257             }
258              
259             sub pulse_dtr_off { # "1" bit
260 2     2 0 22 my $self = shift;
261 2   50     9 my $delay = shift || 1; # length of pulse, default to minimum
262 2         800864 select (undef, undef, undef, $delay/500);
263 2         36 return 1;
264             }
265              
266             ## the select() call sleeps for twice $delay/1000 seconds
267             ## in Win32::SerialPort or Device::SerialPort, this method turns the
268             ## DTR signal OFF, waits $delay, then turns DTR back ON and waits $delay.
269             ## $delay is the desired duration of the pulse in milliseconds.
270             ## $delay is also used as the "recovery time" after a pulse.
271             ## DTR is a hardware signal wired to a pin on the serial port connector.
272              
273             sub pulse_rts_off { # "0" bit
274 2     2 0 45 my $self = shift;
275 2   50     13 my $delay = shift || 1;
276 2         200643 select (undef, undef, undef, $delay/500);
277 2         39 return 1;
278             }
279              
280             sub pulse_dtr_on {
281 2     2 0 18 my $self = shift;
282 2   50     11 my $delay = shift || 1; # length of pulse, default to minimum
283 2         400642 select (undef, undef, undef, $delay/500);
284 2         62 return 1;
285             }
286              
287             sub pulse_rts_on {
288 2     2 0 19 my $self = shift;
289 2   50     8 my $delay = shift || 1; # length of pulse, default to minimum
290 2         600813 select (undef, undef, undef, $delay/500);
291 2         67 return 1;
292             }
293              
294             ## Win32 version which allows setting Blocking and Error bitmasks for test
295             ## backwards compatiblity requires Errors be set first
296              
297             sub is_status {
298 5     5 0 3482 my $self = shift;
299              
300 5 100 66     35 if (@_ and $testactive) {
301 3         9 $self->{"_LATCH"} |= shift;
302 3   100     19 $self->{"_BLOCK"} = shift || 0;
303             }
304              
305 5         16 my @stat = ($self->{"_BLOCK"}, 0, 0);
306 5         9 $self->{"_BLOCK"} = 0;
307 5         11 push @stat, $self->{"_LATCH"};
308 5         28 return @stat;
309             }
310              
311             sub reset_error {
312 2     2 0 4236 my $self = shift;
313 2         8 my $was = $self->{"_LATCH"};
314 2         5 $self->{"_LATCH"} = 0;
315 2         7 return $was;
316             }
317              
318             sub status {
319 0     0 0 0 my $self = shift;
320 0         0 my @stat = $self->is_status;
321 0 0       0 return unless (scalar @stat);
322 0         0 return @stat;
323             }
324              
325             ## The fakestatus method does the same for modemline bits
326              
327             sub fakestatus {
328 0     0 0 0 my $self = shift;
329 0 0       0 return unless (@_);
330 0         0 $self->{"_fake_status"} = shift;
331             }
332              
333             ## In the emulator, the input method returns a character string as if
334             ## those characters had been read from the serial port. It returns
335             ## all the characters at once and sets the input buffer to 'empty'
336              
337             sub input {
338 16 50   16 0 62 return undef unless (@_ == 1);
339 16         24 my $self = shift;
340 16         28 my $result = "";
341              
342 16 100       1216 if ($self->{"_fake_input"}) {
343 8         98 $result = $self->{"_fake_input"};
344 8         19 $self->{"_fake_input"} = "";
345             }
346 16         43 return $result;
347             }
348              
349             sub save {
350 2     2 0 6 my $self = shift;
351 2 50       10 return unless (@_);
352              
353 2         13 my $filename = shift;
354 2 50       317 unless ( open CF, ">$filename" ) {
355             #carp "can't open file: $filename";
356 0         0 return undef;
357             }
358 2         35 print CF "$cfg_file_sig";
359 2         10 print CF "$self->{_device}\n";
360             # used to "reopen" so must be DEVICE
361 2         161 close CF;
362 2         13 1;
363             }
364              
365             sub start {
366 0     0 0 0 my $proto = shift;
367 0   0     0 my $class = ref($proto) || $proto;
368              
369 0 0       0 return unless (@_);
370 0         0 my $filename = shift;
371              
372 0 0       0 unless ( open CF, "<$filename" ) {
373 0         0 carp "can't open file: $filename: $!";
374 0         0 return;
375             }
376 0         0 my ($signature, $name) = ;
377 0         0 close CF;
378            
379 0 0       0 unless ( $cfg_file_sig eq $signature ) {
380 0         0 carp "Invalid signature in $filename: $signature";
381 0         0 return;
382             }
383 0         0 chomp $name;
384 0         0 my $self = new ($class, $name);
385 0 0       0 return 0 unless ($self);
386 0         0 return $self;
387             }
388              
389              
390             sub are_match {
391 5     5 0 14060 my $self = shift;
392 5         12 my $pat;
393 5         57 my $re_next = 0;
394 5 100       24 if (@_) {
395 3         7 @{ $self->{"_are_match"} } = @_;
  3         18  
396 3         6 @{ $self->{"_compiled_match"} } = ();
  3         14  
397 3         13 while ($pat = shift) {
398 8 100       20 if ($re_next) {
399 1         2 $re_next = 0;
400 1         109 eval 'push (@{ $self->{"_compiled_match"} }, qr/$pat/)';
401             } else {
402 7         7 push (@{ $self->{"_compiled_match"} }, $pat);
  7         17  
403             }
404 8 100       32 if ($pat eq "-re") {
405 1         3 $re_next++;
406             }
407             }
408             }
409 5         11 return @{ $self->{"_are_match"} };
  5         33  
410             }
411              
412              
413             # Set the baudrate
414             sub baudrate
415             {
416 11     11 0 1886 my($self, $baud) = @_;
417 11 100       41 if ($baud) {
418 4 100       23 return unless (exists $Bauds{$baud});
419 2         6 $self->{_baudrate} = $baud;
420             }
421 9 100       31 if (wantarray) {
422 2         18 return (keys %Bauds);
423             }
424 7         50 return $self->{_baudrate};
425             }
426              
427             # Device::SerialPort::buffers() is a fake for Windows compatibility
428             sub buffers
429             {
430 7     7 0 2486 my $self = shift;
431 7 100       29 if (@_) {
432 4 100       219 return unless (@_ == 2);
433 2         8 $self->{_rx_bufsize} = shift;
434 2         7 $self->{_tx_bufsize} = shift;
435             }
436 5 100       53 return wantarray ? ($self->{_rx_bufsize}, $self->{_tx_bufsize}) : 1;
437             }
438              
439             # true/false capabilities (read only)
440             # currently just constants in the POSIX case
441              
442             # If this class implements wait_modemlines()
443             sub can_wait_modemlines
444             {
445 0     0 0 0 return(1);
446             }
447              
448             sub can_modemlines
449             {
450 0     0 0 0 return(0); # option on some unix
451             }
452              
453             sub can_intr_count
454             {
455 0     0 0 0 return(0); # option on some unix
456             }
457              
458             sub can_status
459             {
460 0     0 0 0 return(1);
461             }
462              
463             sub can_baud
464             {
465 2     2 0 395 return(1);
466             }
467              
468             sub can_databits
469             {
470 2     2 0 10 return(1);
471             }
472              
473             sub can_stopbits
474             {
475 2     2 0 10 return(1);
476             }
477              
478             sub can_dtrdsr
479             {
480 2     2 0 9 return(1);
481             }
482              
483             sub can_handshake
484             {
485 2     2 0 8 return(1);
486             }
487              
488             sub can_parity_check
489             {
490 2     2 0 16 return(1);
491             }
492              
493             sub can_parity_config
494             {
495 2     2 0 76 return(1);
496             }
497              
498             sub can_parity_enable
499             {
500 2     2 0 9 return(1);
501             }
502              
503             sub can_rlsd
504             {
505 2 50   2 0 13 return ($^O eq 'MSWin32') ? 1 : 0;
506             }
507              
508             sub can_rlsd_config
509             {
510 0     0 0 0 return(1);
511             }
512              
513             sub can_16bitmode
514             {
515 2     2 0 10 return(0); # Win32 specific default off
516             }
517              
518             sub can_ioctl
519             {
520 2 50   2 0 19 return ($^O eq 'MSWin32') ? 0 : 1; # unix specific
521             }
522              
523             sub is_rs232
524             {
525 2     2 0 9 return(1);
526             }
527              
528             sub can_arbitrary_baud
529             {
530 0     0 0 0 return(0); # unix specific default off
531             }
532              
533             sub is_modem
534             {
535 2     2 0 10 return(0); # Win32 specific default off
536             }
537              
538             sub can_rts
539             {
540 0     0 0 0 return(1);
541             }
542              
543             sub can_rtscts
544             {
545 4     4 0 2319 return(1);
546             }
547              
548             sub can_xonxoff
549             {
550 2     2 0 10 return(1);
551             }
552              
553             sub can_xon_char
554             {
555 2     2 0 9 return(1);
556             }
557              
558             sub can_spec_char
559             {
560 2     2 0 12 return(0);
561             }
562              
563             sub binary
564             {
565 3     3 0 15 return(1);
566             }
567              
568             sub can_write_done
569             {
570 0     0 0 0 return(0); # so test does not try to time
571             }
572              
573             sub write_done
574             {
575 0     0 0 0 return(0); #invalid with Solaris, VM and USB ports
576             }
577              
578             sub can_interval_timeout
579             {
580 2 50   2 0 25 return ($^O eq 'MSWin32') ? 1 : 0;
581             }
582              
583             sub can_total_timeout
584             {
585 2     2 0 10 return(1);
586             }
587              
588             ## for test suite only
589             sub set_no_random_data {
590 3     3 0 984 my $self = shift;
591 3 100       13 if (@_) { $self->{_no_random_data} = yes_true ( shift ) }
  1         5  
592 3         15 return $self->{_no_random_data};
593             }
594              
595             sub user_msg {
596 7     7 0 797 my $self = shift;
597 7 100       36 if (@_) { $self->{_user_msg} = yes_true ( shift ) }
  2         12  
598 7 100       58 return wantarray ? @binary_opt : $self->{_user_msg};
599             }
600              
601             sub error_msg {
602 7     7 0 696 my $self = shift;
603 7 100       28 if (@_) { $self->{_error_msg} = yes_true ( shift ) }
  2         8  
604 7 100       42 return wantarray ? @binary_opt : $self->{_error_msg};
605             }
606              
607              
608             sub close
609             {
610             # noop
611 2     2 0 1174 return(1);
612             }
613              
614             # Set databits
615             sub databits
616             {
617 11     11 0 1773 my($self, $databits) = @_;
618 11 100       40 if ($databits) {
619 4 100       26 return unless (exists $Databits{$databits});
620 2         33 $self->{_databits} = $databits;
621             }
622 9 100       39 if (wantarray) {
623 2         19 return (keys %Databits);
624             }
625 7         45 return $self->{_databits};
626             }
627              
628             # Set handshake type property
629             sub handshake
630             {
631 15     15 0 2097 my($self, $handshake) = @_;
632 15 100       49 if ($handshake) {
633 10 100       61 return unless (exists $Handshakes{$handshake});
634 8         27 $self->{_handshake} = $handshake;
635             }
636 13 100       54 if (wantarray) {
637 2         24 return (keys %Handshakes);
638             }
639 11         67 return $self->{_handshake};
640             }
641              
642             sub lookfor
643             {
644 12     12 0 9705 my $self = shift;
645 12 50       56 if ($self->{_no_random_data}) {
646             ## redirect to faster version without stty emulation
647 12         52 return $self->streamline(@_);
648             }
649 0         0 my $count = undef;
650 0 0       0 if( @_ )
651             {
652 0         0 $count = $_[0];
653             }
654              
655             # When count is defined, behave like read()
656 0 0       0 if( $count > 0 )
657             {
658 0         0 return $self->read($count);
659             }
660              
661             # Lookfor specific behaviour
662 0         0 my $look = 0;
663 0         0 my @patt = $self->are_match();
664              
665             # XXX What we do here?
666 0 0       0 if( ! @patt )
667             {
668 0         0 @patt = ("\n");
669             }
670              
671 0 0       0 if( rand(1) < 0.3 )
672             {
673 0         0 $look = 1;
674             }
675              
676 0 0       0 return '' unless $look;
677              
678             # Return random data with appended one of the user-defined patterns
679              
680 0         0 my $data = $self->_produce_data(10);
681 0         0 $data .= $patt[ rand(@patt) ];
682              
683 0         0 return($data);
684             }
685              
686             ## routines copied from Win32::SerialPort
687             sub lookclear {
688 9     9 0 9444 my $self = shift;
689 9 100 66     43 if (nocarp && (@_ == 1)) {
690 7         25 $self->{"_fake_input"} = shift;
691             }
692 9         20 $self->{"_LOOK"} = "";
693 9         24 $self->{"_LASTLOOK"} = "";
694 9         17 $self->{"_LMATCH"} = "";
695 9         17 $self->{"_LPATT"} = "";
696 9 50       27 return if (@_);
697 9         42 1;
698             }
699              
700             sub matchclear {
701 9     9 0 11618 my $self = shift;
702 9         24 my $found = $self->{"_LMATCH"};
703 9         22 $self->{"_LMATCH"} = "";
704 9 50       34 return if (@_);
705 9         49 return $found;
706             }
707              
708             sub lastlook {
709 15     15 0 35 my $self = shift;
710 15 50       56 return if (@_);
711 15         109 return ( $self->{"_LMATCH"}, $self->{"_LASTLOOK"},
712             $self->{"_LPATT"}, $self->{"_LOOK"} );
713             }
714              
715             sub streamline {
716 15     15 0 30 my $self = shift;
717 15         25 my $size = 0;
718 15 50       40 if (@_) { $size = shift; }
  0         0  
719 15         29 my $loc = "";
720 15         23 my $mpos;
721 15         19 my $count_in = 0;
722 15         21 my $string_in = "";
723 15         18 my $re_next = 0;
724 15         15 my $got_match = 0;
725 15         25 my $best_pos = 0;
726 15         25 my $pat;
727 15         24 my $match = "";
728 15         22 my $before = "";
729 15         17 my $after = "";
730 15         17 my $best_match = "";
731 15         18 my $best_before = "";
732 15         19 my $best_after = "";
733 15         18 my $best_pat = "";
734 15         179 $self->{"_LMATCH"} = "";
735 15         30 $self->{"_LPATT"} = "";
736              
737 15 50       42 if ( ! $self->{"_LOOK"} ) {
738 15         36 $loc = $self->{"_LASTLOOK"};
739             }
740              
741 15         49 $loc .= $self->input;
742 15         33 my $lenloc = length($loc);
743 15 50 33     61 if ($size && ($lenloc < $size)) {
744 0         0 warn "Test Suite streamline length mismatch: requested: $size\n\tgot: $lenloc, data: $loc\n";
745             }
746              
747 15 100       43 if ($loc ne "") {
748 12         30 $self->{"_LOOK"} .= $loc;
749 12         20 $count_in = 0;
750 12         19 foreach $pat ( @{ $self->{"_compiled_match"} } ) {
  12         40  
751 31 100       74 if ($pat eq "-re") {
752 3         6 $re_next++;
753 3         8 $count_in++;
754 3         7 next;
755             }
756 28 100       260 if ($re_next) {
    100          
757 3         4 $re_next = 0;
758 3 100       24 if ( $self->{"_LOOK"} =~ /$pat/s ) {
759 2         81 ( $match, $before, $after ) = ( $&, $`, $' );
760 2         4 $got_match++;
761 2         2 $mpos = length($before);
762 2 50       6 if ($mpos) {
763 2 100 66     40 next if ($best_pos && ($mpos > $best_pos));
764 1         3 $best_pos = $mpos;
765 1         2 $best_pat = $self->{"_are_match"}[$count_in];
766 1         3 $best_match = $match;
767 1         2 $best_before = $before;
768 1         2 $best_after = $after;
769             } else {
770 0         0 $self->{"_LPATT"} = $self->{"_are_match"}[$count_in];
771 0         0 $self->{"_LMATCH"} = $match;
772 0         0 $self->{"_LASTLOOK"} = $after;
773 0         0 $self->{"_LOOK"} = "";
774 0         0 return $before;
775             # pattern at start will be best
776             }
777             }
778             }
779             elsif (($mpos = index($self->{"_LOOK"}, $pat)) > -1) {
780 11         13 $got_match++;
781 11         24 $before = substr ($self->{"_LOOK"}, 0, $mpos);
782 11 100       20 if ($mpos) {
783 10 50 66     31 next if ($best_pos && ($mpos > $best_pos));
784 10         16 $best_pos = $mpos;
785 10         11 $best_pat = $pat;
786 10         12 $best_match = $pat;
787 10         15 $best_before = $before;
788 10         14 $mpos += length($pat);
789 10         24 $best_after = substr ($self->{"_LOOK"}, $mpos);
790             } else {
791 1         3 $self->{"_LPATT"} = $pat;
792 1         3 $self->{"_LMATCH"} = $pat;
793 1         3 $before = substr ($self->{"_LOOK"}, 0, $mpos);
794 1         4 $mpos += length($pat);
795 1         4 $self->{"_LASTLOOK"} = substr ($self->{"_LOOK"}, $mpos);
796 1         3 $self->{"_LOOK"} = "";
797 1         11 return $before;
798             # match at start will be best
799             }
800             }
801 26         44 $count_in++;
802             }
803 11 100       41 if ($got_match) {
804 9         13 $self->{"_LPATT"} = $best_pat;
805 9         16 $self->{"_LMATCH"} = $best_match;
806 9         13 $self->{"_LASTLOOK"} = $best_after;
807 9         11 $self->{"_LOOK"} = "";
808 9         60 return $best_before;
809             }
810             }
811 5         35 return "";
812             }
813              
814             # non-POSIX constants commonly defined in termios.ph
815 3     3   33 use constant CRTSCTS => 0;
  3         7  
  3         246  
816 3     3   15 use constant OCRNL => 0;
  3         31  
  3         136  
817 3     3   21 use constant ONLCR => 0;
  3         4  
  3         145  
818 3     3   46 use constant ECHOKE => 0;
  3         4  
  3         144  
819 3     3   126 use constant ECHOCTL => 0;
  3         6  
  3         273  
820 3     3   58 use constant TIOCM_LE => 0x001;
  3         18  
  3         127  
821 3     3   14 use constant TIOCM_CD => 0x040;
  3         4  
  3         128  
822 3     3   14 use constant TIOCM_RI => 0x080;
  3         4  
  3         116  
823 3     3   14 use constant TIOCM_CTS => 0x020;
  3         5  
  3         120  
824 3     3   14 use constant TIOCM_DSR => 0x100;
  3         4  
  3         549  
825             #
826             ## Next 4 use Win32 names for compatibility
827 6 50   6 0 37 sub MS_RLSD_ON { return ($^O eq 'MSWin32') ? 0x80 : TIOCM_CD; }
828 4 50   4 0 27 sub MS_RING_ON { return ($^O eq 'MSWin32') ? 0x40 : TIOCM_RI; }
829 5 50   5 0 36 sub MS_CTS_ON { return ($^O eq 'MSWin32') ? 0x10 : TIOCM_CTS; }
830 6 50   6 0 33 sub MS_DSR_ON { return ($^O eq 'MSWin32') ? 0x20 : TIOCM_DSR; }
831             #
832             # For POSIX completeness, but not on Win32
833 3     3   17 use constant TIOCM_RTS => 0x004;
  3         5  
  3         138  
834 3     3   14 use constant TIOCM_DTR => 0x002;
  3         5  
  3         261  
835 0     0 0 0 sub MS_RTS_ON { TIOCM_RTS; }
836 0     0 0 0 sub MS_DTR_ON { TIOCM_DTR; }
837             #
838             # "status"
839 3     3   22 use constant ST_BLOCK => 0; # status offsets for caller
  3         10  
  3         138  
840 3     3   113 use constant ST_INPUT => 1;
  3         6  
  3         307  
841 3     3   16 use constant ST_OUTPUT => 2;
  3         4  
  3         201  
842 3     3   14 use constant ST_ERROR => 3; # latched
  3         6  
  3         6060  
843             #
844             # Return the status of the serial line signals
845             # Randomly activate signals...
846             sub modemlines
847             {
848 2     2 0 21 my $self = shift;
849 2 50       14 return $self->{_fake_status} if ($self->{_no_random_data}); # Test Suite
850 2         5 my $status = 0;
851 2 100       16 $status |= MS_CTS_ON if rand(1) > 0.3;
852 2 50       14 $status |= MS_DSR_ON if rand(1) > 0.3;
853 2 50       19 $status |= MS_RING_ON if rand(1) > 0.95;
854 2 50       39 $status |= MS_RLSD_ON if rand(1) > 0.5;
855 2         11 return $status;
856             }
857              
858             # Set parity
859             sub parity
860             {
861 11     11 0 1570 my($self, $parity) = @_;
862 11 100       37 if ($parity) {
863 4 100       80 return unless (exists $Parities{$parity});
864 2         10 $self->{_parity} = $parity;
865             }
866 9 100       31 if (wantarray) {
867 2         14 return (keys %Parities);
868             }
869 7         47 return $self->{_parity};
870             }
871              
872              
873             sub parity_enable {
874 2     2 0 6 my $self = shift;
875 2 50       10 if (@_) {
876 2         16 $self->{_parity_enable} = yes_true( shift );
877             }
878 2 50       16 return wantarray ? @binary_opt : $self->{_parity_enable};
879             }
880              
881              
882              
883             # Produce random data
884             sub _produce_data
885             {
886 0     0   0 my($self, $bytes) = @_;
887 0         0 my @chars = ('A' .. 'Z', 0 .. 9, 'a' .. 'z' );
888 0         0 my $data = '';
889 0         0 my $len = int rand($bytes);
890              
891 0         0 for( 1 .. $len )
892             {
893 0         0 $data .= $chars[rand(@chars)];
894             }
895 0         0 return($data);
896             }
897              
898             # Empty transmit and receive buffers
899             sub purge_rx {
900 2     2 0 6 my $self = shift;
901 2         7 $self->{_rx_buf} = '';
902 2 50       12 return if (@_);
903 2         10 return 1;
904             }
905              
906             sub purge_tx {
907 2     2 0 1893 my $self = shift;
908 2         6 $self->{_tx_buf} = '';
909 2 50       12 return if (@_);
910 2         9 return 1;
911             }
912              
913             sub purge_all
914             {
915 2     2 0 6 my $self = shift;
916 2         6 $self->{_tx_buf} = '';
917 2         6 $self->{_rx_buf} = '';
918 2 50       11 return if (@_);
919 2         10 return 1;
920             }
921              
922             # Wait some time between a min and a max (seconds)
923             sub _random_wait
924             {
925 2     2   7 my($self, $min, $max) = @_;
926 2         498 my $time = $min + rand($max - $min);
927 2         447666 select(undef, undef, undef, $time);
928 2         14 return();
929             }
930              
931             # Read data from line. For us is "generate" some random
932             # data as it came from the serial line.
933             sub read
934             {
935 0     0 0 0 my($self, $bytes) = @_;
936 0         0 my $new_input = '';
937 0         0 my $buf;
938              
939             # for test suite only
940 0 0       0 if ($self->{_no_random_data}) {
941 0         0 $buf = $self->input();
942 0         0 $self->{_rx_buf} = '';
943 0         0 my $size = length($buf);
944 0 0       0 unless ($size == $bytes) {
945 0         0 warn "Test Suite input length mismatch: requested: $bytes\n\tgot: $size, data: $self->{_fake_input}\n";
946             }
947 0         0 return($size, $buf);
948             }
949              
950             # Wait some random time
951 0         0 $self->_random_wait(0, 0.5);
952              
953             # We can have or not input
954 0         0 my $have_input = rand(1);
955              
956 0 0       0 if( $have_input > 0.7 )
957             {
958 0         0 $new_input = $self->_produce_data($bytes);
959 0         0 $self->{_rx_buf} .= $new_input;
960             }
961              
962             # Empty read buffer
963 0         0 $buf = $self->{_rx_buf};
964 0         0 $self->{_rx_buf} = '';
965              
966 0         0 return(length($buf), $buf);
967             }
968              
969             sub read_char_time
970             {
971 5     5 0 10 my $self = shift;
972 5 100       26 if( @_ )
973             {
974 2         10 $self->{_read_char_time} = shift() / 1000;
975             }
976 5         29 return($self->{_read_char_time} * 1000);
977             }
978              
979             sub read_const_time
980             {
981 5     5 0 14 my $self = shift;
982 5 100       24 if( @_ )
983             {
984 2         9 $self->{_read_const_time} = shift() / 1000;
985             }
986 5         33 return($self->{_read_const_time} * 1000);
987             }
988              
989             sub read_interval
990             {
991 0     0 0 0 die qq(Can't locate object method "read_interval" via package "Device::SerialPort");
992             }
993              
994             # Set stopbits
995             sub stopbits
996             {
997 11     11 0 3033 my($self, $stopbits) = @_;
998 11 100       103 if ($stopbits) {
999 4 100       30 return unless (exists $Stopbits{$stopbits});
1000 2         8 $self->{_stopbits} = $stopbits;
1001             }
1002 9 100       35 if (wantarray) {
1003 2         15 return (keys %Stopbits);
1004             }
1005 7         48 return $self->{_stopbits};
1006             }
1007              
1008             # Randomly wait some time, and then return with status 1
1009             sub wait_modemlines
1010             {
1011 0     0 0 0 my $self = shift;
1012 0         0 $self->_random_wait(10, 60);
1013 0         0 return(1);
1014             }
1015              
1016             # Write data down the line
1017             sub write
1018             {
1019 2     2 0 507 my($self, $str) = @_;
1020 2         29 $self->_random_wait(0, 0.5);
1021 2         15 $self->{_tx_buf} .= $str;
1022 2         14 return(length($str));
1023             }
1024              
1025             ## this alternate write method decodes the commands sent to the CM11 and
1026             ## preloads the expected response via 'fakeinput'. Hence, it
1027             ## looks like a two-way conversation is occurring.
1028              
1029             sub cm11_write {
1030 0 0   0 0 0 return unless (@_ == 2);
1031 0         0 my $self = shift;
1032 0         0 my $wbuf = shift;
1033 0         0 my $response = "";
1034 0 0       0 return unless ($wbuf);
1035 0         0 my @loc_char = split (//, $wbuf);
1036 0         0 my $f_char = ord (shift @loc_char);
1037              
1038 0 0       0 if ($f_char == 0x00) {
    0          
1039             # start operation (sent after checksum is verified)
1040 0         0 $response = chr(0x55); # emulator will respond with 'done'
1041 0         0 $self->fakeinput($response);
1042 0         0 return 1;
1043             }
1044             elsif ($f_char == 0xc3) {
1045             # tell CM11 to send data waiting in the buffer
1046             # issued after CM11 sends "data available" message (0x5a)
1047 0         0 $response = chr(0x03).chr(0x02).chr(0x6e).chr(0x62);
1048             # Buffer contents which translate to 'A2AJ'
1049 0         0 $self->fakeinput($response);
1050 0         0 return 1;
1051             }
1052             else {
1053             # else just compute the checksum and pass the command on
1054             # for any other command written.
1055 0         0 my $ccount = 1;
1056 0         0 my $n_char = "";
1057 0         0 foreach $n_char (@loc_char) {
1058 0         0 $f_char += ord($n_char);
1059 0         0 $ccount++;
1060             }
1061 0         0 $response = chr($f_char & 0xff);
1062 0         0 $self->fakeinput($response);
1063 0         0 return $ccount;
1064             }
1065             }
1066              
1067             # Empty the write buffer
1068             sub write_drain
1069             {
1070 0     0 0 0 my($self) = @_;
1071 0         0 $self->{_tx_buf} = '';
1072 0         0 return(1);
1073             }
1074              
1075             sub buffer_max {
1076 4     4 0 712 my $self = shift;
1077 4 100       15 if (@_) {return undef; }
  2         7  
1078 2         8 return (4096, 4096);
1079             }
1080              
1081             sub device {
1082 1     1 0 2 my $self = shift;
1083 1 50       6 if (@_) { $self->{_device} = shift; }
  0         0  
1084             # should return true for legal names
1085 1         7 return $self->{_device};
1086             }
1087              
1088             sub alias {
1089 7     7 0 3047 my $self = shift;
1090 7 100       30 if (@_) { $self->{_alias} = shift; }
  2         7  
1091             # should return true for legal names
1092 7         42 return $self->{_alias};
1093             }
1094              
1095              
1096              
1097             # Write serial port settings into external files
1098             sub write_settings
1099             {
1100             # noop
1101 2     2 0 10 return(1);
1102             }
1103              
1104              
1105 0     0 0 0 sub OS_Error { print "Test::Device::SerialPort OS_Error\n"; }
1106              
1107             # test*.pl only - suppresses default messages
1108             sub set_test_mode_active {
1109 3 50   3 0 4106 return unless (@_ == 2);
1110 3         9 $testactive = $_[1]; # allow "off"
1111 3         9 my @fields = ();
1112 3         28 foreach my $item (keys %validate) {
1113 72         126 push @fields, "$item";
1114             }
1115 3         66 return @fields;
1116             }
1117              
1118             ;
1119              
1120             __END__