[Specification] [TitleIndex] [WordIndex

Overview

As far as I understand, there are three basic types of commands:

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;

2014-06-05 10:30