OTASP
*228 is over-the-air provisioning. Dial it on the handset and the network reads the phone’s current settings (identity, dialed number, system banner, MMS URL, roaming list), optionally overwrites each one with values from the HLR, and ends with a commit that makes the writes survive a power cycle.
OTASP currently runs in soft mode by default — read-only, the network never overwrites anything. That means handsets will report “Activation Unsuccessful” at the end of a *228 session even though everything actually worked; the phone expected a Commit with downloaded blocks and got a Commit with no writes. The session detail page shows the full read-back so you can see what’s on each device. Writes can be enabled per block for advanced users (see Per-block writes below).
What you see without enabling any writes
With the shipped msc.json defaults, *228 runs end-to-end without changing anything on the handset:
- The MSC asks the phone for each block and decodes the response.
- Each block lands on the session timeline in the web UI as a “NAM Read-Back — …” entry showing the decoded fields (phone number, system banner, roaming list, etc.).
- The handset’s capabilities are decoded into plain labels (dual-mode, slotted, 25 MHz bandwidth, …).
- The Preferred Roaming List read-back shows counts and a download link for the raw file — handy for grabbing a known-good carrier PRL.
A read-only *228 is operationally safe. Use it to verify what each phone has from its prior carrier before deciding what to overwrite.
Per-block writes
In config/msc.json:
{
"otasp": {
"enabled": true,
"feature_codes": ["*228"],
"writes": {
"cdma_analog_nam": false,
"mdn": false,
"cdma_nam": false,
"home_system_tag": false,
"mms_uri": false,
"prl": false
}
}
}
Each flag corresponds to one block on the handset:
| Flag | What it writes | When to enable |
|---|---|---|
cdma_analog_nam | Network identity: phone IMSI, access class, home system ID, paging channel, roaming permissions | After IMSI and phone number assignments are correct in the HLR |
mdn | Mobile Directory Number — the handset’s stored phone number | Same time as cdma_analog_nam |
cdma_nam | Same identity / roaming fields as the analog block, for modern CDMA-only handsets | Always pair with cdma_analog_nam |
home_system_tag | The system banner shown on the phone status bar | Anytime |
mms_uri | The MMSC URL the handset uses for picture messages | Requires otasp.mms.uri to be set |
prl | The Preferred Roaming List that tells the phone which networks to camp on | After at least one PRL has been uploaded and a default is marked (see PRL management) |
Reads still happen for every block regardless of the flag. If the handset rejects any write, the session stops before commit and nothing persists on the device — half-written state is impossible by design.
Where each identity field comes from
When a block is enabled for writing, the values come from:
| Field | Source |
|---|---|
| IMSI components | The subscriber’s HLR IMSI record (split into prefix + identifier) |
| Access class | Derived from the subscriber’s phone number |
| Home system ID, network ID, paging channel | The cell’s overhead settings in bts.json |
| Roaming pair | One entry, the cell’s home system ID and network ID |
| MT call acceptance | otasp.nam_defaults in msc.json |
| Operator banner | otasp.system_tag.name |
| MMS URL | otasp.mms.uri |
| PRL | The subscriber’s override if set, otherwise the system default PRL |
That means a *228 write makes the handset’s identity match what the HLR says it is, on the cell that’s currently providing service. If the HLR IMSI prefix doesn’t match what the cell broadcasts, the phone won’t register correctly after the write — use the Generate button (below) to keep them aligned.
IMSI Generate
On the subscriber edit page, the IMSI input has a Generate button. It builds an IMSI from the cell’s broadcast settings and the subscriber’s phone number — short numbers are zero-padded, longer numbers (e.g. with a country code) use their last 10 digits. You can always edit the result manually if your numbering plan needs something different.
Per-subscriber PRL override
The runtime picks the system-default PRL — whichever one is marked default in the PRL list — for every subscriber. On the subscriber edit page, the PRL override section lets you pin a specific PRL for one subscriber, useful for test devices or carrier-specific provisioning. Clearing the dropdown restores the default fallback.
When PRL writes are enabled, the runtime checks the override first, then the system default, then skips the PRL write entirely if neither exists.
Per-subscriber Service Programming Code
The MSC has to present the handset’s lock code before any write. The shipped default is 000000, which every never-locked handset accepts.
For devices a prior carrier locked with a custom code, the Service Programming Code section on the subscriber edit page accepts the 6 digits and the MSC will use them on the next *228. Blank means “use the default 000000”.
This is only the lock code we present to the phone — *228 never changes the lock code stored on a device.
PRL management
The PRLs section of the web UI is a full editor for classic and Extended PRLs. Either upload a .prl file (the format used by every commercial CDMA PRL editor) or build one from scratch with header, acquisition records, system records, and the Common Subnet Table. Every save round-trips through the encoder so the bytes you commit decode back to the structure you edited.
Mark one PRL as the system default with the Set default button on its detail page. The PRL override dropdown on the subscriber edit page pins a specific PRL for one subscriber.
Session history viewer
Every *228 session is persisted. The Recent OTASP Sessions section on the mobile and subscriber pages paginates through history. Each row shows the ESN/MEID, phone number, feature code dialed, outcome (Committed, Rejected, TimedOut, …), and how many blocks succeeded.
Click a session to see every step: capability decode, Station Class Mark, NAM Read-Back entries with all decoded fields, Block Downloaded entries showing exactly what was written, PRL push progress, and the final Commit Result.
Recommended workflow
- Leave all
writes.*flags off. Dial*228on a few handsets and read the session detail page. Verify the cell’s identity settings, what each phone has from a prior carrier, and the PRL summary. - Use the Generate button when creating or editing subscribers so the HLR record matches what the cell broadcasts.
- Upload a PRL (or build one in the editor) and mark it the system default. Confirm a couple of read-backs decode cleanly before flipping writes on.
- Turn on
cdma_analog_nam,mdn,cdma_namfirst — those are the writes that make the network usable. Re-dial*228on one device and confirm the post-write read-back matches. - Turn on
home_system_tagafter setting the system banner inotasp.system_tag.name. - Turn on
mms_uriafterotasp.mms.uripoints at the MMSC. - Turn on
prllast — it’s the longest write and slightly more involved.