1pub use sdio_host2::{RawResponse, ResponseType};
2
3use crate::error::{CardError, Error, ErrorContext, Phase};
4
5#[derive(Debug, Clone, Copy)]
10#[non_exhaustive]
11pub enum Response {
12 Empty,
17 R1(R1Response),
18 R1b(R1Response),
19 R2([u8; 16]),
20 R3(OcrResponse),
21 R4(SdioOcrResponse),
22 R5(SdioRwResponse),
23 R6(RcaResponse),
24 R7(IfCondResponse),
25}
26
27impl Response {
28 pub fn to_raw_response(self, expected: ResponseType) -> RawResponse {
31 let mut words = [0; 4];
32 match self {
33 Self::Empty => {}
34 Self::R1(resp) | Self::R1b(resp) => words[0] = resp.raw,
35 Self::R2(bytes) => {
36 for (word, chunk) in words.iter_mut().zip(bytes.chunks_exact(4)) {
37 *word = u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
38 }
39 }
40 Self::R3(resp) => words[0] = resp.raw,
41 Self::R4(resp) => words[0] = resp.raw,
42 Self::R5(resp) => words[0] = resp.raw,
43 Self::R6(resp) => words[0] = resp.raw,
44 Self::R7(resp) => words[0] = resp.raw,
45 }
46 RawResponse::new(expected, words)
47 }
48}
49
50pub fn response_from_raw(raw: RawResponse) -> Result<Response, Error> {
52 Ok(match raw.ty {
53 ResponseType::None => Response::Empty,
54 ResponseType::R1 => Response::R1(R1Response::from_native_raw(raw.words[0])?),
55 ResponseType::R1b => Response::R1b(R1Response::from_native_raw(raw.words[0])?),
56 ResponseType::R2 => {
57 let mut bytes = [0; 16];
58 for (chunk, word) in bytes.chunks_exact_mut(4).zip(raw.words) {
59 chunk.copy_from_slice(&word.to_be_bytes());
60 }
61 Response::R2(bytes)
62 }
63 ResponseType::R3 => Response::R3(OcrResponse::from_raw(raw.words[0])),
64 ResponseType::R4 => Response::R4(SdioOcrResponse::from_raw(raw.words[0])),
65 ResponseType::R5 => Response::R5(SdioRwResponse::from_raw(raw.words[0])),
66 ResponseType::R6 => Response::R6(RcaResponse::from_raw(raw.words[0])),
67 ResponseType::R7 => Response::R7(IfCondResponse::from_raw(raw.words[0])),
68 _ => return Err(Error::UnsupportedCommand),
69 })
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub struct R1Response {
75 pub raw: u32,
76}
77
78impl R1Response {
79 pub fn from_native_raw(raw: u32) -> Result<Self, Error> {
111 let err_bits = raw & R1_NATIVE_ERROR_MASK;
112 if err_bits != 0 {
113 return Err(Error::CardError(decode_native_card_error(err_bits)));
114 }
115 Ok(Self { raw })
116 }
117
118 pub fn from_spi_byte(byte: u8) -> Result<Self, Error> {
131 if byte & 0x80 != 0 {
132 return Err(Error::BadResponse(ErrorContext::new(Phase::ResponseWait)));
133 }
134 Ok(Self { raw: byte as u32 })
135 }
136
137 pub fn spi_card_error(&self) -> Option<CardError> {
144 let bits = (self.raw as u8) & 0b0111_1110;
145 if bits == 0 {
146 None
147 } else {
148 Some(decode_spi_card_error(bits))
149 }
150 }
151
152 pub fn idle(&self) -> bool {
154 self.raw & (1 << 0) != 0
155 }
156
157 pub fn erase_reset(&self) -> bool {
159 self.raw & (1 << 1) != 0
160 }
161
162 pub fn illegal_command(&self) -> bool {
164 self.raw & (1 << 2) != 0
165 }
166
167 pub fn command_crc_failed(&self) -> bool {
169 self.raw & (1 << 3) != 0
170 }
171
172 pub fn current_state(&self) -> CardState {
177 match ((self.raw >> 9) & 0xF) as u8 {
178 0 => CardState::Idle,
179 1 => CardState::Ready,
180 2 => CardState::Identification,
181 3 => CardState::Standby,
182 4 => CardState::Transfer,
183 5 => CardState::SendingData,
184 6 => CardState::ReceiveData,
185 7 => CardState::Programming,
186 8 => CardState::Disconnect,
187 other => CardState::Reserved(other),
188 }
189 }
190
191 pub fn card_is_locked(&self) -> bool {
193 self.raw & (1 << 19) != 0
194 }
195
196 pub fn ready_for_data(&self) -> bool {
202 self.raw & (1 << 8) != 0
203 }
204
205 pub fn switch_error(&self) -> bool {
210 self.raw & (1 << 7) != 0
211 }
212}
213
214#[derive(Debug, Clone, Copy, PartialEq, Eq)]
219#[non_exhaustive]
220pub enum CardState {
221 Idle,
222 Ready,
223 Identification,
224 Standby,
225 Transfer,
226 SendingData,
227 ReceiveData,
228 Programming,
229 Disconnect,
230 Reserved(u8),
231}
232
233#[derive(Debug, Clone, Copy)]
235pub struct OcrResponse {
236 pub raw: u32,
237}
238
239impl OcrResponse {
240 pub fn from_raw(raw: u32) -> Self {
241 Self { raw }
242 }
243
244 pub fn card_powered_up(&self) -> bool {
246 self.raw & (1 << 31) != 0
247 }
248
249 pub fn ccs(&self) -> bool {
251 self.raw & (1 << 30) != 0
252 }
253
254 pub fn voltage_window(&self) -> u32 {
256 self.raw & 0x00FF_FF00
257 }
258
259 pub fn vdd_35_36(&self) -> bool {
261 self.raw & (1 << 23) != 0
262 }
263
264 pub fn vdd_34_35(&self) -> bool {
266 self.raw & (1 << 22) != 0
267 }
268
269 pub fn vdd_33_34(&self) -> bool {
271 self.raw & (1 << 21) != 0
272 }
273
274 pub fn vdd_32_33(&self) -> bool {
276 self.raw & (1 << 20) != 0
277 }
278
279 pub fn supports_2v7_to_3v6(&self) -> bool {
281 self.raw & 0x00FF_8000 != 0
282 }
283
284 pub fn uhs2(&self) -> bool {
286 self.raw & (1 << 29) != 0
287 }
288
289 pub fn s18a(&self) -> bool {
291 self.raw & (1 << 24) != 0
292 }
293}
294
295#[derive(Debug, Clone, Copy)]
297pub struct RcaResponse {
298 pub raw: u32,
299}
300
301impl RcaResponse {
302 pub fn from_raw(raw: u32) -> Self {
303 Self { raw }
304 }
305
306 pub fn rca(&self) -> u16 {
308 ((self.raw >> 16) & 0xFFFF) as u16
309 }
310
311 pub fn status(&self) -> u16 {
313 (self.raw & 0xFFFF) as u16
314 }
315}
316
317#[derive(Debug, Clone, Copy)]
319pub struct IfCondResponse {
320 pub raw: u32,
321}
322
323impl IfCondResponse {
324 pub fn from_raw(raw: u32) -> Self {
325 Self { raw }
326 }
327
328 pub fn voltage(&self) -> u8 {
330 ((self.raw >> 8) & 0xF) as u8
331 }
332
333 pub fn check_pattern(&self) -> u8 {
335 (self.raw & 0xFF) as u8
336 }
337
338 pub fn verify(&self, voltage: u8, pattern: u8) -> bool {
340 self.voltage() == voltage && self.check_pattern() == pattern
341 }
342}
343
344#[derive(Debug, Clone, Copy)]
347pub struct CsdResponse {
348 pub raw: [u8; 16],
349}
350
351impl CsdResponse {
352 pub fn from_raw(raw: [u8; 16]) -> Self {
353 Self { raw }
354 }
355
356 pub fn version(&self) -> u8 {
358 (self.raw[0] >> 6) & 0x03
359 }
360
361 pub fn capacity_blocks(&self) -> Option<u64> {
366 match self.version() {
367 0 => Some(self.csd_v1_capacity_blocks()),
368 1 => Some(self.csd_v2_capacity_blocks()),
369 _ => None,
370 }
371 }
372
373 fn csd_v1_capacity_blocks(&self) -> u64 {
374 let read_bl_len = (self.raw[5] & 0x0F) as u32;
380 let c_size = (((self.raw[6] & 0x03) as u32) << 10)
381 | ((self.raw[7] as u32) << 2)
382 | ((self.raw[8] as u32) >> 6);
383 let c_size_mult = (((self.raw[9] & 0x03) as u32) << 1) | ((self.raw[10] as u32) >> 7);
384 let mult = 1u64 << (c_size_mult + 2);
385 let block_len = 1u64 << read_bl_len;
386 let bytes = (c_size as u64 + 1) * mult * block_len;
387 bytes / 512
388 }
389
390 fn csd_v2_capacity_blocks(&self) -> u64 {
391 let c_size = (((self.raw[7] & 0x3F) as u32) << 16)
396 | ((self.raw[8] as u32) << 8)
397 | (self.raw[9] as u32);
398 (c_size as u64 + 1) * 1024
399 }
400}
401
402#[derive(Debug, Clone, Copy)]
408pub struct CidResponse {
409 pub raw: [u8; 16],
410}
411
412impl CidResponse {
413 pub fn from_raw(raw: [u8; 16]) -> Self {
414 Self { raw }
415 }
416
417 pub fn manufacturer_id(&self) -> u8 {
419 self.raw[0]
420 }
421
422 pub fn oem_id(&self) -> [u8; 2] {
426 [self.raw[1], self.raw[2]]
427 }
428
429 pub fn product_name(&self) -> [u8; 5] {
431 [
432 self.raw[3],
433 self.raw[4],
434 self.raw[5],
435 self.raw[6],
436 self.raw[7],
437 ]
438 }
439
440 pub fn product_revision(&self) -> (u8, u8) {
442 (self.raw[8] >> 4, self.raw[8] & 0x0F)
443 }
444
445 pub fn serial_number(&self) -> u32 {
447 u32::from_be_bytes([self.raw[9], self.raw[10], self.raw[11], self.raw[12]])
448 }
449
450 pub fn manufacture_date(&self) -> (u16, u8) {
456 let year = ((self.raw[13] & 0x0F) << 4) | (self.raw[14] >> 4);
457 let month = self.raw[14] & 0x0F;
458 (2000 + year as u16, month)
459 }
460}
461
462#[derive(Debug, Clone, Copy)]
468pub struct SwitchStatus {
469 pub raw: [u8; 64],
470}
471
472impl SwitchStatus {
473 pub fn from_raw(raw: [u8; 64]) -> Self {
474 Self { raw }
475 }
476
477 pub fn selected_function(&self, group: u8) -> u8 {
484 match group {
485 1 => self.raw[16] & 0x0F,
486 2 => self.raw[16] >> 4,
487 3 => self.raw[15] & 0x0F,
488 4 => self.raw[15] >> 4,
489 5 => self.raw[14] & 0x0F,
490 6 => self.raw[14] >> 4,
491 _ => 0xF,
492 }
493 }
494
495 pub fn high_speed_active(&self) -> bool {
497 self.selected_function(1) == 1
498 }
499
500 pub fn access_mode_supported(&self, function: u8) -> bool {
505 function < 8 && (self.raw[13] & (1 << function)) != 0
506 }
507}
508
509#[derive(Debug, Clone, Copy)]
511pub struct SdioOcrResponse {
512 pub raw: u32,
513}
514
515impl SdioOcrResponse {
516 pub fn from_raw(raw: u32) -> Self {
517 Self { raw }
518 }
519
520 pub fn io_functions(&self) -> u8 {
522 ((self.raw >> 28) & 0x7) as u8
523 }
524
525 pub fn memory_present(&self) -> bool {
527 self.raw & (1 << 27) != 0
528 }
529
530 pub fn io_ready(&self) -> bool {
532 self.raw & (1 << 31) != 0
533 }
534}
535
536#[derive(Debug, Clone, Copy)]
538pub struct SdioRwResponse {
539 pub raw: u32,
540}
541
542impl SdioRwResponse {
543 pub fn from_raw(raw: u32) -> Self {
544 Self { raw }
545 }
546
547 pub fn data(&self) -> u8 {
549 (self.raw & 0xFF) as u8
550 }
551
552 pub fn flags(&self) -> u8 {
554 ((self.raw >> 8) & 0xFF) as u8
555 }
556}
557
558const R1_NATIVE_ERROR_MASK: u32 = 0xFFF8_0000;
563
564const R1_BIT_OUT_OF_RANGE: u32 = 1 << 31;
565const R1_BIT_ADDRESS_ERROR: u32 = 1 << 30;
566const R1_BIT_BLOCK_LEN_ERROR: u32 = 1 << 29;
567const R1_BIT_ERASE_SEQ_ERROR: u32 = 1 << 28;
568const R1_BIT_ERASE_PARAM: u32 = 1 << 27;
569const R1_BIT_WP_VIOLATION: u32 = 1 << 26;
570const R1_BIT_CARD_IS_LOCKED: u32 = 1 << 25;
571const R1_BIT_LOCK_UNLOCK_FAILED: u32 = 1 << 24;
572const R1_BIT_COM_CRC_ERROR: u32 = 1 << 23;
573const R1_BIT_ILLEGAL_COMMAND: u32 = 1 << 22;
574const R1_BIT_CARD_ECC_FAILED: u32 = 1 << 21;
575const R1_BIT_CC_ERROR: u32 = 1 << 20;
576const R1_BIT_ERROR: u32 = 1 << 19;
577
578fn decode_spi_card_error(bits: u8) -> CardError {
592 if bits & 0b0000_1000 != 0 {
593 CardError::CommandCrcFailed
594 } else if bits & 0b0000_0100 != 0 {
595 CardError::IllegalCommand
596 } else if bits & 0b0010_0000 != 0 {
597 CardError::AddressError
598 } else if bits & 0b0100_0000 != 0 {
599 CardError::BlockLenError
601 } else if bits & (0b0001_0000 | 0b0000_0010) != 0 {
602 CardError::EraseSequence
604 } else {
605 CardError::Unknown(bits as u32)
606 }
607}
608
609fn decode_native_card_error(err_bits: u32) -> CardError {
619 if err_bits & R1_BIT_OUT_OF_RANGE != 0 {
620 CardError::OutOfRange
621 } else if err_bits & R1_BIT_ADDRESS_ERROR != 0 {
622 CardError::AddressError
623 } else if err_bits & R1_BIT_BLOCK_LEN_ERROR != 0 {
624 CardError::BlockLenError
625 } else if err_bits & R1_BIT_WP_VIOLATION != 0 {
626 CardError::WriteProtect
627 } else if err_bits & R1_BIT_COM_CRC_ERROR != 0 {
628 CardError::CommandCrcFailed
629 } else if err_bits & R1_BIT_ILLEGAL_COMMAND != 0 {
630 CardError::IllegalCommand
631 } else if err_bits & R1_BIT_CARD_ECC_FAILED != 0 {
632 CardError::CardEccFailed
633 } else if err_bits & R1_BIT_CC_ERROR != 0 {
634 CardError::ControllerError
635 } else if err_bits & R1_BIT_LOCK_UNLOCK_FAILED != 0 {
636 CardError::LockUnlockFailed
637 } else if err_bits & R1_BIT_CARD_IS_LOCKED != 0 {
638 CardError::CardIsLocked
639 } else if err_bits & (R1_BIT_ERASE_SEQ_ERROR | R1_BIT_ERASE_PARAM) != 0 {
640 CardError::EraseSequence
641 } else if err_bits & R1_BIT_ERROR != 0 {
642 CardError::GenericError
643 } else {
644 CardError::Unknown(err_bits >> 19)
645 }
646}
647
648#[cfg(test)]
649mod tests {
650 use super::*;
651
652 #[test]
653 fn spi_r1_idle_uses_bit_zero() {
654 let response = R1Response::from_spi_byte(0x01).unwrap();
655 assert!(response.idle());
656 assert!(!response.illegal_command());
657 assert!(response.spi_card_error().is_none());
658 }
659
660 #[test]
661 fn spi_r1_illegal_command_sets_flag_and_card_error() {
662 let response = R1Response::from_spi_byte(0x04).unwrap();
663 assert!(response.illegal_command());
664 assert_eq!(response.spi_card_error(), Some(CardError::IllegalCommand));
665 }
666
667 #[test]
668 fn spi_r1_idle_plus_illegal_command_preserves_both() {
669 let response = R1Response::from_spi_byte(0x05).unwrap();
670 assert!(response.idle());
671 assert!(response.illegal_command());
672 assert_eq!(response.spi_card_error(), Some(CardError::IllegalCommand));
673 }
674
675 #[test]
676 fn spi_r1_high_bit_is_bus_error() {
677 assert!(matches!(
678 R1Response::from_spi_byte(0x80),
679 Err(Error::BadResponse(_))
680 ));
681 assert!(matches!(
682 R1Response::from_spi_byte(0xFF),
683 Err(Error::BadResponse(_))
684 ));
685 }
686
687 #[test]
688 fn native_r1_status_bits_decoded() {
689 let r1 = R1Response::from_native_raw(4 << 9).unwrap();
691 assert_eq!(r1.current_state(), CardState::Transfer);
692 }
693
694 #[test]
695 fn native_r1_with_illegal_command_returns_error() {
696 let err = R1Response::from_native_raw(1 << 22).unwrap_err();
698 assert_eq!(err, Error::CardError(CardError::IllegalCommand));
699 }
700
701 #[test]
707 fn native_r1_out_of_range_was_previously_dropped() {
708 let err = R1Response::from_native_raw(1 << 31).unwrap_err();
709 assert_eq!(err, Error::CardError(CardError::OutOfRange));
710 }
711
712 #[test]
713 fn native_r1_decodes_each_priority_class() {
714 let cases = [
715 (1u32 << 31, CardError::OutOfRange),
716 (1 << 30, CardError::AddressError),
717 (1 << 29, CardError::BlockLenError),
718 (1 << 26, CardError::WriteProtect),
719 (1 << 25, CardError::CardIsLocked),
720 (1 << 24, CardError::LockUnlockFailed),
721 (1 << 23, CardError::CommandCrcFailed),
722 (1 << 22, CardError::IllegalCommand),
723 (1 << 21, CardError::CardEccFailed),
724 (1 << 20, CardError::ControllerError),
725 (1 << 19, CardError::GenericError),
726 (1 << 28, CardError::EraseSequence),
727 (1 << 27, CardError::EraseSequence),
728 ];
729 for (raw, expected) in cases {
730 let err = R1Response::from_native_raw(raw).unwrap_err();
731 assert_eq!(err, Error::CardError(expected), "raw={raw:#010x}");
732 }
733 }
734
735 #[test]
738 fn native_r1_priority_picks_argument_errors_first() {
739 let err = R1Response::from_native_raw((1 << 31) | (1 << 26)).unwrap_err();
740 assert_eq!(err, Error::CardError(CardError::OutOfRange));
741 }
742
743 #[test]
747 fn native_r1_status_only_response_is_ok() {
748 let raw = (1u32 << 8) | (4u32 << 9); let r1 = R1Response::from_native_raw(raw).unwrap();
750 assert!(r1.ready_for_data());
751 assert_eq!(r1.current_state(), CardState::Transfer);
752 }
753
754 #[test]
755 fn decode_spi_card_error_priority_handles_multiple_bits() {
756 assert_eq!(
758 decode_spi_card_error(0b0000_1100),
759 CardError::CommandCrcFailed
760 );
761 }
762
763 #[test]
764 fn decode_spi_card_error_unknown_for_unrecognized_bits() {
765 assert_eq!(decode_spi_card_error(0b0000_0000), CardError::Unknown(0));
767 }
768
769 #[test]
770 fn csd_v2_decodes_2gib_capacity() {
771 let mut raw = [0u8; 16];
775 raw[0] = 0x40;
776 raw[7] = 0x00;
777 raw[8] = 0x0F;
778 raw[9] = 0x0F;
779 let csd = CsdResponse::from_raw(raw);
780 assert_eq!(csd.version(), 1);
781 assert_eq!(csd.capacity_blocks(), Some((0x0F0F + 1) * 1024));
782 }
783
784 #[test]
785 fn csd_v1_decodes_known_capacity() {
786 let mut raw = [0u8; 16];
790 raw[0] = 0x00; raw[5] = 0x09; raw[6] = 0b0000_0011; raw[6] = 0b0000_0011;
804 raw[7] = 0xBF;
805 raw[8] = 0b1100_0000;
806 raw[9] = 0b0000_0011;
809 raw[10] = 0b1000_0000;
810 let csd = CsdResponse::from_raw(raw);
811 assert_eq!(csd.version(), 0);
812 let expected = (0x0EFFu64 + 1) * (1 << (7 + 2)) * (1 << 9) / 512;
813 assert_eq!(csd.capacity_blocks(), Some(expected));
814 }
815
816 #[test]
817 fn csd_unknown_version_returns_none() {
818 let mut raw = [0u8; 16];
819 raw[0] = 0x80; let csd = CsdResponse::from_raw(raw);
821 assert_eq!(csd.version(), 2);
822 assert_eq!(csd.capacity_blocks(), None);
823 }
824
825 #[test]
826 fn cid_decodes_manufacturer_oem_product_serial_and_date() {
827 let mut raw = [0u8; 16];
830 raw[0] = 0x03;
831 raw[1] = b'S';
832 raw[2] = b'D';
833 raw[3] = b'A';
834 raw[4] = b'B';
835 raw[5] = b'C';
836 raw[6] = b'1';
837 raw[7] = b'2';
838 raw[8] = (2 << 4) | 7;
839 raw[9] = 0xDE;
840 raw[10] = 0xAD;
841 raw[11] = 0xBE;
842 raw[12] = 0xEF;
843 raw[13] = 0x01; raw[14] = 0xA5; let cid = CidResponse::from_raw(raw);
849 assert_eq!(cid.manufacturer_id(), 0x03);
850 assert_eq!(&cid.oem_id(), b"SD");
851 assert_eq!(&cid.product_name(), b"ABC12");
852 assert_eq!(cid.product_revision(), (2, 7));
853 assert_eq!(cid.serial_number(), 0xDEAD_BEEF);
854 assert_eq!(cid.manufacture_date(), (2026, 5));
855 }
856
857 #[test]
858 fn switch_status_reports_high_speed_when_group_one_function_one() {
859 let mut raw = [0u8; 64];
860 raw[16] = 0x01; let status = SwitchStatus::from_raw(raw);
862 assert_eq!(status.selected_function(1), 1);
863 assert!(status.high_speed_active());
864 }
865
866 #[test]
867 fn switch_status_reports_access_mode_support_bits() {
868 let mut raw = [0u8; 64];
869 raw[13] = (1 << 1) | (1 << 3);
870 let status = SwitchStatus::from_raw(raw);
871
872 assert!(status.access_mode_supported(1));
873 assert!(status.access_mode_supported(3));
874 assert!(!status.access_mode_supported(2));
875 assert!(!status.access_mode_supported(8));
876 }
877
878 #[test]
879 fn switch_status_reports_default_when_group_one_function_zero() {
880 let raw = [0u8; 64];
881 let status = SwitchStatus::from_raw(raw);
882 assert_eq!(status.selected_function(1), 0);
883 assert!(!status.high_speed_active());
884 }
885
886 #[test]
887 fn switch_status_unsupported_group_returns_0xf() {
888 let mut raw = [0u8; 64];
889 raw[16] = 0xF0; let status = SwitchStatus::from_raw(raw);
891 assert_eq!(status.selected_function(2), 0xF);
892 assert_eq!(status.selected_function(7), 0xF); }
894}