Hook up embassy-net. IT WORKS.
This commit is contained in:
parent
f60407feb3
commit
ce7353fba4
@ -9,6 +9,7 @@ log = ["dep:log"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
embassy = { version = "0.1.0" }
|
embassy = { version = "0.1.0" }
|
||||||
embassy-rp = { version = "0.1.0", features = ["unstable-traits", "nightly", "unstable-pac"] }
|
embassy-rp = { version = "0.1.0", features = ["unstable-traits", "nightly", "unstable-pac"] }
|
||||||
|
embassy-net = { version = "0.1.0" }
|
||||||
atomic-polyfill = "0.1.5"
|
atomic-polyfill = "0.1.5"
|
||||||
|
|
||||||
defmt = { version = "0.3", optional = true }
|
defmt = { version = "0.3", optional = true }
|
||||||
|
@ -8,6 +8,7 @@ edition = "2021"
|
|||||||
cyw43 = { path = "../../", features = ["defmt"]}
|
cyw43 = { path = "../../", features = ["defmt"]}
|
||||||
embassy = { version = "0.1.0", features = ["defmt", "defmt-timestamp-uptime"] }
|
embassy = { version = "0.1.0", features = ["defmt", "defmt-timestamp-uptime"] }
|
||||||
embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac"] }
|
embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac"] }
|
||||||
|
embassy-net = { version = "0.1.0", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] }
|
||||||
atomic-polyfill = "0.1.5"
|
atomic-polyfill = "0.1.5"
|
||||||
|
|
||||||
defmt = "0.3"
|
defmt = "0.3"
|
||||||
@ -20,13 +21,21 @@ 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-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" }
|
||||||
embedded-hal-async = { version = "0.1.0-alpha.1" }
|
embedded-hal-async = { version = "0.1.0-alpha.1" }
|
||||||
|
embedded-io = { version = "0.3.0", features = ["async", "defmt"] }
|
||||||
|
heapless = "0.7.15"
|
||||||
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
embassy = { git = "https://github.com/embassy-rs/embassy", rev = "5f43c1d37e9db847c7861fe0bd821db62edba9f6" }
|
embassy = { git = "https://github.com/embassy-rs/embassy", rev = "5f43c1d37e9db847c7861fe0bd821db62edba9f6" }
|
||||||
embassy-rp = { git = "https://github.com/embassy-rs/embassy", rev = "5f43c1d37e9db847c7861fe0bd821db62edba9f6" }
|
embassy-rp = { git = "https://github.com/embassy-rs/embassy", rev = "5f43c1d37e9db847c7861fe0bd821db62edba9f6" }
|
||||||
|
embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "5f43c1d37e9db847c7861fe0bd821db62edba9f6" }
|
||||||
#embassy = { path = "/home/dirbaio/embassy/embassy/embassy" }
|
#embassy = { path = "/home/dirbaio/embassy/embassy/embassy" }
|
||||||
#embassy-rp = { path = "/home/dirbaio/embassy/embassy/embassy-rp" }
|
#embassy-rp = { path = "/home/dirbaio/embassy/embassy/embassy-rp" }
|
||||||
|
#embassy-net = { path = "/home/dirbaio/embassy/embassy/embassy-net" }
|
||||||
|
#smoltcp = { path = "./smoltcp" }
|
||||||
|
|
||||||
|
#[patch."https://github.com/smoltcp-rs/smoltcp"]
|
||||||
|
#smoltcp = { path = "./smoltcp" }
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
debug = 2
|
debug = 2
|
||||||
|
@ -8,9 +8,13 @@ use defmt::{assert, assert_eq, panic, *};
|
|||||||
use embassy::executor::Spawner;
|
use embassy::executor::Spawner;
|
||||||
use embassy::time::{Duration, Timer};
|
use embassy::time::{Duration, Timer};
|
||||||
use embassy::util::Forever;
|
use embassy::util::Forever;
|
||||||
|
use embassy_net::tcp::TcpSocket;
|
||||||
|
use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources};
|
||||||
use embassy_rp::gpio::{Flex, Level, Output, Pin};
|
use embassy_rp::gpio::{Flex, Level, Output, Pin};
|
||||||
use embassy_rp::peripherals::{PIN_23, PIN_24, PIN_25, PIN_29};
|
use embassy_rp::peripherals::{PIN_23, PIN_24, PIN_25, PIN_29};
|
||||||
use embassy_rp::Peripherals;
|
use embassy_rp::Peripherals;
|
||||||
|
use embedded_io::asynch::{Read, Write};
|
||||||
|
use heapless::Vec;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
macro_rules! forever {
|
macro_rules! forever {
|
||||||
@ -26,6 +30,11 @@ async fn wifi_task(runner: cyw43::Runner<'static, PIN_23, PIN_25, PIN_29, PIN_24
|
|||||||
runner.run().await
|
runner.run().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[embassy::task]
|
||||||
|
async fn net_task(stack: &'static Stack<cyw43::NetDevice<'static>>) -> ! {
|
||||||
|
stack.run().await
|
||||||
|
}
|
||||||
|
|
||||||
#[embassy::main]
|
#[embassy::main]
|
||||||
async fn main(spawner: Spawner, p: Peripherals) {
|
async fn main(spawner: Spawner, p: Peripherals) {
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
@ -45,8 +54,71 @@ async fn main(spawner: Spawner, p: Peripherals) {
|
|||||||
|
|
||||||
spawner.spawn(wifi_task(runner)).unwrap();
|
spawner.spawn(wifi_task(runner)).unwrap();
|
||||||
|
|
||||||
control.init().await;
|
let net_device = control.init().await;
|
||||||
|
|
||||||
//control.join_open("MikroTik-951589").await;
|
control.join_open("MikroTik-951589").await;
|
||||||
control.join_wpa2("MikroTik-951589", "fasdfasdfasdf").await;
|
//control.join_wpa2("MikroTik-951589", "asdfasdfasdfasdf").await;
|
||||||
|
|
||||||
|
let config = embassy_net::ConfigStrategy::Dhcp;
|
||||||
|
//let config = embassy_net::ConfigStrategy::Static(embassy_net::Config {
|
||||||
|
// address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
|
||||||
|
// dns_servers: Vec::new(),
|
||||||
|
// gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
|
||||||
|
//});
|
||||||
|
|
||||||
|
// Generate random seed
|
||||||
|
let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random.
|
||||||
|
|
||||||
|
// Init network stack
|
||||||
|
let stack = &*forever!(Stack::new(
|
||||||
|
net_device,
|
||||||
|
config,
|
||||||
|
forever!(StackResources::<1, 2, 8>::new()),
|
||||||
|
seed
|
||||||
|
));
|
||||||
|
|
||||||
|
unwrap!(spawner.spawn(net_task(stack)));
|
||||||
|
|
||||||
|
// And now we can use it!
|
||||||
|
|
||||||
|
let mut rx_buffer = [0; 4096];
|
||||||
|
let mut tx_buffer = [0; 4096];
|
||||||
|
let mut buf = [0; 4096];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
|
||||||
|
socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10)));
|
||||||
|
|
||||||
|
info!("Listening on TCP:1234...");
|
||||||
|
if let Err(e) = socket.accept(1234).await {
|
||||||
|
warn!("accept error: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Received connection from {:?}", socket.remote_endpoint());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let n = match socket.read(&mut buf).await {
|
||||||
|
Ok(0) => {
|
||||||
|
warn!("read EOF");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("read error: {:?}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("rxd {:02x}", &buf[..n]);
|
||||||
|
|
||||||
|
match socket.write_all(&buf[..n]).await {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => {
|
||||||
|
warn!("write error: {:?}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
168
src/lib.rs
168
src/lib.rs
@ -12,12 +12,19 @@ mod structs;
|
|||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::slice;
|
use core::slice;
|
||||||
|
use core::sync::atomic::Ordering;
|
||||||
|
use core::task::Waker;
|
||||||
|
|
||||||
|
use atomic_polyfill::AtomicBool;
|
||||||
|
use embassy::blocking_mutex::raw::NoopRawMutex;
|
||||||
|
use embassy::channel::mpmc::Channel;
|
||||||
use embassy::time::{block_for, Duration, Timer};
|
use embassy::time::{block_for, Duration, Timer};
|
||||||
use embassy::util::yield_now;
|
use embassy::util::yield_now;
|
||||||
|
use embassy_net::{PacketBoxExt, PacketBuf};
|
||||||
use embassy_rp::gpio::{Flex, Output, Pin};
|
use embassy_rp::gpio::{Flex, Output, Pin};
|
||||||
|
|
||||||
use self::structs::*;
|
use self::structs::*;
|
||||||
|
use crate::events::Event;
|
||||||
|
|
||||||
fn swap16(x: u32) -> u32 {
|
fn swap16(x: u32) -> u32 {
|
||||||
(x & 0xFF00FF00) >> 8 | (x & 0x00FF00FF) << 8
|
(x & 0xFF00FF00) >> 8 | (x & 0x00FF00FF) << 8
|
||||||
@ -197,6 +204,10 @@ enum IoctlState {
|
|||||||
pub struct State {
|
pub struct State {
|
||||||
ioctl_id: Cell<u16>,
|
ioctl_id: Cell<u16>,
|
||||||
ioctl_state: Cell<IoctlState>,
|
ioctl_state: Cell<IoctlState>,
|
||||||
|
|
||||||
|
tx_channel: Channel<NoopRawMutex, PacketBuf, 8>,
|
||||||
|
rx_channel: Channel<NoopRawMutex, PacketBuf, 8>,
|
||||||
|
link_up: AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
@ -204,6 +215,10 @@ impl State {
|
|||||||
Self {
|
Self {
|
||||||
ioctl_id: Cell::new(0),
|
ioctl_id: Cell::new(0),
|
||||||
ioctl_state: Cell::new(IoctlState::Idle),
|
ioctl_state: Cell::new(IoctlState::Idle),
|
||||||
|
|
||||||
|
tx_channel: Channel::new(),
|
||||||
|
rx_channel: Channel::new(),
|
||||||
|
link_up: AtomicBool::new(true), // TODO set up/down as we join/deassociate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,7 +228,7 @@ pub struct Control<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Control<'a> {
|
impl<'a> Control<'a> {
|
||||||
pub async fn init(&mut self) {
|
pub async fn init(&mut self) -> NetDevice<'a> {
|
||||||
const CHUNK_SIZE: usize = 1024;
|
const CHUNK_SIZE: usize = 1024;
|
||||||
|
|
||||||
let clm = unsafe { slice::from_raw_parts(0x10140000 as *const u8, 4752) };
|
let clm = unsafe { slice::from_raw_parts(0x10140000 as *const u8, 4752) };
|
||||||
@ -253,6 +268,15 @@ impl<'a> Control<'a> {
|
|||||||
self.set_iovar_u32("apsta", 1).await;
|
self.set_iovar_u32("apsta", 1).await;
|
||||||
//self.set_iovar("cur_etheraddr", &[02, 03, 04, 05, 06, 07]).await;
|
//self.set_iovar("cur_etheraddr", &[02, 03, 04, 05, 06, 07]).await;
|
||||||
|
|
||||||
|
// read MAC addr.
|
||||||
|
let mut mac_addr = [0; 6];
|
||||||
|
assert_eq!(self.get_iovar("cur_etheraddr", &mut mac_addr).await, 6);
|
||||||
|
info!("mac addr: {:02x}", mac_addr);
|
||||||
|
|
||||||
|
// TODO get_iovar is broken, it returns all zeros.
|
||||||
|
// Harcdode our own MAC for now.
|
||||||
|
let mac_addr = [0x28, 0xCD, 0xC1, 0x00, 0x3F, 0x05];
|
||||||
|
|
||||||
let country = countries::WORLD_WIDE_XX;
|
let country = countries::WORLD_WIDE_XX;
|
||||||
let country_info = CountryInfo {
|
let country_info = CountryInfo {
|
||||||
country_abbrev: [country.code[0], country.code[1], 0, 0],
|
country_abbrev: [country.code[0], country.code[1], 0, 0],
|
||||||
@ -283,6 +307,15 @@ impl<'a> Control<'a> {
|
|||||||
iface: 0,
|
iface: 0,
|
||||||
events: [0xFF; 24],
|
events: [0xFF; 24],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Disable spammy uninteresting events.
|
||||||
|
evts.unset(Event::RADIO);
|
||||||
|
evts.unset(Event::IF);
|
||||||
|
evts.unset(Event::PROBREQ_MSG);
|
||||||
|
evts.unset(Event::PROBREQ_MSG_RX);
|
||||||
|
evts.unset(Event::PROBRESP_MSG);
|
||||||
|
evts.unset(Event::PROBRESP_MSG);
|
||||||
|
|
||||||
self.set_iovar("bsscfg:event_msgs", &evts.to_bytes()).await;
|
self.set_iovar("bsscfg:event_msgs", &evts.to_bytes()).await;
|
||||||
|
|
||||||
Timer::after(Duration::from_millis(100)).await;
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
@ -305,6 +338,11 @@ impl<'a> Control<'a> {
|
|||||||
Timer::after(Duration::from_millis(100)).await;
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
|
|
||||||
info!("INIT DONE");
|
info!("INIT DONE");
|
||||||
|
|
||||||
|
NetDevice {
|
||||||
|
state: self.state,
|
||||||
|
mac_addr,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn join_open(&mut self, ssid: &str) {
|
pub async fn join_open(&mut self, ssid: &str) {
|
||||||
@ -387,6 +425,7 @@ impl<'a> Control<'a> {
|
|||||||
self.ioctl(2, 263, 0, &mut buf).await;
|
self.ioctl(2, 263, 0, &mut buf).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO this is not really working, it always returns all zeros.
|
||||||
async fn get_iovar(&mut self, name: &str, res: &mut [u8]) -> usize {
|
async fn get_iovar(&mut self, name: &str, res: &mut [u8]) -> usize {
|
||||||
info!("get {}", name);
|
info!("get {}", name);
|
||||||
|
|
||||||
@ -395,7 +434,7 @@ impl<'a> Control<'a> {
|
|||||||
buf[name.len()] = 0;
|
buf[name.len()] = 0;
|
||||||
|
|
||||||
let total_len = name.len() + 1 + res.len();
|
let total_len = name.len() + 1 + res.len();
|
||||||
let res_len = self.ioctl(2, 262, 0, &mut buf[..total_len]).await - name.len() - 1;
|
let res_len = self.ioctl(0, 262, 0, &mut buf[..total_len]).await - name.len() - 1;
|
||||||
res[..res_len].copy_from_slice(&buf[name.len() + 1..][..res_len]);
|
res[..res_len].copy_from_slice(&buf[name.len() + 1..][..res_len]);
|
||||||
res_len
|
res_len
|
||||||
}
|
}
|
||||||
@ -408,9 +447,6 @@ impl<'a> Control<'a> {
|
|||||||
async fn ioctl(&mut self, kind: u32, cmd: u32, iface: u32, buf: &mut [u8]) -> usize {
|
async fn ioctl(&mut self, kind: u32, cmd: u32, iface: u32, buf: &mut [u8]) -> usize {
|
||||||
// TODO cancel ioctl on future drop.
|
// TODO cancel ioctl on future drop.
|
||||||
|
|
||||||
// snail mode 🐌
|
|
||||||
Timer::after(Duration::from_millis(100)).await;
|
|
||||||
|
|
||||||
while !matches!(self.state.ioctl_state.get(), IoctlState::Idle) {
|
while !matches!(self.state.ioctl_state.get(), IoctlState::Idle) {
|
||||||
yield_now().await;
|
yield_now().await;
|
||||||
}
|
}
|
||||||
@ -434,6 +470,50 @@ impl<'a> Control<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct NetDevice<'a> {
|
||||||
|
state: &'a State,
|
||||||
|
mac_addr: [u8; 6],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> embassy_net::Device for NetDevice<'a> {
|
||||||
|
fn register_waker(&mut self, waker: &Waker) {
|
||||||
|
// loopy loopy wakey wakey
|
||||||
|
waker.wake_by_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn link_state(&mut self) -> embassy_net::LinkState {
|
||||||
|
match self.state.link_up.load(Ordering::Relaxed) {
|
||||||
|
true => embassy_net::LinkState::Up,
|
||||||
|
false => embassy_net::LinkState::Down,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn capabilities(&self) -> embassy_net::DeviceCapabilities {
|
||||||
|
let mut caps = embassy_net::DeviceCapabilities::default();
|
||||||
|
caps.max_transmission_unit = 1514; // 1500 IP + 14 ethernet header
|
||||||
|
caps.medium = embassy_net::Medium::Ethernet;
|
||||||
|
caps
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_transmit_ready(&mut self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transmit(&mut self, pkt: PacketBuf) {
|
||||||
|
if self.state.tx_channel.try_send(pkt).is_err() {
|
||||||
|
warn!("TX failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive(&mut self) -> Option<PacketBuf> {
|
||||||
|
self.state.rx_channel.try_recv().ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ethernet_address(&self) -> [u8; 6] {
|
||||||
|
self.mac_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Runner<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> {
|
pub struct Runner<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> {
|
||||||
state: &'a State,
|
state: &'a State,
|
||||||
|
|
||||||
@ -576,7 +656,10 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> {
|
|||||||
while self.read32(FUNC_BUS, REG_BUS_STATUS) & STATUS_F2_RX_READY == 0 {}
|
while self.read32(FUNC_BUS, REG_BUS_STATUS) & STATUS_F2_RX_READY == 0 {}
|
||||||
|
|
||||||
// Some random configs related to sleep.
|
// Some random configs related to sleep.
|
||||||
// I think they're not needed if we don't want sleep...???
|
// These aren't needed if we don't want to sleep the bus.
|
||||||
|
// TODO do we need to sleep the bus to read the irq line, due to
|
||||||
|
// being on the same pin as MOSI/MISO?
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let mut val = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL);
|
let mut val = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL);
|
||||||
val |= 0x02; // WAKE_TILL_HT_AVAIL
|
val |= 0x02; // WAKE_TILL_HT_AVAIL
|
||||||
@ -606,11 +689,16 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> {
|
|||||||
let mut buf = [0; 2048];
|
let mut buf = [0; 2048];
|
||||||
loop {
|
loop {
|
||||||
// Send stuff
|
// Send stuff
|
||||||
|
// TODO flow control
|
||||||
if let IoctlState::Pending { kind, cmd, iface, buf } = self.state.ioctl_state.get() {
|
if let IoctlState::Pending { kind, cmd, iface, buf } = self.state.ioctl_state.get() {
|
||||||
self.send_ioctl(kind, cmd, iface, unsafe { &*buf }, self.state.ioctl_id.get());
|
self.send_ioctl(kind, cmd, iface, unsafe { &*buf }, self.state.ioctl_id.get());
|
||||||
self.state.ioctl_state.set(IoctlState::Sent { buf });
|
self.state.ioctl_state.set(IoctlState::Sent { buf });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Ok(p) = self.state.tx_channel.try_recv() {
|
||||||
|
self.send_packet(&p);
|
||||||
|
}
|
||||||
|
|
||||||
// Receive stuff
|
// Receive stuff
|
||||||
let irq = self.read16(FUNC_BUS, REG_BUS_INTERRUPT);
|
let irq = self.read16(FUNC_BUS, REG_BUS_INTERRUPT);
|
||||||
|
|
||||||
@ -646,6 +734,52 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_packet(&mut self, packet: &[u8]) {
|
||||||
|
trace!("tx pkt {:02x}", &packet[..packet.len().min(48)]);
|
||||||
|
|
||||||
|
let mut buf = [0; 2048];
|
||||||
|
|
||||||
|
let total_len = SdpcmHeader::SIZE + BcdHeader::SIZE + packet.len();
|
||||||
|
|
||||||
|
let seq = self.ioctl_seq;
|
||||||
|
self.ioctl_seq = self.ioctl_seq.wrapping_add(1);
|
||||||
|
|
||||||
|
let sdpcm_header = SdpcmHeader {
|
||||||
|
len: total_len as u16, // TODO does this len need to be rounded up to u32?
|
||||||
|
len_inv: !total_len as u16,
|
||||||
|
sequence: seq,
|
||||||
|
channel_and_flags: 2, // data channel
|
||||||
|
next_length: 0,
|
||||||
|
header_length: SdpcmHeader::SIZE as _,
|
||||||
|
wireless_flow_control: 0,
|
||||||
|
bus_data_credit: 0,
|
||||||
|
reserved: [0, 0],
|
||||||
|
};
|
||||||
|
|
||||||
|
let bcd_header = BcdHeader {
|
||||||
|
flags: 0x20,
|
||||||
|
priority: 0,
|
||||||
|
flags2: 0,
|
||||||
|
data_offset: 0,
|
||||||
|
};
|
||||||
|
trace!("tx {:?}", sdpcm_header);
|
||||||
|
trace!(" {:?}", bcd_header);
|
||||||
|
|
||||||
|
buf[0..SdpcmHeader::SIZE].copy_from_slice(&sdpcm_header.to_bytes());
|
||||||
|
buf[SdpcmHeader::SIZE..][..BcdHeader::SIZE].copy_from_slice(&bcd_header.to_bytes());
|
||||||
|
buf[SdpcmHeader::SIZE + BcdHeader::SIZE..][..packet.len()].copy_from_slice(packet);
|
||||||
|
|
||||||
|
let total_len = (total_len + 3) & !3; // round up to 4byte
|
||||||
|
|
||||||
|
trace!(" {:02x}", &buf[..total_len.min(48)]);
|
||||||
|
|
||||||
|
let cmd = cmd_word(true, true, FUNC_WLAN, 0, total_len as _);
|
||||||
|
self.cs.set_low();
|
||||||
|
self.spi_write(&cmd.to_le_bytes());
|
||||||
|
self.spi_write(&buf[..total_len]);
|
||||||
|
self.cs.set_high();
|
||||||
|
}
|
||||||
|
|
||||||
fn rx(&mut self, packet: &[u8]) {
|
fn rx(&mut self, packet: &[u8]) {
|
||||||
if packet.len() < SdpcmHeader::SIZE {
|
if packet.len() < SdpcmHeader::SIZE {
|
||||||
warn!("packet too short, len={}", packet.len());
|
warn!("packet too short, len={}", packet.len());
|
||||||
@ -683,6 +817,8 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> {
|
|||||||
assert_eq!(cdc_header.status, 0); // todo propagate error instead
|
assert_eq!(cdc_header.status, 0); // todo propagate error instead
|
||||||
|
|
||||||
let resp_len = cdc_header.len as usize;
|
let resp_len = cdc_header.len as usize;
|
||||||
|
info!("IOCTL Response: {:02x}", &payload[CdcHeader::SIZE..][..resp_len]);
|
||||||
|
|
||||||
(unsafe { &mut *buf }[..resp_len]).copy_from_slice(&payload[CdcHeader::SIZE..][..resp_len]);
|
(unsafe { &mut *buf }[..resp_len]).copy_from_slice(&payload[CdcHeader::SIZE..][..resp_len]);
|
||||||
self.state.ioctl_state.set(IoctlState::Done { resp_len });
|
self.state.ioctl_state.set(IoctlState::Done { resp_len });
|
||||||
}
|
}
|
||||||
@ -703,14 +839,32 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> {
|
|||||||
let mut evt = EventHeader::from_bytes(&packet[24..][..EventHeader::SIZE].try_into().unwrap());
|
let mut evt = EventHeader::from_bytes(&packet[24..][..EventHeader::SIZE].try_into().unwrap());
|
||||||
evt.byteswap();
|
evt.byteswap();
|
||||||
let evt_data = &packet[24 + EventHeader::SIZE..][..evt.datalen as usize];
|
let evt_data = &packet[24 + EventHeader::SIZE..][..evt.datalen as usize];
|
||||||
info!(
|
debug!(
|
||||||
"=== EVENT {}: {} {:02x}",
|
"=== EVENT {}: {} {:02x}",
|
||||||
events::Event::from(evt.event_type as u8),
|
events::Event::from(evt.event_type as u8),
|
||||||
evt,
|
evt,
|
||||||
evt_data
|
evt_data
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
2 => {
|
||||||
|
let bcd_header = BcdHeader::from_bytes(&payload[..BcdHeader::SIZE].try_into().unwrap());
|
||||||
|
trace!(" {:?}", 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..];
|
||||||
|
trace!("rx pkt {:02x}", &packet[..(packet.len() as usize).min(48)]);
|
||||||
|
|
||||||
|
let mut p = unwrap!(embassy_net::PacketBox::new(embassy_net::Packet::new()));
|
||||||
|
p[..packet.len()].copy_from_slice(packet);
|
||||||
|
|
||||||
|
if let Err(_) = self.state.rx_channel.try_send(p.slice(0..packet.len())) {
|
||||||
|
warn!("failed to push rxd packet to the channel.")
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use crate::events::Event;
|
||||||
|
|
||||||
macro_rules! impl_bytes {
|
macro_rules! impl_bytes {
|
||||||
($t:ident) => {
|
($t:ident) => {
|
||||||
impl $t {
|
impl $t {
|
||||||
@ -157,3 +159,10 @@ pub struct EventMask {
|
|||||||
pub events: [u8; 24],
|
pub events: [u8; 24],
|
||||||
}
|
}
|
||||||
impl_bytes!(EventMask);
|
impl_bytes!(EventMask);
|
||||||
|
|
||||||
|
impl EventMask {
|
||||||
|
pub fn unset(&mut self, evt: Event) {
|
||||||
|
let evt = evt as u8 as usize;
|
||||||
|
self.events[evt / 8] &= !(1 << (evt % 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user