Skip to content

Commit

Permalink
Merge pull request #103 from rust-embedded-community/handles-own-volu…
Browse files Browse the repository at this point in the history
…me-mgr

Smart Handles
  • Loading branch information
thejpster authored Oct 28, 2023
2 parents dd8835c + db74a65 commit 2f14459
Show file tree
Hide file tree
Showing 20 changed files with 835 additions and 335 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic

## [Unreleased]

* None
* `Volume`, `Directory` and `File` are now smart! They hold references to the thing they were made from, and will clean themselves up when dropped. The trade-off is you can can't open multiple volumes, directories or files at the same time.
* Renamed the old types to `RawVolume`, `RawDirectory` and `RawFile`

## [Version 0.6.0] - 2023-10-20

Expand Down
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ log = {version = "0.4", default-features = false, optional = true}
env_logger = "0.9"
hex-literal = "0.3"
flate2 = "1.0"
sha256 = "1.4"
sha2 = "0.10"
chrono = "0.4"

[features]
default = ["log"]
defmt-log = ["defmt"]
defmt-log = ["dep:defmt"]
log = ["dep:log"]
24 changes: 8 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ designed for readability and simplicity over performance.
You will need something that implements the `BlockDevice` trait, which can read and write the 512-byte blocks (or sectors) from your card. If you were to implement this over USB Mass Storage, there's no reason this crate couldn't work with a USB Thumb Drive, but we only supply a `BlockDevice` suitable for reading SD and SDHC cards over SPI.

```rust
// Build an SD Card interface out of an SPI device, a chip-select pin and a delay object
// Build an SD Card interface out of an SPI device, a chip-select pin and the delay object
let sdcard = embedded_sdmmc::SdCard::new(sdmmc_spi, sdmmc_cs, delay);
// Get the card size (this also triggers card initialisation because it's not been done yet)
println!("Card size is {} bytes", sdcard.num_bytes()?);
Expand All @@ -20,29 +20,21 @@ println!("Card size is {} bytes", sdcard.num_bytes()?);
let mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, time_source);
// Try and access Volume 0 (i.e. the first partition).
// The volume object holds information about the filesystem on that volume.
// It doesn't hold a reference to the Volume Manager and so must be passed back
// to every Volume Manager API call. This makes it easier to handle multiple
// volumes in parallel.
let volume0 = volume_mgr.get_volume(embedded_sdmmc::VolumeIdx(0))?;
let mut volume0 = volume_mgr.open_volume(embedded_sdmmc::VolumeIdx(0))?;
println!("Volume 0: {:?}", volume0);
// Open the root directory (passing in the volume we're using).
let root_dir = volume_mgr.open_root_dir(&volume0)?;
// Open the root directory (mutably borrows from the volume).
let mut root_dir = volume0.open_root_dir()?;
// Open a file called "MY_FILE.TXT" in the root directory
let my_file = volume_mgr.open_file_in_dir(
root_dir,
"MY_FILE.TXT",
embedded_sdmmc::Mode::ReadOnly,
)?;
// This mutably borrows the directory.
let mut my_file = root_dir.open_file_in_dir("MY_FILE.TXT", embedded_sdmmc::Mode::ReadOnly)?;
// Print the contents of the file
while !volume_manager.file_eof(my_file).unwrap() {
while !my_file.is_eof() {
let mut buffer = [0u8; 32];
let num_read = volume_mgr.read(&volume0, &mut my_file, &mut buffer)?;
let num_read = my_file.read(&mut buffer)?;
for b in &buffer[0..num_read] {
print!("{}", *b as char);
}
}
volume_mgr.close_file(my_file)?;
volume_mgr.close_dir(root_dir)?;
```

### Open directories and files
Expand Down
10 changes: 4 additions & 6 deletions examples/append_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume_mgr.open_root_dir(volume)?;
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
let mut root_dir = volume.open_root_dir()?;
println!("\nCreating file {}...", FILE_TO_APPEND);
let f = volume_mgr.open_file_in_dir(root_dir, FILE_TO_APPEND, Mode::ReadWriteAppend)?;
volume_mgr.write(f, b"\r\n\r\nThis has been added to your file.\r\n")?;
volume_mgr.close_file(f)?;
volume_mgr.close_dir(root_dir)?;
let mut f = root_dir.open_file_in_dir(FILE_TO_APPEND, Mode::ReadWriteAppend)?;
f.write(b"\r\n\r\nThis has been added to your file.\r\n")?;
Ok(())
}

Expand Down
10 changes: 4 additions & 6 deletions examples/create_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,14 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume_mgr.open_root_dir(volume)?;
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
let mut root_dir = volume.open_root_dir()?;
println!("\nCreating file {}...", FILE_TO_CREATE);
// This will panic if the file already exists: use ReadWriteCreateOrAppend
// or ReadWriteCreateOrTruncate instead if you want to modify an existing
// file.
let f = volume_mgr.open_file_in_dir(root_dir, FILE_TO_CREATE, Mode::ReadWriteCreate)?;
volume_mgr.write(f, b"Hello, this is a new file on disk\r\n")?;
volume_mgr.close_file(f)?;
volume_mgr.close_dir(root_dir)?;
let mut f = root_dir.open_file_in_dir(FILE_TO_CREATE, Mode::ReadWriteCreate)?;
f.write(b"Hello, this is a new file on disk\r\n")?;
Ok(())
}

