CSI Extraction for Mediatek based Wi-Fi chipsets

Hi everybody,

a friend of mine and I managed to enable extraction of CSI (Channel State Information) on Mediatek based Wi-Fi chipsets. The project can be found here: https://github.com/MtkWifiRev/MtkCSIdump
No firmware modifications are necessary, its purely done by some patches in mt76. The driver changes are based on this patch set. We provide squashfs images for two mt7981 based routers which we tested:

  • OpenWRT One
  • Xiaomi Mi AX3000T

It should work for other chipsets as well, but Wi-Fi 7 based cards might need a different interpretation of the CSI data.
In our repo you can find:

  • A tool to run on the OpenWRT based router to start collection of the CSI data
  • A Python based GUI which can be used to receive the CSI data via UDP from the OpenWRT router.

I hope this is interesting and helpful to some people.

Update:
Here is a link to a recording from Nullcon this year were we presented this (sorry for the bad audio). And a link to the slides.

-Daniel

2 Likes

Why not mainline it?

2 Likes

I would love to have spectral scan in LuCI, just like in Ubiquiti and Mikrotik.

You have survey dump at 5MHz chunks already.

Not all channels return noise floor from what I can see.

root@OpenWrt:~# iw dev phy0-ap0 survey dump
Survey data from phy0-ap0
        frequency:                      2412 MHz
        noise:                          -91 dBm
        channel active time:            48 ms
        channel busy time:              11 ms
        channel receive time:           8 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2417 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2422 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2427 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2432 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2437 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2442 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2447 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2452 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2457 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2462 MHz [in use]
        noise:                          -90 dBm
        channel active time:            234027155 ms
        channel busy time:              74846531 ms
        channel receive time:           72670783 ms
        channel BSS receive time:       12505 ms
        channel transmit time:          916557 ms
Survey data from phy0-ap0
        frequency:                      2467 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms
Survey data from phy0-ap0
        frequency:                      2472 MHz
        channel active time:            0 ms
        channel busy time:              0 ms
        channel receive time:           0 ms
        channel BSS receive time:       0 ms
        channel transmit time:          0 ms

We can try, but I think the question is always how to maintain it. And I can't do it in the long run.

We do have another project were we enabled raw I/Q capture on a specific Android chipset, see MtkICAPtool. We are trying to get this working on other chipsets, but no luck so far. But I don't think this is the level of data you are looking for, right?

Only FFT data is required. This is what FFT visualisation looks like on Ubiquiti:

Source: https://flyteccomputers.com/blog/unlocking-wifi-optimization-with-the-u7promax-realtime-spectrum-analyzer/?srsltid=AfmBOooT_b_fUHyokiYBsqxDn2QYiIPjswHGYoGiYHSkLbPrsM19cDZt

All devices I have seen that support this feature have an Atheros chip. This feature is supported by the ath9k/ath10k and ath11k drivers. Here is the interface documentation. It would be ideal if Mediatek had the same interface.

Thats interesting, thanks for the pointer @olek210. mt76 does mention a "WIFI_SPECTRUM" mode:


There are even more details in mt_wifi. We already tried to enable this but it did not work so far, we will keep trying to figure out how to get this one enabled.

1 Like

Interesting work!

Took a quick look at the driver code, and it's completely crazy. TLVs from the firmware are parsed using a packed struct:

This is unnecessarily fragile and unmaintainable. Extending it to more chipsets is meaningless. Why not start mapping the TLVs? I bet they are the same across different chipsets and firmwares, but possibly with variable lengths and order

Excellent work. I was able to use your base to reproduce on the BananaPi-RP3. This required some FW patching on the NDS32 binary for this target. (mt7986)
The code was there, but 0xc2 was removed from the dispatch loop which required some patches.

Stock mt7986 ext_eid dispatch loop:

   eid   FW   Linux  Linux name
