firewire_dice_protocols/tcat/extension/
mixer_section.rs1use super::{caps_section::*, *};
9
10#[derive(Default, Debug, Clone, PartialEq, Eq)]
12pub struct MixerSaturationParams(pub Vec<bool>);
13
14#[derive(Default, Debug, Clone, PartialEq, Eq)]
16pub struct MixerCoefficientParams(pub Vec<Vec<u16>>);
17
18const SATURATION_OFFSET: usize = 0x00;
19const COEFF_OFFSET: usize = 0x04;
20
21const MAX_OUTPUT_COUNT: usize = 16;
22const MAX_INPUT_COUNT: usize = 18;
23
24fn calculate_mixer_coefficients_size() -> usize {
25 4 * MAX_OUTPUT_COUNT * MAX_INPUT_COUNT
26}
27
28fn serialize_mixer_coefficients<T: AsRef<[u16]>>(
29 coefs: &[T],
30 caps: &MixerCaps,
31 raw: &mut [u8],
32) -> Result<(), String> {
33 assert!(raw.len() >= calculate_mixer_coefficients_size());
34
35 coefs
36 .iter()
37 .take(caps.output_count as usize)
38 .enumerate()
39 .for_each(|(i, entries)| {
40 entries
41 .as_ref()
42 .iter()
43 .take(caps.input_count as usize)
44 .enumerate()
45 .for_each(|(j, &coef)| {
46 let pos = 4 * (i * MAX_INPUT_COUNT + j);
47 serialize_u32(&(coef as u32), &mut raw[pos..(pos + 4)]);
48 });
49 });
50
51 Ok(())
52}
53
54fn deserialize_mixer_coefficients<T: AsMut<[u16]>>(
55 coefs: &mut [T],
56 caps: &MixerCaps,
57 raw: &[u8],
58) -> Result<(), String> {
59 assert!(raw.len() >= calculate_mixer_coefficients_size());
60
61 coefs
62 .iter_mut()
63 .take(caps.output_count as usize)
64 .enumerate()
65 .for_each(|(i, entries)| {
66 entries
67 .as_mut()
68 .iter_mut()
69 .take(caps.input_count as usize)
70 .enumerate()
71 .for_each(|(j, coef)| {
72 let pos = 4 * (i * MAX_INPUT_COUNT + j);
73 let mut val = 0u32;
74 deserialize_u32(&mut val, &raw[pos..(pos + 4)]);
75 *coef = val as u16
76 });
77 });
78
79 Ok(())
80}
81
82impl<O: TcatExtensionOperation> TcatExtensionSectionParamsOperation<MixerSaturationParams> for O {
83 fn cache_extension_whole_params(
84 req: &FwReq,
85 node: &FwNode,
86 sections: &ExtensionSections,
87 caps: &ExtensionCaps,
88 params: &mut MixerSaturationParams,
89 timeout_ms: u32,
90 ) -> Result<(), Error> {
91 if !caps.mixer.is_exposed {
92 Err(Error::new(
93 ProtocolExtensionError::Mixer,
94 "Mixer is not available",
95 ))?
96 }
97
98 let mut raw = [0; 4];
99 Self::read_extension(
100 req,
101 node,
102 §ions.mixer,
103 SATURATION_OFFSET,
104 &mut raw,
105 timeout_ms,
106 )?;
107
108 let mut val = 0u32;
109 deserialize_u32(&mut val, &raw);
110
111 params
112 .0
113 .resize_with(caps.mixer.output_count as usize, Default::default);
114 params
115 .0
116 .iter_mut()
117 .enumerate()
118 .for_each(|(i, saturation)| *saturation = val & (1 << i) > 0);
119
120 Ok(())
121 }
122}
123
124impl<O: TcatExtensionOperation> TcatExtensionSectionParamsOperation<MixerCoefficientParams> for O {
125 fn cache_extension_whole_params(
126 req: &FwReq,
127 node: &FwNode,
128 sections: &ExtensionSections,
129 caps: &ExtensionCaps,
130 params: &mut MixerCoefficientParams,
131 timeout_ms: u32,
132 ) -> Result<(), Error> {
133 if !caps.mixer.is_exposed {
134 Err(Error::new(
135 ProtocolExtensionError::Mixer,
136 "Mixer is not available",
137 ))?
138 }
139
140 let mut raw = vec![0u8; calculate_mixer_coefficients_size()];
141 Self::read_extension(
142 req,
143 node,
144 §ions.mixer,
145 COEFF_OFFSET,
146 &mut raw,
147 timeout_ms,
148 )?;
149
150 params
151 .0
152 .resize_with(caps.mixer.output_count as usize, Default::default);
153 params
154 .0
155 .iter_mut()
156 .for_each(|coefs| coefs.resize_with(caps.mixer.input_count as usize, Default::default));
157 deserialize_mixer_coefficients(&mut params.0, &caps.mixer, &raw)
158 .map_err(|cause| Error::new(ProtocolExtensionError::Mixer, &cause))
159 }
160}
161
162impl<O: TcatExtensionOperation>
163 TcatExtensionSectionPartialMutableParamsOperation<MixerCoefficientParams> for O
164{
165 fn update_extension_partial_params(
166 req: &FwReq,
167 node: &FwNode,
168 sections: &ExtensionSections,
169 caps: &ExtensionCaps,
170 params: &MixerCoefficientParams,
171 prev: &mut MixerCoefficientParams,
172 timeout_ms: u32,
173 ) -> Result<(), Error> {
174 let mut new = vec![0u8; calculate_mixer_coefficients_size()];
175 serialize_mixer_coefficients(¶ms.0, &caps.mixer, &mut new)
176 .map_err(|cause| Error::new(ProtocolExtensionError::Mixer, &cause))?;
177
178 let mut old = vec![0u8; calculate_mixer_coefficients_size()];
179 serialize_mixer_coefficients(&prev.0, &caps.mixer, &mut old)
180 .map_err(|cause| Error::new(ProtocolExtensionError::Mixer, &cause))?;
181
182 (0..calculate_mixer_coefficients_size())
183 .step_by(4)
184 .try_for_each(|pos| {
185 if new[pos..(pos + 4)] != old[pos..(pos + 4)] {
186 Self::write_extension(
187 req,
188 node,
189 §ions.mixer,
190 COEFF_OFFSET + pos,
191 &mut new[pos..(pos + 4)],
192 timeout_ms,
193 )
194 } else {
195 Ok(())
196 }
197 })?;
198
199 deserialize_mixer_coefficients(&mut prev.0, &caps.mixer, &new)
200 .map_err(|cause| Error::new(ProtocolExtensionError::Mixer, &cause))
201 }
202}