pub mod caps_section;
pub mod cmd_section;
pub mod current_config_section;
pub mod mixer_section;
pub mod peak_section;
#[doc(hidden)]
pub(crate) mod router_entry;
pub mod router_section;
pub mod standalone_section;
#[doc(hidden)]
mod stream_format_entry;
pub mod stream_format_section;
use {
super::{global_section::ClockRate, *},
std::cmp::Ordering,
};
pub use {
caps_section::ExtensionCaps,
current_config_section::{CurrentRouterParams, CurrentStreamFormatParams},
mixer_section::{MixerCoefficientParams, MixerSaturationParams},
peak_section::PeakParams,
router_section::RouterParams,
standalone_section::StandaloneParameters,
stream_format_section::StreamFormatParams,
};
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub struct ExtensionSections {
pub caps: Section,
pub cmd: Section,
pub mixer: Section,
pub peak: Section,
pub router: Section,
pub stream_format: Section,
pub current_config: Section,
pub standalone: Section,
pub application: Section,
}
impl ExtensionSections {
const SECTION_COUNT: usize = 9;
const SIZE: usize = Section::SIZE * Self::SECTION_COUNT;
}
#[cfg(test)]
fn serialize_extension_sections(
sections: &ExtensionSections,
raw: &mut [u8],
) -> Result<(), String> {
assert!(raw.len() >= ExtensionSections::SIZE);
serialize_section(§ions.caps, &mut raw[..8])?;
serialize_section(§ions.cmd, &mut raw[8..16])?;
serialize_section(§ions.mixer, &mut raw[16..24])?;
serialize_section(§ions.peak, &mut raw[24..32])?;
serialize_section(§ions.router, &mut raw[32..40])?;
serialize_section(§ions.stream_format, &mut raw[40..48])?;
serialize_section(§ions.current_config, &mut raw[48..56])?;
serialize_section(§ions.standalone, &mut raw[56..64])?;
serialize_section(§ions.application, &mut raw[64..72])?;
Ok(())
}
fn deserialize_extension_sections(
sections: &mut ExtensionSections,
raw: &[u8],
) -> Result<(), String> {
assert!(raw.len() >= ExtensionSections::SIZE);
deserialize_section(&mut sections.caps, &raw[..8])?;
deserialize_section(&mut sections.cmd, &raw[8..16])?;
deserialize_section(&mut sections.mixer, &raw[16..24])?;
deserialize_section(&mut sections.peak, &raw[24..32])?;
deserialize_section(&mut sections.router, &raw[32..40])?;
deserialize_section(&mut sections.stream_format, &raw[40..48])?;
deserialize_section(&mut sections.current_config, &raw[48..56])?;
deserialize_section(&mut sections.standalone, &raw[56..64])?;
deserialize_section(&mut sections.application, &raw[64..72])?;
Ok(())
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ProtocolExtensionError {
Caps,
Cmd,
Mixer,
RouterEntry,
Peak,
Router,
StreamFormatEntry,
StreamFormat,
CurrentConfig,
Appl,
Standalone,
Invalid(i32),
}
impl std::fmt::Display for ProtocolExtensionError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let msg = match self {
ProtocolExtensionError::Caps => "caps",
ProtocolExtensionError::Cmd => "command",
ProtocolExtensionError::Mixer => "mixer",
ProtocolExtensionError::RouterEntry => "router-entry",
ProtocolExtensionError::Peak => "peak",
ProtocolExtensionError::Router => "router",
ProtocolExtensionError::StreamFormatEntry => "stream-format-entry",
ProtocolExtensionError::StreamFormat => "stream-format",
ProtocolExtensionError::CurrentConfig => "current-config",
ProtocolExtensionError::Appl => "application",
ProtocolExtensionError::Standalone => "standalone",
ProtocolExtensionError::Invalid(_) => "invalid",
};
write!(f, "ProtocolExtensionError::{}", msg)
}
}
impl ErrorDomain for ProtocolExtensionError {
fn domain() -> Quark {
Quark::from_str("tcat-protocol-extension-error-quark")
}
fn code(self) -> i32 {
match self {
ProtocolExtensionError::Caps => 0,
ProtocolExtensionError::Cmd => 1,
ProtocolExtensionError::Mixer => 2,
ProtocolExtensionError::RouterEntry => 3,
ProtocolExtensionError::Peak => 4,
ProtocolExtensionError::Router => 5,
ProtocolExtensionError::StreamFormatEntry => 6,
ProtocolExtensionError::StreamFormat => 7,
ProtocolExtensionError::CurrentConfig => 8,
ProtocolExtensionError::Appl => 9,
ProtocolExtensionError::Standalone => 10,
ProtocolExtensionError::Invalid(v) => v,
}
}
fn from(code: i32) -> Option<Self> {
let enumeration = match code {
0 => ProtocolExtensionError::Caps,
1 => ProtocolExtensionError::Cmd,
2 => ProtocolExtensionError::Mixer,
3 => ProtocolExtensionError::RouterEntry,
4 => ProtocolExtensionError::Peak,
5 => ProtocolExtensionError::Router,
7 => ProtocolExtensionError::StreamFormat,
8 => ProtocolExtensionError::CurrentConfig,
9 => ProtocolExtensionError::Appl,
10 => ProtocolExtensionError::Standalone,
_ => ProtocolExtensionError::Invalid(code),
};
Some(enumeration)
}
}
const EXTENSION_OFFSET: usize = 0x00200000;
pub trait TcatExtensionOperation: TcatOperation {
fn read_extension(
req: &FwReq,
node: &FwNode,
section: &Section,
offset: usize,
frames: &mut [u8],
timeout_ms: u32,
) -> Result<(), Error> {
Self::read(
req,
node,
EXTENSION_OFFSET + section.offset + offset,
frames,
timeout_ms,
)
}
fn write_extension(
req: &FwReq,
node: &FwNode,
section: &Section,
offset: usize,
frames: &mut [u8],
timeout_ms: u32,
) -> Result<(), Error> {
Self::write(
req,
node,
EXTENSION_OFFSET + section.offset + offset,
frames,
timeout_ms,
)
}
fn read_extension_sections(
req: &FwReq,
node: &FwNode,
sections: &mut ExtensionSections,
timeout_ms: u32,
) -> Result<(), Error> {
let mut raw = [0; ExtensionSections::SIZE];
Self::read(req, node, EXTENSION_OFFSET, &mut raw, timeout_ms)
.map(|_| deserialize_extension_sections(sections, &raw).unwrap())
}
}
pub trait TcatExtensionSectionParamsOperation<T: Debug> {
fn cache_extension_whole_params(
req: &FwReq,
node: &FwNode,
sections: &ExtensionSections,
caps: &ExtensionCaps,
params: &mut T,
timeout_ms: u32,
) -> Result<(), Error>;
}
pub trait TcatExtensionSectionWholeMutableParamsOperation<T: Debug> {
fn update_extension_whole_params(
req: &FwReq,
node: &FwNode,
sections: &ExtensionSections,
caps: &ExtensionCaps,
params: &T,
timeout_ms: u32,
) -> Result<(), Error>;
}
pub trait TcatExtensionSectionPartialMutableParamsOperation<T: Debug> {
fn update_extension_partial_params(
req: &FwReq,
node: &FwNode,
sections: &ExtensionSections,
caps: &ExtensionCaps,
params: &T,
prev: &mut T,
timeout_ms: u32,
) -> Result<(), Error>;
}
pub trait TcatExtensionSectionNotifiedParamsOperation<T: Debug> {
fn cache_extension_notified_params(
req: &FwReq,
node: &FwNode,
sections: &ExtensionSections,
caps: &ExtensionCaps,
params: &mut T,
msg: u32,
timeout_ms: u32,
) -> Result<(), Error>;
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum DstBlkId {
Aes,
Adat,
MixerTx0,
MixerTx1,
Ins0,
Ins1,
ArmApbAudio,
Avs0,
Avs1,
Reserved(u8),
}
impl Default for DstBlkId {
fn default() -> Self {
DstBlkId::Reserved(0xff)
}
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub struct DstBlk {
pub id: DstBlkId,
pub ch: u8,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SrcBlkId {
Aes,
Adat,
Mixer,
Ins0,
Ins1,
ArmAprAudio,
Avs0,
Avs1,
Mute,
Reserved(u8),
}
impl Default for SrcBlkId {
fn default() -> Self {
SrcBlkId::Reserved(0xff)
}
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub struct SrcBlk {
pub id: SrcBlkId,
pub ch: u8,
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub struct RouterEntry {
pub dst: DstBlk,
pub src: SrcBlk,
pub peak: u16,
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct FormatEntry {
pub pcm_count: u8,
pub midi_count: u8,
pub labels: Vec<String>,
pub enable_ac3: [bool; AC3_CHANNELS],
}
pub const AC3_CHANNELS: usize = 32;
#[cfg(test)]
mod test {
use super::*;
#[test]
fn section_from() {
let raw = [
0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b,
0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00,
];
let space = ExtensionSections {
caps: Section {
offset: 0x44,
size: 0x40,
},
cmd: Section {
offset: 0x3c,
size: 0x38,
},
mixer: Section {
offset: 0x34,
size: 0x30,
},
peak: Section {
offset: 0x2c,
size: 0x28,
},
router: Section {
offset: 0x24,
size: 0x20,
},
stream_format: Section {
offset: 0x1c,
size: 0x18,
},
current_config: Section {
offset: 0x14,
size: 0x10,
},
standalone: Section {
offset: 0x0c,
size: 0x08,
},
application: Section {
offset: 0x04,
size: 0x00,
},
};
let mut r = vec![0u8; raw.len()];
serialize_extension_sections(&space, &mut r).unwrap();
assert_eq!(&raw[..], &r);
let mut s = ExtensionSections::default();
deserialize_extension_sections(&mut s, &raw).unwrap();
assert_eq!(space, s);
}
}