Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ULCP: Wi-Fi

Wi-Fi control is the subsystem the host uses to configure and observe a device’s 802.11 hardware. It covers three functions, each its own capability, because the hardware that has one does not always have the others:

  • Scanning, listening for access points and reporting what was heard. Every Wi-Fi receiver can do this, including ones that can do nothing else.
  • The station, joining a network the device is given and staying on it.
  • The access point, offering a network of the device’s own for other stations to join.

This chapter specifies the interface, not what the connection carries. Addressing is IP Connectivity; a bridge tunnel, a time source, or a binding a client could attach through is a capability of its own.

Everything here is device-domain state. The configuration properties, the two switches, the network table, the selection, and the access point’s network, are part of a saved snapshot and survive a change of host. The rest is live: what a scan found, what the link is doing, who is on the access point. Live state is never saved, and CMD_RST reaches it only through the configuration it reverts, so each live property’s post-reset value is declared as whatever the fact is at the time.

A device with a station and a network selected tries to be on that network whenever it is enabled, with no host present and none ever required. That is why nothing here is a command: a device on Wi-Fi is infrastructure, and infrastructure that needs a phone to get back on the network after a power cut is not.

Capabilities

CodeNameRequiresGrants
53CAP_WIFI_SCANA Wi-Fi receiver the device can scan with: PROP_WIFI_SCANNING, PROP_WIFI_SCAN_RESULTS
54CAP_WIFICAP_WIFI_SCANA Wi-Fi station the device can enable and join networks with: PROP_WIFI_ENABLED, PROP_WIFI_NETWORKS, PROP_WIFI_NETWORK, PROP_WIFI_LINK
57CAP_WIFI_APCAP_WIFI_SCANAn access point the device can bring up: PROP_WIFI_AP_ENABLED, PROP_WIFI_AP_CONFIG, PROP_WIFI_AP_STATE, PROP_WIFI_AP_CLIENTS

Three capabilities on one base, and everything else discovered by asking. The scan is the base because it is what every Wi-Fi radio can do: a station that can join can always scan, and so can a radio that can beacon, so both requiring CAP_WIFI_SCAN is a fact about hardware rather than a policy, and the rule that a device advertises what its capabilities require does the rest.

The station and the access point do not require each other. Nearly every chip does both, but they are different functions with different state, and a device that has one and not the other is describable. A device advertising any of the three MUST serve every property it grants.

The two remaining station properties, PROP_WIFI_RSSI and PROP_WIFI_MAC, report things a stack may not expose, and a device that only scans has neither. A device that cannot answer them answers STATUS_PROP_NOT_FOUND, in the same exchange the host was already making, for the reason the BLE binding gives: a refusal is a complete answer, and a second capability buys a host nothing it cannot learn in the reply it is already waiting for.

None of the three requires CAP_SAVE. Without it the configuration is volatile and the device knows no networks after a power cycle, which is a worse device but a conforming one.

Properties

Allocated from the extended device and transport configuration range: the station and its scan in a block of sixteen after the BLE transport’s, the access point in a block after IP Connectivity, so that neither the station nor the stack has to move to make room.

IdMnemonicCommandsDescription
4880PROP_WIFI_ENABLEDGet, Set, IsWhether the station is up
4881PROP_WIFI_NETWORKSGet, Set, Insert, RemoveKnown networks and their credentials
4882PROP_WIFI_NETWORKGet, Set, IsThe selected network, or empty
4883PROP_WIFI_SCANNINGGet, Set, IsWhether a scan is in progress
4884PROP_WIFI_SCAN_RESULTSGet, Is, InsertedWhat the current or last scan has found
4885PROP_WIFI_LINKGet, IsLink state, failure reason, and association
4886PROP_WIFI_RSSIGetSignal of the current association
4887PROP_WIFI_MACGetThe station’s MAC address
4912PROP_WIFI_AP_ENABLEDGet, Set, IsWhether the access point is up
4913PROP_WIFI_AP_CONFIGGet, SetThe network the device offers
4914PROP_WIFI_AP_STATEGet, IsWhether it is beaconing, and where
4915PROP_WIFI_AP_CLIENTSGet, Is, Inserted, RemovedWho is on it

4888 through 4895 are reserved for the station, and 4916 through 4927 for the access point.

PROP 4880: PROP_WIFI_ENABLED

  • Type: Single-Value, Read-Write
  • Asynchronous Updates: Yes
  • Required: CAP_WIFI
  • Value Type: BOOL
  • Post-Reset Value: 0 (false), or restored from saved state

Whether the station is up. Cleared, the device MUST drop any association, abandon any scan in progress, and put the station into the lowest power state the platform offers. This is PROP_GNSS_ENABLED’s promise rather than PROP_BLE_ENABLED’s: on a battery-powered node a Wi-Fi radio that is merely idle is still the largest load on the board, and a property that only stopped reporting would solve nothing.

Set again, the device comes back up and, if a network is selected, starts joining it. The known-network table and the selection are configuration and are not disturbed in either direction, so turning the station off and on is not a way to forget anything.

Off by default, for the reason PROP_GNSS_ENABLED is: a device that has never been given a network has nothing to spend the power on. Saved state overrides the default, which is how a commissioned device comes up connected.

Asynchronous because a device with a screen MAY offer the switch on it, and a switch someone can flip is a value that moves without the host asking.

