-
Notifications
You must be signed in to change notification settings - Fork 10
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
New module for integrating Matter into RIOT OS #92
base: main
Are you sure you want to change the base?
Changes from 2 commits
093983d
faaed06
a67c93e
6b517bc
1190442
fe1aa07
1ffbcf0
2d946f2
5e62302
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
use riot_sys::gnrc_nettype_t; | ||
|
||
use crate::gnrc::pktbuf::{Pktsnip, Shared}; | ||
use riot_sys::inline::gnrc_netapi_set; | ||
use riot_sys::{netopt_t_NETOPT_IPV6_GROUP, size_t}; | ||
use crate::thread::KernelPID; | ||
use core::ffi::c_void; | ||
|
||
/// Dispatch a packet to all listeners of the given nettype and demux context. | ||
/// | ||
|
@@ -21,3 +24,11 @@ pub fn dispatch_send( | |
} | ||
subscribers | ||
} | ||
|
||
/// Joins an IPV6 multicast group at the provided address | ||
pub fn join_multicast_v6(pid: KernelPID, addr: &[u8; 16]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is sure a more suitable type for an IP address than [u8; 16]; too many to pick from, maybe (given there is gnrc::Address but now also core::net::Ipv6Addr, I'd pick the latter for new code). The pid parameter could be named There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. embedded-nal also has the Ipv6Addr type. Wouldn't it make more sense to use this one? Using core::net::Ipv6Addr, we would have two different types then in riot-wrappers for the same purpose. |
||
unsafe { | ||
let addr_ptr = addr.as_ptr() as *const c_void; | ||
let _ = gnrc_netapi_set(pid.into(), netopt_t_NETOPT_IPV6_GROUP, 0, addr_ptr, addr.len() as size_t); | ||
maikerlab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
use crate::println; | ||
maikerlab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
use crate::mutex::Mutex; | ||
use crate::socket_embedded_nal_async_udp::UnconnectedUdpSocket; | ||
use crate::ztimer; | ||
|
||
use embedded_nal_async::{SocketAddr, UnconnectedUdp}; | ||
use embassy_futures::select::{Either, select}; | ||
use embedded_hal_async::delay::DelayNs as _; | ||
use embassy_sync::{ | ||
signal::Signal, | ||
blocking_mutex::raw::NoopRawMutex, | ||
}; | ||
use rs_matter::error::{Error, ErrorCode}; | ||
use rs_matter::transport::network::{UdpReceive, UdpSend}; | ||
use log::{debug, warn, error, Level, LevelFilter, Log, Record, SetLoggerError}; | ||
|
||
pub struct MatterCompatUdpSocket { | ||
local_addr: SocketAddr, | ||
socket: Mutex<UnconnectedUdpSocket>, | ||
release_socket_notification: Notification, | ||
socket_released_notification: Notification, | ||
} | ||
|
||
struct RiotLogger; | ||
|
||
pub type Notification = Signal<NoopRawMutex, ()>; | ||
|
||
static LOGGER: RiotLogger = RiotLogger; | ||
|
||
impl Log for RiotLogger { | ||
fn enabled(&self, metadata: &log::Metadata) -> bool { | ||
metadata.level() >= Level::Info | ||
} | ||
|
||
fn log(&self, record: &Record) { | ||
if self.enabled(record.metadata()) { | ||
println!("[{}] {}", record.level(), record.args()); | ||
} | ||
} | ||
|
||
fn flush(&self) {} | ||
} | ||
|
||
pub fn init_logger(level: LevelFilter) -> Result<(), SetLoggerError> { | ||
log::set_logger(&LOGGER) | ||
.map(|_| log::set_max_level(level)) | ||
} | ||
|
||
impl MatterCompatUdpSocket { | ||
pub fn new(local_addr: SocketAddr, socket: UnconnectedUdpSocket) -> Self { | ||
Self { | ||
local_addr, | ||
socket: Mutex::new(socket), | ||
release_socket_notification: Notification::new(), | ||
socket_released_notification: Notification::new(), | ||
} | ||
} | ||
} | ||
|
||
impl UdpSend for &MatterCompatUdpSocket { | ||
async fn send_to(&mut self, data: &[u8], addr: SocketAddr) -> Result<(), Error> { | ||
if addr.is_ipv4() { | ||
// IPv4 not supported! | ||
return Ok(()); | ||
} | ||
// Tell recv_from to release mutex | ||
self.release_socket_notification.signal(()); | ||
ztimer::Delay.delay_ms(10).await; | ||
let mut sock = self.socket.try_lock().expect("receiver should have ensured that this mutex is free"); | ||
sock.send(self.local_addr, addr, data) | ||
.await | ||
.map_err(|_| Error::new(ErrorCode::StdIoError))?; | ||
// Release socket and notify recv_from -> sending is finished | ||
drop(sock); | ||
self.socket_released_notification.signal(()); | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl UdpReceive for &MatterCompatUdpSocket { | ||
async fn recv_from(&mut self, buffer: &mut [u8]) -> Result<(usize, SocketAddr), Error> { | ||
loop { | ||
let mut sock = self.socket.try_lock().expect("sender should have ensured that this mutex is free"); | ||
match select( | ||
self.release_socket_notification.wait(), | ||
sock.receive_into(buffer), | ||
).await { | ||
Either::First(_) => { | ||
// Release Mutex for send_to | ||
drop(sock); | ||
// ... and wait until available again | ||
self.socket_released_notification.wait().await; | ||
continue; | ||
} | ||
Either::Second(res) => { | ||
match res { | ||
Ok((bytes_recvd, local_addr, remote_addr)) => { | ||
if remote_addr.is_ipv4() { | ||
// IPv4 not supported! | ||
return Ok((bytes_recvd, remote_addr)); | ||
} | ||
} | ||
Err(_) => { error!("Error during UDP receive!"); } | ||
} | ||
// return receive result | ||
let (bytes_recvd, remote_addr) = res.map(|(bytes_recvd, _, remote_addr)| | ||
(bytes_recvd, remote_addr) | ||
).map_err(|_| Error::new(ErrorCode::StdIoError))?; | ||
return Ok((bytes_recvd, remote_addr)); | ||
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it foreseeable that the adjustments there can be upstreamed? Are there open PRs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, not yet. I will discuss this with rs-matter contributors, bc it's also not ideal if all the possible specific adaptations for different OS etc. are in this repo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked again and I guess we could get rid of all the changes I made in rs-matter.
The only "big" task which needs to be done is implementing embassy-time-driver and embassy-time-queue-driver using ztimer.