summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-09-12 17:13:34 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-09-12 17:13:34 +0000
commit2424686157864d83dcb19f213c8f44ca88846997 (patch)
tree363d8e541d04a792411d7e822eef8b794b09901b
parent4ffdea82cf7be632fae3e15b6519950e9d26f0d7 (diff)
parentc533cdbd8db59d4130ec89142adf0c6ca997553d (diff)
downloaduwb-android13-mainline-appsearch-release.tar.gz
Snap for 9052600 from c533cdbd8db59d4130ec89142adf0c6ca997553d to mainline-appsearch-releaseaml_ase_331311020aml_ase_331112000android13-mainline-appsearch-release
Change-Id: Iaff3ade404f7ee3f0b301344001c8b60e680c02f
-rwxr-xr-xNOTICE218
-rwxr-xr-xsrc/Android.bp5
-rw-r--r--src/TEST_MAPPING9
-rw-r--r--src/rust/uci/mod.rs29
-rw-r--r--src/rust/uci/uci_hrcv.rs1
-rw-r--r--src/rust/uci_hal_android/uci_hal_android.rs47
-rw-r--r--src/rust/uwb_core/Cargo.toml3
-rw-r--r--src/rust/uwb_core/examples/main.rs8
-rw-r--r--src/rust/uwb_core/src/params/ccc_app_config_params.rs30
-rw-r--r--src/rust/uwb_core/src/params/fira_app_config_params.rs108
-rw-r--r--src/rust/uwb_core/src/service/uwb_service.rs20
-rw-r--r--src/rust/uwb_core/src/session/session_manager.rs63
-rw-r--r--src/rust/uwb_core/src/session/uwb_session.rs15
-rw-r--r--src/rust/uwb_core/src/uci.rs3
-rw-r--r--src/rust/uwb_core/src/uci/command.rs6
-rw-r--r--src/rust/uwb_core/src/uci/mock_uci_hal.rs50
-rw-r--r--src/rust/uwb_core/src/uci/timeout_uci_hal.rs19
-rw-r--r--src/rust/uwb_core/src/uci/uci_hal.rs66
-rw-r--r--src/rust/uwb_core/src/uci/uci_manager.rs447
-rw-r--r--src/rust/uwb_core/src/uci/uci_manager_sync.rs10
-rw-r--r--src/rust/uwb_core/src/utils.rs31
-rw-r--r--src/rust/uwb_uci_packets/Cargo.toml2
-rw-r--r--src/rust/uwb_uci_packets/uci_packets.pdl4
23 files changed, 657 insertions, 537 deletions
diff --git a/NOTICE b/NOTICE
index d645695..da14657 100755
--- a/NOTICE
+++ b/NOTICE
@@ -1,202 +1,16 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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.
+Notice of Rights Limitations – Important User Information
+AOSP may include one or more implementations of
+Specifications or draft Specifications developed by the FiRa Consortium. The
+FiRa Consortium is a non­profit organization formed for the purposes of defining
+one or more specifications, best practices, implementation guidelines and
+certification programs to promote the availability of compliant implementations
+of FiRa Specifications. Information on becoming a Member, including information
+about the benefits thereof, can be found at http://firaconsortium.org.
+
+AOSP is not affiliated with or endorsed by the FiRa
+Consortium. Implementation of this AOSP code does not
+assure compliance with any FiRa Specifications and does not convey the right to
+identify any final product as FiRa certified. Members of the FiRa Consortium or
+others may hold patents and other intellectual property rights relating to FiRa
+Specifications. The FiRa Intellectual Property Rights Policy can be found at
+https://www.firaconsortium.org/membership/documents.
diff --git a/src/Android.bp b/src/Android.bp
index 8bd2271..2cadd12 100755
--- a/src/Android.bp
+++ b/src/Android.bp
@@ -98,6 +98,7 @@ rust_defaults {
"rust/uwb_uci_packets/src/lib.rs",
":UwbGeneratedPackets_rust",
],
+ edition: "2021",
proc_macros: ["libnum_derive"],
rustlibs:[
"libbytes",
@@ -169,6 +170,7 @@ genrule {
rust_defaults {
name: "libuwb_core_defaults",
srcs: ["rust/uwb_core/src/lib.rs"],
+ edition: "2021",
lints: "android",
clippy_lints: "android",
rustlibs: [
@@ -181,6 +183,7 @@ rust_defaults {
],
proc_macros: [
"libasync_trait",
+ "libnum_derive",
],
min_sdk_version: "Tiramisu",
host_supported: true,
@@ -279,7 +282,7 @@ rust_library {
"libasync_trait",
],
apex_available: [
- "com.android.ucihal",
+ "com.android.uwb",
],
min_sdk_version: "Tiramisu",
host_supported: true,
diff --git a/src/TEST_MAPPING b/src/TEST_MAPPING
index ac3f1ce..510d37b 100644
--- a/src/TEST_MAPPING
+++ b/src/TEST_MAPPING
@@ -1,9 +1,10 @@
{
"presubmit": [
- {
- "name": "libuwb_core_cargo_test",
- "host": true
- },
+ // TODO(b/245028544): Disable the presubmit check temporarily.
+ // {
+ // "name": "libuwb_core_cargo_test",
+ // "host": true
+ // },
{
"name": "libuwb_uci_rust_tests"
},
diff --git a/src/rust/uci/mod.rs b/src/rust/uci/mod.rs
index 43a24b5..116d03e 100644
--- a/src/rust/uci/mod.rs
+++ b/src/rust/uci/mod.rs
@@ -48,6 +48,7 @@ pub type SyncUwbAdaptation = Arc<dyn UwbAdaptation + Send + Sync>;
#[derive(Arbitrary, Clone, Debug, PartialEq, Eq)]
pub enum JNICommand {
// Blocking UCI commands
+ Enable,
UciGetCapsInfo,
UciGetDeviceInfo,
UciSessionInit(u32, u8),
@@ -90,7 +91,6 @@ pub enum JNICommand {
UciGetPowerStats,
// Non blocking commands
- Enable,
Disable(bool),
}
@@ -250,6 +250,24 @@ impl<T: EventManager> Driver<T> {
) -> Result<()> {
log::debug!("Received blocking cmd {:?}", cmd);
let command: UciCommandPacket = match cmd {
+ JNICommand::Enable => {
+ match (
+ self.adaptation.hal_open(&chip_id).await,
+ self.adaptation.core_initialization(&chip_id).await,
+ ) {
+ (Ok(()), Ok(())) => {
+ tx.send(UciResponse::EnableRsp(true))
+ .unwrap_or_else(|e| error!("Error sending Enable response: {:?}", e));
+ self.set_state(UwbState::W4HalOpen);
+ }
+ (Err(e), _) | (_, Err(e)) => {
+ error!("Enable UWB failed with: {:?}", e);
+ tx.send(UciResponse::EnableRsp(false))
+ .unwrap_or_else(|e| error!("Error sending Enable response: {:?}", e));
+ }
+ }
+ return Ok(());
+ }
JNICommand::UciGetDeviceInfo => GetDeviceInfoCmdBuilder {}.build().into(),
JNICommand::UciGetCapsInfo => GetCapsInfoCmdBuilder {}.build().into(),
JNICommand::UciSessionInit(session_id, session_type) => {
@@ -325,11 +343,6 @@ impl<T: EventManager> Driver<T> {
) -> Result<()> {
log::debug!("Received non blocking cmd {:?}", cmd);
match cmd {
- JNICommand::Enable => {
- self.adaptation.hal_open(&chip_id).await?;
- self.adaptation.core_initialization(&chip_id).await?;
- self.set_state(UwbState::W4HalOpen);
- }
JNICommand::Disable(_graceful) => match self.adaptation.hal_close(&chip_id).await {
Ok(()) => self.set_state(UwbState::W4HalClose),
Err(e) => {
@@ -637,7 +650,7 @@ mod tests {
mock_adaptation.expect_core_initialization(Ok(()));
});
- dispatcher.send_jni_command(JNICommand::Enable, String::from("chip_id")).unwrap();
+ dispatcher.block_on_jni_command(JNICommand::Enable, String::from("chip_id")).unwrap();
}
#[test]
@@ -650,7 +663,7 @@ mod tests {
});
let chip_id = String::from("chip_id");
- dispatcher.send_jni_command(JNICommand::Enable, chip_id.clone()).unwrap();
+ dispatcher.block_on_jni_command(JNICommand::Enable, chip_id.clone()).unwrap();
hal_sender
.send((
HalCallback::Event { event: UwbEvent::ERROR, event_status: UwbStatus::FAILED },
diff --git a/src/rust/uci/uci_hrcv.rs b/src/rust/uci/uci_hrcv.rs
index ab5da94..c79b7c6 100644
--- a/src/rust/uci/uci_hrcv.rs
+++ b/src/rust/uci/uci_hrcv.rs
@@ -43,6 +43,7 @@ pub enum UciResponse {
AndroidSetCountryCodeRsp(AndroidSetCountryCodeRspPacket),
AndroidGetPowerStatsRsp(AndroidGetPowerStatsRspPacket),
RawVendorRsp(UciResponsePacket),
+ EnableRsp(bool),
DisableRsp,
}
diff --git a/src/rust/uci_hal_android/uci_hal_android.rs b/src/rust/uci_hal_android/uci_hal_android.rs
index 5e1edcf..a9b3048 100644
--- a/src/rust/uci_hal_android/uci_hal_android.rs
+++ b/src/rust/uci_hal_android/uci_hal_android.rs
@@ -34,22 +34,25 @@ use tokio::runtime::Handle;
use tokio::sync::{mpsc, Mutex};
use uwb_core::error::{Error as UwbCoreError, Result as UwbCoreResult};
use uwb_core::params::uci_packets::SessionId;
-use uwb_core::uci::uci_hal::{RawUciMessage, UciHal};
+use uwb_core::uci::uci_hal::{UciHal, UciHalPacket};
use uwb_uci_packets::{DeviceState, DeviceStatusNtfBuilder};
use crate::error::{Error, Result};
-fn into_raw_messages<T: Into<uwb_uci_packets::UciPacketPacket>>(builder: T) -> Vec<RawUciMessage> {
+fn input_uci_hal_packet<T: Into<uwb_uci_packets::UciPacketPacket>>(
+ builder: T,
+) -> Vec<UciHalPacket> {
let packets: Vec<uwb_uci_packets::UciPacketHalPacket> = builder.into().into();
packets.into_iter().map(|packet| packet.into()).collect()
}
/// Send device status notification with error state.
fn send_device_state_error_notification(
- uci_sender: &mpsc::UnboundedSender<RawUciMessage>,
+ uci_sender: &mpsc::UnboundedSender<UciHalPacket>,
) -> UwbCoreResult<()> {
- let raw_message_packets =
- into_raw_messages(DeviceStatusNtfBuilder { device_state: DeviceState::DeviceStateError });
+ let raw_message_packets = input_uci_hal_packet(DeviceStatusNtfBuilder {
+ device_state: DeviceState::DeviceStateError,
+ });
for raw_message_packet in raw_message_packets {
if let Err(e) = uci_sender.send(raw_message_packet) {
error!("Error sending device state error notification: {:?}", e);
@@ -66,14 +69,14 @@ fn send_device_state_error_notification(
/// trait is consumed by BnUwbClientCallback, thus it cannot be implemented for UciHalAndroid.
#[derive(Clone, Debug)]
struct RawUciCallback {
- uci_sender: mpsc::UnboundedSender<RawUciMessage>,
+ uci_sender: mpsc::UnboundedSender<UciHalPacket>,
hal_open_result_sender: mpsc::Sender<Result<()>>,
hal_close_result_sender: mpsc::Sender<Result<()>>,
}
impl RawUciCallback {
pub fn new(
- uci_sender: mpsc::UnboundedSender<RawUciMessage>,
+ uci_sender: mpsc::UnboundedSender<UciHalPacket>,
hal_open_result_sender: mpsc::Sender<Result<()>>,
hal_close_result_sender: mpsc::Sender<Result<()>>,
) -> Self {
@@ -153,7 +156,7 @@ impl UciHal for UciHalAndroid {
/// Open the UCI HAL and power on the UWBS.
async fn open(
&mut self,
- uci_rsp_ntf_sender: mpsc::UnboundedSender<RawUciMessage>,
+ packet_sender: mpsc::UnboundedSender<UciHalPacket>,
) -> UwbCoreResult<()> {
// Returns error if UciHalAndroid is already open.
if self.hal_uci_recipient.is_some() {
@@ -171,8 +174,8 @@ impl UciHal for UciHalAndroid {
return Err(UwbCoreError::BadParameters);
}
let chip_name: &str = match &self.chip_id == "default" {
- false => &chip_names[0],
- true => &self.chip_id,
+ true => &chip_names[0],
+ false => &self.chip_id,
};
if !chip_names.contains(&chip_name.to_string()) {
return Err(UwbCoreError::BadParameters);
@@ -185,9 +188,9 @@ impl UciHal for UciHalAndroid {
// If the binder object unexpectedly goes away (typically because its hosting process has
// been killed), then the `DeathRecipient`'s callback will be called.
- let uci_rsp_ntf_sender_clone = uci_rsp_ntf_sender.clone();
+ let packet_sender_clone = packet_sender.clone();
let mut bare_death_recipient = DeathRecipient::new(move || {
- send_device_state_error_notification(&uci_rsp_ntf_sender_clone).unwrap_or_else(|e| {
+ send_device_state_error_notification(&packet_sender_clone).unwrap_or_else(|e| {
error!("Error sending device state error notification: {:?}", e);
});
});
@@ -196,12 +199,12 @@ impl UciHal for UciHalAndroid {
.link_to_death(&mut bare_death_recipient)
.map_err(|e| UwbCoreError::from(Error::from(e)))?;
- // Connect callback to uci_rsp_ntf_sender.
+ // Connect callback to packet_sender.
let (hal_open_result_sender, mut hal_open_result_receiver) = mpsc::channel::<Result<()>>(1);
let (hal_close_result_sender, hal_close_result_receiver) = mpsc::channel::<Result<()>>(1);
let m_cback = BnUwbClientCallback::new_async_binder(
RawUciCallback::new(
- uci_rsp_ntf_sender,
+ packet_sender.clone(),
hal_open_result_sender,
hal_close_result_sender,
),
@@ -209,11 +212,21 @@ impl UciHal for UciHalAndroid {
BinderFeatures::default(),
);
i_uwb_chip.open(&m_cback).await.map_err(|e| UwbCoreError::from(Error::from(e)))?;
-
// Initialize core and wait for POST_INIT_CPLT.
i_uwb_chip.coreInit().await.map_err(|e| UwbCoreError::from(Error::from(e)))?;
match hal_open_result_receiver.recv().await {
Some(Ok(())) => {
+ // Workaround while http://b/243140882 is not fixed:
+ // Send DEVICE_STATE_READY notification as chip is not sending this notification.
+ let device_ready_ntfs = input_uci_hal_packet(
+ DeviceStatusNtfBuilder { device_state: DeviceState::DeviceStateReady }.build(),
+ );
+ for device_ready_ntf in device_ready_ntfs {
+ packet_sender.send(device_ready_ntf).unwrap_or_else(|e| {
+ error!("UCI HAL: failed to send device ready notification: {:?}", e);
+ });
+ }
+ // End of workaround.
self.hal_uci_recipient.replace(i_uwb_chip);
self.hal_death_recipient.replace(Arc::new(Mutex::new(bare_death_recipient)));
self.hal_close_result_receiver.replace(hal_close_result_receiver);
@@ -246,11 +259,11 @@ impl UciHal for UciHalAndroid {
}
}
- async fn send_command(&mut self, cmd: RawUciMessage) -> UwbCoreResult<()> {
+ async fn send_packet(&mut self, packet: UciHalPacket) -> UwbCoreResult<()> {
match &self.hal_uci_recipient {
Some(i_uwb_chip) => {
i_uwb_chip
- .sendUciMessage(&cmd)
+ .sendUciMessage(&packet)
.await
.map_err(|e| UwbCoreError::from(Error::from(e)))?;
Ok(())
diff --git a/src/rust/uwb_core/Cargo.toml b/src/rust/uwb_core/Cargo.toml
index c9294f1..71325f2 100644
--- a/src/rust/uwb_core/Cargo.toml
+++ b/src/rust/uwb_core/Cargo.toml
@@ -1,13 +1,14 @@
[package]
name = "uwb_core"
version = "0.0.1"
-edition = "2018"
+edition = "2021"
[dependencies]
async-trait = "0.1.32"
bytes = "1.1.0"
log = "0.4.14"
num-traits = "0.2.12"
+num-derive = "0.3.3"
thiserror = "1.0.30"
tokio = { version = "1.14.0", features = ["macros", "rt", "rt-multi-thread", "sync", "time"] }
diff --git a/src/rust/uwb_core/examples/main.rs b/src/rust/uwb_core/examples/main.rs
index 4962820..86a8893 100644
--- a/src/rust/uwb_core/examples/main.rs
+++ b/src/rust/uwb_core/examples/main.rs
@@ -21,13 +21,13 @@ use tokio::sync::mpsc;
use uwb_core::error::{Error as UwbError, Result as UwbResult};
use uwb_core::params::uci_packets::{DeviceState, ReasonCode, SessionId, SessionState};
use uwb_core::service::{UwbServiceBuilder, UwbServiceCallback};
-use uwb_core::uci::{RawUciMessage, SessionRangeData, UciHal};
+use uwb_core::uci::{SessionRangeData, UciHal, UciHalPacket};
/// A placeholder implementation for UciHal.
struct UciHalImpl {}
#[async_trait]
impl UciHal for UciHalImpl {
- async fn open(&mut self, _msg_sender: mpsc::UnboundedSender<RawUciMessage>) -> UwbResult<()> {
+ async fn open(&mut self, _packet_sender: mpsc::UnboundedSender<UciHalPacket>) -> UwbResult<()> {
debug!("UciHalImpl::open() is called");
Ok(())
}
@@ -35,8 +35,8 @@ impl UciHal for UciHalImpl {
debug!("UciHalImpl::close() is called");
Ok(())
}
- async fn send_command(&mut self, cmd: RawUciMessage) -> UwbResult<()> {
- debug!("UciHalImpl::send_command({:?}) is called", cmd);
+ async fn send_packet(&mut self, packet: UciHalPacket) -> UwbResult<()> {
+ debug!("UciHalImpl::send_packet({:?}) is called", packet);
Ok(())
}
}
diff --git a/src/rust/uwb_core/src/params/ccc_app_config_params.rs b/src/rust/uwb_core/src/params/ccc_app_config_params.rs
index d6bcfe2..ab90d3a 100644
--- a/src/rust/uwb_core/src/params/ccc_app_config_params.rs
+++ b/src/rust/uwb_core/src/params/ccc_app_config_params.rs
@@ -24,7 +24,8 @@ use crate::params::fira_app_config_params::{
};
use crate::params::uci_packets::{AppConfigTlvType, SessionState};
use crate::params::utils::{u16_to_bytes, u32_to_bytes, u8_to_bytes, validate};
-use crate::utils::builder_field;
+use crate::utils::{builder_field, getter_field};
+use num_derive::{FromPrimitive, ToPrimitive};
const CHAP_IN_RSTU: u16 = 400; // 1 Chap = 400 RSTU.
pub(super) const MINIMUM_BLOCK_DURATION_MS: u32 = 96;
@@ -54,7 +55,20 @@ pub struct CccAppConfigParams {
hopping_mode: CccHoppingMode,
}
+#[allow(missing_docs)]
impl CccAppConfigParams {
+ // Generate the getter methods for all the fields.
+ getter_field!(protocol_version, CccProtocolVersion);
+ getter_field!(uwb_config, CccUwbConfig);
+ getter_field!(pulse_shape_combo, CccPulseShapeCombo);
+ getter_field!(ran_multiplier, u32);
+ getter_field!(channel_number, CccUwbChannel);
+ getter_field!(chaps_per_slot, ChapsPerSlot);
+ getter_field!(num_responder_nodes, u8);
+ getter_field!(slots_per_rr, u8);
+ getter_field!(sync_code_index, u8);
+ getter_field!(hopping_mode, CccHoppingMode);
+
pub fn is_config_updatable(config_map: &AppConfigTlvMap, session_state: SessionState) -> bool {
match session_state {
SessionState::SessionStateIdle => {
@@ -201,7 +215,7 @@ impl From<CccProtocolVersion> for Vec<u8> {
}
#[repr(u16)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum CccUwbConfig {
Config0 = 0,
Config1 = 1,
@@ -220,7 +234,7 @@ impl From<CccPulseShapeCombo> for Vec<u8> {
}
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum PulseShape {
SymmetricalRootRaisedCosine = 0x0,
PrecursorFree = 0x1,
@@ -228,14 +242,14 @@ pub enum PulseShape {
}
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum CccUwbChannel {
Channel5 = 5,
Channel9 = 9,
}
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum HoppingConfigMode {
None = 0,
Continuous = 1,
@@ -243,14 +257,14 @@ pub enum HoppingConfigMode {
}
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum HoppingSequence {
Default = 0,
Aes = 1,
}
#[repr(u16)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum ChapsPerSlot {
Value3 = 3,
Value4 = 4,
@@ -262,7 +276,7 @@ pub enum ChapsPerSlot {
}
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum CccHoppingMode {
Disable = 0,
AdaptiveDefault = 2,
diff --git a/src/rust/uwb_core/src/params/fira_app_config_params.rs b/src/rust/uwb_core/src/params/fira_app_config_params.rs
index c6b459e..4c0cf51 100644
--- a/src/rust/uwb_core/src/params/fira_app_config_params.rs
+++ b/src/rust/uwb_core/src/params/fira_app_config_params.rs
@@ -15,13 +15,16 @@
//! This module defines the UCI application config parameters for the FiRa ranging session.
use std::collections::{HashMap, HashSet};
+use std::convert::{TryFrom, TryInto};
use log::warn;
+use num_derive::{FromPrimitive, ToPrimitive};
+
use crate::params::app_config_params::{AppConfigParams, AppConfigTlvMap};
use crate::params::uci_packets::{AppConfigTlvType, SessionState, SubSessionId};
use crate::params::utils::{u16_to_bytes, u32_to_bytes, u8_to_bytes, validate};
-use crate::utils::builder_field;
+use crate::utils::{builder_field, getter_field};
// The default value of each parameters.
const DEFAULT_RANGING_ROUND_USAGE: RangingRoundUsage = RangingRoundUsage::DsTwr;
@@ -126,7 +129,57 @@ pub struct FiraAppConfigParams {
number_of_aoa_elevation_measurements: u8,
}
+#[allow(missing_docs)]
impl FiraAppConfigParams {
+ // Generate the getter methods for all the fields.
+ getter_field!(device_type, DeviceType);
+ getter_field!(ranging_round_usage, RangingRoundUsage);
+ getter_field!(sts_config, StsConfig);
+ getter_field!(multi_node_mode, MultiNodeMode);
+ getter_field!(channel_number, UwbChannel);
+ getter_field!(device_mac_address, UwbAddress);
+ getter_field!(dst_mac_address, Vec<UwbAddress>);
+ getter_field!(slot_duration_rstu, u16);
+ getter_field!(ranging_interval_ms, u32);
+ getter_field!(mac_fcs_type, MacFcsType);
+ getter_field!(ranging_round_control, RangingRoundControl);
+ getter_field!(aoa_result_request, AoaResultRequest);
+ getter_field!(range_data_ntf_config, RangeDataNtfConfig);
+ getter_field!(range_data_ntf_proximity_near_cm, u16);
+ getter_field!(range_data_ntf_proximity_far_cm, u16);
+ getter_field!(device_role, DeviceRole);
+ getter_field!(rframe_config, RframeConfig);
+ getter_field!(preamble_code_index, u8);
+ getter_field!(sfd_id, u8);
+ getter_field!(psdu_data_rate, PsduDataRate);
+ getter_field!(preamble_duration, PreambleDuration);
+ getter_field!(ranging_time_struct, RangingTimeStruct);
+ getter_field!(slots_per_rr, u8);
+ getter_field!(tx_adaptive_payload_power, TxAdaptivePayloadPower);
+ getter_field!(responder_slot_index, u8);
+ getter_field!(prf_mode, PrfMode);
+ getter_field!(scheduled_mode, ScheduledMode);
+ getter_field!(key_rotation, KeyRotation);
+ getter_field!(key_rotation_rate, u8);
+ getter_field!(session_priority, u8);
+ getter_field!(mac_address_mode, MacAddressMode);
+ getter_field!(vendor_id, [u8; 2]);
+ getter_field!(static_sts_iv, [u8; 6]);
+ getter_field!(number_of_sts_segments, u8);
+ getter_field!(max_rr_retry, u16);
+ getter_field!(uwb_initiation_time_ms, u32);
+ getter_field!(hopping_mode, HoppingMode);
+ getter_field!(block_stride_length, u8);
+ getter_field!(result_report_config, ResultReportConfig);
+ getter_field!(in_band_termination_attempt_count, u8);
+ getter_field!(sub_session_id, u32);
+ getter_field!(bprf_phr_data_rate, BprfPhrDataRate);
+ getter_field!(max_number_of_measurements, u16);
+ getter_field!(sts_length, StsLength);
+ getter_field!(number_of_range_measurements, u8);
+ getter_field!(number_of_aoa_azimuth_measurements, u8);
+ getter_field!(number_of_aoa_elevation_measurements, u8);
+
/// validate if the params are valid.
fn is_valid(&self) -> Option<()> {
if self.device_type == DeviceType::Controlee {
@@ -641,7 +694,7 @@ impl FiraAppConfigParamsBuilder {
/// The device type.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum DeviceType {
/// Controlee
Controlee = 0,
@@ -651,7 +704,7 @@ pub enum DeviceType {
/// The mode of ranging round usage.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum RangingRoundUsage {
/// SS-TWR with Deferred Mode
SsTwr = 1,
@@ -665,7 +718,7 @@ pub enum RangingRoundUsage {
/// This parameter indicates how the system shall generate the STS.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum StsConfig {
/// Static STS (default)
Static = 0,
@@ -677,7 +730,7 @@ pub enum StsConfig {
/// The mode of multi node.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum MultiNodeMode {
/// Single device to Single device (Unicast)
Unicast = 0,
@@ -690,7 +743,7 @@ pub enum MultiNodeMode {
/// The UWB channel number. (default = 9)
#[allow(missing_docs)]
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum UwbChannel {
Channel5 = 5,
Channel6 = 6,
@@ -720,13 +773,24 @@ impl From<UwbAddress> for Vec<u8> {
}
}
+impl TryFrom<Vec<u8>> for UwbAddress {
+ type Error = &'static str;
+ fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
+ match value.len() {
+ 2 => Ok(UwbAddress::Short(value.try_into().unwrap())),
+ 8 => Ok(UwbAddress::Extended(value.try_into().unwrap())),
+ _ => Err("Invalid address length"),
+ }
+ }
+}
+
fn addresses_to_bytes(addresses: Vec<UwbAddress>) -> Vec<u8> {
addresses.into_iter().flat_map(Into::<Vec<u8>>::into).collect()
}
/// CRC type in MAC footer.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum MacFcsType {
/// CRC 16 (default)
Crc16 = 0,
@@ -785,7 +849,7 @@ impl RangingRoundControl {
/// This parameter is used to configure AOA results in the range data notification.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum AoaResultRequest {
/// Disable AOA
NoAoaReport = 0,
@@ -801,7 +865,7 @@ pub enum AoaResultRequest {
/// This config is used to enable/disable the range data notification.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum RangeDataNtfConfig {
/// Disable range data notification
Disable = 0,
@@ -813,7 +877,7 @@ pub enum RangeDataNtfConfig {
/// The device role.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum DeviceRole {
/// Responder of the session
Responder = 0,
@@ -823,7 +887,7 @@ pub enum DeviceRole {
/// Rframe config.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum RframeConfig {
/// SP0
SP0 = 0,
@@ -835,7 +899,7 @@ pub enum RframeConfig {
/// This value configures the data rate.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum PsduDataRate {
/// 6.81 Mbps (default)
Rate6m81 = 0,
@@ -853,7 +917,7 @@ pub enum PsduDataRate {
///
/// Two configurations are possible. BPRF uses only 64 symbols. HPRF can use both.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum PreambleDuration {
/// 32 symbols
T32Symbols = 0,
@@ -863,7 +927,7 @@ pub enum PreambleDuration {
/// The type of ranging time scheduling.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum RangingTimeStruct {
/// Interval Based Scheduling
IntervalBasedScheduling = 0,
@@ -873,7 +937,7 @@ pub enum RangingTimeStruct {
/// This configuration is used to enable/disable adaptive payload power for TX.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum TxAdaptivePayloadPower {
/// Disable (default)
Disable = 0,
@@ -883,7 +947,7 @@ pub enum TxAdaptivePayloadPower {
/// This parameter is used to configure the mean PRF.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum PrfMode {
/// 62.4 MHz PRF. BPRF mode (default)
Bprf = 0,
@@ -895,7 +959,7 @@ pub enum PrfMode {
/// This parameter is used to set the Multinode Ranging Type.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum ScheduledMode {
/// Time scheduled ranging (default)
TimeScheduledRanging = 1,
@@ -904,7 +968,7 @@ pub enum ScheduledMode {
/// This configuration is used to enable/disable the key rotation feature during Dynamic STS
/// ranging.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum KeyRotation {
/// Disable (default)
Disable = 0,
@@ -914,7 +978,7 @@ pub enum KeyRotation {
/// MAC Addressing mode to be used in UWBS.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum MacAddressMode {
/// MAC address is 2 bytes and 2 bytes to be used in MAC header (default)
MacAddress2Bytes = 0,
@@ -928,7 +992,7 @@ pub enum MacAddressMode {
///
/// Note: This config is applicable only for controller and ignored in case of controlee.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum HoppingMode {
/// Hopping Diable (default)
Disable = 0,
@@ -979,7 +1043,7 @@ impl ResultReportConfig {
/// The data rate for BPRF mode.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum BprfPhrDataRate {
/// 850 kbps (default)
Rate850k = 0,
@@ -989,7 +1053,7 @@ pub enum BprfPhrDataRate {
/// The number of symbols in an STS segment.
#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum StsLength {
/// 32 symbols
Length32 = 0,
diff --git a/src/rust/uwb_core/src/service/uwb_service.rs b/src/rust/uwb_core/src/service/uwb_service.rs
index 81cd52b..26bb73f 100644
--- a/src/rust/uwb_core/src/service/uwb_service.rs
+++ b/src/rust/uwb_core/src/service/uwb_service.rs
@@ -166,6 +166,14 @@ impl UwbService {
}
}
+ /// Get app config params for the given session id
+ pub fn session_params(&mut self, session_id: SessionId) -> Result<AppConfigParams> {
+ match self.block_on_cmd(Command::GetParams { session_id })? {
+ Response::AppConfigParams(params) => Ok(params),
+ _ => panic!("session_params() should return AppConfigParams"),
+ }
+ }
+
/// Send the |cmd| to UwbServiceActor and wait until receiving the response.
fn block_on_cmd(&self, cmd: Command) -> Result<Response> {
let (result_sender, result_receiver) = oneshot::channel();
@@ -331,6 +339,15 @@ impl<C: UwbServiceCallback, U: UciManager> UwbServiceActor<C, U> {
let msg = self.uci_manager.raw_vendor_cmd(gid, oid, payload).await?;
Ok(Response::RawVendorMessage(msg))
}
+ Command::GetParams { session_id } => {
+ if let Some(session_manager) = self.session_manager.as_mut() {
+ let params = session_manager.session_params(session_id).await?;
+ Ok(Response::AppConfigParams(params))
+ } else {
+ error!("The service is not enabled yet");
+ Err(Error::BadParameters)
+ }
+ }
}
}
@@ -445,6 +462,9 @@ enum Command {
oid: u32,
payload: Vec<u8>,
},
+ GetParams {
+ session_id: SessionId,
+ },
}
#[derive(Debug)]
diff --git a/src/rust/uwb_core/src/session/session_manager.rs b/src/rust/uwb_core/src/session/session_manager.rs
index f2280ad..396c215 100644
--- a/src/rust/uwb_core/src/session/session_manager.rs
+++ b/src/rust/uwb_core/src/session/session_manager.rs
@@ -118,6 +118,13 @@ impl SessionManager {
Ok(())
}
+ pub async fn session_params(&mut self, session_id: SessionId) -> Result<AppConfigParams> {
+ match self.send_cmd(SessionCommand::GetParams { session_id }).await? {
+ SessionResponse::AppConfigParams(params) => Ok(params),
+ _ => panic!("session_params() should reply AppConfigParams result"),
+ }
+ }
+
// Send the |cmd| to the SessionManagerActor.
async fn send_cmd(&self, cmd: SessionCommand) -> Result<SessionResponse> {
let (result_sender, result_receiver) = oneshot::channel();
@@ -270,6 +277,17 @@ impl<T: UciManager> SessionManagerActor<T> {
}
}
}
+ SessionCommand::GetParams { session_id } => {
+ match self.active_sessions.get_mut(&session_id) {
+ None => {
+ warn!("Session {} doesn't exist", session_id);
+ let _ = result_sender.send(Err(Error::BadParameters));
+ }
+ Some(session) => {
+ session.params(result_sender);
+ }
+ }
+ }
}
}
@@ -356,6 +374,9 @@ enum SessionCommand {
action: UpdateMulticastListAction,
controlees: Vec<Controlee>,
},
+ GetParams {
+ session_id: SessionId,
+ },
}
#[cfg(test)]
@@ -987,4 +1008,46 @@ mod tests {
assert!(mock_uci_manager.wait_expected_calls_done().await);
}
+
+ #[tokio::test]
+ async fn test_session_params() {
+ let session_id = 0x123;
+ let session_type = SessionType::FiraRangingSession;
+
+ let params = generate_params();
+ let tlvs = params.generate_tlvs();
+
+ 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,
+ tlvs,
+ vec![session_status_notf(session_id, SessionState::SessionStateIdle)],
+ Ok(SetAppConfigResponse {
+ status: StatusCode::UciStatusOk,
+ config_status: vec![],
+ }),
+ );
+ })
+ .await;
+
+ // Getting session params without initing a session should fail
+ let result = session_manager.session_params(session_id).await;
+ assert_eq!(result, Err(Error::BadParameters));
+
+ let result = session_manager.init_session(session_id, session_type, params.clone()).await;
+ result.unwrap();
+
+ // Getting session params after they've been properly set should succeed
+ let result = session_manager.session_params(session_id).await;
+ assert_eq!(result, Ok(params));
+
+ assert!(mock_uci_manager.wait_expected_calls_done().await);
+ }
}
diff --git a/src/rust/uwb_core/src/session/uwb_session.rs b/src/rust/uwb_core/src/session/uwb_session.rs
index a536b65..bb0a42c 100644
--- a/src/rust/uwb_core/src/session/uwb_session.rs
+++ b/src/rust/uwb_core/src/session/uwb_session.rs
@@ -102,6 +102,10 @@ impl UwbSession {
));
}
+ pub fn params(&mut self, result_sender: ResponseSender) {
+ let _ = self.cmd_sender.send((Command::GetParams, result_sender));
+ }
+
pub fn on_session_status_changed(&mut self, state: SessionState) {
let _ = self.state_sender.send(state);
}
@@ -160,7 +164,8 @@ impl<T: UciManager> UwbSessionActor<T> {
notf_receiver,
)
.await
- }
+ },
+ Command::GetParams => self.params().await,
};
let _ = result_sender.send(result);
}
@@ -352,6 +357,13 @@ impl<T: UciManager> UwbSessionActor<T> {
Ok(())
}
+
+ async fn params(&mut self) -> Result<Response> {
+ match &self.params {
+ None => Err(Error::BadParameters),
+ Some(params) => Ok(Response::AppConfigParams(params.clone())),
+ }
+ }
}
enum Command {
@@ -369,4 +381,5 @@ enum Command {
controlees: Vec<Controlee>,
notf_receiver: oneshot::Receiver<Vec<ControleeStatus>>,
},
+ GetParams,
}
diff --git a/src/rust/uwb_core/src/uci.rs b/src/rust/uwb_core/src/uci.rs
index 326fb15..5d21432 100644
--- a/src/rust/uwb_core/src/uci.rs
+++ b/src/rust/uwb_core/src/uci.rs
@@ -32,7 +32,8 @@ pub(crate) mod mock_uci_hal;
pub(crate) mod mock_uci_manager;
// Re-export the public elements.
+pub use command::UciCommand;
pub use notification::{
CoreNotification, RangingMeasurements, SessionNotification, SessionRangeData, UciNotification,
};
-pub use uci_hal::{RawUciMessage, UciHal};
+pub use uci_hal::{UciHal, UciHalPacket};
diff --git a/src/rust/uwb_core/src/uci/command.rs b/src/rust/uwb_core/src/uci/command.rs
index f395555..61ccc83 100644
--- a/src/rust/uwb_core/src/uci/command.rs
+++ b/src/rust/uwb_core/src/uci/command.rs
@@ -24,8 +24,10 @@ use crate::params::uci_packets::{
ResetConfig, SessionId, SessionType, UpdateMulticastListAction,
};
-#[derive(Debug, Clone)]
-pub(super) enum UciCommand {
+/// The enum to represent the UCI commands. The definition of each field should follow UCI spec.
+#[allow(missing_docs)]
+#[derive(Debug, Clone, PartialEq)]
+pub enum UciCommand {
DeviceReset {
reset_config: ResetConfig,
},
diff --git a/src/rust/uwb_core/src/uci/mock_uci_hal.rs b/src/rust/uwb_core/src/uci/mock_uci_hal.rs
index e7fe037..eb27e00 100644
--- a/src/rust/uwb_core/src/uci/mock_uci_hal.rs
+++ b/src/rust/uwb_core/src/uci/mock_uci_hal.rs
@@ -22,12 +22,13 @@ use tokio::time::timeout;
use crate::error::{Error, Result};
use crate::params::uci_packets::SessionId;
-use crate::uci::uci_hal::{RawUciMessage, UciHal};
+use crate::uci::command::UciCommand;
+use crate::uci::uci_hal::{UciHal, UciHalPacket};
/// The mock implementation of UciHal.
#[derive(Default, Clone)]
pub struct MockUciHal {
- msg_sender: Option<mpsc::UnboundedSender<RawUciMessage>>,
+ packet_sender: Option<mpsc::UnboundedSender<UciHalPacket>>,
expected_calls: Arc<Mutex<VecDeque<ExpectedCall>>>,
expect_call_consumed: Arc<Notify>,
}
@@ -37,8 +38,8 @@ impl MockUciHal {
Default::default()
}
- pub fn expected_open(&mut self, msgs: Option<Vec<RawUciMessage>>, out: Result<()>) {
- self.expected_calls.lock().unwrap().push_back(ExpectedCall::Open { msgs, out });
+ pub fn expected_open(&mut self, packets: Option<Vec<UciHalPacket>>, out: Result<()>) {
+ self.expected_calls.lock().unwrap().push_back(ExpectedCall::Open { packets, out });
}
pub fn expected_close(&mut self, out: Result<()>) {
@@ -47,13 +48,13 @@ impl MockUciHal {
pub fn expected_send_command(
&mut self,
- expected_cmd: RawUciMessage,
- msgs: Vec<RawUciMessage>,
+ expected_cmd: UciCommand,
+ packets: Vec<UciHalPacket>,
out: Result<()>,
) {
self.expected_calls.lock().unwrap().push_back(ExpectedCall::SendCommand {
expected_cmd,
- msgs,
+ packets,
out,
});
}
@@ -82,18 +83,18 @@ impl MockUciHal {
#[async_trait]
impl UciHal for MockUciHal {
- async fn open(&mut self, msg_sender: mpsc::UnboundedSender<RawUciMessage>) -> Result<()> {
+ async fn open(&mut self, packet_sender: mpsc::UnboundedSender<UciHalPacket>) -> Result<()> {
let mut expected_calls = self.expected_calls.lock().unwrap();
match expected_calls.pop_front() {
- Some(ExpectedCall::Open { msgs, out }) => {
+ Some(ExpectedCall::Open { packets, out }) => {
self.expect_call_consumed.notify_one();
- if let Some(msgs) = msgs {
- for msg in msgs.into_iter() {
- let _ = msg_sender.send(msg);
+ if let Some(packets) = packets {
+ for msg in packets.into_iter() {
+ let _ = packet_sender.send(msg);
}
}
if out.is_ok() {
- self.msg_sender.replace(msg_sender);
+ self.packet_sender.replace(packet_sender);
}
out
}
@@ -111,7 +112,7 @@ impl UciHal for MockUciHal {
Some(ExpectedCall::Close { out }) => {
self.expect_call_consumed.notify_one();
if out.is_ok() {
- self.msg_sender = None;
+ self.packet_sender = None;
}
out
}
@@ -123,14 +124,16 @@ impl UciHal for MockUciHal {
}
}
- async fn send_command(&mut self, cmd: RawUciMessage) -> Result<()> {
+ async fn send_command(&mut self, cmd: UciCommand) -> Result<()> {
let mut expected_calls = self.expected_calls.lock().unwrap();
match expected_calls.pop_front() {
- Some(ExpectedCall::SendCommand { expected_cmd, msgs, out }) if expected_cmd == cmd => {
+ Some(ExpectedCall::SendCommand { expected_cmd, packets, out })
+ if expected_cmd == cmd =>
+ {
self.expect_call_consumed.notify_one();
- let msg_sender = self.msg_sender.as_mut().unwrap();
- for msg in msgs.into_iter() {
- let _ = msg_sender.send(msg);
+ let packet_sender = self.packet_sender.as_mut().unwrap();
+ for msg in packets.into_iter() {
+ let _ = packet_sender.send(msg);
}
out
}
@@ -142,6 +145,11 @@ impl UciHal for MockUciHal {
}
}
+ async fn send_packet(&mut self, _packet: UciHalPacket) -> Result<()> {
+ // We mock the send_command(), so send_packet() would not be called.
+ Err(Error::MockUndefined)
+ }
+
async fn notify_session_initialized(&mut self, session_id: SessionId) -> Result<()> {
let mut expected_calls = self.expected_calls.lock().unwrap();
match expected_calls.pop_front() {
@@ -161,8 +169,8 @@ impl UciHal for MockUciHal {
}
enum ExpectedCall {
- Open { msgs: Option<Vec<RawUciMessage>>, out: Result<()> },
+ Open { packets: Option<Vec<UciHalPacket>>, out: Result<()> },
Close { out: Result<()> },
- SendCommand { expected_cmd: RawUciMessage, msgs: Vec<RawUciMessage>, out: Result<()> },
+ SendCommand { expected_cmd: UciCommand, packets: Vec<UciHalPacket>, out: Result<()> },
NotifySessionInitialized { expected_session_id: SessionId, out: Result<()> },
}
diff --git a/src/rust/uwb_core/src/uci/timeout_uci_hal.rs b/src/rust/uwb_core/src/uci/timeout_uci_hal.rs
index e1bdcb4..9a660ff 100644
--- a/src/rust/uwb_core/src/uci/timeout_uci_hal.rs
+++ b/src/rust/uwb_core/src/uci/timeout_uci_hal.rs
@@ -21,7 +21,8 @@ use tokio::time::timeout;
use crate::error::{Error, Result};
use crate::params::uci_packets::SessionId;
-use crate::uci::uci_hal::{RawUciMessage, UciHal};
+use crate::uci::command::UciCommand;
+use crate::uci::uci_hal::{UciHal, UciHalPacket};
const HAL_API_TIMEOUT_MS: u64 = 800;
@@ -42,8 +43,8 @@ impl<T: UciHal> TimeoutUciHal<T> {
#[async_trait]
impl<T: UciHal> UciHal for TimeoutUciHal<T> {
- async fn open(&mut self, msg_sender: mpsc::UnboundedSender<RawUciMessage>) -> Result<()> {
- Self::call_with_timeout(self.0.open(msg_sender)).await
+ async fn open(&mut self, packet_sender: mpsc::UnboundedSender<UciHalPacket>) -> Result<()> {
+ Self::call_with_timeout(self.0.open(packet_sender)).await
}
async fn close(&mut self) -> Result<()> {
@@ -54,9 +55,13 @@ impl<T: UciHal> UciHal for TimeoutUciHal<T> {
Self::call_with_timeout(self.0.notify_session_initialized(session_id)).await
}
- async fn send_command(&mut self, cmd: RawUciMessage) -> Result<()> {
+ async fn send_command(&mut self, cmd: UciCommand) -> Result<()> {
Self::call_with_timeout(self.0.send_command(cmd)).await
}
+
+ async fn send_packet(&mut self, packet: UciHalPacket) -> Result<()> {
+ Self::call_with_timeout(self.0.send_packet(packet)).await
+ }
}
#[cfg(test)]
@@ -73,13 +78,13 @@ mod tests {
#[async_trait]
impl UciHal for FakeUciHal {
- async fn open(&mut self, _: mpsc::UnboundedSender<RawUciMessage>) -> Result<()> {
+ async fn open(&mut self, _: mpsc::UnboundedSender<UciHalPacket>) -> Result<()> {
Ok(())
}
async fn close(&mut self) -> Result<()> {
Err(Error::Unknown)
}
- async fn send_command(&mut self, _: RawUciMessage) -> Result<()> {
+ async fn send_packet(&mut self, _: UciHalPacket) -> Result<()> {
sleep(Duration::MAX).await;
Ok(())
}
@@ -110,6 +115,6 @@ mod tests {
let mut hal = setup_hal();
let cmd = vec![];
- assert!(matches!(hal.send_command(cmd).await, Err(Error::Timeout)));
+ assert!(matches!(hal.send_packet(cmd).await, Err(Error::Timeout)));
}
}
diff --git a/src/rust/uwb_core/src/uci/uci_hal.rs b/src/rust/uwb_core/src/uci/uci_hal.rs
index c48416a..aaf6d22 100644
--- a/src/rust/uwb_core/src/uci/uci_hal.rs
+++ b/src/rust/uwb_core/src/uci/uci_hal.rs
@@ -14,14 +14,19 @@
//! This module defines the UciHal trait, used for the UCI hardware abstration layer.
+use std::convert::TryInto;
+
use async_trait::async_trait;
use tokio::sync::mpsc;
+use uwb_uci_packets::{Packet, UciCommandPacket, UciPacketHalPacket, UciPacketPacket};
use crate::error::Result;
use crate::params::uci_packets::SessionId;
+use crate::uci::command::UciCommand;
-/// The type of the message that is used to communicate with the UciHal trait.
-pub type RawUciMessage = Vec<u8>;
+/// The byte buffer of a UCI packet that is used to communicate with the UciHal trait.
+/// The format of the byte buffer should follow the UCI packet spec.
+pub type UciHalPacket = Vec<u8>;
/// The trait for the UCI hardware abstration layer. The client of this library should implement
/// this trait and inject into the library.
@@ -31,23 +36,70 @@ pub trait UciHal: 'static + Send {
/// Open the UCI HAL and power on the UWB Subsystem.
///
/// All the other API should be called after the open() completes successfully. Once the method
- /// completes successfully, the UciHal instance should store |msg_sender| and send the UCI
- /// messages (responses or notifications) back to the caller via the |msg_sender|.
- async fn open(&mut self, msg_sender: mpsc::UnboundedSender<RawUciMessage>) -> Result<()>;
+ /// completes successfully, the UciHal instance should store |packet_sender| and send the UCI
+ /// packets (responses or notifications) back to the caller via the |packet_sender|.
+ async fn open(&mut self, packet_sender: mpsc::UnboundedSender<UciHalPacket>) -> Result<()>;
/// Close the UCI HAL.
///
- /// After calling this method, the instance would drop |msg_sender| received from open() method.
+ /// After calling this method, the instance would drop |packet_sender| received from open()
+ /// method.
async fn close(&mut self) -> Result<()>;
/// Write the UCI command to the UWB Subsystem.
///
/// The caller should call this method after the response of the previous send_command() is
/// received.
- async fn send_command(&mut self, cmd: RawUciMessage) -> Result<()>;
+ async fn send_command(&mut self, cmd: UciCommand) -> Result<()> {
+ // A UCI command message may consist of multiple UCI packets when the payload is over the
+ // maximum packet size. We convert the command into list of UciHalPacket, then send the
+ // packets via send_packet().
+ let packet: UciCommandPacket = cmd.try_into()?;
+ let packet: UciPacketPacket = packet.into();
+ let fragmented_packets: Vec<UciPacketHalPacket> = packet.into();
+ for packet in fragmented_packets.into_iter() {
+ self.send_packet(packet.to_vec()).await?;
+ }
+ Ok(())
+ }
+
+ /// Write the UCI packet to the UWB Subsystem.
+ async fn send_packet(&mut self, packet: UciHalPacket) -> Result<()>;
/// Notify the HAL that the UWB session is initialized successfully.
async fn notify_session_initialized(&mut self, _session_id: SessionId) -> Result<()> {
Ok(())
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ struct MockUciHal {
+ pub packets: Vec<UciHalPacket>,
+ }
+
+ #[async_trait]
+ impl UciHal for MockUciHal {
+ async fn open(&mut self, _: mpsc::UnboundedSender<UciHalPacket>) -> Result<()> {
+ Ok(())
+ }
+ async fn close(&mut self) -> Result<()> {
+ Ok(())
+ }
+ async fn send_packet(&mut self, packet: UciHalPacket) -> Result<()> {
+ self.packets.push(packet);
+ Ok(())
+ }
+ }
+
+ // Verify if UciHal::send_command() split the packets correctly.
+ #[tokio::test]
+ async fn test_send_command() {
+ let mut hal = MockUciHal { packets: vec![] };
+ let _ = hal.send_command(UciCommand::CoreGetDeviceInfo).await;
+ let expected_packets = vec![vec![0x20, 0x02, 0x00, 0x00]];
+ assert_eq!(hal.packets, expected_packets);
+ }
+}
diff --git a/src/rust/uwb_core/src/uci/uci_manager.rs b/src/rust/uwb_core/src/uci/uci_manager.rs
index b86f862..e9504c8 100644
--- a/src/rust/uwb_core/src/uci/uci_manager.rs
+++ b/src/rust/uwb_core/src/uci/uci_manager.rs
@@ -18,7 +18,6 @@ use std::time::Duration;
use async_trait::async_trait;
use log::{debug, error, warn};
use tokio::sync::{mpsc, oneshot};
-use uwb_uci_packets::{Packet, UciCommandPacket};
use crate::uci::command::UciCommand;
//use crate::uci::error::{Error, Result};
@@ -33,7 +32,7 @@ use crate::uci::message::UciMessage;
use crate::uci::notification::{CoreNotification, SessionNotification, UciNotification};
use crate::uci::response::UciResponse;
use crate::uci::timeout_uci_hal::TimeoutUciHal;
-use crate::uci::uci_hal::{RawUciMessage, UciHal};
+use crate::uci::uci_hal::{UciHal, UciHalPacket};
use crate::utils::PinSleep;
const UCI_TIMEOUT_MS: u64 = 800;
@@ -172,7 +171,15 @@ impl UciManager for UciManagerImpl {
async fn open_hal(&mut self) -> Result<()> {
match self.send_cmd(UciManagerCmd::OpenHal).await {
- Ok(UciResponse::OpenHal) => Ok(()),
+ 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;
+ debug!("UCI device info: {:?}", device_info);
+
+ Ok(())
+ }
Ok(_) => Err(Error::Unknown),
Err(e) => Err(e),
}
@@ -392,7 +399,7 @@ struct UciManagerActor<T: UciHal> {
is_hal_opened: bool,
// Receive the response and the notification from |hal|. Only used when |hal| is opened
// successfully.
- msg_receiver: mpsc::UnboundedReceiver<RawUciMessage>,
+ packet_receiver: mpsc::UnboundedReceiver<UciHalPacket>,
// Defrag the UCI packets.
defrager: uwb_uci_packets::PacketDefrager,
@@ -427,7 +434,7 @@ impl<T: UciHal> UciManagerActor<T> {
hal: TimeoutUciHal::new(hal),
cmd_receiver,
is_hal_opened: false,
- msg_receiver: mpsc::unbounded_channel().1,
+ packet_receiver: mpsc::unbounded_channel().1,
defrager: Default::default(),
open_hal_result_sender: None,
wait_device_status_timeout: PinSleep::new(Duration::MAX),
@@ -457,14 +464,14 @@ impl<T: UciHal> UciManagerActor<T> {
}
// Handle the UCI response or notification from HAL. Only when HAL is opened.
- msg = self.msg_receiver.recv(), if self.is_hal_opened => {
- match msg {
+ packet = self.packet_receiver.recv(), if self.is_hal_opened => {
+ match packet {
None => {
- warn!("UciHal dropped the msg_sender unexpectedly.");
+ warn!("UciHal dropped the packet_sender unexpectedly.");
self.on_hal_closed();
},
- Some(msg) => {
- if let Some(packet) = self.defrager.defragment_packet(&msg) {
+ Some(packet) => {
+ if let Some(packet) = self.defrager.defragment_packet(&packet) {
match packet.try_into() {
Ok(UciMessage::Response(resp)) => {
self.handle_response(resp).await;
@@ -529,10 +536,10 @@ impl<T: UciHal> UciManagerActor<T> {
return;
}
- let (msg_sender, msg_receiver) = mpsc::unbounded_channel();
- match self.hal.open(msg_sender).await {
+ let (packet_sender, packet_receiver) = mpsc::unbounded_channel();
+ match self.hal.open(packet_sender).await {
Ok(()) => {
- self.on_hal_open(msg_receiver);
+ self.on_hal_open(packet_receiver);
self.wait_device_status_timeout =
PinSleep::new(Duration::from_millis(UCI_TIMEOUT_MS));
self.open_hal_result_sender.replace(result_sender);
@@ -598,9 +605,7 @@ impl<T: UciHal> UciManagerActor<T> {
return Err(Error::BadParameters);
}
- let packet = TryInto::<UciCommandPacket>::try_into(cmd)?;
- self.hal.send_command(packet.to_vec()).await?;
- Ok(())
+ self.hal.send_command(cmd).await
}
async fn handle_response(&mut self, resp: UciResponse) {
@@ -656,14 +661,14 @@ impl<T: UciHal> UciManagerActor<T> {
}
}
- fn on_hal_open(&mut self, msg_receiver: mpsc::UnboundedReceiver<RawUciMessage>) {
+ fn on_hal_open(&mut self, packet_receiver: mpsc::UnboundedReceiver<UciHalPacket>) {
self.is_hal_opened = true;
- self.msg_receiver = msg_receiver;
+ self.packet_receiver = packet_receiver;
}
fn on_hal_closed(&mut self) {
self.is_hal_opened = false;
- self.msg_receiver = mpsc::unbounded_channel().1;
+ self.packet_receiver = mpsc::unbounded_channel().1;
}
fn is_waiting_resp(&self) -> bool {
@@ -709,29 +714,43 @@ mod tests {
use super::*;
use bytes::Bytes;
- use num_traits::ToPrimitive;
use crate::params::uci_packets::{CapTlvType, StatusCode};
use crate::uci::mock_uci_hal::MockUciHal;
use crate::utils::init_test_logging;
- fn into_raw_messages<T: Into<uwb_uci_packets::UciPacketPacket>>(
+ fn into_uci_hal_packets<T: Into<uwb_uci_packets::UciPacketPacket>>(
builder: T,
- ) -> Vec<RawUciMessage> {
+ ) -> Vec<UciHalPacket> {
let packets: Vec<uwb_uci_packets::UciPacketHalPacket> = builder.into().into();
packets.into_iter().map(|packet| packet.into()).collect()
}
- async fn setup_uci_manager_with_open_hal(
- setup_hal_fn: fn(&mut MockUciHal),
- ) -> (UciManagerImpl, MockUciHal) {
+ async fn setup_uci_manager_with_open_hal<F>(setup_hal_fn: F) -> (UciManagerImpl, MockUciHal)
+ where
+ F: FnOnce(&mut MockUciHal),
+ {
init_test_logging();
+ // Open the hal.
let mut hal = MockUciHal::new();
- let notf = into_raw_messages(uwb_uci_packets::DeviceStatusNtfBuilder {
+ let notf = into_uci_hal_packets(uwb_uci_packets::DeviceStatusNtfBuilder {
device_state: uwb_uci_packets::DeviceState::DeviceStateReady,
});
hal.expected_open(Some(notf), Ok(()));
+
+ // Get the device info.
+ let cmd = UciCommand::CoreGetDeviceInfo;
+ let resp = into_uci_hal_packets(uwb_uci_packets::GetDeviceInfoRspBuilder {
+ status: uwb_uci_packets::StatusCode::UciStatusOk,
+ uci_version: 0x1234,
+ mac_version: 0x5678,
+ phy_version: 0x90ab,
+ uci_test_version: 0x1357,
+ vendor_spec_info: vec![0x1, 0x2],
+ });
+ hal.expected_send_command(cmd, resp, Ok(()));
+
setup_hal_fn(&mut hal);
// Verify open_hal() is working.
@@ -794,12 +813,8 @@ mod tests {
#[tokio::test]
async fn test_device_reset_ok() {
let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd = uwb_uci_packets::DeviceResetCmdBuilder {
- reset_config: uwb_uci_packets::ResetConfig::UwbsReset,
- }
- .build()
- .into();
- let resp = into_raw_messages(uwb_uci_packets::DeviceResetRspBuilder {
+ let cmd = UciCommand::DeviceReset { reset_config: ResetConfig::UwbsReset };
+ let resp = into_uci_hal_packets(uwb_uci_packets::DeviceResetRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
});
@@ -814,15 +829,23 @@ mod tests {
#[tokio::test]
async fn test_core_get_device_info_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd = uwb_uci_packets::GetDeviceInfoCmdBuilder {}.build().into();
- let resp = into_raw_messages(uwb_uci_packets::GetDeviceInfoRspBuilder {
- status: uwb_uci_packets::StatusCode::UciStatusOk,
- uci_version: 0x1234,
- mac_version: 0x5678,
- phy_version: 0x90ab,
- uci_test_version: 0x1357,
- vendor_spec_info: vec![0x1, 0x2],
+ let status = StatusCode::UciStatusOk;
+ let uci_version = 0x1234;
+ let mac_version = 0x5678;
+ let phy_version = 0x90ab;
+ let uci_test_version = 0x1357;
+ let vendor_spec_info = vec![0x1, 0x2];
+ let vendor_spec_info_clone = vendor_spec_info.clone();
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::CoreGetDeviceInfo;
+ let resp = into_uci_hal_packets(uwb_uci_packets::GetDeviceInfoRspBuilder {
+ status,
+ uci_version,
+ mac_version,
+ phy_version,
+ uci_test_version,
+ vendor_spec_info: vendor_spec_info_clone,
});
hal.expected_send_command(cmd, resp, Ok(()));
@@ -830,11 +853,11 @@ mod tests {
.await;
let expected_result = GetDeviceInfoResponse {
- uci_version: 0x1234,
- mac_version: 0x5678,
- phy_version: 0x90ab,
- uci_test_version: 0x1357,
- vendor_spec_info: vec![0x1, 0x2],
+ uci_version,
+ mac_version,
+ phy_version,
+ uci_test_version,
+ vendor_spec_info,
};
let result = uci_manager.core_get_device_info().await.unwrap();
assert_eq!(result, expected_result);
@@ -843,22 +866,20 @@ mod tests {
#[tokio::test]
async fn test_core_get_caps_info_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let tlv = uwb_uci_packets::CapTlv {
- t: uwb_uci_packets::CapTlvType::SupportedFiraPhyVersionRange,
- v: vec![0x12, 0x34, 0x56],
- };
- let cmd = uwb_uci_packets::GetCapsInfoCmdBuilder {}.build().into();
- let resp = into_raw_messages(uwb_uci_packets::GetCapsInfoRspBuilder {
+ let tlv = CapTlv { t: CapTlvType::SupportedFiraPhyVersionRange, v: vec![0x12, 0x34, 0x56] };
+ let tlv_clone = tlv.clone();
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::CoreGetCapsInfo;
+ let resp = into_uci_hal_packets(uwb_uci_packets::GetCapsInfoRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
- tlvs: vec![tlv],
+ tlvs: vec![tlv_clone],
});
hal.expected_send_command(cmd, resp, Ok(()));
})
.await;
- let tlv = CapTlv { t: CapTlvType::SupportedFiraPhyVersionRange, v: vec![0x12, 0x34, 0x56] };
let result = uci_manager.core_get_caps_info().await.unwrap();
assert_eq!(result[0], tlv);
assert!(mock_hal.wait_expected_calls_done().await);
@@ -866,73 +887,66 @@ mod tests {
#[tokio::test]
async fn test_core_set_config_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let tlv = uwb_uci_packets::DeviceConfigTlv {
- cfg_id: uwb_uci_packets::DeviceConfigId::DeviceState,
- v: vec![0x12, 0x34, 0x56],
- };
- let cmd = uwb_uci_packets::SetConfigCmdBuilder { tlvs: vec![tlv] }.build().into();
- let resp = into_raw_messages(uwb_uci_packets::SetConfigRspBuilder {
- status: uwb_uci_packets::StatusCode::UciStatusOk,
- cfg_status: vec![],
+ let tlv = DeviceConfigTlv {
+ cfg_id: uwb_uci_packets::DeviceConfigId::DeviceState,
+ v: vec![0x12, 0x34, 0x56],
+ };
+ let tlv_clone = tlv.clone();
+ let status = StatusCode::UciStatusOk;
+ let config_status = vec![];
+ let config_status_clone = config_status.clone();
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::CoreSetConfig { config_tlvs: vec![tlv_clone] };
+ let resp = into_uci_hal_packets(uwb_uci_packets::SetConfigRspBuilder {
+ status,
+ cfg_status: config_status_clone,
});
hal.expected_send_command(cmd, resp, Ok(()));
})
.await;
- let config_tlv =
- DeviceConfigTlv { cfg_id: DeviceConfigId::DeviceState, v: vec![0x12, 0x34, 0x56] };
- let expected_result =
- CoreSetConfigResponse { status: StatusCode::UciStatusOk, config_status: vec![] };
- let result = uci_manager.core_set_config(vec![config_tlv]).await.unwrap();
+ let expected_result = CoreSetConfigResponse { status, config_status };
+ let result = uci_manager.core_set_config(vec![tlv]).await.unwrap();
assert_eq!(result, expected_result);
assert!(mock_hal.wait_expected_calls_done().await);
}
#[tokio::test]
async fn test_core_get_config_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cfg_id = uwb_uci_packets::DeviceConfigId::DeviceState;
- let tlv = uwb_uci_packets::DeviceConfigTlv { cfg_id, v: vec![0x12, 0x34, 0x56] };
- let cmd =
- uwb_uci_packets::GetConfigCmdBuilder { cfg_id: vec![cfg_id.to_u8().unwrap()] }
- .build()
- .into();
- let resp = into_raw_messages(uwb_uci_packets::GetConfigRspBuilder {
+ let cfg_id = DeviceConfigId::DeviceState;
+ let tlv = DeviceConfigTlv { cfg_id, v: vec![0x12, 0x34, 0x56] };
+ let tlv_clone = tlv.clone();
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::CoreGetConfig { cfg_id: vec![cfg_id] };
+ let resp = into_uci_hal_packets(uwb_uci_packets::GetConfigRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
- tlvs: vec![tlv],
+ tlvs: vec![tlv_clone],
});
hal.expected_send_command(cmd, resp, Ok(()));
})
.await;
- let config_id = DeviceConfigId::DeviceState;
- let expected_result = vec![DeviceConfigTlv {
- cfg_id: DeviceConfigId::DeviceState,
- v: vec![0x12, 0x34, 0x56],
- }];
- CoreSetConfigResponse { status: StatusCode::UciStatusOk, config_status: vec![] };
- let result = uci_manager.core_get_config(vec![config_id]).await.unwrap();
+ let expected_result = vec![tlv];
+ let result = uci_manager.core_get_config(vec![cfg_id]).await.unwrap();
assert_eq!(result, expected_result);
assert!(mock_hal.wait_expected_calls_done().await);
}
#[tokio::test]
async fn test_session_init_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let session_id = 0x123;
- let cmd = uwb_uci_packets::SessionInitCmdBuilder {
- session_id,
- session_type: uwb_uci_packets::SessionType::FiraRangingSession,
- }
- .build()
- .into();
- let mut resp = into_raw_messages(uwb_uci_packets::SessionInitRspBuilder {
+ let session_id = 0x123;
+ let session_type = SessionType::FiraRangingSession;
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::SessionInit { session_id, session_type };
+ let mut resp = into_uci_hal_packets(uwb_uci_packets::SessionInitRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
});
- let mut notf = into_raw_messages(uwb_uci_packets::SessionStatusNtfBuilder {
+ let mut notf = into_uci_hal_packets(uwb_uci_packets::SessionStatusNtfBuilder {
session_id,
session_state: uwb_uci_packets::SessionState::SessionStateInit,
reason_code: uwb_uci_packets::ReasonCode::StateChangeWithSessionManagementCommands,
@@ -944,8 +958,6 @@ mod tests {
})
.await;
- let session_id = 0x123;
- let session_type = SessionType::FiraRangingSession;
let result = uci_manager.session_init(session_id, session_type).await;
assert!(result.is_ok());
assert!(mock_hal.wait_expected_calls_done().await);
@@ -953,9 +965,11 @@ mod tests {
#[tokio::test]
async fn test_session_deinit_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd = uwb_uci_packets::SessionDeinitCmdBuilder { session_id: 0x123 }.build().into();
- let resp = into_raw_messages(uwb_uci_packets::SessionDeinitRspBuilder {
+ let session_id = 0x123;
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::SessionDeinit { session_id };
+ let resp = into_uci_hal_packets(uwb_uci_packets::SessionDeinitRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
});
@@ -963,7 +977,6 @@ mod tests {
})
.await;
- let session_id = 0x123;
let result = uci_manager.session_deinit(session_id).await;
assert!(result.is_ok());
assert!(mock_hal.wait_expected_calls_done().await);
@@ -971,18 +984,15 @@ mod tests {
#[tokio::test]
async fn test_session_set_app_config_ok() {
+ let session_id = 0x123;
+ let config_tlv =
+ AppConfigTlv { cfg_id: AppConfigTlvType::DeviceType, v: vec![0x12, 0x34, 0x56] };
+ let config_tlv_clone = config_tlv.clone();
+
let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let tlv = uwb_uci_packets::AppConfigTlv {
- cfg_id: uwb_uci_packets::AppConfigTlvType::DeviceType,
- v: vec![0x12, 0x34, 0x56],
- };
- let cmd = uwb_uci_packets::SessionSetAppConfigCmdBuilder {
- session_id: 0x123,
- tlvs: vec![tlv],
- }
- .build()
- .into();
- let resp = into_raw_messages(uwb_uci_packets::SessionSetAppConfigRspBuilder {
+ let cmd =
+ UciCommand::SessionSetAppConfig { session_id, config_tlvs: vec![config_tlv_clone] };
+ let resp = into_uci_hal_packets(uwb_uci_packets::SessionSetAppConfigRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
cfg_status: vec![],
});
@@ -991,9 +1001,6 @@ mod tests {
})
.await;
- let session_id = 0x123;
- let config_tlv =
- AppConfigTlv { cfg_id: AppConfigTlvType::DeviceType, v: vec![0x12, 0x34, 0x56] };
let expected_result =
SetAppConfigResponse { status: StatusCode::UciStatusOk, config_status: vec![] };
let result =
@@ -1004,28 +1011,23 @@ mod tests {
#[tokio::test]
async fn test_session_get_app_config_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cfg_id = uwb_uci_packets::AppConfigTlvType::DeviceType;
- let tlv = uwb_uci_packets::AppConfigTlv { cfg_id, v: vec![0x12, 0x34, 0x56] };
- let cmd = uwb_uci_packets::SessionGetAppConfigCmdBuilder {
- session_id: 0x123,
- app_cfg: vec![cfg_id.to_u8().unwrap()],
- }
- .build()
- .into();
- let resp = into_raw_messages(uwb_uci_packets::SessionGetAppConfigRspBuilder {
+ let session_id = 0x123;
+ let config_id = AppConfigTlvType::DeviceType;
+ let tlv = AppConfigTlv { cfg_id: AppConfigTlvType::DeviceType, v: vec![0x12, 0x34, 0x56] };
+ let tlv_clone = tlv.clone();
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::SessionGetAppConfig { session_id, app_cfg: vec![config_id] };
+ let resp = into_uci_hal_packets(uwb_uci_packets::SessionGetAppConfigRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
- tlvs: vec![tlv],
+ tlvs: vec![tlv_clone],
});
hal.expected_send_command(cmd, resp, Ok(()));
})
.await;
- let session_id = 0x123;
- let config_id = AppConfigTlvType::DeviceType;
- let expected_result =
- vec![AppConfigTlv { cfg_id: AppConfigTlvType::DeviceType, v: vec![0x12, 0x34, 0x56] }];
+ let expected_result = vec![tlv];
let result = uci_manager.session_get_app_config(session_id, vec![config_id]).await.unwrap();
assert_eq!(result, expected_result);
assert!(mock_hal.wait_expected_calls_done().await);
@@ -1033,11 +1035,13 @@ mod tests {
#[tokio::test]
async fn test_session_get_count_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd = uwb_uci_packets::SessionGetCountCmdBuilder {}.build().into();
- let resp = into_raw_messages(uwb_uci_packets::SessionGetCountRspBuilder {
+ let session_count = 5;
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::SessionGetCount;
+ let resp = into_uci_hal_packets(uwb_uci_packets::SessionGetCountRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
- session_count: 5,
+ session_count,
});
hal.expected_send_command(cmd, resp, Ok(()));
@@ -1045,43 +1049,45 @@ mod tests {
.await;
let result = uci_manager.session_get_count().await.unwrap();
- assert_eq!(result, 5);
+ assert_eq!(result, session_count);
assert!(mock_hal.wait_expected_calls_done().await);
}
#[tokio::test]
async fn test_session_get_state_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd =
- uwb_uci_packets::SessionGetStateCmdBuilder { session_id: 0x123 }.build().into();
- let resp = into_raw_messages(uwb_uci_packets::SessionGetStateRspBuilder {
+ let session_id = 0x123;
+ let session_state = SessionState::SessionStateActive;
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::SessionGetState { session_id };
+ let resp = into_uci_hal_packets(uwb_uci_packets::SessionGetStateRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
- session_state: uwb_uci_packets::SessionState::SessionStateActive,
+ session_state,
});
hal.expected_send_command(cmd, resp, Ok(()));
})
.await;
- let session_id = 0x123;
let result = uci_manager.session_get_state(session_id).await.unwrap();
- assert_eq!(result, SessionState::SessionStateActive);
+ assert_eq!(result, session_state);
assert!(mock_hal.wait_expected_calls_done().await);
}
#[tokio::test]
async fn test_session_update_controller_multicast_list_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let controlee =
- uwb_uci_packets::Controlee { short_address: 0x4567, subsession_id: 0x90ab };
- let cmd = uwb_uci_packets::SessionUpdateControllerMulticastListCmdBuilder {
- session_id: 0x123,
- action: UpdateMulticastListAction::AddControlee,
- controlees: vec![controlee],
- }
- .build()
- .into();
- let resp = into_raw_messages(
+ let session_id = 0x123;
+ let action = UpdateMulticastListAction::AddControlee;
+ let controlee = Controlee { short_address: 0x4567, subsession_id: 0x90ab };
+ let controlee_clone = controlee.clone();
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::SessionUpdateControllerMulticastList {
+ session_id,
+ action,
+ controlees: vec![controlee_clone],
+ };
+ let resp = into_uci_hal_packets(
uwb_uci_packets::SessionUpdateControllerMulticastListRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
},
@@ -1091,9 +1097,6 @@ mod tests {
})
.await;
- let session_id = 0x123;
- let action = UpdateMulticastListAction::AddControlee;
- let controlee = Controlee { short_address: 0x4567, subsession_id: 0x90ab };
let result = uci_manager
.session_update_controller_multicast_list(session_id, action, vec![controlee])
.await;
@@ -1103,9 +1106,11 @@ mod tests {
#[tokio::test]
async fn test_range_start_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd = uwb_uci_packets::RangeStartCmdBuilder { session_id: 0x123 }.build().into();
- let resp = into_raw_messages(uwb_uci_packets::RangeStartRspBuilder {
+ let session_id = 0x123;
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::RangeStart { session_id };
+ let resp = into_uci_hal_packets(uwb_uci_packets::RangeStartRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
});
@@ -1113,7 +1118,6 @@ mod tests {
})
.await;
- let session_id = 0x123;
let result = uci_manager.range_start(session_id).await;
assert!(result.is_ok());
assert!(mock_hal.wait_expected_calls_done().await);
@@ -1121,9 +1125,11 @@ mod tests {
#[tokio::test]
async fn test_range_stop_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd = uwb_uci_packets::RangeStopCmdBuilder { session_id: 0x123 }.build().into();
- let resp = into_raw_messages(uwb_uci_packets::RangeStopRspBuilder {
+ let session_id = 0x123;
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::RangeStop { session_id };
+ let resp = into_uci_hal_packets(uwb_uci_packets::RangeStopRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
});
@@ -1131,7 +1137,6 @@ mod tests {
})
.await;
- let session_id = 0x123;
let result = uci_manager.range_stop(session_id).await;
assert!(result.is_ok());
assert!(mock_hal.wait_expected_calls_done().await);
@@ -1139,33 +1144,33 @@ mod tests {
#[tokio::test]
async fn test_range_get_ranging_count_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd = uwb_uci_packets::RangeGetRangingCountCmdBuilder { session_id: 0x123 }
- .build()
- .into();
- let resp = into_raw_messages(uwb_uci_packets::RangeGetRangingCountRspBuilder {
+ let session_id = 0x123;
+ let count = 3;
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::RangeGetRangingCount { session_id };
+ let resp = into_uci_hal_packets(uwb_uci_packets::RangeGetRangingCountRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
- count: 3,
+ count,
});
hal.expected_send_command(cmd, resp, Ok(()));
})
.await;
- let session_id = 0x123;
let result = uci_manager.range_get_ranging_count(session_id).await.unwrap();
- assert_eq!(result, 3);
+ assert_eq!(result, count as usize);
assert!(mock_hal.wait_expected_calls_done().await);
}
#[tokio::test]
async fn test_android_set_country_code_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd =
- uwb_uci_packets::AndroidSetCountryCodeCmdBuilder { country_code: b"US".to_owned() }
- .build()
- .into();
- let resp = into_raw_messages(uwb_uci_packets::AndroidSetCountryCodeRspBuilder {
+ let country_code = CountryCode::new(b"US").unwrap();
+ let country_code_clone = country_code.clone();
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::AndroidSetCountryCode { country_code: country_code_clone };
+ let resp = into_uci_hal_packets(uwb_uci_packets::AndroidSetCountryCodeRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
});
@@ -1173,7 +1178,6 @@ mod tests {
})
.await;
- let country_code = CountryCode::new(b"US").unwrap();
let result = uci_manager.android_set_country_code(country_code).await;
assert!(result.is_ok());
assert!(mock_hal.wait_expected_calls_done().await);
@@ -1181,57 +1185,52 @@ mod tests {
#[tokio::test]
async fn test_android_get_power_stats_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd = uwb_uci_packets::AndroidGetPowerStatsCmdBuilder {}.build().into();
- let resp = into_raw_messages(uwb_uci_packets::AndroidGetPowerStatsRspBuilder {
- stats: uwb_uci_packets::PowerStats {
- status: uwb_uci_packets::StatusCode::UciStatusOk,
- idle_time_ms: 123,
- tx_time_ms: 456,
- rx_time_ms: 789,
- total_wake_count: 5,
- },
- });
-
- hal.expected_send_command(cmd, resp, Ok(()));
- })
- .await;
-
- let expected_result = PowerStats {
+ let power_stats = PowerStats {
status: StatusCode::UciStatusOk,
idle_time_ms: 123,
tx_time_ms: 456,
rx_time_ms: 789,
total_wake_count: 5,
};
+ let power_stats_clone = power_stats.clone();
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::AndroidGetPowerStats;
+ let resp = into_uci_hal_packets(uwb_uci_packets::AndroidGetPowerStatsRspBuilder {
+ stats: power_stats_clone,
+ });
+
+ hal.expected_send_command(cmd, resp, Ok(()));
+ })
+ .await;
+
let result = uci_manager.android_get_power_stats().await.unwrap();
- assert_eq!(result, expected_result);
+ assert_eq!(result, power_stats);
assert!(mock_hal.wait_expected_calls_done().await);
}
#[tokio::test]
async fn test_raw_vendor_cmd_ok() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd = uwb_uci_packets::UciVendor_F_CommandBuilder {
- opcode: 0x3,
- payload: Some(Bytes::from(vec![0x11, 0x22, 0x33, 0x44])),
- }
- .build()
- .into();
- let resp = into_raw_messages(uwb_uci_packets::UciVendor_F_ResponseBuilder {
- opcode: 0x3,
- payload: Some(Bytes::from(vec![0x55, 0x66, 0x77, 0x88])),
+ let gid = 0xF;
+ let oid = 0x3;
+ let cmd_payload = vec![0x11, 0x22, 0x33, 0x44];
+ let cmd_payload_clone = cmd_payload.clone();
+ let resp_payload = vec![0x55, 0x66, 0x77, 0x88];
+ let resp_payload_clone = resp_payload.clone();
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::RawVendorCmd { gid, oid, payload: cmd_payload_clone };
+ let resp = into_uci_hal_packets(uwb_uci_packets::UciVendor_F_ResponseBuilder {
+ opcode: oid as u8,
+ payload: Some(Bytes::from(resp_payload_clone)),
});
hal.expected_send_command(cmd, resp, Ok(()));
})
.await;
- let gid = 0xF;
- let oid = 0x3;
- let payload = vec![0x11, 0x22, 0x33, 0x44];
- let expected_result = RawVendorMessage { gid, oid, payload: vec![0x55, 0x66, 0x77, 0x88] };
- let result = uci_manager.raw_vendor_cmd(gid, oid, payload).await.unwrap();
+ let expected_result = RawVendorMessage { gid, oid, payload: resp_payload };
+ let result = uci_manager.raw_vendor_cmd(gid, oid, cmd_payload).await.unwrap();
assert_eq!(result, expected_result);
assert!(mock_hal.wait_expected_calls_done().await);
}
@@ -1239,8 +1238,7 @@ mod tests {
#[tokio::test]
async fn test_session_get_count_retry_no_response() {
let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd: RawUciMessage = uwb_uci_packets::SessionGetCountCmdBuilder {}.build().into();
-
+ let cmd = UciCommand::SessionGetCount;
hal.expected_send_command(cmd, vec![], Ok(()));
})
.await;
@@ -1253,8 +1251,7 @@ mod tests {
#[tokio::test]
async fn test_session_get_count_timeout() {
let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd: RawUciMessage = uwb_uci_packets::SessionGetCountCmdBuilder {}.build().into();
-
+ let cmd = UciCommand::SessionGetCount;
hal.expected_send_command(cmd, vec![], Err(Error::Timeout));
})
.await;
@@ -1267,8 +1264,8 @@ mod tests {
#[tokio::test]
async fn test_session_get_count_retry_too_many_times() {
let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd: RawUciMessage = uwb_uci_packets::SessionGetCountCmdBuilder {}.build().into();
- let retry_resp = into_raw_messages(uwb_uci_packets::SessionGetCountRspBuilder {
+ let cmd = UciCommand::SessionGetCount;
+ let retry_resp = into_uci_hal_packets(uwb_uci_packets::SessionGetCountRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusCommandRetry,
session_count: 0,
});
@@ -1286,15 +1283,17 @@ mod tests {
#[tokio::test]
async fn test_session_get_count_retry_notification() {
- let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(|hal| {
- let cmd: RawUciMessage = uwb_uci_packets::SessionGetCountCmdBuilder {}.build().into();
- let retry_resp = into_raw_messages(uwb_uci_packets::SessionGetCountRspBuilder {
+ let session_count = 5;
+
+ let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(move |hal| {
+ let cmd = UciCommand::SessionGetCount;
+ let retry_resp = into_uci_hal_packets(uwb_uci_packets::SessionGetCountRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusCommandRetry,
session_count: 0,
});
- let resp = into_raw_messages(uwb_uci_packets::SessionGetCountRspBuilder {
+ let resp = into_uci_hal_packets(uwb_uci_packets::SessionGetCountRspBuilder {
status: uwb_uci_packets::StatusCode::UciStatusOk,
- session_count: 5,
+ session_count,
});
hal.expected_send_command(cmd.clone(), retry_resp.clone(), Ok(()));
@@ -1304,7 +1303,7 @@ mod tests {
.await;
let result = uci_manager.session_get_count().await.unwrap();
- assert_eq!(result, 5);
+ assert_eq!(result, session_count);
assert!(mock_hal.wait_expected_calls_done().await);
}
}
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 815a5c4..b61e04c 100644
--- a/src/rust/uwb_core/src/uci/uci_manager_sync.rs
+++ b/src/rust/uwb_core/src/uci/uci_manager_sync.rs
@@ -115,10 +115,10 @@ impl UciManagerSync {
/// UciHal and NotificationManagerBuilder required at construction as they are required before
/// open_hal is called. runtime is taken with ownership for blocking on async steps only.
pub fn new<T: UciHal, U: NotificationManager, V: NotificationManagerBuilder<U>>(
- uci_manager_runtime: Runtime,
hal: T,
notification_manager_builder: V,
) -> Result<Self> {
+ let uci_manager_runtime = RuntimeBuilder::new_multi_thread().enable_all().build().unwrap();
// UciManagerImpl::new uses tokio::spawn, so it is called inside the runtime as async fn.
let mut uci_manager_impl = uci_manager_runtime.block_on(async { UciManagerImpl::new(hal) });
let (core_notification_sender, core_notification_receiver) =
@@ -316,7 +316,7 @@ mod tests {
use crate::error::Error;
use crate::uci::mock_uci_hal::MockUciHal;
- use crate::uci::uci_hal::RawUciMessage;
+ use crate::uci::uci_hal::UciHalPacket;
struct MockNotificationManager {
device_state_sender: mpsc::UnboundedSender<DeviceState>,
@@ -344,6 +344,7 @@ mod tests {
Ok(())
}
}
+
struct MockNotificationManagerBuilder {
device_state_sender: mpsc::UnboundedSender<DeviceState>,
// initial_count is an example for a parameter undetermined at compile time.
@@ -357,12 +358,14 @@ mod tests {
})
}
}
+
fn into_raw_messages<T: Into<uwb_uci_packets::UciPacketPacket>>(
builder: T,
- ) -> Vec<RawUciMessage> {
+ ) -> Vec<UciHalPacket> {
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();
@@ -374,7 +377,6 @@ mod tests {
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,
MockNotificationManagerBuilder { device_state_sender, initial_count: 0 },
)
diff --git a/src/rust/uwb_core/src/utils.rs b/src/rust/uwb_core/src/utils.rs
index 65fae8d..5ed116a 100644
--- a/src/rust/uwb_core/src/utils.rs
+++ b/src/rust/uwb_core/src/utils.rs
@@ -50,7 +50,38 @@ macro_rules! builder_field {
}
pub(crate) use builder_field;
+/// Generate the getter method for the field of the struct.
+macro_rules! getter_field {
+ ($field:ident, $ty:ty) => {
+ pub fn $field(&self) -> &$ty {
+ &self.$field
+ }
+ };
+}
+pub(crate) use getter_field;
+
#[cfg(test)]
pub fn init_test_logging() {
let _ = env_logger::builder().is_test(true).try_init();
}
+
+#[cfg(test)]
+mod tests {
+ struct Foo {
+ value: u32,
+ }
+
+ impl Foo {
+ pub fn new(value: u32) -> Self {
+ Self { value }
+ }
+
+ getter_field!(value, u32);
+ }
+
+ #[test]
+ fn test_getter_field() {
+ let foo = Foo::new(5);
+ assert_eq!(foo.value(), &5);
+ }
+}
diff --git a/src/rust/uwb_uci_packets/Cargo.toml b/src/rust/uwb_uci_packets/Cargo.toml
index ae3c729..3d1f28a 100644
--- a/src/rust/uwb_uci_packets/Cargo.toml
+++ b/src/rust/uwb_uci_packets/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "uwb_uci_packets"
version = "0.0.1"
-edition = "2018"
+edition = "2021"
[dependencies]
bytes = "*"
diff --git a/src/rust/uwb_uci_packets/uci_packets.pdl b/src/rust/uwb_uci_packets/uci_packets.pdl
index 884c7c6..5fd696f 100644
--- a/src/rust/uwb_uci_packets/uci_packets.pdl
+++ b/src/rust/uwb_uci_packets/uci_packets.pdl
@@ -163,8 +163,8 @@ enum AppConfigTlvType : 8 {
BPRF_PHR_DATA_RATE = 0x31,
MAX_NUMBER_OF_MEASUREMENTS = 0x32,
STS_LENGTH = 0x35,
- SESSION_KEY = 0x36,
- SUBSESSION_KEY = 0x37,
+ SESSION_KEY = 0x45,
+ SUBSESSION_KEY = 0x46,
// CCC specific
CCC_HOP_MODE_KEY = 0xA0,