USB 413c:81e0 (81d7 is the non-eSIM DW5821e), Foxconn T77W968, Qualcomm
Snapdragon X20, firmware T77W968.F1.0.0.5.2.GC.013. A single eUICC, no
physical SIM slot.
option exposes four ttyUSB ports. udev/78-dell-dw5821e.rules
gives them stable names by USB interface number so scripts never guess:
| symlink | interface | use |
|---|---|---|
/dev/dw5821e-at |
2 | AT commands and PPP data (ATD*99#) |
/dev/dw5821e-at2 |
3 | second AT port — diagnostics while PPP holds the first (+CGCONTRDP, +CSQ, SMS) |
/dev/dw5821e-gps |
4 | NMEA |
/dev/dw5821e-dm |
5 | Qualcomm DM |
cdc_mbim also registers wwan0/cdc-wdm0; we do not use MBIM data on this
modem (untested, not needed), but qmicli --device-open-mbim
--dms-set-operating-mode=reset on cdc-wdm0 works as a last-resort reset.
AT+CSIMexport LPAC_APDU=at_csim LPAC_APDU_AT_DEVICE=/dev/dw5821e-at LPAC_HTTP=curl
lpac profile list
The AT port must be exclusively free: stop pppd, check with fuser, kill a
stuck lpac. Leftover /var/lock/LCK..ttyUSB0 files from a dead pppd block
the next dial — the scripts remove them.
scripts/dw5821e-ppp/esim-switch-profile-ppp.sh <AID> <APN>:
AT+CFUN? before touching lpac. If a previous cycle died
between CFUN=0 and CFUN=1 the radio is off, the eUICC is unpowered and
lpac returns nothing; the script sends AT+CFUN=1 and waits for
+CPIN: READY first;lpac profile list → disable current → enable target;AT+CFUN=0, 2 s, AT+CFUN=1; poll AT+CREG? for ,1/,5
(3 s after CFUN=1 on our network);esim-ensure-apn.sh <APN>: the attach that CFUN=1 triggers
uses whatever APN context 1 held before, i.e. the previous operator’s; the
modem answers ERROR to AT+CGDCONT while CFUN=0. The helper sets
AT+CGDCONT=1,"IP","<APN>" with the radio on, reads +CGCONTRDP=1, and if
the active context carries another APN does AT+CGATT=0 → AT+CGATT=1
(≈14 s) and re-checks. It uses the second AT port so it never competes with
pppd. Called from the switch, bearer-up and refresh paths;pppd call esim-auto, wait
for ppp0 to get an address, routing table 100 + rule, namespace.Whole switch: ≈80 s.
Generated by _ppp-peer-template.sh
(regenerated on every bring-up — a hand-edited peer with a wrong device path
once sent a recovery ladder through seven escalations for nothing):
/dev/dw5821e-at
115200
connect "/usr/sbin/chat -v -f /etc/ppp/chatscripts/esim-auto"
noauth usepeerdns noipdefault nopcomp noaccomp novj nobsdcomp nodeflate
maxfail 5
holdoff 10
ABORT "BUSY" ABORT "NO CARRIER" ABORT "ERROR"
"" AT
OK ATH
OK AT+CGDCONT=1,"IP","<APN>"
OK ATD*99#
CONNECT ""
Expect Could not determine remote IP address: defaulting to 10.64.64.64 and
IPV6CP: timeout sending Config-Requests in the pppd log — both harmless.
PAP succeeds with empty credentials on the Russian operators we use.
esim-bearer-refresh-ppp.sh <APN>
kills pppd, drops ppp0, removes stale lock files, ensures the attach APN and
dials again. A PPP session that negotiated IPCP but shows Sent N bytes,
received 0 bytes on hangup never carried payload — look at the attach APN
(+CGCONTRDP=1 on the second port) and at the operator, not at pppd.