A write of 1 answers STATUS_INVALID_STATE on a platform that cannot run the station alongside another radio it currently has on, the device’s own access point included. The device MUST NOT take the other radio down to honor the write; the host turns that one off first. A platform that coexists, which is most of them, answers the write like any other.

PROP 4881: PROP_WIFI_NETWORKS

  • Type: Multiple-Value, Read-Write
  • Has Item Length Prefix: Yes
  • Asynchronous Updates: No
  • Required: CAP_WIFI
  • Item Form: structure below
  • Reported Form: the item with its credential omitted
  • Remove Selector: the SSID
  • Post-Reset Value: Empty, or restored from saved state

The networks the device knows. Each item:

+-------+----------+----------+----------+------------------+
| FLAGS | SECURITY | SSID_LEN |   SSID   |  CREDENTIAL ...  |
+-------+----------+----------+----------+------------------+
   1 B      1 B        1 B      1-32 B    security-defined

Figure: Known-network item format

FLAGS bit 0 set means the network hides its SSID and the device probes for it by name rather than waiting to hear it. Bit 1 set means the credential is a raw 32-octet pairwise master key rather than a passphrase, which is valid only for the modes that derive one; a host that holds the key need never hand the device the passphrase, and a device never has to run the derivation. Bits 2 through 7 are reserved and MUST be zero.

SECURITY is one mode:

ValueNameCredential
0WIFI_SEC_OPENnone
1WIFI_SEC_OWEnone
2WIFI_SEC_WPA2passphrase of 8-63 octets, or a key
3WIFI_SEC_WPA3password of 1-128 octets
4WIFI_SEC_WPApassphrase of 8-63 octets, or a key
5WIFI_SEC_WEPnone defined
6WIFI_SEC_WPA2_ENTnone defined
7WIFI_SEC_WPA3_ENTnone defined
8WIFI_SEC_WPA3_ENT_192none defined

Values 9 through 15 are reserved. Sixteen is the ceiling because PROP_WIFI_SCAN_RESULTS reports these as a 16-bit set.

WIFI_SEC_OPEN is no security at all. WIFI_SEC_OWE is Enhanced Open: encrypted against anyone listening, authenticated against nobody, with no credential, and the only credential-free mode permitted on 6 GHz. An OWE entry names the network as the operator sees it. Where that is a plain OWE network the device joins it; where it is the visible half of an OWE transition deployment, the device follows the transition element to the hidden companion BSS and joins that. PROP_WIFI_LINK then reports the companion’s BSSID and frequency, which is all it ever reports of any association, while PROP_WIFI_NETWORK goes on naming the visible network the operator selected. The entry never names the companion, because the operator never saw it.

WIFI_SEC_WPA2 is WPA2-Personal and covers the WPA/WPA2 mixed networks that negotiate CCMP; WIFI_SEC_WPA is the TKIP-only remainder, which a device MAY decline to join. WIFI_SEC_WPA3 is WPA3-Personal, SAE, whose password is not a WPA2 passphrase: SAE puts no bounds on it, so the 8 to 63 rule does not apply, and the table admits up to 128 octets, which is where the more generous stacks stop. A device whose stack holds a shorter limit refuses a longer password with STATUS_UNIMPLEMENTED, since the entry is well-formed and the device is what cannot hold it. A password shared with a transition network’s WPA2 side is 8 to 63 octets by that side’s rule, which is the host’s to know.

The remaining four exist so that scan results can say what they heard. WEP is not worth a credential form, and the three enterprise modes are a provisioning surface this chapter does not open; they are numbered so that opening it later renumbers nothing.

A passphrase or password is the UTF-8 encoding of what the operator typed, with no terminator and no U+0000, and its length bounds count octets. The device MUST derive keys from exactly those octets: the PBKDF2 of 802.11 Annex J for WIFI_SEC_WPA2 and WIFI_SEC_WPA, and SAE over the octets directly. An ASCII passphrase therefore yields what every router yields, and a non-ASCII one yields what a router that accepted UTF-8 yielded. In both cases the host’s job is to hand over the same octets the router’s operator entered, and the device’s is not to reinterpret them. A raw key, FLAGS bit 1, is exactly 32 octets and skips the derivation.

An insert is refused with STATUS_INVALID_ARGUMENT when it is not well-formed: an empty SSID, a mode with no credential form, a credential of the wrong length or kind for its mode, a reserved mode, a reserved flag bit set. The SSID is never empty because an empty PROP_WIFI_NETWORK means no selection, so an entry with no name could be stored and never chosen; a hidden network has a real name, and it is only the advertisement that is blank. An insert is refused with STATUS_UNIMPLEMENTED when it is well-formed and this device cannot do it: a WPA3 entry on a chip without SAE, or a WPA entry on a device that declines TKIP. The two are different answers because a host acts on them differently. The first is a bug in the host, and the second is a reason to pick the next mode the network offers.

The security mode is exact. It is the mode the device uses, not a ceiling it negotiates down from. An entry marked WIFI_SEC_WPA3 joins a WPA2/WPA3 transition network with SAE and fails against a WPA2-only one; an entry marked WIFI_SEC_WPA2 joins either with PSK; an entry marked WIFI_SEC_OWE never falls back to open. A device MUST NOT negotiate a mode other than the one the entry names, so a host that takes the mode out of a scan result gets exactly the network it saw, and an evil twin advertising a weaker one gets nothing. Where the passphrase is the same across a transition network’s modes, which it usually is, the host writes the strongest one the device accepts.

