rework event handling to allow sending data
This commit is contained in:
parent
6a1a3e6877
commit
2d7ba44621
7 changed files with 192 additions and 42 deletions
|
@ -1,11 +1,10 @@
|
|||
use core::slice;
|
||||
|
||||
use embassy_futures::yield_now;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embedded_hal_1::digital::OutputPin;
|
||||
use futures::FutureExt;
|
||||
|
||||
use crate::consts::*;
|
||||
use crate::slice8_mut;
|
||||
|
||||
/// Custom Spi Trait that _only_ supports the bus operation of the cyw43
|
||||
/// Implementors are expected to hold the CS pin low during an operation.
|
||||
|
@ -327,8 +326,3 @@ fn swap16(x: u32) -> u32 {
|
|||
fn cmd_word(write: bool, incr: bool, func: u32, addr: u32, len: u32) -> u32 {
|
||||
(write as u32) << 31 | (incr as u32) << 30 | (func & 0b11) << 28 | (addr & 0x1FFFF) << 11 | (len & 0x7FF)
|
||||
}
|
||||
|
||||
fn slice8_mut(x: &mut [u32]) -> &mut [u8] {
|
||||
let len = x.len() * 4;
|
||||
unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) }
|
||||
}
|
||||
|
|
|
@ -109,6 +109,50 @@ pub(crate) const READ: bool = false;
|
|||
pub(crate) const INC_ADDR: bool = true;
|
||||
pub(crate) const FIXED_ADDR: bool = false;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(u8)]
|
||||
pub enum EStatus {
|
||||
/// operation was successful
|
||||
SUCCESS = 0,
|
||||
/// operation failed
|
||||
FAIL = 1,
|
||||
/// operation timed out
|
||||
TIMEOUT = 2,
|
||||
/// failed due to no matching network found
|
||||
NO_NETWORKS = 3,
|
||||
/// operation was aborted
|
||||
ABORT = 4,
|
||||
/// protocol failure: packet not ack'd
|
||||
NO_ACK = 5,
|
||||
/// AUTH or ASSOC packet was unsolicited
|
||||
UNSOLICITED = 6,
|
||||
/// attempt to assoc to an auto auth configuration
|
||||
ATTEMPT = 7,
|
||||
/// scan results are incomplete
|
||||
PARTIAL = 8,
|
||||
/// scan aborted by another scan
|
||||
NEWSCAN = 9,
|
||||
/// scan aborted due to assoc in progress
|
||||
NEWASSOC = 10,
|
||||
/// 802.11h quiet period started
|
||||
_11HQUIET = 11,
|
||||
/// user disabled scanning (WLC_SET_SCANSUPPRESS)
|
||||
SUPPRESS = 12,
|
||||
/// no allowable channels to scan
|
||||
NOCHANS = 13,
|
||||
/// scan aborted due to CCX fast roam
|
||||
CCXFASTRM = 14,
|
||||
/// abort channel select
|
||||
CS_ABORT = 15,
|
||||
}
|
||||
|
||||
impl PartialEq<EStatus> for u32 {
|
||||
fn eq(&self, other: &EStatus) -> bool {
|
||||
*self == *other as Self
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) struct FormatStatus(pub u32);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use embassy_time::{Duration, Timer};
|
|||
|
||||
pub use crate::bus::SpiBusCyw43;
|
||||
use crate::consts::*;
|
||||
use crate::events::{Event, EventQueue};
|
||||
use crate::events::{Event, Events};
|
||||
use crate::fmt::Bytes;
|
||||
use crate::ioctl::{IoctlState, IoctlType};
|
||||
use crate::structs::*;
|
||||
|
@ -14,15 +14,15 @@ use crate::{countries, PowerManagementMode};
|
|||
|
||||
pub struct Control<'a> {
|
||||
state_ch: ch::StateRunner<'a>,
|
||||
event_sub: &'a EventQueue,
|
||||
events: &'a Events,
|
||||
ioctl_state: &'a IoctlState,
|
||||
}
|
||||
|
||||
impl<'a> Control<'a> {
|
||||
pub(crate) fn new(state_ch: ch::StateRunner<'a>, event_sub: &'a EventQueue, ioctl_state: &'a IoctlState) -> Self {
|
||||
pub(crate) fn new(state_ch: ch::StateRunner<'a>, event_sub: &'a Events, ioctl_state: &'a IoctlState) -> Self {
|
||||
Self {
|
||||
state_ch,
|
||||
event_sub,
|
||||
events: event_sub,
|
||||
ioctl_state,
|
||||
}
|
||||
}
|
||||
|
@ -195,24 +195,25 @@ impl<'a> Control<'a> {
|
|||
}
|
||||
|
||||
async fn wait_for_join(&mut self, i: SsidInfo) {
|
||||
let mut subscriber = self.event_sub.subscriber().unwrap();
|
||||
self.events.mask.enable(&[Event::JOIN, Event::AUTH]);
|
||||
let mut subscriber = self.events.queue.subscriber().unwrap();
|
||||
self.ioctl(IoctlType::Set, IOCTL_CMD_SET_SSID, 0, &mut i.to_bytes())
|
||||
.await;
|
||||
// set_ssid
|
||||
|
||||
loop {
|
||||
let msg = subscriber.next_message_pure().await;
|
||||
if msg.event_type == Event::AUTH && msg.status != 0 {
|
||||
if msg.header.event_type == Event::AUTH && msg.header.status != 0 {
|
||||
// retry
|
||||
warn!("JOIN failed with status={}", msg.status);
|
||||
warn!("JOIN failed with status={}", msg.header.status);
|
||||
self.ioctl(IoctlType::Set, IOCTL_CMD_SET_SSID, 0, &mut i.to_bytes())
|
||||
.await;
|
||||
} else if msg.event_type == Event::JOIN && msg.status == 0 {
|
||||
} else if msg.header.event_type == Event::JOIN && msg.header.status == 0 {
|
||||
// successful join
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self.events.mask.disable_all();
|
||||
self.state_ch.set_link_state(LinkState::Up);
|
||||
info!("JOINED");
|
||||
}
|
||||
|
|
111
src/events.rs
111
src/events.rs
|
@ -1,7 +1,7 @@
|
|||
#![allow(unused)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use core::num;
|
||||
use core::cell::RefCell;
|
||||
|
||||
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
||||
use embassy_sync::pubsub::{PubSubChannel, Publisher, Subscriber};
|
||||
|
@ -284,13 +284,114 @@ pub enum Event {
|
|||
LAST = 190,
|
||||
}
|
||||
|
||||
pub type EventQueue = PubSubChannel<NoopRawMutex, EventStatus, 2, 1, 1>;
|
||||
pub type EventPublisher<'a> = Publisher<'a, NoopRawMutex, EventStatus, 2, 1, 1>;
|
||||
pub type EventSubscriber<'a> = Subscriber<'a, NoopRawMutex, EventStatus, 2, 1, 1>;
|
||||
// TODO this PubSub can probably be replaced with shared memory to make it a bit more efficient.
|
||||
pub type EventQueue = PubSubChannel<NoopRawMutex, Message, 2, 1, 1>;
|
||||
pub type EventPublisher<'a> = Publisher<'a, NoopRawMutex, Message, 2, 1, 1>;
|
||||
pub type EventSubscriber<'a> = Subscriber<'a, NoopRawMutex, Message, 2, 1, 1>;
|
||||
|
||||
pub struct Events {
|
||||
pub queue: EventQueue,
|
||||
pub mask: SharedEventMask,
|
||||
}
|
||||
|
||||
impl Events {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
queue: EventQueue::new(),
|
||||
mask: SharedEventMask::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct EventStatus {
|
||||
pub struct Status {
|
||||
pub event_type: Event,
|
||||
pub status: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Payload {
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
pub struct Message {
|
||||
pub header: Status,
|
||||
pub payload: Payload,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn new(status: Status, payload: Payload) -> Self {
|
||||
Self {
|
||||
header: status,
|
||||
payload,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const EVENT_BITS: usize = ((Event::LAST as usize + 31) & !31) / 32;
|
||||
|
||||
#[derive(Default)]
|
||||
struct EventMask {
|
||||
mask: [u32; EVENT_BITS],
|
||||
}
|
||||
|
||||
impl EventMask {
|
||||
fn enable(&mut self, event: Event) {
|
||||
let n = event as u32;
|
||||
let word = n >> 5;
|
||||
let bit = n & 0b11111;
|
||||
|
||||
self.mask[word as usize] |= (1 << bit);
|
||||
}
|
||||
|
||||
fn disable(&mut self, event: Event) {
|
||||
let n = event as u32;
|
||||
let word = n >> 5;
|
||||
let bit = n & 0b11111;
|
||||
|
||||
self.mask[word as usize] &= !(1 << bit);
|
||||
}
|
||||
|
||||
fn is_enabled(&self, event: Event) -> bool {
|
||||
let n = event as u32;
|
||||
let word = n >> 5;
|
||||
let bit = n & 0b11111;
|
||||
|
||||
self.mask[word as usize] & (1 << bit) > 0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
||||
pub struct SharedEventMask {
|
||||
mask: RefCell<EventMask>,
|
||||
}
|
||||
|
||||
impl SharedEventMask {
|
||||
pub fn enable(&self, events: &[Event]) {
|
||||
let mut mask = self.mask.borrow_mut();
|
||||
for event in events {
|
||||
mask.enable(*event);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn disable(&self, events: &[Event]) {
|
||||
let mut mask = self.mask.borrow_mut();
|
||||
for event in events {
|
||||
mask.disable(*event);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn disable_all(&self) {
|
||||
let mut mask = self.mask.borrow_mut();
|
||||
mask.mask = Default::default();
|
||||
}
|
||||
|
||||
pub fn is_enabled(&self, event: Event) -> bool {
|
||||
let mask = self.mask.borrow();
|
||||
mask.is_enabled(event)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ use core::task::{Poll, Waker};
|
|||
|
||||
use embassy_sync::waitqueue::WakerRegistration;
|
||||
|
||||
use crate::fmt::Bytes;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum IoctlType {
|
||||
Get = 0,
|
||||
|
@ -100,6 +102,8 @@ impl IoctlState {
|
|||
|
||||
pub fn ioctl_done(&self, response: &[u8]) {
|
||||
if let IoctlStateInner::Sent { buf } = self.state.get() {
|
||||
info!("IOCTL Response: {:02x}", Bytes(response));
|
||||
|
||||
// TODO fix this
|
||||
(unsafe { &mut *buf }[..response.len()]).copy_from_slice(response);
|
||||
|
||||
|
@ -107,6 +111,8 @@ impl IoctlState {
|
|||
resp_len: response.len(),
|
||||
});
|
||||
self.wake_control();
|
||||
} else {
|
||||
warn!("IOCTL Response but no pending Ioctl");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -18,9 +18,11 @@ mod control;
|
|||
mod nvram;
|
||||
mod runner;
|
||||
|
||||
use core::slice;
|
||||
|
||||
use embassy_net_driver_channel as ch;
|
||||
use embedded_hal_1::digital::OutputPin;
|
||||
use events::EventQueue;
|
||||
use events::Events;
|
||||
use ioctl::IoctlState;
|
||||
|
||||
use crate::bus::Bus;
|
||||
|
@ -103,7 +105,7 @@ const CHIP: Chip = Chip {
|
|||
pub struct State {
|
||||
ioctl_state: IoctlState,
|
||||
ch: ch::State<MTU, 4, 4>,
|
||||
events: EventQueue,
|
||||
events: Events,
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
@ -111,7 +113,7 @@ impl State {
|
|||
Self {
|
||||
ioctl_state: IoctlState::new(),
|
||||
ch: ch::State::new(),
|
||||
events: EventQueue::new(),
|
||||
events: Events::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,3 +227,8 @@ where
|
|||
runner,
|
||||
)
|
||||
}
|
||||
|
||||
fn slice8_mut(x: &mut [u32]) -> &mut [u8] {
|
||||
let len = x.len() * 4;
|
||||
unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) }
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use core::slice;
|
||||
|
||||
use embassy_futures::select::{select3, Either3};
|
||||
use embassy_net_driver_channel as ch;
|
||||
use embassy_sync::pubsub::PubSubBehavior;
|
||||
|
@ -9,12 +7,12 @@ use embedded_hal_1::digital::OutputPin;
|
|||
use crate::bus::Bus;
|
||||
pub use crate::bus::SpiBusCyw43;
|
||||
use crate::consts::*;
|
||||
use crate::events::{EventQueue, EventStatus};
|
||||
use crate::events::{Events, Status};
|
||||
use crate::fmt::Bytes;
|
||||
use crate::ioctl::{IoctlState, IoctlType, PendingIoctl};
|
||||
use crate::nvram::NVRAM;
|
||||
use crate::structs::*;
|
||||
use crate::{events, Core, CHIP, MTU};
|
||||
use crate::{events, slice8_mut, Core, CHIP, MTU};
|
||||
|
||||
#[cfg(feature = "firmware-logs")]
|
||||
struct LogState {
|
||||
|
@ -45,7 +43,7 @@ pub struct Runner<'a, PWR, SPI> {
|
|||
sdpcm_seq: u8,
|
||||
sdpcm_seq_max: u8,
|
||||
|
||||
events: &'a EventQueue,
|
||||
events: &'a Events,
|
||||
|
||||
#[cfg(feature = "firmware-logs")]
|
||||
log: LogState,
|
||||
|
@ -60,7 +58,7 @@ where
|
|||
ch: ch::Runner<'a, MTU>,
|
||||
bus: Bus<PWR, SPI>,
|
||||
ioctl_state: &'a IoctlState,
|
||||
events: &'a EventQueue,
|
||||
events: &'a Events,
|
||||
) -> Self {
|
||||
Self {
|
||||
ch,
|
||||
|
@ -353,8 +351,6 @@ where
|
|||
panic!("IOCTL error {}", cdc_header.status as i32);
|
||||
}
|
||||
|
||||
info!("IOCTL Response: {:02x}", Bytes(response));
|
||||
|
||||
self.ioctl_state.ioctl_done(response);
|
||||
}
|
||||
}
|
||||
|
@ -406,11 +402,17 @@ where
|
|||
Bytes(evt_data)
|
||||
);
|
||||
|
||||
if evt_type == events::Event::AUTH || evt_type == events::Event::JOIN {
|
||||
self.events.publish_immediate(EventStatus {
|
||||
status: event_packet.msg.status,
|
||||
if self.events.mask.is_enabled(evt_type) {
|
||||
let status = event_packet.msg.status;
|
||||
let event_payload = events::Payload::None;
|
||||
|
||||
self.events.queue.publish_immediate(events::Message::new(
|
||||
Status {
|
||||
event_type: evt_type,
|
||||
});
|
||||
status,
|
||||
},
|
||||
event_payload,
|
||||
));
|
||||
}
|
||||
}
|
||||
CHANNEL_TYPE_DATA => {
|
||||
|
@ -548,8 +550,3 @@ where
|
|||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn slice8_mut(x: &mut [u32]) -> &mut [u8] {
|
||||
let len = x.len() * 4;
|
||||
unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue