1use crate::error::{CardError, Error, ErrorContext, Phase};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8#[non_exhaustive]
9pub enum ResponseType {
10 None,
12 R1,
14 R1b,
16 R2,
18 R3,
20 R4,
22 R5,
24 R6,
26 R7,
28}
29
30#[derive(Debug, Clone, Copy)]
35#[non_exhaustive]
36pub enum Response {
37 Empty,
42 R1(R1Response),
43 R1b(R1Response),
44 R2([u8; 16]),
45 R3(OcrResponse),
46 R4(SdioOcrResponse),
47 R5(SdioRwResponse),
48 R6(RcaResponse),
49 R7(IfCondResponse),
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub struct R1Response {
55 pub raw: u32,
56}
57
58impl R1Response {
59 pub fn from_native_raw(raw: u32) -> Result<Self, Error> {
91 let err_bits = raw & R1_NATIVE_ERROR_MASK;
92 if err_bits != 0 {
93 return Err(Error::CardError(decode_native_card_error(err_bits)));
94 }
95 Ok(Self { raw })
96 }
97
98 pub fn from_spi_byte(byte: u8) -> Result<Self, Error> {
111 if byte & 0x80 != 0 {
112 return Err(Error::BadResponse(ErrorContext::new(Phase::ResponseWait)));
113 }
114 Ok(Self { raw: byte as u32 })
115 }
116
117 pub fn spi_card_error(&self) -> Option<CardError> {
124 let bits = (self.raw as u8) & 0b0111_1110;
125 if bits == 0 {
126 None
127 } else {
128 Some(decode_spi_card_error(bits))
129 }
130 }
131
132 pub fn idle(&self) -> bool {
134 self.raw & (1 << 0) != 0
135 }
136
137 pub fn erase_reset(&self) -> bool {
139 self.raw & (1 << 1) != 0
140 }
141
142 pub fn illegal_command(&self) -> bool {
144 self.raw & (1 << 2) != 0
145 }
146
147 pub fn command_crc_failed(&self) -> bool {
149 self.raw & (1 << 3) != 0
150 }
151
152 pub fn current_state(&self) -> CardState {
157 match ((self.raw >> 9) & 0xF) as u8 {
158 0 => CardState::Idle,
159 1 => CardState::Ready,
160 2 => CardState::Identification,
161 3 => CardState::Standby,
162 4 => CardState::Transfer,
163 5 => CardState::SendingData,
164 6 => CardState::ReceiveData,
165 7 => CardState::Programming,
166 8 => CardState::Disconnect,
167 other => CardState::Reserved(other),
168 }
169 }
170
171 pub fn card_is_locked(&self) -> bool {
173 self.raw & (1 << 19) != 0
174 }
175
176 pub fn ready_for_data(&self) -> bool {
182 self.raw & (1 << 8) != 0
183 }
184
185 pub fn switch_error(&self) -> bool {
190 self.raw & (1 << 7) != 0
191 }
192}
193
194#[derive(Debug, Clone, Copy, PartialEq, Eq)]
199#[non_exhaustive]
200pub enum CardState {
201 Idle,
202 Ready,
203 Identification,
204 Standby,
205 Transfer,
206 SendingData,
207 ReceiveData,
208 Programming,
209 Disconnect,
210 Reserved(u8),
211}
212
213#[derive(Debug, Clone, Copy)]
215pub struct OcrResponse {
216 pub raw: u32,
217}
218
219impl OcrResponse {
220 pub fn from_raw(raw: u32) -> Self {
221 Self { raw }
222 }
223
224 pub fn card_powered_up(&self) -> bool {
226 self.raw & (1 << 31) != 0
227 }
228
229 pub fn ccs(&self) -> bool {
231 self.raw & (1 << 30) != 0
232 }
233
234 pub fn voltage_window(&self) -> u32 {
236 self.raw & 0x00FF_FF00
237 }
238
239 pub fn vdd_35_36(&self) -> bool {
241 self.raw & (1 << 23) != 0
242 }
243
244 pub fn vdd_34_35(&self) -> bool {
246 self.raw & (1 << 22) != 0
247 }
248
249 pub fn vdd_33_34(&self) -> bool {
251 self.raw & (1 << 21) != 0
252 }
253
254 pub fn vdd_32_33(&self) -> bool {
256 self.raw & (1 << 20) != 0
257 }
258
259 pub fn supports_2v7_to_3v6(&self) -> bool {
261 self.raw & 0x00FF_8000 != 0
262 }
263
264 pub fn uhs2(&self) -> bool {
266 self.raw & (1 << 29) != 0
267 }
268
269 pub fn s18a(&self) -> bool {
271 self.raw & (1 << 24) != 0
272 }
273}
274
275#[derive(Debug, Clone, Copy)]
277pub struct RcaResponse {
278 pub raw: u32,
279}
280
281impl RcaResponse {
282 pub fn from_raw(raw: u32) -> Self {
283 Self { raw }
284 }
285
286 pub fn rca(&self) -> u16 {
288 ((self.raw >> 16) & 0xFFFF) as u16
289 }
290
291 pub fn status(&self) -> u16 {
293 (self.raw & 0xFFFF) as u16
294 }
295}
296
297#[derive(Debug, Clone, Copy)]
299pub struct IfCondResponse {
300 pub raw: u32,
301}
302
303impl IfCondResponse {
304 pub fn from_raw(raw: u32) -> Self {
305 Self { raw }
306 }
307
308 pub fn voltage(&self) -> u8 {
310 ((self.raw >> 8) & 0xF) as u8
311 }
312
313 pub fn check_pattern(&self) -> u8 {
315 (self.raw & 0xFF) as u8
316 }
317
318 pub fn verify(&self, voltage: u8, pattern: u8) -> bool {
320 self.voltage() == voltage && self.check_pattern() == pattern
321 }
322}
323
324#[derive(Debug, Clone, Copy)]
327pub struct CsdResponse {
328 pub raw: [u8; 16],
329}
330
331impl CsdResponse {
332 pub fn from_raw(raw: [u8; 16]) -> Self {
333 Self { raw }
334 }
335
336 pub fn version(&self) -> u8 {
338 (self.raw[0] >> 6) & 0x03
339 }
340
341 pub fn capacity_blocks(&self) -> Option<u64> {
346 match self.version() {
347 0 => Some(self.csd_v1_capacity_blocks()),
348 1 => Some(self.csd_v2_capacity_blocks()),
349 _ => None,
350 }
351 }
352
353 fn csd_v1_capacity_blocks(&self) -> u64 {
354 let read_bl_len = (self.raw[5] & 0x0F) as u32;
360 let c_size = (((self.raw[6] & 0x03) as u32) << 10)
361 | ((self.raw[7] as u32) << 2)
362 | ((self.raw[8] as u32) >> 6);
363 let c_size_mult = (((self.raw[9] & 0x03) as u32) << 1) | ((self.raw[10] as u32) >> 7);
364 let mult = 1u64 << (c_size_mult + 2);
365 let block_len = 1u64 << read_bl_len;
366 let bytes = (c_size as u64 + 1) * mult * block_len;
367 bytes / 512
368 }
369
370 fn csd_v2_capacity_blocks(&self) -> u64 {
371 let c_size = (((self.raw[7] & 0x3F) as u32) << 16)
376 | ((self.raw[8] as u32) << 8)
377 | (self.raw[9] as u32);
378 (c_size as u64 + 1) * 1024
379 }
380}
381
382#[derive(Debug, Clone, Copy)]
388pub struct CidResponse {
389 pub raw: [u8; 16],
390}
391
392impl CidResponse {
393 pub fn from_raw(raw: [u8; 16]) -> Self {
394 Self { raw }
395 }
396
397 pub fn manufacturer_id(&self) -> u8 {
399 self.raw[0]
400 }
401
402 pub fn oem_id(&self) -> [u8; 2] {
406 [self.raw[1], self.raw[2]]
407 }
408
409 pub fn product_name(&self) -> [u8; 5] {
411 [
412 self.raw[3],
413 self.raw[4],
414 self.raw[5],
415 self.raw[6],
416 self.raw[7],
417 ]
418 }
419
420 pub fn product_revision(&self) -> (u8, u8) {
422 (self.raw[8] >> 4, self.raw[8] & 0x0F)
423 }
424
425 pub fn serial_number(&self) -> u32 {
427 u32::from_be_bytes([self.raw[9], self.raw[10], self.raw[11], self.raw[12]])
428 }
429
430 pub fn manufacture_date(&self) -> (u16, u8) {
436 let year = ((self.raw[13] & 0x0F) << 4) | (self.raw[14] >> 4);
437 let month = self.raw[14] & 0x0F;
438 (2000 + year as u16, month)
439 }
440}
441
442#[derive(Debug, Clone, Copy)]
448pub struct SwitchStatus {
449 pub raw: [u8; 64],
450}
451
452impl SwitchStatus {
453 pub fn from_raw(raw: [u8; 64]) -> Self {
454 Self { raw }
455 }
456
457 pub fn selected_function(&self, group: u8) -> u8 {
464 match group {
465 1 => self.raw[16] & 0x0F,
466 2 => self.raw[16] >> 4,
467 3 => self.raw[15] & 0x0F,
468 4 => self.raw[15] >> 4,
469 5 => self.raw[14] & 0x0F,
470 6 => self.raw[14] >> 4,
471 _ => 0xF,
472 }
473 }
474
475 pub fn high_speed_active(&self) -> bool {
477 self.selected_function(1) == 1
478 }
479
480 pub fn access_mode_supported(&self, function: u8) -> bool {
485 function < 8 && (self.raw[13] & (1 << function)) != 0
486 }
487}
488
489#[derive(Debug, Clone, Copy)]
491pub struct SdioOcrResponse {
492 pub raw: u32,
493}
494
495impl SdioOcrResponse {
496 pub fn from_raw(raw: u32) -> Self {
497 Self { raw }
498 }
499
500 pub fn io_functions(&self) -> u8 {
502 ((self.raw >> 28) & 0x7) as u8
503 }
504
505 pub fn memory_present(&self) -> bool {
507 self.raw & (1 << 27) != 0
508 }
509
510 pub fn io_ready(&self) -> bool {
512 self.raw & (1 << 31) != 0
513 }
514}
515
516#[derive(Debug, Clone, Copy)]
518pub struct SdioRwResponse {
519 pub raw: u32,
520}
521
522impl SdioRwResponse {
523 pub fn from_raw(raw: u32) -> Self {
524 Self { raw }
525 }
526
527 pub fn data(&self) -> u8 {
529 (self.raw & 0xFF) as u8
530 }
531
532 pub fn flags(&self) -> u8 {
534 ((self.raw >> 8) & 0xFF) as u8
535 }
536}
537
538const R1_NATIVE_ERROR_MASK: u32 = 0xFFF8_0000;
543
544const R1_BIT_OUT_OF_RANGE: u32 = 1 << 31;
545const R1_BIT_ADDRESS_ERROR: u32 = 1 << 30;
546const R1_BIT_BLOCK_LEN_ERROR: u32 = 1 << 29;
547const R1_BIT_ERASE_SEQ_ERROR: u32 = 1 << 28;
548const R1_BIT_ERASE_PARAM: u32 = 1 << 27;
549const R1_BIT_WP_VIOLATION: u32 = 1 << 26;
550const R1_BIT_CARD_IS_LOCKED: u32 = 1 << 25;
551const R1_BIT_LOCK_UNLOCK_FAILED: u32 = 1 << 24;
552const R1_BIT_COM_CRC_ERROR: u32 = 1 << 23;
553const R1_BIT_ILLEGAL_COMMAND: u32 = 1 << 22;
554const R1_BIT_CARD_ECC_FAILED: u32 = 1 << 21;
555const R1_BIT_CC_ERROR: u32 = 1 << 20;
556const R1_BIT_ERROR: u32 = 1 << 19;
557
558fn decode_spi_card_error(bits: u8) -> CardError {
572 if bits & 0b0000_1000 != 0 {
573 CardError::CommandCrcFailed
574 } else if bits & 0b0000_0100 != 0 {
575 CardError::IllegalCommand
576 } else if bits & 0b0010_0000 != 0 {
577 CardError::AddressError
578 } else if bits & 0b0100_0000 != 0 {
579 CardError::BlockLenError
581 } else if bits & (0b0001_0000 | 0b0000_0010) != 0 {
582 CardError::EraseSequence
584 } else {
585 CardError::Unknown(bits as u32)
586 }
587}
588
589fn decode_native_card_error(err_bits: u32) -> CardError {
599 if err_bits & R1_BIT_OUT_OF_RANGE != 0 {
600 CardError::OutOfRange
601 } else if err_bits & R1_BIT_ADDRESS_ERROR != 0 {
602 CardError::AddressError
603 } else if err_bits & R1_BIT_BLOCK_LEN_ERROR != 0 {
604 CardError::BlockLenError
605 } else if err_bits & R1_BIT_WP_VIOLATION != 0 {
606 CardError::WriteProtect
607 } else if err_bits & R1_BIT_COM_CRC_ERROR != 0 {
608 CardError::CommandCrcFailed
609 } else if err_bits & R1_BIT_ILLEGAL_COMMAND != 0 {
610 CardError::IllegalCommand
611 } else if err_bits & R1_BIT_CARD_ECC_FAILED != 0 {
612 CardError::CardEccFailed
613 } else if err_bits & R1_BIT_CC_ERROR != 0 {
614 CardError::ControllerError
615 } else if err_bits & R1_BIT_LOCK_UNLOCK_FAILED != 0 {
616 CardError::LockUnlockFailed
617 } else if err_bits & R1_BIT_CARD_IS_LOCKED != 0 {
618 CardError::CardIsLocked
619 } else if err_bits & (R1_BIT_ERASE_SEQ_ERROR | R1_BIT_ERASE_PARAM) != 0 {
620 CardError::EraseSequence
621 } else if err_bits & R1_BIT_ERROR != 0 {
622 CardError::GenericError
623 } else {
624 CardError::Unknown(err_bits >> 19)
625 }
626}
627
628#[cfg(test)]
629mod tests {
630 use super::*;
631
632 #[test]
633 fn spi_r1_idle_uses_bit_zero() {
634 let response = R1Response::from_spi_byte(0x01).unwrap();
635 assert!(response.idle());
636 assert!(!response.illegal_command());
637 assert!(response.spi_card_error().is_none());
638 }
639
640 #[test]
641 fn spi_r1_illegal_command_sets_flag_and_card_error() {
642 let response = R1Response::from_spi_byte(0x04).unwrap();
643 assert!(response.illegal_command());
644 assert_eq!(response.spi_card_error(), Some(CardError::IllegalCommand));
645 }
646
647 #[test]
648 fn spi_r1_idle_plus_illegal_command_preserves_both() {
649 let response = R1Response::from_spi_byte(0x05).unwrap();
650 assert!(response.idle());
651 assert!(response.illegal_command());
652 assert_eq!(response.spi_card_error(), Some(CardError::IllegalCommand));
653 }
654
655 #[test]
656 fn spi_r1_high_bit_is_bus_error() {
657 assert!(matches!(
658 R1Response::from_spi_byte(0x80),
659 Err(Error::BadResponse(_))
660 ));
661 assert!(matches!(
662 R1Response::from_spi_byte(0xFF),
663 Err(Error::BadResponse(_))
664 ));
665 }
666
667 #[test]
668 fn native_r1_status_bits_decoded() {
669 let r1 = R1Response::from_native_raw(4 << 9).unwrap();
671 assert_eq!(r1.current_state(), CardState::Transfer);
672 }
673
674 #[test]
675 fn native_r1_with_illegal_command_returns_error() {
676 let err = R1Response::from_native_raw(1 << 22).unwrap_err();
678 assert_eq!(err, Error::CardError(CardError::IllegalCommand));
679 }
680
681 #[test]
687 fn native_r1_out_of_range_was_previously_dropped() {
688 let err = R1Response::from_native_raw(1 << 31).unwrap_err();
689 assert_eq!(err, Error::CardError(CardError::OutOfRange));
690 }
691
692 #[test]
693 fn native_r1_decodes_each_priority_class() {
694 let cases = [
695 (1u32 << 31, CardError::OutOfRange),
696 (1 << 30, CardError::AddressError),
697 (1 << 29, CardError::BlockLenError),
698 (1 << 26, CardError::WriteProtect),
699 (1 << 25, CardError::CardIsLocked),
700 (1 << 24, CardError::LockUnlockFailed),
701 (1 << 23, CardError::CommandCrcFailed),
702 (1 << 22, CardError::IllegalCommand),
703 (1 << 21, CardError::CardEccFailed),
704 (1 << 20, CardError::ControllerError),
705 (1 << 19, CardError::GenericError),
706 (1 << 28, CardError::EraseSequence),
707 (1 << 27, CardError::EraseSequence),
708 ];
709 for (raw, expected) in cases {
710 let err = R1Response::from_native_raw(raw).unwrap_err();
711 assert_eq!(err, Error::CardError(expected), "raw={raw:#010x}");
712 }
713 }
714
715 #[test]
718 fn native_r1_priority_picks_argument_errors_first() {
719 let err = R1Response::from_native_raw((1 << 31) | (1 << 26)).unwrap_err();
720 assert_eq!(err, Error::CardError(CardError::OutOfRange));
721 }
722
723 #[test]
727 fn native_r1_status_only_response_is_ok() {
728 let raw = (1u32 << 8) | (4u32 << 9); let r1 = R1Response::from_native_raw(raw).unwrap();
730 assert!(r1.ready_for_data());
731 assert_eq!(r1.current_state(), CardState::Transfer);
732 }
733
734 #[test]
735 fn decode_spi_card_error_priority_handles_multiple_bits() {
736 assert_eq!(
738 decode_spi_card_error(0b0000_1100),
739 CardError::CommandCrcFailed
740 );
741 }
742
743 #[test]
744 fn decode_spi_card_error_unknown_for_unrecognized_bits() {
745 assert_eq!(decode_spi_card_error(0b0000_0000), CardError::Unknown(0));
747 }
748
749 #[test]
750 fn csd_v2_decodes_2gib_capacity() {
751 let mut raw = [0u8; 16];
755 raw[0] = 0x40;
756 raw[7] = 0x00;
757 raw[8] = 0x0F;
758 raw[9] = 0x0F;
759 let csd = CsdResponse::from_raw(raw);
760 assert_eq!(csd.version(), 1);
761 assert_eq!(csd.capacity_blocks(), Some((0x0F0F + 1) * 1024));
762 }
763
764 #[test]
765 fn csd_v1_decodes_known_capacity() {
766 let mut raw = [0u8; 16];
770 raw[0] = 0x00; raw[5] = 0x09; raw[6] = 0b0000_0011; raw[6] = 0b0000_0011;
784 raw[7] = 0xBF;
785 raw[8] = 0b1100_0000;
786 raw[9] = 0b0000_0011;
789 raw[10] = 0b1000_0000;
790 let csd = CsdResponse::from_raw(raw);
791 assert_eq!(csd.version(), 0);
792 let expected = (0x0EFFu64 + 1) * (1 << (7 + 2)) * (1 << 9) / 512;
793 assert_eq!(csd.capacity_blocks(), Some(expected));
794 }
795
796 #[test]
797 fn csd_unknown_version_returns_none() {
798 let mut raw = [0u8; 16];
799 raw[0] = 0x80; let csd = CsdResponse::from_raw(raw);
801 assert_eq!(csd.version(), 2);
802 assert_eq!(csd.capacity_blocks(), None);
803 }
804
805 #[test]
806 fn cid_decodes_manufacturer_oem_product_serial_and_date() {
807 let mut raw = [0u8; 16];
810 raw[0] = 0x03;
811 raw[1] = b'S';
812 raw[2] = b'D';
813 raw[3] = b'A';
814 raw[4] = b'B';
815 raw[5] = b'C';
816 raw[6] = b'1';
817 raw[7] = b'2';
818 raw[8] = (2 << 4) | 7;
819 raw[9] = 0xDE;
820 raw[10] = 0xAD;
821 raw[11] = 0xBE;
822 raw[12] = 0xEF;
823 raw[13] = 0x01; raw[14] = 0xA5; let cid = CidResponse::from_raw(raw);
829 assert_eq!(cid.manufacturer_id(), 0x03);
830 assert_eq!(&cid.oem_id(), b"SD");
831 assert_eq!(&cid.product_name(), b"ABC12");
832 assert_eq!(cid.product_revision(), (2, 7));
833 assert_eq!(cid.serial_number(), 0xDEAD_BEEF);
834 assert_eq!(cid.manufacture_date(), (2026, 5));
835 }
836
837 #[test]
838 fn switch_status_reports_high_speed_when_group_one_function_one() {
839 let mut raw = [0u8; 64];
840 raw[16] = 0x01; let status = SwitchStatus::from_raw(raw);
842 assert_eq!(status.selected_function(1), 1);
843 assert!(status.high_speed_active());
844 }
845
846 #[test]
847 fn switch_status_reports_access_mode_support_bits() {
848 let mut raw = [0u8; 64];
849 raw[13] = (1 << 1) | (1 << 3);
850 let status = SwitchStatus::from_raw(raw);
851
852 assert!(status.access_mode_supported(1));
853 assert!(status.access_mode_supported(3));
854 assert!(!status.access_mode_supported(2));
855 assert!(!status.access_mode_supported(8));
856 }
857
858 #[test]
859 fn switch_status_reports_default_when_group_one_function_zero() {
860 let raw = [0u8; 64];
861 let status = SwitchStatus::from_raw(raw);
862 assert_eq!(status.selected_function(1), 0);
863 assert!(!status.high_speed_active());
864 }
865
866 #[test]
867 fn switch_status_unsupported_group_returns_0xf() {
868 let mut raw = [0u8; 64];
869 raw[16] = 0xF0; let status = SwitchStatus::from_raw(raw);
871 assert_eq!(status.selected_function(2), 0xF);
872 assert_eq!(status.selected_function(7), 0xF); }
874}