BeRTOS
diskio_emul.c
Go to the documentation of this file.
00001 
00038 /*-----------------------------------------------------------------------*/
00039 /* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2007        */
00040 /*-----------------------------------------------------------------------*/
00041 
00042 #include <fs/fatfs/diskio.h>
00043 #include <stdio.h>
00044 #include <errno.h>
00045 #include <time.h>
00046 
00047 #define SECTOR_SIZE 512
00048 
00049 static volatile DSTATUS Stat = STA_NOINIT;
00050 
00057 /*-----------------------------------------------------------------------*/
00058 /* Inidialize a Drive                                                    */
00059 
00060 static FILE *fake_disk = 0;
00061 
00062 DSTATUS disk_initialize (
00063     BYTE drv                /* Physical drive nmuber (0..) */
00064 )
00065 {
00066     if (drv)
00067         return STA_NOINIT; /* Support only drive 0 */
00068     // XXX: pay attention here: some functions call disk_initialize *after* it has
00069     //  been initialized for the first time.
00070     //  Here we just return the status (that should always be ~STA_NOINIT after the first
00071     //  call)
00072     if (fake_disk)
00073         return Stat;
00074 
00075     const char *path = "emuldisk.dsk";
00076     fake_disk = fopen(path, "w+");
00077     int err = errno;
00078     if (!fake_disk)
00079     {
00080         switch (err)
00081         {
00082         case EINVAL:
00083             fprintf(stderr, "invalid mode\n");
00084         default:
00085             return STA_NOINIT;
00086         }
00087     }
00088     Stat &= ~STA_NOINIT;
00089     return Stat;
00090 }
00091 
00092 
00093 
00094 /*-----------------------------------------------------------------------*/
00095 /* Return Disk Status                                                    */
00096 
00097 DSTATUS disk_status (
00098     BYTE drv        /* Physical drive nmuber (0..) */
00099 )
00100 {
00101     if (drv)
00102         return STA_NOINIT; /* Support only drive 0 */
00103     return Stat;
00104 }
00105 
00106 
00107 
00108 /*-----------------------------------------------------------------------*/
00109 /* Read Sector(s)                                                        */
00110 
00111 DRESULT disk_read (
00112     BYTE drv,       /* Physical drive nmuber (0..) */
00113     BYTE *buff,     /* Data buffer to store read data */
00114     DWORD sector,   /* Sector address (LBA) */
00115     BYTE count      /* Number of sectors to read (1..255) */
00116 )
00117 {
00118     if (drv || !count) return RES_PARERR;
00119     if (Stat & STA_NOINIT) return RES_NOTRDY;
00120 
00121     fseek(fake_disk, sector * SECTOR_SIZE, SEEK_SET);
00122     size_t read_items = fread(buff, SECTOR_SIZE, count, fake_disk);
00123     if (read_items == count)
00124         return RES_OK;
00125     else
00126     {
00127         if (feof(fake_disk))
00128             fprintf(stderr, "end-of-file\n");
00129         if (ferror(fake_disk))
00130             fprintf(stderr, "error\n");
00131         return RES_ERROR;
00132     }
00133 }
00134 
00135 
00136 /*-----------------------------------------------------------------------*/
00137 /* Write Sector(s)                                                       */
00138 
00139 #if _READONLY == 0
00140 DRESULT disk_write (
00141     BYTE drv,           /* Physical drive nmuber (0..) */
00142     const BYTE *buff,   /* Data to be written */
00143     DWORD sector,       /* Sector address (LBA) */
00144     BYTE count          /* Number of sectors to write (1..255) */
00145 )
00146 {
00147     if (drv || !count) return RES_PARERR;
00148     if (Stat & STA_NOINIT) return RES_NOTRDY;
00149     if (Stat & STA_PROTECT) return RES_WRPRT;
00150 
00151     fseek(fake_disk, sector * SECTOR_SIZE, SEEK_SET);
00152     size_t write_items = fwrite(buff, SECTOR_SIZE, count, fake_disk);
00153     if (write_items == count)
00154         return RES_OK;
00155     else
00156     {
00157         if (feof(fake_disk))
00158             fprintf(stderr, "end-of-file\n");
00159         if (ferror(fake_disk))
00160             fprintf(stderr, "error\n");
00161         return RES_ERROR;
00162     }
00163 }
00164 #endif /* _READONLY */
00165 
00166 
00167 
00168 /*-----------------------------------------------------------------------*/
00169 /* Miscellaneous Functions                                               */
00170 
00171 DRESULT disk_ioctl (
00172     BYTE drv,       /* Physical drive nmuber (0..) */
00173     BYTE ctrl,      /* Control code */
00174     void *buff      /* Buffer to send/receive control data */
00175 )
00176 {
00177     if (drv) return RES_PARERR;
00178     if (Stat & STA_NOINIT) return RES_NOTRDY;
00179 
00180     switch (ctrl)
00181     {
00182     case GET_SECTOR_SIZE:
00183         *(WORD*)buff = SECTOR_SIZE;
00184         break;
00185     case GET_SECTOR_COUNT:
00186         *(DWORD*)buff = 65536;
00187         break;
00188     case GET_BLOCK_SIZE:
00189         *(DWORD*)buff = 1;
00190         break;
00191     case CTRL_SYNC:
00192         fflush(fake_disk);
00193         break;
00194     default:
00195         return RES_PARERR;
00196     }
00197     return RES_OK;
00198 }
00199 
00200 DWORD get_fattime(void)
00201 {
00202     time_t tmp = time(0);
00203     struct tm *t = localtime(&tmp);
00204     DWORD tim = 0;
00205     // seconds
00206     tim |= (t->tm_sec / 2);
00207     // min
00208     tim |= (t->tm_min << 5);
00209     // hour
00210     tim |= (t->tm_hour << 11);
00211     // month day (1..31)
00212     tim |= (t->tm_mday << 16);
00213     // month (1..12)
00214     tim |= ((t->tm_mon + 1) << 21);
00215     // year (0..127)
00216     tim |= ((t->tm_year - 80) << 25);
00217     return tim;
00218 }
00219