1pub mod ext_sync_section;
14pub mod global_section;
15pub mod rx_stream_format_section;
16pub mod tx_stream_format_section;
17
18pub mod extension;
19pub mod tcd22xx_spec;
20
21pub mod config_rom;
22
23use {
24 super::*,
25 glib::{error::ErrorDomain, Quark},
26 hinawa::{prelude::FwReqExtManual, FwTcode},
27 std::fmt::Debug,
28};
29
30pub use {
31 ext_sync_section::ExtendedSyncParameters,
32 global_section::{GlobalParameters, TcatGlobalSectionSpecification},
33 rx_stream_format_section::RxStreamFormatParameters,
34 tx_stream_format_section::TxStreamFormatParameters,
35};
36
37#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
39pub struct Section {
40 pub offset: usize,
42 pub size: usize,
44}
45
46impl Section {
47 pub(crate) const SIZE: usize = 8;
48}
49
50#[cfg(test)]
51pub(crate) fn serialize_section(section: &Section, raw: &mut [u8]) -> Result<(), String> {
52 assert!(raw.len() >= Section::SIZE);
53
54 let val = (section.offset as u32) / 4;
55 serialize_u32(&val, &mut raw[..4]);
56
57 let val = (section.size as u32) / 4;
58 serialize_u32(&val, &mut raw[4..8]);
59
60 Ok(())
61}
62
63pub(crate) fn deserialize_section(section: &mut Section, raw: &[u8]) -> Result<(), String> {
64 assert!(raw.len() >= Section::SIZE);
65
66 let mut val = 0u32;
67 deserialize_u32(&mut val, &raw[..4]);
68 section.offset = 4 * val as usize;
69
70 deserialize_u32(&mut val, &raw[4..8]);
71 section.size = 4 * val as usize;
72
73 Ok(())
74}
75
76#[derive(Default, Debug, Clone, PartialEq, Eq)]
78pub struct GeneralSections {
79 pub global: Section,
81 pub tx_stream_format: Section,
83 pub rx_stream_format: Section,
85 pub ext_sync: Section,
87 pub reserved: Section,
88}
89
90impl GeneralSections {
91 const SECTION_COUNT: usize = 5;
92 const SIZE: usize = Section::SIZE * Self::SECTION_COUNT;
93}
94
95#[cfg(test)]
96fn serialize_general_sections(sections: &GeneralSections, raw: &mut [u8]) -> Result<(), String> {
97 assert!(raw.len() >= GeneralSections::SIZE);
98
99 serialize_section(§ions.global, &mut raw[..8])?;
100 serialize_section(§ions.tx_stream_format, &mut raw[8..16])?;
101 serialize_section(§ions.rx_stream_format, &mut raw[16..24])?;
102 serialize_section(§ions.ext_sync, &mut raw[24..32])?;
103 serialize_section(§ions.reserved, &mut raw[32..40])?;
104
105 Ok(())
106}
107
108fn deserialize_general_sections(sections: &mut GeneralSections, raw: &[u8]) -> Result<(), String> {
109 assert!(raw.len() >= GeneralSections::SIZE);
110
111 deserialize_section(&mut sections.global, &raw[..8])?;
112 deserialize_section(&mut sections.tx_stream_format, &raw[8..16])?;
113 deserialize_section(&mut sections.rx_stream_format, &raw[16..24])?;
114 deserialize_section(&mut sections.ext_sync, &raw[24..32])?;
115 deserialize_section(&mut sections.reserved, &raw[32..40])?;
116
117 Ok(())
118}
119
120pub trait TcatSectionSerdes<T> {
122 const MIN_SIZE: usize;
124
125 const ERROR_TYPE: GeneralProtocolError;
127
128 fn serialize(params: &T, raw: &mut [u8]) -> Result<(), String>;
130
131 fn deserialize(params: &mut T, raw: &[u8]) -> Result<(), String>;
133}
134
135#[derive(Debug, Copy, Clone, PartialEq, Eq)]
137pub enum GeneralProtocolError {
138 Global,
140 TxStreamFormat,
142 RxStreamFormat,
144 ExtendedSync,
146 VendorDependent,
148 Invalid(i32),
149}
150
151impl std::fmt::Display for GeneralProtocolError {
152 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
153 let msg = match self {
154 GeneralProtocolError::Global => "global",
155 GeneralProtocolError::TxStreamFormat => "tx-stream-format",
156 GeneralProtocolError::RxStreamFormat => "rx-stream-format",
157 GeneralProtocolError::ExtendedSync => "external-sync",
158 GeneralProtocolError::VendorDependent => "vendor-dependent",
159 GeneralProtocolError::Invalid(_) => "invalid",
160 };
161
162 write!(f, "GeneralProtocolError::{}", msg)
163 }
164}
165
166impl ErrorDomain for GeneralProtocolError {
167 fn domain() -> Quark {
168 Quark::from_str("tcat-general-protocol-error-quark")
169 }
170
171 fn code(self) -> i32 {
172 match self {
173 GeneralProtocolError::Global => 0,
174 GeneralProtocolError::TxStreamFormat => 1,
175 GeneralProtocolError::RxStreamFormat => 2,
176 GeneralProtocolError::ExtendedSync => 3,
177 GeneralProtocolError::VendorDependent => 4,
178 GeneralProtocolError::Invalid(v) => v,
179 }
180 }
181
182 fn from(code: i32) -> Option<Self> {
183 let enumeration = match code {
184 0 => GeneralProtocolError::Global,
185 1 => GeneralProtocolError::TxStreamFormat,
186 2 => GeneralProtocolError::RxStreamFormat,
187 3 => GeneralProtocolError::ExtendedSync,
188 4 => GeneralProtocolError::VendorDependent,
189 _ => GeneralProtocolError::Invalid(code),
190 };
191 Some(enumeration)
192 }
193}
194
195const MAX_FRAME_SIZE: usize = 512;
196
197pub trait TcatOperation {
199 fn read(
201 req: &FwReq,
202 node: &FwNode,
203 offset: usize,
204 mut frames: &mut [u8],
205 timeout_ms: u32,
206 ) -> Result<(), Error> {
207 let mut addr = BASE_ADDR + offset as u64;
208
209 while frames.len() > 0 {
210 let len = std::cmp::min(frames.len(), MAX_FRAME_SIZE);
211 let tcode = if len == 4 {
212 FwTcode::ReadQuadletRequest
213 } else {
214 FwTcode::ReadBlockRequest
215 };
216
217 req.transaction_sync(node, tcode, addr, len, &mut frames[0..len], timeout_ms)?;
218
219 addr += len as u64;
220 frames = &mut frames[len..];
221 }
222
223 Ok(())
224 }
225
226 fn write(
228 req: &FwReq,
229 node: &FwNode,
230 offset: usize,
231 mut frames: &mut [u8],
232 timeout_ms: u32,
233 ) -> Result<(), Error> {
234 let mut addr = BASE_ADDR + (offset as u64);
235
236 while frames.len() > 0 {
237 let len = std::cmp::min(frames.len(), MAX_FRAME_SIZE);
238 let tcode = if len == 4 {
239 FwTcode::WriteQuadletRequest
240 } else {
241 FwTcode::WriteBlockRequest
242 };
243
244 req.transaction_sync(node, tcode, addr, len, &mut frames[0..len], timeout_ms)?;
245
246 addr += len as u64;
247 frames = &mut frames[len..];
248 }
249
250 Ok(())
251 }
252
253 fn read_general_sections(
255 req: &FwReq,
256 node: &FwNode,
257 sections: &mut GeneralSections,
258 timeout_ms: u32,
259 ) -> Result<(), Error> {
260 let mut raw = [0; GeneralSections::SIZE];
261 Self::read(req, node, 0, &mut raw, timeout_ms)?;
262 deserialize_general_sections(sections, &raw)
263 .map_err(|cause| Error::new(GeneralProtocolError::Invalid(0), &cause))
264 }
265}
266
267fn check_section_cache(
268 section: &Section,
269 min_size: usize,
270 error_type: GeneralProtocolError,
271) -> Result<(), Error> {
272 if section.size < min_size {
273 let msg = format!(
274 "The size of section should be larger than {}, actually {}",
275 min_size, section.size
276 );
277 Err(Error::new(error_type, &msg))
278 } else {
279 Ok(())
280 }
281}
282
283pub trait TcatSectionOperation<T>: TcatOperation + TcatSectionSerdes<T>
285where
286 T: Default + Debug,
287{
288 fn whole_cache(
290 req: &FwReq,
291 node: &FwNode,
292 section: &Section,
293 params: &mut T,
294 timeout_ms: u32,
295 ) -> Result<(), Error> {
296 check_section_cache(section, Self::MIN_SIZE, Self::ERROR_TYPE)?;
297 let mut raw = vec![0u8; section.size];
298 Self::read(req, node, section.offset, &mut raw, timeout_ms)?;
299 Self::deserialize(params, &raw).map_err(|msg| Error::new(Self::ERROR_TYPE, &msg))
300 }
301}
302
303pub trait TcatMutableSectionOperation<T>: TcatOperation + TcatSectionSerdes<T>
305where
306 T: Default + Debug,
307{
308 fn whole_update(
310 req: &FwReq,
311 node: &FwNode,
312 section: &Section,
313 params: &T,
314 timeout_ms: u32,
315 ) -> Result<(), Error> {
316 check_section_cache(section, Self::MIN_SIZE, Self::ERROR_TYPE)?;
317 let mut raw = vec![0u8; section.size];
318 Self::serialize(params, &mut raw).map_err(|msg| Error::new(Self::ERROR_TYPE, &msg))?;
319 Self::write(req, node, section.offset, &mut raw, timeout_ms)
320 }
321
322 fn partial_update(
324 req: &FwReq,
325 node: &FwNode,
326 section: &Section,
327 params: &T,
328 prev: &mut T,
329 timeout_ms: u32,
330 ) -> Result<(), Error> {
331 check_section_cache(section, Self::MIN_SIZE, Self::ERROR_TYPE)?;
332
333 let mut new = vec![0u8; section.size];
334 Self::serialize(params, &mut new).map_err(|msg| Error::new(Self::ERROR_TYPE, &msg))?;
335
336 let mut old = vec![0u8; section.size];
337 Self::serialize(prev, &mut old).map_err(|msg| Error::new(Self::ERROR_TYPE, &msg))?;
338
339 (0..section.size).step_by(4).try_for_each(|pos| {
340 if new[pos..(pos + 4)] != old[pos..(pos + 4)] {
341 Self::write(
342 req,
343 node,
344 section.offset + pos,
345 &mut new[pos..(pos + 4)],
346 timeout_ms,
347 )
348 } else {
349 Ok(())
350 }
351 })?;
352
353 Self::deserialize(prev, &new).map_err(|msg| Error::new(Self::ERROR_TYPE, &msg))
354 }
355}
356
357pub trait TcatNotifiedSectionOperation<T>: TcatSectionOperation<T>
359where
360 T: Default + Debug,
361{
362 const NOTIFY_FLAG: u32;
364
365 fn notified(_: &T, msg: u32) -> bool {
367 msg & Self::NOTIFY_FLAG > 0
368 }
369}
370
371pub trait TcatFluctuatedSectionOperation<T>: TcatSectionOperation<T>
373where
374 T: Default + Debug,
375{
376 const FLUCTUATED_OFFSETS: &'static [usize];
379
380 fn partial_cache(
382 req: &FwReq,
383 node: &FwNode,
384 section: &Section,
385 params: &mut T,
386 timeout_ms: u32,
387 ) -> Result<(), Error> {
388 check_section_cache(section, Self::MIN_SIZE, Self::ERROR_TYPE)?;
389
390 let mut raw = vec![0u8; section.size];
391 Self::serialize(params, &mut raw).map_err(|msg| Error::new(Self::ERROR_TYPE, &msg))?;
392
393 Self::FLUCTUATED_OFFSETS.iter().try_for_each(|&offset| {
394 Self::read(
395 req,
396 node,
397 section.offset + offset,
398 &mut raw[offset..(offset + 4)],
399 timeout_ms,
400 )
401 })?;
402 Self::deserialize(params, &raw).map_err(|msg| Error::new(Self::ERROR_TYPE, &msg))
403 }
404}
405
406const BASE_ADDR: u64 = 0xffffe0000000;
407
408#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
410pub struct Iec60958Param {
411 pub cap: bool,
413 pub enable: bool,
415}
416
417pub const IEC60958_CHANNELS: usize = 32;
419
420fn serialize_iec60958_params(
421 params: &[Iec60958Param; IEC60958_CHANNELS],
422 raw: &mut [u8],
423) -> Result<(), String> {
424 assert!(raw.len() >= IEC60958_CHANNELS / 8 * 2);
425
426 let (caps, enables) =
427 params
428 .iter()
429 .enumerate()
430 .fold((0u32, 0u32), |(mut caps, mut enables), (i, params)| {
431 if params.cap {
432 caps |= 1 << i;
433 }
434 if params.enable {
435 enables |= 1 << i;
436 }
437 (caps, enables)
438 });
439
440 raw[..4].copy_from_slice(&caps.to_be_bytes());
441 raw[4..8].copy_from_slice(&enables.to_be_bytes());
442
443 Ok(())
444}
445
446fn deserialize_iec60958_params(
447 params: &mut [Iec60958Param; IEC60958_CHANNELS],
448 raw: &[u8],
449) -> Result<(), String> {
450 assert!(raw.len() >= IEC60958_CHANNELS / 8 * 2);
451
452 let mut quadlet = [0; 4];
453
454 quadlet.copy_from_slice(&raw[..4]);
455 let caps = u32::from_be_bytes(quadlet);
456
457 quadlet.copy_from_slice(&raw[4..8]);
458 let enables = u32::from_be_bytes(quadlet);
459
460 params.iter_mut().enumerate().for_each(|(i, param)| {
461 param.cap = (1 << i) & caps > 0;
462 param.enable = (1 << i) & enables > 0;
463 });
464
465 Ok(())
466}
467
468fn from_ne(raw: &mut [u8]) {
469 let mut quadlet = [0; 4];
470 (0..raw.len()).step_by(4).for_each(|pos| {
471 quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
472 raw[pos..(pos + 4)].copy_from_slice(&u32::from_ne_bytes(quadlet).to_be_bytes());
473 });
474}
475
476fn to_ne(raw: &mut [u8]) {
477 let mut quadlet = [0; 4];
478 (0..raw.len()).step_by(4).for_each(|pos| {
479 quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
480 raw[pos..(pos + 4)].copy_from_slice(&u32::from_be_bytes(quadlet).to_ne_bytes());
481 });
482}
483
484fn serialize_label<T: AsRef<str>>(name: T, raw: &mut [u8]) -> Result<(), String> {
485 let r = name.as_ref().as_bytes();
486
487 if r.len() >= raw.len() {
488 Err(format!("Insufficient buffer size {} for label", raw.len()))
489 } else {
490 raw[..r.len()].copy_from_slice(r);
491 from_ne(raw);
492
493 Ok(())
494 }
495}
496
497fn serialize_labels<T: AsRef<str>>(labels: &[T], raw: &mut [u8]) -> Result<(), String> {
498 raw.fill(0x00);
499
500 let mut pos = 0;
501 labels.iter().try_for_each(|label| {
502 let r = label.as_ref().as_bytes();
503
504 if pos + r.len() + 1 >= raw.len() {
505 Err(format!(
506 "Insufficient buffer size {} for all of labels",
507 raw.len()
508 ))
509 } else {
510 let end = pos + r.len();
511 raw[pos..end].copy_from_slice(r);
512
513 raw[end] = '\\' as u8;
514 pos = end + 1;
515
516 Ok(())
517 }
518 })?;
519
520 if pos + 1 >= raw.len() {
521 Err(format!(
522 "Insufficient buffer size {} for all of labels",
523 raw.len()
524 ))
525 } else {
526 raw[pos] = '\\' as u8;
527
528 from_ne(raw);
529
530 Ok(())
531 }
532}
533
534fn deserialize_label(label: &mut String, raw: &[u8]) -> Result<(), String> {
535 let mut data = raw.to_vec();
536 to_ne(&mut data);
537
538 data.push(0x00);
539 std::str::from_utf8(&data)
540 .map_err(|err| err.to_string())
541 .and_then(|text| {
542 text.find('\0')
543 .ok_or_else(|| "String terminator not found".to_string())
544 .map(|pos| *label = text[..pos].to_string())
545 })
546}
547
548fn deserialize_labels(labels: &mut Vec<String>, raw: &[u8]) -> Result<(), String> {
549 labels.truncate(0);
550
551 let mut data = raw.to_vec();
552 to_ne(&mut data);
553
554 data.split(|&b| b == '\\' as u8)
555 .filter(|chunk| chunk.len() > 0 && chunk[0] != '\0' as u8)
556 .fuse()
557 .try_for_each(|chunk| {
558 std::str::from_utf8(&chunk)
559 .map(|label| labels.push(label.to_string()))
560 .map_err(|err| err.to_string())
561 })
562}
563
564const NOTIFY_RX_CFG_CHG: u32 = 0x00000001;
565const NOTIFY_TX_CFG_CHG: u32 = 0x00000002;
566const NOTIFY_LOCK_CHG: u32 = 0x00000010;
567const NOTIFY_CLOCK_ACCEPTED: u32 = 0x00000020;
568const NOTIFY_EXT_STATUS: u32 = 0x00000040;
569
570#[cfg(test)]
571mod test {
572 use super::*;
573
574 #[test]
575 fn label_serdes() {
576 let label = "label-0";
577
578 let mut raw = vec![0u8; 20];
579 serialize_label(&label, &mut raw).unwrap();
580
581 let mut l = String::new();
582 deserialize_label(&mut l, &raw).unwrap();
583
584 assert_eq!(label, l);
585 }
586
587 #[test]
588 fn labels_serdes() {
589 let labels: Vec<String> = (0..10).map(|num| format!("label-{}", num)).collect();
590
591 let mut raw = vec![0u8; 100];
592 serialize_labels(&labels, &mut raw).unwrap();
593
594 let mut l = Vec::new();
595 deserialize_labels(&mut l, &raw).unwrap();
596
597 assert_eq!(labels, l);
598 }
599
600 #[test]
601 fn sections_serdes() {
602 let raw = [
603 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00,
604 0x00, 0x8e, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, 0x02, 0x11,
605 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 ];
607 let mut params = GeneralSections::default();
608 deserialize_general_sections(&mut params, &raw).unwrap();
609
610 assert_eq!(params.global.offset, 0x28);
611 assert_eq!(params.global.size, 0x17c);
612 assert_eq!(params.tx_stream_format.offset, 0x1a4);
613 assert_eq!(params.tx_stream_format.size, 0x238);
614 assert_eq!(params.rx_stream_format.offset, 0x3dc);
615 assert_eq!(params.rx_stream_format.size, 0x468);
616 assert_eq!(params.ext_sync.offset, 0x844);
617 assert_eq!(params.ext_sync.size, 0x10);
618 assert_eq!(params.reserved.offset, 0);
619 assert_eq!(params.reserved.size, 0);
620
621 let mut r = vec![0u8; raw.len()];
622 serialize_general_sections(¶ms, &mut r).unwrap();
623
624 assert_eq!(r, raw);
625 }
626}