diskio_emul.c

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