diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-07-21 20:35:26 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-07-21 20:35:26 +0000 |
commit | ae7b20087858ddb4019e59f799658e85732c1cc3 (patch) | |
tree | 3bb1202e781ae4a03690f444889db8d34e60b201 | |
parent | 3007b82d01ba24fd57b29b3332ed84e0b3a867a7 (diff) | |
parent | e177c03e15f8d05ca724173217f9cb43f8efed87 (diff) | |
download | uwb-android13-mainline-go-media-release.tar.gz |
Snap for 8857176 from e177c03e15f8d05ca724173217f9cb43f8efed87 to mainline-go-media-releaseaml_go_med_330913000android13-mainline-go-media-release
Change-Id: I4233d2c0bc3403abae3d7fc76a59e114763af80b
-rw-r--r-- | src/rust/uwb_core/Cargo.toml | 9 | ||||
-rw-r--r-- | src/rust/uwb_core/rustfmt.toml | 1 | ||||
-rw-r--r-- | src/rust/uwb_core/src/session/session_manager.rs | 98 | ||||
-rw-r--r-- | src/rust/uwb_core/src/uci.rs | 1 | ||||
-rw-r--r-- | src/rust/uwb_core/src/uci/mock_uci_manager.rs | 6 | ||||
-rw-r--r-- | src/rust/uwb_core/src/uci/notification.rs | 6 | ||||
-rw-r--r-- | src/rust/uwb_core/src/uci/response.rs | 4 | ||||
-rw-r--r-- | src/rust/uwb_core/src/uci/uci_manager.rs | 4 | ||||
-rw-r--r-- | src/rust/uwb_core/src/uci/uci_manager_sync.rs | 344 | ||||
-rw-r--r-- | src/rust/uwb_uci_packets/uci_packets.pdl | 56 |
10 files changed, 514 insertions, 15 deletions
diff --git a/src/rust/uwb_core/Cargo.toml b/src/rust/uwb_core/Cargo.toml index a22cd90..c9294f1 100644 --- a/src/rust/uwb_core/Cargo.toml +++ b/src/rust/uwb_core/Cargo.toml @@ -4,15 +4,14 @@ version = "0.0.1" edition = "2018" [dependencies] -async-trait = "0.1.52" +async-trait = "0.1.32" bytes = "1.1.0" -num-traits = "0.2.14" log = "0.4.14" +num-traits = "0.2.12" thiserror = "1.0.30" -tokio = {version = "1.14.0", features = ["sync", "rt", "macros", "time"]} +tokio = { version = "1.14.0", features = ["macros", "rt", "rt-multi-thread", "sync", "time"] } -uwb_uci_packets = { path = "../uwb_uci_packets"} +uwb_uci_packets = { path = "../uwb_uci_packets" } # provided by ebuild [dev-dependencies] env_logger = "0.9.0" -tokio = {version = "1.14.0", features = ["rt-multi-thread"]} diff --git a/src/rust/uwb_core/rustfmt.toml b/src/rust/uwb_core/rustfmt.toml index 12c133b..5831856 100644 --- a/src/rust/uwb_core/rustfmt.toml +++ b/src/rust/uwb_core/rustfmt.toml @@ -1,3 +1,4 @@ edition = "2018" use_small_heuristics = "Max" newline_style = "Unix" +max_width = 100
\ No newline at end of file diff --git a/src/rust/uwb_core/src/session/session_manager.rs b/src/rust/uwb_core/src/session/session_manager.rs index 8233766..f2280ad 100644 --- a/src/rust/uwb_core/src/session/session_manager.rs +++ b/src/rust/uwb_core/src/session/session_manager.rs @@ -481,6 +481,7 @@ mod tests { SetAppConfigResponse, StatusCode, }; use crate::params::utils::{u32_to_bytes, u64_to_bytes, u8_to_bytes}; + use crate::params::{FiraAppConfigParamsBuilder, KeyRotation}; use crate::uci::notification::UciNotification; #[tokio::test] @@ -889,4 +890,101 @@ mod tests { assert!(mock_uci_manager.wait_expected_calls_done().await); } + + #[tokio::test] + async fn test_reconfigure_app_config() { + let session_id = 0x123; + let session_type = SessionType::FiraRangingSession; + + let initial_params = generate_params(); + let initial_tlvs = initial_params.generate_tlvs(); + + let non_default_key_rotation_val = KeyRotation::Enable; + let idle_params = FiraAppConfigParamsBuilder::from_params(&initial_params) + .unwrap() + .key_rotation(non_default_key_rotation_val) + .build() + .unwrap(); + let idle_tlvs = idle_params + .generate_updated_tlvs(&initial_params, SessionState::SessionStateIdle) + .unwrap(); + + let non_default_block_stride_val = 2u8; + let active_params = FiraAppConfigParamsBuilder::from_params(&idle_params) + .unwrap() + .block_stride_length(non_default_block_stride_val) + .build() + .unwrap(); + let active_tlvs = active_params + .generate_updated_tlvs(&idle_params, SessionState::SessionStateIdle) + .unwrap(); + + let (mut session_manager, mut mock_uci_manager, _) = + setup_session_manager(move |uci_manager| { + uci_manager.expect_session_init( + session_id, + session_type, + vec![session_status_notf(session_id, SessionState::SessionStateInit)], + Ok(()), + ); + uci_manager.expect_session_set_app_config( + session_id, + initial_tlvs, + vec![session_status_notf(session_id, SessionState::SessionStateIdle)], + Ok(SetAppConfigResponse { + status: StatusCode::UciStatusOk, + config_status: vec![], + }), + ); + uci_manager.expect_session_set_app_config( + session_id, + idle_tlvs, + vec![], + Ok(SetAppConfigResponse { + status: StatusCode::UciStatusOk, + config_status: vec![], + }), + ); + uci_manager.expect_range_start( + session_id, + vec![session_status_notf(session_id, SessionState::SessionStateActive)], + Ok(()), + ); + uci_manager.expect_session_set_app_config( + session_id, + active_tlvs, + vec![], + Ok(SetAppConfigResponse { + status: StatusCode::UciStatusOk, + config_status: vec![], + }), + ); + }) + .await; + + // Reconfiguring without first initing a session should fail. + let result = session_manager.reconfigure(session_id, initial_params.clone()).await; + assert_eq!(result, Err(Error::BadParameters)); + + let result = + session_manager.init_session(session_id, session_type, initial_params.clone()).await; + assert_eq!(result, Ok(())); + + // Reconfiguring any parameters during idle state should succeed. + let result = session_manager.reconfigure(session_id, idle_params.clone()).await; + assert_eq!(result, Ok(())); + + let result = session_manager.start_ranging(session_id).await; + assert_eq!(result, Ok(idle_params)); + + // Reconfiguring most parameters during active state should fail. + let result = session_manager.reconfigure(session_id, initial_params).await; + assert_eq!(result, Err(Error::BadParameters)); + + // Only some parameters are allowed to be reconfigured during active state. + let result = session_manager.reconfigure(session_id, active_params).await; + assert_eq!(result, Ok(())); + + assert!(mock_uci_manager.wait_expected_calls_done().await); + } } diff --git a/src/rust/uwb_core/src/uci.rs b/src/rust/uwb_core/src/uci.rs index 38456ad..55fe794 100644 --- a/src/rust/uwb_core/src/uci.rs +++ b/src/rust/uwb_core/src/uci.rs @@ -24,6 +24,7 @@ pub(crate) mod notification; pub(crate) mod uci_manager; pub mod uci_hal; +pub mod uci_manager_sync; #[cfg(test)] pub(crate) mod mock_uci_hal; 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 9a9eaac..6b9086d 100644 --- a/src/rust/uwb_core/src/uci/mock_uci_manager.rs +++ b/src/rust/uwb_core/src/uci/mock_uci_manager.rs @@ -166,7 +166,7 @@ impl MockUciManager { }); } - pub fn expect_session_get_count(&mut self, out: Result<usize>) { + pub fn expect_session_get_count(&mut self, out: Result<u8>) { self.expected_calls.lock().unwrap().push_back(ExpectedCall::SessionGetCount { out }); } @@ -516,7 +516,7 @@ impl UciManager for MockUciManager { } } - async fn session_get_count(&mut self) -> Result<usize> { + async fn session_get_count(&mut self) -> Result<u8> { let mut expected_calls = self.expected_calls.lock().unwrap(); match expected_calls.pop_front() { Some(ExpectedCall::SessionGetCount { out }) => { @@ -742,7 +742,7 @@ enum ExpectedCall { out: Result<Vec<AppConfigTlv>>, }, SessionGetCount { - out: Result<usize>, + out: Result<u8>, }, SessionGetState { expected_session_id: SessionId, diff --git a/src/rust/uwb_core/src/uci/notification.rs b/src/rust/uwb_core/src/uci/notification.rs index 714aeb1..79d382e 100644 --- a/src/rust/uwb_core/src/uci/notification.rs +++ b/src/rust/uwb_core/src/uci/notification.rs @@ -25,20 +25,20 @@ use crate::params::uci_packets::{ }; #[derive(Debug, Clone, PartialEq)] -pub(crate) enum UciNotification { +pub enum UciNotification { Core(CoreNotification), Session(SessionNotification), Vendor(RawVendorMessage), } #[derive(Debug, Clone, PartialEq)] -pub(crate) enum CoreNotification { +pub enum CoreNotification { DeviceStatus(DeviceState), GenericError(StatusCode), } #[derive(Debug, Clone, PartialEq)] -pub(crate) enum SessionNotification { +pub enum SessionNotification { Status { session_id: SessionId, session_state: SessionState, diff --git a/src/rust/uwb_core/src/uci/response.rs b/src/rust/uwb_core/src/uci/response.rs index 0037a0c..efcf466 100644 --- a/src/rust/uwb_core/src/uci/response.rs +++ b/src/rust/uwb_core/src/uci/response.rs @@ -38,7 +38,7 @@ pub(super) enum UciResponse { SessionDeinit(Result<()>), SessionSetAppConfig(SetAppConfigResponse), SessionGetAppConfig(Result<Vec<AppConfigTlv>>), - SessionGetCount(Result<usize>), + SessionGetCount(Result<u8>), SessionGetState(Result<SessionState>), SessionUpdateControllerMulticastList(Result<()>), RangeStart(Result<()>), @@ -156,7 +156,7 @@ impl TryFrom<uwb_uci_packets::SessionResponsePacket> for UciResponse { Ok(UciResponse::SessionDeinit(status_code_to_result(evt.get_status()))) } SessionResponseChild::SessionGetCountRsp(evt) => Ok(UciResponse::SessionGetCount( - status_code_to_result(evt.get_status()).map(|_| evt.get_session_count() as usize), + status_code_to_result(evt.get_status()).map(|_| evt.get_session_count()), )), SessionResponseChild::SessionGetStateRsp(evt) => Ok(UciResponse::SessionGetState( status_code_to_result(evt.get_status()).map(|_| evt.get_session_state()), diff --git a/src/rust/uwb_core/src/uci/uci_manager.rs b/src/rust/uwb_core/src/uci/uci_manager.rs index 2a4d682..b86f862 100644 --- a/src/rust/uwb_core/src/uci/uci_manager.rs +++ b/src/rust/uwb_core/src/uci/uci_manager.rs @@ -92,7 +92,7 @@ pub(crate) trait UciManager: 'static + Send + Clone { session_id: SessionId, config_ids: Vec<AppConfigTlvType>, ) -> Result<Vec<AppConfigTlv>>; - async fn session_get_count(&mut self) -> Result<usize>; + async fn session_get_count(&mut self) -> Result<u8>; async fn session_get_state(&mut self, session_id: SessionId) -> Result<SessionState>; async fn session_update_controller_multicast_list( &mut self, @@ -285,7 +285,7 @@ impl UciManager for UciManagerImpl { } } - async fn session_get_count(&mut self) -> Result<usize> { + async fn session_get_count(&mut self) -> Result<u8> { let cmd = UciCommand::SessionGetCount; match self.send_cmd(UciManagerCmd::SendUciCommand { cmd }).await { Ok(UciResponse::SessionGetCount(resp)) => resp, diff --git a/src/rust/uwb_core/src/uci/uci_manager_sync.rs b/src/rust/uwb_core/src/uci/uci_manager_sync.rs new file mode 100644 index 0000000..027a98d --- /dev/null +++ b/src/rust/uwb_core/src/uci/uci_manager_sync.rs @@ -0,0 +1,344 @@ +// 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. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! This module offers a synchornized interface at UCI level. +//! +//! The module is designed with the replacement for Android UCI JNI adaptation in mind. The handling +//! of UciNotifications is different in UciManager and UciManagerSync as the sync version has its +//! behavior aligned with the Android JNI UCI, and routes the UciNotifications to NotificationManager. + +use log::{error, info}; +use tokio::runtime::Runtime; +use tokio::sync::mpsc; + +use crate::error::Result; +use crate::params::{ + AppConfigTlv, AppConfigTlvType, CapTlv, Controlee, CoreSetConfigResponse, CountryCode, + DeviceConfigId, DeviceConfigTlv, GetDeviceInfoResponse, PowerStats, RawVendorMessage, + ResetConfig, SessionId, SessionState, SessionType, SetAppConfigResponse, + UpdateMulticastListAction, +}; +use crate::uci::notification::{CoreNotification, SessionNotification}; +use crate::uci::uci_hal::UciHal; +use crate::uci::uci_manager::{UciManager, UciManagerImpl}; + +/// The NotificationManager trait is needed to process UciNotification relayed from UciManagerSync. +/// +/// The UciManagerSync assumes the NotificationManager takes the responsibility to properly handle +/// the notifications, including tracking the state of HAL. UciManagerSync and lower levels only +/// redirect and categorize the notifications. The notifications are processed through callbacks. +pub trait NotificationManager: 'static + Send { + /// Callback for CoreNotification. + fn on_core_notification(&mut self, core_notification: CoreNotification) -> Result<()>; + + /// Callback for SessionNotification. + fn on_session_notification(&mut self, session_notification: SessionNotification) -> Result<()>; + + /// Callback for RawVendorMessage. + fn on_vendor_notification(&mut self, vendor_notification: RawVendorMessage) -> Result<()>; +} +struct NotificationDriver<U: NotificationManager> { + core_notification_receiver: mpsc::UnboundedReceiver<CoreNotification>, + session_notification_receiver: mpsc::UnboundedReceiver<SessionNotification>, + vendor_notification_receiver: mpsc::UnboundedReceiver<RawVendorMessage>, + notification_manager: U, +} +impl<U: NotificationManager> NotificationDriver<U> { + fn new(notification_manager: U) -> Self { + Self { + core_notification_receiver: mpsc::unbounded_channel::<CoreNotification>().1, + session_notification_receiver: mpsc::unbounded_channel::<SessionNotification>().1, + vendor_notification_receiver: mpsc::unbounded_channel::<RawVendorMessage>().1, + notification_manager, + } + } + fn set_core_notification_receiver( + &mut self, + core_notification_receiver: mpsc::UnboundedReceiver<CoreNotification>, + ) { + self.core_notification_receiver = core_notification_receiver; + } + fn set_session_notification_receiver( + &mut self, + session_notification_receiver: mpsc::UnboundedReceiver<SessionNotification>, + ) { + self.session_notification_receiver = session_notification_receiver; + } + fn set_vendor_notification_receiver( + &mut self, + vendor_notification_receiver: mpsc::UnboundedReceiver<RawVendorMessage>, + ) { + self.vendor_notification_receiver = vendor_notification_receiver; + } + async fn run(&mut self) { + loop { + tokio::select! { + Some(ntf) = self.core_notification_receiver.recv() =>{ + self.notification_manager.on_core_notification(ntf).unwrap_or_else(|e|{ + error!("NotificationDriver: CoreNotification callback error: {:?}",e); + }); + } + Some(ntf) = self.session_notification_receiver.recv() =>{ + self.notification_manager.on_session_notification(ntf).unwrap_or_else(|e|{ + error!("NotificationDriver: SessionNotification callback error: {:?}",e); + }); + } + Some(ntf) = self.vendor_notification_receiver.recv() =>{ + self.notification_manager.on_vendor_notification(ntf).unwrap_or_else(|e|{ + error!("NotificationDriver: RawVendorMessage callback error: {:?}",e); + }); + } + else =>{ + info!("NotificationDriver dropping."); + } + } + } + } +} +/// The UciManagerSync provides a synchornized version of UciManager using the runtime supplied +/// at its initialization. +/// +/// Note the processing of UciNotification is different: they are handled by NotificationManager +/// provided at construction, and the async version set_X_notification_sender methods are removed. +pub struct UciManagerSync { + runtime: Runtime, + uci_manager_impl: UciManagerImpl, +} +impl UciManagerSync { + /// UciHal and NotificationManager required at construction as they are required before open_hal + /// called. runtime is taken with ownership for blocking on async steps only. + pub fn new<T: UciHal, U: NotificationManager>( + runtime: Runtime, + hal: T, + notification_manager: U, + ) -> Self { + // UciManagerImpl::new uses tokio::spawn, so it is called inside the runtime as async fn. + let mut uci_manager_impl = runtime.block_on(async { UciManagerImpl::new(hal) }); + let mut notification_driver = NotificationDriver::new(notification_manager); + runtime.block_on(async { + let (core_notification_sender, core_notification_receiver) = + mpsc::unbounded_channel::<CoreNotification>(); + uci_manager_impl.set_core_notification_sender(core_notification_sender).await; + notification_driver.set_core_notification_receiver(core_notification_receiver); + }); + runtime.block_on(async { + let (session_notification_sender, session_notification_receiver) = + mpsc::unbounded_channel::<SessionNotification>(); + uci_manager_impl.set_session_notification_sender(session_notification_sender).await; + notification_driver.set_session_notification_receiver(session_notification_receiver); + }); + runtime.block_on(async { + let (vendor_notification_sender, vendor_notification_receiver) = + mpsc::unbounded_channel::<RawVendorMessage>(); + uci_manager_impl.set_vendor_notification_sender(vendor_notification_sender).await; + notification_driver.set_vendor_notification_receiver(vendor_notification_receiver); + }); + runtime.spawn(async move { notification_driver.run().await }); + Self { runtime, uci_manager_impl } + } + + /// Start UCI HAL and blocking until UCI commands can be sent. + pub fn open_hal(&mut self) -> Result<()> { + self.runtime.block_on(self.uci_manager_impl.open_hal()) + } + + /// Stop the UCI HAL. + pub fn close_hal(&mut self, force: bool) -> Result<()> { + self.runtime.block_on(self.uci_manager_impl.close_hal(force)) + } + + // Methods for sending UCI commands. Functions are blocked until UCI response is received. + /// Send UCI command for device reset. + pub fn device_reset(&mut self, reset_config: ResetConfig) -> Result<()> { + self.runtime.block_on(self.uci_manager_impl.device_reset(reset_config)) + } + + /// Send UCI command for getting device info. + pub fn core_get_device_info(&mut self) -> Result<GetDeviceInfoResponse> { + self.runtime.block_on(self.uci_manager_impl.core_get_device_info()) + } + + /// Send UCI command for getting capability info + pub fn core_get_caps_info(&mut self) -> Result<Vec<CapTlv>> { + self.runtime.block_on(self.uci_manager_impl.core_get_caps_info()) + } + + /// Send UCI command for setting core configuration. + pub fn core_set_config( + &mut self, + config_tlvs: Vec<DeviceConfigTlv>, + ) -> Result<CoreSetConfigResponse> { + self.runtime.block_on(self.uci_manager_impl.core_set_config(config_tlvs)) + } + + /// Send UCI command for getting core configuration. + pub fn core_get_config( + &mut self, + config_ids: Vec<DeviceConfigId>, + ) -> Result<Vec<DeviceConfigTlv>> { + self.runtime.block_on(self.uci_manager_impl.core_get_config(config_ids)) + } + + /// Send UCI command for initiating session. + pub fn session_init(&mut self, session_id: SessionId, session_type: SessionType) -> Result<()> { + self.runtime.block_on(self.uci_manager_impl.session_init(session_id, session_type)) + } + + /// Send UCI command for deinitiating session. + pub fn session_deinit(&mut self, session_id: SessionId) -> Result<()> { + self.runtime.block_on(self.uci_manager_impl.session_deinit(session_id)) + } + + /// Send UCI command for setting app config. + pub fn session_set_app_config( + &mut self, + session_id: SessionId, + config_tlvs: Vec<AppConfigTlv>, + ) -> Result<SetAppConfigResponse> { + self.runtime.block_on(self.uci_manager_impl.session_set_app_config(session_id, config_tlvs)) + } + + /// Send UCI command for getting app config. + pub fn session_get_app_config( + &mut self, + session_id: SessionId, + config_ids: Vec<AppConfigTlvType>, + ) -> Result<Vec<AppConfigTlv>> { + self.runtime.block_on(self.uci_manager_impl.session_get_app_config(session_id, config_ids)) + } + + /// Send UCI command for getting count of sessions. + pub fn session_get_count(&mut self) -> Result<u8> { + self.runtime.block_on(self.uci_manager_impl.session_get_count()) + } + + /// Send UCI command for getting state of session. + pub fn session_get_state(&mut self, session_id: SessionId) -> Result<SessionState> { + self.runtime.block_on(self.uci_manager_impl.session_get_state(session_id)) + } + + /// Send UCI command for updating multicast list for multicast session. + pub fn session_update_controller_multicast_list( + &mut self, + session_id: SessionId, + action: UpdateMulticastListAction, + controlees: Vec<Controlee>, + ) -> Result<()> { + self.runtime.block_on( + self.uci_manager_impl + .session_update_controller_multicast_list(session_id, action, controlees), + ) + } + + /// Send UCI command for starting ranging of the session. + pub fn range_start(&mut self, session_id: SessionId) -> Result<()> { + self.runtime.block_on(self.uci_manager_impl.range_start(session_id)) + } + + /// Send UCI command for stopping ranging of the session. + pub fn range_stop(&mut self, session_id: SessionId) -> Result<()> { + self.runtime.block_on(self.uci_manager_impl.range_stop(session_id)) + } + + /// Send UCI command for getting ranging count. + pub fn range_get_ranging_count(&mut self, session_id: SessionId) -> Result<usize> { + self.runtime.block_on(self.uci_manager_impl.range_get_ranging_count(session_id)) + } + + /// Set the country code. Android-specific method. + pub fn android_set_country_code(&mut self, country_code: CountryCode) -> Result<()> { + self.runtime.block_on(self.uci_manager_impl.android_set_country_code(country_code)) + } + + /// Get the power statistics. Android-specific method. + pub fn android_get_power_stats(&mut self) -> Result<PowerStats> { + self.runtime.block_on(self.uci_manager_impl.android_get_power_stats()) + } + + /// Send UCI command for a vendor-specific message. + pub fn raw_vendor_cmd( + &mut self, + gid: u32, + oid: u32, + payload: Vec<u8>, + ) -> Result<RawVendorMessage> { + self.runtime.block_on(self.uci_manager_impl.raw_vendor_cmd(gid, oid, payload)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use tokio::runtime::Builder; + use uwb_uci_packets::DeviceState; + + use crate::error::Error; + use crate::uci::mock_uci_hal::MockUciHal; + use crate::uci::uci_hal::RawUciMessage; + + struct MockNotificationManager { + device_state_sender: mpsc::UnboundedSender<DeviceState>, + } + impl MockNotificationManager { + fn new(device_state_sender: mpsc::UnboundedSender<DeviceState>) -> Self { + MockNotificationManager { device_state_sender } + } + } + impl NotificationManager for MockNotificationManager { + fn on_core_notification(&mut self, core_notification: CoreNotification) -> Result<()> { + match core_notification { + CoreNotification::DeviceStatus(device_state) => { + self.device_state_sender.send(device_state).map_err(|_| Error::Unknown)?; + } + CoreNotification::GenericError(_) => {} + }; + Ok(()) + } + fn on_session_notification( + &mut self, + _session_notification: SessionNotification, + ) -> Result<()> { + Ok(()) + } + fn on_vendor_notification(&mut self, _vendor_notification: RawVendorMessage) -> Result<()> { + Ok(()) + } + } + fn into_raw_messages<T: Into<uwb_uci_packets::UciPacketPacket>>( + builder: T, + ) -> Vec<RawUciMessage> { + let packets: Vec<uwb_uci_packets::UciPacketHalPacket> = builder.into().into(); + packets.into_iter().map(|packet| packet.into()).collect() + } + #[test] + fn test_sync_uci_open_hal() { + let mut hal = MockUciHal::new(); + let notf = into_raw_messages(uwb_uci_packets::DeviceStatusNtfBuilder { + device_state: uwb_uci_packets::DeviceState::DeviceStateReady, + }); + hal.expected_open(Some(notf), Ok(())); + let test_rt = Builder::new_multi_thread().enable_all().build().unwrap(); + let (device_state_sender, mut device_state_receiver) = + mpsc::unbounded_channel::<DeviceState>(); + let mut uci_manager_sync = UciManagerSync::new( + Builder::new_multi_thread().enable_all().build().unwrap(), + hal, + MockNotificationManager::new(device_state_sender), + ); + assert!(uci_manager_sync.open_hal().is_ok()); + let device_state = test_rt.block_on(async { device_state_receiver.recv().await }); + assert_eq!(device_state, Some(DeviceState::DeviceStateReady)); + } +} diff --git a/src/rust/uwb_uci_packets/uci_packets.pdl b/src/rust/uwb_uci_packets/uci_packets.pdl index 3ad5d5f..28263fb 100644 --- a/src/rust/uwb_uci_packets/uci_packets.pdl +++ b/src/rust/uwb_uci_packets/uci_packets.pdl @@ -57,6 +57,7 @@ enum AppDataOpCode : 6 { enum AndroidOpCode : 6 { ANDROID_GET_POWER_STATS = 0x0, ANDROID_SET_COUNTRY_CODE = 0x1, + ANDROID_FIRA_RANGE_DIAGNOSTICS = 0x2, } enum StatusCode : 8 { @@ -177,6 +178,15 @@ enum AppConfigTlvType : 8 { NB_OF_RANGE_MEASUREMENTS = 0xE3, NB_OF_AZIMUTH_MEASUREMENTS = 0xE4, NB_OF_ELEVATION_MEASUREMENTS = 0xE5, + + ENABLE_DIAGNOSTICS = 0xE8, + DIAGRAMS_FRAME_REPORTS_FIELDS = 0xE9, +} + +enum FrameReportTlvType : 8 { + RSSI = 0x0, + AOA = 0x1, + CIR = 0x2, } enum CapTlvType : 8 { @@ -827,6 +837,52 @@ test AndroidSetCountryCodeRsp { "\x4c\x01\x00\x01\x00\x00\x00\x00", } +struct FrameReportTlv { + t: FrameReportTlvType, + length: 8, + v: 8[], +} + +packet AoaMeasurement { + tdoa: 16, + pdoa: 16, + aoa: 16, + fom: 8, + t: 8, +} + +packet Cir { + first_path_index : 16, + first_path_snr: 16, + first_path_ns: 16, + peak_path_index: 16, + peak_path_snr: 16, + peak_path_ns: 16, + first_path_sample_offset: 8, + sample_size: 8, + samples_number: 8, + sample_window: 8[], +} + +struct FrameReport { + uwb_msg_id: 8, + action: 8, + antenna_set: 8, + _count_(frame_report_tlvs): 8, + frame_report_tlvs: FrameReportTlv[], +} + +packet AndroidFiraRangeDiagnosticsNtf : AndroidNotification (opcode = 0x2) { //QORVO_FIRA_RANGE_DIAGNOSTICS + session_id: 32, + sequence_number: 32, + _count_(frame_reports): 8, + frame_reports: FrameReport[], +} + +test AndroidFiraRangeDiagnosticsNtf { + "\x6c\x02\x00\x10\x00\x00\x00\x01\x01\x01\x01\x02\x02\x02\x02\x01\x00\x01\x02\x01\x00\x01\x00", +} + packet UciVendor_9_Command : UciCommand (group_id = VENDOR_RESERVED_9) { _payload_, } |