summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-10-16 20:21:59 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-10-16 20:21:59 +0000
commitef4a95ceb69fcad719a2b87b25f8dd7bfc5b5d79 (patch)
tree576362cb77c8ca2a427821afdd65110a100e39bf
parent916812682d317bf2f25cafc63ed2e4ca03dc141b (diff)
parent85f38f76787c158c3b2fdc3ac115aa5f8412958c (diff)
downloaduwb-ef4a95ceb69fcad719a2b87b25f8dd7bfc5b5d79.tar.gz
Snap for 10957012 from 85f38f76787c158c3b2fdc3ac115aa5f8412958c to simpleperf-release
Change-Id: Ib048ae20b5ed38b1d45e2b42f470af52151dba92
-rw-r--r--src/TEST_MAPPING3
-rw-r--r--src/rust/uwb_core/protos/uwb_service.proto2
-rw-r--r--src/rust/uwb_core/src/params/uci_packets.rs33
-rw-r--r--src/rust/uwb_core/src/proto/mappings.rs3
-rw-r--r--src/rust/uwb_core/src/service/uwb_service.rs25
-rw-r--r--src/rust/uwb_core/src/session/session_manager.rs13
-rw-r--r--src/rust/uwb_core/src/uci.rs4
-rw-r--r--src/rust/uwb_core/src/uci/command.rs49
-rw-r--r--src/rust/uwb_core/src/uci/mock_uci_manager.rs127
-rw-r--r--src/rust/uwb_core/src/uci/notification.rs158
-rw-r--r--src/rust/uwb_core/src/uci/response.rs30
-rw-r--r--src/rust/uwb_core/src/uci/uci_manager.rs332
-rw-r--r--src/rust/uwb_core/src/uci/uci_manager_sync.rs78
-rw-r--r--src/rust/uwb_uci_packets/src/lib.rs49
-rw-r--r--src/rust/uwb_uci_packets/uci_packets.pdl112
15 files changed, 910 insertions, 108 deletions
diff --git a/src/TEST_MAPPING b/src/TEST_MAPPING
index 4676de2..3713fda 100644
--- a/src/TEST_MAPPING
+++ b/src/TEST_MAPPING
@@ -5,6 +5,9 @@
},
{
"name": "libuwb_core_tests"
+ },
+ {
+ "name": "CtsUwbTestCases"
}
]
}
diff --git a/src/rust/uwb_core/protos/uwb_service.proto b/src/rust/uwb_core/protos/uwb_service.proto
index e979bcc..d7c4c38 100644
--- a/src/rust/uwb_core/protos/uwb_service.proto
+++ b/src/rust/uwb_core/protos/uwb_service.proto
@@ -76,6 +76,7 @@ enum StatusCode {
UCI_STATUS_UNKNOWN_OID = 8;
UCI_STATUS_READ_ONLY = 9;
UCI_STATUS_COMMAND_RETRY = 10;
+ UCI_STATUS_UNKNOWN = 11;
UCI_STATUS_SESSION_NOT_EXIST = 17;
UCI_STATUS_SESSION_DUPLICATE = 18;
@@ -194,6 +195,7 @@ enum SessionType {
FIRA_IN_BAND_DATA_PHASE = 0x04;
FIRA_RANGING_WITH_DATA_PHASE = 0x05;
CCC = 0xA0;
+ RADAR_SESSION = 0xA1;
DEVICE_TEST_MODE = 0xD0;
}
diff --git a/src/rust/uwb_core/src/params/uci_packets.rs b/src/rust/uwb_core/src/params/uci_packets.rs
index 23597ce..e3a7722 100644
--- a/src/rust/uwb_core/src/params/uci_packets.rs
+++ b/src/rust/uwb_core/src/params/uci_packets.rs
@@ -20,13 +20,14 @@ use std::iter::FromIterator;
// Re-export enums and structs from uwb_uci_packets.
pub use uwb_uci_packets::{
- AppConfigStatus, AppConfigTlv as RawAppConfigTlv, AppConfigTlvType, CapTlv, CapTlvType,
- Controlee, ControleeStatus, Controlees, CreditAvailability, DataRcvStatusCode,
+ AppConfigStatus, AppConfigTlv as RawAppConfigTlv, AppConfigTlvType, BitsPerSample, CapTlv,
+ CapTlvType, Controlee, ControleeStatus, Controlees, CreditAvailability, DataRcvStatusCode,
DataTransferNtfStatusCode, DeviceConfigId, DeviceConfigStatus, DeviceConfigTlv, DeviceState,
ExtendedAddressDlTdoaRangingMeasurement, ExtendedAddressOwrAoaRangingMeasurement,
ExtendedAddressTwoWayRangingMeasurement, GroupId, MessageType, MulticastUpdateStatusCode,
- PhaseList, PowerStats, RangingMeasurementType, ReasonCode, ResetConfig, SessionState,
- SessionType, ShortAddressDlTdoaRangingMeasurement, ShortAddressOwrAoaRangingMeasurement,
+ PhaseList, PowerStats, RadarConfigStatus, RadarConfigTlv, RadarConfigTlvType, RadarDataType,
+ RangingMeasurementType, ReasonCode, ResetConfig, SessionState, SessionType,
+ ShortAddressDlTdoaRangingMeasurement, ShortAddressOwrAoaRangingMeasurement,
ShortAddressTwoWayRangingMeasurement, StatusCode, UpdateMulticastListAction,
};
pub(crate) use uwb_uci_packets::{UciControlPacket, UciDataPacket, UciDataPacketHal};
@@ -124,6 +125,19 @@ fn device_config_tlvs_to_map(
HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
}
+/// Compare if two RadarConfigTlv array are equal. Convert the array to HashMap before comparing
+/// because the order of TLV elements doesn't matter.
+#[allow(dead_code)]
+pub fn radar_config_tlvs_eq(a: &[RadarConfigTlv], b: &[RadarConfigTlv]) -> bool {
+ radar_config_tlvs_to_map(a) == radar_config_tlvs_to_map(b)
+}
+
+fn radar_config_tlvs_to_map(
+ tlvs: &[RadarConfigTlv],
+) -> HashMap<RadarConfigTlvType, &Vec<u8>, RandomState> {
+ HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
+}
+
/// The response of the UciManager::core_set_config() method.
#[derive(Debug, Clone, PartialEq)]
pub struct CoreSetConfigResponse {
@@ -142,6 +156,15 @@ pub struct SetAppConfigResponse {
pub config_status: Vec<AppConfigStatus>,
}
+/// The response of the UciManager::android_set_radar_config() method.
+#[derive(Debug, Clone, PartialEq)]
+pub struct AndroidRadarConfigResponse {
+ /// The status code of the response.
+ pub status: StatusCode,
+ /// The status of each config TLV.
+ pub config_status: Vec<RadarConfigStatus>,
+}
+
/// The response from UciManager::session_update_dt_tag_ranging_rounds() method.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SessionUpdateDtTagRangingRoundsResponse {
@@ -204,6 +227,8 @@ impl From<UpdateTime> for [u8; 8] {
/// The response of the UciManager::core_get_device_info() method.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GetDeviceInfoResponse {
+ /// Status
+ pub status: StatusCode,
/// The UCI version.
pub uci_version: u16,
/// The MAC version.
diff --git a/src/rust/uwb_core/src/proto/mappings.rs b/src/rust/uwb_core/src/proto/mappings.rs
index 1b14711..c10cf0e 100644
--- a/src/rust/uwb_core/src/proto/mappings.rs
+++ b/src/rust/uwb_core/src/proto/mappings.rs
@@ -116,6 +116,7 @@ impl From<ProtoStatusCode> for StatusCode {
ProtoStatusCode::UCI_STATUS_UNKNOWN_OID => StatusCode::UciStatusUnknownOid,
ProtoStatusCode::UCI_STATUS_READ_ONLY => StatusCode::UciStatusReadOnly,
ProtoStatusCode::UCI_STATUS_COMMAND_RETRY => StatusCode::UciStatusCommandRetry,
+ ProtoStatusCode::UCI_STATUS_UNKNOWN => StatusCode::UciStatusUnknown,
ProtoStatusCode::UCI_STATUS_SESSION_NOT_EXIST => StatusCode::UciStatusSessionNotExist,
ProtoStatusCode::UCI_STATUS_SESSION_DUPLICATE => StatusCode::UciStatusSessionDuplicate,
ProtoStatusCode::UCI_STATUS_SESSION_ACTIVE => StatusCode::UciStatusSessionActive,
@@ -199,6 +200,7 @@ impl From<StatusCode> for ProtoStatusCode {
StatusCode::UciStatusUnknownOid => ProtoStatusCode::UCI_STATUS_UNKNOWN_OID,
StatusCode::UciStatusReadOnly => ProtoStatusCode::UCI_STATUS_READ_ONLY,
StatusCode::UciStatusCommandRetry => ProtoStatusCode::UCI_STATUS_COMMAND_RETRY,
+ StatusCode::UciStatusUnknown => ProtoStatusCode::UCI_STATUS_UNKNOWN,
StatusCode::UciStatusSessionNotExist => ProtoStatusCode::UCI_STATUS_SESSION_NOT_EXIST,
StatusCode::UciStatusSessionDuplicate => ProtoStatusCode::UCI_STATUS_SESSION_DUPLICATE,
StatusCode::UciStatusSessionActive => ProtoStatusCode::UCI_STATUS_SESSION_ACTIVE,
@@ -536,6 +538,7 @@ enum_mapping! {
FIRA_IN_BAND_DATA_PHASE => FiraInBandDataPhase,
FIRA_RANGING_WITH_DATA_PHASE => FiraRangingWithDataPhase,
CCC => Ccc,
+ RADAR_SESSION => RadarSession,
DEVICE_TEST_MODE => DeviceTestMode,
}
diff --git a/src/rust/uwb_core/src/service/uwb_service.rs b/src/rust/uwb_core/src/service/uwb_service.rs
index ce00f95..012fbda 100644
--- a/src/rust/uwb_core/src/service/uwb_service.rs
+++ b/src/rust/uwb_core/src/service/uwb_service.rs
@@ -576,6 +576,7 @@ mod tests {
use tokio::runtime::Runtime;
use crate::params::uci_packets::{SessionState, SetAppConfigResponse, StatusCode};
+ use crate::params::GetDeviceInfoResponse;
use crate::service::mock_uwb_service_callback::MockUwbServiceCallback;
use crate::service::uwb_service_builder::default_runtime;
use crate::service::uwb_service_callback_builder::UwbServiceCallbackSendBuilder;
@@ -584,6 +585,16 @@ mod tests {
};
use crate::uci::mock_uci_manager::MockUciManager;
use crate::uci::notification::UciNotification;
+ use uwb_uci_packets::StatusCode::UciStatusOk;
+
+ const GET_DEVICE_INFO_RSP: GetDeviceInfoResponse = GetDeviceInfoResponse {
+ status: UciStatusOk,
+ uci_version: 0,
+ mac_version: 0,
+ phy_version: 0,
+ uci_test_version: 0,
+ vendor_spec_info: vec![],
+ };
fn setup_uwb_service(
uci_manager: MockUciManager,
@@ -599,7 +610,7 @@ mod tests {
#[test]
fn test_open_close_uci() {
let mut uci_manager = MockUciManager::new();
- uci_manager.expect_open_hal(vec![], Ok(()));
+ uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP));
uci_manager.expect_close_hal(false, Ok(()));
let (service, _, _runtime) = setup_uwb_service(uci_manager);
@@ -618,7 +629,7 @@ mod tests {
let range_data = session_range_data(session_id);
let mut uci_manager = MockUciManager::new();
- uci_manager.expect_open_hal(vec![], Ok(()));
+ uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP));
uci_manager.expect_session_init(
session_id,
session_type,
@@ -788,7 +799,7 @@ mod tests {
let mut uci_manager = MockUciManager::new();
uci_manager.expect_open_hal(
vec![UciNotification::Vendor(RawUciMessage { gid, oid, payload: payload.clone() })],
- Ok(()),
+ Ok(GET_DEVICE_INFO_RSP),
);
let (service, mut callback, _runtime) = setup_uwb_service(uci_manager);
@@ -804,7 +815,7 @@ mod tests {
let mut uci_manager = MockUciManager::new();
uci_manager.expect_open_hal(
vec![UciNotification::Core(CoreNotification::DeviceStatus(state))],
- Ok(()),
+ Ok(GET_DEVICE_INFO_RSP),
);
let (service, mut callback, _runtime) = setup_uwb_service(uci_manager);
callback.expect_on_uci_device_status_changed(state);
@@ -819,7 +830,7 @@ mod tests {
uci_manager.expect_open_hal(vec![], Err(Error::Timeout));
// Then UwbService should close_hal() and open_hal() to reset the HAL.
uci_manager.expect_close_hal(true, Ok(()));
- uci_manager.expect_open_hal(vec![], Ok(()));
+ uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP));
let (service, mut callback, _runtime) = setup_uwb_service(uci_manager.clone());
callback.expect_on_service_reset(true);
@@ -838,11 +849,11 @@ mod tests {
vec![UciNotification::Core(CoreNotification::DeviceStatus(
DeviceState::DeviceStateError,
))],
- Ok(()),
+ Ok(GET_DEVICE_INFO_RSP),
);
// Then UwbService should close_hal() and open_hal() to reset the HAL.
uci_manager.expect_close_hal(true, Ok(()));
- uci_manager.expect_open_hal(vec![], Ok(()));
+ uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP));
let (service, mut callback, _runtime) = setup_uwb_service(uci_manager.clone());
callback.expect_on_service_reset(true);
diff --git a/src/rust/uwb_core/src/session/session_manager.rs b/src/rust/uwb_core/src/session/session_manager.rs
index e49dd9c..449d50d 100644
--- a/src/rust/uwb_core/src/session/session_manager.rs
+++ b/src/rust/uwb_core/src/session/session_manager.rs
@@ -443,9 +443,20 @@ pub(crate) mod test_utils {
use crate::params::uci_packets::{
RangingMeasurementType, ReasonCode, ShortAddressTwoWayRangingMeasurement, StatusCode,
};
+ use crate::params::GetDeviceInfoResponse;
use crate::uci::mock_uci_manager::MockUciManager;
use crate::uci::notification::{RangingMeasurements, UciNotification};
use crate::utils::init_test_logging;
+ use uwb_uci_packets::StatusCode::UciStatusOk;
+
+ const GET_DEVICE_INFO_RSP: GetDeviceInfoResponse = GetDeviceInfoResponse {
+ status: UciStatusOk,
+ uci_version: 0,
+ mac_version: 0,
+ phy_version: 0,
+ uci_test_version: 0,
+ vendor_spec_info: vec![],
+ };
pub(crate) fn generate_params() -> AppConfigParams {
FiraAppConfigParamsBuilder::new()
@@ -533,7 +544,7 @@ pub(crate) mod test_utils {
let (uci_notf_sender, uci_notf_receiver) = mpsc::unbounded_channel();
let (session_notf_sender, session_notf_receiver) = mpsc::unbounded_channel();
let mut uci_manager = MockUciManager::new();
- uci_manager.expect_open_hal(vec![], Ok(()));
+ uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP));
setup_uci_manager_fn(&mut uci_manager);
uci_manager.set_session_notification_sender(uci_notf_sender).await;
let _ = uci_manager.open_hal().await;
diff --git a/src/rust/uwb_core/src/uci.rs b/src/rust/uwb_core/src/uci.rs
index cac1be2..4364966 100644
--- a/src/rust/uwb_core/src/uci.rs
+++ b/src/rust/uwb_core/src/uci.rs
@@ -41,8 +41,8 @@ pub mod mock_uci_manager;
// Re-export the public elements.
pub use command::UciCommand;
pub use notification::{
- CoreNotification, DataRcvNotification, RangingMeasurements, SessionNotification,
- SessionRangeData, UciNotification,
+ CoreNotification, DataRcvNotification, RadarDataRcvNotification, RadarSweepData,
+ RangingMeasurements, SessionNotification, SessionRangeData, UciNotification,
};
pub use uci_hal::{NopUciHal, UciHal, UciHalPacket};
pub use uci_logger_factory::{NopUciLoggerFactory, UciLoggerFactory};
diff --git a/src/rust/uwb_core/src/uci/command.rs b/src/rust/uwb_core/src/uci/command.rs
index 8693073..864ca8f 100644
--- a/src/rust/uwb_core/src/uci/command.rs
+++ b/src/rust/uwb_core/src/uci/command.rs
@@ -20,9 +20,12 @@ use log::error;
use crate::error::{Error, Result};
use crate::params::uci_packets::{
AppConfigTlv, AppConfigTlvType, Controlees, CountryCode, DeviceConfigId, DeviceConfigTlv,
- ResetConfig, SessionId, SessionToken, SessionType, UpdateMulticastListAction, UpdateTime,
+ RadarConfigTlv, RadarConfigTlvType, ResetConfig, SessionId, SessionToken, SessionType,
+ UpdateMulticastListAction, UpdateTime,
+};
+use uwb_uci_packets::{
+ build_session_update_controller_multicast_list_cmd, GroupId, MessageType, PhaseList,
};
-use uwb_uci_packets::{ build_session_update_controller_multicast_list_cmd, GroupId, MessageType, PhaseList,};
/// The enum to represent the UCI commands. The definition of each field should follow UCI spec.
#[allow(missing_docs)]
@@ -90,6 +93,14 @@ pub enum UciCommand {
country_code: CountryCode,
},
AndroidGetPowerStats,
+ AndroidSetRadarConfig {
+ session_token: SessionToken,
+ config_tlvs: Vec<RadarConfigTlv>,
+ },
+ AndroidGetRadarConfig {
+ session_token: SessionToken,
+ radar_cfg: Vec<RadarConfigTlvType>,
+ },
RawUciCmd {
mt: u32,
gid: u32,
@@ -154,6 +165,22 @@ impl TryFrom<UciCommand> for uwb_uci_packets::UciControlPacket {
.build()
.into()
}
+ UciCommand::AndroidSetRadarConfig { session_token, config_tlvs } => {
+ uwb_uci_packets::AndroidSetRadarConfigCmdBuilder {
+ session_token,
+ tlvs: config_tlvs,
+ }
+ .build()
+ .into()
+ }
+ UciCommand::AndroidGetRadarConfig { session_token, radar_cfg } => {
+ uwb_uci_packets::AndroidGetRadarConfigCmdBuilder {
+ session_token,
+ tlvs: radar_cfg.into_iter().map(u8::from).collect(),
+ }
+ .build()
+ .into()
+ }
UciCommand::SessionUpdateDtTagRangingRounds {
session_token,
ranging_round_indexes,
@@ -406,5 +433,23 @@ mod tests {
cmd = UciCommand::AndroidGetPowerStats {};
packet = uwb_uci_packets::UciControlPacket::try_from(cmd).unwrap();
assert_eq!(packet, uwb_uci_packets::AndroidGetPowerStatsCmdBuilder {}.build().into());
+
+ cmd = UciCommand::AndroidSetRadarConfig { session_token: 1, config_tlvs: vec![] };
+ packet = uwb_uci_packets::UciControlPacket::try_from(cmd.clone()).unwrap();
+ assert_eq!(
+ packet,
+ uwb_uci_packets::AndroidSetRadarConfigCmdBuilder { session_token: 1, tlvs: vec![] }
+ .build()
+ .into()
+ );
+
+ cmd = UciCommand::AndroidGetRadarConfig { session_token: 1, radar_cfg: vec![] };
+ packet = uwb_uci_packets::UciControlPacket::try_from(cmd).unwrap();
+ assert_eq!(
+ packet,
+ uwb_uci_packets::AndroidGetRadarConfigCmdBuilder { session_token: 1, tlvs: vec![] }
+ .build()
+ .into()
+ );
}
}
diff --git a/src/rust/uwb_core/src/uci/mock_uci_manager.rs b/src/rust/uwb_core/src/uci/mock_uci_manager.rs
index d7f944a..f6e84ba 100644
--- a/src/rust/uwb_core/src/uci/mock_uci_manager.rs
+++ b/src/rust/uwb_core/src/uci/mock_uci_manager.rs
@@ -27,13 +27,16 @@ use tokio::time::timeout;
use crate::error::{Error, Result};
use crate::params::uci_packets::{
- app_config_tlvs_eq, device_config_tlvs_eq, AppConfigTlv, AppConfigTlvType, CapTlv, Controlees,
- CoreSetConfigResponse, CountryCode, DeviceConfigId, DeviceConfigTlv, GetDeviceInfoResponse, PhaseList,
- PowerStats, RawUciMessage, ResetConfig, SessionId, SessionState, SessionToken, SessionType,
- SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse, UpdateMulticastListAction, UpdateTime,
+ app_config_tlvs_eq, device_config_tlvs_eq, radar_config_tlvs_eq, AndroidRadarConfigResponse,
+ AppConfigTlv, AppConfigTlvType, CapTlv, Controlees, CoreSetConfigResponse, CountryCode,
+ DeviceConfigId, DeviceConfigTlv, GetDeviceInfoResponse, PhaseList, PowerStats, RadarConfigTlv,
+ RadarConfigTlvType, RawUciMessage, ResetConfig, SessionId, SessionState, SessionToken,
+ SessionType, SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse,
+ UpdateMulticastListAction, UpdateTime,
};
use crate::uci::notification::{
- CoreNotification, DataRcvNotification, SessionNotification, UciNotification,
+ CoreNotification, DataRcvNotification, RadarDataRcvNotification, SessionNotification,
+ UciNotification,
};
use crate::uci::uci_logger::UciLoggerMode;
use crate::uci::uci_manager::UciManager;
@@ -47,6 +50,7 @@ pub struct MockUciManager {
session_notf_sender: mpsc::UnboundedSender<SessionNotification>,
vendor_notf_sender: mpsc::UnboundedSender<RawUciMessage>,
data_rcv_notf_sender: mpsc::UnboundedSender<DataRcvNotification>,
+ radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
}
#[allow(dead_code)]
@@ -60,6 +64,7 @@ impl MockUciManager {
session_notf_sender: mpsc::unbounded_channel().0,
vendor_notf_sender: mpsc::unbounded_channel().0,
data_rcv_notf_sender: mpsc::unbounded_channel().0,
+ radar_data_rcv_notf_sender: mpsc::unbounded_channel().0,
}
}
@@ -79,7 +84,11 @@ impl MockUciManager {
/// Prepare Mock to expect for open_hal.
///
/// MockUciManager expects call, returns out as response, followed by notfs sent.
- pub fn expect_open_hal(&mut self, notfs: Vec<UciNotification>, out: Result<()>) {
+ pub fn expect_open_hal(
+ &mut self,
+ notfs: Vec<UciNotification>,
+ out: Result<GetDeviceInfoResponse>,
+ ) {
self.expected_calls.lock().unwrap().push_back(ExpectedCall::OpenHal { notfs, out });
}
@@ -368,6 +377,41 @@ impl MockUciManager {
self.expected_calls.lock().unwrap().push_back(ExpectedCall::AndroidGetPowerStats { out });
}
+ /// Prepare Mock to expect android_set_radar_config.
+ ///
+ /// MockUciManager expects call with parameters, returns out as response, followed by notfs
+ /// sent.
+ pub fn expect_android_set_radar_config(
+ &mut self,
+ expected_session_id: SessionId,
+ expected_config_tlvs: Vec<RadarConfigTlv>,
+ notfs: Vec<UciNotification>,
+ out: Result<AndroidRadarConfigResponse>,
+ ) {
+ self.expected_calls.lock().unwrap().push_back(ExpectedCall::AndroidSetRadarConfig {
+ expected_session_id,
+ expected_config_tlvs,
+ notfs,
+ out,
+ });
+ }
+
+ /// Prepare Mock to expect android_get_app_config.
+ ///
+ /// MockUciManager expects call with parameters, returns out as response.
+ pub fn expect_android_get_radar_config(
+ &mut self,
+ expected_session_id: SessionId,
+ expected_config_ids: Vec<RadarConfigTlvType>,
+ out: Result<Vec<RadarConfigTlv>>,
+ ) {
+ self.expected_calls.lock().unwrap().push_back(ExpectedCall::AndroidGetRadarConfig {
+ expected_session_id,
+ expected_config_ids,
+ out,
+ });
+ }
+
/// Prepare Mock to expect raw_uci_cmd.
///
/// MockUciManager expects call with parameters, returns out as response.
@@ -481,8 +525,14 @@ impl UciManager for MockUciManager {
) {
self.data_rcv_notf_sender = data_rcv_notf_sender;
}
+ async fn set_radar_data_rcv_notification_sender(
+ &mut self,
+ radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
+ ) {
+ self.radar_data_rcv_notf_sender = radar_data_rcv_notf_sender;
+ }
- async fn open_hal(&self) -> Result<()> {
+ async fn open_hal(&self) -> Result<GetDeviceInfoResponse> {
let mut expected_calls = self.expected_calls.lock().unwrap();
match expected_calls.pop_front() {
Some(ExpectedCall::OpenHal { notfs, out }) => {
@@ -893,6 +943,56 @@ impl UciManager for MockUciManager {
}
}
+ async fn android_set_radar_config(
+ &self,
+ session_id: SessionId,
+ config_tlvs: Vec<RadarConfigTlv>,
+ ) -> Result<AndroidRadarConfigResponse> {
+ let mut expected_calls = self.expected_calls.lock().unwrap();
+ match expected_calls.pop_front() {
+ Some(ExpectedCall::AndroidSetRadarConfig {
+ expected_session_id,
+ expected_config_tlvs,
+ notfs,
+ out,
+ }) if expected_session_id == session_id
+ && radar_config_tlvs_eq(&expected_config_tlvs, &config_tlvs) =>
+ {
+ self.expect_call_consumed.notify_one();
+ self.send_notifications(notfs);
+ out
+ }
+ Some(call) => {
+ expected_calls.push_front(call);
+ Err(Error::MockUndefined)
+ }
+ None => Err(Error::MockUndefined),
+ }
+ }
+
+ async fn android_get_radar_config(
+ &self,
+ session_id: SessionId,
+ config_ids: Vec<RadarConfigTlvType>,
+ ) -> Result<Vec<RadarConfigTlv>> {
+ let mut expected_calls = self.expected_calls.lock().unwrap();
+ match expected_calls.pop_front() {
+ Some(ExpectedCall::AndroidGetRadarConfig {
+ expected_session_id,
+ expected_config_ids,
+ out,
+ }) if expected_session_id == session_id && expected_config_ids == config_ids => {
+ self.expect_call_consumed.notify_one();
+ out
+ }
+ Some(call) => {
+ expected_calls.push_front(call);
+ Err(Error::MockUndefined)
+ }
+ None => Err(Error::MockUndefined),
+ }
+ }
+
async fn raw_uci_cmd(
&self,
mt: u32,
@@ -999,7 +1099,7 @@ impl UciManager for MockUciManager {
enum ExpectedCall {
OpenHal {
notfs: Vec<UciNotification>,
- out: Result<()>,
+ out: Result<GetDeviceInfoResponse>,
},
CloseHal {
expected_force: bool,
@@ -1092,6 +1192,17 @@ enum ExpectedCall {
AndroidGetPowerStats {
out: Result<PowerStats>,
},
+ AndroidSetRadarConfig {
+ expected_session_id: SessionId,
+ expected_config_tlvs: Vec<RadarConfigTlv>,
+ notfs: Vec<UciNotification>,
+ out: Result<AndroidRadarConfigResponse>,
+ },
+ AndroidGetRadarConfig {
+ expected_session_id: SessionId,
+ expected_config_ids: Vec<RadarConfigTlvType>,
+ out: Result<Vec<RadarConfigTlv>>,
+ },
RawUciCmd {
expected_mt: u32,
expected_gid: u32,
diff --git a/src/rust/uwb_core/src/uci/notification.rs b/src/rust/uwb_core/src/uci/notification.rs
index 90231ae..d99f602 100644
--- a/src/rust/uwb_core/src/uci/notification.rs
+++ b/src/rust/uwb_core/src/uci/notification.rs
@@ -15,15 +15,20 @@
use std::convert::{TryFrom, TryInto};
use log::{debug, error};
-use uwb_uci_packets::{parse_diagnostics_ntf, Packet, UCI_PACKET_HEADER_LEN};
+use uwb_uci_packets::{
+ parse_diagnostics_ntf, radar_bytes_per_sample_value, Packet, RadarDataRcv, RadarSweepDataRaw,
+ UCI_PACKET_HEADER_LEN, UCI_RADAR_SEQUENCE_NUMBER_LEN, UCI_RADAR_TIMESTAMP_LEN,
+ UCI_RADAR_VENDOR_DATA_LEN_LEN,
+};
use crate::error::{Error, Result};
use crate::params::fira_app_config_params::UwbAddress;
use crate::params::uci_packets::{
- ControleeStatus, CreditAvailability, DataRcvStatusCode, DataTransferNtfStatusCode, DeviceState,
- ExtendedAddressDlTdoaRangingMeasurement, ExtendedAddressOwrAoaRangingMeasurement,
- ExtendedAddressTwoWayRangingMeasurement, RangingMeasurementType, RawUciMessage, SessionState,
- SessionToken, ShortAddressDlTdoaRangingMeasurement, ShortAddressOwrAoaRangingMeasurement,
+ BitsPerSample, ControleeStatus, CreditAvailability, DataRcvStatusCode,
+ DataTransferNtfStatusCode, DeviceState, ExtendedAddressDlTdoaRangingMeasurement,
+ ExtendedAddressOwrAoaRangingMeasurement, ExtendedAddressTwoWayRangingMeasurement,
+ RadarDataType, RangingMeasurementType, RawUciMessage, SessionState, SessionToken,
+ ShortAddressDlTdoaRangingMeasurement, ShortAddressOwrAoaRangingMeasurement,
ShortAddressTwoWayRangingMeasurement, StatusCode,
};
@@ -145,7 +150,7 @@ pub struct DataRcvNotification {
pub session_token: SessionToken,
/// The status of the data rx.
- pub status: DataRcvStatusCode,
+ pub status: StatusCode,
/// The sequence number of the data packet.
pub uci_sequence_num: u16,
@@ -157,6 +162,142 @@ pub struct DataRcvNotification {
pub payload: Vec<u8>,
}
+/// The Radar sweep data struct
+#[derive(Debug, Clone, std::cmp::PartialEq)]
+pub struct RadarSweepData {
+ /// Counter of a single radar sweep per receiver. Starting
+ /// with 0 when the radar session is started.
+ pub sequence_number: u32,
+
+ /// Timestamp when this radar sweep is received. Unit is
+ /// based on the PRF.
+ pub timestamp: u32,
+
+ /// The radar vendor specific data.
+ pub vendor_specific_data: Vec<u8>,
+
+ /// The radar sample data.
+ pub sample_data: Vec<u8>,
+}
+
+/// The RADAR_DATA_RCV packet
+#[derive(Debug, Clone, std::cmp::PartialEq)]
+pub struct RadarDataRcvNotification {
+ /// The identifier of the session on which radar data transfer is happening.
+ pub session_token: SessionToken,
+
+ /// The status of the radar data rx.
+ pub status: DataRcvStatusCode,
+
+ /// The radar data type.
+ pub radar_data_type: RadarDataType,
+
+ /// The number of sweeps.
+ pub number_of_sweeps: u8,
+
+ /// Number of samples captured for each radar sweep.
+ pub samples_per_sweep: u8,
+
+ /// Bits per sample in the radar sweep.
+ pub bits_per_sample: BitsPerSample,
+
+ /// Defines the start offset with respect to 0cm distance. Unit in samples.
+ pub sweep_offset: u16,
+
+ /// Radar sweep data.
+ pub sweep_data: Vec<RadarSweepData>,
+}
+
+impl From<&uwb_uci_packets::RadarSweepDataRaw> for RadarSweepData {
+ fn from(evt: &uwb_uci_packets::RadarSweepDataRaw) -> Self {
+ Self {
+ sequence_number: evt.sequence_number,
+ timestamp: evt.timestamp,
+ vendor_specific_data: evt.vendor_specific_data.clone(),
+ sample_data: evt.sample_data.clone(),
+ }
+ }
+}
+
+impl TryFrom<uwb_uci_packets::UciDataPacket> for RadarDataRcvNotification {
+ type Error = Error;
+ fn try_from(evt: uwb_uci_packets::UciDataPacket) -> std::result::Result<Self, Self::Error> {
+ match evt.specialize() {
+ uwb_uci_packets::UciDataPacketChild::RadarDataRcv(evt) => parse_radar_data(evt),
+ _ => Err(Error::Unknown),
+ }
+ }
+}
+
+fn parse_radar_data(data: RadarDataRcv) -> Result<RadarDataRcvNotification> {
+ let session_token = data.get_session_handle();
+ let status = data.get_status();
+ let radar_data_type = data.get_radar_data_type();
+ let number_of_sweeps = data.get_number_of_sweeps();
+ let samples_per_sweep = data.get_samples_per_sweep();
+ let bits_per_sample = data.get_bits_per_sample();
+ let bytes_per_sample_value = radar_bytes_per_sample_value(bits_per_sample);
+ let sweep_offset = data.get_sweep_offset();
+
+ Ok(RadarDataRcvNotification {
+ session_token,
+ status,
+ radar_data_type,
+ number_of_sweeps,
+ samples_per_sweep,
+ bits_per_sample,
+ sweep_offset,
+ sweep_data: parse_radar_sweep_data(
+ number_of_sweeps,
+ samples_per_sweep,
+ bytes_per_sample_value,
+ data.get_sweep_data().clone(),
+ )?,
+ })
+}
+
+fn parse_radar_sweep_data(
+ number_of_sweeps: u8,
+ samples_per_sweep: u8,
+ bytes_per_sample_value: u8,
+ data: Vec<u8>,
+) -> Result<Vec<RadarSweepData>> {
+ let mut radar_sweep_data: Vec<RadarSweepData> = Vec::new();
+ let mut sweep_data_cursor = 0;
+ for _ in 0..number_of_sweeps {
+ let vendor_data_len_index =
+ sweep_data_cursor + UCI_RADAR_SEQUENCE_NUMBER_LEN + UCI_RADAR_TIMESTAMP_LEN;
+ if data.len() <= vendor_data_len_index {
+ error!("Invalid radar sweep data length for vendor, data: {:?}", &data);
+ return Err(Error::BadParameters);
+ }
+ let vendor_specific_data_len = data[vendor_data_len_index] as usize;
+ let sweep_data_len = UCI_RADAR_SEQUENCE_NUMBER_LEN
+ + UCI_RADAR_TIMESTAMP_LEN
+ + UCI_RADAR_VENDOR_DATA_LEN_LEN
+ + vendor_specific_data_len
+ + (samples_per_sweep * bytes_per_sample_value) as usize;
+ if data.len() < sweep_data_cursor + sweep_data_len {
+ error!("Invalid radar sweep data length, data: {:?}", &data);
+ return Err(Error::BadParameters);
+ }
+ radar_sweep_data.push(
+ (&RadarSweepDataRaw::parse(
+ &data[sweep_data_cursor..sweep_data_cursor + sweep_data_len],
+ )
+ .map_err(|e| {
+ error!("Failed to parse raw Radar Sweep Data {:?}, data: {:?}", e, &data);
+ Error::BadParameters
+ })?)
+ .into(),
+ );
+
+ sweep_data_cursor += sweep_data_len;
+ }
+
+ Ok(radar_sweep_data)
+}
+
impl TryFrom<uwb_uci_packets::UciDataPacket> for DataRcvNotification {
type Error = Error;
fn try_from(evt: uwb_uci_packets::UciDataPacket) -> std::result::Result<Self, Self::Error> {
@@ -168,10 +309,7 @@ impl TryFrom<uwb_uci_packets::UciDataPacket> for DataRcvNotification {
source_address: UwbAddress::Extended(evt.get_source_mac_address().to_le_bytes()),
payload: evt.get_data().to_vec(),
}),
- _ => {
- error!("Unknown UciData packet: {:?}", evt);
- Err(Error::Unknown)
- }
+ _ => Err(Error::Unknown),
}
}
}
diff --git a/src/rust/uwb_core/src/uci/response.rs b/src/rust/uwb_core/src/uci/response.rs
index 23279c9..d70f9f7 100644
--- a/src/rust/uwb_core/src/uci/response.rs
+++ b/src/rust/uwb_core/src/uci/response.rs
@@ -16,8 +16,8 @@ use std::convert::{TryFrom, TryInto};
use crate::error::{Error, Result};
use crate::params::uci_packets::{
- AppConfigTlv, CapTlv, CoreSetConfigResponse, DeviceConfigTlv, GetDeviceInfoResponse,
- PowerStats, RawUciMessage, SessionHandle, SessionState,
+ AndroidRadarConfigResponse, AppConfigTlv, CapTlv, CoreSetConfigResponse, DeviceConfigTlv,
+ GetDeviceInfoResponse, PowerStats, RadarConfigTlv, RawUciMessage, SessionHandle, SessionState,
SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse, StatusCode, UciControlPacket,
};
use crate::uci::error::status_code_to_result;
@@ -48,6 +48,8 @@ pub(super) enum UciResponse {
SessionGetRangingCount(Result<usize>),
AndroidSetCountryCode(Result<()>),
AndroidGetPowerStats(Result<PowerStats>),
+ AndroidSetRadarConfig(AndroidRadarConfigResponse),
+ AndroidGetRadarConfig(Result<Vec<RadarConfigTlv>>),
RawUciCmd(Result<RawUciMessage>),
SendUciData(Result<()>),
SessionSetHybridConfig(Result<()>),
@@ -76,6 +78,8 @@ impl UciResponse {
Self::SessionGetRangingCount(result) => Self::matches_result_retry(result),
Self::AndroidSetCountryCode(result) => Self::matches_result_retry(result),
Self::AndroidGetPowerStats(result) => Self::matches_result_retry(result),
+ Self::AndroidGetRadarConfig(result) => Self::matches_result_retry(result),
+ Self::AndroidSetRadarConfig(resp) => Self::matches_status_retry(&resp.status),
Self::RawUciCmd(result) => Self::matches_result_retry(result),
Self::SessionSetHybridConfig(result) => Self::matches_result_retry(result),
@@ -122,6 +126,7 @@ impl TryFrom<uwb_uci_packets::CoreResponse> for UciResponse {
match evt.specialize() {
CoreResponseChild::GetDeviceInfoRsp(evt) => Ok(UciResponse::CoreGetDeviceInfo(
status_code_to_result(evt.get_status()).map(|_| GetDeviceInfoResponse {
+ status: evt.get_status(),
uci_version: evt.get_uci_version(),
mac_version: evt.get_mac_version(),
phy_version: evt.get_phy_version(),
@@ -206,11 +211,13 @@ impl TryFrom<uwb_uci_packets::SessionConfigResponse> for UciResponse {
))
}
SessionConfigResponseChild::SessionQueryMaxDataSizeRsp(evt) => {
- Ok(UciResponse::SessionQueryMaxDataSize(Ok(evt.get_max_data_size())))
+ Ok(UciResponse::SessionQueryMaxDataSize(
+ status_code_to_result(evt.get_status()).map(|_| evt.get_max_data_size()),
+ ))
+ }
+ SessionConfigResponseChild::SessionSetHybridConfigRsp(evt) => {
+ Ok(UciResponse::SessionSetHybridConfig(status_code_to_result(evt.get_status())))
}
- SessionConfigResponseChild::SessionSetHybridConfigRsp(evt) => Ok(
- UciResponse::SessionSetHybridConfig(status_code_to_result(evt.get_status())),
- ),
_ => Err(Error::Unknown),
}
}
@@ -252,6 +259,17 @@ impl TryFrom<uwb_uci_packets::AndroidResponse> for UciResponse {
status_code_to_result(evt.get_stats().status).map(|_| evt.get_stats().clone()),
))
}
+ AndroidResponseChild::AndroidSetRadarConfigRsp(evt) => {
+ Ok(UciResponse::AndroidSetRadarConfig(AndroidRadarConfigResponse {
+ status: evt.get_status(),
+ config_status: evt.get_cfg_status().clone(),
+ }))
+ }
+ AndroidResponseChild::AndroidGetRadarConfigRsp(evt) => {
+ Ok(UciResponse::AndroidGetRadarConfig(
+ status_code_to_result(evt.get_status()).map(|_| evt.get_tlvs().clone()),
+ ))
+ }
_ => Err(Error::Unknown),
}
}
diff --git a/src/rust/uwb_core/src/uci/uci_manager.rs b/src/rust/uwb_core/src/uci/uci_manager.rs
index 53595e4..a1a97f1 100644
--- a/src/rust/uwb_core/src/uci/uci_manager.rs
+++ b/src/rust/uwb_core/src/uci/uci_manager.rs
@@ -24,16 +24,18 @@ use crate::uci::command::UciCommand;
//use crate::uci::error::{Error, Result};
use crate::error::{Error, Result};
use crate::params::uci_packets::{
- AppConfigTlv, AppConfigTlvType, CapTlv, Controlees, CoreSetConfigResponse, CountryCode,
- CreditAvailability, DeviceConfigId, DeviceConfigTlv, DeviceState, GetDeviceInfoResponse,
- GroupId, MessageType, PowerStats, RawUciMessage, ResetConfig, SessionId, SessionState,
- SessionToken, SessionType, SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse,
- UciDataPacket, UciDataPacketHal, UpdateMulticastListAction, UpdateTime,
+ AndroidRadarConfigResponse, AppConfigTlv, AppConfigTlvType, CapTlv, Controlees,
+ CoreSetConfigResponse, CountryCode, CreditAvailability, DeviceConfigId, DeviceConfigTlv,
+ DeviceState, GetDeviceInfoResponse, GroupId, MessageType, PowerStats, RadarConfigTlv,
+ RadarConfigTlvType, RawUciMessage, ResetConfig, SessionId, SessionState, SessionToken,
+ SessionType, SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse, UciDataPacket,
+ UciDataPacketHal, UpdateMulticastListAction, UpdateTime,
};
use crate::params::utils::bytes_to_u64;
use crate::uci::message::UciMessage;
use crate::uci::notification::{
- CoreNotification, DataRcvNotification, SessionNotification, SessionRangeData, UciNotification,
+ CoreNotification, DataRcvNotification, RadarDataRcvNotification, SessionNotification,
+ SessionRangeData, UciNotification,
};
use crate::uci::response::UciResponse;
use crate::uci::timeout_uci_hal::TimeoutUciHal;
@@ -68,10 +70,14 @@ pub trait UciManager: 'static + Send + Sync + Clone {
&mut self,
data_rcv_notf_sender: mpsc::UnboundedSender<DataRcvNotification>,
);
+ async fn set_radar_data_rcv_notification_sender(
+ &mut self,
+ radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
+ );
// Open the UCI HAL.
// All the UCI commands should be called after the open_hal() completes successfully.
- async fn open_hal(&self) -> Result<()>;
+ async fn open_hal(&self) -> Result<GetDeviceInfoResponse>;
// Close the UCI HAL.
async fn close_hal(&self, force: bool) -> Result<()>;
@@ -126,6 +132,16 @@ pub trait UciManager: 'static + Send + Sync + Clone {
// Send the Android-specific UCI commands
async fn android_set_country_code(&self, country_code: CountryCode) -> Result<()>;
async fn android_get_power_stats(&self) -> Result<PowerStats>;
+ async fn android_set_radar_config(
+ &self,
+ session_id: SessionId,
+ config_tlvs: Vec<RadarConfigTlv>,
+ ) -> Result<AndroidRadarConfigResponse>;
+ async fn android_get_radar_config(
+ &self,
+ session_id: SessionId,
+ config_ids: Vec<RadarConfigTlvType>,
+ ) -> Result<Vec<RadarConfigTlv>>;
// Send a raw uci command.
async fn raw_uci_cmd(
@@ -254,17 +270,32 @@ impl UciManager for UciManagerImpl {
.send_cmd(UciManagerCmd::SetDataRcvNotificationSender { data_rcv_notf_sender })
.await;
}
+ async fn set_radar_data_rcv_notification_sender(
+ &mut self,
+ radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
+ ) {
+ let _ = self
+ .send_cmd(UciManagerCmd::SetRadarDataRcvNotificationSender {
+ radar_data_rcv_notf_sender,
+ })
+ .await;
+ }
- async fn open_hal(&self) -> Result<()> {
+ async fn open_hal(&self) -> Result<GetDeviceInfoResponse> {
match self.send_cmd(UciManagerCmd::OpenHal).await {
Ok(UciResponse::OpenHal) => {
// According to the UCI spec: "The Host shall send CORE_GET_DEVICE_INFO_CMD to
// retrieve the device information.", we call get_device_info() after successfully
// opening the HAL.
- let device_info = self.core_get_device_info().await;
+ let device_info = match self.core_get_device_info().await {
+ Ok(resp) => resp,
+ Err(e) => {
+ return Err(e);
+ }
+ };
debug!("UCI device info: {:?}", device_info);
- Ok(())
+ Ok(device_info)
}
Ok(_) => Err(Error::Unknown),
Err(e) => Err(e),
@@ -510,6 +541,38 @@ impl UciManager for UciManagerImpl {
}
}
+ async fn android_set_radar_config(
+ &self,
+ session_id: SessionId,
+ config_tlvs: Vec<RadarConfigTlv>,
+ ) -> Result<AndroidRadarConfigResponse> {
+ let cmd = UciCommand::AndroidSetRadarConfig {
+ session_token: self.get_session_token(&session_id).await?,
+ config_tlvs,
+ };
+ match self.send_cmd(UciManagerCmd::SendUciCommand { cmd }).await {
+ Ok(UciResponse::AndroidSetRadarConfig(resp)) => Ok(resp),
+ Ok(_) => Err(Error::Unknown),
+ Err(e) => Err(e),
+ }
+ }
+
+ async fn android_get_radar_config(
+ &self,
+ session_id: SessionId,
+ radar_cfg: Vec<RadarConfigTlvType>,
+ ) -> Result<Vec<RadarConfigTlv>> {
+ let cmd = UciCommand::AndroidGetRadarConfig {
+ session_token: self.get_session_token(&session_id).await?,
+ radar_cfg,
+ };
+ match self.send_cmd(UciManagerCmd::SendUciCommand { cmd }).await {
+ Ok(UciResponse::AndroidGetRadarConfig(resp)) => resp,
+ Ok(_) => Err(Error::Unknown),
+ Err(e) => Err(e),
+ }
+ }
+
async fn raw_uci_cmd(
&self,
mt: u32,
@@ -634,6 +697,7 @@ struct UciManagerActor<T: UciHal, U: UciLogger> {
session_notf_sender: mpsc::UnboundedSender<SessionNotification>,
vendor_notf_sender: mpsc::UnboundedSender<RawUciMessage>,
data_rcv_notf_sender: mpsc::UnboundedSender<DataRcvNotification>,
+ radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
// Used to store the last init session id to help map the session handle sent
// in session int response can be correctly mapped.
@@ -674,6 +738,7 @@ impl<T: UciHal, U: UciLogger> UciManagerActor<T, U> {
session_notf_sender: mpsc::unbounded_channel().0,
vendor_notf_sender: mpsc::unbounded_channel().0,
data_rcv_notf_sender: mpsc::unbounded_channel().0,
+ radar_data_rcv_notf_sender: mpsc::unbounded_channel().0,
last_init_session_id: None,
session_id_to_token_map,
}
@@ -807,6 +872,10 @@ impl<T: UciHal, U: UciLogger> UciManagerActor<T, U> {
self.data_rcv_notf_sender = data_rcv_notf_sender;
let _ = result_sender.send(Ok(UciResponse::SetNotification));
}
+ UciManagerCmd::SetRadarDataRcvNotificationSender { radar_data_rcv_notf_sender } => {
+ self.radar_data_rcv_notf_sender = radar_data_rcv_notf_sender;
+ let _ = result_sender.send(Ok(UciResponse::SetNotification));
+ }
UciManagerCmd::OpenHal => {
if self.is_hal_opened {
warn!("The UCI HAL is already opened, skip.");
@@ -1305,28 +1374,41 @@ impl<T: UciHal, U: UciLogger> UciManagerActor<T, U> {
}
async fn handle_data_rcv(&mut self, packet: UciDataPacket) {
- match packet.try_into() {
- Ok(DataRcvNotification { session_token, status, uci_sequence_num,
- source_address, payload }) => {
- match self.get_session_id(&session_token).await {
- Ok(session_id) => {
- let data_recv = DataRcvNotification {
- session_token: session_id,
- status,
- uci_sequence_num,
- source_address,
- payload,
- };
- let _ = self.data_rcv_notf_sender.send(data_recv);
- }
- Err(e) => {
- error!("Unable to find session Id, error {:?}", e);
- }
+ if let Ok(data) = DataRcvNotification::try_from(packet.clone()) {
+ match self.get_session_id(&data.session_token).await {
+ Ok(session_id) => {
+ let _ = self.data_rcv_notf_sender.send(DataRcvNotification {
+ session_token: session_id,
+ status: data.status,
+ uci_sequence_num: data.uci_sequence_num,
+ source_address: data.source_address,
+ payload: data.payload,
+ });
+ }
+ Err(e) => {
+ error!("Unable to find session Id, error {:?}", e);
}
}
- Err(e) => {
- error!("Unable to parse incoming Data packet, error {:?}", e);
+ } else if let Ok(data) = RadarDataRcvNotification::try_from(packet.clone()) {
+ match self.get_session_id(&data.session_token).await {
+ Ok(session_id) => {
+ let _ = self.radar_data_rcv_notf_sender.send(RadarDataRcvNotification {
+ session_token: session_id,
+ status: data.status,
+ radar_data_type: data.radar_data_type,
+ number_of_sweeps: data.number_of_sweeps,
+ samples_per_sweep: data.samples_per_sweep,
+ bits_per_sample: data.bits_per_sample,
+ sweep_offset: data.sweep_offset,
+ sweep_data: data.sweep_data,
+ });
+ }
+ Err(e) => {
+ error!("Unable to find session Id, error {:?}", e);
+ }
}
+ } else {
+ error!("Unable to parse incoming Data packet, packet {:?}", packet);
}
}
@@ -1415,6 +1497,9 @@ enum UciManagerCmd {
SetDataRcvNotificationSender {
data_rcv_notf_sender: mpsc::UnboundedSender<DataRcvNotification>,
},
+ SetRadarDataRcvNotificationSender {
+ radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
+ },
OpenHal,
CloseHal {
force: bool,
@@ -1436,12 +1521,13 @@ mod tests {
use uwb_uci_packets::{SessionGetCountCmdBuilder, SessionGetCountRspBuilder};
use crate::params::uci_packets::{
- AppConfigStatus, AppConfigTlvType, CapTlvType, Controlee, DataRcvStatusCode,
- DataTransferNtfStatusCode, StatusCode,
+ AppConfigStatus, AppConfigTlvType, BitsPerSample, CapTlvType, Controlee, DataRcvStatusCode,
+ DataTransferNtfStatusCode, RadarDataType, StatusCode,
};
use crate::params::UwbAddress;
use crate::uci::mock_uci_hal::MockUciHal;
use crate::uci::mock_uci_logger::{MockUciLogger, UciLogEvent};
+ use crate::uci::notification::RadarSweepData;
use crate::uci::uci_logger::NopUciLogger;
use crate::utils::init_test_logging;
@@ -1626,6 +1712,7 @@ mod tests {
.await;
let expected_result = GetDeviceInfoResponse {
+ status,
uci_version,
mac_version,
phy_version,
@@ -2282,6 +2369,76 @@ mod tests {
}
#[tokio::test]
+ async fn test_android_set_radar_config_ok() {
+ let session_id = 0x123;
+ let session_token = 0x123;
+ let config_tlv =
+ RadarConfigTlv { cfg_id: RadarConfigTlvType::SamplesPerSweep, v: vec![0x12, 0x34] };
+ let config_tlv_clone = config_tlv.clone();
+
+ let (uci_manager, mut mock_hal) = setup_uci_manager_with_session_initialized(
+ |mut hal| async move {
+ let cmd = UciCommand::AndroidSetRadarConfig {
+ session_token,
+ config_tlvs: vec![config_tlv_clone],
+ };
+ let resp = into_uci_hal_packets(uwb_uci_packets::AndroidSetRadarConfigRspBuilder {
+ status: uwb_uci_packets::StatusCode::UciStatusOk,
+ cfg_status: vec![],
+ });
+
+ hal.expected_send_command(cmd, resp, Ok(()));
+ },
+ UciLoggerMode::Disabled,
+ mpsc::unbounded_channel::<UciLogEvent>().0,
+ session_id,
+ session_token,
+ )
+ .await;
+
+ let expected_result =
+ AndroidRadarConfigResponse { status: StatusCode::UciStatusOk, config_status: vec![] };
+ let result =
+ uci_manager.android_set_radar_config(session_id, vec![config_tlv]).await.unwrap();
+ assert_eq!(result, expected_result);
+ assert!(mock_hal.wait_expected_calls_done().await);
+ }
+
+ #[tokio::test]
+ async fn test_android_get_radar_config_ok() {
+ let session_id = 0x123;
+ let session_token = 0x123;
+ let config_id = RadarConfigTlvType::SamplesPerSweep;
+ let tlv =
+ RadarConfigTlv { cfg_id: RadarConfigTlvType::SamplesPerSweep, v: vec![0x12, 0x34] };
+ let tlv_clone = tlv.clone();
+
+ let (uci_manager, mut mock_hal) = setup_uci_manager_with_session_initialized(
+ |mut hal| async move {
+ let cmd =
+ UciCommand::AndroidGetRadarConfig { session_token, radar_cfg: vec![config_id] };
+ let resp = into_uci_hal_packets(uwb_uci_packets::AndroidGetRadarConfigRspBuilder {
+ status: uwb_uci_packets::StatusCode::UciStatusOk,
+ tlvs: vec![tlv_clone],
+ });
+
+ hal.expected_send_command(cmd, resp, Ok(()));
+ },
+ UciLoggerMode::Disabled,
+ mpsc::unbounded_channel::<UciLogEvent>().0,
+ session_id,
+ session_token,
+ )
+ .await;
+
+ let expected_result = vec![tlv];
+ let result =
+ uci_manager.android_get_radar_config(session_id, vec![config_id]).await.unwrap();
+ assert_eq!(result, expected_result);
+ assert!(mock_hal.wait_expected_calls_done().await);
+ }
+
+ #[tokio::test]
async fn test_raw_uci_cmd_vendor_gid_ok() {
let mt = 0x1;
let gid = 0xF; // Vendor reserved GID.
@@ -2431,7 +2588,7 @@ mod tests {
let resp_payload_fragment_1 = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
let resp_payload_fragment_2 = vec![0x09, 0x0a, 0x0b];
let mut resp_payload_expected = resp_payload_fragment_1.clone();
- resp_payload_expected.extend(resp_payload_fragment_2.clone().into_iter());
+ resp_payload_expected.extend(resp_payload_fragment_2.clone());
let (uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(
|mut hal| async move {
@@ -2708,7 +2865,7 @@ mod tests {
let app_data = vec![0x01, 0x02, 0x03];
let data_rcv_payload = vec![
0x05, 0x00, 0x00, 0x00, // SessionToken
- 0x00, // DataRcvStatusCode
+ 0x00, // StatusCode
0xa0, 0xb0, 0xc0, 0xd0, 0xa1, 0xb1, 0xc1, 0xd1, // MacAddress
0x0a, 0x00, // UciSequenceNumber
0x03, 0x00, // AppDataLen
@@ -2719,7 +2876,7 @@ mod tests {
let data_packet_rcv = build_uci_packet(mt_data, pbf, dpf, oid, data_rcv_payload);
let expected_data_rcv_notification = DataRcvNotification {
session_token: session_id,
- status: DataRcvStatusCode::UciStatusSuccess,
+ status: StatusCode::UciStatusOk,
uci_sequence_num,
source_address,
payload: app_data,
@@ -2768,7 +2925,7 @@ mod tests {
let app_data_fragment_1_len = 200;
let mut data_rcv_payload_fragment_1: Vec<u8> = vec![
0x05, 0x00, 0x00, 0x00, // SessionToken
- 0x00, // DataRcvStatusCode
+ 0x00, // StatusCode
0xa0, 0xb0, 0xc0, 0xd0, 0xa1, 0xb1, 0xc1, 0xd1, // MacAddress
0x0a, 0x00, // UciSequenceNumber
0x2c, 0x01, // AppData Length (300)
@@ -2790,7 +2947,7 @@ mod tests {
build_uci_packet(mt_data, pbf_fragment_2, dpf, oid, data_rcv_payload_fragment_2);
let expected_data_rcv_notification = DataRcvNotification {
session_token: session_id,
- status: DataRcvStatusCode::UciStatusSuccess,
+ status: StatusCode::UciStatusOk,
uci_sequence_num,
source_address,
payload: app_data,
@@ -2828,6 +2985,109 @@ mod tests {
#[tokio::test]
async fn test_data_packet_recv_bad_payload_len_failure() {}
+ // Test Radar Data packet receive for a single packet (on an active UWB session).
+ #[tokio::test]
+ async fn test_radar_data_packet_recv_ok() {
+ let mt_data = 0x0;
+ let pbf = 0x0;
+ let dpf = 0xf;
+ let oid = 0x0;
+ let session_id = 0x3;
+ let session_token = 0x5;
+ let radar_data_type = RadarDataType::RadarSweepSamples;
+ let number_of_sweeps = 0x02;
+ let samples_per_sweep = 0x02;
+ let bits_per_sample = BitsPerSample::Value32;
+ let sweep_offset = 0x0;
+ let sequence_number_1 = 0xa;
+ let sequence_number_2 = 0xb;
+ let timestamp_1 = 0xc;
+ let timestamp_2 = 0xd;
+ let vendor_specific_data_1 = vec![0x0b];
+ let vendor_specific_data_2 = vec![0x0b, 0x0c];
+ let sample_data_1 = vec![0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa];
+ let sample_data_2 = vec![0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8];
+ let radar_data_rcv_payload = vec![
+ 0x05, 0x00, 0x00, 0x00, // session_handle
+ 0x00, // status
+ 0x00, // radar data type
+ 0x02, // number of sweeps
+ 0x02, // samples per sweep
+ 0x00, // bits per sample
+ 0x00, 0x00, // sweep offset
+ 0x10, 0x11, // sweep data size
+ // sweep data 1
+ 0x0a, 0x00, 0x00, 0x00, // sequence number
+ 0x0c, 0x00, 0x00, 0x00, // timestamp
+ 0x01, // vendor specific data length
+ 0x0b, // vendor specific data
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, // sample data
+ // sweep data 2
+ 0x0b, 0x00, 0x00, 0x00, // sequence number
+ 0x0d, 0x00, 0x00, 0x00, // timestamp
+ 0x02, // vendor specific data length
+ 0x0b, 0x0c, // vendor specific data
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // sample data
+ ];
+
+ // Setup the DataPacketRcv (Rx by HAL) and the expected DataRcvNotification.
+ let radar_data_packet_rcv =
+ build_uci_packet(mt_data, pbf, dpf, oid, radar_data_rcv_payload);
+ let expected_radar_data_rcv_notification = RadarDataRcvNotification {
+ session_token: session_id,
+ status: DataRcvStatusCode::UciStatusSuccess,
+ radar_data_type,
+ number_of_sweeps,
+ samples_per_sweep,
+ bits_per_sample,
+ sweep_offset,
+ sweep_data: vec![
+ RadarSweepData {
+ sequence_number: sequence_number_1,
+ timestamp: timestamp_1,
+ vendor_specific_data: vendor_specific_data_1,
+ sample_data: sample_data_1,
+ },
+ RadarSweepData {
+ sequence_number: sequence_number_2,
+ timestamp: timestamp_2,
+ vendor_specific_data: vendor_specific_data_2,
+ sample_data: sample_data_2,
+ },
+ ],
+ };
+
+ // Setup an active UWBS session over which the DataPacket will be received by the Host.
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_session_active(
+ |_| async move {},
+ UciLoggerMode::Disabled,
+ mpsc::unbounded_channel::<UciLogEvent>().0,
+ session_id,
+ session_token,
+ )
+ .await;
+
+ let (radar_data_rcv_notification_sender, mut radar_data_rcv_notification_receiver) =
+ mpsc::unbounded_channel::<RadarDataRcvNotification>();
+ uci_manager
+ .set_radar_data_rcv_notification_sender(radar_data_rcv_notification_sender)
+ .await;
+
+ // Inject the UCI DataPacketRcv into HAL.
+ let result = mock_hal.receive_packet(radar_data_packet_rcv);
+ assert!(result.is_ok());
+
+ // UciManager should send a DataRcvNotification (for the valid Rx packet).
+ let result = tokio::time::timeout(
+ Duration::from_millis(100),
+ radar_data_rcv_notification_receiver.recv(),
+ )
+ .await;
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), Some(expected_radar_data_rcv_notification));
+ assert!(mock_hal.wait_expected_calls_done().await);
+ }
+
#[tokio::test]
async fn test_data_packet_send_ok() {
// Test Data packet send for a single packet (on a UWB session).
diff --git a/src/rust/uwb_core/src/uci/uci_manager_sync.rs b/src/rust/uwb_core/src/uci/uci_manager_sync.rs
index 688f1e9..27a213b 100644
--- a/src/rust/uwb_core/src/uci/uci_manager_sync.rs
+++ b/src/rust/uwb_core/src/uci/uci_manager_sync.rs
@@ -1,4 +1,4 @@
- // Copyright 2022, The Android Open Source Project
+// Copyright 2022, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -26,14 +26,17 @@ use tokio::task;
use crate::error::{Error, Result};
use crate::params::{
- AppConfigTlv, AppConfigTlvType, CapTlv, CoreSetConfigResponse, CountryCode, DeviceConfigId,
- DeviceConfigTlv, GetDeviceInfoResponse, PowerStats, RawUciMessage, ResetConfig, SessionId,
- SessionState, SessionType, SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse,
+ AndroidRadarConfigResponse, AppConfigTlv, AppConfigTlvType, CapTlv, CoreSetConfigResponse,
+ CountryCode, DeviceConfigId, DeviceConfigTlv, GetDeviceInfoResponse, PowerStats,
+ RadarConfigTlv, RadarConfigTlvType, RawUciMessage, ResetConfig, SessionId, SessionState,
+ SessionType, SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse,
UpdateMulticastListAction, UpdateTime,
};
#[cfg(any(test, feature = "mock-utils"))]
use crate::uci::mock_uci_manager::MockUciManager;
-use crate::uci::notification::{CoreNotification, DataRcvNotification, SessionNotification};
+use crate::uci::notification::{
+ CoreNotification, DataRcvNotification, RadarDataRcvNotification, SessionNotification,
+};
use crate::uci::uci_hal::UciHal;
use crate::uci::uci_logger::{UciLogger, UciLoggerMode};
use crate::uci::uci_manager::{UciManager, UciManagerImpl};
@@ -59,6 +62,12 @@ pub trait NotificationManager: 'static {
&mut self,
data_rcv_notification: DataRcvNotification,
) -> Result<()>;
+
+ /// Callback for RadarDataRcvNotification.
+ fn on_radar_data_rcv_notification(
+ &mut self,
+ radar_data_rcv_notification: RadarDataRcvNotification,
+ ) -> Result<()>;
}
/// Builder for NotificationManager. Builder is sent between threads.
@@ -74,6 +83,7 @@ struct NotificationDriver<U: NotificationManager> {
session_notification_receiver: mpsc::UnboundedReceiver<SessionNotification>,
vendor_notification_receiver: mpsc::UnboundedReceiver<RawUciMessage>,
data_rcv_notification_receiver: mpsc::UnboundedReceiver<DataRcvNotification>,
+ radar_data_rcv_notification_receiver: mpsc::UnboundedReceiver<RadarDataRcvNotification>,
notification_manager: U,
}
impl<U: NotificationManager> NotificationDriver<U> {
@@ -82,6 +92,7 @@ impl<U: NotificationManager> NotificationDriver<U> {
session_notification_receiver: mpsc::UnboundedReceiver<SessionNotification>,
vendor_notification_receiver: mpsc::UnboundedReceiver<RawUciMessage>,
data_rcv_notification_receiver: mpsc::UnboundedReceiver<DataRcvNotification>,
+ radar_data_rcv_notification_receiver: mpsc::UnboundedReceiver<RadarDataRcvNotification>,
notification_manager: U,
) -> Self {
Self {
@@ -89,6 +100,7 @@ impl<U: NotificationManager> NotificationDriver<U> {
session_notification_receiver,
vendor_notification_receiver,
data_rcv_notification_receiver,
+ radar_data_rcv_notification_receiver,
notification_manager,
}
}
@@ -115,6 +127,11 @@ impl<U: NotificationManager> NotificationDriver<U> {
error!("NotificationDriver: OnDataRcv callback error: {:?}",e);
});
}
+ Some(data) = self.radar_data_rcv_notification_receiver.recv() =>{
+ self.notification_manager.on_radar_data_rcv_notification(data).unwrap_or_else(|e|{
+ error!("NotificationDriver: OnRadarDataRcv callback error: {:?}",e);
+ });
+ }
else =>{
debug!("NotificationDriver dropping.");
break;
@@ -149,11 +166,16 @@ impl<U: UciManager> UciManagerSync<U> {
mpsc::unbounded_channel::<RawUciMessage>();
let (data_rcv_notification_sender, data_rcv_notification_receiver) =
mpsc::unbounded_channel::<DataRcvNotification>();
+ let (radar_data_rcv_notification_sender, radar_data_rcv_notification_receiver) =
+ mpsc::unbounded_channel::<RadarDataRcvNotification>();
self.runtime_handle.to_owned().block_on(async {
self.uci_manager.set_core_notification_sender(core_notification_sender).await;
self.uci_manager.set_session_notification_sender(session_notification_sender).await;
self.uci_manager.set_vendor_notification_sender(vendor_notification_sender).await;
self.uci_manager.set_data_rcv_notification_sender(data_rcv_notification_sender).await;
+ self.uci_manager
+ .set_radar_data_rcv_notification_sender(radar_data_rcv_notification_sender)
+ .await;
});
// The potentially !Send NotificationManager is created in a separate thread.
let (driver_status_sender, mut driver_status_receiver) = mpsc::unbounded_channel::<bool>();
@@ -186,6 +208,7 @@ impl<U: UciManager> UciManagerSync<U> {
session_notification_receiver,
vendor_notification_receiver,
data_rcv_notification_receiver,
+ radar_data_rcv_notification_receiver,
notification_manager,
);
local.spawn_local(async move {
@@ -204,7 +227,7 @@ impl<U: UciManager> UciManagerSync<U> {
self.runtime_handle.block_on(self.uci_manager.set_logger_mode(logger_mode))
}
/// Start UCI HAL and blocking until UCI commands can be sent.
- pub fn open_hal(&self) -> Result<()> {
+ pub fn open_hal(&self) -> Result<GetDeviceInfoResponse> {
self.runtime_handle.block_on(self.uci_manager.open_hal())
}
@@ -342,6 +365,26 @@ impl<U: UciManager> UciManagerSync<U> {
self.runtime_handle.block_on(self.uci_manager.android_get_power_stats())
}
+ /// Set radar config. Android-specific method.
+ pub fn android_set_radar_config(
+ &self,
+ session_id: SessionId,
+ config_tlvs: Vec<RadarConfigTlv>,
+ ) -> Result<AndroidRadarConfigResponse> {
+ self.runtime_handle
+ .block_on(self.uci_manager.android_set_radar_config(session_id, config_tlvs))
+ }
+
+ /// Get radar config. Android-specific method.
+ pub fn android_get_radar_config(
+ &self,
+ session_id: SessionId,
+ config_ids: Vec<RadarConfigTlvType>,
+ ) -> Result<Vec<RadarConfigTlv>> {
+ self.runtime_handle
+ .block_on(self.uci_manager.android_get_radar_config(session_id, config_ids))
+ }
+
/// Send a raw UCI command.
pub fn raw_uci_cmd(
&self,
@@ -449,6 +492,7 @@ mod tests {
use crate::params::uci_packets::GetDeviceInfoResponse;
use crate::uci::mock_uci_manager::MockUciManager;
use crate::uci::{CoreNotification, UciNotification};
+ use uwb_uci_packets::StatusCode::UciStatusOk;
/// Mock NotificationManager forwarding notifications received.
/// The nonsend_counter is deliberately !send to check UciManagerSync::redirect_notification.
@@ -484,6 +528,13 @@ mod tests {
self.nonsend_counter.replace_with(|&mut prev| prev + 1);
Ok(())
}
+ fn on_radar_data_rcv_notification(
+ &mut self,
+ _data_rcv_notf: RadarDataRcvNotification,
+ ) -> Result<()> {
+ self.nonsend_counter.replace_with(|&mut prev| prev + 1);
+ Ok(())
+ }
}
/// Builder for MockNotificationManager.
@@ -516,17 +567,20 @@ mod tests {
let test_rt = Builder::new_multi_thread().enable_all().build().unwrap();
let (notf_sender, mut notf_receiver) = mpsc::unbounded_channel::<UciNotification>();
let mut uci_manager_impl = MockUciManager::new();
- uci_manager_impl.expect_open_hal(
- vec![UciNotification::Core(CoreNotification::DeviceStatus(DeviceStateReady))],
- Ok(()),
- );
- uci_manager_impl.expect_core_get_device_info(Ok(GetDeviceInfoResponse {
+ let get_device_info_rsp = GetDeviceInfoResponse {
+ status: UciStatusOk,
uci_version: 0,
mac_version: 0,
phy_version: 0,
uci_test_version: 0,
vendor_spec_info: vec![],
- }));
+ };
+
+ uci_manager_impl.expect_open_hal(
+ vec![UciNotification::Core(CoreNotification::DeviceStatus(DeviceStateReady))],
+ Ok(get_device_info_rsp.clone()),
+ );
+ uci_manager_impl.expect_core_get_device_info(Ok(get_device_info_rsp));
let uci_manager_sync = UciManagerSync::new_mock(
uci_manager_impl,
test_rt.handle().to_owned(),
diff --git a/src/rust/uwb_uci_packets/src/lib.rs b/src/rust/uwb_uci_packets/src/lib.rs
index 0c9fa3c..d3e7c8a 100644
--- a/src/rust/uwb_uci_packets/src/lib.rs
+++ b/src/rust/uwb_uci_packets/src/lib.rs
@@ -53,6 +53,11 @@ const UCI_CONTROL_HEADER_GID_MASK: u8 = 0xF;
const UCI_CONTROL_HEADER_OID_BYTE_POSITION: usize = 1;
const UCI_CONTROL_HEADER_OID_MASK: u8 = 0x3F;
+// Radar field lengths
+pub const UCI_RADAR_SEQUENCE_NUMBER_LEN: usize = 4;
+pub const UCI_RADAR_TIMESTAMP_LEN: usize = 4;
+pub const UCI_RADAR_VENDOR_DATA_LEN_LEN: usize = 1;
+
#[derive(Debug, Clone, PartialEq, FromPrimitive)]
pub enum TimeStampLength {
Timestamp40Bit = 0x0,
@@ -432,16 +437,21 @@ impl RawUciControlPacket {
}
}
-// UCI Data packet functions.
-fn is_uci_data_rcv_packet(message_type: MessageType, data_packet_format: DataPacketFormat) -> bool {
- message_type == MessageType::Data && data_packet_format == DataPacketFormat::DataRcv
+fn is_uci_data_packet(message_type: MessageType) -> bool {
+ message_type == MessageType::Data
+}
+
+fn is_data_rcv_or_radar_format(data_packet_format: DataPacketFormat) -> bool {
+ data_packet_format == DataPacketFormat::DataRcv
+ || data_packet_format == DataPacketFormat::RadarDataMessage
}
-fn try_into_data_payload(packet: UciPacketHal) -> Result<Bytes> {
- if is_uci_data_rcv_packet(
- packet.get_message_type(),
- packet.get_group_id_or_data_packet_format().try_into()?,
- ) {
+fn try_into_data_payload(
+ packet: UciPacketHal,
+ expected_data_packet_format: DataPacketFormat,
+) -> Result<Bytes> {
+ let dpf: DataPacketFormat = packet.get_group_id_or_data_packet_format().try_into()?;
+ if is_uci_data_packet(packet.get_message_type()) && dpf == expected_data_packet_format {
Ok(packet.to_bytes().slice(UCI_PACKET_HAL_HEADER_LEN..))
} else {
error!("Received unexpected data packet fragment: {:?}", packet);
@@ -459,12 +469,17 @@ impl TryFrom<Vec<UciPacketHal>> for UciDataPacket {
return Err(Error::InvalidPacketError);
}
+ let dpf: DataPacketFormat = packets[0].get_group_id_or_data_packet_format().try_into()?;
+ if !is_data_rcv_or_radar_format(dpf) {
+ error!("Unexpected data packet format {:?}", dpf);
+ }
+
// Create the reassembled payload.
let mut payload_buf = Bytes::new();
for packet in packets {
// Ensure that the fragment is a Data Rcv packet.
// Get payload by stripping the header.
- payload_buf = [payload_buf, try_into_data_payload(packet)?].concat().into();
+ payload_buf = [payload_buf, try_into_data_payload(packet, dpf)?].concat().into();
}
// Create assembled |UciDataPacket| and convert to bytes again since we need to
@@ -472,7 +487,7 @@ impl TryFrom<Vec<UciPacketHal>> for UciDataPacket {
UciDataPacket::parse(
&UciDataPacketBuilder {
message_type: MessageType::Data,
- data_packet_format: DataPacketFormat::DataRcv,
+ data_packet_format: dpf,
payload: Some(payload_buf.into()),
}
.build()
@@ -824,8 +839,7 @@ pub fn build_session_update_controller_multicast_list_cmd(
) -> Result<SessionUpdateControllerMulticastListCmd> {
let mut controlees_buf = BytesMut::new();
match controlees {
- Controlees::NoSessionKey(controlee_v1) =>
- {
+ Controlees::NoSessionKey(controlee_v1) => {
controlees_buf.extend_from_slice(&(controlee_v1.len() as u8).to_le_bytes());
for controlee in controlee_v1 {
controlees_buf.extend_from_slice(&write_controlee(&controlee));
@@ -866,6 +880,17 @@ impl Drop for AppConfigTlv {
}
}
+// Radar data 'bits per sample' field isn't a raw value, instead it's an enum
+// that maps to the raw value. We need this mapping to get the max sample size
+// length.
+pub fn radar_bytes_per_sample_value(bps: BitsPerSample) -> u8 {
+ match bps {
+ BitsPerSample::Value32 => 4,
+ BitsPerSample::Value48 => 6,
+ BitsPerSample::Value64 => 8,
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/rust/uwb_uci_packets/uci_packets.pdl b/src/rust/uwb_uci_packets/uci_packets.pdl
index cfa548d..1f3969c 100644
--- a/src/rust/uwb_uci_packets/uci_packets.pdl
+++ b/src/rust/uwb_uci_packets/uci_packets.pdl
@@ -22,6 +22,7 @@ enum GroupId : 4 {
enum DataPacketFormat: 4 {
DATA_SND = 0x01,
DATA_RCV = 0x02,
+ RADAR_DATA_MESSAGE = 0x0f,
}
// Define a merged enum across GroupId & DataPacketFormat as they are at the same bits in
@@ -87,6 +88,8 @@ enum AndroidOpCode : 6 {
ANDROID_GET_POWER_STATS = 0x0,
ANDROID_SET_COUNTRY_CODE = 0x1,
ANDROID_FIRA_RANGE_DIAGNOSTICS = 0x2,
+ ANDROID_RADAR_SET_APP_CONFIG = 0x11,
+ ANDROID_RADAR_GET_APP_CONFIG = 0x12,
}
enum StatusCode : 8 {
@@ -173,6 +176,7 @@ enum DataTransferNtfStatusCode : 8 {
UCI_DATA_TRANSFER_STATUS_ERROR_REJECTED = 0x04,
UCI_DATA_TRANSFER_STATUS_SESSION_TYPE_NOT_SUPPORTED = 0x05,
UCI_DATA_TRANSFER_STATUS_ERROR_DATA_TRANSFER_IS_ONGOING = 0x06,
+ UCI_DATA_TRANSFER_STATUS_INVALID_FORMAT = 0x07,
}
enum ResetConfig : 8 {
@@ -246,12 +250,14 @@ enum AppConfigTlvType : 8 {
MIN_FRAMES_PER_RR = 0x3A,
MTU_SIZE = 0x3B,
INTER_FRAME_INTERVAL = 0x3C,
- RFU_APP_CFG_TLV_TYPE_RANGE_1 = 0x3D..0x44,
+ RFU_APP_CFG_TLV_TYPE_RANGE_1 = 0x3D..0x42,
+ DLTDOA_BLOCK_STRIDING = 0x43,
+ RFU_APP_CFG_TLV_TYPE_RANGE_2 = 0x44,
SESSION_KEY = 0x45,
SUBSESSION_KEY = 0x46,
SESSION_DATA_TRANSFER_STATUS_NTF_CONFIG = 0x47,
SESSION_TIME_BASE = 0x48,
- RFU_APP_CFG_TLV_TYPE_RANGE_2 = 0x49..0x9F,
+ RFU_APP_CFG_TLV_TYPE_RANGE_3 = 0x49..0x9F,
VENDOR_SPECIFIC_APP_CFG_TLV_TYPE_RANGE_1 = 0xA0..0xDF {
// CCC specific
@@ -265,7 +271,7 @@ enum AppConfigTlvType : 8 {
},
// Reserved for extension IDs.
- RFU_APP_CFG_TLV_TYPE_RANGE_3 = 0xE0..0xE2,
+ RFU_APP_CFG_TLV_TYPE_RANGE_4 = 0xE0..0xE2,
VENDOR_SPECIFIC_APP_CFG_TLV_TYPE_RANGE_2 = 0xE3..0xFF {
// Interleaving ratio if AOA_RESULT_REQ is set to 0xF0.
@@ -317,6 +323,8 @@ enum CapTlvType : 8 {
CCC_SUPPORTED_PULSE_SHAPE_COMBOS = 0xA6,
CCC_SUPPORTED_RAN_MULTIPLIER = 0xA7,
CCC_SUPPORTED_MAX_RANGING_SESSION_NUMBER = 0xA8,
+ // RADAR specific
+ RADAR_SUPPORT = 0xB0
},
SUPPORTED_POWER_STATS = 0xC0,
@@ -418,9 +426,10 @@ enum MulticastUpdateStatusCode : 8 {
STATUS_ERROR_MULTICAST_LIST_FULL = 0x01,
STATUS_ERROR_KEY_FETCH_FAIL = 0x02,
STATUS_ERROR_SUB_SESSION_ID_NOT_FOUND = 0x03,
- STATUS_ERROR_SUB_SESSION_KEY_NOT_FOUND = 0x05,
- STATUS_ERROR_SUB_SESSION_KEY_NOT_APPLICABLE = 0x06,
- STATUS_ERROR_SESSION_KEY_NOT_FOUND = 0x07,
+ STATUS_ERROR_SUB_SESSION_KEY_NOT_FOUND = 0x04,
+ STATUS_ERROR_SUB_SESSION_KEY_NOT_APPLICABLE = 0x05,
+ STATUS_ERROR_SESSION_KEY_NOT_FOUND = 0x06,
+ STATUS_ERROR_ADDRESS_NOT_FOUND = 0x07,
STATUS_ERROR_ADDRESS_ALREADY_PRESENT = 0x08,
RFU_STATUS_CODE_RANGE_1 = 0x09..0xFF,
}
@@ -438,6 +447,7 @@ enum SessionType: 8 {
FIRA_IN_BAND_DATA_PHASE = 0x04,
FIRA_RANGING_WITH_DATA_PHASE = 0x05,
CCC = 0xA0,
+ RADAR_SESSION = 0xA1,
DEVICE_TEST_MODE = 0xD0,
}
@@ -527,7 +537,7 @@ packet UciDataSnd : UciDataPacket (data_packet_format = DATA_SND, message_type =
packet UciDataRcv : UciDataPacket (data_packet_format = DATA_RCV, message_type = DATA) {
session_token: 32, // Session ID or Session Handle (based on UWBS version)
- status: DataRcvStatusCode,
+ status: StatusCode,
source_mac_address: 64,
uci_sequence_number: 16,
_size_(data): 16,
@@ -1017,11 +1027,12 @@ test SessionQueryMaxDataSizeCmd {
packet SessionQueryMaxDataSizeRsp : SessionConfigResponse (opcode = 0xB) { //QUER_MAX_DATA_SIZE
session_token: 32, // Session ID or Session Handle (based on UWBS version)
+ status: StatusCode,
max_data_size: 16,
}
test SessionQueryMaxDataSizeRsp {
- "\x41\x0B\x00\x06\x00\x00\x00\x00\x0E7\0x07",
+ "\x41\x0B\x00\x06\x00\x00\x00\x00\x00\x0E7\0x07",
}
packet SessionStartCmd : SessionControlCommand (opcode = 0x0) { //RANGE_START
@@ -1373,3 +1384,88 @@ packet UciVendor_F_Notification : UciNotification (group_id = VENDOR_RESERVED_F)
packet TestNotification : UciNotification (group_id = TEST) {
_payload_,
}
+
+enum RadarDataType : 8 {
+ RADAR_SWEEP_SAMPLES = 0x00,
+}
+
+enum RadarConfigTlvType : 8 {
+ RADAR_TIMING_PARAMS = 0x00,
+ SAMPLES_PER_SWEEP = 0x01,
+ CHANNEL_NUMBER = 0x02,
+ SWEEP_OFFSET = 0x03,
+ RFRAME_CONFIG = 0x04,
+ PREAMBLE_DURATION = 0x05,
+ PREAMBLE_CODE_INDEX = 0x06,
+ SESSION_PRIORITY = 0x07,
+ BITS_PER_SAMPLE = 0x08,
+ PRF_MODE = 0x09,
+ NUMBER_OF_BURSTS = 0x0A,
+ RADAR_DATA_TYPE = 0x0B,
+
+ RFU_RADAR_APP_CFG_TLV_TYPE_RANGE = 0x0C..0x9F,
+
+ VENDOR_SPECIFIC_RADAR_APP_CFG_TLV_TYPE_RANGE = 0xA0..0xDF,
+}
+
+struct RadarConfigTlv {
+ cfg_id: RadarConfigTlvType,
+ _count_(v): 8,
+ v: 8[],
+}
+
+struct RadarConfigStatus {
+ cfg_id: RadarConfigTlvType,
+ status: StatusCode,
+}
+
+packet AndroidSetRadarConfigCmd: AndroidCommand (opcode = 0x11) {
+ session_token: 32,
+ _count_(tlvs): 8,
+ tlvs: RadarConfigTlv[]
+}
+
+packet AndroidSetRadarConfigRsp : AndroidResponse (opcode = 0x11) {
+ status: StatusCode,
+ _count_(cfg_status): 8,
+ cfg_status: RadarConfigStatus[],
+}
+
+packet AndroidGetRadarConfigCmd: AndroidCommand (opcode = 0x12) {
+ session_token: 32,
+ _count_(tlvs): 8,
+ tlvs: 8[], // RadarConfigTlvType (Infra does not allow array of enums)
+}
+
+packet AndroidGetRadarConfigRsp : AndroidResponse (opcode = 0x12) {
+ status: StatusCode,
+ _count_(tlvs): 8,
+ tlvs: RadarConfigTlv[],
+}
+
+enum BitsPerSample : 8 {
+ VALUE_32 = 0x00,
+ VALUE_48 = 0x01,
+ VALUE_64 = 0x02
+}
+
+struct RadarSweepDataRaw {
+ sequence_number: 32,
+ timestamp: 32,
+ _count_(vendor_specific_data): 8,
+ vendor_specific_data: 8[],
+ sample_data: 8[],
+}
+
+packet RadarDataRcv : UciDataPacket (data_packet_format = RADAR_DATA_MESSAGE, message_type = DATA) {
+ session_handle: 32,
+ status: DataRcvStatusCode,
+ radar_data_type: RadarDataType,
+ number_of_sweeps: 8,
+ samples_per_sweep: 8,
+ bits_per_sample: BitsPerSample,
+ sweep_offset: 16,
+ sweep_data_size: 16,
+ sweep_data: 8[],
+}
+