firewire_dice_protocols/tcat/
tcd22xx_spec.rs1use super::{
7 extension::{caps_section::*, cmd_section::*, current_config_section::*, router_section::*, *},
8 *,
9};
10
11#[derive(Default, Debug, Clone, PartialEq, Eq)]
13pub struct Tcd22xxAvailableBlocks(pub Vec<SrcBlk>, pub Vec<DstBlk>);
14
15#[derive(Debug, Copy, Clone, PartialEq, Eq)]
17pub struct Input {
18 pub id: SrcBlkId,
20 pub offset: u8,
22 pub count: u8,
24 pub label: Option<&'static str>,
26}
27
28#[derive(Debug, Copy, Clone, PartialEq, Eq)]
30pub struct Output {
31 pub id: DstBlkId,
33 pub offset: u8,
35 pub count: u8,
37 pub label: Option<&'static str>,
39}
40
41pub trait Tcd22xxSpecification {
43 const INPUTS: &'static [Input];
45
46 const OUTPUTS: &'static [Output];
48
49 const FIXED: &'static [SrcBlk];
51
52 const MIXER_OUT_PORTS: [u8; 3] = [16, 16, 8];
54
55 const MIXER_IN_PORTS: [(DstBlkId, u8); 2] = [(DstBlkId::MixerTx0, 16), (DstBlkId::MixerTx1, 2)];
57
58 const ADAT_CHANNELS: [u8; 3] = [8, 4, 2];
60
61 fn adat_channel_count(rate_mode: RateMode) -> u8 {
63 let index = match rate_mode {
64 RateMode::Low => 0,
65 RateMode::Middle => 1,
66 RateMode::High => 2,
67 };
68 Self::ADAT_CHANNELS[index]
69 }
70
71 fn mixer_out_port_count(rate_mode: RateMode) -> u8 {
73 let index = match rate_mode {
74 RateMode::Low => 0,
75 RateMode::Middle => 1,
76 RateMode::High => 2,
77 };
78 Self::MIXER_OUT_PORTS[index]
79 }
80
81 fn mixer_in_port_count() -> u8 {
83 Self::MIXER_IN_PORTS
84 .iter()
85 .fold(0, |accum, (_, count)| accum + count)
86 }
87
88 fn compute_avail_real_blk_pair(rate_mode: RateMode) -> (Vec<SrcBlk>, Vec<DstBlk>) {
90 let mut srcs = Vec::<SrcBlk>::new();
91 Self::INPUTS.iter().for_each(|entry| {
92 let offset = match entry.id {
93 SrcBlkId::Adat => srcs.iter().filter(|&s| s.id.eq(&entry.id)).count() as u8,
94 _ => entry.offset,
95 };
96 let count = match entry.id {
97 SrcBlkId::Adat => Self::adat_channel_count(rate_mode),
98 _ => entry.count,
99 };
100 (offset..(offset + count)).for_each(|ch| {
101 srcs.push(SrcBlk { id: entry.id, ch });
102 });
103 });
104
105 let mut dsts = Vec::<DstBlk>::new();
106 Self::OUTPUTS.iter().for_each(|entry| {
107 let offset = match entry.id {
108 DstBlkId::Adat => dsts.iter().filter(|d| d.id.eq(&entry.id)).count() as u8,
109 _ => entry.offset,
110 };
111 let count = match entry.id {
112 DstBlkId::Adat => Self::adat_channel_count(rate_mode),
113 _ => entry.count,
114 };
115 (offset..(offset + count)).for_each(|ch| {
116 dsts.push(DstBlk { id: entry.id, ch });
117 });
118 });
119
120 (srcs, dsts)
121 }
122
123 fn compute_avail_stream_blk_pair(
125 tx_entries: &[FormatEntry],
126 rx_entries: &[FormatEntry],
127 ) -> (Vec<SrcBlk>, Vec<DstBlk>) {
128 let dst_blk_list = tx_entries
129 .iter()
130 .zip([DstBlkId::Avs0, DstBlkId::Avs1])
131 .map(|(entry, id)| (0..entry.pcm_count).map(move |ch| DstBlk { id, ch }))
132 .flatten()
133 .collect();
134
135 let src_blk_list = rx_entries
136 .iter()
137 .zip([SrcBlkId::Avs0, SrcBlkId::Avs1])
138 .map(|(entry, id)| (0..entry.pcm_count).map(move |ch| SrcBlk { id, ch }))
139 .flatten()
140 .collect();
141
142 (src_blk_list, dst_blk_list)
143 }
144
145 fn compute_avail_mixer_blk_pair(
147 caps: &ExtensionCaps,
148 rate_mode: RateMode,
149 ) -> (Vec<SrcBlk>, Vec<DstBlk>) {
150 let port_count = std::cmp::min(
151 caps.mixer.output_count,
152 Self::mixer_out_port_count(rate_mode),
153 );
154
155 let id = SrcBlkId::Mixer;
156 let src_blk_list = (0..port_count).map(move |ch| SrcBlk { id, ch }).collect();
157
158 let dst_blk_list = Self::MIXER_IN_PORTS
159 .iter()
160 .flat_map(|&(id, count)| (0..count).map(move |ch| DstBlk { id, ch }))
161 .take(caps.mixer.input_count as usize)
162 .collect();
163
164 (src_blk_list, dst_blk_list)
165 }
166
167 fn refine_router_entries(
169 entries: &mut Vec<RouterEntry>,
170 avail_blocks: &Tcd22xxAvailableBlocks,
171 ) {
172 entries.retain(|entry| {
173 avail_blocks
174 .0
175 .iter()
176 .find(|src| entry.src.eq(src))
177 .is_some()
178 });
179 entries.retain(|entry| {
180 avail_blocks
181 .1
182 .iter()
183 .find(|dst| entry.dst.eq(dst))
184 .is_some()
185 });
186 Self::FIXED.iter().enumerate().for_each(|(i, &src)| {
187 match entries.iter().position(|entry| entry.src.eq(&src)) {
188 Some(pos) => entries.swap(i, pos),
189 None => {
190 let dst = DstBlk {
191 id: DstBlkId::Reserved(0xff),
192 ch: 0xff,
193 };
194 entries.insert(
195 i,
196 RouterEntry {
197 dst,
198 src,
199 ..Default::default()
200 },
201 )
202 }
203 }
204 });
205 }
206}
207
208pub trait Tcd22xxOperation:
210 Tcd22xxSpecification
211 + TcatExtensionCommandSectionOperation
212 + TcatExtensionSectionParamsOperation<CurrentStreamFormatParams>
213 + TcatExtensionSectionWholeMutableParamsOperation<RouterParams>
214{
215 fn detect_available_blocks(
217 req: &FwReq,
218 node: &FwNode,
219 sections: &ExtensionSections,
220 caps: &ExtensionCaps,
221 rate_mode: RateMode,
222 avail_blocks: &mut Tcd22xxAvailableBlocks,
223 timeout_ms: u32,
224 ) -> Result<(), Error> {
225 let real_blk_pair = Self::compute_avail_real_blk_pair(rate_mode);
226
227 let pair = StreamFormatParams {
228 tx_entries: Vec::with_capacity(caps.general.max_tx_streams as usize),
229 rx_entries: Vec::with_capacity(caps.general.max_rx_streams as usize),
230 };
231 let mut params = CurrentStreamFormatParams { pair, rate_mode };
232 Self::cache_extension_whole_params(req, node, sections, caps, &mut params, timeout_ms)?;
233 let stream_blk_pair =
234 Self::compute_avail_stream_blk_pair(¶ms.pair.tx_entries, ¶ms.pair.rx_entries);
235
236 let mixer_blk_pair = Self::compute_avail_mixer_blk_pair(caps, rate_mode);
237
238 avail_blocks.0 = real_blk_pair
239 .0
240 .iter()
241 .chain(&stream_blk_pair.0)
242 .chain(&mixer_blk_pair.0)
243 .copied()
244 .collect();
245
246 avail_blocks.1 = real_blk_pair
247 .1
248 .iter()
249 .chain(&stream_blk_pair.1)
250 .chain(&mixer_blk_pair.1)
251 .copied()
252 .collect();
253
254 Ok(())
255 }
256
257 fn update_router_entries(
259 req: &FwReq,
260 node: &FwNode,
261 sections: &ExtensionSections,
262 caps: &ExtensionCaps,
263 rate_mode: RateMode,
264 avail_blocks: &Tcd22xxAvailableBlocks,
265 params: &mut RouterParams,
266 timeout_ms: u32,
267 ) -> Result<(), Error> {
268 Self::refine_router_entries(&mut params.0, avail_blocks);
269 if params.0.len() > caps.router.maximum_entry_count as usize {
270 let msg = format!(
271 "The number of entries for router section should be less than {} but {}",
272 caps.router.maximum_entry_count,
273 params.0.len()
274 );
275 Err(Error::new(ProtocolExtensionError::Router, &msg))?
276 }
277
278 Self::update_extension_whole_params(req, node, sections, caps, params, timeout_ms)?;
279 Self::initiate(
280 req,
281 node,
282 sections,
283 caps,
284 Opcode::LoadRouter(rate_mode),
285 timeout_ms,
286 )?;
287
288 Ok(())
289 }
290
291 fn load_configuration(
293 req: &FwReq,
294 node: &FwNode,
295 sections: &ExtensionSections,
296 caps: &ExtensionCaps,
297 timeout_ms: u32,
298 ) -> Result<(), Error> {
299 Self::initiate(
300 req,
301 node,
302 sections,
303 caps,
304 Opcode::LoadConfigFromFlash,
305 timeout_ms,
306 )
307 .map(|_| ())
308 }
309
310 fn store_configuration(
312 req: &FwReq,
313 node: &FwNode,
314 sections: &ExtensionSections,
315 caps: &ExtensionCaps,
316 timeout_ms: u32,
317 ) -> Result<(), Error> {
318 Self::initiate(
319 req,
320 node,
321 sections,
322 caps,
323 Opcode::StoreConfigToFlash,
324 timeout_ms,
325 )
326 .map(|_| ())
327 }
328}
329
330impl<O> Tcd22xxOperation for O where
331 O: Tcd22xxSpecification
332 + TcatExtensionCommandSectionOperation
333 + TcatExtensionSectionParamsOperation<CurrentStreamFormatParams>
334 + TcatExtensionSectionWholeMutableParamsOperation<RouterParams>
335{
336}