cyw43: use enum for ioctl instead of consts.

This commit is contained in:
Dario Nieuwenhuis 2024-09-08 23:48:45 +02:00
parent 74e724f968
commit 3ac38e917c
4 changed files with 319 additions and 48 deletions

View File

@ -113,17 +113,6 @@ pub(crate) const IRQ_F1_INTR: u16 = 0x2000;
pub(crate) const IRQ_F2_INTR: u16 = 0x4000; pub(crate) const IRQ_F2_INTR: u16 = 0x4000;
pub(crate) const IRQ_F3_INTR: u16 = 0x8000; pub(crate) const IRQ_F3_INTR: u16 = 0x8000;
pub(crate) const IOCTL_CMD_UP: u32 = 2;
pub(crate) const IOCTL_CMD_DOWN: u32 = 3;
pub(crate) const IOCTL_CMD_SET_SSID: u32 = 26;
pub(crate) const IOCTL_CMD_SET_CHANNEL: u32 = 30;
pub(crate) const IOCTL_CMD_DISASSOC: u32 = 52;
pub(crate) const IOCTL_CMD_ANTDIV: u32 = 64;
pub(crate) const IOCTL_CMD_SET_AP: u32 = 118;
pub(crate) const IOCTL_CMD_SET_VAR: u32 = 263;
pub(crate) const IOCTL_CMD_GET_VAR: u32 = 262;
pub(crate) const IOCTL_CMD_SET_PASSPHRASE: u32 = 268;
pub(crate) const CHANNEL_TYPE_CONTROL: u8 = 0; pub(crate) const CHANNEL_TYPE_CONTROL: u8 = 0;
pub(crate) const CHANNEL_TYPE_EVENT: u8 = 1; pub(crate) const CHANNEL_TYPE_EVENT: u8 = 1;
pub(crate) const CHANNEL_TYPE_DATA: u8 = 2; pub(crate) const CHANNEL_TYPE_DATA: u8 = 2;
@ -376,3 +365,291 @@ impl core::fmt::Display for FormatInterrupt {
core::fmt::Debug::fmt(self, f) core::fmt::Debug::fmt(self, f)
} }
} }
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u32)]
pub(crate) enum Ioctl {
GetMagic = 0,
GetVersion = 1,
Up = 2,
Down = 3,
GetLoop = 4,
SetLoop = 5,
Dump = 6,
GetMsglevel = 7,
SetMsglevel = 8,
GetPromisc = 9,
SetPromisc = 10,
GetRate = 12,
GetInstance = 14,
GetInfra = 19,
SetInfra = 20,
GetAuth = 21,
SetAuth = 22,
GetBssid = 23,
SetBssid = 24,
GetSsid = 25,
SetSsid = 26,
Restart = 27,
GetChannel = 29,
SetChannel = 30,
GetSrl = 31,
SetSrl = 32,
GetLrl = 33,
SetLrl = 34,
GetPlcphdr = 35,
SetPlcphdr = 36,
GetRadio = 37,
SetRadio = 38,
GetPhytype = 39,
DumpRate = 40,
SetRateParams = 41,
GetKey = 44,
SetKey = 45,
GetRegulatory = 46,
SetRegulatory = 47,
GetPassiveScan = 48,
SetPassiveScan = 49,
Scan = 50,
ScanResults = 51,
Disassoc = 52,
Reassoc = 53,
GetRoamTrigger = 54,
SetRoamTrigger = 55,
GetRoamDelta = 56,
SetRoamDelta = 57,
GetRoamScanPeriod = 58,
SetRoamScanPeriod = 59,
Evm = 60,
GetTxant = 61,
SetTxant = 62,
GetAntdiv = 63,
SetAntdiv = 64,
GetClosed = 67,
SetClosed = 68,
GetMaclist = 69,
SetMaclist = 70,
GetRateset = 71,
SetRateset = 72,
Longtrain = 74,
GetBcnprd = 75,
SetBcnprd = 76,
GetDtimprd = 77,
SetDtimprd = 78,
GetSrom = 79,
SetSrom = 80,
GetWepRestrict = 81,
SetWepRestrict = 82,
GetCountry = 83,
SetCountry = 84,
GetPm = 85,
SetPm = 86,
GetWake = 87,
SetWake = 88,
GetForcelink = 90,
SetForcelink = 91,
FreqAccuracy = 92,
CarrierSuppress = 93,
GetPhyreg = 94,
SetPhyreg = 95,
GetRadioreg = 96,
SetRadioreg = 97,
GetRevinfo = 98,
GetUcantdiv = 99,
SetUcantdiv = 100,
RReg = 101,
WReg = 102,
GetMacmode = 105,
SetMacmode = 106,
GetMonitor = 107,
SetMonitor = 108,
GetGmode = 109,
SetGmode = 110,
GetLegacyErp = 111,
SetLegacyErp = 112,
GetRxAnt = 113,
GetCurrRateset = 114,
GetScansuppress = 115,
SetScansuppress = 116,
GetAp = 117,
SetAp = 118,
GetEapRestrict = 119,
SetEapRestrict = 120,
ScbAuthorize = 121,
ScbDeauthorize = 122,
GetWdslist = 123,
SetWdslist = 124,
GetAtim = 125,
SetAtim = 126,
GetRssi = 127,
GetPhyantdiv = 128,
SetPhyantdiv = 129,
ApRxOnly = 130,
GetTxPathPwr = 131,
SetTxPathPwr = 132,
GetWsec = 133,
SetWsec = 134,
GetPhyNoise = 135,
GetBssInfo = 136,
GetPktcnts = 137,
GetLazywds = 138,
SetLazywds = 139,
GetBandlist = 140,
GetBand = 141,
SetBand = 142,
ScbDeauthenticate = 143,
GetShortslot = 144,
GetShortslotOverride = 145,
SetShortslotOverride = 146,
GetShortslotRestrict = 147,
SetShortslotRestrict = 148,
GetGmodeProtection = 149,
GetGmodeProtectionOverride = 150,
SetGmodeProtectionOverride = 151,
Upgrade = 152,
GetIgnoreBcns = 155,
SetIgnoreBcns = 156,
GetScbTimeout = 157,
SetScbTimeout = 158,
GetAssoclist = 159,
GetClk = 160,
SetClk = 161,
GetUp = 162,
Out = 163,
GetWpaAuth = 164,
SetWpaAuth = 165,
GetUcflags = 166,
SetUcflags = 167,
GetPwridx = 168,
SetPwridx = 169,
GetTssi = 170,
GetSupRatesetOverride = 171,
SetSupRatesetOverride = 172,
GetProtectionControl = 178,
SetProtectionControl = 179,
GetPhylist = 180,
EncryptStrength = 181,
DecryptStatus = 182,
GetKeySeq = 183,
GetScanChannelTime = 184,
SetScanChannelTime = 185,
GetScanUnassocTime = 186,
SetScanUnassocTime = 187,
GetScanHomeTime = 188,
SetScanHomeTime = 189,
GetScanNprobes = 190,
SetScanNprobes = 191,
GetPrbRespTimeout = 192,
SetPrbRespTimeout = 193,
GetAtten = 194,
SetAtten = 195,
GetShmem = 196,
SetShmem = 197,
SetWsecTest = 200,
ScbDeauthenticateForReason = 201,
TkipCountermeasures = 202,
GetPiomode = 203,
SetPiomode = 204,
SetAssocPrefer = 205,
GetAssocPrefer = 206,
SetRoamPrefer = 207,
GetRoamPrefer = 208,
SetLed = 209,
GetLed = 210,
GetInterferenceMode = 211,
SetInterferenceMode = 212,
GetChannelQa = 213,
StartChannelQa = 214,
GetChannelSel = 215,
StartChannelSel = 216,
GetValidChannels = 217,
GetFakefrag = 218,
SetFakefrag = 219,
GetPwroutPercentage = 220,
SetPwroutPercentage = 221,
SetBadFramePreempt = 222,
GetBadFramePreempt = 223,
SetLeapList = 224,
GetLeapList = 225,
GetCwmin = 226,
SetCwmin = 227,
GetCwmax = 228,
SetCwmax = 229,
GetWet = 230,
SetWet = 231,
GetPub = 232,
GetKeyPrimary = 235,
SetKeyPrimary = 236,
GetAciArgs = 238,
SetAciArgs = 239,
UnsetCallback = 240,
SetCallback = 241,
GetRadar = 242,
SetRadar = 243,
SetSpectManagment = 244,
GetSpectManagment = 245,
WdsGetRemoteHwaddr = 246,
WdsGetWpaSup = 247,
SetCsScanTimer = 248,
GetCsScanTimer = 249,
MeasureRequest = 250,
Init = 251,
SendQuiet = 252,
Keepalive = 253,
SendPwrConstraint = 254,
UpgradeStatus = 255,
CurrentPwr = 256,
GetScanPassiveTime = 257,
SetScanPassiveTime = 258,
LegacyLinkBehavior = 259,
GetChannelsInCountry = 260,
GetCountryList = 261,
GetVar = 262,
SetVar = 263,
NvramGet = 264,
NvramSet = 265,
NvramDump = 266,
Reboot = 267,
SetWsecPmk = 268,
GetAuthMode = 269,
SetAuthMode = 270,
GetWakeentry = 271,
SetWakeentry = 272,
NdconfigItem = 273,
Nvotpw = 274,
Otpw = 275,
IovBlockGet = 276,
IovModulesGet = 277,
SoftReset = 278,
GetAllowMode = 279,
SetAllowMode = 280,
GetDesiredBssid = 281,
SetDesiredBssid = 282,
DisassocMyap = 283,
GetNbands = 284,
GetBandstates = 285,
GetWlcBssInfo = 286,
GetAssocInfo = 287,
GetOidPhy = 288,
SetOidPhy = 289,
SetAssocTime = 290,
GetDesiredSsid = 291,
GetChanspec = 292,
GetAssocState = 293,
SetPhyState = 294,
GetScanPending = 295,
GetScanreqPending = 296,
GetPrevRoamReason = 297,
SetPrevRoamReason = 298,
GetBandstatesPi = 299,
GetPhyState = 300,
GetBssWpaRsn = 301,
GetBssWpa2Rsn = 302,
GetBssBcnTs = 303,
GetIntDisassoc = 304,
SetNumPeers = 305,
GetNumBss = 306,
GetWsecPmk = 318,
GetRandomBytes = 319,
}

