line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Device::Modem - a Perl class to interface generic modems (AT-compliant) |
2
|
|
|
|
|
|
|
# Copyright (C) 2002-2020 Cosimo Streppone, cosimo@cpan.org |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or |
5
|
|
|
|
|
|
|
# modify it under the same terms as Perl itself. |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful, |
8
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
9
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10
|
|
|
|
|
|
|
# Perl licensing terms for details. |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
package Device::Modem; |
13
|
|
|
|
|
|
|
our $VERSION = '1.59'; |
14
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
BEGIN { |
17
|
|
|
|
|
|
|
|
18
|
2
|
50
|
|
2
|
|
71810
|
if( index($^O, 'Win') >= 0 ) { # MSWin32 (and not darwin, cygwin, ...) |
19
|
|
|
|
|
|
|
|
20
|
0
|
|
|
|
|
0
|
require Win32::SerialPort; |
21
|
0
|
|
|
|
|
0
|
Win32::SerialPort->import; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# Import line status constants from Win32::SerialPort module |
24
|
0
|
|
|
|
|
0
|
*Device::Modem::MS_CTS_ON = *Win32::SerialPort::MS_CTS_ON; |
25
|
0
|
|
|
|
|
0
|
*Device::Modem::MS_DSR_ON = *Win32::SerialPort::MS_DSR_ON; |
26
|
0
|
|
|
|
|
0
|
*Device::Modem::MS_RING_ON = *Win32::SerialPort::MS_RING_ON; |
27
|
0
|
|
|
|
|
0
|
*Device::Modem::MS_RLSD_ON = *Win32::SerialPort::MS_RLSD_ON; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
} else { |
30
|
|
|
|
|
|
|
|
31
|
2
|
|
|
|
|
1612
|
require Device::SerialPort; |
32
|
2
|
|
|
|
|
65525
|
Device::SerialPort->import; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Import line status constants from Device::SerialPort module |
35
|
2
|
|
|
|
|
12
|
*Device::Modem::MS_CTS_ON = *Device::SerialPort::MS_CTS_ON; |
36
|
2
|
|
|
|
|
7
|
*Device::Modem::MS_DSR_ON = *Device::SerialPort::MS_DSR_ON; |
37
|
2
|
|
|
|
|
5
|
*Device::Modem::MS_RING_ON = *Device::SerialPort::MS_RING_ON; |
38
|
2
|
|
|
|
|
71
|
*Device::Modem::MS_RLSD_ON = *Device::SerialPort::MS_RLSD_ON; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
2
|
|
|
2
|
|
15
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
40
|
|
44
|
2
|
|
|
2
|
|
9
|
use Carp (); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
62
|
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# Constants definition |
47
|
2
|
|
|
2
|
|
12
|
use constant CTRL_Z => chr(26); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
229
|
|
48
|
2
|
|
|
2
|
|
13
|
use constant CR => "\r"; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
8611
|
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Connection defaults |
51
|
|
|
|
|
|
|
$Device::Modem::DEFAULT_PORT = index($^O, 'Win') >= 0 ? 'COM1' : '/dev/modem'; |
52
|
|
|
|
|
|
|
$Device::Modem::DEFAULT_INIT_STRING = 'S7=45 S0=0 L1 V1 X4 &c1 E1 Q0'; |
53
|
|
|
|
|
|
|
$Device::Modem::BAUDRATE = 19200; |
54
|
|
|
|
|
|
|
$Device::Modem::DATABITS = 8; |
55
|
|
|
|
|
|
|
$Device::Modem::STOPBITS = 1; |
56
|
|
|
|
|
|
|
$Device::Modem::HANDSHAKE= 'none'; |
57
|
|
|
|
|
|
|
$Device::Modem::PARITY = 'none'; |
58
|
|
|
|
|
|
|
$Device::Modem::TIMEOUT = 500; # milliseconds |
59
|
|
|
|
|
|
|
$Device::Modem::READCHARS= 130; |
60
|
|
|
|
|
|
|
$Device::Modem::WAITCMD = 200; # milliseconds |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Setup text and numerical response codes |
63
|
|
|
|
|
|
|
@Device::Modem::RESPONSE = ( 'OK', undef, 'RING', 'NO CARRIER', 'ERROR', undef, 'NO DIALTONE', 'BUSY' ); |
64
|
|
|
|
|
|
|
$Device::Modem::STD_RESPONSE = qr/^(OK|ERROR|COMMAND NOT SUPPORT)$/m; |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
#%Device::Modem::RESPONSE = ( |
67
|
|
|
|
|
|
|
# 'OK' => 'Command executed without errors', |
68
|
|
|
|
|
|
|
# 'RING' => 'Detected phone ring', |
69
|
|
|
|
|
|
|
# 'NO CARRIER' => 'Link not established or disconnected', |
70
|
|
|
|
|
|
|
# 'ERROR' => 'Invalid command or command line too long', |
71
|
|
|
|
|
|
|
# 'NO DIALTONE' => 'No dial tone, dialing not possible or wrong mode', |
72
|
|
|
|
|
|
|
# 'BUSY' => 'Remote terminal busy' |
73
|
|
|
|
|
|
|
#); |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# object constructor (prepare only object) |
76
|
|
|
|
|
|
|
sub new { |
77
|
0
|
|
|
0
|
1
|
|
my($proto,%aOpt) = @_; # Get reference to object |
78
|
|
|
|
|
|
|
# Options of object |
79
|
0
|
|
0
|
|
|
|
my $class = ref($proto) || $proto; # Get reference to class |
80
|
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
|
$aOpt{'ostype'} = $^O; # Store OSTYPE in object |
82
|
0
|
0
|
|
|
|
|
$aOpt{'ostype'} = 'windoze' if index( $aOpt{'ostype'}, 'Win' ) >= 0; |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# Initialize flags array |
85
|
0
|
|
|
|
|
|
$aOpt{'flags'} = {}; |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Start as not connected |
88
|
0
|
|
|
|
|
|
$aOpt{'CONNECTED'} = 0; |
89
|
|
|
|
|
|
|
|
90
|
0
|
|
0
|
|
|
|
$aOpt{'port'} ||= $Device::Modem::DEFAULT_PORT; |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# Instance log object |
93
|
0
|
|
0
|
|
|
|
$aOpt{'log'} ||= 'file'; |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# Force logging to file if this is windoze and user requested syslog mechanism |
96
|
0
|
0
|
0
|
|
|
|
$aOpt{'log'} = 'file' if( $aOpt{'ostype'} eq 'windoze' && $aOpt{'log'} =~ /syslog/i ); |
97
|
0
|
|
0
|
|
|
|
$aOpt{'loglevel'} ||= 'warning'; |
98
|
|
|
|
|
|
|
|
99
|
0
|
0
|
|
|
|
|
if( ! ref $aOpt{'log'} ) { |
100
|
0
|
|
|
|
|
|
my($method, @options) = split ',', delete $aOpt{'log'}; |
101
|
0
|
|
|
|
|
|
my $logclass = 'Device/Modem/Log/'.ucfirst(lc $method).'.pm'; |
102
|
0
|
|
|
|
|
|
my $package = 'Device::Modem::Log::'.ucfirst lc $method; |
103
|
0
|
|
|
|
|
|
eval { require $logclass; }; |
|
0
|
|
|
|
|
|
|
104
|
0
|
0
|
|
|
|
|
unless($@) { |
105
|
0
|
|
|
|
|
|
$aOpt{'_log'} = $package->new( $class, @options ); |
106
|
|
|
|
|
|
|
} else { |
107
|
0
|
|
|
|
|
|
print STDERR "Failed to require Log package: $@\n"; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
} else { |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# User passed an already instanced log object |
112
|
0
|
|
|
|
|
|
$aOpt{'_log'} = $aOpt{'log'}; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
0
|
0
|
0
|
|
|
|
if( ref $aOpt{'_log'} && $aOpt{'_log'}->can('loglevel') ) { |
116
|
0
|
|
|
|
|
|
$aOpt{'_log'}->loglevel($aOpt{'loglevel'}); |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
0
|
|
|
|
|
|
bless \%aOpt, $class; # Instance $class object |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub attention { |
123
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
124
|
0
|
|
|
|
|
|
$self->log->write('info', 'sending attention sequence...'); |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# Send attention sequence |
127
|
0
|
|
|
|
|
|
$self->atsend('+++'); |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# Wait for response |
130
|
0
|
|
|
|
|
|
$self->answer(); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub dial { |
134
|
0
|
|
|
0
|
1
|
|
my($self, $number, $timeout, $mode) = @_; |
135
|
0
|
|
|
|
|
|
my $ok = 0; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# Default timeout in seconds |
138
|
0
|
|
0
|
|
|
|
$timeout ||= 30; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
# Default is data calls |
141
|
0
|
0
|
0
|
|
|
|
if (! defined $mode) { |
|
|
0
|
|
|
|
|
|
142
|
0
|
|
|
|
|
|
$mode = 'DATA'; |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
# Numbers with ';' mean voice calls |
145
|
|
|
|
|
|
|
elsif ($mode =~ m{VOICE}i || $number =~ m{;}) { |
146
|
0
|
|
|
|
|
|
$mode = 'VOICE'; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
# Invalid input, or explicit 'DATA' call |
149
|
|
|
|
|
|
|
else { |
150
|
0
|
|
|
|
|
|
$mode = 'DATA'; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# Check if we have already dialed some number... |
154
|
0
|
0
|
|
|
|
|
if ($self->flag('CARRIER')) { |
155
|
0
|
|
|
|
|
|
$self->log->write( 'warning', 'line is already connected, ignoring dial()' ); |
156
|
0
|
|
|
|
|
|
return; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# Check if no number supplied |
160
|
0
|
0
|
|
|
|
|
if (! defined $number) { |
161
|
|
|
|
|
|
|
# |
162
|
|
|
|
|
|
|
# XXX Here we could enable ATDL command (dial last number) |
163
|
|
|
|
|
|
|
# |
164
|
0
|
|
|
|
|
|
$self->log->write( 'warning', 'cannot dial without a number!' ); |
165
|
0
|
|
|
|
|
|
return; |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# Remove all non number chars plus some others allowed |
169
|
|
|
|
|
|
|
# Thanks to Pierre Hilson for the `#' (UMTS) |
170
|
|
|
|
|
|
|
# and to Marek Jaros for the `;' (voice calls) |
171
|
0
|
|
|
|
|
|
$number =~ s{[^0-9,\(\)\*\-#;\sp]}{}g; |
172
|
|
|
|
|
|
|
|
173
|
0
|
|
|
|
|
|
my $suffix = ''; |
174
|
0
|
0
|
|
|
|
|
if ($mode eq 'VOICE') { |
175
|
0
|
|
|
|
|
|
$self->log->write('info', 'trying to make a voice call'); |
176
|
0
|
|
|
|
|
|
$suffix = ';'; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
# Dial number and wait for response |
180
|
0
|
0
|
|
|
|
|
if( length $number == 1 ) { |
181
|
0
|
|
|
|
|
|
$self->log->write('info', 'dialing address book number ['.$number.']' ); |
182
|
|
|
|
|
|
|
|
183
|
0
|
|
|
|
|
|
$self->atsend( 'ATDS' . $number . $suffix . CR ); |
184
|
|
|
|
|
|
|
} else { |
185
|
0
|
|
|
|
|
|
$self->log->write('info', 'dialing number ['.$number.']' ); |
186
|
0
|
|
|
|
|
|
$self->atsend( 'ATDT' . $number . $suffix . CR ); |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# XXX Check response times here (timeout!) |
190
|
0
|
|
|
|
|
|
my $ans = $self->answer( qr/[A-Z]/, $timeout * 1000 ); |
191
|
|
|
|
|
|
|
|
192
|
0
|
0
|
0
|
|
|
|
if( (index($ans,'CONNECT') > -1) || (index($ans,'RING') > -1) ) { |
193
|
0
|
|
|
|
|
|
$ok = 1; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
# Turn on/off `CARRIER' flag |
197
|
0
|
|
|
|
|
|
$self->flag('CARRIER', $ok); |
198
|
|
|
|
|
|
|
|
199
|
0
|
|
|
|
|
|
$self->log->write('info', 'dialing result = '.$ok); |
200
|
0
|
0
|
|
|
|
|
return wantarray ? ($ok, $ans) : $ok; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Enable/disable local echo of commands (enabling echo can cause everything else to fail, I think) |
204
|
|
|
|
|
|
|
sub echo { |
205
|
0
|
|
|
0
|
1
|
|
my($self, $lEnable) = @_; |
206
|
|
|
|
|
|
|
|
207
|
0
|
0
|
|
|
|
|
$self->log->write( 'info', ( $lEnable ? 'enabling' : 'disabling' ) . ' echo' ); |
208
|
0
|
0
|
|
|
|
|
$self->atsend( ($lEnable ? 'ATE1' : 'ATE0') . CR ); |
209
|
|
|
|
|
|
|
|
210
|
0
|
|
|
|
|
|
$self->answer($Device::Modem::STD_RESPONSE); |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
# Terminate current call (XXX not tested) |
214
|
|
|
|
|
|
|
sub hangup { |
215
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
216
|
|
|
|
|
|
|
|
217
|
0
|
|
|
|
|
|
$self->log->write('info', 'hanging up...'); |
218
|
0
|
|
|
|
|
|
$self->atsend( 'ATH0' . CR ); |
219
|
0
|
|
|
|
|
|
my $ok = $self->answer($Device::Modem::STD_RESPONSE); |
220
|
0
|
0
|
|
|
|
|
unless ($ok) { |
221
|
0
|
|
|
|
|
|
$self->attention(); |
222
|
0
|
|
|
|
|
|
$self->atsend( 'ATH0' . CR ); |
223
|
0
|
|
|
|
|
|
$self->answer($Device::Modem::STD_RESPONSE, 5000); |
224
|
|
|
|
|
|
|
} |
225
|
0
|
|
|
|
|
|
$self->_reset_flags(); |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# Checks if modem is enabled (for now, it works ok for modem OFF/ON case) |
229
|
|
|
|
|
|
|
sub is_active { |
230
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
231
|
0
|
|
|
|
|
|
my $lOk; |
232
|
|
|
|
|
|
|
|
233
|
0
|
|
0
|
|
|
|
$self->log->write('info', 'testing modem activity on port ' . ($self->options->{'port'} || '') ); |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
# Modem is active if already connected to a line |
236
|
0
|
0
|
|
|
|
|
if( $self->flag('CARRIER') ) { |
237
|
|
|
|
|
|
|
|
238
|
0
|
|
|
|
|
|
$self->log->write('info', 'carrier is '.$self->flag('CARRIER').', modem is connected, it should be active'); |
239
|
0
|
|
|
|
|
|
$lOk = 1; |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
} else { |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# XXX Old mode to test modem ... |
244
|
|
|
|
|
|
|
# Try sending an echo enable|disable command |
245
|
|
|
|
|
|
|
#$self->attention(); |
246
|
|
|
|
|
|
|
#$self->verbose(0); |
247
|
|
|
|
|
|
|
#$lOk = $self->verbose(1); |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
# If DSR signal is on, modem is active |
250
|
0
|
|
|
|
|
|
my %sig = $self->status(); |
251
|
0
|
|
|
|
|
|
$lOk = $sig{DSR}; |
252
|
0
|
|
|
|
|
|
undef %sig; |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# If we have no success, try to reset |
255
|
0
|
0
|
|
|
|
|
if( ! $lOk ) { |
256
|
0
|
|
|
|
|
|
$self->log->write('warning', 'modem not responding... trying to reset'); |
257
|
0
|
|
|
|
|
|
$lOk = $self->reset(); |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
0
|
|
|
|
|
|
$self->log->write('info', 'modem reset result = '.$lOk); |
263
|
|
|
|
|
|
|
|
264
|
0
|
|
|
|
|
|
return $lOk; |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# Take modem off hook, prepare to dial |
268
|
|
|
|
|
|
|
sub offhook { |
269
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
270
|
|
|
|
|
|
|
|
271
|
0
|
|
|
|
|
|
$self->log->write('info', 'taking off hook'); |
272
|
0
|
|
|
|
|
|
$self->atsend( 'ATH1' . CR ); |
273
|
|
|
|
|
|
|
|
274
|
0
|
|
|
|
|
|
$self->flag('OFFHOOK', 1); |
275
|
|
|
|
|
|
|
|
276
|
0
|
|
|
|
|
|
return 1; |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
# Get/Set S* registers value: S_register( number [, new_value] ) |
280
|
|
|
|
|
|
|
# returns undef on failure ( zero is a good value ) |
281
|
|
|
|
|
|
|
sub S_register { |
282
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
283
|
0
|
|
|
|
|
|
my $register = shift; |
284
|
0
|
|
|
|
|
|
my $value = 0; |
285
|
|
|
|
|
|
|
|
286
|
0
|
0
|
|
|
|
|
return unless $register; |
287
|
|
|
|
|
|
|
|
288
|
0
|
|
|
|
|
|
my $ok; |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# If `new_value' supplied, we want to update value of this register |
291
|
0
|
0
|
|
|
|
|
if( @_ ) { |
292
|
|
|
|
|
|
|
|
293
|
0
|
|
|
|
|
|
my $new_value = shift; |
294
|
0
|
|
|
|
|
|
$new_value =~ s|\D||g; |
295
|
0
|
|
|
|
|
|
$self->log->write('info', 'storing value ['.$new_value.'] into register S'.$register); |
296
|
0
|
|
|
|
|
|
$self->atsend( sprintf( 'AT S%02d=%d' . CR, $register, $new_value ) ); |
297
|
|
|
|
|
|
|
|
298
|
0
|
0
|
|
|
|
|
$value = ( index( $self->answer(), 'OK' ) != -1 ) ? $new_value : undef; |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
} else { |
301
|
|
|
|
|
|
|
|
302
|
0
|
|
|
|
|
|
$self->atsend( sprintf( 'AT S%d?' . CR, $register ) ); |
303
|
0
|
|
|
|
|
|
($ok, $value) = $self->parse_answer(); |
304
|
|
|
|
|
|
|
|
305
|
0
|
0
|
|
|
|
|
if( index($ok, 'OK') != -1 ) { |
306
|
0
|
|
|
|
|
|
$self->log->write('info', 'value of S'.$register.' register seems to be ['.$value.']'); |
307
|
|
|
|
|
|
|
} else { |
308
|
0
|
|
|
|
|
|
$value = undef; |
309
|
0
|
|
|
|
|
|
$self->log->write('err', 'error reading value of S'.$register.' register'); |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# Return updated value of register |
315
|
0
|
|
|
|
|
|
$self->log->write('info', 'S'.$register.' = '.$value); |
316
|
|
|
|
|
|
|
|
317
|
0
|
|
|
|
|
|
return $value; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# Repeat the last commands (this comes gratis with `A/' at-command) |
321
|
|
|
|
|
|
|
sub repeat { |
322
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
323
|
|
|
|
|
|
|
|
324
|
0
|
|
|
|
|
|
$self->log->write('info', 'repeating last command' ); |
325
|
0
|
|
|
|
|
|
$self->atsend( 'A/' . CR ); |
326
|
|
|
|
|
|
|
|
327
|
0
|
|
|
|
|
|
$self->answer(); |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# Complete modem reset |
331
|
|
|
|
|
|
|
sub reset { |
332
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
333
|
|
|
|
|
|
|
|
334
|
0
|
|
|
|
|
|
$self->log->write('warning', 'resetting modem on '.$self->{'port'} ); |
335
|
0
|
|
|
|
|
|
$self->hangup(); |
336
|
0
|
|
|
|
|
|
my $result = $self->send_init_string(); |
337
|
0
|
|
|
|
|
|
$self->_reset_flags(); |
338
|
0
|
|
|
|
|
|
return $result; |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
# Return an hash with the status of main modem signals |
342
|
|
|
|
|
|
|
sub status { |
343
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
344
|
0
|
|
|
|
|
|
$self->log->write('info', 'getting modem line status on '.$self->{'port'}); |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
# This also relies on Device::SerialPort |
347
|
0
|
|
|
|
|
|
my $status = $self->port->modemlines(); |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
# See top of module for these constants, exported by (Win32|Device)::SerialPort |
350
|
0
|
|
|
|
|
|
my %signal = ( |
351
|
|
|
|
|
|
|
CTS => $status & Device::Modem::MS_CTS_ON, |
352
|
|
|
|
|
|
|
DSR => $status & Device::Modem::MS_DSR_ON, |
353
|
|
|
|
|
|
|
RING => $status & Device::Modem::MS_RING_ON, |
354
|
|
|
|
|
|
|
RLSD => $status & Device::Modem::MS_RLSD_ON |
355
|
|
|
|
|
|
|
); |
356
|
|
|
|
|
|
|
|
357
|
0
|
|
|
|
|
|
$self->log->write('info', 'modem on '.$self->{'port'}.' status is ['.$status.']'); |
358
|
0
|
|
|
|
|
|
$self->log->write('info', "CTS=$signal{CTS} DSR=$signal{DSR} RING=$signal{RING} RLSD=$signal{RLSD}"); |
359
|
|
|
|
|
|
|
|
360
|
0
|
|
|
|
|
|
return %signal; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
# Of little use here, but nice to have it |
364
|
|
|
|
|
|
|
# restore_factory_settings( profile ) |
365
|
|
|
|
|
|
|
# profile can be 0 or 1 |
366
|
|
|
|
|
|
|
sub restore_factory_settings { |
367
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
368
|
0
|
|
|
|
|
|
my $profile = shift; |
369
|
0
|
0
|
|
|
|
|
$profile = 0 unless defined $profile; |
370
|
|
|
|
|
|
|
|
371
|
0
|
|
|
|
|
|
$self->log->write('warning', 'restoring factory settings '.$profile.' on '.$self->{'port'} ); |
372
|
0
|
|
|
|
|
|
$self->atsend( 'AT&F'.$profile . CR); |
373
|
|
|
|
|
|
|
|
374
|
0
|
|
|
|
|
|
$self->answer($Device::Modem::STD_RESPONSE); |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
# Store telephone number in modem's internal address book, to dial later |
378
|
|
|
|
|
|
|
# store_number( position, number ) |
379
|
|
|
|
|
|
|
sub store_number { |
380
|
0
|
|
|
0
|
1
|
|
my( $self, $position, $number ) = @_; |
381
|
0
|
|
|
|
|
|
my $ok = 0; |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
# Check parameters |
384
|
0
|
0
|
0
|
|
|
|
unless( defined($position) && $number ) { |
385
|
0
|
|
|
|
|
|
$self->log->write('warning', 'store_number() called with wrong parameters'); |
386
|
0
|
|
|
|
|
|
return $ok; |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
0
|
|
|
|
|
|
$self->log->write('info', 'storing number ['.$number.'] into memory ['.$position.']'); |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
# Remove all non-numerical chars from position and number |
392
|
0
|
|
|
|
|
|
$position =~ s/\D//g; |
393
|
0
|
|
|
|
|
|
$number =~ s/[^0-9,]//g; |
394
|
|
|
|
|
|
|
|
395
|
0
|
|
|
|
|
|
$self->atsend( sprintf( 'AT &Z%d=%s' . CR, $position, $number ) ); |
396
|
|
|
|
|
|
|
|
397
|
0
|
0
|
|
|
|
|
if( index( $self->answer(), 'OK' ) != -1 ) { |
398
|
0
|
|
|
|
|
|
$self->log->write('info', 'stored number ['.$number.'] into memory ['.$position.']'); |
399
|
0
|
|
|
|
|
|
$ok = 1; |
400
|
|
|
|
|
|
|
} else { |
401
|
0
|
|
|
|
|
|
$self->log->write('warning', 'error storing number ['.$number.'] into memory ['.$position.']'); |
402
|
0
|
|
|
|
|
|
$ok = 0; |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
|
405
|
0
|
|
|
|
|
|
return $ok; |
406
|
|
|
|
|
|
|
} |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
# Enable/disable verbose response messages against numerical response messages |
409
|
|
|
|
|
|
|
# XXX I need to manage also numerical values... |
410
|
|
|
|
|
|
|
sub verbose { |
411
|
0
|
|
|
0
|
1
|
|
my($self, $lEnable) = @_; |
412
|
|
|
|
|
|
|
|
413
|
0
|
0
|
|
|
|
|
$self->log->write( 'info', ( $lEnable ? 'enabling' : 'disabling' ) . ' verbose messages' ); |
414
|
0
|
0
|
|
|
|
|
$self->atsend( ($lEnable ? 'ATQ0V1' : 'ATQ0V0') . CR ); |
415
|
|
|
|
|
|
|
|
416
|
0
|
|
|
|
|
|
$self->answer($Device::Modem::STD_RESPONSE); |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
sub wait { |
420
|
0
|
|
|
0
|
1
|
|
my( $self, $msec ) = @_; |
421
|
|
|
|
|
|
|
|
422
|
0
|
|
|
|
|
|
$self->log->write('debug', 'waiting for '.$msec.' msecs'); |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
# Perhaps Time::HiRes here is not so useful, since I tested `select()' system call also on Windows |
425
|
0
|
|
|
|
|
|
select( undef, undef, undef, $msec / 1000 ); |
426
|
0
|
|
|
|
|
|
return 1; |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
# Set a named flag. Flags are now: OFFHOOK, CARRIER |
431
|
|
|
|
|
|
|
sub flag { |
432
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
433
|
0
|
|
|
|
|
|
my $cFlag = uc shift; |
434
|
|
|
|
|
|
|
|
435
|
0
|
0
|
|
|
|
|
$self->{'_flags'}->{$cFlag} = shift() if @_; |
436
|
|
|
|
|
|
|
|
437
|
0
|
|
|
|
|
|
$self->{'_flags'}->{$cFlag}; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
# reset internal flags that tell the status of modem (XXX to be extended) |
441
|
|
|
|
|
|
|
sub _reset_flags { |
442
|
0
|
|
|
0
|
|
|
my $self = shift(); |
443
|
|
|
|
|
|
|
|
444
|
0
|
|
|
|
|
|
map { $self->flag($_, 0) } |
|
0
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
'OFFHOOK', 'CARRIER'; |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
# initialize modem with some basic commands (XXX &C0) |
449
|
|
|
|
|
|
|
# send_init_string( [my_init_string] ) |
450
|
|
|
|
|
|
|
# my_init_string goes without 'AT' prefix |
451
|
|
|
|
|
|
|
sub send_init_string { |
452
|
0
|
|
|
0
|
1
|
|
my($self, $cInit) = @_; |
453
|
0
|
0
|
|
|
|
|
$cInit = $self->options->{'init_string'} unless defined $cInit; |
454
|
|
|
|
|
|
|
# If no Init string then do nothing! |
455
|
0
|
0
|
|
|
|
|
if ($cInit) { |
456
|
0
|
|
|
|
|
|
$self->attention(); |
457
|
0
|
|
|
|
|
|
$self->atsend('AT '.$cInit. CR ); |
458
|
0
|
|
|
|
|
|
return $self->answer($Device::Modem::STD_RESPONSE); |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
# returns log object reference or nothing if it is not defined |
463
|
|
|
|
|
|
|
sub log { |
464
|
0
|
|
|
0
|
1
|
|
my $me = shift; |
465
|
0
|
0
|
|
|
|
|
if( ref $me->{'_log'} ) { |
466
|
0
|
|
|
|
|
|
return $me->{'_log'}; |
467
|
|
|
|
|
|
|
} else { |
468
|
0
|
|
|
|
|
|
return {}; |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
} |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
# instances (Device|Win32)::SerialPort object and initializes communications |
473
|
|
|
|
|
|
|
sub connect { |
474
|
0
|
|
|
0
|
1
|
|
my $me = shift(); |
475
|
|
|
|
|
|
|
|
476
|
0
|
|
|
|
|
|
my %aOpt = (); |
477
|
0
|
0
|
|
|
|
|
if( @_ ) { |
478
|
0
|
|
|
|
|
|
%aOpt = @_; |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
0
|
|
|
|
|
|
my $lOk = 0; |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
# Set default values if missing |
484
|
0
|
|
0
|
|
|
|
$aOpt{'baudrate'} ||= $Device::Modem::BAUDRATE; |
485
|
0
|
|
0
|
|
|
|
$aOpt{'databits'} ||= $Device::Modem::DATABITS; |
486
|
0
|
|
0
|
|
|
|
$aOpt{'parity'} ||= $Device::Modem::PARITY; |
487
|
0
|
|
0
|
|
|
|
$aOpt{'stopbits'} ||= $Device::Modem::STOPBITS; |
488
|
0
|
|
0
|
|
|
|
$aOpt{'handshake'}||= $Device::Modem::HANDSHAKE; |
489
|
0
|
|
0
|
|
|
|
$aOpt{'max_reset_iter'} ||= 0; |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
# Store communication options in object |
492
|
0
|
|
|
|
|
|
$me->{'_comm_options'} = \%aOpt; |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
# Connect on serial (use different mod for win32) |
495
|
0
|
0
|
|
|
|
|
if( $me->ostype eq 'windoze' ) { |
496
|
0
|
|
|
|
|
|
$me->port( Win32::SerialPort->new($me->{'port'}) ); |
497
|
|
|
|
|
|
|
} else { |
498
|
0
|
|
|
|
|
|
$me->port( Device::SerialPort->new($me->{'port'}) ); |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
# Check connection |
502
|
0
|
0
|
|
|
|
|
unless( ref $me->port ) { |
503
|
0
|
|
|
|
|
|
$me->log->write( 'err', '*FAILED* connect on '.$me->{'port'} ); |
504
|
0
|
|
|
|
|
|
return $lOk; |
505
|
|
|
|
|
|
|
} |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
# Set communication options |
508
|
0
|
|
|
|
|
|
my $oPort = $me->port; |
509
|
0
|
|
|
|
|
|
$oPort -> baudrate ( $me->options->{'baudrate'} ); |
510
|
0
|
|
|
|
|
|
$oPort -> databits ( $me->options->{'databits'} ); |
511
|
0
|
|
|
|
|
|
$oPort -> stopbits ( $me->options->{'stopbits'} ); |
512
|
0
|
|
|
|
|
|
$oPort -> parity ( $me->options->{'parity'} ); |
513
|
0
|
|
|
|
|
|
$oPort -> handshake( $me->options->{'handshake'} ); |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
# Non configurable options |
516
|
0
|
|
|
|
|
|
$oPort -> buffers ( 10000, 10000 ); |
517
|
0
|
|
|
|
|
|
$oPort -> read_const_time ( 20 ); # was 500 |
518
|
0
|
|
|
|
|
|
$oPort -> read_char_time ( 0 ); |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
# read_interval() seems to be unsupported on Device::SerialPort, |
521
|
|
|
|
|
|
|
# while allowed on Win32::SerialPort... |
522
|
0
|
0
|
|
|
|
|
if( $oPort->can('read_interval') ) |
523
|
|
|
|
|
|
|
{ |
524
|
0
|
|
|
|
|
|
$oPort->read_interval( 20 ); |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
|
527
|
0
|
|
|
|
|
|
$oPort -> are_match ( 'OK' ); |
528
|
0
|
|
|
|
|
|
$oPort -> lookclear; |
529
|
|
|
|
|
|
|
|
530
|
0
|
0
|
|
|
|
|
unless ( $oPort -> write_settings ) { |
531
|
0
|
|
|
|
|
|
$me->log->write('err', '*FAILED* write_settings on '.$me->{'port'} ); |
532
|
0
|
|
|
|
|
|
return $lOk; |
533
|
|
|
|
|
|
|
} |
534
|
0
|
|
|
|
|
|
$oPort -> purge_all; |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
# Get the modems attention |
537
|
|
|
|
|
|
|
# Send multiple reset commands looking for a sensible response. |
538
|
|
|
|
|
|
|
# A small number of modems need time to settle down and start responding to the serial port |
539
|
0
|
|
|
|
|
|
my $iter = 0; |
540
|
0
|
|
|
|
|
|
my $ok = 0; |
541
|
0
|
|
|
|
|
|
my $blank = 0; |
542
|
0
|
|
0
|
|
|
|
while ( ($iter < $aOpt{'max_reset_iter'}) && ($ok < 2) && ($blank < 3) ) { |
|
|
|
0
|
|
|
|
|
543
|
0
|
|
|
|
|
|
$me->atsend('AT E0'. CR ); |
544
|
0
|
|
|
|
|
|
my $rslt = $me->answer($Device::Modem::STD_RESPONSE, 1500); |
545
|
|
|
|
|
|
|
# print "Res: $rslt \r\n"; |
546
|
0
|
|
|
|
|
|
$iter+=1; |
547
|
0
|
0
|
0
|
|
|
|
if ($rslt && $rslt =~ /^OK/) { |
548
|
0
|
|
|
|
|
|
$ok+=1; |
549
|
|
|
|
|
|
|
} else { |
550
|
0
|
|
|
|
|
|
$ok=0; |
551
|
|
|
|
|
|
|
} |
552
|
0
|
0
|
|
|
|
|
if (!$rslt) { |
553
|
0
|
|
|
|
|
|
$blank++; |
554
|
|
|
|
|
|
|
} else { |
555
|
0
|
|
|
|
|
|
$blank=0; |
556
|
|
|
|
|
|
|
} |
557
|
|
|
|
|
|
|
} |
558
|
0
|
0
|
|
|
|
|
if ($aOpt{'max_reset_iter'}) { |
559
|
0
|
|
|
|
|
|
$me->log->write('debug', "DEBUG CONNECT: $iter : $ok : $blank\n"); # DEBUG |
560
|
|
|
|
|
|
|
} |
561
|
0
|
|
|
|
|
|
$me-> log -> write('info', 'sending init string...' ); |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
# Set default initialization string if none supplied |
564
|
|
|
|
|
|
|
my $init_string = defined $me->options->{'init_string'} |
565
|
0
|
0
|
|
|
|
|
? $me->options->{'init_string'} |
566
|
|
|
|
|
|
|
: $Device::Modem::DEFAULT_INIT_STRING; |
567
|
|
|
|
|
|
|
|
568
|
0
|
|
0
|
|
|
|
my $init_response = $me->send_init_string($init_string) || ''; |
569
|
0
|
|
|
|
|
|
$me-> log -> write('debug', "init response: $init_response\n"); # DEBUG |
570
|
0
|
|
|
|
|
|
$me-> _reset_flags(); |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
# Disable local echo |
573
|
0
|
|
|
|
|
|
$me-> echo(0); |
574
|
|
|
|
|
|
|
|
575
|
0
|
|
|
|
|
|
$me-> log -> write('info', 'Ok connected' ); |
576
|
0
|
|
|
|
|
|
$me-> {'CONNECTED'} = 1; |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
# $^O is stored into object |
581
|
|
|
|
|
|
|
sub ostype { |
582
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
583
|
0
|
|
|
|
|
|
$self->{'ostype'}; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
# returns Device::SerialPort reference to hash options |
587
|
|
|
|
|
|
|
sub options { |
588
|
0
|
|
|
0
|
0
|
|
my $self = shift(); |
589
|
|
|
|
|
|
|
@_ ? $self->{'_comm_options'} = shift() |
590
|
0
|
0
|
|
|
|
|
: $self->{'_comm_options'}; |
591
|
|
|
|
|
|
|
} |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
# returns Device::SerialPort object handle |
594
|
|
|
|
|
|
|
sub port { |
595
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
596
|
|
|
|
|
|
|
|
597
|
0
|
0
|
|
|
|
|
if (@_) { |
598
|
0
|
|
|
|
|
|
return ($self->{'_comm_object'} = shift); |
599
|
|
|
|
|
|
|
} |
600
|
|
|
|
|
|
|
|
601
|
0
|
|
|
|
|
|
my $port_obj = $self->{'_comm_object'}; |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
# Maybe the port was disconnected? |
604
|
0
|
0
|
0
|
|
|
|
if (defined $self->{'CONNECTED'} && |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
605
|
|
|
|
|
|
|
$self->{'CONNECTED'} == 1 && # We were connected |
606
|
|
|
|
|
|
|
(! defined $port_obj || ! $port_obj)) { # Now we aren't anymore |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
# Avoid recursion on ourselves |
609
|
0
|
|
|
|
|
|
$self->{'CONNECTED'} = 0; |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
# Try to reconnect if possible |
612
|
0
|
|
|
|
|
|
my $connect_options = $self->options; |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
# No connect options probably because we didn't ever connect |
615
|
0
|
0
|
|
|
|
|
if (! $connect_options) { |
616
|
0
|
|
|
|
|
|
Carp::croak("Not connected"); |
617
|
|
|
|
|
|
|
} |
618
|
|
|
|
|
|
|
|
619
|
0
|
|
|
|
|
|
$self->connect(%{ $connect_options }); |
|
0
|
|
|
|
|
|
|
620
|
0
|
|
|
|
|
|
$port_obj = $self->{'_comm_object'}; |
621
|
|
|
|
|
|
|
} |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
# Still not connected? bail out |
624
|
0
|
0
|
0
|
|
|
|
if (! defined $port_obj || ! $port_obj) { |
625
|
0
|
|
|
|
|
|
Carp::croak("Not connected"); |
626
|
|
|
|
|
|
|
} |
627
|
|
|
|
|
|
|
|
628
|
0
|
|
|
|
|
|
return $port_obj; |
629
|
|
|
|
|
|
|
} |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
# disconnect serial port |
632
|
|
|
|
|
|
|
sub disconnect { |
633
|
0
|
|
|
0
|
1
|
|
my $me = shift; |
634
|
0
|
|
|
|
|
|
$me->port->close(); |
635
|
0
|
|
|
|
|
|
$me->log->write('info', 'Disconnected from '.$me->{'port'} ); |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
# Send AT command to device on serial port (command must include CR for now) |
639
|
|
|
|
|
|
|
sub atsend { |
640
|
0
|
|
|
0
|
1
|
|
my( $me, $msg ) = @_; |
641
|
0
|
|
|
|
|
|
my $cnt = 0; |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
# Write message on port |
644
|
0
|
|
|
|
|
|
$me->port->purge_all(); |
645
|
0
|
|
|
|
|
|
$cnt = $me->port->write($msg); |
646
|
|
|
|
|
|
|
|
647
|
0
|
|
|
|
|
|
my $lbuf=length($msg); |
648
|
0
|
|
|
|
|
|
my $ret; |
649
|
|
|
|
|
|
|
|
650
|
0
|
|
|
|
|
|
while ($cnt < $lbuf) |
651
|
|
|
|
|
|
|
{ |
652
|
0
|
|
|
|
|
|
$ret = $me->port->write(substr($msg, $cnt)); |
653
|
0
|
|
|
|
|
|
$me->write_drain(); |
654
|
0
|
0
|
|
|
|
|
last unless defined $ret; |
655
|
0
|
|
|
|
|
|
$cnt += $ret; |
656
|
|
|
|
|
|
|
} |
657
|
|
|
|
|
|
|
|
658
|
0
|
|
|
|
|
|
$me->log->write('debug', 'atsend: wrote '.$cnt.'/'.length($msg).' chars'); |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
# If wrote all chars of `msg', we are successful |
661
|
0
|
|
|
|
|
|
return $cnt == length $msg; |
662
|
|
|
|
|
|
|
} |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
# Call write_drain() if platform allows to (no call for Win32) |
665
|
|
|
|
|
|
|
sub write_drain |
666
|
|
|
|
|
|
|
{ |
667
|
0
|
|
|
0
|
1
|
|
my $me = shift; |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
# No write_drain() call for win32 systems |
670
|
0
|
0
|
|
|
|
|
return if $me->ostype eq 'windoze'; |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
# No write_drain() if no port object available |
673
|
0
|
|
|
|
|
|
my $port = $me->port; |
674
|
0
|
0
|
|
|
|
|
return unless $port; |
675
|
|
|
|
|
|
|
|
676
|
0
|
|
|
|
|
|
return $port->write_drain(); |
677
|
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
# answer() takes strings from the device until a pattern |
680
|
|
|
|
|
|
|
# is encountered or a timeout happens. |
681
|
|
|
|
|
|
|
sub _answer { |
682
|
0
|
|
|
0
|
|
|
my $me = shift; |
683
|
0
|
|
|
|
|
|
my($expect, $timeout) = @_; |
684
|
0
|
0
|
|
|
|
|
$expect = $Device::Modem::STD_RESPONSE if (! defined($expect)); |
685
|
0
|
0
|
|
|
|
|
$timeout = $Device::Modem::TIMEOUT if (! defined($timeout)); |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
# If we expect something, we must first match against serial input |
688
|
0
|
|
0
|
|
|
|
my $done = (defined $expect and $expect ne ''); |
689
|
|
|
|
|
|
|
|
690
|
0
|
0
|
0
|
|
|
|
$me->log->write('debug', 'answer: expecting ['.($expect||'').']'.($timeout ? ' or '.($timeout/1000).' seconds timeout' : '' ) ); |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
# Main read cycle |
693
|
0
|
|
|
|
|
|
my $cycles = 0; |
694
|
0
|
|
|
|
|
|
my $idle_cycles = 0; |
695
|
0
|
|
|
|
|
|
my $answer; |
696
|
0
|
|
|
|
|
|
my $start_time = time(); |
697
|
0
|
|
|
|
|
|
my $end_time = 0; |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
# If timeout was defined, check max time (timeout is in milliseconds) |
700
|
0
|
|
0
|
|
|
|
$me->log->write('debug', 'answer: timeout value is '.($timeout||'undef')); |
701
|
|
|
|
|
|
|
|
702
|
0
|
0
|
0
|
|
|
|
if( defined $timeout && $timeout > 0 ) { |
703
|
0
|
|
|
|
|
|
$end_time = $start_time + ($timeout / 1000); |
704
|
0
|
0
|
|
|
|
|
$end_time++ if $end_time == $start_time; |
705
|
0
|
|
|
|
|
|
$me->log->write( debug => 'answer: end time set to '.$end_time ); |
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
|
708
|
0
|
|
|
|
|
|
do { |
709
|
0
|
|
|
|
|
|
my ($what, $howmany); |
710
|
0
|
|
|
|
|
|
$what = $me->port->read(1) . $me->port->input; |
711
|
0
|
|
|
|
|
|
$howmany = length($what); |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
# Timeout count incremented only on empty readings |
714
|
0
|
0
|
0
|
|
|
|
if( defined $what && $howmany > 0 ) { |
|
|
0
|
|
|
|
|
|
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
# Add received chars to answer string |
717
|
0
|
|
|
|
|
|
$answer .= $what; |
718
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
# Check if buffer matches "expect string" |
720
|
0
|
0
|
|
|
|
|
if( defined $expect ) { |
721
|
0
|
|
|
|
|
|
my $copy = $answer; |
722
|
0
|
|
|
|
|
|
$copy =~ s/\r(\n)?/\n/g; # Convert line endings from "\r" or "\r\n" to "\n" |
723
|
0
|
0
|
0
|
|
|
|
$done = ( defined $copy && $copy =~ $expect ) ? 1 : 0; |
724
|
0
|
0
|
|
|
|
|
$me->log->write( debug => 'answer: matched expect: '.$expect ) if ($done); |
725
|
|
|
|
|
|
|
} |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
# Check if we reached max time for timeout (only if end_time is defined) |
728
|
|
|
|
|
|
|
} elsif( $end_time > 0 ) { |
729
|
|
|
|
|
|
|
|
730
|
0
|
0
|
|
|
|
|
$done = (time >= $end_time) ? 1 : 0; |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
# Read last chars in read queue |
733
|
0
|
0
|
|
|
|
|
if( $done ) |
734
|
|
|
|
|
|
|
{ |
735
|
0
|
|
|
|
|
|
$me->log->write('info', 'reached timeout max wait without response'); |
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
# Else we have done |
739
|
|
|
|
|
|
|
} else { |
740
|
|
|
|
|
|
|
|
741
|
0
|
|
|
|
|
|
$done = 1; |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
|
744
|
0
|
|
|
|
|
|
$me->log->write('debug', 'done='.$done.' end='.$end_time.' now='.time().' start='.$start_time ); |
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
} while (not $done); |
747
|
|
|
|
|
|
|
|
748
|
0
|
|
0
|
|
|
|
$me->log->write('info', 'answer: read ['.($answer||'').']' ); |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
# Flush receive and trasmit buffers |
751
|
0
|
|
|
|
|
|
$me->port->purge_all; |
752
|
|
|
|
|
|
|
|
753
|
0
|
|
|
|
|
|
return $answer; |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
} |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
sub answer { |
758
|
|
|
|
|
|
|
|
759
|
0
|
|
|
0
|
1
|
|
my $me = shift(); |
760
|
0
|
|
|
|
|
|
my $answer = $me->_answer(@_); |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
# Trim result of beginning and ending CR+LF (XXX) |
763
|
0
|
0
|
|
|
|
|
if( defined $answer ) { |
764
|
0
|
|
|
|
|
|
$answer =~ s/^[\r\n]+//; |
765
|
0
|
|
|
|
|
|
$answer =~ s/[\r\n]+$//; |
766
|
|
|
|
|
|
|
} |
767
|
|
|
|
|
|
|
|
768
|
0
|
|
0
|
|
|
|
$me->log->write('info', 'answer: `'.($answer||'').'\'' ); |
769
|
|
|
|
|
|
|
|
770
|
0
|
|
|
|
|
|
return $answer; |
771
|
|
|
|
|
|
|
} |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
# parse_answer() cleans out answer() result as response code + |
774
|
|
|
|
|
|
|
# useful information (useful in informative commands, for example |
775
|
|
|
|
|
|
|
# Gsm command AT+CGMI) |
776
|
|
|
|
|
|
|
sub parse_answer { |
777
|
0
|
|
|
0
|
1
|
|
my $me = shift; |
778
|
|
|
|
|
|
|
|
779
|
0
|
|
|
|
|
|
my $buff = $me->answer( @_ ); |
780
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
# Separate response code from information |
782
|
0
|
0
|
0
|
|
|
|
if( defined $buff && $buff ne '' ) { |
783
|
|
|
|
|
|
|
|
784
|
0
|
|
|
|
|
|
my @buff = split /[\r\n]+/o, $buff; |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
# Remove all empty lines before/after response |
787
|
0
|
|
|
|
|
|
shift @buff while $buff[0] =~ /^[\r\n]+/o; |
788
|
0
|
|
|
|
|
|
pop @buff while $buff[-1] =~ /^[\r\n]+/o; |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
# Extract responde code |
791
|
0
|
|
|
|
|
|
$buff = join( CR, @buff ); |
792
|
0
|
|
|
|
|
|
my $code = pop @buff; |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
return |
795
|
|
|
|
|
|
|
wantarray |
796
|
0
|
0
|
|
|
|
|
? ($code, @buff) |
797
|
|
|
|
|
|
|
: $buff; |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
} else { |
800
|
|
|
|
|
|
|
|
801
|
0
|
|
|
|
|
|
return ''; |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
} |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
1; |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
=head1 NAME |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
Device::Modem - Perl extension to talk to modem devices connected via serial port |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
=head1 WARNING |
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
This is B software, so use it at your own risk, |
816
|
|
|
|
|
|
|
and without B warranty! Have fun. |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
=head1 SYNOPSIS |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
use Device::Modem; |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
my $modem = Device::Modem->new( port => '/dev/ttyS1' ); |
823
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
if( $modem->connect( baudrate => 9600 ) ) { |
825
|
|
|
|
|
|
|
print "connected!\n"; |
826
|
|
|
|
|
|
|
} else { |
827
|
|
|
|
|
|
|
print "sorry, no connection with serial port!\n"; |
828
|
|
|
|
|
|
|
} |
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
$modem->attention(); # send `attention' sequence (+++) |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
($ok, $answer) = $modem->dial('02270469012'); # dial phone number |
833
|
|
|
|
|
|
|
$ok = $modem->dial(3); # 1-digit parameter = dial number stored in memory 3 |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
$modem->echo(1); # enable local echo (0 to disable) |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
$modem->offhook(); # Take off hook (ready to dial) |
838
|
|
|
|
|
|
|
$modem->hangup(); # returns modem answer |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
$modem->is_active(); # Tests whether modem device is active or not |
841
|
|
|
|
|
|
|
# So far it works for modem OFF/ modem ON condition |
842
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
$modem->reset(); # hangup + attention + restore setting 0 (Z0) |
844
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
$modem->restore_factory_settings(); # Handle with care! |
846
|
|
|
|
|
|
|
$modem->restore_factory_settings(1); # Same with preset profile 1 (can be 0 or 1) |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
$modem->send_init_string(); # Send initialization string |
849
|
|
|
|
|
|
|
# Now this is fixed to 'AT H0 Z S7=45 S0=0 Q0 V1 E0 &C0 X4' |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
# Get/Set value of S1 register |
852
|
|
|
|
|
|
|
my $S1 = $modem->S_register(1); |
853
|
|
|
|
|
|
|
my $S1 = $modem->S_register(1, 55); # Don't do that if you definitely don't know! |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
# Get status of managed signals (CTS, DSR, RLSD, RING) |
856
|
|
|
|
|
|
|
my %signal = $modem->status(); |
857
|
|
|
|
|
|
|
if( $signal{DSR} ) { print "Data Set Ready signal active!\n"; } |
858
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
# Stores this number in modem memory number 3 |
860
|
|
|
|
|
|
|
$modem->store_number(3, '01005552817'); |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
$modem->repeat(); # Repeat last command |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
$modem->verbose(1); # Normal text responses (0=numeric codes) |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
# Some raw AT commands |
867
|
|
|
|
|
|
|
$modem->atsend( 'ATH0' ); |
868
|
|
|
|
|
|
|
print $modem->answer(); |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
$modem->atsend( 'ATDT01234567' . Device::Modem::CR ); |
871
|
|
|
|
|
|
|
print $modem->answer(); |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
=head1 DESCRIPTION |
875
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
C class implements basic B device abstraction. |
877
|
|
|
|
|
|
|
It can be inherited by sub classes (as C), which are based on serial connections. |
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
=head2 Things C can do |
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
=over 4 |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
=item * |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
connect to a modem on your serial port |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
=item * |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
test if the modem is alive and working |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
=item * |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
dial a number and connect to a remote modem |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
=item * |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
work with registers and settings of the modem |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
=item * |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
issue standard or arbitrary C commands, getting results from modem |
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
=back |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
=head2 Things C can't do yet |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
=over 4 |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
=item * |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
Transfer a file to a remote modem |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
=item * |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
Control a terminal-like (or a PPP) connection. This should really not |
917
|
|
|
|
|
|
|
be very hard to do anyway. |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
=item * |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
Many others... |
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
=back |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
=head2 Things it will never be able to do |
926
|
|
|
|
|
|
|
|
927
|
|
|
|
|
|
|
=over 4 |
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
=item * |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
Coffee :-) |
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
=back |
934
|
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
=head2 Examples |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
In the `examples' directory, there are some scripts that should work without big problems, |
939
|
|
|
|
|
|
|
that you can take as (yea) examples: |
940
|
|
|
|
|
|
|
|
941
|
|
|
|
|
|
|
=over 4 |
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
=item `examples/active.pl' |
944
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
Tests if modem is alive |
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
=item `examples/caller-id.pl' |
948
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
Waits for an incoming call and displays date, time and phone number of the caller. |
950
|
|
|
|
|
|
|
Normally this is available everywhere, but you should check your local phone line |
951
|
|
|
|
|
|
|
and settings. |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
=item `examples/dial.pl' |
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
Dials a phone number and display result of call |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
=item `examples/shell.pl' |
958
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
(Very) poor man's minicom/hyperterminal utility |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
=item `examples/xmodem.pl' |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
First attempt at a test script to receive a file via xmodem protocol. |
964
|
|
|
|
|
|
|
Please be warned that this thing does not have a chance to work. It's |
965
|
|
|
|
|
|
|
only a (very low priority) work in progress... |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
If you want to help out, be welcome! |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
=back |
971
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
=head1 METHODS |
973
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
=head2 answer() |
975
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
One of the most used methods, waits for an answer from the device. It waits until |
977
|
|
|
|
|
|
|
$timeout (seconds) is reached (but don't rely on this time to be very correct) or until an |
978
|
|
|
|
|
|
|
expected string is encountered. Example: |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
$answer = $modem->answer( [$expect [, $timeout]] ) |
981
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
Returns C<$answer> that is the string received from modem stripped of all |
983
|
|
|
|
|
|
|
B and B chars B at the beginning and at the end of the |
984
|
|
|
|
|
|
|
string. No in-between B are stripped. |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
Note that if you need the raw answer from the modem, you can use the _answer() (note |
987
|
|
|
|
|
|
|
that underscore char before answer) method, which does not strip anything from the response, |
988
|
|
|
|
|
|
|
so you get the real modem answer string. |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
Parameters: |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
=over 4 |
993
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
=item * |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
C<$expect> - Can be a regexp compiled with C or a simple substring. Input coming from the |
997
|
|
|
|
|
|
|
modem is matched against this parameter. If input matches, result is returned. |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
=item * |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
C<$timeout> - Expressed in milliseconds. After that time, answer returns result also if nothing |
1002
|
|
|
|
|
|
|
has been received. Example: C<10000>. Default: C<$Device::Modem::TIMEOUT>, currently 500 ms. |
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
=back |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
=head2 atsend() |
1009
|
|
|
|
|
|
|
|
1010
|
|
|
|
|
|
|
Sends a raw C command to the device connected. Note that this method is most used |
1011
|
|
|
|
|
|
|
internally, but can be also used to send your own custom commands. Example: |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
$ok = $modem->atsend( $msg ) |
1014
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
The only parameter is C<$msg>, that is the raw AT command to be sent to |
1016
|
|
|
|
|
|
|
modem expressed as string. You must include the C prefix and final |
1017
|
|
|
|
|
|
|
B and/or B manually. There is the special constant |
1018
|
|
|
|
|
|
|
C that can be used to include such a char sequence into the at command. |
1019
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
Returns C<$ok> flag that is true if all characters are sent successfully, false |
1021
|
|
|
|
|
|
|
otherwise. |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
Example: |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
# Enable verbose messages |
1026
|
|
|
|
|
|
|
$modem->atsend( 'AT V1' . Device::Modem::CR ); |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
# The same as: |
1029
|
|
|
|
|
|
|
$modem->verbose(1); |
1030
|
|
|
|
|
|
|
|
1031
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
=head2 attention() |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
This command sends an B sequence to modem. This allows modem |
1035
|
|
|
|
|
|
|
to pass in B and accept B commands. Example: |
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
$ok = $modem->attention() |
1038
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
=head2 connect() |
1040
|
|
|
|
|
|
|
|
1041
|
|
|
|
|
|
|
Connects C object to the specified serial port. |
1042
|
|
|
|
|
|
|
There are options (the same options that C has) to control |
1043
|
|
|
|
|
|
|
the parameters associated to serial link. Example: |
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
$ok = $modem->connect( [%options] ) |
1046
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
List of allowed options follows: |
1048
|
|
|
|
|
|
|
|
1049
|
|
|
|
|
|
|
=over 4 |
1050
|
|
|
|
|
|
|
|
1051
|
|
|
|
|
|
|
=item C |
1052
|
|
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
Controls the speed of serial communications. The default is B<19200> baud, that should |
1054
|
|
|
|
|
|
|
be supported by all modern modems. However, here you can supply a custom value. |
1055
|
|
|
|
|
|
|
Common speed values: 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, |
1056
|
|
|
|
|
|
|
115200. |
1057
|
|
|
|
|
|
|
This parameter is handled directly by C object. |
1058
|
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
=item C |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
This tells how many bits your data word is composed of. |
1062
|
|
|
|
|
|
|
Default (and most common setting) is C<8>. |
1063
|
|
|
|
|
|
|
This parameter is handled directly by C object. |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
=item C |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
Sets the handshake (or flow control) method for the serial port. |
1068
|
|
|
|
|
|
|
By default it is C, but can be either C (hardware flow control) |
1069
|
|
|
|
|
|
|
or C (software flow control). These flow control modes may or may not |
1070
|
|
|
|
|
|
|
work depending on your modem device or software. |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
=item C |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
Custom initialization string can be supplied instead of the built-in one, that is the |
1075
|
|
|
|
|
|
|
following: C, that is taken shamelessly from |
1076
|
|
|
|
|
|
|
C utility, I think. |
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
=item C |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
Controls how parity bit is generated and checked. |
1081
|
|
|
|
|
|
|
Can be B, B or B. Default is B. |
1082
|
|
|
|
|
|
|
This parameter is handled directly by C object. |
1083
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
=item C |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
Tells how many bits are used to identify the end of a data word. |
1087
|
|
|
|
|
|
|
Default (and most common usage) is C<1>. |
1088
|
|
|
|
|
|
|
This parameter is handled directly by C object. |
1089
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
=back |
1091
|
|
|
|
|
|
|
|
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
=head2 dial() |
1095
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
Dials a telephone number. Can perform both voice and data calls. |
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
Usage: |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
$ok = $modem->dial($number); |
1101
|
|
|
|
|
|
|
$ok = $modem->dial($number, $timeout); |
1102
|
|
|
|
|
|
|
$ok = $modem->dial($number, $timeout, $mode); |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
Takes the modem off hook, dials the specified number and returns |
1105
|
|
|
|
|
|
|
modem answer. |
1106
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
Regarding voice calls, you B be able to send your voice through. |
1108
|
|
|
|
|
|
|
You probably have to connect an analog microphone, and just speak. |
1109
|
|
|
|
|
|
|
Or use a GSM phone. For voice calls, a simple C<;> is appended to the |
1110
|
|
|
|
|
|
|
number to be dialed. |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
If the number to dial is 1 digit only, extracts the number from the address book, provided your device has one. See C. |
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
Examples: |
1115
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
# Simple usage. Timeout and mode are optional. |
1117
|
|
|
|
|
|
|
$ok = $mode->dial('123456789'); |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
# List context: allows to get at exact modem answer |
1120
|
|
|
|
|
|
|
# like `CONNECT 19200/...', `BUSY', `NO CARRIER', ... |
1121
|
|
|
|
|
|
|
# Also, 30 seconds timeout |
1122
|
|
|
|
|
|
|
($ok, $answer) = $modem->dial('123456789', 30); |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
If called in B, returns only success of connection. |
1125
|
|
|
|
|
|
|
If modem answer contains the C string, C returns |
1126
|
|
|
|
|
|
|
successful state, otherwise a false value is returned. |
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
If called in B, returns the same C<$ok> flag, but also the |
1129
|
|
|
|
|
|
|
exact modem answer to the dial operation in the C<$answer> scalar. |
1130
|
|
|
|
|
|
|
C<$answer> typically can contain strings like: |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
=over 4 |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
=item C |
1135
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
=item C |
1137
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
=item C |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
=back |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
and so on ... all standard modem answers to a dial command. |
1143
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
Parameters are: |
1145
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
=over 4 |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
=item C<$number> |
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
B, this is the phone number to dial. |
1151
|
|
|
|
|
|
|
If C<$number> is only 1 digit, it is interpreted as: |
1152
|
|
|
|
|
|
|
B>. |
1153
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
So if your code is: |
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
$modem->dial( 2, 10 ); |
1157
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
This means: dial number in the modem internal address book |
1159
|
|
|
|
|
|
|
(see C for a way to read/write address book) |
1160
|
|
|
|
|
|
|
in position number B<2> and wait for a timeout of B<10> seconds. |
1161
|
|
|
|
|
|
|
|
1162
|
|
|
|
|
|
|
=item C<$timeout> |
1163
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
B, default is B<30 seconds>. |
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
Timeout expressed in seconds to wait for the remote device |
1167
|
|
|
|
|
|
|
to answer. Please do not expect an B wait for the number of |
1168
|
|
|
|
|
|
|
seconds you specified. |
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
=item C<$mode> |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
B, default is C, as string. |
1173
|
|
|
|
|
|
|
Allows to specify the type of call. Can be either: |
1174
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
=over 4 |
1176
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
=item C (default) |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
To perform a B. |
1180
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
=item C |
1182
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
To perform a B, if your device supports it. |
1184
|
|
|
|
|
|
|
No attempt to verify whether your device can do that will be made. |
1185
|
|
|
|
|
|
|
|
1186
|
|
|
|
|
|
|
=back |
1187
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
=back |
1189
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
=head2 disconnect() |
1191
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
Disconnects C object from serial port. This method calls underlying |
1193
|
|
|
|
|
|
|
C of C object. |
1194
|
|
|
|
|
|
|
Example: |
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
$modem->disconnect(); |
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
=head2 echo() |
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
Enables or disables local echo of commands. This is managed automatically by C |
1201
|
|
|
|
|
|
|
object. Normally you should not need to worry about this. Usage: |
1202
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
$ok = $modem->echo( $enable ) |
1204
|
|
|
|
|
|
|
|
1205
|
|
|
|
|
|
|
=head2 hangup() |
1206
|
|
|
|
|
|
|
|
1207
|
|
|
|
|
|
|
Does what it is supposed to do. Hang up the phone thus terminating any active call. |
1208
|
|
|
|
|
|
|
Usage: |
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
$ok = $modem->hangup(); |
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
=head2 is_active() |
1213
|
|
|
|
|
|
|
|
1214
|
|
|
|
|
|
|
Can be used to check if there is a modem attached to your computer. |
1215
|
|
|
|
|
|
|
If modem is alive and responding (on serial link, not to a remote call), |
1216
|
|
|
|
|
|
|
C returns true (1), otherwise returns false (0). |
1217
|
|
|
|
|
|
|
|
1218
|
|
|
|
|
|
|
Test of modem activity is done through DSR (Data Set Ready) signal. If |
1219
|
|
|
|
|
|
|
this signal is in off state, modem is probably turned off, or not working. |
1220
|
|
|
|
|
|
|
From my tests I've found that DSR stays in "on" state after more or less |
1221
|
|
|
|
|
|
|
one second I turn off my modem, so know you know that. |
1222
|
|
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
Example: |
1224
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
if( $modem->is_active() ) { |
1226
|
|
|
|
|
|
|
# Ok! |
1227
|
|
|
|
|
|
|
} else { |
1228
|
|
|
|
|
|
|
# Modem turned off? |
1229
|
|
|
|
|
|
|
} |
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
=head2 log() |
1232
|
|
|
|
|
|
|
|
1233
|
|
|
|
|
|
|
Simple accessor to log object instanced at object creation time. |
1234
|
|
|
|
|
|
|
Used internally. If you want to know the gory details, see C objects. |
1235
|
|
|
|
|
|
|
You can also see the B for how to log something without knowing |
1236
|
|
|
|
|
|
|
all the gory details. |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
Hint: |
1239
|
|
|
|
|
|
|
$modem->log->write('warning', 'ok, my log message here'); |
1240
|
|
|
|
|
|
|
|
1241
|
|
|
|
|
|
|
=head2 new() |
1242
|
|
|
|
|
|
|
|
1243
|
|
|
|
|
|
|
C constructor. This takes several options. A basic example: |
1244
|
|
|
|
|
|
|
|
1245
|
|
|
|
|
|
|
my $modem = Device::Modem->new( port => '/dev/ttyS0' ); |
1246
|
|
|
|
|
|
|
|
1247
|
|
|
|
|
|
|
if under Linux or some kind of unix machine, or |
1248
|
|
|
|
|
|
|
|
1249
|
|
|
|
|
|
|
my $modem = Device::Modem->new( port => 'COM1' ); |
1250
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
if you are using a Win32 machine. |
1252
|
|
|
|
|
|
|
|
1253
|
|
|
|
|
|
|
This builds the C object with all the default parameters. |
1254
|
|
|
|
|
|
|
This should be fairly usable if you want to connect to a real modem. |
1255
|
|
|
|
|
|
|
Note that I'm testing it with a B<3Com US Robotics 56K Message> modem |
1256
|
|
|
|
|
|
|
at B<19200> baud and works ok. |
1257
|
|
|
|
|
|
|
|
1258
|
|
|
|
|
|
|
List of allowed options: |
1259
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
=over 4 |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
=item * |
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
C - serial port to connect to. On Unix, can be also a convenient link as |
1265
|
|
|
|
|
|
|
F (the default value). For Win32, C can be used. |
1266
|
|
|
|
|
|
|
|
1267
|
|
|
|
|
|
|
=item * |
1268
|
|
|
|
|
|
|
|
1269
|
|
|
|
|
|
|
C - this specifies the method and eventually the filename for logging. |
1270
|
|
|
|
|
|
|
Logging process with C is controlled by B, stored under |
1271
|
|
|
|
|
|
|
F folder. At present, there are two main plugins: C and C. |
1272
|
|
|
|
|
|
|
C does not work with Win32 machines. |
1273
|
|
|
|
|
|
|
When using C plug-in, all log information will be written to a default filename |
1274
|
|
|
|
|
|
|
if you don't specify one yourself. The default is F<%WINBOOTDIR%\temp\modem.log> on |
1275
|
|
|
|
|
|
|
Win32 and F on Unix. |
1276
|
|
|
|
|
|
|
|
1277
|
|
|
|
|
|
|
Also there is the possibility to pass a B, if this object |
1278
|
|
|
|
|
|
|
provides the following C call: |
1279
|
|
|
|
|
|
|
|
1280
|
|
|
|
|
|
|
$log_object->write( $loglevel, $logmessage ) |
1281
|
|
|
|
|
|
|
|
1282
|
|
|
|
|
|
|
You can simply pass this object (already instanced) as the C property. |
1283
|
|
|
|
|
|
|
|
1284
|
|
|
|
|
|
|
Examples: |
1285
|
|
|
|
|
|
|
|
1286
|
|
|
|
|
|
|
# For Win32, default is to log in "%WINBOOTDIR%/temp/modem.log" file |
1287
|
|
|
|
|
|
|
my $modem = Device::Modem->new( port => 'COM1' ); |
1288
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
# Unix, custom logfile |
1290
|
|
|
|
|
|
|
my $modem = Device::Modem->new( port => '/dev/ttyS0', log => 'file,/home/neo/matrix.log' ) |
1291
|
|
|
|
|
|
|
|
1292
|
|
|
|
|
|
|
# With custom log object |
1293
|
|
|
|
|
|
|
my $modem = Device::modem->new( port => '/dev/ttyS0', log => My::LogObj->new() ); |
1294
|
|
|
|
|
|
|
|
1295
|
|
|
|
|
|
|
=item * |
1296
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
C - default logging level. One of (order of decrescent verbosity): C, |
1298
|
|
|
|
|
|
|
C, C, C, C, C, C, C, C. |
1299
|
|
|
|
|
|
|
|
1300
|
|
|
|
|
|
|
=back |
1301
|
|
|
|
|
|
|
|
1302
|
|
|
|
|
|
|
|
1303
|
|
|
|
|
|
|
=head2 offhook() |
1304
|
|
|
|
|
|
|
|
1305
|
|
|
|
|
|
|
Takes the modem "off hook", ready to dial. Normally you don't need to use this. |
1306
|
|
|
|
|
|
|
Also C goes automatically off hook before dialing. |
1307
|
|
|
|
|
|
|
|
1308
|
|
|
|
|
|
|
|
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
=head2 parse_answer() |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
This method works like C, it accepts the same parameters, but it |
1313
|
|
|
|
|
|
|
does not return the raw modem answer. Instead, it returns the answer string |
1314
|
|
|
|
|
|
|
stripped of all B/B characters at the beginning B at the end. |
1315
|
|
|
|
|
|
|
|
1316
|
|
|
|
|
|
|
C is meant as an easy way of extracting result code |
1317
|
|
|
|
|
|
|
(C, C, ...) and information strings that can be sent by modem |
1318
|
|
|
|
|
|
|
in response to specific commands. Example: |
1319
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
> AT xSHOW_MODELx |
1321
|
|
|
|
|
|
|
US Robotics 56K Message |
1322
|
|
|
|
|
|
|
OK |
1323
|
|
|
|
|
|
|
> |
1324
|
|
|
|
|
|
|
|
1325
|
|
|
|
|
|
|
In this example, C is the result and C is the |
1326
|
|
|
|
|
|
|
informational message. |
1327
|
|
|
|
|
|
|
|
1328
|
|
|
|
|
|
|
In fact, another difference with C is in the return value(s). |
1329
|
|
|
|
|
|
|
Here are some examples: |
1330
|
|
|
|
|
|
|
|
1331
|
|
|
|
|
|
|
$modem->atsend( '?my_at_command?' ); |
1332
|
|
|
|
|
|
|
$answer = $modem->parse_answer(); |
1333
|
|
|
|
|
|
|
|
1334
|
|
|
|
|
|
|
where C<$answer> is the complete response string, or: |
1335
|
|
|
|
|
|
|
|
1336
|
|
|
|
|
|
|
($result, @lines) = $modem->parse_answer(); |
1337
|
|
|
|
|
|
|
|
1338
|
|
|
|
|
|
|
where C<$result> is the C or C final message and C<@lines> is |
1339
|
|
|
|
|
|
|
the array of information messages (one or more lines). For the I example, |
1340
|
|
|
|
|
|
|
C<$result> would hold "C" and C<@lines> would consist of only 1 line with |
1341
|
|
|
|
|
|
|
the string "C". |
1342
|
|
|
|
|
|
|
|
1343
|
|
|
|
|
|
|
|
1344
|
|
|
|
|
|
|
=head2 port() |
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
Used internally. Accesses the C underlying object. If you need to |
1347
|
|
|
|
|
|
|
experiment or do low-level serial calls, you may want to access this. Please report |
1348
|
|
|
|
|
|
|
any usage of this kind, because probably (?) it is possible to include it in a higher |
1349
|
|
|
|
|
|
|
level method. |
1350
|
|
|
|
|
|
|
|
1351
|
|
|
|
|
|
|
As of 1.52, C will automatically try to reconnect if it detects |
1352
|
|
|
|
|
|
|
a bogus underlying port object. It will reconnect with the same options used |
1353
|
|
|
|
|
|
|
when Cing the first time. |
1354
|
|
|
|
|
|
|
|
1355
|
|
|
|
|
|
|
If no connection has taken place yet, then B |
1356
|
|
|
|
|
|
|
will be attempted. |
1357
|
|
|
|
|
|
|
|
1358
|
|
|
|
|
|
|
=head2 repeat() |
1359
|
|
|
|
|
|
|
|
1360
|
|
|
|
|
|
|
Repeats the last C command issued. |
1361
|
|
|
|
|
|
|
Usage: |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
$ok = $modem->repeat() |
1364
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
|
1366
|
|
|
|
|
|
|
=head2 reset() |
1367
|
|
|
|
|
|
|
|
1368
|
|
|
|
|
|
|
Tries in any possible way to reset the modem to the starting state, hanging up all |
1369
|
|
|
|
|
|
|
active calls, resending the initialization string and preparing to receive C |
1370
|
|
|
|
|
|
|
commands. |
1371
|
|
|
|
|
|
|
|
1372
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
|
1374
|
|
|
|
|
|
|
=head2 restore_factory_settings() |
1375
|
|
|
|
|
|
|
|
1376
|
|
|
|
|
|
|
Restores the modem default factory settings. There are normally two main "profiles", |
1377
|
|
|
|
|
|
|
two different memories for all modem settings, so you can load profile 0 and profile 1, |
1378
|
|
|
|
|
|
|
that can be different depending on your modem manufacturer. |
1379
|
|
|
|
|
|
|
|
1380
|
|
|
|
|
|
|
Usage: |
1381
|
|
|
|
|
|
|
|
1382
|
|
|
|
|
|
|
$ok = $modem->restore_factory_settings( [$profile] ) |
1383
|
|
|
|
|
|
|
|
1384
|
|
|
|
|
|
|
If no C<$profile> is supplied, C<0> is assumed as default value. |
1385
|
|
|
|
|
|
|
|
1386
|
|
|
|
|
|
|
Check on your modem hardware manual for the meaning of these B. |
1387
|
|
|
|
|
|
|
|
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
|
1390
|
|
|
|
|
|
|
=head2 S_register() |
1391
|
|
|
|
|
|
|
|
1392
|
|
|
|
|
|
|
Gets or sets an B value. These are some internal modem registers that |
1393
|
|
|
|
|
|
|
hold important information that controls all modem behaviour. If you don't know |
1394
|
|
|
|
|
|
|
what you are doing, don't use this method. Usage: |
1395
|
|
|
|
|
|
|
|
1396
|
|
|
|
|
|
|
$value = $modem->S_register( $reg_number [, $new_value] ); |
1397
|
|
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
C<$reg_number> ranges from 0 to 99 (sure?). |
1399
|
|
|
|
|
|
|
If no C<$new_value> is supplied, return value is the current register value. |
1400
|
|
|
|
|
|
|
If a C<$new_value> is supplied (you want to set the register value), return value |
1401
|
|
|
|
|
|
|
is the new value or C if there was an error setting the new value. |
1402
|
|
|
|
|
|
|
|
1403
|
|
|
|
|
|
|
|
1404
|
|
|
|
|
|
|
|
1405
|
|
|
|
|
|
|
Examples: |
1406
|
|
|
|
|
|
|
|
1407
|
|
|
|
|
|
|
# Get value of S7 register |
1408
|
|
|
|
|
|
|
$modem->S_register(7); |
1409
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
# Set value of S0 register to 0 |
1411
|
|
|
|
|
|
|
$modem->S_register(0, 0); |
1412
|
|
|
|
|
|
|
|
1413
|
|
|
|
|
|
|
|
1414
|
|
|
|
|
|
|
=head2 send_init_string() |
1415
|
|
|
|
|
|
|
|
1416
|
|
|
|
|
|
|
Sends the initialization string to the connected modem. Usage: |
1417
|
|
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
$ok = $modem->send_init_string( [$init_string] ); |
1419
|
|
|
|
|
|
|
|
1420
|
|
|
|
|
|
|
If you specified an C as an option to C object constructor, |
1421
|
|
|
|
|
|
|
that is taken by default to initialize the modem. |
1422
|
|
|
|
|
|
|
Else you can specify C<$init_string> parameter to use your own custom initialization |
1423
|
|
|
|
|
|
|
string. Be careful! |
1424
|
|
|
|
|
|
|
|
1425
|
|
|
|
|
|
|
=head2 status() |
1426
|
|
|
|
|
|
|
|
1427
|
|
|
|
|
|
|
Returns status of main modem signals as managed by C (or C) objects. |
1428
|
|
|
|
|
|
|
The signals reported are: |
1429
|
|
|
|
|
|
|
|
1430
|
|
|
|
|
|
|
=over 4 |
1431
|
|
|
|
|
|
|
|
1432
|
|
|
|
|
|
|
=item CTS |
1433
|
|
|
|
|
|
|
|
1434
|
|
|
|
|
|
|
Clear to send |
1435
|
|
|
|
|
|
|
|
1436
|
|
|
|
|
|
|
=item DSR |
1437
|
|
|
|
|
|
|
|
1438
|
|
|
|
|
|
|
Data set ready |
1439
|
|
|
|
|
|
|
|
1440
|
|
|
|
|
|
|
=item RING |
1441
|
|
|
|
|
|
|
|
1442
|
|
|
|
|
|
|
Active if modem is ringing |
1443
|
|
|
|
|
|
|
|
1444
|
|
|
|
|
|
|
=item RLSD |
1445
|
|
|
|
|
|
|
|
1446
|
|
|
|
|
|
|
??? Released line ??? |
1447
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
=back |
1449
|
|
|
|
|
|
|
|
1450
|
|
|
|
|
|
|
Return value of C call is a hash, where each key is a signal name and |
1451
|
|
|
|
|
|
|
each value is > 0 if signal is active, 0 otherwise. |
1452
|
|
|
|
|
|
|
Usage: |
1453
|
|
|
|
|
|
|
|
1454
|
|
|
|
|
|
|
... |
1455
|
|
|
|
|
|
|
my %sig = $modem->status(); |
1456
|
|
|
|
|
|
|
for ('CTS','DSR','RING','RLSD') { |
1457
|
|
|
|
|
|
|
print "Signal $_ is ", ($sig{$_} > 0 ? 'on' : 'off'), "\n"; |
1458
|
|
|
|
|
|
|
} |
1459
|
|
|
|
|
|
|
|
1460
|
|
|
|
|
|
|
=head2 store_number() |
1461
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
Store telephone number in modem internal address book, to be dialed later (see C method). |
1463
|
|
|
|
|
|
|
Usage: |
1464
|
|
|
|
|
|
|
|
1465
|
|
|
|
|
|
|
$ok = $modem->store_number( $position, $number ) |
1466
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
where C<$position> is the address book memory slot to store phone number (usually from 0 to 9), |
1468
|
|
|
|
|
|
|
and C<$number> is the number to be stored in the slot. |
1469
|
|
|
|
|
|
|
Return value is true if operation was successful, false otherwise. |
1470
|
|
|
|
|
|
|
|
1471
|
|
|
|
|
|
|
=head2 verbose() |
1472
|
|
|
|
|
|
|
|
1473
|
|
|
|
|
|
|
Enables or disables verbose messages. This is managed automatically by C |
1474
|
|
|
|
|
|
|
object. Normally you should not need to worry about this. Usage: |
1475
|
|
|
|
|
|
|
|
1476
|
|
|
|
|
|
|
$ok = $modem->verbose( $enable ) |
1477
|
|
|
|
|
|
|
|
1478
|
|
|
|
|
|
|
=head2 wait() |
1479
|
|
|
|
|
|
|
|
1480
|
|
|
|
|
|
|
Waits (yea) for a given amount of time (in milliseconds). Usage: |
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
$modem->wait( [$msecs] ) |
1483
|
|
|
|
|
|
|
|
1484
|
|
|
|
|
|
|
Wait is implemented via C |
1485
|
|
|
|
|
|
|
Don't know if this is really a problem on some platforms. |
1486
|
|
|
|
|
|
|
|
1487
|
|
|
|
|
|
|
=head2 write_drain() |
1488
|
|
|
|
|
|
|
|
1489
|
|
|
|
|
|
|
Only a simple wrapper around C method. |
1490
|
|
|
|
|
|
|
Disabled for Win32 platform, that doesn't have that. |
1491
|
|
|
|
|
|
|
|
1492
|
|
|
|
|
|
|
|
1493
|
|
|
|
|
|
|
=head1 REQUIRES |
1494
|
|
|
|
|
|
|
|
1495
|
|
|
|
|
|
|
=over 4 |
1496
|
|
|
|
|
|
|
|
1497
|
|
|
|
|
|
|
=item Device::SerialPort (Win32::SerialPort for Win32 machines) |
1498
|
|
|
|
|
|
|
|
1499
|
|
|
|
|
|
|
=back |
1500
|
|
|
|
|
|
|
|
1501
|
|
|
|
|
|
|
=head1 EXPORT |
1502
|
|
|
|
|
|
|
|
1503
|
|
|
|
|
|
|
None |
1504
|
|
|
|
|
|
|
|
1505
|
|
|
|
|
|
|
|
1506
|
|
|
|
|
|
|
|
1507
|
|
|
|
|
|
|
=head1 TO-DO |
1508
|
|
|
|
|
|
|
|
1509
|
|
|
|
|
|
|
=over 4 |
1510
|
|
|
|
|
|
|
|
1511
|
|
|
|
|
|
|
=item AutoScan |
1512
|
|
|
|
|
|
|
|
1513
|
|
|
|
|
|
|
An AT command script with all interesting commands is run |
1514
|
|
|
|
|
|
|
when `autoscan' is invoked, creating a `profile' of the |
1515
|
|
|
|
|
|
|
current device, with list of supported commands, and database |
1516
|
|
|
|
|
|
|
of brand/model-specific commands |
1517
|
|
|
|
|
|
|
|
1518
|
|
|
|
|
|
|
=item Serial speed auto-detect |
1519
|
|
|
|
|
|
|
|
1520
|
|
|
|
|
|
|
Now if you connect to a different baud rate than that of your modem, |
1521
|
|
|
|
|
|
|
probably you will get no response at all. It would be nice if C |
1522
|
|
|
|
|
|
|
could auto-detect the speed to correctly connect at your modem. |
1523
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
=item File transfers |
1525
|
|
|
|
|
|
|
|
1526
|
|
|
|
|
|
|
It would be nice to implement C<[xyz]modem> like transfers between |
1527
|
|
|
|
|
|
|
two C objects connected with two modems. |
1528
|
|
|
|
|
|
|
|
1529
|
|
|
|
|
|
|
=back |
1530
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
|
1532
|
|
|
|
|
|
|
=head1 FAQ |
1533
|
|
|
|
|
|
|
|
1534
|
|
|
|
|
|
|
There is a minimal FAQ document for this module online at |
1535
|
|
|
|
|
|
|
L |
1536
|
|
|
|
|
|
|
|
1537
|
|
|
|
|
|
|
=head1 SUPPORT |
1538
|
|
|
|
|
|
|
|
1539
|
|
|
|
|
|
|
Please feel free to contact me at my e-mail address L |
1540
|
|
|
|
|
|
|
for any information, to resolve problems you can encounter with this module |
1541
|
|
|
|
|
|
|
or for any kind of commercial support you may need. |
1542
|
|
|
|
|
|
|
|
1543
|
|
|
|
|
|
|
=head1 AUTHOR |
1544
|
|
|
|
|
|
|
|
1545
|
|
|
|
|
|
|
Cosimo Streppone, L |
1546
|
|
|
|
|
|
|
|
1547
|
|
|
|
|
|
|
=head1 COPYRIGHT |
1548
|
|
|
|
|
|
|
|
1549
|
|
|
|
|
|
|
(C) 2002-2014 Cosimo Streppone, L |
1550
|
|
|
|
|
|
|
|
1551
|
|
|
|
|
|
|
This library is free software; you can only redistribute it and/or |
1552
|
|
|
|
|
|
|
modify it under the same terms as Perl itself. |
1553
|
|
|
|
|
|
|
|
1554
|
|
|
|
|
|
|
=head1 SEE ALSO |
1555
|
|
|
|
|
|
|
|
1556
|
|
|
|
|
|
|
Device::SerialPort, |
1557
|
|
|
|
|
|
|
Win32::SerialPort, |
1558
|
|
|
|
|
|
|
Device::Gsm, |
1559
|
|
|
|
|
|
|
perl |
1560
|
|
|
|
|
|
|
|
1561
|
|
|
|
|
|
|
=cut |
1562
|
|
|
|
|
|
|
|
1563
|
|
|
|
|
|
|
# vim: set ts=4 sw=4 tw=120 nowrap nu |