Skip to content

Commit 496a362

Browse files
committed
Make indirect indications possible
1 parent 464e5b7 commit 496a362

File tree

6 files changed

+100
-24
lines changed

6 files changed

+100
-24
lines changed

lr-wpan-rs/src/mac/commander.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
use crate::{
22
allocation::{Allocated, Allocation},
3-
reqresp::ReqResp,
3+
reqresp::{ReqResp, RequestFuture},
44
sap::{
55
ConfirmValue, DynamicRequest, Indication, IndicationValue, Request, RequestValue,
66
ResponseValue,
77
},
88
};
99

10+
pub const CHANNEL_SIZE: usize = 4;
11+
1012
/// The main interface to the MAC layer. It can be used to make requests and receive indications
1113
pub struct MacCommander {
12-
request_confirm_channel: ReqResp<RequestValue, ConfirmValue, 4>,
13-
indication_response_channel: ReqResp<IndicationValue, ResponseValue, 4>,
14+
request_confirm_channel: ReqResp<RequestValue, ConfirmValue, CHANNEL_SIZE>,
15+
indication_response_channel: ReqResp<IndicationValue, ResponseValue, CHANNEL_SIZE>,
1416
}
1517

1618
impl MacCommander {
@@ -85,8 +87,12 @@ impl Default for MacCommander {
8587
}
8688
}
8789

90+
pub type IndicateIndirectFuture<'a> =
91+
RequestFuture<'a, IndicationValue, ResponseValue, CHANNEL_SIZE>;
92+
8893
pub(crate) struct MacHandler<'a> {
8994
commander: &'a MacCommander,
95+
9096
}
9197

9298
impl MacHandler<'_> {
@@ -99,6 +105,14 @@ impl MacHandler<'_> {
99105
.into()
100106
}
101107

108+
/// Send an indication, but don't immediately wait on it.
109+
/// Instead the response wait is put in a buffer so it can be dealt with later.
110+
pub fn indicate_indirect<I: Indication>(&self, indication: I) -> IndicateIndirectFuture<'_> {
111+
self.commander
112+
.indication_response_channel
113+
.request(indication.into())
114+
}
115+
102116
pub async fn wait_for_request(&self) -> RequestResponder<'_, RequestValue> {
103117
let (id, request) = self
104118
.commander

lr-wpan-rs/src/mac/mlme_associate.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
use super::{
22
callback::DataRequestCallback,
3-
commander::RequestResponder,
3+
commander::{MacHandler, RequestResponder},
44
state::{DataRequestMode, MacState, ScheduledDataRequest},
55
};
66
use crate::{
77
phy::{Phy, SendContinuation, SendResult},
88
pib::MacPib,
99
sap::{
10-
associate::{AssociateConfirm, AssociateRequest},
10+
associate::{AssociateConfirm, AssociateIndication, AssociateRequest},
1111
SecurityInfo, Status,
1212
},
1313
wire::{
14-
command::Command, Address, Frame, FrameContent, FrameType, FrameVersion, Header, PanId,
15-
ShortAddress,
16-
},
14+
command::{CapabilityInformation, Command}, Address, ExtendedAddress, Frame, FrameContent, FrameType, FrameVersion, Header, PanId, ShortAddress
15+
}, DeviceAddress,
1716
};
1817

1918
pub async fn process_associate_request<'a>(
@@ -152,7 +151,7 @@ pub async fn process_associate_request<'a>(
152151
return;
153152
};
154153

155-
debug!("Association procedure now waiting until");
154+
debug!("Association procedure now waiting until the response can be requested");
156155

157156
// We have received the ack to our association request.
158157
// Now we must wait and request our data later.
@@ -172,3 +171,14 @@ pub async fn process_associate_request<'a>(
172171
callback: DataRequestCallback::AssociationProcedure(responder),
173172
});
174173
}
174+
175+
// Received from the radio, not as an MLME request
176+
pub async fn process_received_associate_request(mac_handler: &MacHandler<'_>, device_address: ExtendedAddress, capability_information: CapabilityInformation) {
177+
let indirect_response = mac_handler.indicate_indirect(AssociateIndication {
178+
device_address,
179+
capability_information,
180+
security_info: SecurityInfo::new_none_security(),
181+
});
182+
183+
// TODO: Store the indirect_response and await it later
184+
}

lr-wpan-rs/src/mac/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,5 +837,25 @@ async fn process_message<P: Phy>(
837837
});
838838
}
839839