Items are keyed by SSID: the table holds at most one entry per network, and an insert whose SSID matches an existing entry replaces it and reports the item as inserted. That is the path for a wrong passphrase, a changed one, or a mode upgrade, and it never needs a remove. The SSID is octets, not text, and a device compares it bytewise. A whole-table CMD_PROP_SET carrying two entries with the same SSID is refused with STATUS_INVALID_ARGUMENT before anything changes, under Mutation Atomicity: the value is an unordered set, so neither entry has standing to win, and a host that wrote both did not mean either.

The credential is write-only, under the rules of Provisioning Security. The reported form is the item through its SSID, and neither CMD_PROP_GET nor any notification ever carries a passphrase. This is why replacing an entry is the only way to change its credential: a host cannot read one back to compare it. Writes that carry a credential are subject to the same transport requirement as key material.

A device bounds the table and refuses an insert past its capacity with STATUS_NOMEM. Four entries is enough for anything a device of this class does, and a device SHOULD hold at least that many. The bound MUST also keep the complete reported table, every entry in its redacted form, inside one frame on every transport the device exposes, so that a CMD_PROP_GET always answers in one piece. At under forty octets per reported entry that constrains nothing a device would want.

Removing the selected network, whether by CMD_PROP_REMOVE or a whole-table CMD_PROP_SET that omits it, clears the selection: the device drops the association, publishes PROP_WIFI_NETWORK as empty, and publishes the link going down. Replacing the selected network’s entry drops any association it holds and starts a fresh join with the new entry at once, because a host that has just corrected a passphrase should not wait out a backoff to learn whether it worked.

The table is part of the saved snapshot, credentials included, which is what lets the device rejoin unattended. CMD_CLEAR erases the persisted copy with everything else and, as with everything else, leaves the live table alone: the device stays on its network until the CMD_RST that completes a factory reset reverts the table to its now-empty post-reset value. A device advertising CAP_SAVE stores it as it stores key material.

PROP 4882: PROP_WIFI_NETWORK

  • Type: Single-Value, Read-Write
  • Asynchronous Updates: Yes
  • Required: CAP_WIFI
  • Value Type: 1 to 32 octets (an SSID), or empty
  • Post-Reset Value: Empty, or restored from saved state

The network the device is on, or is to be on: the SSID of one entry in PROP_WIFI_NETWORKS. This is “connect” and “disconnect” both.

Writing an SSID selects that network. If the station is enabled, the device drops any current association and starts joining the new one; if it is not, the selection waits for it, so a whole configuration can be staged and the station enabled last. Writing the SSID that is already selected changes nothing and disturbs nothing, like any other property written with its own value.

An SSID not in the table is refused with STATUS_ITEM_NOT_FOUND: the credential lives in the table, and the selection only names it. A host acts on that differently from STATUS_INVALID_ARGUMENT, one being “insert it first” and the other a bug.

Writing the empty value deselects. The device leaves the network and associates with nothing until something is selected again. This is a stable state, not a moment: the station stays up, scans on request, and joins nothing, which is what a phone with Wi-Fi on and no network in range is doing. A device MUST NOT select a network on its own, because a disconnect the device undoes by itself is not one.

The device MUST publish the property when it changes it: a removal from the table that empties the selection, or a picker on the device’s own screen.

The selection is the network the device will spend its unattended life trying to reach, so it is saved with the table. A device restored from a snapshot comes up joining what it was joining.

PROP 4883: PROP_WIFI_SCANNING

  • Type: Single-Value, Read-Write
  • Asynchronous Updates: Yes
  • Required: CAP_WIFI_SCAN
  • Value Type: BOOL
  • Post-Reset Value: whether a scan is running

Whether a scan is in progress. Writing 1 starts one; the device answers with 1, reports each access point as it is heard through PROP_WIFI_SCAN_RESULTS, and publishes 0 when the scan completes. Writing 0 abandons a scan in progress and leaves in the results whatever had been found by then.

The frames of a scan MUST go out in this order, so that a host can never misattribute one:

  1. CMD_PROP_IS for PROP_WIFI_SCAN_RESULTS carrying the empty value: the previous results are gone.
  2. CMD_PROP_IS for this property carrying 1, as the reply to the host’s write or unsolicited when the device started the scan itself.
  3. One CMD_PROP_INSERTED per access point heard, in the order heard.
  4. CMD_PROP_IS for this property carrying 0, after the last of them.

The clear goes first so that every insert lands in a table the host knows to be empty, and the completion goes last so that a host seeing 0 holds the whole list without reading it.

This is a pairing window’s shape exactly: a state the host can enter, that ends by itself, and that a device with a screen can enter without the host. A device MUST bound a scan’s duration; a few seconds is what the hardware takes.

On a device with a station, a write of 1 answers STATUS_INVALID_STATE while the station is disabled, and MAY answer STATUS_BUSY while a join is in the middle of its handshake, which resolves by itself. On a device without one there is nothing to enable: the receiver is powered for the scan’s duration and put back to sleep after, which is the right power shape for a tracker that scans a few times an hour. Writing 1 during a scan succeeds and answers 1; there is nothing to restart. A write of 0 always succeeds.

A device MAY scan while associated, at the cost of the association’s traffic while it is off-channel. Whether the scan is active or passive, and on which channels, is the device’s business, except that a device with a station MUST probe by name for a hidden network in its table so that it can appear.

