1use alloc::{borrow::ToOwned, string::String};
2use thiserror::Error;
3
4#[derive(Debug, Clone, PartialEq, Eq, Error)]
6#[must_use]
7pub enum NetError {
8    #[error("Failed to load module {}: {}", 0, 1)]
10    LoadModuleFailed(String, i32),
11    #[error("Failed to initialize {}: {}", 0, 1)]
13    InitFailed(String, i32),
14    #[error("{}: {}", 0, 1)]
16    Error(String, i32),
17    #[error("Net config does not exist")]
19    NetConfigNotExist,
20    #[error("Timeout")]
22    Timeout,
23}
24
25impl NetError {
26    pub fn load_module_failed(module: &str, error: i32) -> Self {
27        NetError::LoadModuleFailed(module.to_owned(), error)
28    }
29
30    pub fn init_failed(fn_name: &str, error: i32) -> Self {
31        NetError::InitFailed(fn_name.to_owned(), error)
32    }
33
34    pub fn error(fn_name: &str, error: i32) -> Self {
35        NetError::Error(fn_name.to_owned(), error)
36    }
37}
38
39#[allow(unused)]
44#[inline]
45pub fn load_net_modules() -> Result<(), NetError> {
46    unsafe {
47        let res = psp::sys::sceUtilityLoadNetModule(psp::sys::NetModule::NetCommon);
48        if res != 0 {
49            return Err(NetError::load_module_failed("", res));
50        }
51
52        let res = psp::sys::sceUtilityLoadNetModule(psp::sys::NetModule::NetInet);
53        if res != 0 {
54            return Err(NetError::load_module_failed("", res));
55        }
56
57        let res = psp::sys::sceUtilityLoadNetModule(psp::sys::NetModule::NetParseUri);
58        if res != 0 {
59            return Err(NetError::load_module_failed("", res));
60        }
61
62        let res = psp::sys::sceUtilityLoadNetModule(psp::sys::NetModule::NetHttp);
63        if res != 0 {
64            return Err(NetError::load_module_failed("", res));
65        }
66
67        Ok(())
68    }
69}
70
71#[allow(unused)]
76#[inline]
77pub fn net_init() -> Result<(), NetError> {
78    unsafe {
79        let res = psp::sys::sceNetInit(0x20000, 0x20, 0x1000, 0x20, 0x1000);
80        if res != 0 {
81            return Err(NetError::init_failed("sceNetInit", res));
82        }
83
84        let res = psp::sys::sceNetInetInit();
85        if res != 0 {
86            return Err(NetError::init_failed("sceNetInetInit", res));
87        }
88
89        let res = psp::sys::sceNetResolverInit();
90        if res != 0 {
91            return Err(NetError::init_failed("sceNetResolverInit", res));
92        }
93
94        let res = psp::sys::sceNetApctlInit(0x1600, 42);
95        if res != 0 {
96            return Err(NetError::init_failed("sceNetApctlInit", res));
97        }
98    }
99
100    Ok(())
101}
102
103#[allow(unused)]
114#[inline]
115pub fn check_netconfig_existence(id: i32) -> Result<(), NetError> {
116    unsafe {
117        let res = psp::sys::sceUtilityCheckNetParam(id);
118        if res != 0 {
119            return Err(NetError::NetConfigNotExist);
120        }
121    }
122
123    Ok(())
124}
125
126#[allow(unused)]
131#[inline]
132pub fn check_first_netconfig_existence() -> Result<(), NetError> {
133    check_netconfig_existence(1)
134}
135
136pub fn init_connection_to_access_point(connection_id: i32) -> Result<(), NetError> {
152    unsafe {
153        let res = psp::sys::sceNetApctlConnect(connection_id);
154        if res != 0 {
155            return Err(NetError::error("sceNetApctlConnect", res));
156        }
157    }
158
159    Ok(())
160}
161
162#[inline]
174pub fn block_until_connected(desist_after: usize) -> Result<(), NetError> {
175    let mut state: psp::sys::ApctlState = unsafe { core::mem::zeroed() };
176    for _ in 0..desist_after {
177        unsafe {
178            let err = psp::sys::sceNetApctlGetState(&mut state);
179            if err != 0 {
180                return Err(NetError::error("sceNetApctlGetState", err));
181            }
182        }
183        if let psp::sys::ApctlState::GotIp = state {
184            return Ok(());
185        }
186        unsafe { psp::sys::sceKernelDelayThread(50_000) };
187    }
188
189    Err(NetError::Timeout)
190}