How to switch the Orbic RC400L between carriers using only a root shell and AT commands. No custom firmware required — just the stock device with root access.
The Orbic RC400L ships with Verizon/Kajeet PDP context profiles baked in. When you insert a different carrier's SIM (T-Mobile, AT&T, etc.), the modem detects the new network but the old APN configurations remain, preventing a data connection. You must manually delete the old PDP contexts, configure new ones, update the QCMAP config file, and reboot.
Why AT+CGACT doesn't work: The stock QCMAP_ConnectionManager daemon owns the data call. Attempting AT+CGACT=1,<cid> returns +CME ERROR: unknown. Instead, we configure the APN at both the AT command level and in QCMAP's config file, then reboot to let QCMAP establish the connection cleanly.
Two things must be changed:
- Modem PDP contexts (via AT commands) — tells the modem which APN to use
- QCMAP config file (
/usrdata/data/qcmap/mobileap_cfg.xml) — tells the connection manager which APN to request
If these are out of sync, you'll get connection loops (^DATACONNECT / ^DATADISCONN cycling).
| Requirement | Details |
|---|---|
| Root shell | Port 2323 via rayhunter exploit (see Getting Root Access) |
| WiFi connection | Connected to the device's hotspot (default: 192.168.1.1) |
| SIM card | Activated SIM from the target carrier, inserted in the device |
These are the known-working APN configurations, tested on real devices.
| CID | PDP Type | APN |
|---|---|---|
| 1 | IPV4V6 | fast.t-mobile.com |
Single context. T-Mobile is the simplest — one APN handles everything. The generic fast.t-mobile.com works for all T-Mobile and T-Mobile MVNO SIMs tested (2026-02-15).
| CID | PDP Type | APN |
|---|---|---|
| 1 | IPV4V6 | vzwinternet |
| 2 | IPV6 | VZWAPP |
| 3 | IPV4V6 | vzwinternet |
| 6 | IPV4V6 | VZWEMERGENCY |
Verizon requires multiple contexts. CID 1 is the primary data bearer; CID 3 is a duplicate used by IMS. CID 6 is for E911.
| CID | PDP Type | APN |
|---|---|---|
| 1 | IPV4V6 | nxtgenphone |
Single context. Tested on device 2026-02-15 with AT&T prepaid SIM (IMSI 310410...). The nxtgenphone APN is the correct one for AT&T prepaid/consumer plans. The broadband APN (sometimes auto-configured by the modem) gets an IP address but routes zero packets — do not use it.
Important: AT&T prepaid SIMs must be activated at att.com/prepaid/activations or att.com/activateprepaid before they will pass data. An unactivated SIM will connect to the network (get an IP) but all HTTP traffic is redirected to the activation portal.
| CID | PDP Type | APN |
|---|---|---|
| 1 | IPV4V6 | LAUSDFG.GW5.VZWENTP |
| 2 | IPV6 | VZWAPP |
| 3 | IPV4V6 | LAUSDFG.GW5.VZWENTP |
| 4 | IPV4V6 | VZWAPP |
| 6 | IPV4V6 | VZWEMERGENCY |
This is the factory default for Kajeet SmartSpot units. The enterprise APN LAUSDFG.GW5.VZWENTP will only work with an active Kajeet account.
Always save your current configuration before switching carriers. This lets you restore if something goes wrong.
# On the device (via root shell):
cp /usrdata/data/qcmap/mobileap_cfg.xml /usrdata/data/qcmap/mobileap_cfg.xml.bak# Record current AT-level PDP contexts:
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# Save the output somewhere — you'll need the CID numbers, PDP types, and APN names to restoreTo revert to a previous carrier configuration:
# Restore QCMAP config
cp /usrdata/data/qcmap/mobileap_cfg.xml.bak /usrdata/data/qcmap/mobileap_cfg.xml
# Then follow the normal carrier switch procedure to set the AT-level PDP contexts back
# and reboot (Step 9)Spawn a root shell.
get a root shellVerify the shell is up:
nc 192.168.1.1 2323
# You should see no prompt — type 'id' and press Enter
id
# Expected: uid=0(root) gid=0(root)The modem's AT command port is /dev/smd7. It's a character device with no line buffering — you need to use a background reader pattern. Send commands one at a time. Rapid-fire commands will crash the modem.
The pattern for every AT command in this guide:
# Template — replace CMD with the actual AT command
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'CMD\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outTest it with a simple command first:
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'ATI\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outExpected output:
Manufacturer: QUALCOMM INCORPORATED
Model: 0
Revision: MPSS.JO.2.0.2.c1.1-00032-9607_GENNS_PACK-1 1 [Sep 01 2017 01:00:00]
SVN: 03
IMEI: 861064040xxxxxx
+GCAP: +CGSM,+DS,+ES
OK
If you get no output, wait 5 seconds and try again. The /dev/smd7 device can only have one reader at a time.
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CIMI\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outExample output for T-Mobile:
3102604215xxxxx
OK
The first 5-6 digits tell you the carrier:
31026x= T-Mobile31148xor31048x= Verizon31041x= AT&T
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outExample output (device still has Verizon config with T-Mobile SIM):
+CGDCONT: 1,"IPV4V6","fast.t-mobile.com","0.0.0.0",0,0,0,0
+CGDCONT: 2,"IPV6","VZWAPP","0.0.0.0",0,0,0,0
+CGDCONT: 3,"IPV4V6","vzwinternet","0.0.0.0",0,0,0,0
+CGDCONT: 4,"IPV4V6","VZWAPP","0.0.0.0",0,0,0,0
+CGDCONT: 6,"IPV4V6","VZWEMERGENCY","0.0.0.0",0,0,0,0
OK
CIDs 2, 3, 4, 6 are leftover Verizon contexts that need to be removed.
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGACT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outExample output:
+CGACT: 1,0
+CGACT: 2,0
+CGACT: 3,1
+CGACT: 6,0
OK
The ,1 at the end means active. Here CID 3 (vzwinternet) is active — the old Verizon APN grabbed the T-Mobile radio, which won't work properly.
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CEREG?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out+CEREG: 0,1 <- registered, home network
States: 0=not registered, 1=home, 2=searching, 3=denied, 5=roaming
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGPADDR=1\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out+CGPADDR: 1,"28.183.217.80"
OK
If you see 0.0.0.0 or no address, data isn't connected.
Delete every context that doesn't belong to the target carrier. To delete a context, send AT+CGDCONT=<cid> with no other parameters — this removes that CID entirely.
Wait 3 seconds between each command. Do not rush.
Example: switching from Verizon/Kajeet to T-Mobile. Keep CID 1 (we'll reconfigure it), delete 2, 3, 4, 6:
# Delete CID 2
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=2\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# Expected: OK
# Wait between commands
sleep 3
# Delete CID 3
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=3\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
# Delete CID 4
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=4\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
# Delete CID 6
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=6\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outAll should return OK. If a CID doesn't exist, you'll get ERROR — that's fine, it just means it was already gone.
Set up the PDP contexts for the target carrier. Format:
AT+CGDCONT=<cid>,"<pdp_type>","<apn>"
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=1,"IPV4V6","fast.t-mobile.com"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# Expected: OKThat's it — one command for T-Mobile.
# CID 1 - Primary internet
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=1,"IPV4V6","vzwinternet"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
# CID 2 - App services
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=2,"IPV6","VZWAPP"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
# CID 3 - Secondary internet (IMS)
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=3,"IPV4V6","vzwinternet"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
# CID 6 - Emergency services
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=6,"IPV4V6","VZWEMERGENCY"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=1,"IPV4V6","nxtgenphone"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# Expected: OKDo NOT use broadband — it connects but routes zero packets. nxtgenphone is the correct AT&T APN.
Confirm the new contexts are set:
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outFor T-Mobile you should see only:
+CGDCONT: 1,"IPV4V6","fast.t-mobile.com","0.0.0.0",0,0,0,0
OK
No leftover Verizon CIDs.
This is critical. AT commands alone are not enough. The QCMAP_ConnectionManager daemon reads its APN from a config file and will try to establish a data session using whatever APN is in that file, regardless of what AT-level PDP contexts are set.
# Check current QCMAP APN:
grep -i apn /usrdata/data/qcmap/mobileap_cfg.xmlYou'll see something like:
<APN>LAUSDFG.GW5.VZWENTP</APN>Change it to match the new carrier's primary APN:
sed -i 's|<APN>[^<]*</APN>|<APN>fast.t-mobile.com</APN>|' /usrdata/data/qcmap/mobileap_cfg.xmlsed -i 's|<APN>[^<]*</APN>|<APN>vzwinternet</APN>|' /usrdata/data/qcmap/mobileap_cfg.xmlsed -i 's|<APN>[^<]*</APN>|<APN>nxtgenphone</APN>|' /usrdata/data/qcmap/mobileap_cfg.xmlAlso ensure AutoConnect is enabled:
sed -i 's|<AutoConnect>0</AutoConnect>|<AutoConnect>1</AutoConnect>|' /usrdata/data/qcmap/mobileap_cfg.xmlVerify the changes:
grep -E '<APN>|<AutoConnect>' /usrdata/data/qcmap/mobileap_cfg.xmlThe stock device may have mobile data disabled. The quickest check is via the GoAhead stock web API (port 80):
# Check if mobile data is enabled (from the device shell):
# If you see "status":0 in the response, data is offIf you have HTTP access to GoAhead (port 80), enable it via the stock API. See Alternative: GoAhead Stock Web API below.
Do NOT kill QCMAP_ConnectionManager directly — it manages the WiFi bridge, and killing it drops WiFi immediately with no way to reconnect except via ADB USB or physical reboot.
Instead, reboot the device cleanly:
rebootAfter reboot (~30 seconds), reconnect to the device WiFi and re-establish the root shell:
nc 192.168.1.1 2323Wait a few seconds for QCMAP to establish the data bearer, then check:
sleep 5
# Check for IP address
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGPADDR=1\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outExpected:
+CGPADDR: 1,"100.138.59.177"
OK
Any non-zero, non-0.0.0.0 address means the data connection is up.
Verify registration:
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CEREG?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out+CEREG: 0,1 <- home network
Or +CEREG: 0,5 if roaming.
Check the operator name:
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+COPS?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out+COPS: 0,0,"T-Mobile",7
OK
The 7 at the end means E-UTRAN (LTE).
Check the Linux network interface:
ifconfig rmnet_data0You should see UP RUNNING with an assigned IP address and non-zero RX packets.
At this point the device should be serving data on the new carrier. Connect a WiFi client and test.
This is the exact sequence that was tested and proven on a live device (2026-02-15). SIM already swapped, device booted.
# 1. Get a shell
# (from your machine, connected to device WiFi)
nc 192.168.1.1 2323
# 2. Backup current config
cp /usrdata/data/qcmap/mobileap_cfg.xml /usrdata/data/qcmap/mobileap_cfg.xml.bak
# 3. Confirm SIM is T-Mobile
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CIMI\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> 310260421579252 (31026 = T-Mobile)
# 4. See what's configured
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> CID 1: fast.t-mobile.com
# -> CID 2: VZWAPP <- leftover
# -> CID 3: vzwinternet <- leftover, ACTIVE
# -> CID 4: VZWAPP <- leftover
# -> CID 6: VZWEMERGENCY <- leftover
# 5. Delete old Verizon contexts
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=2\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=3\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=4\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=6\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
# 6. Configure T-Mobile APN (CID 1 may already be correct from SIM auto-config)
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=1,"IPV4V6","fast.t-mobile.com"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
# 7. Verify clean config
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> Only CID 1: fast.t-mobile.com
# 8. Update QCMAP config
sed -i 's|<APN>[^<]*</APN>|<APN>fast.t-mobile.com</APN>|' /usrdata/data/qcmap/mobileap_cfg.xml
sed -i 's|<AutoConnect>0</AutoConnect>|<AutoConnect>1</AutoConnect>|' /usrdata/data/qcmap/mobileap_cfg.xml
# 9. Reboot
reboot
# Wait ~30s, reconnect WiFi, re-spawn shell
# 10. Verify
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGPADDR=1\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGPADDR: 1,"100.138.59.177"
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+COPS?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +COPS: 0,0,"T-Mobile",7Total time: ~90 seconds from shell to verified data connection (including reboot).
# 1. Swap SIM (power off, swap, power on, connect WiFi, get shell)
# 2. Backup config
cp /usrdata/data/qcmap/mobileap_cfg.xml /usrdata/data/qcmap/mobileap_cfg.xml.bak
# 3. Confirm SIM is Verizon
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CIMI\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> 311480xxxxxxxxx (31148 = Verizon)
# 4. Delete old T-Mobile context (only CID 1 if clean)
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGDCONT: 1,"IPV4V6","fast.t-mobile.com",...
# CID 1 will be overwritten, no need to delete
# 5. Configure Verizon contexts
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=1,"IPV4V6","vzwinternet"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=2,"IPV6","VZWAPP"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=3,"IPV4V6","vzwinternet"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=6,"IPV4V6","VZWEMERGENCY"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
# 6. Update QCMAP config
sed -i 's|<APN>[^<]*</APN>|<APN>vzwinternet</APN>|' /usrdata/data/qcmap/mobileap_cfg.xml
sed -i 's|<AutoConnect>0</AutoConnect>|<AutoConnect>1</AutoConnect>|' /usrdata/data/qcmap/mobileap_cfg.xml
# 7. Reboot
reboot
# Wait ~30s, reconnect WiFi, re-spawn shell
# 8. Verify
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGATT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGATT: 1
sleep 5
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGPADDR=1\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGPADDR: 1,"28.167.107.145"
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+COPS?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +COPS: 0,0,"Verizon",7Tested 2026-02-15 with AT&T prepaid SIM.
# 1. Swap SIM, power on, connect WiFi, get shell
nc 192.168.1.1 2323
# 2. Backup config
cp /usrdata/data/qcmap/mobileap_cfg.xml /usrdata/data/qcmap/mobileap_cfg.xml.bak
# 3. Confirm SIM is AT&T
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CIMI\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> 310410426347917 (31041 = AT&T)
# 4. Check current config — modem may auto-configure CID 1 with "broadband"
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGDCONT: 1,"IPV4V6","broadband","0.0.0.0",0,0,0,0
# -> +CGDCONT: 6,"IPV4V6","VZWEMERGENCY","0.0.0.0",0,0,0,0
# Note: CID 6 VZWEMERGENCY is stored in modem NV and reappears after reboot
# 5. Delete leftover Verizon emergency context
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=6\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
# 6. Set correct AT&T APN (NOT broadband!)
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=1,"IPV4V6","nxtgenphone"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
sleep 3
# 7. Verify
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGDCONT: 1,"IPV4V6","nxtgenphone","0.0.0.0",0,0,0,0
# 8. Update QCMAP config
sed -i 's|<APN>[^<]*</APN>|<APN>nxtgenphone</APN>|' /usrdata/data/qcmap/mobileap_cfg.xml
sed -i 's|<AutoConnect>0</AutoConnect>|<AutoConnect>1</AutoConnect>|' /usrdata/data/qcmap/mobileap_cfg.xml
# 9. Reboot
reboot
# Wait ~30s, reconnect WiFi, re-spawn shell
# 10. Verify connection
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGATT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGATT: 1
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGPADDR=1\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGPADDR: 1,"10.191.55.176"
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+COPS?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +COPS: 0,0,"AT&T",7
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CSQ\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CSQ: 31,99 (excellent signal)
# 11. Check Linux interface
ifconfig rmnet_data0
# -> Should show UP RUNNING with assigned IP and non-zero RX packets
# If RX packets is 0, the SIM may need activation (see AT&T note above)Note: If ping 8.8.8.8 fails but you have an IP, check for carrier HTTP redirect:
# Raw HTTP test (from device shell):
printf 'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n' | nc 142.250.80.46 80
# If you see "302 Found" + "Location: https://www.att.com/prepaid/activations/"
# then the SIM is not activated yetThe stock GoAhead web server on port 80 provides another way to manage data connections. This is useful when you can't use AT commands or need to toggle mobile data on/off.
GoAhead requires authentication. From the device shell:
# Get the auth key:
curl -s http://127.0.0.1/goform/GetLoginInfo
# Response: {"priKey":"<some_key>"}# Enable mobile data:
curl -s -X POST http://127.0.0.1/action/SetMobileDataStatus \
-H "Content-Type: application/json" \
-b "token=<your_token>" \
-d '{"status":1}'
# Disable mobile data:
curl -s -X POST http://127.0.0.1/action/SetMobileDataStatus \
-H "Content-Type: application/json" \
-b "token=<your_token>" \
-d '{"status":0}'curl -s http://127.0.0.1/action/GetMobileStatusInfo -b "token=<your_token>"
# Returns: mode, signal, ip, connection_time, uptime, etc.- The GoAhead profile system is read-only — you cannot change the APN through
SetProfileorAddProfile. These calls crash GoAhead. - To change the APN, you must edit the QCMAP config file directly (Step 7 above).
- GoAhead always shows its built-in profile (e.g.,
broadbandfor AT&T SIMs) regardless of what QCMAP is actually using.
If WiFi goes down (e.g., QCMAP was killed), USB ADB provides a backup path.
# From your Mac:
adb forward tcp:8080 tcp:80
# Now access GoAhead via localhost:
curl http://localhost:8080/goform/GetLoginInfoAnother process may be reading the device. Kill any existing readers:
# Check for processes using smd7
fuser /dev/smd7
# Kill if found
kill <pid>Wait 5 seconds, then retry.
The modem can't find the network. This happens when:
- SIM not recognized — check
AT+CIMIreturns a valid IMSI - Wrong APN — verify
AT+CGDCONT?shows the correct APNs for your carrier - Weak signal — try
AT+CSQto check signal strength (10+ is usable, 20+ is good) - Rapid switching — the modem needs time between detach/attach cycles. Wait 5-10 seconds and try again. It consistently works by the 2nd or 3rd attempt.
Retry pattern:
# Wait longer, then try again
sleep 5
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGATT=1\r' > /dev/smd7; sleep 3; kill %1 2>/dev/null; cat /tmp/at_out
sleep 2
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGATT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outSeveral possible causes:
- Wrong APN — most common cause. For AT&T,
broadbandgets an IP but doesn't route. Usenxtgenphone. - SIM not activated — carrier assigns an IP but redirects all traffic. Test with raw HTTP:
If you see a
printf 'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n' | nc 142.250.80.46 80
302redirect to your carrier's activation page, the SIM needs activation. - QCMAP not bridging — check
ifconfig rmnet_data0. If it showsNO FLAGSor no IP, QCMAP isn't managing the connection. Verify QCMAP config has<AutoConnect>1</AutoConnect>and reboot. - QCMAP/modem APN mismatch — if QCMAP config says one APN but modem has another, you'll get connection cycling. Make sure both match (Step 7).
Traffic is flowing but being intercepted:
- Carrier captive portal — unactivated SIM. See "SIM not activated" above.
- DNS failure — try pinging by IP:
ping -c1 8.8.8.8. If that works but DNS doesn't, check/tmp/resolv_rmnet_data.conffor carrier DNS servers and verify dnsmasq is forwarding.
Symptoms: ^DATACONNECT immediately followed by ^DATADISCONN in dmesg, connection cycling.
Fix: Make sure the APN in QCMAP config matches the AT-level CID 1 APN, then reboot.
# Check QCMAP APN
grep '<APN>' /usrdata/data/qcmap/mobileap_cfg.xml
# Check AT-level APN
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outNever killall QCMAP_ConnectionManager — it manages the WiFi bridge. Killing it drops WiFi immediately.
Recovery:
- ADB USB —
adb forward tcp:8080 tcp:80to access GoAhead, then reboot via command injection (see Recovery section above) - Physical reboot — hold power button, or unplug/replug USB power
The carrier rejected the APN. This means:
- The APN name is wrong for your SIM/plan
- The SIM isn't activated on the carrier's network
- The carrier requires a specific APN that differs from the generic one
Check with AT+CEER for the detailed rejection cause:
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CEER\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_outSome PDP contexts are stored in modem NV memory. The Verizon VZWEMERGENCY (CID 6) is particularly persistent — it reappears after every reboot even when deleted. This is harmless; just ensure CID 1 has the correct APN.
The QCMAP config file changes DO persist across reboots (stored on /usrdata/ partition).
The stock GoAhead web API crashes (connection drops) when you try SetProfile or AddProfile for the built-in readonly profile. Don't use these endpoints. Edit the QCMAP config file directly instead.
Python requests library (HTTP/1.1 with keepalive) causes GoAhead to drop connections. Use raw HTTP/1.0 sockets or curl instead.
| IMSI Prefix | Carrier |
|---|---|
| 31026 | T-Mobile |
| 31020-31025, 31027 | T-Mobile (alternate) |
| 31148, 31048 | Verizon |
| 31041 | AT&T |
| Carrier | APN | Notes |
|---|---|---|
| T-Mobile | fast.t-mobile.com |
Works for MVNOs too |
| Verizon | vzwinternet |
Primary; also needs VZWAPP + VZWEMERGENCY |
| AT&T | nxtgenphone |
Do NOT use broadband |
| Kajeet | LAUSDFG.GW5.VZWENTP |
Enterprise only |
| File | Purpose |
|---|---|
/usrdata/data/qcmap/mobileap_cfg.xml |
QCMAP APN and AutoConnect config |
/usrdata/data/usr/goahead/default_pwd |
GoAhead/WiFi password |
/data/dnsmasq.conf |
DNS forwarder config |
/tmp/resolv_rmnet_data.conf |
Carrier DNS servers (auto-populated) |
| Command | Purpose |
|---|---|
AT+CIMI |
Read SIM IMSI |
AT+CGSN |
Read IMEI (just the number) |
ATI |
Read IMEI + device info |
AT+CGDCONT? |
List configured PDP contexts |
AT+CGACT? |
List active PDP contexts |
AT+CGDCONT=<cid> |
Delete PDP context |
AT+CGDCONT=<cid>,"<type>","<apn>" |
Configure PDP context |
AT+CGATT=0 |
Detach from network |
AT+CGATT=1 |
Attach to network |
AT+CGATT? |
Check attach status |
AT+CGPADDR=1 |
Check IP address on CID 1 |
AT+COPS? |
Check registered operator |
AT+CEREG? |
Check LTE registration status |
AT+CSQ |
Check signal strength |
AT+CEER |
Last error/rejection cause |
If you're in a hurry and know the device has a T-Mobile SIM:
# Delete all non-CID-1 contexts, set CID 1 to T-Mobile, update QCMAP, reboot
for cid in 2 3 4 5 6; do printf "AT+CGDCONT=$cid\r" > /dev/smd7; sleep 1; done; \
printf 'AT+CGDCONT=1,"IPV4V6","fast.t-mobile.com"\r' > /dev/smd7; sleep 1; \
sed -i 's|<APN>[^<]*</APN>|<APN>fast.t-mobile.com</APN>|' /usrdata/data/qcmap/mobileap_cfg.xml; \
sed -i 's|<AutoConnect>0</AutoConnect>|<AutoConnect>1</AutoConnect>|' /usrdata/data/qcmap/mobileap_cfg.xml; \
rebootWarning: This fires commands without reading responses and reboots immediately. Use the step-by-step procedure above when debugging.
AT&T SIM swapped out, T-Mobile SIM inserted, device booted.
# 1. Spawn shell
nc 192.168.1.1 2323
# 2. Backup config (was AT&T nxtgenphone)
cp /usrdata/data/qcmap/mobileap_cfg.xml /usrdata/data/qcmap/mobileap_cfg.xml.bak.att
# 3. Confirm SIM is T-Mobile
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CIMI\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> 310260421579252 (31026 = T-Mobile)
# 4. Check current config — modem auto-configured CID 1 with correct APN!
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGDCONT: 1,"IPV4V6","fast.t-mobile.com","0.0.0.0...",0,0,0,0
# -> +CGDCONT: 6,"IPV4V6","VZWEMERGENCY","0.0.0.0...",0,0,0,1
# Note: CID 1 auto-detected correctly. CID 6 VZWEMERGENCY persists in modem NV.
# 5. Delete leftover Verizon emergency context
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=6\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> OK
sleep 3
# 6. CID 1 already has fast.t-mobile.com — set it explicitly to be safe
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGDCONT=1,"IPV4V6","fast.t-mobile.com"\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> OK
sleep 3
# 7. Update QCMAP config (was nxtgenphone from AT&T)
sed -i 's|<APN>[^<]*</APN>|<APN>fast.t-mobile.com</APN>|' /usrdata/data/qcmap/mobileap_cfg.xml
sed -i 's|<AutoConnect>0</AutoConnect>|<AutoConnect>1</AutoConnect>|' /usrdata/data/qcmap/mobileap_cfg.xml
# 8. Verify QCMAP
grep -E '<APN>|<AutoConnect>' /usrdata/data/qcmap/mobileap_cfg.xml
# -> <AutoConnect>1</AutoConnect>
# -> <APN>fast.t-mobile.com</APN>
# 9. Check status (no reboot needed — CID 1 was already active)
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGACT?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGACT: 1,1 (CID 1 active)
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CEREG?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CEREG: 0,1 (registered, home)
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+COPS?\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +COPS: 0,0,"T-Mobile",7 (LTE)
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CGPADDR=1\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CGPADDR: 1,100.243.217.154,... (CGNAT IPv4 + IPv6)
(cat /dev/smd7 > /tmp/at_out &); sleep 0.3; printf 'AT+CSQ\r' > /dev/smd7; sleep 2; kill %1 2>/dev/null; cat /tmp/at_out
# -> +CSQ: 28,99 (good signal)
# 10. Check Linux interface
ifconfig rmnet_data0
# -> UP RUNNING, inet 100.243.217.154, inet6 2607:fb90:...
# -> RX packets:9 (low — SIM activation still processing)
route -n
# -> Default route via 100.243.217.153 on rmnet_data0
# 11. Test connectivity
ping -c3 8.8.8.8
# -> 100% packet loss (SIM activation still processing)
cat /tmp/resolv_rmnet_data.conf
# -> nameserver 10.177.0.34
# -> nameserver 10.177.0.210
# -> nameserver fd00:976a::9
# -> nameserver fd00:976a::10Result: Device registered on T-Mobile LTE with valid CGNAT IP and IPv6, QCMAP bridging active, default route configured. Ping fails because SIM activation is still processing. Once activation completes, data should flow without any further configuration changes.
Key observation: When switching to T-Mobile, the modem auto-configured CID 1 with fast.t-mobile.com — no manual APN setup was needed at the AT level. The QCMAP config update was still required since it had the previous carrier's APN.
The full QCMAP config file at /usrdata/data/qcmap/mobileap_cfg.xml:
<?xml version="1.0"?>
<system xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="mobileap_cfg.xsd">
<MobileAPCfg>
<MobileAPNatCfg>
<Firewall>/data/mobileap_firewall.xml</Firewall>
<NatEntryGenericTimeout>200</NatEntryGenericTimeout>
<NatEntryICMPTimeout>30</NatEntryICMPTimeout>
<NatEntryTCPEstablishedTimeout>3600</NatEntryTCPEstablishedTimeout>
<NatEntryUDPTimeout>60</NatEntryUDPTimeout>
<DmzIP>0.0.0.0</DmzIP>
<EnableIPSECVpnPassthrough>1</EnableIPSECVpnPassthrough>
<EnablePPTPVpnPassthrough>1</EnablePPTPVpnPassthrough>
<EnableL2TPVpnPassthrough>1</EnableL2TPVpnPassthrough>
<EnableWebserverWWANAccess>0</EnableWebserverWWANAccess>
<NATType>SYM</NATType>
<!-- ... ALG, limits ... -->
</MobileAPNatCfg>
<MobileAPLanCfg>
<EnableIPV4>1</EnableIPV4>
<EnableIPV6>1</EnableIPV6>
<WlanMode>AP</WlanMode>
<APIPAddr>192.168.1.1</APIPAddr>
<SubNetMask>255.255.255.0</SubNetMask>
<EnableDHCPServer>1</EnableDHCPServer>
<DHCPCfg>
<StartIP>192.168.1.100</StartIP>
<EndIP>192.168.1.200</EndIP>
<LeaseTime>86400</LeaseTime>
</DHCPCfg>
<!-- ... hostapd, guest AP, STA mode ... -->
</MobileAPLanCfg>
<MobileAPWanCfg>
<!-- === THESE ARE THE FIELDS YOU CHANGE === -->
<AutoConnect>1</AutoConnect> <!-- Must be 1 for auto data -->
<Roaming>1</Roaming>
<TECH>0</TECH>
<V4_UMTS_PROFILE_INDEX>1</V4_UMTS_PROFILE_INDEX>
<V4_CDMA_PROFILE_INDEX>0</V4_CDMA_PROFILE_INDEX>
<V6_UMTS_PROFILE_INDEX>1</V6_UMTS_PROFILE_INDEX>
<V6_CDMA_PROFILE_INDEX>0</V6_CDMA_PROFILE_INDEX>
<APN>fast.t-mobile.com</APN> <!-- Must match AT+CGDCONT CID 1 -->
<UserName></UserName>
<PassWord />
<AUTH>0</AUTH>
<PrefixDelegation>0</PrefixDelegation>
<!-- ... backhaul priority, SIP, ERI ... -->
</MobileAPWanCfg>
<!-- ... services (UPnP, DLNA, DDNS), boot config ... -->
</MobileAPCfg>
</system>The critical fields for carrier switching are in <MobileAPWanCfg>:
<AutoConnect>1</AutoConnect>— must be 1 or QCMAP won't auto-establish the data call<APN>...</APN>— must match the AT-level CID 1 APN exactly<V4_UMTS_PROFILE_INDEX>1</V4_UMTS_PROFILE_INDEX>— maps to CID 1<AUTH>0</AUTH>— no authentication (correct for T-Mobile, AT&T, Verizon consumer)
This helped me get the orbic working in Canada on the Fizz network. Absolute top notch write up. If I can help contribute somehow let me know.