| 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__ |