1pub use embedded_svc::utils::io as utils;
2pub use esp_idf_hal::io::*;
3
4#[cfg(esp_idf_comp_vfs_enabled)]
5pub mod vfs {
6 use core::borrow::BorrowMut;
7 use core::marker::PhantomData;
8
9 use crate::hal::uart::UartDriver;
10 #[cfg(esp_idf_soc_usb_serial_jtag_supported)]
11 use crate::hal::usb_serial::UsbSerialDriver;
12 use crate::sys::{self, EspError};
13 #[cfg(not(esp_idf_version_at_least_6_0_0))]
14 use crate::sys::{esp_vfs_dev_uart_use_driver, esp_vfs_dev_uart_use_nonblocking};
15 #[cfg(all(
16 not(esp_idf_version_at_least_6_0_0),
17 esp_idf_soc_usb_serial_jtag_supported
18 ))]
19 use crate::sys::{esp_vfs_usb_serial_jtag_use_driver, esp_vfs_usb_serial_jtag_use_nonblocking};
20 #[cfg(esp_idf_version_at_least_6_0_0)]
21 use crate::sys::{
22 uart_vfs_dev_use_driver as esp_vfs_dev_uart_use_driver,
23 uart_vfs_dev_use_nonblocking as esp_vfs_dev_uart_use_nonblocking,
24 };
25 #[cfg(all(esp_idf_version_at_least_6_0_0, esp_idf_soc_usb_serial_jtag_supported))]
26 use crate::sys::{
27 usb_serial_jtag_vfs_use_driver as esp_vfs_usb_serial_jtag_use_driver,
28 usb_serial_jtag_vfs_use_nonblocking as esp_vfs_usb_serial_jtag_use_nonblocking,
29 };
30
31 #[cfg(feature = "alloc")]
32 extern crate alloc;
33
34 pub struct MountedEventfs(());
38
39 impl MountedEventfs {
40 #[allow(clippy::needless_update)]
45 pub fn mount(max_fds: usize) -> Result<Self, sys::EspError> {
46 sys::esp!(unsafe {
47 sys::esp_vfs_eventfd_register(&sys::esp_vfs_eventfd_config_t {
48 max_fds: max_fds as _,
49 ..Default::default()
50 })
51 })?;
52
53 Ok(Self(()))
54 }
55 }
56
57 impl Drop for MountedEventfs {
58 fn drop(&mut self) {
59 sys::esp!(unsafe { sys::esp_vfs_eventfd_unregister() }).unwrap();
60 }
61 }
62
63 #[cfg(feature = "alloc")]
65 pub struct MountedSpiffs<T> {
66 _spiffs: T,
67 path: alloc::ffi::CString,
68 }
69
70 #[cfg(feature = "alloc")]
71 impl<T> MountedSpiffs<T> {
72 pub fn mount(mut spiffs: T, path: &str, max_fds: usize) -> Result<Self, sys::EspError>
79 where
80 T: core::borrow::BorrowMut<crate::fs::spiffs::Spiffs>,
81 {
82 let path = crate::private::cstr::to_cstring_arg(path)?;
83
84 sys::esp!(unsafe {
85 sys::esp_vfs_spiffs_register(&sys::esp_vfs_spiffs_conf_t {
86 base_path: path.as_ptr(),
87 max_files: max_fds as _,
88 partition_label: spiffs.borrow_mut().partition_label().as_ptr(),
89 format_if_mount_failed: false,
90 })
91 })?;
92
93 Ok(Self {
94 _spiffs: spiffs,
95 path,
96 })
97 }
98 }
99
100 #[cfg(feature = "alloc")]
101 impl<T> Drop for MountedSpiffs<T> {
102 fn drop(&mut self) {
103 sys::esp!(unsafe { sys::esp_vfs_spiffs_unregister(self.path.as_ptr()) }).unwrap();
104 }
105 }
106
107 #[cfg(feature = "alloc")]
109 pub struct MountedFatfs<T> {
110 _handle: *mut sys::FATFS,
111 _fatfs: T,
112 path: alloc::ffi::CString,
113 drive: u8,
114 }
115
116 #[cfg(feature = "alloc")]
117 impl<T> MountedFatfs<T> {
118 pub fn mount<H>(mut fatfs: T, path: &str, max_fds: usize) -> Result<Self, sys::EspError>
125 where
126 T: core::borrow::BorrowMut<crate::fs::fatfs::Fatfs<H>>,
127 {
128 let path = crate::private::cstr::to_cstring_arg(path)?;
129 let drive_path = fatfs.borrow_mut().drive_path();
130
131 let mut handle = core::ptr::null_mut();
132
133 #[cfg(esp_idf_version_at_least_5_3_0)]
134 let conf = sys::esp_vfs_fat_conf_t {
135 base_path: path.as_ptr(),
136 fat_drive: drive_path.as_ptr(),
137 max_files: max_fds as _,
138 };
139
140 sys::esp!(unsafe {
141 #[cfg(not(esp_idf_version_at_least_5_3_0))]
142 {
143 sys::esp_vfs_fat_register(
144 path.as_ptr(),
145 drive_path.as_ptr(),
146 max_fds as _,
147 &mut handle,
148 )
149 }
150 #[cfg(all(esp_idf_version_at_least_5_3_0, not(esp_idf_version_at_least_6_1_0)))]
152 {
153 sys::esp_vfs_fat_register_cfg(&conf, &mut handle)
154 }
155 #[cfg(esp_idf_version_at_least_6_1_0)]
157 {
158 sys::esp_vfs_fat_register(&conf, &mut handle)
159 }
160 })?;
161
162 unsafe {
163 sys::f_mount(handle, drive_path.as_ptr(), 0); }
165
166 let drive = fatfs.borrow_mut().drive();
167
168 Ok(Self {
169 _handle: handle,
170 _fatfs: fatfs,
171 path,
172 drive,
173 })
174 }
175 }
176
177 #[cfg(feature = "alloc")]
178 impl<T> Drop for MountedFatfs<T> {
179 fn drop(&mut self) {
180 let drive_path = crate::fs::fatfs::Fatfs::<()>::drive_path_from(self.drive);
181
182 unsafe {
183 sys::f_mount(core::ptr::null_mut(), drive_path.as_ptr(), 0);
184 }
185
186 sys::esp!(unsafe { sys::esp_vfs_fat_unregister_path(self.path.as_ptr()) }).unwrap();
187 }
188 }
189
190 #[cfg(all(feature = "alloc", esp_idf_comp_joltwallet__littlefs_enabled))]
192 pub struct MountedLittlefs<T> {
193 _littlefs: T,
194 partition_raw_data: crate::fs::littlefs::PartitionRawData,
195 }
196
197 #[cfg(all(feature = "alloc", esp_idf_comp_joltwallet__littlefs_enabled))]
198 impl<T> MountedLittlefs<T> {
199 pub fn mount<H>(mut littlefs: T, path: &str) -> Result<Self, sys::EspError>
205 where
206 T: core::borrow::BorrowMut<crate::fs::littlefs::Littlefs<H>>,
207 {
208 use crate::fs::littlefs::PartitionRawData;
209 use crate::private::cstr::to_cstring_arg;
210
211 let path = to_cstring_arg(path)?;
212
213 let partition_raw_data = littlefs.borrow_mut().partition_raw_data();
214
215 let conf = sys::esp_vfs_littlefs_conf_t {
216 base_path: path.as_ptr(),
217 partition_label: if let PartitionRawData::PartitionLabel(label) = partition_raw_data
218 {
219 label
220 } else {
221 core::ptr::null()
222 },
223 partition: if let PartitionRawData::RawPartition(partition) = partition_raw_data {
224 partition
225 } else {
226 core::ptr::null_mut()
227 },
228 #[cfg(esp_idf_littlefs_sdmmc_support)]
229 sdcard: if let PartitionRawData::SdCard(sdcard) = partition_raw_data {
230 sdcard
231 } else {
232 core::ptr::null_mut()
233 },
234 ..Default::default()
235 };
236
237 sys::esp!(unsafe { sys::esp_vfs_littlefs_register(&conf) })?;
238
239 Ok(Self {
240 _littlefs: littlefs,
241 partition_raw_data,
242 })
243 }
244
245 pub fn info(&self) -> Result<crate::fs::littlefs::LittleFsInfo, sys::EspError> {
246 use crate::fs::littlefs::PartitionRawData;
247
248 let mut info = crate::fs::littlefs::LittleFsInfo {
249 total_bytes: 0,
250 used_bytes: 0,
251 };
252
253 match self.partition_raw_data {
254 #[cfg(esp_idf_littlefs_sdmmc_support)]
255 PartitionRawData::SdCard(sd_card_ptr) => {
256 sys::esp!(unsafe {
257 sys::esp_littlefs_sdmmc_info(
258 sd_card_ptr,
259 &mut info.total_bytes,
260 &mut info.used_bytes,
261 )
262 })?;
263 }
264 PartitionRawData::PartitionLabel(label) => {
265 sys::esp!(unsafe {
266 sys::esp_littlefs_info(label, &mut info.total_bytes, &mut info.used_bytes)
267 })?;
268 }
269 PartitionRawData::RawPartition(partition) => {
270 sys::esp!(unsafe {
271 sys::esp_littlefs_partition_info(
272 partition,
273 &mut info.total_bytes,
274 &mut info.used_bytes,
275 )
276 })?;
277 }
278 }
279
280 Ok(info)
281 }
282 }
283
284 #[cfg(all(feature = "alloc", esp_idf_comp_joltwallet__littlefs_enabled))]
285 impl<T> Drop for MountedLittlefs<T> {
286 fn drop(&mut self) {
287 use crate::fs::littlefs::PartitionRawData;
288
289 match self.partition_raw_data {
290 PartitionRawData::PartitionLabel(label) => {
291 sys::esp!(unsafe { sys::esp_vfs_littlefs_unregister(label) }).unwrap();
292 }
293 PartitionRawData::RawPartition(partition) => {
294 sys::esp!(unsafe { sys::esp_vfs_littlefs_unregister_partition(partition) })
295 .unwrap();
296 }
297 #[cfg(esp_idf_littlefs_sdmmc_support)]
298 PartitionRawData::SdCard(sdcard) => {
299 sys::esp!(unsafe { sys::esp_vfs_littlefs_unregister_sdmmc(sdcard) }).unwrap();
300 }
301 }
302 }
303 }
304
305 pub struct BlockingStdIo<'d, T> {
315 uart_port: Option<crate::sys::uart_port_t>,
316 _driver: T,
317 _t: PhantomData<&'d mut ()>,
318 }
319
320 impl<'d, T> BlockingStdIo<'d, T>
321 where
322 T: BorrowMut<UartDriver<'d>>,
323 {
324 pub fn uart(driver: T) -> Result<Self, EspError> {
329 unsafe { esp_vfs_dev_uart_use_driver(driver.borrow().port() as _) }
330
331 Ok(Self {
332 uart_port: Some(driver.borrow().port()),
333 _driver: driver,
334 _t: PhantomData,
335 })
336 }
337 }
338
339 #[cfg(esp_idf_soc_usb_serial_jtag_supported)]
340 impl<'d, T> BlockingStdIo<'d, T>
341 where
342 T: BorrowMut<UsbSerialDriver<'d>>,
343 {
344 pub fn usb_serial(driver: T) -> Result<Self, EspError> {
360 unsafe { esp_vfs_usb_serial_jtag_use_driver() }
361
362 Ok(Self {
363 uart_port: None,
364 _driver: driver,
365 _t: PhantomData,
366 })
367 }
368 }
369
370 impl<T> Drop for BlockingStdIo<'_, T> {
371 fn drop(&mut self) {
372 if let Some(port) = self.uart_port {
373 unsafe { esp_vfs_dev_uart_use_nonblocking(port as _) }
374 } else {
375 #[cfg(esp_idf_soc_usb_serial_jtag_supported)]
376 {
377 unsafe { esp_vfs_usb_serial_jtag_use_nonblocking() }
378 }
379 }
380 }
381 }
382}