blob: f66e79d911940152411866824ce7973a80352eed [file] [log] [blame]
// Copyright 2022 Google LLC
//
// 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
//
// https://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.
// @generated rust packets from uci_packets.pdl
#![allow(clippy::all)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused)]
#![allow(missing_docs)]
use bytes::{BufMut, Bytes, BytesMut};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive};
use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::sync::Arc;
use thiserror::Error;
type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
pub enum Error {
#[error("Packet parsing failed")]
InvalidPacketError,
#[error("{field} was {value:x}, which is not known")]
ConstraintOutOfBounds { field: String, value: u64 },
#[error("when parsing {obj}.{field} needed length of {wanted} but got {got}")]
InvalidLengthError {
obj: String,
field: String,
wanted: usize,
got: usize,
},
#[error("Due to size restrictions a struct could not be parsed.")]
ImpossibleStructError,
#[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")]
InvalidEnumValueError {
obj: String,
field: String,
value: u64,
type_: String,
},
}
#[derive(Debug, Error)]
#[error("{0}")]
pub struct TryFromError(&'static str);
pub trait Packet {
fn to_bytes(self) -> Bytes;
fn to_vec(self) -> Vec<u8>;
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum PacketBoundaryFlag {
Complete = 0x0,
NotComplete = 0x1,
}
impl fmt::Display for PacketBoundaryFlag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PacketBoundaryFlag::Complete => write!(f, "{:#04X} (COMPLETE)", self.to_u8().unwrap()),
PacketBoundaryFlag::NotComplete => {
write!(f, "{:#04X} (NOT_COMPLETE)", self.to_u8().unwrap())
}
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum GroupId {
Core = 0x0,
SessionConfig = 0x1,
RangingSessionControl = 0x2,
DataControl = 0x3,
VendorReservedA = 0xa,
VendorReservedB = 0xb,
VendorAndroid = 0xc,
Test = 0xd,
VendorReservedE = 0xe,
VendorReservedF = 0xf,
}
impl fmt::Display for GroupId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GroupId::Core => write!(f, "{:#04X} (CORE)", self.to_u8().unwrap()),
GroupId::SessionConfig => write!(f, "{:#04X} (SESSION_CONFIG)", self.to_u8().unwrap()),
GroupId::RangingSessionControl => write!(
f,
"{:#04X} (RANGING_SESSION_CONTROL)",
self.to_u8().unwrap()
),
GroupId::DataControl => write!(f, "{:#04X} (DATA_CONTROL)", self.to_u8().unwrap()),
GroupId::VendorReservedA => {
write!(f, "{:#04X} (VENDOR_RESERVED_A)", self.to_u8().unwrap())
}
GroupId::VendorReservedB => {
write!(f, "{:#04X} (VENDOR_RESERVED_B)", self.to_u8().unwrap())
}
GroupId::VendorAndroid => write!(f, "{:#04X} (VENDOR_ANDROID)", self.to_u8().unwrap()),
GroupId::Test => write!(f, "{:#04X} (TEST)", self.to_u8().unwrap()),
GroupId::VendorReservedE => {
write!(f, "{:#04X} (VENDOR_RESERVED_E)", self.to_u8().unwrap())
}
GroupId::VendorReservedF => {
write!(f, "{:#04X} (VENDOR_RESERVED_F)", self.to_u8().unwrap())
}
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum CoreOpCode {
CoreDeviceReset = 0x0,
CoreDeviceStatusNtf = 0x1,
CoreGetDeviceInfo = 0x2,
CoreGetCapsInfo = 0x3,
CoreSetConfig = 0x4,
CoreGetConfig = 0x5,
CoreDeviceSuspend = 0x6,
CoreGenericErrorNtf = 0x7,
}
impl fmt::Display for CoreOpCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CoreOpCode::CoreDeviceReset => {
write!(f, "{:#04X} (CORE_DEVICE_RESET)", self.to_u8().unwrap())
}
CoreOpCode::CoreDeviceStatusNtf => {
write!(f, "{:#04X} (CORE_DEVICE_STATUS_NTF)", self.to_u8().unwrap())
}
CoreOpCode::CoreGetDeviceInfo => {
write!(f, "{:#04X} (CORE_GET_DEVICE_INFO)", self.to_u8().unwrap())
}
CoreOpCode::CoreGetCapsInfo => {
write!(f, "{:#04X} (CORE_GET_CAPS_INFO)", self.to_u8().unwrap())
}
CoreOpCode::CoreSetConfig => {
write!(f, "{:#04X} (CORE_SET_CONFIG)", self.to_u8().unwrap())
}
CoreOpCode::CoreGetConfig => {
write!(f, "{:#04X} (CORE_GET_CONFIG)", self.to_u8().unwrap())
}
CoreOpCode::CoreDeviceSuspend => {
write!(f, "{:#04X} (CORE_DEVICE_SUSPEND)", self.to_u8().unwrap())
}
CoreOpCode::CoreGenericErrorNtf => {
write!(f, "{:#04X} (CORE_GENERIC_ERROR_NTF)", self.to_u8().unwrap())
}
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum SessionOpCode {
SessionInit = 0x0,
SessionDeinit = 0x1,
SessionStatusNtf = 0x2,
SessionSetAppConfig = 0x3,
SessionGetAppConfig = 0x4,
SessionGetCount = 0x5,
SessionGetState = 0x6,
SessionUpdateControllerMulticastList = 0x7,
}
impl fmt::Display for SessionOpCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
SessionOpCode::SessionInit => {
write!(f, "{:#04X} (SESSION_INIT)", self.to_u8().unwrap())
}
SessionOpCode::SessionDeinit => {
write!(f, "{:#04X} (SESSION_DEINIT)", self.to_u8().unwrap())
}
SessionOpCode::SessionStatusNtf => {
write!(f, "{:#04X} (SESSION_STATUS_NTF)", self.to_u8().unwrap())
}
SessionOpCode::SessionSetAppConfig => {
write!(f, "{:#04X} (SESSION_SET_APP_CONFIG)", self.to_u8().unwrap())
}
SessionOpCode::SessionGetAppConfig => {
write!(f, "{:#04X} (SESSION_GET_APP_CONFIG)", self.to_u8().unwrap())
}
SessionOpCode::SessionGetCount => {
write!(f, "{:#04X} (SESSION_GET_COUNT)", self.to_u8().unwrap())
}
SessionOpCode::SessionGetState => {
write!(f, "{:#04X} (SESSION_GET_STATE)", self.to_u8().unwrap())
}
SessionOpCode::SessionUpdateControllerMulticastList => write!(
f,
"{:#04X} (SESSION_UPDATE_CONTROLLER_MULTICAST_LIST)",
self.to_u8().unwrap()
),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum RangeOpCode {
RangeStart = 0x0,
RangeStop = 0x1,
RangeIntervalUpdateReq = 0x2,
RangeGetRangingCount = 0x3,
}
impl fmt::Display for RangeOpCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
RangeOpCode::RangeStart => write!(f, "{:#04X} (RANGE_START)", self.to_u8().unwrap()),
RangeOpCode::RangeStop => write!(f, "{:#04X} (RANGE_STOP)", self.to_u8().unwrap()),
RangeOpCode::RangeIntervalUpdateReq => write!(
f,
"{:#04X} (RANGE_INTERVAL_UPDATE_REQ)",
self.to_u8().unwrap()
),
RangeOpCode::RangeGetRangingCount => write!(
f,
"{:#04X} (RANGE_GET_RANGING_COUNT)",
self.to_u8().unwrap()
),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum AppDataOpCode {
AppDataTx = 0x0,
AppDataRx = 0x1,
}
impl fmt::Display for AppDataOpCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AppDataOpCode::AppDataTx => write!(f, "{:#04X} (APP_DATA_TX)", self.to_u8().unwrap()),
AppDataOpCode::AppDataRx => write!(f, "{:#04X} (APP_DATA_RX)", self.to_u8().unwrap()),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum PicaOpCode {
PicaInitDevice = 0x0,
PicaSetDevicePosition = 0x1,
PicaCreateBeacon = 0x2,
PicaSetBeaconPosition = 0x3,
PicaDestroyBeacon = 0x4,
}
impl fmt::Display for PicaOpCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PicaOpCode::PicaInitDevice => {
write!(f, "{:#04X} (PICA_INIT_DEVICE)", self.to_u8().unwrap())
}
PicaOpCode::PicaSetDevicePosition => write!(
f,
"{:#04X} (PICA_SET_DEVICE_POSITION)",
self.to_u8().unwrap()
),
PicaOpCode::PicaCreateBeacon => {
write!(f, "{:#04X} (PICA_CREATE_BEACON)", self.to_u8().unwrap())
}
PicaOpCode::PicaSetBeaconPosition => write!(
f,
"{:#04X} (PICA_SET_BEACON_POSITION)",
self.to_u8().unwrap()
),
PicaOpCode::PicaDestroyBeacon => {
write!(f, "{:#04X} (PICA_DESTROY_BEACON)", self.to_u8().unwrap())
}
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum AndroidOpCode {
AndroidGetPowerStats = 0x0,
AndroidSetCountryCode = 0x1,
}
impl fmt::Display for AndroidOpCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AndroidOpCode::AndroidGetPowerStats => write!(
f,
"{:#04X} (ANDROID_GET_POWER_STATS)",
self.to_u8().unwrap()
),
AndroidOpCode::AndroidSetCountryCode => write!(
f,
"{:#04X} (ANDROID_SET_COUNTRY_CODE)",
self.to_u8().unwrap()
),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum StatusCode {
UciStatusOk = 0x0,
UciStatusRejected = 0x1,
UciStatusFailed = 0x2,
UciStatusSyntaxError = 0x3,
UciStatusInvalidParam = 0x4,
UciStatusInvalidRange = 0x5,
UciStatusInvalidMsgSize = 0x6,
UciStatusUnknownGid = 0x7,
UciStatusUnknownOid = 0x8,
UciStatusReadOnly = 0x9,
UciStatusCommandRetry = 0xa,
UciStatusSessionNotExist = 0x11,
UciStatusSessionDuplicate = 0x12,
UciStatusSessionActive = 0x13,
UciStatusMaxSessionsExceeded = 0x14,
UciStatusSessionNotConfigured = 0x15,
UciStatusActiveSessionOngoing = 0x16,
UciStatusMulticastListFull = 0x17,
UciStatusAddressNotFound = 0x18,
UciStatusAddressAlreadyPresent = 0x19,
UciStatusRangingTxFailed = 0x20,
UciStatusRangingRxTimeout = 0x21,
UciStatusRangingRxPhyDecFailed = 0x22,
UciStatusRangingRxPhyToaFailed = 0x23,
UciStatusRangingRxPhyStsFailed = 0x24,
UciStatusRangingRxMacDecFailed = 0x25,
UciStatusRangingRxMacIeDecFailed = 0x26,
UciStatusRangingRxMacIeMissing = 0x27,
UciStatusDataMaxTxPsduSizeExceeded = 0x30,
UciStatusDataRxCrcError = 0x31,
UciStatusErrorCccSeBusy = 0x50,
UciStatusErrorCccLifecycle = 0x51,
}
impl fmt::Display for StatusCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
StatusCode::UciStatusOk => write!(f, "{:#04X} (UCI_STATUS_OK)", self.to_u8().unwrap()),
StatusCode::UciStatusRejected => {
write!(f, "{:#04X} (UCI_STATUS_REJECTED)", self.to_u8().unwrap())
}
StatusCode::UciStatusFailed => {
write!(f, "{:#04X} (UCI_STATUS_FAILED)", self.to_u8().unwrap())
}
StatusCode::UciStatusSyntaxError => write!(
f,
"{:#04X} (UCI_STATUS_SYNTAX_ERROR)",
self.to_u8().unwrap()
),
StatusCode::UciStatusInvalidParam => write!(
f,
"{:#04X} (UCI_STATUS_INVALID_PARAM)",
self.to_u8().unwrap()
),
StatusCode::UciStatusInvalidRange => write!(
f,
"{:#04X} (UCI_STATUS_INVALID_RANGE)",
self.to_u8().unwrap()
),
StatusCode::UciStatusInvalidMsgSize => write!(
f,
"{:#04X} (UCI_STATUS_INVALID_MSG_SIZE)",
self.to_u8().unwrap()
),
StatusCode::UciStatusUnknownGid => {
write!(f, "{:#04X} (UCI_STATUS_UNKNOWN_GID)", self.to_u8().unwrap())
}
StatusCode::UciStatusUnknownOid => {
write!(f, "{:#04X} (UCI_STATUS_UNKNOWN_OID)", self.to_u8().unwrap())
}
StatusCode::UciStatusReadOnly => {
write!(f, "{:#04X} (UCI_STATUS_READ_ONLY)", self.to_u8().unwrap())
}
StatusCode::UciStatusCommandRetry => write!(
f,
"{:#04X} (UCI_STATUS_COMMAND_RETRY)",
self.to_u8().unwrap()
),
StatusCode::UciStatusSessionNotExist => write!(
f,
"{:#04X} (UCI_STATUS_SESSION_NOT_EXIST)",
self.to_u8().unwrap()
),
StatusCode::UciStatusSessionDuplicate => write!(
f,
"{:#04X} (UCI_STATUS_SESSION_DUPLICATE)",
self.to_u8().unwrap()
),
StatusCode::UciStatusSessionActive => write!(
f,
"{:#04X} (UCI_STATUS_SESSION_ACTIVE)",
self.to_u8().unwrap()
),
StatusCode::UciStatusMaxSessionsExceeded => write!(
f,
"{:#04X} (UCI_STATUS_MAX_SESSIONS_EXCEEDED)",
self.to_u8().unwrap()
),
StatusCode::UciStatusSessionNotConfigured => write!(
f,
"{:#04X} (UCI_STATUS_SESSION_NOT_CONFIGURED)",
self.to_u8().unwrap()
),
StatusCode::UciStatusActiveSessionOngoing => write!(
f,
"{:#04X} (UCI_STATUS_ACTIVE_SESSION_ONGOING)",
self.to_u8().unwrap()
),
StatusCode::UciStatusMulticastListFull => write!(
f,
"{:#04X} (UCI_STATUS_MULTICAST_LIST_FULL)",
self.to_u8().unwrap()
),
StatusCode::UciStatusAddressNotFound => write!(
f,
"{:#04X} (UCI_STATUS_ADDRESS_NOT_FOUND)",
self.to_u8().unwrap()
),
StatusCode::UciStatusAddressAlreadyPresent => write!(
f,
"{:#04X} (UCI_STATUS_ADDRESS_ALREADY_PRESENT)",
self.to_u8().unwrap()
),
StatusCode::UciStatusRangingTxFailed => write!(
f,
"{:#04X} (UCI_STATUS_RANGING_TX_FAILED)",
self.to_u8().unwrap()
),
StatusCode::UciStatusRangingRxTimeout => write!(
f,
"{:#04X} (UCI_STATUS_RANGING_RX_TIMEOUT)",
self.to_u8().unwrap()
),
StatusCode::UciStatusRangingRxPhyDecFailed => write!(
f,
"{:#04X} (UCI_STATUS_RANGING_RX_PHY_DEC_FAILED)",
self.to_u8().unwrap()
),
StatusCode::UciStatusRangingRxPhyToaFailed => write!(
f,
"{:#04X} (UCI_STATUS_RANGING_RX_PHY_TOA_FAILED)",
self.to_u8().unwrap()
),
StatusCode::UciStatusRangingRxPhyStsFailed => write!(
f,
"{:#04X} (UCI_STATUS_RANGING_RX_PHY_STS_FAILED)",
self.to_u8().unwrap()
),
StatusCode::UciStatusRangingRxMacDecFailed => write!(
f,
"{:#04X} (UCI_STATUS_RANGING_RX_MAC_DEC_FAILED)",
self.to_u8().unwrap()
),
StatusCode::UciStatusRangingRxMacIeDecFailed => write!(
f,
"{:#04X} (UCI_STATUS_RANGING_RX_MAC_IE_DEC_FAILED)",
self.to_u8().unwrap()
),
StatusCode::UciStatusRangingRxMacIeMissing => write!(
f,
"{:#04X} (UCI_STATUS_RANGING_RX_MAC_IE_MISSING)",
self.to_u8().unwrap()
),
StatusCode::UciStatusDataMaxTxPsduSizeExceeded => write!(
f,
"{:#04X} (UCI_STATUS_DATA_MAX_TX_PSDU_SIZE_EXCEEDED)",
self.to_u8().unwrap()
),
StatusCode::UciStatusDataRxCrcError => write!(
f,
"{:#04X} (UCI_STATUS_DATA_RX_CRC_ERROR)",
self.to_u8().unwrap()
),
StatusCode::UciStatusErrorCccSeBusy => write!(
f,
"{:#04X} (UCI_STATUS_ERROR_CCC_SE_BUSY)",
self.to_u8().unwrap()
),
StatusCode::UciStatusErrorCccLifecycle => write!(
f,
"{:#04X} (UCI_STATUS_ERROR_CCC_LIFECYCLE)",
self.to_u8().unwrap()
),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum ResetConfig {
UwbsReset = 0x0,
}
impl fmt::Display for ResetConfig {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ResetConfig::UwbsReset => write!(f, "{:#04X} (UWBS_RESET)", self.to_u8().unwrap()),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum DeviceConfigId {
DeviceState = 0x0,
LowPowerMode = 0x1,
}
impl fmt::Display for DeviceConfigId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DeviceConfigId::DeviceState => {
write!(f, "{:#04X} (DEVICE_STATE)", self.to_u8().unwrap())
}
DeviceConfigId::LowPowerMode => {
write!(f, "{:#04X} (LOW_POWER_MODE)", self.to_u8().unwrap())
}
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum AppConfigTlvType {
DeviceType = 0x0,
RangingRoundUsage = 0x1,
StsConfig = 0x2,
MultiNodeMode = 0x3,
ChannelNumber = 0x4,
NoOfControlee = 0x5,
DeviceMacAddress = 0x6,
DstMacAddress = 0x7,
SlotDuration = 0x8,
RangingInterval = 0x9,
StsIndex = 0xa,
MacFcsType = 0xb,
RangingRoundControl = 0xc,
AoaResultReq = 0xd,
RngDataNtf = 0xe,
RngDataNtfProximityNear = 0xf,
RngDataNtfProximityFar = 0x10,
DeviceRole = 0x11,
RframeConfig = 0x12,
PreambleCodeIndex = 0x14,
SfdId = 0x15,
PsduDataRate = 0x16,
PreambleDuration = 0x17,
RangingTimeStruct = 0x1a,
SlotsPerRr = 0x1b,
TxAdaptivePayloadPower = 0x1c,
ResponderSlotIndex = 0x1e,
PrfMode = 0x1f,
ScheduledMode = 0x22,
KeyRotation = 0x23,
KeyRotationRate = 0x24,
SessionPriority = 0x25,
MacAddressMode = 0x26,
VendorId = 0x27,
StaticStsIv = 0x28,
NumberOfStsSegments = 0x29,
MaxRrRetry = 0x2a,
UwbInitiationTime = 0x2b,
HoppingMode = 0x2c,
BlockStrideLength = 0x2d,
ResultReportConfig = 0x2e,
InBandTerminationAttemptCount = 0x2f,
SubSessionId = 0x30,
BprfPhrDataRate = 0x31,
MaxNumberOfMeasurements = 0x32,
StsLength = 0x35,
CccHopModeKey = 0xa0,
CccUwbTime0 = 0xa1,
CccRangingProtocolVer = 0xa3,
CccUwbConfigId = 0xa4,
CccPulseshapeCombo = 0xa5,
CccUrskTtl = 0xa6,
NbOfRangeMeasurements = 0xe3,
NbOfAzimuthMeasurements = 0xe4,
NbOfElevationMeasurements = 0xe5,
}
impl fmt::Display for AppConfigTlvType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AppConfigTlvType::DeviceType => {
write!(f, "{:#04X} (DEVICE_TYPE)", self.to_u8().unwrap())
}
AppConfigTlvType::RangingRoundUsage => {
write!(f, "{:#04X} (RANGING_ROUND_USAGE)", self.to_u8().unwrap())
}
AppConfigTlvType::StsConfig => write!(f, "{:#04X} (STS_CONFIG)", self.to_u8().unwrap()),
AppConfigTlvType::MultiNodeMode => {
write!(f, "{:#04X} (MULTI_NODE_MODE)", self.to_u8().unwrap())
}
AppConfigTlvType::ChannelNumber => {
write!(f, "{:#04X} (CHANNEL_NUMBER)", self.to_u8().unwrap())
}
AppConfigTlvType::NoOfControlee => {
write!(f, "{:#04X} (NO_OF_CONTROLEE)", self.to_u8().unwrap())
}
AppConfigTlvType::DeviceMacAddress => {
write!(f, "{:#04X} (DEVICE_MAC_ADDRESS)", self.to_u8().unwrap())
}
AppConfigTlvType::DstMacAddress => {
write!(f, "{:#04X} (DST_MAC_ADDRESS)", self.to_u8().unwrap())
}
AppConfigTlvType::SlotDuration => {
write!(f, "{:#04X} (SLOT_DURATION)", self.to_u8().unwrap())
}
AppConfigTlvType::RangingInterval => {
write!(f, "{:#04X} (RANGING_INTERVAL)", self.to_u8().unwrap())
}
AppConfigTlvType::StsIndex => write!(f, "{:#04X} (STS_INDEX)", self.to_u8().unwrap()),
AppConfigTlvType::MacFcsType => {
write!(f, "{:#04X} (MAC_FCS_TYPE)", self.to_u8().unwrap())
}
AppConfigTlvType::RangingRoundControl => {
write!(f, "{:#04X} (RANGING_ROUND_CONTROL)", self.to_u8().unwrap())
}
AppConfigTlvType::AoaResultReq => {
write!(f, "{:#04X} (AOA_RESULT_REQ)", self.to_u8().unwrap())
}
AppConfigTlvType::RngDataNtf => {
write!(f, "{:#04X} (RNG_DATA_NTF)", self.to_u8().unwrap())
}
AppConfigTlvType::RngDataNtfProximityNear => write!(
f,
"{:#04X} (RNG_DATA_NTF_PROXIMITY_NEAR)",
self.to_u8().unwrap()
),
AppConfigTlvType::RngDataNtfProximityFar => write!(
f,
"{:#04X} (RNG_DATA_NTF_PROXIMITY_FAR)",
self.to_u8().unwrap()
),
AppConfigTlvType::DeviceRole => {
write!(f, "{:#04X} (DEVICE_ROLE)", self.to_u8().unwrap())
}
AppConfigTlvType::RframeConfig => {
write!(f, "{:#04X} (RFRAME_CONFIG)", self.to_u8().unwrap())
}
AppConfigTlvType::PreambleCodeIndex => {
write!(f, "{:#04X} (PREAMBLE_CODE_INDEX)", self.to_u8().unwrap())
}
AppConfigTlvType::SfdId => write!(f, "{:#04X} (SFD_ID)", self.to_u8().unwrap()),
AppConfigTlvType::PsduDataRate => {
write!(f, "{:#04X} (PSDU_DATA_RATE)", self.to_u8().unwrap())
}
AppConfigTlvType::PreambleDuration => {
write!(f, "{:#04X} (PREAMBLE_DURATION)", self.to_u8().unwrap())
}
AppConfigTlvType::RangingTimeStruct => {
write!(f, "{:#04X} (RANGING_TIME_STRUCT)", self.to_u8().unwrap())
}
AppConfigTlvType::SlotsPerRr => {
write!(f, "{:#04X} (SLOTS_PER_RR)", self.to_u8().unwrap())
}
AppConfigTlvType::TxAdaptivePayloadPower => write!(
f,
"{:#04X} (TX_ADAPTIVE_PAYLOAD_POWER)",
self.to_u8().unwrap()
),
AppConfigTlvType::ResponderSlotIndex => {
write!(f, "{:#04X} (RESPONDER_SLOT_INDEX)", self.to_u8().unwrap())
}
AppConfigTlvType::PrfMode => write!(f, "{:#04X} (PRF_MODE)", self.to_u8().unwrap()),
AppConfigTlvType::ScheduledMode => {
write!(f, "{:#04X} (SCHEDULED_MODE)", self.to_u8().unwrap())
}
AppConfigTlvType::KeyRotation => {
write!(f, "{:#04X} (KEY_ROTATION)", self.to_u8().unwrap())
}
AppConfigTlvType::KeyRotationRate => {
write!(f, "{:#04X} (KEY_ROTATION_RATE)", self.to_u8().unwrap())
}
AppConfigTlvType::SessionPriority => {
write!(f, "{:#04X} (SESSION_PRIORITY)", self.to_u8().unwrap())
}
AppConfigTlvType::MacAddressMode => {
write!(f, "{:#04X} (MAC_ADDRESS_MODE)", self.to_u8().unwrap())
}
AppConfigTlvType::VendorId => write!(f, "{:#04X} (VENDOR_ID)", self.to_u8().unwrap()),
AppConfigTlvType::StaticStsIv => {
write!(f, "{:#04X} (STATIC_STS_IV)", self.to_u8().unwrap())
}
AppConfigTlvType::NumberOfStsSegments => {
write!(f, "{:#04X} (NUMBER_OF_STS_SEGMENTS)", self.to_u8().unwrap())
}
AppConfigTlvType::MaxRrRetry => {
write!(f, "{:#04X} (MAX_RR_RETRY)", self.to_u8().unwrap())
}
AppConfigTlvType::UwbInitiationTime => {
write!(f, "{:#04X} (UWB_INITIATION_TIME)", self.to_u8().unwrap())
}
AppConfigTlvType::HoppingMode => {
write!(f, "{:#04X} (HOPPING_MODE)", self.to_u8().unwrap())
}
AppConfigTlvType::BlockStrideLength => {
write!(f, "{:#04X} (BLOCK_STRIDE_LENGTH)", self.to_u8().unwrap())
}
AppConfigTlvType::ResultReportConfig => {
write!(f, "{:#04X} (RESULT_REPORT_CONFIG)", self.to_u8().unwrap())
}
AppConfigTlvType::InBandTerminationAttemptCount => write!(
f,
"{:#04X} (IN_BAND_TERMINATION_ATTEMPT_COUNT)",
self.to_u8().unwrap()
),
AppConfigTlvType::SubSessionId => {
write!(f, "{:#04X} (SUB_SESSION_ID)", self.to_u8().unwrap())
}
AppConfigTlvType::BprfPhrDataRate => {
write!(f, "{:#04X} (BPRF_PHR_DATA_RATE)", self.to_u8().unwrap())
}
AppConfigTlvType::MaxNumberOfMeasurements => write!(
f,
"{:#04X} (MAX_NUMBER_OF_MEASUREMENTS)",
self.to_u8().unwrap()
),
AppConfigTlvType::StsLength => write!(f, "{:#04X} (STS_LENGTH)", self.to_u8().unwrap()),
AppConfigTlvType::CccHopModeKey => {
write!(f, "{:#04X} (CCC_HOP_MODE_KEY)", self.to_u8().unwrap())
}
AppConfigTlvType::CccUwbTime0 => {
write!(f, "{:#04X} (CCC_UWB_TIME0)", self.to_u8().unwrap())
}
AppConfigTlvType::CccRangingProtocolVer => write!(
f,
"{:#04X} (CCC_RANGING_PROTOCOL_VER)",
self.to_u8().unwrap()
),
AppConfigTlvType::CccUwbConfigId => {
write!(f, "{:#04X} (CCC_UWB_CONFIG_ID)", self.to_u8().unwrap())
}
AppConfigTlvType::CccPulseshapeCombo => {
write!(f, "{:#04X} (CCC_PULSESHAPE_COMBO)", self.to_u8().unwrap())
}
AppConfigTlvType::CccUrskTtl => {
write!(f, "{:#04X} (CCC_URSK_TTL)", self.to_u8().unwrap())
}
AppConfigTlvType::NbOfRangeMeasurements => write!(
f,
"{:#04X} (NB_OF_RANGE_MEASUREMENTS)",
self.to_u8().unwrap()
),
AppConfigTlvType::NbOfAzimuthMeasurements => write!(
f,
"{:#04X} (NB_OF_AZIMUTH_MEASUREMENTS)",
self.to_u8().unwrap()
),
AppConfigTlvType::NbOfElevationMeasurements => write!(
f,
"{:#04X} (NB_OF_ELEVATION_MEASUREMENTS)",
self.to_u8().unwrap()
),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum CapTlvType {
SupportedFiraPhyVersionRange = 0x0,
SupportedFiraMacVersionRange = 0x1,
SupportedDeviceRoles = 0x2,
SupportedRangingMethod = 0x3,
SupportedStsConfig = 0x4,
SupportedMultiNodeModes = 0x5,
SupportedRangingTimeStruct = 0x6,
SupportedScheduledMode = 0x7,
SupportedHoppingMode = 0x8,
SupportedBlockStriding = 0x9,
SupportedUwbInitiationTime = 0xa,
SupportedChannels = 0xb,
SupportedRframeConfig = 0xc,
SupportedCcConstraintLength = 0xd,
SupportedBprfParameterSets = 0xe,
SupportedHprfParameterSets = 0xf,
SupportedAoa = 0x10,
SupportedExtendedMacAddress = 0x11,
CccSupportedChapsPerSlot = 0xa0,
CccSupportedSyncCodes = 0xa1,
CccSupportedHoppingConfigModesAndSequences = 0xa2,
CccSupportedChannels = 0xa3,
CccSupportedVersions = 0xa4,
CccSupportedUwbConfigs = 0xa5,
CccSupportedPulseShapeCombos = 0xa6,
CccSupportedRanMultiplier = 0xa7,
SupportedPowerStats = 0xc0,
SupportedAoaResultReqAntennaInterleaving = 0xe3,
}
impl fmt::Display for CapTlvType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CapTlvType::SupportedFiraPhyVersionRange => write!(
f,
"{:#04X} (SUPPORTED_FIRA_PHY_VERSION_RANGE)",
self.to_u8().unwrap()
),
CapTlvType::SupportedFiraMacVersionRange => write!(
f,
"{:#04X} (SUPPORTED_FIRA_MAC_VERSION_RANGE)",
self.to_u8().unwrap()
),
CapTlvType::SupportedDeviceRoles => {
write!(f, "{:#04X} (SUPPORTED_DEVICE_ROLES)", self.to_u8().unwrap())
}
CapTlvType::SupportedRangingMethod => write!(
f,
"{:#04X} (SUPPORTED_RANGING_METHOD)",
self.to_u8().unwrap()
),
CapTlvType::SupportedStsConfig => {
write!(f, "{:#04X} (SUPPORTED_STS_CONFIG)", self.to_u8().unwrap())
}
CapTlvType::SupportedMultiNodeModes => write!(
f,
"{:#04X} (SUPPORTED_MULTI_NODE_MODES)",
self.to_u8().unwrap()
),
CapTlvType::SupportedRangingTimeStruct => write!(
f,
"{:#04X} (SUPPORTED_RANGING_TIME_STRUCT)",
self.to_u8().unwrap()
),
CapTlvType::SupportedScheduledMode => write!(
f,
"{:#04X} (SUPPORTED_SCHEDULED_MODE)",
self.to_u8().unwrap()
),
CapTlvType::SupportedHoppingMode => {
write!(f, "{:#04X} (SUPPORTED_HOPPING_MODE)", self.to_u8().unwrap())
}
CapTlvType::SupportedBlockStriding => write!(
f,
"{:#04X} (SUPPORTED_BLOCK_STRIDING)",
self.to_u8().unwrap()
),
CapTlvType::SupportedUwbInitiationTime => write!(
f,
"{:#04X} (SUPPORTED_UWB_INITIATION_TIME)",
self.to_u8().unwrap()
),
CapTlvType::SupportedChannels => {
write!(f, "{:#04X} (SUPPORTED_CHANNELS)", self.to_u8().unwrap())
}
CapTlvType::SupportedRframeConfig => write!(
f,
"{:#04X} (SUPPORTED_RFRAME_CONFIG)",
self.to_u8().unwrap()
),
CapTlvType::SupportedCcConstraintLength => write!(
f,
"{:#04X} (SUPPORTED_CC_CONSTRAINT_LENGTH)",
self.to_u8().unwrap()
),
CapTlvType::SupportedBprfParameterSets => write!(
f,
"{:#04X} (SUPPORTED_BPRF_PARAMETER_SETS)",
self.to_u8().unwrap()
),
CapTlvType::SupportedHprfParameterSets => write!(
f,
"{:#04X} (SUPPORTED_HPRF_PARAMETER_SETS)",
self.to_u8().unwrap()
),
CapTlvType::SupportedAoa => write!(f, "{:#04X} (SUPPORTED_AOA)", self.to_u8().unwrap()),
CapTlvType::SupportedExtendedMacAddress => write!(
f,
"{:#04X} (SUPPORTED_EXTENDED_MAC_ADDRESS)",
self.to_u8().unwrap()
),
CapTlvType::CccSupportedChapsPerSlot => write!(
f,
"{:#04X} (CCC_SUPPORTED_CHAPS_PER_SLOT)",
self.to_u8().unwrap()
),
CapTlvType::CccSupportedSyncCodes => write!(
f,
"{:#04X} (CCC_SUPPORTED_SYNC_CODES)",
self.to_u8().unwrap()
),
CapTlvType::CccSupportedHoppingConfigModesAndSequences => write!(
f,
"{:#04X} (CCC_SUPPORTED_HOPPING_CONFIG_MODES_AND_SEQUENCES)",
self.to_u8().unwrap()
),
CapTlvType::CccSupportedChannels => {
write!(f, "{:#04X} (CCC_SUPPORTED_CHANNELS)", self.to_u8().unwrap())
}
CapTlvType::CccSupportedVersions => {
write!(f, "{:#04X} (CCC_SUPPORTED_VERSIONS)", self.to_u8().unwrap())
}
CapTlvType::CccSupportedUwbConfigs => write!(
f,
"{:#04X} (CCC_SUPPORTED_UWB_CONFIGS)",
self.to_u8().unwrap()
),
CapTlvType::CccSupportedPulseShapeCombos => write!(
f,
"{:#04X} (CCC_SUPPORTED_PULSE_SHAPE_COMBOS)",
self.to_u8().unwrap()
),
CapTlvType::CccSupportedRanMultiplier => write!(
f,
"{:#04X} (CCC_SUPPORTED_RAN_MULTIPLIER)",
self.to_u8().unwrap()
),
CapTlvType::SupportedPowerStats => {
write!(f, "{:#04X} (SUPPORTED_POWER_STATS)", self.to_u8().unwrap())
}
CapTlvType::SupportedAoaResultReqAntennaInterleaving => write!(
f,
"{:#04X} (SUPPORTED_AOA_RESULT_REQ_ANTENNA_INTERLEAVING)",
self.to_u8().unwrap()
),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum AoaResultReqType {
AoaDisable = 0x0,
AoaEnable = 0x1,
AoaEnableAzimuth = 0x2,
AoaEnableElevation = 0x3,
AoaEnableInterleaved = 0xf0,
}
impl fmt::Display for AoaResultReqType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AoaResultReqType::AoaDisable => {
write!(f, "{:#04X} (AOA_DISABLE)", self.to_u8().unwrap())
}
AoaResultReqType::AoaEnable => write!(f, "{:#04X} (AOA_ENABLE)", self.to_u8().unwrap()),
AoaResultReqType::AoaEnableAzimuth => {
write!(f, "{:#04X} (AOA_ENABLE_AZIMUTH)", self.to_u8().unwrap())
}
AoaResultReqType::AoaEnableElevation => {
write!(f, "{:#04X} (AOA_ENABLE_ELEVATION)", self.to_u8().unwrap())
}
AoaResultReqType::AoaEnableInterleaved => {
write!(f, "{:#04X} (AOA_ENABLE_INTERLEAVED)", self.to_u8().unwrap())
}
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum DeviceState {
DeviceStateReady = 0x1,
DeviceStateActive = 0x2,
DeviceStateError = 0xff,
}
impl fmt::Display for DeviceState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DeviceState::DeviceStateReady => {
write!(f, "{:#04X} (DEVICE_STATE_READY)", self.to_u8().unwrap())
}
DeviceState::DeviceStateActive => {
write!(f, "{:#04X} (DEVICE_STATE_ACTIVE)", self.to_u8().unwrap())
}
DeviceState::DeviceStateError => {
write!(f, "{:#04X} (DEVICE_STATE_ERROR)", self.to_u8().unwrap())
}
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum SessionState {
SessionStateInit = 0x0,
SessionStateDeinit = 0x1,
SessionStateActive = 0x2,
SessionStateIdle = 0x3,
}
impl fmt::Display for SessionState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
SessionState::SessionStateInit => {
write!(f, "{:#04X} (SESSION_STATE_INIT)", self.to_u8().unwrap())
}
SessionState::SessionStateDeinit => {
write!(f, "{:#04X} (SESSION_STATE_DEINIT)", self.to_u8().unwrap())
}
SessionState::SessionStateActive => {
write!(f, "{:#04X} (SESSION_STATE_ACTIVE)", self.to_u8().unwrap())
}
SessionState::SessionStateIdle => {
write!(f, "{:#04X} (SESSION_STATE_IDLE)", self.to_u8().unwrap())
}
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum ReasonCode {
StateChangeWithSessionManagementCommands = 0x0,
MaxRangingRoundRetryCountReached = 0x1,
MaxNumberOfMeasurementsReached = 0x2,
ErrorSlotLengthNotSupported = 0x20,
ErrorInsufficientSlotsPerRr = 0x21,
ErrorMacAddressModeNotSupported = 0x22,
ErrorInvalidRangingInterval = 0x23,
ErrorInvalidStsConfig = 0x24,
ErrorInvalidRframeConfig = 0x25,
}
impl fmt::Display for ReasonCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ReasonCode::StateChangeWithSessionManagementCommands => write!(
f,
"{:#04X} (STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS)",
self.to_u8().unwrap()
),
ReasonCode::MaxRangingRoundRetryCountReached => write!(
f,
"{:#04X} (MAX_RANGING_ROUND_RETRY_COUNT_REACHED)",
self.to_u8().unwrap()
),
ReasonCode::MaxNumberOfMeasurementsReached => write!(
f,
"{:#04X} (MAX_NUMBER_OF_MEASUREMENTS_REACHED)",
self.to_u8().unwrap()
),
ReasonCode::ErrorSlotLengthNotSupported => write!(
f,
"{:#04X} (ERROR_SLOT_LENGTH_NOT_SUPPORTED)",
self.to_u8().unwrap()
),
ReasonCode::ErrorInsufficientSlotsPerRr => write!(
f,
"{:#04X} (ERROR_INSUFFICIENT_SLOTS_PER_RR)",
self.to_u8().unwrap()
),
ReasonCode::ErrorMacAddressModeNotSupported => write!(
f,
"{:#04X} (ERROR_MAC_ADDRESS_MODE_NOT_SUPPORTED)",
self.to_u8().unwrap()
),
ReasonCode::ErrorInvalidRangingInterval => write!(
f,
"{:#04X} (ERROR_INVALID_RANGING_INTERVAL)",
self.to_u8().unwrap()
),
ReasonCode::ErrorInvalidStsConfig => write!(
f,
"{:#04X} (ERROR_INVALID_STS_CONFIG)",
self.to_u8().unwrap()
),
ReasonCode::ErrorInvalidRframeConfig => write!(
f,
"{:#04X} (ERROR_INVALID_RFRAME_CONFIG)",
self.to_u8().unwrap()
),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum MulticastUpdateStatusCode {
StatusOkMulticastListUpdate = 0x0,
StatusErrorMulticastListFull = 0x1,
StatusErrorKeyFetchFail = 0x2,
StatusErrorSubSessionIdNotFound = 0x3,
}
impl fmt::Display for MulticastUpdateStatusCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
MulticastUpdateStatusCode::StatusOkMulticastListUpdate => write!(
f,
"{:#04X} (STATUS_OK_MULTICAST_LIST_UPDATE)",
self.to_u8().unwrap()
),
MulticastUpdateStatusCode::StatusErrorMulticastListFull => write!(
f,
"{:#04X} (STATUS_ERROR_MULTICAST_LIST_FULL)",
self.to_u8().unwrap()
),
MulticastUpdateStatusCode::StatusErrorKeyFetchFail => write!(
f,
"{:#04X} (STATUS_ERROR_KEY_FETCH_FAIL)",
self.to_u8().unwrap()
),
MulticastUpdateStatusCode::StatusErrorSubSessionIdNotFound => write!(
f,
"{:#04X} (STATUS_ERROR_SUB_SESSION_ID_NOT_FOUND)",
self.to_u8().unwrap()
),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum MacAddressIndicator {
ShortAddress = 0x0,
ExtendedAddress = 0x1,
}
impl fmt::Display for MacAddressIndicator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
MacAddressIndicator::ShortAddress => {
write!(f, "{:#04X} (SHORT_ADDRESS)", self.to_u8().unwrap())
}
MacAddressIndicator::ExtendedAddress => {
write!(f, "{:#04X} (EXTENDED_ADDRESS)", self.to_u8().unwrap())
}
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum SessionType {
FiraRangingSession = 0x0,
FiraDataTransfer = 0x1,
Ccc = 0xa0,
}
impl fmt::Display for SessionType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
SessionType::FiraRangingSession => {
write!(f, "{:#04X} (FIRA_RANGING_SESSION)", self.to_u8().unwrap())
}
SessionType::FiraDataTransfer => {
write!(f, "{:#04X} (FIRA_DATA_TRANSFER)", self.to_u8().unwrap())
}
SessionType::Ccc => write!(f, "{:#04X} (CCC)", self.to_u8().unwrap()),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum MessageType {
Command = 0x1,
Response = 0x2,
Notification = 0x3,
}
impl fmt::Display for MessageType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
MessageType::Command => write!(f, "{:#04X} (COMMAND)", self.to_u8().unwrap()),
MessageType::Response => write!(f, "{:#04X} (RESPONSE)", self.to_u8().unwrap()),
MessageType::Notification => write!(f, "{:#04X} (NOTIFICATION)", self.to_u8().unwrap()),
}
}
}
#[derive(FromPrimitive, ToPrimitive, Debug, Hash, Eq, PartialEq, Clone, Copy)]
#[repr(u64)]
pub enum RangingMeasurementType {
OneWay = 0x0,
TwoWay = 0x1,
}
impl fmt::Display for RangingMeasurementType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
RangingMeasurementType::OneWay => write!(f, "{:#04X} (ONE_WAY)", self.to_u8().unwrap()),
RangingMeasurementType::TwoWay => write!(f, "{:#04X} (TWO_WAY)", self.to_u8().unwrap()),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct CapTlv {
pub t: CapTlvType,
pub v: Vec<u8>,
}
impl CapTlv {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 2 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 1 {
return Err(Error::InvalidLengthError {
obj: "CapTlv".to_string(),
field: "t".to_string(),
wanted: 1,
got: bytes.len(),
});
}
let t = u8::from_le_bytes([bytes[0]]);
let t = CapTlvType::from_u8(t).ok_or_else(|| Error::InvalidEnumValueError {
obj: "CapTlv".to_string(),
field: "t".to_string(),
value: t as u64,
type_: "CapTlvType".to_string(),
})?;
if bytes.len() < 2 {
return Err(Error::InvalidLengthError {
obj: "CapTlv".to_string(),
field: "v_count".to_string(),
wanted: 2,
got: bytes.len(),
});
}
let v_count = u8::from_le_bytes([bytes[1]]);
let want_ = 2 + ((v_count as usize) * 1);
if bytes.len() < want_ {
return Err(Error::InvalidLengthError {
obj: "CapTlv".to_string(),
field: "v".to_string(),
wanted: want_,
got: bytes.len(),
});
}
let v: Vec<u8> = bytes[2..2 + ((v_count as usize) * 1)]
.to_vec()
.chunks_exact(1)
.into_iter()
.map(|i| u8::from_le_bytes([i[0]]))
.collect();
Ok(Self { t, v })
}
fn write_to(&self, buffer: &mut [u8]) {
let t = self.t.to_u8().unwrap();
buffer[0..1].copy_from_slice(&t.to_le_bytes()[0..1]);
buffer[1..2].copy_from_slice(&(self.v.len() as u8).to_le_bytes());
for (i, e) in self.v.iter().enumerate() {
buffer[2 + i..2 + i + 1].copy_from_slice(&e.to_le_bytes())
}
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 2;
let ret = ret + (self.v.len() * ((/* Bits: */8 + /* Dynamic: */ 0) / 8));
ret
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct DeviceParameter {
pub id: u8,
pub value: Vec<u8>,
}
impl DeviceParameter {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 2 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 1 {
return Err(Error::InvalidLengthError {
obj: "DeviceParameter".to_string(),
field: "id".to_string(),
wanted: 1,
got: bytes.len(),
});
}
let id = u8::from_le_bytes([bytes[0]]);
if bytes.len() < 2 {
return Err(Error::InvalidLengthError {
obj: "DeviceParameter".to_string(),
field: "value_count".to_string(),
wanted: 2,
got: bytes.len(),
});
}
let value_count = u8::from_le_bytes([bytes[1]]);
let want_ = 2 + ((value_count as usize) * 1);
if bytes.len() < want_ {
return Err(Error::InvalidLengthError {
obj: "DeviceParameter".to_string(),
field: "value".to_string(),
wanted: want_,
got: bytes.len(),
});
}
let value: Vec<u8> = bytes[2..2 + ((value_count as usize) * 1)]
.to_vec()
.chunks_exact(1)
.into_iter()
.map(|i| u8::from_le_bytes([i[0]]))
.collect();
Ok(Self { id, value })
}
fn write_to(&self, buffer: &mut [u8]) {
let id = self.id;
buffer[0..1].copy_from_slice(&id.to_le_bytes()[0..1]);
buffer[1..2].copy_from_slice(&(self.value.len() as u8).to_le_bytes());
for (i, e) in self.value.iter().enumerate() {
buffer[2 + i..2 + i + 1].copy_from_slice(&e.to_le_bytes())
}
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 2;
let ret = ret + (self.value.len() * ((/* Bits: */8 + /* Dynamic: */ 0) / 8));
ret
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct DeviceConfigStatus {
pub parameter_id: u8,
pub status: StatusCode,
}
impl DeviceConfigStatus {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 2 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 1 {
return Err(Error::InvalidLengthError {
obj: "DeviceConfigStatus".to_string(),
field: "parameter_id".to_string(),
wanted: 1,
got: bytes.len(),
});
}
let parameter_id = u8::from_le_bytes([bytes[0]]);
if bytes.len() < 2 {
return Err(Error::InvalidLengthError {
obj: "DeviceConfigStatus".to_string(),
field: "status".to_string(),
wanted: 2,
got: bytes.len(),
});
}
let status = u8::from_le_bytes([bytes[1]]);
let status = StatusCode::from_u8(status).ok_or_else(|| Error::InvalidEnumValueError {
obj: "DeviceConfigStatus".to_string(),
field: "status".to_string(),
value: status as u64,
type_: "StatusCode".to_string(),
})?;
Ok(Self {
parameter_id,
status,
})
}
fn write_to(&self, buffer: &mut [u8]) {
let parameter_id = self.parameter_id;
buffer[0..1].copy_from_slice(&parameter_id.to_le_bytes()[0..1]);
let status = self.status.to_u8().unwrap();
buffer[1..2].copy_from_slice(&status.to_le_bytes()[0..1]);
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 2;
ret
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct AppConfigParameter {
pub id: u8,
pub value: Vec<u8>,
}
impl AppConfigParameter {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 2 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 1 {
return Err(Error::InvalidLengthError {
obj: "AppConfigParameter".to_string(),
field: "id".to_string(),
wanted: 1,
got: bytes.len(),
});
}
let id = u8::from_le_bytes([bytes[0]]);
if bytes.len() < 2 {
return Err(Error::InvalidLengthError {
obj: "AppConfigParameter".to_string(),
field: "value_count".to_string(),
wanted: 2,
got: bytes.len(),
});
}
let value_count = u8::from_le_bytes([bytes[1]]);
let want_ = 2 + ((value_count as usize) * 1);
if bytes.len() < want_ {
return Err(Error::InvalidLengthError {
obj: "AppConfigParameter".to_string(),
field: "value".to_string(),
wanted: want_,
got: bytes.len(),
});
}
let value: Vec<u8> = bytes[2..2 + ((value_count as usize) * 1)]
.to_vec()
.chunks_exact(1)
.into_iter()
.map(|i| u8::from_le_bytes([i[0]]))
.collect();
Ok(Self { id, value })
}
fn write_to(&self, buffer: &mut [u8]) {
let id = self.id;
buffer[0..1].copy_from_slice(&id.to_le_bytes()[0..1]);
buffer[1..2].copy_from_slice(&(self.value.len() as u8).to_le_bytes());
for (i, e) in self.value.iter().enumerate() {
buffer[2 + i..2 + i + 1].copy_from_slice(&e.to_le_bytes())
}
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 2;
let ret = ret + (self.value.len() * ((/* Bits: */8 + /* Dynamic: */ 0) / 8));
ret
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct AppConfigStatus {
pub config_id: u8,
pub status: StatusCode,
}
impl AppConfigStatus {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 2 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 1 {
return Err(Error::InvalidLengthError {
obj: "AppConfigStatus".to_string(),
field: "config_id".to_string(),
wanted: 1,
got: bytes.len(),
});
}
let config_id = u8::from_le_bytes([bytes[0]]);
if bytes.len() < 2 {
return Err(Error::InvalidLengthError {
obj: "AppConfigStatus".to_string(),
field: "status".to_string(),
wanted: 2,
got: bytes.len(),
});
}
let status = u8::from_le_bytes([bytes[1]]);
let status = StatusCode::from_u8(status).ok_or_else(|| Error::InvalidEnumValueError {
obj: "AppConfigStatus".to_string(),
field: "status".to_string(),
value: status as u64,
type_: "StatusCode".to_string(),
})?;
Ok(Self { config_id, status })
}
fn write_to(&self, buffer: &mut [u8]) {
let config_id = self.config_id;
buffer[0..1].copy_from_slice(&config_id.to_le_bytes()[0..1]);
let status = self.status.to_u8().unwrap();
buffer[1..2].copy_from_slice(&status.to_le_bytes()[0..1]);
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 2;
ret
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Controlee {
pub short_address: u16,
pub subsession_id: u32,
}
impl Controlee {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 6 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 2 {
return Err(Error::InvalidLengthError {
obj: "Controlee".to_string(),
field: "short_address".to_string(),
wanted: 2,
got: bytes.len(),
});
}
let short_address = u16::from_le_bytes([bytes[0], bytes[1]]);
if bytes.len() < 6 {
return Err(Error::InvalidLengthError {
obj: "Controlee".to_string(),
field: "subsession_id".to_string(),
wanted: 6,
got: bytes.len(),
});
}
let subsession_id = u32::from_le_bytes([bytes[2], bytes[3], bytes[4], bytes[5]]);
Ok(Self {
short_address,
subsession_id,
})
}
fn write_to(&self, buffer: &mut [u8]) {
let short_address = self.short_address;
buffer[0..2].copy_from_slice(&short_address.to_le_bytes()[0..2]);
let subsession_id = self.subsession_id;
buffer[2..6].copy_from_slice(&subsession_id.to_le_bytes()[0..4]);
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 6;
ret
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ControleeStatus {
pub mac_address: u16,
pub subsession_id: u32,
pub status: u8,
}
impl ControleeStatus {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 7 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 2 {
return Err(Error::InvalidLengthError {
obj: "ControleeStatus".to_string(),
field: "mac_address".to_string(),
wanted: 2,
got: bytes.len(),
});
}
let mac_address = u16::from_le_bytes([bytes[0], bytes[1]]);
if bytes.len() < 6 {
return Err(Error::InvalidLengthError {
obj: "ControleeStatus".to_string(),
field: "subsession_id".to_string(),
wanted: 6,
got: bytes.len(),
});
}
let subsession_id = u32::from_le_bytes([bytes[2], bytes[3], bytes[4], bytes[5]]);
if bytes.len() < 7 {
return Err(Error::InvalidLengthError {
obj: "ControleeStatus".to_string(),
field: "status".to_string(),
wanted: 7,
got: bytes.len(),
});
}
let status = u8::from_le_bytes([bytes[6]]);
Ok(Self {
mac_address,
subsession_id,
status,
})
}
fn write_to(&self, buffer: &mut [u8]) {
let mac_address = self.mac_address;
buffer[0..2].copy_from_slice(&mac_address.to_le_bytes()[0..2]);
let subsession_id = self.subsession_id;
buffer[2..6].copy_from_slice(&subsession_id.to_le_bytes()[0..4]);
let status = self.status;
buffer[6..7].copy_from_slice(&status.to_le_bytes()[0..1]);
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 7;
ret
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ShortAddressTwoWayRangingMeasurement {
pub mac_address: u16,
pub status: StatusCode,
pub nlos: u8,
pub distance: u16,
pub aoa_azimuth: u16,
pub aoa_azimuth_fom: u8,
pub aoa_elevation: u16,
pub aoa_elevation_fom: u8,
pub aoa_destination_azimuth: u16,
pub aoa_destination_azimuth_fom: u8,
pub aoa_destination_elevation: u16,
pub aoa_destination_elevation_fom: u8,
pub slot_index: u8,
}
impl ShortAddressTwoWayRangingMeasurement {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 31 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 2 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "mac_address".to_string(),
wanted: 2,
got: bytes.len(),
});
}
let mac_address = u16::from_le_bytes([bytes[0], bytes[1]]);
if bytes.len() < 3 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "status".to_string(),
wanted: 3,
got: bytes.len(),
});
}
let status = u8::from_le_bytes([bytes[2]]);
let status = StatusCode::from_u8(status).ok_or_else(|| Error::InvalidEnumValueError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "status".to_string(),
value: status as u64,
type_: "StatusCode".to_string(),
})?;
if bytes.len() < 4 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "nlos".to_string(),
wanted: 4,
got: bytes.len(),
});
}
let nlos = u8::from_le_bytes([bytes[3]]);
if bytes.len() < 6 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "distance".to_string(),
wanted: 6,
got: bytes.len(),
});
}
let distance = u16::from_le_bytes([bytes[4], bytes[5]]);
if bytes.len() < 8 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_azimuth".to_string(),
wanted: 8,
got: bytes.len(),
});
}
let aoa_azimuth = u16::from_le_bytes([bytes[6], bytes[7]]);
if bytes.len() < 9 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_azimuth_fom".to_string(),
wanted: 9,
got: bytes.len(),
});
}
let aoa_azimuth_fom = u8::from_le_bytes([bytes[8]]);
if bytes.len() < 11 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_elevation".to_string(),
wanted: 11,
got: bytes.len(),
});
}
let aoa_elevation = u16::from_le_bytes([bytes[9], bytes[10]]);
if bytes.len() < 12 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_elevation_fom".to_string(),
wanted: 12,
got: bytes.len(),
});
}
let aoa_elevation_fom = u8::from_le_bytes([bytes[11]]);
if bytes.len() < 14 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_destination_azimuth".to_string(),
wanted: 14,
got: bytes.len(),
});
}
let aoa_destination_azimuth = u16::from_le_bytes([bytes[12], bytes[13]]);
if bytes.len() < 15 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_destination_azimuth_fom".to_string(),
wanted: 15,
got: bytes.len(),
});
}
let aoa_destination_azimuth_fom = u8::from_le_bytes([bytes[14]]);
if bytes.len() < 17 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_destination_elevation".to_string(),
wanted: 17,
got: bytes.len(),
});
}
let aoa_destination_elevation = u16::from_le_bytes([bytes[15], bytes[16]]);
if bytes.len() < 18 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_destination_elevation_fom".to_string(),
wanted: 18,
got: bytes.len(),
});
}
let aoa_destination_elevation_fom = u8::from_le_bytes([bytes[17]]);
if bytes.len() < 19 {
return Err(Error::InvalidLengthError {
obj: "ShortAddressTwoWayRangingMeasurement".to_string(),
field: "slot_index".to_string(),
wanted: 19,
got: bytes.len(),
});
}
let slot_index = u8::from_le_bytes([bytes[18]]);
Ok(Self {
mac_address,
status,
nlos,
distance,
aoa_azimuth,
aoa_azimuth_fom,
aoa_elevation,
aoa_elevation_fom,
aoa_destination_azimuth,
aoa_destination_azimuth_fom,
aoa_destination_elevation,
aoa_destination_elevation_fom,
slot_index,
})
}
fn write_to(&self, buffer: &mut [u8]) {
let mac_address = self.mac_address;
buffer[0..2].copy_from_slice(&mac_address.to_le_bytes()[0..2]);
let status = self.status.to_u8().unwrap();
buffer[2..3].copy_from_slice(&status.to_le_bytes()[0..1]);
let nlos = self.nlos;
buffer[3..4].copy_from_slice(&nlos.to_le_bytes()[0..1]);
let distance = self.distance;
buffer[4..6].copy_from_slice(&distance.to_le_bytes()[0..2]);
let aoa_azimuth = self.aoa_azimuth;
buffer[6..8].copy_from_slice(&aoa_azimuth.to_le_bytes()[0..2]);
let aoa_azimuth_fom = self.aoa_azimuth_fom;
buffer[8..9].copy_from_slice(&aoa_azimuth_fom.to_le_bytes()[0..1]);
let aoa_elevation = self.aoa_elevation;
buffer[9..11].copy_from_slice(&aoa_elevation.to_le_bytes()[0..2]);
let aoa_elevation_fom = self.aoa_elevation_fom;
buffer[11..12].copy_from_slice(&aoa_elevation_fom.to_le_bytes()[0..1]);
let aoa_destination_azimuth = self.aoa_destination_azimuth;
buffer[12..14].copy_from_slice(&aoa_destination_azimuth.to_le_bytes()[0..2]);
let aoa_destination_azimuth_fom = self.aoa_destination_azimuth_fom;
buffer[14..15].copy_from_slice(&aoa_destination_azimuth_fom.to_le_bytes()[0..1]);
let aoa_destination_elevation = self.aoa_destination_elevation;
buffer[15..17].copy_from_slice(&aoa_destination_elevation.to_le_bytes()[0..2]);
let aoa_destination_elevation_fom = self.aoa_destination_elevation_fom;
buffer[17..18].copy_from_slice(&aoa_destination_elevation_fom.to_le_bytes()[0..1]);
let slot_index = self.slot_index;
buffer[18..19].copy_from_slice(&slot_index.to_le_bytes()[0..1]);
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 31;
ret
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ExtendedAddressTwoWayRangingMeasurement {
pub mac_address: u64,
pub status: StatusCode,
pub nlos: u8,
pub distance: u16,
pub aoa_azimuth: u16,
pub aoa_azimuth_fom: u8,
pub aoa_elevation: u16,
pub aoa_elevation_fom: u8,
pub aoa_destination_azimuth: u16,
pub aoa_destination_azimuth_fom: u8,
pub aoa_destination_elevation: u16,
pub aoa_destination_elevation_fom: u8,
pub slot_index: u8,
}
impl ExtendedAddressTwoWayRangingMeasurement {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 31 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 8 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "mac_address".to_string(),
wanted: 8,
got: bytes.len(),
});
}
let mac_address = u64::from_le_bytes([
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
]);
if bytes.len() < 9 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "status".to_string(),
wanted: 9,
got: bytes.len(),
});
}
let status = u8::from_le_bytes([bytes[8]]);
let status = StatusCode::from_u8(status).ok_or_else(|| Error::InvalidEnumValueError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "status".to_string(),
value: status as u64,
type_: "StatusCode".to_string(),
})?;
if bytes.len() < 10 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "nlos".to_string(),
wanted: 10,
got: bytes.len(),
});
}
let nlos = u8::from_le_bytes([bytes[9]]);
if bytes.len() < 12 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "distance".to_string(),
wanted: 12,
got: bytes.len(),
});
}
let distance = u16::from_le_bytes([bytes[10], bytes[11]]);
if bytes.len() < 14 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_azimuth".to_string(),
wanted: 14,
got: bytes.len(),
});
}
let aoa_azimuth = u16::from_le_bytes([bytes[12], bytes[13]]);
if bytes.len() < 15 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_azimuth_fom".to_string(),
wanted: 15,
got: bytes.len(),
});
}
let aoa_azimuth_fom = u8::from_le_bytes([bytes[14]]);
if bytes.len() < 17 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_elevation".to_string(),
wanted: 17,
got: bytes.len(),
});
}
let aoa_elevation = u16::from_le_bytes([bytes[15], bytes[16]]);
if bytes.len() < 18 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_elevation_fom".to_string(),
wanted: 18,
got: bytes.len(),
});
}
let aoa_elevation_fom = u8::from_le_bytes([bytes[17]]);
if bytes.len() < 20 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_destination_azimuth".to_string(),
wanted: 20,
got: bytes.len(),
});
}
let aoa_destination_azimuth = u16::from_le_bytes([bytes[18], bytes[19]]);
if bytes.len() < 21 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_destination_azimuth_fom".to_string(),
wanted: 21,
got: bytes.len(),
});
}
let aoa_destination_azimuth_fom = u8::from_le_bytes([bytes[20]]);
if bytes.len() < 23 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_destination_elevation".to_string(),
wanted: 23,
got: bytes.len(),
});
}
let aoa_destination_elevation = u16::from_le_bytes([bytes[21], bytes[22]]);
if bytes.len() < 24 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "aoa_destination_elevation_fom".to_string(),
wanted: 24,
got: bytes.len(),
});
}
let aoa_destination_elevation_fom = u8::from_le_bytes([bytes[23]]);
if bytes.len() < 25 {
return Err(Error::InvalidLengthError {
obj: "ExtendedAddressTwoWayRangingMeasurement".to_string(),
field: "slot_index".to_string(),
wanted: 25,
got: bytes.len(),
});
}
let slot_index = u8::from_le_bytes([bytes[24]]);
Ok(Self {
mac_address,
status,
nlos,
distance,
aoa_azimuth,
aoa_azimuth_fom,
aoa_elevation,
aoa_elevation_fom,
aoa_destination_azimuth,
aoa_destination_azimuth_fom,
aoa_destination_elevation,
aoa_destination_elevation_fom,
slot_index,
})
}
fn write_to(&self, buffer: &mut [u8]) {
let mac_address = self.mac_address;
buffer[0..8].copy_from_slice(&mac_address.to_le_bytes()[0..8]);
let status = self.status.to_u8().unwrap();
buffer[8..9].copy_from_slice(&status.to_le_bytes()[0..1]);
let nlos = self.nlos;
buffer[9..10].copy_from_slice(&nlos.to_le_bytes()[0..1]);
let distance = self.distance;
buffer[10..12].copy_from_slice(&distance.to_le_bytes()[0..2]);
let aoa_azimuth = self.aoa_azimuth;
buffer[12..14].copy_from_slice(&aoa_azimuth.to_le_bytes()[0..2]);
let aoa_azimuth_fom = self.aoa_azimuth_fom;
buffer[14..15].copy_from_slice(&aoa_azimuth_fom.to_le_bytes()[0..1]);
let aoa_elevation = self.aoa_elevation;
buffer[15..17].copy_from_slice(&aoa_elevation.to_le_bytes()[0..2]);
let aoa_elevation_fom = self.aoa_elevation_fom;
buffer[17..18].copy_from_slice(&aoa_elevation_fom.to_le_bytes()[0..1]);
let aoa_destination_azimuth = self.aoa_destination_azimuth;
buffer[18..20].copy_from_slice(&aoa_destination_azimuth.to_le_bytes()[0..2]);
let aoa_destination_azimuth_fom = self.aoa_destination_azimuth_fom;
buffer[20..21].copy_from_slice(&aoa_destination_azimuth_fom.to_le_bytes()[0..1]);
let aoa_destination_elevation = self.aoa_destination_elevation;
buffer[21..23].copy_from_slice(&aoa_destination_elevation.to_le_bytes()[0..2]);
let aoa_destination_elevation_fom = self.aoa_destination_elevation_fom;
buffer[23..24].copy_from_slice(&aoa_destination_elevation_fom.to_le_bytes()[0..1]);
let slot_index = self.slot_index;
buffer[24..25].copy_from_slice(&slot_index.to_le_bytes()[0..1]);
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 31;
ret
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct PicaPosition {
pub x: u16,
pub y: u16,
pub z: u16,
pub yaw: u16,
pub pitch: u8,
pub roll: u16,
}
impl PicaPosition {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 11 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 2 {
return Err(Error::InvalidLengthError {
obj: "PicaPosition".to_string(),
field: "x".to_string(),
wanted: 2,
got: bytes.len(),
});
}
let x = u16::from_le_bytes([bytes[0], bytes[1]]);
if bytes.len() < 4 {
return Err(Error::InvalidLengthError {
obj: "PicaPosition".to_string(),
field: "y".to_string(),
wanted: 4,
got: bytes.len(),
});
}
let y = u16::from_le_bytes([bytes[2], bytes[3]]);
if bytes.len() < 6 {
return Err(Error::InvalidLengthError {
obj: "PicaPosition".to_string(),
field: "z".to_string(),
wanted: 6,
got: bytes.len(),
});
}
let z = u16::from_le_bytes([bytes[4], bytes[5]]);
if bytes.len() < 8 {
return Err(Error::InvalidLengthError {
obj: "PicaPosition".to_string(),
field: "yaw".to_string(),
wanted: 8,
got: bytes.len(),
});
}
let yaw = u16::from_le_bytes([bytes[6], bytes[7]]);
if bytes.len() < 9 {
return Err(Error::InvalidLengthError {
obj: "PicaPosition".to_string(),
field: "pitch".to_string(),
wanted: 9,
got: bytes.len(),
});
}
let pitch = u8::from_le_bytes([bytes[8]]);
if bytes.len() < 11 {
return Err(Error::InvalidLengthError {
obj: "PicaPosition".to_string(),
field: "roll".to_string(),
wanted: 11,
got: bytes.len(),
});
}
let roll = u16::from_le_bytes([bytes[9], bytes[10]]);
Ok(Self {
x,
y,
z,
yaw,
pitch,
roll,
})
}
fn write_to(&self, buffer: &mut [u8]) {
let x = self.x;
buffer[0..2].copy_from_slice(&x.to_le_bytes()[0..2]);
let y = self.y;
buffer[2..4].copy_from_slice(&y.to_le_bytes()[0..2]);
let z = self.z;
buffer[4..6].copy_from_slice(&z.to_le_bytes()[0..2]);
let yaw = self.yaw;
buffer[6..8].copy_from_slice(&yaw.to_le_bytes()[0..2]);
let pitch = self.pitch;
buffer[8..9].copy_from_slice(&pitch.to_le_bytes()[0..1]);
let roll = self.roll;
buffer[9..11].copy_from_slice(&roll.to_le_bytes()[0..2]);
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 11;
ret
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct PowerStats {
pub status: StatusCode,
pub idle_time_ms: u32,
pub tx_time_ms: u32,
pub rx_time_ms: u32,
pub total_wake_count: u32,
}
impl PowerStats {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 17 {
return false;
}
true
}
pub fn parse(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 1 {
return Err(Error::InvalidLengthError {
obj: "PowerStats".to_string(),
field: "status".to_string(),
wanted: 1,
got: bytes.len(),
});
}
let status = u8::from_le_bytes([bytes[0]]);
let status = StatusCode::from_u8(status).ok_or_else(|| Error::InvalidEnumValueError {
obj: "PowerStats".to_string(),
field: "status".to_string(),
value: status as u64,
type_: "StatusCode".to_string(),
})?;
if bytes.len() < 5 {
return Err(Error::InvalidLengthError {
obj: "PowerStats".to_string(),
field: "idle_time_ms".to_string(),
wanted: 5,
got: bytes.len(),
});
}
let idle_time_ms = u32::from_le_bytes([bytes[1], bytes[2], bytes[3], bytes[4]]);
if bytes.len() < 9 {
return Err(Error::InvalidLengthError {
obj: "PowerStats".to_string(),
field: "tx_time_ms".to_string(),
wanted: 9,
got: bytes.len(),
});
}
let tx_time_ms = u32::from_le_bytes([bytes[5], bytes[6], bytes[7], bytes[8]]);
if bytes.len() < 13 {
return Err(Error::InvalidLengthError {
obj: "PowerStats".to_string(),
field: "rx_time_ms".to_string(),
wanted: 13,
got: bytes.len(),
});
}
let rx_time_ms = u32::from_le_bytes([bytes[9], bytes[10], bytes[11], bytes[12]]);
if bytes.len() < 17 {
return Err(Error::InvalidLengthError {
obj: "PowerStats".to_string(),
field: "total_wake_count".to_string(),
wanted: 17,
got: bytes.len(),
});
}
let total_wake_count = u32::from_le_bytes([bytes[13], bytes[14], bytes[15], bytes[16]]);
Ok(Self {
status,
idle_time_ms,
tx_time_ms,
rx_time_ms,
total_wake_count,
})
}
fn write_to(&self, buffer: &mut [u8]) {
let status = self.status.to_u8().unwrap();
buffer[0..1].copy_from_slice(&status.to_le_bytes()[0..1]);
let idle_time_ms = self.idle_time_ms;
buffer[1..5].copy_from_slice(&idle_time_ms.to_le_bytes()[0..4]);
let tx_time_ms = self.tx_time_ms;
buffer[5..9].copy_from_slice(&tx_time_ms.to_le_bytes()[0..4]);
let rx_time_ms = self.rx_time_ms;
buffer[9..13].copy_from_slice(&rx_time_ms.to_le_bytes()[0..4]);
let total_wake_count = self.total_wake_count;
buffer[13..17].copy_from_slice(&total_wake_count.to_le_bytes()[0..4]);
}
fn get_total_size(&self) -> usize {
let ret = 0;
let ret = ret + 17;
ret
}
}
#[derive(Debug)]
enum UciPacketDataChild {
UciCommand(Arc<UciCommandData>),
UciResponse(Arc<UciResponseData>),
UciNotification(Arc<UciNotificationData>),
Payload(Bytes),
None,
}
impl UciPacketDataChild {
fn get_total_size(&self) -> usize {
match self {
UciPacketDataChild::UciCommand(value) => value.get_total_size(),
UciPacketDataChild::UciResponse(value) => value.get_total_size(),
UciPacketDataChild::UciNotification(value) => value.get_total_size(),
UciPacketDataChild::Payload(p) => p.len(),
UciPacketDataChild::None => 0,
}
}
}
#[derive(Debug)]
pub enum UciPacketChild {
UciCommand(UciCommandPacket),
UciResponse(UciResponsePacket),
UciNotification(UciNotificationPacket),
Payload(Bytes),
None,
}
#[derive(Debug)]
struct UciPacketData {
group_id: GroupId,
packet_boundary_flag: PacketBoundaryFlag,
message_type: MessageType,
opcode: u8,
child: UciPacketDataChild,
}
#[derive(Debug, Clone)]
pub struct UciPacketPacket {
uci_packet: Arc<UciPacketData>,
}
#[derive(Debug)]
pub struct UciPacketBuilder {
pub group_id: GroupId,
pub packet_boundary_flag: PacketBoundaryFlag,
pub message_type: MessageType,
pub opcode: u8,
pub payload: Option<Bytes>,
}
impl UciPacketData {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 4 {
return false;
}
true
}
fn parse(bytes: &[u8]) -> Result<Self> {
let group_id = u8::from_le_bytes([bytes[0]]);
let group_id = group_id & 0xf;
let group_id = GroupId::from_u8(group_id).ok_or_else(|| Error::InvalidEnumValueError {
obj: "UciPacket".to_string(),
field: "group_id".to_string(),
value: group_id as u64,
type_: "GroupId".to_string(),
})?;
let packet_boundary_flag = u8::from_le_bytes([bytes[0]]);
let packet_boundary_flag = packet_boundary_flag >> 4;
let packet_boundary_flag = packet_boundary_flag & 0x1;
let packet_boundary_flag =
PacketBoundaryFlag::from_u8(packet_boundary_flag).ok_or_else(|| {
Error::InvalidEnumValueError {
obj: "UciPacket".to_string(),
field: "packet_boundary_flag".to_string(),
value: packet_boundary_flag as u64,
type_: "PacketBoundaryFlag".to_string(),
}
})?;
let message_type = u8::from_le_bytes([bytes[0]]);
let message_type = message_type >> 5;
let message_type = message_type & 0x7;
let message_type =
MessageType::from_u8(message_type).ok_or_else(|| Error::InvalidEnumValueError {
obj: "UciPacket".to_string(),
field: "message_type".to_string(),
value: message_type as u64,
type_: "MessageType".to_string(),
})?;
let opcode = u8::from_le_bytes([bytes[1]]);
let opcode = opcode & 0x3f;
if bytes.len() < 4 {
return Err(Error::InvalidLengthError {
obj: "UciPacket".to_string(),
field: "payload_size".to_string(),
wanted: 4,
got: bytes.len(),
});
}
let payload_size = u8::from_le_bytes([bytes[3]]);
let want_ = 4 + (payload_size as usize);
if bytes.len() < want_ {
return Err(Error::InvalidLengthError {
obj: "UciPacket".to_string(),
field: "payload".to_string(),
wanted: want_,
got: bytes.len(),
});
}
let payload: Vec<u8> = bytes[4..(4 + payload_size as usize)].into();
let child = match (packet_boundary_flag, message_type) {
(PacketBoundaryFlag::Complete, MessageType::Command)
if UciCommandData::conforms(&bytes[..]) =>
{
UciPacketDataChild::UciCommand(Arc::new(UciCommandData::parse(
&bytes[..],
group_id,
opcode,
)?))
}
(PacketBoundaryFlag::Complete, MessageType::Response)
if UciResponseData::conforms(&bytes[..]) =>
{
UciPacketDataChild::UciResponse(Arc::new(UciResponseData::parse(
&bytes[..],
group_id,
opcode,
)?))
}
(PacketBoundaryFlag::Complete, MessageType::Notification)
if UciNotificationData::conforms(&bytes[..]) =>
{
UciPacketDataChild::UciNotification(Arc::new(UciNotificationData::parse(
&bytes[..],
group_id,
opcode,
)?))
}
(_, _) => return Err(Error::InvalidPacketError),
};
Ok(Self {
group_id,
packet_boundary_flag,
message_type,
opcode,
child,
})
}
fn write_to(&self, buffer: &mut BytesMut) {
let group_id = self.group_id.to_u8().unwrap();
let group_id = group_id & 0xf;
buffer[0..1].copy_from_slice(&group_id.to_le_bytes()[0..1]);
let packet_boundary_flag = self.packet_boundary_flag.to_u8().unwrap();
let packet_boundary_flag = packet_boundary_flag & 0x1;
let packet_boundary_flag = (packet_boundary_flag << 4) | ((buffer[0] as u8) & 0xf);
buffer[0..1].copy_from_slice(&packet_boundary_flag.to_le_bytes()[0..1]);
let message_type = self.message_type.to_u8().unwrap();
let message_type = message_type & 0x7;
let message_type = (message_type << 5) | ((buffer[0] as u8) & 0x1f);
buffer[0..1].copy_from_slice(&message_type.to_le_bytes()[0..1]);
let opcode = self.opcode;
let opcode = opcode & 0x3f;
buffer[1..2].copy_from_slice(&opcode.to_le_bytes()[0..1]);
let payload_size =
u8::try_from(self.child.get_total_size()).expect("payload size did not fit");
buffer[3..4].copy_from_slice(&payload_size.to_le_bytes()[0..1]);
match &self.child {
UciPacketDataChild::UciCommand(value) => value.write_to(buffer),
UciPacketDataChild::UciResponse(value) => value.write_to(buffer),
UciPacketDataChild::UciNotification(value) => value.write_to(buffer),
UciPacketDataChild::Payload(p) => buffer[4..].copy_from_slice(&p[..]),
UciPacketDataChild::None => {}
}
}
fn get_total_size(&self) -> usize {
self.get_size() + self.child.get_total_size()
}
fn get_size(&self) -> usize {
let ret = 0;
let ret = ret + 4;
ret
}
}
impl Packet for UciPacketPacket {
fn to_bytes(self) -> Bytes {
let mut buffer = BytesMut::new();
buffer.resize(self.uci_packet.get_total_size(), 0);
self.uci_packet.write_to(&mut buffer);
buffer.freeze()
}
fn to_vec(self) -> Vec<u8> {
self.to_bytes().to_vec()
}
}
impl From<UciPacketPacket> for Bytes {
fn from(packet: UciPacketPacket) -> Self {
packet.to_bytes()
}
}
impl From<UciPacketPacket> for Vec<u8> {
fn from(packet: UciPacketPacket) -> Self {
packet.to_vec()
}
}
impl UciPacketPacket {
pub fn parse(bytes: &[u8]) -> Result<Self> {
Ok(Self::new(Arc::new(UciPacketData::parse(bytes)?)).unwrap())
}
pub fn specialize(&self) -> UciPacketChild {
match &self.uci_packet.child {
UciPacketDataChild::UciCommand(_) => {
UciPacketChild::UciCommand(UciCommandPacket::new(self.uci_packet.clone()).unwrap())
}
UciPacketDataChild::UciResponse(_) => UciPacketChild::UciResponse(
UciResponsePacket::new(self.uci_packet.clone()).unwrap(),
),
UciPacketDataChild::UciNotification(_) => UciPacketChild::UciNotification(
UciNotificationPacket::new(self.uci_packet.clone()).unwrap(),
),
UciPacketDataChild::Payload(p) => UciPacketChild::Payload(p.clone()),
UciPacketDataChild::None => UciPacketChild::None,
}
}
fn new(root: Arc<UciPacketData>) -> std::result::Result<Self, &'static str> {
let uci_packet = root;
Ok(Self { uci_packet })
}
pub fn get_group_id(&self) -> GroupId {
self.uci_packet.as_ref().group_id
}
pub fn get_packet_boundary_flag(&self) -> PacketBoundaryFlag {
self.uci_packet.as_ref().packet_boundary_flag
}
pub fn get_message_type(&self) -> MessageType {
self.uci_packet.as_ref().message_type
}
pub fn get_opcode(&self) -> u8 {
self.uci_packet.as_ref().opcode
}
}
impl UciPacketBuilder {
pub fn build(self) -> UciPacketPacket {
let uci_packet = Arc::new(UciPacketData {
group_id: self.group_id,
packet_boundary_flag: self.packet_boundary_flag,
message_type: self.message_type,
opcode: self.opcode,
child: match self.payload {
None => UciPacketDataChild::None,
Some(bytes) => UciPacketDataChild::Payload(bytes),
},
});
UciPacketPacket::new(uci_packet).unwrap()
}
}
#[derive(Debug)]
enum UciCommandDataChild {
CoreCommand(Arc<CoreCommandData>),
SessionCommand(Arc<SessionCommandData>),
RangingCommand(Arc<RangingCommandData>),
AndroidCommand(Arc<AndroidCommandData>),
UciVendor_A_Command(Arc<UciVendor_A_CommandData>),
UciVendor_B_Command(Arc<UciVendor_B_CommandData>),
UciVendor_E_Command(Arc<UciVendor_E_CommandData>),
UciVendor_F_Command(Arc<UciVendor_F_CommandData>),
Payload(Bytes),
None,
}
impl UciCommandDataChild {
fn get_total_size(&self) -> usize {
match self {
UciCommandDataChild::CoreCommand(value) => value.get_total_size(),
UciCommandDataChild::SessionCommand(value) => value.get_total_size(),
UciCommandDataChild::RangingCommand(value) => value.get_total_size(),
UciCommandDataChild::AndroidCommand(value) => value.get_total_size(),
UciCommandDataChild::UciVendor_A_Command(value) => value.get_total_size(),
UciCommandDataChild::UciVendor_B_Command(value) => value.get_total_size(),
UciCommandDataChild::UciVendor_E_Command(value) => value.get_total_size(),
UciCommandDataChild::UciVendor_F_Command(value) => value.get_total_size(),
UciCommandDataChild::Payload(p) => p.len(),
UciCommandDataChild::None => 0,
}
}
}
#[derive(Debug)]
pub enum UciCommandChild {
CoreCommand(CoreCommandPacket),
SessionCommand(SessionCommandPacket),
RangingCommand(RangingCommandPacket),
AndroidCommand(AndroidCommandPacket),
UciVendor_A_Command(UciVendor_A_CommandPacket),
UciVendor_B_Command(UciVendor_B_CommandPacket),
UciVendor_E_Command(UciVendor_E_CommandPacket),
UciVendor_F_Command(UciVendor_F_CommandPacket),
Payload(Bytes),
None,
}
#[derive(Debug)]
struct UciCommandData {
child: UciCommandDataChild,
}
#[derive(Debug, Clone)]
pub struct UciCommandPacket {
uci_packet: Arc<UciPacketData>,
uci_command: Arc<UciCommandData>,
}
#[derive(Debug)]
pub struct UciCommandBuilder {
pub group_id: GroupId,
pub opcode: u8,
pub payload: Option<Bytes>,
}
impl UciCommandData {
fn conforms(bytes: &[u8]) -> bool {
if bytes.len() < 4 {
return false;
}
true
}
fn parse(bytes: &[u8], group_id: GroupId, opcode: u8) -> Result<Self> {
let payload: Vec<u8> = bytes[4..].into();
let child = match (group_id) {
(GroupId::Core) if CoreCommandData::conforms(&bytes[..]) => {
UciCommandDataChild::CoreCommand(Arc::new(CoreCommandData::parse(
&bytes[..],
opcode,
)?))
}
(GroupId::SessionConfig) if SessionCommandData::conforms(&bytes[..]) => {
UciCommandDataChild::SessionCommand(Arc::new(SessionCommandData::parse(
&bytes[..],
opcode,
)?))
}
(GroupId::RangingSessionControl) if RangingCommandData::conforms(&bytes[..]) => {
UciCommandDataChild::RangingCommand(Arc::new(RangingCommandData::parse(
&bytes[..],
opcode,
)?))
}
(GroupId::VendorAndroid) if AndroidCommandData::conforms(&bytes[..]) => {
UciCommandDataChild::AndroidCommand(Arc::new(AndroidCommandData::parse(
&bytes[..],
opcode,
)?))
}
(GroupId::VendorReservedA) if UciVendor_A_CommandData::conforms(&bytes[..]) => {
UciCommandDataChild::UciVendor_A_Command(Arc::new(UciVendor_A_CommandData::parse(
&bytes[..],
)?))
}
(GroupId::VendorReservedB) if UciVendor_B_CommandData::conforms(&bytes[..]) => {
UciCommandDataChild::UciVendor_B_Command(Arc::new(UciVendor_B_CommandData::parse(
&bytes[..],
)?))
}
(GroupId::VendorReservedE) if UciVendor_E_CommandData::conforms(&bytes[..]) => {
UciCommandDataChild::UciVendor_E_Command(Arc::new(UciVendor_E_CommandData::parse(
&bytes[..],
)?))
}
(GroupId::VendorReservedF) if UciVendor_F_CommandData::conforms(&bytes[..]) => {
UciCommandDataChild::UciVendor_F_Command(Arc::new(UciVendor_F_CommandData::parse(
&bytes[..],
)?))
}
(_) => return Err(Error::InvalidPacketError),
};
Ok(Self { child })
}
fn write_to(&self, buffer: &mut BytesMut) {
match &self.child {
UciCommandDataChild::CoreCommand(value) => value.write_to(buffer),
UciCommandDataChild::SessionCommand(value) => value.write_to(buffer),
UciCommandDataChild::RangingCommand(value) => value.write_to(buffer),
UciCommandDataChild::AndroidCommand(value) => value.write_to(buffer),
UciCommandDataChild::UciVendor_A_Command(value) => value.write_to(buffer),
UciCommandDataChild::UciVendor_B_Command(value) => value.write_to(buffer),
UciCommandDataChild::UciVendor_E_Command(value) => value.write_to(buffer),
UciCommandDataChild::UciVendor_F_Command(value) => value.write_to(buffer),
UciCommandDataChild::Payload(p) => buffer[4..].copy_from_slice(&p[..]),
UciCommandDataChild::None => {}
}
}
fn get_total_size(&self) -> usize {
self.get_size() + self.child.get_total_size()
}
fn get_size(&self) -> usize {
let ret = 0;
ret
}
}
impl Packet for UciCommandPacket {
fn to_bytes(self) -> Bytes {
let mut buffer = BytesMut::new();