blob: 1f72b51fe549219f2674da714a4c096a5c42367e [file] [log] [blame] [edit]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Provide a simple uwbd client, used to verify the uwbd service end-to-end.
use std::error::Error;
use std::time::Duration;
use clap::{arg, Command, ArgGroup};
use dbus::blocking::{Connection, Proxy};
use protobuf::{Message, RepeatedField};
use uwb_core::proto::bindings::{
EnableResponse, InitSessionRequest, SessionType, FiraAppConfigParams, DeviceType,
RangingRoundUsage, StsConfig, MultiNodeMode, UwbChannel, MacFcsType, RangingRoundControl,
AoaResultRequest, RangeDataNtfConfig, DeviceRole, RframeConfig, PsduDataRate, RangingTimeStruct,
TxAdaptivePayloadPower, PrfMode, ScheduledMode, KeyRotation, MacAddressMode, HoppingMode,
ResultReportConfig, BprfPhrDataRate, StsLength, InitSessionResponse, PreambleDuration,
StartRangingRequest, StartRangingResponse, StopRangingRequest, StopRangingResponse,
DeinitSessionRequest, DeinitSessionResponse,
};
use uwb_core::proto::utils::write_to_bytes;
use uwbd::common::{DBUS_OBJECT_PATH, DBUS_SERVICE_NAME};
use uwbd::dbus_bindings::client::OrgChromiumUwbd;
// Returns the clap Command that this CLI will use
fn cli() -> Command {
Command::new("uwbd_client")
.about("CLI connecting to uwbd to start and stop UWB ranging sessions")
.subcommand_required(true)
.arg_required_else_help(true)
.subcommand(
Command::new("start")
.about("Enables UWB, initializes and starts a ranging session.")
.args_conflicts_with_subcommands(true)
.arg(arg!(-i --initiator "Uses the initiator + controller parameter profile"))
.arg(arg!(-r --responder "Uses the responder + controlee parameter profile"))
.group(ArgGroup::new("vers")
.args(["initiator", "responder"])
.required(true))
)
.subcommand(
Command::new("stop")
.about("stops and deinits the default UWB ranging session")
)
}
// Returns a FiraAppConfigParams that has been initialized with a default set of parameters.
// The profile specific parameters i.e. Device Type, Device Role, Mac Address and Destination
// Mac Addresses are not set.
fn create_app_config_params() -> FiraAppConfigParams {
let mut app_config_params = FiraAppConfigParams::new();
app_config_params.set_device_type(DeviceType::CONTROLEE);
app_config_params.set_ranging_round_usage(RangingRoundUsage::DS_TWR);
app_config_params.set_sts_config(StsConfig::STATIC);
app_config_params.set_multi_node_mode(MultiNodeMode::UNICAST);
app_config_params.set_channel_number(UwbChannel::CHANNEL_9);
app_config_params.set_slot_duration_rstu(2400);
app_config_params.set_ranging_interval_ms(200);
app_config_params.set_mac_fcs_type(MacFcsType::CRC_16);
let mut ranging_round_control = RangingRoundControl::new();
ranging_round_control.set_ranging_result_report_message(true);
ranging_round_control.set_control_message(true);
ranging_round_control.set_measurement_report_message(false);
app_config_params.set_ranging_round_control(ranging_round_control);
app_config_params.set_aoa_result_request(AoaResultRequest::REQ_AOA_RESULTS);
app_config_params.set_range_data_ntf_config(RangeDataNtfConfig::RANGE_DATA_NTF_CONFIG_ENABLE);
app_config_params.set_range_data_ntf_proximity_near_cm(0);
app_config_params.set_range_data_ntf_proximity_far_cm(20000);
app_config_params.set_device_role(DeviceRole::RESPONDER);
app_config_params.set_rframe_config(RframeConfig::SP3);
app_config_params.set_preamble_code_index(9);
app_config_params.set_sfd_id(2);
app_config_params.set_psdu_data_rate(PsduDataRate::RATE_6M_81);
app_config_params.set_preamble_duration(PreambleDuration::T64_SYMBOLS);
app_config_params.set_ranging_time_struct(RangingTimeStruct::BLOCK_BASED_SCHEDULING);
app_config_params.set_slots_per_rr(25);
app_config_params.set_tx_adaptive_payload_power(TxAdaptivePayloadPower::
TX_ADAPTIVE_PAYLOAD_POWER_DISABLE);
app_config_params.set_responder_slot_index(1);
app_config_params.set_prf_mode(PrfMode::BPRF);
app_config_params.set_scheduled_mode(ScheduledMode::TIME_SCHEDULED_RANGING);
app_config_params.set_key_rotation(KeyRotation::KEY_ROTATION_DISABLE);
app_config_params.set_key_rotation_rate(0);
app_config_params.set_session_priority(70);
app_config_params.set_mac_address_mode(MacAddressMode::MAC_ADDRESS_2_BYTES);
app_config_params.set_vendor_id(vec![0x0,0x0]);
app_config_params.set_static_sts_iv(vec![0x0,0x0,0x0,0x0,0x0,0x0]);
app_config_params.set_number_of_sts_segments(1);
app_config_params.set_max_rr_retry(0);
app_config_params.set_uwb_initiation_time_ms(0);
app_config_params.set_hopping_mode(HoppingMode::HOPPING_MODE_DISABLE);
app_config_params.set_block_stride_length(0);
let mut result_report_config = ResultReportConfig::new();
result_report_config.set_tof(true);
result_report_config.set_aoa_azimuth(false);
result_report_config.set_aoa_elevation(false);
result_report_config.set_aoa_fom(false);
app_config_params.set_result_report_config(result_report_config);
app_config_params.set_in_band_termination_attempt_count(1);
app_config_params.set_sub_session_id(0);
app_config_params.set_bprf_phr_data_rate(BprfPhrDataRate::BPRF_PHR_DATA_RATE_850K);
app_config_params.set_max_number_of_measurements(0);
app_config_params.set_sts_length(StsLength::LENGTH_64);
app_config_params.set_number_of_range_measurements(0); //dropped by HAL
app_config_params.set_number_of_aoa_azimuth_measurements(0); //dropped by HAL
app_config_params.set_number_of_aoa_elevation_measurements(0); //dropped by HAL
app_config_params
}
fn main() -> Result<(), Box<dyn Error>> {
let matches = cli().get_matches();
let session_id = 1;
const TIMEOUT: Duration = Duration::from_millis(5000);
// Connect to D-Bus and create uwbd proxy.
let dbus_connection = Connection::new_system()?;
let uwbd_proxy = Proxy::new(
DBUS_SERVICE_NAME,
DBUS_OBJECT_PATH,
TIMEOUT,
&dbus_connection,
);
match matches.subcommand(){
Some(("start", sub_matches)) => {
// Create params
let mut app_config_params = create_app_config_params();
// Set initiator profile in params
if sub_matches.get_flag("initiator"){
app_config_params.set_device_type(DeviceType::CONTROLLER);
app_config_params.set_device_role(DeviceRole::INITIATOR);
app_config_params.set_device_mac_address(vec![0x08,0x00]);
let mut dst_mac_addresses: RepeatedField<Vec<u8>> = RepeatedField::new();
dst_mac_addresses.push(vec![0x04,0x00]);
app_config_params.set_dst_mac_address(dst_mac_addresses);
println!("Using initiator profile");
}
// Set responder profile in params
if sub_matches.get_flag("responder"){
app_config_params.set_device_type(DeviceType::CONTROLEE);
app_config_params.set_device_role(DeviceRole::RESPONDER);
app_config_params.set_device_mac_address(vec![0x04,0x00]);
let mut dst_mac_addresses: RepeatedField<Vec<u8>> = RepeatedField::new();
dst_mac_addresses.push(vec![0x08,0x00]);
app_config_params.set_dst_mac_address(dst_mac_addresses);
println!("Using responder profile");
}
// Enable UwB
let result_bytes = uwbd_proxy.enable()?;
let result = EnableResponse::parse_from_bytes(&result_bytes)?;
println!("Enable() returns: {:?}", result.status);
// Initialize the ranging session
let mut request = InitSessionRequest::new();
request.set_session_id(session_id);
request.set_session_type(SessionType::FIRA_RANGING_SESSION);
request.set_params(app_config_params);
let request_bytes = write_to_bytes(&request)?;
let result_bytes = uwbd_proxy.init_session(request_bytes)?;
let result = InitSessionResponse::parse_from_bytes(&result_bytes)?;
println!("InitSessionRequest returns: {:?}", result.status);
// Start the ranging session
let mut request = StartRangingRequest::new();
request.set_session_id(session_id);
let request_bytes = write_to_bytes(&request)?;
let result_bytes = uwbd_proxy.start_ranging(request_bytes)?;
let result = StartRangingResponse::parse_from_bytes(&result_bytes)?;
println!("StartRangingResponse returns: {:?}", result.status);
}
Some(("stop", _)) => {
// Stop the ranging session
let mut request = StopRangingRequest::new();
request.set_session_id(session_id);
let request_bytes = write_to_bytes(&request)?;
let result_bytes = uwbd_proxy.stop_ranging(request_bytes)?;
let result = StopRangingResponse::parse_from_bytes(&result_bytes)?;
println!("StopRangingResponse returns: {:?}", result.status);
// Deinit the ranging session
let mut request = DeinitSessionRequest::new();
request.set_session_id(session_id);
let request_bytes = write_to_bytes(&request)?;
let result_bytes = uwbd_proxy.stop_ranging(request_bytes)?;
let result = DeinitSessionResponse::parse_from_bytes(&result_bytes)?;
println!("DeinitSessionResponse returns: {:?}", result.status);
}
_ => unreachable!(),
}
Ok(())
}