Expand Down
7 changes: 3 additions & 4 deletions examples/delete_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,11 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume_mgr.open_root_dir(volume)?;
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
let mut root_dir = volume.open_root_dir()?;
println!("Deleting file {}...", FILE_TO_DELETE);
volume_mgr.delete_file_in_dir(root_dir, FILE_TO_DELETE)?;
root_dir.delete_file_in_dir(FILE_TO_DELETE)?;
println!("Deleted!");
volume_mgr.close_dir(root_dir)?;
Ok(())
}

Expand Down
17 changes: 7 additions & 10 deletions examples/list_dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,22 @@ fn main() -> Result<(), Error> {
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume_mgr.open_root_dir(volume)?;
list_dir(&mut volume_mgr, root_dir, "/")?;
volume_mgr.close_dir(root_dir)?;
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume.open_root_dir()?;
list_dir(root_dir, "/")?;
Ok(())
}

/// Recursively print a directory listing for the open directory given.
///
/// The path is for display purposes only.
fn list_dir(
volume_mgr: &mut VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4>,
directory: Directory,
mut directory: Directory<LinuxBlockDevice, Clock, 8, 8, 4>,
path: &str,
) -> Result<(), Error> {
println!("Listing {}", path);
let mut children = Vec::new();
volume_mgr.iterate_dir(directory, |entry| {
directory.iterate_dir(|entry| {
println!(
"{:12} {:9} {} {}",
entry.name,
Expand All @@ -87,14 +85,13 @@ fn list_dir(
}
})?;
for child_name in children {
let child_dir = volume_mgr.open_dir(directory, &child_name)?;
let child_dir = directory.open_dir(&child_name)?;
let child_path = if path == "/" {
format!("/{}", child_name)
} else {
format!("{}/{}", path, child_name)
};
list_dir(volume_mgr, child_dir, &child_path)?;
volume_mgr.close_dir(child_dir)?;
list_dir(child_dir, &child_path)?;
}
Ok(())
}
Expand Down
14 changes: 6 additions & 8 deletions examples/read_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,14 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume_mgr.open_root_dir(volume)?;
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
let mut root_dir = volume.open_root_dir()?;
println!("\nReading file {}...", FILE_TO_READ);
let f = volume_mgr.open_file_in_dir(root_dir, FILE_TO_READ, Mode::ReadOnly)?;
volume_mgr.close_dir(root_dir)?;
while !volume_mgr.file_eof(f)? {
let mut f = root_dir.open_file_in_dir(FILE_TO_READ, Mode::ReadOnly)?;
while !f.is_eof() {
let mut buffer = [0u8; 16];
let offset = volume_mgr.file_offset(f)?;
let mut len = volume_mgr.read(f, &mut buffer)?;
let offset = f.offset();
let mut len = f.read(&mut buffer)?;
print!("{:08x} {:02x?}", offset, &buffer[0..len]);
while len < buffer.len() {
print!(" ");
Expand All @@ -74,7 +73,6 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
}
println!("|");
}
volume_mgr.close_file(f)?;
Ok(())
}

Expand Down
19 changes: 7 additions & 12 deletions examples/readme_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,26 +87,21 @@ fn main() -> Result<(), Error> {
let mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, time_source);
// Try and access Volume 0 (i.e. the first partition).
// The volume object holds information about the filesystem on that volume.
// It doesn't hold a reference to the Volume Manager and so must be passed back
// to every Volume Manager API call. This makes it easier to handle multiple
// volumes in parallel.
let volume0 = volume_mgr.open_volume(embedded_sdmmc::VolumeIdx(0))?;
let mut volume0 = volume_mgr.open_volume(embedded_sdmmc::VolumeIdx(0))?;
println!("Volume 0: {:?}", volume0);
// Open the root directory (passing in the volume we're using).
let root_dir = volume_mgr.open_root_dir(volume0)?;
// Open the root directory (mutably borrows from the volume).
let mut root_dir = volume0.open_root_dir()?;
// Open a file called "MY_FILE.TXT" in the root directory
let my_file =
volume_mgr.open_file_in_dir(root_dir, "MY_FILE.TXT", embedded_sdmmc::Mode::ReadOnly)?;
// This mutably borrows the directory.
let mut my_file = root_dir.open_file_in_dir("MY_FILE.TXT", embedded_sdmmc::Mode::ReadOnly)?;
// Print the contents of the file
while !volume_mgr.file_eof(my_file).unwrap() {
while !my_file.is_eof() {
let mut buffer = [0u8; 32];
let num_read = volume_mgr.read(my_file, &mut buffer)?;
let num_read = my_file.read(&mut buffer)?;
for b in &buffer[0..num_read] {
print!("{}", *b as char);
}
}
volume_mgr.close_file(my_file)?;
volume_mgr.close_dir(root_dir)?;
Ok(())
}

Expand Down
Loading

0 comments on commit 2f14459

Please sign in to comment.