CFDP initial packet support #14
@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
- The `EcssEnumeration` now requires the `UnsignedEnum` trait and only adds the `pfc` method to it.
|
- The `EcssEnumeration` now requires the `UnsignedEnum` trait and only adds the `pfc` method to it.
|
||||||
- Renamed `byte_width` usages to `len` (part of new `UnsignedEnum` trait)
|
- Renamed `byte_width` usages to `len` (part of new `UnsignedEnum` trait)
|
||||||
|
- Moved `ecss::CRC_CCITT_FALSE` CRC constant to the root module. This CRC type is not just used by
|
||||||
|
the PUS standard, but by the CCSDS Telecommand standard and the CFDP standard as well.
|
||||||
|
|
||||||
# [v0.5.4] 2023-02-12
|
# [v0.5.4] 2023-02-12
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ impl<'src_name, 'dest_name, 'opts> MetadataPdu<'src_name, 'dest_name, 'opts> {
|
|||||||
|
|
||||||
pub fn written_len(&self) -> usize {
|
pub fn written_len(&self) -> usize {
|
||||||
// One directive type octet, and one byte of the parameter field.
|
// One directive type octet, and one byte of the parameter field.
|
||||||
let mut len = self.pdu_header.written_len() + 2;
|
let mut len = self.pdu_header.header_len() + 2;
|
||||||
if self.pdu_header.common_pdu_conf().file_flag == LargeFileFlag::Large {
|
if self.pdu_header.common_pdu_conf().file_flag == LargeFileFlag::Large {
|
||||||
len += 8;
|
len += 8;
|
||||||
} else {
|
} else {
|
||||||
@ -116,6 +116,7 @@ impl<'src_name, 'dest_name, 'opts> MetadataPdu<'src_name, 'dest_name, 'opts> {
|
|||||||
}
|
}
|
||||||
len
|
len
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||||
let expected_len = self.written_len();
|
let expected_len = self.written_len();
|
||||||
if buf.len() < expected_len {
|
if buf.len() < expected_len {
|
||||||
@ -129,7 +130,7 @@ impl<'src_name, 'dest_name, 'opts> MetadataPdu<'src_name, 'dest_name, 'opts> {
|
|||||||
buf[current_idx] = FileDirectiveType::MetadataPdu as u8;
|
buf[current_idx] = FileDirectiveType::MetadataPdu as u8;
|
||||||
current_idx += 1;
|
current_idx += 1;
|
||||||
buf[current_idx] = ((self.metadata_params.closure_requested as u8) << 7)
|
buf[current_idx] = ((self.metadata_params.closure_requested as u8) << 7)
|
||||||
| ((self.metadata_params.checksum_type as u8) << 4);
|
| (self.metadata_params.checksum_type as u8);
|
||||||
current_idx += 1;
|
current_idx += 1;
|
||||||
if self.pdu_header.common_pdu_conf().file_flag == LargeFileFlag::Large {
|
if self.pdu_header.common_pdu_conf().file_flag == LargeFileFlag::Large {
|
||||||
buf[current_idx..current_idx + core::mem::size_of::<u64>()]
|
buf[current_idx..current_idx + core::mem::size_of::<u64>()]
|
||||||
@ -155,6 +156,69 @@ impl<'src_name, 'dest_name, 'opts> MetadataPdu<'src_name, 'dest_name, 'opts> {
|
|||||||
}
|
}
|
||||||
Ok(current_idx)
|
Ok(current_idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_be_bytes<'longest: 'src_name + 'dest_name + 'opts>(
|
||||||
|
buf: &'longest [u8],
|
||||||
|
) -> Result<MetadataPdu<'src_name, 'dest_name, 'opts>, PduError> {
|
||||||
|
let (pdu_header, mut current_idx) = PduHeader::from_be_bytes(buf)?;
|
||||||
|
let full_len_without_crc = pdu_header.verify_length_and_checksum(buf)?;
|
||||||
|
let is_large_file = pdu_header.pdu_conf.file_flag == LargeFileFlag::Large;
|
||||||
|
// Minimal length: 1 byte + FSS (4 byte) + 2 empty LV (1 byte)
|
||||||
|
let mut min_expected_len = current_idx + 7;
|
||||||
|
if is_large_file {
|
||||||
|
min_expected_len += 4;
|
||||||
|
}
|
||||||
|
min_expected_len = core::cmp::max(min_expected_len, pdu_header.pdu_len());
|
||||||
|
if buf.len() < min_expected_len {
|
||||||
|
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
|
||||||
|
found: buf.len(),
|
||||||
|
expected: min_expected_len,
|
||||||
|
})
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
let directive_type = FileDirectiveType::try_from(buf[current_idx]).map_err(|_| {
|
||||||
|
PduError::InvalidDirectiveType((buf[current_idx], FileDirectiveType::MetadataPdu))
|
||||||
|
})?;
|
||||||
|
if directive_type != FileDirectiveType::MetadataPdu {
|
||||||
|
return Err(PduError::WrongDirectiveType((
|
||||||
|
directive_type,
|
||||||
|
FileDirectiveType::MetadataPdu,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
current_idx += 1;
|
||||||
|
|
||||||
|
let file_size = if pdu_header.pdu_conf.file_flag == LargeFileFlag::Large {
|
||||||
|
u64::from_be_bytes(buf[current_idx + 1..current_idx + 9].try_into().unwrap())
|
||||||
|
} else {
|
||||||
|
u32::from_be_bytes(buf[current_idx + 1..current_idx + 5].try_into().unwrap()) as u64
|
||||||
|
};
|
||||||
|
let metadata_params = MetadataGenericParams {
|
||||||
|
closure_requested: ((buf[current_idx] >> 6) & 0b1) != 0,
|
||||||
|
checksum_type: ChecksumType::try_from(buf[current_idx] & 0b1111)
|
||||||
|
.map_err(|_| PduError::InvalidChecksumType(buf[current_idx] & 0b1111))?,
|
||||||
|
file_size,
|
||||||
|
};
|
||||||
|
current_idx += 5;
|
||||||
|
if is_large_file {
|
||||||
|
current_idx += 4;
|
||||||
|
}
|
||||||
|
let src_file_name = Lv::from_be_bytes(&buf[current_idx..])?;
|
||||||
|
current_idx += src_file_name.len_full();
|
||||||
|
let dest_file_name = Lv::from_be_bytes(&buf[current_idx..])?;
|
||||||
|
current_idx += dest_file_name.len_full();
|
||||||
|
// All left-over bytes are options.
|
||||||
|
let mut options = None;
|
||||||
|
if current_idx < full_len_without_crc {
|
||||||
|
options = Some(&buf[current_idx..full_len_without_crc]);
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
pdu_header,
|
||||||
|
metadata_params,
|
||||||
|
src_file_name,
|
||||||
|
dest_file_name,
|
||||||
|
options,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -188,7 +252,7 @@ pub mod tests {
|
|||||||
MetadataPdu::new(pdu_header, metadata_params, src_filename, dest_filename);
|
MetadataPdu::new(pdu_header, metadata_params, src_filename, dest_filename);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
metadata_pdu.written_len(),
|
metadata_pdu.written_len(),
|
||||||
pdu_header.written_len() + 1 + 1 + 4 + src_len + dest_len
|
pdu_header.header_len() + 1 + 1 + 4 + src_len + dest_len
|
||||||
);
|
);
|
||||||
assert_eq!(metadata_pdu.src_file_name(), src_filename);
|
assert_eq!(metadata_pdu.src_file_name(), src_filename);
|
||||||
assert_eq!(metadata_pdu.dest_file_name(), dest_filename);
|
assert_eq!(metadata_pdu.dest_file_name(), dest_filename);
|
||||||
@ -213,9 +277,23 @@ pub mod tests {
|
|||||||
let written = res.unwrap();
|
let written = res.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
written,
|
written,
|
||||||
pdu_header.written_len() + 1 + 1 + 4 + src_len + dest_len
|
pdu_header.header_len() + 1 + 1 + 4 + src_len + dest_len
|
||||||
);
|
);
|
||||||
verify_raw_header(&pdu_header, &buf);
|
verify_raw_header(&pdu_header, &buf);
|
||||||
assert_eq!(buf[7], FileDirectiveType::MetadataPdu as u8);
|
assert_eq!(buf[7], FileDirectiveType::MetadataPdu as u8);
|
||||||
|
assert_eq!(buf[8] >> 6, false as u8);
|
||||||
|
assert_eq!(buf[8] & 0b1111, ChecksumType::Crc32 as u8);
|
||||||
|
assert_eq!(u32::from_be_bytes(buf[9..13].try_into().unwrap()), 10);
|
||||||
|
let mut current_idx = 13;
|
||||||
|
let src_name_from_raw =
|
||||||
|
Lv::from_be_bytes(&buf[current_idx..]).expect("Creating source name LV failed");
|
||||||
|
assert_eq!(src_name_from_raw, src_filename);
|
||||||
|
current_idx += src_name_from_raw.len_full();
|
||||||
|
let dest_name_from_raw =
|
||||||
|
Lv::from_be_bytes(&buf[current_idx..]).expect("Creating dest name LV failed");
|
||||||
|
assert_eq!(dest_name_from_raw, dest_filename);
|
||||||
|
current_idx += dest_name_from_raw.len_full();
|
||||||
|
// No options, so no additional data here.
|
||||||
|
assert_eq!(current_idx, written);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! CFDP Packet Data Unit (PDU) support.
|
//! CFDP Packet Data Unit (PDU) support.
|
||||||
use crate::cfdp::*;
|
use crate::cfdp::*;
|
||||||
use crate::util::{UnsignedByteField, UnsignedEnum};
|
use crate::util::{UnsignedByteField, UnsignedEnum};
|
||||||
|
use crate::CRC_CCITT_FALSE;
|
||||||
use crate::{ByteConversionError, SizeMissmatch};
|
use crate::{ByteConversionError, SizeMissmatch};
|
||||||
use core::fmt::{Display, Formatter};
|
use core::fmt::{Display, Formatter};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -34,7 +35,19 @@ pub enum PduError {
|
|||||||
/// The first entry will be the source entity ID length, the second one the destination entity
|
/// The first entry will be the source entity ID length, the second one the destination entity
|
||||||
/// ID length.
|
/// ID length.
|
||||||
SourceDestIdLenMissmatch((usize, usize)),
|
SourceDestIdLenMissmatch((usize, usize)),
|
||||||
|
/// The first tuple entry will be the found directive type, the second entry the expected entry
|
||||||
|
/// type.
|
||||||
|
WrongDirectiveType((FileDirectiveType, FileDirectiveType)),
|
||||||
|
/// The directive type field contained a value not in the range of permitted values.
|
||||||
|
/// The first tuple entry will be the found raw number, the second entry the expected entry
|
||||||
|
/// type.
|
||||||
|
InvalidDirectiveType((u8, FileDirectiveType)),
|
||||||
|
/// Invalid checksum type which is not part of the checksums listed in the
|
||||||
|
/// [SANA Checksum Types registry](https://sanaregistry.org/r/checksum_identifiers/).
|
||||||
|
InvalidChecksumType(u8),
|
||||||
FileSizeTooLarge(u64),
|
FileSizeTooLarge(u64),
|
||||||
|
/// If the CRC flag for a PDU is enabled and the checksum check fails. Contains raw 16-bit CRC.
|
||||||
|
ChecksumError(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for PduError {
|
impl Display for PduError {
|
||||||
@ -68,7 +81,23 @@ impl Display for PduError {
|
|||||||
write!(f, "{}", e)
|
write!(f, "{}", e)
|
||||||
}
|
}
|
||||||
PduError::FileSizeTooLarge(value) => {
|
PduError::FileSizeTooLarge(value) => {
|
||||||
write!(f, "file size value {} exceeds allowed 32 bit width", value)
|
write!(f, "file size value {value} exceeds allowed 32 bit width")
|
||||||
|
}
|
||||||
|
PduError::WrongDirectiveType((found, expected)) => {
|
||||||
|
write!(f, "found directive type {found:?}, expected {expected:?}")
|
||||||
|
}
|
||||||
|
PduError::InvalidDirectiveType((found, expected)) => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"invalid directive type value {found}, expected {expected:?} ({})",
|
||||||
|
*expected as u8
|
||||||
|
)
|
||||||
|
}
|
||||||
|
PduError::InvalidChecksumType(checksum_type) => {
|
||||||
|
write!(f, "invalid checksum type {checksum_type}")
|
||||||
|
}
|
||||||
|
PduError::ChecksumError(checksum) => {
|
||||||
|
write!(f, "checksum error for CRC {checksum:#04x}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,12 +243,20 @@ impl PduHeader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn written_len(&self) -> usize {
|
/// Returns only the length of the PDU header when written to a raw buffer.
|
||||||
|
pub fn header_len(&self) -> usize {
|
||||||
FIXED_HEADER_LEN
|
FIXED_HEADER_LEN
|
||||||
+ self.pdu_conf.source_entity_id.len()
|
+ self.pdu_conf.source_entity_id.len()
|
||||||
+ self.pdu_conf.transaction_seq_num.len()
|
+ self.pdu_conf.transaction_seq_num.len()
|
||||||
+ self.pdu_conf.dest_entity_id.len()
|
+ self.pdu_conf.dest_entity_id.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the full length of the PDU when written to a raw buffer, which is the header length
|
||||||
|
/// plus the PDU datafield length.
|
||||||
|
pub fn pdu_len(&self) -> usize {
|
||||||
|
self.header_len() + self.pdu_datafield_len as usize
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||||
// Internal note: There is currently no way to pass a PDU configuration like this, but
|
// Internal note: There is currently no way to pass a PDU configuration like this, but
|
||||||
// this check is still kept for defensive programming.
|
// this check is still kept for defensive programming.
|
||||||
@ -270,6 +307,39 @@ impl PduHeader {
|
|||||||
Ok(current_idx)
|
Ok(current_idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This function first verifies that the buffer can hold the full length of the PDU parsed from
|
||||||
|
/// the header. Then, it verifies the checksum as specified in the standard if the CRC flag
|
||||||
|
/// of the PDU header is set.
|
||||||
|
///
|
||||||
|
/// This function will return the PDU length excluding the 2 CRC bytes on success. If the CRC
|
||||||
|
/// flag is not set, it will simply return the PDU length.
|
||||||
|
pub fn verify_length_and_checksum(&self, buf: &[u8]) -> Result<usize, PduError> {
|
||||||
|
if buf.len() < self.pdu_len() {
|
||||||
|
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
|
||||||
|
found: buf.len(),
|
||||||
|
expected: self.pdu_len(),
|
||||||
|
})
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
if self.pdu_conf.crc_flag == CrcFlag::WithCrc {
|
||||||
|
let mut digest = CRC_CCITT_FALSE.digest();
|
||||||
|
digest.update(&buf[..self.pdu_len()]);
|
||||||
|
if digest.finalize() != 0 {
|
||||||
|
return Err(PduError::ChecksumError(u16::from_be_bytes(
|
||||||
|
buf[self.pdu_len() - 2..self.pdu_len()].try_into().unwrap(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(self.pdu_len())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Please note that this function will not verify that the passed buffer can hold the full
|
||||||
|
/// PDU length. This allows recovering the header portion even if the data field length is
|
||||||
|
/// invalid. This function will also not do the CRC procedure specified in chapter 4.1.1
|
||||||
|
/// and 4.1.2 because performing the CRC procedure requires the buffer to be large enough
|
||||||
|
/// to hold the full PDU.
|
||||||
|
///
|
||||||
|
/// Both functions can however be performed with the [verify_length_and_checksum] function.
|
||||||
pub fn from_be_bytes(buf: &[u8]) -> Result<(Self, usize), PduError> {
|
pub fn from_be_bytes(buf: &[u8]) -> Result<(Self, usize), PduError> {
|
||||||
if buf.len() < FIXED_HEADER_LEN {
|
if buf.len() < FIXED_HEADER_LEN {
|
||||||
return Err(PduError::ByteConversionError(
|
return Err(PduError::ByteConversionError(
|
||||||
@ -464,7 +534,7 @@ mod tests {
|
|||||||
SegmentationControl::NoRecordBoundaryPreservation
|
SegmentationControl::NoRecordBoundaryPreservation
|
||||||
);
|
);
|
||||||
assert_eq!(pdu_header.pdu_datafield_len, 5);
|
assert_eq!(pdu_header.pdu_datafield_len, 5);
|
||||||
assert_eq!(pdu_header.written_len(), 7);
|
assert_eq!(pdu_header.header_len(), 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -519,7 +589,7 @@ mod tests {
|
|||||||
SegmentMetadataFlag::Present,
|
SegmentMetadataFlag::Present,
|
||||||
SegmentationControl::WithRecordBoundaryPreservation,
|
SegmentationControl::WithRecordBoundaryPreservation,
|
||||||
);
|
);
|
||||||
assert_eq!(pdu_header.written_len(), 10);
|
assert_eq!(pdu_header.header_len(), 10);
|
||||||
let mut buf: [u8; 16] = [0; 16];
|
let mut buf: [u8; 16] = [0; 16];
|
||||||
let res = pdu_header.write_to_be_bytes(&mut buf);
|
let res = pdu_header.write_to_be_bytes(&mut buf);
|
||||||
assert!(res.is_ok(), "{}", format!("Result {res:?} not okay"));
|
assert!(res.is_ok(), "{}", format!("Result {res:?} not okay"));
|
||||||
|
@ -3,10 +3,9 @@
|
|||||||
//!
|
//!
|
||||||
//! You can find the PUS telecommand definitions in the [crate::tc] module and ithe PUS telemetry definitions
|
//! You can find the PUS telecommand definitions in the [crate::tc] module and ithe PUS telemetry definitions
|
||||||
//! inside the [crate::tm] module.
|
//! inside the [crate::tm] module.
|
||||||
use crate::{ByteConversionError, CcsdsPacket};
|
use crate::{ByteConversionError, CcsdsPacket, CRC_CCITT_FALSE};
|
||||||
use core::fmt::{Debug, Display, Formatter};
|
use core::fmt::{Debug, Display, Formatter};
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
use crc::{Crc, CRC_16_IBM_3740};
|
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -19,9 +18,6 @@ pub mod scheduling;
|
|||||||
pub mod verification;
|
pub mod verification;
|
||||||
|
|
||||||
pub type CrcType = u16;
|
pub type CrcType = u16;
|
||||||
|
|
||||||
/// CRC algorithm used by the PUS standard.
|
|
||||||
pub const CRC_CCITT_FALSE: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_3740);
|
|
||||||
pub const CCSDS_HEADER_LEN: usize = size_of::<crate::zc::SpHeader>();
|
pub const CCSDS_HEADER_LEN: usize = size_of::<crate::zc::SpHeader>();
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
|
||||||
@ -261,7 +257,10 @@ pub(crate) fn user_data_from_raw(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn verify_crc16_from_raw(raw_data: &[u8], crc16: u16) -> Result<(), PusError> {
|
pub(crate) fn verify_crc16_ccitt_false_from_raw(
|
||||||
|
raw_data: &[u8],
|
||||||
|
crc16: u16,
|
||||||
|
) -> Result<(), PusError> {
|
||||||
let mut digest = CRC_CCITT_FALSE.digest();
|
let mut digest = CRC_CCITT_FALSE.digest();
|
||||||
digest.update(raw_data);
|
digest.update(raw_data);
|
||||||
if digest.finalize() == 0 {
|
if digest.finalize() == 0 {
|
||||||
|
@ -61,6 +61,7 @@ extern crate std;
|
|||||||
|
|
||||||
use crate::ecss::CCSDS_HEADER_LEN;
|
use crate::ecss::CCSDS_HEADER_LEN;
|
||||||
use core::fmt::{Debug, Display, Formatter};
|
use core::fmt::{Debug, Display, Formatter};
|
||||||
|
use crc::{Crc, CRC_16_IBM_3740};
|
||||||
use delegate::delegate;
|
use delegate::delegate;
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use num_traits::Unsigned;
|
use num_traits::Unsigned;
|
||||||
@ -81,6 +82,9 @@ mod private {
|
|||||||
pub trait Sealed {}
|
pub trait Sealed {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CRC algorithm used by the PUS standard, the CCSDS TC standard and the CFDP standard.
|
||||||
|
pub const CRC_CCITT_FALSE: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_3740);
|
||||||
|
|
||||||
pub const MAX_APID: u16 = 2u16.pow(11) - 1;
|
pub const MAX_APID: u16 = 2u16.pow(11) - 1;
|
||||||
pub const MAX_SEQ_COUNT: u16 = 2u16.pow(14) - 1;
|
pub const MAX_SEQ_COUNT: u16 = 2u16.pow(14) - 1;
|
||||||
|
|
||||||
|
@ -33,12 +33,12 @@
|
|||||||
//! ```
|
//! ```
|
||||||
use crate::ecss::{
|
use crate::ecss::{
|
||||||
ccsds_impl, crc_from_raw_data, crc_procedure, sp_header_impls, user_data_from_raw,
|
ccsds_impl, crc_from_raw_data, crc_procedure, sp_header_impls, user_data_from_raw,
|
||||||
verify_crc16_from_raw, CrcType, PusError, PusPacket, PusVersion, CRC_CCITT_FALSE,
|
verify_crc16_ccitt_false_from_raw, CrcType, PusError, PusPacket, PusVersion,
|
||||||
};
|
};
|
||||||
use crate::SpHeader;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SizeMissmatch, CCSDS_HEADER_LEN,
|
ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SizeMissmatch, CCSDS_HEADER_LEN,
|
||||||
};
|
};
|
||||||
|
use crate::{SpHeader, CRC_CCITT_FALSE};
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
use delegate::delegate;
|
use delegate::delegate;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
@ -437,7 +437,7 @@ impl<'raw_data> PusTc<'raw_data> {
|
|||||||
calc_crc_on_serialization: false,
|
calc_crc_on_serialization: false,
|
||||||
crc16: Some(crc_from_raw_data(raw_data)?),
|
crc16: Some(crc_from_raw_data(raw_data)?),
|
||||||
};
|
};
|
||||||
verify_crc16_from_raw(raw_data, pus_tc.crc16.expect("CRC16 invalid"))?;
|
verify_crc16_ccitt_false_from_raw(raw_data, pus_tc.crc16.expect("CRC16 invalid"))?;
|
||||||
Ok((pus_tc, total_len))
|
Ok((pus_tc, total_len))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
//! to [ECSS-E-ST-70-41C](https://ecss.nl/standard/ecss-e-st-70-41c-space-engineering-telemetry-and-telecommand-packet-utilization-15-april-2016/).
|
//! to [ECSS-E-ST-70-41C](https://ecss.nl/standard/ecss-e-st-70-41c-space-engineering-telemetry-and-telecommand-packet-utilization-15-april-2016/).
|
||||||
use crate::ecss::{
|
use crate::ecss::{
|
||||||
ccsds_impl, crc_from_raw_data, crc_procedure, sp_header_impls, user_data_from_raw,
|
ccsds_impl, crc_from_raw_data, crc_procedure, sp_header_impls, user_data_from_raw,
|
||||||
verify_crc16_from_raw, CrcType, PusError, PusPacket, PusVersion, CRC_CCITT_FALSE,
|
verify_crc16_ccitt_false_from_raw, CrcType, PusError, PusPacket, PusVersion,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SizeMissmatch, SpHeader,
|
ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SizeMissmatch, SpHeader,
|
||||||
CCSDS_HEADER_LEN,
|
CCSDS_HEADER_LEN, CRC_CCITT_FALSE,
|
||||||
};
|
};
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
@ -439,7 +439,7 @@ impl<'raw_data> PusTm<'raw_data> {
|
|||||||
calc_crc_on_serialization: false,
|
calc_crc_on_serialization: false,
|
||||||
crc16: Some(crc_from_raw_data(raw_data)?),
|
crc16: Some(crc_from_raw_data(raw_data)?),
|
||||||
};
|
};
|
||||||
verify_crc16_from_raw(raw_data, pus_tm.crc16.expect("CRC16 invalid"))?;
|
verify_crc16_ccitt_false_from_raw(raw_data, pus_tm.crc16.expect("CRC16 invalid"))?;
|
||||||
Ok((pus_tm, total_len))
|
Ok((pus_tm, total_len))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user