A scan the device starts from its own menu is reported the same way, inserts and all. An attached host pays twenty-odd small frames once per scan, which is nothing against the scan itself, and a picker that appears as networks are heard is the difference between a list that fills in and a spinner.

PROP 4884: PROP_WIFI_SCAN_RESULTS

  • Type: Multiple-Value, Read-Only
  • Has Item Length Prefix: Yes
  • Asynchronous Updates: Yes (Is, Inserted)
  • Required: CAP_WIFI_SCAN
  • Post-Reset Value: what the receiver has found; empty after a power-on

What the scan in progress has found so far, or what the last one found. Each item:

+-------+-----------+------+--------+-----------+
| MODES | FREQUENCY | RSSI | BSSID  |  SSID ... |
+-------+-----------+------+--------+-----------+
  2 B     2 B, MHz    1 B     6 B      0-32 B

Figure: Scan result item format

MODES is a 16-bit little-endian set of the security modes the access point offers, bit n standing for mode n of the enumeration above. No bits at all means the device did not determine them: a receiver that reads beacon headers for their addresses has no reason to parse the security elements, and no real access point offers nothing, so the empty set is free to mean that.

A WPA2/WPA3 transition network sets both bits. An OWE transition network is two BSSs, a visible open one and a hidden OWE companion that the open one’s transition element names by BSSID and SSID; the device reads the element and reports the visible BSS with both the open and the OWE bit set, so the host sees one network offering two modes and picks between them like any other. The companion is reported as itself, under the SSID the element gave it, and nothing depends on it. A set rather than a single strongest value, because which of the offered modes the host should write depends on what the device can do, and the scan result is not the place to guess: the host writes the strongest bit it likes and steps down on STATUS_UNIMPLEMENTED.

FREQUENCY is the center frequency of the access point’s primary 20 MHz channel, in megahertz, little-endian. A frequency rather than a channel number because a channel number is ambiguous across bands and a frequency is not, and the number follows from the frequency in one line wherever a display wants it. The width of the operating channel is not reported: the device negotiates it at association, and nothing about it is needed to join.

RSSI is a signed dBm. SSID is the remainder of the item, and empty means no name was reported, because the network hides it or because the scanner does not read names; the BSSID is what distinguishes one nameless entry from the next. A device with a station always reads names, so on such a device empty means hidden. A picker treats the two alike in any case, since neither can be chosen by name.

One item per access point, keyed by BSSID, and never the device’s own: a device that is also an access point MUST NOT report itself. The device reports what it heard and nothing it inferred. Which of several access points make up one network is a question the host answers by grouping on SSID, and a host that wants the list a phone shows coalesces, keeps the strongest per name, and sorts. A host that wants to see every radio in the building has that too. Hidden networks need no special case, since an access point with no name still has an address.

The device reports each access point with CMD_PROP_INSERTED as it is heard, and hearing one again is another CMD_PROP_INSERTED under the same BSSID, which replaces the host’s entry. Replacement by key is what makes the inserts idempotent, and idempotence is what makes it safe for a host to read the table mid-scan and follow the inserts from there: an item that arrives in both the reply and a notification is the same item twice.

The device retains a bounded table and reports an unbounded scan. Every access point heard is inserted; the device keeps the strongest of them up to its bound, evicting the weakest as stronger ones arrive, and never reports an eviction. The bound MUST be chosen so that the whole retained value fits in one frame on every transport the device exposes; on BLE that is the 512-octet reassembled frame, into which twenty or so typical items fit. The inserts are one item each and never approach it.

This is the one place the property model bends on purpose. A host that followed the inserts holds a superset of what a CMD_PROP_GET returns: everything the scan heard, against the strongest twenty the device kept. It is harmless because nothing in the host’s copy is invented, every item in it was heard, and the two are reconciled by the clear at the next scan. The alternative, a CMD_PROP_REMOVED per eviction, would spend frames telling the host to stop showing an access point it can see, in order to keep two views identical that nobody needs to compare. Where removals do describe something a host wants, as they do for access point clients, they are sent.

CMD_PROP_GET returns the retained table strongest first. Inserts arrive in the order the access points were heard, which is the order the host receives them in and has no other meaning.

Delivering results as they are found is a promise about delivery, not about pace. Most stacks hand back a scan only when it finishes; a device gets progressive results by scanning a channel at a time, which the usual scan interfaces allow and which costs a little total duration for first results in a fraction of a second. A device that cannot do that emits every insert at the end and conforms.

The value is cleared, and the empty value published with CMD_PROP_IS, when a scan starts and when the station is disabled. A list of what was in the air somewhere the device may no longer be is worse than an empty one.

  • Type: Single-Value, Read-Only
  • Asynchronous Updates: Yes
  • Required: CAP_WIFI
  • Value Type: structure below
  • Post-Reset Value: what the station is doing
+-------+--------+--------+-----------+
| STATE | REASON | BSSID  | FREQUENCY |
+-------+--------+--------+-----------+
  1 B     1 B      6 B      2 B, MHz
                 (present only when STATE is WIFI_LINK_UP)

Figure: Link state format

STATE:

ValueNameMeaning
0WIFI_LINK_DOWNNot trying: the station is off, or nothing is selected
1WIFI_LINK_CONNECTINGA network is selected and the device is not on it yet, or not any more
2WIFI_LINK_UPAssociated

