[uwb] Support updateMulticastListNtf for both Fira 1.x and 2.0.
patched from aosp/3018363
Bug: 331836038
Test: manual
Change-Id: I121c9e527d1e94d63c8be6da2512bd7f75d26275
diff --git a/src/rust/uwb_core/src/params/uci_packets.rs b/src/rust/uwb_core/src/params/uci_packets.rs
index 6f42e3b..8ccb0ce 100644
--- a/src/rust/uwb_core/src/params/uci_packets.rs
+++ b/src/rust/uwb_core/src/params/uci_packets.rs
@@ -18,19 +18,22 @@
use std::collections::{hash_map::RandomState, HashMap};
use std::iter::FromIterator;
+use num_derive::{FromPrimitive, ToPrimitive};
+
// Re-export enums and structs from uwb_uci_packets.
pub use uwb_uci_packets::{
AppConfigStatus, AppConfigTlv as RawAppConfigTlv, AppConfigTlvType, BitsPerSample, CapTlv,
- CapTlvType, Controlee, ControleePhaseList, ControleeStatus, Controlees, CreditAvailability,
- DataRcvStatusCode, DataTransferNtfStatusCode, DataTransferPhaseConfigUpdateStatusCode,
- DeviceConfigId, DeviceConfigStatus, DeviceConfigTlv, DeviceState,
- ExtendedAddressDlTdoaRangingMeasurement, ExtendedAddressOwrAoaRangingMeasurement,
- ExtendedAddressTwoWayRangingMeasurement, GroupId, MacAddressIndicator,
- MessageType, MulticastUpdateStatusCode, PhaseList, PowerStats, RadarConfigStatus,
- RadarConfigTlv, RadarConfigTlvType, RadarDataType, RangingMeasurementType, ReasonCode,
- ResetConfig, SessionState, SessionType, ShortAddressDlTdoaRangingMeasurement,
- ShortAddressOwrAoaRangingMeasurement, ShortAddressTwoWayRangingMeasurement,
- StatusCode, UpdateMulticastListAction,
+ CapTlvType, Controlee, ControleePhaseList, ControleeStatusV1, ControleeStatusV2, Controlees,
+ CreditAvailability, DataRcvStatusCode, DataTransferNtfStatusCode,
+ DataTransferPhaseConfigUpdateStatusCode, DeviceConfigId, DeviceConfigStatus, DeviceConfigTlv,
+ DeviceState, ExtendedAddressDlTdoaRangingMeasurement, ExtendedAddressOwrAoaRangingMeasurement,
+ ExtendedAddressTwoWayRangingMeasurement, GroupId, MacAddressIndicator, MessageType,
+ MulticastUpdateStatusCode, PhaseList, PowerStats, RadarConfigStatus, RadarConfigTlv,
+ RadarConfigTlvType, RadarDataType, RangingMeasurementType, ReasonCode, ResetConfig,
+ SessionState, SessionType, SessionUpdateControllerMulticastListNtfV1Payload,
+ SessionUpdateControllerMulticastListNtfV2Payload, ShortAddressDlTdoaRangingMeasurement,
+ ShortAddressOwrAoaRangingMeasurement, ShortAddressTwoWayRangingMeasurement, StatusCode,
+ UpdateMulticastListAction,
};
pub(crate) use uwb_uci_packets::{UciControlPacket, UciDataPacket, UciDataPacketHal};
@@ -51,6 +54,24 @@
tlv: RawAppConfigTlv,
}
+/// Controlee Status Enum compatible with different Fira version.
+pub enum ControleeStatusList {
+ /// Controlee status defined in Fira 1.x.
+ V1(Vec<ControleeStatusV1>),
+ /// Controlee status defined in Fira 2.0.
+ V2(Vec<ControleeStatusV2>),
+}
+
+/// UCI major version
+#[derive(FromPrimitive, ToPrimitive, PartialEq, Clone)]
+#[repr(u8)]
+pub enum UCIMajorVersion {
+ /// Version 1.x
+ V1 = 1,
+ /// Version 2.0
+ V2 = 2,
+}
+
impl std::fmt::Debug for AppConfigTlv {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
static REDACTED_STR: &str = "redacted";
diff --git a/src/rust/uwb_core/src/session/session_manager.rs b/src/rust/uwb_core/src/session/session_manager.rs
index 40801fa..5436747 100644
--- a/src/rust/uwb_core/src/session/session_manager.rs
+++ b/src/rust/uwb_core/src/session/session_manager.rs
@@ -20,7 +20,8 @@
use crate::error::{Error, Result};
use crate::params::app_config_params::AppConfigParams;
use crate::params::uci_packets::{
- Controlee, ReasonCode, SessionId, SessionState, SessionType, UpdateMulticastListAction,
+ Controlee, ControleeStatusList, ReasonCode, SessionId, SessionState, SessionType,
+ UpdateMulticastListAction,
};
use crate::session::uwb_session::{Response as SessionResponse, ResponseSender, UwbSession};
use crate::uci::notification::{SessionNotification as UciSessionNotification, SessionRangeData};
@@ -295,7 +296,11 @@
fn handle_uci_notification(&mut self, notf: UciSessionNotification) {
match notf {
UciSessionNotification::Status {
- session_id:_, session_token, session_state, reason_code } => {
+ session_id: _,
+ session_token,
+ session_state,
+ reason_code,
+ } => {
let reason_code = match ReasonCode::try_from(reason_code) {
Ok(r) => r,
Err(_) => {
@@ -334,12 +339,26 @@
}
}
}
- UciSessionNotification::UpdateControllerMulticastList {
+ UciSessionNotification::UpdateControllerMulticastListV1 {
session_token,
remaining_multicast_list_size: _,
status_list,
} => match self.active_sessions.get_mut(&session_token) {
- Some(session) => session.on_controller_multicast_list_udpated(status_list),
+ Some(session) => session
+ .on_controller_multicast_list_updated(ControleeStatusList::V1(status_list)),
+ None => {
+ warn!(
+ "Received the notification of the unknown Session {}: {:?}",
+ session_token, status_list
+ );
+ }
+ },
+ UciSessionNotification::UpdateControllerMulticastListV2 {
+ session_token,
+ status_list,
+ } => match self.active_sessions.get_mut(&session_token) {
+ Some(session) => session
+ .on_controller_multicast_list_updated(ControleeStatusList::V2(status_list)),
None => {
warn!(
"Received the notification of the unknown Session {}: {:?}",
@@ -586,7 +605,7 @@
use crate::params::ccc_started_app_config_params::CccStartedAppConfigParams;
use crate::params::uci_packets::{
- AppConfigTlv, AppConfigTlvType, ControleeStatus, Controlees, MulticastUpdateStatusCode,
+ AppConfigTlv, AppConfigTlvType, ControleeStatusV1, Controlees, MulticastUpdateStatusCode,
ReasonCode, SetAppConfigResponse, StatusCode,
};
use crate::params::utils::{u32_to_bytes, u64_to_bytes, u8_to_bytes};
@@ -812,10 +831,10 @@
let (mut session_manager, mut mock_uci_manager, _) =
setup_session_manager(move |uci_manager| {
let multicast_list_notf = vec![UciNotification::Session(
- UciSessionNotification::UpdateControllerMulticastList {
+ UciSessionNotification::UpdateControllerMulticastListV1 {
session_token: session_id,
remaining_multicast_list_size: 1,
- status_list: vec![ControleeStatus {
+ status_list: vec![ControleeStatusV1 {
mac_address: [0x34, 0x12],
subsession_id: 0x24,
status: MulticastUpdateStatusCode::StatusOkMulticastListUpdate,
diff --git a/src/rust/uwb_core/src/session/uwb_session.rs b/src/rust/uwb_core/src/session/uwb_session.rs
index 37fcba4..d41b693 100644
--- a/src/rust/uwb_core/src/session/uwb_session.rs
+++ b/src/rust/uwb_core/src/session/uwb_session.rs
@@ -24,7 +24,7 @@
use crate::params::app_config_params::AppConfigParams;
use crate::params::ccc_started_app_config_params::CccStartedAppConfigParams;
use crate::params::uci_packets::{
- Controlee, ControleeStatus, Controlees, MulticastUpdateStatusCode, SessionId, SessionState,
+ Controlee, ControleeStatusList, Controlees, MulticastUpdateStatusCode, SessionId, SessionState,
SessionType, UpdateMulticastListAction,
};
use crate::uci::error::status_code_to_result;
@@ -42,7 +42,7 @@
pub(super) struct UwbSession {
cmd_sender: mpsc::UnboundedSender<(Command, ResponseSender)>,
state_sender: watch::Sender<SessionState>,
- controlee_status_notf_sender: Option<oneshot::Sender<Vec<ControleeStatus>>>,
+ controlee_status_notf_sender: Option<oneshot::Sender<ControleeStatusList>>,
}
impl UwbSession {
@@ -110,7 +110,7 @@
let _ = self.state_sender.send(state);
}
- pub fn on_controller_multicast_list_udpated(&mut self, status_list: Vec<ControleeStatus>) {
+ pub fn on_controller_multicast_list_updated(&mut self, status_list: ControleeStatusList) {
if let Some(sender) = self.controlee_status_notf_sender.take() {
let _ = sender.send(status_list);
}
@@ -294,7 +294,7 @@
&mut self,
action: UpdateMulticastListAction,
controlees: Vec<Controlee>,
- notf_receiver: oneshot::Receiver<Vec<ControleeStatus>>,
+ notf_receiver: oneshot::Receiver<ControleeStatusList>,
) -> Result<Response> {
if self.session_type == SessionType::Ccc {
error!("Cannot update multicast list for CCC session");
@@ -329,10 +329,22 @@
// Check the update status for adding new controlees.
if action == UpdateMulticastListAction::AddControlee {
- for result in results.iter() {
- if result.status != MulticastUpdateStatusCode::StatusOkMulticastListUpdate {
- error!("Failed to update multicast list: {:?}", result);
- return Err(Error::Unknown);
+ match results {
+ ControleeStatusList::V1(res) => {
+ for result in res.iter() {
+ if result.status != MulticastUpdateStatusCode::StatusOkMulticastListUpdate {
+ error!("Failed to update multicast list: {:?}", result);
+ return Err(Error::Unknown);
+ }
+ }
+ }
+ ControleeStatusList::V2(res) => {
+ for result in res.iter() {
+ if result.status != MulticastUpdateStatusCode::StatusOkMulticastListUpdate {
+ error!("Failed to update multicast list: {:?}", result);
+ return Err(Error::Unknown);
+ }
+ }
}
}
}
@@ -387,7 +399,7 @@
UpdateControllerMulticastList {
action: UpdateMulticastListAction,
controlees: Vec<Controlee>,
- notf_receiver: oneshot::Receiver<Vec<ControleeStatus>>,
+ notf_receiver: oneshot::Receiver<ControleeStatusList>,
},
GetParams,
}
diff --git a/src/rust/uwb_core/src/uci/message.rs b/src/rust/uwb_core/src/uci/message.rs
index fcbc65d..a4f72e8 100644
--- a/src/rust/uwb_core/src/uci/message.rs
+++ b/src/rust/uwb_core/src/uci/message.rs
@@ -20,21 +20,27 @@
use crate::uci::notification::UciNotification;
use crate::uci::response::UciResponse;
+use crate::params::UCIMajorVersion;
+
#[derive(Debug)]
pub(super) enum UciMessage {
Response(UciResponse),
Notification(UciNotification),
}
-impl TryFrom<uwb_uci_packets::UciControlPacket> for UciMessage {
+impl TryFrom<(uwb_uci_packets::UciControlPacket, UCIMajorVersion)> for UciMessage {
type Error = Error;
- fn try_from(packet: uwb_uci_packets::UciControlPacket) -> Result<Self, Self::Error> {
+ fn try_from(
+ pair: (uwb_uci_packets::UciControlPacket, UCIMajorVersion),
+ ) -> Result<Self, Self::Error> {
+ let packet = pair.0;
+ let uci_fira_major_ver = pair.1;
match packet.specialize() {
uwb_uci_packets::UciControlPacketChild::UciResponse(evt) => {
Ok(UciMessage::Response(evt.try_into()?))
}
uwb_uci_packets::UciControlPacketChild::UciNotification(evt) => {
- Ok(UciMessage::Notification(evt.try_into()?))
+ Ok(UciMessage::Notification((evt, uci_fira_major_ver).try_into()?))
}
_ => {
error!("Unknown packet for converting to UciMessage: {:?}", packet);
diff --git a/src/rust/uwb_core/src/uci/notification.rs b/src/rust/uwb_core/src/uci/notification.rs
index 06cc909..86af468 100644
--- a/src/rust/uwb_core/src/uci/notification.rs
+++ b/src/rust/uwb_core/src/uci/notification.rs
@@ -25,12 +25,14 @@
use crate::error::{Error, Result};
use crate::params::fira_app_config_params::UwbAddress;
use crate::params::uci_packets::{
- BitsPerSample, ControleeStatus, CreditAvailability, DataRcvStatusCode,
+ BitsPerSample, ControleeStatusV1, ControleeStatusV2, CreditAvailability, DataRcvStatusCode,
DataTransferNtfStatusCode, DataTransferPhaseConfigUpdateStatusCode, DeviceState,
ExtendedAddressDlTdoaRangingMeasurement, ExtendedAddressOwrAoaRangingMeasurement,
ExtendedAddressTwoWayRangingMeasurement, RadarDataType, RangingMeasurementType, RawUciMessage,
- SessionId, SessionState, SessionToken, ShortAddressDlTdoaRangingMeasurement,
+ SessionId, SessionState, SessionToken, SessionUpdateControllerMulticastListNtfV1Payload,
+ SessionUpdateControllerMulticastListNtfV2Payload, ShortAddressDlTdoaRangingMeasurement,
ShortAddressOwrAoaRangingMeasurement, ShortAddressTwoWayRangingMeasurement, StatusCode,
+ UCIMajorVersion,
};
/// enum of all UCI notifications with structured fields.
@@ -67,14 +69,21 @@
/// uwb_uci_packets::Reasoncode.
reason_code: u8,
},
- /// SessionUpdateControllerMulticastListNtf equivalent.
- UpdateControllerMulticastList {
+ /// SessionUpdateControllerMulticastListNtfV1 equivalent.
+ UpdateControllerMulticastListV1 {
/// SessionToken : u32
session_token: SessionToken,
/// count of controlees: u8
remaining_multicast_list_size: usize,
/// list of controlees.
- status_list: Vec<ControleeStatus>,
+ status_list: Vec<ControleeStatusV1>,
+ },
+ /// SessionUpdateControllerMulticastListNtfV2 equivalent.
+ UpdateControllerMulticastListV2 {
+ /// SessionToken : u32
+ session_token: SessionToken,
+ /// list of controlees.
+ status_list: Vec<ControleeStatusV2>,
},
/// (Short/Extended)Mac()SessionInfoNtf equivalent
SessionInfo(SessionRangeData),
@@ -333,14 +342,19 @@
}
}
-impl TryFrom<uwb_uci_packets::UciNotification> for UciNotification {
+impl TryFrom<(uwb_uci_packets::UciNotification, UCIMajorVersion)> for UciNotification {
type Error = Error;
- fn try_from(evt: uwb_uci_packets::UciNotification) -> std::result::Result<Self, Self::Error> {
+ fn try_from(
+ pair: (uwb_uci_packets::UciNotification, UCIMajorVersion),
+ ) -> std::result::Result<Self, Self::Error> {
use uwb_uci_packets::UciNotificationChild;
+ let evt = pair.0;
+ let uci_fira_major_ver = pair.1;
+
match evt.specialize() {
UciNotificationChild::CoreNotification(evt) => Ok(Self::Core(evt.try_into()?)),
UciNotificationChild::SessionConfigNotification(evt) => {
- Ok(Self::Session(evt.try_into()?))
+ Ok(Self::Session((evt, uci_fira_major_ver).try_into()?))
}
UciNotificationChild::SessionControlNotification(evt) => {
Ok(Self::Session(evt.try_into()?))
@@ -377,12 +391,16 @@
}
}
-impl TryFrom<uwb_uci_packets::SessionConfigNotification> for SessionNotification {
+impl TryFrom<(uwb_uci_packets::SessionConfigNotification, UCIMajorVersion)>
+ for SessionNotification
+{
type Error = Error;
fn try_from(
- evt: uwb_uci_packets::SessionConfigNotification,
+ pair: (uwb_uci_packets::SessionConfigNotification, UCIMajorVersion),
) -> std::result::Result<Self, Self::Error> {
use uwb_uci_packets::SessionConfigNotificationChild;
+ let evt = pair.0;
+ let uci_fira_major_ver = pair.1;
match evt.specialize() {
SessionConfigNotificationChild::SessionStatusNtf(evt) => Ok(Self::Status {
//no sessionId recieved, assign from sessionIdToToken map in uci_manager
@@ -391,11 +409,45 @@
session_state: evt.get_session_state(),
reason_code: evt.get_reason_code(),
}),
- SessionConfigNotificationChild::SessionUpdateControllerMulticastListNtf(evt) => {
- Ok(Self::UpdateControllerMulticastList {
+ SessionConfigNotificationChild::SessionUpdateControllerMulticastListNtf(evt)
+ if uci_fira_major_ver == UCIMajorVersion::V1 =>
+ {
+ let payload = evt.get_payload();
+ let multicast_update_list_payload_v1 =
+ SessionUpdateControllerMulticastListNtfV1Payload::parse(payload).map_err(
+ |e| {
+ error!(
+ "Failed to parse Multicast list ntf v1 {:?}, payload: {:?}",
+ e, &payload
+ );
+ Error::BadParameters
+ },
+ )?;
+ Ok(Self::UpdateControllerMulticastListV1 {
session_token: evt.get_session_token(),
- remaining_multicast_list_size: evt.get_remaining_multicast_list_size() as usize,
- status_list: evt.get_controlee_status().clone(),
+ remaining_multicast_list_size: multicast_update_list_payload_v1
+ .remaining_multicast_list_size
+ as usize,
+ status_list: multicast_update_list_payload_v1.controlee_status,
+ })
+ }
+ SessionConfigNotificationChild::SessionUpdateControllerMulticastListNtf(evt)
+ if uci_fira_major_ver == UCIMajorVersion::V2 =>
+ {
+ let payload = evt.get_payload();
+ let multicast_update_list_payload_v2 =
+ SessionUpdateControllerMulticastListNtfV2Payload::parse(payload).map_err(
+ |e| {
+ error!(
+ "Failed to parse Multicast list ntf v2 {:?}, payload: {:?}",
+ e, &payload
+ );
+ Error::BadParameters
+ },
+ )?;
+ Ok(Self::UpdateControllerMulticastListV2 {
+ session_token: evt.get_session_token(),
+ status_list: multicast_update_list_payload_v2.controlee_status,
})
}
SessionConfigNotificationChild::SessionDataTransferPhaseConfigNtf(evt) => {
@@ -623,6 +675,7 @@
#[cfg(test)]
mod tests {
use super::*;
+ use bytes::{BufMut, BytesMut};
#[test]
fn test_ranging_measurements_trait() {
@@ -889,8 +942,10 @@
.build();
let session_notification_packet =
uwb_uci_packets::SessionConfigNotification::try_from(session_status_ntf).unwrap();
+ let uci_fira_major_version = UCIMajorVersion::V1;
let session_notification =
- SessionNotification::try_from(session_notification_packet).unwrap();
+ SessionNotification::try_from((session_notification_packet, uci_fira_major_version))
+ .unwrap();
let uci_notification_from_session_status_ntf =
UciNotification::Session(session_notification);
assert_eq!(
@@ -905,40 +960,130 @@
);
}
+ fn write_multicast_ntf_v1_payload(
+ payload: &SessionUpdateControllerMulticastListNtfV1Payload,
+ buffer: &mut BytesMut,
+ ) {
+ buffer.put_u8(payload.remaining_multicast_list_size);
+ buffer.put_u8(payload.controlee_status.len() as u8);
+ for elem in &payload.controlee_status {
+ write_v1_controlee_status(elem, buffer);
+ }
+ }
+
+ fn write_v1_controlee_status(status: &ControleeStatusV1, buffer: &mut BytesMut) {
+ for elem in &status.mac_address {
+ buffer.put_u8(*elem);
+ }
+ buffer.put_u32_le(status.subsession_id);
+ buffer.put_u8(u8::from(status.status));
+ }
+
+ fn write_multicast_ntf_v2_payload(
+ payload: &SessionUpdateControllerMulticastListNtfV2Payload,
+ buffer: &mut BytesMut,
+ ) {
+ buffer.put_u8(payload.controlee_status.len() as u8);
+ for elem in &payload.controlee_status {
+ write_v2_controlee_status(elem, buffer);
+ }
+ }
+
+ fn write_v2_controlee_status(status: &ControleeStatusV2, buffer: &mut BytesMut) {
+ for elem in &status.mac_address {
+ buffer.put_u8(*elem);
+ }
+ buffer.put_u8(u8::from(status.status));
+ }
+
#[test]
- fn test_session_notification_casting_from_session_update_controller_multicast_list_ntf_packet()
- {
- let controlee_status = uwb_uci_packets::ControleeStatus {
+ fn test_session_notification_casting_from_session_update_controller_multicast_list_ntf_v1_packet(
+ ) {
+ let controlee_status_v1 = uwb_uci_packets::ControleeStatusV1 {
mac_address: [0x0c, 0xa8],
subsession_id: 0x30,
status: uwb_uci_packets::MulticastUpdateStatusCode::StatusOkMulticastListUpdate,
};
- let another_controlee_status = uwb_uci_packets::ControleeStatus {
+ let another_controlee_status_v1 = uwb_uci_packets::ControleeStatusV1 {
mac_address: [0x0c, 0xa9],
subsession_id: 0x31,
status: uwb_uci_packets::MulticastUpdateStatusCode::StatusErrorKeyFetchFail,
};
- let session_update_controller_multicast_list_ntf =
+ let payload = uwb_uci_packets::SessionUpdateControllerMulticastListNtfV1Payload {
+ remaining_multicast_list_size: 0x2,
+ controlee_status: vec![
+ controlee_status_v1.clone(),
+ another_controlee_status_v1.clone(),
+ ],
+ };
+ let mut buf = BytesMut::new();
+ write_multicast_ntf_v1_payload(&payload, &mut buf);
+ let session_update_controller_multicast_list_ntf_v1 =
uwb_uci_packets::SessionUpdateControllerMulticastListNtfBuilder {
session_token: 0x32,
- remaining_multicast_list_size: 0x2,
- controlee_status: vec![controlee_status.clone(), another_controlee_status.clone()],
+ payload: Some(buf.freeze()),
}
.build();
let session_notification_packet = uwb_uci_packets::SessionConfigNotification::try_from(
- session_update_controller_multicast_list_ntf,
+ session_update_controller_multicast_list_ntf_v1,
)
.unwrap();
+ let uci_fira_major_version = UCIMajorVersion::V1;
let session_notification =
- SessionNotification::try_from(session_notification_packet).unwrap();
+ SessionNotification::try_from((session_notification_packet, uci_fira_major_version))
+ .unwrap();
let uci_notification_from_session_update_controller_multicast_list_ntf =
UciNotification::Session(session_notification);
assert_eq!(
uci_notification_from_session_update_controller_multicast_list_ntf,
- UciNotification::Session(SessionNotification::UpdateControllerMulticastList {
+ UciNotification::Session(SessionNotification::UpdateControllerMulticastListV1 {
session_token: 0x32,
remaining_multicast_list_size: 0x2,
- status_list: vec![controlee_status, another_controlee_status],
+ status_list: vec![controlee_status_v1, another_controlee_status_v1],
+ })
+ );
+ }
+
+ #[test]
+ fn test_session_notification_casting_from_session_update_controller_multicast_list_ntf_v2_packet(
+ ) {
+ let controlee_status_v2 = uwb_uci_packets::ControleeStatusV2 {
+ mac_address: [0x0c, 0xa8],
+ status: uwb_uci_packets::MulticastUpdateStatusCode::StatusOkMulticastListUpdate,
+ };
+ let another_controlee_status_v2 = uwb_uci_packets::ControleeStatusV2 {
+ mac_address: [0x0c, 0xa9],
+ status: uwb_uci_packets::MulticastUpdateStatusCode::StatusErrorKeyFetchFail,
+ };
+ let payload = uwb_uci_packets::SessionUpdateControllerMulticastListNtfV2Payload {
+ controlee_status: vec![
+ controlee_status_v2.clone(),
+ another_controlee_status_v2.clone(),
+ ],
+ };
+ let mut buf = BytesMut::new();
+ write_multicast_ntf_v2_payload(&payload, &mut buf);
+ let session_update_controller_multicast_list_ntf_v2 =
+ uwb_uci_packets::SessionUpdateControllerMulticastListNtfBuilder {
+ session_token: 0x32,
+ payload: Some(buf.freeze()),
+ }
+ .build();
+ let session_notification_packet = uwb_uci_packets::SessionConfigNotification::try_from(
+ session_update_controller_multicast_list_ntf_v2,
+ )
+ .unwrap();
+ let uci_fira_major_version = UCIMajorVersion::V2;
+ let session_notification =
+ SessionNotification::try_from((session_notification_packet, uci_fira_major_version))
+ .unwrap();
+ let uci_notification_from_session_update_controller_multicast_list_ntf =
+ UciNotification::Session(session_notification);
+ assert_eq!(
+ uci_notification_from_session_update_controller_multicast_list_ntf,
+ UciNotification::Session(SessionNotification::UpdateControllerMulticastListV2 {
+ session_token: 0x32,
+ status_list: vec![controlee_status_v2, another_controlee_status_v2],
})
);
}
@@ -957,10 +1102,15 @@
}
.build()
.into();
- let uci_notification_from_vendor_9 =
- UciNotification::try_from(vendor_9_empty_notification).unwrap();
+ let uci_fira_major_version = UCIMajorVersion::V1;
+ let uci_notification_from_vendor_9 = UciNotification::try_from((
+ vendor_9_empty_notification,
+ uci_fira_major_version.clone(),
+ ))
+ .unwrap();
let uci_notification_from_vendor_A =
- UciNotification::try_from(vendor_A_nonempty_notification).unwrap();
+ UciNotification::try_from((vendor_A_nonempty_notification, uci_fira_major_version))
+ .unwrap();
assert_eq!(
uci_notification_from_vendor_9,
UciNotification::Vendor(RawUciMessage {
@@ -983,7 +1133,9 @@
fn test_test_to_vendor_notification_casting() {
let test_notification: uwb_uci_packets::UciNotification =
uwb_uci_packets::TestNotificationBuilder { opcode: 0x22, payload: None }.build().into();
- let test_uci_notification = UciNotification::try_from(test_notification).unwrap();
+ let uci_fira_major_version = UCIMajorVersion::V1;
+ let test_uci_notification =
+ UciNotification::try_from((test_notification, uci_fira_major_version)).unwrap();
assert_eq!(
test_uci_notification,
UciNotification::Vendor(RawUciMessage {
diff --git a/src/rust/uwb_core/src/uci/uci_manager.rs b/src/rust/uwb_core/src/uci/uci_manager.rs
index 8fd1acc..d1a289f 100644
--- a/src/rust/uwb_core/src/uci/uci_manager.rs
+++ b/src/rust/uwb_core/src/uci/uci_manager.rs
@@ -18,6 +18,7 @@
use async_trait::async_trait;
use log::{debug, error, info, warn};
+use num_traits::FromPrimitive;
use tokio::sync::{mpsc, oneshot, Mutex};
use crate::error::{Error, Result};
@@ -30,6 +31,7 @@
UciDataPacketHal, UpdateMulticastListAction, UpdateTime,
};
use crate::params::utils::{bytes_to_u16, bytes_to_u64};
+use crate::params::UCIMajorVersion;
use crate::uci::command::UciCommand;
use crate::uci::message::UciMessage;
use crate::uci::notification::{
@@ -932,6 +934,15 @@
}
}
+ fn get_uwbs_uci_major_version(&mut self) -> Option<u8> {
+ if let Some(core_get_device_info_rsp) = &self.get_device_info_rsp {
+ // Byte 0 : Major UCI version
+ // Calling unwrap() will be safe here as with the bitmask, the value will be within u8.
+ return Some((core_get_device_info_rsp.uci_version & 0xFF).try_into().unwrap());
+ }
+ None
+ }
+
#[allow(unknown_lints)]
#[allow(clippy::unnecessary_fallible_conversions)]
fn store_if_uwbs_caps_info(&mut self, resp: &UciResponse) {
@@ -1264,7 +1275,15 @@
UciDefragPacket::Control(packet) => {
self.logger.log_uci_response_or_notification(&packet);
- match packet.try_into() {
+ // Use a safe value of Fira 1.x as the UWBS UCI version.
+ let uci_fira_major_version = self.get_uwbs_uci_major_version().unwrap_or(1);
+ match (
+ packet,
+ UCIMajorVersion::from_u8(uci_fira_major_version)
+ .map_or(UCIMajorVersion::V1, |v| v),
+ )
+ .try_into()
+ {
Ok(UciMessage::Response(resp)) => {
self.handle_response(resp).await;
}
@@ -1348,9 +1367,7 @@
}
UciNotification::Session(orig_session_notf) => {
let mod_session_notf = {
- match self
- .add_session_id_to_session_status_ntf(orig_session_notf.clone())
- .await
+ match self.add_session_id_to_session_status_ntf(orig_session_notf.clone()).await
{
Ok(session_notf) => session_notf,
Err(e) => {
@@ -1361,7 +1378,7 @@
};
match orig_session_notf {
SessionNotification::Status {
- session_id:_,
+ session_id: _,
session_token,
session_state,
reason_code: _,
@@ -1422,23 +1439,31 @@
) -> Result<SessionNotification> {
match session_notification {
SessionNotification::Status {
- session_id:_, session_token, session_state, reason_code } => {
- Ok(SessionNotification::Status {
- session_id: self.get_session_id(&session_token).await?,
- session_token,
- session_state,
- reason_code,
- })
- }
- SessionNotification::UpdateControllerMulticastList {
+ session_id: _,
+ session_token,
+ session_state,
+ reason_code,
+ } => Ok(SessionNotification::Status {
+ session_id: self.get_session_id(&session_token).await?,
+ session_token,
+ session_state,
+ reason_code,
+ }),
+ SessionNotification::UpdateControllerMulticastListV1 {
session_token,
remaining_multicast_list_size,
status_list,
- } => Ok(SessionNotification::UpdateControllerMulticastList {
+ } => Ok(SessionNotification::UpdateControllerMulticastListV1 {
session_token: self.get_session_id(&session_token).await?,
remaining_multicast_list_size,
status_list,
}),
+ SessionNotification::UpdateControllerMulticastListV2 { session_token, status_list } => {
+ Ok(SessionNotification::UpdateControllerMulticastListV2 {
+ session_token: self.get_session_id(&session_token).await?,
+ status_list,
+ })
+ }
SessionNotification::SessionInfo(session_range_data) => {
Ok(SessionNotification::SessionInfo(SessionRangeData {
sequence_number: session_range_data.sequence_number,
diff --git a/src/rust/uwb_uci_packets/uci_packets.pdl b/src/rust/uwb_uci_packets/uci_packets.pdl
index 7b3e174..0fa887d 100644
--- a/src/rust/uwb_uci_packets/uci_packets.pdl
+++ b/src/rust/uwb_uci_packets/uci_packets.pdl
@@ -997,23 +997,37 @@
"\x41\x07\x00\x01\x00\x00\x00\x00",
}
-struct ControleeStatus {
+struct ControleeStatusV1 {
mac_address: 8[2],
subsession_id: 32,
status: MulticastUpdateStatusCode,
}
+struct ControleeStatusV2 {
+ mac_address: 8[2],
+ status: MulticastUpdateStatusCode,
+}
+
packet SessionUpdateControllerMulticastListNtf : SessionConfigNotification (opcode = 0x7) { //SESSION_UPDATE_CONTROLLER_MULTICAST_LIST
session_token: 32, // Session ID or Session Handle (based on UWBS version)
- remaining_multicast_list_size: 8,
- _count_(controlee_status): 8,
- controlee_status: ControleeStatus[],
+ _payload_,
}
test SessionUpdateControllerMulticastListNtf {
"\x61\x07\x00\x06\x00\x00\x00\x00\x01\x02\x03\x04\x00",
}
+struct SessionUpdateControllerMulticastListNtfV1Payload {
+ remaining_multicast_list_size: 8,
+ _count_(controlee_status): 8,
+ controlee_status: ControleeStatusV1[],
+}
+
+struct SessionUpdateControllerMulticastListNtfV2Payload {
+ _count_(controlee_status): 8,
+ controlee_status: ControleeStatusV2[],
+}
+
packet DataCreditNtf : SessionControlNotification (opcode = 0x04) { // SESSION_DATA_CREDIT_NTF
session_token: 32, // Session ID or Session Handle (based on UWBS version)
credit_availability: CreditAvailability,