firewire_dice_protocols/tcat/extension/
standalone_section.rs1use super::{global_section::*, *};
10
11#[derive(Debug, Copy, Clone, PartialEq, Eq)]
19pub enum AdatParam {
20 Normal,
21 SMUX2,
22 SMUX4,
23 Auto,
24}
25
26impl Default for AdatParam {
27 fn default() -> Self {
28 AdatParam::Auto
29 }
30}
31
32#[derive(Debug, Copy, Clone, PartialEq, Eq)]
34pub enum WordClockMode {
35 Normal,
36 Low,
37 Middle,
38 High,
39}
40
41impl Default for WordClockMode {
42 fn default() -> Self {
43 WordClockMode::Normal
44 }
45}
46
47#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
49pub struct WordClockRate {
50 pub numerator: u16,
51 pub denominator: u16,
52}
53
54#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
56pub struct WordClockParam {
57 pub mode: WordClockMode,
58 pub rate: WordClockRate,
59}
60
61#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
63pub struct StandaloneParameters {
64 pub clock_source: ClockSource,
66 pub aes_high_rate: bool,
68 pub adat_mode: AdatParam,
70 pub word_clock_param: WordClockParam,
72 pub internal_rate: ClockRate,
74}
75
76#[derive(Default)]
78pub struct StandaloneSectionProtocol;
79
80const MIN_SIZE: usize = 20;
81
82fn serialize(params: &StandaloneParameters, raw: &mut [u8]) -> Result<(), String> {
83 assert!(raw.len() >= MIN_SIZE);
84
85 let mut val = 0u8;
86 serialize_clock_source(¶ms.clock_source, &mut val)?;
87 serialize_u8(&val, &mut raw[..4]);
88
89 serialize_bool(¶ms.aes_high_rate, &mut raw[4..8]);
90
91 let val = match params.adat_mode {
92 AdatParam::Normal => 0x00u32,
93 AdatParam::SMUX2 => 0x01,
94 AdatParam::SMUX4 => 0x02,
95 AdatParam::Auto => 0x03,
96 };
97 serialize_u32(&val, &mut raw[8..12]);
98
99 let mut val = match params.word_clock_param.mode {
100 WordClockMode::Normal => 0x00u32,
101 WordClockMode::Low => 0x01,
102 WordClockMode::Middle => 0x02,
103 WordClockMode::High => 0x03,
104 };
105 if params.word_clock_param.rate.numerator < 1 || params.word_clock_param.rate.denominator < 1 {
106 let msg = format!(
107 "Invalid parameters for rate of word clock: {} / {}",
108 params.word_clock_param.rate.numerator, params.word_clock_param.rate.denominator
109 );
110 Err(msg)?;
111 }
112 val |= ((params.word_clock_param.rate.numerator as u32) - 1) << 4;
113 val |= ((params.word_clock_param.rate.denominator as u32) - 1) << 16;
114 serialize_u32(&val, &mut raw[12..16]);
115
116 let mut val = 0u8;
117 serialize_clock_rate(¶ms.internal_rate, &mut val)?;
118 serialize_u8(&val, &mut raw[16..20]);
119
120 Ok(())
121}
122
123fn deserialize(params: &mut StandaloneParameters, raw: &[u8]) -> Result<(), String> {
124 assert!(raw.len() >= MIN_SIZE);
125
126 let mut val = 0u8;
127 deserialize_u8(&mut val, &raw[..4]);
128 deserialize_clock_source(&mut params.clock_source, &val)?;
129
130 deserialize_bool(&mut params.aes_high_rate, &raw[4..8]);
131
132 let mut val = 0u32;
133 deserialize_u32(&mut val, &raw[8..12]);
134 params.adat_mode = match val {
135 0x01 => AdatParam::SMUX2,
136 0x02 => AdatParam::SMUX4,
137 0x03 => AdatParam::Auto,
138 _ => AdatParam::Normal,
139 };
140
141 deserialize_u32(&mut val, &raw[12..16]);
142 params.word_clock_param.mode = match val & 0x03 {
143 0x01 => WordClockMode::Low,
144 0x02 => WordClockMode::Middle,
145 0x03 => WordClockMode::High,
146 _ => WordClockMode::Normal,
147 };
148 params.word_clock_param.rate.numerator = 1 + ((val >> 4) & 0x0fff) as u16;
149 params.word_clock_param.rate.denominator = 1 + ((val >> 16) & 0xffff) as u16;
150
151 let mut val = 0u8;
152 deserialize_u8(&mut val, &raw[16..20]);
153 deserialize_clock_rate(&mut params.internal_rate, &val)?;
154
155 Ok(())
156}
157
158impl<O: TcatExtensionOperation> TcatExtensionSectionParamsOperation<StandaloneParameters> for O {
159 fn cache_extension_whole_params(
160 req: &FwReq,
161 node: &FwNode,
162 sections: &ExtensionSections,
163 _: &ExtensionCaps,
164 params: &mut StandaloneParameters,
165 timeout_ms: u32,
166 ) -> Result<(), Error> {
167 let mut raw = vec![0; sections.standalone.size];
168 Self::read_extension(req, node, §ions.standalone, 0, &mut raw, timeout_ms)?;
169
170 deserialize(params, &raw)
171 .map_err(|msg| Error::new(ProtocolExtensionError::Standalone, &msg))
172 }
173}
174
175impl<O: TcatExtensionOperation>
176 TcatExtensionSectionPartialMutableParamsOperation<StandaloneParameters> for O
177{
178 fn update_extension_partial_params(
179 req: &FwReq,
180 node: &FwNode,
181 sections: &ExtensionSections,
182 _: &ExtensionCaps,
183 params: &StandaloneParameters,
184 prev: &mut StandaloneParameters,
185 timeout_ms: u32,
186 ) -> Result<(), Error> {
187 let mut new = vec![0; sections.standalone.size];
188 serialize(params, &mut new)
189 .map_err(|e| Error::new(ProtocolExtensionError::Standalone, &e.to_string()))?;
190
191 let mut old = vec![0; sections.standalone.size];
192 serialize(params, &mut old)
193 .map_err(|e| Error::new(ProtocolExtensionError::Standalone, &e.to_string()))?;
194
195 (0..sections.standalone.size)
196 .step_by(4)
197 .try_for_each(|pos| {
198 if new[pos] != old[pos] {
199 Self::write_extension(
200 req,
201 node,
202 §ions.standalone,
203 pos,
204 &mut new[pos..(pos + 4)],
205 timeout_ms,
206 )
207 } else {
208 Ok(())
209 }
210 })?;
211
212 deserialize(prev, &new)
213 .map_err(|e| Error::new(ProtocolExtensionError::Standalone, &e.to_string()))
214 }
215}
216
217#[cfg(test)]
218mod test {
219 use super::*;
220
221 #[test]
222 fn standalone_params_serdes() {
223 let params = StandaloneParameters {
224 clock_source: ClockSource::Tdif,
225 aes_high_rate: true,
226 adat_mode: AdatParam::SMUX4,
227 word_clock_param: WordClockParam {
228 mode: WordClockMode::Middle,
229 rate: WordClockRate {
230 numerator: 12,
231 denominator: 7,
232 },
233 },
234 internal_rate: ClockRate::R88200,
235 };
236
237 let mut raw = [0u8; MIN_SIZE];
238 assert!(serialize(¶ms, &mut raw).is_ok());
239
240 let mut p = StandaloneParameters::default();
241 assert!(deserialize(&mut p, &raw).is_ok());
242
243 assert_eq!(params, p);
244 }
245}