REASON says why the device is in WIFI_LINK_CONNECTING rather than WIFI_LINK_UP, and is 0 in the other two states:

ValueNameMeaning
0WIFI_REASON_NONENo attempt has failed yet
1WIFI_REASON_NOT_FOUNDThe network was not heard and did not answer a probe
2WIFI_REASON_AUTHThe network rejected the credential
3WIFI_REASON_REJECTEDThe network refused the association for another reason
4WIFI_REASON_LOSTThe association was up and dropped
5WIFI_REASON_OTHERSomething the device has no name for

WIFI_LINK_UP is an 802.11 statement: the station is authenticated and associated. Whether the device has an address on the link it is now on is a different layer’s fact and belongs to the family state properties, which report it.

WIFI_LINK_CONNECTING is the whole of trying, including the waits between attempts. While the station is enabled and a network is selected, the device MUST retry indefinitely with backoff and MUST NOT give up: a wrong passphrase is a device that retries a few times an hour until someone fixes it, which costs nothing and is what unattended infrastructure should do. WIFI_LINK_DOWN is reserved for the two states in which the device is not trying at all, so that a host reading DOWN knows the fix is configuration and a host reading CONNECTING knows the fix is in the reason.

The device MUST publish the property on every change of state and on every change of reason, and on nothing else. Retrying and failing the same way again is not a transition and is not published, so a device with a wrong passphrase reports WIFI_REASON_AUTH once, not every attempt.

When WIFI_LINK_UP, the value carries the association: which access point, and the center frequency of its primary channel in megahertz, as in a scan result. A roam to another access point of the same network is a change of value and is published.

Live state: NOT part of the saved snapshot, and CMD_RST reaches it only as a consequence of reverting the configuration it follows.

PROP 4886: PROP_WIFI_RSSI

  • Type: Single-Value, Read-Only
  • Asynchronous Updates: No
  • Required: CAP_WIFI
  • Value Type: INT8 in dBm, or empty
  • Post-Reset Value: the current measurement; empty when the link is not up

The received signal strength of the current association, measured when the property is read. Empty when the link is not up.

Kept out of PROP_WIFI_LINK for the reason PROP_GNSS_LOCATION is kept quiet: a measurement that changes on every beacon has no business in a property that is published on every change. PROP_PHY_RSSI is the same split on the LoRa side.

PROP 4887: PROP_WIFI_MAC

  • Type: Single-Value, Constant
  • Asynchronous Updates: No
  • Required: CAP_WIFI
  • Value Type: 6 octets

The station’s MAC address, as it appears to the access point. Constant because a router’s allow list is keyed on it, and a device that randomized it would be reporting an address nobody can use.

PROP 4912: PROP_WIFI_AP_ENABLED

  • Type: Single-Value, Read-Write
  • Asynchronous Updates: Yes
  • Required: CAP_WIFI_AP
  • Value Type: BOOL
  • Post-Reset Value: 0 (false), or restored from saved state

Whether the access point is up. Set, the device beacons the configured network, accepts stations onto it, and serves them addresses; cleared, it MUST disassociate every client, stop beaconing, and release whatever the access point held of the radio. The configuration is untouched in both directions.

Off by default, and a write of 1 while PROP_WIFI_AP_CONFIG is empty answers STATUS_INVALID_STATE. Together those two rules mean there is no factory network: no default name a stranger can look up, no default passphrase, and no open network a device falls back to because nobody configured one. A device that has never been given a network to offer offers nothing.

A write of 1 answers STATUS_INVALID_STATE on a platform that cannot run the access point alongside a radio it currently has on, the station included, and the device MUST NOT take the other down to honor the write. A platform that runs both, which is most of them, answers the write like any other.

Asynchronous for the reason every switch here is: a device with a screen MAY offer it, and the device takes the access point down by itself when its configuration is cleared.

PROP 4913: PROP_WIFI_AP_CONFIG

  • Type: Single-Value, Read-Write
  • Asynchronous Updates: No
  • Required: CAP_WIFI_AP
  • Value Type: structure below, or empty
  • Reported Form: the structure with its credential omitted
  • Post-Reset Value: Empty, or restored from saved state
+-------+----------+-------------+-----------+---------+--------+----------+--------+----------------+
| FLAGS | SECURITY | MAX_CLIENTS | FREQUENCY | ADDRESS | PREFIX | SSID_LEN |  SSID  | CREDENTIAL ... |
+-------+----------+-------------+-----------+---------+--------+----------+--------+----------------+
   1 B      1 B         1 B        2 B, MHz     4 B       1 B       1 B      1-32 B  security-defined

Figure: Access point configuration format

FLAGS, SECURITY, SSID_LEN, SSID, and CREDENTIAL are as in a PROP_WIFI_NETWORKS item, with the same encodings, the same well-formedness rules, and STATUS_INVALID_ARGUMENT for the same faults. The modes an access point may offer are WIFI_SEC_OPEN, WIFI_SEC_OWE, WIFI_SEC_WPA2, and WIFI_SEC_WPA3; any other is refused with STATUS_INVALID_ARGUMENT, because no credential form for offering it is defined here, and a device without SAE refuses WIFI_SEC_WPA3 with STATUS_UNIMPLEMENTED as it does in the table. A hidden network beacons without its name and answers probes for it; the flag is a courtesy to neighbors’ pickers and not a secret, since the name is in every association.

