1use {super::*, std::ops::Range};
67
68#[derive(Default, Debug)]
70pub struct Fw1814ClkProtocol;
71
72impl MediaClockFrequencyOperation for Fw1814ClkProtocol {
73 const FREQ_LIST: &'static [u32] = &[44100, 48000, 88200, 96000, 176400, 192000];
74
75 fn cache_freq(
76 avc: &BebobAvc,
77 params: &mut MediaClockParameters,
78 timeout_ms: u32,
79 ) -> Result<(), Error> {
80 cache_freq(avc, params, Self::FREQ_LIST, timeout_ms)
81 }
82}
83
84#[derive(Default, Debug)]
86pub struct ProjectMixClkProtocol;
87
88impl MediaClockFrequencyOperation for ProjectMixClkProtocol {
89 const FREQ_LIST: &'static [u32] = &[44100, 48000, 88200, 96000];
90
91 fn cache_freq(
92 avc: &BebobAvc,
93 params: &mut MediaClockParameters,
94 timeout_ms: u32,
95 ) -> Result<(), Error> {
96 cache_freq(avc, params, Self::FREQ_LIST, timeout_ms)
97 }
98}
99
100fn cache_freq(
102 avc: &BebobAvc,
103 params: &mut MediaClockParameters,
104 freq_list: &[u32],
105 timeout_ms: u32,
106) -> Result<(), Error> {
107 let mut op = OutputPlugSignalFormat::new(0);
108 avc.status(&AvcAddr::Unit, &mut op, timeout_ms)?;
109 let fdf = AmdtpFdf::from(&op.0.fdf[..]);
110 freq_list
111 .iter()
112 .position(|&freq| freq == fdf.freq)
113 .ok_or_else(|| {
114 let msg = format!("Unexpected value of FDF: {:?}", fdf);
115 Error::new(FileError::Io, &msg)
116 })
117 .map(|freq_idx| params.freq_idx = freq_idx)
118}
119
120pub struct MaudioSpecialLedSwitch {
122 state: bool,
123 op: VendorDependent,
124}
125
126const SPECIAL_OUI_A: [u8; 3] = [0x03, 0x00, 0x01];
128
129impl Default for MaudioSpecialLedSwitch {
130 fn default() -> Self {
131 Self {
132 state: Default::default(),
133 op: VendorDependent {
134 company_id: SPECIAL_OUI_A,
135 data: vec![0xff, 0xff],
136 },
137 }
138 }
139}
140
141impl MaudioSpecialLedSwitch {
142 pub fn new(state: bool) -> Self {
143 Self {
144 state,
145 ..Default::default()
146 }
147 }
148}
149
150impl AvcOp for MaudioSpecialLedSwitch {
151 const OPCODE: u8 = VendorDependent::OPCODE;
152}
153
154impl AvcControl for MaudioSpecialLedSwitch {
155 fn build_operands(&mut self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
156 self.op.data[0] = self.state.into();
157 AvcControl::build_operands(&mut self.op, addr)
158 }
159
160 fn parse_operands(&mut self, addr: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
161 AvcControl::parse_operands(&mut self.op, addr, operands)
162 }
163}
164
165#[derive(Default, Debug)]
167pub struct MaudioSpecialMeterProtocol;
168
169const METER_SIZE: usize = 84;
170
171#[derive(Debug)]
173pub struct MaudioSpecialMeterState {
174 pub analog_inputs: [i16; 8],
176 pub spdif_inputs: [i16; 2],
178 pub adat_inputs: [i16; 8],
180 pub analog_outputs: [i16; 4],
182 pub spdif_outputs: [i16; 2],
184 pub adat_outputs: [i16; 8],
186
187 pub headphone: [i16; 4],
189 pub aux_outputs: [i16; 2],
191 pub switch: bool,
193 pub rotaries: [i16; 3],
195 pub sync_status: bool,
197 cache: [u8; METER_SIZE],
198}
199
200impl Default for MaudioSpecialMeterState {
201 fn default() -> Self {
202 Self {
203 analog_inputs: Default::default(),
204 spdif_inputs: Default::default(),
205 adat_inputs: Default::default(),
206 analog_outputs: Default::default(),
207 spdif_outputs: Default::default(),
208 adat_outputs: Default::default(),
209 headphone: Default::default(),
210 aux_outputs: Default::default(),
211 switch: Default::default(),
212 rotaries: Default::default(),
213 sync_status: Default::default(),
214 cache: [0; METER_SIZE],
215 }
216 }
217}
218
219impl MaudioSpecialMeterProtocol {
220 pub const LEVEL_MIN: i16 = 0;
222 pub const LEVEL_MAX: i16 = i16::MAX;
224 pub const LEVEL_STEP: i16 = 0x100;
226
227 pub const ROTARY_MIN: i16 = i16::MIN;
229 pub const ROTARY_MAX: i16 = 0;
231 pub const ROTARY_STEP: i16 = 0x400;
233
234 pub fn cache(
235 req: &FwReq,
236 node: &FwNode,
237 meter: &mut MaudioSpecialMeterState,
238 timeout_ms: u32,
239 ) -> Result<(), Error> {
240 let frame = &mut meter.cache;
241
242 let mut bitmap0 = [0; 4];
243 bitmap0.copy_from_slice(&frame[..4]);
244
245 let mut bitmap1 = [0; 4];
246 bitmap1.copy_from_slice(&frame[(METER_SIZE - 4)..]);
247
248 req.transaction_sync(
249 node,
250 FwTcode::ReadBlockRequest,
251 DM_APPL_METER_OFFSET,
252 frame.len(),
253 frame,
254 timeout_ms,
255 )?;
256
257 let mut doublet = [0; 2];
258
259 meter
260 .analog_inputs
261 .iter_mut()
262 .chain(&mut meter.spdif_inputs)
263 .chain(&mut meter.adat_inputs)
264 .chain(&mut meter.analog_outputs)
265 .chain(&mut meter.spdif_outputs)
266 .chain(&mut meter.adat_outputs)
267 .chain(&mut meter.headphone)
268 .chain(&mut meter.aux_outputs)
269 .enumerate()
270 .for_each(|(i, m)| {
271 let pos = 2 + (1 + i) * 2;
272 doublet.copy_from_slice(&frame[pos..(pos + 2)]);
273 *m = i16::from_be_bytes(doublet);
274 });
275
276 if bitmap0[0] ^ frame[0] > 0 {
277 if frame[0] == 0x01 {
278 meter.switch = !meter.switch;
279 }
280 }
281
282 meter.rotaries.iter_mut().enumerate().for_each(|(i, r)| {
283 let pos = i + 1;
284
285 if bitmap0[pos] ^ frame[pos] > 0 {
286 if frame[pos] == 0x01 {
287 if *r <= Self::ROTARY_MAX - Self::ROTARY_STEP {
288 *r += Self::ROTARY_STEP;
289 } else {
290 *r = Self::ROTARY_MAX;
291 }
292 } else if frame[pos] == 0x02 {
293 if *r >= Self::ROTARY_MIN + Self::ROTARY_STEP {
294 *r -= Self::ROTARY_STEP;
295 } else {
296 *r = Self::ROTARY_MIN;
297 }
298 }
299 }
300 });
301
302 meter.sync_status = bitmap1[3] ^ frame[METER_SIZE - 1] > 0;
303
304 Ok(())
305 }
306}
307
308const CACHE_SIZE: usize = 160;
309
310const STREAM_INPUT_GAIN_RANGE: Range<usize> = Range {
329 start: 0x0000,
330 end: 0x0008,
331};
332const ANALOG_OUTPUT_VOLUME_RANGE: Range<usize> = Range {
333 start: 0x0008,
334 end: 0x0010,
335};
336const ANALOG_INPUT_GAIN_RANGE: Range<usize> = Range {
337 start: 0x0010,
338 end: 0x0020,
339};
340const SPDIF_INPUT_GAIN_RANGE: Range<usize> = Range {
341 start: 0x0020,
342 end: 0x0024,
343};
344const ADAT_INPUT_GAIN_RANGE: Range<usize> = Range {
345 start: 0x0024,
346 end: 0x0034,
347};
348const AUX_OUTPUT_VOLUME_RANGE: Range<usize> = Range {
349 start: 0x0034,
350 end: 0x0038,
351};
352const HEADPHONE_VOLUME_RANGE: Range<usize> = Range {
353 start: 0x0038,
354 end: 0x0040,
355};
356const ANALOG_INPUT_BALANCE_RANGE: Range<usize> = Range {
357 start: 0x0040,
358 end: 0x0050,
359};
360const SPDIF_INPUT_BALANCE_RANGE: Range<usize> = Range {
361 start: 0x0050,
362 end: 0x0054,
363};
364const ADAT_INPUT_BALANCE_RANGE: Range<usize> = Range {
365 start: 0x0054,
366 end: 0x0064,
367};
368const AUX_STREAM_INPUT_GAIN_RANGE: Range<usize> = Range {
369 start: 0x0064,
370 end: 0x006c,
371};
372const AUX_ANALOG_INPUT_GAIN_RANGE: Range<usize> = Range {
373 start: 0x006c,
374 end: 0x007c,
375};
376const AUX_SPDIF_INPUT_GAIN_RANGE: Range<usize> = Range {
377 start: 0x007c,
378 end: 0x0080,
379};
380const AUX_ADAT_INPUT_GAIN_RANGE: Range<usize> = Range {
381 start: 0x0080,
382 end: 0x0090,
383};
384const MIXER_PHYS_SOURCE_RANGE: Range<usize> = Range {
385 start: 0x0090,
386 end: 0x0094,
387};
388const MIXER_STREAM_SOURCE_RANGE: Range<usize> = Range {
389 start: 0x0094,
390 end: 0x0098,
391};
392const HEADPHONE_PAIR_SOURCE_RANGE: Range<usize> = Range {
393 start: 0x0098,
394 end: 0x009c,
395};
396const ANALOG_OUTPUT_PAIR_SOURCE_RANGE: Range<usize> = Range {
397 start: 0x009c,
398 end: 0x00a0,
399};
400
401#[derive(Debug)]
403pub struct MaudioSpecialStateCache(pub [u8; CACHE_SIZE]);
404
405impl Default for MaudioSpecialStateCache {
406 fn default() -> Self {
407 Self([0; CACHE_SIZE])
408 }
409}
410
411#[derive(Debug, Copy, Clone, PartialEq, Eq)]
413pub struct MaudioSpecialInputParameters {
414 pub stream_gains: [i16; 4],
416
417 pub analog_gains: [i16; 8],
419 pub spdif_gains: [i16; 2],
421 pub adat_gains: [i16; 8],
423
424 pub analog_balances: [i16; 8],
426 pub spdif_balances: [i16; 2],
428 pub adat_balances: [i16; 8],
430}
431
432impl Default for MaudioSpecialInputParameters {
433 fn default() -> Self {
434 Self {
435 stream_gains: [MaudioSpecialInputProtocol::GAIN_MAX; 4],
436 analog_gains: [MaudioSpecialInputProtocol::GAIN_MAX; 8],
437 spdif_gains: [MaudioSpecialInputProtocol::GAIN_MAX; 2],
438 adat_gains: [MaudioSpecialInputProtocol::GAIN_MAX; 8],
439 analog_balances: [
440 MaudioSpecialInputProtocol::BALANCE_MIN,
441 MaudioSpecialInputProtocol::BALANCE_MAX,
442 MaudioSpecialInputProtocol::BALANCE_MIN,
443 MaudioSpecialInputProtocol::BALANCE_MAX,
444 MaudioSpecialInputProtocol::BALANCE_MIN,
445 MaudioSpecialInputProtocol::BALANCE_MAX,
446 MaudioSpecialInputProtocol::BALANCE_MIN,
447 MaudioSpecialInputProtocol::BALANCE_MAX,
448 ],
449 spdif_balances: [
450 MaudioSpecialInputProtocol::BALANCE_MIN,
451 MaudioSpecialInputProtocol::BALANCE_MAX,
452 ],
453 adat_balances: [
454 MaudioSpecialInputProtocol::BALANCE_MIN,
455 MaudioSpecialInputProtocol::BALANCE_MAX,
456 MaudioSpecialInputProtocol::BALANCE_MIN,
457 MaudioSpecialInputProtocol::BALANCE_MAX,
458 MaudioSpecialInputProtocol::BALANCE_MIN,
459 MaudioSpecialInputProtocol::BALANCE_MAX,
460 MaudioSpecialInputProtocol::BALANCE_MIN,
461 MaudioSpecialInputProtocol::BALANCE_MAX,
462 ],
463 }
464 }
465}
466
467#[derive(Default, Debug)]
469pub struct MaudioSpecialInputProtocol;
470
471impl MaudioSpecialInputProtocol {
472 pub const GAIN_MIN: i16 = i16::MIN;
474 pub const GAIN_MAX: i16 = 0;
476 pub const GAIN_STEP: i16 = 0x100;
478
479 pub const BALANCE_MIN: i16 = i16::MIN;
481 pub const BALANCE_MAX: i16 = i16::MAX;
483 pub const BALANCE_STEP: i16 = 0x100;
485}
486
487impl SpecialParametersSerdes<MaudioSpecialInputParameters> for MaudioSpecialInputProtocol {
488 const OFFSET_RANGES: &'static [&'static Range<usize>] = &[
489 &STREAM_INPUT_GAIN_RANGE,
490 &ANALOG_INPUT_GAIN_RANGE,
491 &SPDIF_INPUT_GAIN_RANGE,
492 &ADAT_INPUT_GAIN_RANGE,
493 &ANALOG_INPUT_BALANCE_RANGE,
494 &SPDIF_INPUT_BALANCE_RANGE,
495 &ADAT_INPUT_BALANCE_RANGE,
496 ];
497
498 fn serialize(params: &MaudioSpecialInputParameters, raw: &mut [u8]) {
499 [
500 (¶ms.stream_gains[..], &STREAM_INPUT_GAIN_RANGE),
501 (¶ms.analog_gains[..], &ANALOG_INPUT_GAIN_RANGE),
502 (¶ms.spdif_gains[..], &SPDIF_INPUT_GAIN_RANGE),
503 (¶ms.adat_gains[..], &ADAT_INPUT_GAIN_RANGE),
504 (¶ms.analog_balances[..], &ANALOG_INPUT_BALANCE_RANGE),
505 (¶ms.spdif_balances[..], &SPDIF_INPUT_BALANCE_RANGE),
506 (¶ms.adat_balances[..], &ADAT_INPUT_BALANCE_RANGE),
507 ]
508 .iter()
509 .for_each(|(gains, range)| {
510 gains.iter().enumerate().for_each(|(i, gain)| {
511 let pos = range.start + i * 2;
512 raw[pos..(pos + 2)].copy_from_slice(&gain.to_be_bytes());
513 })
514 });
515 }
516
517 fn deserialize(params: &mut MaudioSpecialInputParameters, raw: &[u8]) {
518 let mut doublet = [0u8; 2];
519
520 [
521 (&mut params.stream_gains[..], &STREAM_INPUT_GAIN_RANGE),
522 (&mut params.analog_gains[..], &ANALOG_INPUT_GAIN_RANGE),
523 (&mut params.spdif_gains[..], &SPDIF_INPUT_GAIN_RANGE),
524 (&mut params.adat_gains[..], &ADAT_INPUT_GAIN_RANGE),
525 (&mut params.analog_balances[..], &ANALOG_INPUT_BALANCE_RANGE),
526 (&mut params.spdif_balances[..], &SPDIF_INPUT_BALANCE_RANGE),
527 (&mut params.adat_balances[..], &ADAT_INPUT_BALANCE_RANGE),
528 ]
529 .iter_mut()
530 .for_each(|(gains, range)| {
531 gains.iter_mut().enumerate().for_each(|(i, gain)| {
532 let pos = range.start + i * 2;
533 doublet.copy_from_slice(&raw[pos..(pos + 2)]);
534 *gain = i16::from_be_bytes(doublet);
535 })
536 });
537 }
538}
539
540#[derive(Debug, Copy, Clone, Eq, PartialEq)]
542pub enum OutputSource {
543 MixerOutputPair,
545 AuxOutputPair0,
547}
548
549impl Default for OutputSource {
550 fn default() -> Self {
551 Self::MixerOutputPair
552 }
553}
554
555#[derive(Debug, Copy, Clone, Eq, PartialEq)]
557pub enum HeadphoneSource {
558 MixerOutputPair0,
560 MixerOutputPair1,
562 AuxOutputPair0,
564}
565
566impl Default for HeadphoneSource {
567 fn default() -> Self {
568 Self::AuxOutputPair0
569 }
570}
571
572#[derive(Debug, Copy, Clone, PartialEq, Eq)]
574pub struct MaudioSpecialOutputParameters {
575 pub analog_volumes: [i16; 4],
577 pub analog_pair_sources: [OutputSource; 2],
579 pub headphone_volumes: [i16; 4],
581 pub headphone_pair_sources: [HeadphoneSource; 2],
583}
584
585impl Default for MaudioSpecialOutputParameters {
586 fn default() -> Self {
587 Self {
588 analog_volumes: [MaudioSpecialOutputProtocol::VOLUME_MAX; 4],
589 analog_pair_sources: [OutputSource::MixerOutputPair; 2],
590 headphone_volumes: [MaudioSpecialOutputProtocol::VOLUME_MAX; 4],
591 headphone_pair_sources: [
592 HeadphoneSource::MixerOutputPair0,
593 HeadphoneSource::MixerOutputPair1,
594 ],
595 }
596 }
597}
598
599#[derive(Default, Debug)]
601pub struct MaudioSpecialOutputProtocol;
602
603impl MaudioSpecialOutputProtocol {
604 pub const VOLUME_MIN: i16 = i16::MIN;
606 pub const VOLUME_MAX: i16 = 0;
608 pub const VOLUME_STEP: i16 = 0x100;
610}
611
612impl SpecialParametersSerdes<MaudioSpecialOutputParameters> for MaudioSpecialOutputProtocol {
613 const OFFSET_RANGES: &'static [&'static Range<usize>] = &[
614 &ANALOG_OUTPUT_VOLUME_RANGE,
615 &HEADPHONE_VOLUME_RANGE,
616 &HEADPHONE_PAIR_SOURCE_RANGE,
617 &ANALOG_OUTPUT_PAIR_SOURCE_RANGE,
618 ];
619
620 fn serialize(params: &MaudioSpecialOutputParameters, raw: &mut [u8]) {
621 [
622 (¶ms.analog_volumes[..], &ANALOG_OUTPUT_VOLUME_RANGE),
623 (¶ms.headphone_volumes[..], &HEADPHONE_VOLUME_RANGE),
624 ]
625 .iter()
626 .for_each(|(vols, range)| {
627 vols.iter().enumerate().for_each(|(i, vol)| {
628 let pos = range.start + i * 2;
629 raw[pos..(pos + 2)].copy_from_slice(&vol.to_be_bytes());
630 });
631 });
632
633 let mut quadlet = [0; 4];
634 let pos = HEADPHONE_PAIR_SOURCE_RANGE.start;
635 quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
636 let mut val = u32::from_be_bytes(quadlet);
637
638 params
639 .headphone_pair_sources
640 .iter()
641 .enumerate()
642 .for_each(|(i, &src)| {
643 let shift = i * 16;
644 let mask = 0x07;
645 let flag = match src {
646 HeadphoneSource::MixerOutputPair0 => 0x01,
647 HeadphoneSource::MixerOutputPair1 => 0x02,
648 HeadphoneSource::AuxOutputPair0 => 0x04,
649 };
650
651 val &= !(mask << shift);
652 val |= flag << shift;
653 });
654
655 raw[pos..(pos + 4)].copy_from_slice(&val.to_be_bytes());
656
657 let pos = ANALOG_OUTPUT_PAIR_SOURCE_RANGE.start;
658 quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
659 let mut val = u32::from_be_bytes(quadlet);
660
661 params
662 .analog_pair_sources
663 .iter()
664 .enumerate()
665 .for_each(|(i, &src)| {
666 let shift = i;
667 let mask = 0x01;
668 let flag = match src {
669 OutputSource::MixerOutputPair => 0x00,
670 OutputSource::AuxOutputPair0 => 0x01,
671 };
672
673 val &= !(mask << shift);
674 val |= flag << shift;
675 });
676
677 raw[pos..(pos + 4)].copy_from_slice(&val.to_be_bytes());
678 }
679
680 fn deserialize(params: &mut MaudioSpecialOutputParameters, raw: &[u8]) {
681 let mut doublet = [0u8; 2];
682
683 [
684 (&mut params.analog_volumes[..], &ANALOG_OUTPUT_VOLUME_RANGE),
685 (&mut params.headphone_volumes[..], &HEADPHONE_VOLUME_RANGE),
686 ]
687 .iter_mut()
688 .for_each(|(vols, range)| {
689 vols.iter_mut().enumerate().for_each(|(i, vol)| {
690 let pos = range.start + i * 2;
691 doublet.copy_from_slice(&raw[pos..(pos + 2)]);
692 *vol = i16::from_be_bytes(doublet);
693 });
694 });
695
696 let mut quadlet = [0u8; 4];
697 let pos = HEADPHONE_PAIR_SOURCE_RANGE.start;
698 quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
699 let val = u32::from_be_bytes(quadlet);
700
701 params
702 .headphone_pair_sources
703 .iter_mut()
704 .enumerate()
705 .for_each(|(i, src)| {
706 let shift = i * 16;
707 let mask = 0x07;
708 let flag = (val >> shift) & mask;
709 *src = match flag {
710 0x04 => HeadphoneSource::AuxOutputPair0,
711 0x02 => HeadphoneSource::MixerOutputPair1,
712 _ => HeadphoneSource::MixerOutputPair0,
713 };
714 });
715
716 let pos = ANALOG_OUTPUT_PAIR_SOURCE_RANGE.start;
717 quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
718 let val = u32::from_be_bytes(quadlet);
719
720 params
721 .analog_pair_sources
722 .iter_mut()
723 .enumerate()
724 .for_each(|(i, src)| {
725 let shift = i;
726 let mask = 0x01;
727 let flag = (val >> shift) & mask;
728 *src = match flag {
729 0x01 => OutputSource::AuxOutputPair0,
730 _ => OutputSource::MixerOutputPair,
731 };
732 });
733 }
734}
735
736#[derive(Debug, Copy, Clone, PartialEq, Eq)]
738pub struct MaudioSpecialAuxParameters {
739 pub output_volumes: [i16; 2],
741 pub stream_gains: [i16; 4],
743 pub analog_gains: [i16; 8],
745 pub spdif_gains: [i16; 2],
747 pub adat_gains: [i16; 8],
749}
750
751impl Default for MaudioSpecialAuxParameters {
752 fn default() -> Self {
753 Self {
754 output_volumes: [MaudioSpecialAuxProtocol::VOLUME_MAX; 2],
755 stream_gains: [0; 4],
756 analog_gains: [
757 MaudioSpecialAuxProtocol::GAIN_MAX,
758 MaudioSpecialAuxProtocol::GAIN_MAX,
759 MaudioSpecialAuxProtocol::GAIN_MIN,
760 MaudioSpecialAuxProtocol::GAIN_MIN,
761 MaudioSpecialAuxProtocol::GAIN_MIN,
762 MaudioSpecialAuxProtocol::GAIN_MIN,
763 MaudioSpecialAuxProtocol::GAIN_MIN,
764 MaudioSpecialAuxProtocol::GAIN_MIN,
765 ],
766 spdif_gains: [MaudioSpecialAuxProtocol::GAIN_MIN; 2],
767 adat_gains: [MaudioSpecialAuxProtocol::GAIN_MIN; 8],
768 }
769 }
770}
771
772#[derive(Default, Debug)]
774pub struct MaudioSpecialAuxProtocol;
775
776impl MaudioSpecialAuxProtocol {
777 pub const GAIN_MIN: i16 = i16::MIN;
779 pub const GAIN_MAX: i16 = 0;
781 pub const GAIN_STEP: i16 = 0x100;
783
784 pub const VOLUME_MIN: i16 = i16::MIN;
786 pub const VOLUME_MAX: i16 = 0;
788 pub const VOLUME_STEP: i16 = 0x100;
790}
791
792impl SpecialParametersSerdes<MaudioSpecialAuxParameters> for MaudioSpecialAuxProtocol {
793 const OFFSET_RANGES: &'static [&'static Range<usize>] = &[
794 &AUX_OUTPUT_VOLUME_RANGE,
795 &AUX_STREAM_INPUT_GAIN_RANGE,
796 &AUX_ANALOG_INPUT_GAIN_RANGE,
797 &AUX_SPDIF_INPUT_GAIN_RANGE,
798 &AUX_ADAT_INPUT_GAIN_RANGE,
799 ];
800
801 fn serialize(params: &MaudioSpecialAuxParameters, raw: &mut [u8]) {
802 [
803 (¶ms.output_volumes[..], &AUX_OUTPUT_VOLUME_RANGE),
804 (¶ms.stream_gains[..], &AUX_STREAM_INPUT_GAIN_RANGE),
805 (¶ms.analog_gains[..], &AUX_ANALOG_INPUT_GAIN_RANGE),
806 (¶ms.spdif_gains[..], &AUX_SPDIF_INPUT_GAIN_RANGE),
807 (¶ms.adat_gains[..], &AUX_ADAT_INPUT_GAIN_RANGE),
808 ]
809 .iter()
810 .for_each(|(levels, range)| {
811 levels.iter().enumerate().for_each(|(i, level)| {
812 let pos = range.start + i * 2;
813 raw[pos..(pos + 2)].copy_from_slice(&level.to_be_bytes());
814 })
815 });
816 }
817
818 fn deserialize(params: &mut MaudioSpecialAuxParameters, raw: &[u8]) {
819 let mut doublet = [0u8; 2];
820
821 [
822 (&mut params.output_volumes[..], &AUX_OUTPUT_VOLUME_RANGE),
823 (&mut params.stream_gains[..], &AUX_STREAM_INPUT_GAIN_RANGE),
824 (&mut params.analog_gains[..], &AUX_ANALOG_INPUT_GAIN_RANGE),
825 (&mut params.spdif_gains[..], &AUX_SPDIF_INPUT_GAIN_RANGE),
826 (&mut params.adat_gains[..], &AUX_ADAT_INPUT_GAIN_RANGE),
827 ]
828 .iter_mut()
829 .for_each(|(levels, range)| {
830 levels.iter_mut().enumerate().for_each(|(i, level)| {
831 let pos = range.start + i * 2;
832 doublet.copy_from_slice(&raw[pos..(pos + 2)]);
833 *level = i16::from_be_bytes(doublet);
834 })
835 });
836 }
837}
838
839#[derive(Debug, Copy, Clone, PartialEq, Eq)]
841pub struct MaudioSpecialMixerParameters {
842 pub analog_pairs: [[bool; 4]; 2],
844 pub spdif_pairs: [bool; 2],
846 pub adat_pairs: [[bool; 4]; 2],
848 pub stream_pairs: [[bool; 2]; 2],
850}
851
852impl Default for MaudioSpecialMixerParameters {
853 fn default() -> Self {
854 Self {
855 analog_pairs: [[false; 4]; 2],
856 spdif_pairs: [false; 2],
857 adat_pairs: [[false; 4]; 2],
858 stream_pairs: [[true, false], [false, true]],
859 }
860 }
861}
862
863#[derive(Default, Debug)]
865pub struct MaudioSpecialMixerProtocol;
866
867impl SpecialParametersSerdes<MaudioSpecialMixerParameters> for MaudioSpecialMixerProtocol {
868 const OFFSET_RANGES: &'static [&'static Range<usize>] =
869 &[&MIXER_PHYS_SOURCE_RANGE, &MIXER_STREAM_SOURCE_RANGE];
870
871 fn serialize(params: &MaudioSpecialMixerParameters, raw: &mut [u8]) {
872 let mut quadlet = [0; 4];
873
874 quadlet.copy_from_slice(&raw[MIXER_PHYS_SOURCE_RANGE]);
875 let mut val = u32::from_be_bytes(quadlet);
876
877 params
878 .analog_pairs
879 .iter()
880 .enumerate()
881 .for_each(|(i, pairs)| {
882 pairs.iter().enumerate().for_each(|(j, &enabled)| {
883 let flag = 1u32 << (i * 4 + j);
884 val &= !flag;
885 if enabled {
886 val |= flag;
887 }
888 });
889 });
890
891 params
892 .spdif_pairs
893 .iter()
894 .enumerate()
895 .for_each(|(i, &enabled)| {
896 let flag = 1u32 << (16 + i);
897 val &= !flag;
898 if enabled {
899 val |= flag;
900 }
901 });
902
903 params.adat_pairs.iter().enumerate().for_each(|(i, pairs)| {
904 pairs.iter().enumerate().for_each(|(j, &enabled)| {
905 let flag = 1u32 << (8 + i * 4 + j);
906 val &= !flag;
907 if enabled {
908 val |= flag;
909 }
910 });
911 });
912
913 raw[MIXER_PHYS_SOURCE_RANGE].copy_from_slice(&val.to_be_bytes());
914
915 quadlet.copy_from_slice(&raw[MIXER_STREAM_SOURCE_RANGE]);
916 let mut val = u32::from_be_bytes(quadlet);
917
918 params
919 .stream_pairs
920 .iter()
921 .enumerate()
922 .for_each(|(i, pairs)| {
923 pairs.iter().enumerate().for_each(|(j, &enabled)| {
924 let flag = 1u32 << (j * 2 + i);
925
926 val &= !flag;
927 if enabled {
928 val |= flag;
929 }
930 });
931 });
932
933 raw[MIXER_STREAM_SOURCE_RANGE].copy_from_slice(&val.to_be_bytes());
934 }
935
936 fn deserialize(params: &mut MaudioSpecialMixerParameters, raw: &[u8]) {
937 let mut quadlet = [0; 4];
938
939 quadlet.copy_from_slice(&raw[MIXER_PHYS_SOURCE_RANGE]);
940 let val = u32::from_be_bytes(quadlet);
941
942 params
943 .analog_pairs
944 .iter_mut()
945 .enumerate()
946 .for_each(|(i, pairs)| {
947 pairs.iter_mut().enumerate().for_each(|(j, enabled)| {
948 let flag = 1u32 << (i * 4 + j);
949 *enabled = val & flag > 0;
950 });
951 });
952
953 params
954 .spdif_pairs
955 .iter_mut()
956 .enumerate()
957 .for_each(|(i, enabled)| {
958 let flag = 1u32 << (16 + i);
959 *enabled = val & flag > 0;
960 });
961
962 params
963 .adat_pairs
964 .iter_mut()
965 .enumerate()
966 .for_each(|(i, pairs)| {
967 pairs.iter_mut().enumerate().for_each(|(j, enabled)| {
968 let flag = 1u32 << (8 + i * 4 + j);
969 *enabled = val & flag > 0;
970 });
971 });
972
973 quadlet.copy_from_slice(&raw[MIXER_STREAM_SOURCE_RANGE]);
974 let val = u32::from_be_bytes(quadlet);
975
976 params
977 .stream_pairs
978 .iter_mut()
979 .enumerate()
980 .for_each(|(i, pairs)| {
981 pairs.iter_mut().enumerate().for_each(|(j, enabled)| {
982 let flag = 1u32 << (j * 2 + i);
983 *enabled = val & flag > 0;
984 });
985 });
986 }
987}
988
989pub trait SpecialParametersSerdes<T: Copy> {
991 const OFFSET_RANGES: &'static [&'static Range<usize>];
993
994 fn serialize(params: &T, raw: &mut [u8]);
996
997 fn deserialize(params: &mut T, raw: &[u8]);
999}
1000
1001pub trait MaudioSpecialParameterProtocol<T: Copy>: SpecialParametersSerdes<T> {
1003 fn whole_update(
1005 req: &FwReq,
1006 node: &FwNode,
1007 params: &T,
1008 cache: &mut MaudioSpecialStateCache,
1009 timeout_ms: u32,
1010 ) -> Result<(), Error> {
1011 assert!(Self::OFFSET_RANGES.len() > 0);
1012
1013 Self::serialize(params, &mut cache.0);
1014
1015 let mut peek_iter = Self::OFFSET_RANGES.iter().peekable();
1016 let mut prev_offset = Self::OFFSET_RANGES[0].start;
1017
1018 while let Some(curr_range) = peek_iter.next() {
1020 let begin_offset = prev_offset;
1021 let mut next = peek_iter.peek();
1022
1023 if let Some(next_range) = next {
1024 if curr_range.end != next_range.start {
1025 prev_offset = next_range.start;
1026 next = None;
1027 }
1028 }
1029
1030 if next.is_none() {
1031 let raw = &mut cache.0[begin_offset..curr_range.end];
1032 if raw.len() == 4 {
1033 FwTcode::WriteQuadletRequest
1034 } else {
1035 FwTcode::WriteBlockRequest
1036 };
1037
1038 req.transaction_sync(
1039 node,
1040 FwTcode::WriteQuadletRequest,
1041 DM_APPL_PARAM_OFFSET + begin_offset as u64,
1042 raw.len(),
1043 raw,
1044 timeout_ms,
1045 )?;
1046 }
1047 }
1048
1049 Ok(())
1050 }
1051
1052 fn partial_update(
1054 req: &FwReq,
1055 node: &FwNode,
1056 params: &T,
1057 cache: &mut MaudioSpecialStateCache,
1058 old: &mut T,
1059 timeout_ms: u32,
1060 ) -> Result<(), Error> {
1061 assert!(Self::OFFSET_RANGES.len() > 0);
1062
1063 let mut new = [0; CACHE_SIZE];
1064 new.copy_from_slice(&cache.0);
1065 Self::serialize(params, &mut new);
1066
1067 Self::OFFSET_RANGES
1068 .iter()
1069 .try_for_each(|range| {
1070 let raw = &mut new[range.start..range.end];
1071
1072 if raw != &cache.0[range.start..range.end] {
1073 if raw.len() == 4 {
1074 FwTcode::WriteQuadletRequest
1075 } else {
1076 FwTcode::WriteBlockRequest
1077 };
1078
1079 req.transaction_sync(
1080 node,
1081 FwTcode::WriteQuadletRequest,
1082 DM_APPL_PARAM_OFFSET + range.start as u64,
1083 raw.len(),
1084 raw,
1085 timeout_ms,
1086 )
1087 .map(|_| cache.0[range.start..range.end].copy_from_slice(raw))
1088 } else {
1089 Ok(())
1090 }
1091 })
1092 .map(|_| *old = *params)
1093 }
1094}
1095
1096impl<O: SpecialParametersSerdes<T>, T: Copy> MaudioSpecialParameterProtocol<T> for O {}
1097
1098#[cfg(test)]
1099mod test {
1100 use super::*;
1101
1102 #[test]
1103 fn offset_ranges() {
1104 let ranges = [
1105 &STREAM_INPUT_GAIN_RANGE,
1106 &ANALOG_OUTPUT_VOLUME_RANGE,
1107 &ANALOG_INPUT_GAIN_RANGE,
1108 &SPDIF_INPUT_GAIN_RANGE,
1109 &ADAT_INPUT_GAIN_RANGE,
1110 &AUX_OUTPUT_VOLUME_RANGE,
1111 &HEADPHONE_VOLUME_RANGE,
1112 &ANALOG_INPUT_BALANCE_RANGE,
1113 &SPDIF_INPUT_BALANCE_RANGE,
1114 &ADAT_INPUT_BALANCE_RANGE,
1115 &AUX_STREAM_INPUT_GAIN_RANGE,
1116 &AUX_ANALOG_INPUT_GAIN_RANGE,
1117 &AUX_SPDIF_INPUT_GAIN_RANGE,
1118 &AUX_ADAT_INPUT_GAIN_RANGE,
1119 &MIXER_PHYS_SOURCE_RANGE,
1120 &MIXER_STREAM_SOURCE_RANGE,
1121 &HEADPHONE_PAIR_SOURCE_RANGE,
1122 &ANALOG_OUTPUT_PAIR_SOURCE_RANGE,
1123 ];
1124
1125 (0..CACHE_SIZE).for_each(|pos| {
1126 let count = ranges.iter().filter(|range| range.contains(&pos)).count();
1127 assert_eq!(count, 1);
1128 });
1129 }
1130
1131 #[test]
1132 fn input_params_serdes() {
1133 let expected = MaudioSpecialInputParameters {
1134 stream_gains: [-2, -1, 0, 1],
1135 analog_gains: [-3, -2, -1, 0, 1, 2, 3, 4],
1136 spdif_gains: [-1, 0],
1137 adat_gains: [-3, -2, -1, 0, 1, 2, 3, 4],
1138 analog_balances: [-3, -2, -1, 0, 1, 2, 3, 4],
1139 spdif_balances: [-1, 0],
1140 adat_balances: [-3, -2, -1, 0, 1, 2, 3, 4],
1141 };
1142 let mut cache = MaudioSpecialStateCache::default();
1143 MaudioSpecialInputProtocol::serialize(&expected, &mut cache.0);
1144
1145 let mut params = MaudioSpecialInputParameters::default();
1146 MaudioSpecialInputProtocol::deserialize(&mut params, &cache.0);
1147
1148 assert_eq!(expected, params);
1149 }
1150
1151 #[test]
1152 fn output_params_serdes() {
1153 let expected = MaudioSpecialOutputParameters {
1154 analog_volumes: [-2, -1, 0, 1],
1155 analog_pair_sources: [OutputSource::MixerOutputPair, OutputSource::AuxOutputPair0],
1156 headphone_volumes: [-1, 0, 1, 2],
1157 headphone_pair_sources: [
1158 HeadphoneSource::AuxOutputPair0,
1159 HeadphoneSource::MixerOutputPair0,
1160 ],
1161 };
1162 let mut cache = MaudioSpecialStateCache::default();
1163 MaudioSpecialOutputProtocol::serialize(&expected, &mut cache.0);
1164
1165 let mut params = MaudioSpecialOutputParameters::default();
1166 MaudioSpecialOutputProtocol::deserialize(&mut params, &cache.0);
1167
1168 assert_eq!(expected, params);
1169 }
1170
1171 #[test]
1172 fn aux_params_serdes() {
1173 let expected = MaudioSpecialAuxParameters {
1174 output_volumes: [0, 1],
1175 stream_gains: [-3, -2, -1, 0],
1176 analog_gains: [-3, -2, -1, 0, 1, 2, 3, 4],
1177 spdif_gains: [-1, 0],
1178 adat_gains: [-3, -2, -1, 0, 1, 2, 3, 4],
1179 };
1180 let mut cache = MaudioSpecialStateCache::default();
1181 MaudioSpecialAuxProtocol::serialize(&expected, &mut cache.0);
1182
1183 let mut params = MaudioSpecialAuxParameters::default();
1184 MaudioSpecialAuxProtocol::deserialize(&mut params, &cache.0);
1185
1186 assert_eq!(expected, params);
1187 }
1188
1189 #[test]
1190 fn mixer_params_serdes() {
1191 let expected = MaudioSpecialMixerParameters {
1192 analog_pairs: [[false, true, false, true], [true, false, true, false]],
1193 spdif_pairs: [true, false],
1194 adat_pairs: [[false, true, false, true], [true, false, true, false]],
1195 stream_pairs: [[true, false], [false, true]],
1196 };
1197 let mut cache = MaudioSpecialStateCache::default();
1198 MaudioSpecialMixerProtocol::serialize(&expected, &mut cache.0);
1199
1200 let mut params = MaudioSpecialMixerParameters::default();
1201 MaudioSpecialMixerProtocol::deserialize(&mut params, &cache.0);
1202
1203 assert_eq!(expected, params);
1204 }
1205}