Hello all,
I wrote a powershell script to automatically unlock a pin-locked broadband device during windows boot. The script already works fine (somehow... this is my first powershell script exceeding 10 lines) but I'm not very happy about the way I solved the problme.
There must be a simpler way to do it. Let me show you why:
The 'real' WWAN device which is attached to the computer is split up into several virtual devices. The two important ones are the modem itself, (found under modems in the device manager) and a so called “broadband network adaptor” (found under network adaptors).
Although we are talking about a mini PCI Card, all devices are published as USB-Devices. So by looking at the DeviceIDs and PIDs you can find out which network adaptor is related to which modem.
Now, what I did to unlock the modem is the following:
I connected to the COM-Port of the modem to send a CPIN AT-command.
$port.Write("AT+CPIN=""" + $pin + """`r")Since unlocking the modem is not enough to make windows realize the status change I search for the corresponding network adapter and reset it.
# find corresponding network adapter and reset it
$modemPID = [regex]::match($modem.DeviceID, "(PID_\d+)[&\\]").Groups[1]
$bbd = gwmi Win32_NetworkAdapter | Where-Object {$_.PNPDeviceID -like "*$modemPID*"}
$bbd.Disable()
$bbd.Enable()After that, the broadband device is shown as “ready to connect” in the network tray icon.
Like I said: It works. But there should be a way to solve it without AT-commands. All this modem chat and COMPort stuff makes it rather complex and error prone. And I doubt that any AT-commands are involved when you unlock the device using the windows GUI…
Any ideas are very welcome.
Thanks in advance
Henning
Here' the full script: It has been tested on two differnt notebooks so far. So don't expect anything stable :-)
# - SIMunlock - unlocks USB driven broadband devices by using AT-commands
#on the modem and resetting the corresponding network adapter afterwards.
#pin is read from file specified in $pinFile (see below functions)
#This is designed to run at system startup
#Eventlog entries are made in 'System', source 'SIMunlock'
#EventID 3001: (Error) catch all, everything not excepted
#EventID 3002: (Warning) no or empty pinFile
#EventID 3003: (info) modem unlocked
#EventID 3004: (info) nothing to do, modem already unlocked
### functinos ###
#get lock state
# false if already unlocked
# true if SIM PIN is needed
# throws an Error if anything else happens
function isLocked($port)
{
try
{
$port.Write("AT+CPIN?`r")#request pin status
$result=""
$loops=0
while($line = $port.ReadLine())
{
$loops++
$result = $result + "`n" + $line
#check if the usual SIM PIN ist needed.
#(Could also be SIM PUK for instance,
#something we wouldn't be able to deal with...)
if ($line -eq "+CPIN: SIM PIN`r")
{ return $true }
# 'Ready' means already unlocked...
if ($line -eq "+CPIN: Ready`r")
{ return $false }
if ($loops -gt 20)
{ throw $result }
}
}
catch
{
throw $result
}
}
#unlock modem
#no return code
#throws an runtime exception if anything unexpected happens
function unlock($port)
{
try
{
#send pin to modem
$port.Write("AT+CPIN=""" + $pin + """`r")
$result=""
$loops=0
$cpinReply=$false
#wait for modem to ack pin
while($line = $port.ReadLine())
{
$loops++
$result = $result + "`n" + $line
if ($line -match "^AT[+]CPIN")
{ $cpinReply = $true }
if (($line -eq "OK`r") -and ($cpinReply))
{ return }
if ($loops -gt 20)
{ throw $result }
}
}
catch
{
throw $result
}
}
### script ###
$pinFile="C:\Software\p.txt"
try{
#find active modem
$modem = Get-WMIObject win32_potsmodem | Where-Object {$_.Status -like "Ok"}
if (!$modem.AttachedTo) { throw "Kein Modem gefunden!" }
#connect to modem
$port = New-Object System.IO.Ports.SerialPort
$port.PortName = $modem.AttachedTo
$port.BaudRate = "9600"
$port.Parity = "None"
$port.DataBits = 8
$port.StopBits = 1
$port.ReadTimeout = 2000 # 2 seconds
$port.DtrEnable = "true"
$port.open() #opens serial connection
Start-Sleep 0.3 # wait 0.3 seconds until device is ready
#check if there's need to get busy
if (isLocked($port))
{#yes, read pin from file
$pin=get-content $pinFile -TotalCount 1 -ea SilentlyContinue
if (($pin -eq $null) -or ($pin -eq ""))
{#no pin found
new-eventlog -source $MyInvocation.MyCommand.Name -logname System -ErrorAction SilentlyContinue
write-eventlog -logname System -source $MyInvocation.MyCommand.Name -eventID 3002 -entrytype Warning -message "Modem konnte nicht entsperrt werden, da keine PIN hinterlegt wurde"
}
else
{#pin found, unlock device
unlock($port)
new-eventlog -source $MyInvocation.MyCommand.Name -logname System -ErrorAction SilentlyContinue
write-eventlog -logname System -source $MyInvocation.MyCommand.Name -eventID 3003 -entrytype Information -message "Modem wurde entsperrt"
}
}
else
{#no, device is already unlocked
new-eventlog -source $MyInvocation.MyCommand.Name -logname System -ErrorAction SilentlyContinue
write-eventlog -logname System -source $MyInvocation.MyCommand.Name -eventID 3004 -entrytype Information -message "Nichts zu tun. Modem ist bereits ensperrt"
}
# find corresponding network adapter and reset it
$modemPID = [regex]::match($modem.DeviceID, "(PID_\d+)[&\\]").Groups[1]
$bbd = gwmi Win32_NetworkAdapter | Where-Object {$_.PNPDeviceID -like "*$modemPID*"}
$bbd.Disable()
$bbd.Enable()
}
catch{
$msg=$_
new-eventlog -source $MyInvocation.MyCommand.Name -logname System -ErrorAction SilentlyContinue
write-eventlog -logname System -source $MyInvocation.MyCommand.Name -eventID 3001 -entrytype Error -message $msg
}
finally{
$port.Close() #closes serial connection
# echo "Done...!"
}