MAX_CLIENTS is how many stations the device admits at once, or 0 for the device’s own limit. A device bounds it to what its stack can hold and to what keeps PROP_WIFI_AP_CLIENTS in one frame, and clamps a larger write to that bound rather than refusing it, reporting the clamped value: the host asked for “many”, and the device’s most is the honest answer.

FREQUENCY is the center frequency of the primary channel the access point is to use, in megahertz, or 0 for the device’s choice. It is a preference, not a promise. A frequency the device may not use under its regulatory configuration is refused with STATUS_INVALID_ARGUMENT, and one it may use is what the access point beacons on while the station is not associated. On hardware where the access point and the station share one radio, and therefore one channel, the access point sits on the station’s channel while the station is up, whatever this field says, and moves when the station roams. PROP_WIFI_AP_STATE reports where the access point actually is.

ADDRESS and PREFIX are the device’s own IPv4 address on the network it offers and the prefix of that network, or all-zero and 0 for the device’s default, which SHOULD be 192.168.4.1/24 since that is what a phone joining an embedded device has come to expect. The device serves DHCP on this subnet, handing out addresses within the prefix other than its own, and answers as the gateway and resolver a lease names, whether or not it can forward anything. The prefix is 8 to 30. An address that is not a usable unicast address in the sense PROP_IPV4_STATE defines, or one that lies within the subnet the station holds, is refused with STATUS_INVALID_ARGUMENT. IPv6 on the offered network is link-local only, which needs no configuration and is not reported.

This is where the access point’s addressing lives, and not in the IP Connectivity properties, which describe the interface the device joins a network with and only that. Those properties configure how a device gets onto someone else’s network; the access point’s subnet is not a configuration the network hands the device but one the device imposes, it never changes without a write here, and a fixed address in the same structure as the network it belongs to is the shape every embedded access point already has.

The credential is write-only under Provisioning Security, and the reported form stops at the SSID. This is a passphrase the operator hands to other people, which makes a case for reading it back, and the case loses. The reader is a party that could write any passphrase it liked, so reading one back leaks nothing but the ability to rotate it without disturbing clients; a device with a screen MAY show it or a QR code for it; and one rule for every credential on the device is worth more than that convenience. It follows that every write of a secured configuration carries its credential, since there is nothing to leave in place.

A write takes effect at once. While the access point is up, the device disassociates every client, brings the network up again under the new configuration, and publishes the client list going empty; a client that knows the new credential rejoins on its own. Writing the empty value clears the configuration and is refused with STATUS_INVALID_STATE while the access point is enabled, so that no write here ever takes the network down as a side effect. The host disables it first.

Saved with the switch, credential included, so that a device commissioned to offer a network offers it at every boot.

PROP 4914: PROP_WIFI_AP_STATE

  • Type: Single-Value, Read-Only
  • Asynchronous Updates: Yes
  • Required: CAP_WIFI_AP
  • Value Type: structure below
  • Post-Reset Value: what the access point is doing
+-------+-----------+
| STATE | FREQUENCY |
+-------+-----------+
  1 B     2 B, MHz
        (present only when STATE is WIFI_AP_UP)

Figure: Access point state format

STATE:

ValueNameMeaning
0WIFI_AP_DOWNNot beaconing: disabled, unconfigured, or refused the radio
1WIFI_AP_UPBeaconing and accepting stations

FREQUENCY is the center frequency of the primary channel the access point is beaconing on, which is the configured one while the station is not associated and the station’s while it is. This is the field the property exists for: the configuration says what was asked, and only the state says where the network actually is, which a host that wants to tell a person which channel to expect has no other way to learn.

The device MUST publish it on every change of state and every change of frequency, so that a station roam which drags the access point to a new channel is reported, and on nothing else. Two states and no reason, because every way of being down is readable from the two configuration properties and the station’s link, and a reason octet would only quote them.

PROP 4915: PROP_WIFI_AP_CLIENTS

  • Type: Multiple-Value, Read-Only
  • Has Item Length Prefix: Yes
  • Asynchronous Updates: Yes (Is, Inserted, Removed)
  • Required: CAP_WIFI_AP
  • Remove Selector: the MAC
  • Post-Reset Value: the stations currently associated; empty when the access point is down

The stations on the device’s network. Each item:

+-------+------+---------+
|  MAC  | RSSI | ADDRESS |
+-------+------+---------+
   6 B    1 B     4 B

Figure: Access point client item format

MAC is the client’s, and the key. RSSI is a signed dBm as the device last heard the client. ADDRESS is the IPv4 address the device’s DHCP server leased it, or all-zero until it has one, which is what lets a host reach a client it can see.

The device publishes CMD_PROP_INSERTED when a station associates and again, under the same MAC, when its address is leased or changes, which replaces the host’s entry as a scan result does; CMD_PROP_REMOVED with the MAC when a station leaves or is dropped; and CMD_PROP_IS with the empty value when the access point goes down. RSSI is reported as it stood at the last of those and is not published on its own, under the rule that keeps a beacon-rate measurement out of every published property here.

This is the one multi-value property in this chapter that emits CMD_PROP_REMOVED, and the difference from PROP_WIFI_SCAN_RESULTS is not a matter of taste. The scan table withholds removals because they would describe an eviction from a bounded view of an unbounded list, telling the host to stop showing something real. A client leaving is a fact about the world that the host wants, the list is bounded by MAX_CLIENTS to something small, and the device’s view and the host’s are meant to be the same view, so the ordinary property model applies without amendment. The bound MUST keep the whole list in one frame, which at eleven octets an item constrains nothing.

