1#![doc = include_str!("../README.md")]
5
6pub mod amdtp;
8
9use ta1394_avc_general::*;
10
11pub const AUDIO_SUBUNIT_0_ADDR: AvcAddr = AvcAddr::Subunit(AUDIO_SUBUNIT_0);
13
14#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16enum AudioFuncBlkType {
17 Selector,
19 Feature,
21 Processing,
23 Reserved(u8),
24}
25
26impl Default for AudioFuncBlkType {
27 fn default() -> Self {
28 Self::Reserved(0xff)
29 }
30}
31
32impl AudioFuncBlkType {
33 fn from_val(val: u8) -> Self {
34 match val {
35 0x80 => Self::Selector,
36 0x81 => Self::Feature,
37 0x82 => Self::Processing,
38 _ => Self::Reserved(val),
39 }
40 }
41
42 fn to_val(&self) -> u8 {
43 match self {
44 Self::Selector => 0x80,
45 Self::Feature => 0x81,
46 Self::Processing => 0x82,
47 Self::Reserved(val) => *val,
48 }
49 }
50}
51
52#[derive(Clone, Copy, Debug, Eq, PartialEq)]
54pub enum CtlAttr {
55 Resolution,
57 Minimum,
59 Maximum,
61 Default,
63 Duration,
65 Current,
67 Move,
69 Delta,
71 Reserved(u8),
72}
73
74impl Default for CtlAttr {
75 fn default() -> Self {
76 Self::Reserved(0xff)
77 }
78}
79
80impl CtlAttr {
81 fn from_val(val: u8) -> Self {
82 match val {
83 0x01 => Self::Resolution,
84 0x02 => Self::Minimum,
85 0x03 => Self::Maximum,
86 0x04 => Self::Default,
87 0x08 => Self::Duration,
88 0x10 => Self::Current,
89 0x18 => Self::Move,
90 0x19 => Self::Delta,
91 _ => Self::Reserved(val),
92 }
93 }
94
95 fn to_val(&self) -> u8 {
96 match self {
97 Self::Resolution => 0x01,
98 Self::Minimum => 0x02,
99 Self::Maximum => 0x03,
100 Self::Default => 0x04,
101 Self::Duration => 0x08,
102 Self::Current => 0x10,
103 Self::Move => 0x18,
104 Self::Delta => 0x19,
105 Self::Reserved(val) => *val,
106 }
107 }
108}
109
110impl std::fmt::Display for CtlAttr {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 let label = match self {
113 Self::Resolution => "resolution".to_owned(),
114 Self::Minimum => "minimum".to_owned(),
115 Self::Maximum => "maximum".to_owned(),
116 Self::Default => "default".to_owned(),
117 Self::Duration => "duration".to_owned(),
118 Self::Current => "current".to_owned(),
119 Self::Move => "move".to_owned(),
120 Self::Delta => "delta".to_owned(),
121 Self::Reserved(val) => format!("reserved: {}", val),
122 };
123 write!(f, "{}", &label)
124 }
125}
126
127#[derive(Clone, Debug, Eq, PartialEq)]
129struct AudioFuncBlkCtl {
130 selector: u8,
132 data: Vec<u8>,
134}
135
136impl Default for AudioFuncBlkCtl {
137 fn default() -> Self {
138 Self {
139 selector: 0xff,
140 data: Default::default(),
141 }
142 }
143}
144
145impl AudioFuncBlkCtl {
146 const LENGTH_MIN: usize = 1;
147
148 fn from_raw(raw: &[u8]) -> Result<Self, AvcRespParseError> {
149 if raw.len() < Self::LENGTH_MIN {
150 Err(AvcRespParseError::TooShortResp(Self::LENGTH_MIN))?;
151 }
152
153 let mut ctl = Self {
154 selector: raw[0],
155 data: Default::default(),
156 };
157 if raw.len() > 1 {
158 let length = raw[1] as usize;
159 if raw.len() >= 2 + length {
160 ctl.data.extend_from_slice(&raw[2..(2 + length)]);
161 }
162 }
163 Ok(ctl)
164 }
165
166 fn to_raw(&self) -> Vec<u8> {
167 let mut raw = Vec::with_capacity(Self::LENGTH_MIN);
168 raw.push(self.selector);
169 if self.data.len() > 0 {
170 raw.push(self.data.len() as u8);
171 raw.extend_from_slice(&self.data);
172 }
173 raw
174 }
175}
176
177#[derive(Clone, Debug, Eq, PartialEq)]
180struct AudioFuncBlk {
181 func_blk_type: AudioFuncBlkType,
182 func_blk_id: u8,
183 ctl_attr: CtlAttr,
184 audio_selector_data: Vec<u8>,
185 ctl: AudioFuncBlkCtl,
186}
187
188impl Default for AudioFuncBlk {
189 fn default() -> Self {
190 Self {
191 func_blk_type: Default::default(),
192 func_blk_id: 0xff,
193 ctl_attr: Default::default(),
194 audio_selector_data: Default::default(),
195 ctl: Default::default(),
196 }
197 }
198}
199
200impl AudioFuncBlk {
201 fn build_operands(&self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
202 if let AvcAddr::Subunit(AvcAddrSubunit {
203 subunit_type: AvcSubunitType::Audio,
204 subunit_id: _,
205 }) = addr
206 {
207 let mut operands = Vec::new();
208 operands.push(self.func_blk_type.to_val());
209 operands.push(self.func_blk_id);
210 operands.push(self.ctl_attr.to_val());
211 operands.push(1 + self.audio_selector_data.len() as u8);
212 operands.extend_from_slice(&self.audio_selector_data);
213 operands.append(&mut self.ctl.to_raw());
214 Ok(operands)
215 } else {
216 Err(AvcCmdBuildError::InvalidAddress)
217 }
218 }
219
220 fn parse_operands(&mut self, operands: &[u8]) -> Result<(), AvcRespParseError> {
221 if operands.len() < 4 {
222 Err(AvcRespParseError::TooShortResp(4))?;
223 }
224 let func_blk_type = AudioFuncBlkType::from_val(operands[0]);
225 if func_blk_type != self.func_blk_type {
226 Err(AvcRespParseError::UnexpectedOperands(0))?;
227 }
228
229 let func_blk_id = operands[1];
230 if func_blk_id != self.func_blk_id {
231 Err(AvcRespParseError::UnexpectedOperands(1))?;
232 }
233
234 let ctl_attr = CtlAttr::from_val(operands[2]);
235 if ctl_attr != self.ctl_attr {
236 Err(AvcRespParseError::UnexpectedOperands(2))?;
237 }
238
239 let mut audio_selector_length = operands[3] as usize;
240 if operands.len() < 3 + audio_selector_length {
241 Err(AvcRespParseError::TooShortResp(3 + audio_selector_length))?;
242 } else if audio_selector_length < 1 {
243 Err(AvcRespParseError::UnexpectedOperands(3))?;
244 }
245 audio_selector_length -= 1;
246 self.audio_selector_data = operands[4..(4 + audio_selector_length)].to_vec();
247
248 self.ctl = AudioFuncBlkCtl::from_raw(&operands[(4 + audio_selector_length)..])
249 .map_err(|err| err.add_offset(4))?;
250
251 Ok(())
252 }
253}
254
255impl AvcOp for AudioFuncBlk {
256 const OPCODE: u8 = 0xb8;
257}
258
259impl AvcStatus for AudioFuncBlk {
260 fn build_operands(&mut self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
261 AudioFuncBlk::build_operands(self, addr)
262 }
263
264 fn parse_operands(&mut self, _: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
265 AudioFuncBlk::parse_operands(self, operands)
266 }
267}
268
269impl AvcControl for AudioFuncBlk {
270 fn build_operands(&mut self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
271 AudioFuncBlk::build_operands(self, addr)
272 }
273
274 fn parse_operands(&mut self, _: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
275 AudioFuncBlk::parse_operands(self, operands)
276 }
277}
278
279pub struct AudioSelector {
284 pub input_plug_id: u8,
285 func_blk: AudioFuncBlk,
286}
287
288impl AudioSelector {
289 const SELECTOR_CONTROL: u8 = 0x01;
290
291 pub fn new(func_blk_id: u8, ctl_attr: CtlAttr, input_plug_id: u8) -> Self {
292 Self {
293 input_plug_id,
294 func_blk: AudioFuncBlk {
295 func_blk_type: AudioFuncBlkType::Selector,
296 func_blk_id,
297 ctl_attr,
298 ..Default::default()
299 },
300 }
301 }
302
303 fn build_func_blk(&mut self) -> Result<(), AvcCmdBuildError> {
304 self.func_blk.audio_selector_data.clear();
305 self.func_blk.audio_selector_data.push(self.input_plug_id);
306 self.func_blk.ctl.selector = Self::SELECTOR_CONTROL;
307 self.func_blk.ctl.data.clear();
308 Ok(())
309 }
310
311 fn parse_func_blk(&mut self) -> Result<(), AvcRespParseError> {
312 if self.func_blk.ctl.selector != Self::SELECTOR_CONTROL {
313 Err(AvcRespParseError::UnexpectedOperands(5))
314 } else if self.func_blk.ctl.data.len() > 0 {
315 Err(AvcRespParseError::UnexpectedOperands(7))
316 } else {
317 self.input_plug_id = self.func_blk.audio_selector_data[0];
318 Ok(())
319 }
320 }
321}
322
323impl AvcOp for AudioSelector {
324 const OPCODE: u8 = AudioFuncBlk::OPCODE;
325}
326
327impl AvcStatus for AudioSelector {
328 fn build_operands(&mut self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
329 self.build_func_blk()
330 .and_then(|_| AvcStatus::build_operands(&mut self.func_blk, addr))
331 }
332
333 fn parse_operands(&mut self, addr: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
334 AvcStatus::parse_operands(&mut self.func_blk, addr, operands)
335 .and_then(|_| self.parse_func_blk())
336 }
337}
338
339impl AvcControl for AudioSelector {
340 fn build_operands(&mut self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
341 self.build_func_blk()
342 .and_then(|_| AvcControl::build_operands(&mut self.func_blk, addr))
343 }
344
345 fn parse_operands(&mut self, addr: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
346 AvcControl::parse_operands(&mut self.func_blk, addr, operands)
347 .and_then(|_| self.parse_func_blk())
348 }
349}
350
351#[derive(Debug, Default, Clone, Eq, PartialEq)]
355pub struct VolumeData(pub Vec<i16>);
356
357impl VolumeData {
358 pub const VALUE_INVALID: i16 = 0x7fffu16 as i16;
360 pub const VALUE_MAX: i16 = 0x7ffeu16 as i16;
362 pub const VALUE_ZERO: i16 = 0;
364 pub const VALUE_MIN: i16 = 0x8001u16 as i16;
366 pub const VALUE_NEG_INFINITY: i16 = 0x8000u16 as i16;
368
369 pub fn new(count: usize) -> Self {
370 Self(vec![Self::VALUE_INVALID; count])
371 }
372
373 fn from_raw<T: AsRef<[u8]>>(raw: &T) -> Self {
374 Self(i16_vector_from_raw(raw.as_ref()))
375 }
376
377 fn to_raw(&self) -> Vec<u8> {
378 i16_vector_to_raw(&self.0)
379 }
380}
381
382#[derive(Debug, Clone, Eq, PartialEq)]
386pub struct LrBalanceData(pub i16);
387
388impl Default for LrBalanceData {
389 fn default() -> Self {
390 Self(Self::VALUE_INVALID)
391 }
392}
393
394impl LrBalanceData {
395 pub const VALUE_INVALID: i16 = 0x7fffu16 as i16;
397
398 pub const VALUE_LEFT_MAX: i16 = 0x7ffeu16 as i16;
400 pub const VALUE_LEFT_ZERO: i16 = 0;
402 pub const VALUE_LEFT_MIN: i16 = 0x8001u16 as i16;
404 pub const VALUE_LEFT_NEG_INFINITY: i16 = 0x8000u16 as i16;
406
407 pub const VALUE_RIGHT_MAX: i16 = 0x8000u16 as i16;
409 pub const VALUE_RIGHT_ZERO: i16 = 0;
411 pub const VALUE_RIGHT_MIN: i16 = 0x7ffdu16 as i16;
413 pub const VALUE_RIGHT_NEG_INFINITY: i16 = 0x7ffeu16 as i16;
415
416 fn from_raw<T: AsRef<[u8]>>(raw: &T) -> Self {
417 Self(i16_from_raw(raw.as_ref()))
418 }
419
420 fn to_raw(&self) -> Vec<u8> {
421 self.0.to_be_bytes().to_vec()
422 }
423}
424
425#[derive(Debug, Clone, Eq, PartialEq)]
429pub struct FrBalanceData(pub i16);
430
431impl Default for FrBalanceData {
432 fn default() -> Self {
433 Self(Self::VALUE_INVALID)
434 }
435}
436
437impl FrBalanceData {
438 pub const VALUE_INVALID: i16 = 0x7fffu16 as i16;
440
441 pub const VALUE_FRONT_MAX: i16 = 0x7ffeu16 as i16;
443 pub const VALUE_FRONT_ZERO: i16 = 0;
445 pub const VALUE_FRONT_MIN: i16 = 0x8001u16 as i16;
447 pub const VALUE_FRONT_NEG_INFINITY: i16 = 0x8000u16 as i16;
449
450 pub const VALUE_REAR_MAX: i16 = 0x8000u16 as i16;
452 pub const VALUE_REAR_ZERO: i16 = 0;
454 pub const VALUE_REAR_MIN: i16 = 0x7ffdu16 as i16;
456 pub const VALUE_REAR_NEG_INFINITY: i16 = 0x7ffeu16 as i16;
458
459 fn from_raw<T: AsRef<[u8]>>(raw: &T) -> Self {
460 Self(i16_from_raw(raw.as_ref()))
461 }
462
463 fn to_raw(&self) -> Vec<u8> {
464 self.0.to_be_bytes().to_vec()
465 }
466}
467
468#[derive(Debug, Default, Clone, Eq, PartialEq)]
472pub struct BassData(pub Vec<i8>);
473
474impl BassData {
475 pub const VALUE_INVALID: i8 = 0x7f;
477 pub const VALUE_MAX: i8 = 0x7e;
479 pub const VALUE_ZERO: i8 = 0x00;
481 pub const VALUE_MIN: i8 = 0x80u8 as i8;
483
484 pub fn new(count: usize) -> Self {
485 Self(vec![Self::VALUE_INVALID; count])
486 }
487
488 fn from_raw<T: AsRef<[u8]>>(raw: &T) -> Self {
489 Self(i8_vector_from_raw(raw.as_ref()))
490 }
491
492 fn to_raw(&self) -> Vec<u8> {
493 self.0.iter().map(|v| *v as u8).collect()
494 }
495}
496
497#[derive(Debug, Default, Clone, Eq, PartialEq)]
501pub struct MidData(pub Vec<i8>);
502
503impl MidData {
504 pub const VALUE_INVALID: i8 = 0x7f;
506 pub const VALUE_MAX: i8 = 0x7e;
508 pub const VALUE_ZERO: i8 = 0x00;
510 pub const VALUE_MIN: i8 = 0x80u8 as i8;
512
513 pub fn new(count: usize) -> Self {
514 Self(vec![Self::VALUE_INVALID; count])
515 }
516
517 fn from_raw<T: AsRef<[u8]>>(raw: &T) -> Self {
518 Self(i8_vector_from_raw(raw.as_ref()))
519 }
520
521 fn to_raw(&self) -> Vec<u8> {
522 self.0.iter().map(|v| *v as u8).collect()
523 }
524}
525
526#[derive(Debug, Default, Clone, Eq, PartialEq)]
530pub struct TrebleData(pub Vec<i8>);
531
532impl TrebleData {
533 pub const VALUE_INVALID: i8 = 0x7f;
535 pub const VALUE_MAX: i8 = 0x7e;
537 pub const VALUE_ZERO: i8 = 0x00;
539 pub const VALUE_MIN: i8 = 0x80u8 as i8;
541
542 pub fn new(count: usize) -> Self {
543 Self(vec![Self::VALUE_INVALID; count])
544 }
545
546 fn from_raw<T: AsRef<[u8]>>(raw: &T) -> Self {
547 Self(i8_vector_from_raw(raw.as_ref()))
548 }
549
550 fn to_raw(&self) -> Vec<u8> {
551 self.0.iter().map(|v| *v as u8).collect()
552 }
553}
554
555#[derive(Debug, Copy, Clone, Eq, PartialEq)]
559pub struct GraphicEqualizerData {
560 pub ansi_band_gains: [Option<i8>; Self::ANSI_BAND_COUNT],
596
597 pub extra_band_gains: [Option<i8>; Self::EXTRA_BAND_COUNT],
634}
635
636impl GraphicEqualizerData {
637 pub const VALUE_MIN: i8 = i8::MIN;
639
640 pub const VALUE_ZERO: i8 = 0;
642
643 pub const VALUE_MAX: i8 = i8::MAX;
645
646 const VALUE_INVALID: u8 = 0x7f;
647
648 const ANSI_BAND_COUNT: usize = 30;
649 const EXTRA_BAND_COUNT: usize = 32;
650
651 const LENGTH_MIN: usize = 8;
652
653 fn from_raw<T: AsRef<[u8]>>(raw: T) -> Self {
654 let mut ansi_band_gains = [None; Self::ANSI_BAND_COUNT];
655 let mut extra_band_gains = [None; Self::EXTRA_BAND_COUNT];
656
657 let mut gain_index = Self::LENGTH_MIN;
658
659 let mut band_gains = [
660 (ansi_band_gains.as_mut_slice(), 0usize),
661 (extra_band_gains.as_mut_slice(), 4usize),
662 ];
663
664 let r = raw.as_ref();
665
666 band_gains.iter_mut().for_each(|(gains, offset)| {
667 gains
668 .iter_mut()
669 .enumerate()
670 .filter(|(i, _)| (r[*offset + i / 8] & (1 << (i % 8)) > 0))
671 .for_each(|(_, gain)| {
672 *gain = if r.len() < gain_index {
673 None
674 } else if r[gain_index] == Self::VALUE_INVALID {
675 None
676 } else {
677 let val = Some(r[gain_index] as i8);
678 gain_index += 1;
679 val
680 }
681 });
682 });
683
684 Self {
685 ansi_band_gains,
686 extra_band_gains,
687 }
688 }
689
690 fn to_raw(&self) -> Vec<u8> {
691 let band_gains = [
692 (self.ansi_band_gains.as_slice(), 0usize),
693 (self.extra_band_gains.as_slice(), 4usize),
694 ];
695 let mut raw = vec![0x00u8; Self::LENGTH_MIN];
696
697 band_gains.iter().for_each(|(gains, offset)| {
698 gains
699 .iter()
700 .enumerate()
701 .filter_map(|(i, gain)| {
702 if let Some(g) = gain {
703 Some((i, *g))
704 } else {
705 None
706 }
707 })
708 .for_each(|(i, gain)| {
709 raw[offset + i / 8] |= 1 << (i % 8);
710 raw.push(gain as u8);
711 });
712 });
713
714 raw
715 }
716}
717
718#[derive(Debug, Default, Clone, Eq, PartialEq)]
722pub struct DelayData(pub Vec<u16>);
723
724impl DelayData {
725 pub const VALUE_INVALID: u16 = 0xffff;
727 pub const VALUE_MAX: u16 = 0x7ffe;
729 pub const VALUE_ZERO: u16 = 0;
731
732 pub fn new(count: usize) -> Self {
733 Self(vec![Self::VALUE_INVALID; count])
734 }
735
736 fn from_raw<T: AsRef<[u8]>>(raw: &T) -> Self {
737 Self(u16_vector_from_raw(raw.as_ref()))
738 }
739
740 fn to_raw(&self) -> Vec<u8> {
741 u16_vector_to_raw(&self.0)
742 }
743}
744
745fn i16_vector_to_raw(data: &[i16]) -> Vec<u8> {
746 data.iter().fold(Vec::new(), |mut raw, d| {
747 raw.extend_from_slice(&d.to_be_bytes());
748 raw
749 })
750}
751
752fn u16_vector_to_raw(data: &[u16]) -> Vec<u8> {
753 data.iter().fold(Vec::new(), |mut raw, d| {
754 raw.extend_from_slice(&d.to_be_bytes());
755 raw
756 })
757}
758
759fn bool_vector_to_raw(data: &[bool]) -> Vec<u8> {
760 data.iter()
761 .map(|&d| {
762 if d {
763 FeatureCtl::TRUE
764 } else {
765 FeatureCtl::FALSE
766 }
767 })
768 .collect()
769}
770
771#[derive(Clone, Debug, Eq, PartialEq)]
773pub enum FeatureCtl {
774 Mute(Vec<bool>),
776 Volume(VolumeData),
778 LrBalance(LrBalanceData),
780 FrBalance(FrBalanceData),
782 Bass(BassData),
784 Mid(MidData),
786 Treble(TrebleData),
788 GraphicEqualizer(GraphicEqualizerData),
790 AutomaticGain(Vec<bool>),
792 Delay(DelayData),
794 BassBoost(Vec<bool>),
796 Loudness(Vec<bool>),
798 Reserved(Vec<u8>),
799}
800
801impl FeatureCtl {
802 const MUTE: u8 = 0x01;
803 const VOLUME: u8 = 0x02;
804 const LR_BALANCE: u8 = 0x03;
805 const FR_BALANCE: u8 = 0x04;
806 const BASS: u8 = 0x05;
807 const MID: u8 = 0x06;
808 const TREBLE: u8 = 0x07;
809 const GRAPHIC_EQUALIZER: u8 = 0x08;
810 const AUTOMATIC_GAIN: u8 = 0x09;
811 const DELAY: u8 = 0x0a;
812 const BASS_BOOST: u8 = 0x0b;
813 const LOUDNESS: u8 = 0x0c;
814
815 const TRUE: u8 = 0x70;
816 const FALSE: u8 = 0x60;
817}
818
819impl FeatureCtl {
820 fn to_ctl(&self) -> AudioFuncBlkCtl {
821 match self {
822 Self::Mute(data) => AudioFuncBlkCtl {
823 selector: Self::MUTE,
824 data: bool_vector_to_raw(data),
825 },
826 Self::Volume(data) => AudioFuncBlkCtl {
827 selector: Self::VOLUME,
828 data: data.to_raw(),
829 },
830 Self::LrBalance(data) => AudioFuncBlkCtl {
831 selector: Self::LR_BALANCE,
832 data: data.to_raw(),
833 },
834 Self::FrBalance(data) => AudioFuncBlkCtl {
835 selector: Self::FR_BALANCE,
836 data: data.to_raw(),
837 },
838 Self::Bass(data) => AudioFuncBlkCtl {
839 selector: Self::BASS,
840 data: data.to_raw(),
841 },
842 Self::Mid(data) => AudioFuncBlkCtl {
843 selector: Self::MID,
844 data: data.to_raw(),
845 },
846 Self::Treble(data) => AudioFuncBlkCtl {
847 selector: Self::TREBLE,
848 data: data.to_raw(),
849 },
850 Self::GraphicEqualizer(data) => AudioFuncBlkCtl {
851 selector: Self::GRAPHIC_EQUALIZER,
852 data: data.to_raw(),
853 },
854 Self::AutomaticGain(data) => AudioFuncBlkCtl {
855 selector: Self::AUTOMATIC_GAIN,
856 data: bool_vector_to_raw(data),
857 },
858 Self::Delay(data) => AudioFuncBlkCtl {
859 selector: Self::DELAY,
860 data: data.to_raw(),
861 },
862 Self::BassBoost(data) => AudioFuncBlkCtl {
863 selector: Self::BASS_BOOST,
864 data: bool_vector_to_raw(data),
865 },
866 Self::Loudness(data) => AudioFuncBlkCtl {
867 selector: Self::LOUDNESS,
868 data: bool_vector_to_raw(data),
869 },
870 Self::Reserved(data) => AudioFuncBlkCtl {
871 selector: data[0],
872 data: data[2..].to_vec(),
873 },
874 }
875 }
876}
877
878fn i16_vector_from_raw(raw: &[u8]) -> Vec<i16> {
879 (0..(raw.len() / 2))
880 .map(|i| {
881 let mut doublet = [0; 2];
882 doublet.copy_from_slice(&raw[(i * 2)..(i * 2 + 2)]);
883 i16::from_be_bytes(doublet)
884 })
885 .collect()
886}
887
888fn u16_vector_from_raw(raw: &[u8]) -> Vec<u16> {
889 (0..(raw.len() / 2))
890 .map(|i| {
891 let mut doublet = [0; 2];
892 doublet.copy_from_slice(&raw[(i * 2)..(i * 2 + 2)]);
893 u16::from_be_bytes(doublet)
894 })
895 .collect()
896}
897
898fn bool_vector_from_raw(raw: &[u8]) -> Vec<bool> {
899 raw.iter().map(|&b| b == FeatureCtl::TRUE).collect()
900}
901
902fn i8_vector_from_raw(raw: &[u8]) -> Vec<i8> {
903 raw.iter().map(|&b| b as i8).collect()
904}
905
906fn i16_from_raw(data: &[u8]) -> i16 {
907 let mut doublet = [0; 2];
908 doublet.copy_from_slice(&data);
909 i16::from_be_bytes(doublet)
910}
911
912impl FeatureCtl {
913 fn from_ctl(ctl: &AudioFuncBlkCtl) -> Self {
914 match ctl.selector {
915 Self::MUTE => Self::Mute(bool_vector_from_raw(&ctl.data)),
916 Self::VOLUME => Self::Volume(VolumeData::from_raw(&ctl.data)),
917 Self::LR_BALANCE => Self::LrBalance(LrBalanceData::from_raw(&ctl.data)),
918 Self::FR_BALANCE => Self::FrBalance(FrBalanceData::from_raw(&ctl.data)),
919 Self::BASS => Self::Bass(BassData::from_raw(&ctl.data)),
920 Self::MID => Self::Mid(MidData::from_raw(&ctl.data)),
921 Self::TREBLE => Self::Treble(TrebleData::from_raw(&ctl.data)),
922 Self::GRAPHIC_EQUALIZER => {
923 Self::GraphicEqualizer(GraphicEqualizerData::from_raw(&ctl.data))
924 }
925 Self::AUTOMATIC_GAIN => Self::AutomaticGain(bool_vector_from_raw(&ctl.data)),
926 Self::DELAY => Self::Delay(DelayData::from_raw(&ctl.data)),
927 Self::BASS_BOOST => Self::BassBoost(bool_vector_from_raw(&ctl.data)),
928 Self::LOUDNESS => Self::Loudness(bool_vector_from_raw(&ctl.data)),
929 _ => {
930 let mut data = Vec::new();
931 data.push(ctl.selector);
932 data.push(1 + ctl.data.len() as u8);
933 data.extend_from_slice(&ctl.data);
934 Self::Reserved(data)
935 }
936 }
937 }
938}
939
940#[derive(Clone, Copy, Debug, Eq, PartialEq)]
943pub enum AudioCh {
944 Master,
946 Each(u8),
948 Void,
950 All,
952}
953
954impl Default for AudioCh {
955 fn default() -> Self {
956 Self::All
957 }
958}
959
960impl AudioCh {
961 const MASTER: u8 = 0x00;
962 const VOID: u8 = 0xfe;
963 const ALL: u8 = 0xff;
964}
965
966impl AudioCh {
967 fn from_val(val: u8) -> Self {
968 match val {
969 Self::MASTER => Self::Master,
970 Self::ALL => Self::All,
971 Self::VOID => Self::Void,
972 _ => Self::Each(val - 1),
975 }
976 }
977
978 fn to_val(&self) -> u8 {
979 match self {
980 Self::Master => Self::MASTER,
981 Self::All => Self::ALL,
982 Self::Void => Self::VOID,
983 Self::Each(val) => val + 1,
984 }
985 }
986}
987
988#[derive(Clone, Debug, Eq, PartialEq)]
993pub struct AudioFeature {
994 pub audio_ch_num: AudioCh,
996 pub ctl: FeatureCtl,
998
999 func_blk: AudioFuncBlk,
1000}
1001
1002impl AudioFeature {
1003 pub fn new(func_blk_id: u8, ctl_attr: CtlAttr, audio_ch_num: AudioCh, ctl: FeatureCtl) -> Self {
1004 Self {
1005 audio_ch_num,
1006 ctl,
1007 func_blk: AudioFuncBlk {
1008 func_blk_type: AudioFuncBlkType::Feature,
1009 func_blk_id,
1010 ctl_attr,
1011 ..Default::default()
1012 },
1013 }
1014 }
1015
1016 fn build_func_blk(&mut self) -> Result<(), AvcCmdBuildError> {
1017 self.func_blk.audio_selector_data.clear();
1018 self.func_blk
1019 .audio_selector_data
1020 .push(self.audio_ch_num.to_val());
1021 self.func_blk.ctl = self.ctl.to_ctl();
1022 Ok(())
1023 }
1024
1025 fn parse_func_blk(&mut self) -> Result<(), AvcRespParseError> {
1026 let audio_ch_num = AudioCh::from_val(self.func_blk.audio_selector_data[0]);
1027 if audio_ch_num != self.audio_ch_num {
1028 Err(AvcRespParseError::UnexpectedOperands(7))
1029 } else {
1030 self.ctl = FeatureCtl::from_ctl(&self.func_blk.ctl);
1031 Ok(())
1032 }
1033 }
1034}
1035
1036impl AvcOp for AudioFeature {
1037 const OPCODE: u8 = AudioFuncBlk::OPCODE;
1038}
1039
1040impl AvcStatus for AudioFeature {
1041 fn build_operands(&mut self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
1042 self.build_func_blk()
1043 .and_then(|_| AvcStatus::build_operands(&mut self.func_blk, addr))
1044 }
1045
1046 fn parse_operands(&mut self, addr: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
1047 AvcStatus::parse_operands(&mut self.func_blk, addr, operands)
1048 .and_then(|_| self.parse_func_blk())
1049 }
1050}
1051
1052impl AvcControl for AudioFeature {
1053 fn build_operands(&mut self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
1054 self.build_func_blk()
1055 .and_then(|_| AvcControl::build_operands(&mut self.func_blk, addr))
1056 }
1057
1058 fn parse_operands(&mut self, addr: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
1059 AvcControl::parse_operands(&mut self.func_blk, addr, operands)
1060 .and_then(|_| self.parse_func_blk())
1061 }
1062}
1063
1064#[derive(Clone, Debug, Eq, PartialEq)]
1066pub enum ProcessingCtl {
1067 Enable(bool),
1068 Mode(Vec<u8>),
1069 Mixer(Vec<i16>),
1070 Reserved(Vec<u8>),
1071}
1072
1073impl ProcessingCtl {
1074 const ENABLE: u8 = 0x01;
1075 const MODE: u8 = 0x02;
1076 const MIXER: u8 = 0x03;
1077
1078 const TRUE: u8 = 0x70;
1079 const FALSE: u8 = 0x60;
1080
1081 pub const INFINITY: i16 = 0x7ffeu16 as i16;
1082 pub const NEG_INFINITY: i16 = 0x8000u16 as i16;
1083}
1084
1085impl ProcessingCtl {
1086 fn to_ctl(&self) -> AudioFuncBlkCtl {
1087 match self {
1088 Self::Enable(data) => AudioFuncBlkCtl {
1089 selector: Self::ENABLE,
1090 data: vec![if *data { Self::TRUE } else { Self::FALSE }],
1091 },
1092 Self::Mode(data) => AudioFuncBlkCtl {
1093 selector: Self::MODE,
1094 data: data.to_vec(),
1095 },
1096 Self::Mixer(data) => AudioFuncBlkCtl {
1097 selector: Self::MIXER,
1098 data: i16_vector_to_raw(data),
1099 },
1100 Self::Reserved(data) => AudioFuncBlkCtl {
1101 selector: data[0],
1102 data: data[2..].to_vec(),
1103 },
1104 }
1105 }
1106
1107 fn from_ctl(ctl_blk: &AudioFuncBlkCtl) -> Self {
1108 match ctl_blk.selector {
1109 Self::ENABLE => Self::Enable(ctl_blk.data[0] == Self::TRUE),
1110 Self::MODE => Self::Mode(ctl_blk.data.to_vec()),
1111 Self::MIXER => Self::Mixer(i16_vector_from_raw(&ctl_blk.data)),
1112 _ => {
1113 let mut data = Vec::new();
1114 data.push(ctl_blk.selector);
1115 data.push(1 + ctl_blk.data.len() as u8);
1116 data.extend_from_slice(&ctl_blk.data);
1117 Self::Reserved(data)
1118 }
1119 }
1120 }
1121}
1122
1123pub struct AudioProcessing {
1128 pub input_plug_id: u8,
1130 pub input_ch: AudioCh,
1132 pub output_ch: AudioCh,
1134 pub ctl: ProcessingCtl,
1136
1137 func_blk: AudioFuncBlk,
1138}
1139
1140impl AudioProcessing {
1141 pub fn new(
1142 func_blk_id: u8,
1143 ctl_attr: CtlAttr,
1144 input_plug_id: u8,
1145 input_ch: AudioCh,
1146 output_ch: AudioCh,
1147 ctl: ProcessingCtl,
1148 ) -> Self {
1149 Self {
1150 input_plug_id,
1151 input_ch,
1152 output_ch,
1153 ctl,
1154 func_blk: AudioFuncBlk {
1155 func_blk_type: AudioFuncBlkType::Processing,
1156 func_blk_id,
1157 ctl_attr,
1158 ..Default::default()
1159 },
1160 }
1161 }
1162
1163 fn build_func_blk(&mut self) -> Result<(), AvcCmdBuildError> {
1164 self.func_blk.audio_selector_data.clear();
1165 self.func_blk.audio_selector_data.push(self.input_plug_id);
1166 self.func_blk
1167 .audio_selector_data
1168 .push(self.input_ch.to_val());
1169 self.func_blk
1170 .audio_selector_data
1171 .push(self.output_ch.to_val());
1172 self.func_blk.ctl = self.ctl.to_ctl();
1173 Ok(())
1174 }
1175
1176 fn parse_func_blk(&mut self) -> Result<(), AvcRespParseError> {
1177 if self.func_blk.audio_selector_data[0] != self.input_plug_id {
1178 Err(AvcRespParseError::UnexpectedOperands(7))?;
1179 }
1180
1181 let input_ch = AudioCh::from_val(self.func_blk.audio_selector_data[1]);
1182 if input_ch != self.input_ch {
1183 Err(AvcRespParseError::UnexpectedOperands(8))?;
1184 }
1185
1186 let output_ch = AudioCh::from_val(self.func_blk.audio_selector_data[2]);
1187 if output_ch != self.output_ch {
1188 Err(AvcRespParseError::UnexpectedOperands(9))?;
1189 }
1190
1191 self.ctl = ProcessingCtl::from_ctl(&self.func_blk.ctl);
1192 Ok(())
1193 }
1194}
1195
1196impl AvcOp for AudioProcessing {
1197 const OPCODE: u8 = AudioFuncBlk::OPCODE;
1198}
1199
1200impl AvcStatus for AudioProcessing {
1201 fn build_operands(&mut self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
1202 self.build_func_blk()
1203 .and_then(|_| AvcStatus::build_operands(&mut self.func_blk, addr))
1204 }
1205
1206 fn parse_operands(&mut self, addr: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
1207 AvcStatus::parse_operands(&mut self.func_blk, addr, operands)
1208 .and_then(|_| self.parse_func_blk())
1209 }
1210}
1211
1212impl AvcControl for AudioProcessing {
1213 fn build_operands(&mut self, addr: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
1214 self.build_func_blk()
1215 .and_then(|_| AvcControl::build_operands(&mut self.func_blk, addr))
1216 }
1217
1218 fn parse_operands(&mut self, addr: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
1219 AvcControl::parse_operands(&mut self.func_blk, addr, operands)
1220 .and_then(|_| self.parse_func_blk())
1221 }
1222}
1223
1224#[cfg(test)]
1225mod test {
1226 use crate::*;
1227
1228 #[test]
1229 fn func_blk_operands() {
1230 let mut op = AudioFuncBlk {
1231 func_blk_type: AudioFuncBlkType::Selector,
1232 func_blk_id: 0xfe,
1233 ctl_attr: CtlAttr::Resolution,
1234 ..Default::default()
1235 };
1236 op.audio_selector_data
1237 .extend_from_slice(&[0xde, 0xad, 0xbe, 0xef]);
1238 op.ctl.selector = 0x11;
1239 op.ctl.data.extend_from_slice(&[0xbe, 0xef]);
1240
1241 let operands = AvcStatus::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1242 assert_eq!(
1243 &operands,
1244 &[0x80, 0xfe, 0x01, 0x05, 0xde, 0xad, 0xbe, 0xef, 0x11, 0x02, 0xbe, 0xef]
1245 );
1246
1247 AvcStatus::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1248 assert_eq!(op.func_blk_type, AudioFuncBlkType::Selector);
1249 assert_eq!(op.func_blk_id, 0xfe);
1250 assert_eq!(op.ctl_attr, CtlAttr::Resolution);
1251 assert_eq!(&op.audio_selector_data, &[0xde, 0xad, 0xbe, 0xef]);
1252 assert_eq!(op.ctl.selector, 0x11);
1253 assert_eq!(&op.ctl.data, &[0xbe, 0xef]);
1254
1255 let mut op = AudioFuncBlk {
1256 func_blk_type: AudioFuncBlkType::Selector,
1257 func_blk_id: 0xfd,
1258 ctl_attr: CtlAttr::Minimum,
1259 ..Default::default()
1260 };
1261 op.audio_selector_data
1262 .extend_from_slice(&[0xde, 0xad, 0xbe, 0xef]);
1263 op.ctl.selector = 0x12;
1264 op.ctl.data.extend_from_slice(&[0xbe, 0xef]);
1265
1266 let operands = AvcControl::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1267 assert_eq!(
1268 &operands,
1269 &[0x80, 0xfd, 0x02, 0x05, 0xde, 0xad, 0xbe, 0xef, 0x12, 0x02, 0xbe, 0xef]
1270 );
1271
1272 AvcControl::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1273 assert_eq!(op.func_blk_type, AudioFuncBlkType::Selector);
1274 assert_eq!(op.func_blk_id, 0xfd);
1275 assert_eq!(op.ctl_attr, CtlAttr::Minimum);
1276 assert_eq!(&op.audio_selector_data, &[0xde, 0xad, 0xbe, 0xef]);
1277 assert_eq!(op.ctl.selector, 0x12);
1278 assert_eq!(&op.ctl.data, &[0xbe, 0xef]);
1279
1280 let mut op = AudioFuncBlk {
1282 func_blk_type: AudioFuncBlkType::Feature,
1283 func_blk_id: 0xfc,
1284 ctl_attr: CtlAttr::Maximum,
1285 ..Default::default()
1286 };
1287 op.ctl.selector = 0x13;
1288 op.ctl.data.extend_from_slice(&[0xfe, 0xeb, 0xda, 0xed]);
1289
1290 let operands = AvcStatus::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1291 assert_eq!(
1292 &operands,
1293 &[0x81, 0xfc, 0x03, 0x01, 0x13, 0x04, 0xfe, 0xeb, 0xda, 0xed]
1294 );
1295
1296 AvcStatus::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1297 assert_eq!(op.func_blk_type, AudioFuncBlkType::Feature);
1298 assert_eq!(op.func_blk_id, 0xfc);
1299 assert_eq!(op.ctl_attr, CtlAttr::Maximum);
1300 assert_eq!(&op.audio_selector_data, &[]);
1301 assert_eq!(op.ctl.selector, 0x13);
1302 assert_eq!(&op.ctl.data, &[0xfe, 0xeb, 0xda, 0xed]);
1303
1304 let mut op = AudioFuncBlk {
1305 func_blk_type: AudioFuncBlkType::Feature,
1306 func_blk_id: 0xfb,
1307 ctl_attr: CtlAttr::Default,
1308 ctl: AudioFuncBlkCtl {
1309 selector: 0x14,
1310 data: vec![0xfe, 0xeb, 0xda, 0xed],
1311 },
1312 ..Default::default()
1313 };
1314
1315 let operands = AvcControl::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1316 assert_eq!(
1317 &operands,
1318 &[0x81, 0xfb, 0x04, 0x01, 0x14, 0x04, 0xfe, 0xeb, 0xda, 0xed]
1319 );
1320
1321 AvcControl::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1322 assert_eq!(op.func_blk_type, AudioFuncBlkType::Feature);
1323 assert_eq!(op.func_blk_id, 0xfb);
1324 assert_eq!(op.ctl_attr, CtlAttr::Default);
1325 assert_eq!(&op.audio_selector_data, &[]);
1326 assert_eq!(op.ctl.selector, 0x14);
1327 assert_eq!(&op.ctl.data, &[0xfe, 0xeb, 0xda, 0xed]);
1328
1329 let mut op = AudioFuncBlk {
1331 func_blk_type: AudioFuncBlkType::Processing,
1332 func_blk_id: 0xfa,
1333 ctl_attr: CtlAttr::Duration,
1334 audio_selector_data: vec![0xda, 0xed],
1335 ctl: AudioFuncBlkCtl {
1336 selector: 0x15,
1337 ..Default::default()
1338 },
1339 };
1340
1341 let operands = AvcStatus::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1342 assert_eq!(&operands, &[0x82, 0xfa, 0x08, 0x03, 0xda, 0xed, 0x15]);
1343
1344 AvcStatus::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1345 assert_eq!(op.func_blk_type, AudioFuncBlkType::Processing);
1346 assert_eq!(op.func_blk_id, 0xfa);
1347 assert_eq!(op.ctl_attr, CtlAttr::Duration);
1348 assert_eq!(&op.audio_selector_data, &[0xda, 0xed]);
1349 assert_eq!(op.ctl.selector, 0x15);
1350 assert_eq!(&op.ctl.data, &[]);
1351
1352 let mut op = AudioFuncBlk {
1353 func_blk_type: AudioFuncBlkType::Processing,
1354 func_blk_id: 0xf9,
1355 ctl_attr: CtlAttr::Current,
1356 audio_selector_data: vec![0xda, 0xed],
1357 ctl: AudioFuncBlkCtl {
1358 selector: 0x16,
1359 ..Default::default()
1360 },
1361 };
1362
1363 let operands = AvcControl::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1364 assert_eq!(&operands, &[0x82, 0xf9, 0x10, 0x03, 0xda, 0xed, 0x16]);
1365
1366 AvcControl::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1367 assert_eq!(op.func_blk_type, AudioFuncBlkType::Processing);
1368 assert_eq!(op.func_blk_id, 0xf9);
1369 assert_eq!(op.ctl_attr, CtlAttr::Current);
1370 assert_eq!(&op.audio_selector_data, &[0xda, 0xed]);
1371 assert_eq!(op.ctl.selector, 0x16);
1372 assert_eq!(&op.ctl.data, &[]);
1373 }
1374
1375 #[test]
1376 fn avcaudioselector_operands() {
1377 let mut op = AudioSelector::new(0xe5, CtlAttr::Duration, 0x28);
1378 let operands = AvcStatus::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1379 assert_eq!(&operands, &[0x80, 0xe5, 0x08, 0x02, 0x28, 0x01]);
1380
1381 AvcStatus::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1382 assert_eq!(op.input_plug_id, 0x28);
1383
1384 let mut op = AudioSelector::new(0x1e, CtlAttr::Move, 0x96);
1385 let operands = AvcControl::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1386 assert_eq!(&operands, &[0x80, 0x1e, 0x18, 0x02, 0x96, 0x01]);
1387
1388 AvcControl::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1389 assert_eq!(op.input_plug_id, 0x96);
1390 }
1391
1392 #[test]
1393 fn featurectl_from() {
1394 let ctl = FeatureCtl::Mute(vec![false, true, false]);
1395 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1396
1397 let data = VolumeData(vec![0x1234, 0x3456, 0x789a]);
1398 let ctl = FeatureCtl::Volume(data);
1399 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1400
1401 let ctl = FeatureCtl::LrBalance(LrBalanceData(-123));
1402 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1403
1404 let ctl = FeatureCtl::FrBalance(FrBalanceData(321));
1405 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1406
1407 let ctl = FeatureCtl::Bass(BassData(vec![10, -10, 20, -20]));
1408 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1409
1410 let ctl = FeatureCtl::Mid(MidData(vec![30, -30, -40, 40]));
1411 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1412
1413 let data = GraphicEqualizerData {
1414 ansi_band_gains: [
1415 Some(-1),
1416 Some(-2),
1417 Some(-3),
1418 Some(10),
1419 None,
1420 None,
1421 None,
1422 None,
1423 Some(14),
1424 Some(-40),
1425 Some(-100),
1426 Some(33),
1427 None,
1428 None,
1429 None,
1430 None,
1431 Some(-1),
1432 Some(-2),
1433 Some(-3),
1434 Some(10),
1435 None,
1436 None,
1437 None,
1438 None,
1439 Some(14),
1440 Some(-40),
1441 Some(-100),
1442 Some(33),
1443 None,
1444 None,
1445 ],
1446 extra_band_gains: [
1447 Some(87),
1448 Some(99),
1449 Some(-123),
1450 Some(100),
1451 None,
1452 None,
1453 None,
1454 None,
1455 Some(-76),
1456 Some(-97),
1457 Some(18),
1458 Some(21),
1459 None,
1460 None,
1461 None,
1462 None,
1463 Some(87),
1464 Some(99),
1465 Some(-123),
1466 Some(100),
1467 None,
1468 None,
1469 None,
1470 None,
1471 Some(-76),
1472 Some(-97),
1473 Some(18),
1474 Some(21),
1475 None,
1476 None,
1477 None,
1478 None,
1479 ],
1480 };
1481 let ctl = FeatureCtl::GraphicEqualizer(data);
1482 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1483
1484 let ctl = FeatureCtl::Treble(TrebleData(vec![50, 60, -70, -80]));
1485 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1486
1487 let ctl = FeatureCtl::AutomaticGain(vec![false, true, false]);
1488 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1489
1490 let ctl = FeatureCtl::Delay(DelayData(vec![0x1234, 0x3456, 0x789a]));
1491 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1492
1493 let ctl = FeatureCtl::BassBoost(vec![true, false, true]);
1494 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1495
1496 let ctl = FeatureCtl::Loudness(vec![false, true, false]);
1497 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1498
1499 let ctl = FeatureCtl::Reserved(vec![0xff, 0x04, 0xad, 0xbe, 0xef]);
1500 assert_eq!(ctl, FeatureCtl::from_ctl(&ctl.to_ctl()));
1501 }
1502
1503 #[test]
1504 fn avcaudiofeature_operands() {
1505 let data = VolumeData(vec![-1234, 5678, 3210]);
1506 let ctl = FeatureCtl::Volume(data);
1507 let mut op = AudioFeature::new(0x03, CtlAttr::Minimum, AudioCh::Each(0x1b), ctl.clone());
1508 let operands = AvcStatus::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1509 assert_eq!(
1510 &operands,
1511 &[0x81, 0x03, 0x02, 0x02, 0x1c, 0x02, 0x06, 0xfb, 0x2e, 0x16, 0x2e, 0x0c, 0x8a]
1512 );
1513
1514 AvcStatus::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1515 assert_eq!(AudioCh::Each(0x1b), op.audio_ch_num);
1516 assert_eq!(ctl, op.ctl);
1517
1518 let ctl = FeatureCtl::Treble(TrebleData(vec![40, -33, 123, -96]));
1519 let mut op = AudioFeature::new(0x33, CtlAttr::Resolution, AudioCh::Each(0xd8), ctl.clone());
1520 let operands = AvcControl::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1521 assert_eq!(
1522 &operands,
1523 &[0x81, 0x33, 0x01, 0x2, 0xd9, 0x07, 0x04, 0x28, 0xdf, 0x7b, 0xa0]
1524 );
1525
1526 AvcControl::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1527 assert_eq!(AudioCh::Each(0xd8), op.audio_ch_num);
1528 assert_eq!(ctl, op.ctl);
1529 }
1530
1531 #[test]
1532 fn processingctl_from() {
1533 let ctl = ProcessingCtl::Enable(true);
1534 assert_eq!(ctl, ProcessingCtl::from_ctl(&ctl.to_ctl()));
1535
1536 let ctl = ProcessingCtl::Mode(vec![0xde, 0xad, 0xbe, 0xef]);
1537 assert_eq!(ctl, ProcessingCtl::from_ctl(&ctl.to_ctl()));
1538
1539 let ctl = ProcessingCtl::Mixer(vec![-73, -157]);
1540 assert_eq!(ctl, ProcessingCtl::from_ctl(&ctl.to_ctl()));
1541 }
1542
1543 #[test]
1544 fn avcaudioprocessing_operands() {
1545 let ctl = ProcessingCtl::Enable(true);
1546 let mut op = AudioProcessing::new(
1547 0xf5,
1548 CtlAttr::Default,
1549 0x71,
1550 AudioCh::Each(0xa8),
1551 AudioCh::Each(0x3e),
1552 ctl.clone(),
1553 );
1554 let operands = AvcStatus::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1555 assert_eq!(
1556 &operands,
1557 &[0x82, 0xf5, 0x04, 0x04, 0x71, 0xa9, 0x3f, 0x01, 0x01, 0x70]
1558 );
1559
1560 AvcStatus::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1561 assert_eq!(0x71, op.input_plug_id);
1562 assert_eq!(AudioCh::Each(0xa8), op.input_ch);
1563 assert_eq!(AudioCh::Each(0x3e), op.output_ch);
1564 assert_eq!(ctl, op.ctl);
1565
1566 let ctl = ProcessingCtl::Mixer(vec![10, -10]);
1567 let mut op = AudioProcessing::new(
1568 0x11,
1569 CtlAttr::Minimum,
1570 0x22,
1571 AudioCh::Each(0x32),
1572 AudioCh::Each(0x43),
1573 ctl.clone(),
1574 );
1575 let operands = AvcControl::build_operands(&mut op, &AUDIO_SUBUNIT_0_ADDR).unwrap();
1576 assert_eq!(
1577 &operands,
1578 &[0x82, 0x11, 0x02, 0x04, 0x22, 0x33, 0x44, 0x03, 0x04, 0x00, 0x0a, 0xff, 0xf6]
1579 );
1580
1581 AvcControl::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
1582 assert_eq!(0x22, op.input_plug_id);
1583 assert_eq!(AudioCh::Each(0x32), op.input_ch);
1584 assert_eq!(AudioCh::Each(0x43), op.output_ch);
1585 assert_eq!(ctl, op.ctl);
1586 }
1587}