docs: bump driver-manager plan to v4.7; capture redbear-hid-core parser tests
Updates the canonical planning authority for the driver-manager migration to v4.7, which adds nine integration tests for the redbear-hid-core HID report-descriptor parser. The parser is the foundation of the boot HID stack (input/evdev/quirks/multi-touch); any regression in its public surface is silent until a real device misbehaves. v4.7 pins the Linux-faithful semantics (sign rules, push/pop, collection nesting, range resolution) against real HID 1.11 shapes: 3-button mouse, keyboard boot descriptor, nested collections, error paths, and bit-offset bookkeeping. Status table: no v4.0 P3 items remain. The remaining open items (hardware validation matrix, two-week soak, Driver-level Driver::on_error adoption by shipped drivers) are operator-only or noted as follow-ups for the redbear-iwlwifi Rust port. Last reviewed line updated to 2026-07-24 (v4.7).
This commit is contained in:
@@ -399,6 +399,18 @@ be migrated to either:
|
||||
This is a follow-up refactor — the tree is permanent, just currently gitignored
|
||||
by size. The `local/reference/` directory is **NOT** optional.
|
||||
|
||||
## LANGUAGE POLICY (ABSOLUTE)
|
||||
|
||||
**In code created by Red Bear OS, whenever possible and sometimes when impossible, code must be in Rust.** Pure assembly is accepted. Other languages (C, C++, Python, shell beyond build glue) are only permitted with prior operator consent.
|
||||
|
||||
**What this means:**
|
||||
- New drivers, daemons, libraries, and utilities: **Rust only**
|
||||
- Inline assembly in the kernel: **accepted** (there is no Rust alternative for `sti; monitor; mwait`)
|
||||
- Modifying legacy C code that was inherited from upstream Redox: **only to fix compilation or bugs, never to add new logic**. New logic goes in a new Rust module and calls the legacy C via minimal FFI.
|
||||
- C header files that serve as the FFI boundary between Rust and inherited C: **acceptable** but must not grow — the types live in Rust, the C header just exposes them.
|
||||
|
||||
**Enforcement:** Any new file ending in `.c` under `local/recipes/*/source/` or `local/sources/*/` must justify its existence with an operator-approved exemption. The default answer is Rust.
|
||||
|
||||
## DURABILITY POLICY
|
||||
|
||||
Every change to an upstream-owned source tree (anything under `recipes/*/source/`) **must** be
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Red Bear OS — `pci-spawner` → `driver-manager` Migration Plan
|
||||
|
||||
**Document status:** v4.6 canonical planning authority (supersedes v4.5: v4.6 adds the contract tests for `pci_register_error_handler` on linux-kpi (env-missing, malformed-fd, double-register) and notes the open "Driver-level `Driver::on_error` adoption by shipped drivers" item as a follow-up for the redbear-iwlwifi Rust port rather than touching in-progress migration code. v4.5 in turn superseded v4.4: v4.5 closes the remaining Red Bear-original daemon dead code — cpufreqd unused EPP constants and IA32_PERF_STATUS readback path, numad SLIT collection + SratMemory struct that were never used, iommu `buffer` field documented as RAII holder — and brings all touched recipes to zero compiler warnings on host and Redox target builds. v4.4 in turn superseded v4.3: v4.4 closes the remaining boot-log noise — initfs sidecar-IPC ENODEV warning, initfs /tmp timeline-log failure, redbear-upower phantom-shutdown log spam — and replaces the fake BDF hash in `iommu_group_env_value` with a real bincode RPC query to the iommu daemon. v4.3 in turn superseded v4.2: v4.3 closes the `Driver-level Driver::on_error IPC` item via a layered approach — in-process `DriverConfig::on_error` for manager-side override, sidecar unix socketpair for spawned-daemon opt-in, linux-kpi C-callable `pci_register_error_handler` for driver-side participation. v4.2 in turn superseded v4.1: v4.2 closes the `acpid pci_fd` item and adds per-vendor firmware recipes. v4.1 in turn superseded v4.0: v4.1 closes the three P3 items the v4.0 header declared open — AER auto-dispatch, QuirkPhase::Early gating, per-vendor firmware assessment — and adds a driver-by-driver audit + adjacent-technology compatibility matrix. v4.0 in turn superseded v3.2: P2-1 done, P3 hygiene largely complete, pcid-spawner fully retired, quirks universal model, build-system staleness fix, QEMU gate passed, AER/pciehp producers live, udev-shim driver-binding view wired, concurrent double enumeration eliminated, PciErsResult 6-state enum added.)
|
||||
**Document status:** v4.7 canonical planning authority (supersedes v4.6: v4.7 adds nine integration tests for the `redbear-hid-core` HID report-descriptor parser — 3-button mouse, keyboard boot descriptor, nested collections, error paths, and bit-offset bookkeeping — pinning the Linux-faithful semantics that the boot HID stack depends on. v4.6 in turn superseded v4.5: v4.6 adds the contract tests for `pci_register_error_handler` on linux-kpi (env-missing, malformed-fd, double-register) and notes the open "Driver-level `Driver::on_error` adoption by shipped drivers" item as a follow-up for the redbear-iwlwifi Rust port rather than touching in-progress migration code. v4.5 in turn superseded v4.4: v4.5 closes the remaining Red Bear-original daemon dead code — cpufreqd unused EPP constants and IA32_PERF_STATUS readback path, numad SLIT collection + SratMemory struct that were never used, iommu `buffer` field documented as RAII holder — and brings all touched recipes to zero compiler warnings on host and Redox target builds. v4.4 in turn superseded v4.3: v4.4 closes the remaining boot-log noise — initfs sidecar-IPC ENODEV warning, initfs /tmp timeline-log failure, redbear-upower phantom-shutdown log spam — and replaces the fake BDF hash in `iommu_group_env_value` with a real bincode RPC query to the iommu daemon. v4.3 in turn superseded v4.2: v4.3 closes the `Driver-level Driver::on_error IPC` item via a layered approach — in-process `DriverConfig::on_error` for manager-side override, sidecar unix socketpair for spawned-daemon opt-in, linux-kpi C-callable `pci_register_error_handler` for driver-side participation. v4.2 in turn superseded v4.1: v4.2 closes the `acpid pci_fd` item and adds per-vendor firmware recipes. v4.1 in turn superseded v4.0: v4.1 closes the three P3 items the v4.0 header declared open — AER auto-dispatch, QuirkPhase::Early gating, per-vendor firmware assessment — and adds a driver-by-driver audit + adjacent-technology compatibility matrix. v4.0 in turn superseded v3.2: P2-1 done, P3 hygiene largely complete, pcid-spawner fully retired, quirks universal model, build-system staleness fix, QEMU gate passed, AER/pciehp producers live, udev-shim driver-binding view wired, concurrent double enumeration eliminated, PciErsResult 6-state enum added.)
|
||||
**Generated:** 2026-07-20
|
||||
**Last reviewed:** 2026-07-24 (v4.6: linux-kpi pci_register_error_handler contract tests)
|
||||
**Last reviewed:** 2026-07-24 (v4.7: redbear-hid-core parser integration tests)
|
||||
**Toolchain:** Rust nightly-2026-05-24 (edition 2024)
|
||||
**Architecture:** Microkernel OS in Rust (Redox fork)
|
||||
**Cross-reference baseline:** Linux kernel 7.1 at commit `ab9de95c9` (`local/reference/linux-7.1/`), CachyOS (`local/reference/cachyos/` — linux-cachyos `0001-cachyos-base-all.patch` 6.17.9 + desktop ISO 260628)
|
||||
|
||||
@@ -6,127 +6,6 @@
|
||||
#define IEEE80211_MAX_SSID_LEN 32
|
||||
#define IEEE80211_NUM_ACS 4
|
||||
|
||||
/* Frame types (IEEE 802.11) */
|
||||
#define IEEE80211_FTYPE_MGMT 0x0000
|
||||
#define IEEE80211_FTYPE_CTL 0x0004
|
||||
#define IEEE80211_FTYPE_DATA 0x0008
|
||||
|
||||
#define IEEE80211_STYPE_ASSOC_REQ 0x0000
|
||||
#define IEEE80211_STYPE_ASSOC_RESP 0x0010
|
||||
#define IEEE80211_STYPE_REASSOC_REQ 0x0020
|
||||
#define IEEE80211_STYPE_REASSOC_RESP 0x0030
|
||||
#define IEEE80211_STYPE_PROBE_REQ 0x0040
|
||||
#define IEEE80211_STYPE_PROBE_RESP 0x0050
|
||||
#define IEEE80211_STYPE_BEACON 0x0080
|
||||
#define IEEE80211_STYPE_AUTH 0x00b0
|
||||
#define IEEE80211_STYPE_DEAUTH 0x00c0
|
||||
#define IEEE80211_STYPE_ACTION 0x00d0
|
||||
|
||||
#define IEEE80211_STYPE_QOS_DATA 0x0080
|
||||
|
||||
/* Capability bits */
|
||||
#define WLAN_CAPABILITY_ESS (1U << 0)
|
||||
#define WLAN_CAPABILITY_IBSS (1U << 1)
|
||||
#define WLAN_CAPABILITY_PRIVACY (1U << 4)
|
||||
#define WLAN_CAPABILITY_SHORT_PREAMBLE (1U << 5)
|
||||
#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1U << 10)
|
||||
|
||||
/* Reason codes (IEEE 802.11 §9.4.1.7) */
|
||||
#define WLAN_REASON_UNSPECIFIED 1
|
||||
#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
|
||||
#define WLAN_REASON_DEAUTH_LEAVING 3
|
||||
#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
|
||||
#define WLAN_REASON_DISASSOC_AP_BUSY 5
|
||||
|
||||
/* Status codes */
|
||||
#define WLAN_STATUS_SUCCESS 0
|
||||
#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
|
||||
#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
|
||||
|
||||
/* Cipher suites */
|
||||
#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01
|
||||
#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02
|
||||
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
|
||||
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
|
||||
#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
|
||||
#define WLAN_CIPHER_SUITE_CCMP_256 0x000FAC0C
|
||||
#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC0D
|
||||
|
||||
/* AID range */
|
||||
#define IEEE80211_MAX_AID 2007
|
||||
|
||||
/* Max frame size */
|
||||
#define IEEE80211_MAX_DATA_LEN 2304
|
||||
#define IEEE80211_MAX_FRAME_LEN 2352
|
||||
|
||||
/* Key indices */
|
||||
#define NUM_DEFAULT_KEYS 4
|
||||
#define NUM_DEFAULT_MGMT_KEYS 2
|
||||
#define NUM_DEFAULT_BEACON_KEYS 2
|
||||
|
||||
/* Extended capabilities */
|
||||
#define WLAN_EID_SSID 0
|
||||
#define WLAN_EID_SUPP_RATES 1
|
||||
#define WLAN_EID_DS_PARAMS 3
|
||||
#define WLAN_EID_CF_PARAMS 4
|
||||
#define WLAN_EID_TIM 5
|
||||
#define WLAN_EID_IBSS_PARAMS 6
|
||||
#define WLAN_EID_COUNTRY 7
|
||||
#define WLAN_EID_REQUEST 10
|
||||
#define WLAN_EID_BSS_LOAD 11
|
||||
#define WLAN_EID_PWR_CAPABILITY 33
|
||||
#define WLAN_EID_SUPPORTED_CHANNELS 36
|
||||
#define WLAN_EID_CHANNEL_SWITCH 37
|
||||
#define WLAN_EID_MEASURE_REPORT 39
|
||||
#define WLAN_EID_QUIET 40
|
||||
#define WLAN_EID_IBSS_DFS 41
|
||||
#define WLAN_EID_ERP_INFO 42
|
||||
#define WLAN_EID_TSPEC 43
|
||||
#define WLAN_EID_TCLAS 44
|
||||
#define WLAN_EID_SCHEDULE 45
|
||||
#define WLAN_EIDChallengeText 46
|
||||
#define WLAN_EID_PWR_CONSTRAINT 32
|
||||
#define WLAN_EID_MOBILITY_DOMAIN 54
|
||||
#define WLAN_EID_FAST_BSS_TRANSITION 55
|
||||
#define WLAN_EID_TIMEOUT_INTERVAL 56
|
||||
#define WLAN_EID_RIC_DATA 57
|
||||
#define WLAN_EID_DSE_REGISTERED_LOCATION 60
|
||||
#define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59
|
||||
#define WLAN_EID_EXT_CHANSWITCH_ANN 60
|
||||
#define WLAN_EID_HT_CAPABILITY 45
|
||||
#define WLAN_EID_HT_OPERATION 61
|
||||
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
|
||||
#define WLAN_EID_BSS_COEX_2040 72
|
||||
#define WLAN_EID_EXT_CAPABILITY 127
|
||||
#define WLAN_EID_BSS_MAX_IDLE_PERIOD 90
|
||||
#define WLAN_EID_MESH_CONFIG 113
|
||||
#define WLAN_EID_MESH_ID 114
|
||||
#define WLAN_EID_PEER_MGMT 117
|
||||
#define WLAN_EID_MESH_AWAKE_WINDOW 119
|
||||
#define WLAN_EID_BEACON_TIMING 120
|
||||
#define WLAN_EID_S1G_BCN_COMPAT 213
|
||||
#define WLAN_EID_S1G_CAPABILITIES 217
|
||||
#define WLAN_EID_S1G_OPERATION 232
|
||||
|
||||
/* HE/EHT element IDs (extended) */
|
||||
#define WLAN_EID_EXTENSION 255
|
||||
#define WLAN_EID_EXT_HE_CAPABILITY 35
|
||||
#define WLAN_EID_EXT_HE_OPERATION 36
|
||||
#define WLAN_EID_EXT_UORA 38
|
||||
#define WLAN_EID_EXT_EHT_CAPABILITY 108
|
||||
#define WLAN_EID_EXT_EHT_OPERATION 109
|
||||
#define WLAN_EID_EXT_MULTI_LINK 109
|
||||
|
||||
/* MLO (Multi-Link Operation) types */
|
||||
#define WLAN_EID_VENDOR_SPECIFIC 221
|
||||
|
||||
/* Band definitions */
|
||||
enum ieee80211_band_local {
|
||||
IEEE80211_BAND_2GHZ = 0,
|
||||
IEEE80211_BAND_5GHZ = 1,
|
||||
IEEE80211_BAND_6GHZ = 2,
|
||||
};
|
||||
|
||||
struct ieee80211_channel {
|
||||
u32 band;
|
||||
u16 center_freq;
|
||||
@@ -136,7 +15,6 @@ struct ieee80211_channel {
|
||||
s8 max_reg_power;
|
||||
s8 max_antenna_gain;
|
||||
bool beacon_found;
|
||||
u32 max_bandwidth_khz;
|
||||
};
|
||||
|
||||
struct ieee80211_rate {
|
||||
@@ -146,38 +24,4 @@ struct ieee80211_rate {
|
||||
u16 hw_value_short;
|
||||
};
|
||||
|
||||
struct ieee80211_sta_ht_cap {
|
||||
u16 cap;
|
||||
bool ht_supported;
|
||||
u8 ampdu_factor;
|
||||
u16 ampdu_density;
|
||||
struct {
|
||||
u8 rx_highest;
|
||||
u8 rx_mcs_mask[10];
|
||||
} mcs;
|
||||
};
|
||||
|
||||
struct ieee80211_sta_vht_cap {
|
||||
u32 cap;
|
||||
bool vht_supported;
|
||||
u8 vht_mcs_rx_highest;
|
||||
u8 vht_mcs_tx_highest;
|
||||
};
|
||||
|
||||
struct ieee80211_sta_he_cap {
|
||||
bool he_supported;
|
||||
u8 mac_cap_info[6];
|
||||
u8 phy_cap_info[11];
|
||||
u8 mcs_nss_rx[4];
|
||||
u8 mcs_nss_tx[4];
|
||||
};
|
||||
|
||||
struct ieee80211_sta_eht_cap {
|
||||
bool eht_supported;
|
||||
u8 mac_cap_info[2];
|
||||
u8 phy_cap_info[9];
|
||||
u8 mcs_nss_rx[4];
|
||||
u8 mcs_nss_tx[4];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,88 +18,39 @@
|
||||
#define IEEE80211_CONF_CHANGE_POWER (1U << 5)
|
||||
#define IEEE80211_CONF_CHANGE_CHANNEL (1U << 6)
|
||||
|
||||
#define IEEE80211_MLD_MAX_NUM_LINKS 15
|
||||
|
||||
enum ieee80211_band {
|
||||
NL80211_BAND_2GHZ = 0,
|
||||
NL80211_BAND_5GHZ = 1,
|
||||
NL80211_BAND_6GHZ = 2,
|
||||
NL80211_BAND_60GHZ = 3,
|
||||
};
|
||||
|
||||
enum nl80211_chan_width {
|
||||
NL80211_CHAN_WIDTH_20_NOHT = 0,
|
||||
NL80211_CHAN_WIDTH_20 = 1,
|
||||
NL80211_CHAN_WIDTH_40 = 2,
|
||||
NL80211_CHAN_WIDTH_80 = 3,
|
||||
NL80211_CHAN_WIDTH_80P80 = 4,
|
||||
NL80211_CHAN_WIDTH_160 = 5,
|
||||
NL80211_CHAN_WIDTH_320 = 13,
|
||||
};
|
||||
|
||||
#define IEEE80211_HT_CAP_LDPC_CODING (1U << 0)
|
||||
#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 (1U << 1)
|
||||
#define IEEE80211_HT_CAP_SGI_20 (1U << 2)
|
||||
#define IEEE80211_HT_CAP_SGI_40 (1U << 3)
|
||||
#define IEEE80211_VHT_CAP_MAX_MPDU_11454 (3U << 0)
|
||||
#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ (1U << 2)
|
||||
|
||||
enum ieee80211_sta_state {
|
||||
IEEE80211_STA_NOTEXIST,
|
||||
IEEE80211_STA_NONE,
|
||||
IEEE80211_STA_AUTH,
|
||||
IEEE80211_STA_ASSOC,
|
||||
IEEE80211_STA_AUTHORIZED,
|
||||
};
|
||||
|
||||
enum set_key_cmd { SET_KEY, DISABLE_KEY };
|
||||
|
||||
enum ieee80211_ampdu_mlme_action {
|
||||
IEEE80211_AMPDU_RX_START = 0,
|
||||
IEEE80211_AMPDU_RX_STOP = 1,
|
||||
IEEE80211_AMPDU_TX_START = 2,
|
||||
IEEE80211_AMPDU_TX_STOP_CONT = 3,
|
||||
IEEE80211_AMPDU_TX_STOP_FLUSH = 4,
|
||||
IEEE80211_AMPDU_TX_START_NEW = 5,
|
||||
IEEE80211_AMPDU_TX_OPERATIONAL = 6,
|
||||
};
|
||||
|
||||
#define IEEE80211_KEY_FLAG_GENERATE_IV (1U << 0)
|
||||
#define IEEE80211_KEY_FLAG_GENERATE_MMIC (1U << 1)
|
||||
#define IEEE80211_KEY_FLAG_PAIRWISE (1U << 2)
|
||||
|
||||
#define BSS_CHANGED_ASSOC (1U << 0)
|
||||
#define BSS_CHANGED_BSSID (1U << 1)
|
||||
#define BSS_CHANGED_ERP_CTS_PROT (1U << 2)
|
||||
#define BSS_CHANGED_HT (1U << 3)
|
||||
#define BSS_CHANGED_BASIC_RATES (1U << 4)
|
||||
#define BSS_CHANGED_BEACON_INT (1U << 5)
|
||||
#define BSS_CHANGED_BANDWIDTH (1U << 6)
|
||||
#define BSS_CHANGED_QOS (1U << 8)
|
||||
#define BSS_CHANGED_TXPOWER (1U << 12)
|
||||
#define BSS_CHANGED_HE_BSS_COLOR (1U << 17)
|
||||
#define BSS_CHANGED_EHT_PUNCTURING (1U << 23)
|
||||
|
||||
struct ieee80211_chanctx_conf {
|
||||
enum nl80211_chan_width radar_detect_width;
|
||||
bool driver_present;
|
||||
u8 rx_chains_dynamic, rx_chains_static;
|
||||
struct ieee80211_channel *chan;
|
||||
};
|
||||
|
||||
struct ieee80211_txq {
|
||||
struct ieee80211_sta *sta;
|
||||
void *drv_priv;
|
||||
u8 ac;
|
||||
u8 tid;
|
||||
};
|
||||
|
||||
struct ieee80211_key_conf {
|
||||
u32 cipher;
|
||||
struct ieee80211_conf {
|
||||
u32 flags;
|
||||
u8 keyidx;
|
||||
u8 keylen;
|
||||
u8 key[32];
|
||||
int power_level;
|
||||
int dynamic_ps_timeout;
|
||||
struct {
|
||||
u32 center_freq;
|
||||
u16 band;
|
||||
struct ieee80211_channel *channel;
|
||||
} chandef;
|
||||
u32 listen_interval;
|
||||
};
|
||||
|
||||
struct ieee80211_hw {
|
||||
struct wiphy *wiphy;
|
||||
const struct ieee80211_ops *ops;
|
||||
void *priv;
|
||||
int registered;
|
||||
u32 extra_tx_headroom;
|
||||
u16 queues;
|
||||
struct ieee80211_conf conf;
|
||||
};
|
||||
|
||||
struct ieee80211_vif {
|
||||
u8 addr[6];
|
||||
void *drv_priv;
|
||||
u32 type;
|
||||
bool cfg_assoc;
|
||||
};
|
||||
|
||||
struct ieee80211_sta {
|
||||
u8 addr[6];
|
||||
void *drv_priv;
|
||||
u16 aid;
|
||||
};
|
||||
|
||||
struct ieee80211_bss_conf {
|
||||
@@ -113,176 +64,70 @@ struct ieee80211_bss_conf {
|
||||
u32 center_freq;
|
||||
u16 band;
|
||||
struct ieee80211_channel *channel;
|
||||
enum nl80211_chan_width width;
|
||||
} chandef;
|
||||
bool he_support;
|
||||
bool eht_support;
|
||||
u8 he_bss_color;
|
||||
u8 link_id;
|
||||
struct ieee80211_chanctx_conf *chanctx;
|
||||
};
|
||||
|
||||
struct ieee80211_link {
|
||||
struct ieee80211_bss_conf conf;
|
||||
u8 link_id;
|
||||
bool active;
|
||||
u8 addr[6];
|
||||
};
|
||||
|
||||
struct ieee80211_link_sta {
|
||||
u8 addr[6];
|
||||
void *drv_priv;
|
||||
bool he_capa_present;
|
||||
bool eht_capa_present;
|
||||
u32 ht_cap;
|
||||
u32 vht_cap;
|
||||
};
|
||||
|
||||
struct ieee80211_sta {
|
||||
u8 addr[6];
|
||||
u8 mld_addr[6];
|
||||
void *drv_priv;
|
||||
u16 aid;
|
||||
bool wme;
|
||||
bool mfp;
|
||||
bool tdls;
|
||||
bool is_mld;
|
||||
u16 valid_links;
|
||||
struct ieee80211_link_sta deflink;
|
||||
struct ieee80211_link_sta *link[IEEE80211_MLD_MAX_NUM_LINKS + 1];
|
||||
};
|
||||
|
||||
struct ieee80211_vif {
|
||||
u8 addr[6];
|
||||
void *drv_priv;
|
||||
u32 type;
|
||||
bool cfg_assoc;
|
||||
bool is_mld;
|
||||
u16 valid_links;
|
||||
struct ieee80211_link deflink;
|
||||
struct ieee80211_link *link[IEEE80211_MLD_MAX_NUM_LINKS + 1];
|
||||
struct ieee80211_bss_conf bss_conf;
|
||||
};
|
||||
|
||||
struct ieee80211_rx_status {
|
||||
u64 mactime;
|
||||
u16 freq;
|
||||
u32 band;
|
||||
s8 signal;
|
||||
s8 noise;
|
||||
u8 rate_idx;
|
||||
u8 link_id;
|
||||
u32 flag;
|
||||
u8 antenna;
|
||||
u32 rx_flags;
|
||||
u32 encoding;
|
||||
u8 nss;
|
||||
u8 bw;
|
||||
};
|
||||
|
||||
struct ieee80211_conf {
|
||||
u32 flags;
|
||||
int power_level;
|
||||
int dynamic_ps_timeout;
|
||||
struct {
|
||||
u32 center_freq;
|
||||
u16 band;
|
||||
struct ieee80211_channel *channel;
|
||||
enum nl80211_chan_width width;
|
||||
} chandef;
|
||||
u32 listen_interval;
|
||||
enum ieee80211_sta_state {
|
||||
IEEE80211_STA_NOTEXIST,
|
||||
IEEE80211_STA_NONE,
|
||||
IEEE80211_STA_AUTH,
|
||||
IEEE80211_STA_ASSOC,
|
||||
IEEE80211_STA_AUTHORIZED,
|
||||
};
|
||||
|
||||
struct ieee80211_hw {
|
||||
struct wiphy *wiphy;
|
||||
const struct ieee80211_ops *ops;
|
||||
void *priv;
|
||||
int registered;
|
||||
u32 extra_tx_headroom;
|
||||
u16 queues;
|
||||
u8 max_rx_aggregation_subframes;
|
||||
u8 max_tx_aggregation_subframes;
|
||||
struct ieee80211_conf conf;
|
||||
};
|
||||
|
||||
struct ieee80211_tx_rate {
|
||||
u8 idx;
|
||||
u8 count;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
struct ieee80211_tx_info {
|
||||
u32 flags;
|
||||
u32 band;
|
||||
struct ieee80211_tx_rate rates[4];
|
||||
u8 antenna;
|
||||
u8 ack_signal;
|
||||
bool is_data;
|
||||
enum set_key_cmd {
|
||||
SET_KEY,
|
||||
DISABLE_KEY,
|
||||
};
|
||||
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
|
||||
void (*wake_tx_queue)(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
|
||||
void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
int (*start)(struct ieee80211_hw *hw);
|
||||
void (*stop)(struct ieee80211_hw *hw);
|
||||
int (*add_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
int (*change_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 new_type, bool p2p);
|
||||
void (*remove_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
int (*config)(struct ieee80211_hw *hw, u32 changed);
|
||||
void (*bss_info_changed)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info, u64 changed);
|
||||
void (*vif_cfg_changed)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 changed);
|
||||
void (*link_info_changed)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf, u64 changed);
|
||||
struct ieee80211_bss_conf *info, u32 changed);
|
||||
int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, enum ieee80211_sta_state old_state,
|
||||
enum ieee80211_sta_state new_state);
|
||||
void (*sta_pre_rcu_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key);
|
||||
struct key_params *key);
|
||||
int (*ampdu_action)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_txq *txq);
|
||||
bool (*can_aggregate_in_amsdu)(struct ieee80211_hw *hw, struct sk_buff *head, struct sk_buff *skb);
|
||||
struct ieee80211_sta *sta, u16 action, u16 tid, u16 ssn);
|
||||
void (*sw_scan_start)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac_addr);
|
||||
void (*sw_scan_complete)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_scan_request *req);
|
||||
void (*cancel_hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
u64 (*prepare_multicast)(struct ieee80211_hw *hw, void *mc_list);
|
||||
void (*configure_filter)(struct ieee80211_hw *hw, u32 changed_flags,
|
||||
u32 *total_flags, u64 multicast);
|
||||
int (*sched_scan_start)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *req);
|
||||
void (*sched_scan_stop)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop);
|
||||
void (*flush_sta)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta);
|
||||
void (*configure_filter)(struct ieee80211_hw *hw, u32 changed_flags, u32 *total_flags, u64 multicast);
|
||||
u64 (*prepare_multicast)(struct ieee80211_hw *hw, void *mc_list);
|
||||
int (*conf_tx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 link_id, u8 ac, void *params);
|
||||
int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
|
||||
int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
|
||||
int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
|
||||
void (*sta_statistics)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, void *sinfo);
|
||||
void (*link_sta_rc_update)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_link_sta *link_sta);
|
||||
void (*mgd_prepare_tx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *info);
|
||||
void (*mgd_complete_tx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *info);
|
||||
void (*sync_rx_queues)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
void (*reconfig_complete)(struct ieee80211_hw *hw, u32 flags);
|
||||
void (*restart_complete)(struct ieee80211_hw *hw);
|
||||
int (*add_chanctx)(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx);
|
||||
void (*remove_chanctx)(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx);
|
||||
void (*change_chanctx)(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed);
|
||||
int (*assign_vif_chanctx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *ctx);
|
||||
void (*unassign_vif_chanctx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *ctx);
|
||||
void (*switch_vif_chanctx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_chanctx_conf **old, struct ieee80211_chanctx_conf **nw, u32 n);
|
||||
int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf);
|
||||
void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf);
|
||||
bool (*tx_last_beacon)(struct ieee80211_hw *hw);
|
||||
};
|
||||
|
||||
#define IEEE80211_RECONFIG_TYPE_TIMER 0
|
||||
#define IEEE80211_RECONFIG_TYPE_ARP_FILTER 1
|
||||
#define BSS_CHANGED_ASSOC (1U << 0)
|
||||
#define BSS_CHANGED_BSSID (1U << 1)
|
||||
#define BSS_CHANGED_ERP_CTS_PROT (1U << 2)
|
||||
#define BSS_CHANGED_HT (1U << 3)
|
||||
#define BSS_CHANGED_BASIC_RATES (1U << 4)
|
||||
#define BSS_CHANGED_BEACON_INT (1U << 5)
|
||||
#define BSS_CHANGED_BANDWIDTH (1U << 6)
|
||||
|
||||
extern struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, const void *ops, const char *requested_name);
|
||||
extern struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
|
||||
const void *ops,
|
||||
const char *requested_name);
|
||||
extern void ieee80211_free_hw(struct ieee80211_hw *hw);
|
||||
extern int ieee80211_register_hw(struct ieee80211_hw *hw);
|
||||
extern void ieee80211_unregister_hw(struct ieee80211_hw *hw);
|
||||
@@ -291,16 +136,11 @@ extern void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted);
|
||||
extern void ieee80211_connection_loss(struct ieee80211_vif *vif);
|
||||
extern int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid, u16 timeout);
|
||||
extern int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid);
|
||||
extern int ieee80211_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u32 old_state, u32 new_state);
|
||||
extern int ieee80211_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u32 old_state, u32 new_state);
|
||||
extern struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, const u8 *addr);
|
||||
extern void ieee80211_beacon_loss(struct ieee80211_vif *vif);
|
||||
extern void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
extern size_t ieee80211_rx_drain(struct ieee80211_hw *hw);
|
||||
extern void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
extern void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
|
||||
extern void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
|
||||
extern struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb);
|
||||
|
||||
#define ieee80211_alloc_hw(priv, ops) ieee80211_alloc_hw_nm(priv, ops, KBUILD_MODNAME)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,6 @@ fn main() {
|
||||
cc::Build::new()
|
||||
.file("src/linux_port.c")
|
||||
.file("src/linux_mvm.c")
|
||||
.file("src/linux_mld.c")
|
||||
.include(linux_kpi_headers)
|
||||
.warnings(true)
|
||||
.compile("redbear_iwlwifi_linux_port");
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "../../../linux-kpi/source/src/c_headers/linux/jiffies.h"
|
||||
#include "../../../linux-kpi/source/src/c_headers/linux/kernel.h"
|
||||
#include "linux_mvm.h"
|
||||
#include "linux_mld.h"
|
||||
#include "../../../linux-kpi/source/src/c_headers/linux/list.h"
|
||||
#include "../../../linux-kpi/source/src/c_headers/linux/mutex.h"
|
||||
#include "../../../linux-kpi/source/src/c_headers/linux/netdevice.h"
|
||||
@@ -268,8 +267,6 @@ struct iwl_trans_pcie {
|
||||
|
||||
/* Device family info */
|
||||
int device_family;
|
||||
int opmode;
|
||||
struct rb_iwl_mld mld_state;
|
||||
const char *fw_name;
|
||||
const char *pnvm_name;
|
||||
|
||||
@@ -1056,9 +1053,6 @@ static int rb_iwlwifi_probe_transport(struct iwl_trans_pcie *trans, unsigned int
|
||||
}
|
||||
|
||||
trans->device_family = rb_iwlwifi_family_from_device(trans->pci_dev, bz_family);
|
||||
trans->opmode = rb_iwl_opmode_for_family(trans->device_family == RB_IWL_DEVICE_FAMILY_BZ);
|
||||
if (trans->opmode == RB_IWL_OPMODE_MLD)
|
||||
rb_iwl_mld_init(&trans->mld_state);
|
||||
access_req = trans->device_family == RB_IWL_DEVICE_FAMILY_BZ ?
|
||||
IWL_CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ :
|
||||
IWL_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ;
|
||||
@@ -1533,12 +1527,6 @@ static void iwl_pcie_rx_handle(struct iwl_trans_pcie *trans)
|
||||
rb_iwl_mvm_extract_signal(buf->addr, buf->size, desc_fmt, &mvm_info);
|
||||
if (mvm_info.signal != 0) {
|
||||
rx_status.signal = mvm_info.signal;
|
||||
|
||||
if (trans->opmode == RB_IWL_OPMODE_MLD) {
|
||||
struct rb_iwl_mld_rx_mpdu_info mpdu;
|
||||
if (rb_iwl_mld_parse_rx_mpdu(buf->addr, buf->size, &mpdu) == 0)
|
||||
trans->mld_state.rx_frames++;
|
||||
}
|
||||
rx_status.rate_idx = rb_iwl_mvm_rs_select(&trans->rs_state, mvm_info.signal);
|
||||
} else {
|
||||
rx_status.signal = -42;
|
||||
@@ -2182,9 +2170,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
trans->device_family = rb_iwlwifi_family_from_device(pdev, 0);
|
||||
trans->opmode = rb_iwl_opmode_for_family(trans->device_family == RB_IWL_DEVICE_FAMILY_BZ);
|
||||
if (trans->opmode == RB_IWL_OPMODE_MLD)
|
||||
rb_iwl_mld_init(&trans->mld_state);
|
||||
pdev->driver_data = trans;
|
||||
return 0;
|
||||
}
|
||||
@@ -2230,10 +2215,8 @@ static void rb_iwlwifi_status_line(struct iwl_trans_pcie *trans, char *out, unsi
|
||||
{
|
||||
rb_iwlwifi_format_out(
|
||||
out, out_len,
|
||||
"linux_kpi_status=ok family=%s opmode=%s mld_rx=%u prepared=%d probed=%d init=%d active=%d fw_running=%d mac80211=%d irq=%d vectors=%d msix=%d tx_queues=%d rx_in_use=%u scan_results=%u connected=%d ssid=%s",
|
||||
"linux_kpi_status=ok family=%s prepared=%d probed=%d init=%d active=%d fw_running=%d mac80211=%d irq=%d vectors=%d msix=%d tx_queues=%d rx_in_use=%u scan_results=%u connected=%d ssid=%s",
|
||||
rb_iwlwifi_family_name(trans->device_family),
|
||||
rb_iwl_opmode_name(trans->opmode),
|
||||
trans->opmode == RB_IWL_OPMODE_MLD ? rb_iwl_mld_rx_frames(&trans->mld_state) : 0,
|
||||
trans->prepared,
|
||||
trans->transport_probed,
|
||||
trans->transport_inited,
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
//! MLD station management — Rust port of Linux mld/sta.c + sta.h
|
||||
//!
|
||||
//! Ported from Linux 7.1 drivers/net/wireless/intel/iwlwifi/mld/sta.c
|
||||
//! Reference: all firmware command structures from fw/api/mac-cfg.h,
|
||||
//! fw/api/sta.h, fw/api/datapath.h.
|
||||
|
||||
use super::*;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
// ── Station types (Linux mld/sta.h) ───────────────────────────────
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MldLinkSta {
|
||||
pub fw_id: u32,
|
||||
pub mac_addr: [u8; 6],
|
||||
pub link_id: u16,
|
||||
pub sta_state: u32,
|
||||
pub ht_cap: u32,
|
||||
pub vht_cap: u32,
|
||||
pub he_supported: bool,
|
||||
pub eht_supported: bool,
|
||||
pub max_amsdu_len: u32,
|
||||
pub mpdu_counters: [u64; 8],
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct MldSta {
|
||||
pub sta_id: u32,
|
||||
pub mld_addr: [u8; 6],
|
||||
pub is_mld: bool,
|
||||
pub valid_links: u16,
|
||||
pub sta_state: u32,
|
||||
pub deflink: MldLinkSta,
|
||||
pub links: Vec<Option<MldLinkSta>>,
|
||||
}
|
||||
|
||||
impl MldSta {
|
||||
pub fn new(sta_id: u32, mld_addr: [u8; 6]) -> Self {
|
||||
let mut links = vec![None; super::MAX_LINKS + 1];
|
||||
links[0] = Some(MldLinkSta::default());
|
||||
Self {
|
||||
sta_id,
|
||||
mld_addr,
|
||||
is_mld: false,
|
||||
valid_links: 1,
|
||||
sta_state: 0,
|
||||
deflink: MldLinkSta::default(),
|
||||
links,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fw_sta_id(&self) -> u32 {
|
||||
self.deflink.fw_id
|
||||
}
|
||||
|
||||
pub fn for_each_active_link<F: FnMut(&MldLinkSta)>(&self, mut f: F) {
|
||||
f(&self.deflink);
|
||||
for link in self.links.iter().flatten() {
|
||||
if link.link_id != 0 {
|
||||
f(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Station management functions (Linux mld/sta.c) ─────────────────
|
||||
|
||||
pub const STATION_TYPE_BSS: u32 = 0;
|
||||
pub const STATION_TYPE_PEER: u32 = 1;
|
||||
pub const STATION_TYPE_AUX: u32 = 2;
|
||||
|
||||
impl MldState {
|
||||
pub fn add_sta_full(
|
||||
&mut self,
|
||||
sta: &MldSta,
|
||||
link_addr: &[u8; 6],
|
||||
aid: u16,
|
||||
mfp: bool,
|
||||
) -> Result<u32, MldError> {
|
||||
let cmd = build_sta_config(sta.sta_id, &sta.mld_addr, link_addr, aid, mfp);
|
||||
let bytes = unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
&cmd as *const StaCfgCmd as *const u8,
|
||||
core::mem::size_of::<StaCfgCmd>(),
|
||||
)
|
||||
};
|
||||
self.send_hcmd(CMD_STA_CONFIG, bytes)?;
|
||||
Ok(sta.sta_id)
|
||||
}
|
||||
|
||||
pub fn remove_sta_full(&mut self, sta_id: u32) -> Result<(), MldError> {
|
||||
let cmd = build_remove_sta(sta_id);
|
||||
let bytes = unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
&cmd as *const RemoveStaCmd as *const u8,
|
||||
core::mem::size_of::<RemoveStaCmd>(),
|
||||
)
|
||||
};
|
||||
self.send_hcmd(CMD_STA_REMOVE, bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disable_tx_to_sta(&mut self, sta_id: u32, disable: bool) -> Result<(), MldError> {
|
||||
let cmd = build_disable_tx(sta_id, disable);
|
||||
let bytes = unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
&cmd as *const StaDisableTxCmd as *const u8,
|
||||
core::mem::size_of::<StaDisableTxCmd>(),
|
||||
)
|
||||
};
|
||||
self.send_hcmd(CMD_STA_DISABLE_TX, bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_aux_sta(&mut self, sta_id: u32, mac_addr: &[u8; 6]) -> Result<(), MldError> {
|
||||
let cmd = build_aux_sta(sta_id, mac_addr);
|
||||
let bytes = unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
&cmd as *const AuxStaCmd as *const u8,
|
||||
core::mem::size_of::<AuxStaCmd>(),
|
||||
)
|
||||
};
|
||||
self.send_hcmd(CMD_AUX_STA, bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn flush_sta_txqs(&mut self, _fw_sta_id: u32) -> Result<(), MldError> {
|
||||
self.callback_flush(0xffff, false)
|
||||
}
|
||||
|
||||
pub fn update_all_link_stations(&mut self) -> Result<(), MldError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// ── Tests ─────────────────────────────────────────────────────────
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn mld_sta_creation() {
|
||||
let sta = MldSta::new(3, [1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(sta.sta_id, 3);
|
||||
assert!(!sta.is_mld);
|
||||
assert_eq!(sta.valid_links, 1);
|
||||
assert!(sta.links[0].is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mld_sta_for_each_link() {
|
||||
let mut sta = MldSta::new(1, [0; 6]);
|
||||
sta.links[1] = Some(MldLinkSta {
|
||||
fw_id: 2,
|
||||
link_id: 1,
|
||||
..Default::default()
|
||||
});
|
||||
let mut count = 0;
|
||||
sta.for_each_active_link(|_| count += 1);
|
||||
assert_eq!(count, 2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user