---------------------------------------------------------------------------
  0x00    ✓           (firmware only)
  0x01    ✓      ✓    MCU_EXT_CMD_EFUSE_ACCESS
  0x02    ✓      ✓    MCU_EXT_CMD_RF_REG_ACCESS
  0x03    ✓           (firmware only)
  0x04    ✓      ✓    MCU_EXT_CMD_RF_TEST
  0x05    ✓           (firmware only)
  0x06    ✓           (firmware only)
  0x07    ✓      ✓    MCU_EXT_CMD_PM_STATE_CTRL
  0x08    ✓      ✓    MCU_EXT_CMD_CHANNEL_SWITCH
  0x09    ✓           (firmware only)
  0x0a    ✓           (firmware only)
  0x0b    ✓           (firmware only)
  0x0c    ✓           (firmware only)
  0x0d    ✓           (firmware only)
  0x0e    ✓           (firmware only)
  0x0f    ✓           (firmware only)
  0x10    ✓           (firmware only)
  0x11    ✓      ✓    MCU_EXT_CMD_SET_TX_POWER_CTRL
  0x12    ✓           (firmware only)
  0x13    ✓      ✓    MCU_EXT_CMD_FW_LOG_2_HOST
  0x14    ✓           (firmware only)
  0x15    ✓           (firmware only)
  0x16    ✓           (firmware only)
  0x17    ✓           (firmware only)
  0x18    ✓           (firmware only)
  0x19    ✓           (firmware only)
  0x1a    ✓           (firmware only)
  0x1b    ✓           (firmware only)
  0x1c    ✓           (firmware only)
  0x1d    ✓           (firmware only)
  0x1e    ✓      ✓    MCU_EXT_CMD_TXBF_ACTION
  0x1f    ✓           (firmware only)
  0x20    ✓           (firmware only)
  0x21    ✓      ✓    MCU_EXT_CMD_EFUSE_BUFFER_MODE
  0x22    ✓           (firmware only)
  0x23    ✓      ✓    MCU_EXT_CMD_THERMAL_PROT
  0x24    ✓           (firmware only)
  0x25    ✓      ✓    MCU_EXT_CMD_STA_REC_UPDATE
  0x26    ✓      ✓    MCU_EXT_CMD_BSS_INFO_UPDATE
  0x27    ✓      ✓    MCU_EXT_CMD_EDCA_UPDATE
  0x28    ✓           (firmware only)
  0x29    ✓           (firmware only)
  0x2a    ✓      ✓    MCU_EXT_CMD_DEV_INFO_UPDATE
  0x2b    ✓           (firmware only)
  0x2c    ✓      ✓    MCU_EXT_CMD_THERMAL_CTRL
  0x2d    ✓           (firmware only)
  0x2e    ✓           (firmware only)
  0x2f    ✓           (firmware only)
  0x30    ✓           (firmware only)
  0x31    ✓           (firmware only)
  0x32    ✓      ✓    MCU_EXT_CMD_WTBL_UPDATE
  0x33    ✓           (firmware only)
  0x34    ✓           (firmware only)
  0x35    ✓           (firmware only)
  0x36    ✓      ✓    MCU_EXT_CMD_SET_DRR_CTRL
  0x37    ✓           (firmware only)
  0x38    ✓           (firmware only)
  0x39    ✓           (firmware only)
  0x3a    ✓      ✓    MCU_EXT_CMD_SET_RDD_CTRL
  0x3b    ✓           (firmware only)
  0x3c    ✓           (firmware only)
  0x3d    ✓      ✓    MCU_EXT_CMD_ATE_CTRL
  0x3e    ✓      ✓    MCU_EXT_CMD_PROTECT_CTRL
  0x3f    ✓           (firmware only)
  0x40    ✓           (firmware only)
  0x41    ✓           (firmware only)
  0x42    ✓           (firmware only)
  0x43    ✓           (firmware only)
  0x44    ✓           (firmware only)
  0x45    ✓      ✓    MCU_EXT_CMD_DBDC_CTRL
  0x46    ✓      ✓    MCU_EXT_CMD_MAC_INIT_CTRL
  0x47    ✓      ✓    MCU_EXT_CMD_RX_HDR_TRANS
  0x48    ✓      ✓    MCU_EXT_CMD_MUAR_UPDATE
  0x49    ✓      ✓    MCU_EXT_CMD_BCN_OFFLOAD
  0x4a    ✓      ✓    MCU_EXT_CMD_RX_AIRTIME_CTRL
  0x4b    ✓           (firmware only)
  0x4c    ✓           (firmware only)
  0x4d    ✓           (firmware only)
  0x4e    ✓      ✓    MCU_EXT_CMD_SET_RX_PATH
  0x4f    ✓      ✓    MCU_EXT_CMD_EFUSE_FREE_BLOCK
  0x50    ✓           (firmware only)
  0x51    ✓           (firmware only)
  0x52    ✓           (firmware only)
  0x53    ✓           (firmware only)
  0x54    ✓           (firmware only)
  0x55    ✓           (firmware only)
  0x56    ✓           (firmware only)
  0x57    ✓           (firmware only)
  0x58    ✓      ✓    MCU_EXT_CMD_TX_POWER_FEATURE_CTRL
  0x59    ✓      ✓    MCU_EXT_CMD_RXDCOC_CAL
  0x5a    ✓      ✓    MCU_EXT_CMD_GET_MIB_INFO
  0x5b    ✓           (firmware only)
  0x5c    ✓           (firmware only)
  0x5d    ✓           (firmware only)
  0x5e    ✓           (firmware only)
  0x5f    ✓           (firmware only)
  0x60    ✓      ✓    MCU_EXT_CMD_TXDPD_CAL
  0x61    ✓           (firmware only)
  0x62    ✓           (firmware only)
  0x63    ✓           (firmware only)
  0x64    ✓           (firmware only)
  0x65    ✓           (firmware only)
  0x66    ✓           (firmware only)
  0x67    ✓      ✓    MCU_EXT_CMD_CAL_CACHE
  0x68    ✓      ✓    MCU_EXT_CMD_RED_ENABLE
  0x69    ✓           (firmware only)
  0x6a    ✓           (firmware only)
  0x6b    ✓           (firmware only)
  0x6c    ✓           (firmware only)
  0x6d    ✓           (firmware only)
  0x6e    ✓           (firmware only)
  0x6f    ✓           (firmware only)
  0x70    ✓           (firmware only)
  0x71    ✓           (firmware only)
  0x72    ✓           (firmware only)
  0x73    ✓           (firmware only)
  0x74    ✓           (firmware only)
  0x75    ✓           (firmware only)
  0x76    ✓           (firmware only)
  0x77    ✓           (firmware only)
  0x7c           ✓    MCU_EXT_CMD_SET_RADAR_TH  ← NOT IN FIRMWARE
  0x7d           ✓    MCU_EXT_CMD_SET_RDD_PATTERN  ← NOT IN FIRMWARE
  0x80           ✓    MCU_EXT_CMD_MWDS_SUPPORT  ← NOT IN FIRMWARE
  0x81           ✓    MCU_EXT_CMD_SET_SER_TRIGGER  ← NOT IN FIRMWARE
  0x94           ✓    MCU_EXT_CMD_TWT_AGRT_UPDATE  ← NOT IN FIRMWARE
  0x95           ✓    MCU_EXT_CMD_FW_DBG_CTRL  ← NOT IN FIRMWARE
  0x9a           ✓    MCU_EXT_CMD_OFFCH_SCAN_CTRL  ← NOT IN FIRMWARE
  0x9d           ✓    MCU_EXT_CMD_SET_RDD_TH  ← NOT IN FIRMWARE
  0x9f           ✓    MCU_EXT_CMD_MURU_CTRL  ← NOT IN FIRMWARE
  0xa8           ✓    MCU_EXT_CMD_SET_SPR  ← NOT IN FIRMWARE
  0xab           ✓    MCU_EXT_CMD_GROUP_PRE_CAL_INFO  ← NOT IN FIRMWARE
  0xac           ✓    MCU_EXT_CMD_DPD_PRE_CAL_INFO  ← NOT IN FIRMWARE
  0xad           ✓    MCU_EXT_CMD_PHY_STAT_INFO  ← NOT IN FIRMWARE
  0xba           ✓    MCU_EXT_CMD_EDCCA  ← NOT IN FIRMWARE
  0xbd           ✓    MCU_EXT_CMD_WF_RF_PIN_CTRL  ← NOT IN FIRMWARE
  0xc2           ✓    MCU_EXT_CMD_CSI_CTRL  ← NOT IN FIRMWARE
  0xc5           ✓    MCU_EXT_CMD_IPI_HIST_SCAN  ← NOT IN FIRMWARE

Hi everyboy
I want to use CSI function on MT7981, does the WIFI_RAM_CODE_MT7981.bin need to be updated? what's the version of this bin file?

Hi nysan,
So you have succeeded? Did you change the mt7986 firmware bin? thanks very much.

Yes, FW patch required. The fuction is available in linux-firmware FW, but not in ext_eid dispatch hook.

Hi nysan:
Thanks very much for your reply ! Can you tell me where to dowload the FW patch or the new linux-firmare FW?