' prlupdate.sb
'
' Does a PRL update from a file
'
' the following line makes all string comparisons case insensitive
'
OPTION COMPARE sbCaseInsensitive
' set up the error handler
'
on error goto ErrorLabel
const nl = "\r\n"
' Enter an error message in the event log
' Also prints message to console output
' And appends the message to the web log file
'
function eventmsg(msg)
print #aspout, msg, nl
print msg, nl
junk = system("setevent \"" & msg & "\"" & " 0")
end function
' Appends the message to the web log file
'
function logmsg(msg)
print #aspout, msg, nl
end function
' Generate the log files for monitoring progress at the web interface
'
function init_log_files
local fh
fh = 0
open "sstat.asp" for output as fh
print #fh, "\r\n"
print #fh, "
\r\n"
print #fh, "\r\n"
print #fh, "\r\n"
print #fh, "\r\n"
close fh
aspout=0
open "sstat.txt" for output as aspout
end function
' Generate a final status message which can be displayed at the web interface
' This re-writes the top sstat1 frame page
function log_status(log_msg)
local fh
fh = 0
open "sstat1.asp" for output as fh
print #fh, "\r\n"
print #fh, "\r\n"
print #fh, "PRL Update Status\r\n"
print #fh, "\r\n"
print #fh, "\r\n"
print #fh, "\r\n"
print #fh, "\r\n"
print #fh, "\r\n"
print #fh, "
"
print #fh, "\r\n"
print #fh, "\r\n"
print #fh, "\r\n"
close fh
end function
' Close i/o handles and try to put the config back the way it was
' If using a TCP socket we only have one handle to close.
function restorecfg
local res, resstr
if atopened <> 0 then
if socketopened = 0 then
close(mc75out)
endif
close(mc75in)
endif
if cnsopened <> 0 then
close(cnsout)
close(cnsin)
endif
sleep(1)
if asyportchanged <> 0 then
res = execute("modemcc 0 asy_add " & asystr, 0, resstr)
else
res = execute("modemconn", 0, resstr)
endif
end function
' Enter an error message in the event log and exit
' Also prints message to console output
' And updates the web status page
'
function errexit(msg)
if do_restore <> 0 then restorecfg()
log_status(msg)
print #aspout, msg, nl
print msg, nl
print "Please reboot the router", nl
junk = system("setevent \"" & msg & "\"" & " 6")
stop
end function
' Return the value of Sarian parameter in rsp
' strCmd needs to be of form " ?"
' e.g. "ppp 0 ans ?"
function getParam(strCmd,rsp)
local res, tmp, tmpPos, x, pos2
getParam = false
res = execute(strCmd, 0, tmp)
if res = true then
tmpPos = InStr(tmp, nl & "OK" & nl)
if tmpPos > 0 then
For x = tmpPos To 1 Step -1
pos2 = InStr(tmp, nl, x - 3)
If pos2 > 0 and pos2 <> tmpPos then
x = 1
endif
next x
if pos2 > 0 and pos2 <> tmpPos then
rsp = mid(tmp, pos2 + 2, tmpPos - pos2 - 2)
getParam = true
endif
endif
endif
end function
' find the first PPP instance configured for GPRS
' returns TRUE if we found one, and put the instance number into num
' otherwise returns FALSE
'
function get_gprs_ppp_instance(num)
local mdmstr, i
get_gprs_ppp_instance = false
for i = 0 to 4
if getParam("ppp " & i & " use_modem ?", mdmstr) = TRUE then
' print "PPP ", i, " use_modem = ", mdmstr, nl
if mdmstr = "1" or mdmstr = "4" or mdmstr = "5" then
get_gprs_ppp_instance = true
num = i
exit function
endif
else
print "Failed to get PPP ", i, " use_modem", nl
endif
next i
end function
' init_mc75io - opens a serial port and initialises a receive buffer for it
' Sets the following GLOBAL vars:
' mc75in - the input file handle
' mc75out - the output file handle
' mc75rxbuf - the receive buffer
' Parameter required is a GLOBAL variable mc75asyport, eg "ASY5"
'
function init_mc75io
' open the serial port used for the MC75
' two handles, one for input and one for output
mc75in = 0
open mc75asyport for input as mc75in
' if error() <> 0 then
' print "error opening asy port", nl
' endif
mc75out = 0
open mc75asyport for output as mc75out
mc75rxbuf = ""
junk = setevent(0)
junk = setevent(mc75in)
end function
' clear the receive buffer
'
function clear_mc75io
local junk, infobuf, tbuf
mx75rxbuf = ""
if waitevents(1000) = mc75in then
junk = sockinfo(mc75in, infobuf)
if infobuf[2] <> 0 then
tbuf = input(infobuf[2], mc75in)
endif
endif
end function
' gets a character from mc75in
' timeout is fixed at 10 secs for now
' Return TRUE if successful, otherwise FALSE
' If TRUE, then character is retuned in the rsp parameter
'
function getchar(rsp)
local tstart, junk, sinfo
getchar = FALSE
tstart = ticks
while ticks-tstart < 1000
if len(mc75rxbuf) <> 0 then
rsp = left(mc75rxbuf, 1)
mc75rxbuf = mid(mc75rxbuf, 2)
getchar = TRUE
exit function
endif
junk = sockinfo(mc75in, sinfo)
' print "Bytes available = ", sinfo[2], nl
if sinfo[2] <> 0 then
' print "Reading ", sinfo[2], " Bytes", nl
mc75rxbuf = input(sinfo[2], mc75in)
' else
' sleep(1)
endif
wend
end function
' Get a line from mc75in
' Return TRUE if successful, otherwise FALSE
' If TRUE, then line is retuned in the rsp parameter
'
function getline(rsp)
local junk, sinfo, tbuf, tchr
getline = FALSE
tbuf = ""
while TRUE
if getchar(tchr) <> TRUE then exit function
' see if we received a LF (our end of line)
if asc(tchr) = 0x0a then
rsp = tbuf
getline = TRUE
exit function
endif
' ignore CR, append all other chars
if asc(tchr) <> 0x0d then
tbuf = tbuf & tchr
endif
wend
end function
function getOKline
local i, myline
getOKline = FALSE
for i = 1 to 10
if getline(myline) <> TRUE then exit function
if myline = "OK" then
getOKline = TRUE
exit function
endif
next i
end function
'
' Collect a number of lines into an array
' Stop at OK, ERROR or timeout
' return the number of lines received.
'
function getResplines(rsplines)
local nlines, i, myline
nlines = 0
getResplines = 0
for i = 1 to 10
if getline(myline) <> TRUE then exit function
rsplines[nlines] = myline
nlines += 1
getResplines = nlines
if (instr(myline, "OK") <> undef) or (instr(myline, "ERROR") <> undef) then
exit function
endif
next i
end function
' sends a command to the modem and returns the first reponse line
'
function modem_cmd(cmd_str)
local i, nlines, rsplines
modem_cmd = ""
print #mc75out, cmd_str & "\r"
nlines = getResplines(rsplines)
if nlines = 0 then
eventmsg "No response to " & cmd_str
exit function
endif
if rsplines[nlines-1] <> "OK" then
eventmsg cmd_str & " did not return OK, got " & rsplines[nlines-1]
exit function
endif
' for i = 0 to nlines-1
' eventmsg "Got line: " & rsplines[i]
' next i
for i = 0 to nlines-1
if rsplines[i] <> "" AND rsplines[i] <> cmd_str then
modem_cmd = rsplines[i]
exit function
endif
next i
end function
' sends a command to the modem and returns the reponse lines
'
function modem_cmd_lines(cmd_str, rsplines)
local i, j, nlines, rlines
modem_cmd_lines = 0
print #mc75out, cmd_str & "\r"
nlines = getResplines(rlines)
if nlines = 0 then
eventmsg "No response to " & cmd_str
exit function
endif
j = 0
for i = 0 to nlines-1
if rlines[i] <> "" AND rlines[i] <> cmd_str then
rsplines[j] = rlines[i]
j += 1
endif
next i
modem_cmd_lines = j
end function
' hex and ascii dump of a string
'
function dump_packet(pkt)
local i, j, n, ll, chval, astr
n = len(pkt)
print "Received ", n, " bytes\r\n"
i = 1
while n > 0
if n >= 16 then
ll = 16
else
ll = n
endif
for j = i to i+ll-1
print format("%02X", asc(mid(pkt,j,1))), " "
next j
astr = string((16-ll)*3+4, " ")
for j = i to i+ll-1
chval = asc(mid(pkt,j,1))
if chval >= 0x20 and chval <= 0x7e then
astr = astr & mid(pkt,j,1)
else
astr = astr & "."
endif
next j
print astr, "\r\n"
n -= 16
i += 16
wend
end function
' CnS operation codes
const CNS_GET_REQUEST = 1
const CNS_GET_REPLY = 2
const CNS_SET_COMMAND = 3
const CNS_SET_ACKNOWLEDGE = 4
const CNS_NOTIFICATION_ENABLE = 5
const CNS_ENABLE_RESPONSE = 6
const CNS_NOTIFICATION = 7
const CNS_NOTIFICATION_DISABLE = 8
const CNS_FORWARD_DISABLE_ACKNOWLEDGE = 9
' the index of the first Cns payload byte in a received packet
const CNS_PAYLOAD_INDEX = 16
' Send a CnS get request message for the given object id
'
' optype: the CnS operation type:
' 1: Get request
' 3: Set request
' 5: Notification enable
' 8: Notification disable
' objid: the Cns object ID
' payloaddata: an array containing the Cns payload data starting at index 0
' payloadlen: the number of bytes in the payload data
'
' Uses the global file handle cnsout to send the data
'
function send_cns(optype, objid, payloaddata, payloadlen)
local i, buf, msglen, ostr
' HIP header: payload len hi, payload len lo, message id (host to modem), parameter
i = payloadlen+10
buf[1] = i\256
buf[2] = i AND 255
buf[3] = 0x2b
buf[4] = 0
' CnS message
buf[5] = objid\256
buf[6] = objid AND 255
buf[7] = optype
buf[8] = 0
buf[9] = 0
buf[10] = 0
buf[11] = 0
buf[12] = 0
buf[13] = payloadlen\256
buf[14] = payloadlen AND 255
if payloadlen <> 0 then
for i = 0 to payloadlen-1
buf[15+i] = payloaddata[i]
next i
endif
msglen = payloadlen + 14
' add framing and escape characters
ostr = chr(0x7e)
for i = 1 to msglen
if buf[i] = 0x7e or buf[i] = 0x7d then
ostr = ostr & chr(0x7d)
ostr = ostr & chr(buf[i] XOR 0x20)
else
ostr = ostr & chr(buf[i])
endif
next i
ostr = ostr & chr(0x7e)
print #cnsout, ostr
end function
' remove escape character sequences from a received packet
'
function decode_escapes(string_data_buf)
local ostr, n, i, c
ostr = ""
n = len(string_data_buf)
for i = 1 to n-1
c = asc(mid(string_data_buf,i,1))
if c = 0x7D then
i += 1
c = asc(mid(string_data_buf,i,1))
c = c XOR 0x20
endif
ostr = ostr & chr(c)
next i
' add the last character
ostr = ostr & right(string_data_buf, 1)
decode_escapes = ostr
end function
' gets a character from cnsin
' Return TRUE if successful, otherwise FALSE
' If TRUE, then character is retuned in the rsp parameter
' Data is buffered in the global string variable cnsrxbuf
' timeout is specified in units of secs
'
function getCnSchar(rsp, timeout)
local tstart, junk, sinfo, ttimeout
getCnSchar = FALSE
tstart = ticks
ttimeout = timeout * 100
while ticks-tstart < ttimeout
if len(cnsrxbuf) <> 0 then
rsp = left(cnsrxbuf, 1)
cnsrxbuf = mid(cnsrxbuf, 2)
getCnSchar = TRUE
' print "getCnsChar returning ", asc(rsp), "\r\n"
exit function
endif
junk = sockinfo(cnsin, sinfo)
if sinfo[2] <> 0 then
cnsrxbuf = input(sinfo[2], cnsin)
endif
' sleep(1)
wend
end function
' experimental version that splits up multiple packets
'
function get_cns_response1(timeout)
local pktbuf, tchr, unescstr
get_cns_response1 = ""
pktbuf = ""
while TRUE
if getCnSchar(tchr, timeout) <> TRUE then exit function
' see if we received 0x7e (our start/end of packet)
'
if asc(tchr) = 0x7e then
pktbuf = pktbuf & tchr
' print "Added 7E, length is now ", len(pktbuf), "\r\n"
' we got 7e - see if it's the end of a packet
'
if len(pktbuf) > 1 then
unescstr = decode_escapes(pktbuf)
dump_packet(unescstr)
get_cns_response1 = unescstr
exit function
endif
else
'
' not 7e - append to buffer if it's not the first byte
'
' print "Got other char, length is ", len(pktbuf), "\r\n"
if len(pktbuf) >= 1 then
pktbuf = pktbuf & tchr
endif
endif
wend
end function
' check the HIP header and CnS operation type for a valid, non-error response
' return <0 if there's something wrong with it, otherwise the length of the CnS payload data
'
function check_cns_packet(rsppkt, optype, objid)
local plenhi, plenlo, plen, msgid, pobjidhi, pobjidlo, pobjid, poptype, payloadlen
' check for empty packet
if rsppkt = "" then
print "No CnS reply\r\n"
check_cns_packet = -1
exit function
endif
' check the HIP header
plenhi = asc(mid(rsppkt, 2, 1))
plenlo = asc(mid(rsppkt, 3, 1))
plen = plenhi*256 + plenlo
msgid = asc(mid(rsppkt, 4, 1))
print "HIP header: payload len=", plen, ", msgid=0x", format("%02X", msgid), "\r\n"
if len(rsppkt) <> plen+6 then
print "Bad HIP payload length\r\n"
check_cns_packet = -2
exit function
endif
if msgid <> 0x6B then
print "Unknown Message ID\r\n"
check_cns_packet = -3
exit function
endif
' check the CnS packet
pobjidhi = asc(mid(rsppkt, 6, 1))
pobjidlo = asc(mid(rsppkt, 7, 1))
pobjid = pobjidhi*256 + pobjidlo
poptype = asc(mid(rsppkt, 8, 1))
payloadlen = asc(mid(rsppkt, 15, 1))
print "CnS header: Objid=0x", format("%04X", pobjid), ", Optype=0x", format("%02X", poptype), ", Payloadlen=", payloadlen, "\r\n"
if (poptype and 0x80) <> 0 then
print "Got CnS Error response: ", mid(rsppkt, 16, payloadlen), "\r\n"
check_cns_packet = -4
exit function
endif
if pobjid <> objid then
print "Unexpected Object ID\r\n"
check_cns_packet = -5
exit function
endif
if poptype <> optype then
print "Unexpected Operation type\r\n"
check_cns_packet = -6
exit function
endif
if payloadlen+10 <> plen then
print "Bad CnS payload length\r\n"
check_cns_packet = -7
exit function
endif
check_cns_packet = payloadlen
end function
function recv_cns(rsppkt, optype, objid)
local payloadlen, rslt
rsppkt = get_cns_response1(5)
rslt = check_cns_packet(rsppkt, optype, objid)
' we can extract the message from an error response
if rslt = -4 then
payloadlen = asc(mid(rsppkt, 15, 1))
if payloadlen <> 0 then eventmsg "Received CnS error response: " & mid(rsppkt, CNS_PAYLOAD_INDEX, payloadlen)
endif
recv_cns = rslt
end function
' opens a file for reading
' returns the file handle, or -1 on error
function openfile(filename)
local fh
openfile = -1
fh = 0
on error goto openfileerror
open filename for input as fh
openfile = fh
exit function
openfileerror:
print "Error opening the file\r\n"
end function
' get the size in bytes of the given file
' return 0 if we can't open it
'
function getfilesize(filename)
local fh, n, total_bytes, buf
getfilesize = 0
total_bytes = 0
fh = openfile(filename)
if fh = -1 then exit function
while not eof(fh)
buf = input(120, fh)
n = len(buf)
total_bytes += n
wend
getfilesize = total_bytes
close(fh)
end function
function decode_prl_write_result(rcode)
if rcode = 0 then
decode_prl_write_result = "Success"
else if rcode = 1 then
decode_prl_write_result = "SPC is locked"
else if rcode = 2 then
decode_prl_write_result = "PRL size not set"
else if rcode = 3 then
decode_prl_write_result = "incorrect NAM set"
else if rcode = 4 then
decode_prl_write_result = "incorrect block sequence"
else if rcode = 5 then
decode_prl_write_result = "incorrect block size"
else if rcode = 6 then
decode_prl_write_result = "invalid PRL (CRC failure)"
else if rcode = 7 then
decode_prl_write_result = "invalid write"
else
decode_prl_write_result = "Unknown reason (" & rcode & ")"
endif
end function
' unlock an activation session using the two step activation validation sequence
'
function do_unlock(msl_string)
local t0, t1, scd, scr, srd, srr, cnsbuf, rsp, rslt
do_unlock = false
' construct and send 8 Secure Challenge Digits (scd)
'
t0 = rnd() % 100
if t0 = 0 then t0 += 1
scd = str(t0 * msl_string)
while len(scd) < 8
scd = "0" & scd
wend
cnsbuf[0] = asc(mid(scd, 1, 1))
cnsbuf[1] = asc(mid(scd, 2, 1))
cnsbuf[2] = asc(mid(scd, 3, 1))
cnsbuf[3] = asc(mid(scd, 4, 1))
cnsbuf[4] = asc(mid(scd, 5, 1))
cnsbuf[5] = asc(mid(scd, 6, 1))
cnsbuf[6] = asc(mid(scd, 7, 1))
cnsbuf[7] = asc(mid(scd, 8, 1))
send_cns(CNS_SET_COMMAND, 0x1015, cnsbuf, 8)
' receive 10 digit Secure Challenge Response (scr)
'
rslt = recv_cns(rsp, CNS_SET_ACKNOWLEDGE, 0x1015)
if rslt <> 10 then
eventmsg "Bad response to secure challenge"
exit function
endif
scr = mid(rsp, CNS_PAYLOAD_INDEX, 10)
' construct and send 4 Secure Rebuttal Digits (srd)
'
t1 = scr\scd - 1
srd = str(t1 * t0)
while len(srd) < 4
srd = "0" & srd
wend
cnsbuf[0] = asc(mid(srd, 1, 1))
cnsbuf[1] = asc(mid(srd, 2, 1))
cnsbuf[2] = asc(mid(srd, 3, 1))
cnsbuf[3] = asc(mid(srd, 4, 1))
send_cns(CNS_SET_COMMAND, 0x1016, cnsbuf, 4)
' receive UINT16 Secure Rebuttal Response (srr)
'
rslt = recv_cns(rsp, CNS_SET_ACKNOWLEDGE, 0x1016)
if rslt <> 2 then
eventmsg "Bad response to secure rebuttal"
eventmsg "T0:" & t0 & " SCD:" & scd & " SCR:" & scr & " SRD:" & srd
exit function
endif
srr = asc(mid(rsp, CNS_PAYLOAD_INDEX, 1))*256 + asc(mid(rsp, CNS_PAYLOAD_INDEX+1, 1))
if srr = 1 or srr = 2 then
do_unlock = true
exit function
endif
eventmsg "Activation challenge failed: possible incorrect MSL"
eventmsg "T0:" & t0 & " SCD:" & scd & " SCR:" & scr & " SRD:" & srd & " SRR:" & srr
end function
' This runs through the PRL Update procedure for Sierra Wireless modules
'
function do_prlupdate
local CnsPortName, rsp, rslt, cnsbuf, prlversion, prlsize, prlfile, prlfh, prlbuf, n, i, prlrslt
eventmsg "PRL update started"
' Get the parameters.
' First check the command line, as this can override the configured parameters
' Then check the provisioning config settings. These are:
'
' string1: the MSL
' string20: the PRL filename
'
split command() by " " to msl_str, prlfile
if isundef(msl_str) or isundef(prlfile) then
if getParam("provision 0 string1 ?", msl_str) = TRUE then
if getParam("provision 0 string20 ?", prlfile) = TRUE then
else
errexit "failed to get prlfile\r\n"
endif
else
errexit "failed to get msl_str\r\n"
endif
' print "\nUsage: prlupdate.sb \r\n"
' errexit "PRL update failed: missing parameters"
' exit sub
endif
print "msl_str=", msl_str, ", prlfile=", prlfile, "\r\n"
if msl_str = "" then errexit "PRL update failed: missing MSL parameter"
if prlfile = "" then errexit "PRL update failed: missing PRL file parameter"
fsize = getfilesize(prlfile)
if fsize = 0 then errexit "PRL update failed: couldn't get PRL filesize"
' open the CnS port
'
errcnt = 0
CnsPortName = "ASY" & infoasystr
cnsout = 0
cnsin = 0
open CnsPortName for output as cnsout
open CnsPortName for input as cnsin
cnsrxbuf = ""
cnsopened = 1
if do_unlock(msl_str) = false then errexit "PRL update failed: cannot unlock modem"
eventmsg "Modem unlocked successfully"
' Get the current PRL version
'
send_cns(CNS_GET_REQUEST, 0x1008, undef, 0)
rslt = recv_cns(rsp, CNS_GET_REPLY, 0x1008)
if rslt < 0 then errexit "PRL update failed: bad response getting current PRL version"
prlversion = asc(mid(rsp, CNS_PAYLOAD_INDEX, 1))*256 + asc(mid(rsp, CNS_PAYLOAD_INDEX+1, 1))
eventmsg "Current PRL Version is " & prlversion
' Get the current PRL size
'
' UINT16 parameter: NAM
cnsbuf[0] = 0
cnsbuf[1] = 0
send_cns(CNS_GET_REQUEST, 0x1052, cnsbuf, 2)
rslt = recv_cns(rsp, CNS_GET_REPLY, 0x1052)
if rslt < 0 then errexit "PRL update failed: bad response getting current PRL size"
prlsize = asc(mid(rsp, CNS_PAYLOAD_INDEX+4, 1))*256 + asc(mid(rsp, CNS_PAYLOAD_INDEX+5, 1))
eventmsg "Current PRL size is " & prlsize
print "PRL file size is ", fsize, nl
' now try setting the PRL size just to see what error we get
'
' parameters are NAM (UINT16), PRL Size (UINT32)
cnsbuf[0] = 0
cnsbuf[1] = 0
cnsbuf[2] = 0
cnsbuf[3] = 0
cnsbuf[4] = fsize\256
cnsbuf[5] = fsize AND 255
send_cns(CNS_SET_COMMAND, 0x1052, cnsbuf, 6)
rslt = recv_cns(rsp, CNS_SET_ACKNOWLEDGE, 0x1052)
if rslt < 0 then errexit "PRL update failed: bad response setting the PRL size"
' now try writing the PRL file to see the responses
' we write in 120 byte chunks
'
prlfh = openfile(prlfile)
if prlfh = -1 then errexit "PRL update failed: couldn't open PRL file"
prlblk = 0
while not eof(prlfh)
prlbuf = input(120, prlfh)
n = len(prlbuf)
' parameters are: NAM (UINT16), Block number (UINT16), Block size (UINT16), Block data
cnsbuf[0] = 0
cnsbuf[1] = 0
cnsbuf[2] = 0
cnsbuf[3] = prlblk
cnsbuf[4] = 0
cnsbuf[5] = n
for i = 1 to n
cnsbuf[i+5] = asc(mid(prlbuf, i, 1))
next i
send_cns(CNS_SET_COMMAND, 0x1054, cnsbuf, 6+n)
rslt = recv_cns(rsp, CNS_SET_ACKNOWLEDGE, 0x1054)
if rslt <> 2 then errexit "PRL update failed: bad response to PRL block write request"
prlrslt = asc(mid(rsp, CNS_PAYLOAD_INDEX, 1))*256 + asc(mid(rsp, CNS_PAYLOAD_INDEX+1, 1))
if prlrslt <> 0 then errexit "PRL update failed: " & decode_prl_write_result(prlrslt)
prlblk += 1
wend
close(prlfh)
errexit "PRL Update SUCCESSFUL"
end function
' decode a MODIND update progress code
'
function decode_modind(mcode)
local mcodestr
if mcode = 1 then
mcodestr = "Network Initiated, INFORMATIVE"
elseif mcode = 2 then
mcodestr = "CIDC Started"
elseif mcode = 3 then
mcodestr = "Network Initiated, BACKGROUND"
elseif mcode = 4 then
mcodestr = "CIPRL Started"
elseif mcode = 5 then
mcodestr = "HFA Started"
elseif mcode = 6 then
mcodestr = "Checking for DC Update"
elseif mcode = 7 then
mcodestr = "Updating DC"
elseif mcode = 8 then
mcodestr = "No provisioning update available"
elseif mcode = 9 then
mcodestr = "Checking for PRL Update"
elseif mcode = 10 then
mcodestr = "Updating PRL"
elseif mcode = 11 then
mcodestr = "No PRL update available"
elseif mcode = 12 then
mcodestr = "DC Update Complete"
elseif mcode = 13 then
mcodestr = "PRL Update Complete"
elseif mcode = 14 then
mcodestr = "HFA Update Complete"
elseif mcode = 15 then
mcodestr = "Update Failed Error xxx"
elseif mcode = 16 then
mcodestr = "Retry Re-Establish Session"
elseif mcode = 17 then
mcodestr = "Session Aborted"
elseif mcode = 18 then
mcodestr = "Network Initiated, Complete"
else
mcodestr = "Unknown"
endif
eventmsg "DM status: " & mcodestr
end function
' This runs through the PRL Update procedure for Motorola modules
'
function do_moto_prlupdate
local modind_cmd, modci_cmd, ticks_end, iota_done, modindline, mpos, mcode
' command to enable unsolicited progress reports
modind_cmd = "AT+MODIND=1"
' command to start client initiated PRL update
modci_cmd = "AT+MODCI=1"
eventmsg "Sent " & modind_cmd
print #mc75out, modind_cmd, "\r"
if getOKline() = false then errexit "PRL update failed: MODIND command failed"
eventmsg "Sent " & modci_cmd
print #mc75out, modci_cmd, "\r"
if getOKline() = false then errexit "PRL update failed: MODCI command failed"
' now sit and wait for progress reports
' log all output received
'
' Typical sequence of reports is as follows (see decode_modind for meanings):
' +MODIND: 4
' +MODIND: 9
' +MODIND: 10
' +MODIND: 13
eventmsg "Monitoring progress (up to 5 mins)..."
' set the end time. ticks are units of 10ms
' 5 mins normally
ticks_end = ticks + 5*60*100
' 15 secs for debugging
' ticks_end = ticks + 15*100
iota_done = FALSE
while ticks <= ticks_end and iota_done = FALSE
if getline(modindline) = TRUE then
if modindline <> "" then eventmsg "Received: " & modindline
mpos = instr(modindline, "+MODIND: ")
if mpos > 0 then
mcode = val(mid(modindline, mpos+9))
decode_modind(mcode)
if mcode = 8 or mcode = 11 or mcode = 15 or mcode = 17 then errexit "PRL update failed"
if mcode = 13 then
iota_done = TRUE
endif
endif
endif
wend
if iota_done = FALSE then errexit "PRL update failed: timeout awaiting completion"
' send a reset command. Don't worry about the reply as we'll be rebooting anyway
'
eventmsg "Sent AT$SPRESET"
print #mc75out, "AT$SPRESET\r"
errexit "PRL update SUCCESSFUL"
end function
' Do an automatic PRL update
' This is done using the "AT+PRL=2" command, and monitoring progress using "AT+OMADM=?"
' GOBI modules appear to reboot themselves at the end, so we try to detect this
'
function do_gobi_auto
local res, resstr, i
local omadm_cmd, omadmstatus_cmd, rsp, nrsp, prev_rsp, prev_nrsp, tstart, ticks_end, omadm_done, state_changed
' errexit "Automatic update not yet implemented"
' reset the modem and disable the driver
'
res = execute("modemoff", 0, resstr)
eventmsg "Resetting modem..."
for i = 1 to 5
sleep(1)
next i
' and release only the AT port, not the info port
'
res = execute("modemcc 0 asy_add 255", 0, resstr)
asyportchanged = 1
for i = 1 to 35
sleep(1)
next i
' initialise the AT serial port IO
'
AsyPortName = "ASY" & asystr
mc75asyport = AsyPortName
print "AsyPortName = ", AsyPortName, nl
init_mc75io()
atopened = 1
' First make sure we can talk to the device by ATing it
' until we get OK back
'
i = 0
GotOK = false
while i < 10 and GotOK = false
i += 1
print "Sending AT...", nl
print #mc75out, "AT\r"
if getOKline() = true then GotOK = true
wend
if GotOK = false then
restorecfg()
errexit "PRL update failed: cannot AT device on " & AsyPortName
endif
clear_mc75io()
eventmsg "Automatic provisioning starting"
omadm_cmd = "AT+PRL=2"
omadmstatus_cmd = "AT+OMADM=?"
' get the initial status
'
eventmsg "Getting initial status"
init_nrsp = modem_cmd_lines(omadmstatus_cmd, init_rsp)
if init_nrsp <> 0 then
for i = 0 to init_nrsp-1
eventmsg init_rsp[i]
next i
else
restorecfg()
errexit "PRL update failed: failed to get initial status"
endif
' Start up the OMADM session
'
eventmsg "Sent " & omadm_cmd
print #mc75out, omadm_cmd, "\r"
if getOKline() = false then
restorecfg()
errexit "PRL update failed: bad response to " & omadm_cmd
endif
eventmsg "Monitoring status (up to 5 mins)..."
' set the end time. ticks are units of 10ms
' 5 mins normally
' ticks_end = ticks + 5*60*100
' 60 secs for debugging
tstart = ticks
ticks_end = ticks + 60*100
' now monitor the status
'
prev_nrsp = 0
omadm_done = FALSE
while ticks <= ticks_end and omadm_done = FALSE
sleep(1)
nrsp = modem_cmd_lines(omadmstatus_cmd, rsp)
if nrsp <> 0 then
' check to see if state info has changed
state_changed = 0
if nrsp <> prev_nrsp then
state_changed = 1
else
for i = 0 to nrsp-1
if prev_rsp[i] <> rsp[i] then
state_changed = 1
endif
next i
endif
' and only report state if it has changed
if state_changed <> 0 then
for i = 0 to nrsp-1
eventmsg rsp[i]
prev_rsp[i] = rsp[i]
next i
prev_nrsp = nrsp
endif
' difficult to determine completion because it will
' probably always say "Device is programmed".
' So for now we just look for "None" after "Current device config session status:"
'
' first check to see if state info has changed from initial state
init_state_changed = false
if nrsp <> init_nrsp then
init_state_changed = true
else
for i = 0 to nrsp-1
if init_rsp[i] <> rsp[i] then
init_state_changed = true
endif
next i
endif
if (init_state_changed = false) and ((ticks-tstart) < 500) then
' hold off checking for the first 5 secs if there is no state change
else
for i = 0 to nrsp-1
if instr(rsp[i], "None") > 0 then
omadm_done = TRUE
endif
next i
endif
endif
wend
if omadm_done = FALSE then
restorecfg()
errexit "PRL update failed: timeout awaiting completion"
endif
restorecfg()
errexit "Automatic PRL update session finished"
end function
' do a manual prl update
' this is done using the built in command "qmiprlupd"
'
function do_gobi_manual
local res
res = execute("qmiprlupd", 130, resstr)
if instr(resstr, "PRL update successful") > 0 then
errexit "PRL successfully programmed"
else
errexit "PRL update failed: " & resstr
end if
end function
' For the GOBI module, we can do either automatic or manual update
' The method used depends on whether or not the MSL and PRL file parameters are given
'
function do_gobi_prlupdate
local msl_str, prlfile
' Get the parameters.
'
' string1: the MSL
' string20: the PRL filename
'
if getParam("provision 0 string1 ?", msl_str) = TRUE then
if getParam("provision 0 string20 ?", prlfile) = TRUE then
else
errexit "failed to get prlfile parameter\r\n"
end if
else
errexit "failed to get msl_str parameter\r\n"
end if
print "msl_str=", msl_str, ", prlfile=", prlfile, "\r\n"
' do automatic update if MSL and PRL file are empty
if msl_str = "" AND prlfile = "" then
do_gobi_auto()
exit function
end if
' otherwise we need both for a manual update
if msl_str = "" then errexit "PRL update failed: missing MSL parameter"
if prlfile = "" then errexit "PRL update failed: missing PRL file parameter"
do_gobi_manual()
end function
' returns true if we are running GOBI CDMA firmware
'
function gobi_module_detected
local res, tmp
gobi_module_detected = false
res = execute("tags", 0, tmp)
if res = true then
if InStr(tmp, "QUALCOMM_GOBI_CDMA") > 0 then
gobi_module_detected = true
endif
endif
end function
' ******** MAIN PROGRAM STARTS HERE ********
errcnt = 0
socketopened = 0
cnsopened = 0
atopened = 0
do_restore = 0
asyportchanged = 0
init_log_files()
tnow = now() and 0x7fffffff
eventmsg "PRL update script started at " & FormatDate("0D-MON-YY 0H:0m:0s",tnow)
gobi_module = gobi_module_detected()
' Find out what ASY port is used by modemcc for GPRS
'
if getParam("modemcc 0 asy_add ?", asystr) = TRUE then
print "modemcc 0 asy_add is: ", asystr, nl
else
errexit "PRL update cannot start: unable to get modemcc 0 asy_add"
endif
if asystr = "255" or asystr = "0" or asystr = "" then
errexit "PRL update cannot start: invalid modemcc asy_add (try muxon)"
endif
' Find out what INFO ASY port is used by modemcc for GPRS
'
if getParam("modemcc 0 info_asy_add ?", infoasystr) = TRUE then
print "modemcc 0 info_asy_add is: ", infoasystr, nl
else
errexit "PRL update cannot start: unable to get modemcc 0 info_asy_add"
endif
if infoasystr = "0" or infoasystr = "" then
errexit "PRL update cannot start: invalid modemcc info_asy_add (try muxon)"
endif
' Find out which PPP instance is configured for GPRS
'
got_gprs_ppp = get_gprs_ppp_instance(gprs_ppp_instance)
' deactivate PPP
'
if got_gprs_ppp then
print "PPP ", gprs_ppp_instance, " is configured for GPRS", nl
res = execute("ppp " & gprs_ppp_instance & " deact_rq", 0, resstr)
sleep(1)
else
print "No PPP instances configured for GPRS", nl
endif
if gobi_module then
do_gobi_prlupdate()
stop
endif
' now reset the modem and disable the driver
'
res = execute("modemoff", 0, resstr)
eventmsg "Connecting to modem..."
for i = 1 to 5
sleep(1)
next i
' the modemdisc command releases the modemports and disables the driver
'
res = execute("modemdisc", 0, resstr)
do_restore = 1
for i = 1 to 15
sleep(1)
next i
' initialise the AT serial port IO
'
AsyPortName = "ASY" & asystr
mc75asyport = AsyPortName
print "AsyPortName = ", AsyPortName, nl
init_mc75io()
atopened = 1
' First make sure we can talk to the device by ATing it
' until we get OK back
'
i = 0
GotOK = false
while i < 10 and GotOK = false
i += 1
print "Sending AT...", nl
print #mc75out, "AT\r"
if getOKline() = true then GotOK = true
wend
if GotOK = false then errexit "PRL update failed: cannot AT device on " & AsyPortName
manufacturer = modem_cmd("AT+GMI")
eventmsg "Manufacturer is: " & manufacturer
if instr(manufacturer, "Motorola") <> undef then
eventmsg "Motorola module specific PRL update starting"
do_moto_prlupdate()
else
eventmsg "Sierra Wireless module specific PRL update starting"
do_prlupdate()
endif
stop
ErrorLabel:
'print "Got error code: ", error(), "(", error$, ")", nl
if error() = 22 and errcnt < 20 then
print "Retrying connection ...", nl
sleep(1)
errcnt = errcnt + 1
on error goto ErrorLabel
resume
endif
errexit(error$)