use heterob::{bit_numbering::Lsb, endianness::Le, Seq, P2, P3, P4};
use super::{ExtendedCapabilityDataError, ExtendedCapabilityHeader};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FrsQueuing {
pub frs_queuing_capability: FrsQueuingCapability,
pub frs_queuing_status: FrsQueuingStatus,
pub frs_queuing_control: FrsQueuingControl,
pub frs_message_queue: FrsMessageQueue,
}
impl FrsQueuing {
pub const SIZE: usize = ExtendedCapabilityHeader::SIZE
+ FrsQueuingCapability::SIZE
+ FrsQueuingStatus::SIZE
+ FrsQueuingControl::SIZE
+ FrsMessageQueue::SIZE;
}
impl TryFrom<&[u8]> for FrsQueuing {
type Error = ExtendedCapabilityDataError;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
let slice = slice
.get(ExtendedCapabilityHeader::SIZE..)
.unwrap_or_default();
let Seq {
head:
Le((frs_queuing_capability, frs_queuing_status, frs_queuing_control, frs_message_queue)),
..
} = P4(slice)
.try_into()
.map_err(|_| ExtendedCapabilityDataError {
name: "FRS Queuing",
size: Self::SIZE,
})?;
Ok(Self {
frs_queuing_capability: From::<u32>::from(frs_queuing_capability),
frs_queuing_status: From::<u16>::from(frs_queuing_status),
frs_queuing_control: From::<u16>::from(frs_queuing_control),
frs_message_queue: From::<u32>::from(frs_message_queue),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FrsQueuingCapability {
pub frs_queue_max_depth: u16,
pub frs_interrupt_message_number: u8,
}
impl FrsQueuingCapability {
pub const SIZE: usize = 4;
}
impl From<u32> for FrsQueuingCapability {
fn from(dword: u32) -> Self {
let Lsb((frs_queue_max_depth, (), frs_interrupt_message_number, ())) =
P4::<_, 12, 4, 5, 11>(dword).into();
Self {
frs_queue_max_depth,
frs_interrupt_message_number,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FrsQueuingStatus {
pub frs_message_received: bool,
pub frs_message_overflow: bool,
}
impl FrsQueuingStatus {
pub const SIZE: usize = 2;
}
impl From<u16> for FrsQueuingStatus {
fn from(word: u16) -> Self {
let Lsb((frs_message_received, frs_message_overflow, ())) = P3::<_, 1, 1, 14>(word).into();
Self {
frs_message_received,
frs_message_overflow,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FrsQueuingControl {
pub frs_interrupt_enable: bool,
}
impl FrsQueuingControl {
pub const SIZE: usize = 2;
}
impl From<u16> for FrsQueuingControl {
fn from(word: u16) -> Self {
let Lsb((frs_interrupt_enable, ())) = P2::<_, 1, 15>(word).into();
Self {
frs_interrupt_enable,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FrsMessageQueue {
pub frs_message_queue_function_id: u16,
pub frs_message_queue_reason: u8,
pub frs_message_queue_depth: u16,
}
impl FrsMessageQueue {
pub const SIZE: usize = 4;
}
impl From<u32> for FrsMessageQueue {
fn from(dword: u32) -> Self {
let Lsb((frs_message_queue_function_id, frs_message_queue_reason, frs_message_queue_depth)) =
P3::<_, 16, 4, 12>(dword).into();
Self {
frs_message_queue_function_id,
frs_message_queue_reason,
frs_message_queue_depth,
}
}
}