Sharing the Radio

One radio, one channel. Where the access point and the station are two interfaces on one transceiver, the transceiver is on one channel. While the station is associated the access point is on the station’s channel; when the station roams, the access point moves with it and its clients drop and rejoin, which is a few seconds of disruption the device did not choose and cannot avoid, and which PROP_WIFI_AP_STATE reports as a frequency change. A host that needs the access point to stay put keeps the station off, or on a network with one access point.

A scan is a gap. Scanning takes the transceiver off channel. Every client of the access point loses its beacons for the duration, which most stations tolerate and some do not, and an association loses its traffic. On a device whose Wi-Fi receiver is its LoRa transceiver, a scan is also a gap in mesh reception lasting as long as the scan does, during which nothing on the air is heard and nothing is forwarded. The host asked for that, and it is not free: a repeater’s operator scanning on a schedule is spending the mesh’s reliability. A device MAY answer STATUS_BUSY to a scan request rather than abandon a transmission in progress or drop the clients it is serving.

Enable in either order. The two switches are independent, and a platform that cannot run both refuses the second 1 with STATUS_INVALID_STATE and leaves the first alone. Nothing about the station’s table, selection, or link changes when the access point comes up or goes down, and nothing about the access point’s configuration changes with the station’s.

Forwarding is not specified. Whether a client of the access point can reach the network the station is on, and how, is a policy about what the device does with its two interfaces. A device that forwards nothing is a conforming access point, and a useful one to a phone that only wants to reach the device.

Regulatory. The channel set follows the platform’s regulatory configuration, with one asymmetry: a station on the wrong channel is a receiver that hears nothing, and an access point on the wrong channel is a transmitter beaconing where it may not. A device advertising CAP_WIFI_AP therefore MUST refuse a FREQUENCY outside its regulatory configuration, and MUST choose within it when the field is 0.

Host Procedures

The flows a host runs, in terms of the properties above. None of them needs anything the property grammar does not already provide.

Turn on. Write PROP_WIFI_ENABLED to 1. If a network is selected, PROP_WIFI_LINK publishes CONNECTING and then UP or a reason.

Scan. Write PROP_WIFI_SCANNING to 1; clear the list on the CMD_PROP_IS that follows; add or replace an entry per CMD_PROP_INSERTED, grouping by SSID for display; stop the spinner on the unsolicited 0. A host on a binding that carries no notifications polls PROP_WIFI_SCANNING and reads PROP_WIFI_SCAN_RESULTS once it reads 0. A host presenting a picker marks each network already in PROP_WIFI_NETWORKS by matching SSIDs, since the reported table form carries them.

Join a new network. Insert an entry in PROP_WIFI_NETWORKS with the SSID from the scan result, the strongest mode in its offered set, and the passphrase from the operator; on STATUS_UNIMPLEMENTED, insert again with the next mode down. Then write the SSID to PROP_WIFI_NETWORK. Two writes rather than one because the credential has one home and the selection only names it. There is no safe one-frame shortcut: a whole-table CMD_PROP_SET replaces every entry, and since credentials cannot be read back, a host can only write a whole table it holds every credential for. That is the first host commissioning a fresh device, and nobody after it.

Fix a wrong passphrase. PROP_WIFI_LINK reads CONNECTING with WIFI_REASON_AUTH. Insert the entry again with the corrected credential; the device tries it immediately and the link reports the outcome.

Switch networks. Write the other SSID to PROP_WIFI_NETWORK.

Reconnect. There is no such flow. The device is already retrying, and a host that wants a fresh start with the same credentials has the honest two-step: deselect, then select, each of which is a real state.

Disconnect. Write PROP_WIFI_NETWORK empty. The device leaves and stays off the network with the station still up.

Forget. Remove the entry from PROP_WIFI_NETWORKS. If it was selected the selection empties and the link drops, both published.

Turn off. Write PROP_WIFI_ENABLED to 0. Nothing is forgotten.

Locate. On a device with CAP_WIFI_SCAN and no station, run the scan flow and hand the BSSIDs and signal levels to whatever resolves them into a position. The item format is what a geolocation resolver consumes, and a phone passes the list straight through. What the device does with its own scan, resolving on board or sending access points over the air, is application and is not here.

Offer a network. Write PROP_WIFI_AP_CONFIG with the SSID, mode, and credential, then PROP_WIFI_AP_ENABLED to 1. Watch PROP_WIFI_AP_STATE for the channel it landed on and PROP_WIFI_AP_CLIENTS for who arrives.

Commission for unattended use. Do any of the above, then CMD_SAVE. The station comes up and rejoins, and the access point comes up, at every boot after that.

Synchronize on attach. Read PROP_WIFI_ENABLED, PROP_WIFI_NETWORK, PROP_WIFI_LINK, and, where the device has one, PROP_WIFI_AP_ENABLED and PROP_WIFI_AP_STATE, in one CMD_PROP_MULTI_GET where available. The tables are read only when the host needs to show them.

What Survives What

