cat_dev/fsemul/sdio/proto/
mod.rs

1//! SDIO Protocol implementations live here.
2//!
3//! NOTE: this is not a traditional SDIO protocol that you may be familiar with
4//! this is very specific to the nintendo's CAT-DEV environment. It is also
5//! split over two TCP ports.
6//!
7//! The only part that "has a protocol" too is the control port. The data port
8//! is literally just transferring files around.
9
10pub mod message;
11pub mod read;
12pub mod write;
13
14use crate::fsemul::sdio::errors::SdioProtocolError;
15
16/// The size of an SDIO Block we end up serving.
17pub const SDIO_BLOCK_SIZE: usize = 0x200_usize;
18/// The size of an SDIO Block we end up serving.
19pub const SDIO_BLOCK_SIZE_AS_U32: u32 = 0x200_u32;
20
21/// The types of packets that can be received by the SDIO Control Port.
22#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
23pub enum SdioControlPacketType {
24	/// A message that comes through or gets sent out on a particular telnet
25	/// channel.
26	TelnetMessage,
27	/// Instruction to read on the data stream.
28	Read,
29	/// Instruction to write on the data stream.
30	Write,
31	/// TODO(mythra): confirm this is what it does.
32	///
33	/// Seems to be used in older firmwares to tell the server to
34	/// 'start' the SDIO block channel.
35	StartBlockChannel,
36	/// TODO(mythra): confirm this is what it does.
37	///
38	/// Seems to be used in older firmwares to tell the server to
39	/// 'start' the CTRL Character channel.
40	StartControlListeningChannel,
41}
42
43impl From<SdioControlPacketType> for u16 {
44	fn from(value: SdioControlPacketType) -> Self {
45		match value {
46			SdioControlPacketType::TelnetMessage => 8,
47			SdioControlPacketType::Read => 0,
48			SdioControlPacketType::Write => 1,
49			SdioControlPacketType::StartBlockChannel => 0xA,
50			SdioControlPacketType::StartControlListeningChannel => 0xB,
51		}
52	}
53}
54
55impl TryFrom<u16> for SdioControlPacketType {
56	type Error = SdioProtocolError;
57
58	fn try_from(value: u16) -> Result<Self, Self::Error> {
59		match value {
60			0 => Ok(Self::Read),
61			1 => Ok(Self::Write),
62			8 => Ok(Self::TelnetMessage),
63			0xA => Ok(Self::StartBlockChannel),
64			0xB => Ok(Self::StartControlListeningChannel),
65			_ => Err(SdioProtocolError::UnknownPrintfPacketType(value)),
66		}
67	}
68}
69
70#[cfg(test)]
71mod unit_tests {
72	use super::*;
73
74	#[test]
75	pub fn roundtrip_control_packet_type() {
76		for packet_ty in vec![
77			SdioControlPacketType::TelnetMessage,
78			SdioControlPacketType::Read,
79			SdioControlPacketType::Write,
80		] {
81			assert_eq!(
82				Ok(packet_ty),
83				SdioControlPacketType::try_from(u16::from(packet_ty)),
84				"Round-tripped control packet type was not the same?"
85			);
86		}
87	}
88}