56 for (uint32_t i = 0; i < n; i++) {
101 const uint32_t cluster_idx_now = (uint32_t)(file->offset / cluster_bytes);
105 if (file->no_fat_chain != 0U) {
106 target = file->first_cluster + cluster_idx_now;
124 uint32_t walk_from = file->first_cluster;
125 uint32_t walk_n = cluster_idx_now;
127 (cluster_idx_now >= file->walk_cache_idx)) {
128 walk_from = file->walk_cache_cluster;
129 walk_n = cluster_idx_now - file->walk_cache_idx;
135 file->walk_cache_idx = cluster_idx_now;
136 file->walk_cache_cluster = target;
138 file->cur_cluster = target;
139 const uint32_t off_in_cluster = (uint32_t)(file->offset % cluster_bytes);
140 const uint32_t sector_in_cluster = off_in_cluster /
priv_bps(file->mount);
141 const uint32_t off_in_sector = off_in_cluster %
priv_bps(file->mount);
142 const uint64_t lba =
priv_cluster_to_lba(file->mount, file->cur_cluster) + sector_in_cluster;
148 uint32_t take =
priv_bps(file->mount) - off_in_sector;
149 if (take > remaining) {
197 const uint64_t valid =
199 if (file->offset >= valid) {
200 for (uint32_t i = 0U; i < remaining; i++) {
203 *out_take = remaining;
206 uint32_t want = remaining;
207 const uint64_t cap = valid - file->offset;
208 if ((uint64_t)want > cap) {
209 want = (uint32_t)cap;
247 if (file ==
nullptr || buf ==
nullptr || got_len ==
nullptr) {
250 if (file->in_use == 0U) {
251 return k_ra8_err_invalid_state;
254 if (file->offset >= file->size_bytes || max_len == 0U) {
257 const uint64_t left = file->size_bytes - file->offset;
258 uint32_t remaining = max_len;
259 if ((uint64_t)max_len > left) {
260 remaining = (uint32_t)left;
262 uint32_t produced = 0;
263 while (remaining > 0U) {
270 file->offset += take;
315 uint32_t cur = start;
316 for (uint32_t i = 0; i < idx; i++) {
343 uint32_t off_in_sector,
413 file->first_cluster = c;
414 file->cur_cluster = c;
458 uint32_t consumed = 0;
460 file->walk_cache_cluster = 0;
461 write_walk_t way = {.cluster = file->first_cluster, .index = 0U};
462 while (consumed < len) {
463 const uint32_t cluster_idx_now = (uint32_t)(file->offset / cluster_bytes);
469 file->cur_cluster = cur;
470 const uint32_t off_in_cluster = (uint32_t)(file->offset % cluster_bytes);
471 const uint32_t sector_in_cluster = off_in_cluster /
priv_bps(m);
472 const uint32_t off_in_sector = off_in_cluster %
priv_bps(m);
474 uint32_t put =
priv_bps(m) - off_in_sector;
475 if (put > (len - consumed)) {
476 put = len - consumed;
484 if (file->offset > file->size_bytes) {
485 file->size_bytes = file->offset;
521 if (file ==
nullptr || buf ==
nullptr) {
525 return k_ra8_err_invalid_state;
531 const ra8_err_t xe = priv_exfat_write_stream(file, buf, len);
532 if (xe != k_ra8_ok) {
543 return k_ra8_err_invalid_size;
557 (uint32_t)file->size_bytes);
612 if (handle ==
nullptr) {
615 if (path ==
nullptr) {
618 if (data ==
nullptr) {
621 if (handle->in_use == 0U) {
622 return k_ra8_err_invalid_state;
664 if (file ==
nullptr) {
667 if (file->in_use == 0U) {
668 return k_ra8_err_invalid_state;
670 uint64_t target = offset_bytes;
671 if (target > file->size_bytes) {
672 target = file->size_bytes;
674 file->offset = target;
705 if (file ==
nullptr || out_offset ==
nullptr) {
708 if (file->in_use == 0U) {
709 return k_ra8_err_invalid_state;
711 *out_offset = file->offset;
742 if (file ==
nullptr || out_bytes ==
nullptr) {
745 if (file->in_use == 0U) {
746 return k_ra8_err_invalid_state;
748 *out_bytes = file->size_bytes;
Annotation-attribute framework macros for ra8-firmware.
#define RA8_OWNS_RESOURCE(kind)
RAII-style resource ownership contract.
#define RA8_EXPECTS_LOCK(name)
The function expects the named thread/IRQ lock to be held on entry.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
ra8_err_t ra8_fs_write(ra8_fs_file_t *file, const uint8_t *buf, uint32_t len)
Write len bytes; allocate new clusters from FAT free-space scan as needed.
ra8_err_t ra8_fs_size(const ra8_fs_file_t *file, uint64_t *out_bytes)
Report the file's size in bytes (64-bit on exFAT, #676).
ra8_err_t ra8_fs_read(ra8_fs_file_t *file, uint8_t *buf, uint32_t max_len, uint32_t *got_len)
Read up to max_len bytes; advance the cluster chain on cluster crossings.
ra8_err_t ra8_fs_seek(ra8_fs_file_t *file, uint64_t offset_bytes)
Move the file offset to offset_bytes (clamped to size).
ra8_err_t ra8_fs_tell(const ra8_fs_file_t *file, uint64_t *out_offset)
Report the current offset (64-bit; see ra8_fs_seek).
ra8_err_t ra8_fs_write_file(ra8_fs_mount_t *handle, const char *path, const uint8_t *data, uint32_t len)
Create a whole file in one call (provisioning helper).
ra8_err_t priv_fat_get(const ra8_fs_mount_t *m, uint32_t cluster, uint32_t *out_value)
Fetch the FAT entry for cluster, returning the next-cluster value.
ra8_err_t priv_fat_set(const ra8_fs_mount_t *m, uint32_t cluster, uint32_t value)
Write value into the FAT entry for cluster across every FAT copy.
uint64_t priv_cluster_to_lba(const ra8_fs_mount_t *m, uint32_t cluster)
Convert a cluster number into its first data-region LBA.
uint8_t priv_is_eoc(const ra8_fs_mount_t *m, uint32_t value)
Test whether value is an end-of-chain marker for this FAT type.
ra8_err_t priv_read_sector(const ra8_fs_mount_t *m, uint64_t lba, uint8_t *buf)
Read a single sector into the module scratch buffer.
uint32_t priv_bps(const ra8_fs_mount_t *m)
One mounted volume's sector size in bytes.
uint32_t priv_eoc_write(const ra8_fs_mount_t *m)
End-of-chain value to write for this FAT type.
ra8_err_t priv_alloc_cluster(const ra8_fs_mount_t *m, uint32_t *out_cluster)
Free-cluster scan from the next-free hint, wrapping exactly once.
void priv_byte_copy(uint8_t *dst, const uint8_t *src, uint32_t n)
Length-checked byte copy used in place of memcpy().
uint32_t priv_cluster_bytes(const ra8_fs_mount_t *m)
One mounted volume's cluster size in bytes.
ra8_err_t priv_write_sector(const ra8_fs_mount_t *m, uint64_t lba, const uint8_t *buf)
Write a single sector from a caller-provided buffer.
uint8_t * priv_sec_io(void)
The IO-role sector buffer (leaf data / bitmap sector transfers).
uint8_t * priv_sec_walk(void)
The WALK-role sector buffer (directory scans and entry RMW).
ra8_err_t priv_exfat_flush_set(ra8_fs_file_t *file)
Rewrite a file's entry set from the handle, checksum last.
ra8_err_t priv_close_locked(ra8_fs_file_t *file)
Close an open file – the guarded body of ra8_fs_close().
void priv_entry_set_cluster_size(uint8_t *entry, uint32_t cluster, uint32_t size)
Patch first-cluster + size back into a 32-byte directory entry.
void priv_fat_entry_apply_attr(uint8_t *entry, uint8_t set_mask, uint8_t clear_mask)
Clear then set attribute bits in a 32-byte FAT directory entry.
ra8_err_t priv_open_locked(ra8_fs_mount_t *handle, const char *path, ra8_fs_mode_t mode, ra8_fs_file_t **out_file)
Open a file by path – the guarded body of ra8_fs_open().
static ra8_err_t internal_write_stream(ra8_fs_file_t *file, const uint8_t *buf, uint32_t len)
Inner write loop: stream len bytes from buf into the file's chain.
static ra8_err_t internal_skip_clusters(const ra8_fs_mount_t *m, uint32_t start, uint32_t n, uint32_t *out)
Walk n clusters forward from start along the FAT chain.
static ra8_err_t internal_seek_locked(ra8_fs_file_t *file, uint64_t offset_bytes)
Move the cursor – the guarded body of ra8_fs_seek().
static ra8_err_t internal_tell_locked(const ra8_fs_file_t *file, uint64_t *out_offset)
Report the cursor – the guarded body of ra8_fs_tell().
static ra8_err_t internal_walk_grow(const ra8_fs_mount_t *m, uint32_t start, uint32_t idx, uint32_t *out_cluster)
Walk to cluster index idx from start, growing the chain as needed.
static ra8_err_t internal_write_position(ra8_fs_file_t *file, write_walk_t *way, uint32_t idx, uint32_t *out_cluster)
Position the write cursor at chain index idx, growing as needed.
static ra8_err_t internal_write_locked(ra8_fs_file_t *file, const uint8_t *buf, uint32_t len)
Write bytes – the guarded body of ra8_fs_write().
static ra8_err_t internal_size_locked(const ra8_fs_file_t *file, uint64_t *out_bytes)
Report the size – the guarded body of ra8_fs_size().
static ra8_err_t internal_read_one_chunk(ra8_fs_file_t *file, uint8_t *buf, uint32_t remaining, uint32_t *out_take)
Read up to one sector's worth of bytes at the file's current offset.
ra8_err_t priv_alloc_eoc_cluster(const ra8_fs_mount_t *m, uint32_t *out_c)
Allocate a fresh cluster, mark it EOC, and return its number.
static ra8_err_t internal_read_span(ra8_fs_file_t *file, uint8_t *buf, uint32_t remaining, uint32_t *out_take)
Read one span, serving zeros past exFAT's ValidDataLength.
ra8_err_t priv_write_into_sector(const ra8_fs_mount_t *m, uint64_t lba, uint32_t off_in_sector, const uint8_t *src, uint32_t put)
Implementation of priv_write_into_sector() – one read-modify-write.
static ra8_err_t internal_read_locked(ra8_fs_file_t *file, uint8_t *buf, uint32_t max_len, uint32_t *got_len)
Read bytes – the guarded body of ra8_fs_read().
static ra8_err_t internal_write_file_locked(ra8_fs_mount_t *handle, const char *path, const uint8_t *data, uint32_t len)
Create a whole file – the guarded body of ra8_fs_write_file().
Cross-TU shared declarations for the FAT/exFAT ra8_fs adapter.
void priv_lock_release(void)
Drop the library lock taken by priv_lock_acquire.
void priv_lock_acquire(void)
Take the library lock, if the caller installed one.
void priv_fat_entry_stamp_write(uint8_t *entry)
Advance a FAT directory entry's modification time and access date.
@ k_cluster_first_data
Cluster numbers start at 2.
@ k_ra8_fs_fat_max_file_bytes
4 GiB - 1: max DIR_FileSize.
@ k_ra8_fs_type_exfat
exFAT (read + streaming write + format).
@ k_ra8_fs_attr_archive
MS FAT spec sec 6 "ATTR_ARCHIVE".
@ k_ra8_fs_mode_read
Read-only, must exist.
@ k_ra8_fs_mode_write
Truncate (or create) for writing.
Cached parse of one mounted FAT volume.
Forward waypoint carried across one write's grow-walks.
uint32_t index
Chain index of cluster.
uint32_t cluster
Cluster the last walk reached.