PropertySavedCMD_RSTDetachStation off
PROP_WIFI_ENABLEDyesrevertskept
PROP_WIFI_NETWORKSyesrevertskeptkept
PROP_WIFI_NETWORKyesrevertskeptkept
PROP_WIFI_SCANNINGnofollowskeptabandoned
PROP_WIFI_SCAN_RESULTSnofollowskeptcleared
PROP_WIFI_LINKnofollowskeptDOWN
PROP_WIFI_RSSInofollowskeptempty
PROP_WIFI_MAC
PROP_WIFI_AP_ENABLEDyesrevertskept
PROP_WIFI_AP_CONFIGyesrevertskept
PROP_WIFI_AP_STATEnofollowskept
PROP_WIFI_AP_CLIENTSnofollowskept

“Reverts” means to the post-reset value, which on a device with a snapshot is the saved one. “Follows” means the live state ends up wherever the reverted configuration puts it, and nowhere else. A CMD_RST on a device whose live configuration already matches its snapshot leaves a running scan running, an association up, and an access point beaconing; one that reverts the selection or its credential drops the association and joins the restored entry; and one on a device with no snapshot takes the station and the access point down and everything live with them.

CMD_RESTORE is the same column: in either of its forms it reverts the configuration properties to the snapshot and the live state follows. Detach touches nothing, because the station and the access point are device-domain and run unattended, and a scan that was in progress when the host left completes and leaves its results for the next one.

Over the Node Management Binding

Every property here is device-domain, so a listed administrator over the mesh may read all of them and write the configuration ones, under the same rule that lets channel keys be provisioned remotely: the binding already delivers each request authenticated and encrypted, so an administrator may provision a credential.

Reading is the redacted form and nothing else, here as on the local link. The network table and the access point’s configuration read back without their credentials, and no binding exists over which a credential can be read.

That binding carries no unsolicited notifications, so a scan is the polled flow above, and an administrator that wants the client list reads it while PROP_WIFI_AP_STATE says there is one to read. Scan results are the one large read, and the binding’s cursors carry them.

An administrator who disables the station a bridge tunnel rides on has done the same thing as one who writes PROP_MAC_BACKHAUL, and warrants the same warning in the same place.

On BLE

The frame-size concerns are a CMD_PROP_GET of the scan results, of the network table, and of the client list, and all three are bounded above so that they fit. The inserts that deliver scanned access points live are one item each. The largest credential write, a 32-octet SSID with a 128-octet SAE password, is under two hundred octets with framing. Everything else is a few.

Security Considerations

  • A passphrase crosses the link once, inbound, over a transport that meets the provisioning requirement, and is never reported. A later host on the same device cannot extract an earlier host’s Wi-Fi credentials any more than its channel keys.
  • The security mode is exact. A device joins with the mode the entry names and no other, whatever the network in front of it advertises, so a downgrade has to be written by the host rather than offered by the air.
  • Scan results are what the device heard, and an SSID is what its sender chose to call itself. A host displays them as untrusted strings.
  • A scan result list is a location fingerprint of wherever the device is standing, precise to a building, which is exactly why a tracker wants one. It is readable only by an admitted party, like everything else here, and a device that resolves positions on board treats what it learned the way it treats a fix.
  • An access point is the one thing here that announces the device to everyone in range. Its SSID and its MAC are in every beacon, a hidden network is hidden from pickers and not from anyone listening, and the name it beacons MUST NOT carry the device’s mesh identity or any part of its address. There is no factory network: the access point offers nothing until a host configures it, and its passphrase is write-only like every other credential.
  • PROP_WIFI_MAC and the SSIDs in the table are identifying. They are no more so than PROP_DEV_NAME, and they are readable only by a party that has already been admitted.
  • A device on Wi-Fi is a device on a LAN, and a device with an access point is a device hosting one. This chapter gives it an address and nothing that listens on one. Any service the device later offers over the interface, a ULCP binding over TCP above all, carries the full authority of an attached host and needs an admission ceremony of its own before it exists; the serial transports’ physical-possession argument does not extend to a network port, and it extends least of all to a network the device invited the client onto. Whether knowing the access point’s passphrase is itself such a ceremony is a decision for the binding that would rely on it.

Not Specified

Deliberately absent, with the reason:

  • Anything on the access point’s network. Forwarding between the offered network and the station’s, a captive portal, a provisioning flow, or a binding a client could attach through: each is a thing the device does with the network rather than the network itself, and the last needs the admission ceremony above before it can exist.
  • Enterprise authentication. Certificates and identities are a provisioning surface an order of magnitude larger than a passphrase. The three enterprise modes have numbers so that scan results can name them and a host can explain why a network is unavailable; the credential forms come with the capability that opens them.
  • Negotiation details. Management frame protection, SAE hash-to-element, transition-disable: the device does what the mode requires and the host never sees them. WPS and Easy Connect are provisioning methods rather than modes.
  • Auto-join across the table. There is none. The device joins the network it was told to and no other, because a device that picks networks by itself is a device whose behavior depends on what is in the air around it, which is the wrong property for a repeater on a wall.
  • Regulatory country. The channel set follows the platform’s regulatory configuration, which may later be tied to the device’s region; nothing here decides how that configuration is set. What is decided is that an access point stays inside it.
  • Power-save mode, PHY rate, band preference. The device’s business. A property that exposes them is easy to add and hard to remove.
  • A reconnect request. The one genuinely command-shaped act in the vicinity is deliberately not disguised as a property: a property write with a side effect when written with the value it already holds is a command in a costume, and it breaks the moment a host replays its configuration. It is also unnecessary, since the device retries on its own and replacing the selected entry restarts the join at once.