Browse Source

Add more documentation, add NetworkNodeID enum

pull/156/head
Jhynjhiruu 11 months ago
parent
commit
5287023486
  1. 8
      ctru-rs/examples/local-networking.rs
  2. 75
      ctru-rs/src/services/uds.rs

8
ctru-rs/examples/local-networking.rs

@ -165,7 +165,7 @@ fn main() {
Ok(p) => { Ok(p) => {
if let Some((pkt, node)) = p { if let Some((pkt, node)) = p {
println!( println!(
"{:02X}{:02X}{:02X}{:02X} from {:04X}", "{:02X}{:02X}{:02X}{:02X} from {:?}",
pkt[0], pkt[1], pkt[2], pkt[3], node pkt[0], pkt[1], pkt[2], pkt[3], node
); );
} }
@ -186,7 +186,7 @@ fn main() {
if mode != ConnectionType::Spectator { if mode != ConnectionType::Spectator {
uds.send_packet( uds.send_packet(
&transfer_data.to_le_bytes(), &transfer_data.to_le_bytes(),
ctru_sys::UDS_BROADCAST_NETWORKNODEID as _, NodeID::Broadcast,
data_channel, data_channel,
SendFlags::Default, SendFlags::Default,
) )
@ -241,7 +241,7 @@ fn main() {
Ok(p) => { Ok(p) => {
if let Some((pkt, node)) = p { if let Some((pkt, node)) = p {
println!( println!(
"{:02X}{:02X}{:02X}{:02X} from {:04X}", "{:02X}{:02X}{:02X}{:02X} from {:?}",
pkt[0], pkt[1], pkt[2], pkt[3], node pkt[0], pkt[1], pkt[2], pkt[3], node
); );
} }
@ -261,7 +261,7 @@ fn main() {
let transfer_data = hid.keys_held().bits(); let transfer_data = hid.keys_held().bits();
uds.send_packet( uds.send_packet(
&transfer_data.to_le_bytes(), &transfer_data.to_le_bytes(),
ctru_sys::UDS_BROADCAST_NETWORKNODEID as _, NodeID::Broadcast,
data_channel, data_channel,
SendFlags::Default, SendFlags::Default,
) )

75
ctru-rs/src/services/uds.rs

@ -20,11 +20,11 @@ use macaddr::MacAddr6;
bitflags! { bitflags! {
/// Flags used for sending packets to a network. /// Flags used for sending packets to a network.
#[allow(missing_docs)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SendFlags: u8 { pub struct SendFlags: u8 {
/// According to libctru source, it's not really known what these do. /// Unknown function according to `libctru`.
const Default = ctru_sys::UDS_SENDFLAG_Default as u8; const Default = ctru_sys::UDS_SENDFLAG_Default as u8;
/// Broadcast the data frame even when sending to a non-broadcast address.
const Broadcast = ctru_sys::UDS_SENDFLAG_Broadcast as u8; const Broadcast = ctru_sys::UDS_SENDFLAG_Broadcast as u8;
} }
} }
@ -94,6 +94,43 @@ impl TryFrom<u8> for ConnectionType {
} }
} }
/// ID for a node on the network.
#[doc(alias = "NetworkNodeID")]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeID {
/// No node ID set (not connected to a network).
None,
/// A normal node on the network, counting from 1 (the host) to 16, inclusive.
Node(u8),
/// Broadcast to all nodes
Broadcast,
}
impl From<NodeID> for u16 {
fn from(value: NodeID) -> Self {
match value {
NodeID::None => 0,
NodeID::Node(node) => node as u16,
NodeID::Broadcast => ctru_sys::UDS_BROADCAST_NETWORKNODEID as u16,
}
}
}
impl TryFrom<u16> for NodeID {
type Error = ();
fn try_from(value: u16) -> std::result::Result<Self, Self::Error> {
match value as u32 {
0 => Ok(Self::None),
ctru_sys::UDS_HOST_NETWORKNODEID..=ctru_sys::UDS_MAXNODES => {
Ok(Self::Node(value as u8))
}
ctru_sys::UDS_BROADCAST_NETWORKNODEID => Ok(Self::Broadcast),
_ => Err(()),
}
}
}
/// Information about a network node. /// Information about a network node.
#[allow(missing_docs)] #[allow(missing_docs)]
#[doc(alias = "udsNodeInfo")] #[doc(alias = "udsNodeInfo")]
@ -105,7 +142,7 @@ pub struct NodeInfo {
unk_x1c: u16, unk_x1c: u16,
pub flag: u8, pub flag: u8,
pad_x1f: u8, pad_x1f: u8,
pub node_id: u16, pub node_id: NodeID,
pad_x22: u16, pad_x22: u16,
word_x24: u32, word_x24: u32,
} }
@ -121,7 +158,10 @@ impl From<ctru_sys::udsNodeInfo> for NodeInfo {
unk_x1c: value.__bindgen_anon_1.__bindgen_anon_1.unk_x1c, unk_x1c: value.__bindgen_anon_1.__bindgen_anon_1.unk_x1c,
flag: value.__bindgen_anon_1.__bindgen_anon_1.flag, flag: value.__bindgen_anon_1.__bindgen_anon_1.flag,
pad_x1f: value.__bindgen_anon_1.__bindgen_anon_1.pad_x1f, pad_x1f: value.__bindgen_anon_1.__bindgen_anon_1.pad_x1f,
node_id: value.NetworkNodeID, node_id: value
.NetworkNodeID
.try_into()
.expect("UDS service should always provide a valid NetworkNodeID"),
pad_x22: value.pad_x22, pad_x22: value.pad_x22,
word_x24: value.word_x24, word_x24: value.word_x24,
} }
@ -163,11 +203,12 @@ impl From<ctru_sys::udsNetworkScanInfo> for NetworkScanInfo {
#[doc(alias = "udsConnectionStatus")] #[doc(alias = "udsConnectionStatus")]
#[derive(Debug)] #[derive(Debug)]
pub struct ConnectionStatus { pub struct ConnectionStatus {
/// Raw status information
// TODO: is this in some kind of readable format? // TODO: is this in some kind of readable format?
pub status: u32, pub status: u32,
unk_x4: u32, unk_x4: u32,
/// Network node ID for the current device. /// Network node ID for the current device.
pub cur_node_id: u16, pub cur_node_id: NodeID,
unk_xa: u16, unk_xa: u16,
unk_xc: [u32; 8], unk_xc: [u32; 8],
/// Number of nodes connected to the network. /// Number of nodes connected to the network.
@ -185,7 +226,10 @@ impl From<ctru_sys::udsConnectionStatus> for ConnectionStatus {
Self { Self {
status: value.status, status: value.status,
unk_x4: value.unk_x4, unk_x4: value.unk_x4,
cur_node_id: value.cur_NetworkNodeID, cur_node_id: value
.cur_NetworkNodeID
.try_into()
.expect("UDS service should always provide a valid NetworkNodeID"),
unk_xa: value.unk_xa, unk_xa: value.unk_xa,
unk_xc: value.unk_xc, unk_xc: value.unk_xc,
total_nodes: value.total_nodes, total_nodes: value.total_nodes,
@ -196,7 +240,7 @@ impl From<ctru_sys::udsConnectionStatus> for ConnectionStatus {
} }
/// Status of the service handle. /// Status of the service handle.
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ServiceStatus { pub enum ServiceStatus {
/// Not connected to or hosting a network. /// Not connected to or hosting a network.
Disconnected, Disconnected,
@ -252,7 +296,7 @@ impl Uds {
/// Initialise a new service handle. /// Initialise a new service handle.
/// No `new_with_buffer_size` function is provided, as there isn't really a /// No `new_with_buffer_size` function is provided, as there isn't really a
/// reason to use any size other than the default. /// reason to use any size other than the default.
/// ///
/// The `username` parameter should be a max 10-byte (not 10 code point!) UTF-8 string, converted to UTF-16 internally. /// The `username` parameter should be a max 10-byte (not 10 code point!) UTF-8 string, converted to UTF-16 internally.
/// Pass `None` to use the 3DS's configured username. /// Pass `None` to use the 3DS's configured username.
/// ///
@ -754,7 +798,7 @@ impl Uds {
pub fn send_packet( pub fn send_packet(
&self, &self,
packet: &[u8], packet: &[u8],
to_nodes: u16, address: NodeID,
channel: u8, channel: u8,
flags: SendFlags, flags: SendFlags,
) -> Result<(), Error> { ) -> Result<(), Error> {
@ -768,7 +812,7 @@ impl Uds {
let code = ResultCode(unsafe { let code = ResultCode(unsafe {
ctru_sys::udsSendTo( ctru_sys::udsSendTo(
to_nodes, address.into(),
channel, channel,
flags.bits(), flags.bits(),
packet.as_ptr().cast(), packet.as_ptr().cast(),
@ -815,7 +859,7 @@ impl Uds {
/// # } /// # }
/// ``` /// ```
#[doc(alias = "udsPullPacket")] #[doc(alias = "udsPullPacket")]
pub fn pull_packet(&self) -> Result<Option<(Vec<u8>, u16)>, Error> { pub fn pull_packet(&self) -> Result<Option<(Vec<u8>, NodeID)>, Error> {
if self.service_status() == ServiceStatus::Disconnected { if self.service_status() == ServiceStatus::Disconnected {
return Err(Error::NotConnected); return Err(Error::NotConnected);
} }
@ -843,7 +887,12 @@ impl Uds {
None None
} else { } else {
// TODO: to_vec() first, then truncate() and shrink_to_fit()? // TODO: to_vec() first, then truncate() and shrink_to_fit()?
Some((frame[..actual_size].to_vec(), src_node_id)) Some((
frame[..actual_size].to_vec(),
src_node_id
.try_into()
.expect("UDS service should always provide a valid NetworkNodeID"),
))
}) })
} }

Loading…
Cancel
Save