add event printing, add join but not working yet.
This commit is contained in:
parent
7ddcacac7b
commit
30b7800f9a
@ -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 }
|
||||
|
@ -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;
|
||||
}
|
||||
|
281
src/events.rs
Normal file
281
src/events.rs
Normal file
@ -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,
|
||||
}
|
80
src/lib.rs
80
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();
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user