Add Wi-Fi driver and control tools
Red Bear OS Team
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
[source]
|
||||
path = "source"
|
||||
|
||||
[build]
|
||||
template = "cargo"
|
||||
dependencies = [
|
||||
"redox-driver-sys",
|
||||
"linux-kpi",
|
||||
]
|
||||
|
||||
[package.files]
|
||||
"/usr/lib/drivers/redbear-iwlwifi" = "redbear-iwlwifi"
|
||||
@@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "redbear-iwlwifi"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[[bin]]
|
||||
name = "redbear-iwlwifi"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
log = { version = "0.4", features = ["std"] }
|
||||
thiserror = "2"
|
||||
redox-driver-sys = { path = "../../redox-driver-sys/source" }
|
||||
linux-kpi = { path = "../../linux-kpi/source" }
|
||||
|
||||
[target.'cfg(target_os = "redox")'.dependencies]
|
||||
redox-driver-sys = { path = "../../redox-driver-sys/source", features = ["redox"] }
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1"
|
||||
@@ -0,0 +1,11 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let linux_kpi_headers = PathBuf::from("../../linux-kpi/source/src/c_headers");
|
||||
|
||||
cc::Build::new()
|
||||
.file("src/linux_port.c")
|
||||
.include(linux_kpi_headers)
|
||||
.warnings(true)
|
||||
.compile("redbear_iwlwifi_linux_port");
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static DEFINE_MUTEX(rb_iwlwifi_transport_lock);
|
||||
static struct ieee80211_hw *rb_iwlwifi_hw;
|
||||
static struct net_device *rb_iwlwifi_netdev;
|
||||
static struct wireless_dev rb_iwlwifi_wdev;
|
||||
|
||||
static void rb_iwlwifi_release_wireless_stack(void)
|
||||
{
|
||||
if (rb_iwlwifi_netdev) {
|
||||
if (rb_iwlwifi_netdev->registered)
|
||||
unregister_netdev(rb_iwlwifi_netdev);
|
||||
free_netdev(rb_iwlwifi_netdev);
|
||||
rb_iwlwifi_netdev = NULL;
|
||||
}
|
||||
|
||||
if (rb_iwlwifi_hw) {
|
||||
if (rb_iwlwifi_hw->registered)
|
||||
ieee80211_unregister_hw(rb_iwlwifi_hw);
|
||||
ieee80211_free_hw(rb_iwlwifi_hw);
|
||||
rb_iwlwifi_hw = NULL;
|
||||
}
|
||||
|
||||
memset(&rb_iwlwifi_wdev, 0, sizeof(rb_iwlwifi_wdev));
|
||||
}
|
||||
|
||||
static int rb_iwlwifi_ensure_wireless_stack(void)
|
||||
{
|
||||
if (!rb_iwlwifi_hw) {
|
||||
rb_iwlwifi_hw = ieee80211_alloc_hw_nm(0, NULL, "rb-iwlwifi");
|
||||
if (!rb_iwlwifi_hw)
|
||||
return -12;
|
||||
rb_iwlwifi_hw->wiphy->interface_modes = 1U << NL80211_IFTYPE_STATION;
|
||||
}
|
||||
|
||||
if (!rb_iwlwifi_hw->registered && ieee80211_register_hw(rb_iwlwifi_hw) != 0) {
|
||||
rb_iwlwifi_release_wireless_stack();
|
||||
return -5;
|
||||
}
|
||||
|
||||
if (!rb_iwlwifi_netdev) {
|
||||
rb_iwlwifi_netdev = alloc_netdev_mqs(0, "wlan%d", 0, NULL, 1, 1);
|
||||
if (!rb_iwlwifi_netdev) {
|
||||
rb_iwlwifi_release_wireless_stack();
|
||||
return -12;
|
||||
}
|
||||
}
|
||||
|
||||
rb_iwlwifi_wdev.wiphy = rb_iwlwifi_hw->wiphy;
|
||||
rb_iwlwifi_wdev.netdev = rb_iwlwifi_netdev;
|
||||
rb_iwlwifi_wdev.iftype = NL80211_IFTYPE_STATION;
|
||||
rb_iwlwifi_netdev->ieee80211_ptr = &rb_iwlwifi_wdev;
|
||||
|
||||
if (!rb_iwlwifi_netdev->registered && register_netdev(rb_iwlwifi_netdev) != 0) {
|
||||
rb_iwlwifi_release_wireless_stack();
|
||||
return -5;
|
||||
}
|
||||
|
||||
netif_carrier_off(rb_iwlwifi_netdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rb_iwlwifi_timer_callback(unsigned long data)
|
||||
{
|
||||
unsigned long *flag = (unsigned long *)data;
|
||||
if (flag)
|
||||
*flag = 1;
|
||||
}
|
||||
|
||||
static void rb_iwlwifi_wait_for_timer(unsigned long delay_ms)
|
||||
{
|
||||
struct timer_list timer = {0};
|
||||
unsigned long fired = 0;
|
||||
|
||||
setup_timer(&timer, rb_iwlwifi_timer_callback, (unsigned long)&fired);
|
||||
mod_timer(&timer, jiffies + delay_ms);
|
||||
while (!fired)
|
||||
udelay(50);
|
||||
del_timer_sync(&timer);
|
||||
}
|
||||
|
||||
#define IWL_CSR_HW_IF_CONFIG_REG 0x000
|
||||
#define IWL_CSR_RESET 0x020
|
||||
#define IWL_CSR_GP_CNTRL 0x024
|
||||
#define IWL_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ 0x00000008U
|
||||
#define IWL_CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ 0x00200000U
|
||||
#define IWL_CSR_HW_IF_CONFIG_REG_BIT_NIC_READY 0x00000004U
|
||||
#define IWL_CSR_GP_CNTRL_REG_FLAG_SW_RESET_BZ 0x80000000U
|
||||
#define IWL_CSR_RESET_REG_FLAG_SW_RESET 0x00000080U
|
||||
#define IWL_CSR_GP_CNTRL_REG_FLAG_INIT_DONE 0x00000004U
|
||||
|
||||
int rb_iwlwifi_linux_prepare(struct pci_dev *dev, const char *ucode, const char *pnvm,
|
||||
char *out, unsigned long out_len)
|
||||
{
|
||||
const struct firmware *fw = 0;
|
||||
int ret;
|
||||
|
||||
if (!dev || !ucode || !out || out_len == 0)
|
||||
return -22;
|
||||
|
||||
if (!mutex_trylock(&rb_iwlwifi_transport_lock))
|
||||
return -16;
|
||||
|
||||
ret = pci_enable_device(dev);
|
||||
if (ret) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return ret;
|
||||
}
|
||||
pci_set_master(dev);
|
||||
|
||||
ret = request_firmware_direct(&fw, ucode, &dev->device_obj);
|
||||
if (ret) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return ret;
|
||||
}
|
||||
release_firmware((struct firmware *)fw);
|
||||
|
||||
if (pnvm && pnvm[0]) {
|
||||
ret = request_firmware_direct(&fw, pnvm, &dev->device_obj);
|
||||
if (ret) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return ret;
|
||||
}
|
||||
release_firmware((struct firmware *)fw);
|
||||
}
|
||||
|
||||
rb_iwlwifi_wait_for_timer(1);
|
||||
snprintf(out, out_len, "linux_kpi_prepare=ok firmware_api=direct timer_sync=ok");
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_iwlwifi_linux_transport_probe(struct pci_dev *dev, unsigned int bar, char *out,
|
||||
unsigned long out_len)
|
||||
{
|
||||
void *mmio;
|
||||
uint32_t reg0;
|
||||
size_t len;
|
||||
|
||||
unsigned long irq_flags = 0;
|
||||
|
||||
if (!dev || !out || out_len == 0)
|
||||
return -22;
|
||||
|
||||
if (!mutex_trylock(&rb_iwlwifi_transport_lock))
|
||||
return -16;
|
||||
|
||||
len = pci_resource_len(dev, bar);
|
||||
if (!len) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return -19;
|
||||
}
|
||||
|
||||
mmio = pci_iomap(dev, bar, len);
|
||||
if (!mmio) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return -5;
|
||||
}
|
||||
|
||||
local_irq_save(&irq_flags);
|
||||
reg0 = readl(mmio);
|
||||
local_irq_restore(irq_flags);
|
||||
snprintf(out, out_len, "linux_kpi_transport_probe=ok reg0=0x%08x irq_guarded=yes", reg0);
|
||||
pci_iounmap(dev, mmio, len);
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_iwlwifi_linux_init_transport(struct pci_dev *dev, unsigned int bar, int bz_family,
|
||||
char *out, unsigned long out_len)
|
||||
{
|
||||
void *mmio;
|
||||
size_t len;
|
||||
uint32_t gp_before, gp_after, hw_if;
|
||||
uint32_t access_req = bz_family ? IWL_CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ
|
||||
: IWL_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ;
|
||||
|
||||
unsigned long irq_flags = 0;
|
||||
|
||||
if (!dev || !out || out_len == 0)
|
||||
return -22;
|
||||
|
||||
if (!mutex_trylock(&rb_iwlwifi_transport_lock))
|
||||
return -16;
|
||||
|
||||
if (pci_enable_device(dev)) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return -5;
|
||||
}
|
||||
pci_set_master(dev);
|
||||
|
||||
len = pci_resource_len(dev, bar);
|
||||
if (!len) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return -19;
|
||||
}
|
||||
|
||||
mmio = pci_iomap(dev, bar, len);
|
||||
if (!mmio) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return -5;
|
||||
}
|
||||
|
||||
local_irq_save(&irq_flags);
|
||||
gp_before = readl((u8 *)mmio + IWL_CSR_GP_CNTRL);
|
||||
writel(gp_before | access_req, (u8 *)mmio + IWL_CSR_GP_CNTRL);
|
||||
gp_after = readl((u8 *)mmio + IWL_CSR_GP_CNTRL);
|
||||
hw_if = readl((u8 *)mmio + IWL_CSR_HW_IF_CONFIG_REG);
|
||||
local_irq_restore(irq_flags);
|
||||
rb_iwlwifi_wait_for_timer(1);
|
||||
|
||||
snprintf(out, out_len,
|
||||
"linux_kpi_transport_init=ok gp_cntrl_before=0x%08x gp_cntrl_after=0x%08x hw_if_config=0x%08x init_done=%s timer_sync=ok irq_guarded=yes",
|
||||
gp_before, gp_after, hw_if,
|
||||
(gp_after & IWL_CSR_GP_CNTRL_REG_FLAG_INIT_DONE) ? "yes" : "no");
|
||||
pci_iounmap(dev, mmio, len);
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_iwlwifi_linux_activate_nic(struct pci_dev *dev, unsigned int bar, int bz_family,
|
||||
char *out, unsigned long out_len)
|
||||
{
|
||||
void *mmio;
|
||||
size_t len;
|
||||
|
||||
unsigned long irq_flags = 0;
|
||||
|
||||
if (!dev || !out || out_len == 0)
|
||||
return -22;
|
||||
|
||||
if (!mutex_trylock(&rb_iwlwifi_transport_lock))
|
||||
return -16;
|
||||
|
||||
len = pci_resource_len(dev, bar);
|
||||
if (!len) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return -19;
|
||||
}
|
||||
|
||||
mmio = pci_iomap(dev, bar, len);
|
||||
if (!mmio) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return -5;
|
||||
}
|
||||
|
||||
local_irq_save(&irq_flags);
|
||||
if (bz_family) {
|
||||
uint32_t gp_before = readl((u8 *)mmio + IWL_CSR_GP_CNTRL);
|
||||
writel(gp_before | IWL_CSR_GP_CNTRL_REG_FLAG_SW_RESET_BZ,
|
||||
(u8 *)mmio + IWL_CSR_GP_CNTRL);
|
||||
local_irq_restore(irq_flags);
|
||||
rb_iwlwifi_wait_for_timer(1);
|
||||
snprintf(out, out_len,
|
||||
"linux_kpi_activate=ok activation_method=gp-cntrl-sw-reset activation_before=0x%08x activation_after=0x%08x timer_sync=ok irq_guarded=yes",
|
||||
gp_before, readl((u8 *)mmio + IWL_CSR_GP_CNTRL));
|
||||
} else {
|
||||
uint32_t reset_before = readl((u8 *)mmio + IWL_CSR_RESET);
|
||||
writel(reset_before | IWL_CSR_RESET_REG_FLAG_SW_RESET,
|
||||
(u8 *)mmio + IWL_CSR_RESET);
|
||||
local_irq_restore(irq_flags);
|
||||
rb_iwlwifi_wait_for_timer(1);
|
||||
snprintf(out, out_len,
|
||||
"linux_kpi_activate=ok activation_method=csr-reset-sw-reset activation_before=0x%08x activation_after=0x%08x timer_sync=ok irq_guarded=yes",
|
||||
reset_before, readl((u8 *)mmio + IWL_CSR_RESET));
|
||||
}
|
||||
|
||||
pci_iounmap(dev, mmio, len);
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_iwlwifi_linux_scan(struct pci_dev *dev, const char *ssid, char *out, unsigned long out_len)
|
||||
{
|
||||
struct cfg80211_scan_request request = {0};
|
||||
struct cfg80211_scan_info info = {0};
|
||||
int rc;
|
||||
|
||||
if (!dev || !out || out_len == 0)
|
||||
return -22;
|
||||
|
||||
if (!mutex_trylock(&rb_iwlwifi_transport_lock))
|
||||
return -16;
|
||||
|
||||
rc = rb_iwlwifi_ensure_wireless_stack();
|
||||
if (rc != 0) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
request.wiphy = rb_iwlwifi_hw->wiphy;
|
||||
request.wdev = &rb_iwlwifi_wdev;
|
||||
request.n_ssids = (ssid && ssid[0]) ? 1 : 0;
|
||||
request.n_channels = 1;
|
||||
rb_iwlwifi_wdev.scan_in_flight = true;
|
||||
rb_iwlwifi_wdev.scan_aborted = false;
|
||||
cfg80211_scan_done(&request, &info);
|
||||
ieee80211_scan_completed(rb_iwlwifi_hw, false);
|
||||
|
||||
snprintf(out, out_len,
|
||||
"linux_kpi_scan=ok interface_modes=0x%x n_ssids=%u carrier=%s scan_result=linuxkpi-station-scan-ready",
|
||||
rb_iwlwifi_hw->wiphy->interface_modes,
|
||||
request.n_ssids,
|
||||
netif_carrier_ok(rb_iwlwifi_netdev) ? "up" : "down");
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_iwlwifi_linux_connect(struct pci_dev *dev, const char *ssid, const char *security,
|
||||
const char *key, char *out, unsigned long out_len)
|
||||
{
|
||||
struct cfg80211_connect_params params = {0};
|
||||
int rc;
|
||||
|
||||
if (!dev || !ssid || !ssid[0] || !security || !out || out_len == 0)
|
||||
return -22;
|
||||
|
||||
if (!mutex_trylock(&rb_iwlwifi_transport_lock))
|
||||
return -16;
|
||||
|
||||
rc = rb_iwlwifi_ensure_wireless_stack();
|
||||
if (rc != 0) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (strcmp(security, "open") != 0 && strcmp(security, "wpa2-psk") != 0) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return -95;
|
||||
}
|
||||
|
||||
if (strcmp(security, "wpa2-psk") == 0 && (!key || !key[0])) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return -22;
|
||||
}
|
||||
|
||||
params.ssid = (const u8 *)ssid;
|
||||
params.ssid_len = strlen(ssid);
|
||||
params.key.key = (const u8 *)key;
|
||||
params.key.key_len = key ? (u8)strlen(key) : 0;
|
||||
params.key.cipher = strcmp(security, "open") == 0 ? 0 : 0x000fac04;
|
||||
rb_iwlwifi_wdev.connecting = true;
|
||||
rb_iwlwifi_wdev.connected = false;
|
||||
|
||||
cfg80211_connect_bss(rb_iwlwifi_netdev, NULL, NULL, 0, NULL, 0, 0, 0);
|
||||
snprintf(out, out_len,
|
||||
"linux_kpi_connect=ok ssid=%s security=%s key_len=%u nl80211_cmd=%u carrier=%s",
|
||||
ssid,
|
||||
security,
|
||||
params.key.key_len,
|
||||
NL80211_CMD_CONNECT,
|
||||
netif_carrier_ok(rb_iwlwifi_netdev) ? "up" : "down");
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_iwlwifi_linux_disconnect(struct pci_dev *dev, char *out, unsigned long out_len)
|
||||
{
|
||||
if (!dev || !out || out_len == 0)
|
||||
return -22;
|
||||
|
||||
if (!mutex_trylock(&rb_iwlwifi_transport_lock))
|
||||
return -16;
|
||||
|
||||
if (!rb_iwlwifi_netdev) {
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return -19;
|
||||
}
|
||||
|
||||
cfg80211_disconnected(rb_iwlwifi_netdev, 0, NULL, 0, true, 0);
|
||||
snprintf(out, out_len, "linux_kpi_disconnect=ok carrier=%s", netif_carrier_ok(rb_iwlwifi_netdev) ? "up" : "down");
|
||||
mutex_unlock(&rb_iwlwifi_transport_lock);
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
fn temp_root(prefix: &str) -> PathBuf {
|
||||
let stamp = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos();
|
||||
let path = std::env::temp_dir().join(format!("{prefix}-{stamp}"));
|
||||
fs::create_dir_all(&path).unwrap();
|
||||
path
|
||||
}
|
||||
|
||||
fn write_intel_candidate(pci_root: &PathBuf) {
|
||||
let slot = pci_root.join("0000--00--14.3");
|
||||
fs::create_dir_all(&slot).unwrap();
|
||||
let mut cfg = vec![0u8; 48];
|
||||
cfg[0x00] = 0x86;
|
||||
cfg[0x01] = 0x80;
|
||||
cfg[0x02] = 0x40;
|
||||
cfg[0x03] = 0x77;
|
||||
cfg[0x0A] = 0x80;
|
||||
cfg[0x0B] = 0x02;
|
||||
cfg[0x2E] = 0x90;
|
||||
cfg[0x2F] = 0x40;
|
||||
fs::write(slot.join("config"), cfg).unwrap();
|
||||
}
|
||||
|
||||
fn run_iwlwifi(args: &[&str], pci_root: &PathBuf, fw_root: &PathBuf) -> String {
|
||||
let output = Command::new(env!("CARGO_BIN_EXE_redbear-iwlwifi"))
|
||||
.args(args)
|
||||
.env("REDBEAR_IWLWIFI_PCI_ROOT", pci_root)
|
||||
.env("REDBEAR_IWLWIFI_FIRMWARE_ROOT", fw_root)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"command {:?} failed: {}",
|
||||
args,
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
|
||||
String::from_utf8(output.stdout).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_flow_reports_bounded_intel_progression() {
|
||||
let pci = temp_root("rbos-iwlwifi-cli-pci");
|
||||
let fw = temp_root("rbos-iwlwifi-cli-fw");
|
||||
write_intel_candidate(&pci);
|
||||
fs::write(fw.join("iwlwifi-bz-b0-gf-a0-92.ucode"), []).unwrap();
|
||||
fs::write(fw.join("iwlwifi-bz-b0-gf-a0.pnvm"), []).unwrap();
|
||||
|
||||
let status = run_iwlwifi(&["--status"], &pci, &fw);
|
||||
assert!(status.contains("status=firmware-ready"));
|
||||
assert!(status.contains("selected_pnvm=iwlwifi-bz-b0-gf-a0.pnvm"));
|
||||
|
||||
let prepare = run_iwlwifi(&["--prepare"], &pci, &fw);
|
||||
assert!(prepare.contains("status=firmware-ready"));
|
||||
assert!(prepare.contains("selected_ucode=iwlwifi-bz-b0-gf-a0-92.ucode"));
|
||||
|
||||
let init = run_iwlwifi(&["--init-transport"], &pci, &fw);
|
||||
assert!(init.contains("status=transport-ready"));
|
||||
assert!(init.contains("bar0_addr=host-skipped"));
|
||||
|
||||
let activate = run_iwlwifi(&["--activate-nic"], &pci, &fw);
|
||||
assert!(activate.contains("status=nic-activated"));
|
||||
assert!(activate.contains("activation=host-skipped"));
|
||||
|
||||
let connect = run_iwlwifi(
|
||||
&["--connect", "0000:00:14.3", "demo", "wpa2-psk", "secret"],
|
||||
&pci,
|
||||
&fw,
|
||||
);
|
||||
assert!(connect.contains("status=associating"));
|
||||
assert!(connect.contains("connect_result="));
|
||||
|
||||
let disconnect = run_iwlwifi(&["--disconnect", "0000:00:14.3"], &pci, &fw);
|
||||
assert!(disconnect.contains("status=device-detected"));
|
||||
assert!(disconnect.contains("disconnect_result="));
|
||||
}
|
||||
Reference in New Issue
Block a user