sdmmc_core/command/class/class8/acmd53/
arg.rs

1use crate::lib_bitfield;
2use crate::result::{Error, Result};
3
4mod sssf;
5
6pub use sssf::*;
7
8lib_bitfield! {
9    /// Argumentument for CMD5.
10    pub Argument(u32): u8 {
11        raw_sp: 31, 24;
12        raw_spsp1: 23, 16;
13        raw_spsp0: 15, 8;
14        raw_sssf: 7, 0;
15    }
16}
17
18impl Argument {
19    /// Represents the byte length of the [Argument].
20    pub const LEN: usize = 4;
21    /// Represents the raw default value of the [Argument].
22    pub const DEFAULT: u32 = 1;
23
24    /// Creates a new [Argument].
25    pub const fn new() -> Self {
26        Self(Self::DEFAULT)
27    }
28
29    /// Gets the `security protocol` field of the [Argument].
30    pub const fn sp(&self) -> u8 {
31        self.raw_sp()
32    }
33
34    /// Sets the `security protocol` field of the [Argument].
35    pub fn set_sp(&mut self, val: u8) {
36        self.set_raw_sp(val as u32);
37    }
38
39    /// Gets the `security protocol specific 1` field of the [Argument].
40    pub const fn spsp1(&self) -> u8 {
41        self.raw_spsp1()
42    }
43
44    /// Sets the `security protocol specific 1` field of the [Argument].
45    pub fn set_spsp1(&mut self, val: u8) {
46        self.set_raw_spsp1(val as u32);
47    }
48
49    /// Gets the `security protocol specific 0` field of the [Argument].
50    pub const fn spsp0(&self) -> u8 {
51        self.raw_spsp0()
52    }
53
54    /// Sets the `security protocol specific 0` field of the [Argument].
55    pub fn set_spsp0(&mut self, val: u8) {
56        self.set_raw_spsp0(val as u32);
57    }
58
59    /// Gets the `SD security specific field` field of the [Argument].
60    pub const fn sssf(&self) -> Result<SdSecuritySpecificField> {
61        SdSecuritySpecificField::from_raw(self.raw_sssf())
62    }
63
64    /// Sets the `SD security specific field` field of the [Argument].
65    pub fn set_sssf(&mut self, val: SdSecuritySpecificField) {
66        self.set_raw_sssf(val.into_raw() as u32);
67    }
68
69    /// Attempts to convert a [`u32`] into an [Argument].
70    pub const fn try_from_bits(val: u32) -> Result<Self> {
71        match Self(val) {
72            acmd if acmd.sssf().is_err() => Err(Error::invalid_field_variant(
73                "command::argument::sssf",
74                acmd.raw_sssf() as usize,
75            )),
76            acmd => Ok(acmd),
77        }
78    }
79
80    /// Converts the [Argument] into a byte array.
81    pub const fn bytes(&self) -> [u8; Self::LEN] {
82        self.0.to_be_bytes()
83    }
84
85    /// Attempts to convert a byte slice into an [Argument].
86    pub const fn try_from_bytes(val: &[u8]) -> Result<Self> {
87        match val.len() {
88            len if len < Self::LEN => Err(Error::invalid_length(len, Self::LEN)),
89            _ => Self::try_from_bits(u32::from_be_bytes([val[0], val[1], val[2], val[3]])),
90        }
91    }
92}
93
94impl Default for Argument {
95    fn default() -> Self {
96        Self::new()
97    }
98}
99
100impl TryFrom<u32> for Argument {
101    type Error = Error;
102
103    fn try_from(val: u32) -> Result<Self> {
104        Self::try_from_bits(val)
105    }
106}
107
108impl From<Argument> for u32 {
109    fn from(val: Argument) -> Self {
110        val.bits()
111    }
112}
113
114impl From<Argument> for [u8; Argument::LEN] {
115    fn from(val: Argument) -> Self {
116        val.bytes()
117    }
118}
119
120impl TryFrom<&[u8]> for Argument {
121    type Error = Error;
122
123    fn try_from(val: &[u8]) -> Result<Self> {
124        Self::try_from_bytes(val)
125    }
126}
127
128impl<const N: usize> TryFrom<&[u8; N]> for Argument {
129    type Error = Error;
130
131    fn try_from(val: &[u8; N]) -> Result<Self> {
132        Self::try_from_bytes(val.as_ref())
133    }
134}
135
136impl<const N: usize> TryFrom<[u8; N]> for Argument {
137    type Error = Error;
138
139    fn try_from(val: [u8; N]) -> Result<Self> {
140        Self::try_from_bytes(val.as_ref())
141    }
142}
143
144#[cfg(test)]
145mod tests {
146    use super::*;
147    use crate::test_field;
148
149    #[test]
150    fn test_fields() {
151        let new_sssf = SdSecuritySpecificField::new();
152        let new_sp = 0;
153        let new_spsp1 = 0;
154        let new_spsp0 = 0;
155
156        // test non-sssf fields with a fixed, valid sssf variant
157        (8..=u32::BITS)
158            .map(|r| (((1u64 << r) - 1) as u32) | 1)
159            .for_each(|raw_arg| {
160                let raw = raw_arg.to_be_bytes();
161                let exp_sp = ((raw_arg & 0xff00_0000) >> 24) as u8;
162                let exp_spsp1 = ((raw_arg & 0xff_0000) >> 16) as u8;
163                let exp_spsp0 = ((raw_arg & 0xff00) >> 8) as u8;
164                let raw_sssf = (raw_arg & 0xff) as u8;
165
166                match Argument::try_from_bits(raw_arg) {
167                    Ok(mut exp_arg) => {
168                        let exp_sssf = SdSecuritySpecificField::from_raw(raw_sssf).unwrap();
169
170                        assert_eq!(Argument::try_from_bits(raw_arg), Ok(exp_arg));
171                        assert_eq!(Argument::try_from_bytes(&raw), Ok(exp_arg));
172                        assert_eq!(Argument::try_from(raw_arg), Ok(exp_arg));
173                        assert_eq!(Argument::try_from(raw), Ok(exp_arg));
174                        assert_eq!(Argument::try_from(&raw), Ok(exp_arg));
175
176                        assert_eq!(exp_arg.sp(), exp_sp);
177
178                        exp_arg.set_sp(new_sp);
179                        assert_eq!(exp_arg.sp(), new_sp);
180
181                        exp_arg.set_sp(exp_sp);
182                        assert_eq!(exp_arg.sp(), exp_sp);
183
184                        assert_eq!(exp_arg.spsp1(), exp_spsp1);
185
186                        exp_arg.set_spsp1(new_spsp1);
187                        assert_eq!(exp_arg.spsp1(), new_spsp1);
188
189                        exp_arg.set_spsp1(exp_spsp1);
190                        assert_eq!(exp_arg.spsp1(), exp_spsp1);
191
192                        assert_eq!(exp_arg.spsp0(), exp_spsp0);
193
194                        exp_arg.set_spsp0(new_spsp0);
195                        assert_eq!(exp_arg.spsp0(), new_spsp0);
196
197                        exp_arg.set_spsp0(exp_spsp0);
198                        assert_eq!(exp_arg.spsp0(), exp_spsp0);
199
200                        assert_eq!(exp_arg.spsp0(), exp_spsp0);
201
202                        exp_arg.set_sssf(new_sssf);
203                        assert_eq!(exp_arg.sssf(), Ok(new_sssf));
204
205                        exp_arg.set_sssf(exp_sssf);
206                        assert_eq!(exp_arg.sssf(), Ok(exp_sssf));
207                    }
208                    Err(err) => {
209                        let exp_err = Error::invalid_field_variant(
210                            "command::argument::sssf",
211                            raw_sssf as usize,
212                        );
213                        assert_eq!(err, exp_err);
214
215                        assert_eq!(Argument::try_from_bits(raw_arg), Err(exp_err));
216                        assert_eq!(Argument::try_from_bytes(&raw), Err(exp_err));
217                        assert_eq!(Argument::try_from(raw_arg), Err(exp_err));
218                        assert_eq!(Argument::try_from(raw), Err(exp_err));
219                        assert_eq!(Argument::try_from(&raw), Err(exp_err));
220                    }
221                }
222            });
223
224        // test sssf variants
225        (1..=8u32)
226            .map(|r| ((1u64 << r) - 1) as u32)
227            .for_each(|raw_arg| {
228                let raw = raw_arg.to_be_bytes();
229                let raw_sssf = (raw_arg & 0xff) as u8;
230
231                match Argument::try_from_bits(raw_arg) {
232                    Ok(mut exp_arg) => {
233                        let exp_sssf = SdSecuritySpecificField::from_raw(raw_sssf).unwrap();
234
235                        assert_eq!(Argument::try_from_bits(raw_arg), Ok(exp_arg));
236                        assert_eq!(Argument::try_from_bytes(&raw), Ok(exp_arg));
237                        assert_eq!(Argument::try_from(raw_arg), Ok(exp_arg));
238                        assert_eq!(Argument::try_from(raw), Ok(exp_arg));
239                        assert_eq!(Argument::try_from(&raw), Ok(exp_arg));
240
241                        exp_arg.set_sssf(new_sssf);
242                        assert_eq!(exp_arg.sssf(), Ok(new_sssf));
243
244                        exp_arg.set_sssf(exp_sssf);
245                        assert_eq!(exp_arg.sssf(), Ok(exp_sssf));
246                    }
247                    Err(err) => {
248                        let exp_err = Error::invalid_field_variant(
249                            "command::argument::sssf",
250                            raw_sssf as usize,
251                        );
252                        assert_eq!(err, exp_err);
253
254                        assert_eq!(Argument::try_from_bits(raw_arg), Err(exp_err));
255                        assert_eq!(Argument::try_from_bytes(&raw), Err(exp_err));
256                        assert_eq!(Argument::try_from(raw_arg), Err(exp_err));
257                        assert_eq!(Argument::try_from(raw), Err(exp_err));
258                        assert_eq!(Argument::try_from(&raw), Err(exp_err));
259                    }
260                }
261            });
262    }
263}