jaylink/
capabilities.rs

1#![allow(non_upper_case_globals)]
2
3use std::fmt;
4
5enum_and_set!(
6    /// List of capabilities that may be advertised by a probe.
7    ///
8    /// Not many of these are actually used, and a lot of these have unknown meaning.
9    #[non_exhaustive]
10    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
11    pub enum Capability {
12        Reserved0 = 0,  // Reserved, seems to be always set
13        GetHwVersion = 1,
14        WriteDcc = 2,
15        AdaptiveClocking = 3,
16        ReadConfig = 4,
17        WriteConfig = 5,
18        Trace = 6,
19        WriteMem = 7,
20        ReadMem = 8,
21        SpeedInfo = 9,
22        ExecCode = 10,
23        GetMaxBlockSize = 11,
24        GetHwInfo = 12,
25        SetKsPower = 13,
26        ResetStopTimed = 14,
27        // 15 = Reserved, seems to never be set
28        MeasureRtckReact = 16,
29        SelectIf = 17,
30        RwMemArm79 = 18,
31        GetCounters = 19,
32        ReadDcc = 20,
33        GetCpuCaps = 21,
34        ExecCpuCmd = 22,
35        Swo = 23,
36        WriteDccEx = 24,
37        UpdateFirmwareEx = 25,
38        FileIo = 26,
39        Register = 27,
40        Indicators = 28,
41        TestNetSpeed = 29,
42        RawTrace = 30,
43        // For the legacy capabilities, bit 31 is documented as reserved, but it must be
44        // GET_CAPS_EX, since there'd be no other way to know if GET_CAPS_EX is supported.
45        GetCapsEx = 31,
46
47        // Extended capabilities
48
49        HwJtagWrite = 32,
50        Com = 33,
51    }
52
53    flags CapabilityFlags: u128;
54);
55
56impl CapabilityFlags {
57    fn from_capability(cap: Capability) -> Self {
58        Self::from_bits(1 << cap as u32).unwrap()
59    }
60}
61
62/// A set of capabilities advertised by a probe.
63#[derive(Copy, Clone, PartialEq, Eq)]
64pub struct Capabilities(CapabilityFlags);
65
66impl Capabilities {
67    /// Creates a `Capabilities` instance from 32 raw bits.
68    pub(crate) fn from_raw_legacy(raw: u32) -> Self {
69        let mut capabilities = CapabilityFlags::from_bits_truncate(u128::from(raw));
70        if capabilities.bits() != u128::from(raw) {
71            log::debug!(
72                "unknown capability bits: 0x{:08X} truncated to 0x{:08X} ({:?})",
73                raw,
74                capabilities.bits(),
75                capabilities,
76            );
77        }
78        // Hide reserved bits from user-facing output.
79        capabilities.remove(CapabilityFlags::Reserved0);
80        Self(capabilities)
81    }
82
83    /// Creates a `Capabilities` instance from a 256-bit bitset.
84    pub(crate) fn from_raw_ex(raw: [u8; 32]) -> Self {
85        if raw[16..] != [0; 16] {
86            log::debug!(
87                "unknown ext. capability bits: dropping high 16 bytes {:02X?}",
88                &raw[16..],
89            );
90        }
91        let mut bytes = [0; 16];
92        bytes.copy_from_slice(&raw[..16]);
93        let raw = u128::from_le_bytes(bytes);
94        let mut capabilities = CapabilityFlags::from_bits_truncate(raw);
95        if capabilities.bits() != raw {
96            log::debug!(
97                "unknown ext. capability bits: 0x{:08X} truncated to 0x{:08X} ({:?})",
98                raw,
99                capabilities.bits(),
100                capabilities,
101            );
102        }
103        // Hide reserved bits from user-facing output.
104        capabilities.remove(CapabilityFlags::Reserved0);
105        Self(capabilities)
106    }
107
108    /// Determines whether `self` contains capability `cap`.
109    pub fn contains(&self, cap: Capability) -> bool {
110        self.0.contains(CapabilityFlags::from_capability(cap))
111    }
112
113    /// Determines whether `self` contains all capabilities in `caps`.
114    pub fn contains_all(&self, caps: Capabilities) -> bool {
115        self.0.contains(caps.0)
116    }
117}
118
119impl fmt::Debug for Capabilities {
120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121        self.0.fmt(f)
122    }
123}