Skip to content

Commit 69e1754

Browse files
authored
Merge pull request #224 from robamu/cid-register
Restructuring, CID support
2 parents 4d842eb + 8952e12 commit 69e1754

6 files changed

Lines changed: 2140 additions & 2015 deletions

File tree

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ pub use crate::filesystem::{
111111
use filesystem::DirectoryInfo;
112112

113113
#[doc(inline)]
114-
pub use crate::sdcard::Error as SdCardError;
114+
pub use crate::sdcard::spi::Error as SdCardError;
115115

116116
#[doc(inline)]
117-
pub use crate::sdcard::SdCard;
117+
pub use crate::sdcard::spi::SdCard;
118118

119119
mod volume_mgr;
120120
#[doc(inline)]

src/sdcard/cid.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
//! # CID support module
2+
3+
use arbitrary_int::{u7, u12, u40};
4+
5+
use crate::sdcard::crc7;
6+
7+
/// Checksum is invalid.
8+
#[derive(Debug, thiserror::Error)]
9+
#[error("checksum is invalid")]
10+
pub struct ChecksumInvalidError;
11+
12+
/// Card IDentification (CID) register structure.
13+
#[bitbybit::bitfield(u128, debug, defmt_fields(feature = "defmt-log"))]
14+
pub struct Cid {
15+
/// MID.
16+
#[bits(120..=127, rw)]
17+
manufacturer_id: u8,
18+
/// OID.
19+
#[bits(104..=119, rw)]
20+
oem_id: u16,
21+
/// PVM.
22+
#[bits(64..=103, rw)]
23+
product_name_raw: u40,
24+
/// PSN.
25+
#[bits(24..=55, rw)]
26+
product_serial_number: u32,
27+
/// MDT.
28+
#[bits(8..=19, rw)]
29+
manufacturing_date: u12,
30+
/// CRC.
31+
#[bits(1..=7, rw)]
32+
crc7: u7,
33+
}
34+
35+
impl Cid {
36+
/// Construct a [Cid] from a raw byte slice with 16 bytes.
37+
///
38+
/// Also verifies the CRC7 checksum.
39+
pub fn new(raw: &[u8; 16]) -> Result<Cid, ChecksumInvalidError> {
40+
let cid = Cid::new_with_raw_value(u128::from_be_bytes(*raw));
41+
if !cid.verify_crc7() {
42+
return Err(ChecksumInvalidError);
43+
}
44+
Ok(cid)
45+
}
46+
47+
/// Construct a [Cid] without verifying the checksum.
48+
pub fn new_unchecked(raw: &[u8; 16]) -> Cid {
49+
Cid::new_with_raw_value(u128::from_be_bytes(*raw))
50+
}
51+
52+
/// Verify CRC7 checksum.
53+
pub fn verify_crc7(&self) -> bool {
54+
let raw_bytes = self.raw_value().to_be_bytes();
55+
let calculated = crc7(&raw_bytes[0..15]);
56+
self.crc7().value() == calculated
57+
}
58+
59+
/// Product name as a byte array.
60+
#[inline]
61+
pub fn product_name_bytes(&self) -> [u8; 5] {
62+
self.product_name_raw().to_be_bytes()
63+
}
64+
}
65+
66+
#[cfg(test)]
67+
mod tests {
68+
use super::*;
69+
70+
#[test]
71+
fn basic_test() {
72+
// CID retrieved from a real SD card.
73+
let raw_cid = [
74+
0x12, 0x34, 0x56, 0x41, 0x53, 0x54, 0x43, 0x0, 0x20, 0x0, 0x0, 0xc, 0xef, 0x1, 0x65,
75+
0xef,
76+
];
77+
// This also verifies the checksum.
78+
let cid = Cid::new(&raw_cid);
79+
assert!(cid.is_ok());
80+
81+
let cid = cid.unwrap();
82+
// https://www.bahjeez.com/sd-card-manufacturer-ids/: Patriot.
83+
assert_eq!(cid.manufacturer_id(), 0x12);
84+
assert_eq!(cid.oem_id(), 0x3456);
85+
86+
let product_name_raw = cid.product_name_bytes();
87+
let product_name = core::str::from_utf8(&product_name_raw).unwrap();
88+
assert_eq!(product_name, "ASTC\0");
89+
}
90+
91+
#[test]
92+
fn basic_test_unchecked() {
93+
// CID retrieved from a real SD card.
94+
let raw_cid = [
95+
0x12, 0x34, 0x56, 0x41, 0x53, 0x54, 0x43, 0x0, 0x20, 0x0, 0x0, 0xc, 0xef, 0x1, 0x65,
96+
0x00,
97+
];
98+
// Invalid checksum ignored.
99+
let cid = Cid::new_unchecked(&raw_cid);
100+
assert!(!cid.verify_crc7());
101+
102+
// https://www.bahjeez.com/sd-card-manufacturer-ids/: Patriot.
103+
assert_eq!(cid.manufacturer_id(), 0x12);
104+
assert_eq!(cid.oem_id(), 0x3456);
105+
106+
let product_name_raw = cid.product_name_bytes();
107+
let product_name = core::str::from_utf8(&product_name_raw).unwrap();
108+
assert_eq!(product_name, "ASTC\0");
109+
}
110+
}

0 commit comments

Comments
 (0)