sdio_host/
common_cmd.rs

1use core::marker::PhantomData;
2
3/// Host to Card commands
4pub 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
16/// Marker for commands that don't have any response
17pub struct Rz;
18/// R1: Normal response
19pub struct R1;
20/// R2: CID and CSD register
21pub struct R2;
22/// R3: OCR register
23pub 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/// Command Response type
41#[derive(Eq, PartialEq, Copy, Clone)]
42pub enum ResponseLen {
43    /// No response expected
44    Zero,
45    /// Short (48 bit) response
46    R48,
47    /// Long (136 bit) response
48    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
59/// CMD0: Put card in idle mode
60pub fn idle() -> Cmd<Rz> {
61    cmd(0, 0)
62}
63
64/// CMD2: Ask any card to send their CID
65pub fn all_send_cid() -> Cmd<R2> {
66    cmd(2, 0)
67}
68
69/// CMD7: Select or deselect card
70pub fn select_card(rca: u16) -> Cmd<R1> {
71    cmd(7, u32::from(rca) << 16)
72}
73
74/// CMD9: Send CSD
75pub fn send_csd(rca: u16) -> Cmd<R2> {
76    cmd(9, u32::from(rca) << 16)
77}
78
79/// CMD10: Send CID
80pub fn send_cid(rca: u16) -> Cmd<R2> {
81    cmd(10, u32::from(rca) << 16)
82}
83
84/// CMD12: Stop transmission
85pub fn stop_transmission() -> Cmd<R1> {
86    cmd(12, 0)
87}
88
89/// CMD13: Ask card to send status or task status
90pub 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
95/// CMD15: Sends card to inactive state
96pub fn go_inactive_state(rca: u16) -> Cmd<Rz> {
97    cmd(15, u32::from(rca) << 16)
98}
99
100/// CMD16: Set block len
101pub fn set_block_length(blocklen: u32) -> Cmd<R1> {
102    cmd(16, blocklen)
103}
104
105/// CMD17: Read a single block from the card
106pub fn read_single_block(addr: u32) -> Cmd<R1> {
107    cmd(17, addr)
108}
109
110/// CMD18: Read multiple block from the card
111pub fn read_multiple_blocks(addr: u32) -> Cmd<R1> {
112    cmd(18, addr)
113}
114
115/// CMD24: Write block
116pub fn write_single_block(addr: u32) -> Cmd<R1> {
117    cmd(24, addr)
118}
119
120/// CMD25: Write multiple blocks
121pub fn write_multiple_blocks(addr: u32) -> Cmd<R1> {
122    cmd(25, addr)
123}
124
125/// CMD27: Program CSD
126pub fn program_csd() -> Cmd<R1> {
127    cmd(27, 0)
128}
129
130/// CMD38: Erase all previously selected write blocks
131pub fn erase() -> Cmd<R1> {
132    cmd(38, 0)
133}
134
135/// CMD55: App Command. Indicates that next command will be a app command
136pub fn app_cmd(rca: u16) -> Cmd<R1> {
137    cmd(55, u32::from(rca) << 16)
138}