User | Revision | Line number | New contents of line |
iva2k |
0:1802fb31b938
|
1
|
/*
|
iva2k |
0:1802fb31b938
|
2
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
3
|
* NXP USB Host Stack
|
iva2k |
0:1802fb31b938
|
4
|
*
|
iva2k |
0:1802fb31b938
|
5
|
* (c) Copyright 2008, NXP SemiConductors
|
iva2k |
0:1802fb31b938
|
6
|
* (c) Copyright 2008, OnChip Technologies LLC
|
iva2k |
0:1802fb31b938
|
7
|
* All Rights Reserved
|
iva2k |
0:1802fb31b938
|
8
|
*
|
iva2k |
0:1802fb31b938
|
9
|
* www.nxp.com
|
iva2k |
0:1802fb31b938
|
10
|
* www.onchiptech.com
|
iva2k |
0:1802fb31b938
|
11
|
*
|
iva2k |
0:1802fb31b938
|
12
|
* File : usbhost_fat.c
|
iva2k |
0:1802fb31b938
|
13
|
* Programmer(s) : Ravikanth.P
|
iva2k |
0:1802fb31b938
|
14
|
* Version :
|
iva2k |
0:1802fb31b938
|
15
|
*
|
iva2k |
0:1802fb31b938
|
16
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
17
|
*/
|
iva2k |
0:1802fb31b938
|
18
|
|
iva2k |
0:1802fb31b938
|
19
|
/*
|
iva2k |
0:1802fb31b938
|
20
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
21
|
* INCLUDE HEADER FILES
|
iva2k |
0:1802fb31b938
|
22
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
23
|
*/
|
iva2k |
0:1802fb31b938
|
24
|
|
iva2k |
0:1802fb31b938
|
25
|
#include "usbhost_fat.h"
|
iva2k |
0:1802fb31b938
|
26
|
|
iva2k |
0:1802fb31b938
|
27
|
/*
|
iva2k |
0:1802fb31b938
|
28
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
29
|
* GLOBAL VARIABLES
|
iva2k |
0:1802fb31b938
|
30
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
31
|
*/
|
iva2k |
0:1802fb31b938
|
32
|
|
iva2k |
0:1802fb31b938
|
33
|
#define MAX_FILE_DESCRIPTORS 2
|
iva2k |
0:1802fb31b938
|
34
|
static BOOT_SEC FAT_BootSec;
|
iva2k |
0:1802fb31b938
|
35
|
static FILE_ENTRY FAT_FileEntry[MAX_FILE_DESCRIPTORS];
|
iva2k |
0:1802fb31b938
|
36
|
|
iva2k |
0:1802fb31b938
|
37
|
/*
|
iva2k |
0:1802fb31b938
|
38
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
39
|
* INITIALIZE THE FILE SYSTEM
|
iva2k |
0:1802fb31b938
|
40
|
*
|
iva2k |
0:1802fb31b938
|
41
|
* Description: This function initializes the FAT16 file system
|
iva2k |
0:1802fb31b938
|
42
|
*
|
iva2k |
0:1802fb31b938
|
43
|
* Arguments : None
|
iva2k |
0:1802fb31b938
|
44
|
*
|
iva2k |
0:1802fb31b938
|
45
|
* Returns : OK if Success
|
iva2k |
0:1802fb31b938
|
46
|
* ERR_INVALID_BOOTSIG if Failed
|
iva2k |
0:1802fb31b938
|
47
|
*
|
iva2k |
0:1802fb31b938
|
48
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
49
|
*/
|
iva2k |
0:1802fb31b938
|
50
|
|
iva2k |
0:1802fb31b938
|
51
|
USB_INT32S FAT_Init (void)
|
iva2k |
0:1802fb31b938
|
52
|
{
|
iva2k |
0:1802fb31b938
|
53
|
USB_INT16U boot_sig;
|
iva2k |
0:1802fb31b938
|
54
|
USB_INT32S rc, i;
|
iva2k |
0:1802fb31b938
|
55
|
FILE_ENTRY *entry;
|
iva2k |
0:1802fb31b938
|
56
|
|
iva2k |
0:1802fb31b938
|
57
|
for (i=0;i<MAX_FILE_DESCRIPTORS;i++) {
|
iva2k |
0:1802fb31b938
|
58
|
entry = &FAT_FileEntry[i];
|
iva2k |
0:1802fb31b938
|
59
|
entry->CurrClus = 0;
|
iva2k |
0:1802fb31b938
|
60
|
entry->CurrClusOffset = 0;
|
iva2k |
0:1802fb31b938
|
61
|
entry->FileSize = 0;
|
iva2k |
0:1802fb31b938
|
62
|
entry->EntrySec = 0;
|
iva2k |
0:1802fb31b938
|
63
|
entry->EntrySecOffset = 0;
|
iva2k |
0:1802fb31b938
|
64
|
entry->FileStatus = 0;
|
iva2k |
0:1802fb31b938
|
65
|
}
|
iva2k |
0:1802fb31b938
|
66
|
|
iva2k |
0:1802fb31b938
|
67
|
MS_BulkRecv(0, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
68
|
boot_sig = ReadLE16U(&FATBuffer[510]);
|
iva2k |
0:1802fb31b938
|
69
|
if (boot_sig != 0xAA55) {
|
iva2k |
0:1802fb31b938
|
70
|
rc = ERR_INVALID_BOOT_SIG;
|
iva2k |
0:1802fb31b938
|
71
|
} else {
|
iva2k |
0:1802fb31b938
|
72
|
if (FATBuffer[0] != 0xEB && FATBuffer[0] != 0xE9) {
|
iva2k |
0:1802fb31b938
|
73
|
FAT_BootSec.BootSecOffset = ReadLE32U(&FATBuffer[454]);
|
iva2k |
0:1802fb31b938
|
74
|
MS_BulkRecv(FAT_BootSec.BootSecOffset, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
75
|
}
|
iva2k |
0:1802fb31b938
|
76
|
FAT_BootSec.BytsPerSec = ReadLE16U(&FATBuffer[11]); /* Bytes per cluster */
|
iva2k |
0:1802fb31b938
|
77
|
FAT_BootSec.SecPerClus = FATBuffer[13]; /* Sectors per cluster */
|
iva2k |
0:1802fb31b938
|
78
|
/* Reserved sector count */
|
iva2k |
0:1802fb31b938
|
79
|
FAT_BootSec.RsvdSecCnt = ReadLE16U(&FATBuffer[14]) + FAT_BootSec.BootSecOffset;
|
iva2k |
0:1802fb31b938
|
80
|
FAT_BootSec.NumFATs = FATBuffer[16]; /* Number of FAT copies */
|
iva2k |
0:1802fb31b938
|
81
|
FAT_BootSec.RootEntCnt = ReadLE16U(&FATBuffer[17]); /* Root entry count */
|
iva2k |
0:1802fb31b938
|
82
|
FAT_BootSec.TotSec16 = ReadLE16U(&FATBuffer[19]); /* Total FAT16 sectors */
|
iva2k |
0:1802fb31b938
|
83
|
FAT_BootSec.TotSec32 = ReadLE32U(&FATBuffer[32]); /* Total FAT32 sectors */
|
iva2k |
0:1802fb31b938
|
84
|
FAT_BootSec.FATSz16 = ReadLE16U(&FATBuffer[22]); /* Size of the FAT table */
|
iva2k |
0:1802fb31b938
|
85
|
/* Bytes per cluster */
|
iva2k |
0:1802fb31b938
|
86
|
FAT_BootSec.BytsPerClus = (FAT_BootSec.BytsPerSec * FAT_BootSec.SecPerClus);
|
iva2k |
0:1802fb31b938
|
87
|
/* Root directory starting sector */
|
iva2k |
0:1802fb31b938
|
88
|
FAT_BootSec.RootDirStartSec = FAT_BootSec.RsvdSecCnt + (FAT_BootSec.FATSz16 * FAT_BootSec.NumFATs);
|
iva2k |
0:1802fb31b938
|
89
|
/* Sectors occupied by root directory */
|
iva2k |
0:1802fb31b938
|
90
|
FAT_BootSec.RootDirSec = ((FAT_BootSec.RootEntCnt * 32) + (FAT_BootSec.BytsPerSec - 1)) /
|
iva2k |
0:1802fb31b938
|
91
|
(FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
92
|
/* First data sector */
|
iva2k |
0:1802fb31b938
|
93
|
FAT_BootSec.FirstDataSec = FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec;
|
iva2k |
0:1802fb31b938
|
94
|
FAT_BootSec.FATType = FAT_GetFATType(); /* Type of FAT */
|
iva2k |
0:1802fb31b938
|
95
|
if (FAT_BootSec.FATType == FAT_16) {
|
iva2k |
0:1802fb31b938
|
96
|
rc = OK;
|
iva2k |
0:1802fb31b938
|
97
|
} else {
|
iva2k |
0:1802fb31b938
|
98
|
rc = ERR_FAT_NOT_SUPPORTED;
|
iva2k |
0:1802fb31b938
|
99
|
PRINT_Err(rc);
|
iva2k |
0:1802fb31b938
|
100
|
}
|
iva2k |
0:1802fb31b938
|
101
|
}
|
iva2k |
0:1802fb31b938
|
102
|
return (rc);
|
iva2k |
0:1802fb31b938
|
103
|
}
|
iva2k |
0:1802fb31b938
|
104
|
|
iva2k |
0:1802fb31b938
|
105
|
/*
|
iva2k |
0:1802fb31b938
|
106
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
107
|
* GET FILE SYSTEM TYPE
|
iva2k |
0:1802fb31b938
|
108
|
*
|
iva2k |
0:1802fb31b938
|
109
|
* Description: This function returns the file system type with which the disk is formatted
|
iva2k |
0:1802fb31b938
|
110
|
*
|
iva2k |
0:1802fb31b938
|
111
|
* Arguments : None
|
iva2k |
0:1802fb31b938
|
112
|
*
|
iva2k |
0:1802fb31b938
|
113
|
* Returns : FAT16 On Success
|
iva2k |
0:1802fb31b938
|
114
|
* ERR_FAT_TYPE On Failure
|
iva2k |
0:1802fb31b938
|
115
|
*
|
iva2k |
0:1802fb31b938
|
116
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
117
|
*/
|
iva2k |
0:1802fb31b938
|
118
|
|
iva2k |
0:1802fb31b938
|
119
|
USB_INT08U FAT_GetFATType (void)
|
iva2k |
0:1802fb31b938
|
120
|
{
|
iva2k |
0:1802fb31b938
|
121
|
USB_INT08U fat_type;
|
iva2k |
0:1802fb31b938
|
122
|
USB_INT32U tot_sec;
|
iva2k |
0:1802fb31b938
|
123
|
USB_INT32U tot_data_clus;
|
iva2k |
0:1802fb31b938
|
124
|
|
iva2k |
0:1802fb31b938
|
125
|
|
iva2k |
0:1802fb31b938
|
126
|
if (FAT_BootSec.TotSec16 != 0) { /* Get total sectors in the disk */
|
iva2k |
0:1802fb31b938
|
127
|
tot_sec = FAT_BootSec.TotSec16;
|
iva2k |
0:1802fb31b938
|
128
|
} else {
|
iva2k |
0:1802fb31b938
|
129
|
tot_sec = FAT_BootSec.TotSec32;
|
iva2k |
0:1802fb31b938
|
130
|
}
|
iva2k |
0:1802fb31b938
|
131
|
|
iva2k |
0:1802fb31b938
|
132
|
tot_data_clus = tot_sec / (FAT_BootSec.SecPerClus); /* Get total data clusters in the disk */
|
iva2k |
0:1802fb31b938
|
133
|
/* If total data clusters >= 4085 and */
|
iva2k |
0:1802fb31b938
|
134
|
/* < 65525, then it is FAT16 file system */
|
iva2k |
0:1802fb31b938
|
135
|
if (tot_data_clus >= 4085 && tot_data_clus < 65525) {
|
iva2k |
0:1802fb31b938
|
136
|
fat_type = FAT_16;
|
iva2k |
0:1802fb31b938
|
137
|
} else {
|
iva2k |
0:1802fb31b938
|
138
|
fat_type = 0;
|
iva2k |
0:1802fb31b938
|
139
|
}
|
iva2k |
0:1802fb31b938
|
140
|
|
iva2k |
0:1802fb31b938
|
141
|
return (fat_type);
|
iva2k |
0:1802fb31b938
|
142
|
}
|
iva2k |
0:1802fb31b938
|
143
|
|
iva2k |
0:1802fb31b938
|
144
|
/*
|
iva2k |
0:1802fb31b938
|
145
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
146
|
* OPENING A FILE
|
iva2k |
0:1802fb31b938
|
147
|
*
|
iva2k |
0:1802fb31b938
|
148
|
* Description: This function stores the attributes of a file, such as starting cluster, file size,
|
iva2k |
0:1802fb31b938
|
149
|
* sector where the file entry is stored and offset of the entry in that sector
|
iva2k |
0:1802fb31b938
|
150
|
*
|
iva2k |
0:1802fb31b938
|
151
|
* Arguments : file_name Name of the file. The file must be in root directory.
|
iva2k |
0:1802fb31b938
|
152
|
*
|
iva2k |
0:1802fb31b938
|
153
|
* Returns : pointer to the entry On Success
|
iva2k |
0:1802fb31b938
|
154
|
* NULL On Failure
|
iva2k |
0:1802fb31b938
|
155
|
*
|
iva2k |
0:1802fb31b938
|
156
|
* Modifed 6/9/08 WCB returns a file descriptor which is the INDEX+1 to the entry.
|
iva2k |
0:1802fb31b938
|
157
|
* returning the entry address itself could be interpreted as a negative number --
|
iva2k |
0:1802fb31b938
|
158
|
* and thus an error -- for memory locations of 0x80000000 and above. We return
|
iva2k |
0:1802fb31b938
|
159
|
* INDEX+1 instead of just the index to avoid returning a file descriptor of zero,
|
iva2k |
0:1802fb31b938
|
160
|
* which could be potentially confused with an error.
|
iva2k |
0:1802fb31b938
|
161
|
*
|
iva2k |
0:1802fb31b938
|
162
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
163
|
*/
|
iva2k |
0:1802fb31b938
|
164
|
|
iva2k |
0:1802fb31b938
|
165
|
USB_INT32S FILE_Open (USB_INT08U *file_name,
|
iva2k |
0:1802fb31b938
|
166
|
USB_INT08U flags)
|
iva2k |
0:1802fb31b938
|
167
|
{
|
iva2k |
0:1802fb31b938
|
168
|
USB_INT32S rc;
|
iva2k |
0:1802fb31b938
|
169
|
FILE_ENTRY *entry = 0;
|
iva2k |
0:1802fb31b938
|
170
|
USB_INT32S fd = -1;
|
iva2k |
0:1802fb31b938
|
171
|
|
iva2k |
0:1802fb31b938
|
172
|
do {
|
iva2k |
0:1802fb31b938
|
173
|
if (FAT_FileEntry[++fd].FileStatus == 0)
|
iva2k |
0:1802fb31b938
|
174
|
entry = &FAT_FileEntry[fd];
|
iva2k |
0:1802fb31b938
|
175
|
} while ((entry == 0) && (fd < MAX_FILE_DESCRIPTORS-1));
|
iva2k |
0:1802fb31b938
|
176
|
if (entry == 0) {
|
iva2k |
0:1802fb31b938
|
177
|
return (ERR_OPEN_LIMIT_REACHED);
|
iva2k |
0:1802fb31b938
|
178
|
}
|
iva2k |
0:1802fb31b938
|
179
|
if (flags == RDONLY) { /* Search for a file. If it doesn't exist, don't create it */
|
iva2k |
0:1802fb31b938
|
180
|
rc = FAT_FindEntry(file_name, entry);
|
iva2k |
0:1802fb31b938
|
181
|
if (rc == MATCH_FOUND) {
|
iva2k |
0:1802fb31b938
|
182
|
entry->FileStatus = 1;
|
iva2k |
0:1802fb31b938
|
183
|
rc = fd+1;
|
iva2k |
0:1802fb31b938
|
184
|
}
|
iva2k |
0:1802fb31b938
|
185
|
} else { /* Search for a file. If it doesn't exist, create it */
|
iva2k |
0:1802fb31b938
|
186
|
rc = FAT_CreateEntry(file_name, entry);
|
iva2k |
0:1802fb31b938
|
187
|
if (rc == MATCH_FOUND) {
|
iva2k |
0:1802fb31b938
|
188
|
entry->FileStatus = 1;
|
iva2k |
0:1802fb31b938
|
189
|
rc = fd+1;
|
iva2k |
0:1802fb31b938
|
190
|
}
|
iva2k |
0:1802fb31b938
|
191
|
}
|
iva2k |
0:1802fb31b938
|
192
|
return (rc);
|
iva2k |
0:1802fb31b938
|
193
|
}
|
iva2k |
0:1802fb31b938
|
194
|
|
iva2k |
0:1802fb31b938
|
195
|
/*
|
iva2k |
0:1802fb31b938
|
196
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
197
|
* FINDING AN ENTRY
|
iva2k |
0:1802fb31b938
|
198
|
*
|
iva2k |
0:1802fb31b938
|
199
|
* Description: This function searches for a file name in the root directory
|
iva2k |
0:1802fb31b938
|
200
|
*
|
iva2k |
0:1802fb31b938
|
201
|
* Arguments : ent_name_given Pointer to the file name to be searched.
|
iva2k |
0:1802fb31b938
|
202
|
* entry Pointer to the entry structure. The attributes of the file are stored in this
|
iva2k |
0:1802fb31b938
|
203
|
* structure if the file was found in the root directory.
|
iva2k |
0:1802fb31b938
|
204
|
*
|
iva2k |
0:1802fb31b938
|
205
|
* Returns : MATCH_FOUND if the file was found in the root directory.
|
iva2k |
0:1802fb31b938
|
206
|
* MATCH_NOT_FOUND if the file was not found in the root directory.
|
iva2k |
0:1802fb31b938
|
207
|
*
|
iva2k |
0:1802fb31b938
|
208
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
209
|
*/
|
iva2k |
0:1802fb31b938
|
210
|
|
iva2k |
0:1802fb31b938
|
211
|
USB_INT32S FAT_FindEntry (USB_INT08U *ent_name_given,
|
iva2k |
0:1802fb31b938
|
212
|
FILE_ENTRY *entry)
|
iva2k |
0:1802fb31b938
|
213
|
{
|
iva2k |
0:1802fb31b938
|
214
|
USB_INT32U sec_num;
|
iva2k |
0:1802fb31b938
|
215
|
volatile USB_INT08U *buf;
|
iva2k |
0:1802fb31b938
|
216
|
USB_INT08U ent_type;
|
iva2k |
0:1802fb31b938
|
217
|
USB_INT08U ent_name_read[13];
|
iva2k |
0:1802fb31b938
|
218
|
|
iva2k |
0:1802fb31b938
|
219
|
|
iva2k |
0:1802fb31b938
|
220
|
for (sec_num = FAT_BootSec.RootDirStartSec; /* For all the sectors in root directory */
|
iva2k |
0:1802fb31b938
|
221
|
sec_num < (FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec);
|
iva2k |
0:1802fb31b938
|
222
|
sec_num++) {
|
iva2k |
0:1802fb31b938
|
223
|
|
iva2k |
0:1802fb31b938
|
224
|
|
iva2k |
0:1802fb31b938
|
225
|
MS_BulkRecv(sec_num, 1, FATBuffer); /* Read one sector */
|
iva2k |
0:1802fb31b938
|
226
|
buf = FATBuffer;
|
iva2k |
0:1802fb31b938
|
227
|
while (buf < (FATBuffer + FAT_BootSec.BytsPerSec)) {
|
iva2k |
0:1802fb31b938
|
228
|
ent_type = FAT_ChkEntType(buf); /* Check for the entry type */
|
iva2k |
0:1802fb31b938
|
229
|
if (ent_type == SFN_ENTRY) { /* If it is short entry get short file name */
|
iva2k |
0:1802fb31b938
|
230
|
FAT_GetSFN(buf, ent_name_read);
|
iva2k |
0:1802fb31b938
|
231
|
/* Compare given name with this name case insensitively */
|
iva2k |
0:1802fb31b938
|
232
|
if (FAT_StrCaseCmp(ent_name_given, ent_name_read) == MATCH_FOUND) {
|
iva2k |
0:1802fb31b938
|
233
|
entry->CurrClus = ReadLE16U(&buf[26]); /* If they are same, get starting cluster */
|
iva2k |
0:1802fb31b938
|
234
|
entry->FileSize = ReadLE32U(&buf[28]); /* Get file size */
|
iva2k |
0:1802fb31b938
|
235
|
entry->EntrySec = sec_num; /* Get sector number where the filename is located */
|
iva2k |
0:1802fb31b938
|
236
|
/* Get offset in this sector where the filename is located */
|
iva2k |
0:1802fb31b938
|
237
|
entry->EntrySecOffset = buf - FATBuffer;
|
iva2k |
0:1802fb31b938
|
238
|
return (MATCH_FOUND);
|
iva2k |
0:1802fb31b938
|
239
|
}
|
iva2k |
0:1802fb31b938
|
240
|
}
|
iva2k |
0:1802fb31b938
|
241
|
if (ent_type == LAST_ENTRY) { /* If it is the last entry, no more entries will exist. Return */
|
iva2k |
0:1802fb31b938
|
242
|
return (MATCH_NOT_FOUND);
|
iva2k |
0:1802fb31b938
|
243
|
}
|
iva2k |
0:1802fb31b938
|
244
|
buf = buf + 32; /* Move to the next entry */
|
iva2k |
0:1802fb31b938
|
245
|
}
|
iva2k |
0:1802fb31b938
|
246
|
}
|
iva2k |
0:1802fb31b938
|
247
|
return (MATCH_NOT_FOUND);
|
iva2k |
0:1802fb31b938
|
248
|
}
|
iva2k |
0:1802fb31b938
|
249
|
|
iva2k |
0:1802fb31b938
|
250
|
/*
|
iva2k |
0:1802fb31b938
|
251
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
252
|
* GET SHORT FILE NAME AND EXTENSION OF A FILE
|
iva2k |
0:1802fb31b938
|
253
|
*
|
iva2k |
0:1802fb31b938
|
254
|
* Description: This function reads the short file name and extension corresponding to a file
|
iva2k |
0:1802fb31b938
|
255
|
*
|
iva2k |
0:1802fb31b938
|
256
|
* Arguments : ent_buf buffer which contains the 32 byte entry of a file
|
iva2k |
0:1802fb31b938
|
257
|
* name buffer to store the file name and extension of a file
|
iva2k |
0:1802fb31b938
|
258
|
*
|
iva2k |
0:1802fb31b938
|
259
|
* Returns : None
|
iva2k |
0:1802fb31b938
|
260
|
*
|
iva2k |
0:1802fb31b938
|
261
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
262
|
*/
|
iva2k |
0:1802fb31b938
|
263
|
|
iva2k |
0:1802fb31b938
|
264
|
void FAT_GetSFN (volatile USB_INT08U *entry,
|
iva2k |
0:1802fb31b938
|
265
|
USB_INT08U *name)
|
iva2k |
0:1802fb31b938
|
266
|
{
|
iva2k |
0:1802fb31b938
|
267
|
USB_INT08U ext[4]; /* Buffer to store the extension of a file */
|
iva2k |
0:1802fb31b938
|
268
|
USB_INT08U *ext_ptr;
|
iva2k |
0:1802fb31b938
|
269
|
|
iva2k |
0:1802fb31b938
|
270
|
|
iva2k |
0:1802fb31b938
|
271
|
ext_ptr = ext;
|
iva2k |
0:1802fb31b938
|
272
|
|
iva2k |
0:1802fb31b938
|
273
|
FAT_GetSfnName(entry, name); /* Get file name into "name" buffer */
|
iva2k |
0:1802fb31b938
|
274
|
FAT_GetSfnExt(entry, ext_ptr); /* Get extension into "ext" buffer */
|
iva2k |
0:1802fb31b938
|
275
|
|
iva2k |
0:1802fb31b938
|
276
|
while (*name) { /* Goto the end of the filename */
|
iva2k |
0:1802fb31b938
|
277
|
name++;
|
iva2k |
0:1802fb31b938
|
278
|
}
|
iva2k |
0:1802fb31b938
|
279
|
if (*ext_ptr) { /* If the extension exists, put a '.' charecter */
|
iva2k |
0:1802fb31b938
|
280
|
*name = '.';
|
iva2k |
0:1802fb31b938
|
281
|
name++;
|
iva2k |
0:1802fb31b938
|
282
|
}
|
iva2k |
0:1802fb31b938
|
283
|
while (*ext_ptr) { /* Append the extension to the file name */
|
iva2k |
0:1802fb31b938
|
284
|
*name = *ext_ptr;
|
iva2k |
0:1802fb31b938
|
285
|
name++;
|
iva2k |
0:1802fb31b938
|
286
|
ext_ptr++;
|
iva2k |
0:1802fb31b938
|
287
|
}
|
iva2k |
0:1802fb31b938
|
288
|
*name = '\0';
|
iva2k |
0:1802fb31b938
|
289
|
}
|
iva2k |
0:1802fb31b938
|
290
|
|
iva2k |
0:1802fb31b938
|
291
|
/*
|
iva2k |
0:1802fb31b938
|
292
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
293
|
* GET SHORT FILE NAME OF A FILE
|
iva2k |
0:1802fb31b938
|
294
|
*
|
iva2k |
0:1802fb31b938
|
295
|
* Description: This function reads the short file name of a file
|
iva2k |
0:1802fb31b938
|
296
|
*
|
iva2k |
0:1802fb31b938
|
297
|
* Arguments : ent_buf buffer which contains the 32 byte entry of a file
|
iva2k |
0:1802fb31b938
|
298
|
* name buffer to store the short file name of a file
|
iva2k |
0:1802fb31b938
|
299
|
*
|
iva2k |
0:1802fb31b938
|
300
|
* Returns : None
|
iva2k |
0:1802fb31b938
|
301
|
*
|
iva2k |
0:1802fb31b938
|
302
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
303
|
*/
|
iva2k |
0:1802fb31b938
|
304
|
|
iva2k |
0:1802fb31b938
|
305
|
void FAT_GetSfnName (volatile USB_INT08U *entry,
|
iva2k |
0:1802fb31b938
|
306
|
USB_INT08U *name)
|
iva2k |
0:1802fb31b938
|
307
|
{
|
iva2k |
0:1802fb31b938
|
308
|
USB_INT32U cnt;
|
iva2k |
0:1802fb31b938
|
309
|
|
iva2k |
0:1802fb31b938
|
310
|
|
iva2k |
0:1802fb31b938
|
311
|
cnt = 0;
|
iva2k |
0:1802fb31b938
|
312
|
while (cnt < 8) {
|
iva2k |
0:1802fb31b938
|
313
|
*name = *entry; /* Get first 8 charecters of an SFN entry */
|
iva2k |
0:1802fb31b938
|
314
|
name++;
|
iva2k |
0:1802fb31b938
|
315
|
entry++;
|
iva2k |
0:1802fb31b938
|
316
|
cnt++;
|
iva2k |
0:1802fb31b938
|
317
|
}
|
iva2k |
0:1802fb31b938
|
318
|
*name = 0;
|
iva2k |
0:1802fb31b938
|
319
|
name--;
|
iva2k |
0:1802fb31b938
|
320
|
while (*name == 0x20) { /* If any spaces exist after the file name, replace them with 0 */
|
iva2k |
0:1802fb31b938
|
321
|
*name = 0;
|
iva2k |
0:1802fb31b938
|
322
|
name--;
|
iva2k |
0:1802fb31b938
|
323
|
}
|
iva2k |
0:1802fb31b938
|
324
|
}
|
iva2k |
0:1802fb31b938
|
325
|
|
iva2k |
0:1802fb31b938
|
326
|
/*
|
iva2k |
0:1802fb31b938
|
327
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
328
|
* GET EXTENSION OF A FILE
|
iva2k |
0:1802fb31b938
|
329
|
*
|
iva2k |
0:1802fb31b938
|
330
|
* Description: This function reads the extension of a file
|
iva2k |
0:1802fb31b938
|
331
|
*
|
iva2k |
0:1802fb31b938
|
332
|
* Arguments : ent_buf buffer which contains the 32 byte entry of a file
|
iva2k |
0:1802fb31b938
|
333
|
* ext_ptr buffer to store the extension of a file
|
iva2k |
0:1802fb31b938
|
334
|
*
|
iva2k |
0:1802fb31b938
|
335
|
* Returns : None
|
iva2k |
0:1802fb31b938
|
336
|
*
|
iva2k |
0:1802fb31b938
|
337
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
338
|
*/
|
iva2k |
0:1802fb31b938
|
339
|
|
iva2k |
0:1802fb31b938
|
340
|
void FAT_GetSfnExt (volatile USB_INT08U *entry,
|
iva2k |
0:1802fb31b938
|
341
|
USB_INT08U *ext_ptr)
|
iva2k |
0:1802fb31b938
|
342
|
{
|
iva2k |
0:1802fb31b938
|
343
|
USB_INT32U cnt;
|
iva2k |
0:1802fb31b938
|
344
|
|
iva2k |
0:1802fb31b938
|
345
|
|
iva2k |
0:1802fb31b938
|
346
|
cnt = 0;
|
iva2k |
0:1802fb31b938
|
347
|
while (cnt < 8) { /* Goto the beginning of the file extension */
|
iva2k |
0:1802fb31b938
|
348
|
entry++;
|
iva2k |
0:1802fb31b938
|
349
|
cnt++;
|
iva2k |
0:1802fb31b938
|
350
|
}
|
iva2k |
0:1802fb31b938
|
351
|
cnt = 0;
|
iva2k |
0:1802fb31b938
|
352
|
while (cnt < 3) { /* Get 3 charecters from there */
|
iva2k |
0:1802fb31b938
|
353
|
*ext_ptr = *entry;
|
iva2k |
0:1802fb31b938
|
354
|
ext_ptr++;
|
iva2k |
0:1802fb31b938
|
355
|
entry++;
|
iva2k |
0:1802fb31b938
|
356
|
cnt++;
|
iva2k |
0:1802fb31b938
|
357
|
}
|
iva2k |
0:1802fb31b938
|
358
|
*ext_ptr = 0;
|
iva2k |
0:1802fb31b938
|
359
|
ext_ptr--;
|
iva2k |
0:1802fb31b938
|
360
|
while (*ext_ptr == ' ') { /* If any spaces exist after the file extension, replace them with 0 */
|
iva2k |
0:1802fb31b938
|
361
|
*ext_ptr = 0;
|
iva2k |
0:1802fb31b938
|
362
|
ext_ptr--;
|
iva2k |
0:1802fb31b938
|
363
|
}
|
iva2k |
0:1802fb31b938
|
364
|
}
|
iva2k |
0:1802fb31b938
|
365
|
|
iva2k |
0:1802fb31b938
|
366
|
/*
|
iva2k |
0:1802fb31b938
|
367
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
368
|
* CASE INSENSITIVE COMPARISION OF STRINGS
|
iva2k |
0:1802fb31b938
|
369
|
*
|
iva2k |
0:1802fb31b938
|
370
|
* Description: This function compares two strings case insensitively
|
iva2k |
0:1802fb31b938
|
371
|
*
|
iva2k |
0:1802fb31b938
|
372
|
* Arguments : str1 Pointer to the first string
|
iva2k |
0:1802fb31b938
|
373
|
* str2 Pointer to the second string
|
iva2k |
0:1802fb31b938
|
374
|
*
|
iva2k |
0:1802fb31b938
|
375
|
* Returns : MATCH_FOUND if both the strings are same
|
iva2k |
0:1802fb31b938
|
376
|
* NATCH_NOT_FOUND if both the strings are different
|
iva2k |
0:1802fb31b938
|
377
|
*
|
iva2k |
0:1802fb31b938
|
378
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
379
|
*/
|
iva2k |
0:1802fb31b938
|
380
|
|
iva2k |
0:1802fb31b938
|
381
|
USB_INT32S FAT_StrCaseCmp (USB_INT08U *str1,
|
iva2k |
0:1802fb31b938
|
382
|
USB_INT08U *str2)
|
iva2k |
0:1802fb31b938
|
383
|
{
|
iva2k |
0:1802fb31b938
|
384
|
while (*str1 && *str2) {
|
iva2k |
0:1802fb31b938
|
385
|
if (*str1 == *str2 || *str1 == (*str2 + 32) || *str1 == (*str2 - 32)) {
|
iva2k |
0:1802fb31b938
|
386
|
str1++;
|
iva2k |
0:1802fb31b938
|
387
|
str2++;
|
iva2k |
0:1802fb31b938
|
388
|
continue;
|
iva2k |
0:1802fb31b938
|
389
|
} else {
|
iva2k |
0:1802fb31b938
|
390
|
return (MATCH_NOT_FOUND);
|
iva2k |
0:1802fb31b938
|
391
|
}
|
iva2k |
0:1802fb31b938
|
392
|
}
|
iva2k |
0:1802fb31b938
|
393
|
if (*str1 == 0 && *str2 == 0) {
|
iva2k |
0:1802fb31b938
|
394
|
return (MATCH_FOUND);
|
iva2k |
0:1802fb31b938
|
395
|
} else {
|
iva2k |
0:1802fb31b938
|
396
|
return (MATCH_NOT_FOUND);
|
iva2k |
0:1802fb31b938
|
397
|
}
|
iva2k |
0:1802fb31b938
|
398
|
}
|
iva2k |
0:1802fb31b938
|
399
|
|
iva2k |
0:1802fb31b938
|
400
|
/*
|
iva2k |
0:1802fb31b938
|
401
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
402
|
* CHECK TYPE OF THE ENTRY
|
iva2k |
0:1802fb31b938
|
403
|
*
|
iva2k |
0:1802fb31b938
|
404
|
* Description: This function checks the type of file entry.
|
iva2k |
0:1802fb31b938
|
405
|
*
|
iva2k |
0:1802fb31b938
|
406
|
* Arguments : ent Pointer to the buffer containing the entry
|
iva2k |
0:1802fb31b938
|
407
|
*
|
iva2k |
0:1802fb31b938
|
408
|
* Returns : LAST_ENTRY if the entry is last entry
|
iva2k |
0:1802fb31b938
|
409
|
* FREE_ENTRY if the entry is free entry
|
iva2k |
0:1802fb31b938
|
410
|
* LFN_ENTRY if the entry is long file name entry
|
iva2k |
0:1802fb31b938
|
411
|
* SFN_ENTRY if the entry is short file name entry
|
iva2k |
0:1802fb31b938
|
412
|
*
|
iva2k |
0:1802fb31b938
|
413
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
414
|
*/
|
iva2k |
0:1802fb31b938
|
415
|
|
iva2k |
0:1802fb31b938
|
416
|
USB_INT32U FAT_ChkEntType (volatile USB_INT08U *ent)
|
iva2k |
0:1802fb31b938
|
417
|
{
|
iva2k |
0:1802fb31b938
|
418
|
if (ent[0] == 0x00) { /* First byte is 0 means it is the last entry */
|
iva2k |
0:1802fb31b938
|
419
|
return (LAST_ENTRY);
|
iva2k |
0:1802fb31b938
|
420
|
}
|
iva2k |
0:1802fb31b938
|
421
|
|
iva2k |
0:1802fb31b938
|
422
|
if (ent[0] == 0xE5) { /* First byte is 0xE5 means it is the free entry */
|
iva2k |
0:1802fb31b938
|
423
|
return (FREE_ENTRY);
|
iva2k |
0:1802fb31b938
|
424
|
}
|
iva2k |
0:1802fb31b938
|
425
|
|
iva2k |
0:1802fb31b938
|
426
|
if (0x0F == ent[11]) { /* If 11th byte of an entry is 0x0F, it is LFN */
|
iva2k |
0:1802fb31b938
|
427
|
return (LFN_ENTRY);
|
iva2k |
0:1802fb31b938
|
428
|
|
iva2k |
0:1802fb31b938
|
429
|
} else {
|
iva2k |
0:1802fb31b938
|
430
|
return (SFN_ENTRY); /* Else it is the SFN */
|
iva2k |
0:1802fb31b938
|
431
|
}
|
iva2k |
0:1802fb31b938
|
432
|
}
|
iva2k |
0:1802fb31b938
|
433
|
|
iva2k |
0:1802fb31b938
|
434
|
/*
|
iva2k |
0:1802fb31b938
|
435
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
436
|
* READ DATA REQUESTED BY THE USER
|
iva2k |
0:1802fb31b938
|
437
|
*
|
iva2k |
0:1802fb31b938
|
438
|
* Description: This function reads data requested by the application from the file pointed by file descriptor.
|
iva2k |
0:1802fb31b938
|
439
|
*
|
iva2k |
0:1802fb31b938
|
440
|
* Arguments : fd file descriptor that points to a file
|
iva2k |
0:1802fb31b938
|
441
|
* buffer buffer into which the data is to be read
|
iva2k |
0:1802fb31b938
|
442
|
* num_bytes number of bytes requested by the application
|
iva2k |
0:1802fb31b938
|
443
|
*
|
iva2k |
0:1802fb31b938
|
444
|
* Returns : total_bytes_read Total bytes actually read.
|
iva2k |
0:1802fb31b938
|
445
|
*
|
iva2k |
0:1802fb31b938
|
446
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
447
|
*/
|
iva2k |
0:1802fb31b938
|
448
|
|
iva2k |
0:1802fb31b938
|
449
|
USB_INT32U FILE_Read ( USB_INT32S fd,
|
iva2k |
0:1802fb31b938
|
450
|
volatile USB_INT08U *buffer,
|
iva2k |
0:1802fb31b938
|
451
|
USB_INT32U num_bytes)
|
iva2k |
0:1802fb31b938
|
452
|
{
|
iva2k |
0:1802fb31b938
|
453
|
USB_INT32U total_bytes_to_read; /* Total bytes requested by the application */
|
iva2k |
0:1802fb31b938
|
454
|
USB_INT32U total_bytes_read; /* Total bytes read */
|
iva2k |
0:1802fb31b938
|
455
|
USB_INT32U bytes_read; /* Bytes read from one cluster */
|
iva2k |
0:1802fb31b938
|
456
|
USB_INT32U bytes_to_read; /* Bytes to be read in one cluster */
|
iva2k |
0:1802fb31b938
|
457
|
FILE_ENTRY *entry; /* Entry that contains the file attribute information */
|
iva2k |
0:1802fb31b938
|
458
|
USB_INT16U next_clus; /* Next cluster of the current cluster in the cluster chain */
|
iva2k |
0:1802fb31b938
|
459
|
|
iva2k |
0:1802fb31b938
|
460
|
entry = &FAT_FileEntry[fd-1]; /* Get file entry from file descriptor */
|
iva2k |
0:1802fb31b938
|
461
|
total_bytes_read = 0;
|
iva2k |
0:1802fb31b938
|
462
|
|
iva2k |
0:1802fb31b938
|
463
|
if (entry->FileSize == 0) {
|
iva2k |
0:1802fb31b938
|
464
|
return (0);
|
iva2k |
0:1802fb31b938
|
465
|
}
|
iva2k |
0:1802fb31b938
|
466
|
if (num_bytes < entry->FileSize) {
|
iva2k |
0:1802fb31b938
|
467
|
total_bytes_to_read = num_bytes;
|
iva2k |
0:1802fb31b938
|
468
|
} else {
|
iva2k |
0:1802fb31b938
|
469
|
total_bytes_to_read = entry->FileSize;
|
iva2k |
0:1802fb31b938
|
470
|
}
|
iva2k |
0:1802fb31b938
|
471
|
do {
|
iva2k |
0:1802fb31b938
|
472
|
next_clus = FAT_GetNextClus(entry->CurrClus); /* Get next cluster */
|
iva2k |
0:1802fb31b938
|
473
|
if (next_clus == 0) { /* If the current cluster is the last cluster */
|
iva2k |
0:1802fb31b938
|
474
|
/* If the offset is at the end of the file */
|
iva2k |
0:1802fb31b938
|
475
|
if (entry->CurrClusOffset == (entry->FileSize % FAT_BootSec.BytsPerClus)) {
|
iva2k |
0:1802fb31b938
|
476
|
return (0); /* No more bytes to read */
|
iva2k |
0:1802fb31b938
|
477
|
} /* If requested number is > remaining bytes in the last cluster */
|
iva2k |
0:1802fb31b938
|
478
|
if (total_bytes_to_read > ((entry->FileSize % FAT_BootSec.BytsPerClus) - entry->CurrClusOffset)) {
|
iva2k |
0:1802fb31b938
|
479
|
total_bytes_to_read = (entry->FileSize % FAT_BootSec.BytsPerClus) - entry->CurrClusOffset;
|
iva2k |
0:1802fb31b938
|
480
|
}
|
iva2k |
0:1802fb31b938
|
481
|
bytes_to_read = total_bytes_to_read;
|
iva2k |
0:1802fb31b938
|
482
|
/* If requested number is > remaining bytes in the current cluster */
|
iva2k |
0:1802fb31b938
|
483
|
} else if (total_bytes_to_read > (FAT_BootSec.BytsPerClus - entry->CurrClusOffset)) {
|
iva2k |
0:1802fb31b938
|
484
|
bytes_to_read = FAT_BootSec.BytsPerClus - entry->CurrClusOffset;
|
iva2k |
0:1802fb31b938
|
485
|
} else {
|
iva2k |
0:1802fb31b938
|
486
|
bytes_to_read = total_bytes_to_read;
|
iva2k |
0:1802fb31b938
|
487
|
}
|
iva2k |
0:1802fb31b938
|
488
|
bytes_read = FAT_ClusRead(entry->CurrClus, /* Read bytes from a single cluster */
|
iva2k |
0:1802fb31b938
|
489
|
entry->CurrClusOffset,
|
iva2k |
0:1802fb31b938
|
490
|
buffer,
|
iva2k |
0:1802fb31b938
|
491
|
bytes_to_read);
|
iva2k |
0:1802fb31b938
|
492
|
buffer += bytes_read;
|
iva2k |
0:1802fb31b938
|
493
|
total_bytes_read += bytes_read;
|
iva2k |
0:1802fb31b938
|
494
|
total_bytes_to_read -= bytes_read;
|
iva2k |
0:1802fb31b938
|
495
|
/* If the cluster offset reaches end of the cluster, make it 0 */
|
iva2k |
0:1802fb31b938
|
496
|
if (entry->CurrClusOffset + bytes_read == FAT_BootSec.BytsPerClus) {
|
iva2k |
0:1802fb31b938
|
497
|
entry->CurrClusOffset = 0;
|
iva2k |
0:1802fb31b938
|
498
|
} else {
|
iva2k |
0:1802fb31b938
|
499
|
entry->CurrClusOffset += bytes_read; /* Else increment the cluster offset */
|
iva2k |
0:1802fb31b938
|
500
|
}
|
iva2k |
0:1802fb31b938
|
501
|
if (entry->CurrClusOffset == 0) {
|
iva2k |
0:1802fb31b938
|
502
|
entry->CurrClus = (next_clus > 0) ? next_clus : entry->CurrClus;
|
iva2k |
0:1802fb31b938
|
503
|
}
|
iva2k |
0:1802fb31b938
|
504
|
} while (total_bytes_to_read);
|
iva2k |
0:1802fb31b938
|
505
|
return (total_bytes_read);
|
iva2k |
0:1802fb31b938
|
506
|
}
|
iva2k |
0:1802fb31b938
|
507
|
|
iva2k |
0:1802fb31b938
|
508
|
/*
|
iva2k |
0:1802fb31b938
|
509
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
510
|
* READ FROM ONE CLUSTER
|
iva2k |
0:1802fb31b938
|
511
|
*
|
iva2k |
0:1802fb31b938
|
512
|
* Description: This function reads the data from a single cluster.
|
iva2k |
0:1802fb31b938
|
513
|
*
|
iva2k |
0:1802fb31b938
|
514
|
* Arguments : curr_clus Current cluster from which the data has to read
|
iva2k |
0:1802fb31b938
|
515
|
* clus_offset Position in the current cluster from which the data has to read
|
iva2k |
0:1802fb31b938
|
516
|
* buffer Buffer into which the data has to read
|
iva2k |
0:1802fb31b938
|
517
|
* num_bytes Number of bytes to read
|
iva2k |
0:1802fb31b938
|
518
|
*
|
iva2k |
0:1802fb31b938
|
519
|
* Returns : tot_bytes_read Total bytes read from the current cluster
|
iva2k |
0:1802fb31b938
|
520
|
*
|
iva2k |
0:1802fb31b938
|
521
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
522
|
*/
|
iva2k |
0:1802fb31b938
|
523
|
|
iva2k |
0:1802fb31b938
|
524
|
USB_INT32U FAT_ClusRead ( USB_INT16U curr_clus,
|
iva2k |
0:1802fb31b938
|
525
|
USB_INT32U clus_offset,
|
iva2k |
0:1802fb31b938
|
526
|
volatile USB_INT08U *buffer,
|
iva2k |
0:1802fb31b938
|
527
|
USB_INT32U num_bytes)
|
iva2k |
0:1802fb31b938
|
528
|
{
|
iva2k |
0:1802fb31b938
|
529
|
USB_INT32U tot_bytes_read; /* total bytes read in the current cluster */
|
iva2k |
0:1802fb31b938
|
530
|
USB_INT32U n_bytes; /* Bytes to read in the current sector */
|
iva2k |
0:1802fb31b938
|
531
|
USB_INT32U start_sec; /* Starting sector of the current cluster */
|
iva2k |
0:1802fb31b938
|
532
|
USB_INT32U sec_num; /*Current sector number */
|
iva2k |
0:1802fb31b938
|
533
|
USB_INT16U num_sec; /* Number of sectors to be read */
|
iva2k |
0:1802fb31b938
|
534
|
USB_INT32U sec_offset; /* Offset in the current sector */
|
iva2k |
0:1802fb31b938
|
535
|
USB_INT32U cnt;
|
iva2k |
0:1802fb31b938
|
536
|
|
iva2k |
0:1802fb31b938
|
537
|
|
iva2k |
0:1802fb31b938
|
538
|
tot_bytes_read = 0;
|
iva2k |
0:1802fb31b938
|
539
|
start_sec = ((curr_clus - 2) * FAT_BootSec.SecPerClus) + FAT_BootSec.FirstDataSec;
|
iva2k |
0:1802fb31b938
|
540
|
sec_num = start_sec + (clus_offset / FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
541
|
num_sec = num_bytes / FAT_BootSec.BytsPerSec;
|
iva2k |
0:1802fb31b938
|
542
|
sec_offset = clus_offset % FAT_BootSec.BytsPerSec;
|
iva2k |
0:1802fb31b938
|
543
|
|
iva2k |
0:1802fb31b938
|
544
|
if (sec_offset) { /* If the sector offset is at the middle of a sector */
|
iva2k |
0:1802fb31b938
|
545
|
MS_BulkRecv(sec_num, 1, FATBuffer); /* Read the first sector */
|
iva2k |
0:1802fb31b938
|
546
|
n_bytes = (FAT_BootSec.BytsPerSec - sec_offset <= num_bytes) ?
|
iva2k |
0:1802fb31b938
|
547
|
(FAT_BootSec.BytsPerSec - sec_offset) : num_bytes;
|
iva2k |
0:1802fb31b938
|
548
|
for (cnt = sec_offset; cnt < sec_offset + n_bytes; cnt++) {
|
iva2k |
0:1802fb31b938
|
549
|
*buffer = FATBuffer[cnt]; /* Copy the required bytes to user buffer */
|
iva2k |
0:1802fb31b938
|
550
|
buffer++;
|
iva2k |
0:1802fb31b938
|
551
|
}
|
iva2k |
0:1802fb31b938
|
552
|
tot_bytes_read += n_bytes;
|
iva2k |
0:1802fb31b938
|
553
|
clus_offset += n_bytes;
|
iva2k |
0:1802fb31b938
|
554
|
num_bytes -= n_bytes;
|
iva2k |
0:1802fb31b938
|
555
|
sec_num++;
|
iva2k |
0:1802fb31b938
|
556
|
}
|
iva2k |
0:1802fb31b938
|
557
|
|
iva2k |
0:1802fb31b938
|
558
|
if (num_bytes / FAT_BootSec.BytsPerSec) { /* Read all the remaining full sectors */
|
iva2k |
0:1802fb31b938
|
559
|
|
iva2k |
0:1802fb31b938
|
560
|
num_sec = num_bytes / FAT_BootSec.BytsPerSec;
|
iva2k |
0:1802fb31b938
|
561
|
MS_BulkRecv(sec_num, num_sec, buffer);
|
iva2k |
0:1802fb31b938
|
562
|
buffer += (num_sec * FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
563
|
tot_bytes_read += (num_sec * FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
564
|
clus_offset += (num_sec * FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
565
|
num_bytes -= (num_sec * FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
566
|
sec_num += num_sec;
|
iva2k |
0:1802fb31b938
|
567
|
}
|
iva2k |
0:1802fb31b938
|
568
|
|
iva2k |
0:1802fb31b938
|
569
|
if (num_bytes) { /* Read the last sector for the remaining bytes */
|
iva2k |
0:1802fb31b938
|
570
|
MS_BulkRecv(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
571
|
for (cnt = 0; cnt < num_bytes; cnt++) {
|
iva2k |
0:1802fb31b938
|
572
|
*buffer = FATBuffer[cnt]; /* Copy the required bytes to user buffer */
|
iva2k |
0:1802fb31b938
|
573
|
buffer++;
|
iva2k |
0:1802fb31b938
|
574
|
}
|
iva2k |
0:1802fb31b938
|
575
|
tot_bytes_read += num_bytes;
|
iva2k |
0:1802fb31b938
|
576
|
}
|
iva2k |
0:1802fb31b938
|
577
|
|
iva2k |
0:1802fb31b938
|
578
|
return (tot_bytes_read);
|
iva2k |
0:1802fb31b938
|
579
|
}
|
iva2k |
0:1802fb31b938
|
580
|
|
iva2k |
0:1802fb31b938
|
581
|
/*
|
iva2k |
0:1802fb31b938
|
582
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
583
|
* WRITE THE DATA REQUESTED BY THE USER
|
iva2k |
0:1802fb31b938
|
584
|
*
|
iva2k |
0:1802fb31b938
|
585
|
* Description: This function writes data requested by the application to the file pointed by file descriptor
|
iva2k |
0:1802fb31b938
|
586
|
*
|
iva2k |
0:1802fb31b938
|
587
|
* Arguments : fd file descriptor that points to a file
|
iva2k |
0:1802fb31b938
|
588
|
* buffer buffer from which the data is to be written
|
iva2k |
0:1802fb31b938
|
589
|
* num_bytes number of bytes requested by the application
|
iva2k |
0:1802fb31b938
|
590
|
*
|
iva2k |
0:1802fb31b938
|
591
|
* Returns : total_bytes_written Total bytes actually written
|
iva2k |
0:1802fb31b938
|
592
|
*
|
iva2k |
0:1802fb31b938
|
593
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
594
|
*/
|
iva2k |
0:1802fb31b938
|
595
|
|
iva2k |
0:1802fb31b938
|
596
|
USB_INT32U FILE_Write ( USB_INT32S fd,
|
iva2k |
0:1802fb31b938
|
597
|
volatile USB_INT08U *buffer,
|
iva2k |
0:1802fb31b938
|
598
|
USB_INT32U num_bytes)
|
iva2k |
0:1802fb31b938
|
599
|
{
|
iva2k |
0:1802fb31b938
|
600
|
USB_INT32U total_bytes_to_write; /* Total bytes requested by application */
|
iva2k |
0:1802fb31b938
|
601
|
USB_INT32U total_bytes_written; /* Total bytes written */
|
iva2k |
0:1802fb31b938
|
602
|
USB_INT32U bytes_written; /* Bytes written in a single cluster */
|
iva2k |
0:1802fb31b938
|
603
|
USB_INT32U bytes_to_write; /* Bytes to write in a single cluster */
|
iva2k |
0:1802fb31b938
|
604
|
FILE_ENTRY *entry; /* Entry that contains the file attribute information */
|
iva2k |
0:1802fb31b938
|
605
|
USB_INT16U free_clus; /* Free cluster available in the disk */
|
iva2k |
0:1802fb31b938
|
606
|
|
iva2k |
0:1802fb31b938
|
607
|
|
iva2k |
0:1802fb31b938
|
608
|
entry = &FAT_FileEntry[fd-1]; /* Get file entry from file descriptor */
|
iva2k |
0:1802fb31b938
|
609
|
total_bytes_written = 0;
|
iva2k |
0:1802fb31b938
|
610
|
total_bytes_to_write = num_bytes;
|
iva2k |
0:1802fb31b938
|
611
|
|
iva2k |
0:1802fb31b938
|
612
|
if (num_bytes) {
|
iva2k |
0:1802fb31b938
|
613
|
if (entry->FileSize == 0) {
|
iva2k |
0:1802fb31b938
|
614
|
free_clus = FAT_GetFreeClus();
|
iva2k |
0:1802fb31b938
|
615
|
FAT_UpdateFAT(free_clus, 0xFFFF);
|
iva2k |
0:1802fb31b938
|
616
|
entry->CurrClus = free_clus;
|
iva2k |
0:1802fb31b938
|
617
|
MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
618
|
WriteLE16U(&FATBuffer[(entry->EntrySecOffset) + 26], free_clus);
|
iva2k |
0:1802fb31b938
|
619
|
MS_BulkSend(entry->EntrySec, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
620
|
}
|
iva2k |
0:1802fb31b938
|
621
|
} else {
|
iva2k |
0:1802fb31b938
|
622
|
return (0);
|
iva2k |
0:1802fb31b938
|
623
|
}
|
iva2k |
0:1802fb31b938
|
624
|
entry->CurrClus = FAT_GetEndClus(entry->CurrClus); /* Make the current cluster as end cluster */
|
iva2k |
0:1802fb31b938
|
625
|
entry->CurrClusOffset = entry->FileSize % FAT_BootSec.BytsPerClus; /* Move cluster offset to file end */
|
iva2k |
0:1802fb31b938
|
626
|
do {
|
iva2k |
0:1802fb31b938
|
627
|
if (total_bytes_to_write > FAT_BootSec.BytsPerClus - entry->CurrClusOffset) {
|
iva2k |
0:1802fb31b938
|
628
|
bytes_to_write = FAT_BootSec.BytsPerClus - entry->CurrClusOffset;
|
iva2k |
0:1802fb31b938
|
629
|
} else {
|
iva2k |
0:1802fb31b938
|
630
|
bytes_to_write = total_bytes_to_write;
|
iva2k |
0:1802fb31b938
|
631
|
}
|
iva2k |
0:1802fb31b938
|
632
|
bytes_written = FAT_ClusWrite(entry->CurrClus,
|
iva2k |
0:1802fb31b938
|
633
|
entry->CurrClusOffset,
|
iva2k |
0:1802fb31b938
|
634
|
buffer,
|
iva2k |
0:1802fb31b938
|
635
|
bytes_to_write);
|
iva2k |
0:1802fb31b938
|
636
|
buffer += bytes_written;
|
iva2k |
0:1802fb31b938
|
637
|
total_bytes_written += bytes_written;
|
iva2k |
0:1802fb31b938
|
638
|
total_bytes_to_write -= bytes_written;
|
iva2k |
0:1802fb31b938
|
639
|
entry->FileSize += bytes_written;
|
iva2k |
0:1802fb31b938
|
640
|
if (entry->CurrClusOffset + bytes_written == FAT_BootSec.BytsPerClus) {
|
iva2k |
0:1802fb31b938
|
641
|
entry->CurrClusOffset = 0;
|
iva2k |
0:1802fb31b938
|
642
|
} else {
|
iva2k |
0:1802fb31b938
|
643
|
entry->CurrClusOffset += bytes_written;
|
iva2k |
0:1802fb31b938
|
644
|
}
|
iva2k |
0:1802fb31b938
|
645
|
if (entry->CurrClusOffset == 0) {
|
iva2k |
0:1802fb31b938
|
646
|
free_clus = FAT_GetFreeClus();
|
iva2k |
0:1802fb31b938
|
647
|
if (free_clus == 0) {
|
iva2k |
0:1802fb31b938
|
648
|
return (total_bytes_written);
|
iva2k |
0:1802fb31b938
|
649
|
}
|
iva2k |
0:1802fb31b938
|
650
|
FAT_UpdateFAT(entry->CurrClus, free_clus);
|
iva2k |
0:1802fb31b938
|
651
|
FAT_UpdateFAT(free_clus, 0xFFFF);
|
iva2k |
0:1802fb31b938
|
652
|
entry->CurrClus = free_clus;
|
iva2k |
0:1802fb31b938
|
653
|
}
|
iva2k |
0:1802fb31b938
|
654
|
} while (total_bytes_to_write);
|
iva2k |
0:1802fb31b938
|
655
|
return (total_bytes_written);
|
iva2k |
0:1802fb31b938
|
656
|
}
|
iva2k |
0:1802fb31b938
|
657
|
|
iva2k |
0:1802fb31b938
|
658
|
/*
|
iva2k |
0:1802fb31b938
|
659
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
660
|
* WRITE TO ONE CLUSTER
|
iva2k |
0:1802fb31b938
|
661
|
*
|
iva2k |
0:1802fb31b938
|
662
|
* Description: This function writes the data to a single cluster.
|
iva2k |
0:1802fb31b938
|
663
|
*
|
iva2k |
0:1802fb31b938
|
664
|
* Arguments : curr_clus Current cluster into which the data has to write
|
iva2k |
0:1802fb31b938
|
665
|
* clus_offset Position in the current cluster from which the data has to write
|
iva2k |
0:1802fb31b938
|
666
|
* buffer Buffer from which the data has to write
|
iva2k |
0:1802fb31b938
|
667
|
* num_bytes Number of bytes to write
|
iva2k |
0:1802fb31b938
|
668
|
*
|
iva2k |
0:1802fb31b938
|
669
|
* Returns : tot_bytes_read Total bytes written into the current cluster
|
iva2k |
0:1802fb31b938
|
670
|
*
|
iva2k |
0:1802fb31b938
|
671
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
672
|
*/
|
iva2k |
0:1802fb31b938
|
673
|
|
iva2k |
0:1802fb31b938
|
674
|
USB_INT32U FAT_ClusWrite ( USB_INT16U curr_clus,
|
iva2k |
0:1802fb31b938
|
675
|
USB_INT32U clus_offset,
|
iva2k |
0:1802fb31b938
|
676
|
volatile USB_INT08U *buffer,
|
iva2k |
0:1802fb31b938
|
677
|
USB_INT32U num_bytes)
|
iva2k |
0:1802fb31b938
|
678
|
{
|
iva2k |
0:1802fb31b938
|
679
|
USB_INT32U tot_bytes_written;
|
iva2k |
0:1802fb31b938
|
680
|
USB_INT32U n_bytes;
|
iva2k |
0:1802fb31b938
|
681
|
USB_INT32U start_sec;
|
iva2k |
0:1802fb31b938
|
682
|
USB_INT32U sec_num;
|
iva2k |
0:1802fb31b938
|
683
|
USB_INT16U num_sec;
|
iva2k |
0:1802fb31b938
|
684
|
USB_INT32U sec_offset;
|
iva2k |
0:1802fb31b938
|
685
|
USB_INT32U cnt;
|
iva2k |
0:1802fb31b938
|
686
|
|
iva2k |
0:1802fb31b938
|
687
|
|
iva2k |
0:1802fb31b938
|
688
|
tot_bytes_written = 0;
|
iva2k |
0:1802fb31b938
|
689
|
start_sec = ((curr_clus - 2) * FAT_BootSec.SecPerClus) + FAT_BootSec.FirstDataSec;
|
iva2k |
0:1802fb31b938
|
690
|
sec_num = start_sec + (clus_offset / FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
691
|
num_sec = num_bytes / FAT_BootSec.BytsPerSec;
|
iva2k |
0:1802fb31b938
|
692
|
sec_offset = clus_offset % FAT_BootSec.BytsPerSec;
|
iva2k |
0:1802fb31b938
|
693
|
|
iva2k |
0:1802fb31b938
|
694
|
if (sec_offset) {
|
iva2k |
0:1802fb31b938
|
695
|
MS_BulkRecv(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
696
|
n_bytes = (FAT_BootSec.BytsPerSec - sec_offset <= num_bytes) ?
|
iva2k |
0:1802fb31b938
|
697
|
(FAT_BootSec.BytsPerSec - sec_offset) : num_bytes;
|
iva2k |
0:1802fb31b938
|
698
|
for (cnt = sec_offset; cnt < (sec_offset + n_bytes); cnt++) {
|
iva2k |
0:1802fb31b938
|
699
|
FATBuffer[cnt] = *buffer;
|
iva2k |
0:1802fb31b938
|
700
|
buffer++;
|
iva2k |
0:1802fb31b938
|
701
|
}
|
iva2k |
0:1802fb31b938
|
702
|
MS_BulkSend(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
703
|
tot_bytes_written += n_bytes;
|
iva2k |
0:1802fb31b938
|
704
|
clus_offset += n_bytes;
|
iva2k |
0:1802fb31b938
|
705
|
num_bytes -= n_bytes;
|
iva2k |
0:1802fb31b938
|
706
|
sec_num++;
|
iva2k |
0:1802fb31b938
|
707
|
}
|
iva2k |
0:1802fb31b938
|
708
|
if (num_bytes / FAT_BootSec.BytsPerSec) {
|
iva2k |
0:1802fb31b938
|
709
|
num_sec = num_bytes / FAT_BootSec.BytsPerSec;
|
iva2k |
0:1802fb31b938
|
710
|
MS_BulkSend(sec_num, num_sec, buffer);
|
iva2k |
0:1802fb31b938
|
711
|
buffer += (num_sec * FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
712
|
tot_bytes_written += (num_sec * FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
713
|
clus_offset += (num_sec * FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
714
|
num_bytes -= (num_sec * FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
715
|
sec_num += num_sec;
|
iva2k |
0:1802fb31b938
|
716
|
}
|
iva2k |
0:1802fb31b938
|
717
|
if (num_bytes) {
|
iva2k |
0:1802fb31b938
|
718
|
MS_BulkRecv(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
719
|
|
iva2k |
0:1802fb31b938
|
720
|
for (cnt = 0; cnt < num_bytes; cnt++) {
|
iva2k |
0:1802fb31b938
|
721
|
FATBuffer[cnt] = *buffer;
|
iva2k |
0:1802fb31b938
|
722
|
buffer++;
|
iva2k |
0:1802fb31b938
|
723
|
}
|
iva2k |
0:1802fb31b938
|
724
|
MS_BulkSend(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
725
|
tot_bytes_written += num_bytes;
|
iva2k |
0:1802fb31b938
|
726
|
}
|
iva2k |
0:1802fb31b938
|
727
|
return (tot_bytes_written);
|
iva2k |
0:1802fb31b938
|
728
|
}
|
iva2k |
0:1802fb31b938
|
729
|
|
iva2k |
0:1802fb31b938
|
730
|
/*
|
iva2k |
0:1802fb31b938
|
731
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
732
|
* GET NEXT CLUSTER
|
iva2k |
0:1802fb31b938
|
733
|
*
|
iva2k |
0:1802fb31b938
|
734
|
* Description: This function returns next cluster of the current cluster in the cluster chain. If the current
|
iva2k |
0:1802fb31b938
|
735
|
* cluster is the last cluster then this function returns 0
|
iva2k |
0:1802fb31b938
|
736
|
*
|
iva2k |
0:1802fb31b938
|
737
|
* Arguments : clus_no The cluster number for which the next cluster to be found
|
iva2k |
0:1802fb31b938
|
738
|
*
|
iva2k |
0:1802fb31b938
|
739
|
* Returns : next_clus if the current cluster is not the last cluster
|
iva2k |
0:1802fb31b938
|
740
|
* 0 if the current cluster is the last cluster
|
iva2k |
0:1802fb31b938
|
741
|
* Note: In practical cluster number 0 doesn't exist
|
iva2k |
0:1802fb31b938
|
742
|
*
|
iva2k |
0:1802fb31b938
|
743
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
744
|
*/
|
iva2k |
0:1802fb31b938
|
745
|
|
iva2k |
0:1802fb31b938
|
746
|
USB_INT16U FAT_GetNextClus (USB_INT16U clus_no)
|
iva2k |
0:1802fb31b938
|
747
|
{
|
iva2k |
0:1802fb31b938
|
748
|
USB_INT32U sec_num;
|
iva2k |
0:1802fb31b938
|
749
|
USB_INT32U ent_offset;
|
iva2k |
0:1802fb31b938
|
750
|
USB_INT16U next_clus;
|
iva2k |
0:1802fb31b938
|
751
|
|
iva2k |
0:1802fb31b938
|
752
|
/* Get the sector number in the FAT that contains current cluster */
|
iva2k |
0:1802fb31b938
|
753
|
sec_num = FAT_BootSec.RsvdSecCnt + ((clus_no * 2) / FAT_BootSec.BytsPerSec);
|
iva2k |
0:1802fb31b938
|
754
|
/* Get the sector offset in the FAT where the current cluster is located */
|
iva2k |
0:1802fb31b938
|
755
|
ent_offset = (clus_no * 2) % FAT_BootSec.BytsPerSec;
|
iva2k |
0:1802fb31b938
|
756
|
MS_BulkRecv(sec_num, 1, FATBuffer); /* Read that sector */
|
iva2k |
0:1802fb31b938
|
757
|
next_clus = ReadLE16U(&FATBuffer[ent_offset]); /* Read the next cluster */
|
iva2k |
0:1802fb31b938
|
758
|
if (next_clus >= 0xFFF8 && next_clus <= 0xFFFF) { /* If that value is in between 0xFFF8 and 0xFFFF */
|
iva2k |
0:1802fb31b938
|
759
|
next_clus = 0; /* Current cluster is the end cluster */
|
iva2k |
0:1802fb31b938
|
760
|
}
|
iva2k |
0:1802fb31b938
|
761
|
return (next_clus);
|
iva2k |
0:1802fb31b938
|
762
|
|
iva2k |
0:1802fb31b938
|
763
|
}
|
iva2k |
0:1802fb31b938
|
764
|
|
iva2k |
0:1802fb31b938
|
765
|
/*
|
iva2k |
0:1802fb31b938
|
766
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
767
|
* GET FREE CLUSTER
|
iva2k |
0:1802fb31b938
|
768
|
*
|
iva2k |
0:1802fb31b938
|
769
|
* Description: This function returns the free cluster if available
|
iva2k |
0:1802fb31b938
|
770
|
*
|
iva2k |
0:1802fb31b938
|
771
|
* Arguments : None
|
iva2k |
0:1802fb31b938
|
772
|
*
|
iva2k |
0:1802fb31b938
|
773
|
* Returns : free_clus if available
|
iva2k |
0:1802fb31b938
|
774
|
* 0 if not available(means the disk is full)
|
iva2k |
0:1802fb31b938
|
775
|
*
|
iva2k |
0:1802fb31b938
|
776
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
777
|
*/
|
iva2k |
0:1802fb31b938
|
778
|
|
iva2k |
0:1802fb31b938
|
779
|
USB_INT16U FAT_GetFreeClus (void)
|
iva2k |
0:1802fb31b938
|
780
|
{
|
iva2k |
0:1802fb31b938
|
781
|
USB_INT32U num_sec;
|
iva2k |
0:1802fb31b938
|
782
|
USB_INT32U cnt;
|
iva2k |
0:1802fb31b938
|
783
|
USB_INT32U sec_num;
|
iva2k |
0:1802fb31b938
|
784
|
USB_INT16U free_clus;
|
iva2k |
0:1802fb31b938
|
785
|
|
iva2k |
0:1802fb31b938
|
786
|
|
iva2k |
0:1802fb31b938
|
787
|
sec_num = FAT_BootSec.RsvdSecCnt;
|
iva2k |
0:1802fb31b938
|
788
|
num_sec = FAT_BootSec.FATSz16;
|
iva2k |
0:1802fb31b938
|
789
|
while (sec_num < (FAT_BootSec.RsvdSecCnt + num_sec)) {
|
iva2k |
0:1802fb31b938
|
790
|
MS_BulkRecv(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
791
|
for (cnt = 0; cnt < FAT_BootSec.BytsPerSec; cnt += 2) {
|
iva2k |
0:1802fb31b938
|
792
|
if (ReadLE16U(&FATBuffer[cnt]) == 0) {
|
iva2k |
0:1802fb31b938
|
793
|
free_clus = (((sec_num - FAT_BootSec.RsvdSecCnt) * FAT_BootSec.BytsPerSec) + cnt) / 2;
|
iva2k |
0:1802fb31b938
|
794
|
return (free_clus);
|
iva2k |
0:1802fb31b938
|
795
|
}
|
iva2k |
0:1802fb31b938
|
796
|
}
|
iva2k |
0:1802fb31b938
|
797
|
sec_num++;
|
iva2k |
0:1802fb31b938
|
798
|
}
|
iva2k |
0:1802fb31b938
|
799
|
return (0);
|
iva2k |
0:1802fb31b938
|
800
|
}
|
iva2k |
0:1802fb31b938
|
801
|
|
iva2k |
0:1802fb31b938
|
802
|
/*
|
iva2k |
0:1802fb31b938
|
803
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
804
|
* UPDATE FILE ALLOCATION TABLE
|
iva2k |
0:1802fb31b938
|
805
|
*
|
iva2k |
0:1802fb31b938
|
806
|
* Description: This function updates the file allocation table
|
iva2k |
0:1802fb31b938
|
807
|
*
|
iva2k |
0:1802fb31b938
|
808
|
* Arguments : curr_clus Offset of the current cluster number in the file allocation table
|
iva2k |
0:1802fb31b938
|
809
|
* value Value with which this offset to be updated
|
iva2k |
0:1802fb31b938
|
810
|
*
|
iva2k |
0:1802fb31b938
|
811
|
* Returns : None
|
iva2k |
0:1802fb31b938
|
812
|
*
|
iva2k |
0:1802fb31b938
|
813
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
814
|
*/
|
iva2k |
0:1802fb31b938
|
815
|
|
iva2k |
0:1802fb31b938
|
816
|
void FAT_UpdateFAT (USB_INT16U curr_clus,
|
iva2k |
0:1802fb31b938
|
817
|
USB_INT16U value)
|
iva2k |
0:1802fb31b938
|
818
|
{
|
iva2k |
0:1802fb31b938
|
819
|
USB_INT32U sec_num;
|
iva2k |
0:1802fb31b938
|
820
|
USB_INT32U sec_offset;
|
iva2k |
0:1802fb31b938
|
821
|
|
iva2k |
0:1802fb31b938
|
822
|
sec_num = FAT_BootSec.RsvdSecCnt + (curr_clus * 2) / FAT_BootSec.BytsPerSec;
|
iva2k |
0:1802fb31b938
|
823
|
sec_offset = (curr_clus * 2) % FAT_BootSec.BytsPerSec;
|
iva2k |
0:1802fb31b938
|
824
|
|
iva2k |
0:1802fb31b938
|
825
|
MS_BulkRecv(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
826
|
WriteLE16U(&FATBuffer[sec_offset], value);
|
iva2k |
0:1802fb31b938
|
827
|
MS_BulkSend(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
828
|
}
|
iva2k |
0:1802fb31b938
|
829
|
|
iva2k |
0:1802fb31b938
|
830
|
/*
|
iva2k |
0:1802fb31b938
|
831
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
832
|
* UPDATE THE FILE ENTRY
|
iva2k |
0:1802fb31b938
|
833
|
*
|
iva2k |
0:1802fb31b938
|
834
|
* Description: This function updates the file entry that is located in the root directory
|
iva2k |
0:1802fb31b938
|
835
|
*
|
iva2k |
0:1802fb31b938
|
836
|
* Arguments : entry Pointer to the FILE ENTRY structure which contains the information about the file
|
iva2k |
0:1802fb31b938
|
837
|
*
|
iva2k |
0:1802fb31b938
|
838
|
* Returns : None
|
iva2k |
0:1802fb31b938
|
839
|
*
|
iva2k |
0:1802fb31b938
|
840
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
841
|
*/
|
iva2k |
0:1802fb31b938
|
842
|
|
iva2k |
0:1802fb31b938
|
843
|
void FAT_UpdateEntry (FILE_ENTRY *entry)
|
iva2k |
0:1802fb31b938
|
844
|
{
|
iva2k |
0:1802fb31b938
|
845
|
USB_INT32U sec_num;
|
iva2k |
0:1802fb31b938
|
846
|
USB_INT32U offset;
|
iva2k |
0:1802fb31b938
|
847
|
|
iva2k |
0:1802fb31b938
|
848
|
sec_num = entry->EntrySec;
|
iva2k |
0:1802fb31b938
|
849
|
offset = entry->EntrySecOffset;
|
iva2k |
0:1802fb31b938
|
850
|
MS_BulkRecv(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
851
|
WriteLE32U(&FATBuffer[offset + 28], entry->FileSize);
|
iva2k |
0:1802fb31b938
|
852
|
MS_BulkSend(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
853
|
}
|
iva2k |
0:1802fb31b938
|
854
|
|
iva2k |
0:1802fb31b938
|
855
|
/*
|
iva2k |
0:1802fb31b938
|
856
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
857
|
* CREATING AN ENTRY
|
iva2k |
0:1802fb31b938
|
858
|
*
|
iva2k |
0:1802fb31b938
|
859
|
* Description: This function creates a file entry in the root directory if the file does not exist
|
iva2k |
0:1802fb31b938
|
860
|
*
|
iva2k |
0:1802fb31b938
|
861
|
* Arguments : ent_name_given The file name with which the entry is to be created
|
iva2k |
0:1802fb31b938
|
862
|
* entry Pointer to FILE ENTRY structure
|
iva2k |
0:1802fb31b938
|
863
|
*
|
iva2k |
0:1802fb31b938
|
864
|
* Returns : OK If the entry already exists or successfully created if it doesn't exists
|
iva2k |
0:1802fb31b938
|
865
|
* ERROR If failed to create the entry
|
iva2k |
0:1802fb31b938
|
866
|
*
|
iva2k |
0:1802fb31b938
|
867
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
868
|
*/
|
iva2k |
0:1802fb31b938
|
869
|
|
iva2k |
0:1802fb31b938
|
870
|
USB_INT32S FAT_CreateEntry (USB_INT08U *ent_name_given,
|
iva2k |
0:1802fb31b938
|
871
|
FILE_ENTRY *entry)
|
iva2k |
0:1802fb31b938
|
872
|
{
|
iva2k |
0:1802fb31b938
|
873
|
USB_INT32S rc;
|
iva2k |
0:1802fb31b938
|
874
|
|
iva2k |
0:1802fb31b938
|
875
|
|
iva2k |
0:1802fb31b938
|
876
|
rc = FAT_FindEntry(ent_name_given, entry); /* Find for the given file name in the root directory */
|
iva2k |
0:1802fb31b938
|
877
|
if (rc == MATCH_FOUND) { /* If match found, return */
|
iva2k |
0:1802fb31b938
|
878
|
return (rc);
|
iva2k |
0:1802fb31b938
|
879
|
} else {
|
iva2k |
0:1802fb31b938
|
880
|
rc = FAT_GetFreeEntry(entry); /* Else get a free entry from the root directory */
|
iva2k |
0:1802fb31b938
|
881
|
if (rc != OK) {
|
iva2k |
0:1802fb31b938
|
882
|
return (rc);
|
iva2k |
0:1802fb31b938
|
883
|
} else {
|
iva2k |
0:1802fb31b938
|
884
|
FAT_PutSFN(ent_name_given, entry); /* Store the given short file name in that entry */
|
iva2k |
0:1802fb31b938
|
885
|
return (rc);
|
iva2k |
0:1802fb31b938
|
886
|
}
|
iva2k |
0:1802fb31b938
|
887
|
}
|
iva2k |
0:1802fb31b938
|
888
|
}
|
iva2k |
0:1802fb31b938
|
889
|
|
iva2k |
0:1802fb31b938
|
890
|
/*
|
iva2k |
0:1802fb31b938
|
891
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
892
|
* GET GREE ENTRY
|
iva2k |
0:1802fb31b938
|
893
|
*
|
iva2k |
0:1802fb31b938
|
894
|
* Description: This function searches for a free entry in the root directory. If a free entry is found, the
|
iva2k |
0:1802fb31b938
|
895
|
* sector number and sector offset where the entry is located will be stored
|
iva2k |
0:1802fb31b938
|
896
|
*
|
iva2k |
0:1802fb31b938
|
897
|
* Arguments : entry Pointer to FILE_ENTRY structure
|
iva2k |
0:1802fb31b938
|
898
|
*
|
iva2k |
0:1802fb31b938
|
899
|
* Returns : OK If a free entry is found
|
iva2k |
0:1802fb31b938
|
900
|
* ERROR If no free entry is found
|
iva2k |
0:1802fb31b938
|
901
|
*
|
iva2k |
0:1802fb31b938
|
902
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
903
|
*/
|
iva2k |
0:1802fb31b938
|
904
|
|
iva2k |
0:1802fb31b938
|
905
|
USB_INT32S FAT_GetFreeEntry (FILE_ENTRY *entry)
|
iva2k |
0:1802fb31b938
|
906
|
{
|
iva2k |
0:1802fb31b938
|
907
|
USB_INT32U sec_num;
|
iva2k |
0:1802fb31b938
|
908
|
volatile USB_INT08U *buf;
|
iva2k |
0:1802fb31b938
|
909
|
USB_INT08U ent_type;
|
iva2k |
0:1802fb31b938
|
910
|
|
iva2k |
0:1802fb31b938
|
911
|
|
iva2k |
0:1802fb31b938
|
912
|
for (sec_num = FAT_BootSec.RootDirStartSec;
|
iva2k |
0:1802fb31b938
|
913
|
sec_num < (FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec);
|
iva2k |
0:1802fb31b938
|
914
|
sec_num++) {
|
iva2k |
0:1802fb31b938
|
915
|
|
iva2k |
0:1802fb31b938
|
916
|
MS_BulkRecv(sec_num, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
917
|
buf = FATBuffer;
|
iva2k |
0:1802fb31b938
|
918
|
while (buf < (FATBuffer + FAT_BootSec.BytsPerSec)) {
|
iva2k |
0:1802fb31b938
|
919
|
ent_type = FAT_ChkEntType(buf);
|
iva2k |
0:1802fb31b938
|
920
|
if (ent_type == FREE_ENTRY) {
|
iva2k |
0:1802fb31b938
|
921
|
entry->EntrySec = sec_num;
|
iva2k |
0:1802fb31b938
|
922
|
entry->EntrySecOffset = buf - FATBuffer;
|
iva2k |
0:1802fb31b938
|
923
|
return (OK);
|
iva2k |
0:1802fb31b938
|
924
|
}
|
iva2k |
0:1802fb31b938
|
925
|
if (ent_type == LAST_ENTRY) {
|
iva2k |
0:1802fb31b938
|
926
|
return (ERR_ROOT_DIR_FULL);
|
iva2k |
0:1802fb31b938
|
927
|
} else {
|
iva2k |
0:1802fb31b938
|
928
|
buf += 32;
|
iva2k |
0:1802fb31b938
|
929
|
}
|
iva2k |
0:1802fb31b938
|
930
|
}
|
iva2k |
0:1802fb31b938
|
931
|
}
|
iva2k |
0:1802fb31b938
|
932
|
return (ERR_ROOT_DIR_FULL);
|
iva2k |
0:1802fb31b938
|
933
|
}
|
iva2k |
0:1802fb31b938
|
934
|
|
iva2k |
0:1802fb31b938
|
935
|
/*
|
iva2k |
0:1802fb31b938
|
936
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
937
|
* PUT SHORT FILE NAME
|
iva2k |
0:1802fb31b938
|
938
|
*
|
iva2k |
0:1802fb31b938
|
939
|
* Description: This function fills the file entry with the short file name given by the user
|
iva2k |
0:1802fb31b938
|
940
|
*
|
iva2k |
0:1802fb31b938
|
941
|
* Arguments : ent_name_given File name given by the user
|
iva2k |
0:1802fb31b938
|
942
|
* entry Pointer to the FILE_ENTRY structure
|
iva2k |
0:1802fb31b938
|
943
|
*
|
iva2k |
0:1802fb31b938
|
944
|
* Returns : None
|
iva2k |
0:1802fb31b938
|
945
|
*
|
iva2k |
0:1802fb31b938
|
946
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
947
|
*/
|
iva2k |
0:1802fb31b938
|
948
|
|
iva2k |
0:1802fb31b938
|
949
|
void FAT_PutSFN (USB_INT08U *ent_name_given,
|
iva2k |
0:1802fb31b938
|
950
|
FILE_ENTRY *entry)
|
iva2k |
0:1802fb31b938
|
951
|
{
|
iva2k |
0:1802fb31b938
|
952
|
USB_INT32U idx;
|
iva2k |
0:1802fb31b938
|
953
|
|
iva2k |
0:1802fb31b938
|
954
|
/* Read the sector from root directory containing the free entry */
|
iva2k |
0:1802fb31b938
|
955
|
MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
956
|
for (idx = 0; idx < 8; idx++) { /* Fill the first eight charecters of the entry with file name */
|
iva2k |
0:1802fb31b938
|
957
|
if (*ent_name_given == '.') {
|
iva2k |
0:1802fb31b938
|
958
|
while (idx < 8) {
|
iva2k |
0:1802fb31b938
|
959
|
FATBuffer[entry->EntrySecOffset + idx] = 0x20;
|
iva2k |
0:1802fb31b938
|
960
|
idx++;
|
iva2k |
0:1802fb31b938
|
961
|
}
|
iva2k |
0:1802fb31b938
|
962
|
ent_name_given++;
|
iva2k |
0:1802fb31b938
|
963
|
} else {
|
iva2k |
0:1802fb31b938
|
964
|
FATBuffer[entry->EntrySecOffset + idx] = *ent_name_given;
|
iva2k |
0:1802fb31b938
|
965
|
ent_name_given++;
|
iva2k |
0:1802fb31b938
|
966
|
}
|
iva2k |
0:1802fb31b938
|
967
|
}
|
iva2k |
0:1802fb31b938
|
968
|
|
iva2k |
0:1802fb31b938
|
969
|
for (idx = 8; idx < 11; idx++) { /* Fill the next 3 charecters with file extension */
|
iva2k |
0:1802fb31b938
|
970
|
if (*ent_name_given == '.') {
|
iva2k |
0:1802fb31b938
|
971
|
while (idx < 11) {
|
iva2k |
0:1802fb31b938
|
972
|
FATBuffer[entry->EntrySecOffset + idx] = 0x20;
|
iva2k |
0:1802fb31b938
|
973
|
idx++;
|
iva2k |
0:1802fb31b938
|
974
|
}
|
iva2k |
0:1802fb31b938
|
975
|
} else {
|
iva2k |
0:1802fb31b938
|
976
|
FATBuffer[entry->EntrySecOffset + idx] = *ent_name_given;
|
iva2k |
0:1802fb31b938
|
977
|
ent_name_given++;
|
iva2k |
0:1802fb31b938
|
978
|
}
|
iva2k |
0:1802fb31b938
|
979
|
}
|
iva2k |
0:1802fb31b938
|
980
|
FATBuffer[entry->EntrySecOffset + idx] = 0x20;
|
iva2k |
0:1802fb31b938
|
981
|
for (idx = 12; idx < 32; idx++) { /* Fill all the remaining bytes with 0's */
|
iva2k |
0:1802fb31b938
|
982
|
FATBuffer[entry->EntrySecOffset + idx] = 0;
|
iva2k |
0:1802fb31b938
|
983
|
}
|
iva2k |
0:1802fb31b938
|
984
|
MS_BulkSend(entry->EntrySec, 1, FATBuffer); /* Write the sector into the root directory */
|
iva2k |
0:1802fb31b938
|
985
|
}
|
iva2k |
0:1802fb31b938
|
986
|
|
iva2k |
0:1802fb31b938
|
987
|
/*
|
iva2k |
0:1802fb31b938
|
988
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
989
|
* FILE CLOSE
|
iva2k |
0:1802fb31b938
|
990
|
*
|
iva2k |
0:1802fb31b938
|
991
|
* Description: This function closes the opened file by making all the elements of FILE_ENTRY structure to 0
|
iva2k |
0:1802fb31b938
|
992
|
*
|
iva2k |
0:1802fb31b938
|
993
|
* Arguments : fd File descriptor which points to the file to be closed
|
iva2k |
0:1802fb31b938
|
994
|
*
|
iva2k |
0:1802fb31b938
|
995
|
* Returns : None
|
iva2k |
0:1802fb31b938
|
996
|
*
|
iva2k |
0:1802fb31b938
|
997
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
998
|
*/
|
iva2k |
0:1802fb31b938
|
999
|
|
iva2k |
0:1802fb31b938
|
1000
|
void FILE_Close (USB_INT32S fd)
|
iva2k |
0:1802fb31b938
|
1001
|
{
|
iva2k |
0:1802fb31b938
|
1002
|
FILE_ENTRY *entry;
|
iva2k |
0:1802fb31b938
|
1003
|
|
iva2k |
0:1802fb31b938
|
1004
|
|
iva2k |
0:1802fb31b938
|
1005
|
entry = &FAT_FileEntry[fd-1];
|
iva2k |
0:1802fb31b938
|
1006
|
MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
1007
|
WriteLE32U(&FATBuffer[entry->EntrySecOffset + 28], entry->FileSize); /* Update the file size */
|
iva2k |
0:1802fb31b938
|
1008
|
MS_BulkSend(entry->EntrySec, 1, FATBuffer);
|
iva2k |
0:1802fb31b938
|
1009
|
entry->CurrClus = 0;
|
iva2k |
0:1802fb31b938
|
1010
|
entry->CurrClusOffset = 0;
|
iva2k |
0:1802fb31b938
|
1011
|
entry->FileSize = 0;
|
iva2k |
0:1802fb31b938
|
1012
|
entry->EntrySec = 0;
|
iva2k |
0:1802fb31b938
|
1013
|
entry->EntrySecOffset = 0;
|
iva2k |
0:1802fb31b938
|
1014
|
entry->FileStatus = 0;
|
iva2k |
0:1802fb31b938
|
1015
|
}
|
iva2k |
0:1802fb31b938
|
1016
|
|
iva2k |
0:1802fb31b938
|
1017
|
/*
|
iva2k |
0:1802fb31b938
|
1018
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
1019
|
* GET END CLUSTER
|
iva2k |
0:1802fb31b938
|
1020
|
*
|
iva2k |
0:1802fb31b938
|
1021
|
* Description: This function end cluster in the cluster chain of a cluster
|
iva2k |
0:1802fb31b938
|
1022
|
*
|
iva2k |
0:1802fb31b938
|
1023
|
* Arguments : clus_no Starting cluster of the cluster chain in which end cluster to be found
|
iva2k |
0:1802fb31b938
|
1024
|
*
|
iva2k |
0:1802fb31b938
|
1025
|
* Returns : End cluster in the cluster chain
|
iva2k |
0:1802fb31b938
|
1026
|
*
|
iva2k |
0:1802fb31b938
|
1027
|
**************************************************************************************************************
|
iva2k |
0:1802fb31b938
|
1028
|
*/
|
iva2k |
0:1802fb31b938
|
1029
|
|
iva2k |
0:1802fb31b938
|
1030
|
USB_INT16U FAT_GetEndClus (USB_INT16U clus_no)
|
iva2k |
0:1802fb31b938
|
1031
|
{
|
iva2k |
0:1802fb31b938
|
1032
|
USB_INT16U next_clus;
|
iva2k |
0:1802fb31b938
|
1033
|
|
iva2k |
0:1802fb31b938
|
1034
|
|
iva2k |
0:1802fb31b938
|
1035
|
next_clus = clus_no;
|
iva2k |
0:1802fb31b938
|
1036
|
while (next_clus) {
|
iva2k |
0:1802fb31b938
|
1037
|
next_clus = FAT_GetNextClus(clus_no);
|
iva2k |
0:1802fb31b938
|
1038
|
if (next_clus) {
|
iva2k |
0:1802fb31b938
|
1039
|
clus_no = next_clus;
|
iva2k |
0:1802fb31b938
|
1040
|
}
|
iva2k |
0:1802fb31b938
|
1041
|
}
|
iva2k |
0:1802fb31b938
|
1042
|
return (clus_no);
|
iva2k |
0:1802fb31b938
|
1043
|
}
|