1 /*-----------------------------------------------------------------------*/ 2 /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2014 */ 3 /*-----------------------------------------------------------------------*/ 4 /* If a working storage control module is available, it should be */ 5 /* attached to the FatFs via a glue function rather than modifying it. */ 6 /* This is an example of glue functions to attach various exsisting */ 7 /* storage control modules to the FatFs module with a defined API. */ 8 /*-----------------------------------------------------------------------*/ 9 10 #include "diskio.h" /* FatFs lower layer API */ 11 #include <stdio.h> 12 13 /*-----------------------------------------------------------------------*/ 14 /* Correspondence between physical drive number and image file handles. */ 15 16 UINT sectorCount[1] = { 0 }; 17 FILE* driveHandle[1] = { NULL }; 18 const int driveHandleCount = sizeof(driveHandle) / sizeof(FILE*); 19 20 /*-----------------------------------------------------------------------*/ 21 /* Open an image file a Drive */ 22 /*-----------------------------------------------------------------------*/ 23 24 DSTATUS disk_openimage(BYTE pdrv, const char* imageFileName) 25 { 26 if (pdrv < driveHandleCount) 27 { 28 if (driveHandle[0] != NULL) 29 return 0; 30 31 driveHandle[0] = fopen(imageFileName, "r+b"); 32 if (!driveHandle[0]) 33 { 34 driveHandle[0] = fopen(imageFileName, "w+b"); 35 } 36 37 if (driveHandle[0] != NULL) 38 return 0; 39 } 40 return STA_NOINIT; 41 } 42 43 44 /*-----------------------------------------------------------------------*/ 45 /* Cleanup a Drive */ 46 /*-----------------------------------------------------------------------*/ 47 48 VOID disk_cleanup( 49 BYTE pdrv /* Physical drive nmuber (0..) */ 50 ) 51 { 52 if (pdrv < driveHandleCount) 53 { 54 if (driveHandle[pdrv] != NULL) 55 { 56 fclose(driveHandle[pdrv]); 57 driveHandle[pdrv] = NULL; 58 } 59 } 60 } 61 62 /*-----------------------------------------------------------------------*/ 63 /* Inidialize a Drive */ 64 /*-----------------------------------------------------------------------*/ 65 66 DSTATUS disk_initialize( 67 BYTE pdrv /* Physical drive nmuber (0..) */ 68 ) 69 { 70 if (pdrv == 0) /* only one drive (image file) supported atm. */ 71 { 72 return 0; 73 } 74 return STA_NOINIT; 75 } 76 77 78 79 /*-----------------------------------------------------------------------*/ 80 /* Get Disk Status */ 81 /*-----------------------------------------------------------------------*/ 82 83 DSTATUS disk_status( 84 BYTE pdrv /* Physical drive nmuber (0..) */ 85 ) 86 { 87 if (pdrv < driveHandleCount) 88 { 89 if (driveHandle[pdrv] != NULL) 90 return 0; 91 } 92 return STA_NOINIT; 93 } 94 95 /*-----------------------------------------------------------------------*/ 96 /* Read Sector(s) */ 97 /*-----------------------------------------------------------------------*/ 98 99 DRESULT disk_read( 100 BYTE pdrv, /* Physical drive nmuber (0..) */ 101 BYTE *buff, /* Data buffer to store read data */ 102 DWORD sector, /* Sector address (LBA) */ 103 UINT count /* Number of sectors to read (1..128) */ 104 ) 105 { 106 DWORD result; 107 108 if (pdrv < driveHandleCount) 109 { 110 if (driveHandle[pdrv] != NULL) 111 { 112 if (fseek(driveHandle[pdrv], sector * 512, SEEK_SET)) 113 return RES_ERROR; 114 115 result = fread(buff, 512, count, driveHandle[pdrv]); 116 117 if (result != count) 118 return RES_ERROR; 119 120 return RES_OK; 121 } 122 } 123 124 return RES_PARERR; 125 } 126 127 128 129 /*-----------------------------------------------------------------------*/ 130 /* Write Sector(s) */ 131 /*-----------------------------------------------------------------------*/ 132 133 #if _USE_WRITE 134 DRESULT disk_write( 135 BYTE pdrv, /* Physical drive nmuber (0..) */ 136 const BYTE *buff, /* Data to be written */ 137 DWORD sector, /* Sector address (LBA) */ 138 UINT count /* Number of sectors to write (1..128) */ 139 ) 140 { 141 DWORD result; 142 143 if (pdrv < driveHandleCount) 144 { 145 if (driveHandle[pdrv] != NULL) 146 { 147 if (fseek(driveHandle[pdrv], sector * 512, SEEK_SET)) 148 return RES_ERROR; 149 150 result = fwrite(buff, 512, count, driveHandle[pdrv]); 151 152 if (result != count) 153 return RES_ERROR; 154 155 return RES_OK; 156 } 157 } 158 159 return RES_PARERR; 160 } 161 #endif 162 163 164 /*-----------------------------------------------------------------------*/ 165 /* Miscellaneous Functions */ 166 /*-----------------------------------------------------------------------*/ 167 168 #if _USE_IOCTL 169 DRESULT disk_ioctl( 170 BYTE pdrv, /* Physical drive nmuber (0..) */ 171 BYTE cmd, /* Control code */ 172 void *buff /* Buffer to send/receive control data */ 173 ) 174 { 175 if (pdrv < driveHandleCount) 176 { 177 if (driveHandle[pdrv] != NULL) 178 { 179 switch (cmd) 180 { 181 case CTRL_SYNC: 182 fflush(driveHandle[pdrv]); 183 return RES_OK; 184 case GET_SECTOR_SIZE: 185 *(DWORD*)buff = 512; 186 return RES_OK; 187 case GET_BLOCK_SIZE: 188 *(DWORD*)buff = 512; 189 return RES_OK; 190 case GET_SECTOR_COUNT: 191 { 192 if (sectorCount[pdrv] <= 0) 193 { 194 if (fseek(driveHandle[pdrv], 0, SEEK_END)) 195 printf("fseek failed!\n"); 196 else 197 sectorCount[pdrv] = ftell(driveHandle[pdrv]) / 512; 198 } 199 200 *(DWORD*)buff = sectorCount[pdrv]; 201 return RES_OK; 202 } 203 case SET_SECTOR_COUNT: 204 { 205 int count = *(DWORD*)buff; 206 long size; 207 208 sectorCount[pdrv] = count; 209 210 fseek(driveHandle[pdrv], 0, SEEK_END); 211 size = ftell(driveHandle[pdrv]) / 512; 212 213 if (size < count) 214 { 215 if (fseek(driveHandle[pdrv], count * 512 - 1, SEEK_SET)) 216 return RES_ERROR; 217 218 fwrite(buff, 1, 1, driveHandle[pdrv]); 219 220 return RES_OK; 221 } 222 else 223 { 224 // SHRINKING NOT IMPLEMENTED 225 return RES_OK; 226 } 227 } 228 } 229 } 230 } 231 232 return RES_PARERR; 233 } 234 #endif 235