firewire_bebob_protocols/terratec/
phase88.rs1use super::*;
39
40#[derive(Default, Debug)]
42pub struct Phase88ClkProtocol;
43
44impl MediaClockFrequencyOperation for Phase88ClkProtocol {
45 const FREQ_LIST: &'static [u32] = &[32000, 44100, 48000, 88200, 96000];
46}
47
48const CLK_SRC_EXT_FB_ID: u8 = 0x08;
49const CLK_SRC_EXT_WORD_FB_ID: u8 = 0x09;
50
51impl SamplingClockSourceOperation for Phase88ClkProtocol {
52 const DST: SignalAddr = SignalAddr::Subunit(SignalSubunitAddr {
53 subunit: MUSIC_SUBUNIT_0,
54 plug_id: 0x03,
55 });
56
57 const SRC_LIST: &'static [SignalAddr] = &[
58 SignalAddr::Subunit(SignalSubunitAddr {
60 subunit: MUSIC_SUBUNIT_0,
61 plug_id: 0x05,
62 }),
63 SignalAddr::Unit(SignalUnitAddr::Ext(0x04)),
65 SignalAddr::Unit(SignalUnitAddr::Ext(0x07)),
67 ];
68
69 fn cache_src(
70 avc: &BebobAvc,
71 params: &mut SamplingClockParameters,
72 timeout_ms: u32,
73 ) -> Result<(), Error> {
74 let mut op = AudioSelector::new(CLK_SRC_EXT_FB_ID, CtlAttr::Current, 0xff);
75 avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
76 params.src_idx = if op.input_plug_id == 0x00 {
77 0
79 } else {
80 let mut op = AudioSelector::new(CLK_SRC_EXT_WORD_FB_ID, CtlAttr::Current, 0xff);
81 avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
82 if op.input_plug_id == 0x00 {
83 1
85 } else {
86 2
88 }
89 };
90 Ok(())
91 }
92
93 fn update_src(
94 avc: &BebobAvc,
95 params: &SamplingClockParameters,
96 old: &mut SamplingClockParameters,
97 timeout_ms: u32,
98 ) -> Result<(), Error> {
99 let (is_ext, ext_is_word) = match params.src_idx {
100 0 => (0u8, 0u8),
101 1 => (0u8, 1u8),
102 2 => (1u8, 1u8),
103 _ => {
104 let msg = format!("Invalid index of source of clock: {}", params.src_idx);
105 Err(Error::new(FileError::Inval, &msg))?
106 }
107 };
108
109 let mut op = AudioSelector::new(CLK_SRC_EXT_WORD_FB_ID, CtlAttr::Current, ext_is_word);
110 avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
111
112 let mut op = AudioSelector::new(CLK_SRC_EXT_FB_ID, CtlAttr::Current, is_ext);
113 avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
114
115 *old = *params;
116
117 Ok(())
118 }
119}
120
121#[derive(Default, Debug)]
123pub struct Phase88PhysInputProtocol;
124
125impl AvcSelectorOperation for Phase88PhysInputProtocol {
126 const FUNC_BLOCK_ID_LIST: &'static [u8] = &[0x0a];
128 const INPUT_PLUG_ID_LIST: &'static [u8] = &[
129 0x00, 0x01, ];
132}
133
134#[derive(Default, Debug)]
136pub struct Phase88MixerPhysSourceProtocol;
137
138impl AvcAudioFeatureSpecification for Phase88MixerPhysSourceProtocol {
139 const ENTRIES: &'static [(u8, AudioCh)] = &[
140 (0x02, AudioCh::Each(0)), (0x02, AudioCh::Each(1)), (0x03, AudioCh::Each(0)), (0x03, AudioCh::Each(1)), (0x04, AudioCh::Each(0)), (0x04, AudioCh::Each(1)), (0x05, AudioCh::Each(0)), (0x05, AudioCh::Each(1)), (0x06, AudioCh::Each(0)), (0x06, AudioCh::Each(1)), ];
151}
152
153impl AvcLevelOperation for Phase88MixerPhysSourceProtocol {}
154
155impl AvcMuteOperation for Phase88MixerPhysSourceProtocol {}
156
157#[derive(Default, Debug)]
159pub struct Phase88MixerStreamSourceProtocol;
160
161impl AvcAudioFeatureSpecification for Phase88MixerStreamSourceProtocol {
162 const ENTRIES: &'static [(u8, AudioCh)] = &[
163 (0x07, AudioCh::Each(0)), (0x07, AudioCh::Each(1)), ];
166}
167
168impl AvcLevelOperation for Phase88MixerStreamSourceProtocol {}
169
170impl AvcMuteOperation for Phase88MixerStreamSourceProtocol {}
171
172impl AvcSelectorOperation for Phase88MixerStreamSourceProtocol {
173 const FUNC_BLOCK_ID_LIST: &'static [u8] = &[0x07];
174 const INPUT_PLUG_ID_LIST: &'static [u8] = &[
175 0x01, 0x02, 0x03, 0x04, 0x00, ];
181}
182
183#[derive(Default, Debug)]
185pub struct Phase88MixerOutputProtocol;
186
187impl AvcAudioFeatureSpecification for Phase88MixerOutputProtocol {
188 const ENTRIES: &'static [(u8, AudioCh)] = &[(0x00, AudioCh::Each(0)), (0x01, AudioCh::Each(1))];
189}
190
191impl AvcLevelOperation for Phase88MixerOutputProtocol {}
192
193impl AvcMuteOperation for Phase88MixerOutputProtocol {}
194
195const MIXER_OUT_SELECTOR_FB_ID_LIST: [u8; 1] = [0x06];
196
197const MIXER_OUT_SELECTOR_ID_LIST: [u8; 6] = [
198 0x01, 0x02, 0x03, 0x04, 0x00, 0x05, ];
205
206const PHYS_OUTPUT_SELECTOR_FB_ID_LIST: [u8; 5] = [
207 0x01, 0x02, 0x03, 0x04, 0x05, ];
213
214#[allow(dead_code)]
216const PHYS_OUTPUT_SELECTOR_ID_LIST: [u8; 2] = [0x00, 0x01];
217
218impl AvcSelectorOperation for Phase88MixerOutputProtocol {
220 const FUNC_BLOCK_ID_LIST: &'static [u8] = &MIXER_OUT_SELECTOR_FB_ID_LIST;
221 const INPUT_PLUG_ID_LIST: &'static [u8] = &MIXER_OUT_SELECTOR_ID_LIST;
222
223 fn cache_selectors(
224 avc: &BebobAvc,
225 params: &mut AvcSelectorParameters,
226 timeout_ms: u32,
227 ) -> Result<(), Error> {
228 assert_eq!(params.selectors.len(), 1);
229
230 let func_block_id = MIXER_OUT_SELECTOR_FB_ID_LIST[0];
231
232 let mut op = AudioSelector::new(func_block_id, CtlAttr::Current, 0xff);
233 avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
234
235 MIXER_OUT_SELECTOR_ID_LIST
236 .iter()
237 .position(|&input_plug_id| input_plug_id == op.input_plug_id)
238 .ok_or_else(|| {
239 let msg = format!(
240 "Unexpected value for index of input plug number: {}",
241 op.input_plug_id
242 );
243 Error::new(FileError::Io, &msg)
244 })
245 .map(|pos| params.selectors[0] = pos)
246 }
247
248 fn update_selectors(
249 avc: &BebobAvc,
250 params: &AvcSelectorParameters,
251 old: &mut AvcSelectorParameters,
252 timeout_ms: u32,
253 ) -> Result<(), Error> {
254 let selector = params.selectors[0];
255
256 if selector != old.selectors[0] {
257 let func_block_id = MIXER_OUT_SELECTOR_FB_ID_LIST[0];
258 let input_plug_id = MIXER_OUT_SELECTOR_ID_LIST
259 .iter()
260 .nth(selector)
261 .ok_or_else(|| {
262 let msg = format!(
263 "Invalid argument for index of input plug number: {}",
264 selector
265 );
266 Error::new(FileError::Inval, &msg)
267 })
268 .copied()?;
269
270 let mut op = AudioSelector::new(func_block_id, CtlAttr::Current, input_plug_id);
271 avc.control(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
272
273 PHYS_OUTPUT_SELECTOR_FB_ID_LIST
274 .iter()
275 .enumerate()
276 .try_for_each(|(i, &func_block_id)| {
277 let plug_id_idx = if input_plug_id == 0x05 {
278 0
281 } else {
282 if i == 0 {
283 0
285 } else {
286 1
288 }
289 };
290
291 let val = PHYS_OUTPUT_SELECTOR_ID_LIST[plug_id_idx];
292 let mut op = AudioSelector::new(func_block_id, CtlAttr::Current, val);
293 avc.control(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)
294 })?;
295
296 old.selectors[0] = selector;
297 }
298
299 Ok(())
300 }
301}