1use alloc::vec::Vec;
11use core::{convert::TryInto, fmt, fmt::Debug, ops::Deref, str::FromStr};
12use std::ops::DerefMut;
13
14use anyhow::Result;
15use bytes::{Buf, BufMut, Bytes, BytesMut};
16#[cfg(feature = "use_serde")]
17use serde::{Deserialize, Serialize};
18#[cfg(feature = "debug")]
19use thiserror::Error;
20
21use super::DeviceInfo;
22use crate::{
23 eeprom, packet::ParseError, util::TryBuf, util::TryBufError, FixedPoint, MasterStatus,
24};
25
26pub const READ_FLOATS_MAX: usize = 14;
28
29#[derive(Clone)]
30#[cfg_attr(feature = "debug", derive(Debug, Error))]
31pub enum ProtocolError {
32 #[cfg_attr(feature = "debug", error("bad cmd id"))]
33 BadCommandId,
34
35 #[cfg_attr(feature = "debug", error("unexpected response type"))]
36 UnexpectedResponseType,
37
38 #[cfg_attr(feature = "debug", error("parse error: {0}"))]
39 ParseError(ParseError),
40
41 #[cfg_attr(
42 feature = "debug",
43 error("the received hardware id was malformed or empty")
44 )]
45 MalformedHardwareId,
46
47 #[cfg_attr(feature = "debug", error("parse error: {0}"))]
48 DecodeError(#[from] TryBufError),
49}
50
51#[derive(Clone)]
52pub struct BytesWrap(pub Bytes);
53impl fmt::Debug for BytesWrap {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 Debug::fmt(self.0.as_ref(), f)
56 }
57}
58impl Deref for BytesWrap {
59 type Target = Bytes;
60
61 fn deref(&self) -> &Self::Target {
62 &self.0
63 }
64}
65impl DerefMut for BytesWrap {
66 fn deref_mut(&mut self) -> &mut Self::Target {
67 &mut self.0
68 }
69}
70
71#[derive(Clone)]
72pub enum Value {
73 Unknown(Bytes),
74 Float(f32),
75 FixedPoint(FixedPoint),
76 Int(u16),
77 Int32(u32),
78}
79
80impl Default for Value {
81 fn default() -> Self {
82 Value::Float(0.)
83 }
84}
85
86impl From<f32> for Value {
87 fn from(f: f32) -> Self {
88 Value::Float(f)
89 }
90}
91
92impl From<FixedPoint> for Value {
93 fn from(fp: FixedPoint) -> Self {
94 Value::FixedPoint(fp)
95 }
96}
97
98impl From<u16> for Value {
99 fn from(x: u16) -> Self {
100 Value::Int(x)
101 }
102}
103
104impl Value {
105 pub fn into_bytes(self) -> Bytes {
106 match self {
107 Value::Unknown(b) => b,
108 Value::Float(f) => Bytes::copy_from_slice(&f.to_le_bytes()),
109 Value::FixedPoint(fp) => Bytes::copy_from_slice(&fp.to_u32().to_be_bytes()),
110 Value::Int(i) => {
111 let mut b = BytesMut::with_capacity(4);
112 b.put_u16_le(i);
113 b.put_u16(0x00);
114 b.freeze()
115 }
116 Value::Int32(i) => Bytes::copy_from_slice(&i.to_be_bytes()),
117 }
118 }
119
120 pub fn from_bytes(mut b: Bytes) -> Result<Self, TryBufError> {
121 Ok(
122 if b.len() == 4 && ((b[0] != 0 || b[1] != 0) && b[2] == 0 && b[3] == 0) {
123 Value::Int(b.try_get_u16_le()?)
124 } else {
125 Value::Unknown(b)
126 },
127 )
128 }
129}
130
131#[cfg(feature = "debug")]
132impl fmt::Debug for Value {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 let b = self.clone().into_bytes();
135 match self {
136 Value::Unknown(_) => {
137 let float = if b.len() >= 4 {
138 Some(b.clone().get_f32_le())
139 } else {
140 None
141 };
142
143 let u = if b.len() >= 4 {
144 Some(b.clone().get_u32())
145 } else {
146 None
147 };
148
149 let fixed = if b.len() >= 4 {
150 Some(FixedPoint::from_u32(b.clone().get_u32()))
151 } else {
152 None
153 };
154
155 let i = b[0];
156 write!(
157 f,
158 "Value {{ Bytes: {:x?} (i: {:?} | i32: {:?} | f32: {:?} | fp: {:?}) }}",
159 b.as_ref(),
160 i,
161 u.unwrap_or_default(),
162 float.unwrap_or_default(),
163 fixed.unwrap_or_default()
164 )
165 }
166 &Value::Float(val) => {
167 write!(f, "Value {{ Bytes: {:x?} (f32: {:?}) }}", b.as_ref(), val)
168 }
169 &Value::FixedPoint(val) => {
170 write!(
171 f,
172 "Value {{ Bytes: {:x?} (fp: {:?}) }}",
173 b.as_ref(),
174 val.to_f32(),
175 )
176 }
177 &Value::Int(val) => {
178 write!(f, "Value {{ Bytes: {:x?} (i: {:?}) }}", b.as_ref(), val)
179 }
180 &Value::Int32(val) => {
181 write!(f, "Value {{ Bytes: {:x?} (i32: {:?}) }}", b.as_ref(), val)
182 }
183 }
184 }
185}
186
187#[derive(Clone, Copy, PartialEq, Eq)]
188#[cfg_attr(feature = "debug", derive(Debug))]
189pub struct Addr {
190 pub val: u32,
191 pub len: u8,
192 pub extra_bit: bool,
193}
194
195impl Addr {
196 pub fn new(val: u16, len: u8) -> Self {
197 Self {
198 val: val as u32,
199 len,
200 extra_bit: true,
201 }
202 }
203
204 pub fn new_with_extra_bit(val: u32, len: u8, extra_bit: bool) -> Self {
205 Self {
206 val,
207 len,
208 extra_bit,
209 }
210 }
211
212 pub fn read(buf: &mut Bytes, len: u8) -> Result<Self, TryBufError> {
213 match len {
214 2 => Self::read_u16(buf),
215 3 => Self::read_u24(buf),
216 _ => panic!("invalid address len"),
217 }
218 }
219
220 pub fn read_u16(buf: &mut Bytes) -> Result<Self, TryBufError> {
221 let mut val = buf.try_get_u16()?;
222 let extra_bit = (val & 0x80_00) != 0;
223
224 val &= 0x0FFF;
225
226 Ok(Self {
227 val: val as _,
228 len: 2,
229 extra_bit,
230 })
231 }
232
233 pub fn read_u24(buf: &mut Bytes) -> Result<Self, TryBufError> {
234 let prefix = buf.try_get_u8()?;
235 let extra_bit = (prefix & 0x80) != 0;
236 let prefix = prefix & 0x0F;
237 let addr = buf.try_get_u16()? as u32;
238 let val = (prefix as u32) << 16 | addr;
239 Ok(Self {
240 val: val as _,
241 len: 3,
242 extra_bit,
243 })
244 }
245
246 pub fn write(&self, buf: &mut BytesMut) {
247 match self.len {
248 2 => {
249 let mut val = 0x80_00 | (self.val & 0x7F_FF);
250 if !self.extra_bit {
251 val ^= 0x80_00;
252 }
253 buf.put_u16(val as _)
254 }
255 3 => {
256 let mut val = 0x80_00_00 | (self.val & 0x7F_FF_FF);
257 if !self.extra_bit {
258 val ^= 0x80_00_00;
259 }
260 buf.put_u8(((val >> 16) & 0xFF) as _);
261 buf.put_u16(val as _);
262 }
263 _ => panic!("invalid address len"),
264 }
265 }
266}
267
268#[derive(Clone)]
269#[cfg_attr(feature = "debug", derive(Debug))]
270pub enum Commands {
271 ReadHardwareId,
273
274 ReadFloats {
276 addr: u16,
277 len: u8,
278 },
279
280 WriteMemory {
282 addr: u16,
283 data: BytesWrap,
284 },
285
286 ReadMemory {
288 addr: u16,
289 size: u8,
290 },
291
292 SetConfig {
294 config: u8,
295 reset: bool,
296 },
297
298 SetSource {
300 source: u8,
301 },
302
303 SetMute {
305 value: bool,
306 },
307
308 SetVolume {
310 value: Gain,
311 },
312
313 WriteBiquad {
315 addr: Addr,
316 data: [Value; 5],
317 },
318
319 WriteBiquadBypass {
321 addr: Addr,
322 value: bool,
323 },
324
325 Read {
327 addr: Addr,
328 len: u8,
329 },
330
331 Write {
333 addr: Addr,
334 value: Value,
335 },
336
337 FirLoadStart {
339 index: u8,
340 },
341
342 FirLoadData {
344 index: u8,
345 data: Vec<f32>, },
347
348 FirLoadEnd,
350
351 DiracBypass {
353 value: u8,
354 },
355
356 BulkLoad {
359 payload: BytesWrap,
369 },
370
371 BulkLoadFilterData {
373 payload: BytesWrap,
376 },
377
378 Unk07 {
380 payload: u8,
381 },
382
383 SwitchMux {
384 addr: Addr, max: u8, arg: bool, slot: u8, },
389
390 Unknown {
391 cmd_id: u8,
392 payload: BytesWrap,
393 },
394}
395
396impl Commands {
397 pub fn from_bytes(mut frame: Bytes) -> Result<Commands, ProtocolError> {
398 Ok(match frame.try_get_u8()? {
399 0x02 => Commands::Read {
400 addr: {
401 let len = if frame.len() >= 3 { 3 } else { 2 };
402 Addr::read(&mut frame, len)?
403 },
404 len: frame.try_get_u8()?,
405 },
406 0x04 => Commands::WriteMemory {
407 addr: frame.try_get_u16()?,
408 data: BytesWrap(frame),
409 },
410 0x05 => Commands::ReadMemory {
411 addr: frame.try_get_u16()?,
412 size: frame.try_get_u8()?,
413 },
414 0x06 => Commands::BulkLoadFilterData {
415 payload: BytesWrap(frame),
416 },
417 0x07 => Commands::Unk07 {
418 payload: frame.try_get_u8()?,
419 },
420 0x12 => Commands::BulkLoad {
421 payload: BytesWrap(frame),
422 },
423 0x13 => {
424 let len = if frame.len() >= 7 { 3 } else { 2 };
425 Commands::Write {
426 addr: Addr::read(&mut frame, len)?,
427 value: Value::from_bytes(frame)?,
428 }
429 }
430 0x14 => Commands::ReadFloats {
431 addr: frame.try_get_u16()?,
432 len: frame.try_get_u8()?,
433 },
434 0x17 => Commands::SetMute {
435 value: frame.try_get_u8()? != 0,
436 },
437 0x19 => {
438 let len = if frame.len() > 2 { 3 } else { 2 };
439 let addr = Addr::read(&mut frame, len)?;
440
441 Commands::WriteBiquadBypass {
442 value: addr.extra_bit,
443 addr,
444 }
445 }
446 0x25 => Commands::SetConfig {
447 config: frame.try_get_u8()?,
448 reset: frame.try_get_u8()? != 0,
449 },
450 0x31 => Commands::ReadHardwareId {},
451 0x29 => {
452 let addr = Addr::read(&mut frame, 2)?;
453 let mut max = frame.try_get_u8()?;
454 let arg = max & 0x80 != 0;
455 if arg {
456 max ^= 0x80;
457 }
458 let slot = frame.try_get_u8()?;
459
460 Commands::SwitchMux {
461 addr,
462 max,
463 arg,
464 slot,
465 }
466 }
467 0x30 => Commands::WriteBiquad {
468 addr: {
469 let len = if frame.len() > 24 { 3 } else { 2 };
470 Addr::read(&mut frame, len)?
471 },
472 data: {
473 frame.try_get_u16()?;
474 let mut data: [Value; 5] = Default::default();
475 for f in data.iter_mut() {
476 *f = Value::Unknown(Bytes::copy_from_slice(&frame[0..4]));
477 frame.advance(4);
478 }
479 data
480 },
481 },
482 0x34 => Commands::SetSource {
483 source: frame.try_get_u8()?,
484 },
485 0x39 => Commands::FirLoadStart {
486 index: frame.try_get_u8()?,
487 },
488 0x3a => Commands::FirLoadData {
489 index: frame.try_get_u8()?,
490 data: {
491 let mut data = Vec::with_capacity(15);
492 while frame.len() > 4 {
493 data.push(frame.try_get_f32_le()?);
494 }
495 data
496 },
497 },
498 0x3b => Commands::FirLoadEnd,
499 0x42 => Commands::SetVolume {
500 value: frame.try_get_u8()?.into(),
501 },
502 cmd_id => Commands::Unknown {
503 cmd_id,
504 payload: BytesWrap(frame),
505 },
506 })
507 }
508
509 pub fn to_bytes(&self) -> Bytes {
510 let mut f = BytesMut::with_capacity(64);
511
512 match self {
513 Commands::ReadHardwareId => {
514 f.put_u8(0x31);
515 }
516 &Commands::ReadFloats { addr, len } => {
517 f.put_u8(0x14);
518 f.put_u16(addr);
519 f.put_u8(len);
520 }
521 &Commands::ReadMemory { addr, size } => {
522 f.put_u8(0x05);
523 f.put_u16(addr);
524 f.put_u8(size);
525 }
526 &Commands::WriteMemory { addr, ref data } => {
527 f.put_u8(0x04);
528 f.put_u16(addr);
529 f.put(data.0.clone());
530 }
531 &Commands::SetConfig { config, reset } => {
532 f.put_u8(0x25);
533 f.put_u8(config);
534 f.put_u8(reset as u8);
535 }
536 &Commands::SetSource { source } => {
537 f.put_u8(0x34);
538 f.put_u8(source);
539 }
540 &Commands::SetMute { value } => {
541 f.put_u8(0x17);
542 f.put_u8(value as u8);
543 }
544 &Commands::SetVolume { value } => {
545 f.put_u8(0x42);
546 f.put_u8((value).into());
547 }
548 Commands::WriteBiquad { addr, data } => {
549 f.put_u8(0x30);
550 addr.write(&mut f);
551 f.put_u16(0x0000);
552 for coeff in data.iter() {
553 f.put(coeff.clone().into_bytes());
554 }
555 }
556 &Commands::WriteBiquadBypass { mut addr, value } => {
557 f.put_u8(0x19);
558 addr.extra_bit = value;
559 addr.write(&mut f);
560 }
561 &Commands::Read { addr, len } => {
562 f.put_u8(0x2);
563 addr.write(&mut f);
564 f.put_u8(len);
565 }
566 &Commands::Write { addr, ref value } => {
567 f.put_u8(0x13);
568 addr.write(&mut f);
569 f.put(value.clone().into_bytes());
570 }
571
572 &Commands::FirLoadStart { index } => {
573 f.put_u8(0x39);
574 f.put_u8(index);
575 }
576 &Commands::FirLoadData { index, ref data } => {
577 f.put_u8(0x3a);
578 f.put_u8(index);
579 for &coeff in data {
580 f.put_f32_le(coeff);
581 }
582 }
583 &Commands::FirLoadEnd => {
584 f.put_u8(0x3b);
585 }
586 Commands::BulkLoad { payload } => {
587 f.put_u8(0x12);
588 f.put(payload.0.clone());
589 }
590 Commands::BulkLoadFilterData { payload } => {
591 f.put_u8(0x06);
592 f.put(payload.0.clone());
593 }
594 &Commands::DiracBypass { value } => {
595 f.put_u8(0x3f);
596 f.put_u8(value);
597 }
598 &Commands::SwitchMux {
599 addr,
600 mut max,
601 arg,
602 slot,
603 } => {
604 f.put_u8(0x29);
605 addr.write(&mut f);
606 if arg {
607 max |= 0x80;
608 }
609 f.put_u8(max);
610 f.put_u8(slot);
611 }
612 &Commands::Unk07 { payload } => {
613 f.put_u8(0x07);
614 f.put_u8(payload);
615 }
616 &Commands::Unknown {
617 cmd_id,
618 ref payload,
619 } => {
620 f.put_u8(cmd_id);
621 f.put(payload.0.clone());
622 }
623 }
624 f.freeze()
625 }
626
627 pub fn matches_response(&self, response: &Responses) -> bool {
628 match self {
629 &Commands::ReadMemory { addr, size } => {
630 if let Responses::MemoryData(data) = response {
631 data.base == addr && data.data.len() == size as usize
632 } else {
633 false
634 }
635 }
636 &Commands::ReadFloats { addr, len } => {
637 if let Responses::FloatData(data) = response {
638 data.base == addr && data.data.len() == len as usize
639 } else {
640 false
641 }
642 }
643 Commands::ReadHardwareId => matches!(response, Responses::HardwareId { .. }),
644 Commands::SetConfig { .. } => matches!(response, Responses::ConfigChanged),
645 Commands::FirLoadStart { .. } => matches!(response, Responses::FirLoadSize { .. }),
646 &Commands::Unk07 { .. } => matches!(response, Responses::Unk02 { .. }),
647 &Commands::Read { .. } => matches!(response, Responses::Read { .. }),
648 Commands::WriteMemory { .. }
649 | Commands::SetSource { .. }
650 | Commands::SetMute { .. }
651 | Commands::SetVolume { .. }
652 | Commands::WriteBiquad { .. }
653 | Commands::WriteBiquadBypass { .. }
654 | Commands::Write { .. }
655 | Commands::FirLoadData { .. }
656 | Commands::FirLoadEnd
657 | Commands::BulkLoad { .. }
658 | Commands::BulkLoadFilterData { .. }
659 | Commands::DiracBypass { .. }
660 | Commands::SwitchMux { .. } => matches!(response, Responses::Ack),
661 Commands::Unknown { .. } => true,
662 }
663 }
664
665 pub fn mute(addr: Addr, value: bool) -> Self {
666 let value: u16 = if value {
667 WriteInt::DISABLED
668 } else {
669 WriteInt::ENABLED
670 };
671
672 Commands::Write {
673 addr,
674 value: Value::Int(value),
675 }
676 }
677}
678
679#[derive(Clone)]
680#[cfg_attr(feature = "debug", derive(Debug))]
681pub enum Responses {
682 Ack,
683 Read {
684 addr: Addr,
685 data: Vec<Value>,
686 },
687 MemoryData(MemoryView),
688 FloatData(FloatView),
689 HardwareId {
690 payload: BytesWrap,
691 },
692 FirLoadSize {
693 size: u16,
694 },
695
696 ConfigChanged,
698
699 Unk02,
701
702 Unknown {
703 cmd_id: u8,
704 payload: BytesWrap,
705 },
706}
707
708impl Responses {
709 pub fn from_bytes(mut frame: Bytes) -> Result<Responses, ProtocolError> {
710 if frame.is_empty() {
711 return Ok(Responses::Ack);
712 }
713
714 Ok(match frame[0] {
715 0x02 => Responses::Read {
716 addr: {
717 frame.try_get_u8()?;
718 Addr::read(&mut frame, 2)?
719 },
720 data: {
721 frame
722 .chunks(4)
723 .filter_map(|x| Value::from_bytes(Bytes::copy_from_slice(x)).ok())
724 .collect()
725 },
726 },
727 0x05 => Responses::MemoryData(MemoryView::from_packet(frame)?),
728 0x14 => Responses::FloatData(FloatView::from_packet(frame)?),
729 0x31 => Responses::HardwareId {
730 payload: {
731 frame.try_get_u8()?;
732 BytesWrap(frame)
733 },
734 },
735 0x39 => Responses::FirLoadSize {
736 size: {
737 frame.try_get_u8()?; frame.try_get_u16()?
739 },
740 },
741 0xab => Responses::ConfigChanged,
742 cmd_id => Responses::Unknown {
743 cmd_id,
744 payload: BytesWrap(frame),
745 },
746 })
747 }
748
749 pub fn to_bytes(&self) -> Bytes {
750 let mut f = BytesMut::with_capacity(64);
751 match self {
752 Responses::Ack => {}
753 Responses::MemoryData(data) => {
754 f.put_u8(0x05);
755 f.put_u16(data.base);
756 f.put(data.data.clone());
757 }
758 Responses::FloatData(data) => {
759 f.put_u8(0x14);
760 f.put_u16(data.base);
761
762 for &item in &data.data {
763 f.put_f32_le(item);
764 }
765 }
766 &Responses::Unknown {
767 cmd_id,
768 ref payload,
769 } => {
770 f.put_u8(cmd_id);
771 f.put(payload.0.clone());
772 }
773 Responses::HardwareId { payload } => {
774 f.put_u8(0x31);
775 f.put(payload.0.clone());
776 }
777 &Responses::FirLoadSize { size } => {
778 f.put_u8(0x39);
779 f.put_u16(size);
780 }
781 Responses::ConfigChanged => {
782 f.put_u8(0xab);
783 }
784 Responses::Read { addr, data } => {
785 f.put_u8(0x02);
786 addr.write(&mut f);
787 for d in data {
788 f.put(d.clone().into_bytes())
789 }
790 }
791 &Responses::Unk02 => {
792 f.put_u8(0x02);
793 }
794 }
795 f.freeze()
796 }
797
798 pub fn is_memory_view(&self) -> bool {
799 matches!(self, Responses::MemoryData(_))
800 }
801
802 pub fn into_memory_view(self) -> Result<MemoryView, ProtocolError> {
803 match self {
804 Responses::MemoryData(m) => Ok(m),
805 _ => Err(ProtocolError::UnexpectedResponseType),
806 }
807 }
808
809 pub fn is_float_view(&self) -> bool {
810 matches!(self, Responses::FloatData(_))
811 }
812
813 pub fn into_float_view(self) -> Result<FloatView, ProtocolError> {
814 match self {
815 Responses::FloatData(m) => Ok(m),
816 _ => Err(ProtocolError::UnexpectedResponseType),
817 }
818 }
819
820 pub fn is_hardware_id(&self) -> bool {
821 matches!(self, Responses::HardwareId { .. })
822 }
823
824 pub fn into_hardware_id(self) -> Result<u8, ProtocolError> {
825 match self {
826 Responses::HardwareId { payload } => {
827 Ok(*payload.last().ok_or(ProtocolError::MalformedHardwareId)?)
828 }
829 _ => Err(ProtocolError::UnexpectedResponseType),
830 }
831 }
832
833 pub fn is_ack(&self) -> bool {
834 matches!(self, Responses::Ack)
835 }
836
837 pub fn into_ack(self) -> Result<(), ProtocolError> {
838 match self {
839 Responses::Ack => Ok(()),
840 _ => Err(ProtocolError::UnexpectedResponseType),
841 }
842 }
843
844 pub fn is_config_changed(&self) -> bool {
845 matches!(self, Responses::ConfigChanged)
846 }
847
848 pub fn into_config_changed(self) -> Result<(), ProtocolError> {
849 match self {
850 Responses::ConfigChanged => Ok(()),
851 _ => Err(ProtocolError::UnexpectedResponseType),
852 }
853 }
854
855 pub fn is_fir_size(&self) -> bool {
856 matches!(self, Responses::FirLoadSize { .. })
857 }
858
859 pub fn into_fir_size(self) -> Result<u16, ProtocolError> {
860 match self {
861 Responses::FirLoadSize { size } => Ok(size),
862 _ => Err(ProtocolError::UnexpectedResponseType),
863 }
864 }
865}
866
867pub trait UnaryResponse: Sized {
869 fn from_packet(packet: Bytes) -> Result<Self, ProtocolError>;
870}
871
872#[derive(Copy, Clone, PartialEq, Default)]
873#[cfg_attr(feature = "debug", derive(Debug))]
874#[cfg_attr(
875 feature = "serde",
876 derive(Serialize, Deserialize, schemars::JsonSchema)
877)]
878pub struct Gain(pub f32);
880
881impl Gain {
882 pub const MIN: f32 = -127.;
883 pub const MAX: f32 = 0.;
884}
885
886impl From<Gain> for u8 {
887 fn from(val: Gain) -> Self {
888 (val.0.abs() * 2.) as u8
889 }
890}
891
892impl From<u8> for Gain {
893 fn from(val: u8) -> Self {
894 Self(-0.5 * (val as f32))
895 }
896}
897
898impl FromStr for Gain {
899 type Err = <f32 as FromStr>::Err;
900
901 fn from_str(s: &str) -> Result<Self, Self::Err> {
902 Ok(Gain(<f32 as FromStr>::from_str(s)?))
903 }
904}
905pub trait ExtendView {
907 fn extend_with(&mut self, other: Self) -> Result<(), ExtendError>;
908}
909
910#[cfg_attr(feature = "debug", derive(Debug, Error))]
911pub enum ExtendError {
912 #[cfg_attr(feature = "debug", error("the corresponding bases do not align"))]
913 MismatchingBases,
914}
915
916#[derive(Clone, Default)]
918#[cfg_attr(feature = "debug", derive(Debug))]
919pub struct FloatView {
920 pub base: u16,
921 pub data: Vec<f32>,
922}
923
924impl FloatView {
925 pub fn get(&self, addr: u16) -> f32 {
926 self.data[(addr - self.base) as usize]
927 }
928}
929
930impl ExtendView for FloatView {
931 fn extend_with(&mut self, other: Self) -> Result<(), ExtendError> {
932 let expected_start = self.base + (self.data.len() as u16);
934 if other.base != expected_start {
935 return Err(ExtendError::MismatchingBases);
936 }
937
938 self.data.extend(other.data.iter());
939
940 Ok(())
941 }
942}
943
944impl UnaryResponse for FloatView {
945 fn from_packet(mut packet: Bytes) -> Result<Self, ProtocolError> {
946 packet.try_get_u8()?; let base = packet.try_get_u16()?;
948 let data = packet
949 .chunks_exact(4)
950 .map(|x| x.try_into().unwrap())
951 .map(f32::from_le_bytes)
952 .collect();
953
954 Ok(FloatView { base, data })
955 }
956}
957
958#[derive(Clone, Default)]
959pub struct MemoryView {
960 pub base: u16,
961 pub data: Bytes,
962}
963
964impl MemoryView {
965 pub fn read_at(&self, addr: u16, len: u8) -> Option<&'_ [u8]> {
966 if addr < self.base || addr as usize > self.base as usize + self.data.len() {
967 return None;
968 }
969
970 let start = (addr - self.base) as usize;
971 let end = start + len as usize;
972
973 if self.data.len() < end {
974 return None;
975 }
976
977 Some(&self.data[start..end])
978 }
979
980 pub fn read_u8(&self, addr: u16) -> Option<u8> {
981 Some(self.read_at(addr, 1)?[0])
982 }
983
984 pub fn read_u16(&self, addr: u16) -> Option<u16> {
985 Some(u16::from_be_bytes(
986 self.read_at(addr, 2)?.try_into().unwrap(),
987 ))
988 }
989}
990
991impl UnaryResponse for MemoryView {
992 fn from_packet(mut packet: Bytes) -> Result<Self, ProtocolError> {
993 packet.try_get_u8()?; let base = packet.try_get_u16()?;
995
996 Ok(MemoryView { base, data: packet })
997 }
998}
999
1000#[cfg(feature = "debug")]
1001impl fmt::Debug for MemoryView {
1002 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1003 write!(
1004 f,
1005 "MemoryView {{ base: {:04x?}, data: {:02x?} }}",
1006 self.base,
1007 self.data.as_ref()
1008 )
1009 }
1010}
1011
1012impl ExtendView for MemoryView {
1013 fn extend_with(&mut self, other: Self) -> Result<(), ExtendError> {
1014 let expected_start = self.base + (self.data.len() as u16);
1016 if other.base != expected_start {
1017 return Err(ExtendError::MismatchingBases);
1018 }
1019
1020 let mut data: BytesMut = BytesMut::with_capacity(self.data.len() + other.data.len());
1021 data.extend(self.data.iter());
1022 data.extend(other.data.iter());
1023
1024 data.truncate((u16::MAX as usize) - (self.base as usize));
1026
1027 self.data = data.freeze();
1028
1029 Ok(())
1030 }
1031}
1032
1033#[derive(Clone, Default)]
1035#[cfg_attr(feature = "debug", derive(Debug))]
1036pub struct WriteInt;
1037
1038impl WriteInt {
1039 pub const DISABLED: u16 = 1;
1040 pub const ENABLED: u16 = 2;
1041 pub const BYPASSED: u16 = 3;
1042}
1043
1044pub trait FromMemory<T: Sized>
1046where
1047 Self: Sized,
1048{
1049 fn from_memory(device_info: &DeviceInfo, view: &MemoryView) -> Result<Self>;
1050}
1051
1052impl FromMemory<MasterStatus> for MasterStatus
1053where
1054 Self: Sized,
1055{
1056 fn from_memory(device_info: &DeviceInfo, view: &MemoryView) -> Result<Self> {
1057 Ok(Self {
1058 preset: view.read_u8(eeprom::PRESET),
1059 source: view
1060 .read_u8(eeprom::SOURCE)
1061 .or_else(|| view.read_u8(eeprom::SOURCE_ASYNC))
1062 .map(|id| super::Source::from_id(id, device_info)),
1063 volume: view.read_u8(eeprom::MASTER_VOLUME).map(Into::into),
1064 mute: view.read_u8(eeprom::MUTE).map(|x| x == 1),
1065 dirac: if device_info.supports_dirac() {
1066 view.read_u8(eeprom::DIRAC_BYPASS).map(|x| x == 0)
1067 } else {
1068 None
1069 },
1070 })
1071 }
1072}
1073
1074#[cfg(test)]
1075mod test {
1076 use super::*;
1077
1078 #[test]
1079 fn test_addr() {
1080 let tests: &[(&[u8], Addr)] = &[
1081 (
1083 &[0x80, 0x10],
1084 Addr {
1085 extra_bit: true,
1086 val: 0x10,
1087 len: 2,
1088 },
1089 ),
1090 (
1092 &[0x80, 0x10, 0x00],
1093 Addr {
1094 extra_bit: true,
1095 val: 0x10_00,
1096 len: 3,
1097 },
1098 ),
1099 (
1100 &[0x8F, 0x10],
1101 Addr {
1102 extra_bit: true,
1103 val: 0xF10,
1104 len: 2,
1105 },
1106 ),
1107 (
1108 &[0x8F, 0x10, 0x00],
1109 Addr {
1110 extra_bit: true,
1111 val: 0x0F_10_00,
1112 len: 3,
1113 },
1114 ),
1115 ];
1116
1117 for (bytes, addr) in tests {
1118 let data = Bytes::from_static(bytes);
1119 let parsed = Addr::read(&mut data.clone(), data.len() as _).unwrap();
1120 assert_eq!(addr, &parsed);
1121
1122 let mut written_bytes = BytesMut::new();
1123 addr.write(&mut written_bytes);
1124 assert_eq!(&written_bytes, bytes);
1125 }
1126 }
1127
1128 #[test]
1129 fn test_read_reg() {
1130 let cmd = Commands::ReadMemory {
1131 addr: 0xffda,
1132 size: 4,
1133 };
1134
1135 let mut req_packet = cmd.to_bytes();
1136 assert_eq!(req_packet.get_u8(), 0x05);
1137 assert_eq!(req_packet.get_u16(), 0xffda);
1138 assert_eq!(req_packet.get_u8(), 4);
1139 assert_eq!(req_packet.remaining(), 0);
1140
1141 let response = Bytes::from_static(&[0x5, 0xff, 0xda, 0x1, 0x2, 0x3, 0x4, 0x0]);
1142 let memory = Responses::from_bytes(response)
1143 .ok()
1144 .unwrap()
1145 .into_memory_view()
1146 .ok()
1147 .unwrap();
1148 let data = memory.read_at(0xffda, 4);
1149
1150 assert_eq!(data.unwrap(), &[0x1, 0x2, 0x3, 0x4]);
1151 assert_eq!(memory.read_u16(0xFFDA), Some(0x0102));
1152 }
1153
1154 #[test]
1155 fn test_master_status() {
1156 let cmd = Commands::ReadMemory {
1157 addr: 0xffd8,
1158 size: 9,
1159 };
1160
1161 let mut req_packet = cmd.to_bytes();
1162 assert_eq!(req_packet.get_u8(), 0x05);
1163 assert_eq!(req_packet.get_u16(), 0xffd8);
1164 assert_eq!(req_packet.get_u8(), 9);
1165 assert_eq!(req_packet.remaining(), 0);
1166
1167 let response = Bytes::from_static(&[
1168 0x5, 0xff, 0xd8, 0x0, 0x1, 0x4f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1169 ]);
1170 let memory = Responses::from_bytes(response)
1171 .ok()
1172 .unwrap()
1173 .into_memory_view()
1174 .ok()
1175 .unwrap();
1176
1177 let device_info = DeviceInfo {
1178 hw_id: 10,
1179 dsp_version: 100,
1180 serial: 0,
1181 };
1182 let status = MasterStatus::from_memory(&device_info, &memory).unwrap();
1183 assert!(status.eq(&MasterStatus {
1184 preset: Some(0),
1185 source: Some(crate::Source::Toslink),
1186 volume: Some(Gain(-39.5)),
1187 mute: Some(false),
1188 dirac: None,
1189 }));
1190 }
1191
1192 #[test]
1193 fn test_combine() {
1194 let mut f1 = FloatView {
1195 base: 0,
1196 data: (0u16..10).map(|x| x.into()).collect(),
1197 };
1198
1199 let f2 = FloatView {
1200 base: 10,
1201 data: (10u16..20).map(|x| x.into()).collect(),
1202 };
1203
1204 f1.extend_with(f2).ok().unwrap();
1205 assert_eq!(f1.base, 0);
1206 assert_eq!(f1.data.len(), 20);
1207 assert!(f1
1208 .data
1209 .into_iter()
1210 .eq((0u16..20).into_iter().map(|x| -> f32 { x.into() })));
1211
1212 let mut m1 = MemoryView {
1213 base: 0,
1214 data: (0u8..10).collect(),
1215 };
1216
1217 let m2 = MemoryView {
1218 base: 10,
1219 data: (10u8..20).collect(),
1220 };
1221
1222 m1.extend_with(m2).ok().unwrap();
1223 assert_eq!(m1.base, 0);
1224 assert_eq!(m1.data.len(), 20);
1225 assert!(m1.data.into_iter().eq((0u8..20).into_iter()));
1226 }
1227}