Contents
Overview
As far as I understand, there are three basic types of commands:
- frame commands, used to transfer 802.11 frames from/to the chip
- control commands, subclassed into
- traps, sent by the firmware on status changes, by driver to request status changes
- object commands, used to read/write objects
Documentation from STMicroelectronics
STMicroelectronics has published (under GPL) the API to the LMAC, i.e. the firmware. I have a copy of this file.
General structure
All commands exchanged with the firmware start with a 16-bit command type identifier and a 16-byte length field.
__le16 command_type; /* identifies frame vs. control vs. trap */ __le16 length;
For better readability I will note these fields in all structures below as well.
The command type field contains the following information:
Bit |
Meaning |
Control commands |
Frame commands |
0x8000 |
if set, command is control command |
||
0x0001 |
|
Control command is trap |
Control Commands
Control commands have the following common header:
__le16 command_type; __le16 length; /* end common header */ __le32 cookie; __le16 control_type;
where the control type indicates the type of packet.
Possible control types I've seen and documented elsewhere are:
Number |
Description |
Direction used |
Type |
0 |
filter configuration |
to firmware |
trap |
1 |
channel switch |
to firmware |
trap |
2 |
frequency setting done |
from firmware |
trap |
3 |
DCF init |
to firmware |
trap |
6 |
unknown |
to firmware |
trap |
7 |
free queue (appears to be unused in STA mode on N810) |
to firmware? |
? |
8 |
transmit done |
from firmware |
trap |
9 |
ping (appears to be unused in STA mode on N810) |
? |
trap |
10 |
Statistics |
both |
object |
11 |
BBP (appears to be unused in STA mode on N810) |
? |
? |
12 |
EEPROM read (no EEPROM on chip in N810) |
? |
? |
13 |
LED control |
to firmware |
trap |
27 |
Ladder init? |
to firmware |
trap |
Filter Configuration
The filter configuration command has the following structure (following the common control command structure):
__le16 command_type; __le16 length; __le32 cookie; __le16 control_type; /* end of command header */ __u16 pad; __le16 filter_type; /* only seen 0 and 1, bitfield? */ u8 dst[ETH_ALEN]; /* local MAC */ u8 src[ETH_ALEN]; /* remote MAC/BSSID */ u8 antenna_cfg; /* diversity, ...? */ u8 debug; /* zero */ /* from here on the old islsm info makes no more sense */ u8 unknown[28];
Channel switch
__le16 command_type; __le16 length; __le32 cookie; __le16 control_type; /* end of command header */ __u16 pad; __le16 magic1; /* bitfield? seen values: 1,2,6 */ __le16 dwell; /* dwell time in ms, seen 0, 120, 140 */ u8 unknown1[10]; /* always zeroed */ u8 unknown2[10]; /* zeroed or 00bfc007dec7006e2fc0 */ __le16 freq; /* in MHz */ __le16 unknown3; /* always 12? */ /* data from PDR_PRISM_ZIF_TX_IQ_CALIBRATION */ u8 iqcal[8]; /* data from PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS */ __le16 barker[4]; /* four times barker data */ __le16 bpsk[2]; /* twice bpsk data */ __le16 qpsk[2]; /* etc. */ __le16 qam16[2]; __le16 qam64[2]; u8 curve[168]; /* see below */ u8 unknown4[80]; /* data from PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED */ u8 rssical[6]; u8 unknown5[2]; /* mostly 0, sometimes 0xbf02, 0xc2ec */
The dwell field coincides with the time until FREQDONE is received from the chips, in milliseconds, and 120ms also makes sense as dwell time for active scanning.
The magic1 field might control sending of the queued (probe request) frames as well as whether "frequency setting done" replies are sent by the firmware. Maybe...
The curve data is built from PDR_PRISM_PA_CAL_CURVE_DATA as follows:
__le16 rf_power; __le16 pa_detector; __le16 unk[4]; /* four times the same value */ __le16 pcv[8]; /* eight times the pcv value */
This data is added six times from the six points per channel my PDR data has (TODO: figure out where the six is encoded in the command structure.)
The unknown data is probably derived from the PDR values too but I don't know how...
DCF init
__le16 command_type; __le16 length; __le32 cookie; __le16 control_type; /* end of command header */ __u16 pad; u8 pad1; /* zeroed */ u8 slottime; /* in usec */ u8 magic1, magic2; /* have seen 10/6 or 16/0 */ struct { __le16 aifs, CWmin, CWmax, TXOP; } queues[8];
Transmit done
__le16 command_type; __le16 length; __le32 cookie; __le16 control_type; /* end of command header */ u8 retry1, retry2; /* retries? copy from TX command? */ u8 status; /* bit 0x1 means ACKed? */ u8 retries; /* number of times packet was sent? */ __le16 ack_rssi; /* ?? */ __le16 seqctrl; /* sequence number, fragment number zeroed? */ u8 unknown[2]; /* contains two rates? */
Frequency setting done
__le16 command_type; __le16 length; __le32 cookie; __le16 control_type; /* end of command header */ __le16 reason; /* copied from set channel command somewhere? */ __le16 freq; /* MHz */
Statistics
__le16 command_type; __le16 length; __le32 cookie; __le16 control_type; /* end of command header */ __u16 pad; u8 unknown[76];
LED control
Not very useful on the N810, but nonetheless used...
__le16 command_type; __le16 length; __le32 cookie; __le16 control_type; /* end of command header */ __u16 pad; __le16 mode; /* always 3? */ __le16 led_temporary; __le16 led_permanent; __le16 duration;
Ladder init?
__le16 command_type; __le16 length; __le32 cookie; __le16 control_type; /* end of command header */ __u16 pad1; __le16 ladder; __u16 pad2;