ta1394_avc_ccm/
lib.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2022 Takashi Sakamoto
3
4#![doc = include_str!("../README.md")]
5
6use ta1394_avc_general::*;
7
8/// Address of plug in unit.
9#[derive(Copy, Clone, Debug, Eq, PartialEq)]
10pub enum SignalUnitAddr {
11    /// The plug for isochronous stream.
12    Isoc(
13        /// The numeric identifier of plug.
14        u8,
15    ),
16    /// The plug for external signal.
17    Ext(
18        /// The numeric identifier of plug.
19        u8,
20    ),
21}
22
23impl Default for SignalUnitAddr {
24    fn default() -> Self {
25        Self::Isoc(Self::PLUG_ID_MASK)
26    }
27}
28
29impl SignalUnitAddr {
30    const EXT_PLUG_FLAG: u8 = 0x80;
31    const PLUG_ID_MASK: u8 = 0x7f;
32
33    const LENGTH: usize = 2;
34
35    fn from_raw(raw: &[u8]) -> Result<Self, AvcRespParseError> {
36        if raw.len() < Self::LENGTH {
37            Err(AvcRespParseError::TooShortResp(Self::LENGTH))?;
38        }
39
40        let plug_id = raw[1] & Self::PLUG_ID_MASK;
41        let plug = if raw[1] & Self::EXT_PLUG_FLAG > 0 {
42            Self::Ext(plug_id)
43        } else {
44            Self::Isoc(plug_id)
45        };
46        Ok(plug)
47    }
48
49    fn to_raw(&self) -> [u8; Self::LENGTH] {
50        let mut raw = [0; Self::LENGTH];
51        raw[0] = AvcAddr::UNIT_ADDR;
52        raw[1] = match self {
53            SignalUnitAddr::Isoc(val) => *val,
54            SignalUnitAddr::Ext(val) => SignalUnitAddr::EXT_PLUG_FLAG | *val,
55        };
56        raw
57    }
58}
59
60/// Address of plug in subunit.
61#[derive(Copy, Clone, Debug, Eq, PartialEq)]
62pub struct SignalSubunitAddr {
63    /// The address of subunit.
64    pub subunit: AvcAddrSubunit,
65    /// The numeric identifier of plug.
66    pub plug_id: u8,
67}
68
69impl Default for SignalSubunitAddr {
70    fn default() -> Self {
71        Self {
72            subunit: Default::default(),
73            plug_id: 0xff,
74        }
75    }
76}
77
78impl SignalSubunitAddr {
79    const LENGTH: usize = 2;
80
81    fn from_raw(raw: &[u8]) -> Result<Self, AvcRespParseError> {
82        if raw.len() < Self::LENGTH {
83            Err(AvcRespParseError::TooShortResp(Self::LENGTH))?;
84        }
85
86        let subunit = AvcAddrSubunit::from(raw[0]);
87        let plug_id = raw[1];
88        Ok(SignalSubunitAddr { subunit, plug_id })
89    }
90
91    fn to_raw(&self) -> [u8; Self::LENGTH] {
92        let mut raw = [0; Self::LENGTH];
93        raw[0] = u8::from(self.subunit);
94        raw[1] = self.plug_id;
95        raw
96    }
97}
98
99/// Address of plug for signal source or destination.
100#[derive(Copy, Clone, Debug, Eq, PartialEq)]
101pub enum SignalAddr {
102    Unit(SignalUnitAddr),
103    Subunit(SignalSubunitAddr),
104}
105
106impl Default for SignalAddr {
107    fn default() -> Self {
108        Self::Unit(Default::default())
109    }
110}
111
112impl SignalAddr {
113    const LENGTH: usize = 2;
114
115    pub fn new_for_isoc_unit(plug_id: u8) -> Self {
116        SignalAddr::Unit(SignalUnitAddr::Isoc(plug_id & SignalUnitAddr::PLUG_ID_MASK))
117    }
118
119    pub fn new_for_ext_unit(plug_id: u8) -> Self {
120        SignalAddr::Unit(SignalUnitAddr::Ext(plug_id & SignalUnitAddr::PLUG_ID_MASK))
121    }
122
123    pub fn new_for_subunit(subunit_type: AvcSubunitType, subunit_id: u8, plug_id: u8) -> Self {
124        SignalAddr::Subunit(SignalSubunitAddr {
125            subunit: AvcAddrSubunit {
126                subunit_type,
127                subunit_id,
128            },
129            plug_id,
130        })
131    }
132
133    fn from_raw(raw: &[u8]) -> Result<Self, AvcRespParseError> {
134        if raw.len() < Self::LENGTH {
135            Err(AvcRespParseError::TooShortResp(Self::LENGTH))?;
136        }
137
138        let addr = if raw[0] == AvcAddr::UNIT_ADDR {
139            let data = SignalUnitAddr::from_raw(&raw)?;
140            SignalAddr::Unit(data)
141        } else {
142            let data = SignalSubunitAddr::from_raw(&raw)?;
143            SignalAddr::Subunit(data)
144        };
145
146        Ok(addr)
147    }
148
149    fn to_raw(&self) -> [u8; Self::LENGTH] {
150        match self {
151            SignalAddr::Unit(a) => a.to_raw(),
152            SignalAddr::Subunit(a) => a.to_raw(),
153        }
154    }
155}
156
157/// AV/C SIGNAL SOURCE command
158///
159/// Described in clause 7.1.1 SIGNAL SOURCE control command format.
160#[derive(Copy, Clone, Debug, Eq, PartialEq)]
161pub struct SignalSource {
162    /// The source of signal.
163    pub src: SignalAddr,
164    /// The destination of signal.
165    pub dst: SignalAddr,
166}
167
168impl SignalSource {
169    const LENGTH_MIN: usize = 5;
170
171    pub fn new(dst: &SignalAddr) -> Self {
172        SignalSource {
173            dst: *dst,
174            ..Default::default()
175        }
176    }
177
178    fn build_operands(&self, for_status: bool) -> Result<Vec<u8>, AvcCmdBuildError> {
179        let mut operands = Vec::new();
180        operands.push(0xff);
181
182        if for_status {
183            operands.extend_from_slice(&[0xff, 0xfe]);
184        } else {
185            operands.extend_from_slice(&self.src.to_raw());
186        }
187
188        operands.extend_from_slice(&self.dst.to_raw());
189        Ok(operands)
190    }
191
192    fn parse_operands(&mut self, operands: &[u8]) -> Result<(), AvcRespParseError> {
193        if operands.len() < Self::LENGTH_MIN {
194            Err(AvcRespParseError::TooShortResp(4))?;
195        }
196
197        self.src = SignalAddr::from_raw(&operands[1..3]).map_err(|err| err.add_offset(1))?;
198        self.dst = SignalAddr::from_raw(&operands[3..5]).map_err(|err| err.add_offset(3))?;
199        Ok(())
200    }
201}
202
203impl Default for SignalSource {
204    fn default() -> Self {
205        Self {
206            src: Default::default(),
207            dst: Default::default(),
208        }
209    }
210}
211
212impl AvcOp for SignalSource {
213    const OPCODE: u8 = 0x1a;
214}
215
216impl AvcControl for SignalSource {
217    fn build_operands(&mut self, _: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
218        Self::build_operands(&self, false)
219    }
220
221    fn parse_operands(&mut self, _: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
222        Self::parse_operands(self, operands)
223    }
224}
225
226impl AvcStatus for SignalSource {
227    fn build_operands(&mut self, _: &AvcAddr) -> Result<Vec<u8>, AvcCmdBuildError> {
228        Self::build_operands(&self, true)
229    }
230
231    fn parse_operands(&mut self, _: &AvcAddr, operands: &[u8]) -> Result<(), AvcRespParseError> {
232        Self::parse_operands(self, operands)
233    }
234}
235
236#[cfg(test)]
237mod test {
238    use crate::*;
239
240    #[test]
241    fn signaladdr_from() {
242        let raw = [0xff, 0x00];
243        let addr = SignalAddr::from_raw(&raw).unwrap();
244        assert_eq!(raw, addr.to_raw());
245
246        let raw = [0xff, 0x27];
247        let addr = SignalAddr::from_raw(&raw).unwrap();
248        assert_eq!(raw, addr.to_raw());
249
250        let raw = [0xff, 0x87];
251        let addr = SignalAddr::from_raw(&raw).unwrap();
252        assert_eq!(raw, addr.to_raw());
253
254        let raw = [0xff, 0xc7];
255        let addr = SignalAddr::from_raw(&raw).unwrap();
256        assert_eq!(raw, addr.to_raw());
257
258        let raw = [0x63, 0x07];
259        let addr = SignalAddr::from_raw(&raw).unwrap();
260        assert_eq!(raw, addr.to_raw());
261
262        let raw = [0x09, 0x11];
263        let addr = SignalAddr::from_raw(&raw).unwrap();
264        assert_eq!(raw, addr.to_raw());
265    }
266
267    #[test]
268    fn signalsource_operands() {
269        let operands = [0x00, 0x2e, 0x1c, 0xff, 0x05];
270        let dst = SignalAddr::Unit(SignalUnitAddr::Isoc(0x05));
271        let src = SignalAddr::Subunit(SignalSubunitAddr {
272            subunit: AvcAddrSubunit::new(AvcSubunitType::Tuner, 0x06),
273            plug_id: 0x1c,
274        });
275        let mut op = SignalSource::new(&dst);
276        AvcStatus::parse_operands(&mut op, &AvcAddr::Unit, &operands).unwrap();
277        assert_eq!(op.src, src);
278        assert_eq!(op.dst, dst);
279
280        let targets = AvcStatus::build_operands(&mut op, &AvcAddr::Unit).unwrap();
281        assert_eq!(targets, [0xff, 0xff, 0xfe, 0xff, 0x05]);
282
283        let src = SignalAddr::Subunit(SignalSubunitAddr {
284            subunit: AvcAddrSubunit::new(AvcSubunitType::Extended, 0x05),
285            plug_id: 0x07,
286        });
287        let dst = SignalAddr::Unit(SignalUnitAddr::Ext(0x03));
288        let mut op = SignalSource { src, dst };
289        let targets = AvcControl::build_operands(&mut op, &AvcAddr::Unit).unwrap();
290        assert_eq!(targets, [0xff, 0xf5, 0x07, 0xff, 0x83]);
291
292        let mut op = SignalSource {
293            src: SignalAddr::Unit(SignalUnitAddr::Isoc(0xf)),
294            dst: SignalAddr::Unit(SignalUnitAddr::Isoc(0xf)),
295        };
296        AvcControl::parse_operands(&mut op, &AvcAddr::Unit, &targets).unwrap();
297        assert_eq!(op.src, src);
298        assert_eq!(op.dst, dst);
299    }
300}