Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cyw43: Add Control method to add multicast HW address #2184

Merged
merged 1 commit into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions cyw43/src/control.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::cmp::{max, min};
use core::iter::zip;

use embassy_net_driver_channel as ch;
use embassy_net_driver_channel::driver::{HardwareAddress, LinkState};
Expand All @@ -16,6 +17,12 @@ pub struct Error {
pub status: u32,
}

#[derive(Debug)]
pub enum AddMulticastAddressError {
NotMulticast,
NoFreeSlots,
}

sammko marked this conversation as resolved.
Show resolved Hide resolved
pub struct Control<'a> {
state_ch: ch::StateRunner<'a>,
events: &'a Events,
Expand Down Expand Up @@ -316,6 +323,54 @@ impl<'a> Control<'a> {
self.set_iovar_u32x2("bss", 0, 1).await; // bss = BSS_UP
}

/// Add specified address to the list of hardware addresses the device
/// listens on. The address must be a Group address (I/G bit set). Up
/// to 10 addresses are supported by the firmware. Returns the number of
/// address slots filled after adding, or an error.
pub async fn add_multicast_address(&mut self, address: [u8; 6]) -> Result<usize, AddMulticastAddressError> {
// The firmware seems to ignore non-multicast addresses, so let's
// prevent the user from adding them and wasting space.
if address[0] & 0x01 != 1 {
return Err(AddMulticastAddressError::NotMulticast);
}

let mut buf = [0; 64];
self.get_iovar("mcast_list", &mut buf).await;

let n = u32::from_le_bytes(buf[..4].try_into().unwrap()) as usize;
let (used, free) = buf[4..].split_at_mut(n * 6);

if used.chunks(6).any(|a| a == address) {
return Ok(n);
}

if free.len() < 6 {
return Err(AddMulticastAddressError::NoFreeSlots);
}

free[..6].copy_from_slice(&address);
let n = n + 1;
buf[..4].copy_from_slice(&(n as u32).to_le_bytes());

self.set_iovar_v::<80>("mcast_list", &buf).await;
Ok(n)
}

/// Retrieve the list of configured multicast hardware addresses.
pub async fn list_mulistcast_addresses(&mut self, result: &mut [[u8; 6]; 10]) -> usize {
let mut buf = [0; 64];
self.get_iovar("mcast_list", &mut buf).await;

let n = u32::from_le_bytes(buf[..4].try_into().unwrap()) as usize;
let used = &buf[4..][..n * 6];

for (addr, output) in zip(used.chunks(6), result.iter_mut()) {
output.copy_from_slice(addr)
}

n
}

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());
Expand Down
2 changes: 1 addition & 1 deletion cyw43/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use ioctl::IoctlState;

use crate::bus::Bus;
pub use crate::bus::SpiBusCyw43;
pub use crate::control::{Control, Error as ControlError, Scanner};
pub use crate::control::{AddMulticastAddressError, Control, Error as ControlError, Scanner};
pub use crate::runner::Runner;
pub use crate::structs::BssInfo;

Expand Down