| // 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(¶meter_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(); |
| |