firewire_dice_protocols/tcat/
extension.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2020 Takashi Sakamoto
3
4//! Protocol extension defined by TCAT for ASICs of DICE.
5//!
6//! The module includes structure, enumeration, and trait and its implementation for protocol
7//! extension defined by TC Applied Technologies (TCAT) for ASICs of Digital Interface Communication
8//! Engine (DICE).
9
10pub 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/// Sections for protocol extension.
39#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
40pub struct ExtensionSections {
41    /// Capability.
42    pub caps: Section,
43    /// Command.
44    pub cmd: Section,
45    /// Mixer.
46    pub mixer: Section,
47    /// Peak.
48    pub peak: Section,
49    /// Router.
50    pub router: Section,
51    /// Stream format configuration.
52    pub stream_format: Section,
53    /// Current configurations.
54    pub current_config: Section,
55    /// Stand alone configuration.
56    pub standalone: Section,
57    /// Application specific configurations.
58    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(&sections.caps, &mut raw[..8])?;
74    serialize_section(&sections.cmd, &mut raw[8..16])?;
75    serialize_section(&sections.mixer, &mut raw[16..24])?;
76    serialize_section(&sections.peak, &mut raw[24..32])?;
77    serialize_section(&sections.router, &mut raw[32..40])?;
78    serialize_section(&sections.stream_format, &mut raw[40..48])?;
79    serialize_section(&sections.current_config, &mut raw[48..56])?;
80    serialize_section(&sections.standalone, &mut raw[56..64])?;
81    serialize_section(&sections.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/// Any error of protocol extension.
106#[derive(Debug, Copy, Clone, PartialEq, Eq)]
107pub enum ProtocolExtensionError {
108    /// Capability.
109    Caps,
110    /// Command.
111    Cmd,
112    /// Mixer.
113    Mixer,
114    /// Entry of router.
115    RouterEntry,
116    /// Peak.
117    Peak,
118    /// Router.
119    Router,
120    /// Entry of stream format.
121    StreamFormatEntry,
122    /// Stream format configuration.
123    StreamFormat,
124    /// Current configurations.
125    CurrentConfig,
126    /// Application specific configuration.
127    Appl,
128    /// Stand alone configuration.
129    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
196/// Operation of TCAT protocol extension.
197pub trait TcatExtensionOperation: TcatOperation {
198    /// Initiate read transaction to offset in specific address space and finish it.
199    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    /// Initiate write transaction to offset in specific address space and finish it.
217    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    /// Read section layout.
235    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
247/// Operation for whole parameters in section of TCAT protocol extension.
248pub trait TcatExtensionSectionParamsOperation<T: Debug> {
249    /// Cache state of hardware for whole parameters.
250    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
260/// Operation for whole mutable parameters in section of TCAT protocol extension.
261pub trait TcatExtensionSectionWholeMutableParamsOperation<T: Debug> {
262    /// Update state of hardware for whole parameters.
263    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
273/// Operation for partial mutable parameters in section of TCAT protocol extension.
274pub trait TcatExtensionSectionPartialMutableParamsOperation<T: Debug> {
275    /// Update state of hardware for partial parameters.
276    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}
286/// Operation for parameters in which any change is notified to owner application in TCAT protocol
287/// extension.
288pub trait TcatExtensionSectionNotifiedParamsOperation<T: Debug> {
289    /// Cache state of hardware for notified parameters.
290    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/// Identifier of destination block.
302#[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/// Destination block in router function.
323#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
324pub struct DstBlk {
325    /// The identifier of destination block.
326    pub id: DstBlkId,
327    /// The channel number.
328    pub ch: u8,
329}
330
331/// Identifier of source block.
332#[derive(Debug, Copy, Clone, PartialEq, Eq)]
333pub enum SrcBlkId {
334    /// AES, S/PDIF, and TOS outputs.
335    Aes,
336    /// ADAT outputs.
337    Adat,
338    /// mixer outputs.
339    Mixer,
340    /// Analog outputs A (Inter IC sound interface).
341    Ins0,
342    /// Analog outputs B (Inter IC sound interface).
343    Ins1,
344    /// Standard AMBA 2.0 compliant APB interface.
345    ArmAprAudio,
346    /// 1394 Audio video system A.
347    Avs0,
348    /// 1394 Audio video system B.
349    Avs1,
350    /// Discard audio signal.
351    Mute,
352    Reserved(u8),
353}
354
355impl Default for SrcBlkId {
356    fn default() -> Self {
357        SrcBlkId::Reserved(0xff)
358    }
359}
360
361/// Source block in router function.
362#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
363pub struct SrcBlk {
364    /// The identifier of source block.
365    pub id: SrcBlkId,
366    /// The channel number.
367    pub ch: u8,
368}
369
370/// Entry of route in router function.
371#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
372pub struct RouterEntry {
373    /// Destination block.
374    pub dst: DstBlk,
375    /// Source block.
376    pub src: SrcBlk,
377    /// Detected level of audio signal.
378    pub peak: u16,
379}
380
381/// Entry of stream format.
382#[derive(Default, Debug, Clone, PartialEq, Eq)]
383pub struct FormatEntry {
384    /// The number of PCM channels.
385    pub pcm_count: u8,
386    /// The number of MIDI channels.
387    pub midi_count: u8,
388    /// Labels for the channels.
389    pub labels: Vec<String>,
390    /// AC3 capabilities.
391    pub enable_ac3: [bool; AC3_CHANNELS],
392}
393
394/// The number of channels in stream format for AC3 channels.
395pub 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}