ctru/services/
cfgu.rs

1//! System Configuration service.
2//!
3//! This module contains basic methods to retrieve the console's system configuration.
4#![doc(alias = "configuration")]
5
6use crate::error::ResultCode;
7
8/// Console region.
9#[doc(alias = "CFG_Region")]
10#[derive(Copy, Clone, Debug, PartialEq, Eq)]
11#[repr(u8)]
12pub enum Region {
13    /// Japan.
14    Japan = ctru_sys::CFG_REGION_JPN,
15    /// USA.
16    USA = ctru_sys::CFG_REGION_USA,
17    /// Europe.
18    Europe = ctru_sys::CFG_REGION_EUR,
19    /// Australia.
20    Australia = ctru_sys::CFG_REGION_AUS,
21    /// China.
22    China = ctru_sys::CFG_REGION_CHN,
23    /// Korea.
24    Korea = ctru_sys::CFG_REGION_KOR,
25    /// Taiwan.
26    Taiwan = ctru_sys::CFG_REGION_TWN,
27}
28
29/// Language set for the console's OS.
30#[doc(alias = "CFG_Language")]
31#[derive(Copy, Clone, Debug, PartialEq, Eq)]
32#[repr(i8)]
33pub enum Language {
34    /// Japanese.
35    Japanese = ctru_sys::CFG_LANGUAGE_JP,
36    /// English.
37    English = ctru_sys::CFG_LANGUAGE_EN,
38    /// French.
39    French = ctru_sys::CFG_LANGUAGE_FR,
40    /// German.
41    German = ctru_sys::CFG_LANGUAGE_DE,
42    /// Italian.
43    Italian = ctru_sys::CFG_LANGUAGE_IT,
44    /// Spanish.
45    Spanish = ctru_sys::CFG_LANGUAGE_ES,
46    /// Korean.
47    Korean = ctru_sys::CFG_LANGUAGE_KO,
48    /// Dutch.
49    Dutch = ctru_sys::CFG_LANGUAGE_NL,
50    /// Portuguese.
51    Portuguese = ctru_sys::CFG_LANGUAGE_PT,
52    /// Russian.
53    Russian = ctru_sys::CFG_LANGUAGE_RU,
54    /// Simplified Chinese.
55    SimplifiedChinese = ctru_sys::CFG_LANGUAGE_ZH,
56    /// Traditional Chinese.
57    TraditionalChinese = ctru_sys::CFG_LANGUAGE_TW,
58}
59
60/// Specific model of the console.
61#[doc(alias = "CFG_SystemModel")]
62#[derive(Copy, Clone, Debug, PartialEq, Eq)]
63#[repr(u8)]
64pub enum SystemModel {
65    /// Old Nintendo 3DS.
66    Old3DS = ctru_sys::CFG_MODEL_3DS,
67    /// Old Nintendo 3DS XL.
68    Old3DSXL = ctru_sys::CFG_MODEL_3DSXL,
69    /// New Nintendo 3DS.
70    New3DS = ctru_sys::CFG_MODEL_N3DS,
71    /// Old Nintendo 2DS.
72    Old2DS = ctru_sys::CFG_MODEL_2DS,
73    /// New Nintendo 3DS XL.
74    New3DSXL = ctru_sys::CFG_MODEL_N3DSXL,
75    /// New Nintendo 2DS XL.
76    New2DSXL = ctru_sys::CFG_MODEL_N2DSXL,
77}
78
79/// Handle to the System Configuration service.
80pub struct Cfgu(());
81
82impl Cfgu {
83    /// Initialize a new service handle.
84    ///
85    /// # Example
86    ///
87    /// ```
88    /// # let _runner = test_runner::GdbRunner::default();
89    /// # use std::error::Error;
90    /// # fn main() -> Result<(), Box<dyn Error>> {
91    /// #
92    /// use ctru::services::cfgu::Cfgu;
93    ///
94    /// let cfgu = Cfgu::new()?;
95    /// #
96    /// # Ok(())
97    /// # }
98    /// ```
99    #[doc(alias = "cfguInit")]
100    pub fn new() -> crate::Result<Cfgu> {
101        ResultCode(unsafe { ctru_sys::cfguInit() })?;
102        Ok(Cfgu(()))
103    }
104
105    /// Returns the console's region from the system's secure info.
106    ///
107    /// # Example
108    ///
109    /// ```
110    /// # let _runner = test_runner::GdbRunner::default();
111    /// # use std::error::Error;
112    /// # fn main() -> Result<(), Box<dyn Error>> {
113    /// #
114    /// use ctru::services::cfgu::Cfgu;
115    /// let cfgu = Cfgu::new()?;
116    ///
117    /// let region = cfgu.region()?;
118    /// #
119    /// # Ok(())
120    /// # }
121    /// ```
122    #[doc(alias = "CFGU_SecureInfoGetRegion")]
123    pub fn region(&self) -> crate::Result<Region> {
124        let mut region: u8 = 0;
125
126        ResultCode(unsafe { ctru_sys::CFGU_SecureInfoGetRegion(&mut region) })?;
127        Ok(Region::try_from(region).unwrap())
128    }
129
130    /// Returns the console's model.
131    ///
132    /// # Example
133    ///
134    /// ```
135    /// # let _runner = test_runner::GdbRunner::default();
136    /// # use std::error::Error;
137    /// # fn main() -> Result<(), Box<dyn Error>> {
138    /// #
139    /// use ctru::services::cfgu::Cfgu;
140    /// let cfgu = Cfgu::new()?;
141    ///
142    /// let model = cfgu.model()?;
143    /// #
144    /// # Ok(())
145    /// # }
146    /// ```
147    #[doc(alias = "CFGU_GetSystemModel")]
148    pub fn model(&self) -> crate::Result<SystemModel> {
149        let mut model: u8 = 0;
150
151        ResultCode(unsafe { ctru_sys::CFGU_GetSystemModel(&mut model) })?;
152        Ok(SystemModel::try_from(model).unwrap())
153    }
154
155    /// Returns the system language set for the console.
156    ///
157    /// # Example
158    ///
159    /// ```
160    /// # let _runner = test_runner::GdbRunner::default();
161    /// # use std::error::Error;
162    /// # fn main() -> Result<(), Box<dyn Error>> {
163    /// #
164    /// use ctru::services::cfgu::Cfgu;
165    /// let cfgu = Cfgu::new()?;
166    ///
167    /// let language = cfgu.language()?;
168    /// #
169    /// # Ok(())
170    /// # }
171    /// ```
172    #[doc(alias = "CFGU_GetSystemLanguage")]
173    pub fn language(&self) -> crate::Result<Language> {
174        let mut language: u8 = 0;
175
176        ResultCode(unsafe { ctru_sys::CFGU_GetSystemLanguage(&mut language) })?;
177        Ok(Language::try_from(language as i8).unwrap())
178    }
179
180    /// Check if NFC is supported by the console.
181    ///
182    /// # Example
183    ///
184    /// ```
185    /// # let _runner = test_runner::GdbRunner::default();
186    /// # use std::error::Error;
187    /// # fn main() -> Result<(), Box<dyn Error>> {
188    /// #
189    /// use ctru::services::cfgu::Cfgu;
190    /// let cfgu = Cfgu::new()?;
191    ///
192    /// if cfgu.is_nfc_supported()? {
193    ///     println!("NFC is available!");
194    /// }
195    /// #
196    /// # Ok(())
197    /// # }
198    /// ```
199    #[doc(alias = "CFGU_IsNFCSupported")]
200    pub fn is_nfc_supported(&self) -> crate::Result<bool> {
201        let mut supported: bool = false;
202
203        ResultCode(unsafe { ctru_sys::CFGU_IsNFCSupported(&mut supported) })?;
204        Ok(supported)
205    }
206
207    /// Check if the console is from the 2DS family ([`Old2DS`](SystemModel::Old2DS), [`New2DSXL`](SystemModel::New2DSXL)).
208    ///
209    /// Useful to avoid stereoscopic 3D rendering when working with 2DS consoles.
210    ///
211    /// # Example
212    ///
213    /// ```
214    /// # let _runner = test_runner::GdbRunner::default();
215    /// # use std::error::Error;
216    /// # fn main() -> Result<(), Box<dyn Error>> {
217    /// #
218    /// use ctru::services::cfgu::Cfgu;
219    /// let cfgu = Cfgu::new()?;
220    ///
221    /// if cfgu.is_2ds_family()? {
222    ///     println!("Stereoscopic 3D is not supported.");
223    /// }
224    /// #
225    /// # Ok(())
226    /// # }
227    /// ```
228    #[doc(alias = "CFGU_GetModelNintendo2DS")]
229    pub fn is_2ds_family(&self) -> crate::Result<bool> {
230        let mut is_2ds_family: u8 = 0;
231
232        ResultCode(unsafe { ctru_sys::CFGU_GetModelNintendo2DS(&mut is_2ds_family) })?;
233        Ok(is_2ds_family == 0)
234    }
235}
236
237impl Drop for Cfgu {
238    #[doc(alias = "cfguExit")]
239    fn drop(&mut self) {
240        unsafe {
241            ctru_sys::cfguExit();
242        }
243    }
244}
245
246from_impl!(Region, u8);
247from_impl!(Language, i8);
248from_impl!(SystemModel, u8);
249
250impl TryFrom<u8> for Region {
251    type Error = ();
252
253    fn try_from(value: u8) -> Result<Self, Self::Error> {
254        match value {
255            ctru_sys::CFG_REGION_JPN => Ok(Region::Japan),
256            ctru_sys::CFG_REGION_USA => Ok(Region::USA),
257            ctru_sys::CFG_REGION_EUR => Ok(Region::Europe),
258            ctru_sys::CFG_REGION_AUS => Ok(Region::Australia),
259            ctru_sys::CFG_REGION_CHN => Ok(Region::China),
260            ctru_sys::CFG_REGION_KOR => Ok(Region::Korea),
261            ctru_sys::CFG_REGION_TWN => Ok(Region::Taiwan),
262            _ => Err(()),
263        }
264    }
265}
266
267impl TryFrom<i8> for Language {
268    type Error = ();
269
270    fn try_from(value: i8) -> Result<Self, Self::Error> {
271        match value {
272            ctru_sys::CFG_LANGUAGE_JP => Ok(Language::Japanese),
273            ctru_sys::CFG_LANGUAGE_EN => Ok(Language::English),
274            ctru_sys::CFG_LANGUAGE_FR => Ok(Language::French),
275            ctru_sys::CFG_LANGUAGE_DE => Ok(Language::German),
276            ctru_sys::CFG_LANGUAGE_IT => Ok(Language::Italian),
277            ctru_sys::CFG_LANGUAGE_ES => Ok(Language::Spanish),
278            ctru_sys::CFG_LANGUAGE_ZH => Ok(Language::SimplifiedChinese),
279            ctru_sys::CFG_LANGUAGE_KO => Ok(Language::Korean),
280            ctru_sys::CFG_LANGUAGE_NL => Ok(Language::Dutch),
281            ctru_sys::CFG_LANGUAGE_PT => Ok(Language::Portuguese),
282            ctru_sys::CFG_LANGUAGE_RU => Ok(Language::Russian),
283            ctru_sys::CFG_LANGUAGE_TW => Ok(Language::TraditionalChinese),
284            _ => Err(()),
285        }
286    }
287}
288
289impl TryFrom<u8> for SystemModel {
290    type Error = ();
291
292    fn try_from(value: u8) -> Result<Self, Self::Error> {
293        match value {
294            ctru_sys::CFG_MODEL_3DS => Ok(SystemModel::Old3DS),
295            ctru_sys::CFG_MODEL_3DSXL => Ok(SystemModel::Old3DSXL),
296            ctru_sys::CFG_MODEL_N3DS => Ok(SystemModel::New3DS),
297            ctru_sys::CFG_MODEL_2DS => Ok(SystemModel::Old2DS),
298            ctru_sys::CFG_MODEL_N3DSXL => Ok(SystemModel::New3DSXL),
299            ctru_sys::CFG_MODEL_N2DSXL => Ok(SystemModel::New2DSXL),
300            _ => Err(()),
301        }
302    }
303}