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
disk_openimage(BYTE pdrv,const char * imageFileName)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
disk_cleanup(BYTE pdrv)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
disk_initialize(BYTE pdrv)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
disk_status(BYTE pdrv)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
disk_read(BYTE pdrv,BYTE * buff,DWORD sector,UINT count)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
disk_write(BYTE pdrv,const BYTE * buff,DWORD sector,UINT count)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
disk_ioctl(BYTE pdrv,BYTE cmd,void * buff)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