firewire_motu_protocols/
config_rom.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2021 Takashi Sakamoto
3
4//! Parser for Configuration ROM.
5//!
6//! The module includes structure, enumeration, and trait and its implementaion to parse
7//! configuration ROM according to specification defined by Mark of the Unicorn.
8
9use ieee1212_config_rom::*;
10
11/// Data in unit directory of Configuration ROM.
12#[derive(Default, Debug, Clone, Copy)]
13pub struct UnitData {
14    pub model_id: u32,
15    pub version: u32,
16}
17
18const OUI_MOTU: u32 = 0x0001f2;
19
20/// The trait for parser of configuration ROM.
21pub trait MotuConfigRom {
22    fn get_unit_data(&self) -> Option<UnitData>;
23}
24
25impl<'a> MotuConfigRom for ConfigRom<'a> {
26    fn get_unit_data(&self) -> Option<UnitData> {
27        self.root
28            .iter()
29            .find_map(|entry| {
30                EntryDataAccess::<u32>::get(entry, KeyType::Vendor).and_then(|vendor_id| {
31                    if vendor_id == OUI_MOTU {
32                        Some(vendor_id)
33                    } else {
34                        None
35                    }
36                })
37            })
38            .and_then(|_| {
39                self.root
40                    .iter()
41                    .find_map(|entry| EntryDataAccess::<&[Entry]>::get(entry, KeyType::Unit))
42                    .and_then(|entries| {
43                        entries
44                            .iter()
45                            .find_map(|entry| {
46                                EntryDataAccess::<u32>::get(entry, KeyType::SpecifierId).and_then(
47                                    |specifier_id| {
48                                        if specifier_id == OUI_MOTU {
49                                            Some(specifier_id)
50                                        } else {
51                                            None
52                                        }
53                                    },
54                                )
55                            })
56                            .and_then(|_| {
57                                // NOTE: It's odd but version field is used for model ID and model field is
58                                // used for version in MOTU case.
59                                entries
60                                    .iter()
61                                    .find_map(|entry| {
62                                        EntryDataAccess::<u32>::get(entry, KeyType::Version)
63                                    })
64                                    .and_then(|model_id| {
65                                        entries
66                                            .iter()
67                                            .find_map(|entry| {
68                                                EntryDataAccess::<u32>::get(entry, KeyType::Model)
69                                            })
70                                            .map(|version| UnitData { model_id, version })
71                                    })
72                            })
73                    })
74            })
75    }
76}