firewire_fireworks_protocols/
hw_ctl.rs1use super::*;
10
11const CATEGORY_HWCTL: u32 = 3;
12
13const CMD_SET_CLOCK: u32 = 0;
14const CMD_GET_CLOCK: u32 = 1;
15const CMD_SET_FLAGS: u32 = 3;
16const CMD_GET_FLAGS: u32 = 4;
17const CMD_BLINK_LED: u32 = 5;
18const CMD_RECONNECT: u32 = 6;
19
20#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
22pub struct EfwSamplingClockParameters {
23 pub rate: u32,
25 pub source: ClkSrc,
27}
28
29impl<O, P> EfwWhollyCachableParamsOperation<P, EfwSamplingClockParameters> for O
30where
31 O: EfwHardwareSpecification,
32 P: EfwProtocolExtManual,
33{
34 fn cache_wholly(
35 proto: &mut P,
36 states: &mut EfwSamplingClockParameters,
37 timeout_ms: u32,
38 ) -> Result<(), Error> {
39 let args = Vec::new();
40 let mut params = vec![0; 3];
41 proto
42 .transaction(
43 CATEGORY_HWCTL,
44 CMD_GET_CLOCK,
45 &args,
46 &mut params,
47 timeout_ms,
48 )
49 .map(|_| {
50 deserialize_clock_source(&mut states.source, params[0]);
51 states.rate = params[1];
52 })
53 }
54}
55
56impl<O, P> EfwWhollyUpdatableParamsOperation<P, EfwSamplingClockParameters> for O
57where
58 O: EfwHardwareSpecification,
59 P: EfwProtocolExtManual,
60{
61 fn update_wholly(
62 proto: &mut P,
63 states: &EfwSamplingClockParameters,
64 timeout_ms: u32,
65 ) -> Result<(), Error> {
66 let args = [serialize_clock_source(&states.source), states.rate, 0];
67 let mut params = vec![0; 3];
68 proto.transaction(
69 CATEGORY_HWCTL,
70 CMD_SET_CLOCK,
71 &args,
72 &mut params,
73 timeout_ms,
74 )
75 }
76}
77
78#[derive(Debug, Copy, Clone, PartialEq, Eq)]
80pub enum HwCtlFlag {
81 MixerEnabled,
83 SpdifPro,
85 SpdifNoneAudio,
87 CtlRoomSelect,
89 OutputLevelBypass,
91 MeterInMode,
93 MeterOutMode,
95 SoftClip,
97 GuitarHexInput,
99 GuitarAutoCharging,
101 PhantomPowering,
103 Reserved(usize),
104}
105
106impl Default for HwCtlFlag {
107 fn default() -> Self {
108 Self::Reserved(usize::MAX)
109 }
110}
111
112fn serialize_hw_ctl_flag(flag: &HwCtlFlag) -> usize {
113 match flag {
114 HwCtlFlag::MixerEnabled => 0,
115 HwCtlFlag::SpdifPro => 1,
116 HwCtlFlag::SpdifNoneAudio => 2,
117 HwCtlFlag::CtlRoomSelect => 8, HwCtlFlag::OutputLevelBypass => 9,
119 HwCtlFlag::MeterInMode => 12,
120 HwCtlFlag::MeterOutMode => 13,
121 HwCtlFlag::SoftClip => 18,
122 HwCtlFlag::GuitarHexInput => 29,
123 HwCtlFlag::GuitarAutoCharging => 30,
124 HwCtlFlag::PhantomPowering => 31,
125 HwCtlFlag::Reserved(pos) => *pos,
126 }
127}
128
129fn deserialize_hw_ctl_flag(flag: &mut HwCtlFlag, pos: usize) {
130 *flag = match pos {
131 0 => HwCtlFlag::MixerEnabled,
132 1 => HwCtlFlag::SpdifPro,
133 2 => HwCtlFlag::SpdifNoneAudio,
134 8 => HwCtlFlag::CtlRoomSelect,
135 9 => HwCtlFlag::OutputLevelBypass,
136 12 => HwCtlFlag::MeterInMode,
137 13 => HwCtlFlag::MeterOutMode,
138 18 => HwCtlFlag::SoftClip,
139 29 => HwCtlFlag::GuitarHexInput,
140 30 => HwCtlFlag::GuitarAutoCharging,
141 31 => HwCtlFlag::PhantomPowering,
142 _ => HwCtlFlag::Reserved(pos),
143 };
144}
145
146#[derive(Default, Debug, Clone, PartialEq, Eq)]
148pub struct EfwHwCtlFlags(pub Vec<HwCtlFlag>);
149
150impl<O, P> EfwWhollyCachableParamsOperation<P, EfwHwCtlFlags> for O
151where
152 O: EfwHardwareSpecification,
153 P: EfwProtocolExtManual,
154{
155 fn cache_wholly(
156 proto: &mut P,
157 states: &mut EfwHwCtlFlags,
158 timeout_ms: u32,
159 ) -> Result<(), Error> {
160 let args = Vec::new();
161 let mut params = vec![0];
162 proto.transaction(
163 CATEGORY_HWCTL,
164 CMD_GET_FLAGS,
165 &args,
166 &mut params,
167 timeout_ms,
168 )?;
169
170 (0..32).filter(|i| params[0] & (1 << i) > 0).for_each(|i| {
171 let mut flag = HwCtlFlag::default();
172 deserialize_hw_ctl_flag(&mut flag, i);
173 if states.0.iter().find(|f| flag.eq(f)).is_none() {
174 states.0.push(flag);
175 }
176 });
177
178 Ok(())
179 }
180}
181
182impl<O, P> EfwPartiallyUpdatableParamsOperation<P, EfwHwCtlFlags> for O
183where
184 O: EfwHardwareSpecification,
185 P: EfwProtocolExtManual,
186{
187 fn update_partially(
188 proto: &mut P,
189 states: &mut EfwHwCtlFlags,
190 updates: EfwHwCtlFlags,
191 timeout_ms: u32,
192 ) -> Result<(), Error> {
193 let mut args = [0; 2];
194 let mut params = Vec::new();
195 updates
197 .0
198 .iter()
199 .for_each(|flag| args[0] |= 1 << serialize_hw_ctl_flag(flag));
200 states.0.iter().for_each(|flag| {
202 if updates.0.iter().find(|f| flag.eq(f)).is_none() {
203 args[1] = 1 << serialize_hw_ctl_flag(flag);
204 }
205 });
206 proto.transaction(
207 CATEGORY_HWCTL,
208 CMD_SET_FLAGS,
209 &args,
210 &mut params,
211 timeout_ms,
212 )
213 }
214}
215
216#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
218pub struct EfwLedBlink;
219
220impl<O, P> EfwWhollyUpdatableParamsOperation<P, EfwLedBlink> for O
221where
222 O: EfwHardwareSpecification,
223 P: EfwProtocolExtManual,
224{
225 fn update_wholly(proto: &mut P, _: &EfwLedBlink, timeout_ms: u32) -> Result<(), Error> {
226 let args = Vec::new();
227 let mut params = Vec::new();
228 proto.transaction(
229 CATEGORY_HWCTL,
230 CMD_BLINK_LED,
231 &args,
232 &mut params,
233 timeout_ms,
234 )
235 }
236}
237
238#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
240pub struct EfwReconnectPhy;
241
242impl<O, P> EfwWhollyUpdatableParamsOperation<P, EfwReconnectPhy> for O
243where
244 O: EfwHardwareSpecification,
245 P: EfwProtocolExtManual,
246{
247 fn update_wholly(proto: &mut P, _: &EfwReconnectPhy, timeout_ms: u32) -> Result<(), Error> {
248 let args = Vec::new();
249 let mut params = Vec::new();
250 proto.transaction(
251 CATEGORY_HWCTL,
252 CMD_RECONNECT,
253 &args,
254 &mut params,
255 timeout_ms,
256 )
257 }
258}
259
260#[cfg(test)]
261mod test {
262 use super::*;
263
264 #[test]
265 fn hw_ctl_flag_serdes() {
266 [
267 HwCtlFlag::MixerEnabled,
268 HwCtlFlag::SpdifPro,
269 HwCtlFlag::SpdifNoneAudio,
270 HwCtlFlag::CtlRoomSelect,
271 HwCtlFlag::OutputLevelBypass,
272 HwCtlFlag::MeterInMode,
273 HwCtlFlag::MeterOutMode,
274 HwCtlFlag::SoftClip,
275 HwCtlFlag::GuitarHexInput,
276 HwCtlFlag::GuitarAutoCharging,
277 HwCtlFlag::PhantomPowering,
278 HwCtlFlag::default(),
279 ]
280 .iter()
281 .for_each(|flag| {
282 let val = serialize_hw_ctl_flag(&flag);
283 let mut f = HwCtlFlag::default();
284 deserialize_hw_ctl_flag(&mut f, val);
285 assert_eq!(*flag, f);
286 });
287 }
288}