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