1use core::marker::PhantomData;
2
3pub struct Cmd<R: Resp> {
5 pub cmd: u8,
6 pub arg: u32,
7 resp: PhantomData<R>,
8}
9
10impl<R: Resp> Cmd<R> {
11 pub fn response_len(&self) -> ResponseLen {
12 R::LENGTH
13 }
14}
15
16pub struct Rz;
18pub struct R1;
20pub struct R2;
22pub struct R3;
24
25pub trait Resp {
26 const LENGTH: ResponseLen = ResponseLen::R48;
27}
28
29impl Resp for Rz {
30 const LENGTH: ResponseLen = ResponseLen::Zero;
31}
32
33impl Resp for R2 {
34 const LENGTH: ResponseLen = ResponseLen::R136;
35}
36
37impl Resp for R1 {}
38impl Resp for R3 {}
39
40#[derive(Eq, PartialEq, Copy, Clone)]
42pub enum ResponseLen {
43 Zero,
45 R48,
47 R136,
49}
50
51pub fn cmd<R: Resp>(cmd: u8, arg: u32) -> Cmd<R> {
52 Cmd {
53 cmd,
54 arg,
55 resp: PhantomData,
56 }
57}
58
59pub fn idle() -> Cmd<Rz> {
61 cmd(0, 0)
62}
63
64pub fn all_send_cid() -> Cmd<R2> {
66 cmd(2, 0)
67}
68
69pub fn select_card(rca: u16) -> Cmd<R1> {
71 cmd(7, u32::from(rca) << 16)
72}
73
74pub fn send_csd(rca: u16) -> Cmd<R2> {
76 cmd(9, u32::from(rca) << 16)
77}
78
79pub fn send_cid(rca: u16) -> Cmd<R2> {
81 cmd(10, u32::from(rca) << 16)
82}
83
84pub fn stop_transmission() -> Cmd<R1> {
86 cmd(12, 0)
87}
88
89pub fn card_status(rca: u16, task_status: bool) -> Cmd<R1> {
91 let arg = u32::from(rca) << 16 | u32::from(task_status) << 15;
92 cmd(13, arg)
93}
94
95pub fn go_inactive_state(rca: u16) -> Cmd<Rz> {
97 cmd(15, u32::from(rca) << 16)
98}
99
100pub fn set_block_length(blocklen: u32) -> Cmd<R1> {
102 cmd(16, blocklen)
103}
104
105pub fn read_single_block(addr: u32) -> Cmd<R1> {
107 cmd(17, addr)
108}
109
110pub fn read_multiple_blocks(addr: u32) -> Cmd<R1> {
112 cmd(18, addr)
113}
114
115pub fn write_single_block(addr: u32) -> Cmd<R1> {
117 cmd(24, addr)
118}
119
120pub fn write_multiple_blocks(addr: u32) -> Cmd<R1> {
122 cmd(25, addr)
123}
124
125pub fn program_csd() -> Cmd<R1> {
127 cmd(27, 0)
128}
129
130pub fn erase() -> Cmd<R1> {
132 cmd(38, 0)
133}
134
135pub fn app_cmd(rca: u16) -> Cmd<R1> {
137 cmd(55, u32::from(rca) << 16)
138}