firewire_bebob_protocols/focusrite/
saffire.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2021 Takashi Sakamoto
3
4//! Protocol implementation for Focusrite Saffire and Saffire LE.
5//!
6//! The module includes structure, enumeration, and trait and its implementation for protocol
7//! defined by Focusrite Audio Engineering for Saffire and Saffire LE.
8//!
9//! DM1000E ASIC is used for Saffire, while DM1000 ASIC is used for Saffire LE.
10//!
11//! ## Diagram of internal signal flow for Saffire.
12//!
13//! ```text
14//!                              ++=========++
15//! analog-input-1/2 -------+--> || effects || --+---------+-------------> stream-output-1/2
16//!                         v    ++=========++   |         |
17//! spdif-input-1/2  ----> or -------------------|--+------|-------------> stream-output-3/4
18//!                                              |  |      v
19//!                                              |  | ++=========+
20//!                                              |  | || reverb ||
21//!                                              |  | ++========++
22//!                                              |  |      |
23//!                                              v  v      v
24//!                                         ++===============++
25//! stream-input-1/2 ---------------------> ||               || ---------> analog-output-1/2
26//! stream-input-3/4 ---------------------> ||     mixer     || ---------> analog-output-3/4
27//! stream-input-5/6 ---------------------> ||               || ---------> analog-output-5/6
28//! stream-input-7/8 ---------------------> ||    16 x 10    || ---------> analog-output-7/8
29//! stream-input-9/10 --------------------> ||               || ---------> analog-output-9/10
30//!                                         ++===============++
31//! ```
32//!
33//! The protocol implementation for Saffire is done with firmware version below:
34//!
35//! ```sh
36//! $ cargo run --bin bco-bootloader-info -- /dev/fw1
37//! protocol:
38//!   version: 1
39//! bootloader:
40//!   timestamp: 2005-05-17T02:19:34+0000
41//!   version: 0.0.0
42//! hardware:
43//!   GUID: 0x0001007200130e01
44//!   model ID: 0x000002
45//!   revision: 0.0.1
46//! software:
47//!   timestamp: 2009-02-16T08:52:00+0000
48//!   ID: 0
49//!   revision: 2.2.7869
50//! image:
51//!   base address: 0x20080000
52//!   maximum size: 0x180000
53//! ```
54//!
55//! ## Diagram of internal signal flow at 44.1/48.0 kHz for Saffire LE.
56//!
57//! ```text
58//! analog-input-1/2 ------------+------------------> stream-output-1/2
59//! analog-input-3/4 ------------|-+----------------> stream-output-3/4
60//! spdif-input-1/2  ------------|-|-+--------------> stream-output-5/6
61//!                              | | |
62//!                              v v v
63//!                         ++===========++
64//! stream-input-1/2 -----> ||           || ----+---> analog-output-1/2
65//! stream-input-3/4 -----> ||   mixer   || ----|---> analog-output-3/4
66//! stream-input-5/6 -----> ||  14 x 8   || ----|---> analog-output-5/6
67//! stream-input-7/8 -----> ||           || ----|---> digital-output-1/2
68//!                         ++===========++     |             v
69//!                                             +----------> or ----> spdif-output-1/2
70//! ```
71//!
72//! ## Diagram of internal signal flow at 88.2/96.0 kHz for Saffire LE.
73//!
74//! ```text
75//! analog-input-1/2 ------------+------------------> stream-output-1/2
76//! analog-input-3/4 ------------|-+----------------> stream-output-3/4
77//! spdif-input-1/2  ------------|-|-+--------------> stream-output-5/6
78//!                              | | |
79//!                              v v v
80//!                         ++===========++
81//!                         ||  monitor  ||
82//!                         ||   6 x 2   ||
83//!                         ++===========++
84//!                                |
85//!                                v
86//!                         ++===========++
87//! stream-input-1/2 -----> ||   mixer   || ----+---> analog-output-1/2
88//! stream-input-3/4 -----> ||   6 x 4   || ----|---> analog-output-3/4
89//!                         ++===========++     |
90//! stream-input-5/6 ---------------------------|---> analog-output-5/6
91//!                                             v
92//! stream-input-7/8 --------------------------or---> digital-output-1/2
93//! ```
94//!
95//! The protocol implementation for Saffire LE is done with firmware version below:
96//!
97//! ```sh
98//! $ cargo run --bin bco-bootloader-info -- /dev/fw1
99//! protocol:
100//!   version: 1
101//! bootloader:
102//!   timestamp: 2005-10-19T09:49:52+0000
103//!   version: 0.0.0
104//! hardware:
105//!   GUID: 0x00040e1a00130e01
106//!   model ID: 0x000002
107//!   revision: 0.0.1
108//! software:
109//!   timestamp: 2006-12-07T02:08:26+0000
110//!   ID: 0
111//!   revision: 1.1.7442
112//! image:
113//!   base address: 0x20080000
114//!   maximum size: 0x180000
115//! ```
116
117use super::*;
118
119/// The protocol implementation of media and sampling clocks for Saffire. 192.0 kHz is available
120/// when configured by the other operation.
121#[derive(Default, Debug)]
122pub struct SaffireClkProtocol;
123
124const SAFFIRE_MODE_192KHZ_OFFSET: usize = 0x138;
125
126impl MediaClockFrequencyOperation for SaffireClkProtocol {
127    const FREQ_LIST: &'static [u32] = &[44100, 48000, 88200, 96000, 192000];
128
129    fn update_freq(
130        avc: &BebobAvc,
131        params: &MediaClockParameters,
132        old: &mut MediaClockParameters,
133        timeout_ms: u32,
134    ) -> Result<(), Error> {
135        // 192 kHz is just available when enabled.
136        let mut op = SaffireAvcOperation {
137            offsets: vec![SAFFIRE_MODE_192KHZ_OFFSET],
138            buf: vec![0; 4],
139            ..Default::default()
140        };
141        avc.status(&AvcAddr::Unit, &mut op, timeout_ms)?;
142
143        let mut quadlet = [0; 4];
144        quadlet.copy_from_slice(&mut op.buf);
145        let val = u32::from_be_bytes(quadlet);
146        if (val > 0 && params.freq_idx < 4) || (val == 0 && params.freq_idx == 4) {
147            let msg = format!(
148                "Invalid frequency of media clock: {}",
149                Self::FREQ_LIST[params.freq_idx]
150            );
151            Err(Error::new(FileError::Inval, &msg))?;
152        }
153
154        let fdf = Self::FREQ_LIST
155            .iter()
156            .nth(params.freq_idx)
157            .ok_or_else(|| {
158                let msg = format!(
159                    "Invalid argument for index of frequency: {}",
160                    params.freq_idx
161                );
162                Error::new(FileError::Inval, &msg)
163            })
164            .map(|&freq| AmdtpFdf::new(AmdtpEventType::Am824, false, freq))?;
165
166        let mut op = InputPlugSignalFormat(PlugSignalFormat {
167            plug_id: 0,
168            fmt: FMT_IS_AMDTP,
169            fdf: fdf.into(),
170        });
171        avc.control(&AvcAddr::Unit, &mut op, timeout_ms)?;
172
173        let mut op = OutputPlugSignalFormat(PlugSignalFormat {
174            plug_id: 0,
175            fmt: FMT_IS_AMDTP,
176            fdf: fdf.into(),
177        });
178        avc.control(&AvcAddr::Unit, &mut op, timeout_ms)?;
179
180        *old = *params;
181
182        Ok(())
183    }
184}
185
186impl SamplingClockSourceOperation for SaffireClkProtocol {
187    const DST: SignalAddr = SignalAddr::Subunit(SignalSubunitAddr {
188        subunit: MUSIC_SUBUNIT_0,
189        plug_id: 0x04,
190    });
191
192    const SRC_LIST: &'static [SignalAddr] = &[
193        // Internal.
194        SignalAddr::Subunit(SignalSubunitAddr {
195            subunit: MUSIC_SUBUNIT_0,
196            plug_id: 0x07,
197        }),
198        // S/PDIF in coaxial interface.
199        SignalAddr::Unit(SignalUnitAddr::Ext(0x03)),
200    ];
201}
202
203/// Information of hardware metering in Saffire.
204#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
205pub struct SaffireMeter {
206    /// Detected level of inputs.
207    pub phys_inputs: [i32; 4],
208    /// Whether to detect any type of digital inputs.
209    pub dig_input_detect: bool,
210    /// The value of hardware knob.
211    pub monitor_knob_value: u16,
212}
213
214/// The protocol implementation of metering in Saffire.
215#[derive(Default, Debug)]
216pub struct SaffireMeterProtocol;
217
218impl SaffireMeterProtocol {
219    /// The minimum value of hardware knob.
220    pub const MONITOR_KNOB_MIN: u16 = 0;
221    /// The maximum value of hardware knob.
222    pub const MONITOR_KNOB_MAX: u16 = 0x1ff0;
223    /// The step value of hardware knob.
224    pub const MONITOR_KNOB_STEP: u16 = 0x10;
225
226    /// The minimum value of detected signal level.
227    pub const LEVEL_MIN: i32 = 0;
228    /// The maximum value of detected signal level.
229    pub const LEVEL_MAX: i32 = 0x7fffffff;
230    /// The step value of detected signal level.
231    pub const LEVEL_STEP: i32 = 1;
232
233    const OFFSETS: &'static [usize] = &[
234        0x00f4, // The value of monitor knob.
235        0x0100, // The signal level of analog-input-0.
236        0x0104, // The signal level of analog-input-2.
237        0x0108, // The signal level of analog-input-1.
238        0x010c, // The signal level of analog-input-3.
239        0x013c, // Whether to detect digital input.
240    ];
241
242    /// Cache the state of hardware to the parameter.
243    pub fn cache(
244        req: &FwReq,
245        node: &FwNode,
246        meter: &mut SaffireMeter,
247        timeout_ms: u32,
248    ) -> Result<(), Error> {
249        let mut raw = [0u8; Self::OFFSETS.len() * 4];
250
251        saffire_read_quadlets(req, node, Self::OFFSETS, &mut raw, timeout_ms).map(|_| {
252            let mut quadlet = [0u8; 4];
253            quadlet.copy_from_slice(&raw[..4]);
254            meter.monitor_knob_value = (u32::from_be_bytes(quadlet) & 0x0000ffff) as u16;
255
256            meter
257                .phys_inputs
258                .iter_mut()
259                .enumerate()
260                .for_each(|(i, level)| {
261                    let pos = 4 + i * 4;
262                    quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
263                    *level = i32::from_be_bytes(quadlet);
264                });
265
266            quadlet.copy_from_slice(&raw[20..]);
267            meter.dig_input_detect = u32::from_be_bytes(quadlet) > 0;
268        })
269    }
270}
271
272/// The protocol implementation for operation of output parameters in Saffire.
273#[derive(Default, Debug)]
274pub struct SaffireOutputProtocol;
275
276impl SaffireOutputSpecification for SaffireOutputProtocol {
277    // physical-output-1/2, 3/4, 5/6, 7/8, and digital-output-1/2.
278    const OUTPUT_OFFSETS: &'static [usize] = &[0xdc, 0xe0, 0xe4, 0xe8, 0xec];
279
280    const MUTE_COUNT: usize = 5;
281    const VOL_COUNT: usize = 4;
282    const HWCTL_COUNT: usize = 4;
283    const DIM_COUNT: usize = 1;
284    const PAD_COUNT: usize = 0;
285}
286
287/// The signal source of input 2/3.
288#[derive(Debug, Copy, Clone, Eq, PartialEq)]
289pub enum SaffireInputPair1Source {
290    /// 1st pair of analog inputs.
291    AnalogInputPair0,
292    /// 1st pair of digital inputs.
293    DigitalInputPair0,
294}
295
296impl Default for SaffireInputPair1Source {
297    fn default() -> Self {
298        Self::AnalogInputPair0
299    }
300}
301
302/// The mode of signal multiplexer.
303#[derive(Debug, Copy, Clone, Eq, PartialEq)]
304pub enum SaffireMixerMode {
305    /// Stereo mode.
306    StereoPaired,
307    /// Monaural mode.
308    StereoSeparated,
309}
310
311impl Default for SaffireMixerMode {
312    fn default() -> Self {
313        Self::StereoPaired
314    }
315}
316
317/// Parameters specific to Saffire.
318#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
319pub struct SaffireSpecificParameters {
320    /// 176.4/192.0 kHz mode. This brings bus reset in IEEE 1394 bus.
321    pub mode_192khz: bool,
322    /// Use 1st pair of analog inputs for capture inputs.
323    pub input_pair_1_src: SaffireInputPair1Source,
324    /// The mode of mixer.
325    pub mixer_mode: SaffireMixerMode,
326}
327
328/// The protocol implementation for operation specific to Saffire.
329#[derive(Default, Debug)]
330pub struct SaffireSpecificProtocol;
331
332impl SaffireParametersSerdes<SaffireSpecificParameters> for SaffireSpecificProtocol {
333    const OFFSETS: &'static [usize] = &[
334        SAFFIRE_MODE_192KHZ_OFFSET,
335        SAFFIRE_INPUT_PAIR1_SRC_OFFSET,
336        SAFFIRE_MIXER_MODE_OFFSET,
337    ];
338
339    fn serialize(params: &SaffireSpecificParameters, raw: &mut [u8]) {
340        raw[..4].copy_from_slice(&(params.mode_192khz as u32).to_be_bytes());
341
342        let val: u32 = if params.input_pair_1_src == SaffireInputPair1Source::DigitalInputPair0 {
343            1
344        } else {
345            0
346        };
347        raw[4..8].copy_from_slice(&val.to_be_bytes());
348
349        let val: u32 = if params.mixer_mode == SaffireMixerMode::StereoSeparated {
350            1
351        } else {
352            0
353        };
354        raw[8..12].copy_from_slice(&val.to_be_bytes());
355    }
356
357    fn deserialize(params: &mut SaffireSpecificParameters, raw: &[u8]) {
358        let mut quadlet = [0u8; 4];
359
360        let quads: Vec<u32> = (0..raw.len())
361            .step_by(4)
362            .map(|pos| {
363                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
364                u32::from_be_bytes(quadlet)
365            })
366            .collect();
367
368        params.mode_192khz = quads[0] > 0;
369
370        params.input_pair_1_src = if quads[1] > 0 {
371            SaffireInputPair1Source::DigitalInputPair0
372        } else {
373            SaffireInputPair1Source::AnalogInputPair0
374        };
375
376        params.mixer_mode = if quads[2] > 0 {
377            SaffireMixerMode::StereoSeparated
378        } else {
379            SaffireMixerMode::StereoPaired
380        };
381    }
382}
383
384const SAFFIRE_INPUT_PAIR1_SRC_OFFSET: usize = 0xf8;
385const SAFFIRE_MIXER_MODE_OFFSET: usize = 0xfc;
386
387/// The protocol implementation for operation of mixer at stereo separated mode in Saffire.
388#[derive(Default, Debug)]
389pub struct SaffireSeparatedMixerProtocol;
390
391impl SaffireMixerSpecification for SaffireSeparatedMixerProtocol {
392    const MIXER_OFFSETS: &'static [usize] = &[
393        // level from phys-input-0
394        0x00, // to phys-output-8
395        0x04, // to phys-output-0
396        0x08, // to phys-output-2
397        0x0c, // to phys-output-4
398        0x10, // to phys-output-6
399        // level from phys-input-2
400        0x14, // to phys-output-8
401        0x18, // to phys-output-0
402        0x1c, // to phys-output-2
403        0x20, // to phys-output-4
404        0x24, // to phys-output-6
405        // level from reverb-output-0
406        0x28, // to phys-output-8
407        0x2c, // to phys-output-0
408        0x30, // to phys-output-2
409        0x34, // to phys-output-4
410        0x38, // to phys-output-6
411        // level from phys-input-1
412        0x3c, // to phys-output-9
413        0x40, // to phys-output-1
414        0x44, // to phys-output-3
415        0x48, // to phys-output-5
416        0x4c, // to phys-output-7
417        // level from phys-input-3
418        0x50, // to phys-output-9
419        0x54, // to phys-output-1
420        0x58, // to phys-output-3
421        0x5c, // to phys-output-5
422        0x60, // to phys-output-7
423        // level from reverb-output-1
424        0x64, // to phys-output-9
425        0x68, // to phys-output-1
426        0x6c, // to phys-output-3
427        0x70, // to phys-output-5
428        0x74, // to phys-output-7
429        // level from stream-input-8/9
430        0x78, // to phys-output-8/9
431        0x7c, // to phys-output-0/1
432        0x80, // to phys-output-2/3
433        0x84, // to phys-output-4/5
434        0x88, // to phys-output-6/7
435        // level from stream-input-0/1
436        0x8c, // to phys-output-8/9
437        0x90, // to phys-output-0/1
438        0x94, // to phys-output-2/3
439        0x98, // to phys-output-4/5
440        0x9c, // to phys-output-6/7
441        // level from stream-input-2/3
442        0xa0, // to phys-output-8/9
443        0xa4, // to phys-output-0/1
444        0xa8, // to phys-output-2/3
445        0xac, // to phys-output-4/5
446        0xb0, // to phys-output-6/7
447        // level from stream-input-4/5
448        0xb4, // to phys-output-8/9
449        0xb8, // to phys-output-0/1
450        0xbc, // to phys-output-2/3
451        0xc0, // to phys-output-4/5
452        0xc4, // to phys-output-6/7
453        // level from stream-input-6/7
454        0xc8, // to phys-output-8/9
455        0xcc, // to phys-output-0/1
456        0xd0, // to phys-output-2/3
457        0xd4, // to phys-output-4/5
458        0xd8, // to phys-output-6/7
459    ];
460
461    const PHYS_INPUT_COUNT: usize = 4;
462    const REVERB_RETURN_COUNT: usize = 2;
463
464    #[inline(always)]
465    fn phys_src_pos(dst_idx: usize, src_idx: usize) -> usize {
466        ((dst_idx + 1) % 5) + ((src_idx % 2 * 15) + (src_idx / 2 * 5))
467    }
468
469    #[inline(always)]
470    fn reverb_return_pos(dst_idx: usize, src_idx: usize) -> usize {
471        10 + ((dst_idx + 1) % 5) + ((src_idx % 2 * 15) + (src_idx / 2 * 5))
472    }
473
474    #[inline(always)]
475    fn stream_src_pos(dst_idx: usize, src_idx: usize) -> usize {
476        30 + ((dst_idx + 1) % 5) + ((src_idx + 1) % 5) * 5
477    }
478}
479
480/// The protocol implementation for operation of mixer at stereo paired mode in Saffire.
481#[derive(Default, Debug)]
482pub struct SaffirePairedMixerProtocol;
483
484impl SaffireMixerSpecification for SaffirePairedMixerProtocol {
485    const MIXER_OFFSETS: &'static [usize] = &[
486        // level from stream-input-8/9
487        0x00, // to phys-output-8/9
488        0x04, // to phys-output-0/1
489        0x08, // to phys-output-2/3
490        0x0c, // to phys-output-4/5
491        0x10, // to phys-output-6/7
492        // level from stream-input-0/1
493        0x14, // to phys-output-8/9
494        0x18, // to phys-output-0/1
495        0x1c, // to phys-output-2/3
496        0x20, // to phys-output-4/5
497        0x24, // to phys-output-6/7
498        // level from stream-input-2/3
499        0x28, // to phys-output-8/9
500        0x2c, // to phys-output-0/1
501        0x30, // to phys-output-2/3
502        0x34, // to phys-output-4/5
503        0x38, // to phys-output-6/7
504        // level from stream-input-4/5
505        0x3c, // to phys-output-8/9
506        0x40, // to phys-output-0/1
507        0x44, // to phys-output-2/3
508        0x48, // to phys-output-4/5
509        0x4c, // to phys-output-6/7
510        // level from stream-input-6/7
511        0x50, // to phys-output-8/9
512        0x54, // to phys-output-0/1
513        0x58, // to phys-output-2/3
514        0x5c, // to phys-output-4/5
515        0x60, // to phys-output-6/7
516        // level from phys-input-0/1
517        0x64, // to phys-output-8/9
518        0x68, // to phys-output-0/1
519        0x6c, // to phys-output-2/3
520        0x70, // to phys-output-4/5
521        0x74, // to phys-output-6/7
522        // level from phys-input-2/3
523        0x78, // to phys-output-8/9
524        0x7c, // to phys-output-0/1
525        0x80, // to phys-output-2/3
526        0x84, // to phys-output-4/5
527        0x88, // to phys-output-6/7
528        // level from reverb-output-0/1
529        0x8c, // to phys-output-8/9
530        0x90, // to phys-output-0/1
531        0x94, // to phys-output-2/3
532        0x98, // to phys-output-4/5
533        0x9c, // to phys-output-6/7
534    ];
535
536    const PHYS_INPUT_COUNT: usize = 2;
537    const REVERB_RETURN_COUNT: usize = 1;
538
539    #[inline(always)]
540    fn stream_src_pos(dst_idx: usize, src_idx: usize) -> usize {
541        ((src_idx + 1) % 5 * 5) + ((dst_idx + 1) % 5)
542    }
543
544    #[inline(always)]
545    fn phys_src_pos(dst_idx: usize, src_idx: usize) -> usize {
546        25 + src_idx * 5 + (dst_idx + 1) % 5
547    }
548
549    #[inline(always)]
550    fn reverb_return_pos(dst_idx: usize, _: usize) -> usize {
551        35 + (dst_idx + 1) % 5
552    }
553}
554
555/// The protocol implementation of media and sampling clocks for Saffire LE.
556#[derive(Default, Debug)]
557pub struct SaffireLeClkProtocol;
558
559impl MediaClockFrequencyOperation for SaffireLeClkProtocol {
560    const FREQ_LIST: &'static [u32] = &[44100, 48000, 88200, 96000];
561}
562
563impl SamplingClockSourceOperation for SaffireLeClkProtocol {
564    const DST: SignalAddr = SignalAddr::Subunit(SignalSubunitAddr {
565        subunit: MUSIC_SUBUNIT_0,
566        plug_id: 0x05,
567    });
568
569    const SRC_LIST: &'static [SignalAddr] = &[
570        // Internal.
571        SignalAddr::Subunit(SignalSubunitAddr {
572            subunit: MUSIC_SUBUNIT_0,
573            plug_id: 0x06,
574        }),
575        // S/PDIF in coaxial interface.
576        SignalAddr::Unit(SignalUnitAddr::Ext(0x04)),
577    ];
578}
579
580/// The protocol implementation to store configuration in Saffire.
581#[derive(Default, Debug)]
582pub struct SaffireStoreConfigProtocol;
583
584impl SaffireStoreConfigSpecification for SaffireStoreConfigProtocol {
585    const STORE_CONFIG_OFFSETS: &'static [usize] = &[0x148];
586}
587
588/// Information of hardware metering in Saffire LE.
589#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
590pub struct SaffireLeMeter {
591    /// The detected level of physical inputs.
592    pub phys_inputs: [i32; 6],
593    /// The detected level of physical outputs.
594    pub phys_outputs: [i32; 8],
595    /// The detected level of stream inputs.
596    pub stream_inputs: [i32; 4],
597    /// Whether to detect any type of digital inputs.
598    pub dig_input_detect: bool,
599}
600
601/// The protocol implementation of metering in Saffire LE.
602#[derive(Default, Debug)]
603pub struct SaffireLeMeterProtocol;
604
605// NOTE: range 0x168-1b0.
606impl SaffireLeMeterProtocol {
607    /// The minimum value of detected signal level.
608    pub const LEVEL_MIN: i32 = 0;
609    /// The maximum value of detected signal level.
610    pub const LEVEL_MAX: i32 = 0x7fffffff;
611    /// The step value of detected signal level.
612    pub const LEVEL_STEP: i32 = 1;
613
614    const OFFSETS: &'static [usize] = &[
615        0x0168, // The signal level of analog-input-0.
616        0x016c, // The signal level of analog-input-2.
617        0x0170, // The signal level of digital-input-0.
618        0x0174, // The signal level of analog-input-1.
619        0x0178, // The signal level of analog-input-3.
620        0x017c, // The signal level of digital-input-1.
621        0x0180, // The signal level of analog-output-0.
622        0x0184, // The signal level of analog-output-2.
623        0x0188, // The signal level of analog-output-1.
624        0x018c, // The signal level of analog-output-3.
625        0x0190, // The signal level of analog-output-4.
626        0x0194, // The signal level of digital-output-0.
627        0x0198, // The signal level of analog-output-5.
628        0x019c, // The signal level of digital-output-1.
629        0x01a0, // The signal level of stream-input-0.
630        0x01a4, // The signal level of stream-input-2.
631        0x01a8, // The signal level of stream-input-1.
632        0x01ac, // The signal level of stream-input-3.
633        0x01b0, // Whether to detect digital input.
634    ];
635
636    /// Cache the state of hardware to the parameter.
637    pub fn cache(
638        req: &FwReq,
639        node: &FwNode,
640        meter: &mut SaffireLeMeter,
641        timeout_ms: u32,
642    ) -> Result<(), Error> {
643        let mut raw = [0u8; Self::OFFSETS.len() * 4];
644        saffire_read_quadlets(req, node, Self::OFFSETS, &mut raw, timeout_ms).map(|_| {
645            let mut quadlet = [0; 4];
646            let vals: Vec<i32> = (0..Self::OFFSETS.len())
647                .map(|i| {
648                    let pos = i * 4;
649                    quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
650                    i32::from_be_bytes(quadlet)
651                })
652                .collect();
653
654            meter.phys_inputs[0] = vals[0];
655            meter.phys_inputs[2] = vals[1];
656            meter.phys_inputs[4] = vals[2];
657            meter.phys_inputs[1] = vals[3];
658            meter.phys_inputs[3] = vals[4];
659            meter.phys_inputs[5] = vals[5];
660
661            meter.phys_outputs[0] = vals[6];
662            meter.phys_outputs[2] = vals[7];
663            meter.phys_outputs[1] = vals[8];
664            meter.phys_outputs[3] = vals[9];
665            meter.phys_outputs[4] = vals[10];
666            meter.phys_outputs[6] = vals[11];
667            meter.phys_outputs[5] = vals[12];
668            meter.phys_outputs[7] = vals[13];
669
670            meter.stream_inputs[0] = vals[14];
671            meter.stream_inputs[2] = vals[15];
672            meter.stream_inputs[1] = vals[16];
673            meter.stream_inputs[3] = vals[17];
674
675            meter.dig_input_detect = vals[18] > 0;
676        })
677    }
678}
679
680/// The protocol implementation for operation of output parameters in Saffire.
681#[derive(Default, Debug)]
682pub struct SaffireLeOutputProtocol;
683
684impl SaffireOutputSpecification for SaffireLeOutputProtocol {
685    // physical-output-1/2, 3/4, 5/6, 7/8, and digital-output-1/2.
686    const OUTPUT_OFFSETS: &'static [usize] = &[0x15c, 0x160, 0x164];
687
688    const MUTE_COUNT: usize = 3;
689    const VOL_COUNT: usize = 3;
690    const HWCTL_COUNT: usize = 0;
691    const DIM_COUNT: usize = 0;
692    const PAD_COUNT: usize = 0;
693}
694
695/// The parameters specific to Saffire.
696#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
697pub struct SaffireLeSpecificParameters {
698    pub analog_input_2_3_high_gains: [bool; 2],
699}
700
701/// The protocol implementation for operation specific to Saffire.
702#[derive(Default, Debug)]
703pub struct SaffireLeSpecificProtocol;
704
705impl SaffireParametersSerdes<SaffireLeSpecificParameters> for SaffireLeSpecificProtocol {
706    const OFFSETS: &'static [usize] = &[
707        0x154, // High gain mode at 3rd analog input.
708        0x158, // High gain mode at 4th analog input.
709    ];
710
711    fn serialize(params: &SaffireLeSpecificParameters, raw: &mut [u8]) {
712        raw[..4].copy_from_slice(&(params.analog_input_2_3_high_gains[0] as u32).to_be_bytes());
713        raw[4..8].copy_from_slice(&(params.analog_input_2_3_high_gains[1] as u32).to_be_bytes());
714    }
715
716    fn deserialize(params: &mut SaffireLeSpecificParameters, raw: &[u8]) {
717        let mut quadlet = [0u8; 4];
718
719        let quads: Vec<u32> = (0..raw.len())
720            .step_by(4)
721            .map(|pos| {
722                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
723                u32::from_be_bytes(quadlet)
724            })
725            .collect();
726
727        params
728            .analog_input_2_3_high_gains
729            .iter_mut()
730            .enumerate()
731            .for_each(|(i, enabled)| *enabled = quads[i] > 0);
732    }
733}
734
735/// Signal source of S/PDIF output.
736#[derive(Debug, Copy, Clone, PartialEq, Eq)]
737pub enum SaffireLeSpdifOutputSource {
738    /// 1st pair of mixer outputs.
739    MixerOutputPair01,
740    /// 2nd pair of mixer outputs.
741    MixerOutputPair67,
742}
743
744impl Default for SaffireLeSpdifOutputSource {
745    fn default() -> Self {
746        Self::MixerOutputPair01
747    }
748}
749
750/// State of signal multiplexer in Saffire LE at 44.1/48.0 kHz.
751#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
752pub struct SaffireLeMixerLowRateState {
753    /// The gain of physical inputs.
754    pub phys_src_gains: [[i16; 6]; 4],
755    /// The gain of stream inputs.
756    pub stream_src_gains: [[i16; 8]; 4],
757    /// The source of S/PDIF outputs.
758    pub spdif_out_src: SaffireLeSpdifOutputSource,
759}
760
761/// The protocol implementation for operation of mixer at 44.1/48.0 kHz in Saffire LE.
762#[derive(Default, Debug)]
763pub struct SaffireLeMixerLowRateProtocol;
764
765impl SaffireParametersSerdes<SaffireLeMixerLowRateState> for SaffireLeMixerLowRateProtocol {
766    const OFFSETS: &'static [usize] = &[
767        // level from stream-input-0
768        0x000, // output-1
769        0x004, // output-3
770        0x008, // output-0
771        0x00c, // output-2
772        // level from stream-input-2
773        0x010, // output-1
774        0x014, // output-3
775        0x018, // output-0
776        0x01c, // output-2
777        // level from stream-input-4
778        0x020, // output-1
779        0x024, // output-3
780        0x028, // output-0
781        0x02c, // output-2
782        // level from stream-input-6
783        0x030, // output-1
784        0x034, // output-3
785        0x038, // output-0
786        0x03c, // output-2
787        // level from stream-input-1
788        0x040, // output-1
789        0x044, // output-3
790        0x048, // output-0
791        0x04c, // output-2
792        // level from stream-input-3
793        0x050, // output-1
794        0x054, // output-3
795        0x058, // output-0
796        0x05c, // output-2
797        // level from stream-input-5
798        0x060, // output-1
799        0x064, // output-3
800        0x068, // output-0
801        0x06c, // output-2
802        // level from stream-input-7
803        0x070, // output-1
804        0x074, // output-3
805        0x078, // output-0
806        0x07c, // output-2
807        // level from analog-input-0
808        0x080, // to output-1
809        0x084, // to output-3
810        0x088, // to output-0
811        0x08c, // to output-2
812        // level from analog-input-2
813        0x090, // to output-1
814        0x094, // to output-3
815        0x098, // to output-0
816        0x09c, // to output-2
817        // level from analog-input-4
818        0x0a0, // to output-1
819        0x0a4, // to output-3
820        0x0a8, // to output-0
821        0x0ac, // to output-2
822        // level from analog-input-1
823        0x0b0, // to output-1
824        0x0b4, // to output-3
825        0x0b8, // to output-0
826        0x0bc, // to output-2
827        // level from analog-input-3
828        0x0c0, // to output-1
829        0x0c4, // to output-3
830        0x0c8, // to output-0
831        0x0cc, // to output-2
832        // level from analog-input-5
833        0x0d0, // to output-1
834        0x0d4, // to output-3
835        0x0d8, // to output-0
836        0x0dc, // to output-2
837        // source of S/PDIF output 0/1
838        0x100,
839    ];
840
841    fn serialize(params: &SaffireLeMixerLowRateState, raw: &mut [u8]) {
842        params
843            .stream_src_gains
844            .iter()
845            .enumerate()
846            .for_each(|(dst_idx, gains)| {
847                gains.iter().enumerate().for_each(|(src_idx, &gain)| {
848                    let pos = SaffireLeMixerLowRateProtocol::stream_src_pos(dst_idx, src_idx) * 4;
849                    let gain = gain as i32;
850                    raw[pos..(pos + 4)].copy_from_slice(&gain.to_be_bytes());
851                });
852            });
853
854        params
855            .phys_src_gains
856            .iter()
857            .enumerate()
858            .for_each(|(dst_idx, gains)| {
859                gains.iter().enumerate().for_each(|(src_idx, &gain)| {
860                    let pos = SaffireLeMixerLowRateProtocol::phys_src_pos(dst_idx, src_idx) * 4;
861                    let gain = gain as i32;
862                    raw[pos..(pos + 4)].copy_from_slice(&gain.to_be_bytes());
863                });
864            });
865
866        let val = match params.spdif_out_src {
867            SaffireLeSpdifOutputSource::MixerOutputPair67 => 1u32,
868            SaffireLeSpdifOutputSource::MixerOutputPair01 => 0,
869        };
870        raw[224..228].copy_from_slice(&val.to_be_bytes());
871    }
872
873    fn deserialize(params: &mut SaffireLeMixerLowRateState, raw: &[u8]) {
874        let mut quadlet = [0u8; 4];
875
876        let quads: Vec<u32> = (0..raw.len())
877            .step_by(4)
878            .map(|pos| {
879                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
880                u32::from_be_bytes(quadlet)
881            })
882            .collect();
883
884        params
885            .stream_src_gains
886            .iter_mut()
887            .enumerate()
888            .for_each(|(dst_idx, gains)| {
889                gains.iter_mut().enumerate().for_each(|(src_idx, gain)| {
890                    let pos = SaffireLeMixerLowRateProtocol::stream_src_pos(dst_idx, src_idx);
891                    *gain = quads[pos] as i16;
892                })
893            });
894
895        params
896            .phys_src_gains
897            .iter_mut()
898            .enumerate()
899            .for_each(|(dst_idx, gains)| {
900                gains.iter_mut().enumerate().for_each(|(src_idx, gain)| {
901                    let pos = SaffireLeMixerLowRateProtocol::phys_src_pos(dst_idx, src_idx);
902                    *gain = quads[pos] as i16;
903                })
904            });
905
906        params.spdif_out_src = if quads[56] != 0 {
907            SaffireLeSpdifOutputSource::MixerOutputPair67
908        } else {
909            SaffireLeSpdifOutputSource::MixerOutputPair01
910        };
911    }
912}
913
914impl SaffireLeMixerLowRateProtocol {
915    /// The minimum value of mixer inputs.
916    pub const LEVEL_MIN: i16 = 0;
917    /// The maximum value of mixer inputs.
918    pub const LEVEL_MAX: i16 = 0x7fff;
919    /// The step value of mixer inputs.
920    pub const LEVEL_STEP: i16 = 0x100;
921
922    #[inline(always)]
923    fn stream_src_pos(dst_idx: usize, src_idx: usize) -> usize {
924        assert!(dst_idx < 4);
925        assert!(src_idx < 8);
926
927        Self::compute_pos(dst_idx, src_idx, 4, 8)
928    }
929
930    #[inline(always)]
931    fn phys_src_pos(dst_idx: usize, src_idx: usize) -> usize {
932        assert!(dst_idx < 4);
933        assert!(src_idx < 6);
934
935        32 + Self::compute_pos(dst_idx, src_idx, 4, 6)
936    }
937
938    #[inline(always)]
939    fn compute_pos(dst_idx: usize, src_idx: usize, dst_count: usize, src_count: usize) -> usize {
940        let pair_gap = dst_count * src_count / 2;
941        ((1 - dst_idx % 2) * 2 + dst_idx / 2 % 2) + (src_idx % 2 * pair_gap + src_idx / 2 * 4)
942    }
943}
944
945/// State of signal multiplexer in Saffire LE at 88.2/96.0 kHz.
946#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
947pub struct SaffireLeMixerMiddleRateState {
948    /// The gain of mixer sources from physical inputs.
949    pub monitor_src_phys_input_gains: [i16; 6],
950    /// The gain of mixer sources from monitor.
951    pub monitor_out_src_pair_gains: [[i16; 1]; 4],
952    /// The gain of mixer source from stream inputs.
953    pub stream_src_pair_gains: [[i16; 2]; 4],
954    /// The source of S/PDIF outputs.
955    pub spdif_out_src: SaffireLeSpdifOutputSource,
956}
957
958impl SaffireParametersSerdes<SaffireLeMixerMiddleRateState> for SaffireLeMixerMiddleRateProtocol {
959    const OFFSETS: &'static [usize] = &[
960        // level to monitor-output-0/1
961        0x108, // from analog-input-0
962        0x10c, // from analog-input-2
963        0x110, // from analog-input-4
964        0x114, // from analog-input-1
965        0x118, // from analog-input-3
966        0x11c, // from analog-input-5
967        // level to output-0
968        0x120, // from monitor-output-0/1
969        0x124, // from stream-input-0/1
970        0x128, // from stream-input-2/3
971        // level to output-1
972        0x12c, // from monitor-output-0/1
973        0x130, // from stream-input-0/1
974        0x134, // from stream-input-2/3
975        // level to output-2
976        0x138, // from monitor-output-0/1
977        0x13c, // from stream-input-0/1
978        0x140, // from stream-input-2/3
979        // level to output-3
980        0x144, // from monitor-output-0/1
981        0x148, // from stream-input-0/1
982        0x14c, // from stream-input-2/3
983        // source of S/PDIF output 0/1.
984        0x150,
985    ];
986
987    fn serialize(params: &SaffireLeMixerMiddleRateState, raw: &mut [u8]) {
988        params
989            .monitor_src_phys_input_gains
990            .iter()
991            .enumerate()
992            .for_each(|(src_idx, &gain)| {
993                let gain = gain as i32;
994                let pos =
995                    SaffireLeMixerMiddleRateProtocol::monitor_analog_input_pos(0, src_idx) * 4;
996                raw[pos..(pos + 4)].copy_from_slice(&gain.to_be_bytes());
997            });
998
999        params
1000            .monitor_out_src_pair_gains
1001            .iter()
1002            .enumerate()
1003            .for_each(|(dst_idx, gains)| {
1004                gains.iter().enumerate().for_each(|(src_idx, &gain)| {
1005                    let gain = gain as i32;
1006                    let pos =
1007                        SaffireLeMixerMiddleRateProtocol::mixer_monitor_src_pos(dst_idx, src_idx)
1008                            * 4;
1009                    raw[pos..(pos + 4)].copy_from_slice(&gain.to_be_bytes());
1010                });
1011            });
1012
1013        params
1014            .stream_src_pair_gains
1015            .iter()
1016            .enumerate()
1017            .for_each(|(dst_idx, gains)| {
1018                gains.iter().enumerate().for_each(|(src_idx, &gain)| {
1019                    let gain = gain as i32;
1020                    let pos =
1021                        SaffireLeMixerMiddleRateProtocol::mixer_stream_input_pos(dst_idx, src_idx)
1022                            * 4;
1023                    raw[pos..(pos + 4)].copy_from_slice(&gain.to_be_bytes());
1024                });
1025            });
1026
1027        let val = if params.spdif_out_src == SaffireLeSpdifOutputSource::MixerOutputPair67 {
1028            1u32
1029        } else {
1030            0
1031        };
1032        raw[72..76].copy_from_slice(&val.to_be_bytes());
1033    }
1034
1035    fn deserialize(params: &mut SaffireLeMixerMiddleRateState, raw: &[u8]) {
1036        let mut quadlet = [0; 4];
1037
1038        let quads: Vec<i16> = (0..raw.len())
1039            .step_by(4)
1040            .map(|pos| {
1041                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
1042                i32::from_be_bytes(quadlet) as i16
1043            })
1044            .collect();
1045
1046        params
1047            .monitor_src_phys_input_gains
1048            .iter_mut()
1049            .enumerate()
1050            .for_each(|(src_idx, gain)| {
1051                let pos = SaffireLeMixerMiddleRateProtocol::monitor_analog_input_pos(0, src_idx);
1052                *gain = quads[pos];
1053            });
1054
1055        params
1056            .monitor_out_src_pair_gains
1057            .iter_mut()
1058            .enumerate()
1059            .for_each(|(dst_idx, gains)| {
1060                gains.iter_mut().enumerate().for_each(|(src_idx, gain)| {
1061                    let pos =
1062                        SaffireLeMixerMiddleRateProtocol::mixer_monitor_src_pos(dst_idx, src_idx);
1063                    *gain = quads[pos];
1064                });
1065            });
1066
1067        params
1068            .stream_src_pair_gains
1069            .iter_mut()
1070            .enumerate()
1071            .for_each(|(dst_idx, gains)| {
1072                gains.iter_mut().enumerate().for_each(|(src_idx, gain)| {
1073                    let pos =
1074                        SaffireLeMixerMiddleRateProtocol::mixer_stream_input_pos(dst_idx, src_idx);
1075                    *gain = quads[pos];
1076                });
1077            });
1078
1079        params.spdif_out_src = if quads[18] > 0 {
1080            SaffireLeSpdifOutputSource::MixerOutputPair67
1081        } else {
1082            SaffireLeSpdifOutputSource::MixerOutputPair01
1083        };
1084    }
1085}
1086
1087/// The protocol implementation for operation of mixer at 88.2/96.0 kHz in Saffire LE.
1088#[derive(Default, Debug)]
1089pub struct SaffireLeMixerMiddleRateProtocol;
1090
1091impl SaffireLeMixerMiddleRateProtocol {
1092    /// The minimum value of source level.
1093    pub const LEVEL_MIN: i16 = 0;
1094    /// The maximum value of source level.
1095    pub const LEVEL_MAX: i16 = 0x7fff;
1096    /// The step value of source level.
1097    pub const LEVEL_STEP: i16 = 0x100;
1098
1099    #[inline(always)]
1100    fn monitor_analog_input_pos(_: usize, src_idx: usize) -> usize {
1101        src_idx % 2 * 3 + src_idx / 2
1102    }
1103
1104    #[inline(always)]
1105    fn mixer_monitor_src_pos(dst_idx: usize, src_idx: usize) -> usize {
1106        6 + (dst_idx * 3) + src_idx
1107    }
1108
1109    #[inline(always)]
1110    fn mixer_stream_input_pos(dst_idx: usize, src_idx: usize) -> usize {
1111        6 + (dst_idx * 3) + src_idx + 1
1112    }
1113}
1114
1115/// The ptorocol implementation of AC3 and MIDI signal through.
1116#[derive(Default, Debug)]
1117pub struct SaffireLeThroughProtocol;
1118
1119impl SaffireThroughSpecification for SaffireLeThroughProtocol {
1120    const THROUGH_OFFSETS: &'static [usize] = &[0x01bc, 0x01c0];
1121}
1122
1123/// The protocol implementation to store configuration in Saffire.
1124#[derive(Default, Debug)]
1125pub struct SaffireLeStoreConfigProtocol;
1126
1127impl SaffireStoreConfigSpecification for SaffireLeStoreConfigProtocol {
1128    const STORE_CONFIG_OFFSETS: &'static [usize] = &[0x1b8];
1129}
1130
1131/// State of signal multiplexer in Saffire.
1132#[derive(Debug, Clone, PartialEq, Eq)]
1133pub struct SaffireMixerState {
1134    /// The level of physical inputs..
1135    pub phys_inputs: Vec<Vec<i16>>,
1136    /// The level of reverb returns.
1137    pub reverb_returns: Vec<Vec<i16>>,
1138    /// The level of stream inputs.
1139    pub stream_inputs: Vec<Vec<i16>>,
1140}
1141
1142/// The specification of protocol for mixer function.
1143pub trait SaffireMixerSpecification {
1144    /// The address offsets to operate for the parameters.
1145    const MIXER_OFFSETS: &'static [usize];
1146
1147    /// The number of physical inputs.
1148    const PHYS_INPUT_COUNT: usize;
1149
1150    /// The number of reverb returns.
1151    const REVERB_RETURN_COUNT: usize;
1152
1153    fn stream_src_pos(dst_idx: usize, src_idx: usize) -> usize;
1154    fn phys_src_pos(dst_idx: usize, src_idx: usize) -> usize;
1155    fn reverb_return_pos(dst_idx: usize, src_idx: usize) -> usize;
1156}
1157
1158impl<O: SaffireMixerSpecification> SaffireParametersSerdes<SaffireMixerState> for O {
1159    const OFFSETS: &'static [usize] = O::MIXER_OFFSETS;
1160
1161    fn serialize(params: &SaffireMixerState, raw: &mut [u8]) {
1162        params
1163            .phys_inputs
1164            .iter()
1165            .enumerate()
1166            .for_each(|(dst_idx, gains)| {
1167                gains.iter().enumerate().for_each(|(src_idx, &gain)| {
1168                    let pos = O::phys_src_pos(dst_idx, src_idx) * 4;
1169                    let gain = gain as i32;
1170                    raw[pos..(pos + 4)].copy_from_slice(&gain.to_be_bytes());
1171                });
1172            });
1173
1174        params
1175            .reverb_returns
1176            .iter()
1177            .enumerate()
1178            .for_each(|(dst_idx, gains)| {
1179                gains.iter().enumerate().for_each(|(src_idx, &gain)| {
1180                    let pos = O::reverb_return_pos(dst_idx, src_idx) * 4;
1181                    let gain = gain as i32;
1182                    raw[pos..(pos + 4)].copy_from_slice(&gain.to_be_bytes());
1183                });
1184            });
1185
1186        params
1187            .stream_inputs
1188            .iter()
1189            .enumerate()
1190            .for_each(|(dst_idx, gains)| {
1191                gains.iter().enumerate().for_each(|(src_idx, &gain)| {
1192                    let pos = O::stream_src_pos(dst_idx, src_idx) * 4;
1193                    let gain = gain as i32;
1194                    raw[pos..(pos + 4)].copy_from_slice(&gain.to_be_bytes());
1195                });
1196            });
1197    }
1198
1199    fn deserialize(params: &mut SaffireMixerState, raw: &[u8]) {
1200        let mut quadlet = [0; 4];
1201
1202        let quads: Vec<i16> = (0..raw.len())
1203            .step_by(4)
1204            .map(|pos| {
1205                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
1206                i32::from_be_bytes(quadlet) as i16
1207            })
1208            .collect();
1209
1210        params
1211            .phys_inputs
1212            .iter_mut()
1213            .enumerate()
1214            .for_each(|(dst_idx, gains)| {
1215                gains.iter_mut().enumerate().for_each(|(src_idx, gain)| {
1216                    let pos = O::phys_src_pos(dst_idx, src_idx);
1217                    *gain = quads[pos];
1218                });
1219            });
1220
1221        params
1222            .reverb_returns
1223            .iter_mut()
1224            .enumerate()
1225            .for_each(|(dst_idx, gains)| {
1226                gains.iter_mut().enumerate().for_each(|(src_idx, gain)| {
1227                    let pos = O::reverb_return_pos(dst_idx, src_idx);
1228                    *gain = quads[pos];
1229                });
1230            });
1231
1232        params
1233            .stream_inputs
1234            .iter_mut()
1235            .enumerate()
1236            .for_each(|(dst_idx, gains)| {
1237                gains.iter_mut().enumerate().for_each(|(src_idx, gain)| {
1238                    let pos = O::stream_src_pos(dst_idx, src_idx);
1239                    *gain = quads[pos];
1240                });
1241            });
1242    }
1243}
1244
1245/// The trait for mixer operation in Saffire.
1246pub trait SaffireMixerOperation: SaffireMixerSpecification {
1247    /// The number of stream inputs.
1248    const STREAM_INPUT_COUNT: usize = 5;
1249
1250    /// The number of output pairs.
1251    const OUTPUT_PAIR_COUNT: usize = 5;
1252
1253    /// The minimum value of source level.
1254    const LEVEL_MIN: i16 = 0x0000;
1255    /// The maximum value of source level.
1256    const LEVEL_MAX: i16 = 0x7fff;
1257    /// The step value of source level.
1258    const LEVEL_STEP: i16 = 0x100;
1259
1260    fn create_mixer_state() -> SaffireMixerState {
1261        SaffireMixerState {
1262            phys_inputs: vec![vec![0; Self::PHYS_INPUT_COUNT]; Self::OUTPUT_PAIR_COUNT],
1263            reverb_returns: vec![vec![0; Self::REVERB_RETURN_COUNT]; Self::OUTPUT_PAIR_COUNT],
1264            stream_inputs: vec![vec![0; Self::STREAM_INPUT_COUNT]; Self::OUTPUT_PAIR_COUNT],
1265        }
1266    }
1267}
1268
1269impl<O: SaffireMixerSpecification> SaffireMixerOperation for O {}
1270
1271/// State of stereo-separated reverb effect in Saffire.
1272#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1273pub struct SaffireReverbParameters {
1274    pub amounts: [i32; 2],
1275    pub room_sizes: [i32; 2],
1276    pub diffusions: [i32; 2],
1277    pub tones: [i32; 2],
1278}
1279
1280/// The protocol implementation to operate parameters of reverb effect.
1281///
1282/// parameters | ch0    | ch1    | minimum    | maximum    | min val  | max val
1283/// ---------- | ------ | ------ | ---------- | ---------- | -------- | --------
1284/// amount     | 0x1004 | 0x1018 | 0x00000000 | 0x7fffffff |    -     |    -
1285/// room_size  | 0x1008 | 0x101c | 0x00000000 | 0x7fffffff |    -     |    -
1286/// diffusion  | 0x100c | 0x1020 | 0x00000000 | 0x7fffffff |    -     |    -
1287/// tone sign  | 0x1010 | 0x1024 | 0x00000000 | 0x00000001 | positive | negative
1288/// tone value | 0x1014 | 0x1028 | 0x00000000 | 0x7fffffff |    -     |    -
1289#[derive(Default, Debug)]
1290pub struct SaffireReverbProtocol;
1291
1292impl SaffireParametersSerdes<SaffireReverbParameters> for SaffireReverbProtocol {
1293    const OFFSETS: &'static [usize] = &[
1294        // ch 0
1295        0x1004, // amount
1296        0x1008, // room-size
1297        0x100c, // diffusion
1298        0x1010, // tone-negative
1299        0x1014, // tone-value
1300        // ch 1
1301        0x1018, // amount
1302        0x101c, // room-size
1303        0x1020, // diffusion
1304        0x1024, // tone-negative
1305        0x1028, // tone-value
1306    ];
1307
1308    fn serialize(params: &SaffireReverbParameters, raw: &mut [u8]) {
1309        raw[..4].copy_from_slice(&params.amounts[0].to_be_bytes());
1310        raw[4..8].copy_from_slice(&params.room_sizes[0].to_be_bytes());
1311        raw[8..12].copy_from_slice(&params.diffusions[0].to_be_bytes());
1312        Self::build_tone(&mut raw[12..20], params.tones[0]);
1313
1314        raw[20..24].copy_from_slice(&params.amounts[1].to_be_bytes());
1315        raw[24..28].copy_from_slice(&params.room_sizes[1].to_be_bytes());
1316        raw[28..32].copy_from_slice(&params.diffusions[1].to_be_bytes());
1317        Self::build_tone(&mut raw[32..40], params.tones[1]);
1318    }
1319
1320    fn deserialize(params: &mut SaffireReverbParameters, raw: &[u8]) {
1321        let mut quadlet = [0u8; 4];
1322
1323        let quads: Vec<i32> = (0..raw.len())
1324            .step_by(4)
1325            .map(|pos| {
1326                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
1327                i32::from_be_bytes(quadlet)
1328            })
1329            .collect();
1330
1331        params.amounts[0] = quads[0];
1332        params.room_sizes[0] = quads[1];
1333        params.diffusions[0] = quads[2];
1334        params.tones[0] = Self::parse_tone(&quads[3..5]);
1335        params.amounts[1] = quads[5];
1336        params.room_sizes[1] = quads[6];
1337        params.diffusions[1] = quads[7];
1338        params.tones[1] = Self::parse_tone(&quads[8..10]);
1339    }
1340}
1341
1342impl SaffireReverbProtocol {
1343    pub const AMOUNT_MIN: i32 = 0x00000000;
1344    pub const AMOUNT_MAX: i32 = 0x7fffffff;
1345    pub const AMOUNT_STEP: i32 = 0x00000001;
1346
1347    pub const ROOM_SIZE_MIN: i32 = 0x00000000;
1348    pub const ROOM_SIZE_MAX: i32 = 0x7fffffff;
1349    pub const ROOM_SIZE_STEP: i32 = 0x00000001;
1350
1351    pub const DIFFUSION_MIN: i32 = 0x00000000;
1352    pub const DIFFUSION_MAX: i32 = 0x7fffffff;
1353    pub const DIFFUSION_STEP: i32 = 0x00000001;
1354
1355    pub const TONE_MIN: i32 = i32::MIN + 1;
1356    pub const TONE_MAX: i32 = i32::MAX;
1357    pub const TONE_STEP: i32 = 0x00000001;
1358
1359    fn parse_tone(vals: &[i32]) -> i32 {
1360        assert_eq!(vals.len(), 2);
1361        let mut tone = vals[1];
1362        if vals[0] > 0 {
1363            tone *= -1;
1364        }
1365        tone
1366    }
1367
1368    fn build_tone(vals: &mut [u8], tone: i32) {
1369        assert_eq!(vals.len(), 8);
1370        vals[..4].copy_from_slice(&((tone < 0) as u32).to_be_bytes());
1371        vals[4..].copy_from_slice(&(tone.abs() as u32).to_be_bytes());
1372    }
1373}
1374
1375/// Parameters of compressor effect in Saffire.
1376#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1377pub struct SaffireCompressorParameters {
1378    pub input_gains: [i32; 2],
1379    pub enables: [bool; 2],
1380    pub output_volumes: [i32; 2],
1381}
1382
1383/// The protocol implementation to operate compressor parameters.
1384///
1385/// parameters    | ch 0  | ch 1  | minimum    | maximum    | min val | max val
1386/// ------------- | ----- | ----- | ---------- | ---------- | ------- | -------
1387/// attack        | 0xc00 | 0xc28 | 0x81539001 | 0x8006d381 | 2 ms    | 100 ms
1388/// threshold     | 0xc04 | 0xc2c | 0x9c000001 | 0x00000000 | -50     | 0
1389/// release       | 0xc08 | 0xc30 | 0x7ff92c7f | 0x7fffc57f | 0.1 s   | 3.0 s
1390/// ratio         | 0xc0c | 0xc34 | 0x0666665f | 0x7f5c28ff | 1.1:1   | 100 ms
1391/// gain          | 0xc10 | 0xc38 | 0x0fffffff | 0x7f17aeff | 0       | +18
1392/// enable        | 0xc14 | 0xc3c | 0x00000000 | 0x7fffffff | disable | enable
1393/// input gain    | 0xc18 | 0xc40 | 0x0203a7e7 | 0x7f17aeff | -18     | +18
1394/// output volume | 0xc1c | 0xc44 | 0x0203a7e7 | 0x7f17aeff | -18     | +18
1395#[derive(Default, Debug)]
1396pub struct SaffireCompressorProtocol;
1397
1398impl SaffireParametersSerdes<SaffireCompressorParameters> for SaffireCompressorProtocol {
1399    const OFFSETS: &'static [usize] = &[
1400        // ch 0.
1401        0x0c00, 0x0c04, 0x0c08, 0x0c0c, 0x0c10, 0x0c14, 0x0c18, 0x0c1c, // ch 1.
1402        0x0c28, 0x0c2c, 0x0c30, 0x0c34, 0x0c38, 0x0c3c, 0x0c40, 0x0c48,
1403    ];
1404
1405    fn serialize(params: &SaffireCompressorParameters, raw: &mut [u8]) {
1406        raw[20..24].copy_from_slice(&(params.enables[0] as u32).to_be_bytes());
1407        raw[24..28].copy_from_slice(&params.input_gains[0].to_be_bytes());
1408        raw[28..32].copy_from_slice(&params.output_volumes[0].to_be_bytes());
1409        raw[52..56].copy_from_slice(&(params.enables[1] as u32).to_be_bytes());
1410        raw[56..60].copy_from_slice(&params.input_gains[1].to_be_bytes());
1411        raw[60..64].copy_from_slice(&params.output_volumes[1].to_be_bytes());
1412    }
1413
1414    fn deserialize(params: &mut SaffireCompressorParameters, raw: &[u8]) {
1415        let mut quadlet = [0u8; 4];
1416
1417        let quads: Vec<i32> = (0..raw.len())
1418            .step_by(4)
1419            .map(|pos| {
1420                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
1421                i32::from_be_bytes(quadlet)
1422            })
1423            .collect();
1424
1425        params.enables[0] = quads[5] > 0;
1426        params.enables[1] = quads[13] > 0;
1427        params.input_gains[0] = quads[6];
1428        params.input_gains[1] = quads[14];
1429        params.output_volumes[0] = quads[7];
1430        params.output_volumes[1] = quads[15];
1431    }
1432}
1433
1434impl SaffireCompressorProtocol {
1435    pub const GAIN_MIN: i32 = 0x0fffffff;
1436    pub const GAIN_MAX: i32 = 0x7fffffff;
1437    pub const GAIN_STEP: i32 = 1;
1438
1439    pub const VOLUME_MIN: i32 = 0x0fffffff;
1440    pub const VOLUME_MAX: i32 = 0x7fffffff;
1441    pub const VOLUME_STEP: i32 = 1;
1442}
1443
1444/// Parameters of equalizer effect in Saffire.
1445#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1446pub struct SaffireEqualizerParameters {
1447    pub enables: [bool; 2],
1448    pub input_gains: [i32; 2],
1449    pub output_volumes: [i32; 2],
1450}
1451
1452/// The protocol implementation to operate equalizer parameters.
1453///
1454/// parameters    | ch0    | ch1    | minimum    | maximum    | min val | max val
1455/// ------------- | ------ | ------ | ---------- | ---------- | ------- | -------
1456/// enable        | 0x0800 | 0x0804 | 0x00000000 | 0x7fffffff | disable | enable
1457/// input gain    | 0x0808 | 0x0810 | 0x0203a7e7 | 0x7f17afff | -18     | +18
1458/// output volume | 0x080c | 0x0814 | 0x0203a7e7 | 0x7f17afff | -18     | +18
1459/// ------------- | ------ | ------ | ---------- | ---------- | ------- | -------
1460/// band 0        | 0x0828 | 0x0878 |      -     |      -     |    -    |    -
1461/// band 0        | 0x082c | 0x087c |      -     |      -     |    -    |    -
1462/// band 0        | 0x0830 | 0x0880 |      -     |      -     |    -    |    -
1463/// band 0        | 0x0834 | 0x0884 |      -     |      -     |    -    |    -
1464/// band 0        | 0x0840 | 0x0890 |      -     |      -     |    -    |    -
1465/// band 0        | 0x0844 | 0x0894 |      -     |      -     |    -    |    -
1466/// band 0        | 0x0850 | 0x08a0 |      -     |      -     |    -    |    -
1467/// ------------- | ------ |------- | ---------- | ---------- | ------- | -------
1468/// band 1        | 0x08c8 | 0x0918 |      -     |      -     |    -    |    -
1469/// band 1        | 0x08cc | 0x091c |      -     |      -     |    -    |    -
1470/// band 1        | 0x08d0 | 0x0920 |      -     |      -     |    -    |    -
1471/// band 1        | 0x08d4 | 0x0924 |      -     |      -     |    -    |    -
1472/// band 1        | 0x08e0 | 0x0930 |      -     |      -     |    -    |    -
1473/// band 1        | 0x08e4 | 0x0934 |      -     |      -     |    -    |    -
1474/// band 1        | 0x08f0 | 0x0940 |      -     |      -     |    -    |    -
1475/// ------------- | ------ |------- | ---------- | ---------- | ------- | -------
1476/// band 2        | 0x0968 | 0x09b8 |      -     |      -     |    -    |    -
1477/// band 2        | 0x096c | 0x09bc |      -     |      -     |    -    |    -
1478/// band 2        | 0x0970 | 0x09c0 |      -     |      -     |    -    |    -
1479/// band 2        | 0x0974 | 0x09c4 |      -     |      -     |    -    |    -
1480/// band 2        | 0x0980 | 0x09d0 |      -     |      -     |    -    |    -
1481/// band 2        | 0x0984 | 0x09d4 |      -     |      -     |    -    |    -
1482/// band 2        | 0x0990 | 0x09e0 |      -     |      -     |    -    |    -
1483/// ------------- | ------ |------- | ---------- | ---------- | ------- | -------
1484/// band 3        | 0x0a08 | 0x0a58 |      -     |      -     |    -    |    -
1485/// band 3        | 0x0a0c | 0x0a5c |      -     |      -     |    -    |    -
1486/// band 3        | 0x0a10 | 0x0a60 |      -     |      -     |    -    |    -
1487/// band 3        | 0x0a14 | 0x0a64 |      -     |      -     |    -    |    -
1488/// band 3        | 0x0a20 | 0x0a70 |      -     |      -     |    -    |    -
1489/// band 3        | 0x0a24 | 0x0a74 |      -     |      -     |    -    |    -
1490/// band 3        | 0x0a30 | 0x0a80 |      -     |      -     |    -    |    -
1491#[derive(Default, Debug)]
1492pub struct SaffireEqualizerProtocol;
1493
1494impl SaffireParametersSerdes<SaffireEqualizerParameters> for SaffireEqualizerProtocol {
1495    const OFFSETS: &'static [usize] = &[
1496        0x0800, 0x0804, 0x0808, 0x080c, 0x0810, 0x0814, // ch 0 band 0.
1497        0x0828, 0x082c, 0x0830, 0x0834, 0x0840, 0x0844, 0x0850, // ch 0 band 1.
1498        0x08c8, 0x08cc, 0x08d0, 0x08d4, 0x08e0, 0x08e4, 0x08f0, // ch 0 band 2.
1499        0x0968, 0x096c, 0x0970, 0x0974, 0x0980, 0x0984, 0x0990, // ch 0 band 3.
1500        0x0a08, 0x0a0c, 0x0a10, 0x0a14, 0x0a20, 0x0a24, 0x0a30, // ch 1 band 0.
1501        0x0878, 0x087c, 0x0880, 0x0884, 0x0890, 0x0894, 0x08a0, // ch 1 band 1.
1502        0x0918, 0x091c, 0x0920, 0x0924, 0x0930, 0x0934, 0x0940, // ch 1 band 2.
1503        0x09b8, 0x09bc, 0x09c0, 0x09c4, 0x09d0, 0x09d4, 0x09e0, // ch 1 band 3.
1504        0x0a58, 0x0a5c, 0x0a60, 0x0a64, 0x0a70, 0x0a74, 0x0a80,
1505    ];
1506
1507    fn serialize(params: &SaffireEqualizerParameters, raw: &mut [u8]) {
1508        raw[20..24].copy_from_slice(&(params.enables[0] as u32).to_be_bytes());
1509        raw[24..28].copy_from_slice(&params.input_gains[0].to_be_bytes());
1510        raw[28..32].copy_from_slice(&params.output_volumes[0].to_be_bytes());
1511        raw[52..56].copy_from_slice(&(params.enables[1] as u32).to_be_bytes());
1512        raw[56..60].copy_from_slice(&params.input_gains[1].to_be_bytes());
1513        raw[60..64].copy_from_slice(&params.output_volumes[1].to_be_bytes());
1514    }
1515
1516    fn deserialize(params: &mut SaffireEqualizerParameters, raw: &[u8]) {
1517        let mut quadlet = [0u8; 4];
1518
1519        let quads: Vec<i32> = (0..raw.len())
1520            .step_by(4)
1521            .map(|pos| {
1522                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
1523                i32::from_be_bytes(quadlet)
1524            })
1525            .collect();
1526
1527        params.enables[0] = quads[5] > 0;
1528        params.enables[1] = quads[13] > 0;
1529        params.input_gains[0] = quads[6];
1530        params.input_gains[1] = quads[14];
1531        params.output_volumes[0] = quads[7];
1532        params.output_volumes[1] = quads[15];
1533    }
1534}
1535
1536/// Parameters of amplifier effect in Saffire.
1537#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1538pub struct SaffireAmplifierParameters {
1539    pub enables: [bool; 2],
1540    pub output_volumes: [i32; 2],
1541}
1542
1543/// parameter     | ch0           | ch1           | minimum    | maximum    | min val | max val
1544/// ------------- | ------------- | ------------- | ---------- | ---------- | ------- | -------
1545/// enable        | 0x1400        | 0x17ec        | 0x00000000 | 0x7fffffff | disable | enable
1546/// coefficients  | 0x1454-0x17e4 | 0x1840-0x1bd0 |      -     |      -     |    -    |    -
1547/// output volume | 0x17e8        | 0x1bd4        | 0x080e9f9f | 0x3fffffff | -18     | +18
1548#[derive(Default, Debug)]
1549pub struct SaffireAmplifierProtocol;
1550
1551impl SaffireParametersSerdes<SaffireAmplifierParameters> for SaffireAmplifierProtocol {
1552    const OFFSETS: &'static [usize] = &[0x1400, 0x17e8, 0x17ec, 0x1bd4];
1553
1554    fn serialize(params: &SaffireAmplifierParameters, raw: &mut [u8]) {
1555        raw[..4].copy_from_slice(&(params.enables[0] as u32).to_be_bytes());
1556        raw[4..8].copy_from_slice(&(params.enables[1] as u32).to_be_bytes());
1557        raw[8..12].copy_from_slice(&params.output_volumes[0].to_be_bytes());
1558        raw[12..16].copy_from_slice(&params.output_volumes[1].to_be_bytes());
1559    }
1560
1561    fn deserialize(params: &mut SaffireAmplifierParameters, raw: &[u8]) {
1562        let mut quadlet = [0u8; 4];
1563
1564        let quads: Vec<i32> = (0..raw.len())
1565            .step_by(4)
1566            .map(|pos| {
1567                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
1568                i32::from_be_bytes(quadlet)
1569            })
1570            .collect();
1571
1572        params.enables[0] = quads[0] > 0;
1573        params.enables[1] = quads[1] > 0;
1574        params.output_volumes[0] = quads[2];
1575        params.output_volumes[1] = quads[3];
1576    }
1577}
1578
1579/// Order of compressor effect against equalizer/amplifier effect.
1580#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1581pub enum SaffireChStripCompOrder {
1582    Pre,
1583    Post,
1584}
1585
1586impl Default for SaffireChStripCompOrder {
1587    fn default() -> Self {
1588        Self::Pre
1589    }
1590}
1591
1592/// General parameters for channel strip effects.
1593#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
1594pub struct SaffireChStripParameters {
1595    pub paired_mode: SaffireMixerMode,
1596    pub comp_orders: [SaffireChStripCompOrder; 2],
1597}
1598
1599impl SaffireParametersSerdes<SaffireChStripParameters> for SaffireChStripProtocol {
1600    const OFFSETS: &'static [usize] = &[0x7d0, 0x7d4, 0x7d8];
1601
1602    fn serialize(params: &SaffireChStripParameters, raw: &mut [u8]) {
1603        raw[..4].copy_from_slice(
1604            &(match params.paired_mode {
1605                SaffireMixerMode::StereoSeparated => 1u32,
1606                SaffireMixerMode::StereoPaired => 0,
1607            })
1608            .to_be_bytes(),
1609        );
1610
1611        params
1612            .comp_orders
1613            .iter()
1614            .enumerate()
1615            .for_each(|(i, comp_order)| {
1616                let pos = 4 + i * 4;
1617                raw[pos..(pos + 4)].copy_from_slice(
1618                    &(match comp_order {
1619                        SaffireChStripCompOrder::Pre => 1u32,
1620                        SaffireChStripCompOrder::Post => 0,
1621                    })
1622                    .to_be_bytes(),
1623                );
1624            });
1625    }
1626
1627    fn deserialize(params: &mut SaffireChStripParameters, raw: &[u8]) {
1628        let mut quadlet = [0u8; 4];
1629
1630        let quads: Vec<u32> = (0..raw.len())
1631            .step_by(4)
1632            .map(|pos| {
1633                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
1634                u32::from_be_bytes(quadlet)
1635            })
1636            .collect();
1637
1638        params.paired_mode = if quads[0] > 0 {
1639            SaffireMixerMode::StereoSeparated
1640        } else {
1641            SaffireMixerMode::StereoPaired
1642        };
1643        params
1644            .comp_orders
1645            .iter_mut()
1646            .enumerate()
1647            .for_each(|(i, comp_order)| {
1648                *comp_order = if quads[1 + i] > 0 {
1649                    SaffireChStripCompOrder::Pre
1650                } else {
1651                    SaffireChStripCompOrder::Post
1652                };
1653            });
1654    }
1655}
1656
1657/// The protocol implementation to operate channel strip effects.
1658#[derive(Default, Debug)]
1659pub struct SaffireChStripProtocol;
1660
1661#[cfg(test)]
1662mod test {
1663    use super::*;
1664
1665    #[test]
1666    fn saffire_output_protocol_serdes() {
1667        let mut params = SaffireOutputProtocol::create_output_parameters();
1668
1669        params
1670            .mutes
1671            .iter_mut()
1672            .step_by(2)
1673            .for_each(|mute| *mute = true);
1674
1675        params
1676            .vols
1677            .iter_mut()
1678            .enumerate()
1679            .for_each(|(i, vol)| *vol = i as u8);
1680
1681        params
1682            .hwctls
1683            .iter_mut()
1684            .step_by(2)
1685            .for_each(|hwctl| *hwctl = true);
1686
1687        params
1688            .dims
1689            .iter_mut()
1690            .step_by(2)
1691            .for_each(|dim| *dim = true);
1692
1693        params
1694            .pads
1695            .iter_mut()
1696            .step_by(2)
1697            .for_each(|pad| *pad = true);
1698
1699        let mut raw = vec![0u8; SaffireOutputProtocol::OFFSETS.len() * 4];
1700        SaffireOutputProtocol::serialize(&params, &mut raw);
1701        let mut p = SaffireOutputProtocol::create_output_parameters();
1702        SaffireOutputProtocol::deserialize(&mut p, &raw);
1703
1704        assert_eq!(params, p);
1705    }
1706
1707    #[test]
1708    fn saffire_le_output_protocol_serdes() {
1709        let mut params = SaffireLeOutputProtocol::create_output_parameters();
1710
1711        params
1712            .mutes
1713            .iter_mut()
1714            .step_by(2)
1715            .for_each(|mute| *mute = true);
1716
1717        params
1718            .vols
1719            .iter_mut()
1720            .enumerate()
1721            .for_each(|(i, vol)| *vol = i as u8);
1722
1723        params
1724            .hwctls
1725            .iter_mut()
1726            .step_by(2)
1727            .for_each(|hwctl| *hwctl = true);
1728
1729        params
1730            .dims
1731            .iter_mut()
1732            .step_by(2)
1733            .for_each(|dim| *dim = true);
1734
1735        params
1736            .pads
1737            .iter_mut()
1738            .step_by(2)
1739            .for_each(|pad| *pad = true);
1740
1741        let mut raw = vec![0u8; SaffireLeOutputProtocol::OFFSETS.len() * 4];
1742        SaffireLeOutputProtocol::serialize(&params, &mut raw);
1743        let mut p = SaffireLeOutputProtocol::create_output_parameters();
1744        SaffireLeOutputProtocol::deserialize(&mut p, &raw);
1745
1746        assert_eq!(params, p);
1747    }
1748
1749    #[test]
1750    fn saffire_le_through_protocol_serdes() {
1751        let params = SaffireThroughParameters {
1752            midi: true,
1753            ac3: true,
1754        };
1755        let mut raw = vec![0u8; SaffireLeThroughProtocol::OFFSETS.len() * 4];
1756        SaffireLeThroughProtocol::serialize(&params, &mut raw);
1757        let mut p = SaffireThroughParameters::default();
1758        SaffireLeThroughProtocol::deserialize(&mut p, &raw);
1759        assert_eq!(params, p);
1760    }
1761
1762    #[test]
1763    fn saffire_specific_protocols_serdes() {
1764        let params = SaffireSpecificParameters {
1765            mode_192khz: true,
1766            input_pair_1_src: SaffireInputPair1Source::DigitalInputPair0,
1767            mixer_mode: SaffireMixerMode::StereoSeparated,
1768        };
1769        let mut raw = vec![0u8; SaffireSpecificProtocol::OFFSETS.len() * 4];
1770        SaffireSpecificProtocol::serialize(&params, &mut raw);
1771        let mut p = SaffireSpecificParameters::default();
1772        SaffireSpecificProtocol::deserialize(&mut p, &raw);
1773    }
1774
1775    #[test]
1776    fn saffire_separated_mixer_phys_src_pos() {
1777        [
1778            (0, 0, 1),
1779            (0, 1, 2),
1780            (0, 2, 3),
1781            (0, 3, 4),
1782            (0, 4, 0),
1783            (1, 0, 16),
1784            (1, 1, 17),
1785            (1, 2, 18),
1786            (1, 3, 19),
1787            (1, 4, 15),
1788            (2, 0, 6),
1789            (2, 1, 7),
1790            (2, 2, 8),
1791            (2, 3, 9),
1792            (2, 4, 5),
1793            (3, 0, 21),
1794            (3, 1, 22),
1795            (3, 2, 23),
1796            (3, 3, 24),
1797            (3, 4, 20),
1798        ]
1799        .iter()
1800        .for_each(|&(src_idx, dst_idx, expected)| {
1801            let pos = SaffireSeparatedMixerProtocol::phys_src_pos(dst_idx, src_idx);
1802            assert_eq!(pos, expected);
1803        });
1804    }
1805
1806    #[test]
1807    fn saffire_separated_mixer_reverb_return_pos() {
1808        [
1809            (0, 0, 11),
1810            (0, 1, 12),
1811            (0, 2, 13),
1812            (0, 3, 14),
1813            (0, 4, 10),
1814            (1, 0, 26),
1815            (1, 1, 27),
1816            (1, 2, 28),
1817            (1, 3, 29),
1818            (1, 4, 25),
1819        ]
1820        .iter()
1821        .for_each(|&(src_idx, dst_idx, expected)| {
1822            let pos = SaffireSeparatedMixerProtocol::reverb_return_pos(dst_idx, src_idx);
1823            assert_eq!(pos, expected);
1824        });
1825    }
1826
1827    #[test]
1828    fn saffire_separated_mixer_stream_src_pos() {
1829        [
1830            (0, 0, 36),
1831            (0, 1, 37),
1832            (0, 2, 38),
1833            (0, 3, 39),
1834            (0, 4, 35),
1835            (1, 0, 41),
1836            (1, 1, 42),
1837            (1, 2, 43),
1838            (1, 3, 44),
1839            (1, 4, 40),
1840            (2, 0, 46),
1841            (2, 1, 47),
1842            (2, 2, 48),
1843            (2, 3, 49),
1844            (2, 4, 45),
1845            (3, 0, 51),
1846            (3, 1, 52),
1847            (3, 2, 53),
1848            (3, 3, 54),
1849            (3, 4, 50),
1850            (4, 0, 31),
1851            (4, 1, 32),
1852            (4, 2, 33),
1853            (4, 3, 34),
1854            (4, 4, 30),
1855        ]
1856        .iter()
1857        .for_each(|&(src_idx, dst_idx, expected)| {
1858            let pos = SaffireSeparatedMixerProtocol::stream_src_pos(dst_idx, src_idx);
1859            assert_eq!(pos, expected);
1860        });
1861    }
1862
1863    #[test]
1864    fn saffire_separated_mixer_protocol_serdes() {
1865        let mut params = SaffireSeparatedMixerProtocol::create_mixer_state();
1866        params
1867            .phys_inputs
1868            .iter_mut()
1869            .enumerate()
1870            .for_each(|(i, gains)| {
1871                gains
1872                    .iter_mut()
1873                    .enumerate()
1874                    .for_each(|(j, gain)| *gain = (i * 100 + j) as i16)
1875            });
1876        params
1877            .reverb_returns
1878            .iter_mut()
1879            .enumerate()
1880            .for_each(|(i, gains)| {
1881                gains
1882                    .iter_mut()
1883                    .enumerate()
1884                    .for_each(|(j, gain)| *gain = (i * 100 + j) as i16)
1885            });
1886        params
1887            .stream_inputs
1888            .iter_mut()
1889            .enumerate()
1890            .for_each(|(i, gains)| {
1891                gains
1892                    .iter_mut()
1893                    .enumerate()
1894                    .for_each(|(j, gain)| *gain = (i * 100 + j) as i16)
1895            });
1896        let mut raw = vec![0u8; SaffireSeparatedMixerProtocol::OFFSETS.len() * 4];
1897        SaffireSeparatedMixerProtocol::serialize(&params, &mut raw);
1898        let mut p = SaffireSeparatedMixerProtocol::create_mixer_state();
1899        SaffireSeparatedMixerProtocol::deserialize(&mut p, &raw);
1900
1901        assert_eq!(params, p);
1902    }
1903
1904    #[test]
1905    fn saffire_paired_mixer_stream_src_pos() {
1906        [
1907            (0, 0, 6),
1908            (0, 1, 7),
1909            (0, 2, 8),
1910            (0, 3, 9),
1911            (0, 4, 5),
1912            (1, 0, 11),
1913            (1, 1, 12),
1914            (1, 2, 13),
1915            (1, 3, 14),
1916            (1, 4, 10),
1917            (2, 0, 16),
1918            (2, 1, 17),
1919            (2, 2, 18),
1920            (2, 3, 19),
1921            (2, 4, 15),
1922            (3, 0, 21),
1923            (3, 1, 22),
1924            (3, 2, 23),
1925            (3, 3, 24),
1926            (3, 4, 20),
1927            (4, 0, 1),
1928            (4, 1, 2),
1929            (4, 2, 3),
1930            (4, 3, 4),
1931            (4, 4, 0),
1932        ]
1933        .iter()
1934        .for_each(|&(src_idx, dst_idx, expected)| {
1935            let pos = SaffirePairedMixerProtocol::stream_src_pos(dst_idx, src_idx);
1936            assert_eq!(pos, expected);
1937        });
1938    }
1939
1940    #[test]
1941    fn saffire_paired_mixer_phys_src_pos() {
1942        [
1943            (0, 0, 26),
1944            (0, 1, 27),
1945            (0, 2, 28),
1946            (0, 3, 29),
1947            (0, 4, 25),
1948            (1, 0, 31),
1949            (1, 1, 32),
1950            (1, 2, 33),
1951            (1, 3, 34),
1952            (1, 4, 30),
1953        ]
1954        .iter()
1955        .for_each(|&(src_idx, dst_idx, expected)| {
1956            let pos = SaffirePairedMixerProtocol::phys_src_pos(dst_idx, src_idx);
1957            assert_eq!(pos, expected);
1958        });
1959    }
1960
1961    #[test]
1962    fn saffire_paired_mixer_reverb_return_pos() {
1963        [(0, 36), (1, 37), (2, 38), (3, 39), (4, 35)]
1964            .iter()
1965            .for_each(|&(dst_idx, expected)| {
1966                let pos = SaffirePairedMixerProtocol::reverb_return_pos(dst_idx, 0);
1967                assert_eq!(pos, expected);
1968            });
1969    }
1970
1971    #[test]
1972    fn saffire_paired_mixer_protocol_serdes() {
1973        let mut params = SaffirePairedMixerProtocol::create_mixer_state();
1974        params
1975            .phys_inputs
1976            .iter_mut()
1977            .enumerate()
1978            .for_each(|(i, gains)| {
1979                gains
1980                    .iter_mut()
1981                    .enumerate()
1982                    .for_each(|(j, gain)| *gain = (i * 100 + j) as i16)
1983            });
1984        params
1985            .reverb_returns
1986            .iter_mut()
1987            .enumerate()
1988            .for_each(|(i, gains)| {
1989                gains
1990                    .iter_mut()
1991                    .enumerate()
1992                    .for_each(|(j, gain)| *gain = (i * 100 + j) as i16)
1993            });
1994        params
1995            .stream_inputs
1996            .iter_mut()
1997            .enumerate()
1998            .for_each(|(i, gains)| {
1999                gains
2000                    .iter_mut()
2001                    .enumerate()
2002                    .for_each(|(j, gain)| *gain = (i * 100 + j) as i16)
2003            });
2004        let mut raw = vec![0u8; SaffirePairedMixerProtocol::OFFSETS.len() * 4];
2005        SaffirePairedMixerProtocol::serialize(&params, &mut raw);
2006        let mut p = SaffirePairedMixerProtocol::create_mixer_state();
2007        SaffirePairedMixerProtocol::deserialize(&mut p, &raw);
2008
2009        assert_eq!(params, p);
2010    }
2011
2012    #[test]
2013    fn saffire_reverb_protocol_serdes() {
2014        let params = SaffireReverbParameters {
2015            amounts: [-101, 102],
2016            room_sizes: [111, -112],
2017            diffusions: [-113, 113],
2018            tones: [114, -114],
2019        };
2020        let mut raw = vec![0u8; SaffireReverbProtocol::OFFSETS.len() * 4];
2021        SaffireReverbProtocol::serialize(&params, &mut raw);
2022        let mut p = SaffireReverbParameters::default();
2023        SaffireReverbProtocol::deserialize(&mut p, &raw);
2024
2025        assert_eq!(params, p);
2026    }
2027
2028    #[test]
2029    fn saffire_compressor_protocol_serdes() {
2030        let params = SaffireCompressorParameters {
2031            input_gains: [-200, 200],
2032            enables: [true, false],
2033            output_volumes: [201, -201],
2034        };
2035        let mut raw = vec![0u8; SaffireCompressorProtocol::OFFSETS.len() * 4];
2036        SaffireCompressorProtocol::serialize(&params, &mut raw);
2037        let mut p = SaffireCompressorParameters::default();
2038        SaffireCompressorProtocol::deserialize(&mut p, &raw);
2039
2040        assert_eq!(params, p);
2041    }
2042
2043    #[test]
2044    fn saffire_equalizer_protocol_serdes() {
2045        let params = SaffireEqualizerParameters {
2046            input_gains: [-200, 200],
2047            enables: [true, false],
2048            output_volumes: [201, -201],
2049        };
2050        let mut raw = vec![0u8; SaffireEqualizerProtocol::OFFSETS.len() * 4];
2051        SaffireEqualizerProtocol::serialize(&params, &mut raw);
2052        let mut p = SaffireEqualizerParameters::default();
2053        SaffireEqualizerProtocol::deserialize(&mut p, &raw);
2054
2055        assert_eq!(params, p);
2056    }
2057
2058    #[test]
2059    fn saffire_amplifier_protocol_serdes() {
2060        let params = SaffireAmplifierParameters {
2061            enables: [false, true],
2062            output_volumes: [400, -401],
2063        };
2064        let mut raw = vec![0u8; SaffireAmplifierProtocol::OFFSETS.len() * 4];
2065        SaffireAmplifierProtocol::serialize(&params, &mut raw);
2066        let mut p = SaffireAmplifierParameters::default();
2067        SaffireAmplifierProtocol::deserialize(&mut p, &raw);
2068
2069        assert_eq!(params, p);
2070    }
2071
2072    #[test]
2073    fn saffire_ch_strip_protocol_serdes() {
2074        let params = SaffireChStripParameters {
2075            paired_mode: SaffireMixerMode::StereoSeparated,
2076            comp_orders: [SaffireChStripCompOrder::Pre, SaffireChStripCompOrder::Post],
2077        };
2078        let mut raw = vec![0u8; SaffireChStripProtocol::OFFSETS.len() * 4];
2079        SaffireChStripProtocol::serialize(&params, &mut raw);
2080        let mut p = SaffireChStripParameters::default();
2081        SaffireChStripProtocol::deserialize(&mut p, &raw);
2082
2083        assert_eq!(params, p);
2084    }
2085
2086    #[test]
2087    fn saffire_le_specific_protocol_serdes() {
2088        let params = SaffireLeSpecificParameters {
2089            analog_input_2_3_high_gains: [true, false],
2090        };
2091        let mut raw = vec![0u8; SaffireLeSpecificProtocol::OFFSETS.len() * 4];
2092        SaffireLeSpecificProtocol::serialize(&params, &mut raw);
2093        let mut p = SaffireLeSpecificParameters::default();
2094        SaffireLeSpecificProtocol::deserialize(&mut p, &raw);
2095
2096        assert_eq!(params, p);
2097    }
2098
2099    #[test]
2100    fn saffire_le_mixer_low_rate_stream_src_pos() {
2101        // NOTE: src_idx, dst_idx, expected offsets index
2102        [
2103            (0, 0, 2),
2104            (0, 1, 0),
2105            (0, 2, 3),
2106            (0, 3, 1),
2107            (1, 0, 18),
2108            (1, 1, 16),
2109            (1, 2, 19),
2110            (1, 3, 17),
2111            (2, 0, 6),
2112            (2, 1, 4),
2113            (2, 2, 7),
2114            (2, 3, 5),
2115            (3, 0, 22),
2116            (3, 1, 20),
2117            (3, 2, 23),
2118            (3, 3, 21),
2119            (4, 0, 10),
2120            (4, 1, 8),
2121            (4, 2, 11),
2122            (4, 3, 9),
2123            (5, 0, 26),
2124            (5, 1, 24),
2125            (5, 2, 27),
2126            (5, 3, 25),
2127            (6, 0, 14),
2128            (6, 1, 12),
2129            (6, 2, 15),
2130            (6, 3, 13),
2131            (7, 0, 30),
2132            (7, 1, 28),
2133            (7, 2, 31),
2134            (7, 3, 29),
2135        ]
2136        .iter()
2137        .for_each(|&(src_idx, dst_idx, expected)| {
2138            let idx = SaffireLeMixerLowRateProtocol::stream_src_pos(dst_idx, src_idx);
2139            assert_eq!(idx, expected, "{}-{}", dst_idx, src_idx);
2140        })
2141    }
2142
2143    #[test]
2144    fn saffire_le_mixer_low_rate_phys_src_pos() {
2145        // NOTE: src_idx, dst_idx, expected offsets index
2146        [
2147            (0, 0, 34),
2148            (0, 1, 32),
2149            (0, 2, 35),
2150            (0, 3, 33),
2151            (1, 0, 46),
2152            (1, 1, 44),
2153            (1, 2, 47),
2154            (1, 3, 45),
2155            (2, 0, 38),
2156            (2, 1, 36),
2157            (2, 2, 39),
2158            (2, 3, 37),
2159            (3, 0, 50),
2160            (3, 1, 48),
2161            (3, 2, 51),
2162            (3, 3, 49),
2163            (4, 0, 42),
2164            (4, 1, 40),
2165            (4, 2, 43),
2166            (4, 3, 41),
2167            (5, 0, 54),
2168            (5, 1, 52),
2169            (5, 2, 55),
2170            (5, 3, 53),
2171        ]
2172        .iter()
2173        .for_each(|&(src_idx, dst_idx, expected)| {
2174            let idx = SaffireLeMixerLowRateProtocol::phys_src_pos(dst_idx, src_idx);
2175            assert_eq!(idx, expected, "{}-{}", dst_idx, src_idx);
2176        })
2177    }
2178
2179    #[test]
2180    fn saffire_le_mixer_middle_rate_monitor_pair_from_analog_input_pos() {
2181        // NOTE: src_idx, expected offset idx.
2182        [(0, 0), (1, 3), (2, 1), (3, 4), (4, 2), (5, 5)]
2183            .iter()
2184            .for_each(|&(src_idx, expected)| {
2185                let idx = SaffireLeMixerMiddleRateProtocol::monitor_analog_input_pos(0, src_idx);
2186                assert_eq!(idx, expected);
2187            });
2188    }
2189
2190    #[test]
2191    fn saffire_le_mixer_middle_rate_monitor_src_pos() {
2192        // NOTE: dst_idx, expected.
2193        [(0, 6), (1, 9), (2, 12), (3, 15)]
2194            .iter()
2195            .for_each(|&(dst_idx, expected)| {
2196                let idx = SaffireLeMixerMiddleRateProtocol::mixer_monitor_src_pos(dst_idx, 0);
2197                assert_eq!(idx, expected);
2198            });
2199    }
2200
2201    #[test]
2202    fn saffire_le_mixer_middle_rate_mixer_stream_input_pos() {
2203        // NOTE: dst_idx, src_idx, expected.
2204        [
2205            (0, 0, 7),
2206            (0, 1, 8),
2207            (1, 0, 10),
2208            (1, 1, 11),
2209            (2, 0, 13),
2210            (2, 1, 14),
2211            (3, 0, 16),
2212            (3, 1, 17),
2213        ]
2214        .iter()
2215        .for_each(|&(dst_idx, src_idx, expected)| {
2216            let idx = SaffireLeMixerMiddleRateProtocol::mixer_stream_input_pos(dst_idx, src_idx);
2217            assert_eq!(idx, expected);
2218        });
2219    }
2220
2221    #[test]
2222    fn saffire_le_mixer_low_rate_protocol_serdes() {
2223        let mut params = SaffireLeMixerLowRateState::default();
2224
2225        params
2226            .phys_src_gains
2227            .iter_mut()
2228            .enumerate()
2229            .for_each(|(i, gains)| {
2230                gains
2231                    .iter_mut()
2232                    .enumerate()
2233                    .for_each(|(j, gain)| *gain = (i * 100 + j) as i16);
2234            });
2235
2236        params
2237            .stream_src_gains
2238            .iter_mut()
2239            .enumerate()
2240            .for_each(|(i, gains)| {
2241                gains
2242                    .iter_mut()
2243                    .enumerate()
2244                    .for_each(|(j, gain)| *gain = (i * 100 + j) as i16);
2245            });
2246
2247        params.spdif_out_src = SaffireLeSpdifOutputSource::MixerOutputPair67;
2248
2249        let mut raw = vec![0u8; SaffireLeMixerLowRateProtocol::OFFSETS.len() * 4];
2250        SaffireLeMixerLowRateProtocol::serialize(&params, &mut raw);
2251        let mut p = SaffireLeMixerLowRateState::default();
2252        SaffireLeMixerLowRateProtocol::deserialize(&mut p, &raw);
2253
2254        assert_eq!(params, p);
2255    }
2256
2257    #[test]
2258    fn saffire_le_mixer_middle_rate_protocol_serdes() {
2259        let mut params = SaffireLeMixerMiddleRateState::default();
2260
2261        params
2262            .monitor_src_phys_input_gains
2263            .iter_mut()
2264            .enumerate()
2265            .for_each(|(i, gain)| *gain = i as i16);
2266
2267        params
2268            .monitor_out_src_pair_gains
2269            .iter_mut()
2270            .enumerate()
2271            .for_each(|(i, gains)| {
2272                gains
2273                    .iter_mut()
2274                    .enumerate()
2275                    .for_each(|(j, gain)| *gain = (i * 100 + j) as i16);
2276            });
2277
2278        params
2279            .stream_src_pair_gains
2280            .iter_mut()
2281            .enumerate()
2282            .for_each(|(i, gains)| {
2283                gains
2284                    .iter_mut()
2285                    .enumerate()
2286                    .for_each(|(j, gain)| *gain = (i * 100 + j) as i16);
2287            });
2288
2289        params.spdif_out_src = SaffireLeSpdifOutputSource::MixerOutputPair67;
2290
2291        let mut raw = vec![0u8; SaffireLeMixerMiddleRateProtocol::OFFSETS.len() * 4];
2292        SaffireLeMixerMiddleRateProtocol::serialize(&params, &mut raw);
2293        let mut p = SaffireLeMixerMiddleRateState::default();
2294        SaffireLeMixerMiddleRateProtocol::deserialize(&mut p, &raw);
2295
2296        assert_eq!(params, p);
2297    }
2298}