Re: snd-firewire-ctl-services: Digidesign Digi-002R - missing control for 'Optical mode'
| Newsgroups | org.alsa-project.alsa-devel |
|---|---|
| Message-ID | <[email protected]> |
On 2026-05-11 22:19, Takashi Sakamoto wrote: > Yes. The service program provides no ALSA control element set > for this purpose, because Digi 002 differs from Digi 003 in how it > selects the source of S/PDIF signals for audio data in IEEE 1394 > isochronous packets sent to the host system. > I experimented some more, and was able to muddle through the Rust code to 'move' the control (from 003 protocol) to act on the 002. This showed that the 002R does actually support this function. I found a couple of things: 1). Parameter is not saved unless the Jack server is stopped before making the change. I think that this is expected. -- simon@EliteBook:~/snd-firewire-ctl-services.github$ amixer -c 2 cset numid=8 'S/PDIF' numid=8,iface=MIXER,name='optical-interface' ; type=ENUMERATED,access=rw------,values=1,items=2 ; Item #0 'ADAT' ; Item #1 'S/PDIF' : values=1 simon@EliteBook:~/snd-firewire-ctl-services.github$ amixer -c 2 cget numid=8 numid=8,iface=MIXER,name='optical-interface' ; type=ENUMERATED,access=rw------,values=1,items=2 ; Item #0 'ADAT' ; Item #1 'S/PDIF' : values=1 -- 2). With 'loop backs' on the RCA and Optical ports I got all channels in 'normal/ADAT' mode, but in the 'S/PDIF' mode the path was re-assigned. I got nothing through channels 11..18 (normally ADAT/optical), instead only channels 9..10 passed audio - HOWEVER these are going over the optical fibre (not co-ax cable), unplug the fibre and this loop-back stops. So in summary I think the existing code can be re-jigged to cover both 002 and 003. Simon.
Screenshot_2026-05-12_12-26-32.png
(image/png, 151.8 KB) - not displayed
20260512_hacky_adat.patch
(text/x-diff, 5.3 KB)
diff --git a/protocols/digi00x/src/lib.rs b/protocols/digi00x/src/lib.rs
index 06942da3..4f4ac697 100644
--- a/protocols/digi00x/src/lib.rs
+++ b/protocols/digi00x/src/lib.rs
@@ -277,7 +277,7 @@ impl Default for OpticalInterfaceMode {
}
}
-impl Dg00xWhollyCachableParamsOperation<OpticalInterfaceMode> for Digi003Protocol {
+impl Dg00xWhollyCachableParamsOperation<OpticalInterfaceMode> for Digi002Protocol {
fn cache_wholly(
req: &mut FwReq,
node: &mut FwNode,
@@ -294,7 +294,7 @@ impl Dg00xWhollyCachableParamsOperation<OpticalInterfaceMode> for Digi003Protoco
}
}
-impl Dg00xWhollyUpdatableParamsOperation<OpticalInterfaceMode> for Digi003Protocol {
+impl Dg00xWhollyUpdatableParamsOperation<OpticalInterfaceMode> for Digi002Protocol {
fn update_wholly(
req: &mut FwReq,
node: &mut FwNode,
diff --git a/runtime/digi00x/src/model.rs b/runtime/digi00x/src/model.rs
index 4e164936..babccf46 100644
--- a/runtime/digi00x/src/model.rs
+++ b/runtime/digi00x/src/model.rs
@@ -11,6 +11,7 @@ pub struct Digi002Model {
common_ctl: CommonCtl<Digi002Protocol>,
meter_ctl: MeterCtl<Digi002Protocol>,
monitor_ctl: MonitorCtl<Digi002Protocol>,
+ opt_iface_ctl: OpticalIfaceCtl,
}
impl CtlModel<(SndDigi00x, FwNode)> for Digi002Model {
@@ -19,6 +20,7 @@ impl CtlModel<(SndDigi00x, FwNode)> for Digi002Model {
self.meter_ctl.cache(&mut self.req, node, TIMEOUT_MS)?;
self.monitor_ctl
.cache(unit, &mut self.req, node, TIMEOUT_MS)?;
+ self.opt_iface_ctl.cache(&mut self.req, node, TIMEOUT_MS)?;
Ok(())
}
@@ -26,6 +28,7 @@ impl CtlModel<(SndDigi00x, FwNode)> for Digi002Model {
self.common_ctl.load(card_cntr)?;
self.meter_ctl.load(card_cntr)?;
self.monitor_ctl.load(card_cntr)?;
+ self.opt_iface_ctl.load(card_cntr)?;
Ok(())
}
@@ -36,6 +39,8 @@ impl CtlModel<(SndDigi00x, FwNode)> for Digi002Model {
Ok(true)
} else if self.monitor_ctl.read(elem_id, elem_value)? {
Ok(true)
+ } else if self.opt_iface_ctl.read(elem_id, elem_value)? {
+ Ok(true)
} else {
Ok(false)
}
@@ -61,6 +66,15 @@ impl CtlModel<(SndDigi00x, FwNode)> for Digi002Model {
TIMEOUT_MS,
)? {
Ok(true)
+ } else if self.opt_iface_ctl.write(
+ unit,
+ &mut self.req,
+ node,
+ elem_id,
+ elem_value,
+ TIMEOUT_MS,
+ )? {
+ Ok(true)
} else {
Ok(false)
}
@@ -103,7 +117,7 @@ pub struct Digi003Model {
common_ctl: CommonCtl<Digi003Protocol>,
meter_ctl: MeterCtl<Digi003Protocol>,
monitor_ctl: MonitorCtl<Digi003Protocol>,
- opt_iface_ctl: OpticalIfaceCtl,
+ //opt_iface_ctl: OpticalIfaceCtl,
}
impl CtlModel<(SndDigi00x, FwNode)> for Digi003Model {
@@ -112,7 +126,7 @@ impl CtlModel<(SndDigi00x, FwNode)> for Digi003Model {
self.meter_ctl.cache(&mut self.req, node, TIMEOUT_MS)?;
self.monitor_ctl
.cache(unit, &mut self.req, node, TIMEOUT_MS)?;
- self.opt_iface_ctl.cache(&mut self.req, node, TIMEOUT_MS)?;
+ //self.opt_iface_ctl.cache(&mut self.req, node, TIMEOUT_MS)?;
Ok(())
}
@@ -120,7 +134,7 @@ impl CtlModel<(SndDigi00x, FwNode)> for Digi003Model {
self.common_ctl.load(card_cntr)?;
self.meter_ctl.load(card_cntr)?;
self.monitor_ctl.load(card_cntr)?;
- self.opt_iface_ctl.load(card_cntr)?;
+ //self.opt_iface_ctl.load(card_cntr)?;
Ok(())
}
@@ -131,8 +145,8 @@ impl CtlModel<(SndDigi00x, FwNode)> for Digi003Model {
Ok(true)
} else if self.monitor_ctl.read(elem_id, elem_value)? {
Ok(true)
- } else if self.opt_iface_ctl.read(elem_id, elem_value)? {
- Ok(true)
+ //} else if self.opt_iface_ctl.read(elem_id, elem_value)? {
+ // Ok(true)
} else {
Ok(false)
}
@@ -158,15 +172,6 @@ impl CtlModel<(SndDigi00x, FwNode)> for Digi003Model {
TIMEOUT_MS,
)? {
Ok(true)
- } else if self.opt_iface_ctl.write(
- unit,
- &mut self.req,
- node,
- elem_id,
- elem_value,
- TIMEOUT_MS,
- )? {
- Ok(true)
} else {
Ok(false)
}
@@ -387,7 +392,7 @@ impl OpticalIfaceCtl {
&[OpticalInterfaceMode::Adat, OpticalInterfaceMode::Spdif];
fn cache(&mut self, req: &mut FwReq, node: &mut FwNode, timeout_ms: u32) -> Result<(), Error> {
- let res = Digi003Protocol::cache_wholly(req, node, &mut self.opt_iface_mode, timeout_ms);
+ let res = Digi002Protocol::cache_wholly(req, node, &mut self.opt_iface_mode, timeout_ms);
debug!(params = ?self.opt_iface_mode, ?res);
res
}
@@ -444,7 +449,7 @@ impl OpticalIfaceCtl {
Error::new(FileError::Inval, &msg)
})
.copied()?;
- let res = Digi003Protocol::update_wholly(req, node, ¶ms, timeout_ms)
+ let res = Digi002Protocol::update_wholly(req, node, ¶ms, timeout_ms)
.map(|_| self.opt_iface_mode = params);
debug!(params = ?self.opt_iface_mode, ?res);
res.map(|_| true)