840+
match frame.content {
841+
FrameContent::Command(Command::AssociationRequest(capability_info)) => {
842+
match frame.header.source {
843+
Some(Address::Extended(_, device_address)) => {
844+
mlme_associate::process_received_associate_request(
845+
mac_handler,
846+
device_address,
847+
capability_info,
848+
)
849+
.await
850+
}
851+
_ => warn!("Association request came from frame without correct source field"),
852+
}
853+
}
854+
content => warn!(
855+
"Received frame has content we don't yet process: {}",
856+
content
857+
),
858+
}
859+
840860
next_event
841861
}

lr-wpan-rs/src/pib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ impl MacPib {
522522
min_be: 0,
523523
pan_id: PanId::broadcast(),
524524
promiscuous_mode: false,
525-
response_wait_time: 2,
525+
response_wait_time: 64,
526526
rx_on_when_idle: false,
527527
security_enabled: false,
528528
short_address: ShortAddress::BROADCAST,

lr-wpan-rs/src/reqresp.rs

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
use core::sync::atomic::{AtomicU32, Ordering};
2-
3-
use embassy_futures::join::join;
4-
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel};
5-
use maitake_sync::WaitMap;
1+
use core::{
2+
future::Future,
3+
sync::atomic::{AtomicU32, Ordering},
4+
task::Poll,
5+
};
6+
7+
use embassy_futures::join::{join, Join};
8+
use embassy_sync::{
9+
blocking_mutex::raw::CriticalSectionRawMutex,
10+
channel::{Channel, SendFuture},
11+
};
12+
use maitake_sync::{wait_map::Wait, WaitMap};
613

714
pub struct ReqResp<Request, Response, const N: usize> {
815
requests: Channel<CriticalSectionRawMutex, (u32, Request), N>,
@@ -19,16 +26,15 @@ impl<Request, Response, const N: usize> ReqResp<Request, Response, N> {
1926
}
2027
}
2128

22-
pub async fn request(&self, request: Request) -> Response {
29+
pub fn request(&self, request: Request) -> RequestFuture<Request, Response, N> {
2330
let current_id = self.next_id.fetch_add(1, Ordering::Relaxed);
2431

25-
let (response, _) = join(
26-
self.responses.wait(current_id),
27-
self.requests.send((current_id, request)),
28-
)
29-
.await;
30-
31-
response.expect("Always succeeds because we use a unique ID")
32+
RequestFuture {
33+
inner: join(
34+
self.responses.wait(current_id),
35+
self.requests.send((current_id, request)),
36+
),
37+
}
3238
}
3339

3440
pub async fn wait_for_request(&self) -> (u32, Request) {
@@ -40,6 +46,30 @@ impl<Request, Response, const N: usize> ReqResp<Request, Response, N> {
4046
}
4147
}
4248

49+
pub struct RequestFuture<'a, Request, Response, const N: usize> {
50+
inner:
51+
Join<Wait<'a, u32, Response>, SendFuture<'a, CriticalSectionRawMutex, (u32, Request), N>>,
52+
}
53+
54+
impl<'a, Request, Response, const N: usize> Future for RequestFuture<'a, Request, Response, N> {
55+
type Output = Response;
56+
57+
fn poll(
58+
self: core::pin::Pin<&mut Self>,
59+
cx: &mut core::task::Context<'_>,
60+
) -> Poll<Self::Output> {
61+
// Safety: Inner is just as pinned as the outer, so it should be safe to project
62+
let inner = unsafe { core::pin::Pin::new_unchecked(&mut self.get_unchecked_mut().inner) };
63+
64+
match inner.poll(cx) {
65+
Poll::Ready((response, _)) => {
66+
Poll::Ready(response.expect("Always succeeds because we use a unique ID"))
67+
}
68+
Poll::Pending => Poll::Pending,
69+
}
70+
}
71+
}
72+
4373
#[cfg(test)]
4474
mod tests {
4575
use embassy_futures::join::join_array;

lr-wpan-rs/src/wire/frame/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub mod security;
1919
use byte::{ctx::Bytes, BytesExt, TryRead, TryWrite, LE};
2020
use ccm::aead::generic_array::typenum::consts::U16;
2121
use cipher::{BlockCipher, BlockEncrypt, NewBlockCipher};
22+
use derive_more::Display;
2223
use header::FrameType;
2324
pub use header::Header;
2425

@@ -387,8 +388,9 @@ impl Default for FooterMode {
387388
}
388389

389390
/// Content of a frame
390-
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
391+
#[derive(Clone, Debug, Eq, Hash, PartialEq, Display)]
391392
#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
393+
#[display("{self:?}")]
392394
pub enum FrameContent {
393395
/// Beacon frame content
394396
Beacon(Beacon),

0 commit comments

Comments
 (0)