1pub mod caps_section;
11pub mod cmd_section;
12pub mod current_config_section;
13pub mod mixer_section;
14pub mod peak_section;
15#[doc(hidden)]
16pub(crate) mod router_entry;
17pub mod router_section;
18pub mod standalone_section;
19#[doc(hidden)]
20mod stream_format_entry;
21pub mod stream_format_section;
22
23use {
24 super::{global_section::ClockRate, *},
25 std::cmp::Ordering,
26};
27
28pub use {
29 caps_section::ExtensionCaps,
30 current_config_section::{CurrentRouterParams, CurrentStreamFormatParams},
31 mixer_section::{MixerCoefficientParams, MixerSaturationParams},
32 peak_section::PeakParams,
33 router_section::RouterParams,
34 standalone_section::StandaloneParameters,
35 stream_format_section::StreamFormatParams,
36};
37
38#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
40pub struct ExtensionSections {
41 pub caps: Section,
43 pub cmd: Section,
45 pub mixer: Section,
47 pub peak: Section,
49 pub router: Section,
51 pub stream_format: Section,
53 pub current_config: Section,
55 pub standalone: Section,
57 pub application: Section,
59}
60
61impl ExtensionSections {
62 const SECTION_COUNT: usize = 9;
63 const SIZE: usize = Section::SIZE * Self::SECTION_COUNT;
64}
65
66#[cfg(test)]
67fn serialize_extension_sections(
68 sections: &ExtensionSections,
69 raw: &mut [u8],
70) -> Result<(), String> {
71 assert!(raw.len() >= ExtensionSections::SIZE);
72
73 serialize_section(§ions.caps, &mut raw[..8])?;
74 serialize_section(§ions.cmd, &mut raw[8..16])?;
75 serialize_section(§ions.mixer, &mut raw[16..24])?;
76 serialize_section(§ions.peak, &mut raw[24..32])?;
77 serialize_section(§ions.router, &mut raw[32..40])?;
78 serialize_section(§ions.stream_format, &mut raw[40..48])?;
79 serialize_section(§ions.current_config, &mut raw[48..56])?;
80 serialize_section(§ions.standalone, &mut raw[56..64])?;
81 serialize_section(§ions.application, &mut raw[64..72])?;
82
83 Ok(())
84}
85
86fn deserialize_extension_sections(
87 sections: &mut ExtensionSections,
88 raw: &[u8],
89) -> Result<(), String> {
90 assert!(raw.len() >= ExtensionSections::SIZE);
91
92 deserialize_section(&mut sections.caps, &raw[..8])?;
93 deserialize_section(&mut sections.cmd, &raw[8..16])?;
94 deserialize_section(&mut sections.mixer, &raw[16..24])?;
95 deserialize_section(&mut sections.peak, &raw[24..32])?;
96 deserialize_section(&mut sections.router, &raw[32..40])?;
97 deserialize_section(&mut sections.stream_format, &raw[40..48])?;
98 deserialize_section(&mut sections.current_config, &raw[48..56])?;
99 deserialize_section(&mut sections.standalone, &raw[56..64])?;
100 deserialize_section(&mut sections.application, &raw[64..72])?;
101
102 Ok(())
103}
104
105#[derive(Debug, Copy, Clone, PartialEq, Eq)]
107pub enum ProtocolExtensionError {
108 Caps,
110 Cmd,
112 Mixer,
114 RouterEntry,
116 Peak,
118 Router,
120 StreamFormatEntry,
122 StreamFormat,
124 CurrentConfig,
126 Appl,
128 Standalone,
130 Invalid(i32),
131}
132
133impl std::fmt::Display for ProtocolExtensionError {
134 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
135 let msg = match self {
136 ProtocolExtensionError::Caps => "caps",
137 ProtocolExtensionError::Cmd => "command",
138 ProtocolExtensionError::Mixer => "mixer",
139 ProtocolExtensionError::RouterEntry => "router-entry",
140 ProtocolExtensionError::Peak => "peak",
141 ProtocolExtensionError::Router => "router",
142 ProtocolExtensionError::StreamFormatEntry => "stream-format-entry",
143 ProtocolExtensionError::StreamFormat => "stream-format",
144 ProtocolExtensionError::CurrentConfig => "current-config",
145 ProtocolExtensionError::Appl => "application",
146 ProtocolExtensionError::Standalone => "standalone",
147 ProtocolExtensionError::Invalid(_) => "invalid",
148 };
149
150 write!(f, "ProtocolExtensionError::{}", msg)
151 }
152}
153
154impl ErrorDomain for ProtocolExtensionError {
155 fn domain() -> Quark {
156 Quark::from_str("tcat-protocol-extension-error-quark")
157 }
158
159 fn code(self) -> i32 {
160 match self {
161 ProtocolExtensionError::Caps => 0,
162 ProtocolExtensionError::Cmd => 1,
163 ProtocolExtensionError::Mixer => 2,
164 ProtocolExtensionError::RouterEntry => 3,
165 ProtocolExtensionError::Peak => 4,
166 ProtocolExtensionError::Router => 5,
167 ProtocolExtensionError::StreamFormatEntry => 6,
168 ProtocolExtensionError::StreamFormat => 7,
169 ProtocolExtensionError::CurrentConfig => 8,
170 ProtocolExtensionError::Appl => 9,
171 ProtocolExtensionError::Standalone => 10,
172 ProtocolExtensionError::Invalid(v) => v,
173 }
174 }
175
176 fn from(code: i32) -> Option<Self> {
177 let enumeration = match code {
178 0 => ProtocolExtensionError::Caps,
179 1 => ProtocolExtensionError::Cmd,
180 2 => ProtocolExtensionError::Mixer,
181 3 => ProtocolExtensionError::RouterEntry,
182 4 => ProtocolExtensionError::Peak,
183 5 => ProtocolExtensionError::Router,
184 7 => ProtocolExtensionError::StreamFormat,
185 8 => ProtocolExtensionError::CurrentConfig,
186 9 => ProtocolExtensionError::Appl,
187 10 => ProtocolExtensionError::Standalone,
188 _ => ProtocolExtensionError::Invalid(code),
189 };
190 Some(enumeration)
191 }
192}
193
194const EXTENSION_OFFSET: usize = 0x00200000;
195
196pub trait TcatExtensionOperation: TcatOperation {
198 fn read_extension(
200 req: &FwReq,
201 node: &FwNode,
202 section: &Section,
203 offset: usize,
204 frames: &mut [u8],
205 timeout_ms: u32,
206 ) -> Result<(), Error> {
207 Self::read(
208 req,
209 node,
210 EXTENSION_OFFSET + section.offset + offset,
211 frames,
212 timeout_ms,
213 )
214 }
215
216 fn write_extension(
218 req: &FwReq,
219 node: &FwNode,
220 section: &Section,
221 offset: usize,
222 frames: &mut [u8],
223 timeout_ms: u32,
224 ) -> Result<(), Error> {
225 Self::write(
226 req,
227 node,
228 EXTENSION_OFFSET + section.offset + offset,
229 frames,
230 timeout_ms,
231 )
232 }
233
234 fn read_extension_sections(
236 req: &FwReq,
237 node: &FwNode,
238 sections: &mut ExtensionSections,
239 timeout_ms: u32,
240 ) -> Result<(), Error> {
241 let mut raw = [0; ExtensionSections::SIZE];
242 Self::read(req, node, EXTENSION_OFFSET, &mut raw, timeout_ms)
243 .map(|_| deserialize_extension_sections(sections, &raw).unwrap())
244 }
245}
246
247pub trait TcatExtensionSectionParamsOperation<T: Debug> {
249 fn cache_extension_whole_params(
251 req: &FwReq,
252 node: &FwNode,
253 sections: &ExtensionSections,
254 caps: &ExtensionCaps,
255 params: &mut T,
256 timeout_ms: u32,
257 ) -> Result<(), Error>;
258}
259
260pub trait TcatExtensionSectionWholeMutableParamsOperation<T: Debug> {
262 fn update_extension_whole_params(
264 req: &FwReq,
265 node: &FwNode,
266 sections: &ExtensionSections,
267 caps: &ExtensionCaps,
268 params: &T,
269 timeout_ms: u32,
270 ) -> Result<(), Error>;
271}
272
273pub trait TcatExtensionSectionPartialMutableParamsOperation<T: Debug> {
275 fn update_extension_partial_params(
277 req: &FwReq,
278 node: &FwNode,
279 sections: &ExtensionSections,
280 caps: &ExtensionCaps,
281 params: &T,
282 prev: &mut T,
283 timeout_ms: u32,
284 ) -> Result<(), Error>;
285}
286pub trait TcatExtensionSectionNotifiedParamsOperation<T: Debug> {
289 fn cache_extension_notified_params(
291 req: &FwReq,
292 node: &FwNode,
293 sections: &ExtensionSections,
294 caps: &ExtensionCaps,
295 params: &mut T,
296 msg: u32,
297 timeout_ms: u32,
298 ) -> Result<(), Error>;
299}
300
301#[derive(Debug, Copy, Clone, PartialEq, Eq)]
303pub enum DstBlkId {
304 Aes,
305 Adat,
306 MixerTx0,
307 MixerTx1,
308 Ins0,
309 Ins1,
310 ArmApbAudio,
311 Avs0,
312 Avs1,
313 Reserved(u8),
314}
315
316impl Default for DstBlkId {
317 fn default() -> Self {
318 DstBlkId::Reserved(0xff)
319 }
320}
321
322#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
324pub struct DstBlk {
325 pub id: DstBlkId,
327 pub ch: u8,
329}
330
331#[derive(Debug, Copy, Clone, PartialEq, Eq)]
333pub enum SrcBlkId {
334 Aes,
336 Adat,
338 Mixer,
340 Ins0,
342 Ins1,
344 ArmAprAudio,
346 Avs0,
348 Avs1,
350 Mute,
352 Reserved(u8),
353}
354
355impl Default for SrcBlkId {
356 fn default() -> Self {
357 SrcBlkId::Reserved(0xff)
358 }
359}
360
361#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
363pub struct SrcBlk {
364 pub id: SrcBlkId,
366 pub ch: u8,
368}
369
370#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
372pub struct RouterEntry {
373 pub dst: DstBlk,
375 pub src: SrcBlk,
377 pub peak: u16,
379}
380
381#[derive(Default, Debug, Clone, PartialEq, Eq)]
383pub struct FormatEntry {
384 pub pcm_count: u8,
386 pub midi_count: u8,
388 pub labels: Vec<String>,
390 pub enable_ac3: [bool; AC3_CHANNELS],
392}
393
394pub const AC3_CHANNELS: usize = 32;
396
397#[cfg(test)]
398mod test {
399 use super::*;
400
401 #[test]
402 fn section_from() {
403 let raw = [
404 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
405 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b,
406 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
407 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
408 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
409 0x00, 0x00,
410 ];
411 let space = ExtensionSections {
412 caps: Section {
413 offset: 0x44,
414 size: 0x40,
415 },
416 cmd: Section {
417 offset: 0x3c,
418 size: 0x38,
419 },
420 mixer: Section {
421 offset: 0x34,
422 size: 0x30,
423 },
424 peak: Section {
425 offset: 0x2c,
426 size: 0x28,
427 },
428 router: Section {
429 offset: 0x24,
430 size: 0x20,
431 },
432 stream_format: Section {
433 offset: 0x1c,
434 size: 0x18,
435 },
436 current_config: Section {
437 offset: 0x14,
438 size: 0x10,
439 },
440 standalone: Section {
441 offset: 0x0c,
442 size: 0x08,
443 },
444 application: Section {
445 offset: 0x04,
446 size: 0x00,
447 },
448 };
449
450 let mut r = vec![0u8; raw.len()];
451 serialize_extension_sections(&space, &mut r).unwrap();
452 assert_eq!(&raw[..], &r);
453
454 let mut s = ExtensionSections::default();
455 deserialize_extension_sections(&mut s, &raw).unwrap();
456 assert_eq!(space, s);
457 }
458}