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