/** * \file * * * \brief FatFS: kfile interface for FatFS module by ChaN. * * * \author Luca Ottaviano * */ #include "fat.h" static size_t fatfile_read(struct KFile *_fd, void *buf, size_t size) { FatFile *fd = FATFILE_CAST(_fd); UINT count; fd->error_code = f_read(&fd->fat_file, buf, size, &count); return count; } static size_t fatfile_write(struct KFile *_fd, const void *buf, size_t size) { FatFile *fd = FATFILE_CAST(_fd); UINT count; fd->error_code = f_write(&fd->fat_file, buf, size, &count); return count; } static int fatfile_close(struct KFile *_fd) { FatFile *fd = FATFILE_CAST(_fd); fd->error_code = f_close(&fd->fat_file); if (fd->error_code) return EOF; else return 0; } static kfile_off_t fatfile_seek(struct KFile *_fd, kfile_off_t offset, KSeekMode whence) { /* clip at start-of-file * don't clip at end-of-file when in write mode */ FatFile *fd = FATFILE_CAST(_fd); DWORD lseek_offset = 0; switch (whence) { case KSM_SEEK_SET: if (offset > 0) lseek_offset = (DWORD) offset; break; case KSM_SEEK_CUR: if (offset > 0) lseek_offset = fd->fat_file.fptr + (DWORD) offset; else { if (fd->fat_file.fptr > (DWORD) (-offset)) lseek_offset = fd->fat_file.fptr - (DWORD)(-offset); } break; case KSM_SEEK_END: if (offset > 0) lseek_offset = fd->fat_file.fsize + (DWORD) offset; else { if (fd->fat_file.fsize > (DWORD) (-offset)) lseek_offset = fd->fat_file.fsize + (DWORD) offset; } break; } fd->error_code = f_lseek(&fd->fat_file, lseek_offset); if ((fd->error_code) || (fd->fat_file.fptr != lseek_offset)) return EOF; else /* TODO: this conversion may overflow */ return (kfile_off_t)fd->fat_file.fptr; } static int fatfile_flush(struct KFile *_fd) { FatFile *fd = FATFILE_CAST(_fd); fd->error_code = f_sync(&fd->fat_file); if (fd->error_code) return EOF; else return 0; } static int fatfile_error(struct KFile *_fd) { FatFile *fd = FATFILE_CAST(_fd); return (int)fd->error_code; } static void fatfile_clearerr(struct KFile *_fd) { FatFile *fd = FATFILE_CAST(_fd); fd->error_code = FR_OK; } FRESULT fatfile_open(FatFile *file, const char *file_path, BYTE mode) { DB(file->fd._type = KFT_FATFILE); file->fd.read = fatfile_read; file->fd.write = fatfile_write; file->fd.reopen = 0; file->fd.close = fatfile_close; file->fd.seek = fatfile_seek; file->fd.flush = fatfile_flush; file->fd.error = fatfile_error; file->fd.clearerr = fatfile_clearerr; return f_open(&file->fat_file, file_path, mode); }