use super::*;
#[derive(Default, Debug)]
pub struct Phase88ClkProtocol;
impl MediaClockFrequencyOperation for Phase88ClkProtocol {
const FREQ_LIST: &'static [u32] = &[32000, 44100, 48000, 88200, 96000];
}
const CLK_SRC_EXT_FB_ID: u8 = 0x08;
const CLK_SRC_EXT_WORD_FB_ID: u8 = 0x09;
impl SamplingClockSourceOperation for Phase88ClkProtocol {
const DST: SignalAddr = SignalAddr::Subunit(SignalSubunitAddr {
subunit: MUSIC_SUBUNIT_0,
plug_id: 0x03,
});
const SRC_LIST: &'static [SignalAddr] = &[
SignalAddr::Subunit(SignalSubunitAddr {
subunit: MUSIC_SUBUNIT_0,
plug_id: 0x05,
}),
SignalAddr::Unit(SignalUnitAddr::Ext(0x04)),
SignalAddr::Unit(SignalUnitAddr::Ext(0x07)),
];
fn cache_src(
avc: &BebobAvc,
params: &mut SamplingClockParameters,
timeout_ms: u32,
) -> Result<(), Error> {
let mut op = AudioSelector::new(CLK_SRC_EXT_FB_ID, CtlAttr::Current, 0xff);
avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
params.src_idx = if op.input_plug_id == 0x00 {
0
} else {
let mut op = AudioSelector::new(CLK_SRC_EXT_WORD_FB_ID, CtlAttr::Current, 0xff);
avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
if op.input_plug_id == 0x00 {
1
} else {
2
}
};
Ok(())
}
fn update_src(
avc: &BebobAvc,
params: &SamplingClockParameters,
old: &mut SamplingClockParameters,
timeout_ms: u32,
) -> Result<(), Error> {
let (is_ext, ext_is_word) = match params.src_idx {
0 => (0u8, 0u8),
1 => (0u8, 1u8),
2 => (1u8, 1u8),
_ => {
let msg = format!("Invalid index of source of clock: {}", params.src_idx);
Err(Error::new(FileError::Inval, &msg))?
}
};
let mut op = AudioSelector::new(CLK_SRC_EXT_WORD_FB_ID, CtlAttr::Current, ext_is_word);
avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
let mut op = AudioSelector::new(CLK_SRC_EXT_FB_ID, CtlAttr::Current, is_ext);
avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
*old = *params;
Ok(())
}
}
#[derive(Default, Debug)]
pub struct Phase88PhysInputProtocol;
impl AvcSelectorOperation for Phase88PhysInputProtocol {
const FUNC_BLOCK_ID_LIST: &'static [u8] = &[0x0a];
const INPUT_PLUG_ID_LIST: &'static [u8] = &[
0x00, 0x01, ];
}
#[derive(Default, Debug)]
pub struct Phase88MixerPhysSourceProtocol;
impl AvcAudioFeatureSpecification for Phase88MixerPhysSourceProtocol {
const ENTRIES: &'static [(u8, AudioCh)] = &[
(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)), ];
}
impl AvcLevelOperation for Phase88MixerPhysSourceProtocol {}
impl AvcMuteOperation for Phase88MixerPhysSourceProtocol {}
#[derive(Default, Debug)]
pub struct Phase88MixerStreamSourceProtocol;
impl AvcAudioFeatureSpecification for Phase88MixerStreamSourceProtocol {
const ENTRIES: &'static [(u8, AudioCh)] = &[
(0x07, AudioCh::Each(0)), (0x07, AudioCh::Each(1)), ];
}
impl AvcLevelOperation for Phase88MixerStreamSourceProtocol {}
impl AvcMuteOperation for Phase88MixerStreamSourceProtocol {}
impl AvcSelectorOperation for Phase88MixerStreamSourceProtocol {
const FUNC_BLOCK_ID_LIST: &'static [u8] = &[0x07];
const INPUT_PLUG_ID_LIST: &'static [u8] = &[
0x01, 0x02, 0x03, 0x04, 0x00, ];
}
#[derive(Default, Debug)]
pub struct Phase88MixerOutputProtocol;
impl AvcAudioFeatureSpecification for Phase88MixerOutputProtocol {
const ENTRIES: &'static [(u8, AudioCh)] = &[(0x00, AudioCh::Each(0)), (0x01, AudioCh::Each(1))];
}
impl AvcLevelOperation for Phase88MixerOutputProtocol {}
impl AvcMuteOperation for Phase88MixerOutputProtocol {}
const MIXER_OUT_SELECTOR_FB_ID_LIST: [u8; 1] = [0x06];
const MIXER_OUT_SELECTOR_ID_LIST: [u8; 6] = [
0x01, 0x02, 0x03, 0x04, 0x00, 0x05, ];
const PHYS_OUTPUT_SELECTOR_FB_ID_LIST: [u8; 5] = [
0x01, 0x02, 0x03, 0x04, 0x05, ];
#[allow(dead_code)]
const PHYS_OUTPUT_SELECTOR_ID_LIST: [u8; 2] = [0x00, 0x01];
impl AvcSelectorOperation for Phase88MixerOutputProtocol {
const FUNC_BLOCK_ID_LIST: &'static [u8] = &MIXER_OUT_SELECTOR_FB_ID_LIST;
const INPUT_PLUG_ID_LIST: &'static [u8] = &MIXER_OUT_SELECTOR_ID_LIST;
fn cache_selectors(
avc: &BebobAvc,
params: &mut AvcSelectorParameters,
timeout_ms: u32,
) -> Result<(), Error> {
assert_eq!(params.selectors.len(), 1);
let func_block_id = MIXER_OUT_SELECTOR_FB_ID_LIST[0];
let mut op = AudioSelector::new(func_block_id, CtlAttr::Current, 0xff);
avc.status(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
MIXER_OUT_SELECTOR_ID_LIST
.iter()
.position(|&input_plug_id| input_plug_id == op.input_plug_id)
.ok_or_else(|| {
let msg = format!(
"Unexpected value for index of input plug number: {}",
op.input_plug_id
);
Error::new(FileError::Io, &msg)
})
.map(|pos| params.selectors[0] = pos)
}
fn update_selectors(
avc: &BebobAvc,
params: &AvcSelectorParameters,
old: &mut AvcSelectorParameters,
timeout_ms: u32,
) -> Result<(), Error> {
let selector = params.selectors[0];
if selector != old.selectors[0] {
let func_block_id = MIXER_OUT_SELECTOR_FB_ID_LIST[0];
let input_plug_id = MIXER_OUT_SELECTOR_ID_LIST
.iter()
.nth(selector)
.ok_or_else(|| {
let msg = format!(
"Invalid argument for index of input plug number: {}",
selector
);
Error::new(FileError::Inval, &msg)
})
.copied()?;
let mut op = AudioSelector::new(func_block_id, CtlAttr::Current, input_plug_id);
avc.control(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)?;
PHYS_OUTPUT_SELECTOR_FB_ID_LIST
.iter()
.enumerate()
.try_for_each(|(i, &func_block_id)| {
let plug_id_idx = if input_plug_id == 0x05 {
0
} else {
if i == 0 {
0
} else {
1
}
};
let val = PHYS_OUTPUT_SELECTOR_ID_LIST[plug_id_idx];
let mut op = AudioSelector::new(func_block_id, CtlAttr::Current, val);
avc.control(&AUDIO_SUBUNIT_0_ADDR, &mut op, timeout_ms)
})?;
old.selectors[0] = selector;
}
Ok(())
}
}