Ilya I
/
pub_UsbHost
Embed:
(wiki syntax)
Show/hide line numbers
usbhost_fat.c
00001 /* 00002 ************************************************************************************************************** 00003 * NXP USB Host Stack 00004 * 00005 * (c) Copyright 2008, NXP SemiConductors 00006 * (c) Copyright 2008, OnChip Technologies LLC 00007 * All Rights Reserved 00008 * 00009 * www.nxp.com 00010 * www.onchiptech.com 00011 * 00012 * File : usbhost_fat.c 00013 * Programmer(s) : Ravikanth.P 00014 * Version : 00015 * 00016 ************************************************************************************************************** 00017 */ 00018 00019 /* 00020 ************************************************************************************************************** 00021 * INCLUDE HEADER FILES 00022 ************************************************************************************************************** 00023 */ 00024 00025 #include "usbhost_fat.h" 00026 00027 /* 00028 ************************************************************************************************************** 00029 * GLOBAL VARIABLES 00030 ************************************************************************************************************** 00031 */ 00032 00033 #define MAX_FILE_DESCRIPTORS 2 00034 static BOOT_SEC FAT_BootSec; 00035 static FILE_ENTRY FAT_FileEntry[MAX_FILE_DESCRIPTORS]; 00036 00037 /* 00038 ************************************************************************************************************** 00039 * INITIALIZE THE FILE SYSTEM 00040 * 00041 * Description: This function initializes the FAT16 file system 00042 * 00043 * Arguments : None 00044 * 00045 * Returns : OK if Success 00046 * ERR_INVALID_BOOTSIG if Failed 00047 * 00048 ************************************************************************************************************** 00049 */ 00050 00051 USB_INT32S FAT_Init (void) 00052 { 00053 USB_INT16U boot_sig; 00054 USB_INT32S rc, i; 00055 FILE_ENTRY *entry; 00056 00057 for (i=0;i<MAX_FILE_DESCRIPTORS;i++) { 00058 entry = &FAT_FileEntry[i]; 00059 entry->CurrClus = 0; 00060 entry->CurrClusOffset = 0; 00061 entry->FileSize = 0; 00062 entry->EntrySec = 0; 00063 entry->EntrySecOffset = 0; 00064 entry->FileStatus = 0; 00065 } 00066 00067 MS_BulkRecv(0, 1, FATBuffer); 00068 boot_sig = ReadLE16U(&FATBuffer[510]); 00069 if (boot_sig != 0xAA55) { 00070 rc = ERR_INVALID_BOOT_SIG; 00071 } else { 00072 if (FATBuffer[0] != 0xEB && FATBuffer[0] != 0xE9) { 00073 FAT_BootSec.BootSecOffset = ReadLE32U(&FATBuffer[454]); 00074 MS_BulkRecv(FAT_BootSec.BootSecOffset, 1, FATBuffer); 00075 } 00076 FAT_BootSec.BytsPerSec = ReadLE16U(&FATBuffer[11]); /* Bytes per cluster */ 00077 FAT_BootSec.SecPerClus = FATBuffer[13]; /* Sectors per cluster */ 00078 /* Reserved sector count */ 00079 FAT_BootSec.RsvdSecCnt = ReadLE16U(&FATBuffer[14]) + FAT_BootSec.BootSecOffset; 00080 FAT_BootSec.NumFATs = FATBuffer[16]; /* Number of FAT copies */ 00081 FAT_BootSec.RootEntCnt = ReadLE16U(&FATBuffer[17]); /* Root entry count */ 00082 FAT_BootSec.TotSec16 = ReadLE16U(&FATBuffer[19]); /* Total FAT16 sectors */ 00083 FAT_BootSec.TotSec32 = ReadLE32U(&FATBuffer[32]); /* Total FAT32 sectors */ 00084 FAT_BootSec.FATSz16 = ReadLE16U(&FATBuffer[22]); /* Size of the FAT table */ 00085 /* Bytes per cluster */ 00086 FAT_BootSec.BytsPerClus = (FAT_BootSec.BytsPerSec * FAT_BootSec.SecPerClus); 00087 /* Root directory starting sector */ 00088 FAT_BootSec.RootDirStartSec = FAT_BootSec.RsvdSecCnt + (FAT_BootSec.FATSz16 * FAT_BootSec.NumFATs); 00089 /* Sectors occupied by root directory */ 00090 FAT_BootSec.RootDirSec = ((FAT_BootSec.RootEntCnt * 32) + (FAT_BootSec.BytsPerSec - 1)) / 00091 (FAT_BootSec.BytsPerSec); 00092 /* First data sector */ 00093 FAT_BootSec.FirstDataSec = FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec; 00094 FAT_BootSec.FATType = FAT_GetFATType(); /* Type of FAT */ 00095 if (FAT_BootSec.FATType == FAT_16) { 00096 rc = OK; 00097 } else { 00098 rc = ERR_FAT_NOT_SUPPORTED; 00099 PRINT_Err(rc); 00100 } 00101 } 00102 return (rc); 00103 } 00104 00105 /* 00106 ************************************************************************************************************** 00107 * GET FILE SYSTEM TYPE 00108 * 00109 * Description: This function returns the file system type with which the disk is formatted 00110 * 00111 * Arguments : None 00112 * 00113 * Returns : FAT16 On Success 00114 * ERR_FAT_TYPE On Failure 00115 * 00116 ************************************************************************************************************** 00117 */ 00118 00119 USB_INT08U FAT_GetFATType (void) 00120 { 00121 USB_INT08U fat_type; 00122 USB_INT32U tot_sec; 00123 USB_INT32U tot_data_clus; 00124 00125 00126 if (FAT_BootSec.TotSec16 != 0) { /* Get total sectors in the disk */ 00127 tot_sec = FAT_BootSec.TotSec16; 00128 } else { 00129 tot_sec = FAT_BootSec.TotSec32; 00130 } 00131 00132 tot_data_clus = tot_sec / (FAT_BootSec.SecPerClus); /* Get total data clusters in the disk */ 00133 /* If total data clusters >= 4085 and */ 00134 /* < 65525, then it is FAT16 file system */ 00135 if (tot_data_clus >= 4085 && tot_data_clus < 65525) { 00136 fat_type = FAT_16; 00137 } else { 00138 fat_type = 0; 00139 } 00140 00141 return (fat_type); 00142 } 00143 00144 /* 00145 ************************************************************************************************************** 00146 * OPENING A FILE 00147 * 00148 * Description: This function stores the attributes of a file, such as starting cluster, file size, 00149 * sector where the file entry is stored and offset of the entry in that sector 00150 * 00151 * Arguments : file_name Name of the file. The file must be in root directory. 00152 * 00153 * Returns : pointer to the entry On Success 00154 * NULL On Failure 00155 * 00156 * Modifed 6/9/08 WCB returns a file descriptor which is the INDEX+1 to the entry. 00157 * returning the entry address itself could be interpreted as a negative number -- 00158 * and thus an error -- for memory locations of 0x80000000 and above. We return 00159 * INDEX+1 instead of just the index to avoid returning a file descriptor of zero, 00160 * which could be potentially confused with an error. 00161 * 00162 ************************************************************************************************************** 00163 */ 00164 00165 USB_INT32S FILE_Open (USB_INT08U *file_name, 00166 USB_INT08U flags) 00167 { 00168 USB_INT32S rc; 00169 FILE_ENTRY *entry = 0; 00170 USB_INT32S fd = -1; 00171 00172 do { 00173 if (FAT_FileEntry[++fd].FileStatus == 0) 00174 entry = &FAT_FileEntry[fd]; 00175 } while ((entry == 0) && (fd < MAX_FILE_DESCRIPTORS-1)); 00176 if (entry == 0) { 00177 return (ERR_OPEN_LIMIT_REACHED); 00178 } 00179 if (flags == RDONLY) { /* Search for a file. If it doesn't exist, don't create it */ 00180 rc = FAT_FindEntry(file_name, entry); 00181 if (rc == MATCH_FOUND) { 00182 entry->FileStatus = 1; 00183 rc = fd+1; 00184 } 00185 } else { /* Search for a file. If it doesn't exist, create it */ 00186 rc = FAT_CreateEntry(file_name, entry); 00187 if (rc == MATCH_FOUND) { 00188 entry->FileStatus = 1; 00189 rc = fd+1; 00190 } 00191 } 00192 return (rc); 00193 } 00194 00195 /* 00196 ************************************************************************************************************** 00197 * FINDING AN ENTRY 00198 * 00199 * Description: This function searches for a file name in the root directory 00200 * 00201 * Arguments : ent_name_given Pointer to the file name to be searched. 00202 * entry Pointer to the entry structure. The attributes of the file are stored in this 00203 * structure if the file was found in the root directory. 00204 * 00205 * Returns : MATCH_FOUND if the file was found in the root directory. 00206 * MATCH_NOT_FOUND if the file was not found in the root directory. 00207 * 00208 ************************************************************************************************************** 00209 */ 00210 00211 USB_INT32S FAT_FindEntry (USB_INT08U *ent_name_given, 00212 FILE_ENTRY *entry) 00213 { 00214 USB_INT32U sec_num; 00215 volatile USB_INT08U *buf; 00216 USB_INT08U ent_type; 00217 USB_INT08U ent_name_read[13]; 00218 00219 00220 for (sec_num = FAT_BootSec.RootDirStartSec; /* For all the sectors in root directory */ 00221 sec_num < (FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec); 00222 sec_num++) { 00223 00224 00225 MS_BulkRecv(sec_num, 1, FATBuffer); /* Read one sector */ 00226 buf = FATBuffer; 00227 while (buf < (FATBuffer + FAT_BootSec.BytsPerSec)) { 00228 ent_type = FAT_ChkEntType(buf); /* Check for the entry type */ 00229 if (ent_type == SFN_ENTRY) { /* If it is short entry get short file name */ 00230 FAT_GetSFN(buf, ent_name_read); 00231 /* Compare given name with this name case insensitively */ 00232 if (FAT_StrCaseCmp(ent_name_given, ent_name_read) == MATCH_FOUND) { 00233 entry->CurrClus = ReadLE16U(&buf[26]); /* If they are same, get starting cluster */ 00234 entry->FileSize = ReadLE32U(&buf[28]); /* Get file size */ 00235 entry->EntrySec = sec_num; /* Get sector number where the filename is located */ 00236 /* Get offset in this sector where the filename is located */ 00237 entry->EntrySecOffset = buf - FATBuffer; 00238 return (MATCH_FOUND); 00239 } 00240 } 00241 if (ent_type == LAST_ENTRY) { /* If it is the last entry, no more entries will exist. Return */ 00242 return (MATCH_NOT_FOUND); 00243 } 00244 buf = buf + 32; /* Move to the next entry */ 00245 } 00246 } 00247 return (MATCH_NOT_FOUND); 00248 } 00249 00250 /* 00251 ************************************************************************************************************** 00252 * GET SHORT FILE NAME AND EXTENSION OF A FILE 00253 * 00254 * Description: This function reads the short file name and extension corresponding to a file 00255 * 00256 * Arguments : ent_buf buffer which contains the 32 byte entry of a file 00257 * name buffer to store the file name and extension of a file 00258 * 00259 * Returns : None 00260 * 00261 ************************************************************************************************************** 00262 */ 00263 00264 void FAT_GetSFN (volatile USB_INT08U *entry, 00265 USB_INT08U *name) 00266 { 00267 USB_INT08U ext[4]; /* Buffer to store the extension of a file */ 00268 USB_INT08U *ext_ptr; 00269 00270 00271 ext_ptr = ext; 00272 00273 FAT_GetSfnName(entry, name); /* Get file name into "name" buffer */ 00274 FAT_GetSfnExt(entry, ext_ptr); /* Get extension into "ext" buffer */ 00275 00276 while (*name) { /* Goto the end of the filename */ 00277 name++; 00278 } 00279 if (*ext_ptr) { /* If the extension exists, put a '.' charecter */ 00280 *name = '.'; 00281 name++; 00282 } 00283 while (*ext_ptr) { /* Append the extension to the file name */ 00284 *name = *ext_ptr; 00285 name++; 00286 ext_ptr++; 00287 } 00288 *name = '\0'; 00289 } 00290 00291 /* 00292 ************************************************************************************************************** 00293 * GET SHORT FILE NAME OF A FILE 00294 * 00295 * Description: This function reads the short file name of a file 00296 * 00297 * Arguments : ent_buf buffer which contains the 32 byte entry of a file 00298 * name buffer to store the short file name of a file 00299 * 00300 * Returns : None 00301 * 00302 ************************************************************************************************************** 00303 */ 00304 00305 void FAT_GetSfnName (volatile USB_INT08U *entry, 00306 USB_INT08U *name) 00307 { 00308 USB_INT32U cnt; 00309 00310 00311 cnt = 0; 00312 while (cnt < 8) { 00313 *name = *entry; /* Get first 8 charecters of an SFN entry */ 00314 name++; 00315 entry++; 00316 cnt++; 00317 } 00318 *name = 0; 00319 name--; 00320 while (*name == 0x20) { /* If any spaces exist after the file name, replace them with 0 */ 00321 *name = 0; 00322 name--; 00323 } 00324 } 00325 00326 /* 00327 ************************************************************************************************************** 00328 * GET EXTENSION OF A FILE 00329 * 00330 * Description: This function reads the extension of a file 00331 * 00332 * Arguments : ent_buf buffer which contains the 32 byte entry of a file 00333 * ext_ptr buffer to store the extension of a file 00334 * 00335 * Returns : None 00336 * 00337 ************************************************************************************************************** 00338 */ 00339 00340 void FAT_GetSfnExt (volatile USB_INT08U *entry, 00341 USB_INT08U *ext_ptr) 00342 { 00343 USB_INT32U cnt; 00344 00345 00346 cnt = 0; 00347 while (cnt < 8) { /* Goto the beginning of the file extension */ 00348 entry++; 00349 cnt++; 00350 } 00351 cnt = 0; 00352 while (cnt < 3) { /* Get 3 charecters from there */ 00353 *ext_ptr = *entry; 00354 ext_ptr++; 00355 entry++; 00356 cnt++; 00357 } 00358 *ext_ptr = 0; 00359 ext_ptr--; 00360 while (*ext_ptr == ' ') { /* If any spaces exist after the file extension, replace them with 0 */ 00361 *ext_ptr = 0; 00362 ext_ptr--; 00363 } 00364 } 00365 00366 /* 00367 ************************************************************************************************************** 00368 * CASE INSENSITIVE COMPARISION OF STRINGS 00369 * 00370 * Description: This function compares two strings case insensitively 00371 * 00372 * Arguments : str1 Pointer to the first string 00373 * str2 Pointer to the second string 00374 * 00375 * Returns : MATCH_FOUND if both the strings are same 00376 * NATCH_NOT_FOUND if both the strings are different 00377 * 00378 ************************************************************************************************************** 00379 */ 00380 00381 USB_INT32S FAT_StrCaseCmp (USB_INT08U *str1, 00382 USB_INT08U *str2) 00383 { 00384 while (*str1 && *str2) { 00385 if (*str1 == *str2 || *str1 == (*str2 + 32) || *str1 == (*str2 - 32)) { 00386 str1++; 00387 str2++; 00388 continue; 00389 } else { 00390 return (MATCH_NOT_FOUND); 00391 } 00392 } 00393 if (*str1 == 0 && *str2 == 0) { 00394 return (MATCH_FOUND); 00395 } else { 00396 return (MATCH_NOT_FOUND); 00397 } 00398 } 00399 00400 /* 00401 ************************************************************************************************************** 00402 * CHECK TYPE OF THE ENTRY 00403 * 00404 * Description: This function checks the type of file entry. 00405 * 00406 * Arguments : ent Pointer to the buffer containing the entry 00407 * 00408 * Returns : LAST_ENTRY if the entry is last entry 00409 * FREE_ENTRY if the entry is free entry 00410 * LFN_ENTRY if the entry is long file name entry 00411 * SFN_ENTRY if the entry is short file name entry 00412 * 00413 ************************************************************************************************************** 00414 */ 00415 00416 USB_INT32U FAT_ChkEntType (volatile USB_INT08U *ent) 00417 { 00418 if (ent[0] == 0x00) { /* First byte is 0 means it is the last entry */ 00419 return (LAST_ENTRY); 00420 } 00421 00422 if (ent[0] == 0xE5) { /* First byte is 0xE5 means it is the free entry */ 00423 return (FREE_ENTRY); 00424 } 00425 00426 if (0x0F == ent[11]) { /* If 11th byte of an entry is 0x0F, it is LFN */ 00427 return (LFN_ENTRY); 00428 00429 } else { 00430 return (SFN_ENTRY); /* Else it is the SFN */ 00431 } 00432 } 00433 00434 /* 00435 ************************************************************************************************************** 00436 * READ DATA REQUESTED BY THE USER 00437 * 00438 * Description: This function reads data requested by the application from the file pointed by file descriptor. 00439 * 00440 * Arguments : fd file descriptor that points to a file 00441 * buffer buffer into which the data is to be read 00442 * num_bytes number of bytes requested by the application 00443 * 00444 * Returns : total_bytes_read Total bytes actually read. 00445 * 00446 ************************************************************************************************************** 00447 */ 00448 00449 USB_INT32U FILE_Read ( USB_INT32S fd, 00450 volatile USB_INT08U *buffer, 00451 USB_INT32U num_bytes) 00452 { 00453 USB_INT32U total_bytes_to_read; /* Total bytes requested by the application */ 00454 USB_INT32U total_bytes_read; /* Total bytes read */ 00455 USB_INT32U bytes_read; /* Bytes read from one cluster */ 00456 USB_INT32U bytes_to_read; /* Bytes to be read in one cluster */ 00457 FILE_ENTRY *entry; /* Entry that contains the file attribute information */ 00458 USB_INT16U next_clus; /* Next cluster of the current cluster in the cluster chain */ 00459 00460 entry = &FAT_FileEntry[fd-1]; /* Get file entry from file descriptor */ 00461 total_bytes_read = 0; 00462 00463 if (entry->FileSize == 0) { 00464 return (0); 00465 } 00466 if (num_bytes < entry->FileSize) { 00467 total_bytes_to_read = num_bytes; 00468 } else { 00469 total_bytes_to_read = entry->FileSize; 00470 } 00471 do { 00472 next_clus = FAT_GetNextClus(entry->CurrClus); /* Get next cluster */ 00473 if (next_clus == 0) { /* If the current cluster is the last cluster */ 00474 /* If the offset is at the end of the file */ 00475 if (entry->CurrClusOffset == (entry->FileSize % FAT_BootSec.BytsPerClus)) { 00476 return (0); /* No more bytes to read */ 00477 } /* If requested number is > remaining bytes in the last cluster */ 00478 if (total_bytes_to_read > ((entry->FileSize % FAT_BootSec.BytsPerClus) - entry->CurrClusOffset)) { 00479 total_bytes_to_read = (entry->FileSize % FAT_BootSec.BytsPerClus) - entry->CurrClusOffset; 00480 } 00481 bytes_to_read = total_bytes_to_read; 00482 /* If requested number is > remaining bytes in the current cluster */ 00483 } else if (total_bytes_to_read > (FAT_BootSec.BytsPerClus - entry->CurrClusOffset)) { 00484 bytes_to_read = FAT_BootSec.BytsPerClus - entry->CurrClusOffset; 00485 } else { 00486 bytes_to_read = total_bytes_to_read; 00487 } 00488 bytes_read = FAT_ClusRead(entry->CurrClus, /* Read bytes from a single cluster */ 00489 entry->CurrClusOffset, 00490 buffer, 00491 bytes_to_read); 00492 buffer += bytes_read; 00493 total_bytes_read += bytes_read; 00494 total_bytes_to_read -= bytes_read; 00495 /* If the cluster offset reaches end of the cluster, make it 0 */ 00496 if (entry->CurrClusOffset + bytes_read == FAT_BootSec.BytsPerClus) { 00497 entry->CurrClusOffset = 0; 00498 } else { 00499 entry->CurrClusOffset += bytes_read; /* Else increment the cluster offset */ 00500 } 00501 if (entry->CurrClusOffset == 0) { 00502 entry->CurrClus = (next_clus > 0) ? next_clus : entry->CurrClus; 00503 } 00504 } while (total_bytes_to_read); 00505 return (total_bytes_read); 00506 } 00507 00508 /* 00509 ************************************************************************************************************** 00510 * READ FROM ONE CLUSTER 00511 * 00512 * Description: This function reads the data from a single cluster. 00513 * 00514 * Arguments : curr_clus Current cluster from which the data has to read 00515 * clus_offset Position in the current cluster from which the data has to read 00516 * buffer Buffer into which the data has to read 00517 * num_bytes Number of bytes to read 00518 * 00519 * Returns : tot_bytes_read Total bytes read from the current cluster 00520 * 00521 ************************************************************************************************************** 00522 */ 00523 00524 USB_INT32U FAT_ClusRead ( USB_INT16U curr_clus, 00525 USB_INT32U clus_offset, 00526 volatile USB_INT08U *buffer, 00527 USB_INT32U num_bytes) 00528 { 00529 USB_INT32U tot_bytes_read; /* total bytes read in the current cluster */ 00530 USB_INT32U n_bytes; /* Bytes to read in the current sector */ 00531 USB_INT32U start_sec; /* Starting sector of the current cluster */ 00532 USB_INT32U sec_num; /*Current sector number */ 00533 USB_INT16U num_sec; /* Number of sectors to be read */ 00534 USB_INT32U sec_offset; /* Offset in the current sector */ 00535 USB_INT32U cnt; 00536 00537 00538 tot_bytes_read = 0; 00539 start_sec = ((curr_clus - 2) * FAT_BootSec.SecPerClus) + FAT_BootSec.FirstDataSec; 00540 sec_num = start_sec + (clus_offset / FAT_BootSec.BytsPerSec); 00541 num_sec = num_bytes / FAT_BootSec.BytsPerSec; 00542 sec_offset = clus_offset % FAT_BootSec.BytsPerSec; 00543 00544 if (sec_offset) { /* If the sector offset is at the middle of a sector */ 00545 MS_BulkRecv(sec_num, 1, FATBuffer); /* Read the first sector */ 00546 n_bytes = (FAT_BootSec.BytsPerSec - sec_offset <= num_bytes) ? 00547 (FAT_BootSec.BytsPerSec - sec_offset) : num_bytes; 00548 for (cnt = sec_offset; cnt < sec_offset + n_bytes; cnt++) { 00549 *buffer = FATBuffer[cnt]; /* Copy the required bytes to user buffer */ 00550 buffer++; 00551 } 00552 tot_bytes_read += n_bytes; 00553 clus_offset += n_bytes; 00554 num_bytes -= n_bytes; 00555 sec_num++; 00556 } 00557 00558 if (num_bytes / FAT_BootSec.BytsPerSec) { /* Read all the remaining full sectors */ 00559 00560 num_sec = num_bytes / FAT_BootSec.BytsPerSec; 00561 MS_BulkRecv(sec_num, num_sec, buffer); 00562 buffer += (num_sec * FAT_BootSec.BytsPerSec); 00563 tot_bytes_read += (num_sec * FAT_BootSec.BytsPerSec); 00564 clus_offset += (num_sec * FAT_BootSec.BytsPerSec); 00565 num_bytes -= (num_sec * FAT_BootSec.BytsPerSec); 00566 sec_num += num_sec; 00567 } 00568 00569 if (num_bytes) { /* Read the last sector for the remaining bytes */ 00570 MS_BulkRecv(sec_num, 1, FATBuffer); 00571 for (cnt = 0; cnt < num_bytes; cnt++) { 00572 *buffer = FATBuffer[cnt]; /* Copy the required bytes to user buffer */ 00573 buffer++; 00574 } 00575 tot_bytes_read += num_bytes; 00576 } 00577 00578 return (tot_bytes_read); 00579 } 00580 00581 /* 00582 ************************************************************************************************************** 00583 * WRITE THE DATA REQUESTED BY THE USER 00584 * 00585 * Description: This function writes data requested by the application to the file pointed by file descriptor 00586 * 00587 * Arguments : fd file descriptor that points to a file 00588 * buffer buffer from which the data is to be written 00589 * num_bytes number of bytes requested by the application 00590 * 00591 * Returns : total_bytes_written Total bytes actually written 00592 * 00593 ************************************************************************************************************** 00594 */ 00595 00596 USB_INT32U FILE_Write ( USB_INT32S fd, 00597 volatile USB_INT08U *buffer, 00598 USB_INT32U num_bytes) 00599 { 00600 USB_INT32U total_bytes_to_write; /* Total bytes requested by application */ 00601 USB_INT32U total_bytes_written; /* Total bytes written */ 00602 USB_INT32U bytes_written; /* Bytes written in a single cluster */ 00603 USB_INT32U bytes_to_write; /* Bytes to write in a single cluster */ 00604 FILE_ENTRY *entry; /* Entry that contains the file attribute information */ 00605 USB_INT16U free_clus; /* Free cluster available in the disk */ 00606 00607 00608 entry = &FAT_FileEntry[fd-1]; /* Get file entry from file descriptor */ 00609 total_bytes_written = 0; 00610 total_bytes_to_write = num_bytes; 00611 00612 if (num_bytes) { 00613 if (entry->FileSize == 0) { 00614 free_clus = FAT_GetFreeClus(); 00615 FAT_UpdateFAT(free_clus, 0xFFFF); 00616 entry->CurrClus = free_clus; 00617 MS_BulkRecv(entry->EntrySec, 1, FATBuffer); 00618 WriteLE16U(&FATBuffer[(entry->EntrySecOffset) + 26], free_clus); 00619 MS_BulkSend(entry->EntrySec, 1, FATBuffer); 00620 } 00621 } else { 00622 return (0); 00623 } 00624 entry->CurrClus = FAT_GetEndClus(entry->CurrClus); /* Make the current cluster as end cluster */ 00625 entry->CurrClusOffset = entry->FileSize % FAT_BootSec.BytsPerClus; /* Move cluster offset to file end */ 00626 do { 00627 if (total_bytes_to_write > FAT_BootSec.BytsPerClus - entry->CurrClusOffset) { 00628 bytes_to_write = FAT_BootSec.BytsPerClus - entry->CurrClusOffset; 00629 } else { 00630 bytes_to_write = total_bytes_to_write; 00631 } 00632 bytes_written = FAT_ClusWrite(entry->CurrClus, 00633 entry->CurrClusOffset, 00634 buffer, 00635 bytes_to_write); 00636 buffer += bytes_written; 00637 total_bytes_written += bytes_written; 00638 total_bytes_to_write -= bytes_written; 00639 entry->FileSize += bytes_written; 00640 if (entry->CurrClusOffset + bytes_written == FAT_BootSec.BytsPerClus) { 00641 entry->CurrClusOffset = 0; 00642 } else { 00643 entry->CurrClusOffset += bytes_written; 00644 } 00645 if (entry->CurrClusOffset == 0) { 00646 free_clus = FAT_GetFreeClus(); 00647 if (free_clus == 0) { 00648 return (total_bytes_written); 00649 } 00650 FAT_UpdateFAT(entry->CurrClus, free_clus); 00651 FAT_UpdateFAT(free_clus, 0xFFFF); 00652 entry->CurrClus = free_clus; 00653 } 00654 } while (total_bytes_to_write); 00655 return (total_bytes_written); 00656 } 00657 00658 /* 00659 ************************************************************************************************************** 00660 * WRITE TO ONE CLUSTER 00661 * 00662 * Description: This function writes the data to a single cluster. 00663 * 00664 * Arguments : curr_clus Current cluster into which the data has to write 00665 * clus_offset Position in the current cluster from which the data has to write 00666 * buffer Buffer from which the data has to write 00667 * num_bytes Number of bytes to write 00668 * 00669 * Returns : tot_bytes_read Total bytes written into the current cluster 00670 * 00671 ************************************************************************************************************** 00672 */ 00673 00674 USB_INT32U FAT_ClusWrite ( USB_INT16U curr_clus, 00675 USB_INT32U clus_offset, 00676 volatile USB_INT08U *buffer, 00677 USB_INT32U num_bytes) 00678 { 00679 USB_INT32U tot_bytes_written; 00680 USB_INT32U n_bytes; 00681 USB_INT32U start_sec; 00682 USB_INT32U sec_num; 00683 USB_INT16U num_sec; 00684 USB_INT32U sec_offset; 00685 USB_INT32U cnt; 00686 00687 00688 tot_bytes_written = 0; 00689 start_sec = ((curr_clus - 2) * FAT_BootSec.SecPerClus) + FAT_BootSec.FirstDataSec; 00690 sec_num = start_sec + (clus_offset / FAT_BootSec.BytsPerSec); 00691 num_sec = num_bytes / FAT_BootSec.BytsPerSec; 00692 sec_offset = clus_offset % FAT_BootSec.BytsPerSec; 00693 00694 if (sec_offset) { 00695 MS_BulkRecv(sec_num, 1, FATBuffer); 00696 n_bytes = (FAT_BootSec.BytsPerSec - sec_offset <= num_bytes) ? 00697 (FAT_BootSec.BytsPerSec - sec_offset) : num_bytes; 00698 for (cnt = sec_offset; cnt < (sec_offset + n_bytes); cnt++) { 00699 FATBuffer[cnt] = *buffer; 00700 buffer++; 00701 } 00702 MS_BulkSend(sec_num, 1, FATBuffer); 00703 tot_bytes_written += n_bytes; 00704 clus_offset += n_bytes; 00705 num_bytes -= n_bytes; 00706 sec_num++; 00707 } 00708 if (num_bytes / FAT_BootSec.BytsPerSec) { 00709 num_sec = num_bytes / FAT_BootSec.BytsPerSec; 00710 MS_BulkSend(sec_num, num_sec, buffer); 00711 buffer += (num_sec * FAT_BootSec.BytsPerSec); 00712 tot_bytes_written += (num_sec * FAT_BootSec.BytsPerSec); 00713 clus_offset += (num_sec * FAT_BootSec.BytsPerSec); 00714 num_bytes -= (num_sec * FAT_BootSec.BytsPerSec); 00715 sec_num += num_sec; 00716 } 00717 if (num_bytes) { 00718 MS_BulkRecv(sec_num, 1, FATBuffer); 00719 00720 for (cnt = 0; cnt < num_bytes; cnt++) { 00721 FATBuffer[cnt] = *buffer; 00722 buffer++; 00723 } 00724 MS_BulkSend(sec_num, 1, FATBuffer); 00725 tot_bytes_written += num_bytes; 00726 } 00727 return (tot_bytes_written); 00728 } 00729 00730 /* 00731 ************************************************************************************************************** 00732 * GET NEXT CLUSTER 00733 * 00734 * Description: This function returns next cluster of the current cluster in the cluster chain. If the current 00735 * cluster is the last cluster then this function returns 0 00736 * 00737 * Arguments : clus_no The cluster number for which the next cluster to be found 00738 * 00739 * Returns : next_clus if the current cluster is not the last cluster 00740 * 0 if the current cluster is the last cluster 00741 * Note: In practical cluster number 0 doesn't exist 00742 * 00743 ************************************************************************************************************** 00744 */ 00745 00746 USB_INT16U FAT_GetNextClus (USB_INT16U clus_no) 00747 { 00748 USB_INT32U sec_num; 00749 USB_INT32U ent_offset; 00750 USB_INT16U next_clus; 00751 00752 /* Get the sector number in the FAT that contains current cluster */ 00753 sec_num = FAT_BootSec.RsvdSecCnt + ((clus_no * 2) / FAT_BootSec.BytsPerSec); 00754 /* Get the sector offset in the FAT where the current cluster is located */ 00755 ent_offset = (clus_no * 2) % FAT_BootSec.BytsPerSec; 00756 MS_BulkRecv(sec_num, 1, FATBuffer); /* Read that sector */ 00757 next_clus = ReadLE16U(&FATBuffer[ent_offset]); /* Read the next cluster */ 00758 if (next_clus >= 0xFFF8 && next_clus <= 0xFFFF) { /* If that value is in between 0xFFF8 and 0xFFFF */ 00759 next_clus = 0; /* Current cluster is the end cluster */ 00760 } 00761 return (next_clus); 00762 00763 } 00764 00765 /* 00766 ************************************************************************************************************** 00767 * GET FREE CLUSTER 00768 * 00769 * Description: This function returns the free cluster if available 00770 * 00771 * Arguments : None 00772 * 00773 * Returns : free_clus if available 00774 * 0 if not available(means the disk is full) 00775 * 00776 ************************************************************************************************************** 00777 */ 00778 00779 USB_INT16U FAT_GetFreeClus (void) 00780 { 00781 USB_INT32U num_sec; 00782 USB_INT32U cnt; 00783 USB_INT32U sec_num; 00784 USB_INT16U free_clus; 00785 00786 00787 sec_num = FAT_BootSec.RsvdSecCnt; 00788 num_sec = FAT_BootSec.FATSz16; 00789 while (sec_num < (FAT_BootSec.RsvdSecCnt + num_sec)) { 00790 MS_BulkRecv(sec_num, 1, FATBuffer); 00791 for (cnt = 0; cnt < FAT_BootSec.BytsPerSec; cnt += 2) { 00792 if (ReadLE16U(&FATBuffer[cnt]) == 0) { 00793 free_clus = (((sec_num - FAT_BootSec.RsvdSecCnt) * FAT_BootSec.BytsPerSec) + cnt) / 2; 00794 return (free_clus); 00795 } 00796 } 00797 sec_num++; 00798 } 00799 return (0); 00800 } 00801 00802 /* 00803 ************************************************************************************************************** 00804 * UPDATE FILE ALLOCATION TABLE 00805 * 00806 * Description: This function updates the file allocation table 00807 * 00808 * Arguments : curr_clus Offset of the current cluster number in the file allocation table 00809 * value Value with which this offset to be updated 00810 * 00811 * Returns : None 00812 * 00813 ************************************************************************************************************** 00814 */ 00815 00816 void FAT_UpdateFAT (USB_INT16U curr_clus, 00817 USB_INT16U value) 00818 { 00819 USB_INT32U sec_num; 00820 USB_INT32U sec_offset; 00821 00822 sec_num = FAT_BootSec.RsvdSecCnt + (curr_clus * 2) / FAT_BootSec.BytsPerSec; 00823 sec_offset = (curr_clus * 2) % FAT_BootSec.BytsPerSec; 00824 00825 MS_BulkRecv(sec_num, 1, FATBuffer); 00826 WriteLE16U(&FATBuffer[sec_offset], value); 00827 MS_BulkSend(sec_num, 1, FATBuffer); 00828 } 00829 00830 /* 00831 ************************************************************************************************************** 00832 * UPDATE THE FILE ENTRY 00833 * 00834 * Description: This function updates the file entry that is located in the root directory 00835 * 00836 * Arguments : entry Pointer to the FILE ENTRY structure which contains the information about the file 00837 * 00838 * Returns : None 00839 * 00840 ************************************************************************************************************** 00841 */ 00842 00843 void FAT_UpdateEntry (FILE_ENTRY *entry) 00844 { 00845 USB_INT32U sec_num; 00846 USB_INT32U offset; 00847 00848 sec_num = entry->EntrySec; 00849 offset = entry->EntrySecOffset; 00850 MS_BulkRecv(sec_num, 1, FATBuffer); 00851 WriteLE32U(&FATBuffer[offset + 28], entry->FileSize); 00852 MS_BulkSend(sec_num, 1, FATBuffer); 00853 } 00854 00855 /* 00856 ************************************************************************************************************** 00857 * CREATING AN ENTRY 00858 * 00859 * Description: This function creates a file entry in the root directory if the file does not exist 00860 * 00861 * Arguments : ent_name_given The file name with which the entry is to be created 00862 * entry Pointer to FILE ENTRY structure 00863 * 00864 * Returns : OK If the entry already exists or successfully created if it doesn't exists 00865 * ERROR If failed to create the entry 00866 * 00867 ************************************************************************************************************** 00868 */ 00869 00870 USB_INT32S FAT_CreateEntry (USB_INT08U *ent_name_given, 00871 FILE_ENTRY *entry) 00872 { 00873 USB_INT32S rc; 00874 00875 00876 rc = FAT_FindEntry(ent_name_given, entry); /* Find for the given file name in the root directory */ 00877 if (rc == MATCH_FOUND) { /* If match found, return */ 00878 return (rc); 00879 } else { 00880 rc = FAT_GetFreeEntry(entry); /* Else get a free entry from the root directory */ 00881 if (rc != OK) { 00882 return (rc); 00883 } else { 00884 FAT_PutSFN(ent_name_given, entry); /* Store the given short file name in that entry */ 00885 return (rc); 00886 } 00887 } 00888 } 00889 00890 /* 00891 ************************************************************************************************************** 00892 * GET GREE ENTRY 00893 * 00894 * Description: This function searches for a free entry in the root directory. If a free entry is found, the 00895 * sector number and sector offset where the entry is located will be stored 00896 * 00897 * Arguments : entry Pointer to FILE_ENTRY structure 00898 * 00899 * Returns : OK If a free entry is found 00900 * ERROR If no free entry is found 00901 * 00902 ************************************************************************************************************** 00903 */ 00904 00905 USB_INT32S FAT_GetFreeEntry (FILE_ENTRY *entry) 00906 { 00907 USB_INT32U sec_num; 00908 volatile USB_INT08U *buf; 00909 USB_INT08U ent_type; 00910 00911 00912 for (sec_num = FAT_BootSec.RootDirStartSec; 00913 sec_num < (FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec); 00914 sec_num++) { 00915 00916 MS_BulkRecv(sec_num, 1, FATBuffer); 00917 buf = FATBuffer; 00918 while (buf < (FATBuffer + FAT_BootSec.BytsPerSec)) { 00919 ent_type = FAT_ChkEntType(buf); 00920 if (ent_type == FREE_ENTRY) { 00921 entry->EntrySec = sec_num; 00922 entry->EntrySecOffset = buf - FATBuffer; 00923 return (OK); 00924 } 00925 if (ent_type == LAST_ENTRY) { 00926 return (ERR_ROOT_DIR_FULL); 00927 } else { 00928 buf += 32; 00929 } 00930 } 00931 } 00932 return (ERR_ROOT_DIR_FULL); 00933 } 00934 00935 /* 00936 ************************************************************************************************************** 00937 * PUT SHORT FILE NAME 00938 * 00939 * Description: This function fills the file entry with the short file name given by the user 00940 * 00941 * Arguments : ent_name_given File name given by the user 00942 * entry Pointer to the FILE_ENTRY structure 00943 * 00944 * Returns : None 00945 * 00946 ************************************************************************************************************** 00947 */ 00948 00949 void FAT_PutSFN (USB_INT08U *ent_name_given, 00950 FILE_ENTRY *entry) 00951 { 00952 USB_INT32U idx; 00953 00954 /* Read the sector from root directory containing the free entry */ 00955 MS_BulkRecv(entry->EntrySec, 1, FATBuffer); 00956 for (idx = 0; idx < 8; idx++) { /* Fill the first eight charecters of the entry with file name */ 00957 if (*ent_name_given == '.') { 00958 while (idx < 8) { 00959 FATBuffer[entry->EntrySecOffset + idx] = 0x20; 00960 idx++; 00961 } 00962 ent_name_given++; 00963 } else { 00964 FATBuffer[entry->EntrySecOffset + idx] = *ent_name_given; 00965 ent_name_given++; 00966 } 00967 } 00968 00969 for (idx = 8; idx < 11; idx++) { /* Fill the next 3 charecters with file extension */ 00970 if (*ent_name_given == '.') { 00971 while (idx < 11) { 00972 FATBuffer[entry->EntrySecOffset + idx] = 0x20; 00973 idx++; 00974 } 00975 } else { 00976 FATBuffer[entry->EntrySecOffset + idx] = *ent_name_given; 00977 ent_name_given++; 00978 } 00979 } 00980 FATBuffer[entry->EntrySecOffset + idx] = 0x20; 00981 for (idx = 12; idx < 32; idx++) { /* Fill all the remaining bytes with 0's */ 00982 FATBuffer[entry->EntrySecOffset + idx] = 0; 00983 } 00984 MS_BulkSend(entry->EntrySec, 1, FATBuffer); /* Write the sector into the root directory */ 00985 } 00986 00987 /* 00988 ************************************************************************************************************** 00989 * FILE CLOSE 00990 * 00991 * Description: This function closes the opened file by making all the elements of FILE_ENTRY structure to 0 00992 * 00993 * Arguments : fd File descriptor which points to the file to be closed 00994 * 00995 * Returns : None 00996 * 00997 ************************************************************************************************************** 00998 */ 00999 01000 void FILE_Close (USB_INT32S fd) 01001 { 01002 FILE_ENTRY *entry; 01003 01004 01005 entry = &FAT_FileEntry[fd-1]; 01006 MS_BulkRecv(entry->EntrySec, 1, FATBuffer); 01007 WriteLE32U(&FATBuffer[entry->EntrySecOffset + 28], entry->FileSize); /* Update the file size */ 01008 MS_BulkSend(entry->EntrySec, 1, FATBuffer); 01009 entry->CurrClus = 0; 01010 entry->CurrClusOffset = 0; 01011 entry->FileSize = 0; 01012 entry->EntrySec = 0; 01013 entry->EntrySecOffset = 0; 01014 entry->FileStatus = 0; 01015 } 01016 01017 /* 01018 ************************************************************************************************************** 01019 * GET END CLUSTER 01020 * 01021 * Description: This function end cluster in the cluster chain of a cluster 01022 * 01023 * Arguments : clus_no Starting cluster of the cluster chain in which end cluster to be found 01024 * 01025 * Returns : End cluster in the cluster chain 01026 * 01027 ************************************************************************************************************** 01028 */ 01029 01030 USB_INT16U FAT_GetEndClus (USB_INT16U clus_no) 01031 { 01032 USB_INT16U next_clus; 01033 01034 01035 next_clus = clus_no; 01036 while (next_clus) { 01037 next_clus = FAT_GetNextClus(clus_no); 01038 if (next_clus) { 01039 clus_no = next_clus; 01040 } 01041 } 01042 return (clus_no); 01043 }
Generated on Thu Jul 14 2022 00:28:57 by 1.7.2