From: batt Date: Thu, 21 May 2009 13:12:04 +0000 (+0000) Subject: Add emulated driver for fatfs. X-Git-Tag: 2.2.0~272 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;ds=sidebyside;h=7d2a034f13052a2dfafda1075ba4eaf975f9f742;p=bertos.git Add emulated driver for fatfs. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@2696 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/bertos/emul/diskio_emul.c b/bertos/emul/diskio_emul.c new file mode 100644 index 00000000..c87a2fea --- /dev/null +++ b/bertos/emul/diskio_emul.c @@ -0,0 +1,220 @@ +/** + * \file + * + * + * \brief Low level disk access for FatFs emulated. + * + * \version $Id$ + * \author Luca Ottaviano + */ + +/*-----------------------------------------------------------------------*/ +/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */ +/*-----------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#define SECTOR_SIZE 512 + +static volatile DSTATUS Stat = STA_NOINIT; + +/** + * This is an example implementation, used to simulate the the calls to normal filesystem calls + * It only works for drive 0. + */ + + +/*-----------------------------------------------------------------------*/ +/* Inidialize a Drive */ + +static FILE *fake_disk = 0; + +DSTATUS disk_initialize ( + BYTE drv /* Physical drive nmuber (0..) */ +) +{ + if (drv) + return STA_NOINIT; /* Support only drive 0 */ + // XXX: pay attention here: some functions call disk_initialize *after* it has + // been initialized for the first time. + // Here we just return the status (that should always be ~STA_NOINIT after the first + // call) + if (fake_disk) + return Stat; + + const char *path = "emuldisk.dsk"; + fake_disk = fopen(path, "w+"); + int err = errno; + if (!fake_disk) + { + switch (err) + { + case EINVAL: + fprintf(stderr, "invalid mode\n"); + default: + return STA_NOINIT; + } + } + Stat &= ~STA_NOINIT; + return Stat; +} + + + +/*-----------------------------------------------------------------------*/ +/* Return Disk Status */ + +DSTATUS disk_status ( + BYTE drv /* Physical drive nmuber (0..) */ +) +{ + if (drv) + return STA_NOINIT; /* Support only drive 0 */ + return Stat; +} + + + +/*-----------------------------------------------------------------------*/ +/* Read Sector(s) */ + +DRESULT disk_read ( + BYTE drv, /* Physical drive nmuber (0..) */ + BYTE *buff, /* Data buffer to store read data */ + DWORD sector, /* Sector address (LBA) */ + BYTE count /* Number of sectors to read (1..255) */ +) +{ + if (drv || !count) return RES_PARERR; + if (Stat & STA_NOINIT) return RES_NOTRDY; + + fseek(fake_disk, sector * SECTOR_SIZE, SEEK_SET); + size_t read_items = fread(buff, SECTOR_SIZE, count, fake_disk); + if (read_items == count) + return RES_OK; + else + { + if (feof(fake_disk)) + fprintf(stderr, "end-of-file\n"); + if (ferror(fake_disk)) + fprintf(stderr, "error\n"); + return RES_ERROR; + } +} + + +/*-----------------------------------------------------------------------*/ +/* Write Sector(s) */ + +#if _READONLY == 0 +DRESULT disk_write ( + BYTE drv, /* Physical drive nmuber (0..) */ + const BYTE *buff, /* Data to be written */ + DWORD sector, /* Sector address (LBA) */ + BYTE count /* Number of sectors to write (1..255) */ +) +{ + if (drv || !count) return RES_PARERR; + if (Stat & STA_NOINIT) return RES_NOTRDY; + if (Stat & STA_PROTECT) return RES_WRPRT; + + fseek(fake_disk, sector * SECTOR_SIZE, SEEK_SET); + size_t write_items = fwrite(buff, SECTOR_SIZE, count, fake_disk); + if (write_items == count) + return RES_OK; + else + { + if (feof(fake_disk)) + fprintf(stderr, "end-of-file\n"); + if (ferror(fake_disk)) + fprintf(stderr, "error\n"); + return RES_ERROR; + } +} +#endif /* _READONLY */ + + + +/*-----------------------------------------------------------------------*/ +/* Miscellaneous Functions */ + +DRESULT disk_ioctl ( + BYTE drv, /* Physical drive nmuber (0..) */ + BYTE ctrl, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) +{ + if (drv) return RES_PARERR; + if (Stat & STA_NOINIT) return RES_NOTRDY; + + switch (ctrl) + { + case GET_SECTOR_SIZE: + *(WORD*)buff = SECTOR_SIZE; + break; + case GET_SECTOR_COUNT: + *(DWORD*)buff = 65536; + break; + case GET_BLOCK_SIZE: + *(DWORD*)buff = 1; + break; + case CTRL_SYNC: + fflush(fake_disk); + break; + default: + return RES_PARERR; + } + return RES_OK; +} + +DWORD get_fattime(void) +{ + time_t tmp = time(0); + struct tm *t = localtime(&tmp); + DWORD tim = 0; + // seconds + tim |= (t->tm_sec / 2); + // min + tim |= (t->tm_min << 5); + // hour + tim |= (t->tm_hour << 11); + // month day (1..31) + tim |= (t->tm_mday << 16); + // month (1..12) + tim |= ((t->tm_mon + 1) << 21); + // year (0..127) + tim |= ((t->tm_year - 80) << 25); + return tim; +} +