From 30b7800f9ae0a7f26e292dbe55cc67fbe2d1b131 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 11 Jul 2022 05:19:31 +0200 Subject: [PATCH] add event printing, add join but not working yet. --- Cargo.toml | 1 + examples/rpi-pico-w/src/main.rs | 3 + src/events.rs | 281 ++++++++++++++++++++++++++++++++ src/lib.rs | 80 ++++++++- src/structs.rs | 55 ++++++- 5 files changed, 414 insertions(+), 6 deletions(-) create mode 100644 src/events.rs diff --git a/Cargo.toml b/Cargo.toml index d1672146..bd27a48b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,4 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" } embedded-hal-async = { version = "0.1.0-alpha.1" } +num_enum = { version = "0.5.7", default-features = false } diff --git a/examples/rpi-pico-w/src/main.rs b/examples/rpi-pico-w/src/main.rs index 7545dfde..d4aae847 100644 --- a/examples/rpi-pico-w/src/main.rs +++ b/examples/rpi-pico-w/src/main.rs @@ -45,4 +45,7 @@ async fn main(spawner: Spawner, p: Peripherals) { spawner.spawn(wifi_task(runner)).unwrap(); control.init().await; + + let ssid = "MikroTik-951589"; + control.join(ssid).await; } diff --git a/src/events.rs b/src/events.rs new file mode 100644 index 00000000..b35b12fa --- /dev/null +++ b/src/events.rs @@ -0,0 +1,281 @@ +#![allow(unused)] + +use core::num; + +#[derive(Clone, Copy, PartialEq, Eq, num_enum::FromPrimitive)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(u8)] +pub enum Event { + #[num_enum(default)] + Unknown = 0xFF, + /// indicates status of set SSID + SET_SSID = 0, + /// differentiates join IBSS from found (START) IBSS + JOIN = 1, + /// STA founded an IBSS or AP started a BSS + START = 2, + /// 802.11 AUTH request + AUTH = 3, + /// 802.11 AUTH indication + AUTH_IND = 4, + /// 802.11 DEAUTH request + DEAUTH = 5, + /// 802.11 DEAUTH indication + DEAUTH_IND = 6, + /// 802.11 ASSOC request + ASSOC = 7, + /// 802.11 ASSOC indication + ASSOC_IND = 8, + /// 802.11 REASSOC request + REASSOC = 9, + /// 802.11 REASSOC indication + REASSOC_IND = 10, + /// 802.11 DISASSOC request + DISASSOC = 11, + /// 802.11 DISASSOC indication + DISASSOC_IND = 12, + /// 802.11h Quiet period started + QUIET_START = 13, + /// 802.11h Quiet period ended + QUIET_END = 14, + /// BEACONS received/lost indication + BEACON_RX = 15, + /// generic link indication + LINK = 16, + /// TKIP MIC error occurred + MIC_ERROR = 17, + /// NDIS style link indication + NDIS_LINK = 18, + /// roam attempt occurred: indicate status & reason + ROAM = 19, + /// change in dot11FailedCount (txfail) + TXFAIL = 20, + /// WPA2 pmkid cache indication + PMKID_CACHE = 21, + /// current AP's TSF value went backward + RETROGRADE_TSF = 22, + /// AP was pruned from join list for reason + PRUNE = 23, + /// report AutoAuth table entry match for join attempt + AUTOAUTH = 24, + /// Event encapsulating an EAPOL message + EAPOL_MSG = 25, + /// Scan results are ready or scan was aborted + SCAN_COMPLETE = 26, + /// indicate to host addts fail/success + ADDTS_IND = 27, + /// indicate to host delts fail/success + DELTS_IND = 28, + /// indicate to host of beacon transmit + BCNSENT_IND = 29, + /// Send the received beacon up to the host + BCNRX_MSG = 30, + /// indicate to host loss of beacon + BCNLOST_MSG = 31, + /// before attempting to roam + ROAM_PREP = 32, + /// PFN network found event + PFN_NET_FOUND = 33, + /// PFN network lost event + PFN_NET_LOST = 34, + RESET_COMPLETE = 35, + JOIN_START = 36, + ROAM_START = 37, + ASSOC_START = 38, + IBSS_ASSOC = 39, + RADIO = 40, + /// PSM microcode watchdog fired + PSM_WATCHDOG = 41, + /// CCX association start + CCX_ASSOC_START = 42, + /// CCX association abort + CCX_ASSOC_ABORT = 43, + /// probe request received + PROBREQ_MSG = 44, + SCAN_CONFIRM_IND = 45, + /// WPA Handshake + PSK_SUP = 46, + COUNTRY_CODE_CHANGED = 47, + /// WMMAC excedded medium time + EXCEEDED_MEDIUM_TIME = 48, + /// WEP ICV error occurred + ICV_ERROR = 49, + /// Unsupported unicast encrypted frame + UNICAST_DECODE_ERROR = 50, + /// Unsupported multicast encrypted frame + MULTICAST_DECODE_ERROR = 51, + TRACE = 52, + /// BT-AMP HCI event + BTA_HCI_EVENT = 53, + /// I/F change (for wlan host notification) + IF = 54, + /// P2P Discovery listen state expires + P2P_DISC_LISTEN_COMPLETE = 55, + /// indicate RSSI change based on configured levels + RSSI = 56, + /// PFN best network batching event + PFN_BEST_BATCHING = 57, + EXTLOG_MSG = 58, + /// Action frame reception + ACTION_FRAME = 59, + /// Action frame Tx complete + ACTION_FRAME_COMPLETE = 60, + /// assoc request received + PRE_ASSOC_IND = 61, + /// re-assoc request received + PRE_REASSOC_IND = 62, + /// channel adopted (xxx: obsoleted) + CHANNEL_ADOPTED = 63, + /// AP started + AP_STARTED = 64, + /// AP stopped due to DFS + DFS_AP_STOP = 65, + /// AP resumed due to DFS + DFS_AP_RESUME = 66, + /// WAI stations event + WAI_STA_EVENT = 67, + /// event encapsulating an WAI message + WAI_MSG = 68, + /// escan result event + ESCAN_RESULT = 69, + /// action frame off channel complete + ACTION_FRAME_OFF_CHAN_COMPLETE = 70, + /// probe response received + PROBRESP_MSG = 71, + /// P2P Probe request received + P2P_PROBREQ_MSG = 72, + DCS_REQUEST = 73, + /// credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] + FIFO_CREDIT_MAP = 74, + /// Received action frame event WITH wl_event_rx_frame_data_t header + ACTION_FRAME_RX = 75, + /// Wake Event timer fired, used for wake WLAN test mode + WAKE_EVENT = 76, + /// Radio measurement complete + RM_COMPLETE = 77, + /// Synchronize TSF with the host + HTSFSYNC = 78, + /// request an overlay IOCTL/iovar from the host + OVERLAY_REQ = 79, + CSA_COMPLETE_IND = 80, + /// excess PM Wake Event to inform host + EXCESS_PM_WAKE_EVENT = 81, + /// no PFN networks around + PFN_SCAN_NONE = 82, + /// last found PFN network gets lost + PFN_SCAN_ALLGONE = 83, + GTK_PLUMBED = 84, + /// 802.11 ASSOC indication for NDIS only + ASSOC_IND_NDIS = 85, + /// 802.11 REASSOC indication for NDIS only + REASSOC_IND_NDIS = 86, + ASSOC_REQ_IE = 87, + ASSOC_RESP_IE = 88, + /// association recreated on resume + ASSOC_RECREATED = 89, + /// rx action frame event for NDIS only + ACTION_FRAME_RX_NDIS = 90, + /// authentication request received + AUTH_REQ = 91, + /// fast assoc recreation failed + SPEEDY_RECREATE_FAIL = 93, + /// port-specific event and payload (e.g. NDIS) + NATIVE = 94, + /// event for tx pkt delay suddently jump + PKTDELAY_IND = 95, + /// AWDL AW period starts + AWDL_AW = 96, + /// AWDL Master/Slave/NE master role event + AWDL_ROLE = 97, + /// Generic AWDL event + AWDL_EVENT = 98, + /// NIC AF txstatus + NIC_AF_TXS = 99, + /// NAN event + NAN = 100, + BEACON_FRAME_RX = 101, + /// desired service found + SERVICE_FOUND = 102, + /// GAS fragment received + GAS_FRAGMENT_RX = 103, + /// GAS sessions all complete + GAS_COMPLETE = 104, + /// New device found by p2p offload + P2PO_ADD_DEVICE = 105, + /// device has been removed by p2p offload + P2PO_DEL_DEVICE = 106, + /// WNM event to notify STA enter sleep mode + WNM_STA_SLEEP = 107, + /// Indication of MAC tx failures (exhaustion of 802.11 retries) exceeding threshold(s) + TXFAIL_THRESH = 108, + /// Proximity Detection event + PROXD = 109, + /// AWDL RX Probe response + AWDL_RX_PRB_RESP = 111, + /// AWDL RX Action Frames + AWDL_RX_ACT_FRAME = 112, + /// AWDL Wowl nulls + AWDL_WOWL_NULLPKT = 113, + /// AWDL Phycal status + AWDL_PHYCAL_STATUS = 114, + /// AWDL OOB AF status + AWDL_OOB_AF_STATUS = 115, + /// Interleaved Scan status + AWDL_SCAN_STATUS = 116, + /// AWDL AW Start + AWDL_AW_START = 117, + /// AWDL AW End + AWDL_AW_END = 118, + /// AWDL AW Extensions + AWDL_AW_EXT = 119, + AWDL_PEER_CACHE_CONTROL = 120, + CSA_START_IND = 121, + CSA_DONE_IND = 122, + CSA_FAILURE_IND = 123, + /// CCA based channel quality report + CCA_CHAN_QUAL = 124, + /// to report change in BSSID while roaming + BSSID = 125, + /// tx error indication + TX_STAT_ERROR = 126, + /// credit check for BCMC supported + BCMC_CREDIT_SUPPORT = 127, + /// psta primary interface indication + PSTA_PRIMARY_INTF_IND = 128, + /// Handover Request Initiated + BT_WIFI_HANDOVER_REQ = 130, + /// Southpaw TxInhibit notification + SPW_TXINHIBIT = 131, + /// FBT Authentication Request Indication + FBT_AUTH_REQ_IND = 132, + /// Enhancement addition for RSSI + RSSI_LQM = 133, + /// Full probe/beacon (IEs etc) results + PFN_GSCAN_FULL_RESULT = 134, + /// Significant change in rssi of bssids being tracked + PFN_SWC = 135, + /// a STA been authroized for traffic + AUTHORIZED = 136, + /// probe req with wl_event_rx_frame_data_t header + PROBREQ_MSG_RX = 137, + /// PFN completed scan of network list + PFN_SCAN_COMPLETE = 138, + /// RMC Event + RMC_EVENT = 139, + /// DPSTA interface indication + DPSTA_INTF_IND = 140, + /// RRM Event + RRM = 141, + /// ULP entry event + ULP = 146, + /// TCP Keep Alive Offload Event + TKO = 151, + /// authentication request received + EXT_AUTH_REQ = 187, + /// authentication request received + EXT_AUTH_FRAME_RX = 188, + /// mgmt frame Tx complete + MGMT_FRAME_TXSTATUS = 189, + /// highest val + 1 for range checking + LAST = 190, +} diff --git a/src/lib.rs b/src/lib.rs index 698c52f4..040caed8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ pub(crate) mod fmt; mod countries; +mod events; mod structs; use core::cell::Cell; @@ -253,9 +254,52 @@ impl<'a> Control<'a> { }; self.set_iovar("country", &country_info.to_bytes()).await; + // set country takes some time, next ioctls fail if we don't wait. + Timer::after(Duration::from_millis(100)).await; + + // self.set_iovar_u32("ampdu_ba_wsize", 8).await; + // self.set_iovar_u32("ampdu_mpdu", 4).await; + // self.set_iovar_u32("ampdu_rx_factor", 0).await; // this crashes + + Timer::after(Duration::from_millis(100)).await; + + // evts + let mut evts = EventMask { + iface: 0, + events: [0xFF; 24], + }; + self.set_iovar("bsscfg:event_msgs", &evts.to_bytes()).await; + + // set wifi up + self.ioctl(2, 2, 0, &[]).await; + + Timer::after(Duration::from_millis(100)).await; + info!("INIT DONE"); } + pub async fn join(&mut self, ssid: &str) { + self.ioctl_set_u32(134, 0, 0).await; // wsec = open + self.set_iovar_u32x2("bsscfg:sup_wpa", 0, 0).await; + self.ioctl_set_u32(20, 0, 1).await; // set_infra = 1 + self.ioctl_set_u32(22, 0, 0).await; // set_auth = open (0) + + let mut i = SsidInfo { + len: ssid.len() as _, + ssid: [0; 32], + }; + i.ssid[..ssid.len()].copy_from_slice(ssid.as_bytes()); + self.ioctl(2, 26, 0, &i.to_bytes()).await; // set_ssid + + info!("JOINED"); + } + + async fn set_iovar_u32x2(&mut self, name: &str, val1: u32, val2: u32) { + let mut buf = [0; 8]; + buf[0..4].copy_from_slice(&val1.to_le_bytes()); + buf[4..8].copy_from_slice(&val2.to_le_bytes()); + self.set_iovar(name, &buf).await + } async fn set_iovar_u32(&mut self, name: &str, val: u32) { self.set_iovar(name, &val.to_le_bytes()).await } @@ -272,6 +316,10 @@ impl<'a> Control<'a> { self.ioctl(2, 263, 0, &buf[..total_len]).await; } + async fn ioctl_set_u32(&mut self, cmd: u32, iface: u32, val: u32) { + self.ioctl(2, cmd, 0, &val.to_le_bytes()).await + } + async fn ioctl(&mut self, kind: u32, cmd: u32, iface: u32, buf: &[u8]) { // TODO cancel ioctl on future drop. @@ -488,7 +536,7 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> { } self.cs.set_high(); - info!("rx {:02x}", &buf[..(len as usize).min(48)]); + //info!("rx {:02x}", &buf[..(len as usize).min(36)]); self.rx(&buf[..len as usize]); } @@ -528,14 +576,38 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> { return; } - let cdc_header = - CdcHeader::from_bytes(payload[..CdcHeader::SIZE].try_into().unwrap()); + let cdc_header = CdcHeader::from_bytes(payload[..CdcHeader::SIZE].try_into().unwrap()); if cdc_header.id == self.state.ioctl_id.get() { assert_eq!(cdc_header.status, 0); // todo propagate error self.state.ioctl_state.set(IoctlState::Done); } } + 1 => { + let bcd_header = BcdHeader::from_bytes(&payload[..BcdHeader::SIZE].try_into().unwrap()); + //info!("{}", bcd_header); + + let packet_start = BcdHeader::SIZE + 4 * bcd_header.data_offset as usize; + if packet_start > payload.len() { + warn!("packet start out of range."); + return; + } + let packet = &payload[packet_start..]; + //info!("rx {:02x}", &packet[..(packet.len() as usize).min(36)]); + + let evt = EventHeader::from_bytes(&packet[24..][..EventHeader::SIZE].try_into().unwrap()); + let evt_num = evt.event_type.to_be() as u8; + let evt_data_len = evt.datalen.to_be() as u8; + let evt_data = &packet[24 + EventHeader::SIZE..][..evt_data_len as usize]; + info!( + "=== EVENT {} ({}) {} {:02x}", + events::Event::from(evt_num), + evt_num, + evt, + evt_data + ); + } + _ => {} } } @@ -575,7 +647,7 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> { let total_len = (total_len + 3) & !3; // round up to 4byte - info!("tx {:02x}", &buf[..total_len.min(48)]); + //info!("tx {:02x}", &buf[..total_len.min(48)]); let cmd = cmd_word(true, true, FUNC_WLAN, 0, total_len as _); self.cs.set_low(); diff --git a/src/structs.rs b/src/structs.rs index bce9ab9f..8a98d522 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -15,6 +15,7 @@ macro_rules! impl_bytes { } #[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(C)] pub struct SdpcmHeader { pub len: u16, @@ -37,6 +38,7 @@ pub struct SdpcmHeader { impl_bytes!(SdpcmHeader); #[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(C)] pub struct CdcHeader { pub cmd: u32, @@ -49,8 +51,9 @@ pub struct CdcHeader { impl_bytes!(CdcHeader); #[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(C)] -pub struct BdcHeader { +pub struct BcdHeader { pub flags: u8, /// 802.1d Priority (low 3 bits) pub priority: u8, @@ -58,7 +61,36 @@ pub struct BdcHeader { /// Offset from end of BDC header to packet data, in 4-uint8_t words. Leaves room for optional headers. pub data_offset: u8, } -impl_bytes!(BdcHeader); +impl_bytes!(BcdHeader); + +#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(C)] +pub struct EventHeader { + /// version + pub version: u16, + /// see flags below + pub flags: u16, + /// Message (see below) + pub event_type: u32, + /// Status code (see below) + pub status: u32, + /// Reason code (if applicable) + pub reason: u32, + /// WLC_E_AUTH + pub auth_type: u32, + /// data buf + pub datalen: u32, + /// Station address (if applicable) + pub addr: [u8; 6], + /// name of the incoming packet interface + pub ifname: [u8; 16], + /// destination OS i/f index + pub ifidx: u8, + /// source bsscfg index + pub bsscfgidx: u8, +} +impl_bytes!(EventHeader); #[derive(Clone, Copy)] #[repr(C)] @@ -78,6 +110,7 @@ pub const DOWNLOAD_FLAG_HANDLER_VER: u16 = 0x1000; pub const DOWNLOAD_TYPE_CLM: u16 = 2; #[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(C)] pub struct CountryInfo { pub country_abbrev: [u8; 4], @@ -85,3 +118,21 @@ pub struct CountryInfo { pub country_code: [u8; 4], } impl_bytes!(CountryInfo); + +#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(C)] +pub struct SsidInfo { + pub len: u32, + pub ssid: [u8; 32], +} +impl_bytes!(SsidInfo); + +#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(C)] +pub struct EventMask { + pub iface: u32, + pub events: [u8; 24], +} +impl_bytes!(EventMask);