View File

@ -109,7 +109,7 @@ impl<'a> Control<'a> {
buf[0..8].copy_from_slice(b"clmload\x00"); buf[0..8].copy_from_slice(b"clmload\x00");
buf[8..20].copy_from_slice(&header.to_bytes()); buf[8..20].copy_from_slice(&header.to_bytes());
buf[20..][..chunk.len()].copy_from_slice(&chunk); buf[20..][..chunk.len()].copy_from_slice(&chunk);
self.ioctl(IoctlType::Set, IOCTL_CMD_SET_VAR, 0, &mut buf[..8 + 12 + chunk.len()]) self.ioctl(IoctlType::Set, Ioctl::SetVar, 0, &mut buf[..8 + 12 + chunk.len()])
.await; .await;
} }
@ -145,7 +145,7 @@ impl<'a> Control<'a> {
Timer::after_millis(100).await; Timer::after_millis(100).await;
// Set antenna to chip antenna // Set antenna to chip antenna
self.ioctl_set_u32(IOCTL_CMD_ANTDIV, 0, 0).await; self.ioctl_set_u32(Ioctl::SetAntdiv, 0, 0).await;
self.set_iovar_u32("bus:txglom", 0).await; self.set_iovar_u32("bus:txglom", 0).await;
Timer::after_millis(100).await; Timer::after_millis(100).await;
@ -183,8 +183,8 @@ impl<'a> Control<'a> {
Timer::after_millis(100).await; Timer::after_millis(100).await;
self.ioctl_set_u32(110, 0, 1).await; // SET_GMODE = auto self.ioctl_set_u32(Ioctl::SetGmode, 0, 1).await; // SET_GMODE = auto
self.ioctl_set_u32(142, 0, 0).await; // SET_BAND = any self.ioctl_set_u32(Ioctl::SetBand, 0, 0).await; // SET_BAND = any
Timer::after_millis(100).await; Timer::after_millis(100).await;
@ -195,12 +195,12 @@ impl<'a> Control<'a> {
/// Set the WiFi interface up. /// Set the WiFi interface up.
async fn up(&mut self) { async fn up(&mut self) {
self.ioctl(IoctlType::Set, IOCTL_CMD_UP, 0, &mut []).await; self.ioctl(IoctlType::Set, Ioctl::Up, 0, &mut []).await;
} }
/// Set the interface down. /// Set the interface down.
async fn down(&mut self) { async fn down(&mut self) {
self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await; self.ioctl(IoctlType::Set, Ioctl::Down, 0, &mut []).await;
} }
/// Set power management mode. /// Set power management mode.
@ -213,17 +213,17 @@ impl<'a> Control<'a> {
self.set_iovar_u32("bcn_li_dtim", mode.dtim_period() as u32).await; self.set_iovar_u32("bcn_li_dtim", mode.dtim_period() as u32).await;
self.set_iovar_u32("assoc_listen", mode.assoc() as u32).await; self.set_iovar_u32("assoc_listen", mode.assoc() as u32).await;
} }
self.ioctl_set_u32(86, 0, mode_num).await; self.ioctl_set_u32(Ioctl::SetPm, 0, mode_num).await;
} }
/// Join an unprotected network with the provided ssid. /// Join an unprotected network with the provided ssid.
pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> { pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> {
self.set_iovar_u32("ampdu_ba_wsize", 8).await; self.set_iovar_u32("ampdu_ba_wsize", 8).await;
self.ioctl_set_u32(134, 0, 0).await; // wsec = open self.ioctl_set_u32(Ioctl::SetWsec, 0, 0).await; // wsec = open
self.set_iovar_u32x2("bsscfg:sup_wpa", 0, 0).await; 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(Ioctl::SetInfra, 0, 1).await; // set_infra = 1
self.ioctl_set_u32(22, 0, 0).await; // set_auth = open (0) self.ioctl_set_u32(Ioctl::SetAuth, 0, 0).await; // set_auth = open (0)
let mut i = SsidInfo { let mut i = SsidInfo {
len: ssid.len() as _, len: ssid.len() as _,
@ -238,24 +238,19 @@ impl<'a> Control<'a> {
async fn join_wpa2_passphrase_info(&mut self, ssid: &str, passphrase_info: &PassphraseInfo) -> Result<(), Error> { async fn join_wpa2_passphrase_info(&mut self, ssid: &str, passphrase_info: &PassphraseInfo) -> Result<(), Error> {
self.set_iovar_u32("ampdu_ba_wsize", 8).await; self.set_iovar_u32("ampdu_ba_wsize", 8).await;
self.ioctl_set_u32(134, 0, 4).await; // wsec = wpa2 self.ioctl_set_u32(Ioctl::SetWsec, 0, 4).await; // wsec = open
self.set_iovar_u32x2("bsscfg:sup_wpa", 0, 1).await; self.set_iovar_u32x2("bsscfg:sup_wpa", 0, 1).await;
self.set_iovar_u32x2("bsscfg:sup_wpa2_eapver", 0, 0xFFFF_FFFF).await; self.set_iovar_u32x2("bsscfg:sup_wpa2_eapver", 0, 0xFFFF_FFFF).await;
self.set_iovar_u32x2("bsscfg:sup_wpa_tmo", 0, 2500).await; self.set_iovar_u32x2("bsscfg:sup_wpa_tmo", 0, 2500).await;
Timer::after_millis(100).await; Timer::after_millis(100).await;
self.ioctl( self.ioctl(IoctlType::Set, Ioctl::SetWsecPmk, 0, &mut passphrase_info.to_bytes())
IoctlType::Set, .await; // WLC_SET_WSEC_PMK
IOCTL_CMD_SET_PASSPHRASE,
0,
&mut passphrase_info.to_bytes(),
)
.await; // WLC_SET_WSEC_PMK
self.ioctl_set_u32(20, 0, 1).await; // set_infra = 1 self.ioctl_set_u32(Ioctl::SetInfra, 0, 1).await; // set_infra = 1
self.ioctl_set_u32(22, 0, 0).await; // set_auth = 0 (open) self.ioctl_set_u32(Ioctl::SetAuth, 0, 0).await; // set_auth = 0 (open)
self.ioctl_set_u32(165, 0, 0x80).await; // set_wpa_auth self.ioctl_set_u32(Ioctl::SetWpaAuth, 0, 0x80).await;
let mut i = SsidInfo { let mut i = SsidInfo {
len: ssid.len() as _, len: ssid.len() as _,
@ -294,9 +289,7 @@ impl<'a> Control<'a> {
// the actual join operation starts here // the actual join operation starts here
// we make sure to enable events before so we don't miss any // we make sure to enable events before so we don't miss any
// set_ssid self.ioctl(IoctlType::Set, Ioctl::SetSsid, 0, &mut i.to_bytes()).await;
self.ioctl(IoctlType::Set, IOCTL_CMD_SET_SSID, 0, &mut i.to_bytes())
.await;
// to complete the join, we wait for a SET_SSID event // to complete the join, we wait for a SET_SSID event
// we also save the AUTH status for the user, it may be interesting // we also save the AUTH status for the user, it may be interesting
@ -357,7 +350,7 @@ impl<'a> Control<'a> {
self.up().await; self.up().await;
// Turn on AP mode // Turn on AP mode
self.ioctl_set_u32(IOCTL_CMD_SET_AP, 0, 1).await; self.ioctl_set_u32(Ioctl::SetAp, 0, 1).await;
// Set SSID // Set SSID
let mut i = SsidInfoWithIndex { let mut i = SsidInfoWithIndex {
@ -371,7 +364,7 @@ impl<'a> Control<'a> {
self.set_iovar("bsscfg:ssid", &i.to_bytes()).await; self.set_iovar("bsscfg:ssid", &i.to_bytes()).await;
// Set channel number // Set channel number
self.ioctl_set_u32(IOCTL_CMD_SET_CHANNEL, 0, channel as u32).await; self.ioctl_set_u32(Ioctl::SetChannel, 0, channel as u32).await;
// Set security // Set security
self.set_iovar_u32x2("bsscfg:wsec", 0, (security as u32) & 0xFF).await; self.set_iovar_u32x2("bsscfg:wsec", 0, (security as u32) & 0xFF).await;
@ -388,7 +381,7 @@ impl<'a> Control<'a> {
passphrase: [0; 64], passphrase: [0; 64],
}; };
pfi.passphrase[..passphrase.as_bytes().len()].copy_from_slice(passphrase.as_bytes()); pfi.passphrase[..passphrase.as_bytes().len()].copy_from_slice(passphrase.as_bytes());
self.ioctl(IoctlType::Set, IOCTL_CMD_SET_PASSPHRASE, 0, &mut pfi.to_bytes()) self.ioctl(IoctlType::Set, Ioctl::SetWsecPmk, 0, &mut pfi.to_bytes())
.await; .await;
} }
@ -405,7 +398,7 @@ impl<'a> Control<'a> {
self.set_iovar_u32x2("bss", 0, 0).await; // bss = BSS_DOWN self.set_iovar_u32x2("bss", 0, 0).await; // bss = BSS_DOWN
// Turn off AP mode // Turn off AP mode
self.ioctl_set_u32(IOCTL_CMD_SET_AP, 0, 0).await; self.ioctl_set_u32(Ioctl::SetAp, 0, 0).await;
// Temporarily set wifi down // Temporarily set wifi down
self.down().await; self.down().await;
@ -496,7 +489,7 @@ impl<'a> Control<'a> {
buf[name.len() + 1..][..val.len()].copy_from_slice(val); buf[name.len() + 1..][..val.len()].copy_from_slice(val);
let total_len = name.len() + 1 + val.len(); let total_len = name.len() + 1 + val.len();
self.ioctl(IoctlType::Set, IOCTL_CMD_SET_VAR, 0, &mut buf[..total_len]) self.ioctl(IoctlType::Set, Ioctl::SetVar, 0, &mut buf[..total_len])
.await; .await;
} }
@ -510,7 +503,7 @@ impl<'a> Control<'a> {
let total_len = max(name.len() + 1, res.len()); let total_len = max(name.len() + 1, res.len());
let res_len = self let res_len = self
.ioctl(IoctlType::Get, IOCTL_CMD_GET_VAR, 0, &mut buf[..total_len]) .ioctl(IoctlType::Get, Ioctl::GetVar, 0, &mut buf[..total_len])
.await; .await;
let out_len = min(res.len(), res_len); let out_len = min(res.len(), res_len);
@ -518,12 +511,12 @@ impl<'a> Control<'a> {
out_len out_len
} }
async fn ioctl_set_u32(&mut self, cmd: u32, iface: u32, val: u32) { async fn ioctl_set_u32(&mut self, cmd: Ioctl, iface: u32, val: u32) {
let mut buf = val.to_le_bytes(); let mut buf = val.to_le_bytes();
self.ioctl(IoctlType::Set, cmd, iface, &mut buf).await; self.ioctl(IoctlType::Set, cmd, iface, &mut buf).await;
} }
async fn ioctl(&mut self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { async fn ioctl(&mut self, kind: IoctlType, cmd: Ioctl, iface: u32, buf: &mut [u8]) -> usize {
struct CancelOnDrop<'a>(&'a IoctlState); struct CancelOnDrop<'a>(&'a IoctlState);
impl CancelOnDrop<'_> { impl CancelOnDrop<'_> {
@ -615,7 +608,7 @@ impl<'a> Control<'a> {
} }
/// Leave the wifi, with which we are currently associated. /// Leave the wifi, with which we are currently associated.
pub async fn leave(&mut self) { pub async fn leave(&mut self) {
self.ioctl(IoctlType::Set, IOCTL_CMD_DISASSOC, 0, &mut []).await; self.ioctl(IoctlType::Set, Ioctl::Disassoc, 0, &mut []).await;
info!("Disassociated") info!("Disassociated")
} }

View File

@ -4,6 +4,7 @@ use core::task::{Poll, Waker};
use embassy_sync::waitqueue::WakerRegistration; use embassy_sync::waitqueue::WakerRegistration;
use crate::consts::Ioctl;
use crate::fmt::Bytes; use crate::fmt::Bytes;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -16,7 +17,7 @@ pub enum IoctlType {
pub struct PendingIoctl { pub struct PendingIoctl {
pub buf: *mut [u8], pub buf: *mut [u8],
pub kind: IoctlType, pub kind: IoctlType,
pub cmd: u32, pub cmd: Ioctl,
pub iface: u32, pub iface: u32,
} }
@ -101,7 +102,7 @@ impl IoctlState {
self.state.set(IoctlStateInner::Done { resp_len: 0 }); self.state.set(IoctlStateInner::Done { resp_len: 0 });
} }
pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { pub async fn do_ioctl(&self, kind: IoctlType, cmd: Ioctl, iface: u32, buf: &mut [u8]) -> usize {
self.state self.state
.set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface })); .set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface }));
self.wake_runner(); self.wake_runner();

View File

@ -560,7 +560,7 @@ where
self.sdpcm_seq != self.sdpcm_seq_max && self.sdpcm_seq_max.wrapping_sub(self.sdpcm_seq) & 0x80 == 0 self.sdpcm_seq != self.sdpcm_seq_max && self.sdpcm_seq_max.wrapping_sub(self.sdpcm_seq) & 0x80 == 0
} }
async fn send_ioctl(&mut self, kind: IoctlType, cmd: u32, iface: u32, data: &[u8], buf: &mut [u32; 512]) { async fn send_ioctl(&mut self, kind: IoctlType, cmd: Ioctl, iface: u32, data: &[u8], buf: &mut [u32; 512]) {
let buf8 = slice8_mut(buf); let buf8 = slice8_mut(buf);
let total_len = SdpcmHeader::SIZE + CdcHeader::SIZE + data.len(); let total_len = SdpcmHeader::SIZE + CdcHeader::SIZE + data.len();
@ -582,7 +582,7 @@ where
}; };
let cdc_header = CdcHeader { let cdc_header = CdcHeader {
cmd: cmd, cmd: cmd as u32,
len: data.len() as _, len: data.len() as _,
flags: kind as u16 | (iface as u16) << 12, flags: kind as u16 | (iface as u16) << 12,
id: self.ioctl_id, id: self.ioctl_id,