feat: pair controllers and show them in the app
Port the MT76 client functions (send_wlan, associate_client, pair_client, set_client_key, remove_client) and wire the RX dispatch into the session: EP IN frames are parsed, ASSOC_REQ associates a controller (WCID plus chip programming), PAIR_REQ replies with PAIR_RESP, and DISASSOC or client-lost removes it. The C API exposes connected controllers and the app lists them by MAC. Bumps xone_cli/xone_app to C++23: they were falling back to the default standard once mt76.hpp started using std::span. Adds a unit test pinning the WCID regions, the 32-byte rxwi, and the new frame control values. Co-Authored-By: qwen3.8-27b@q2_k_xl: client functions, RX dispatch, GUI list
This commit is contained in:
+33
-1
@@ -12,6 +12,7 @@
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
|
||||
#include "mt76/mt76_defs.hpp"
|
||||
|
||||
@@ -55,7 +56,7 @@ public:
|
||||
auto select_function(std::uint32_t func, std::uint32_t val) -> int;
|
||||
auto set_power_mode(power_mode mode) -> int;
|
||||
auto load_cr(cr_mode mode) -> int;
|
||||
auto write_burst(std::uint32_t idx, void *data, std::size_t len) -> int;
|
||||
auto write_burst(std::uint32_t idx, void const *data, std::size_t len) -> int;
|
||||
auto send_ms_command(ms_command cmd, void *data, std::size_t len) -> int;
|
||||
auto calibrate(calibration calib, std::uint32_t val) -> int;
|
||||
|
||||
@@ -69,6 +70,37 @@ public:
|
||||
// Enter or leave pairing mode (port of xone_mt76_set_pairing).
|
||||
auto set_pairing(bool enable) -> int;
|
||||
|
||||
// Controller association and data path (ports of the xone_mt76_* client
|
||||
// functions). `addr` is a 6-byte controller MAC.
|
||||
//
|
||||
// send_wlan prepends a TXWI and frames the payload as an MCU message,
|
||||
// then bulk-writes it to EP OUT.
|
||||
auto send_wlan(std::span<std::uint8_t const> frame) -> int;
|
||||
|
||||
// Associate a controller: program its WCID MAC, ADD_CLIENT ms_command,
|
||||
// and transmit an ASSOC_RESP mgmt frame.
|
||||
auto associate_client(std::uint8_t wcid, std::span<std::uint8_t const> addr)
|
||||
-> int;
|
||||
|
||||
// Reply to a pairing request with a PAIR_RESP mgmt frame.
|
||||
auto pair_client(std::span<std::uint8_t const> addr) -> int;
|
||||
|
||||
// Send a reserved (0x70) management command to a client, waiting for an
|
||||
// acknowledgment (port of xone_mt76_send_client_command).
|
||||
auto send_client_command(std::uint8_t wcid,
|
||||
std::span<std::uint8_t const> addr,
|
||||
client_cmd cmd,
|
||||
std::span<std::uint8_t const> data) -> int;
|
||||
|
||||
// Install the per-client AES-CCMP key (16 bytes) in the chip WCID
|
||||
// registers (port of xone_mt76_set_client_key).
|
||||
auto set_client_key(std::uint8_t wcid, std::span<std::uint8_t const> key)
|
||||
-> int;
|
||||
|
||||
// Remove a client: REMOVE_CLIENT ms_command and zero its WCID regions
|
||||
// (port of xone_mt76_remove_client).
|
||||
auto remove_client(std::uint8_t wcid) -> int;
|
||||
|
||||
private:
|
||||
// Send an MCU command (port of xone_mt76_send_command). `cmd` is the
|
||||
// MT_MCU_MSG_CMD_TYPE field. Returns bytes written, or a negative errno.
|
||||
|
||||
@@ -30,6 +30,13 @@ inline constexpr auto field_prep(std::uint32_t mask, std::uint32_t val) -> std::
|
||||
return (val << __builtin_ctz(mask)) & mask;
|
||||
}
|
||||
|
||||
// Extract a bitfield (port of the kernel FIELD_GET macro).
|
||||
inline constexpr auto field_get(std::uint32_t mask, std::uint32_t val)
|
||||
-> std::uint32_t
|
||||
{
|
||||
return (val & mask) >> __builtin_ctz(mask);
|
||||
}
|
||||
|
||||
// Register address flag: use the config-space vendor request codes.
|
||||
constexpr std::uint32_t mt_vend_type_cfg = bit(30);
|
||||
|
||||
@@ -382,4 +389,102 @@ constexpr std::uint8_t mt_txwi_ack_ctl_nseq = bit(1);
|
||||
// 802.11 frame control for a beacon (MGMT type, BEACON subtype).
|
||||
constexpr std::uint16_t ieee80211_fc_beacon = 0x0080;
|
||||
|
||||
// WCID regions (port of MT_WCID_*). n is the zero-based WCID index.
|
||||
constexpr std::uint32_t mt_wcid_addr_base = 0x1800;
|
||||
inline constexpr auto mt_wcid_addr(std::size_t n) -> std::uint32_t
|
||||
{
|
||||
return mt_wcid_addr_base + (n << 3);
|
||||
}
|
||||
constexpr std::uint32_t mt_wcid_key_base = 0x8000;
|
||||
inline constexpr auto mt_wcid_key(std::size_t n) -> std::uint32_t
|
||||
{
|
||||
return mt_wcid_key_base + (n << 5);
|
||||
}
|
||||
constexpr std::uint32_t mt_wcid_iv_base = 0xa000;
|
||||
inline constexpr auto mt_wcid_iv(std::size_t n) -> std::uint32_t
|
||||
{
|
||||
return mt_wcid_iv_base + (n << 3);
|
||||
}
|
||||
constexpr std::uint32_t mt_wcid_attr_base = 0xa800;
|
||||
inline constexpr auto mt_wcid_attr(std::size_t n) -> std::uint32_t
|
||||
{
|
||||
return mt_wcid_attr_base + (n << 2);
|
||||
}
|
||||
constexpr std::uint32_t mt_wcid_attr_pairwise = bit(0);
|
||||
constexpr std::uint32_t mt_wcid_attr_pkey_mode = genmask(3, 1);
|
||||
constexpr std::size_t xone_mt_wcid_key_len = 16;
|
||||
|
||||
// TX descriptor info fields (port of MT_TXD_INFO_*), used by send_wlan.
|
||||
constexpr std::uint32_t mt_txd_info_80211 = bit(19);
|
||||
constexpr std::uint32_t mt_txd_info_wiv = bit(24);
|
||||
constexpr std::uint32_t mt_txd_info_qsel = genmask(26, 25);
|
||||
constexpr std::uint32_t mt_txd_info_dport = genmask(29, 27);
|
||||
|
||||
// RX FCE info fields (port of MT_RX_FCE_INFO_*), used by the RX path.
|
||||
constexpr std::uint32_t mt_rx_fce_info_len = genmask(13, 0);
|
||||
constexpr std::uint32_t mt_rx_fce_info_evt_type = genmask(23, 20);
|
||||
|
||||
// Receive descriptor (port of struct mt76_rxwi). Little-endian wire order,
|
||||
// 32 bytes total. Only rxinfo and ctl are consumed by the RX path.
|
||||
struct mt76_rxwi {
|
||||
std::uint32_t rxinfo; // MT_RXINFO_L2PAD etc.
|
||||
std::uint32_t ctl; // wcid (bits 7:0), mpdu_len (bits 29:16)
|
||||
std::uint16_t tid_sn;
|
||||
std::uint16_t rate;
|
||||
std::uint8_t rssi[4];
|
||||
std::uint32_t bbp_rxinfo[4];
|
||||
};
|
||||
constexpr std::uint32_t mt_rxinfo_l2pad = bit(14);
|
||||
constexpr std::uint32_t mt_rxwi_ctl_wcid = genmask(7, 0);
|
||||
constexpr std::uint32_t mt_rxwi_ctl_mpdu_len = genmask(29, 16);
|
||||
|
||||
// CPU RX event types (port of XONE_MT_EVT_*).
|
||||
enum cpu_evt : std::uint32_t {
|
||||
evt_button = 0x04,
|
||||
evt_packet_rx = 0x0c,
|
||||
evt_client_lost = 0x0e,
|
||||
};
|
||||
|
||||
// Client command codes (port of XONE_MT_CLIENT_*).
|
||||
enum client_cmd : std::uint32_t {
|
||||
client_pair_req = 0x01,
|
||||
client_pair_resp = 0x02,
|
||||
client_enable_encryption = 0x10,
|
||||
};
|
||||
|
||||
// 802.11 frame control: type (bits 3:2) and subtype (bits 7:4).
|
||||
// FCTL_FTYPE/FCTL_STYPE are the masks used to match a frame's type/subtype.
|
||||
constexpr std::uint16_t ieee80211_fctl_ftype = 0x0c;
|
||||
constexpr std::uint16_t ieee80211_fctl_stype = 0xf0;
|
||||
constexpr std::uint16_t ieee80211_ftype_mgmt = 0x00;
|
||||
constexpr std::uint16_t ieee80211_ftype_data = 0x08;
|
||||
constexpr std::uint16_t ieee80211_stype_assoc_req = 0x00;
|
||||
constexpr std::uint16_t ieee80211_stype_assoc_resp = 0x10;
|
||||
constexpr std::uint16_t ieee80211_stype_disassoc = 0xa0;
|
||||
constexpr std::uint16_t ieee80211_stype_qos_data = 0x70;
|
||||
// MGMT subtype for reserved (pairing) frames.
|
||||
constexpr std::uint16_t ieee80211_stype_wlan_reserved = 0x70;
|
||||
|
||||
// TX descriptor fields (port of MT_TXWI_*).
|
||||
constexpr std::uint32_t mt_txwi_flags_mpdu_density = genmask(7, 5);
|
||||
constexpr std::uint8_t mt_txwi_ack_ctl_req = bit(0);
|
||||
constexpr std::uint8_t ieee80211_ht_mpdu_density_4 = 4;
|
||||
|
||||
// TX queue selection (port of enum mt76_qsel).
|
||||
enum qsel : std::uint32_t {
|
||||
qsel_mgmt = 0,
|
||||
qsel_hcca = 1,
|
||||
qsel_edca = 2,
|
||||
qsel_edca_2 = 3,
|
||||
};
|
||||
|
||||
// Cipher types (port of enum mt76_cipher_type).
|
||||
enum cipher_type : std::uint32_t {
|
||||
cipher_none = 0,
|
||||
cipher_wep40 = 1,
|
||||
cipher_wep104 = 2,
|
||||
cipher_tkip = 3,
|
||||
cipher_aes_ccmp = 4,
|
||||
};
|
||||
|
||||
} // namespace xone::mt76
|
||||
|
||||
Reference in New Issue
Block a user